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