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);