FreeBSD/sys/netinet/in_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 IGMP 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 IGMP 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 IGMP downcall fails the group is not joined and an error code is returned .
int
in_joingroup_locked(struct ifnet *ifp, const struct in_addr *gina,
     struct in_mfilter *imf, struct in_multi **pinm)
{
	struct in_mfilter	 timf;
	struct in_multi		*inm;
	int			 error;
	IN_MULTI_LOCK_ASSERT();
	CTR4(KTR_IGMPV3, "%s: join %s on %p(%s))", __func__,
	    inet_ntoa(*gina), ifp, ifp->if_xname);
	error = 0;
	inm = NULL;
	if (imf == NULL) {
		imf_init(&timf, MCAST_UNDEFINED, MCAST_EXCLUDE);
		imf = &timf;
	}
	error = in_getmulti(ifp, gina, &inm);
	if (error) {
		CTR1(KTR_IGMPV3, "%s: in_getmulti() failure", __func__);
		return (error);
	}
	CTR1(KTR_IGMPV3, "%s: merge inm state", __func__);
	error = inm_merge(inm, imf);
	if (error) {
		CTR1(KTR_IGMPV3, "%s: failed to merge inm state", __func__);
		goto out_inm_release;
	}
	CTR1(KTR_IGMPV3, "%s: doing igmp downcall", __func__);
	error = igmp_change_state(inm);
	if (error) {
		CTR1(KTR_IGMPV3, "%s: failed to update source", __func__);
		goto out_inm_release;
	}
out_inm_release:
	if (error) {
		CTR2(KTR_IGMPV3, "%s: dropping ref on %p", __func__, inm);
		inm_release_locked(inm);
	} else {
		*pinm = inm;
	}
	return (error);
}
int in_joingroup_locked ( struct ifnet * ifp , const struct in_addr * gina , struct in_mfilter * imf , struct in_multi * * pinm ) { struct in_mfilter timf ; struct in_multi * inm ; int error ; IN_MULTI_LOCK_ASSERT ( ) ; CTR4 ( KTR_IGMPV3 , " " , __func__ , inet_ntoa ( * gina ) , ifp , ifp -> if_xname ) ; error = 0 ; inm = NULL ; if ( imf == NULL ) { imf_init ( & timf , MCAST_UNDEFINED , MCAST_EXCLUDE ) ; imf = & timf ; } error = in_getmulti ( ifp , gina , & inm ) ; if ( error ) { CTR1 ( KTR_IGMPV3 , " " , __func__ ) ; return ( error ) ; } CTR1 ( KTR_IGMPV3 , " " , __func__ ) ; error = inm_merge ( inm , imf ) ; if ( error ) { CTR1 ( KTR_IGMPV3 , " " , __func__ ) ; goto out_inm_release ; } CTR1 ( KTR_IGMPV3 , " " , __func__ ) ; error = igmp_change_state ( inm ) ; if ( error ) { CTR1 ( KTR_IGMPV3 , " " , __func__ ) ; goto out_inm_release ; } out_inm_release : if ( error ) { CTR2 ( KTR_IGMPV3 , " " , __func__ , inm ) ; inm_release_locked ( inm ) ; } else { * pinm = inm ; } return ( error ) ; }
Join a multicast group; real entry point.
Join a multicast group ; real entry point .
/*const*/ /*
	 * If no imf was specified (i.e. kernel consumer),
	 * fake one up and assume it is an ASM join.
	 */