From: Roy Marples Date: Mon, 3 Mar 2014 13:56:49 +0000 (+0000) Subject: When deleting IPv6 addresses, remove them from our internal address state X-Git-Tag: v6.3.2~45 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=98d7a13dfa56d128819de2702cb70ac348ce574b;p=thirdparty%2Fdhcpcd.git When deleting IPv6 addresses, remove them from our internal address state as well so we perform DAD when rebinding. Remove debug added with prior commit. --- diff --git a/dhcp6.c b/dhcp6.c index 22c6b1f4..6fe54a24 100644 --- a/dhcp6.c +++ b/dhcp6.c @@ -1545,7 +1545,7 @@ dhcp6_findia(struct interface *ifp, const uint8_t *d, size_t l, TAILQ_REMOVE(&state->addrs, ap, next); if (ap->dadcallback) eloop_q_timeout_delete(ap->iface->ctx->eloop, - 0, NULL, ap->dadcallback); + 0, NULL, ap); free(ap); } } @@ -2392,6 +2392,7 @@ recv: dhcp6_startexpire, ifp); if (ifp->options->ia_type == D6_OPTION_IA_PD) dhcp6_delegate_prefix(ifp); + ipv6nd_probeaddrs(&state->addrs); if (state->state == DH6S_INFORMED) syslog(has_new ? LOG_INFO : LOG_DEBUG, @@ -2409,9 +2410,9 @@ recv: /* If all addresses have completed DAD run the script */ TAILQ_FOREACH(ap, &state->addrs, next) { if (ap->flags & IPV6_AF_ONLINK) { -// if (!(ap->flags & IPV6_AF_DADCOMPLETED) && -// ipv6_findaddr(ap->iface, &ap->addr)) -// ap->flags |= IPV6_AF_DADCOMPLETED; + if (!(ap->flags & IPV6_AF_DADCOMPLETED) && + ipv6_findaddr(ap->iface, &ap->addr)) + ap->flags |= IPV6_AF_DADCOMPLETED; if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0) { len = 0; break; diff --git a/ipv6.c b/ipv6.c index 8e917e64..284c57a0 100644 --- a/ipv6.c +++ b/ipv6.c @@ -488,6 +488,8 @@ ipv6_freedrop_addrs(struct ipv6_addrhead *addrs, int drop, const struct interface *ifd) { struct ipv6_addr *ap, *apn; + struct ipv6_state *state; + struct ipv6_addr_l *lap; TAILQ_FOREACH_SAFE(ap, addrs, next, apn) { if (ifd && ap->delegating_iface != ifd) @@ -509,6 +511,21 @@ ipv6_freedrop_addrs(struct ipv6_addrhead *addrs, int drop, if (del_address6(ap) == -1 && errno != EADDRNOTAVAIL && errno != ENXIO) syslog(LOG_ERR, "del_address6 %m"); + + /* Remove it from our internal state */ + state = IPV6_STATE(ap->iface); + if (state) { + TAILQ_FOREACH(lap, &state->addrs, next) { + if (IN6_ARE_ADDR_EQUAL(&lap->addr, + &ap->addr)) + { + TAILQ_REMOVE(&state->addrs, + lap, next); + free(lap); + break; + } + } + } } free(ap); }