From: Roy Marples Date: Mon, 3 Jun 2013 06:49:34 +0000 (+0000) Subject: Don't assume the kernel will remove or mark tentative LL addresses. X-Git-Tag: v5.99.7~5 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2bf02a2b0b67944a818734261e42369eb35e2fba;p=thirdparty%2Fdhcpcd.git Don't assume the kernel will remove or mark tentative LL addresses. This isn't a problem as we listen to IPv6 address changes. --- diff --git a/dhcpcd.c b/dhcpcd.c index 8fd99844..087e149b 100644 --- a/dhcpcd.c +++ b/dhcpcd.c @@ -389,7 +389,11 @@ handle_carrier(int carrier, int flags, const char *ifname) dhcp_close(ifp); dhcp6_drop(ifp, "EXPIRE6"); ipv6rs_drop(ifp); - ipv6_free(ifp); + /* Don't blindly delete our knowledge of LL addresses. + * We need to listen to what the kernel does with + * them as some OS's will remove, mark tentative or + * do nothing. */ + ipv6_free_ll_callbacks(ifp); dhcp_drop(ifp, "NOCARRIER"); } } else if (carrier == LINK_UP && ifp->flags & IFF_UP) { diff --git a/ipv6.c b/ipv6.c index e0014ad0..78e296c3 100644 --- a/ipv6.c +++ b/ipv6.c @@ -600,23 +600,33 @@ int ipv6_addlinklocalcallback(struct interface *ifp, return 0; } +void +ipv6_free_ll_callbacks(struct interface *ifp) +{ + struct ipv6_state *state; + struct ll_callback *cb; + + state = IPV6_STATE(ifp); + if (state) { + while ((cb = TAILQ_FIRST(&state->ll_callbacks))) { + TAILQ_REMOVE(&state->ll_callbacks, cb, next); + free(cb); + } + } +} void ipv6_free(struct interface *ifp) { struct ipv6_state *state; struct ll_addr *ap; - struct ll_callback *cb; + ipv6_free_ll_callbacks(ifp); state = IPV6_STATE(ifp); if (state) { while ((ap = TAILQ_FIRST(&state->ll_addrs))) { TAILQ_REMOVE(&state->ll_addrs, ap, next); free(ap); } - while ((cb = TAILQ_FIRST(&state->ll_callbacks))) { - TAILQ_REMOVE(&state->ll_callbacks, cb, next); - free(cb); - } free(state); ifp->if_data[IF_DATA_IPV6] = NULL; } diff --git a/ipv6.h b/ipv6.h index dcd1480c..40c1c11c 100644 --- a/ipv6.h +++ b/ipv6.h @@ -154,11 +154,13 @@ int ipv6_handleifa_addrs(int, struct ipv6_addrhead *, const struct in6_addr *, int); const struct ll_addr *ipv6_linklocal(const struct interface *); int ipv6_addlinklocalcallback(struct interface *, void (*)(void *), void *); +void ipv6_free_ll_callbacks(struct interface *); void ipv6_free(struct interface *); int ipv6_removesubnet(const struct interface *, struct ipv6_addr *); void ipv6_buildroutes(void); #else #define ipv6_init() -1 +#define ipv6_free_ll_callbacks(a) #define ipv6_free(a) #endif