]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Detect IPv6 address flags at interface discovery on Linux.
authorRoy Marples <roy@marples.name>
Sun, 19 Jan 2014 22:35:52 +0000 (22:35 +0000)
committerRoy Marples <roy@marples.name>
Sun, 19 Jan 2014 22:35:52 +0000 (22:35 +0000)
if-linux.c
ipv6.c

index dd340a4c925fd48a1087cf6f0ab4584e19e55859..c937380baf8a688f9ceddeab265d7c8c4ecadde0 100644 (file)
@@ -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 a47c4fc53e6150232c4958ff955c417182544aed..3f3a103381491a5b31f28d14666d528179688e91 100644 (file)
--- 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)