diff options
| author | Max Laier <mlaier@FreeBSD.org> | 2009-04-13 22:17:03 +0000 | 
|---|---|---|
| committer | Max Laier <mlaier@FreeBSD.org> | 2009-04-13 22:17:03 +0000 | 
| commit | 5cc303c24b22b9968589424d530ff9d503672d2b (patch) | |
| tree | 41b4238b237e3e7b78c35435cd2e14c60d0c7914 | |
| parent | e3982f8e61b5688f9c73d3249a21bb3a8edfb7c5 (diff) | |
Notes
| -rw-r--r-- | sys/net/if.c | 49 | 
1 files changed, 49 insertions, 0 deletions
diff --git a/sys/net/if.c b/sys/net/if.c index 5dc820a8dd369..ebcf5fd760c54 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -128,6 +128,7 @@ static void	if_start_deferred(void *context, int pending);  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 char *groupname)  }  /* + * 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   */  | 
