From e819beaaae502ccc92c565dfc1262c90c18a6c58 Mon Sep 17 00:00:00 2001 From: david Date: Sun, 22 Apr 2012 02:13:16 +0000 Subject: [PATCH] Make changes for IPv6-only interfaces on Solaris. First try SIOCGLIFFLAGS with an IPv4 socket, then again with an IPv6 socket if that fails. Use that same socket for the other ioctl queries. Avoid adding an IPv6 alias address that is the same as an IPv6 primary address. This is the same as an existing check in the IPv4 case. Fix a loop exit boundary condition check. --- libdnet-stripped/src/intf.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/libdnet-stripped/src/intf.c b/libdnet-stripped/src/intf.c index 2c3aa1df3..6fc17b4e7 100644 --- a/libdnet-stripped/src/intf.c +++ b/libdnet-stripped/src/intf.c @@ -143,7 +143,7 @@ intf_open(void) setsockopt(intf->fd, SOL_SOCKET, SO_BROADCAST, (const char *) &one, sizeof(one)); -#if defined(SIOCGIFNETMASK_IN6) || defined(SIOCGIFNETMASK6) +#if defined(SIOCGLIFCONF) || defined(SIOCGIFNETMASK_IN6) || defined(SIOCGIFNETMASK6) if ((intf->fd6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { # ifdef EPROTONOSUPPORT if (errno != EPROTONOSUPPORT) @@ -398,6 +398,7 @@ int _intf_get_noalias(intf_t *intf, struct intf_entry *entry) { struct lifreq lifr; + int fd; /* Get interface index. */ entry->intf_index = if_nametoindex(entry->intf_name); @@ -406,8 +407,14 @@ _intf_get_noalias(intf_t *intf, struct intf_entry *entry) strlcpy(lifr.lifr_name, entry->intf_name, sizeof(lifr.lifr_name)); - /* Get interface flags. */ - if (ioctl(intf->fd, SIOCGLIFFLAGS, &lifr) < 0) + /* Get interface flags. Here he also check whether we need to use fd or + * fd6 in the rest of the function. Using the wrong address family in + * the ioctls gives ENXIO on Solaris. */ + if (ioctl(intf->fd, SIOCGLIFFLAGS, &lifr) >= 0) + fd = intf->fd; + else if (intf->fd6 == -1 || ioctl(intf->fd6, SIOCGLIFFLAGS, &lifr) >= 0) + fd = intf->fd6; + else return (-1); entry->intf_flags = intf_iff_to_flags(lifr.lifr_flags); @@ -415,7 +422,7 @@ _intf_get_noalias(intf_t *intf, struct intf_entry *entry) /* Get interface MTU. */ #ifdef SIOCGLIFMTU - if (ioctl(intf->fd, SIOCGLIFMTU, &lifr) < 0) + if (ioctl(fd, SIOCGLIFMTU, &lifr) < 0) #endif return (-1); entry->intf_mtu = lifr.lifr_mtu; @@ -424,15 +431,15 @@ _intf_get_noalias(intf_t *intf, struct intf_entry *entry) entry->intf_link_addr.addr_type = ADDR_TYPE_NONE; /* Get primary interface address. */ - if (ioctl(intf->fd, SIOCGLIFADDR, &lifr) == 0) { + if (ioctl(fd, SIOCGLIFADDR, &lifr) == 0) { addr_ston((struct sockaddr *)&lifr.lifr_addr, &entry->intf_addr); - if (ioctl(intf->fd, SIOCGLIFNETMASK, &lifr) < 0) + if (ioctl(fd, SIOCGLIFNETMASK, &lifr) < 0) return (-1); addr_stob((struct sockaddr *)&lifr.lifr_addr, &entry->intf_addr.addr_bits); } /* Get other addresses. */ if (entry->intf_type == INTF_TYPE_TUN) { - if (ioctl(intf->fd, SIOCGLIFDSTADDR, &lifr) == 0) { + if (ioctl(fd, SIOCGLIFDSTADDR, &lifr) == 0) { if (addr_ston((struct sockaddr *)&lifr.lifr_addr, &entry->intf_dst_addr) < 0) return (-1); @@ -604,8 +611,11 @@ _intf_get_aliases(intf_t *intf, struct intf_entry *entry) if (ioctl(intf->fd, SIOCGIFNETMASK, &tmplifr) == 0) addr_stob((struct sockaddr *)&tmplifr.lifr_addr, &ap->addr_bits); } else if (ap->addr_type == ADDR_TYPE_IP6 && intf->fd6 != -1) { + if (memcmp(&ap->addr_ip6, &entry->intf_addr.addr_ip6, IP6_ADDR_LEN) == 0 || + memcmp(&ap->addr_ip6, &entry->intf_dst_addr.addr_ip6, IP6_ADDR_LEN) == 0) + continue; strlcpy(tmplifr.lifr_name, lifr->lifr_name, sizeof(tmplifr.lifr_name)); - if (ioctl(intf->fd, SIOCGLIFNETMASK, &tmplifr) == 0) { + if (ioctl(intf->fd6, SIOCGLIFNETMASK, &tmplifr) == 0) { addr_stob((struct sockaddr *)&tmplifr.lifr_addr, &ap->addr_bits); } @@ -909,7 +919,7 @@ intf_loop(intf_t *intf, intf_handler callback, void *arg) if (strcmp(lifr->lifr_name, plifr->lifr_name) == 0) break; } - if (lifr > intf->lifc.lifc_req && plifr < llifr) + if (lifr > intf->lifc.lifc_req && plifr < lifr) continue; memset(ebuf, 0, sizeof(ebuf));