From: Roy Marples Date: Sun, 19 Jan 2014 22:35:52 +0000 (+0000) Subject: Detect IPv6 address flags at interface discovery on Linux. X-Git-Tag: v6.3.0~104 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5e2809cafc22107144da27856fff40ec9507ae72;p=thirdparty%2Fdhcpcd.git Detect IPv6 address flags at interface discovery on Linux. --- diff --git a/if-linux.c b/if-linux.c index dd340a4c..c937380b 100644 --- a/if-linux.c +++ b/if-linux.c @@ -833,11 +833,40 @@ if_route6(const struct rt6 *rt, int action) } int -in6_addr_flags(__unused const char *ifname, - __unused const struct in6_addr *addr) +in6_addr_flags(const char *ifname, const struct in6_addr *addr) { + FILE *fp; + char *ent, address[33], name[IF_NAMESIZE + 1]; + unsigned int ifindex; + int prefix, scope, flags, i, ret; + struct in6_addr addr6; + static const char *hex = "0123456789abcdef"; - /* How do I get IPv6 address flags on Linux? */ - return 0; + fp = fopen("/proc/net/if_inet6", "r"); + if (fp == NULL) + return -1; + while ((ent = get_line(fp))) { + i = sscanf(ent, "%32[a-f0-9] %x %x %x %x %16s\n", + address, &ifindex, &prefix, &scope, &flags, name); + if (i != 6 || strlen(address) != 32) { + fclose(fp); + errno = ENOTSUP; + return -1; + } + if (strcmp(ifname, name)) + continue; + for (i = 0; i < 16; i++) { + addr6.s6_addr[i] = + ((strchr(hex, address[i * 2]) - hex) << 4) | + (strchr(hex, address[i * 2 + 1]) - hex); + } + if (IN6_ARE_ADDR_EQUAL(addr, &addr6)) { + fclose(fp); + return flags; + } + } + fclose(fp); + errno = ESRCH; + return -1; } #endif diff --git a/ipv6.c b/ipv6.c index a47c4fc5..3f3a1033 100644 --- a/ipv6.c +++ b/ipv6.c @@ -510,7 +510,7 @@ ipv6_handleifa(int cmd, struct if_head *ifs, const char *ifname, /* Safety, remove tentative addresses */ if (cmd == RTM_NEWADDR) { - if (flags & IN6_IFF_TENTATIVE) + if (flags & (IN6_IFF_TENTATIVE | IN6_IFF_DUPLICATED)) cmd = RTM_DELADDR; #ifdef IN6_IFF_DETACHED if (flags & IN6_IFF_DETACHED)