Network addresses added to the interface local list thought ifa_add()
are the link-local address and the IPv4/6 ones.
Since if_detach() now calls in_ifdetach(), there should be no address
left on the list apart from the link-layer one at this stage. So the
diff below removes it directly, there's no need for a loop anymore.
I left a check for safety afterward...
ok?
Index: net/if.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if.c,v
retrieving revision 1.279
diff -u -p -r1.279 if.c
--- net/if.c 28 Nov 2013 10:16:44 -0000 1.279
+++ net/if.c 7 Jan 2014 11:57:09 -0000
@@ -359,12 +359,10 @@ if_free_sadl(struct ifnet *ifp)
s = splnet();
rtinit(ifa, RTM_DELETE, 0);
-#if 0
ifa_del(ifp, ifa);
+ ifafree(ifp->if_lladdr);
ifp->if_lladdr = NULL;
-#endif
ifp->if_sadl = NULL;
-
splx(s);
}
@@ -587,27 +585,22 @@ do { \
if (ISSET(ifp->if_xflags, IFXF_TXREADY))
TAILQ_REMOVE(&iftxlist, ifp, if_txlist);
- /*
- * Deallocate private resources.
- */
- while ((ifa = TAILQ_FIRST(&ifp->if_addrlist)) != NULL) {
- ifa_del(ifp, ifa);
- /* XXX if_free_sadl needs this */
- if (ifa == ifp->if_lladdr)
- continue;
-
- ifa->ifa_ifp = NULL;
- ifafree(ifa);
- }
-
while ((ifg = TAILQ_FIRST(&ifp->if_groups)) != NULL)
if_delgroup(ifp, ifg->ifgl_group->ifg_group);
if_free_sadl(ifp);
- ifp->if_lladdr->ifa_ifp = NULL;
- ifafree(ifp->if_lladdr);
- ifp->if_lladdr = NULL;
+ /* We should not have any address left at this point. */
+ if (!TAILQ_EMPTY(&ifp->if_addrlist)) {
+#ifdef DIAGNOSTIC
+ printf("%s: address list non empty\n", ifp->if_xname);
+#endif
+ while ((ifa = TAILQ_FIRST(&ifp->if_addrlist)) != NULL) {
+ ifa_del(ifp, ifa);
+ ifa->ifa_ifp = NULL;
+ ifafree(ifa);
+ }
+ }
free(ifp->if_addrhooks, M_TEMP);
free(ifp->if_linkstatehooks, M_TEMP);