FreeBSD/sys/netinet6/nd6.c
/*
 * Test whether a given IPv6 address is a neighbor or not, ignoring
 * the actual neighbor cache.  The neighbor cache is ignored in order
 * to not reenter the routing code from within itself.
 */
Test whether a given IPv6 address is a neighbor or not, ignoring
the actual neighbor cache.  The neighbor cache is ignored in order
to not reenter the routing code from within itself.
Test whether a given IPv6 address is a neighbor or not ignoring the actual neighbor cache . The neighbor cache is ignored in order to not reenter the routing code from within itself .
static int
nd6_is_new_addr_neighbor(const struct sockaddr_in6 *addr, struct ifnet *ifp)
{
	struct nd_prefix *pr;
	struct ifaddr *dstaddr;
	struct rt_addrinfo info;
	struct sockaddr_in6 rt_key;
	struct sockaddr *dst6;
	int fibnum;
	if (IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) {
		struct sockaddr_in6 sin6_copy;
		u_int32_t zone;
		sin6_copy = *addr;
		if (sa6_recoverscope(&sin6_copy))
			return (0); 
		if (in6_setscope(&sin6_copy.sin6_addr, ifp, &zone))
			return (0);
		if (sin6_copy.sin6_scope_id == zone)
			return (1);
		else
			return (0);
	}
	bzero(&rt_key, sizeof(rt_key));
	bzero(&info, sizeof(info));
	info.rti_info[RTAX_DST] = (struct sockaddr *)&rt_key;
	fibnum = RT_DEFAULT_FIB;
	LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) {
		if (pr->ndpr_ifp != ifp)
			continue;
		if (!(pr->ndpr_stateflags & NDPRF_ONLINK)) {
			dst6 = (struct sockaddr *)&pr->ndpr_prefix;
			rt_key.sin6_len = sizeof(rt_key);
			if (rib_lookup_info(fibnum, dst6, 0, 0, &info) != 0)
				continue;
			if (!IN6_ARE_ADDR_EQUAL(&pr->ndpr_prefix.sin6_addr,
			       &rt_key.sin6_addr))
				continue;
		}
		if (IN6_ARE_MASKED_ADDR_EQUAL(&pr->ndpr_prefix.sin6_addr,
		    &addr->sin6_addr, &pr->ndpr_mask))
			return (1);
	}
	dstaddr = ifa_ifwithdstaddr((const struct sockaddr *)addr, RT_ALL_FIBS);
	if (dstaddr != NULL) {
		if (dstaddr->ifa_ifp == ifp) {
			ifa_free(dstaddr);
			return (1);
		}
		ifa_free(dstaddr);
	}
	if (ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV &&
	    TAILQ_EMPTY(&V_nd_defrouter) &&
	    V_nd6_defifindex == ifp->if_index) {
		return (1);
	}
	return (0);
}
static int nd6_is_new_addr_neighbor ( const struct sockaddr_in6 * addr , struct ifnet * ifp ) { struct nd_prefix * pr ; struct ifaddr * dstaddr ; struct rt_addrinfo info ; struct sockaddr_in6 rt_key ; struct sockaddr * dst6 ; int fibnum ; if ( IN6_IS_ADDR_LINKLOCAL ( & addr -> sin6_addr ) ) { struct sockaddr_in6 sin6_copy ; u_int32_t zone ; sin6_copy = * addr ; if ( sa6_recoverscope ( & sin6_copy ) ) return ( 0 ) ; if ( in6_setscope ( & sin6_copy . sin6_addr , ifp , & zone ) ) return ( 0 ) ; if ( sin6_copy . sin6_scope_id == zone ) return ( 1 ) ; else return ( 0 ) ; } bzero ( & rt_key , sizeof ( rt_key ) ) ; bzero ( & info , sizeof ( info ) ) ; info . rti_info [ RTAX_DST ] = ( struct sockaddr * ) & rt_key ; fibnum = RT_DEFAULT_FIB ; LIST_FOREACH ( pr , & V_nd_prefix , ndpr_entry ) { if ( pr -> ndpr_ifp != ifp ) continue ; if ( ! ( pr -> ndpr_stateflags & NDPRF_ONLINK ) ) { dst6 = ( struct sockaddr * ) & pr -> ndpr_prefix ; rt_key . sin6_len = sizeof ( rt_key ) ; if ( rib_lookup_info ( fibnum , dst6 , 0 , 0 , & info ) != 0 ) continue ; if ( ! IN6_ARE_ADDR_EQUAL ( & pr -> ndpr_prefix . sin6_addr , & rt_key . sin6_addr ) ) continue ; } if ( IN6_ARE_MASKED_ADDR_EQUAL ( & pr -> ndpr_prefix . sin6_addr , & addr -> sin6_addr , & pr -> ndpr_mask ) ) return ( 1 ) ; } dstaddr = ifa_ifwithdstaddr ( ( const struct sockaddr * ) addr , RT_ALL_FIBS ) ; if ( dstaddr != NULL ) { if ( dstaddr -> ifa_ifp == ifp ) { ifa_free ( dstaddr ) ; return ( 1 ) ; } ifa_free ( dstaddr ) ; } if ( ND_IFINFO ( ifp ) -> flags & ND6_IFF_ACCEPT_RTADV && TAILQ_EMPTY ( & V_nd_defrouter ) && V_nd6_defifindex == ifp -> if_index ) { return ( 1 ) ; } return ( 0 ) ; }
Test whether a given IPv6 address is a neighbor or not, ignoring
 the actual neighbor cache.
Test whether a given IPv6 address is a neighbor or not ignoring the actual neighbor cache .
/*
	 * A link-local address is always a neighbor.
	 * XXX: a link does not necessarily specify a single interface.
	 */ /*
		 * We need sin6_copy since sa6_recoverscope() may modify the
		 * content (XXX).
		 */ /* XXX: should be impossible */ /* Always use the default FIB here. XXME - why? */ /*
	 * If the address matches one of our addresses,
	 * it should be a neighbor.
	 * If the address matches one of our on-link prefixes, it should be a
	 * neighbor.
	 */ /* Always use the default FIB here. */ /* Restore length field before retrying lookup */ /*
			 * This is the case where multiple interfaces
			 * have the same prefix, but only one is installed 
			 * into the routing table and that prefix entry
			 * is not the one being examined here. In the case
			 * where RADIX_MPATH is enabled, multiple route
			 * entries (of the same rt_key value) will be 
			 * installed because the interface addresses all
			 * differ.
			 */ /*
	 * If the address is assigned on the node of the other side of
	 * a p2p interface, the address should be a neighbor.
	 */ /*
	 * If the default router list is empty, all addresses are regarded
	 * as on-link, and thus, as a neighbor.
	 */