summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorsyrinx <syrinx@FreeBSD.org>2010-01-24 16:17:58 +0000
committersyrinx <syrinx@FreeBSD.org>2010-01-24 16:17:58 +0000
commit40d92428fb5aa102b7ab0489b9b39e999c4bab8e (patch)
treea651df091a85231247b0aa8d6f7042ce9ff2ef4c /sys
parentf346ef85e4ce0941c071f15688f353cb189a5b3b (diff)
downloadFreeBSD-src-40d92428fb5aa102b7ab0489b9b39e999c4bab8e.zip
FreeBSD-src-40d92428fb5aa102b7ab0489b9b39e999c4bab8e.tar.gz
While flushing the multicast filter of an interface, do not zero the relevant
ifmultiaddr structures' reference to the parent interface, unless the parent interface is really detaching. While here, program only link layer multicast filters to a wlan's hardware parent interface. PR: kern/142391, kern/142392 Reviewed by: sam, rpaolo, bms MFC after: 1 week
Diffstat (limited to 'sys')
-rw-r--r--sys/net/if.c21
-rw-r--r--sys/net/if_var.h2
-rw-r--r--sys/net80211/ieee80211_ioctl.c7
3 files changed, 25 insertions, 5 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index aa04eff..565913d 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -740,9 +740,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;
@@ -2940,6 +2941,22 @@ if_delmulti(struct ifnet *ifp, struct sockaddr *sa)
}
/*
+ * 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 87ad1a2..9ea533b 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -833,7 +833,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 35c7981..237e556 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);
OpenPOWER on IntegriCloud