This isn't a problem as we listen to IPv6 address changes.
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) {
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;
}
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