Home | History | Annotate | Line # | Download | only in global
      1 /*	$NetBSD: own_inet_addr.c,v 1.3 2026/05/09 18:49:16 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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 int     main(int argc, char **argv)
    300 {
    301     const INET_PROTO_INFO *proto_info;
    302     INET_ADDR_LIST *list;
    303 
    304     if (argc != 3)
    305 	msg_fatal("usage: %s protocols interface_list (e.g. \"all all\")",
    306 		  argv[0]);
    307     msg_verbose = 10;
    308     proto_info = inet_proto_init(argv[0], argv[1]);
    309     var_inet_interfaces = argv[2];
    310     list = own_inet_addr_list();
    311     inet_addr_list_print(list);
    312     return (0);
    313 }
    314 
    315 #endif
    316