inet_addr_list.c revision 1.1
1/* $NetBSD: inet_addr_list.c,v 1.1 2009/06/23 10:09:00 tron Exp $ */ 2 3/*++ 4/* NAME 5/* inet_addr_list 3 6/* SUMMARY 7/* internet address list manager 8/* SYNOPSIS 9/* #include <inet_addr_list.h> 10/* 11/* void inet_addr_list_init(list) 12/* INET_ADDR_LIST *list; 13/* 14/* void inet_addr_list_append(list,addr) 15/* INET_ADDR_LIST *list; 16/* struct sockaddr *addr; 17/* 18/* void inet_addr_list_uniq(list) 19/* INET_ADDR_LIST *list; 20/* 21/* void inet_addr_list_free(list) 22/* INET_ADDR_LIST *list; 23/* DESCRIPTION 24/* This module maintains simple lists of internet addresses. 25/* 26/* inet_addr_list_init() initializes a user-provided structure 27/* so that it can be used by inet_addr_list_append() and by 28/* inet_addr_list_free(). 29/* 30/* inet_addr_list_append() appends the specified address to 31/* the specified list, extending the list on the fly. 32/* 33/* inet_addr_list_uniq() sorts the specified address list and 34/* eliminates duplicates. 35/* 36/* inet_addr_list_free() reclaims memory used for the 37/* specified address list. 38/* LICENSE 39/* .ad 40/* .fi 41/* The Secure Mailer license must be distributed with this software. 42/* AUTHOR(S) 43/* Wietse Venema 44/* IBM T.J. Watson Research 45/* P.O. Box 704 46/* Yorktown Heights, NY 10598, USA 47/*--*/ 48 49/* System library. */ 50 51#include <sys_defs.h> 52#include <sys/socket.h> 53#include <netinet/in.h> 54#include <arpa/inet.h> 55#include <stdlib.h> 56#include <netdb.h> 57 58/* Utility library. */ 59 60#include <msg.h> 61#include <mymalloc.h> 62#include <myaddrinfo.h> 63#include <sock_addr.h> 64#include <inet_addr_list.h> 65 66/* inet_addr_list_init - initialize internet address list */ 67 68void inet_addr_list_init(INET_ADDR_LIST *list) 69{ 70 int init_size; 71 72 list->used = 0; 73 list->size = 0; 74 init_size = 2; 75 list->addrs = (struct sockaddr_storage *) 76 mymalloc(sizeof(*list->addrs) * init_size); 77 list->size = init_size; 78} 79 80/* inet_addr_list_append - append address to internet address list */ 81 82void inet_addr_list_append(INET_ADDR_LIST *list, 83 struct sockaddr * addr) 84{ 85 const char *myname = "inet_addr_list_append"; 86 MAI_HOSTADDR_STR hostaddr; 87 int new_size; 88 89 if (msg_verbose > 1) { 90 SOCKADDR_TO_HOSTADDR(addr, SOCK_ADDR_LEN(addr), 91 &hostaddr, (MAI_SERVPORT_STR *) 0, 0); 92 msg_info("%s: %s", myname, hostaddr.buf); 93 } 94 if (list->used >= list->size) { 95 new_size = list->size * 2; 96 list->addrs = (struct sockaddr_storage *) 97 myrealloc((char *) list->addrs, sizeof(*list->addrs) * new_size); 98 list->size = new_size; 99 } 100 memcpy(list->addrs + list->used++, addr, SOCK_ADDR_LEN(addr)); 101} 102 103/* inet_addr_list_comp - compare addresses */ 104 105static int inet_addr_list_comp(const void *a, const void *b) 106{ 107 108 /* 109 * In case (struct *) != (void *). 110 */ 111 return (sock_addr_cmp_addr(SOCK_ADDR_PTR(a), SOCK_ADDR_PTR(b))); 112} 113 114/* inet_addr_list_uniq - weed out duplicates */ 115 116void inet_addr_list_uniq(INET_ADDR_LIST *list) 117{ 118 int n; 119 int m; 120 121 /* 122 * Put the identical members right next to each other. 123 */ 124 qsort((void *) list->addrs, list->used, 125 sizeof(list->addrs[0]), inet_addr_list_comp); 126 127 /* 128 * Nuke the duplicates. Postcondition after while loop: m is the largest 129 * index for which list->addrs[n] == list->addrs[m]. 130 */ 131 for (m = n = 0; m < list->used; m++, n++) { 132 if (m != n) 133 list->addrs[n] = list->addrs[m]; 134 while (m + 1 < list->used 135 && inet_addr_list_comp((void *) &(list->addrs[n]), 136 (void *) &(list->addrs[m + 1])) == 0) 137 m += 1; 138 } 139 list->used = n; 140} 141 142/* inet_addr_list_free - destroy internet address list */ 143 144void inet_addr_list_free(INET_ADDR_LIST *list) 145{ 146 myfree((char *) list->addrs); 147} 148 149#ifdef TEST 150#include <inet_proto.h> 151 152 /* 153 * Duplicate elimination needs to be tested. 154 */ 155#include <inet_addr_host.h> 156 157static void inet_addr_list_print(INET_ADDR_LIST *list) 158{ 159 MAI_HOSTADDR_STR hostaddr; 160 struct sockaddr_storage *sa; 161 162 for (sa = list->addrs; sa < list->addrs + list->used; sa++) { 163 SOCKADDR_TO_HOSTADDR(SOCK_ADDR_PTR(sa), SOCK_ADDR_LEN(sa), 164 &hostaddr, (MAI_SERVPORT_STR *) 0, 0); 165 msg_info("%s", hostaddr.buf); 166 } 167} 168 169int main(int argc, char **argv) 170{ 171 INET_ADDR_LIST list; 172 INET_PROTO_INFO *proto_info; 173 174 proto_info = inet_proto_init(argv[0], INET_PROTO_NAME_ALL); 175 inet_addr_list_init(&list); 176 while (--argc && *++argv) 177 if (inet_addr_host(&list, *argv) == 0) 178 msg_fatal("host not found: %s", *argv); 179 msg_info("list before sort/uniq"); 180 inet_addr_list_print(&list); 181 inet_addr_list_uniq(&list); 182 msg_info("list after sort/uniq"); 183 inet_addr_list_print(&list); 184 inet_addr_list_free(&list); 185 return (0); 186} 187 188#endif 189