summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNigel Metheringham <nigel@exim.org>2009-10-20 12:39:47 +0000
committerNigel Metheringham <nigel@exim.org>2009-10-20 12:39:47 +0000
commit92f9ced0f1ac270b78c3733ed259f4604d01af16 (patch)
tree43c3e5af0f7c9daac7756cfb894b995032a6b3dc /src
parent482d1455ebb7a291d9ee39a337e5837d8bc3feba (diff)
Improvements to local interface IP addr detection. Fixes: #802
Diffstat (limited to 'src')
-rw-r--r--src/OS/os.h-NetBSD3
-rw-r--r--src/src/os.c82
2 files changed, 75 insertions, 10 deletions
diff --git a/src/OS/os.h-NetBSD b/src/OS/os.h-NetBSD
index 1d6d07070..234f51c18 100644
--- a/src/OS/os.h-NetBSD
+++ b/src/OS/os.h-NetBSD
@@ -1,8 +1,9 @@
-/* $Cambridge: exim/src/OS/os.h-NetBSD,v 1.4 2007/06/27 08:46:28 ph10 Exp $ */
+/* $Cambridge: exim/src/OS/os.h-NetBSD,v 1.5 2009/10/20 12:39:47 nm4 Exp $ */
/* Exim: OS-specific C header file for NetBSD */
#define HAVE_BSD_GETLOADAVG
+#define HAVE_GETIFADDRS
#define HAVE_MMAP
#define HAVE_SYS_MOUNT_H
#define SIOCGIFCONF_GIVES_ADDR
diff --git a/src/src/os.c b/src/src/os.c
index 6a9ed3b73..f9ddbe1a2 100644
--- a/src/src/os.c
+++ b/src/src/os.c
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/os.c,v 1.6 2007/01/08 10:50:18 ph10 Exp $ */
+/* $Cambridge: exim/src/src/os.c,v 1.7 2009/10/20 12:39:47 nm4 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -463,6 +463,75 @@ calls the common function; on Linux it calls the Linux function.
This function finds the addresses of all the running interfaces on the machine.
A chain of blocks containing the textual form of the addresses is returned.
+getifaddrs() provides a sane consistent way to query this on modern OSs,
+otherwise fall back to a maze of twisty ioctl() calls
+
+Arguments: none
+Returns: a chain of ip_address_items, each pointing to a textual
+ version of an IP address, with the port field set to zero
+*/
+
+
+#ifndef NO_FIND_INTERFACES
+
+#ifdef HAVE_GETIFADDRS
+
+#include <ifaddrs.h>
+
+ip_address_item *
+os_common_find_running_interfaces(void)
+{
+struct ifaddrs *ifalist = NULL;
+ip_address_item *yield = NULL;
+ip_address_item *last = NULL;
+ip_address_item *next;
+
+if (getifaddrs(&ifalist) != 0)
+ log_write(0, LOG_PANIC_DIE, "Unable to call getifaddrs: %d %s",
+ errno, strerror(errno));
+
+struct ifaddrs *ifa;
+for (ifa = ifalist; ifa != NULL; ifa = ifa->ifa_next)
+ {
+ if (ifa->ifa_addr->sa_family != AF_INET
+#if HAVE_IPV6
+ && ifa->ifa_addr->sa_family != AF_INET6
+#endif /* HAVE_IPV6 */
+ )
+ continue;
+
+ if ( !(ifa->ifa_flags & IFF_UP) ) /* Only want 'UP' interfaces */
+ continue;
+
+ /* Create a data block for the address, fill in the data, and put it on the
+ chain. */
+
+ next = store_get(sizeof(ip_address_item));
+ next->next = NULL;
+ next->port = 0;
+ (void)host_ntoa(-1, ifa->ifa_addr, next->address, NULL);
+
+ if (yield == NULL)
+ yield = last = next;
+ else
+ {
+ last->next = next;
+ last = next;
+ }
+
+ DEBUG(D_interface) debug_printf("Actual local interface address is %s (%s)\n",
+ last->address, ifa->ifa_name);
+ }
+
+/* free the list of addresses, and return the chain of data blocks. */
+
+freeifaddrs (ifalist);
+return yield;
+}
+
+#else /* HAVE_GETIFADDRS */
+
+/*
Problems:
(1) Solaris 2 has the SIOGIFNUM call to get the number of interfaces, but
@@ -486,15 +555,8 @@ Problems:
the former, calling the latter does no harm, but it causes grief on Linux and
BSD systems in the case of IP aliasing, so a means of cutting it out is
provided.
-
-Arguments: none
-Returns: a chain of ip_address_items, each pointing to a textual
- version of an IP address, with the port field set to zero
*/
-
-#ifndef NO_FIND_INTERFACES
-
/* If there is IPv6 support, and SIOCGLIFCONF is defined, define macros to
use these new, longer versions of the old IPv4 interfaces. Otherwise, define
the macros to use the historical versions. */
@@ -556,7 +618,7 @@ char *cp;
char buf[MAX_INTERFACES*sizeof(struct V_ifreq)];
struct sockaddr *addrp;
size_t len = 0;
-char addrbuf[256];
+char addrbuf[512];
/* We have to create a socket in order to do ioctls on it to find out
what we want to know. */
@@ -701,6 +763,8 @@ for (cp = buf; cp < buf + ifc.V_ifc_len; cp += len)
return yield;
}
+#endif /* HAVE_GETIFADDRS */
+
#else /* NO_FIND_INTERFACES */
/* Some experimental or developing OS (e.g. GNU/Hurd) do not have the ioctls,