|
|
c8bb8f |
From c09dd24a7d63988e0acef7d033bd3e088fc005c0 Mon Sep 17 00:00:00 2001
|
|
|
c8bb8f |
From: Jiri Popelka <jpopelka@redhat.com>
|
|
|
c8bb8f |
Date: Thu, 24 Jan 2013 12:39:50 +0100
|
|
|
c8bb8f |
Subject: [PATCH] Linux interface discovery
|
|
|
c8bb8f |
|
|
|
c8bb8f |
Use the same discovery code as for *BSD and OS X,
|
|
|
c8bb8f |
i.e. the getifaddrs() function.
|
|
|
c8bb8f |
---
|
|
|
c8bb8f |
common/discover.c | 398 +++---------------------------------------------------
|
|
|
c8bb8f |
1 file changed, 17 insertions(+), 381 deletions(-)
|
|
|
c8bb8f |
|
|
|
c8bb8f |
diff --git a/common/discover.c b/common/discover.c
|
|
|
c8bb8f |
index 1d84219..f2a8f6d 100644
|
|
|
c8bb8f |
--- a/common/discover.c
|
|
|
c8bb8f |
+++ b/common/discover.c
|
|
|
c8bb8f |
@@ -379,391 +379,13 @@ end_iface_scan(struct iface_conf_list *ifaces) {
|
|
|
c8bb8f |
ifaces->sock = -1;
|
|
|
c8bb8f |
}
|
|
|
c8bb8f |
|
|
|
c8bb8f |
-#elif __linux /* !HAVE_SIOCGLIFCONF */
|
|
|
c8bb8f |
-/*
|
|
|
c8bb8f |
- * Linux support
|
|
|
c8bb8f |
- * -------------
|
|
|
c8bb8f |
- *
|
|
|
c8bb8f |
- * In Linux, we use the /proc pseudo-filesystem to get information
|
|
|
c8bb8f |
- * about interfaces, along with selected ioctl() calls.
|
|
|
c8bb8f |
- *
|
|
|
c8bb8f |
- * Linux low level access is documented in the netdevice man page.
|
|
|
c8bb8f |
- */
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
-/*
|
|
|
c8bb8f |
- * Structure holding state about the scan.
|
|
|
c8bb8f |
- */
|
|
|
c8bb8f |
-struct iface_conf_list {
|
|
|
c8bb8f |
- int sock; /* file descriptor used to get information */
|
|
|
c8bb8f |
- FILE *fp; /* input from /proc/net/dev */
|
|
|
c8bb8f |
-#ifdef DHCPv6
|
|
|
c8bb8f |
- FILE *fp6; /* input from /proc/net/if_inet6 */
|
|
|
c8bb8f |
-#endif
|
|
|
c8bb8f |
-};
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
-/*
|
|
|
c8bb8f |
- * Structure used to return information about a specific interface.
|
|
|
c8bb8f |
- */
|
|
|
c8bb8f |
-struct iface_info {
|
|
|
c8bb8f |
- char name[IFNAMSIZ]; /* name of the interface, e.g. "eth0" */
|
|
|
c8bb8f |
- struct sockaddr_storage addr; /* address information */
|
|
|
c8bb8f |
- isc_uint64_t flags; /* interface flags, e.g. IFF_LOOPBACK */
|
|
|
c8bb8f |
-};
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
-/*
|
|
|
c8bb8f |
- * Start a scan of interfaces.
|
|
|
c8bb8f |
- *
|
|
|
c8bb8f |
- * The iface_conf_list structure maintains state for this process.
|
|
|
c8bb8f |
- */
|
|
|
c8bb8f |
-int
|
|
|
c8bb8f |
-begin_iface_scan(struct iface_conf_list *ifaces) {
|
|
|
c8bb8f |
- char buf[256];
|
|
|
c8bb8f |
- int len;
|
|
|
c8bb8f |
- int i;
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
- ifaces->fp = fopen("/proc/net/dev", "r");
|
|
|
c8bb8f |
- if (ifaces->fp == NULL) {
|
|
|
c8bb8f |
- log_error("Error opening '/proc/net/dev' to list interfaces");
|
|
|
c8bb8f |
- return 0;
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
- /*
|
|
|
c8bb8f |
- * The first 2 lines are header information, so read and ignore them.
|
|
|
c8bb8f |
- */
|
|
|
c8bb8f |
- for (i=0; i<2; i++) {
|
|
|
c8bb8f |
- if (fgets(buf, sizeof(buf), ifaces->fp) == NULL) {
|
|
|
c8bb8f |
- log_error("Error reading headers from '/proc/net/dev'");
|
|
|
c8bb8f |
- fclose(ifaces->fp);
|
|
|
c8bb8f |
- ifaces->fp = NULL;
|
|
|
c8bb8f |
- return 0;
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
- len = strlen(buf);
|
|
|
c8bb8f |
- if ((len <= 0) || (buf[len-1] != '\n')) {
|
|
|
c8bb8f |
- log_error("Bad header line in '/proc/net/dev'");
|
|
|
c8bb8f |
- fclose(ifaces->fp);
|
|
|
c8bb8f |
- ifaces->fp = NULL;
|
|
|
c8bb8f |
- return 0;
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
- ifaces->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
|
|
c8bb8f |
- if (ifaces->sock < 0) {
|
|
|
c8bb8f |
- log_error("Error creating socket to list interfaces; %m");
|
|
|
c8bb8f |
- fclose(ifaces->fp);
|
|
|
c8bb8f |
- ifaces->fp = NULL;
|
|
|
c8bb8f |
- return 0;
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
-#ifdef DHCPv6
|
|
|
c8bb8f |
- if (local_family == AF_INET6) {
|
|
|
c8bb8f |
- ifaces->fp6 = fopen("/proc/net/if_inet6", "r");
|
|
|
c8bb8f |
- if (ifaces->fp6 == NULL) {
|
|
|
c8bb8f |
- log_error("Error opening '/proc/net/if_inet6' to "
|
|
|
c8bb8f |
- "list IPv6 interfaces; %m");
|
|
|
c8bb8f |
- close(ifaces->sock);
|
|
|
c8bb8f |
- ifaces->sock = -1;
|
|
|
c8bb8f |
- fclose(ifaces->fp);
|
|
|
c8bb8f |
- ifaces->fp = NULL;
|
|
|
c8bb8f |
- return 0;
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
-#endif
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
- return 1;
|
|
|
c8bb8f |
-}
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
-/*
|
|
|
c8bb8f |
- * Read our IPv4 interfaces from /proc/net/dev.
|
|
|
c8bb8f |
- *
|
|
|
c8bb8f |
- * The file looks something like this:
|
|
|
c8bb8f |
- *
|
|
|
c8bb8f |
- * Inter-| Receive ...
|
|
|
c8bb8f |
- * face |bytes packets errs drop fifo frame ...
|
|
|
c8bb8f |
- * lo: 1580562 4207 0 0 0 0 ...
|
|
|
c8bb8f |
- * eth0: 0 0 0 0 0 0 ...
|
|
|
c8bb8f |
- * eth1:1801552440 37895 0 14 0 ...
|
|
|
c8bb8f |
- *
|
|
|
c8bb8f |
- * We only care about the interface name, which is at the start of
|
|
|
c8bb8f |
- * each line.
|
|
|
c8bb8f |
- *
|
|
|
c8bb8f |
- * We use an ioctl() to get the address and flags for each interface.
|
|
|
c8bb8f |
- */
|
|
|
c8bb8f |
-static int
|
|
|
c8bb8f |
-next_iface4(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
|
|
|
c8bb8f |
- char buf[256];
|
|
|
c8bb8f |
- int len;
|
|
|
c8bb8f |
- char *p;
|
|
|
c8bb8f |
- char *name;
|
|
|
c8bb8f |
- struct ifreq tmp;
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
- /*
|
|
|
c8bb8f |
- * Loop exits when we find an interface that has an address, or
|
|
|
c8bb8f |
- * when we run out of interfaces.
|
|
|
c8bb8f |
- */
|
|
|
c8bb8f |
- for (;;) {
|
|
|
c8bb8f |
- do {
|
|
|
c8bb8f |
- /*
|
|
|
c8bb8f |
- * Read the next line in the file.
|
|
|
c8bb8f |
- */
|
|
|
c8bb8f |
- if (fgets(buf, sizeof(buf), ifaces->fp) == NULL) {
|
|
|
c8bb8f |
- if (ferror(ifaces->fp)) {
|
|
|
c8bb8f |
- *err = 1;
|
|
|
c8bb8f |
- log_error("Error reading interface "
|
|
|
c8bb8f |
- "information");
|
|
|
c8bb8f |
- } else {
|
|
|
c8bb8f |
- *err = 0;
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
- return 0;
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
- /*
|
|
|
c8bb8f |
- * Make sure the line is a nice,
|
|
|
c8bb8f |
- * newline-terminated line.
|
|
|
c8bb8f |
- */
|
|
|
c8bb8f |
- len = strlen(buf);
|
|
|
c8bb8f |
- if ((len <= 0) || (buf[len-1] != '\n')) {
|
|
|
c8bb8f |
- log_error("Bad line reading interface "
|
|
|
c8bb8f |
- "information");
|
|
|
c8bb8f |
- *err = 1;
|
|
|
c8bb8f |
- return 0;
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
- /*
|
|
|
c8bb8f |
- * Figure out our name.
|
|
|
c8bb8f |
- */
|
|
|
c8bb8f |
- p = strrchr(buf, ':');
|
|
|
c8bb8f |
- if (p == NULL) {
|
|
|
c8bb8f |
- log_error("Bad line reading interface "
|
|
|
c8bb8f |
- "information (no colon)");
|
|
|
c8bb8f |
- *err = 1;
|
|
|
c8bb8f |
- return 0;
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
- *p = '\0';
|
|
|
c8bb8f |
- name = buf;
|
|
|
c8bb8f |
- while (isspace(*name)) {
|
|
|
c8bb8f |
- name++;
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
- /*
|
|
|
c8bb8f |
- * Copy our name into our interface structure.
|
|
|
c8bb8f |
- */
|
|
|
c8bb8f |
- len = p - name;
|
|
|
c8bb8f |
- if (len >= sizeof(info->name)) {
|
|
|
c8bb8f |
- *err = 1;
|
|
|
c8bb8f |
- log_error("Interface name '%s' too long", name);
|
|
|
c8bb8f |
- return 0;
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
- strcpy(info->name, name);
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
-#ifdef ALIAS_NAMED_PERMUTED
|
|
|
c8bb8f |
- /* interface aliases look like "eth0:1" or "wlan1:3" */
|
|
|
c8bb8f |
- s = strchr(info->name, ':');
|
|
|
c8bb8f |
- if (s != NULL) {
|
|
|
c8bb8f |
- *s = '\0';
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
-#endif
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
-#ifdef SKIP_DUMMY_INTERFACES
|
|
|
c8bb8f |
- } while (strncmp(info->name, "dummy", 5) == 0);
|
|
|
c8bb8f |
-#else
|
|
|
c8bb8f |
- } while (0);
|
|
|
c8bb8f |
-#endif
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
- memset(&tmp, 0, sizeof(tmp));
|
|
|
c8bb8f |
- strcpy(tmp.ifr_name, name);
|
|
|
c8bb8f |
- if (ioctl(ifaces->sock, SIOCGIFADDR, &tmp) < 0) {
|
|
|
c8bb8f |
- if (errno == EADDRNOTAVAIL) {
|
|
|
c8bb8f |
- continue;
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
- log_error("Error getting interface address "
|
|
|
c8bb8f |
- "for '%s'; %m", name);
|
|
|
c8bb8f |
- *err = 1;
|
|
|
c8bb8f |
- return 0;
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
- memcpy(&info->addr, &tmp.ifr_addr, sizeof(tmp.ifr_addr));
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
- memset(&tmp, 0, sizeof(tmp));
|
|
|
c8bb8f |
- strcpy(tmp.ifr_name, name);
|
|
|
c8bb8f |
- if (ioctl(ifaces->sock, SIOCGIFFLAGS, &tmp) < 0) {
|
|
|
c8bb8f |
- log_error("Error getting interface flags for '%s'; %m",
|
|
|
c8bb8f |
- name);
|
|
|
c8bb8f |
- *err = 1;
|
|
|
c8bb8f |
- return 0;
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
- info->flags = tmp.ifr_flags;
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
- *err = 0;
|
|
|
c8bb8f |
- return 1;
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
-}
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
-#ifdef DHCPv6
|
|
|
c8bb8f |
-/*
|
|
|
c8bb8f |
- * Read our IPv6 interfaces from /proc/net/if_inet6.
|
|
|
c8bb8f |
- *
|
|
|
c8bb8f |
- * The file looks something like this:
|
|
|
c8bb8f |
- *
|
|
|
c8bb8f |
- * fe80000000000000025056fffec00008 05 40 20 80 vmnet8
|
|
|
c8bb8f |
- * 00000000000000000000000000000001 01 80 10 80 lo
|
|
|
c8bb8f |
- * fe80000000000000025056fffec00001 06 40 20 80 vmnet1
|
|
|
c8bb8f |
- * 200108881936000202166ffffe497d9b 03 40 00 00 eth1
|
|
|
c8bb8f |
- * fe8000000000000002166ffffe497d9b 03 40 20 80 eth1
|
|
|
c8bb8f |
- *
|
|
|
c8bb8f |
- * We get IPv6 address from the start, the interface name from the end,
|
|
|
c8bb8f |
- * and ioctl() to get flags.
|
|
|
c8bb8f |
- */
|
|
|
c8bb8f |
-static int
|
|
|
c8bb8f |
-next_iface6(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
|
|
|
c8bb8f |
- char buf[256];
|
|
|
c8bb8f |
- int len;
|
|
|
c8bb8f |
- char *p;
|
|
|
c8bb8f |
- char *name;
|
|
|
c8bb8f |
- int i;
|
|
|
c8bb8f |
- struct sockaddr_in6 addr;
|
|
|
c8bb8f |
- struct ifreq tmp;
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
- do {
|
|
|
c8bb8f |
- /*
|
|
|
c8bb8f |
- * Read the next line in the file.
|
|
|
c8bb8f |
- */
|
|
|
c8bb8f |
- if (fgets(buf, sizeof(buf), ifaces->fp6) == NULL) {
|
|
|
c8bb8f |
- if (ferror(ifaces->fp6)) {
|
|
|
c8bb8f |
- *err = 1;
|
|
|
c8bb8f |
- log_error("Error reading IPv6 "
|
|
|
c8bb8f |
- "interface information");
|
|
|
c8bb8f |
- } else {
|
|
|
c8bb8f |
- *err = 0;
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
- return 0;
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
- /*
|
|
|
c8bb8f |
- * Make sure the line is a nice, newline-terminated line.
|
|
|
c8bb8f |
- */
|
|
|
c8bb8f |
- len = strlen(buf);
|
|
|
c8bb8f |
- if ((len <= 0) || (buf[len-1] != '\n')) {
|
|
|
c8bb8f |
- log_error("Bad line reading IPv6 "
|
|
|
c8bb8f |
- "interface information");
|
|
|
c8bb8f |
- *err = 1;
|
|
|
c8bb8f |
- return 0;
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
- /*
|
|
|
c8bb8f |
- * Figure out our name.
|
|
|
c8bb8f |
- */
|
|
|
c8bb8f |
- buf[--len] = '\0';
|
|
|
c8bb8f |
- p = strrchr(buf, ' ');
|
|
|
c8bb8f |
- if (p == NULL) {
|
|
|
c8bb8f |
- log_error("Bad line reading IPv6 interface "
|
|
|
c8bb8f |
- "information (no space)");
|
|
|
c8bb8f |
- *err = 1;
|
|
|
c8bb8f |
- return 0;
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
- name = p+1;
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
- /*
|
|
|
c8bb8f |
- * Copy our name into our interface structure.
|
|
|
c8bb8f |
- */
|
|
|
c8bb8f |
- len = strlen(name);
|
|
|
c8bb8f |
- if (len >= sizeof(info->name)) {
|
|
|
c8bb8f |
- *err = 1;
|
|
|
c8bb8f |
- log_error("IPv6 interface name '%s' too long", name);
|
|
|
c8bb8f |
- return 0;
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
- strcpy(info->name, name);
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
-#ifdef SKIP_DUMMY_INTERFACES
|
|
|
c8bb8f |
- } while (strncmp(info->name, "dummy", 5) == 0);
|
|
|
c8bb8f |
-#else
|
|
|
c8bb8f |
- } while (0);
|
|
|
c8bb8f |
-#endif
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
- /*
|
|
|
c8bb8f |
- * Double-check we start with the IPv6 address.
|
|
|
c8bb8f |
- */
|
|
|
c8bb8f |
- for (i=0; i<32; i++) {
|
|
|
c8bb8f |
- if (!isxdigit(buf[i]) || isupper(buf[i])) {
|
|
|
c8bb8f |
- *err = 1;
|
|
|
c8bb8f |
- log_error("Bad line reading IPv6 interface address "
|
|
|
c8bb8f |
- "for '%s'", name);
|
|
|
c8bb8f |
- return 0;
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
- /*
|
|
|
c8bb8f |
- * Load our socket structure.
|
|
|
c8bb8f |
- */
|
|
|
c8bb8f |
- memset(&addr, 0, sizeof(addr));
|
|
|
c8bb8f |
- addr.sin6_family = AF_INET6;
|
|
|
c8bb8f |
- for (i=0; i<16; i++) {
|
|
|
c8bb8f |
- unsigned char byte;
|
|
|
c8bb8f |
- static const char hex[] = "0123456789abcdef";
|
|
|
c8bb8f |
- byte = ((index(hex, buf[i * 2]) - hex) << 4) |
|
|
|
c8bb8f |
- (index(hex, buf[i * 2 + 1]) - hex);
|
|
|
c8bb8f |
- addr.sin6_addr.s6_addr[i] = byte;
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
- memcpy(&info->addr, &addr, sizeof(addr));
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
- /*
|
|
|
c8bb8f |
- * Get our flags.
|
|
|
c8bb8f |
- */
|
|
|
c8bb8f |
- memset(&tmp, 0, sizeof(tmp));
|
|
|
c8bb8f |
- strcpy(tmp.ifr_name, name);
|
|
|
c8bb8f |
- if (ioctl(ifaces->sock, SIOCGIFFLAGS, &tmp) < 0) {
|
|
|
c8bb8f |
- log_error("Error getting interface flags for '%s'; %m", name);
|
|
|
c8bb8f |
- *err = 1;
|
|
|
c8bb8f |
- return 0;
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
- info->flags = tmp.ifr_flags;
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
- *err = 0;
|
|
|
c8bb8f |
- return 1;
|
|
|
c8bb8f |
-}
|
|
|
c8bb8f |
-#endif /* DHCPv6 */
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
-/*
|
|
|
c8bb8f |
- * Retrieve the next interface.
|
|
|
c8bb8f |
- *
|
|
|
c8bb8f |
- * Returns information in the info structure.
|
|
|
c8bb8f |
- * Sets err to 1 if there is an error, otherwise 0.
|
|
|
c8bb8f |
- */
|
|
|
c8bb8f |
-int
|
|
|
c8bb8f |
-next_iface(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
|
|
|
c8bb8f |
- if (next_iface4(info, err, ifaces)) {
|
|
|
c8bb8f |
- return 1;
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
-#ifdef DHCPv6
|
|
|
c8bb8f |
- if (!(*err)) {
|
|
|
c8bb8f |
- if (local_family == AF_INET6)
|
|
|
c8bb8f |
- return next_iface6(info, err, ifaces);
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
-#endif
|
|
|
c8bb8f |
- return 0;
|
|
|
c8bb8f |
-}
|
|
|
c8bb8f |
-
|
|
|
c8bb8f |
-/*
|
|
|
c8bb8f |
- * End scan of interfaces.
|
|
|
c8bb8f |
- */
|
|
|
c8bb8f |
-void
|
|
|
c8bb8f |
-end_iface_scan(struct iface_conf_list *ifaces) {
|
|
|
c8bb8f |
- fclose(ifaces->fp);
|
|
|
c8bb8f |
- ifaces->fp = NULL;
|
|
|
c8bb8f |
- close(ifaces->sock);
|
|
|
c8bb8f |
- ifaces->sock = -1;
|
|
|
c8bb8f |
-#ifdef DHCPv6
|
|
|
c8bb8f |
- if (local_family == AF_INET6) {
|
|
|
c8bb8f |
- fclose(ifaces->fp6);
|
|
|
c8bb8f |
- ifaces->fp6 = NULL;
|
|
|
c8bb8f |
- }
|
|
|
c8bb8f |
-#endif
|
|
|
c8bb8f |
-}
|
|
|
c8bb8f |
#else
|
|
|
c8bb8f |
|
|
|
c8bb8f |
/*
|
|
|
c8bb8f |
* BSD support
|
|
|
c8bb8f |
* -----------
|
|
|
c8bb8f |
*
|
|
|
c8bb8f |
- * FreeBSD, NetBSD, OpenBSD, and OS X all have the getifaddrs()
|
|
|
c8bb8f |
+ * FreeBSD, NetBSD, OpenBSD, OS X and Linux all have the getifaddrs()
|
|
|
c8bb8f |
* function.
|
|
|
c8bb8f |
*
|
|
|
c8bb8f |
* The getifaddrs() man page describes the use.
|
|
|
c8bb8f |
@@ -811,6 +433,8 @@ begin_iface_scan(struct iface_conf_list *ifaces) {
|
|
|
c8bb8f |
*/
|
|
|
c8bb8f |
int
|
|
|
c8bb8f |
next_iface(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
|
|
|
c8bb8f |
+ size_t sa_len = 0;
|
|
|
c8bb8f |
+
|
|
|
c8bb8f |
if (ifaces->next == NULL) {
|
|
|
c8bb8f |
*err = 0;
|
|
|
c8bb8f |
return 0;
|
|
|
c8bb8f |
@@ -822,8 +446,20 @@ next_iface(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
|
|
|
c8bb8f |
return 0;
|
|
|
c8bb8f |
}
|
|
|
c8bb8f |
strcpy(info->name, ifaces->next->ifa_name);
|
|
|
c8bb8f |
- memcpy(&info->addr, ifaces->next->ifa_addr,
|
|
|
c8bb8f |
- ifaces->next->ifa_addr->sa_len);
|
|
|
c8bb8f |
+
|
|
|
c8bb8f |
+ memset(&info->addr, 0 , sizeof(info->addr));
|
|
|
c8bb8f |
+
|
|
|
c8bb8f |
+ if (ifaces->next->ifa_addr != NULL) {
|
|
|
c8bb8f |
+#ifdef HAVE_SA_LEN
|
|
|
c8bb8f |
+ sa_len = ifaces->next->ifa_addr->sa_len;
|
|
|
c8bb8f |
+#else
|
|
|
c8bb8f |
+ if (ifaces->next->ifa_addr->sa_family == AF_INET)
|
|
|
c8bb8f |
+ sa_len = sizeof(struct sockaddr_in);
|
|
|
c8bb8f |
+ else if (ifaces->next->ifa_addr->sa_family == AF_INET6)
|
|
|
c8bb8f |
+ sa_len = sizeof(struct sockaddr_in6);
|
|
|
c8bb8f |
+#endif
|
|
|
c8bb8f |
+ memcpy(&info->addr, ifaces->next->ifa_addr, sa_len);
|
|
|
c8bb8f |
+ }
|
|
|
c8bb8f |
info->flags = ifaces->next->ifa_flags;
|
|
|
c8bb8f |
ifaces->next = ifaces->next->ifa_next;
|
|
|
c8bb8f |
*err = 0;
|
|
|
c8bb8f |
--
|
|
|
c8bb8f |
1.8.1
|
|
|
c8bb8f |
|