FreeBSD/sys/netinet6/in6.c
/*
 * Join necessary multicast groups.  Factored out from in6_update_ifa().
 * This entire work should only be done once, for the default FIB.
 */
Join necessary multicast groups.  Factored out from in6_update_ifa().
This entire work should only be done once, for the default FIB.
Join necessary multicast groups . Factored out from in6_update_ifa () . This entire work should only be done once for the default FIB .
static int
in6_update_ifa_join_mc(struct ifnet *ifp, struct in6_aliasreq *ifra,
    struct in6_ifaddr *ia, int flags, struct in6_multi **in6m_sol)
{
	char ip6buf[INET6_ADDRSTRLEN];
	struct in6_addr mltaddr;
	struct in6_multi_mship *imm;
	int delay, error;
	KASSERT(in6m_sol != NULL, ("%s: in6m_sol is NULL", __func__));
	bzero(&mltaddr, sizeof(struct in6_addr));
	mltaddr.s6_addr32[0] = IPV6_ADDR_INT32_MLL;
	mltaddr.s6_addr32[2] = htonl(1);
	mltaddr.s6_addr32[3] = ifra->ifra_addr.sin6_addr.s6_addr32[3];
	mltaddr.s6_addr8[12] = 0xff;
	if ((error = in6_setscope(&mltaddr, ifp, NULL)) != 0) {
		log(LOG_ERR, "%s: in6_setscope failed\n", __func__);
		goto cleanup;
	}
	delay = error = 0;
	if ((flags & IN6_IFAUPDATE_DADDELAY)) {
		delay = arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz);
	}
	imm = in6_joingroup(ifp, &mltaddr, &error, delay);
	if (imm == NULL) {
		nd6log((LOG_WARNING, "%s: in6_joingroup failed for %s on %s "
		    "(errno=%d)\n", __func__, ip6_sprintf(ip6buf, &mltaddr),
		    if_name(ifp), error));
		goto cleanup;
	}
	LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
	*in6m_sol = imm->i6mm_maddr;
	mltaddr = in6addr_linklocal_allnodes;
	if ((error = in6_setscope(&mltaddr, ifp, NULL)) != 0)
		goto cleanup; 
	imm = in6_joingroup(ifp, &mltaddr, &error, 0);
	if (imm == NULL) {
		nd6log((LOG_WARNING, "%s: in6_joingroup failed for %s on %s "
		    "(errno=%d)\n", __func__, ip6_sprintf(ip6buf, &mltaddr),
		    if_name(ifp), error));
		goto cleanup;
	}
	LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
	delay = 0;
	if ((flags & IN6_IFAUPDATE_DADDELAY)) {
		delay = arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz);
	}
	if (in6_nigroup(ifp, NULL, -1, &mltaddr) == 0) {
		imm = in6_joingroup(ifp, &mltaddr, &error, delay);
		if (imm == NULL)
			nd6log((LOG_WARNING,
			    "%s: in6_joingroup failed for %s on %s "
			    "(errno=%d)\n", __func__, ip6_sprintf(ip6buf,
			    &mltaddr), if_name(ifp), error));
		else
			LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
	}
	if (V_icmp6_nodeinfo_oldmcprefix &&
	    in6_nigroup_oldmcprefix(ifp, NULL, -1, &mltaddr) == 0) {
		imm = in6_joingroup(ifp, &mltaddr, &error, delay);
		if (imm == NULL)
			nd6log((LOG_WARNING,
			    "%s: in6_joingroup failed for %s on %s "
			    "(errno=%d)\n", __func__, ip6_sprintf(ip6buf,
			    &mltaddr), if_name(ifp), error));
		else
			LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
	}
	mltaddr = in6addr_nodelocal_allnodes;
	if ((error = in6_setscope(&mltaddr, ifp, NULL)) != 0)
		goto cleanup; 
	imm = in6_joingroup(ifp, &mltaddr, &error, 0);
	if (imm == NULL) {
		nd6log((LOG_WARNING, "%s: in6_joingroup failed for %s on %s "
		    "(errno=%d)\n", __func__, ip6_sprintf(ip6buf,
		    &mltaddr), if_name(ifp), error));
		goto cleanup;
	}
	LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
cleanup:
	return (error);
}
static int in6_update_ifa_join_mc ( struct ifnet * ifp , struct in6_aliasreq * ifra , struct in6_ifaddr * ia , int flags , struct in6_multi * * in6m_sol ) { char ip6buf [ INET6_ADDRSTRLEN ] ; struct in6_addr mltaddr ; struct in6_multi_mship * imm ; int delay , error ; KASSERT ( in6m_sol != NULL , ( " " , __func__ ) ) ; bzero ( & mltaddr , sizeof ( struct in6_addr ) ) ; mltaddr . s6_addr32 [ 0 ] = IPV6_ADDR_INT32_MLL ; mltaddr . s6_addr32 [ 2 ] = htonl ( 1 ) ; mltaddr . s6_addr32 [ 3 ] = ifra -> ifra_addr . sin6_addr . s6_addr32 [ 3 ] ; mltaddr . s6_addr8 [ 12 ] = 0xff ; if ( ( error = in6_setscope ( & mltaddr , ifp , NULL ) ) != 0 ) { log ( LOG_ERR , " \n " , __func__ ) ; goto cleanup ; } delay = error = 0 ; if ( ( flags & IN6_IFAUPDATE_DADDELAY ) ) { delay = arc4random ( ) % ( MAX_RTR_SOLICITATION_DELAY * hz ) ; } imm = in6_joingroup ( ifp , & mltaddr , & error , delay ) ; if ( imm == NULL ) { nd6log ( ( LOG_WARNING , " " " \n " , __func__ , ip6_sprintf ( ip6buf , & mltaddr ) , if_name ( ifp ) , error ) ) ; goto cleanup ; } LIST_INSERT_HEAD ( & ia -> ia6_memberships , imm , i6mm_chain ) ; * in6m_sol = imm -> i6mm_maddr ; mltaddr = in6addr_linklocal_allnodes ; if ( ( error = in6_setscope ( & mltaddr , ifp , NULL ) ) != 0 ) goto cleanup ; imm = in6_joingroup ( ifp , & mltaddr , & error , 0 ) ; if ( imm == NULL ) { nd6log ( ( LOG_WARNING , " " " \n " , __func__ , ip6_sprintf ( ip6buf , & mltaddr ) , if_name ( ifp ) , error ) ) ; goto cleanup ; } LIST_INSERT_HEAD ( & ia -> ia6_memberships , imm , i6mm_chain ) ; delay = 0 ; if ( ( flags & IN6_IFAUPDATE_DADDELAY ) ) { delay = arc4random ( ) % ( MAX_RTR_SOLICITATION_DELAY * hz ) ; } if ( in6_nigroup ( ifp , NULL , -1 , & mltaddr ) == 0 ) { imm = in6_joingroup ( ifp , & mltaddr , & error , delay ) ; if ( imm == NULL ) nd6log ( ( LOG_WARNING , " " " \n " , __func__ , ip6_sprintf ( ip6buf , & mltaddr ) , if_name ( ifp ) , error ) ) ; else LIST_INSERT_HEAD ( & ia -> ia6_memberships , imm , i6mm_chain ) ; } if ( V_icmp6_nodeinfo_oldmcprefix && in6_nigroup_oldmcprefix ( ifp , NULL , -1 , & mltaddr ) == 0 ) { imm = in6_joingroup ( ifp , & mltaddr , & error , delay ) ; if ( imm == NULL ) nd6log ( ( LOG_WARNING , " " " \n " , __func__ , ip6_sprintf ( ip6buf , & mltaddr ) , if_name ( ifp ) , error ) ) ; else LIST_INSERT_HEAD ( & ia -> ia6_memberships , imm , i6mm_chain ) ; } mltaddr = in6addr_nodelocal_allnodes ; if ( ( error = in6_setscope ( & mltaddr , ifp , NULL ) ) != 0 ) goto cleanup ; imm = in6_joingroup ( ifp , & mltaddr , & error , 0 ) ; if ( imm == NULL ) { nd6log ( ( LOG_WARNING , " " " \n " , __func__ , ip6_sprintf ( ip6buf , & mltaddr ) , if_name ( ifp ) , error ) ) ; goto cleanup ; } LIST_INSERT_HEAD ( & ia -> ia6_memberships , imm , i6mm_chain ) ; cleanup : return ( error ) ; }
Join necessary multicast groups.
Join necessary multicast groups .
/* Join solicited multicast addr for new host id. */ /* XXX: should not happen */ /*
		 * We need a random delay for DAD on the address being
		 * configured.  It also means delaying transmission of the
		 * corresponding MLD report to avoid report collision.
		 * [RFC 4861, Section 6.3.7]
		 */ /*
	 * Join link-local all-nodes address.
	 */ /* XXX: should not fail */ /*
	 * Join node information group address.
	 */ /*
		 * The spec does not say anything about delay for this group,
		 * but the same logic should apply.
		 */ /* XXX jinmei */ /* XXX not very fatal, go on... */ /* XXX not very fatal, go on... */ /*
	 * Join interface-local all-nodes address.
	 * (ff01::1%ifN, and ff01::%ifN/32)
	 */ /* XXX: should not fail */