Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet6/nd6_nbr.c
Show First 20 Lines • Show All 619 Lines • ▼ Show 20 Lines | nd6_na_input(struct mbuf *m, int off, int icmp6len) | ||||
struct ip6_hdr *ip6; | struct ip6_hdr *ip6; | ||||
struct ifaddr *ifa; | struct ifaddr *ifa; | ||||
struct llentry *ln; | struct llentry *ln; | ||||
struct mbuf *chain; | struct mbuf *chain; | ||||
struct nd_neighbor_advert *nd_na; | struct nd_neighbor_advert *nd_na; | ||||
struct in6_addr daddr6, taddr6; | struct in6_addr daddr6, taddr6; | ||||
struct sockaddr_in6 sin6; | struct sockaddr_in6 sin6; | ||||
union nd_opts ndopts; | union nd_opts ndopts; | ||||
u_char linkhdr[LLE_MAX_LINKHDR]; | |||||
char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN]; | char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN]; | ||||
char *lladdr; | char *lladdr; | ||||
size_t linkhdrsize; | |||||
int flags, is_override, is_router, is_solicited; | int flags, is_override, is_router, is_solicited; | ||||
int lladdr_off, lladdrlen, checklink; | int lladdrlen, checklink; | ||||
bool flush_chains = false; | |||||
NET_EPOCH_ASSERT(); | NET_EPOCH_ASSERT(); | ||||
chain = NULL; | chain = NULL; | ||||
ln = NULL; | ln = NULL; | ||||
checklink = 0; | checklink = 0; | ||||
/* RFC 6980: Nodes MUST silently ignore fragments */ | /* RFC 6980: Nodes MUST silently ignore fragments */ | ||||
▲ Show 20 Lines • Show All 101 Lines • ▼ Show 20 Lines | nd6log((LOG_INFO, "nd6_na_input: lladdrlen mismatch for %s " | ||||
ifp->if_addrlen, lladdrlen - 2)); | ifp->if_addrlen, lladdrlen - 2)); | ||||
goto bad; | goto bad; | ||||
} | } | ||||
/* | /* | ||||
* If no neighbor cache entry is found, NA SHOULD silently be | * If no neighbor cache entry is found, NA SHOULD silently be | ||||
* discarded. | * discarded. | ||||
*/ | */ | ||||
ln = nd6_lookup(&taddr6, LLE_EXCLUSIVE, ifp); | ln = nd6_lookup(&taddr6, ND6_SF6(LLE_EXCLUSIVE), ifp); | ||||
if (ln == NULL) { | if (ln == NULL) { | ||||
goto freeit; | goto freeit; | ||||
} | } | ||||
/* | /* | ||||
* Do not try to override static entry. | * Do not try to override static entry. | ||||
*/ | */ | ||||
if (ln->la_flags & LLE_STATIC) | if (ln->la_flags & LLE_STATIC) | ||||
goto freeit; | goto freeit; | ||||
if (ln->ln_state == ND6_LLINFO_INCOMPLETE) { | if (ln->ln_state == ND6_LLINFO_INCOMPLETE) { | ||||
/* | /* | ||||
* If the link-layer has address, and no lladdr option came, | * If the link-layer has address, and no lladdr option came, | ||||
* discard the packet. | * discard the packet. | ||||
*/ | */ | ||||
if (ifp->if_addrlen && lladdr == NULL) { | if (ifp->if_addrlen && lladdr == NULL) { | ||||
goto freeit; | goto freeit; | ||||
} | } | ||||
/* | /* | ||||
* Record link-layer address, and update the state. | * Record link-layer address, and update the state. | ||||
*/ | */ | ||||
linkhdrsize = sizeof(linkhdr); | if (!nd6_try_set_entry_addr(ifp, ln, lladdr)) | ||||
if (lltable_calc_llheader(ifp, AF_INET6, lladdr, | |||||
linkhdr, &linkhdrsize, &lladdr_off) != 0) | |||||
return; | |||||
if (lltable_try_set_entry_addr(ifp, ln, linkhdr, linkhdrsize, | |||||
lladdr_off) == 0) { | |||||
ln = NULL; | |||||
goto freeit; | goto freeit; | ||||
} | |||||
flush_chains = true; | |||||
EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED); | EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED); | ||||
if (is_solicited) | if (is_solicited) | ||||
nd6_llinfo_setstate(ln, ND6_LLINFO_REACHABLE); | nd6_llinfo_setstate(ln, ND6_LLINFO_REACHABLE); | ||||
else | else | ||||
nd6_llinfo_setstate(ln, ND6_LLINFO_STALE); | nd6_llinfo_setstate(ln, ND6_LLINFO_STALE); | ||||
if ((ln->ln_router = is_router) != 0) { | if ((ln->ln_router = is_router) != 0) { | ||||
/* | /* | ||||
* This means a router's state has changed from | * This means a router's state has changed from | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | if (!is_override && (lladdr != NULL && llchange)) { /* (1) */ | ||||
goto freeit; | goto freeit; | ||||
} else if (is_override /* (2a) */ | } else if (is_override /* (2a) */ | ||||
|| (!is_override && (lladdr != NULL && !llchange)) /* (2b) */ | || (!is_override && (lladdr != NULL && !llchange)) /* (2b) */ | ||||
|| lladdr == NULL) { /* (2c) */ | || lladdr == NULL) { /* (2c) */ | ||||
/* | /* | ||||
* Update link-local address, if any. | * Update link-local address, if any. | ||||
*/ | */ | ||||
if (lladdr != NULL) { | if (lladdr != NULL) { | ||||
linkhdrsize = sizeof(linkhdr); | if (!nd6_try_set_entry_addr(ifp, ln, lladdr)) | ||||
if (lltable_calc_llheader(ifp, AF_INET6, lladdr, | |||||
linkhdr, &linkhdrsize, &lladdr_off) != 0) | |||||
goto freeit; | goto freeit; | ||||
if (lltable_try_set_entry_addr(ifp, ln, linkhdr, | |||||
linkhdrsize, lladdr_off) == 0) { | flush_chains = true; | ||||
ln = NULL; | |||||
goto freeit; | |||||
} | |||||
EVENTHANDLER_INVOKE(lle_event, ln, | EVENTHANDLER_INVOKE(lle_event, ln, | ||||
LLENTRY_RESOLVED); | LLENTRY_RESOLVED); | ||||
} | } | ||||
/* | /* | ||||
* If solicited, make the state REACHABLE. | * If solicited, make the state REACHABLE. | ||||
* If not solicited and the link-layer address was | * If not solicited and the link-layer address was | ||||
* changed, make it STALE. | * changed, make it STALE. | ||||
Show All 37 Lines | if (ln->la_hold != NULL) { | ||||
memset(&sin6, 0, sizeof(sin6)); | memset(&sin6, 0, sizeof(sin6)); | ||||
nd6_grab_holdchain(ln, &chain, &sin6); | nd6_grab_holdchain(ln, &chain, &sin6); | ||||
} | } | ||||
freeit: | freeit: | ||||
if (ln != NULL) | if (ln != NULL) | ||||
LLE_WUNLOCK(ln); | LLE_WUNLOCK(ln); | ||||
if (chain != NULL) | if (chain != NULL) | ||||
nd6_flush_holdchain(ifp, chain, &sin6); | nd6_flush_holdchain(ifp, ln, chain, &sin6); | ||||
if (flush_chains) | |||||
nd6_flush_children_holdchain(ifp, ln); | |||||
if (checklink) | if (checklink) | ||||
pfxlist_onlink_check(); | pfxlist_onlink_check(); | ||||
m_freem(m); | m_freem(m); | ||||
return; | return; | ||||
bad: | bad: | ||||
▲ Show 20 Lines • Show All 652 Lines • Show Last 20 Lines |