Postfix3.3.1
inet_addr_list.c
[詳解]
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 
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 
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) {
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((void *) 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 
103 static int inet_addr_list_comp(const void *a, const void *b)
104 {
105 
106  /*
107  * In case (struct *) != (void *).
108  */
110 }
111 
112 /* inet_addr_list_uniq - weed out duplicates */
113 
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 
143 {
144  myfree((void *) 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 
155 static 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++) {
162  &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
163  msg_info("%s", hostaddr.buf);
164  }
165 }
166 
167 int 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
int msg_verbose
Definition: msg.c:177
void myfree(void *ptr)
Definition: mymalloc.c:207
void inet_addr_list_uniq(INET_ADDR_LIST *list)
int sock_addr_cmp_addr(const struct sockaddr *sa, const struct sockaddr *sb)
Definition: sock_addr.c:109
void inet_addr_list_free(INET_ADDR_LIST *list)
void * myrealloc(void *ptr, ssize_t len)
Definition: mymalloc.c:175
int main(int argc, char **argv)
Definition: anvil.c:1010
INET_PROTO_INFO * inet_proto_init(const char *context, const char *protocols)
Definition: inet_proto.c:180
struct sockaddr_storage * addrs
#define SOCKADDR_TO_HOSTADDR(sa, salen, host, port, sock)
Definition: myaddrinfo.h:197
#define INET_PROTO_NAME_ALL
Definition: mail_params.h:992
char buf[MAI_HOSTADDR_STRSIZE]
Definition: myaddrinfo.h:146
#define SOCK_ADDR_PTR(ptr)
Definition: sock_addr.h:24
void inet_addr_list_init(INET_ADDR_LIST *list)
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
void inet_addr_list_append(INET_ADDR_LIST *list, struct sockaddr *addr)
#define SOCK_ADDR_LEN(sa)
Definition: sock_addr.h:78
int inet_addr_host(INET_ADDR_LIST *addr_list, const char *hostname)
void * mymalloc(ssize_t len)
Definition: mymalloc.c:150
void msg_info(const char *fmt,...)
Definition: msg.c:199