48 #if LWIP_ARP || LWIP_ETHERNET
59 #ifdef LWIP_HOOK_FILENAME
60 #include LWIP_HOOK_FILENAME
63 #if LWIP_IPV4 && LWIP_ARP
67 #define ARP_AGE_REREQUEST_USED_UNICAST (ARP_MAXAGE - 30)
68 #define ARP_AGE_REREQUEST_USED_BROADCAST (ARP_MAXAGE - 15)
77 #define ARP_MAXPENDING 5
81 ETHARP_STATE_EMPTY = 0,
84 ETHARP_STATE_STABLE_REREQUESTING_1,
85 ETHARP_STATE_STABLE_REREQUESTING_2
86 #if ETHARP_SUPPORT_STATIC_ENTRIES
94 struct etharp_q_entry *q;
108 #if !LWIP_NETIF_HWADDRHINT
109 static u8_t etharp_cached_entry;
114 #define ETHARP_FLAG_TRY_HARD 1
115 #define ETHARP_FLAG_FIND_ONLY 2
116 #if ETHARP_SUPPORT_STATIC_ENTRIES
117 #define ETHARP_FLAG_STATIC_ENTRY 4
120 #if LWIP_NETIF_HWADDRHINT
121 #define ETHARP_SET_HINT(netif, hint) if (((netif) != NULL) && ((netif)->addr_hint != NULL)) \
122 *((netif)->addr_hint) = (hint);
124 #define ETHARP_SET_HINT(netif, hint) (etharp_cached_entry = (hint))
129 #if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f))
130 #error "ARP_TABLE_SIZE must fit in an s8_t, you have to reduce it in your lwipopts.h"
134 static err_t etharp_request_dst(
struct netif *
netif,
const ip4_addr_t *ipaddr,
const struct eth_addr* hw_dst_addr);
137 const struct eth_addr *hwsrc_addr,
const ip4_addr_t *ipsrc_addr,
138 const struct eth_addr *hwdst_addr,
const ip4_addr_t *ipdst_addr,
148 free_etharp_q(
struct etharp_q_entry *q)
150 struct etharp_q_entry *r;
164 #define free_etharp_q(q) pbuf_free(q)
170 etharp_free_entry(
int i)
175 if (arp_table[i].q !=
NULL) {
178 free_etharp_q(arp_table[i].q);
179 arp_table[i].q =
NULL;
182 arp_table[i].state = ETHARP_STATE_EMPTY;
185 arp_table[i].ctime = 0;
186 arp_table[i].netif =
NULL;
187 ip4_addr_set_zero(&arp_table[i].ipaddr);
188 arp_table[i].ethaddr = ethzero;
206 u8_t state = arp_table[i].state;
207 if (state != ETHARP_STATE_EMPTY
209 && (state != ETHARP_STATE_STATIC)
212 arp_table[i].ctime++;
214 ((arp_table[i].state == ETHARP_STATE_PENDING) &&
215 (arp_table[i].ctime >= ARP_MAXPENDING))) {
218 arp_table[i].state >= ETHARP_STATE_STABLE ?
"stable" :
"pending", (
u16_t)i));
220 etharp_free_entry(i);
221 }
else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING_1) {
223 arp_table[i].state = ETHARP_STATE_STABLE_REREQUESTING_2;
224 }
else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING_2) {
227 arp_table[i].state = ETHARP_STATE_STABLE;
228 }
else if (arp_table[i].state == ETHARP_STATE_PENDING) {
230 etharp_request(arp_table[i].
netif, &arp_table[i].ipaddr);
258 etharp_find_entry(
const ip4_addr_t *ipaddr,
u8_t flags,
struct netif*
netif)
266 u16_t age_queue = 0, age_pending = 0, age_stable = 0;
286 u8_t state = arp_table[i].state;
292 }
else if (state != ETHARP_STATE_EMPTY) {
293 LWIP_ASSERT(
"state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE",
294 state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE);
296 if (ipaddr && ip4_addr_cmp(ipaddr, &arp_table[i].ipaddr)
306 if (state == ETHARP_STATE_PENDING) {
308 if (arp_table[i].q !=
NULL) {
309 if (arp_table[i].ctime >= age_queue) {
311 age_queue = arp_table[i].ctime;
316 if (arp_table[i].ctime >= age_pending) {
318 age_pending = arp_table[i].ctime;
322 }
else if (state >= ETHARP_STATE_STABLE) {
323 #if ETHARP_SUPPORT_STATIC_ENTRIES
325 if (state < ETHARP_STATE_STATIC)
329 if (arp_table[i].ctime >= age_stable) {
331 age_stable = arp_table[i].ctime;
340 if (((flags & ETHARP_FLAG_FIND_ONLY) != 0) ||
342 ((empty ==
ARP_TABLE_SIZE) && ((flags & ETHARP_FLAG_TRY_HARD) == 0))) {
386 etharp_free_entry(i);
390 LWIP_ASSERT(
"arp_table[i].state == ETHARP_STATE_EMPTY",
391 arp_table[i].state == ETHARP_STATE_EMPTY);
394 if (ipaddr !=
NULL) {
396 ip4_addr_copy(arp_table[i].ipaddr, *ipaddr);
398 arp_table[i].ctime = 0;
399 #if ETHARP_TABLE_MATCH_NETIF
400 arp_table[i].netif =
netif;
424 etharp_update_arp_entry(
struct netif *
netif,
const ip4_addr_t *ipaddr,
struct eth_addr *ethaddr,
u8_t flags)
429 ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr),
430 (
u16_t)ethaddr->addr[0], (
u16_t)ethaddr->addr[1], (
u16_t)ethaddr->addr[2],
431 (
u16_t)ethaddr->addr[3], (
u16_t)ethaddr->addr[4], (
u16_t)ethaddr->addr[5]));
433 if (ip4_addr_isany(ipaddr) ||
434 ip4_addr_isbroadcast(ipaddr,
netif) ||
435 ip4_addr_ismulticast(ipaddr)) {
440 i = etharp_find_entry(ipaddr, flags,
netif);
446 #if ETHARP_SUPPORT_STATIC_ENTRIES
447 if (flags & ETHARP_FLAG_STATIC_ENTRY) {
449 arp_table[i].state = ETHARP_STATE_STATIC;
450 }
else if (arp_table[i].state == ETHARP_STATE_STATIC) {
457 arp_table[i].state = ETHARP_STATE_STABLE;
461 arp_table[i].netif =
netif;
469 arp_table[i].ctime = 0;
472 while (arp_table[i].q !=
NULL) {
475 struct etharp_q_entry *q = arp_table[i].q;
477 arp_table[i].q = q->
next;
483 if (arp_table[i].q !=
NULL) {
484 struct pbuf *p = arp_table[i].q;
485 arp_table[i].q =
NULL;
495 #if ETHARP_SUPPORT_STATIC_ENTRIES
505 etharp_add_static_entry(
const ip4_addr_t *ipaddr,
struct eth_addr *ethaddr)
509 ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr),
510 (
u16_t)ethaddr->addr[0], (
u16_t)ethaddr->addr[1], (
u16_t)ethaddr->addr[2],
511 (
u16_t)ethaddr->addr[3], (
u16_t)ethaddr->addr[4], (
u16_t)ethaddr->addr[5]));
513 netif = ip4_route(ipaddr);
518 return etharp_update_arp_entry(
netif, ipaddr, ethaddr, ETHARP_FLAG_TRY_HARD | ETHARP_FLAG_STATIC_ENTRY);
530 etharp_remove_static_entry(
const ip4_addr_t *ipaddr)
534 ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr)));
537 i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY,
NULL);
543 if (arp_table[i].
state != ETHARP_STATE_STATIC) {
548 etharp_free_entry(i);
566 etharp_free_entry(i);
583 etharp_find_addr(
struct netif *
netif,
const ip4_addr_t *ipaddr,
584 struct eth_addr **eth_ret,
const ip4_addr_t **ip_ret)
593 i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY,
netif);
594 if ((i >= 0) && (arp_table[i].
state >= ETHARP_STATE_STABLE)) {
595 *eth_ret = &arp_table[i].ethaddr;
596 *ip_ret = &arp_table[i].ipaddr;
619 *ipaddr = &arp_table[i].ipaddr;
620 *
netif = arp_table[i].netif;
621 *eth_ret = &arp_table[i].ethaddr;
645 ip4_addr_t sipaddr, dipaddr;
655 (hdr->protolen !=
sizeof(ip4_addr_t)) ||
658 (
"etharp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n",
659 hdr->hwtype, (
u16_t)hdr->hwlen, hdr->proto, (
u16_t)hdr->protolen));
671 autoip_arp_reply(
netif, hdr);
676 IPADDR2_COPY(&sipaddr, &hdr->sipaddr);
677 IPADDR2_COPY(&dipaddr, &hdr->dipaddr);
680 if (ip4_addr_isany_val(*netif_ip4_addr(
netif))) {
684 for_us = (
u8_t)ip4_addr_cmp(&dipaddr, netif_ip4_addr(
netif));
692 etharp_update_arp_entry(
netif, &sipaddr, &(hdr->shwaddr),
693 for_us ? ETHARP_FLAG_TRY_HARD : ETHARP_FLAG_FIND_ONLY);
696 switch (hdr->opcode) {
710 &hdr->shwaddr, &sipaddr,
713 }
else if (ip4_addr_isany_val(*netif_ip4_addr(
netif))) {
725 #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
730 dhcp_arp_reply(
netif, &sipaddr);
748 LWIP_ASSERT(
"arp_table[arp_idx].state >= ETHARP_STATE_STABLE",
749 arp_table[arp_idx].state >= ETHARP_STATE_STABLE);
753 if (arp_table[arp_idx].state == ETHARP_STATE_STABLE) {
754 if (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED_BROADCAST) {
756 if (etharp_request(
netif, &arp_table[arp_idx].ipaddr) ==
ERR_OK) {
757 arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING_1;
759 }
else if (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED_UNICAST) {
761 if (etharp_request_dst(
netif, &arp_table[arp_idx].ipaddr, &arp_table[arp_idx].ethaddr) ==
ERR_OK) {
762 arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING_1;
789 etharp_output(
struct netif *
netif,
struct pbuf *q,
const ip4_addr_t *ipaddr)
793 const ip4_addr_t *dst_addr = ipaddr;
803 if (ip4_addr_isbroadcast(ipaddr,
netif)) {
805 dest = (
const struct eth_addr *)ðbroadcast;
807 }
else if (ip4_addr_ismulticast(ipaddr)) {
812 mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
813 mcastaddr.addr[4] = ip4_addr3(ipaddr);
814 mcastaddr.addr[5] = ip4_addr4(ipaddr);
822 if (!ip4_addr_netcmp(ipaddr, netif_ip4_addr(
netif), netif_ip4_netmask(
netif)) &&
823 !ip4_addr_islinklocal(ipaddr)) {
830 if (!ip4_addr_islinklocal(&iphdr->src))
833 #ifdef LWIP_HOOK_ETHARP_GET_GW
836 dst_addr = LWIP_HOOK_ETHARP_GET_GW(
netif, ipaddr);
837 if (dst_addr ==
NULL)
841 if (!ip4_addr_isany_val(*netif_ip4_gw(
netif))) {
843 dst_addr = netif_ip4_gw(
netif);
852 #if LWIP_NETIF_HWADDRHINT
855 u8_t etharp_cached_entry = *(
netif->addr_hint);
858 if ((arp_table[etharp_cached_entry].state >= ETHARP_STATE_STABLE) &&
859 #if ETHARP_TABLE_MATCH_NETIF
860 (arp_table[etharp_cached_entry].netif ==
netif) &&
862 (ip4_addr_cmp(dst_addr, &arp_table[etharp_cached_entry].ipaddr))) {
865 return etharp_output_to_arp_index(
netif, q, etharp_cached_entry);
867 #if LWIP_NETIF_HWADDRHINT
875 if ((arp_table[i].state >= ETHARP_STATE_STABLE) &&
879 (ip4_addr_cmp(dst_addr, &arp_table[i].ipaddr))) {
881 ETHARP_SET_HINT(
netif, i);
882 return etharp_output_to_arp_index(
netif, q, i);
887 return etharp_query(
netif, dst_addr, q);
930 etharp_query(
struct netif *
netif,
const ip4_addr_t *ipaddr,
struct pbuf *q)
934 int is_new_entry = 0;
938 if (ip4_addr_isbroadcast(ipaddr,
netif) ||
939 ip4_addr_ismulticast(ipaddr) ||
940 ip4_addr_isany(ipaddr)) {
946 i = etharp_find_entry(ipaddr, ETHARP_FLAG_TRY_HARD,
netif);
959 if (arp_table[i].state == ETHARP_STATE_EMPTY) {
961 arp_table[i].state = ETHARP_STATE_PENDING;
963 arp_table[i].netif =
netif;
967 LWIP_ASSERT(
"arp_table[i].state == PENDING or STABLE",
968 ((arp_table[i].state == ETHARP_STATE_PENDING) ||
969 (arp_table[i].state >= ETHARP_STATE_STABLE)));
972 if (is_new_entry || (q ==
NULL)) {
974 result = etharp_request(
netif, ipaddr);
989 if (arp_table[i].state >= ETHARP_STATE_STABLE) {
991 ETHARP_SET_HINT(
netif, i);
993 result = ethernet_output(
netif, q, srcaddr, &(arp_table[i].ethaddr),
ETHTYPE_IP);
995 }
else if (arp_table[i].state == ETHARP_STATE_PENDING) {
1029 struct etharp_q_entry *new_entry;
1031 new_entry = (
struct etharp_q_entry *)
memp_malloc(MEMP_ARP_QUEUE);
1032 if (new_entry !=
NULL) {
1033 unsigned int qlen = 0;
1034 new_entry->next = 0;
1036 if (arp_table[i].q !=
NULL) {
1038 struct etharp_q_entry *r;
1041 while (r->next !=
NULL) {
1045 r->
next = new_entry;
1048 arp_table[i].q = new_entry;
1052 struct etharp_q_entry *old;
1053 old = arp_table[i].q;
1054 arp_table[i].q = arp_table[i].q->
next;
1069 if (arp_table[i].q !=
NULL) {
1103 const struct eth_addr *ethdst_addr,
1104 const struct eth_addr *hwsrc_addr,
const ip4_addr_t *ipsrc_addr,
1105 const struct eth_addr *hwdst_addr,
const ip4_addr_t *ipdst_addr,
1119 (
"etharp_raw: could not allocate pbuf for ARP request.\n"));
1123 LWIP_ASSERT(
"check that first pbuf can hold struct etharp_hdr",
1130 LWIP_ASSERT(
"netif->hwaddr_len must be the same as ETH_HWADDR_LEN for etharp!",
1138 IPADDR2_COPY(&hdr->sipaddr, ipsrc_addr);
1139 IPADDR2_COPY(&hdr->dipaddr, ipdst_addr);
1145 hdr->protolen =
sizeof(ip4_addr_t);
1152 if(ip4_addr_islinklocal(ipsrc_addr)) {
1182 etharp_request_dst(
struct netif *
netif,
const ip4_addr_t *ipaddr,
const struct eth_addr* hw_dst_addr)
1199 etharp_request(
struct netif *
netif,
const ip4_addr_t *ipaddr)
1202 return etharp_request_dst(
netif, ipaddr, ðbroadcast);