From: Roy Marples Date: Thu, 4 Sep 2014 19:55:37 +0000 (+0000) Subject: Only send DHCPv6 and RA to control sockets when DAD has been completed. X-Git-Tag: v6.4.4~42 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a0011b993364c6ac24e4e5e534ac07fcef2d02c3;p=thirdparty%2Fdhcpcd.git Only send DHCPv6 and RA to control sockets when DAD has been completed. --- diff --git a/dhcp6.c b/dhcp6.c index 6a97bf2b..8a81bc5d 100644 --- 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 3727fe15..7aad1b7c 100644 --- 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 diff --git a/dhcpcd.c b/dhcpcd.c index 130e3c52..23142094 100644 --- 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)) diff --git a/ipv6nd.c b/ipv6nd.c index 9a63de18..d62f1615 100644 --- 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) { diff --git a/ipv6nd.h b/ipv6nd.h index f29065d9..688710d5 100644 --- 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 diff --git a/script.c b/script.c index 82f8d280..63daa6a4 100644 --- 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; }