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
71static INET_ADDR_LIST saved_addr_list;
72static INET_ADDR_LIST saved_mask_list;
73static INET_ADDR_LIST saved_proxy_list;
74
75/* own_inet_addr_init - initialize my own address list */
76
77static 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",
104		     VAR_INET_INTERFACES);
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++) {
130	    if (sock_addr_in_loopback(SOCK_ADDR_PTR(sa))) {
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#ifdef __APPLE_OS_X_SERVER__
161	/* remove IPv6 scoped addresses */
162	inet_addr_list_clean(addr_list);
163#endif
164
165	/*
166	 * Find out the netmask for each virtual interface, by looking it up
167	 * among all the local interfaces.
168	 */
169	inet_addr_list_init(&local_addrs);
170	inet_addr_list_init(&local_masks);
171	if (inet_addr_local(&local_addrs, &local_masks,
172			    inet_proto_info()->ai_family_list) == 0)
173	    msg_fatal("could not find any active network interfaces");
174	for (nvirtual = 0; nvirtual < addr_list->used; nvirtual++) {
175	    for (nlocal = 0; /* see below */ ; nlocal++) {
176		if (nlocal >= local_addrs.used) {
177		    SOCKADDR_TO_HOSTADDR(
178				 SOCK_ADDR_PTR(addr_list->addrs + nvirtual),
179				 SOCK_ADDR_LEN(addr_list->addrs + nvirtual),
180				      &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
181		    msg_fatal("parameter %s: no local interface found for %s",
182			      VAR_INET_INTERFACES, hostaddr.buf);
183		}
184		if (SOCK_ADDR_EQ_ADDR(addr_list->addrs + nvirtual,
185				      local_addrs.addrs + nlocal)) {
186		    inet_addr_list_append(mask_list,
187				 SOCK_ADDR_PTR(local_masks.addrs + nlocal));
188		    break;
189		}
190	    }
191	}
192	inet_addr_list_free(&local_addrs);
193	inet_addr_list_free(&local_masks);
194    }
195}
196
197/* own_inet_addr - is this my own internet address */
198
199int     own_inet_addr(struct sockaddr * addr)
200{
201    int     i;
202
203    if (saved_addr_list.used == 0)
204	own_inet_addr_init(&saved_addr_list, &saved_mask_list);
205
206    for (i = 0; i < saved_addr_list.used; i++)
207	if (SOCK_ADDR_EQ_ADDR(addr, saved_addr_list.addrs + i))
208	    return (1);
209    return (0);
210}
211
212/* own_inet_addr_list - return list of addresses */
213
214INET_ADDR_LIST *own_inet_addr_list(void)
215{
216    if (saved_addr_list.used == 0)
217	own_inet_addr_init(&saved_addr_list, &saved_mask_list);
218
219    return (&saved_addr_list);
220}
221
222/* own_inet_mask_list - return list of addresses */
223
224INET_ADDR_LIST *own_inet_mask_list(void)
225{
226    if (saved_addr_list.used == 0)
227	own_inet_addr_init(&saved_addr_list, &saved_mask_list);
228
229    return (&saved_mask_list);
230}
231
232/* proxy_inet_addr_init - initialize my proxy interface list */
233
234static void proxy_inet_addr_init(INET_ADDR_LIST *addr_list)
235{
236    char   *hosts;
237    char   *host;
238    const char *sep = " \t,";
239    char   *bufp;
240
241    /*
242     * Parse the proxy_interfaces parameter, and expand any symbolic
243     * hostnames into IP addresses.
244     */
245    inet_addr_list_init(addr_list);
246    bufp = hosts = mystrdup(var_proxy_interfaces);
247    while ((host = mystrtok(&bufp, sep)) != 0)
248	if (inet_addr_host(addr_list, host) == 0)
249	    msg_fatal("config variable %s: host not found: %s",
250		      VAR_PROXY_INTERFACES, host);
251    myfree(hosts);
252
253    /*
254     * Weed out duplicate IP addresses.
255     */
256    inet_addr_list_uniq(addr_list);
257}
258
259/* proxy_inet_addr - is this my proxy internet address */
260
261int     proxy_inet_addr(struct sockaddr * addr)
262{
263    int     i;
264
265    if (*var_proxy_interfaces == 0)
266	return (0);
267
268    if (saved_proxy_list.used == 0)
269	proxy_inet_addr_init(&saved_proxy_list);
270
271    for (i = 0; i < saved_proxy_list.used; i++)
272	if (SOCK_ADDR_EQ_ADDR(addr, saved_proxy_list.addrs + i))
273	    return (1);
274    return (0);
275}
276
277/* proxy_inet_addr_list - return list of addresses */
278
279INET_ADDR_LIST *proxy_inet_addr_list(void)
280{
281    if (*var_proxy_interfaces != 0 && saved_proxy_list.used == 0)
282	proxy_inet_addr_init(&saved_proxy_list);
283
284    return (&saved_proxy_list);
285}
286
287#ifdef TEST
288#include <inet_proto.h>
289
290static void inet_addr_list_print(INET_ADDR_LIST *list)
291{
292    MAI_HOSTADDR_STR hostaddr;
293    struct sockaddr_storage *sa;
294
295    for (sa = list->addrs; sa < list->addrs + list->used; sa++) {
296	SOCKADDR_TO_HOSTADDR(SOCK_ADDR_PTR(sa), SOCK_ADDR_LEN(sa),
297			     &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
298	msg_info("%s", hostaddr.buf);
299    }
300}
301
302char   *var_inet_interfaces;
303
304int     main(int argc, char **argv)
305{
306    INET_PROTO_INFO *proto_info;
307    INET_ADDR_LIST *list;
308
309    if (argc != 3)
310	msg_fatal("usage: %s protocols interface_list (e.g. \"all all\")",
311		  argv[0]);
312    msg_verbose = 10;
313    proto_info = inet_proto_init(argv[0], argv[1]);
314    var_inet_interfaces = argv[2];
315    list = own_inet_addr_list();
316    inet_addr_list_print(list);
317    return (0);
318}
319
320#endif
321