The Pedigree Project  0.1
etharp.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
33 /*
34  * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
35  * Copyright (c) 2003-2004 Leon Woestenberg <leon.woestenberg@axon.tv>
36  * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands.
37  * All rights reserved.
38  *
39  * Redistribution and use in source and binary forms, with or without modification,
40  * are permitted provided that the following conditions are met:
41  *
42  * 1. Redistributions of source code must retain the above copyright notice,
43  * this list of conditions and the following disclaimer.
44  * 2. Redistributions in binary form must reproduce the above copyright notice,
45  * this list of conditions and the following disclaimer in the documentation
46  * and/or other materials provided with the distribution.
47  * 3. The name of the author may not be used to endorse or promote products
48  * derived from this software without specific prior written permission.
49  *
50  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
51  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
52  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
53  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
54  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
55  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
56  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
57  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
58  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
59  * OF SUCH DAMAGE.
60  *
61  * This file is part of the lwIP TCP/IP stack.
62  *
63  */
64 
65 #include "lwip/opt.h"
66 
67 #if LWIP_ARP || LWIP_ETHERNET
68 
69 #include "lwip/etharp.h"
70 #include "lwip/stats.h"
71 #include "lwip/snmp.h"
72 #include "lwip/dhcp.h"
73 #include "lwip/autoip.h"
74 #include "netif/ethernet.h"
75 
76 #include <string.h>
77 
78 #ifdef LWIP_HOOK_FILENAME
79 #include LWIP_HOOK_FILENAME
80 #endif
81 
82 #if LWIP_IPV4 && LWIP_ARP /* don't build if not configured for use in lwipopts.h */
83 
86 #define ARP_AGE_REREQUEST_USED_UNICAST (ARP_MAXAGE - 30)
87 #define ARP_AGE_REREQUEST_USED_BROADCAST (ARP_MAXAGE - 15)
88 
96 #define ARP_MAXPENDING 5
97 
99 enum etharp_state {
100  ETHARP_STATE_EMPTY = 0,
101  ETHARP_STATE_PENDING,
102  ETHARP_STATE_STABLE,
103  ETHARP_STATE_STABLE_REREQUESTING_1,
104  ETHARP_STATE_STABLE_REREQUESTING_2
105 #if ETHARP_SUPPORT_STATIC_ENTRIES
106  ,ETHARP_STATE_STATIC
107 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
108 };
109 
110 struct etharp_entry {
111 #if ARP_QUEUEING
112 
113  struct etharp_q_entry *q;
114 #else /* ARP_QUEUEING */
115 
116  struct pbuf *q;
117 #endif /* ARP_QUEUEING */
118  ip4_addr_t ipaddr;
119  struct netif *netif;
120  struct eth_addr ethaddr;
121  u16_t ctime;
122  u8_t state;
123 };
124 
125 static struct etharp_entry arp_table[ARP_TABLE_SIZE];
126 
127 #if !LWIP_NETIF_HWADDRHINT
128 static u8_t etharp_cached_entry;
129 #endif /* !LWIP_NETIF_HWADDRHINT */
130 
133 #define ETHARP_FLAG_TRY_HARD 1
134 #define ETHARP_FLAG_FIND_ONLY 2
135 #if ETHARP_SUPPORT_STATIC_ENTRIES
136 #define ETHARP_FLAG_STATIC_ENTRY 4
137 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
138 
139 #if LWIP_NETIF_HWADDRHINT
140 #define ETHARP_SET_HINT(netif, hint) if (((netif) != NULL) && ((netif)->addr_hint != NULL)) \
141  *((netif)->addr_hint) = (hint);
142 #else /* LWIP_NETIF_HWADDRHINT */
143 #define ETHARP_SET_HINT(netif, hint) (etharp_cached_entry = (hint))
144 #endif /* LWIP_NETIF_HWADDRHINT */
145 
146 
147 /* Some checks, instead of etharp_init(): */
148 #if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f))
149  #error "ARP_TABLE_SIZE must fit in an s8_t, you have to reduce it in your lwipopts.h"
150 #endif
151 
152 
153 static err_t etharp_request_dst(struct netif *netif, const ip4_addr_t *ipaddr, const struct eth_addr* hw_dst_addr);
154 static err_t etharp_raw(struct netif *netif,
155  const struct eth_addr *ethsrc_addr, const struct eth_addr *ethdst_addr,
156  const struct eth_addr *hwsrc_addr, const ip4_addr_t *ipsrc_addr,
157  const struct eth_addr *hwdst_addr, const ip4_addr_t *ipdst_addr,
158  const u16_t opcode);
159 
160 #if ARP_QUEUEING
161 
166 static void
167 free_etharp_q(struct etharp_q_entry *q)
168 {
169  struct etharp_q_entry *r;
170  LWIP_ASSERT("q != NULL", q != NULL);
171  LWIP_ASSERT("q->p != NULL", q->p != NULL);
172  while (q) {
173  r = q;
174  q = q->next;
175  LWIP_ASSERT("r->p != NULL", (r->p != NULL));
176  pbuf_free(r->p);
177  memp_free(MEMP_ARP_QUEUE, r);
178  }
179 }
180 #else /* ARP_QUEUEING */
181 
183 #define free_etharp_q(q) pbuf_free(q)
184 
185 #endif /* ARP_QUEUEING */
186 
188 static void
189 etharp_free_entry(int i)
190 {
191  /* remove from SNMP ARP index tree */
192  mib2_remove_arp_entry(arp_table[i].netif, &arp_table[i].ipaddr);
193  /* and empty packet queue */
194  if (arp_table[i].q != NULL) {
195  /* remove all queued packets */
196  LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_free_entry: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].q)));
197  free_etharp_q(arp_table[i].q);
198  arp_table[i].q = NULL;
199  }
200  /* recycle entry for re-use */
201  arp_table[i].state = ETHARP_STATE_EMPTY;
202 #ifdef LWIP_DEBUG
203  /* for debugging, clean out the complete entry */
204  arp_table[i].ctime = 0;
205  arp_table[i].netif = NULL;
206  ip4_addr_set_zero(&arp_table[i].ipaddr);
207  arp_table[i].ethaddr = ethzero;
208 #endif /* LWIP_DEBUG */
209 }
210 
217 void
218 etharp_tmr(void)
219 {
220  u8_t i;
221 
222  LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n"));
223  /* remove expired entries from the ARP table */
224  for (i = 0; i < ARP_TABLE_SIZE; ++i) {
225  u8_t state = arp_table[i].state;
226  if (state != ETHARP_STATE_EMPTY
228  && (state != ETHARP_STATE_STATIC)
229 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
230  ) {
231  arp_table[i].ctime++;
232  if ((arp_table[i].ctime >= ARP_MAXAGE) ||
233  ((arp_table[i].state == ETHARP_STATE_PENDING) &&
234  (arp_table[i].ctime >= ARP_MAXPENDING))) {
235  /* pending or stable entry has become old! */
236  LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n",
237  arp_table[i].state >= ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i));
238  /* clean up entries that have just been expired */
239  etharp_free_entry(i);
240  } else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING_1) {
241  /* Don't send more than one request every 2 seconds. */
242  arp_table[i].state = ETHARP_STATE_STABLE_REREQUESTING_2;
243  } else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING_2) {
244  /* Reset state to stable, so that the next transmitted packet will
245  re-send an ARP request. */
246  arp_table[i].state = ETHARP_STATE_STABLE;
247  } else if (arp_table[i].state == ETHARP_STATE_PENDING) {
248  /* still pending, resend an ARP query */
249  etharp_request(arp_table[i].netif, &arp_table[i].ipaddr);
250  }
251  }
252  }
253 }
254 
276 static s8_t
277 etharp_find_entry(const ip4_addr_t *ipaddr, u8_t flags, struct netif* netif)
278 {
279  s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE;
280  s8_t empty = ARP_TABLE_SIZE;
281  u8_t i = 0;
282  /* oldest entry with packets on queue */
283  s8_t old_queue = ARP_TABLE_SIZE;
284  /* its age */
285  u16_t age_queue = 0, age_pending = 0, age_stable = 0;
286 
287  LWIP_UNUSED_ARG(netif);
288 
295  /* a) in a single search sweep, do all of this
296  * 1) remember the first empty entry (if any)
297  * 2) remember the oldest stable entry (if any)
298  * 3) remember the oldest pending entry without queued packets (if any)
299  * 4) remember the oldest pending entry with queued packets (if any)
300  * 5) search for a matching IP entry, either pending or stable
301  * until 5 matches, or all entries are searched for.
302  */
303 
304  for (i = 0; i < ARP_TABLE_SIZE; ++i) {
305  u8_t state = arp_table[i].state;
306  /* no empty entry found yet and now we do find one? */
307  if ((empty == ARP_TABLE_SIZE) && (state == ETHARP_STATE_EMPTY)) {
308  LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_find_entry: found empty entry %"U16_F"\n", (u16_t)i));
309  /* remember first empty entry */
310  empty = i;
311  } else if (state != ETHARP_STATE_EMPTY) {
312  LWIP_ASSERT("state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE",
313  state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE);
314  /* if given, does IP address match IP address in ARP entry? */
315  if (ipaddr && ip4_addr_cmp(ipaddr, &arp_table[i].ipaddr)
317  && ((netif == NULL) || (netif == arp_table[i].netif))
318 #endif /* ETHARP_TABLE_MATCH_NETIF */
319  ) {
320  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: found matching entry %"U16_F"\n", (u16_t)i));
321  /* found exact IP address match, simply bail out */
322  return i;
323  }
324  /* pending entry? */
325  if (state == ETHARP_STATE_PENDING) {
326  /* pending with queued packets? */
327  if (arp_table[i].q != NULL) {
328  if (arp_table[i].ctime >= age_queue) {
329  old_queue = i;
330  age_queue = arp_table[i].ctime;
331  }
332  } else
333  /* pending without queued packets? */
334  {
335  if (arp_table[i].ctime >= age_pending) {
336  old_pending = i;
337  age_pending = arp_table[i].ctime;
338  }
339  }
340  /* stable entry? */
341  } else if (state >= ETHARP_STATE_STABLE) {
342 #if ETHARP_SUPPORT_STATIC_ENTRIES
343  /* don't record old_stable for static entries since they never expire */
344  if (state < ETHARP_STATE_STATIC)
345 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
346  {
347  /* remember entry with oldest stable entry in oldest, its age in maxtime */
348  if (arp_table[i].ctime >= age_stable) {
349  old_stable = i;
350  age_stable = arp_table[i].ctime;
351  }
352  }
353  }
354  }
355  }
356  /* { we have no match } => try to create a new entry */
357 
358  /* don't create new entry, only search? */
359  if (((flags & ETHARP_FLAG_FIND_ONLY) != 0) ||
360  /* or no empty entry found and not allowed to recycle? */
361  ((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_FLAG_TRY_HARD) == 0))) {
362  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty entry found and not allowed to recycle\n"));
363  return (s8_t)ERR_MEM;
364  }
365 
366  /* b) choose the least destructive entry to recycle:
367  * 1) empty entry
368  * 2) oldest stable entry
369  * 3) oldest pending entry without queued packets
370  * 4) oldest pending entry with queued packets
371  *
372  * { ETHARP_FLAG_TRY_HARD is set at this point }
373  */
374 
375  /* 1) empty entry available? */
376  if (empty < ARP_TABLE_SIZE) {
377  i = empty;
378  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting empty entry %"U16_F"\n", (u16_t)i));
379  } else {
380  /* 2) found recyclable stable entry? */
381  if (old_stable < ARP_TABLE_SIZE) {
382  /* recycle oldest stable*/
383  i = old_stable;
384  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i));
385  /* no queued packets should exist on stable entries */
386  LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL);
387  /* 3) found recyclable pending entry without queued packets? */
388  } else if (old_pending < ARP_TABLE_SIZE) {
389  /* recycle oldest pending */
390  i = old_pending;
391  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i));
392  /* 4) found recyclable pending entry with queued packets? */
393  } else if (old_queue < ARP_TABLE_SIZE) {
394  /* recycle oldest pending (queued packets are free in etharp_free_entry) */
395  i = old_queue;
396  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q)));
397  /* no empty or recyclable entries found */
398  } else {
399  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty or recyclable entries found\n"));
400  return (s8_t)ERR_MEM;
401  }
402 
403  /* { empty or recyclable entry found } */
404  LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE);
405  etharp_free_entry(i);
406  }
407 
408  LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE);
409  LWIP_ASSERT("arp_table[i].state == ETHARP_STATE_EMPTY",
410  arp_table[i].state == ETHARP_STATE_EMPTY);
411 
412  /* IP address given? */
413  if (ipaddr != NULL) {
414  /* set IP address */
415  ip4_addr_copy(arp_table[i].ipaddr, *ipaddr);
416  }
417  arp_table[i].ctime = 0;
418 #if ETHARP_TABLE_MATCH_NETIF
419  arp_table[i].netif = netif;
420 #endif /* ETHARP_TABLE_MATCH_NETIF*/
421  return (err_t)i;
422 }
423 
442 static err_t
443 etharp_update_arp_entry(struct netif *netif, const ip4_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags)
444 {
445  s8_t i;
446  LWIP_ASSERT("netif->hwaddr_len == ETH_HWADDR_LEN", netif->hwaddr_len == ETH_HWADDR_LEN);
447  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n",
448  ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr),
449  (u16_t)ethaddr->addr[0], (u16_t)ethaddr->addr[1], (u16_t)ethaddr->addr[2],
450  (u16_t)ethaddr->addr[3], (u16_t)ethaddr->addr[4], (u16_t)ethaddr->addr[5]));
451  /* non-unicast address? */
452  if (ip4_addr_isany(ipaddr) ||
453  ip4_addr_isbroadcast(ipaddr, netif) ||
454  ip4_addr_ismulticast(ipaddr)) {
455  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: will not add non-unicast IP address to ARP cache\n"));
456  return ERR_ARG;
457  }
458  /* find or create ARP entry */
459  i = etharp_find_entry(ipaddr, flags, netif);
460  /* bail out if no entry could be found */
461  if (i < 0) {
462  return (err_t)i;
463  }
464 
465 #if ETHARP_SUPPORT_STATIC_ENTRIES
466  if (flags & ETHARP_FLAG_STATIC_ENTRY) {
467  /* record static type */
468  arp_table[i].state = ETHARP_STATE_STATIC;
469  } else if (arp_table[i].state == ETHARP_STATE_STATIC) {
470  /* found entry is a static type, don't overwrite it */
471  return ERR_VAL;
472  } else
473 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
474  {
475  /* mark it stable */
476  arp_table[i].state = ETHARP_STATE_STABLE;
477  }
478 
479  /* record network interface */
480  arp_table[i].netif = netif;
481  /* insert in SNMP ARP index tree */
482  mib2_add_arp_entry(netif, &arp_table[i].ipaddr);
483 
484  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i));
485  /* update address */
486  ETHADDR32_COPY(&arp_table[i].ethaddr, ethaddr);
487  /* reset time stamp */
488  arp_table[i].ctime = 0;
489  /* this is where we will send out queued packets! */
490 #if ARP_QUEUEING
491  while (arp_table[i].q != NULL) {
492  struct pbuf *p;
493  /* remember remainder of queue */
494  struct etharp_q_entry *q = arp_table[i].q;
495  /* pop first item off the queue */
496  arp_table[i].q = q->next;
497  /* get the packet pointer */
498  p = q->p;
499  /* now queue entry can be freed */
500  memp_free(MEMP_ARP_QUEUE, q);
501 #else /* ARP_QUEUEING */
502  if (arp_table[i].q != NULL) {
503  struct pbuf *p = arp_table[i].q;
504  arp_table[i].q = NULL;
505 #endif /* ARP_QUEUEING */
506  /* send the queued IP packet */
507  ethernet_output(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr, ETHTYPE_IP);
508  /* free the queued IP packet */
509  pbuf_free(p);
510  }
511  return ERR_OK;
512 }
513 
514 #if ETHARP_SUPPORT_STATIC_ENTRIES
515 
523 err_t
524 etharp_add_static_entry(const ip4_addr_t *ipaddr, struct eth_addr *ethaddr)
525 {
526  struct netif *netif;
527  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_add_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n",
528  ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr),
529  (u16_t)ethaddr->addr[0], (u16_t)ethaddr->addr[1], (u16_t)ethaddr->addr[2],
530  (u16_t)ethaddr->addr[3], (u16_t)ethaddr->addr[4], (u16_t)ethaddr->addr[5]));
531 
532  netif = ip4_route(ipaddr);
533  if (netif == NULL) {
534  return ERR_RTE;
535  }
536 
537  return etharp_update_arp_entry(netif, ipaddr, ethaddr, ETHARP_FLAG_TRY_HARD | ETHARP_FLAG_STATIC_ENTRY);
538 }
539 
548 err_t
549 etharp_remove_static_entry(const ip4_addr_t *ipaddr)
550 {
551  s8_t i;
552  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_remove_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
553  ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr)));
554 
555  /* find or create ARP entry */
556  i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY, NULL);
557  /* bail out if no entry could be found */
558  if (i < 0) {
559  return (err_t)i;
560  }
561 
562  if (arp_table[i].state != ETHARP_STATE_STATIC) {
563  /* entry wasn't a static entry, cannot remove it */
564  return ERR_ARG;
565  }
566  /* entry found, free it */
567  etharp_free_entry(i);
568  return ERR_OK;
569 }
570 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
571 
577 void
578 etharp_cleanup_netif(struct netif *netif)
579 {
580  u8_t i;
581 
582  for (i = 0; i < ARP_TABLE_SIZE; ++i) {
583  u8_t state = arp_table[i].state;
584  if ((state != ETHARP_STATE_EMPTY) && (arp_table[i].netif == netif)) {
585  etharp_free_entry(i);
586  }
587  }
588 }
589 
601 s8_t
602 etharp_find_addr(struct netif *netif, const ip4_addr_t *ipaddr,
603  struct eth_addr **eth_ret, const ip4_addr_t **ip_ret)
604 {
605  s8_t i;
606 
607  LWIP_ASSERT("eth_ret != NULL && ip_ret != NULL",
608  eth_ret != NULL && ip_ret != NULL);
609 
610  LWIP_UNUSED_ARG(netif);
611 
612  i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY, netif);
613  if ((i >= 0) && (arp_table[i].state >= ETHARP_STATE_STABLE)) {
614  *eth_ret = &arp_table[i].ethaddr;
615  *ip_ret = &arp_table[i].ipaddr;
616  return i;
617  }
618  return -1;
619 }
620 
630 u8_t
631 etharp_get_entry(u8_t i, ip4_addr_t **ipaddr, struct netif **netif, struct eth_addr **eth_ret)
632 {
633  LWIP_ASSERT("ipaddr != NULL", ipaddr != NULL);
634  LWIP_ASSERT("netif != NULL", netif != NULL);
635  LWIP_ASSERT("eth_ret != NULL", eth_ret != NULL);
636 
637  if((i < ARP_TABLE_SIZE) && (arp_table[i].state >= ETHARP_STATE_STABLE)) {
638  *ipaddr = &arp_table[i].ipaddr;
639  *netif = arp_table[i].netif;
640  *eth_ret = &arp_table[i].ethaddr;
641  return 1;
642  } else {
643  return 0;
644  }
645 }
646 
659 void
660 etharp_input(struct pbuf *p, struct netif *netif)
661 {
662  struct etharp_hdr *hdr;
663  /* these are aligned properly, whereas the ARP header fields might not be */
664  ip4_addr_t sipaddr, dipaddr;
665  u8_t for_us;
666 
667  LWIP_ERROR("netif != NULL", (netif != NULL), return;);
668 
669  hdr = (struct etharp_hdr *)p->payload;
670 
671  /* RFC 826 "Packet Reception": */
672  if ((hdr->hwtype != PP_HTONS(HWTYPE_ETHERNET)) ||
673  (hdr->hwlen != ETH_HWADDR_LEN) ||
674  (hdr->protolen != sizeof(ip4_addr_t)) ||
675  (hdr->proto != PP_HTONS(ETHTYPE_IP))) {
677  ("etharp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n",
678  hdr->hwtype, (u16_t)hdr->hwlen, hdr->proto, (u16_t)hdr->protolen));
679  ETHARP_STATS_INC(etharp.proterr);
680  ETHARP_STATS_INC(etharp.drop);
681  pbuf_free(p);
682  return;
683  }
684  ETHARP_STATS_INC(etharp.recv);
685 
686 #if LWIP_AUTOIP
687  /* We have to check if a host already has configured our random
688  * created link local address and continuously check if there is
689  * a host with this IP-address so we can detect collisions */
690  autoip_arp_reply(netif, hdr);
691 #endif /* LWIP_AUTOIP */
692 
693  /* Copy struct ip4_addr2 to aligned ip4_addr, to support compilers without
694  * structure packing (not using structure copy which breaks strict-aliasing rules). */
695  IPADDR2_COPY(&sipaddr, &hdr->sipaddr);
696  IPADDR2_COPY(&dipaddr, &hdr->dipaddr);
697 
698  /* this interface is not configured? */
699  if (ip4_addr_isany_val(*netif_ip4_addr(netif))) {
700  for_us = 0;
701  } else {
702  /* ARP packet directed to us? */
703  for_us = (u8_t)ip4_addr_cmp(&dipaddr, netif_ip4_addr(netif));
704  }
705 
706  /* ARP message directed to us?
707  -> add IP address in ARP cache; assume requester wants to talk to us,
708  can result in directly sending the queued packets for this host.
709  ARP message not directed to us?
710  -> update the source IP address in the cache, if present */
711  etharp_update_arp_entry(netif, &sipaddr, &(hdr->shwaddr),
712  for_us ? ETHARP_FLAG_TRY_HARD : ETHARP_FLAG_FIND_ONLY);
713 
714  /* now act on the message itself */
715  switch (hdr->opcode) {
716  /* ARP request? */
717  case PP_HTONS(ARP_REQUEST):
718  /* ARP request. If it asked for our address, we send out a
719  * reply. In any case, we time-stamp any existing ARP entry,
720  * and possibly send out an IP packet that was queued on it. */
721 
722  LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: incoming ARP request\n"));
723  /* ARP request for our address? */
724  if (for_us) {
725  /* send ARP response */
726  etharp_raw(netif,
727  (struct eth_addr *)netif->hwaddr, &hdr->shwaddr,
728  (struct eth_addr *)netif->hwaddr, netif_ip4_addr(netif),
729  &hdr->shwaddr, &sipaddr,
730  ARP_REPLY);
731  /* we are not configured? */
732  } else if (ip4_addr_isany_val(*netif_ip4_addr(netif))) {
733  /* { for_us == 0 and netif->ip_addr.addr == 0 } */
734  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: we are unconfigured, ARP request ignored.\n"));
735  /* request was not directed to us */
736  } else {
737  /* { for_us == 0 and netif->ip_addr.addr != 0 } */
738  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: ARP request was not for us.\n"));
739  }
740  break;
741  case PP_HTONS(ARP_REPLY):
742  /* ARP reply. We already updated the ARP cache earlier. */
743  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: incoming ARP reply\n"));
744 #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
745  /* DHCP wants to know about ARP replies from any host with an
746  * IP address also offered to us by the DHCP server. We do not
747  * want to take a duplicate IP address on a single network.
748  * @todo How should we handle redundant (fail-over) interfaces? */
749  dhcp_arp_reply(netif, &sipaddr);
750 #endif /* (LWIP_DHCP && DHCP_DOES_ARP_CHECK) */
751  break;
752  default:
753  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: ARP unknown opcode type %"S16_F"\n", lwip_htons(hdr->opcode)));
754  ETHARP_STATS_INC(etharp.err);
755  break;
756  }
757  /* free ARP packet */
758  pbuf_free(p);
759 }
760 
764 static err_t
765 etharp_output_to_arp_index(struct netif *netif, struct pbuf *q, u8_t arp_idx)
766 {
767  LWIP_ASSERT("arp_table[arp_idx].state >= ETHARP_STATE_STABLE",
768  arp_table[arp_idx].state >= ETHARP_STATE_STABLE);
769  /* if arp table entry is about to expire: re-request it,
770  but only if its state is ETHARP_STATE_STABLE to prevent flooding the
771  network with ARP requests if this address is used frequently. */
772  if (arp_table[arp_idx].state == ETHARP_STATE_STABLE) {
773  if (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED_BROADCAST) {
774  /* issue a standard request using broadcast */
775  if (etharp_request(netif, &arp_table[arp_idx].ipaddr) == ERR_OK) {
776  arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING_1;
777  }
778  } else if (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED_UNICAST) {
779  /* issue a unicast request (for 15 seconds) to prevent unnecessary broadcast */
780  if (etharp_request_dst(netif, &arp_table[arp_idx].ipaddr, &arp_table[arp_idx].ethaddr) == ERR_OK) {
781  arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING_1;
782  }
783  }
784  }
785 
786  return ethernet_output(netif, q, (struct eth_addr*)(netif->hwaddr), &arp_table[arp_idx].ethaddr, ETHTYPE_IP);
787 }
788 
807 err_t
808 etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr)
809 {
810  const struct eth_addr *dest;
811  struct eth_addr mcastaddr;
812  const ip4_addr_t *dst_addr = ipaddr;
813 
814  LWIP_ASSERT("netif != NULL", netif != NULL);
815  LWIP_ASSERT("q != NULL", q != NULL);
816  LWIP_ASSERT("ipaddr != NULL", ipaddr != NULL);
817 
818  /* Determine on destination hardware address. Broadcasts and multicasts
819  * are special, other IP addresses are looked up in the ARP table. */
820 
821  /* broadcast destination IP address? */
822  if (ip4_addr_isbroadcast(ipaddr, netif)) {
823  /* broadcast on Ethernet also */
824  dest = (const struct eth_addr *)&ethbroadcast;
825  /* multicast destination IP address? */
826  } else if (ip4_addr_ismulticast(ipaddr)) {
827  /* Hash IP multicast address to MAC address.*/
828  mcastaddr.addr[0] = LL_IP4_MULTICAST_ADDR_0;
829  mcastaddr.addr[1] = LL_IP4_MULTICAST_ADDR_1;
830  mcastaddr.addr[2] = LL_IP4_MULTICAST_ADDR_2;
831  mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
832  mcastaddr.addr[4] = ip4_addr3(ipaddr);
833  mcastaddr.addr[5] = ip4_addr4(ipaddr);
834  /* destination Ethernet address is multicast */
835  dest = &mcastaddr;
836  /* unicast destination IP address? */
837  } else {
838  s8_t i;
839  /* outside local network? if so, this can neither be a global broadcast nor
840  a subnet broadcast. */
841  if (!ip4_addr_netcmp(ipaddr, netif_ip4_addr(netif), netif_ip4_netmask(netif)) &&
842  !ip4_addr_islinklocal(ipaddr)) {
843 #if LWIP_AUTOIP
844  struct ip_hdr *iphdr = LWIP_ALIGNMENT_CAST(struct ip_hdr*, q->payload);
845  /* According to RFC 3297, chapter 2.6.2 (Forwarding Rules), a packet with
846  a link-local source address must always be "directly to its destination
847  on the same physical link. The host MUST NOT send the packet to any
848  router for forwarding". */
849  if (!ip4_addr_islinklocal(&iphdr->src))
850 #endif /* LWIP_AUTOIP */
851  {
852 #ifdef LWIP_HOOK_ETHARP_GET_GW
853  /* For advanced routing, a single default gateway might not be enough, so get
854  the IP address of the gateway to handle the current destination address. */
855  dst_addr = LWIP_HOOK_ETHARP_GET_GW(netif, ipaddr);
856  if (dst_addr == NULL)
857 #endif /* LWIP_HOOK_ETHARP_GET_GW */
858  {
859  /* interface has default gateway? */
860  if (!ip4_addr_isany_val(*netif_ip4_gw(netif))) {
861  /* send to hardware address of default gateway IP address */
862  dst_addr = netif_ip4_gw(netif);
863  /* no default gateway available */
864  } else {
865  /* no route to destination error (default gateway missing) */
866  return ERR_RTE;
867  }
868  }
869  }
870  }
871 #if LWIP_NETIF_HWADDRHINT
872  if (netif->addr_hint != NULL) {
873  /* per-pcb cached entry was given */
874  u8_t etharp_cached_entry = *(netif->addr_hint);
875  if (etharp_cached_entry < ARP_TABLE_SIZE) {
876 #endif /* LWIP_NETIF_HWADDRHINT */
877  if ((arp_table[etharp_cached_entry].state >= ETHARP_STATE_STABLE) &&
878 #if ETHARP_TABLE_MATCH_NETIF
879  (arp_table[etharp_cached_entry].netif == netif) &&
880 #endif
881  (ip4_addr_cmp(dst_addr, &arp_table[etharp_cached_entry].ipaddr))) {
882  /* the per-pcb-cached entry is stable and the right one! */
883  ETHARP_STATS_INC(etharp.cachehit);
884  return etharp_output_to_arp_index(netif, q, etharp_cached_entry);
885  }
886 #if LWIP_NETIF_HWADDRHINT
887  }
888  }
889 #endif /* LWIP_NETIF_HWADDRHINT */
890 
891  /* find stable entry: do this here since this is a critical path for
892  throughput and etharp_find_entry() is kind of slow */
893  for (i = 0; i < ARP_TABLE_SIZE; i++) {
894  if ((arp_table[i].state >= ETHARP_STATE_STABLE) &&
896  (arp_table[i].netif == netif) &&
897 #endif
898  (ip4_addr_cmp(dst_addr, &arp_table[i].ipaddr))) {
899  /* found an existing, stable entry */
900  ETHARP_SET_HINT(netif, i);
901  return etharp_output_to_arp_index(netif, q, i);
902  }
903  }
904  /* no stable entry found, use the (slower) query function:
905  queue on destination Ethernet address belonging to ipaddr */
906  return etharp_query(netif, dst_addr, q);
907  }
908 
909  /* continuation for multicast/broadcast destinations */
910  /* obtain source Ethernet address of the given interface */
911  /* send packet directly on the link */
912  return ethernet_output(netif, q, (struct eth_addr*)(netif->hwaddr), dest, ETHTYPE_IP);
913 }
914 
948 err_t
949 etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q)
950 {
951  struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr;
952  err_t result = ERR_MEM;
953  int is_new_entry = 0;
954  s8_t i; /* ARP entry index */
955 
956  /* non-unicast address? */
957  if (ip4_addr_isbroadcast(ipaddr, netif) ||
958  ip4_addr_ismulticast(ipaddr) ||
959  ip4_addr_isany(ipaddr)) {
960  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n"));
961  return ERR_ARG;
962  }
963 
964  /* find entry in ARP cache, ask to create entry if queueing packet */
965  i = etharp_find_entry(ipaddr, ETHARP_FLAG_TRY_HARD, netif);
966 
967  /* could not find or create entry? */
968  if (i < 0) {
969  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not create ARP entry\n"));
970  if (q) {
971  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: packet dropped\n"));
972  ETHARP_STATS_INC(etharp.memerr);
973  }
974  return (err_t)i;
975  }
976 
977  /* mark a fresh entry as pending (we just sent a request) */
978  if (arp_table[i].state == ETHARP_STATE_EMPTY) {
979  is_new_entry = 1;
980  arp_table[i].state = ETHARP_STATE_PENDING;
981  /* record network interface for re-sending arp request in etharp_tmr */
982  arp_table[i].netif = netif;
983  }
984 
985  /* { i is either a STABLE or (new or existing) PENDING entry } */
986  LWIP_ASSERT("arp_table[i].state == PENDING or STABLE",
987  ((arp_table[i].state == ETHARP_STATE_PENDING) ||
988  (arp_table[i].state >= ETHARP_STATE_STABLE)));
989 
990  /* do we have a new entry? or an implicit query request? */
991  if (is_new_entry || (q == NULL)) {
992  /* try to resolve it; send out ARP request */
993  result = etharp_request(netif, ipaddr);
994  if (result != ERR_OK) {
995  /* ARP request couldn't be sent */
996  /* We don't re-send arp request in etharp_tmr, but we still queue packets,
997  since this failure could be temporary, and the next packet calling
998  etharp_query again could lead to sending the queued packets. */
999  }
1000  if (q == NULL) {
1001  return result;
1002  }
1003  }
1004 
1005  /* packet given? */
1006  LWIP_ASSERT("q != NULL", q != NULL);
1007  /* stable entry? */
1008  if (arp_table[i].state >= ETHARP_STATE_STABLE) {
1009  /* we have a valid IP->Ethernet address mapping */
1010  ETHARP_SET_HINT(netif, i);
1011  /* send the packet */
1012  result = ethernet_output(netif, q, srcaddr, &(arp_table[i].ethaddr), ETHTYPE_IP);
1013  /* pending entry? (either just created or already pending */
1014  } else if (arp_table[i].state == ETHARP_STATE_PENDING) {
1015  /* entry is still pending, queue the given packet 'q' */
1016  struct pbuf *p;
1017  int copy_needed = 0;
1018  /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but
1019  * to copy the whole queue into a new PBUF_RAM (see bug #11400)
1020  * PBUF_ROMs can be left as they are, since ROM must not get changed. */
1021  p = q;
1022  while (p) {
1023  LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == 0));
1024  if (p->type != PBUF_ROM) {
1025  copy_needed = 1;
1026  break;
1027  }
1028  p = p->next;
1029  }
1030  if (copy_needed) {
1031  /* copy the whole packet into new pbufs */
1033  if (p != NULL) {
1034  if (pbuf_copy(p, q) != ERR_OK) {
1035  pbuf_free(p);
1036  p = NULL;
1037  }
1038  }
1039  } else {
1040  /* referencing the old pbuf is enough */
1041  p = q;
1042  pbuf_ref(p);
1043  }
1044  /* packet could be taken over? */
1045  if (p != NULL) {
1046  /* queue packet ... */
1047 #if ARP_QUEUEING
1048  struct etharp_q_entry *new_entry;
1049  /* allocate a new arp queue entry */
1050  new_entry = (struct etharp_q_entry *)memp_malloc(MEMP_ARP_QUEUE);
1051  if (new_entry != NULL) {
1052  unsigned int qlen = 0;
1053  new_entry->next = 0;
1054  new_entry->p = p;
1055  if (arp_table[i].q != NULL) {
1056  /* queue was already existent, append the new entry to the end */
1057  struct etharp_q_entry *r;
1058  r = arp_table[i].q;
1059  qlen++;
1060  while (r->next != NULL) {
1061  r = r->next;
1062  qlen++;
1063  }
1064  r->next = new_entry;
1065  } else {
1066  /* queue did not exist, first item in queue */
1067  arp_table[i].q = new_entry;
1068  }
1069 #if ARP_QUEUE_LEN
1070  if (qlen >= ARP_QUEUE_LEN) {
1071  struct etharp_q_entry *old;
1072  old = arp_table[i].q;
1073  arp_table[i].q = arp_table[i].q->next;
1074  pbuf_free(old->p);
1075  memp_free(MEMP_ARP_QUEUE, old);
1076  }
1077 #endif
1078  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
1079  result = ERR_OK;
1080  } else {
1081  /* the pool MEMP_ARP_QUEUE is empty */
1082  pbuf_free(p);
1083  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));
1084  result = ERR_MEM;
1085  }
1086 #else /* ARP_QUEUEING */
1087  /* always queue one packet per ARP request only, freeing a previously queued packet */
1088  if (arp_table[i].q != NULL) {
1089  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: dropped previously queued packet %p for ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
1090  pbuf_free(arp_table[i].q);
1091  }
1092  arp_table[i].q = p;
1093  result = ERR_OK;
1094  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
1095 #endif /* ARP_QUEUEING */
1096  } else {
1097  ETHARP_STATS_INC(etharp.memerr);
1098  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));
1099  result = ERR_MEM;
1100  }
1101  }
1102  return result;
1103 }
1104 
1120 static err_t
1121 etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
1122  const struct eth_addr *ethdst_addr,
1123  const struct eth_addr *hwsrc_addr, const ip4_addr_t *ipsrc_addr,
1124  const struct eth_addr *hwdst_addr, const ip4_addr_t *ipdst_addr,
1125  const u16_t opcode)
1126 {
1127  struct pbuf *p;
1128  err_t result = ERR_OK;
1129  struct etharp_hdr *hdr;
1130 
1131  LWIP_ASSERT("netif != NULL", netif != NULL);
1132 
1133  /* allocate a pbuf for the outgoing ARP request packet */
1134  p = pbuf_alloc(PBUF_LINK, SIZEOF_ETHARP_HDR, PBUF_RAM);
1135  /* could allocate a pbuf for an ARP request? */
1136  if (p == NULL) {
1138  ("etharp_raw: could not allocate pbuf for ARP request.\n"));
1139  ETHARP_STATS_INC(etharp.memerr);
1140  return ERR_MEM;
1141  }
1142  LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr",
1143  (p->len >= SIZEOF_ETHARP_HDR));
1144 
1145  hdr = (struct etharp_hdr *)p->payload;
1146  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n"));
1147  hdr->opcode = lwip_htons(opcode);
1148 
1149  LWIP_ASSERT("netif->hwaddr_len must be the same as ETH_HWADDR_LEN for etharp!",
1150  (netif->hwaddr_len == ETH_HWADDR_LEN));
1151 
1152  /* Write the ARP MAC-Addresses */
1153  ETHADDR16_COPY(&hdr->shwaddr, hwsrc_addr);
1154  ETHADDR16_COPY(&hdr->dhwaddr, hwdst_addr);
1155  /* Copy struct ip4_addr2 to aligned ip4_addr, to support compilers without
1156  * structure packing. */
1157  IPADDR2_COPY(&hdr->sipaddr, ipsrc_addr);
1158  IPADDR2_COPY(&hdr->dipaddr, ipdst_addr);
1159 
1160  hdr->hwtype = PP_HTONS(HWTYPE_ETHERNET);
1161  hdr->proto = PP_HTONS(ETHTYPE_IP);
1162  /* set hwlen and protolen */
1163  hdr->hwlen = ETH_HWADDR_LEN;
1164  hdr->protolen = sizeof(ip4_addr_t);
1165 
1166  /* send ARP query */
1167 #if LWIP_AUTOIP
1168  /* If we are using Link-Local, all ARP packets that contain a Link-Local
1169  * 'sender IP address' MUST be sent using link-layer broadcast instead of
1170  * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */
1171  if(ip4_addr_islinklocal(ipsrc_addr)) {
1172  ethernet_output(netif, p, ethsrc_addr, &ethbroadcast, ETHTYPE_ARP);
1173  } else
1174 #endif /* LWIP_AUTOIP */
1175  {
1176  ethernet_output(netif, p, ethsrc_addr, ethdst_addr, ETHTYPE_ARP);
1177  }
1178 
1179  ETHARP_STATS_INC(etharp.xmit);
1180  /* free ARP query packet */
1181  pbuf_free(p);
1182  p = NULL;
1183  /* could not allocate pbuf for ARP request */
1184 
1185  return result;
1186 }
1187 
1200 static err_t
1201 etharp_request_dst(struct netif *netif, const ip4_addr_t *ipaddr, const struct eth_addr* hw_dst_addr)
1202 {
1203  return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, hw_dst_addr,
1204  (struct eth_addr *)netif->hwaddr, netif_ip4_addr(netif), &ethzero,
1205  ipaddr, ARP_REQUEST);
1206 }
1207 
1217 err_t
1218 etharp_request(struct netif *netif, const ip4_addr_t *ipaddr)
1219 {
1220  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_request: sending ARP request.\n"));
1221  return etharp_request_dst(netif, ipaddr, &ethbroadcast);
1222 }
1223 #endif /* LWIP_IPV4 && LWIP_ARP */
1224 
1225 #endif /* LWIP_ARP || LWIP_ETHERNET */
u8_t hwaddr[NETIF_MAX_HWADDR_LEN]
Definition: netif.h:322
u16_t tot_len
Definition: pbuf.h:175
#define ARP_MAXAGE
Definition: opt.h:576
struct pbuf * next
Definition: pbuf.h:163
u16_t len
Definition: pbuf.h:178
Definition: pbuf.h:131
#define ETHARP_SUPPORT_STATIC_ENTRIES
Definition: opt.h:631
void pbuf_ref(struct pbuf *p)
Definition: pbuf.c:839
#define LWIP_ALIGNMENT_CAST(target_type, val)
Definition: arch.h:204
void memp_free(memp_t type, void *mem)
Definition: memp.c:488
err_t pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from)
Definition: pbuf.c:967
u8_t hwaddr_len
Definition: netif.h:320
Definition: err.h:84
#define ETHADDR32_COPY(dst, src)
Definition: err.h:115
Definition: pbuf.h:161
Definition: netif.h:244
#define ETHARP_DEBUG
Definition: opt.h:2650
#define ARP_QUEUE_LEN
Definition: opt.h:595
s8_t err_t
Definition: err.h:76
#define LWIP_DEBUGF(debug, message)
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
Definition: pbuf.c:267
Definition: pbuf.h:127
#define LL_IP4_MULTICAST_ADDR_0
Definition: err.h:94
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:327
#define ETHARP_TABLE_MATCH_NETIF
Definition: opt.h:639
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:734
Definition: err.h:82
void * payload
Definition: pbuf.h:166
Definition: err.h:90
u8_t type
Definition: pbuf.h:181
void * memp_malloc(memp_t type)
Definition: memp.c:404
#define ARP_TABLE_SIZE
Definition: opt.h:568
#define ETHADDR16_COPY(dst, src)