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