]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Don't assume the kernel will remove or mark tentative LL addresses.
authorRoy Marples <roy@marples.name>
Mon, 3 Jun 2013 06:49:34 +0000 (06:49 +0000)
committerRoy Marples <roy@marples.name>
Mon, 3 Jun 2013 06:49:34 +0000 (06:49 +0000)
This isn't a problem as we listen to IPv6 address changes.

dhcpcd.c
ipv6.c
ipv6.h

index 8fd99844801b6121ce09c81d7f016e81016cd9c9..087e149b1164219491eb01d2abe1d37262caf021 100644 (file)
--- 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 e0014ad0bbe073172ab7e30f8de9a4b3daa57f1d..78e296c343d9931a2f24f9518c42296851979710 100644 (file)
--- 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 dcd1480cee391d1b91330e518771861f77da6fd1..40c1c11c08ca9dbaa1f89fc69fd5b8ccb7eac511 100644 (file)
--- 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