Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/if_ether.c
Show First 20 Lines • Show All 1,139 Lines • ▼ Show 20 Lines | #endif | ||||
ARPSTAT_INC(txreplies); | ARPSTAT_INC(txreplies); | ||||
return; | return; | ||||
drop: | drop: | ||||
m_freem(m); | m_freem(m); | ||||
} | } | ||||
#endif | #endif | ||||
static struct mbuf * | |||||
arp_grab_holdchain(struct llentry *la) | |||||
{ | |||||
struct mbuf *chain; | |||||
LLE_WLOCK_ASSERT(la); | |||||
chain = la->la_hold; | |||||
la->la_hold = NULL; | |||||
la->la_numheld = 0; | |||||
return (chain); | |||||
} | |||||
static void | |||||
arp_flush_holdchain(struct ifnet *ifp, struct llentry *la, struct mbuf *chain) | |||||
{ | |||||
struct mbuf *m_hold, *m_hold_next; | |||||
struct sockaddr_in sin; | |||||
NET_EPOCH_ASSERT(); | |||||
struct route ro = { | |||||
.ro_prepend = la->r_linkdata, | |||||
.ro_plen = la->r_hdrlen, | |||||
}; | |||||
lltable_fill_sa_entry(la, (struct sockaddr *)&sin); | |||||
for (m_hold = chain; m_hold != NULL; m_hold = m_hold_next) { | |||||
m_hold_next = m_hold->m_nextpkt; | |||||
m_hold->m_nextpkt = NULL; | |||||
/* Avoid confusing lower layers. */ | |||||
m_clrprotoflags(m_hold); | |||||
(*ifp->if_output)(ifp, m_hold, (struct sockaddr *)&sin, &ro); | |||||
} | |||||
} | |||||
/* | /* | ||||
* Checks received arp data against existing @la. | * Checks received arp data against existing @la. | ||||
* Updates lle state/performs notification if necessary. | * Updates lle state/performs notification if necessary. | ||||
*/ | */ | ||||
static void | static void | ||||
arp_check_update_lle(struct arphdr *ah, struct in_addr isaddr, struct ifnet *ifp, | arp_check_update_lle(struct arphdr *ah, struct in_addr isaddr, struct ifnet *ifp, | ||||
int bridged, struct llentry *la) | int bridged, struct llentry *la) | ||||
{ | { | ||||
struct sockaddr sa; | |||||
struct mbuf *m_hold, *m_hold_next; | |||||
uint8_t linkhdr[LLE_MAX_LINKHDR]; | uint8_t linkhdr[LLE_MAX_LINKHDR]; | ||||
size_t linkhdrsize; | size_t linkhdrsize; | ||||
int lladdr_off; | int lladdr_off; | ||||
char addrbuf[INET_ADDRSTRLEN]; | char addrbuf[INET_ADDRSTRLEN]; | ||||
LLE_WLOCK_ASSERT(la); | LLE_WLOCK_ASSERT(la); | ||||
/* the following is not an error when doing bridging */ | /* the following is not an error when doing bridging */ | ||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | arp_check_update_lle(struct arphdr *ah, struct in_addr isaddr, struct ifnet *ifp, | ||||
/* | /* | ||||
* The packets are all freed within the call to the output | * The packets are all freed within the call to the output | ||||
* routine. | * routine. | ||||
* | * | ||||
* NB: The lock MUST be released before the call to the | * NB: The lock MUST be released before the call to the | ||||
* output routine. | * output routine. | ||||
*/ | */ | ||||
if (la->la_hold != NULL) { | if (la->la_hold != NULL) { | ||||
m_hold = la->la_hold; | struct mbuf *chain; | ||||
la->la_hold = NULL; | |||||
la->la_numheld = 0; | chain = arp_grab_holdchain(la); | ||||
lltable_fill_sa_entry(la, &sa); | |||||
LLE_WUNLOCK(la); | LLE_WUNLOCK(la); | ||||
for (; m_hold != NULL; m_hold = m_hold_next) { | arp_flush_holdchain(ifp, la, chain); | ||||
m_hold_next = m_hold->m_nextpkt; | |||||
m_hold->m_nextpkt = NULL; | |||||
/* Avoid confusing lower layers. */ | |||||
m_clrprotoflags(m_hold); | |||||
(*ifp->if_output)(ifp, m_hold, &sa, NULL); | |||||
} | |||||
} else | } else | ||||
LLE_WUNLOCK(la); | LLE_WUNLOCK(la); | ||||
} | } | ||||
static void | static void | ||||
arp_mark_lle_reachable(struct llentry *la) | arp_mark_lle_reachable(struct llentry *la) | ||||
{ | { | ||||
int canceled, wtime; | int canceled, wtime; | ||||
▲ Show 20 Lines • Show All 263 Lines • Show Last 20 Lines |