ReactOS 0.4.16-dev-338-g34e76ad
etharp.c
Go to the documentation of this file.
1
14/*
15 * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
16 * Copyright (c) 2003-2004 Leon Woestenberg <leon.woestenberg@axon.tv>
17 * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands.
18 * All rights reserved.
19 *
20 * Redistribution and use in source and binary forms, with or without modification,
21 * are permitted provided that the following conditions are met:
22 *
23 * 1. Redistributions of source code must retain the above copyright notice,
24 * this list of conditions and the following disclaimer.
25 * 2. Redistributions in binary form must reproduce the above copyright notice,
26 * this list of conditions and the following disclaimer in the documentation
27 * and/or other materials provided with the distribution.
28 * 3. The name of the author may not be used to endorse or promote products
29 * derived from this software without specific prior written permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
32 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
33 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
34 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
35 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
36 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
37 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
38 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
39 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
40 * OF SUCH DAMAGE.
41 *
42 * This file is part of the lwIP TCP/IP stack.
43 *
44 */
45
46#include "lwip/opt.h"
47
48#if LWIP_IPV4 && LWIP_ARP /* don't build if not configured for use in lwipopts.h */
49
50#include "lwip/etharp.h"
51#include "lwip/stats.h"
52#include "lwip/snmp.h"
53#include "lwip/dhcp.h"
54#include "lwip/autoip.h"
55#include "lwip/acd.h"
56#include "lwip/prot/iana.h"
57#include "netif/ethernet.h"
58
59#include <string.h>
60
61#ifdef LWIP_HOOK_FILENAME
62#include LWIP_HOOK_FILENAME
63#endif
64
67#define ARP_AGE_REREQUEST_USED_UNICAST (ARP_MAXAGE - 30)
68#define ARP_AGE_REREQUEST_USED_BROADCAST (ARP_MAXAGE - 15)
69
77#define ARP_MAXPENDING 5
78
80enum etharp_state {
81 ETHARP_STATE_EMPTY = 0,
82 ETHARP_STATE_PENDING,
83 ETHARP_STATE_STABLE,
84 ETHARP_STATE_STABLE_REREQUESTING_1,
85 ETHARP_STATE_STABLE_REREQUESTING_2
86#if ETHARP_SUPPORT_STATIC_ENTRIES
87 , ETHARP_STATE_STATIC
88#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
89};
90
91struct etharp_entry {
92#if ARP_QUEUEING
94 struct etharp_q_entry *q;
95#else /* ARP_QUEUEING */
97 struct pbuf *q;
98#endif /* ARP_QUEUEING */
99 ip4_addr_t ipaddr;
100 struct netif *netif;
101 struct eth_addr ethaddr;
102 u16_t ctime;
103 u8_t state;
104};
105
106static struct etharp_entry arp_table[ARP_TABLE_SIZE];
107
108#if !LWIP_NETIF_HWADDRHINT
109static netif_addr_idx_t etharp_cached_entry;
110#endif /* !LWIP_NETIF_HWADDRHINT */
111
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
118#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
119
120#if LWIP_NETIF_HWADDRHINT
121#define ETHARP_SET_ADDRHINT(netif, addrhint) do { if (((netif) != NULL) && ((netif)->hints != NULL)) { \
122 (netif)->hints->addr_hint = (addrhint); }} while(0)
123#else /* LWIP_NETIF_HWADDRHINT */
124#define ETHARP_SET_ADDRHINT(netif, addrhint) (etharp_cached_entry = (addrhint))
125#endif /* LWIP_NETIF_HWADDRHINT */
126
127
128/* Check for maximum ARP_TABLE_SIZE */
129#if (ARP_TABLE_SIZE > NETIF_ADDR_IDX_MAX)
130#error "ARP_TABLE_SIZE must fit in an s16_t, you have to reduce it in your lwipopts.h"
131#endif
132
133
134static err_t etharp_request_dst(struct netif *netif, const ip4_addr_t *ipaddr, const struct eth_addr *hw_dst_addr);
135static err_t etharp_raw(struct netif *netif,
136 const struct eth_addr *ethsrc_addr, const struct eth_addr *ethdst_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,
139 const u16_t opcode);
140
141#if ARP_QUEUEING
147static void
148free_etharp_q(struct etharp_q_entry *q)
149{
150 struct etharp_q_entry *r;
151 LWIP_ASSERT("q != NULL", q != NULL);
152 while (q) {
153 r = q;
154 q = q->next;
155 LWIP_ASSERT("r->p != NULL", (r->p != NULL));
156 pbuf_free(r->p);
157 memp_free(MEMP_ARP_QUEUE, r);
158 }
159}
160#else /* ARP_QUEUEING */
161
163#define free_etharp_q(q) pbuf_free(q)
164
165#endif /* ARP_QUEUEING */
166
168static void
169etharp_free_entry(int i)
170{
171 /* remove from SNMP ARP index tree */
172 mib2_remove_arp_entry(arp_table[i].netif, &arp_table[i].ipaddr);
173 /* and empty packet queue */
174 if (arp_table[i].q != NULL) {
175 /* remove all queued packets */
176 LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_free_entry: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].q)));
177 free_etharp_q(arp_table[i].q);
178 arp_table[i].q = NULL;
179 }
180 /* recycle entry for re-use */
181 arp_table[i].state = ETHARP_STATE_EMPTY;
182#ifdef LWIP_DEBUG
183 /* for debugging, clean out the complete entry */
184 arp_table[i].ctime = 0;
185 arp_table[i].netif = NULL;
186 ip4_addr_set_zero(&arp_table[i].ipaddr);
187 arp_table[i].ethaddr = ethzero;
188#endif /* LWIP_DEBUG */
189}
190
197void
198etharp_tmr(void)
199{
200 int i;
201
202 LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n"));
203 /* remove expired entries from the ARP table */
204 for (i = 0; i < ARP_TABLE_SIZE; ++i) {
205 u8_t state = arp_table[i].state;
206 if (state != ETHARP_STATE_EMPTY
208 && (state != ETHARP_STATE_STATIC)
209#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
210 ) {
211 arp_table[i].ctime++;
212 if ((arp_table[i].ctime >= ARP_MAXAGE) ||
213 ((arp_table[i].state == ETHARP_STATE_PENDING) &&
214 (arp_table[i].ctime >= ARP_MAXPENDING))) {
215 /* pending or stable entry has become old! */
216 LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %d.\n",
217 arp_table[i].state >= ETHARP_STATE_STABLE ? "stable" : "pending", i));
218 /* clean up entries that have just been expired */
219 etharp_free_entry(i);
220 } else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING_1) {
221 /* Don't send more than one request every 2 seconds. */
222 arp_table[i].state = ETHARP_STATE_STABLE_REREQUESTING_2;
223 } else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING_2) {
224 /* Reset state to stable, so that the next transmitted packet will
225 re-send an ARP request. */
226 arp_table[i].state = ETHARP_STATE_STABLE;
227 } else if (arp_table[i].state == ETHARP_STATE_PENDING) {
228 /* still pending, resend an ARP query */
229 etharp_request(arp_table[i].netif, &arp_table[i].ipaddr);
230 }
231 }
232 }
233}
234
256static s16_t
257etharp_find_entry(const ip4_addr_t *ipaddr, u8_t flags, struct netif *netif)
258{
259 s16_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE;
261 s16_t i = 0;
262 /* oldest entry with packets on queue */
263 s16_t old_queue = ARP_TABLE_SIZE;
264 /* its age */
265 u16_t age_queue = 0, age_pending = 0, age_stable = 0;
266
268
275 /* a) in a single search sweep, do all of this
276 * 1) remember the first empty entry (if any)
277 * 2) remember the oldest stable entry (if any)
278 * 3) remember the oldest pending entry without queued packets (if any)
279 * 4) remember the oldest pending entry with queued packets (if any)
280 * 5) search for a matching IP entry, either pending or stable
281 * until 5 matches, or all entries are searched for.
282 */
283
284 for (i = 0; i < ARP_TABLE_SIZE; ++i) {
285 u8_t state = arp_table[i].state;
286 /* no empty entry found yet and now we do find one? */
287 if ((empty == ARP_TABLE_SIZE) && (state == ETHARP_STATE_EMPTY)) {
288 LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_find_entry: found empty entry %d\n", (int)i));
289 /* remember first empty entry */
290 empty = i;
291 } else if (state != ETHARP_STATE_EMPTY) {
292 LWIP_ASSERT("state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE",
293 state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE);
294 /* if given, does IP address match IP address in ARP entry? */
295 if (ipaddr && ip4_addr_eq(ipaddr, &arp_table[i].ipaddr)
297 && ((netif == NULL) || (netif == arp_table[i].netif))
298#endif /* ETHARP_TABLE_MATCH_NETIF */
299 ) {
300 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: found matching entry %d\n", (int)i));
301 /* found exact IP address match, simply bail out */
302 return i;
303 }
304 /* pending entry? */
305 if (state == ETHARP_STATE_PENDING) {
306 /* pending with queued packets? */
307 if (arp_table[i].q != NULL) {
308 if (arp_table[i].ctime >= age_queue) {
309 old_queue = i;
310 age_queue = arp_table[i].ctime;
311 }
312 } else
313 /* pending without queued packets? */
314 {
315 if (arp_table[i].ctime >= age_pending) {
316 old_pending = i;
317 age_pending = arp_table[i].ctime;
318 }
319 }
320 /* stable entry? */
321 } else if (state >= ETHARP_STATE_STABLE) {
322#if ETHARP_SUPPORT_STATIC_ENTRIES
323 /* don't record old_stable for static entries since they never expire */
324 if (state < ETHARP_STATE_STATIC)
325#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
326 {
327 /* remember entry with oldest stable entry in oldest, its age in maxtime */
328 if (arp_table[i].ctime >= age_stable) {
329 old_stable = i;
330 age_stable = arp_table[i].ctime;
331 }
332 }
333 }
334 }
335 }
336 /* { we have no match } => try to create a new entry */
337
338 /* don't create new entry, only search? */
339 if (((flags & ETHARP_FLAG_FIND_ONLY) != 0) ||
340 /* or no empty entry found and not allowed to recycle? */
341 ((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_FLAG_TRY_HARD) == 0))) {
342 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty entry found and not allowed to recycle\n"));
343 return (s16_t)ERR_MEM;
344 }
345
346 /* b) choose the least destructive entry to recycle:
347 * 1) empty entry
348 * 2) oldest stable entry
349 * 3) oldest pending entry without queued packets
350 * 4) oldest pending entry with queued packets
351 *
352 * { ETHARP_FLAG_TRY_HARD is set at this point }
353 */
354
355 /* 1) empty entry available? */
356 if (empty < ARP_TABLE_SIZE) {
357 i = empty;
358 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting empty entry %d\n", (int)i));
359 } else {
360 /* 2) found recyclable stable entry? */
361 if (old_stable < ARP_TABLE_SIZE) {
362 /* recycle oldest stable*/
363 i = old_stable;
364 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest stable entry %d\n", (int)i));
365 /* no queued packets should exist on stable entries */
366 LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL);
367 /* 3) found recyclable pending entry without queued packets? */
368 } else if (old_pending < ARP_TABLE_SIZE) {
369 /* recycle oldest pending */
370 i = old_pending;
371 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %d (without queue)\n", (int)i));
372 /* 4) found recyclable pending entry with queued packets? */
373 } else if (old_queue < ARP_TABLE_SIZE) {
374 /* recycle oldest pending (queued packets are free in etharp_free_entry) */
375 i = old_queue;
376 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %d, freeing packet queue %p\n", (int)i, (void *)(arp_table[i].q)));
377 /* no empty or recyclable entries found */
378 } else {
379 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty or recyclable entries found\n"));
380 return (s16_t)ERR_MEM;
381 }
382
383 /* { empty or recyclable entry found } */
384 LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE);
385 etharp_free_entry(i);
386 }
387
388 LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE);
389 LWIP_ASSERT("arp_table[i].state == ETHARP_STATE_EMPTY",
390 arp_table[i].state == ETHARP_STATE_EMPTY);
391
392 /* IP address given? */
393 if (ipaddr != NULL) {
394 /* set IP address */
395 ip4_addr_copy(arp_table[i].ipaddr, *ipaddr);
396 }
397 arp_table[i].ctime = 0;
398#if ETHARP_TABLE_MATCH_NETIF
399 arp_table[i].netif = netif;
400#endif /* ETHARP_TABLE_MATCH_NETIF */
401 return (s16_t)i;
402}
403
422static err_t
423etharp_update_arp_entry(struct netif *netif, const ip4_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags)
424{
425 s16_t i;
426 LWIP_ASSERT("netif->hwaddr_len == ETH_HWADDR_LEN", netif->hwaddr_len == ETH_HWADDR_LEN);
427 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",
428 ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr),
429 (u16_t)ethaddr->addr[0], (u16_t)ethaddr->addr[1], (u16_t)ethaddr->addr[2],
430 (u16_t)ethaddr->addr[3], (u16_t)ethaddr->addr[4], (u16_t)ethaddr->addr[5]));
431 /* non-unicast address? */
432 if (ip4_addr_isany(ipaddr) ||
433 ip4_addr_isbroadcast(ipaddr, netif) ||
434 ip4_addr_ismulticast(ipaddr)) {
435 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: will not add non-unicast IP address to ARP cache\n"));
436 return ERR_ARG;
437 }
438 /* find or create ARP entry */
439 i = etharp_find_entry(ipaddr, flags, netif);
440 /* bail out if no entry could be found */
441 if (i < 0) {
442 return (err_t)i;
443 }
444
445#if ETHARP_SUPPORT_STATIC_ENTRIES
446 if (flags & ETHARP_FLAG_STATIC_ENTRY) {
447 /* record static type */
448 arp_table[i].state = ETHARP_STATE_STATIC;
449 } else if (arp_table[i].state == ETHARP_STATE_STATIC) {
450 /* found entry is a static type, don't overwrite it */
451 return ERR_VAL;
452 } else
453#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
454 {
455 /* mark it stable */
456 arp_table[i].state = ETHARP_STATE_STABLE;
457 }
458
459 /* record network interface */
460 arp_table[i].netif = netif;
461 /* insert in SNMP ARP index tree */
462 mib2_add_arp_entry(netif, &arp_table[i].ipaddr);
463
464 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: updating stable entry %"S16_F"\n", i));
465 /* update address */
466 SMEMCPY(&arp_table[i].ethaddr, ethaddr, ETH_HWADDR_LEN);
467 /* reset time stamp */
468 arp_table[i].ctime = 0;
469 /* this is where we will send out queued packets! */
470#if ARP_QUEUEING
471 while (arp_table[i].q != NULL) {
472 struct pbuf *p;
473 /* remember remainder of queue */
474 struct etharp_q_entry *q = arp_table[i].q;
475 /* pop first item off the queue */
476 arp_table[i].q = q->next;
477 /* get the packet pointer */
478 p = q->p;
479 /* now queue entry can be freed */
480 memp_free(MEMP_ARP_QUEUE, q);
481#else /* ARP_QUEUEING */
482 if (arp_table[i].q != NULL) {
483 struct pbuf *p = arp_table[i].q;
484 arp_table[i].q = NULL;
485#endif /* ARP_QUEUEING */
486 /* send the queued IP packet */
487 ethernet_output(netif, p, (struct eth_addr *)(netif->hwaddr), ethaddr, ETHTYPE_IP);
488 /* free the queued IP packet */
489 pbuf_free(p);
490 }
491 return ERR_OK;
492}
493
494#if ETHARP_SUPPORT_STATIC_ENTRIES
503err_t
504etharp_add_static_entry(const ip4_addr_t *ipaddr, struct eth_addr *ethaddr)
505{
506 struct netif *netif;
508 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",
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]));
512
513 netif = ip4_route(ipaddr);
514 if (netif == NULL) {
515 return ERR_RTE;
516 }
517
518 return etharp_update_arp_entry(netif, ipaddr, ethaddr, ETHARP_FLAG_TRY_HARD | ETHARP_FLAG_STATIC_ENTRY);
519}
520
529err_t
530etharp_remove_static_entry(const ip4_addr_t *ipaddr)
531{
532 s16_t i;
534 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_remove_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
535 ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr)));
536
537 /* find or create ARP entry */
538 i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY, NULL);
539 /* bail out if no entry could be found */
540 if (i < 0) {
541 return (err_t)i;
542 }
543
544 if (arp_table[i].state != ETHARP_STATE_STATIC) {
545 /* entry wasn't a static entry, cannot remove it */
546 return ERR_ARG;
547 }
548 /* entry found, free it */
549 etharp_free_entry(i);
550 return ERR_OK;
551}
552#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
553
559void
560etharp_cleanup_netif(struct netif *netif)
561{
562 int i;
563
564 for (i = 0; i < ARP_TABLE_SIZE; ++i) {
565 u8_t state = arp_table[i].state;
566 if ((state != ETHARP_STATE_EMPTY) && (arp_table[i].netif == netif)) {
567 etharp_free_entry(i);
568 }
569 }
570}
571
584etharp_find_addr(struct netif *netif, const ip4_addr_t *ipaddr,
585 struct eth_addr **eth_ret, const ip4_addr_t **ip_ret)
586{
587 s16_t i;
588
589 LWIP_ASSERT("eth_ret != NULL && ip_ret != NULL",
590 eth_ret != NULL && ip_ret != NULL);
591
593
594 i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY, netif);
595 if ((i >= 0) && (arp_table[i].state >= ETHARP_STATE_STABLE)) {
596 *eth_ret = &arp_table[i].ethaddr;
597 *ip_ret = &arp_table[i].ipaddr;
598 return i;
599 }
600 return -1;
601}
602
612int
613etharp_get_entry(size_t i, ip4_addr_t **ipaddr, struct netif **netif, struct eth_addr **eth_ret)
614{
615 LWIP_ASSERT("ipaddr != NULL", ipaddr != NULL);
616 LWIP_ASSERT("netif != NULL", netif != NULL);
617 LWIP_ASSERT("eth_ret != NULL", eth_ret != NULL);
618
619 if ((i < ARP_TABLE_SIZE) && (arp_table[i].state >= ETHARP_STATE_STABLE)) {
620 *ipaddr = &arp_table[i].ipaddr;
621 *netif = arp_table[i].netif;
622 *eth_ret = &arp_table[i].ethaddr;
623 return 1;
624 } else {
625 return 0;
626 }
627}
628
641void
642etharp_input(struct pbuf *p, struct netif *netif)
643{
644 struct etharp_hdr *hdr;
645 /* these are aligned properly, whereas the ARP header fields might not be */
646 ip4_addr_t sipaddr, dipaddr;
647 u8_t for_us, from_us;
648
650
651 LWIP_ERROR("netif != NULL", (netif != NULL), return;);
652
653 hdr = (struct etharp_hdr *)p->payload;
654
655 /* RFC 826 "Packet Reception": */
656 if ((hdr->hwtype != PP_HTONS(LWIP_IANA_HWTYPE_ETHERNET)) ||
657 (hdr->hwlen != ETH_HWADDR_LEN) ||
658 (hdr->protolen != sizeof(ip4_addr_t)) ||
659 (hdr->proto != PP_HTONS(ETHTYPE_IP))) {
661 ("etharp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n",
662 hdr->hwtype, (u16_t)hdr->hwlen, hdr->proto, (u16_t)hdr->protolen));
663 ETHARP_STATS_INC(etharp.proterr);
664 ETHARP_STATS_INC(etharp.drop);
665 pbuf_free(p);
666 return;
667 }
668 ETHARP_STATS_INC(etharp.recv);
669
670#if LWIP_ACD
671 /* We have to check if a host already has configured our ip address and
672 * continuously check if there is a host with this IP-address so we can
673 * detect collisions.
674 * acd_arp_reply ensures the detection of conflicts. It will handle possible
675 * defending or retreating and will make sure a new IP address is selected.
676 * etharp_input does not need to handle packets that originate "from_us".
677 */
678 acd_arp_reply(netif, hdr);
679#endif /* LWIP_ACD */
680
681 /* Copy struct ip4_addr_wordaligned to aligned ip4_addr, to support compilers without
682 * structure packing (not using structure copy which breaks strict-aliasing rules). */
683 IPADDR_WORDALIGNED_COPY_TO_IP4_ADDR_T(&sipaddr, &hdr->sipaddr);
684 IPADDR_WORDALIGNED_COPY_TO_IP4_ADDR_T(&dipaddr, &hdr->dipaddr);
685
686 /* this interface is not configured? */
687 if (ip4_addr_isany_val(*netif_ip4_addr(netif))) {
688 for_us = 0;
689 from_us = 0;
690 } else {
691 /* ARP packet directed to us? */
692 for_us = (u8_t)ip4_addr_eq(&dipaddr, netif_ip4_addr(netif));
693 /* ARP packet from us? */
694 from_us = (u8_t)ip4_addr_eq(&sipaddr, netif_ip4_addr(netif));
695 }
696
697 /* ARP message directed to us?
698 -> add IP address in ARP cache; assume requester wants to talk to us,
699 can result in directly sending the queued packets for this host.
700 ARP message not directed to us?
701 -> update the source IP address in the cache, if present */
702 etharp_update_arp_entry(netif, &sipaddr, &(hdr->shwaddr),
703 for_us ? ETHARP_FLAG_TRY_HARD : ETHARP_FLAG_FIND_ONLY);
704
705 /* now act on the message itself */
706 switch (hdr->opcode) {
707 /* ARP request? */
708 case PP_HTONS(ARP_REQUEST):
709 /* ARP request. If it asked for our address, we send out a
710 * reply. In any case, we time-stamp any existing ARP entry,
711 * and possibly send out an IP packet that was queued on it. */
712
713 LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: incoming ARP request\n"));
714 /* ARP request for our address? */
715 if (for_us && !from_us) {
716 /* send ARP response */
717 etharp_raw(netif,
718 (struct eth_addr *)netif->hwaddr, &hdr->shwaddr,
719 (struct eth_addr *)netif->hwaddr, netif_ip4_addr(netif),
720 &hdr->shwaddr, &sipaddr,
721 ARP_REPLY);
722 /* we are not configured? */
723 } else if (ip4_addr_isany_val(*netif_ip4_addr(netif))) {
724 /* { for_us == 0 and netif->ip_addr.addr == 0 } */
725 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: we are unconfigured, ARP request ignored.\n"));
726 /* request was not directed to us */
727 } else {
728 /* { for_us == 0 and netif->ip_addr.addr != 0 } */
729 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: ARP request was not for us.\n"));
730 }
731 break;
732 case PP_HTONS(ARP_REPLY):
733 /* ARP reply. We already updated the ARP cache earlier. */
734 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: incoming ARP reply\n"));
735 break;
736 default:
737 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: ARP unknown opcode type %"S16_F"\n", lwip_htons(hdr->opcode)));
738 ETHARP_STATS_INC(etharp.err);
739 break;
740 }
741 /* free ARP packet */
742 pbuf_free(p);
743}
744
748static err_t
749etharp_output_to_arp_index(struct netif *netif, struct pbuf *q, netif_addr_idx_t arp_idx)
750{
751 LWIP_ASSERT("arp_table[arp_idx].state >= ETHARP_STATE_STABLE",
752 arp_table[arp_idx].state >= ETHARP_STATE_STABLE);
753 /* if arp table entry is about to expire: re-request it,
754 but only if its state is ETHARP_STATE_STABLE to prevent flooding the
755 network with ARP requests if this address is used frequently. */
756 if (arp_table[arp_idx].state == ETHARP_STATE_STABLE) {
757 if (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED_BROADCAST) {
758 /* issue a standard request using broadcast */
759 if (etharp_request(netif, &arp_table[arp_idx].ipaddr) == ERR_OK) {
760 arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING_1;
761 }
762 } else if (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED_UNICAST) {
763 /* issue a unicast request (for 15 seconds) to prevent unnecessary broadcast */
764 if (etharp_request_dst(netif, &arp_table[arp_idx].ipaddr, &arp_table[arp_idx].ethaddr) == ERR_OK) {
765 arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING_1;
766 }
767 }
768 }
769
770 return ethernet_output(netif, q, (struct eth_addr *)(netif->hwaddr), &arp_table[arp_idx].ethaddr, ETHTYPE_IP);
771}
772
791err_t
792etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr)
793{
794 const struct eth_addr *dest;
795 struct eth_addr mcastaddr;
796 const ip4_addr_t *dst_addr = ipaddr;
797
799 LWIP_ASSERT("netif != NULL", netif != NULL);
800 LWIP_ASSERT("q != NULL", q != NULL);
801 LWIP_ASSERT("ipaddr != NULL", ipaddr != NULL);
802
803 /* Determine on destination hardware address. Broadcasts and multicasts
804 * are special, other IP addresses are looked up in the ARP table. */
805
806 /* broadcast destination IP address? */
807 if (ip4_addr_isbroadcast(ipaddr, netif)) {
808 /* broadcast on Ethernet also */
809 dest = (const struct eth_addr *)&ethbroadcast;
810 /* multicast destination IP address? */
811 } else if (ip4_addr_ismulticast(ipaddr)) {
812 /* Hash IP multicast address to MAC address.*/
813 mcastaddr.addr[0] = LL_IP4_MULTICAST_ADDR_0;
814 mcastaddr.addr[1] = LL_IP4_MULTICAST_ADDR_1;
815 mcastaddr.addr[2] = LL_IP4_MULTICAST_ADDR_2;
816 mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
817 mcastaddr.addr[4] = ip4_addr3(ipaddr);
818 mcastaddr.addr[5] = ip4_addr4(ipaddr);
819 /* destination Ethernet address is multicast */
820 dest = &mcastaddr;
821 /* unicast destination IP address? */
822 } else {
824 /* outside local network? if so, this can neither be a global broadcast nor
825 a subnet broadcast. */
826 if (!ip4_addr_net_eq(ipaddr, netif_ip4_addr(netif), netif_ip4_netmask(netif)) &&
827 !ip4_addr_islinklocal(ipaddr)) {
828#if LWIP_AUTOIP
829 struct ip_hdr *iphdr = LWIP_ALIGNMENT_CAST(struct ip_hdr *, q->payload);
830 /* According to RFC 3297, chapter 2.6.2 (Forwarding Rules), a packet with
831 a link-local source address must always be "directly to its destination
832 on the same physical link. The host MUST NOT send the packet to any
833 router for forwarding". */
834 if (!ip4_addr_islinklocal(&iphdr->src))
835#endif /* LWIP_AUTOIP */
836 {
837#ifdef LWIP_HOOK_ETHARP_GET_GW
838 /* For advanced routing, a single default gateway might not be enough, so get
839 the IP address of the gateway to handle the current destination address. */
840 dst_addr = LWIP_HOOK_ETHARP_GET_GW(netif, ipaddr);
841 if (dst_addr == NULL)
842#endif /* LWIP_HOOK_ETHARP_GET_GW */
843 {
844 /* interface has default gateway? */
845 if (!ip4_addr_isany_val(*netif_ip4_gw(netif))) {
846 /* send to hardware address of default gateway IP address */
847 dst_addr = netif_ip4_gw(netif);
848 /* no default gateway available */
849 } else {
850 /* no route to destination error (default gateway missing) */
851 return ERR_RTE;
852 }
853 }
854 }
855 }
856#if LWIP_NETIF_HWADDRHINT
857 if (netif->hints != NULL) {
858 /* per-pcb cached entry was given */
859 netif_addr_idx_t etharp_cached_entry = netif->hints->addr_hint;
860 if (etharp_cached_entry < ARP_TABLE_SIZE) {
861#endif /* LWIP_NETIF_HWADDRHINT */
862 if ((arp_table[etharp_cached_entry].state >= ETHARP_STATE_STABLE) &&
864 (arp_table[etharp_cached_entry].netif == netif) &&
865#endif
866 (ip4_addr_eq(dst_addr, &arp_table[etharp_cached_entry].ipaddr))) {
867 /* the per-pcb-cached entry is stable and the right one! */
868 ETHARP_STATS_INC(etharp.cachehit);
869 return etharp_output_to_arp_index(netif, q, etharp_cached_entry);
870 }
871#if LWIP_NETIF_HWADDRHINT
872 }
873 }
874#endif /* LWIP_NETIF_HWADDRHINT */
875
876 /* find stable entry: do this here since this is a critical path for
877 throughput and etharp_find_entry() is kind of slow */
878 for (i = 0; i < ARP_TABLE_SIZE; i++) {
879 if ((arp_table[i].state >= ETHARP_STATE_STABLE) &&
881 (arp_table[i].netif == netif) &&
882#endif
883 (ip4_addr_eq(dst_addr, &arp_table[i].ipaddr))) {
884 /* found an existing, stable entry */
885 ETHARP_SET_ADDRHINT(netif, i);
886 return etharp_output_to_arp_index(netif, q, i);
887 }
888 }
889 /* no stable entry found, use the (slower) query function:
890 queue on destination Ethernet address belonging to ipaddr */
891 return etharp_query(netif, dst_addr, q);
892 }
893
894 /* continuation for multicast/broadcast destinations */
895 /* obtain source Ethernet address of the given interface */
896 /* send packet directly on the link */
897 return ethernet_output(netif, q, (struct eth_addr *)(netif->hwaddr), dest, ETHTYPE_IP);
898}
899
933err_t
934etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q)
935{
936 struct eth_addr *srcaddr = (struct eth_addr *)netif->hwaddr;
938 int is_new_entry = 0;
939 s16_t i_err;
941
942 /* non-unicast address? */
943 if (ip4_addr_isbroadcast(ipaddr, netif) ||
944 ip4_addr_ismulticast(ipaddr) ||
945 ip4_addr_isany(ipaddr)) {
946 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n"));
947 return ERR_ARG;
948 }
949
950 /* find entry in ARP cache, ask to create entry if queueing packet */
951 i_err = etharp_find_entry(ipaddr, ETHARP_FLAG_TRY_HARD, netif);
952
953 /* could not find or create entry? */
954 if (i_err < 0) {
955 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not create ARP entry\n"));
956 if (q) {
957 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: packet dropped\n"));
958 ETHARP_STATS_INC(etharp.memerr);
959 }
960 return (err_t)i_err;
961 }
962 LWIP_ASSERT("type overflow", (size_t)i_err < NETIF_ADDR_IDX_MAX);
963 i = (netif_addr_idx_t)i_err;
964
965 /* mark a fresh entry as pending (we just sent a request) */
966 if (arp_table[i].state == ETHARP_STATE_EMPTY) {
967 is_new_entry = 1;
968 arp_table[i].state = ETHARP_STATE_PENDING;
969 /* record network interface for re-sending arp request in etharp_tmr */
970 arp_table[i].netif = netif;
971 }
972
973 /* { i is either a STABLE or (new or existing) PENDING entry } */
974 LWIP_ASSERT("arp_table[i].state == PENDING or STABLE",
975 ((arp_table[i].state == ETHARP_STATE_PENDING) ||
976 (arp_table[i].state >= ETHARP_STATE_STABLE)));
977
978 /* do we have a new entry? or an implicit query request? */
979 if (is_new_entry || (q == NULL)) {
980 /* try to resolve it; send out ARP request */
981 result = etharp_request(netif, ipaddr);
982 if (result != ERR_OK) {
983 /* ARP request couldn't be sent */
984 /* We don't re-send arp request in etharp_tmr, but we still queue packets,
985 since this failure could be temporary, and the next packet calling
986 etharp_query again could lead to sending the queued packets. */
987 } else {
988 /* ARP request successfully sent */
989 if ((arp_table[i].state == ETHARP_STATE_PENDING) && !is_new_entry) {
990 /* A new ARP request has been sent for a pending entry. Reset the ctime to
991 not let it expire too fast. */
992 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: reset ctime for entry %"S16_F"\n", (s16_t)i));
993 arp_table[i].ctime = 0;
994 }
995 }
996 if (q == NULL) {
997 return result;
998 }
999 }
1000
1001 /* packet given? */
1002 LWIP_ASSERT("q != NULL", q != NULL);
1003 /* stable entry? */
1004 if (arp_table[i].state >= ETHARP_STATE_STABLE) {
1005 /* we have a valid IP->Ethernet address mapping */
1006 ETHARP_SET_ADDRHINT(netif, i);
1007 /* send the packet */
1008 result = ethernet_output(netif, q, srcaddr, &(arp_table[i].ethaddr), ETHTYPE_IP);
1009 /* pending entry? (either just created or already pending */
1010 } else if (arp_table[i].state == ETHARP_STATE_PENDING) {
1011 /* entry is still pending, queue the given packet 'q' */
1012 struct pbuf *p;
1013 int copy_needed = 0;
1014 /* IF q includes a pbuf that must be copied, copy the whole chain into a
1015 * new PBUF_RAM. See the definition of PBUF_NEEDS_COPY for details. */
1016 p = q;
1017 while (p) {
1018 LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == NULL));
1019 if (PBUF_NEEDS_COPY(p)) {
1020 copy_needed = 1;
1021 break;
1022 }
1023 p = p->next;
1024 }
1025 if (copy_needed) {
1026 /* copy the whole packet into new pbufs */
1028 } else {
1029 /* referencing the old pbuf is enough */
1030 p = q;
1031 pbuf_ref(p);
1032 }
1033 /* packet could be taken over? */
1034 if (p != NULL) {
1035 /* queue packet ... */
1036#if ARP_QUEUEING
1037 struct etharp_q_entry *new_entry;
1038 /* allocate a new arp queue entry */
1039 new_entry = (struct etharp_q_entry *)memp_malloc(MEMP_ARP_QUEUE);
1040 if (new_entry != NULL) {
1041 unsigned int qlen = 0;
1042 new_entry->next = NULL;
1043 new_entry->p = p;
1044 if (arp_table[i].q != NULL) {
1045 /* queue was already existent, append the new entry to the end */
1046 struct etharp_q_entry *r;
1047 r = arp_table[i].q;
1048 qlen++;
1049 while (r->next != NULL) {
1050 r = r->next;
1051 qlen++;
1052 }
1053 r->next = new_entry;
1054 } else {
1055 /* queue did not exist, first item in queue */
1056 arp_table[i].q = new_entry;
1057 }
1058#if ARP_QUEUE_LEN
1059 if (qlen >= ARP_QUEUE_LEN) {
1060 struct etharp_q_entry *old;
1061 old = arp_table[i].q;
1062 arp_table[i].q = arp_table[i].q->next;
1063 pbuf_free(old->p);
1064 memp_free(MEMP_ARP_QUEUE, old);
1065 }
1066#endif
1067 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"U16_F"\n", (void *)q, i));
1068 result = ERR_OK;
1069 } else {
1070 /* the pool MEMP_ARP_QUEUE is empty */
1071 pbuf_free(p);
1072 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));
1073 result = ERR_MEM;
1074 }
1075#else /* ARP_QUEUEING */
1076 /* always queue one packet per ARP request only, freeing a previously queued packet */
1077 if (arp_table[i].q != NULL) {
1078 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: dropped previously queued packet %p for ARP entry %"U16_F"\n", (void *)q, (u16_t)i));
1079 pbuf_free(arp_table[i].q);
1080 }
1081 arp_table[i].q = p;
1082 result = ERR_OK;
1083 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"U16_F"\n", (void *)q, (u16_t)i));
1084#endif /* ARP_QUEUEING */
1085 } else {
1086 ETHARP_STATS_INC(etharp.memerr);
1087 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));
1088 result = ERR_MEM;
1089 }
1090 }
1091 return result;
1092}
1093
1109static err_t
1110etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
1111 const struct eth_addr *ethdst_addr,
1112 const struct eth_addr *hwsrc_addr, const ip4_addr_t *ipsrc_addr,
1113 const struct eth_addr *hwdst_addr, const ip4_addr_t *ipdst_addr,
1114 const u16_t opcode)
1115{
1116 struct pbuf *p;
1118 struct etharp_hdr *hdr;
1119
1120 LWIP_ASSERT("netif != NULL", netif != NULL);
1121
1122 /* allocate a pbuf for the outgoing ARP request packet */
1124 /* could allocate a pbuf for an ARP request? */
1125 if (p == NULL) {
1127 ("etharp_raw: could not allocate pbuf for ARP request.\n"));
1128 ETHARP_STATS_INC(etharp.memerr);
1129 return ERR_MEM;
1130 }
1131 LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr",
1132 (p->len >= SIZEOF_ETHARP_HDR));
1133
1134 hdr = (struct etharp_hdr *)p->payload;
1135 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n"));
1136 hdr->opcode = lwip_htons(opcode);
1137
1138 LWIP_ASSERT("netif->hwaddr_len must be the same as ETH_HWADDR_LEN for etharp!",
1140
1141 /* Write the ARP MAC-Addresses */
1142 SMEMCPY(&hdr->shwaddr, hwsrc_addr, ETH_HWADDR_LEN);
1143 SMEMCPY(&hdr->dhwaddr, hwdst_addr, ETH_HWADDR_LEN);
1144 /* Copy struct ip4_addr_wordaligned to aligned ip4_addr, to support compilers without
1145 * structure packing. */
1146 IPADDR_WORDALIGNED_COPY_FROM_IP4_ADDR_T(&hdr->sipaddr, ipsrc_addr);
1147 IPADDR_WORDALIGNED_COPY_FROM_IP4_ADDR_T(&hdr->dipaddr, ipdst_addr);
1148
1150 hdr->proto = PP_HTONS(ETHTYPE_IP);
1151 /* set hwlen and protolen */
1152 hdr->hwlen = ETH_HWADDR_LEN;
1153 hdr->protolen = sizeof(ip4_addr_t);
1154
1155 /* send ARP query */
1156#if LWIP_AUTOIP
1157 /* If we are using Link-Local, all ARP packets that contain a Link-Local
1158 * 'sender IP address' MUST be sent using link-layer broadcast instead of
1159 * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */
1160 if (ip4_addr_islinklocal(ipsrc_addr)) {
1161 ethernet_output(netif, p, ethsrc_addr, &ethbroadcast, ETHTYPE_ARP);
1162 } else
1163#endif /* LWIP_AUTOIP */
1164 {
1165 ethernet_output(netif, p, ethsrc_addr, ethdst_addr, ETHTYPE_ARP);
1166 }
1167
1168 ETHARP_STATS_INC(etharp.xmit);
1169 /* free ARP query packet */
1170 pbuf_free(p);
1171 p = NULL;
1172 /* could not allocate pbuf for ARP request */
1173
1174 return result;
1175}
1176
1189static err_t
1190etharp_request_dst(struct netif *netif, const ip4_addr_t *ipaddr, const struct eth_addr *hw_dst_addr)
1191{
1192 return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, hw_dst_addr,
1193 (struct eth_addr *)netif->hwaddr, netif_ip4_addr(netif), &ethzero,
1194 ipaddr, ARP_REQUEST);
1195}
1196
1206err_t
1207etharp_request(struct netif *netif, const ip4_addr_t *ipaddr)
1208{
1209 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_request: sending ARP request.\n"));
1210 return etharp_request_dst(netif, ipaddr, &ethbroadcast);
1211}
1212
1213#if LWIP_ACD
1224err_t
1225etharp_acd_probe(struct netif *netif, const ip4_addr_t *ipaddr)
1226{
1227 return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, &ethbroadcast,
1228 (struct eth_addr *)netif->hwaddr, IP4_ADDR_ANY4, &ethzero,
1229 ipaddr, ARP_REQUEST);
1230}
1231
1242err_t
1243etharp_acd_announce(struct netif *netif, const ip4_addr_t *ipaddr)
1244{
1245 return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, &ethbroadcast,
1246 (struct eth_addr *)netif->hwaddr, ipaddr, &ethzero,
1247 ipaddr, ARP_REQUEST);
1248}
1249#endif /* LWIP_ACD */
1250
1251#endif /* LWIP_IPV4 && LWIP_ARP */
static int state
Definition: maze.c:121
#define PP_HTONS(x)
Definition: def.h:90
#define lwip_htons(x)
Definition: def.h:86
#define NULL
Definition: types.h:112
static const WCHAR empty[]
Definition: main.c:47
#define X16_F
Definition: cc.h:21
#define U16_F
Definition: cc.h:19
#define S16_F
Definition: cc.h:20
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:158
#define LWIP_ERROR(message, expression, handler)
Definition: debug.h:130
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:116
#define mib2_remove_arp_entry(ni, ip)
Definition: snmp.h:182
#define mib2_add_arp_entry(ni, ip)
Definition: snmp.h:181
#define ERR_MEM
Definition: fontsub.h:52
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
GLbitfield flags
Definition: glext.h:7161
GLfloat GLfloat p
Definition: glext.h:8902
GLuint64EXT * result
Definition: glext.h:11304
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
uint8_t u8_t
Definition: arch.h:125
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:373
uint16_t u16_t
Definition: arch.h:127
#define LWIP_ALIGNMENT_CAST(target_type, val)
Definition: arch.h:245
int16_t s16_t
Definition: arch.h:128
#define LWIP_DBG_LEVEL_SERIOUS
Definition: debug.h:57
#define LWIP_DBG_LEVEL_WARNING
Definition: debug.h:55
#define LWIP_DBG_TRACE
Definition: debug.h:83
@ LWIP_IANA_HWTYPE_ETHERNET
Definition: iana.h:54
@ ETHTYPE_ARP
Definition: ieee.h:56
@ ETHTYPE_IP
Definition: ieee.h:54
s8_t err_t
Definition: err.h:96
@ ERR_RTE
Definition: err.h:63
@ ERR_OK
Definition: err.h:55
@ ERR_VAL
Definition: err.h:67
@ ERR_ARG
Definition: err.h:88
#define ARP_QUEUE_LEN
Definition: opt.h:656
#define ETHARP_TABLE_MATCH_NETIF
Definition: opt.h:714
#define ETHARP_SUPPORT_STATIC_ENTRIES
Definition: opt.h:706
#define ARP_MAXAGE
Definition: opt.h:637
#define ARP_TABLE_SIZE
Definition: opt.h:629
#define ETHARP_DEBUG
Definition: opt.h:3329
#define LWIP_ASSERT_CORE_LOCKED()
Definition: opt.h:227
#define SMEMCPY(dst, src, len)
Definition: opt.h:145
void pbuf_ref(struct pbuf *p)
Definition: pbuf.c:831
#define PBUF_NEEDS_COPY(p)
Definition: pbuf.h:72
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
Definition: pbuf.c:224
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:727
struct pbuf * pbuf_clone(pbuf_layer layer, pbuf_type type, struct pbuf *p)
Definition: pbuf.c:1337
@ PBUF_RAM
Definition: pbuf.h:152
@ PBUF_LINK
Definition: pbuf.h:102
char hdr[14]
Definition: iptest.cpp:33
if(dx< 0)
Definition: linetemp.h:194
#define SIZEOF_ETHARP_HDR
Definition: etharp.h:102
#define IPADDR_WORDALIGNED_COPY_FROM_IP4_ADDR_T(dest, src)
Definition: etharp.h:78
#define IPADDR_WORDALIGNED_COPY_TO_IP4_ADDR_T(dest, src)
Definition: etharp.h:71
@ ARP_REPLY
Definition: etharp.h:107
@ ARP_REQUEST
Definition: etharp.h:106
#define LL_IP4_MULTICAST_ADDR_2
Definition: ethernet.h:113
#define LL_IP4_MULTICAST_ADDR_1
Definition: ethernet.h:112
#define ETH_HWADDR_LEN
Definition: ethernet.h:51
#define LL_IP4_MULTICAST_ADDR_0
Definition: ethernet.h:111
void * memp_malloc(memp_t type)
Definition: memp.c:337
void memp_free(memp_t type, void *mem)
Definition: memp.c:420
__u16 ctime
Definition: mkdosfs.c:4
static char * dest
Definition: rtl.c:135
#define NETIF_ADDR_IDX_MAX
Definition: netif.h:248
u8_t netif_addr_idx_t
Definition: netif.h:247
int ssize_t
Definition: rosdhcp.h:48
#define ETHARP_STATS_INC(x)
Definition: stats.h:376
Definition: ip4.h:73
Definition: netif.h:269
u8_t hwaddr[NETIF_MAX_HWADDR_LEN]
Definition: netif.h:350
u8_t hwaddr_len
Definition: netif.h:352
Definition: pbuf.h:186