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