FreeBSD/sys/netinet6/in6_mcast.c
/*
 * Join a multicast group; real entry point.
 *
 * Only preserves atomicity at inm level.
 * NOTE: imf argument cannot be const due to sys/tree.h limitations.
 *
 * If the MLD downcall fails, the group is not joined, and an error
 * code is returned.
 */
Join a multicast group; real entry point.
Only preserves atomicity at inm level.
NOTE: imf argument cannot be const due to sys/tree.h limitations.

If the MLD downcall fails, the group is not joined, and an error
code is returned.
Join a multicast group ; real entry point . Only preserves atomicity at inm level . NOTE : imf argument cannot be const due to sys / tree . h limitations . If the MLD downcall fails the group is not joined and an error code is returned .
int
in6_mc_join_locked(struct ifnet *ifp, const struct in6_addr *mcaddr,
     struct in6_mfilter *imf, struct in6_multi **pinm,
    const int delay)
{
	struct in6_mfilter	 timf;
	struct in6_multi	*inm;
	int			 error;
#ifdef KTR
	char			 ip6tbuf[INET6_ADDRSTRLEN];
#endif
#ifdef INVARIANTS
	KASSERT(IN6_IS_ADDR_MULTICAST(mcaddr),
	    ("%s: not a multicast address", __func__));
	if (IN6_IS_ADDR_MC_LINKLOCAL(mcaddr) ||
	    IN6_IS_ADDR_MC_INTFACELOCAL(mcaddr)) {
		KASSERT(mcaddr->s6_addr16[1] != 0,
		    ("%s: scope zone ID not set", __func__));
	}
#endif
	IN6_MULTI_LOCK_ASSERT();
	CTR4(KTR_MLD, "%s: join %s on %p(%s))", __func__,
	    ip6_sprintf(ip6tbuf, mcaddr), ifp, if_name(ifp));
	error = 0;
	inm = NULL;
	if (imf == NULL) {
		im6f_init(&timf, MCAST_UNDEFINED, MCAST_EXCLUDE);
		imf = &timf;
	}
	error = in6_mc_get(ifp, mcaddr, &inm);
	if (error) {
		CTR1(KTR_MLD, "%s: in6_mc_get() failure", __func__);
		return (error);
	}
	CTR1(KTR_MLD, "%s: merge inm state", __func__);
	error = in6m_merge(inm, imf);
	if (error) {
		CTR1(KTR_MLD, "%s: failed to merge inm state", __func__);
		goto out_in6m_release;
	}
	CTR1(KTR_MLD, "%s: doing mld downcall", __func__);
	error = mld_change_state(inm, delay);
	if (error) {
		CTR1(KTR_MLD, "%s: failed to update source", __func__);
		goto out_in6m_release;
	}
out_in6m_release:
	if (error) {
		CTR2(KTR_MLD, "%s: dropping ref on %p", __func__, inm);
		in6m_release_locked(inm);
	} else {
		*pinm = inm;
	}
	return (error);
}
int in6_mc_join_locked ( struct ifnet * ifp , const struct in6_addr * mcaddr , struct in6_mfilter * imf , struct in6_multi * * pinm , const int delay ) { struct in6_mfilter timf ; struct in6_multi * inm ; int error ; #ifdef KTR char ip6tbuf [ INET6_ADDRSTRLEN ] ; #endif #ifdef INVARIANTS KASSERT ( IN6_IS_ADDR_MULTICAST ( mcaddr ) , ( " " , __func__ ) ) ; if ( IN6_IS_ADDR_MC_LINKLOCAL ( mcaddr ) || IN6_IS_ADDR_MC_INTFACELOCAL ( mcaddr ) ) { KASSERT ( mcaddr -> s6_addr16 [ 1 ] != 0 , ( " " , __func__ ) ) ; } #endif IN6_MULTI_LOCK_ASSERT ( ) ; CTR4 ( KTR_MLD , " " , __func__ , ip6_sprintf ( ip6tbuf , mcaddr ) , ifp , if_name ( ifp ) ) ; error = 0 ; inm = NULL ; if ( imf == NULL ) { im6f_init ( & timf , MCAST_UNDEFINED , MCAST_EXCLUDE ) ; imf = & timf ; } error = in6_mc_get ( ifp , mcaddr , & inm ) ; if ( error ) { CTR1 ( KTR_MLD , " " , __func__ ) ; return ( error ) ; } CTR1 ( KTR_MLD , " " , __func__ ) ; error = in6m_merge ( inm , imf ) ; if ( error ) { CTR1 ( KTR_MLD , " " , __func__ ) ; goto out_in6m_release ; } CTR1 ( KTR_MLD , " " , __func__ ) ; error = mld_change_state ( inm , delay ) ; if ( error ) { CTR1 ( KTR_MLD , " " , __func__ ) ; goto out_in6m_release ; } out_in6m_release : if ( error ) { CTR2 ( KTR_MLD , " " , __func__ , inm ) ; in6m_release_locked ( inm ) ; } else { * pinm = inm ; } return ( error ) ; }
Join a multicast group; real entry point.
Join a multicast group ; real entry point .
/*const*/ /*
	 * Sanity: Check scope zone ID was set for ifp, if and
	 * only if group is scoped to an interface.
	 */ /*
	 * If no imf was specified (i.e. kernel consumer),
	 * fake one up and assume it is an ASM join.
	 */