Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet6/nd6.c
Show First 20 Lines • Show All 1,917 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
struct llentry *ln = NULL, *ln_tmp; | struct llentry *ln = NULL, *ln_tmp; | ||||
int is_newentry; | int is_newentry; | ||||
int do_update; | int do_update; | ||||
int olladdr; | int olladdr; | ||||
int llchange; | int llchange; | ||||
int flags; | int flags; | ||||
uint16_t router = 0; | uint16_t router = 0; | ||||
struct sockaddr_in6 sin6; | |||||
struct mbuf *chain = NULL; | struct mbuf *chain = NULL; | ||||
u_char linkhdr[LLE_MAX_LINKHDR]; | u_char linkhdr[LLE_MAX_LINKHDR]; | ||||
size_t linkhdrsize; | size_t linkhdrsize; | ||||
int lladdr_off; | int lladdr_off; | ||||
NET_EPOCH_ASSERT(); | NET_EPOCH_ASSERT(); | ||||
IF_AFDATA_UNLOCK_ASSERT(ifp); | IF_AFDATA_UNLOCK_ASSERT(ifp); | ||||
▲ Show 20 Lines • Show All 104 Lines • ▼ Show 20 Lines | if (lltable_try_set_entry_addr(ifp, ln, linkhdr, linkhdrsize, | ||||
return; | return; | ||||
} | } | ||||
nd6_llinfo_setstate(ln, ND6_LLINFO_STALE); | nd6_llinfo_setstate(ln, ND6_LLINFO_STALE); | ||||
EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED); | EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED); | ||||
if (ln->la_hold != NULL) | if (ln->la_hold != NULL) | ||||
nd6_grab_holdchain(ln, &chain, &sin6); | chain = nd6_grab_holdchain(ln); | ||||
} | } | ||||
/* Calculates new router status */ | /* Calculates new router status */ | ||||
router = nd6_is_router(type, code, is_newentry, olladdr, | router = nd6_is_router(type, code, is_newentry, olladdr, | ||||
lladdr != NULL ? 1 : 0, ln->ln_router); | lladdr != NULL ? 1 : 0, ln->ln_router); | ||||
ln->ln_router = router; | ln->ln_router = router; | ||||
/* Mark non-router redirects with special flag */ | /* Mark non-router redirects with special flag */ | ||||
if ((type & 0xFF) == ND_REDIRECT && code != ND_REDIRECT_ROUTER) | if ((type & 0xFF) == ND_REDIRECT && code != ND_REDIRECT_ROUTER) | ||||
ln->la_flags |= LLE_REDIRECT; | ln->la_flags |= LLE_REDIRECT; | ||||
if (flags & LLE_EXCLUSIVE) | if (flags & LLE_EXCLUSIVE) | ||||
LLE_WUNLOCK(ln); | LLE_WUNLOCK(ln); | ||||
else | else | ||||
LLE_RUNLOCK(ln); | LLE_RUNLOCK(ln); | ||||
if (chain != NULL) | if (chain != NULL) | ||||
nd6_flush_holdchain(ifp, chain, &sin6); | nd6_flush_holdchain(ifp, ln, chain); | ||||
/* | /* | ||||
* When the link-layer address of a router changes, select the | * When the link-layer address of a router changes, select the | ||||
* best router again. In particular, when the neighbor entry is newly | * best router again. In particular, when the neighbor entry is newly | ||||
* created, it might affect the selection policy. | * created, it might affect the selection policy. | ||||
* Question: can we restrict the first condition to the "is_newentry" | * Question: can we restrict the first condition to the "is_newentry" | ||||
* case? | * case? | ||||
* XXX: when we hear an RA from a new router with the link-layer | * XXX: when we hear an RA from a new router with the link-layer | ||||
Show All 40 Lines | if (nd6if->basereachable && /* already initialized */ | ||||
nd6if->recalctm = V_nd6_recalc_reachtm_interval; | nd6if->recalctm = V_nd6_recalc_reachtm_interval; | ||||
nd6if->reachable = ND_COMPUTE_RTIME(nd6if->basereachable); | nd6if->reachable = ND_COMPUTE_RTIME(nd6if->basereachable); | ||||
} | } | ||||
} | } | ||||
NET_EPOCH_EXIT(et); | NET_EPOCH_EXIT(et); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
} | } | ||||
void | struct mbuf * | ||||
nd6_grab_holdchain(struct llentry *ln, struct mbuf **chain, | nd6_grab_holdchain(struct llentry *ln) | ||||
struct sockaddr_in6 *sin6) | |||||
{ | { | ||||
struct mbuf *chain; | |||||
LLE_WLOCK_ASSERT(ln); | LLE_WLOCK_ASSERT(ln); | ||||
*chain = ln->la_hold; | chain = ln->la_hold; | ||||
ln->la_hold = NULL; | ln->la_hold = NULL; | ||||
lltable_fill_sa_entry(ln, (struct sockaddr *)sin6); | |||||
if (ln->ln_state == ND6_LLINFO_STALE) { | if (ln->ln_state == ND6_LLINFO_STALE) { | ||||
/* | /* | ||||
* The first time we send a packet to a | * The first time we send a packet to a | ||||
* neighbor whose entry is STALE, we have | * neighbor whose entry is STALE, we have | ||||
* to change the state to DELAY and a sets | * to change the state to DELAY and a sets | ||||
* a timer to expire in DELAY_FIRST_PROBE_TIME | * a timer to expire in DELAY_FIRST_PROBE_TIME | ||||
* seconds to ensure do neighbor unreachability | * seconds to ensure do neighbor unreachability | ||||
* detection on expiration. | * detection on expiration. | ||||
* (RFC 2461 7.3.3) | * (RFC 2461 7.3.3) | ||||
*/ | */ | ||||
nd6_llinfo_setstate(ln, ND6_LLINFO_DELAY); | nd6_llinfo_setstate(ln, ND6_LLINFO_DELAY); | ||||
} | } | ||||
return (chain); | |||||
} | } | ||||
int | int | ||||
nd6_output_ifp(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m, | nd6_output_ifp(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m, | ||||
struct sockaddr_in6 *dst, struct route *ro) | struct sockaddr_in6 *dst, struct route *ro) | ||||
{ | { | ||||
int error; | int error; | ||||
int ip6len; | int ip6len; | ||||
▲ Show 20 Lines • Show All 277 Lines • ▼ Show 20 Lines | nd6_resolve_addr(struct ifnet *ifp, int flags, const struct sockaddr *dst, | ||||
flags |= LLE_ADDRONLY; | flags |= LLE_ADDRONLY; | ||||
error = nd6_resolve_slow(ifp, flags, NULL, | error = nd6_resolve_slow(ifp, flags, NULL, | ||||
(const struct sockaddr_in6 *)dst, desten, pflags, NULL); | (const struct sockaddr_in6 *)dst, desten, pflags, NULL); | ||||
return (error); | return (error); | ||||
} | } | ||||
int | int | ||||
nd6_flush_holdchain(struct ifnet *ifp, struct mbuf *chain, | nd6_flush_holdchain(struct ifnet *ifp, struct llentry *lle, struct mbuf *chain) | ||||
struct sockaddr_in6 *dst) | |||||
{ | { | ||||
struct mbuf *m, *m_head; | struct mbuf *m, *m_head; | ||||
struct sockaddr_in6 dst6; | |||||
int error = 0; | int error = 0; | ||||
NET_EPOCH_ASSERT(); | |||||
struct route_in6 ro = { | |||||
.ro_prepend = lle->r_linkdata, | |||||
.ro_plen = lle->r_hdrlen, | |||||
}; | |||||
lltable_fill_sa_entry(lle, (struct sockaddr *)&dst6); | |||||
m_head = chain; | m_head = chain; | ||||
while (m_head) { | while (m_head) { | ||||
m = m_head; | m = m_head; | ||||
m_head = m_head->m_nextpkt; | m_head = m_head->m_nextpkt; | ||||
m->m_nextpkt = NULL; | m->m_nextpkt = NULL; | ||||
error = nd6_output_ifp(ifp, ifp, m, dst, NULL); | error = nd6_output_ifp(ifp, ifp, m, &dst6, (struct route *)&ro); | ||||
} | } | ||||
/* | /* | ||||
* XXX | * XXX | ||||
* note that intermediate errors are blindly ignored | * note that intermediate errors are blindly ignored | ||||
*/ | */ | ||||
return (error); | return (error); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 188 Lines • Show Last 20 Lines |