FreeBSD/sys/netinet6/mld6.c
/*
 * Hook for ifdetach.
 *
 * NOTE: Some finalization tasks need to run before the protocol domain
 * is detached, but also before the link layer does its cleanup.
 * Run before link-layer cleanup; cleanup groups, but do not free MLD state.
 *
 * SMPng: Caller must hold IN6_MULTI_LOCK().
 * Must take IF_ADDR_LOCK() to cover if_multiaddrs iterator.
 * XXX This routine is also bitten by unlocked ifma_protospec access.
 */
Hook for ifdetach.
NOTE: Some finalization tasks need to run before the protocol domain
is detached, but also before the link layer does its cleanup.
Run before link-layer cleanup; cleanup groups, but do not free MLD state.

Caller must hold IN6_MULTI_LOCK().
Must take IF_ADDR_LOCK() to cover if_multiaddrs iterator.
XXX This routine is also bitten by unlocked ifma_protospec access.
Hook for ifdetach . NOTE : Some finalization tasks need to run before the protocol domain is detached but also before the link layer does its cleanup . Run before link - layer cleanup ; cleanup groups but do not free MLD state . Caller must hold IN6_MULTI_LOCK () . Must take IF_ADDR_LOCK () to cover if_multiaddrs iterator . XXX This routine is also bitten by unlocked ifma_protospec access .
void
mld_ifdetach(struct ifnet *ifp)
{
	struct mld_ifsoftc	*mli;
	struct ifmultiaddr	*ifma;
	struct in6_multi	*inm, *tinm;
	CTR3(KTR_MLD, "%s: called for ifp %p(%s)", __func__, ifp,
	    if_name(ifp));
	IN6_MULTI_LOCK_ASSERT();
	MLD_LOCK();
	mli = MLD_IFINFO(ifp);
	if (mli->mli_version == MLD_VERSION_2) {
		IF_ADDR_RLOCK(ifp);
		TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
			if (ifma->ifma_addr->sa_family != AF_INET6 ||
			    ifma->ifma_protospec == NULL)
				continue;
			inm = (struct in6_multi *)ifma->ifma_protospec;
			if (inm->in6m_state == MLD_LEAVING_MEMBER) {
				SLIST_INSERT_HEAD(&mli->mli_relinmhead,
				    inm, in6m_nrele);
			}
			in6m_clear_recorded(inm);
		}
		IF_ADDR_RUNLOCK(ifp);
		SLIST_FOREACH_SAFE(inm, &mli->mli_relinmhead, in6m_nrele,
		    tinm) {
			SLIST_REMOVE_HEAD(&mli->mli_relinmhead, in6m_nrele);
			in6m_release_locked(inm);
		}
	}
	MLD_UNLOCK();
}
void mld_ifdetach ( struct ifnet * ifp ) { struct mld_ifsoftc * mli ; struct ifmultiaddr * ifma ; struct in6_multi * inm , * tinm ; CTR3 ( KTR_MLD , " " , __func__ , ifp , if_name ( ifp ) ) ; IN6_MULTI_LOCK_ASSERT ( ) ; MLD_LOCK ( ) ; mli = MLD_IFINFO ( ifp ) ; if ( mli -> mli_version == MLD_VERSION_2 ) { IF_ADDR_RLOCK ( ifp ) ; TAILQ_FOREACH ( ifma , & ifp -> if_multiaddrs , ifma_link ) { if ( ifma -> ifma_addr -> sa_family != AF_INET6 || ifma -> ifma_protospec == NULL ) continue ; inm = ( struct in6_multi * ) ifma -> ifma_protospec ; if ( inm -> in6m_state == MLD_LEAVING_MEMBER ) { SLIST_INSERT_HEAD ( & mli -> mli_relinmhead , inm , in6m_nrele ) ; } in6m_clear_recorded ( inm ) ; } IF_ADDR_RUNLOCK ( ifp ) ; SLIST_FOREACH_SAFE ( inm , & mli -> mli_relinmhead , in6m_nrele , tinm ) { SLIST_REMOVE_HEAD ( & mli -> mli_relinmhead , in6m_nrele ) ; in6m_release_locked ( inm ) ; } } MLD_UNLOCK ( ) ; }
Hook for ifdetach.
Hook for ifdetach .