Postfix3.3.1
own_inet_addr.c
[詳解]
1 /*++
2 /* NAME
3 /* own_inet_addr 3
4 /* SUMMARY
5 /* determine if IP address belongs to this mail system instance
6 /* SYNOPSIS
7 /* #include <own_inet_addr.h>
8 /*
9 /* int own_inet_addr(addr)
10 /* struct sockaddr *addr;
11 /*
12 /* INET_ADDR_LIST *own_inet_addr_list()
13 /*
14 /* INET_ADDR_LIST *own_inet_mask_list()
15 /*
16 /* int proxy_inet_addr(addr)
17 /* struct in_addr *addr;
18 /*
19 /* INET_ADDR_LIST *proxy_inet_addr_list()
20 /* DESCRIPTION
21 /* own_inet_addr() determines if the specified IP address belongs
22 /* to this mail system instance, i.e. if this mail system instance
23 /* is supposed to be listening on this specific IP address.
24 /*
25 /* own_inet_addr_list() returns the list of all addresses that
26 /* belong to this mail system instance.
27 /*
28 /* own_inet_mask_list() returns the list of all corresponding
29 /* netmasks.
30 /*
31 /* proxy_inet_addr() determines if the specified IP address is
32 /* listed with the proxy_interfaces configuration parameter.
33 /*
34 /* proxy_inet_addr_list() returns the list of all addresses that
35 /* belong to proxy network interfaces.
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 <string.h>
51 
52 /* Utility library. */
53 
54 #include <msg.h>
55 #include <mymalloc.h>
56 #include <inet_addr_list.h>
57 #include <inet_addr_local.h>
58 #include <inet_addr_host.h>
59 #include <stringops.h>
60 #include <myaddrinfo.h>
61 #include <sock_addr.h>
62 #include <inet_proto.h>
63 
64 /* Global library. */
65 
66 #include <mail_params.h>
67 #include <own_inet_addr.h>
68 
69 /* Application-specific. */
70 
71 static INET_ADDR_LIST saved_addr_list;
72 static INET_ADDR_LIST saved_mask_list;
73 static INET_ADDR_LIST saved_proxy_list;
74 
75 /* own_inet_addr_init - initialize my own address list */
76 
77 static void own_inet_addr_init(INET_ADDR_LIST *addr_list,
78  INET_ADDR_LIST *mask_list)
79 {
80  INET_ADDR_LIST local_addrs;
81  INET_ADDR_LIST local_masks;
82  char *hosts;
83  char *host;
84  const char *sep = " \t,";
85  char *bufp;
86  int nvirtual;
87  int nlocal;
88  MAI_HOSTADDR_STR hostaddr;
89  struct sockaddr_storage *sa;
90  struct sockaddr_storage *ma;
91 
92  inet_addr_list_init(addr_list);
93  inet_addr_list_init(mask_list);
94 
95  /*
96  * Avoid run-time errors when all network protocols are disabled. We
97  * can't look up interface information, and we can't convert explicit
98  * names or addresses.
99  */
100  if (inet_proto_info()->ai_family_list[0] == 0) {
101  if (msg_verbose)
102  msg_info("skipping %s setting - "
103  "all network protocols are disabled",
105  return;
106  }
107 
108  /*
109  * If we are listening on all interfaces (default), ask the system what
110  * the interfaces are.
111  */
112  if (strcmp(var_inet_interfaces, INET_INTERFACES_ALL) == 0) {
113  if (inet_addr_local(addr_list, mask_list,
114  inet_proto_info()->ai_family_list) == 0)
115  msg_fatal("could not find any active network interfaces");
116  }
117 
118  /*
119  * Select all loopback interfaces from the system's available interface
120  * list.
121  */
122  else if (strcmp(var_inet_interfaces, INET_INTERFACES_LOCAL) == 0) {
123  inet_addr_list_init(&local_addrs);
124  inet_addr_list_init(&local_masks);
125  if (inet_addr_local(&local_addrs, &local_masks,
126  inet_proto_info()->ai_family_list) == 0)
127  msg_fatal("could not find any active network interfaces");
128  for (sa = local_addrs.addrs, ma = local_masks.addrs;
129  sa < local_addrs.addrs + local_addrs.used; sa++, ma++) {
131  inet_addr_list_append(addr_list, SOCK_ADDR_PTR(sa));
132  inet_addr_list_append(mask_list, SOCK_ADDR_PTR(ma));
133  }
134  }
135  inet_addr_list_free(&local_addrs);
136  inet_addr_list_free(&local_masks);
137  }
138 
139  /*
140  * If we are supposed to be listening only on specific interface
141  * addresses (virtual hosting), look up the addresses of those
142  * interfaces.
143  */
144  else {
145  bufp = hosts = mystrdup(var_inet_interfaces);
146  while ((host = mystrtok(&bufp, sep)) != 0)
147  if (inet_addr_host(addr_list, host) == 0)
148  msg_fatal("config variable %s: host not found: %s",
149  VAR_INET_INTERFACES, host);
150  myfree(hosts);
151 
152  /*
153  * Weed out duplicate IP addresses. Duplicates happen when the same
154  * IP address is listed under multiple hostnames. If we don't weed
155  * out duplicates, Postfix can suddenly stop working after the DNS is
156  * changed.
157  */
158  inet_addr_list_uniq(addr_list);
159 
160  /*
161  * Find out the netmask for each virtual interface, by looking it up
162  * among all the local interfaces.
163  */
164  inet_addr_list_init(&local_addrs);
165  inet_addr_list_init(&local_masks);
166  if (inet_addr_local(&local_addrs, &local_masks,
167  inet_proto_info()->ai_family_list) == 0)
168  msg_fatal("could not find any active network interfaces");
169  for (nvirtual = 0; nvirtual < addr_list->used; nvirtual++) {
170  for (nlocal = 0; /* see below */ ; nlocal++) {
171  if (nlocal >= local_addrs.used) {
173  SOCK_ADDR_PTR(addr_list->addrs + nvirtual),
174  SOCK_ADDR_LEN(addr_list->addrs + nvirtual),
175  &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
176  msg_fatal("parameter %s: no local interface found for %s",
177  VAR_INET_INTERFACES, hostaddr.buf);
178  }
179  if (SOCK_ADDR_EQ_ADDR(addr_list->addrs + nvirtual,
180  local_addrs.addrs + nlocal)) {
181  inet_addr_list_append(mask_list,
182  SOCK_ADDR_PTR(local_masks.addrs + nlocal));
183  break;
184  }
185  }
186  }
187  inet_addr_list_free(&local_addrs);
188  inet_addr_list_free(&local_masks);
189  }
190 }
191 
192 /* own_inet_addr - is this my own internet address */
193 
194 int own_inet_addr(struct sockaddr * addr)
195 {
196  int i;
197 
198  if (saved_addr_list.used == 0)
199  own_inet_addr_init(&saved_addr_list, &saved_mask_list);
200 
201  for (i = 0; i < saved_addr_list.used; i++)
202  if (SOCK_ADDR_EQ_ADDR(addr, saved_addr_list.addrs + i))
203  return (1);
204  return (0);
205 }
206 
207 /* own_inet_addr_list - return list of addresses */
208 
210 {
211  if (saved_addr_list.used == 0)
212  own_inet_addr_init(&saved_addr_list, &saved_mask_list);
213 
214  return (&saved_addr_list);
215 }
216 
217 /* own_inet_mask_list - return list of addresses */
218 
220 {
221  if (saved_addr_list.used == 0)
222  own_inet_addr_init(&saved_addr_list, &saved_mask_list);
223 
224  return (&saved_mask_list);
225 }
226 
227 /* proxy_inet_addr_init - initialize my proxy interface list */
228 
229 static void proxy_inet_addr_init(INET_ADDR_LIST *addr_list)
230 {
231  char *hosts;
232  char *host;
233  const char *sep = " \t,";
234  char *bufp;
235 
236  /*
237  * Parse the proxy_interfaces parameter, and expand any symbolic
238  * hostnames into IP addresses.
239  */
240  inet_addr_list_init(addr_list);
241  bufp = hosts = mystrdup(var_proxy_interfaces);
242  while ((host = mystrtok(&bufp, sep)) != 0)
243  if (inet_addr_host(addr_list, host) == 0)
244  msg_fatal("config variable %s: host not found: %s",
245  VAR_PROXY_INTERFACES, host);
246  myfree(hosts);
247 
248  /*
249  * Weed out duplicate IP addresses.
250  */
251  inet_addr_list_uniq(addr_list);
252 }
253 
254 /* proxy_inet_addr - is this my proxy internet address */
255 
256 int proxy_inet_addr(struct sockaddr * addr)
257 {
258  int i;
259 
260  if (*var_proxy_interfaces == 0)
261  return (0);
262 
263  if (saved_proxy_list.used == 0)
264  proxy_inet_addr_init(&saved_proxy_list);
265 
266  for (i = 0; i < saved_proxy_list.used; i++)
267  if (SOCK_ADDR_EQ_ADDR(addr, saved_proxy_list.addrs + i))
268  return (1);
269  return (0);
270 }
271 
272 /* proxy_inet_addr_list - return list of addresses */
273 
275 {
276  if (*var_proxy_interfaces != 0 && saved_proxy_list.used == 0)
277  proxy_inet_addr_init(&saved_proxy_list);
278 
279  return (&saved_proxy_list);
280 }
281 
282 #ifdef TEST
283 #include <inet_proto.h>
284 
285 static void inet_addr_list_print(INET_ADDR_LIST *list)
286 {
287  MAI_HOSTADDR_STR hostaddr;
288  struct sockaddr_storage *sa;
289 
290  for (sa = list->addrs; sa < list->addrs + list->used; sa++) {
292  &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
293  msg_info("%s", hostaddr.buf);
294  }
295 }
296 
297 char *var_inet_interfaces;
298 
299 int main(int argc, char **argv)
300 {
301  INET_PROTO_INFO *proto_info;
302  INET_ADDR_LIST *list;
303 
304  if (argc != 3)
305  msg_fatal("usage: %s protocols interface_list (e.g. \"all all\")",
306  argv[0]);
307  msg_verbose = 10;
308  proto_info = inet_proto_init(argv[0], argv[1]);
309  var_inet_interfaces = argv[2];
310  list = own_inet_addr_list();
311  inet_addr_list_print(list);
312  return (0);
313 }
314 
315 #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)
char * mystrdup(const char *str)
Definition: mymalloc.c:225
#define VAR_PROXY_INTERFACES
Definition: mail_params.h:182
void inet_addr_list_free(INET_ADDR_LIST *list)
#define inet_proto_info()
Definition: inet_proto.h:29
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
int inet_addr_local(INET_ADDR_LIST *addr_list, INET_ADDR_LIST *mask_list, unsigned *addr_family_list)
#define VAR_INET_INTERFACES
Definition: mail_params.h:176
int own_inet_addr(struct sockaddr *addr)
char * mystrtok(char **src, const char *sep)
Definition: mystrtok.c:54
char buf[MAI_HOSTADDR_STRSIZE]
Definition: myaddrinfo.h:146
#define INET_INTERFACES_LOCAL
Definition: mail_params.h:178
INET_ADDR_LIST * proxy_inet_addr_list(void)
int sock_addr_in_loopback(const struct sockaddr *sa)
Definition: sock_addr.c:156
#define SOCK_ADDR_PTR(ptr)
Definition: sock_addr.h:24
INET_ADDR_LIST * own_inet_mask_list(void)
void inet_addr_list_init(INET_ADDR_LIST *list)
int proxy_inet_addr(struct sockaddr *addr)
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
void inet_addr_list_append(INET_ADDR_LIST *list, struct sockaddr *addr)
#define INET_INTERFACES_ALL
Definition: mail_params.h:177
INET_ADDR_LIST * own_inet_addr_list(void)
#define SOCK_ADDR_LEN(sa)
Definition: sock_addr.h:78
int inet_addr_host(INET_ADDR_LIST *addr_list, const char *hostname)
char * var_proxy_interfaces
Definition: mail_params.c:259
#define SOCK_ADDR_EQ_ADDR(sa, sb)
Definition: sock_addr.h:84
char * var_inet_interfaces
Definition: mail_params.c:258
void msg_info(const char *fmt,...)
Definition: msg.c:199