Author: mlaier
Date: Mon Apr 13 22:17:03 2009
New Revision: 191025
URL: http://svn.freebsd.org/changeset/base/191025

Log:
  MFH r190903 & r190895:
    Remove interfaces from interface groups on detach.
  
  Reported by:  various
  Submitted by: Mikolaj Golub (r190895)
  PR:           kern/130977, kern/131310
  Approved by:  re (gnn)

Modified:
  stable/7/sys/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)
  stable/7/sys/dev/ath/ath_hal/   (props changed)
  stable/7/sys/dev/cxgb/   (props changed)
  stable/7/sys/net/if.c

Modified: stable/7/sys/net/if.c
==============================================================================
--- stable/7/sys/net/if.c       Mon Apr 13 21:04:53 2009        (r191024)
+++ stable/7/sys/net/if.c       Mon Apr 13 22:17:03 2009        (r191025)
@@ -128,6 +128,7 @@ static void if_start_deferred(void *cont
 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
 /*
  * XXX: declare here to avoid to include many inet6 related files..
@@ -828,6 +829,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_delgroups(ifp);
 
        IF_AFDATA_LOCK(ifp);
        for (dp = domains; dp; dp = dp->dom_next) {
@@ -963,6 +965,53 @@ if_delgroup(struct ifnet *ifp, const cha
 }
 
 /*
+ * Remove an interface from all groups
+ */
+static void
+if_delgroups(struct ifnet *ifp)
+{
+       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(&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
  */
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to