]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Adjust link-local scope for KAME based stacks in all needed places.
authorRoy Marples <roy@marples.name>
Sun, 5 Oct 2014 11:03:07 +0000 (11:03 +0000)
committerRoy Marples <roy@marples.name>
Sun, 5 Oct 2014 11:03:07 +0000 (11:03 +0000)
if-bsd.c
if-linux.c
if-sun.c
if.c
if.h
ipv6.c

index 6403fb84285d99034a10e2e01fb76968ef3ae28f..7d54e53029a47352ba5e9243b85bb30354134ba3 100644 (file)
--- a/if-bsd.c
+++ b/if-bsd.c
@@ -548,6 +548,27 @@ if_route(const struct rt *rt, int action)
 #endif
 
 #ifdef INET6
+static void
+ifa_scope(struct sockaddr_in6 *sin, unsigned int index)
+{
+
+#ifdef __KAME__
+       /* KAME based systems want to store the scope inside the sin6_addr
+        * for link local addreses */
+       if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr)) {
+               uint16_t scope = htons(index);
+               memcpy(&sin->sin6_addr.s6_addr[2], &scope,
+                   sizeof(scope));
+       }
+       sin->sin6_scope_id = 0;
+#else
+       if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr))
+               sin->sin6_scope_id = index;
+       else
+               sin->sin6_scope_id = 0;
+#endif
+}
+
 int
 if_address6(const struct ipv6_addr *a, int action)
 {
@@ -580,6 +601,7 @@ if_address6(const struct ipv6_addr *a, int action)
        }
 
        ADDADDR(&ifa.ifra_addr, &a->addr);
+       ifa_scope(&ifa.ifra_addr, a->iface->index);
        ipv6_mask(&mask, a->prefix_len);
        ADDADDR(&ifa.ifra_prefixmask, &mask);
        ifa.ifra_lifetime.ia6t_vltime = a->prefix_vltime;
@@ -613,21 +635,6 @@ if_route6(const struct rt6 *rt, int action)
        if ((s = socket(PF_ROUTE, SOCK_RAW, 0)) == -1)
                return -1;
 
-/* KAME based systems want to store the scope inside the sin6_addr
- * for link local addreses */
-#ifdef __KAME__
-#define SCOPE {                                                                      \
-               if (IN6_IS_ADDR_LINKLOCAL(&su.sin.sin6_addr)) {               \
-                       uint16_t scope = htons(su.sin.sin6_scope_id);         \
-                       memcpy(&su.sin.sin6_addr.s6_addr[2], &scope,          \
-                           sizeof(scope));                                   \
-                       su.sin.sin6_scope_id = 0;                             \
-               }                                                             \
-       }
-#else
-#define SCOPE
-#endif
-
 #define ADDSU {                                                                      \
                l = RT_ROUNDUP(su.sa.sa_len);                                 \
                memcpy(bp, &su, l);                                           \
@@ -638,8 +645,8 @@ if_route6(const struct rt6 *rt, int action)
                su.sin.sin6_family = AF_INET6;                                \
                su.sin.sin6_len = sizeof(su.sin);                             \
                (&su.sin)->sin6_addr = *addr;                                 \
-               su.sin.sin6_scope_id = scope;                                 \
-               SCOPE;                                                        \
+               if (scope)                                                    \
+                       ifa_scope(&su.sin, scope);                            \
                ADDSU;                                                        \
        }
 #define ADDADDR(addr) ADDADDRS(addr, 0)
@@ -681,9 +688,7 @@ if_route6(const struct rt6 *rt, int action)
                                return -1;
                        ADDADDRS(&lla->addr, rt->iface->index);
                } else {
-                       ADDADDRS(&rt->gate,
-                           IN6_ARE_ADDR_EQUAL(&rt->gate, &in6addr_loopback)
-                           ? 0 : rt->iface->index);
+                       ADDADDR(&rt->gate);
                }
        }
 
@@ -709,7 +714,6 @@ if_route6(const struct rt6 *rt, int action)
 
 #undef ADDADDR
 #undef ADDSU
-#undef SCOPE
 
        if (action >= 0 && rt->mtu) {
                rtm.hdr.rtm_inits |= RTV_MTU;
@@ -745,7 +749,7 @@ get_addrs(int type, char *cp, struct sockaddr **sa)
 
 #ifdef INET6
 int
-if_addrflags6(const char *ifname, const struct in6_addr *addr)
+if_addrflags6(const struct in6_addr *addr, const struct interface *ifp)
 {
        int s, flags;
        struct in6_ifreq ifr6;
@@ -754,9 +758,10 @@ if_addrflags6(const char *ifname, const struct in6_addr *addr)
        flags = -1;
        if (s != -1) {
                memset(&ifr6, 0, sizeof(ifr6));
-               strncpy(ifr6.ifr_name, ifname, sizeof(ifr6.ifr_name));
+               strncpy(ifr6.ifr_name, ifp->name, sizeof(ifr6.ifr_name));
                ifr6.ifr_addr.sin6_family = AF_INET6;
                ifr6.ifr_addr.sin6_addr = *addr;
+               ifa_scope(&ifr6.ifr_addr, ifp->index);
                if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) != -1)
                        flags = ifr6.ifr_ifru.ifru_flags6;
                close(s);
@@ -918,8 +923,7 @@ if_managelink(struct dhcpcd_ctx *ctx)
                                        ia6.s6_addr[2] = ia6.s6_addr[3] = '\0';
 #endif
                                if (rtm->rtm_type == RTM_NEWADDR) {
-                                       ifa_flags = if_addrflags6(ifp->name,
-                                           &ia6);
+                                       ifa_flags = if_addrflags6(&ia6, ifp);
                                        if (ifa_flags == -1)
                                                break;
                                } else
index 19416feaf1740549d15b568f37ca76c70668843f..c6496c5110697e1f0851669526596a5c814bfd5f 100644 (file)
@@ -1448,7 +1448,7 @@ if_route6(const struct rt6 *rt, int action)
 }
 
 int
-if_addrflags6(const char *ifname, const struct in6_addr *addr)
+if_addrflags6(const struct in6_addr *addr, const struct interface *ifp)
 {
        FILE *fp;
        char *p, ifaddress[33], address[33], name[IF_NAMESIZE + 1];
@@ -1473,7 +1473,7 @@ if_addrflags6(const char *ifname, const struct in6_addr *addr)
                        errno = ENOTSUP;
                        return -1;
                }
-               if (strcmp(ifname, name) == 0 &&
+               if (strcmp(ifname, ifp->name) == 0 &&
                    strcmp(ifaddress, address) == 0)
                {
                        fclose(fp);
index a6a8323c68581aa1dce9e984b1011aaaddd9f4a2..2c9252d3d8e645d7aa50fbeab48819fc42783187 100644 (file)
--- a/if-sun.c
+++ b/if-sun.c
@@ -143,7 +143,7 @@ if_route6(const struct rt6 *rt, int action)
 
 #ifdef INET6
 int
-if_addrflags6(const char *ifname, const struct in6_addr *addr)
+if_addrflags6(const struct in6_addr *addr, const struct interface *ifp)
 {
 
        errno = ENOTSUP;
diff --git a/if.c b/if.c
index e4fedce5a887a5db45dd302c61a760911aaecd0b..70b6de8f646c6d9d32bd5fec0b2b076112e7ce1c 100644 (file)
--- a/if.c
+++ b/if.c
@@ -184,7 +184,7 @@ if_discover(struct dhcpcd_ctx *ctx, int argc, char * const *argv)
        const struct sockaddr_in *dst;
 #endif
 #ifdef INET6
-       const struct sockaddr_in6 *sin6;
+       struct sockaddr_in6 *sin6;
        int ifa_flags;
 #endif
 #ifdef AF_LINK
@@ -453,10 +453,20 @@ if_discover(struct dhcpcd_ctx *ctx, int argc, char * const *argv)
 #endif
 #ifdef INET6
                case AF_INET6:
-                       sin6 = (const struct sockaddr_in6 *)
-                           (void *)ifa->ifa_addr;
-                       ifa_flags = if_addrflags6(ifa->ifa_name,
-                           &sin6->sin6_addr);
+                       TAILQ_FOREACH(ifp, ifs, next) {
+                               if (strcmp(ifp->name, ifa->ifa_name) == 0)
+                                       break;
+                       }
+                       if (ifp == NULL)
+                               break; /* Should be impossible */
+                       sin6 = (struct sockaddr_in6 *)(void *)ifa->ifa_addr;
+#ifdef __KAME__
+                       if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
+                               /* Remove the scope from the address */
+                               sin6->sin6_addr.s6_addr[2] =
+                                   sin6->sin6_addr.s6_addr[3] = '\0';
+#endif
+                       ifa_flags = if_addrflags6(&sin6->sin6_addr, ifp);
                        if (ifa_flags != -1)
                                ipv6_handleifa(ctx, RTM_NEWADDR, ifs,
                                    ifa->ifa_name,
diff --git a/if.h b/if.h
index 3cdf168807445de3aee862a66e1f205743929332..f657f52cee833c14da88dbdfb43406a75811137b 100644 (file)
--- a/if.h
+++ b/if.h
@@ -138,7 +138,7 @@ int if_nd6reachable(const char *ifname, struct in6_addr *addr);
 int if_address6(const struct ipv6_addr *, int);
 #define if_addaddress6(a) if_address6(a, 1)
 #define if_deladdress6(a) if_address6(a, -1)
-int if_addrflags6(const char *, const struct in6_addr *);
+int if_addrflags6(const struct in6_addr *, const struct interface *);
 
 int if_route6(const struct rt6 *rt, int);
 #define if_addroute6(rt) if_route6(rt, 1)
diff --git a/ipv6.c b/ipv6.c
index 8fe837d3345aaa62e29d5be336df5a93358e0c65..3bd0e2cacdd8440b7448a158a86c2015500ff324 100644 (file)
--- a/ipv6.c
+++ b/ipv6.c
@@ -573,7 +573,7 @@ ipv6_checkaddrflags(void *arg)
        int ifa_flags;
 
        ap = arg;
-       ifa_flags = if_addrflags6(ap->iface->name, &ap->addr);
+       ifa_flags = if_addrflags6(&ap->addr, ap->iface);
        if (ifa_flags == -1)
                syslog(LOG_ERR, "%s: if_addrflags6: %m", ap->iface->name);
        else if (!(ifa_flags & IN6_IFF_TENTATIVE)) {