FreeBSD/sys/netinet6/nd6.c
/*
 * Lookup link headerfor @sa_dst address. Stores found
 * data in @desten buffer. Copy of lle ln_flags can be also
 * saved in @pflags if @pflags is non-NULL.
 *
 * If destination LLE does not exists or lle state modification
 * is required, call "slow" version.
 *
 * Return values:
 * - 0 on success (address copied to buffer).
 * - EWOULDBLOCK (no local error, but address is still unresolved)
 * - other errors (alloc failure, etc)
 */
Lookup link headerfor @sa_dst address. Stores found
data in @desten buffer. Copy of lle ln_flags can be also
saved in @pflags if @pflags is non-NULL.

If destination LLE does not exists or lle state modification
is required, call "slow" version.

Return values:
- 0 on success (address copied to buffer).
- EWOULDBLOCK (no local error, but address is still unresolved)
- other errors (alloc failure, etc)
Lookup link headerfor @sa_dst address . Stores found data in @desten buffer . Copy of lle ln_flags can be also saved in @pflags if @pflags is non - NULL . If destination LLE does not exists or lle state modification is required call " slow " version . Return values : - 0 on success ( address copied to buffer ) . - EWOULDBLOCK ( no local error but address is still unresolved ) - other errors ( alloc failure etc )
int
nd6_resolve(struct ifnet *ifp, int is_gw, struct mbuf *m,
    const struct sockaddr *sa_dst, u_char *desten, uint32_t *pflags,
    struct llentry **plle)
{
	struct llentry *ln = NULL;
	const struct sockaddr_in6 *dst6;
	if (pflags != NULL)
		*pflags = 0;
	dst6 = (const struct sockaddr_in6 *)sa_dst;
	if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)) {
		m_freem(m);
		return (ENETDOWN); 
	}
	if (m != NULL && m->m_flags & M_MCAST) {
		switch (ifp->if_type) {
		case IFT_ETHER:
		case IFT_FDDI:
		case IFT_L2VLAN:
		case IFT_IEEE80211:
		case IFT_BRIDGE:
		case IFT_ISO88025:
			ETHER_MAP_IPV6_MULTICAST(&dst6->sin6_addr,
						 desten);
			return (0);
		default:
			m_freem(m);
			return (EAFNOSUPPORT);
		}
	}
	IF_AFDATA_RLOCK(ifp);
	ln = nd6_lookup(&dst6->sin6_addr, plle ? LLE_EXCLUSIVE : LLE_UNLOCKED,
	    ifp);
	if (ln != NULL && (ln->r_flags & RLLE_VALID) != 0) {
		bcopy(ln->r_linkdata, desten, ln->r_hdrlen);
		if (pflags != NULL)
			*pflags = LLE_VALID | (ln->r_flags & RLLE_IFADDR);
		if (ln->r_skip_req != 0) {
			LLE_REQ_LOCK(ln);
			ln->r_skip_req = 0; 
			ln->lle_hittime = time_uptime;
			LLE_REQ_UNLOCK(ln);
		}
		if (plle) {
			LLE_ADDREF(ln);
			*plle = ln;
			LLE_WUNLOCK(ln);
		}
		IF_AFDATA_RUNLOCK(ifp);
		return (0);
	} else if (plle && ln)
		LLE_WUNLOCK(ln);
	IF_AFDATA_RUNLOCK(ifp);
	return (nd6_resolve_slow(ifp, 0, m, dst6, desten, pflags, plle));
}
int nd6_resolve ( struct ifnet * ifp , int is_gw , struct mbuf * m , const struct sockaddr * sa_dst , u_char * desten , uint32_t * pflags , struct llentry * * plle ) { struct llentry * ln = NULL ; const struct sockaddr_in6 * dst6 ; if ( pflags != NULL ) * pflags = 0 ; dst6 = ( const struct sockaddr_in6 * ) sa_dst ; if ( ( ND_IFINFO ( ifp ) -> flags & ND6_IFF_IFDISABLED ) ) { m_freem ( m ) ; return ( ENETDOWN ) ; } if ( m != NULL && m -> m_flags & M_MCAST ) { switch ( ifp -> if_type ) { case IFT_ETHER : case IFT_FDDI : case IFT_L2VLAN : case IFT_IEEE80211 : case IFT_BRIDGE : case IFT_ISO88025 : ETHER_MAP_IPV6_MULTICAST ( & dst6 -> sin6_addr , desten ) ; return ( 0 ) ; default : m_freem ( m ) ; return ( EAFNOSUPPORT ) ; } } IF_AFDATA_RLOCK ( ifp ) ; ln = nd6_lookup ( & dst6 -> sin6_addr , plle ? LLE_EXCLUSIVE : LLE_UNLOCKED , ifp ) ; if ( ln != NULL && ( ln -> r_flags & RLLE_VALID ) != 0 ) { bcopy ( ln -> r_linkdata , desten , ln -> r_hdrlen ) ; if ( pflags != NULL ) * pflags = LLE_VALID | ( ln -> r_flags & RLLE_IFADDR ) ; if ( ln -> r_skip_req != 0 ) { LLE_REQ_LOCK ( ln ) ; ln -> r_skip_req = 0 ; ln -> lle_hittime = time_uptime ; LLE_REQ_UNLOCK ( ln ) ; } if ( plle ) { LLE_ADDREF ( ln ) ; * plle = ln ; LLE_WUNLOCK ( ln ) ; } IF_AFDATA_RUNLOCK ( ifp ) ; return ( 0 ) ; } else if ( plle && ln ) LLE_WUNLOCK ( ln ) ; IF_AFDATA_RUNLOCK ( ifp ) ; return ( nd6_resolve_slow ( ifp , 0 , m , dst6 , desten , pflags , plle ) ) ; }
Lookup link headerfor @sa_dst address.
Lookup link headerfor @sa_dst address .
/* discard the packet if IPv6 operation is disabled on the interface */ /* better error? */ /* Entry found, let's copy lle info */ /* Check if we have feedback request from nd6 timer */ /* Notify that entry was used */