FreeBSD/sys/netinet/in_mcast.c
/*
 * Look up the ifnet to use for a multicast group membership,
 * given the IPv4 address of an interface, and the IPv4 group address.
 *
 * This routine exists to support legacy multicast applications
 * which do not understand that multicast memberships are scoped to
 * specific physical links in the networking stack, or which need
 * to join link-scope groups before IPv4 addresses are configured.
 *
 * If inp is non-NULL, use this socket's current FIB number for any
 * required FIB lookup.
 * If ina is INADDR_ANY, look up the group address in the unicast FIB,
 * and use its ifp; usually, this points to the default next-hop.
 *
 * If the FIB lookup fails, attempt to use the first non-loopback
 * interface with multicast capability in the system as a
 * last resort. The legacy IPv4 ASM API requires that we do
 * this in order to allow groups to be joined when the routing
 * table has not yet been populated during boot.
 *
 * Returns NULL if no ifp could be found.
 *
 * SMPng: TODO: Acquire the appropriate locks for INADDR_TO_IFP.
 * FUTURE: Implement IPv4 source-address selection.
 */
Look up the ifnet to use for a multicast group membership,
given the IPv4 address of an interface, and the IPv4 group address.

This routine exists to support legacy multicast applications
which do not understand that multicast memberships are scoped to
specific physical links in the networking stack, or which need
to join link-scope groups before IPv4 addresses are configured.

If inp is non-NULL, use this socket's current FIB number for any
required FIB lookup.
If ina is INADDR_ANY, look up the group address in the unicast FIB,
and use its ifp; usually, this points to the default next-hop.

If the FIB lookup fails, attempt to use the first non-loopback
interface with multicast capability in the system as a
last resort. The legacy IPv4 ASM API requires that we do
this in order to allow groups to be joined when the routing
table has not yet been populated during boot.

Returns NULL if no ifp could be found.

Acquire the appropriate locks for INADDR_TO_IFP.
FUTURE: Implement IPv4 source-address selection.
Look up the ifnet to use for a multicast group membership given the IPv4 address of an interface and the IPv4 group address . This routine exists to support legacy multicast applications which do not understand that multicast memberships are scoped to specific physical links in the networking stack or which need to join link - scope groups before IPv4 addresses are configured . If inp is non - NULL use this socket ' s current FIB number for any required FIB lookup . If ina is INADDR_ANY look up the group address in the unicast FIB and use its ifp ; usually this points to the default next - hop . If the FIB lookup fails attempt to use the first non - loopback interface with multicast capability in the system as a last resort . The legacy IPv4 ASM API requires that we do this in order to allow groups to be joined when the routing table has not yet been populated during boot . Returns NULL if no ifp could be found . Acquire the appropriate locks for INADDR_TO_IFP . FUTURE : Implement IPv4 source - address selection .
static struct ifnet *
inp_lookup_mcast_ifp(const struct inpcb *inp,
    const struct sockaddr_in *gsin, const struct in_addr ina)
{
	struct rm_priotracker in_ifa_tracker;
	struct ifnet *ifp;
	struct nhop4_basic nh4;
	uint32_t fibnum;
	KASSERT(gsin->sin_family == AF_INET, ("%s: not AF_INET", __func__));
	KASSERT(IN_MULTICAST(ntohl(gsin->sin_addr.s_addr)),
	    ("%s: not multicast", __func__));
	ifp = NULL;
	if (!in_nullhost(ina)) {
		INADDR_TO_IFP(ina, ifp);
	} else {
		fibnum = inp ? inp->inp_inc.inc_fibnum : 0;
		if (fib4_lookup_nh_basic(fibnum, gsin->sin_addr, 0, 0, &nh4)==0)
			ifp = nh4.nh_ifp;
		else {
			struct in_ifaddr *ia;
			struct ifnet *mifp;
			mifp = NULL;
			IN_IFADDR_RLOCK(&in_ifa_tracker);
			TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
				mifp = ia->ia_ifp;
				if (!(mifp->if_flags & IFF_LOOPBACK) &&
				     (mifp->if_flags & IFF_MULTICAST)) {
					ifp = mifp;
					break;
				}
			}
			IN_IFADDR_RUNLOCK(&in_ifa_tracker);
		}
	}
	return (ifp);
}
static struct ifnet * inp_lookup_mcast_ifp ( const struct inpcb * inp , const struct sockaddr_in * gsin , const struct in_addr ina ) { struct rm_priotracker in_ifa_tracker ; struct ifnet * ifp ; struct nhop4_basic nh4 ; uint32_t fibnum ; KASSERT ( gsin -> sin_family == AF_INET , ( " " , __func__ ) ) ; KASSERT ( IN_MULTICAST ( ntohl ( gsin -> sin_addr . s_addr ) ) , ( " " , __func__ ) ) ; ifp = NULL ; if ( ! in_nullhost ( ina ) ) { INADDR_TO_IFP ( ina , ifp ) ; } else { fibnum = inp ? inp -> inp_inc . inc_fibnum : 0 ; if ( fib4_lookup_nh_basic ( fibnum , gsin -> sin_addr , 0 , 0 , & nh4 ) == 0 ) ifp = nh4 . nh_ifp ; else { struct in_ifaddr * ia ; struct ifnet * mifp ; mifp = NULL ; IN_IFADDR_RLOCK ( & in_ifa_tracker ) ; TAILQ_FOREACH ( ia , & V_in_ifaddrhead , ia_link ) { mifp = ia -> ia_ifp ; if ( ! ( mifp -> if_flags & IFF_LOOPBACK ) && ( mifp -> if_flags & IFF_MULTICAST ) ) { ifp = mifp ; break ; } } IN_IFADDR_RUNLOCK ( & in_ifa_tracker ) ; } } return ( ifp ) ; }
Look up the ifnet to use for a multicast group membership,
 given the IPv4 address of an interface, and the IPv4 group address.
Look up the ifnet to use for a multicast group membership given the IPv4 address of an interface and the IPv4 group address .