Index: net/if.c =================================================================== --- net/if.c (revision 202292) +++ net/if.c (working copy) @@ -742,7 +742,13 @@ /* * Remove any multicast network addresses from an interface. */ -void +/* + * syrinx@freebsd.org - 20100120 Do not export this API call for now + * as it NULLs the ifmultiaddr structures' reference to the parent interface. + * Any external subsystem that wants to purge the multicast addresses on + * an interface (net80211 only for now) should use if_delallmulti instead. + */ +static void if_purgemaddrs(struct ifnet *ifp) { struct ifmultiaddr *ifma; @@ -2939,6 +2945,22 @@ } /* + * Delete all multicast group membership for an interface. + * Should be used to quickly flush all multicast filters. + */ +void +if_delallmulti(struct ifnet *ifp) +{ + struct ifmultiaddr *ifma; + struct ifmultiaddr *next; + + IF_ADDR_LOCK(ifp); + TAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link, next) + if_delmulti_locked(ifp, ifma, 0); + IF_ADDR_UNLOCK(ifp); +} + +/* * Delete a multicast group membership by group membership pointer. * Network-layer protocol domains must use this routine. * Index: net/if_var.h =================================================================== --- net/if_var.h (revision 202292) +++ net/if_var.h (working copy) @@ -830,7 +830,8 @@ void if_detach(struct ifnet *); void if_vmove(struct ifnet *, struct vnet *); void if_purgeaddrs(struct ifnet *); -void if_purgemaddrs(struct ifnet *); +/* void if_purgemaddrs(struct ifnet *); */ +void if_delallmulti(struct ifnet *ifp); void if_down(struct ifnet *); struct ifmultiaddr * if_findmulti(struct ifnet *, struct sockaddr *); Index: net80211/ieee80211_ioctl.c =================================================================== --- net80211/ieee80211_ioctl.c (revision 202292) +++ net80211/ieee80211_ioctl.c (working copy) @@ -3199,15 +3199,18 @@ void *ioctl; IEEE80211_LOCK(ic); - if_purgemaddrs(parent); + if_delallmulti(parent); ioctl = parent->if_ioctl; /* XXX WAR if_allmulti */ parent->if_ioctl = NULL; TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { struct ifnet *ifp = vap->iv_ifp; struct ifmultiaddr *ifma; - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) + TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; (void) if_addmulti(parent, ifma->ifma_addr, NULL); + } } parent->if_ioctl = ioctl; ieee80211_runtask(ic, &ic->ic_mcast_task);