summaryrefslogtreecommitdiffstats
path: root/sys/net/if.c
diff options
context:
space:
mode:
authormlaier <mlaier@FreeBSD.org>2009-04-10 19:16:14 +0000
committermlaier <mlaier@FreeBSD.org>2009-04-10 19:16:14 +0000
commitf2cc9938bfa55b9fe6473c3c8559438fba7f6dcc (patch)
tree7b1140964563201e4f305182c7bf7dd4cae237db /sys/net/if.c
parent6dc80f8815866354feab3f0db72ff587963b3d23 (diff)
downloadFreeBSD-src-f2cc9938bfa55b9fe6473c3c8559438fba7f6dcc.zip
FreeBSD-src-f2cc9938bfa55b9fe6473c3c8559438fba7f6dcc.tar.gz
Follow up for r190895 It's not only the "all" group that is affected, but
all groups on the given interface. PR: kern/130977, kern/131310 MFC after: 3 days (%vnet)
Diffstat (limited to 'sys/net/if.c')
-rw-r--r--sys/net/if.c51
1 files changed, 50 insertions, 1 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index d0cbec5..0f76eb1 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -141,6 +141,7 @@ static int if_delmulti_locked(struct ifnet *, struct ifmultiaddr *, int);
static void do_link_state_change(void *, int);
static int if_getgroup(struct ifgroupreq *, struct ifnet *);
static int if_getgroupmembers(struct ifgroupreq *);
+static void if_delgroups(struct ifnet *);
#ifdef INET6
/*
@@ -887,7 +888,7 @@ if_detach(struct ifnet *ifp)
rt_ifannouncemsg(ifp, IFAN_DEPARTURE);
EVENTHANDLER_INVOKE(ifnet_departure_event, ifp);
devctl_notify("IFNET", ifp->if_xname, "DETACH", NULL);
- if_delgroup(ifp, IFG_ALL);
+ if_delgroups(ifp);
IF_AFDATA_LOCK(ifp);
for (dp = domains; dp; dp = dp->dom_next) {
@@ -1025,6 +1026,54 @@ if_delgroup(struct ifnet *ifp, const char *groupname)
}
/*
+ * Remove an interface from all groups
+ */
+static void
+if_delgroups(struct ifnet *ifp)
+{
+ INIT_VNET_NET(ifp->if_vnet);
+ struct ifg_list *ifgl;
+ struct ifg_member *ifgm;
+ char groupname[IFNAMSIZ];
+
+ IFNET_WLOCK();
+ while (!TAILQ_EMPTY(&ifp->if_groups)) {
+ ifgl = TAILQ_FIRST(&ifp->if_groups);
+
+ strlcpy(groupname, ifgl->ifgl_group->ifg_group, IFNAMSIZ);
+
+ IF_ADDR_LOCK(ifp);
+ TAILQ_REMOVE(&ifp->if_groups, ifgl, ifgl_next);
+ IF_ADDR_UNLOCK(ifp);
+
+ TAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next)
+ if (ifgm->ifgm_ifp == ifp)
+ break;
+
+ if (ifgm != NULL) {
+ TAILQ_REMOVE(&ifgl->ifgl_group->ifg_members, ifgm,
+ ifgm_next);
+ free(ifgm, M_TEMP);
+ }
+
+ if (--ifgl->ifgl_group->ifg_refcnt == 0) {
+ TAILQ_REMOVE(&V_ifg_head, ifgl->ifgl_group, ifg_next);
+ EVENTHANDLER_INVOKE(group_detach_event,
+ ifgl->ifgl_group);
+ free(ifgl->ifgl_group, M_TEMP);
+ }
+ IFNET_WUNLOCK();
+
+ free(ifgl, M_TEMP);
+
+ EVENTHANDLER_INVOKE(group_change_event, groupname);
+
+ IFNET_WLOCK();
+ }
+ IFNET_WUNLOCK();
+}
+
+/*
* Stores all groups from an interface in memory pointed
* to by data
*/
OpenPOWER on IntegriCloud