]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Only send DHCPv6 and RA to control sockets when DAD has been completed.
authorRoy Marples <roy@marples.name>
Thu, 4 Sep 2014 19:55:37 +0000 (19:55 +0000)
committerRoy Marples <roy@marples.name>
Thu, 4 Sep 2014 19:55:37 +0000 (19:55 +0000)
dhcp6.c
dhcp6.h
dhcpcd.c
ipv6nd.c
ipv6nd.h
script.c

diff --git a/dhcp6.c b/dhcp6.c
index 6a97bf2bcc46e846224192bba9738df675e8cb45..8a81bc5d456ccdc90a459211771d50ba1d03f228 100644 (file)
--- a/dhcp6.c
+++ b/dhcp6.c
@@ -1162,6 +1162,21 @@ dhcp6_startrenew(void *arg)
                dhcp6_sendrenew(ifp);
 }
 
+int
+dhcp6_dadcompleted(const struct interface *ifp)
+{
+       const struct dhcp6_state *state;
+       const struct ipv6_addr *ap;
+
+       state = D6_CSTATE(ifp);
+       TAILQ_FOREACH(ap, &state->addrs, next) {
+               if (ap->flags & IPV6_AF_ADDED &&
+                   !(ap->flags & IPV6_AF_DADCOMPLETED))
+                       return 0;
+       }
+       return 1;
+}
+
 static void
 dhcp6_dadcallback(void *arg)
 {
diff --git a/dhcp6.h b/dhcp6.h
index 3727fe15efe9cde7ddad0bbb1b3abf630f3384ae..7aad1b7c1759e715bc7e43db6e9bb03068a19b56 100644 (file)
--- a/dhcp6.h
+++ b/dhcp6.h
@@ -208,7 +208,8 @@ struct dhcp6_state {
 #define D6_CSTATE(ifp)                                                        \
        ((const struct dhcp6_state *)(ifp)->if_data[IF_DATA_DHCP6])
 #define D6_STATE_RUNNING(ifp)                                                 \
-       (D6_CSTATE((ifp)) && D6_CSTATE((ifp))->new && D6_CSTATE((ifp))->reason)
+       (D6_CSTATE((ifp)) && D6_CSTATE((ifp))->new &&                          \
+       D6_CSTATE((ifp))->reason && dhcp6_dadcompleted((ifp)))
 
 #define D6_FIRST_OPTION(m)                                                    \
     ((struct dhcp6_option *)                                                  \
@@ -239,6 +240,7 @@ ssize_t dhcp6_env(char **, const char *, const struct interface *,
 void dhcp6_free(struct interface *);
 void dhcp6_handleifa(struct dhcpcd_ctx *, int, const char *,
     const struct in6_addr *addr, int);
+int dhcp6_dadcompleted(const struct interface *);
 void dhcp6_drop(struct interface *, const char *);
 int dhcp6_dump(struct interface *);
 #else
index 130e3c52e839bbff06ab22078d85a673edc96a9f..23142094019fec5daec86dab485d95c04281bff3 100644 (file)
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -1094,9 +1094,9 @@ dhcpcd_getinterfaces(void *arg)
                len++;
                if (D_STATE_RUNNING(ifp))
                        len++;
-               if (D6_STATE_RUNNING(ifp))
+               if (RS_STATE_RUNNING(ifp))
                        len++;
-               if (ipv6nd_hasra(ifp))
+               if (D6_STATE_RUNNING(ifp))
                        len++;
        }
        if (write(fd->fd, &len, sizeof(len)) != sizeof(len))
index 9a63de1867c38a2b9e5766a95139cef8b267af64..d62f16158ab072dbfd9a1b5f22d25509680e2e9e 100644 (file)
--- a/ipv6nd.c
+++ b/ipv6nd.c
@@ -580,6 +580,24 @@ ipv6nd_addaddr(void *arg)
        ipv6_addaddr(ap);
 }
 
+int
+ipv6nd_dadcompleted(const struct interface *ifp)
+{
+       const struct ra *rap;
+       const struct ipv6_addr *ap;
+
+       TAILQ_FOREACH(rap, ifp->ctx->ipv6->ra_routers, next) {
+               if (rap->iface != ifp)
+                       continue;
+               TAILQ_FOREACH(ap, &rap->addrs, next) {
+                       if (ap->flags & IPV6_AF_AUTOCONF &&
+                           !(ap->flags & IPV6_AF_DADCOMPLETED))
+                               return 0;
+               }
+       }
+       return 1;
+}
+
 static void
 ipv6nd_dadcallback(void *arg)
 {
index f29065d9efe1fbade57ff0db65584fb5ade9ad6a..688710d59ac7688b8bc0393415f7c18d7ffb0117 100644 (file)
--- a/ipv6nd.h
+++ b/ipv6nd.h
@@ -69,6 +69,7 @@ struct rs_state {
 };
 
 #define RS_STATE(a) ((struct rs_state *)(ifp)->if_data[IF_DATA_IPV6ND])
+#define RS_STATE_RUNNING(a) (ipv6nd_hasra((a)) && ipv6nd_dadcompleted((a)))
 
 #define MAX_RTR_SOLICITATION_DELAY     1       /* seconds */
 #define MAX_UNICAST_SOLICIT            3       /* 3 transmissions */
@@ -94,6 +95,7 @@ int ipv6nd_hasra(const struct interface *);
 int ipv6nd_hasradhcp(const struct interface *);
 void ipv6nd_handleifa(struct dhcpcd_ctx *, int,
     const char *, const struct in6_addr *, int);
+int ipv6nd_dadcompleted(const struct interface *);
 void ipv6nd_drop(struct interface *);
 
 #ifdef HAVE_RTM_GETNEIGH
index 82f8d280de426d6cb394cfca63e663731d841937..63daa6a45d4e77b3f189f6f42e08e255a142bf9d 100644 (file)
--- a/script.c
+++ b/script.c
@@ -572,7 +572,7 @@ send_interface(int fd, const struct interface *ifp)
 #endif
 
 #ifdef INET6
-       if (ipv6nd_hasra(ifp)) {
+       if (RS_STATE_RUNNING(ifp)) {
                if (send_interface1(fd, ifp, "ROUTERADVERT") == -1)
                        retval = -1;
        }