1 /*        $NetBSD: own_inet_addr.c,v 1.2 2025/02/25 19:15:45 christos 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