Home | History | Annotate | Line # | Download | only in util
      1 /*	$NetBSD: inet_addr_list.c,v 1.3 2026/05/09 18:49:22 christos 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 
     68 void    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 
     82 void    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((void *) 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 
    105 static 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 
    116 void    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 
    144 void    inet_addr_list_free(INET_ADDR_LIST *list)
    145 {
    146     myfree((void *) 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 
    157 static 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 
    169 int     main(int argc, char **argv)
    170 {
    171     INET_ADDR_LIST list;
    172 
    173     inet_proto_init(argv[0], INET_PROTO_NAME_ALL);
    174     inet_addr_list_init(&list);
    175     while (--argc && *++argv)
    176 	if (inet_addr_host(&list, *argv) == 0)
    177 	    msg_fatal("host not found: %s", *argv);
    178     msg_info("list before sort/uniq");
    179     inet_addr_list_print(&list);
    180     inet_addr_list_uniq(&list);
    181     msg_info("list after sort/uniq");
    182     inet_addr_list_print(&list);
    183     inet_addr_list_free(&list);
    184     return (0);
    185 }
    186 
    187 #endif
    188