1 /*	$NetBSD: own_inet_addr.c,v 1.1.1.1 2009/06/23 10:08:47 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 
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      * If we are listening on all interfaces (default), ask the system what
99      * the interfaces are.
100      */
101     if (strcmp(var_inet_interfaces, INET_INTERFACES_ALL) == 0) {
102 	if (inet_addr_local(addr_list, mask_list,
103 			    inet_proto_info()->ai_family_list) == 0)
104 	    msg_fatal("could not find any active network interfaces");
105     }
106 
107     /*
108      * Select all loopback interfaces from the system's available interface
109      * list.
110      */
111     else if (strcmp(var_inet_interfaces, INET_INTERFACES_LOCAL) == 0) {
112 	inet_addr_list_init(&local_addrs);
113 	inet_addr_list_init(&local_masks);
114 	if (inet_addr_local(&local_addrs, &local_masks,
115 			    inet_proto_info()->ai_family_list) == 0)
116 	    msg_fatal("could not find any active network interfaces");
117 	for (sa = local_addrs.addrs, ma = local_masks.addrs;
118 	     sa < local_addrs.addrs + local_addrs.used; sa++, ma++) {
119 	    if (sock_addr_in_loopback(SOCK_ADDR_PTR(sa))) {
120 		inet_addr_list_append(addr_list, SOCK_ADDR_PTR(sa));
121 		inet_addr_list_append(mask_list, SOCK_ADDR_PTR(ma));
122 	    }
123 	}
124 	inet_addr_list_free(&local_addrs);
125 	inet_addr_list_free(&local_masks);
126     }
127 
128     /*
129      * If we are supposed to be listening only on specific interface
130      * addresses (virtual hosting), look up the addresses of those
131      * interfaces.
132      */
133     else {
134 	bufp = hosts = mystrdup(var_inet_interfaces);
135 	while ((host = mystrtok(&bufp, sep)) != 0)
136 	    if (inet_addr_host(addr_list, host) == 0)
137 		msg_fatal("config variable %s: host not found: %s",
138 			  VAR_INET_INTERFACES, host);
139 	myfree(hosts);
140 
141 	/*
142 	 * Weed out duplicate IP addresses. Duplicates happen when the same
143 	 * IP address is listed under multiple hostnames. If we don't weed
144 	 * out duplicates, Postfix can suddenly stop working after the DNS is
145 	 * changed.
146 	 */
147 	inet_addr_list_uniq(addr_list);
148 
149 	/*
150 	 * Find out the netmask for each virtual interface, by looking it up
151 	 * among all the local interfaces.
152 	 */
153 	inet_addr_list_init(&local_addrs);
154 	inet_addr_list_init(&local_masks);
155 	if (inet_addr_local(&local_addrs, &local_masks,
156 			    inet_proto_info()->ai_family_list) == 0)
157 	    msg_fatal("could not find any active network interfaces");
158 	for (nvirtual = 0; nvirtual < addr_list->used; nvirtual++) {
159 	    for (nlocal = 0; /* see below */ ; nlocal++) {
160 		if (nlocal >= local_addrs.used) {
161 		    SOCKADDR_TO_HOSTADDR(
162 				 SOCK_ADDR_PTR(addr_list->addrs + nvirtual),
163 				 SOCK_ADDR_LEN(addr_list->addrs + nvirtual),
164 				      &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
165 		    msg_fatal("parameter %s: no local interface found for %s",
166 			      VAR_INET_INTERFACES, hostaddr.buf);
167 		}
168 		if (SOCK_ADDR_EQ_ADDR(addr_list->addrs + nvirtual,
169 				      local_addrs.addrs + nlocal)) {
170 		    inet_addr_list_append(mask_list,
171 				 SOCK_ADDR_PTR(local_masks.addrs + nlocal));
172 		    break;
173 		}
174 	    }
175 	}
176 	inet_addr_list_free(&local_addrs);
177 	inet_addr_list_free(&local_masks);
178     }
179 }
180 
181 /* own_inet_addr - is this my own internet address */
182 
183 int     own_inet_addr(struct sockaddr * addr)
184 {
185     int     i;
186 
187     if (saved_addr_list.used == 0)
188 	own_inet_addr_init(&saved_addr_list, &saved_mask_list);
189 
190     for (i = 0; i < saved_addr_list.used; i++)
191 	if (SOCK_ADDR_EQ_ADDR(addr, saved_addr_list.addrs + i))
192 	    return (1);
193     return (0);
194 }
195 
196 /* own_inet_addr_list - return list of addresses */
197 
198 INET_ADDR_LIST *own_inet_addr_list(void)
199 {
200     if (saved_addr_list.used == 0)
201 	own_inet_addr_init(&saved_addr_list, &saved_mask_list);
202 
203     return (&saved_addr_list);
204 }
205 
206 /* own_inet_mask_list - return list of addresses */
207 
208 INET_ADDR_LIST *own_inet_mask_list(void)
209 {
210     if (saved_addr_list.used == 0)
211 	own_inet_addr_init(&saved_addr_list, &saved_mask_list);
212 
213     return (&saved_mask_list);
214 }
215 
216 /* proxy_inet_addr_init - initialize my proxy interface list */
217 
218 static void proxy_inet_addr_init(INET_ADDR_LIST *addr_list)
219 {
220     char   *hosts;
221     char   *host;
222     const char *sep = " \t,";
223     char   *bufp;
224 
225     /*
226      * Parse the proxy_interfaces parameter, and expand any symbolic
227      * hostnames into IP addresses.
228      */
229     inet_addr_list_init(addr_list);
230     bufp = hosts = mystrdup(var_proxy_interfaces);
231     while ((host = mystrtok(&bufp, sep)) != 0)
232 	if (inet_addr_host(addr_list, host) == 0)
233 	    msg_fatal("config variable %s: host not found: %s",
234 		      VAR_PROXY_INTERFACES, host);
235     myfree(hosts);
236 
237     /*
238      * Weed out duplicate IP addresses.
239      */
240     inet_addr_list_uniq(addr_list);
241 }
242 
243 /* proxy_inet_addr - is this my proxy internet address */
244 
245 int     proxy_inet_addr(struct sockaddr * addr)
246 {
247     int     i;
248 
249     if (*var_proxy_interfaces == 0)
250 	return (0);
251 
252     if (saved_proxy_list.used == 0)
253 	proxy_inet_addr_init(&saved_proxy_list);
254 
255     for (i = 0; i < saved_proxy_list.used; i++)
256 	if (SOCK_ADDR_EQ_ADDR(addr, saved_proxy_list.addrs + i))
257 	    return (1);
258     return (0);
259 }
260 
261 /* proxy_inet_addr_list - return list of addresses */
262 
263 INET_ADDR_LIST *proxy_inet_addr_list(void)
264 {
265     if (*var_proxy_interfaces != 0 && saved_proxy_list.used == 0)
266 	proxy_inet_addr_init(&saved_proxy_list);
267 
268     return (&saved_proxy_list);
269 }
270 
271 #ifdef TEST
272 #include <inet_proto.h>
273 
274 static void inet_addr_list_print(INET_ADDR_LIST *list)
275 {
276     MAI_HOSTADDR_STR hostaddr;
277     struct sockaddr_storage *sa;
278 
279     for (sa = list->addrs; sa < list->addrs + list->used; sa++) {
280 	SOCKADDR_TO_HOSTADDR(SOCK_ADDR_PTR(sa), SOCK_ADDR_LEN(sa),
281 			     &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
282 	msg_info("%s", hostaddr.buf);
283     }
284 }
285 
286 char   *var_inet_interfaces;
287 
288 int     main(int argc, char **argv)
289 {
290     INET_PROTO_INFO *proto_info;
291     INET_ADDR_LIST *list;
292 
293     if (argc != 3)
294 	msg_fatal("usage: %s protocols interface_list (e.g. \"all all\")",
295 		  argv[0]);
296     msg_verbose = 10;
297     proto_info = inet_proto_init(argv[0], argv[1]);
298     var_inet_interfaces = argv[2];
299     list = own_inet_addr_list();
300     inet_addr_list_print(list);
301     return (0);
302 }
303 
304 #endif
305