summaryrefslogtreecommitdiffstats
path: root/src/global/own_inet_addr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/global/own_inet_addr.c')
-rw-r--r--src/global/own_inet_addr.c315
1 files changed, 315 insertions, 0 deletions
diff --git a/src/global/own_inet_addr.c b/src/global/own_inet_addr.c
new file mode 100644
index 0000000..d164a20
--- /dev/null
+++ b/src/global/own_inet_addr.c
@@ -0,0 +1,315 @@
+/*++
+/* NAME
+/* own_inet_addr 3
+/* SUMMARY
+/* determine if IP address belongs to this mail system instance
+/* SYNOPSIS
+/* #include <own_inet_addr.h>
+/*
+/* 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 <sys_defs.h>
+#include <string.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <inet_addr_list.h>
+#include <inet_addr_local.h>
+#include <inet_addr_host.h>
+#include <stringops.h>
+#include <myaddrinfo.h>
+#include <sock_addr.h>
+#include <inet_proto.h>
+
+/* Global library. */
+
+#include <mail_params.h>
+#include <own_inet_addr.h>
+
+/* 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 <inet_proto.h>
+
+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