/*++ /* NAME /* own_inet_addr 3 /* SUMMARY /* determine if IP address belongs to this mail system instance /* SYNOPSIS /* #include /* /* int own_inet_addr(addr) /* struct sockaddr *addr; /* /* INET_ADDR_LIST *own_inet_addr_list() /* /* INET_ADDR_LIST *own_inet_mask_list() /* /* int proxy_inet_addr(addr) /* struct in_addr *addr; /* /* INET_ADDR_LIST *proxy_inet_addr_list() /* DESCRIPTION /* own_inet_addr() determines if the specified IP address belongs /* to this mail system instance, i.e. if this mail system instance /* is supposed to be listening on this specific IP address. /* /* own_inet_addr_list() returns the list of all addresses that /* belong to this mail system instance. /* /* own_inet_mask_list() returns the list of all corresponding /* netmasks. /* /* proxy_inet_addr() determines if the specified IP address is /* listed with the proxy_interfaces configuration parameter. /* /* proxy_inet_addr_list() returns the list of all addresses that /* belong to proxy network interfaces. /* LICENSE /* .ad /* .fi /* The Secure Mailer license must be distributed with this software. /* AUTHOR(S) /* Wietse Venema /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /*--*/ /* System library. */ #include #include /* Utility library. */ #include #include #include #include #include #include #include #include #include /* Global library. */ #include #include /* Application-specific. */ static INET_ADDR_LIST saved_addr_list; static INET_ADDR_LIST saved_mask_list; static INET_ADDR_LIST saved_proxy_list; /* own_inet_addr_init - initialize my own address list */ static void own_inet_addr_init(INET_ADDR_LIST *addr_list, INET_ADDR_LIST *mask_list) { INET_ADDR_LIST local_addrs; INET_ADDR_LIST local_masks; char *hosts; char *host; const char *sep = " \t,"; char *bufp; int nvirtual; int nlocal; MAI_HOSTADDR_STR hostaddr; struct sockaddr_storage *sa; struct sockaddr_storage *ma; inet_addr_list_init(addr_list); inet_addr_list_init(mask_list); /* * Avoid run-time errors when all network protocols are disabled. We * can't look up interface information, and we can't convert explicit * names or addresses. */ if (inet_proto_info()->ai_family_list[0] == 0) { if (msg_verbose) msg_info("skipping %s setting - " "all network protocols are disabled", VAR_INET_INTERFACES); return; } /* * If we are listening on all interfaces (default), ask the system what * the interfaces are. */ if (strcmp(var_inet_interfaces, INET_INTERFACES_ALL) == 0) { if (inet_addr_local(addr_list, mask_list, inet_proto_info()->ai_family_list) == 0) msg_fatal("could not find any active network interfaces"); } /* * Select all loopback interfaces from the system's available interface * list. */ else if (strcmp(var_inet_interfaces, INET_INTERFACES_LOCAL) == 0) { inet_addr_list_init(&local_addrs); inet_addr_list_init(&local_masks); if (inet_addr_local(&local_addrs, &local_masks, inet_proto_info()->ai_family_list) == 0) msg_fatal("could not find any active network interfaces"); for (sa = local_addrs.addrs, ma = local_masks.addrs; sa < local_addrs.addrs + local_addrs.used; sa++, ma++) { if (sock_addr_in_loopback(SOCK_ADDR_PTR(sa))) { inet_addr_list_append(addr_list, SOCK_ADDR_PTR(sa)); inet_addr_list_append(mask_list, SOCK_ADDR_PTR(ma)); } } inet_addr_list_free(&local_addrs); inet_addr_list_free(&local_masks); } /* * If we are supposed to be listening only on specific interface * addresses (virtual hosting), look up the addresses of those * interfaces. */ else { bufp = hosts = mystrdup(var_inet_interfaces); while ((host = mystrtok(&bufp, sep)) != 0) if (inet_addr_host(addr_list, host) == 0) msg_fatal("config variable %s: host not found: %s", VAR_INET_INTERFACES, host); myfree(hosts); /* * Weed out duplicate IP addresses. Duplicates happen when the same * IP address is listed under multiple hostnames. If we don't weed * out duplicates, Postfix can suddenly stop working after the DNS is * changed. */ inet_addr_list_uniq(addr_list); /* * Find out the netmask for each virtual interface, by looking it up * among all the local interfaces. */ inet_addr_list_init(&local_addrs); inet_addr_list_init(&local_masks); if (inet_addr_local(&local_addrs, &local_masks, inet_proto_info()->ai_family_list) == 0) msg_fatal("could not find any active network interfaces"); for (nvirtual = 0; nvirtual < addr_list->used; nvirtual++) { for (nlocal = 0; /* see below */ ; nlocal++) { if (nlocal >= local_addrs.used) { SOCKADDR_TO_HOSTADDR( SOCK_ADDR_PTR(addr_list->addrs + nvirtual), SOCK_ADDR_LEN(addr_list->addrs + nvirtual), &hostaddr, (MAI_SERVPORT_STR *) 0, 0); msg_fatal("parameter %s: no local interface found for %s", VAR_INET_INTERFACES, hostaddr.buf); } if (SOCK_ADDR_EQ_ADDR(addr_list->addrs + nvirtual, local_addrs.addrs + nlocal)) { inet_addr_list_append(mask_list, SOCK_ADDR_PTR(local_masks.addrs + nlocal)); break; } } } inet_addr_list_free(&local_addrs); inet_addr_list_free(&local_masks); } } /* own_inet_addr - is this my own internet address */ int own_inet_addr(struct sockaddr * addr) { int i; if (saved_addr_list.used == 0) own_inet_addr_init(&saved_addr_list, &saved_mask_list); for (i = 0; i < saved_addr_list.used; i++) if (SOCK_ADDR_EQ_ADDR(addr, saved_addr_list.addrs + i)) return (1); return (0); } /* own_inet_addr_list - return list of addresses */ INET_ADDR_LIST *own_inet_addr_list(void) { if (saved_addr_list.used == 0) own_inet_addr_init(&saved_addr_list, &saved_mask_list); return (&saved_addr_list); } /* own_inet_mask_list - return list of addresses */ INET_ADDR_LIST *own_inet_mask_list(void) { if (saved_addr_list.used == 0) own_inet_addr_init(&saved_addr_list, &saved_mask_list); return (&saved_mask_list); } /* proxy_inet_addr_init - initialize my proxy interface list */ static void proxy_inet_addr_init(INET_ADDR_LIST *addr_list) { char *hosts; char *host; const char *sep = " \t,"; char *bufp; /* * Parse the proxy_interfaces parameter, and expand any symbolic * hostnames into IP addresses. */ inet_addr_list_init(addr_list); bufp = hosts = mystrdup(var_proxy_interfaces); while ((host = mystrtok(&bufp, sep)) != 0) if (inet_addr_host(addr_list, host) == 0) msg_fatal("config variable %s: host not found: %s", VAR_PROXY_INTERFACES, host); myfree(hosts); /* * Weed out duplicate IP addresses. */ inet_addr_list_uniq(addr_list); } /* proxy_inet_addr - is this my proxy internet address */ int proxy_inet_addr(struct sockaddr * addr) { int i; if (*var_proxy_interfaces == 0) return (0); if (saved_proxy_list.used == 0) proxy_inet_addr_init(&saved_proxy_list); for (i = 0; i < saved_proxy_list.used; i++) if (SOCK_ADDR_EQ_ADDR(addr, saved_proxy_list.addrs + i)) return (1); return (0); } /* proxy_inet_addr_list - return list of addresses */ INET_ADDR_LIST *proxy_inet_addr_list(void) { if (*var_proxy_interfaces != 0 && saved_proxy_list.used == 0) proxy_inet_addr_init(&saved_proxy_list); return (&saved_proxy_list); } #ifdef TEST #include static void inet_addr_list_print(INET_ADDR_LIST *list) { MAI_HOSTADDR_STR hostaddr; struct sockaddr_storage *sa; for (sa = list->addrs; sa < list->addrs + list->used; sa++) { SOCKADDR_TO_HOSTADDR(SOCK_ADDR_PTR(sa), SOCK_ADDR_LEN(sa), &hostaddr, (MAI_SERVPORT_STR *) 0, 0); msg_info("%s", hostaddr.buf); } } char *var_inet_interfaces; int main(int argc, char **argv) { INET_PROTO_INFO *proto_info; INET_ADDR_LIST *list; if (argc != 3) msg_fatal("usage: %s protocols interface_list (e.g. \"all all\")", argv[0]); msg_verbose = 10; proto_info = inet_proto_init(argv[0], argv[1]); var_inet_interfaces = argv[2]; list = own_inet_addr_list(); inet_addr_list_print(list); return (0); } #endif