From: Roy Marples Date: Sat, 18 May 2013 15:30:55 +0000 (+0000) Subject: Get local link address flags for supported OS's. X-Git-Tag: v5.99.7~54 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4e39089aa5ac779b5a2b5354a45eed9d6e4a18ed;p=thirdparty%2Fdhcpcd.git Get local link address flags for supported OS's. Just in-case they are tentative. --- diff --git a/net.c b/net.c index cbc71773..ef5ab5d1 100644 --- a/net.c +++ b/net.c @@ -31,9 +31,11 @@ #include #include +#include #ifdef AF_LINK # include # include +# include #endif #ifdef AF_PACKET # include @@ -217,6 +219,14 @@ discover_interfaces(int argc, char * const *argv) #ifdef __linux__ char ifn[IF_NAMESIZE]; #endif +#ifdef INET6 + const struct sockaddr_in6 *sin6; + int ifa_flags; +#ifdef SIOCGIFAFLAG_IN6 + struct in6_ifreq ifr6; + int s6; +#endif +#endif #ifdef AF_LINK const struct sockaddr_dl *sdl; #ifdef IFLR_ACTIVE @@ -231,9 +241,8 @@ discover_interfaces(int argc, char * const *argv) #elif AF_PACKET const struct sockaddr_ll *sll; #endif -#ifdef INET6 - const struct sockaddr_in6 *sin6; -#endif + + if (getifaddrs(&ifaddrs) == -1) return NULL; @@ -315,7 +324,8 @@ discover_interfaces(int argc, char * const *argv) if (up_interface(ifp) == 0) options |= DHCPCD_WAITUP; else - syslog(LOG_ERR, "%s: up_interface: %m", ifp->name); + syslog(LOG_ERR, "%s: up_interface: %m", + ifp->name); } sdl_type = 0; @@ -430,18 +440,47 @@ discover_interfaces(int argc, char * const *argv) #ifdef INET6 /* Capture local link addresses */ +#ifdef SIOCGIFAFLAG_IN6 + s6 = socket(AF_INET6, SOCK_DGRAM, 0); + if (s6 == -1) + syslog(LOG_ERR, "%s: socket: %m", __func__); +#endif + for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr != NULL && ifa->ifa_addr->sa_family == AF_INET6) { sin6 = (const struct sockaddr_in6 *) (void *)ifa->ifa_addr; - if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) - /* XXX: Check tentative, etc? */ + if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { +#ifdef SIOCGIFAFLAG_IN6 + memset(&ifr6, 0, sizeof(ifr6)); + strncpy(ifr6.ifr_name, ifa->ifa_name, + sizeof(ifr6.ifr_name)); + ifr6.ifr_addr = *sin6; + if (ioctl(s6, SIOCGIFAFLAG_IN6, &ifr6) == -1) { + syslog(LOG_ERR, + "%s: SIOCGIFAFLAG_IN6: %m", + ifa->ifa_name); + continue; + } + ifa_flags = ifr6.ifr_ifru.ifru_flags6; +#else + /* We have no way of getting the address flags + * such as tentative on Linux at this point. + * We have to hope that getifaddrs only returns + * useable addresses. */ + ifa_flags = 0; +#endif ipv6_handleifa(RTM_NEWADDR, ifs, ifa->ifa_name, - &sin6->sin6_addr, 0); + &sin6->sin6_addr, ifa_flags); + } } } +#ifdef SIOCGIFAFLAG_IN6 + if (s6 != -1) + close(s6); +#endif #endif freeifaddrs(ifaddrs);