diff --git a/sys/net/if.c b/sys/net/if.c index fe0a304f927b..17240611f360 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -773,9 +773,10 @@ if_purgeaddrs(struct ifnet *ifp) } /* - * Remove any multicast network addresses from an interface. + * Remove any multicast network addresses from an interface when an ifnet + * is going away. */ -void +static void if_purgemaddrs(struct ifnet *ifp) { struct ifmultiaddr *ifma; @@ -3004,6 +3005,22 @@ if_delmulti(struct ifnet *ifp, struct sockaddr *sa) return (0); } +/* + * 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. diff --git a/sys/net/if_var.h b/sys/net/if_var.h index 58e2837ff25a..eac7dbf97836 100644 --- a/sys/net/if_var.h +++ b/sys/net/if_var.h @@ -832,7 +832,7 @@ void if_delmulti_ifma(struct ifmultiaddr *); void if_detach(struct ifnet *); void if_vmove(struct ifnet *, struct vnet *); void if_purgeaddrs(struct ifnet *); -void if_purgemaddrs(struct ifnet *); +void if_delallmulti(struct ifnet *); void if_down(struct ifnet *); struct ifmultiaddr * if_findmulti(struct ifnet *, struct sockaddr *); diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c index 35c79819bdfa..237e556f30c5 100644 --- a/sys/net80211/ieee80211_ioctl.c +++ b/sys/net80211/ieee80211_ioctl.c @@ -3199,15 +3199,18 @@ ieee80211_ioctl_updatemulti(struct ieee80211com *ic) 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);