Mercurial > hg > dhcpcd
changeset 2229:b3fca173d19c draft
Detect IPv6 address flags at interface discovery on Linux.
| author | Roy Marples <roy@marples.name> |
|---|---|
| date | Sun, 19 Jan 2014 22:35:52 +0000 |
| parents | 4c295fa3c929 |
| children | 6f64cbf7fa50 |
| files | if-linux.c ipv6.c |
| diffstat | 2 files changed, 34 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/if-linux.c Sat Jan 18 15:17:37 2014 +0000 +++ b/if-linux.c Sun Jan 19 22:35:52 2014 +0000 @@ -833,11 +833,40 @@ } 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
--- a/ipv6.c Sat Jan 18 15:17:37 2014 +0000 +++ b/ipv6.c Sun Jan 19 22:35:52 2014 +0000 @@ -510,7 +510,7 @@ /* 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)
