ReactOS 0.4.15-dev-7834-g00c4b3d
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_ARP || LWIP_ETHERNET
49
50#include "lwip/ip_addr.h"
51#include "lwip/def.h"
52#include "lwip/ip.h"
53#include "lwip/stats.h"
54#include "lwip/snmp.h"
55#include "lwip/dhcp.h"
56#include "lwip/autoip.h"
57#include "netif/etharp.h"
58
59#if PPPOE_SUPPORT
60#include "netif/ppp_oe.h"
61#endif /* PPPOE_SUPPORT */
62
63#include <string.h>
64
65const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
66const struct eth_addr ethzero = {{0,0,0,0,0,0}};
67
69#define LL_MULTICAST_ADDR_0 0x01
70#define LL_MULTICAST_ADDR_1 0x00
71#define LL_MULTICAST_ADDR_2 0x5e
72
73#if LWIP_ARP /* don't build if not configured for use in lwipopts.h */
74
79#define ARP_MAXAGE 240
82#define ARP_AGE_REREQUEST_USED (ARP_MAXAGE - 12)
83
91#define ARP_MAXPENDING 2
92
93#define HWTYPE_ETHERNET 1
94
95enum etharp_state {
96 ETHARP_STATE_EMPTY = 0,
97 ETHARP_STATE_PENDING,
98 ETHARP_STATE_STABLE,
99 ETHARP_STATE_STABLE_REREQUESTING
100#if ETHARP_SUPPORT_STATIC_ENTRIES
101 ,ETHARP_STATE_STATIC
102#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
103};
104
105struct etharp_entry {
106#if ARP_QUEUEING
108 struct etharp_q_entry *q;
109#else /* ARP_QUEUEING */
111 struct pbuf *q;
112#endif /* ARP_QUEUEING */
113 ip_addr_t ipaddr;
114 struct netif *netif;
115 struct eth_addr ethaddr;
116 u8_t state;
117 u8_t ctime;
118};
119
120static struct etharp_entry arp_table[ARP_TABLE_SIZE];
121
122#if !LWIP_NETIF_HWADDRHINT
123static u8_t etharp_cached_entry;
124#endif /* !LWIP_NETIF_HWADDRHINT */
125
128#define ETHARP_FLAG_TRY_HARD 1
129#define ETHARP_FLAG_FIND_ONLY 2
130#if ETHARP_SUPPORT_STATIC_ENTRIES
131#define ETHARP_FLAG_STATIC_ENTRY 4
132#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
133
134#if LWIP_NETIF_HWADDRHINT
135#define ETHARP_SET_HINT(netif, hint) if (((netif) != NULL) && ((netif)->addr_hint != NULL)) \
136 *((netif)->addr_hint) = (hint);
137#else /* LWIP_NETIF_HWADDRHINT */
138#define ETHARP_SET_HINT(netif, hint) (etharp_cached_entry = (hint))
139#endif /* LWIP_NETIF_HWADDRHINT */
140
141
142/* Some checks, instead of etharp_init(): */
143#if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f))
144 #error "ARP_TABLE_SIZE must fit in an s8_t, you have to reduce it in your lwipopts.h"
145#endif
146
147
148#if ARP_QUEUEING
154static void
155free_etharp_q(struct etharp_q_entry *q)
156{
157 struct etharp_q_entry *r;
158 LWIP_ASSERT("q != NULL", q != NULL);
159 LWIP_ASSERT("q->p != NULL", q->p != NULL);
160 while (q) {
161 r = q;
162 q = q->next;
163 LWIP_ASSERT("r->p != NULL", (r->p != NULL));
164 pbuf_free(r->p);
165 memp_free(MEMP_ARP_QUEUE, r);
166 }
167}
168#else /* ARP_QUEUEING */
169
171#define free_etharp_q(q) pbuf_free(q)
172
173#endif /* ARP_QUEUEING */
174
176static void
177etharp_free_entry(int i)
178{
179 /* remove from SNMP ARP index tree */
180 snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr);
181 /* and empty packet queue */
182 if (arp_table[i].q != NULL) {
183 /* remove all queued packets */
184 LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_free_entry: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].q)));
185 free_etharp_q(arp_table[i].q);
186 arp_table[i].q = NULL;
187 }
188 /* recycle entry for re-use */
189 arp_table[i].state = ETHARP_STATE_EMPTY;
190#ifdef LWIP_DEBUG
191 /* for debugging, clean out the complete entry */
192 arp_table[i].ctime = 0;
193 arp_table[i].netif = NULL;
194 ip_addr_set_zero(&arp_table[i].ipaddr);
195 arp_table[i].ethaddr = ethzero;
196#endif /* LWIP_DEBUG */
197}
198
205void
206etharp_tmr(void)
207{
208 u8_t i;
209
210 LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n"));
211 /* remove expired entries from the ARP table */
212 for (i = 0; i < ARP_TABLE_SIZE; ++i) {
213 u8_t state = arp_table[i].state;
214 if (state != ETHARP_STATE_EMPTY
216 && (state != ETHARP_STATE_STATIC)
217#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
218 ) {
219 arp_table[i].ctime++;
220 if ((arp_table[i].ctime >= ARP_MAXAGE) ||
221 ((arp_table[i].state == ETHARP_STATE_PENDING) &&
222 (arp_table[i].ctime >= ARP_MAXPENDING))) {
223 /* pending or stable entry has become old! */
224 LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n",
225 arp_table[i].state >= ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i));
226 /* clean up entries that have just been expired */
227 etharp_free_entry(i);
228 }
229 else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING) {
230 /* Reset state to stable, so that the next transmitted packet will
231 re-send an ARP request. */
232 arp_table[i].state = ETHARP_STATE_STABLE;
233 }
234#if ARP_QUEUEING
235 /* still pending entry? (not expired) */
236 if (arp_table[i].state == ETHARP_STATE_PENDING) {
237 /* resend an ARP query here? */
238 }
239#endif /* ARP_QUEUEING */
240 }
241 }
242}
243
265static s8_t
266etharp_find_entry(ip_addr_t *ipaddr, u8_t flags)
267{
268 s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE;
270 u8_t i = 0, age_pending = 0, age_stable = 0;
271 /* oldest entry with packets on queue */
272 s8_t old_queue = ARP_TABLE_SIZE;
273 /* its age */
274 u8_t age_queue = 0;
275
282 /* a) in a single search sweep, do all of this
283 * 1) remember the first empty entry (if any)
284 * 2) remember the oldest stable entry (if any)
285 * 3) remember the oldest pending entry without queued packets (if any)
286 * 4) remember the oldest pending entry with queued packets (if any)
287 * 5) search for a matching IP entry, either pending or stable
288 * until 5 matches, or all entries are searched for.
289 */
290
291 for (i = 0; i < ARP_TABLE_SIZE; ++i) {
292 u8_t state = arp_table[i].state;
293 /* no empty entry found yet and now we do find one? */
294 if ((empty == ARP_TABLE_SIZE) && (state == ETHARP_STATE_EMPTY)) {
295 LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_find_entry: found empty entry %"U16_F"\n", (u16_t)i));
296 /* remember first empty entry */
297 empty = i;
298 } else if (state != ETHARP_STATE_EMPTY) {
299 LWIP_ASSERT("state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE",
300 state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE);
301 /* if given, does IP address match IP address in ARP entry? */
302 if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
303 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: found matching entry %"U16_F"\n", (u16_t)i));
304 /* found exact IP address match, simply bail out */
305 return i;
306 }
307 /* pending entry? */
308 if (state == ETHARP_STATE_PENDING) {
309 /* pending with queued packets? */
310 if (arp_table[i].q != NULL) {
311 if (arp_table[i].ctime >= age_queue) {
312 old_queue = i;
313 age_queue = arp_table[i].ctime;
314 }
315 } else
316 /* pending without queued packets? */
317 {
318 if (arp_table[i].ctime >= age_pending) {
319 old_pending = i;
320 age_pending = arp_table[i].ctime;
321 }
322 }
323 /* stable entry? */
324 } else if (state >= ETHARP_STATE_STABLE) {
325#if ETHARP_SUPPORT_STATIC_ENTRIES
326 /* don't record old_stable for static entries since they never expire */
327 if (state < ETHARP_STATE_STATIC)
328#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
329 {
330 /* remember entry with oldest stable entry in oldest, its age in maxtime */
331 if (arp_table[i].ctime >= age_stable) {
332 old_stable = i;
333 age_stable = arp_table[i].ctime;
334 }
335 }
336 }
337 }
338 }
339 /* { we have no match } => try to create a new entry */
340
341 /* don't create new entry, only search? */
342 if (((flags & ETHARP_FLAG_FIND_ONLY) != 0) ||
343 /* or no empty entry found and not allowed to recycle? */
344 ((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_FLAG_TRY_HARD) == 0))) {
345 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty entry found and not allowed to recycle\n"));
346 return (s8_t)ERR_MEM;
347 }
348
349 /* b) choose the least destructive entry to recycle:
350 * 1) empty entry
351 * 2) oldest stable entry
352 * 3) oldest pending entry without queued packets
353 * 4) oldest pending entry with queued packets
354 *
355 * { ETHARP_FLAG_TRY_HARD is set at this point }
356 */
357
358 /* 1) empty entry available? */
359 if (empty < ARP_TABLE_SIZE) {
360 i = empty;
361 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting empty entry %"U16_F"\n", (u16_t)i));
362 } else {
363 /* 2) found recyclable stable entry? */
364 if (old_stable < ARP_TABLE_SIZE) {
365 /* recycle oldest stable*/
366 i = old_stable;
367 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i));
368 /* no queued packets should exist on stable entries */
369 LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL);
370 /* 3) found recyclable pending entry without queued packets? */
371 } else if (old_pending < ARP_TABLE_SIZE) {
372 /* recycle oldest pending */
373 i = old_pending;
374 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i));
375 /* 4) found recyclable pending entry with queued packets? */
376 } else if (old_queue < ARP_TABLE_SIZE) {
377 /* recycle oldest pending (queued packets are free in etharp_free_entry) */
378 i = old_queue;
379 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)));
380 /* no empty or recyclable entries found */
381 } else {
382 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty or recyclable entries found\n"));
383 return (s8_t)ERR_MEM;
384 }
385
386 /* { empty or recyclable entry found } */
387 LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE);
388 etharp_free_entry(i);
389 }
390
391 LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE);
392 LWIP_ASSERT("arp_table[i].state == ETHARP_STATE_EMPTY",
393 arp_table[i].state == ETHARP_STATE_EMPTY);
394
395 /* IP address given? */
396 if (ipaddr != NULL) {
397 /* set IP address */
398 ip_addr_copy(arp_table[i].ipaddr, *ipaddr);
399 }
400 arp_table[i].ctime = 0;
401 return (err_t)i;
402}
403
414static err_t
415etharp_send_ip(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst)
416{
417 struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload;
418
419 LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",
420 (netif->hwaddr_len == ETHARP_HWADDR_LEN));
421 ETHADDR32_COPY(&ethhdr->dest, dst);
422 ETHADDR16_COPY(&ethhdr->src, src);
423 ethhdr->type = PP_HTONS(ETHTYPE_IP);
424 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_send_ip: sending packet %p\n", (void *)p));
425 /* send the packet */
426 return netif->linkoutput(netif, p);
427}
428
447static err_t
448etharp_update_arp_entry(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags)
449{
450 s8_t i;
451 LWIP_ASSERT("netif->hwaddr_len == ETHARP_HWADDR_LEN", netif->hwaddr_len == ETHARP_HWADDR_LEN);
452 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",
453 ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr),
454 ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2],
455 ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5]));
456 /* non-unicast address? */
457 if (ip_addr_isany(ipaddr) ||
458 ip_addr_isbroadcast(ipaddr, netif) ||
459 ip_addr_ismulticast(ipaddr)) {
460 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: will not add non-unicast IP address to ARP cache\n"));
461 return ERR_ARG;
462 }
463 /* find or create ARP entry */
464 i = etharp_find_entry(ipaddr, flags);
465 /* bail out if no entry could be found */
466 if (i < 0) {
467 return (err_t)i;
468 }
469
470#if ETHARP_SUPPORT_STATIC_ENTRIES
471 if (flags & ETHARP_FLAG_STATIC_ENTRY) {
472 /* record static type */
473 arp_table[i].state = ETHARP_STATE_STATIC;
474 } else
475#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
476 {
477 /* mark it stable */
478 arp_table[i].state = ETHARP_STATE_STABLE;
479 }
480
481 /* record network interface */
482 arp_table[i].netif = netif;
483 /* insert in SNMP ARP index tree */
484 snmp_insert_arpidx_tree(netif, &arp_table[i].ipaddr);
485
486 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i));
487 /* update address */
488 ETHADDR32_COPY(&arp_table[i].ethaddr, ethaddr);
489 /* reset time stamp */
490 arp_table[i].ctime = 0;
491 /* this is where we will send out queued packets! */
492#if ARP_QUEUEING
493 while (arp_table[i].q != NULL) {
494 struct pbuf *p;
495 /* remember remainder of queue */
496 struct etharp_q_entry *q = arp_table[i].q;
497 /* pop first item off the queue */
498 arp_table[i].q = q->next;
499 /* get the packet pointer */
500 p = q->p;
501 /* now queue entry can be freed */
502 memp_free(MEMP_ARP_QUEUE, q);
503#else /* ARP_QUEUEING */
504 if (arp_table[i].q != NULL) {
505 struct pbuf *p = arp_table[i].q;
506 arp_table[i].q = NULL;
507#endif /* ARP_QUEUEING */
508 /* send the queued IP packet */
509 etharp_send_ip(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr);
510 /* free the queued IP packet */
511 pbuf_free(p);
512 }
513 return ERR_OK;
514}
515
516#if ETHARP_SUPPORT_STATIC_ENTRIES
525err_t
526etharp_add_static_entry(ip_addr_t *ipaddr, struct eth_addr *ethaddr)
527{
528 struct netif *netif;
529 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",
530 ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr),
531 ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2],
532 ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5]));
533
534 netif = ip_route(ipaddr);
535 if (netif == NULL) {
536 return ERR_RTE;
537 }
538
539 return etharp_update_arp_entry(netif, ipaddr, ethaddr, ETHARP_FLAG_TRY_HARD | ETHARP_FLAG_STATIC_ENTRY);
540}
541
550err_t
551etharp_remove_static_entry(ip_addr_t *ipaddr)
552{
553 s8_t i;
554 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_remove_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
555 ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr)));
556
557 /* find or create ARP entry */
558 i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY);
559 /* bail out if no entry could be found */
560 if (i < 0) {
561 return (err_t)i;
562 }
563
564 if (arp_table[i].state != ETHARP_STATE_STATIC) {
565 /* entry wasn't a static entry, cannot remove it */
566 return ERR_ARG;
567 }
568 /* entry found, free it */
569 etharp_free_entry(i);
570 return ERR_OK;
571}
572#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
573
579void etharp_cleanup_netif(struct netif *netif)
580{
581 u8_t i;
582
583 for (i = 0; i < ARP_TABLE_SIZE; ++i) {
584 u8_t state = arp_table[i].state;
585 if ((state != ETHARP_STATE_EMPTY) && (arp_table[i].netif == netif)) {
586 etharp_free_entry(i);
587 }
588 }
589}
590
602s8_t
603etharp_find_addr(struct netif *netif, ip_addr_t *ipaddr,
604 struct eth_addr **eth_ret, ip_addr_t **ip_ret)
605{
606 s8_t i;
607
608 LWIP_ASSERT("eth_ret != NULL && ip_ret != NULL",
609 eth_ret != NULL && ip_ret != NULL);
610
612
613 i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY);
614 if((i >= 0) && (arp_table[i].state >= ETHARP_STATE_STABLE)) {
615 *eth_ret = &arp_table[i].ethaddr;
616 *ip_ret = &arp_table[i].ipaddr;
617 return i;
618 }
619 return -1;
620}
621
622#if ETHARP_TRUST_IP_MAC
638static void
639etharp_ip_input(struct netif *netif, struct pbuf *p)
640{
641 struct eth_hdr *ethhdr;
642 struct ip_hdr *iphdr;
643 ip_addr_t iphdr_src;
644 LWIP_ERROR("netif != NULL", (netif != NULL), return;);
645
646 /* Only insert an entry if the source IP address of the
647 incoming IP packet comes from a host on the local network. */
648 ethhdr = (struct eth_hdr *)p->payload;
649 iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
650#if ETHARP_SUPPORT_VLAN
651 if (ethhdr->type == PP_HTONS(ETHTYPE_VLAN)) {
652 iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);
653 }
654#endif /* ETHARP_SUPPORT_VLAN */
655
656 ip_addr_copy(iphdr_src, iphdr->src);
657
658 /* source is not on the local network? */
659 if (!ip_addr_netcmp(&iphdr_src, &(netif->ip_addr), &(netif->netmask))) {
660 /* do nothing */
661 return;
662 }
663
664 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n"));
665 /* update the source IP address in the cache, if present */
666 /* @todo We could use ETHARP_FLAG_TRY_HARD if we think we are going to talk
667 * back soon (for example, if the destination IP address is ours. */
668 etharp_update_arp_entry(netif, &iphdr_src, &(ethhdr->src), ETHARP_FLAG_FIND_ONLY);
669}
670#endif /* ETHARP_TRUST_IP_MAC */
671
687static void
688etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
689{
690 struct etharp_hdr *hdr;
691 struct eth_hdr *ethhdr;
692 /* these are aligned properly, whereas the ARP header fields might not be */
693 ip_addr_t sipaddr, dipaddr;
694 u8_t for_us;
695#if LWIP_AUTOIP
696 const u8_t * ethdst_hwaddr;
697#endif /* LWIP_AUTOIP */
698
699 LWIP_ERROR("netif != NULL", (netif != NULL), return;);
700
701 /* drop short ARP packets: we have to check for p->len instead of p->tot_len here
702 since a struct etharp_hdr is pointed to p->payload, so it musn't be chained! */
703 if (p->len < SIZEOF_ETHARP_PACKET) {
705 ("etharp_arp_input: packet dropped, too short (%"S16_F"/%"S16_F")\n", p->tot_len,
706 (s16_t)SIZEOF_ETHARP_PACKET));
707 ETHARP_STATS_INC(etharp.lenerr);
708 ETHARP_STATS_INC(etharp.drop);
709 pbuf_free(p);
710 return;
711 }
712
713 ethhdr = (struct eth_hdr *)p->payload;
714 hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
715#if ETHARP_SUPPORT_VLAN
716 if (ethhdr->type == PP_HTONS(ETHTYPE_VLAN)) {
717 hdr = (struct etharp_hdr *)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);
718 }
719#endif /* ETHARP_SUPPORT_VLAN */
720
721 /* RFC 826 "Packet Reception": */
722 if ((hdr->hwtype != PP_HTONS(HWTYPE_ETHERNET)) ||
723 (hdr->hwlen != ETHARP_HWADDR_LEN) ||
724 (hdr->protolen != sizeof(ip_addr_t)) ||
725 (hdr->proto != PP_HTONS(ETHTYPE_IP))) {
727 ("etharp_arp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n",
728 hdr->hwtype, hdr->hwlen, hdr->proto, hdr->protolen));
729 ETHARP_STATS_INC(etharp.proterr);
730 ETHARP_STATS_INC(etharp.drop);
731 pbuf_free(p);
732 return;
733 }
734 ETHARP_STATS_INC(etharp.recv);
735
736#if LWIP_AUTOIP
737 /* We have to check if a host already has configured our random
738 * created link local address and continously check if there is
739 * a host with this IP-address so we can detect collisions */
740 autoip_arp_reply(netif, hdr);
741#endif /* LWIP_AUTOIP */
742
743 /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
744 * structure packing (not using structure copy which breaks strict-aliasing rules). */
745 IPADDR2_COPY(&sipaddr, &hdr->sipaddr);
746 IPADDR2_COPY(&dipaddr, &hdr->dipaddr);
747
748 /* this interface is not configured? */
749 if (ip_addr_isany(&netif->ip_addr)) {
750 for_us = 0;
751 } else {
752 /* ARP packet directed to us? */
753 for_us = (u8_t)ip_addr_cmp(&dipaddr, &(netif->ip_addr));
754 }
755
756 /* ARP message directed to us?
757 -> add IP address in ARP cache; assume requester wants to talk to us,
758 can result in directly sending the queued packets for this host.
759 ARP message not directed to us?
760 -> update the source IP address in the cache, if present */
761 etharp_update_arp_entry(netif, &sipaddr, &(hdr->shwaddr),
762 for_us ? ETHARP_FLAG_TRY_HARD : ETHARP_FLAG_FIND_ONLY);
763
764 /* now act on the message itself */
765 switch (hdr->opcode) {
766 /* ARP request? */
767 case PP_HTONS(ARP_REQUEST):
768 /* ARP request. If it asked for our address, we send out a
769 * reply. In any case, we time-stamp any existing ARP entry,
770 * and possiby send out an IP packet that was queued on it. */
771
772 LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP request\n"));
773 /* ARP request for our address? */
774 if (for_us) {
775
776 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: replying to ARP request for our IP address\n"));
777 /* Re-use pbuf to send ARP reply.
778 Since we are re-using an existing pbuf, we can't call etharp_raw since
779 that would allocate a new pbuf. */
780 hdr->opcode = htons(ARP_REPLY);
781
782 IPADDR2_COPY(&hdr->dipaddr, &hdr->sipaddr);
783 IPADDR2_COPY(&hdr->sipaddr, &netif->ip_addr);
784
785 LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",
786 (netif->hwaddr_len == ETHARP_HWADDR_LEN));
787#if LWIP_AUTOIP
788 /* If we are using Link-Local, all ARP packets that contain a Link-Local
789 * 'sender IP address' MUST be sent using link-layer broadcast instead of
790 * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */
791 ethdst_hwaddr = ip_addr_islinklocal(&netif->ip_addr) ? (u8_t*)(ethbroadcast.addr) : hdr->shwaddr.addr;
792#endif /* LWIP_AUTOIP */
793
794 ETHADDR16_COPY(&hdr->dhwaddr, &hdr->shwaddr);
795#if LWIP_AUTOIP
796 ETHADDR16_COPY(&ethhdr->dest, ethdst_hwaddr);
797#else /* LWIP_AUTOIP */
798 ETHADDR16_COPY(&ethhdr->dest, &hdr->shwaddr);
799#endif /* LWIP_AUTOIP */
800 ETHADDR16_COPY(&hdr->shwaddr, ethaddr);
801 ETHADDR16_COPY(&ethhdr->src, ethaddr);
802
803 /* hwtype, hwaddr_len, proto, protolen and the type in the ethernet header
804 are already correct, we tested that before */
805
806 /* return ARP reply */
808 /* we are not configured? */
809 } else if (ip_addr_isany(&netif->ip_addr)) {
810 /* { for_us == 0 and netif->ip_addr.addr == 0 } */
811 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n"));
812 /* request was not directed to us */
813 } else {
814 /* { for_us == 0 and netif->ip_addr.addr != 0 } */
815 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP request was not for us.\n"));
816 }
817 break;
818 case PP_HTONS(ARP_REPLY):
819 /* ARP reply. We already updated the ARP cache earlier. */
820 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n"));
821#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
822 /* DHCP wants to know about ARP replies from any host with an
823 * IP address also offered to us by the DHCP server. We do not
824 * want to take a duplicate IP address on a single network.
825 * @todo How should we handle redundant (fail-over) interfaces? */
826 dhcp_arp_reply(netif, &sipaddr);
827#endif /* (LWIP_DHCP && DHCP_DOES_ARP_CHECK) */
828 break;
829 default:
830 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %"S16_F"\n", htons(hdr->opcode)));
831 ETHARP_STATS_INC(etharp.err);
832 break;
833 }
834 /* free ARP packet */
835 pbuf_free(p);
836}
837
841static err_t
842etharp_output_to_arp_index(struct netif *netif, struct pbuf *q, u8_t arp_idx)
843{
844 LWIP_ASSERT("arp_table[arp_idx].state >= ETHARP_STATE_STABLE",
845 arp_table[arp_idx].state >= ETHARP_STATE_STABLE);
846 /* if arp table entry is about to expire: re-request it,
847 but only if its state is ETHARP_STATE_STABLE to prevent flooding the
848 network with ARP requests if this address is used frequently. */
849 if ((arp_table[arp_idx].state == ETHARP_STATE_STABLE) &&
850 (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED)) {
851 if (etharp_request(netif, &arp_table[arp_idx].ipaddr) == ERR_OK) {
852 arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING;
853 }
854 }
855
856 return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr),
857 &arp_table[arp_idx].ethaddr);
858}
859
878err_t
879etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr)
880{
881 struct eth_addr *dest;
882 struct eth_addr mcastaddr;
883 ip_addr_t *dst_addr = ipaddr;
884
885 LWIP_ASSERT("netif != NULL", netif != NULL);
886 LWIP_ASSERT("q != NULL", q != NULL);
887 LWIP_ASSERT("ipaddr != NULL", ipaddr != NULL);
888
889 /* make room for Ethernet header - should not fail */
890 if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
891 /* bail out */
893 ("etharp_output: could not allocate room for header.\n"));
894 LINK_STATS_INC(link.lenerr);
895 return ERR_BUF;
896 }
897
898 /* Determine on destination hardware address. Broadcasts and multicasts
899 * are special, other IP addresses are looked up in the ARP table. */
900
901 /* broadcast destination IP address? */
902 if (ip_addr_isbroadcast(ipaddr, netif)) {
903 /* broadcast on Ethernet also */
904 dest = (struct eth_addr *)&ethbroadcast;
905 /* multicast destination IP address? */
906 } else if (ip_addr_ismulticast(ipaddr)) {
907 /* Hash IP multicast address to MAC address.*/
908 mcastaddr.addr[0] = LL_MULTICAST_ADDR_0;
909 mcastaddr.addr[1] = LL_MULTICAST_ADDR_1;
910 mcastaddr.addr[2] = LL_MULTICAST_ADDR_2;
911 mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
912 mcastaddr.addr[4] = ip4_addr3(ipaddr);
913 mcastaddr.addr[5] = ip4_addr4(ipaddr);
914 /* destination Ethernet address is multicast */
915 dest = &mcastaddr;
916 /* unicast destination IP address? */
917 } else {
918 s8_t i;
919 /* outside local network? if so, this can neither be a global broadcast nor
920 a subnet broadcast. */
921 if (!ip_addr_netcmp(ipaddr, &(netif->ip_addr), &(netif->netmask)) &&
922 !ip_addr_islinklocal(ipaddr)) {
923#if LWIP_AUTOIP
924 struct ip_hdr *iphdr = (struct ip_hdr*)((u8_t*)q->payload +
925 sizeof(struct eth_hdr));
926 /* According to RFC 3297, chapter 2.6.2 (Forwarding Rules), a packet with
927 a link-local source address must always be "directly to its destination
928 on the same physical link. The host MUST NOT send the packet to any
929 router for forwarding". */
930 if (!ip_addr_islinklocal(&iphdr->src))
931#endif /* LWIP_AUTOIP */
932 {
933 /* interface has default gateway? */
934 if (!ip_addr_isany(&netif->gw)) {
935 /* send to hardware address of default gateway IP address */
936 dst_addr = &(netif->gw);
937 /* no default gateway available */
938 } else {
939 /* no route to destination error (default gateway missing) */
940 return ERR_RTE;
941 }
942 }
943 }
944#if LWIP_NETIF_HWADDRHINT
945 if (netif->addr_hint != NULL) {
946 /* per-pcb cached entry was given */
947 u8_t etharp_cached_entry = *(netif->addr_hint);
948 if (etharp_cached_entry < ARP_TABLE_SIZE) {
949#endif /* LWIP_NETIF_HWADDRHINT */
950 if ((arp_table[etharp_cached_entry].state >= ETHARP_STATE_STABLE) &&
951 (ip_addr_cmp(dst_addr, &arp_table[etharp_cached_entry].ipaddr))) {
952 /* the per-pcb-cached entry is stable and the right one! */
953 ETHARP_STATS_INC(etharp.cachehit);
954 return etharp_output_to_arp_index(netif, q, etharp_cached_entry);
955 }
956#if LWIP_NETIF_HWADDRHINT
957 }
958 }
959#endif /* LWIP_NETIF_HWADDRHINT */
960
961 /* find stable entry: do this here since this is a critical path for
962 throughput and etharp_find_entry() is kind of slow */
963 for (i = 0; i < ARP_TABLE_SIZE; i++) {
964 if ((arp_table[i].state >= ETHARP_STATE_STABLE) &&
965 (ip_addr_cmp(dst_addr, &arp_table[i].ipaddr))) {
966 /* found an existing, stable entry */
967 ETHARP_SET_HINT(netif, i);
968 return etharp_output_to_arp_index(netif, q, i);
969 }
970 }
971 /* no stable entry found, use the (slower) query function:
972 queue on destination Ethernet address belonging to ipaddr */
973 return etharp_query(netif, dst_addr, q);
974 }
975
976 /* continuation for multicast/broadcast destinations */
977 /* obtain source Ethernet address of the given interface */
978 /* send packet directly on the link */
979 return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr), dest);
980}
981
1015err_t
1016etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q)
1017{
1018 struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr;
1020 s8_t i; /* ARP entry index */
1021
1022 /* non-unicast address? */
1023 if (ip_addr_isbroadcast(ipaddr, netif) ||
1024 ip_addr_ismulticast(ipaddr) ||
1025 ip_addr_isany(ipaddr)) {
1026 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n"));
1027 return ERR_ARG;
1028 }
1029
1030 /* find entry in ARP cache, ask to create entry if queueing packet */
1031 i = etharp_find_entry(ipaddr, ETHARP_FLAG_TRY_HARD);
1032
1033 /* could not find or create entry? */
1034 if (i < 0) {
1035 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not create ARP entry\n"));
1036 if (q) {
1037 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: packet dropped\n"));
1038 ETHARP_STATS_INC(etharp.memerr);
1039 }
1040 return (err_t)i;
1041 }
1042
1043 /* mark a fresh entry as pending (we just sent a request) */
1044 if (arp_table[i].state == ETHARP_STATE_EMPTY) {
1045 arp_table[i].state = ETHARP_STATE_PENDING;
1046 }
1047
1048 /* { i is either a STABLE or (new or existing) PENDING entry } */
1049 LWIP_ASSERT("arp_table[i].state == PENDING or STABLE",
1050 ((arp_table[i].state == ETHARP_STATE_PENDING) ||
1051 (arp_table[i].state >= ETHARP_STATE_STABLE)));
1052
1053 /* do we have a pending entry? or an implicit query request? */
1054 if ((arp_table[i].state == ETHARP_STATE_PENDING) || (q == NULL)) {
1055 /* try to resolve it; send out ARP request */
1056 result = etharp_request(netif, ipaddr);
1057 if (result != ERR_OK) {
1058 /* ARP request couldn't be sent */
1059 /* We don't re-send arp request in etharp_tmr, but we still queue packets,
1060 since this failure could be temporary, and the next packet calling
1061 etharp_query again could lead to sending the queued packets. */
1062 }
1063 if (q == NULL) {
1064 return result;
1065 }
1066 }
1067
1068 /* packet given? */
1069 LWIP_ASSERT("q != NULL", q != NULL);
1070 /* stable entry? */
1071 if (arp_table[i].state >= ETHARP_STATE_STABLE) {
1072 /* we have a valid IP->Ethernet address mapping */
1073 ETHARP_SET_HINT(netif, i);
1074 /* send the packet */
1075 result = etharp_send_ip(netif, q, srcaddr, &(arp_table[i].ethaddr));
1076 /* pending entry? (either just created or already pending */
1077 } else if (arp_table[i].state == ETHARP_STATE_PENDING) {
1078 /* entry is still pending, queue the given packet 'q' */
1079 struct pbuf *p;
1080 int copy_needed = 0;
1081 /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but
1082 * to copy the whole queue into a new PBUF_RAM (see bug #11400)
1083 * PBUF_ROMs can be left as they are, since ROM must not get changed. */
1084 p = q;
1085 while (p) {
1086 LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == 0));
1087 if(p->type != PBUF_ROM) {
1088 copy_needed = 1;
1089 break;
1090 }
1091 p = p->next;
1092 }
1093 if(copy_needed) {
1094 /* copy the whole packet into new pbufs */
1095 p = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
1096 if(p != NULL) {
1097 if (pbuf_copy(p, q) != ERR_OK) {
1098 pbuf_free(p);
1099 p = NULL;
1100 }
1101 }
1102 } else {
1103 /* referencing the old pbuf is enough */
1104 p = q;
1105 pbuf_ref(p);
1106 }
1107 /* packet could be taken over? */
1108 if (p != NULL) {
1109 /* queue packet ... */
1110#if ARP_QUEUEING
1111 struct etharp_q_entry *new_entry;
1112 /* allocate a new arp queue entry */
1113 new_entry = (struct etharp_q_entry *)memp_malloc(MEMP_ARP_QUEUE);
1114 if (new_entry != NULL) {
1115 new_entry->next = 0;
1116 new_entry->p = p;
1117 if(arp_table[i].q != NULL) {
1118 /* queue was already existent, append the new entry to the end */
1119 struct etharp_q_entry *r;
1120 r = arp_table[i].q;
1121 while (r->next != NULL) {
1122 r = r->next;
1123 }
1124 r->next = new_entry;
1125 } else {
1126 /* queue did not exist, first item in queue */
1127 arp_table[i].q = new_entry;
1128 }
1129 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
1130 result = ERR_OK;
1131 } else {
1132 /* the pool MEMP_ARP_QUEUE is empty */
1133 pbuf_free(p);
1134 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));
1135 result = ERR_MEM;
1136 }
1137#else /* ARP_QUEUEING */
1138 /* always queue one packet per ARP request only, freeing a previously queued packet */
1139 if (arp_table[i].q != NULL) {
1140 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));
1141 pbuf_free(arp_table[i].q);
1142 }
1143 arp_table[i].q = p;
1144 result = ERR_OK;
1145 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
1146#endif /* ARP_QUEUEING */
1147 } else {
1148 ETHARP_STATS_INC(etharp.memerr);
1149 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));
1150 result = ERR_MEM;
1151 }
1152 }
1153 return result;
1154}
1155
1171#if !LWIP_AUTOIP
1172static
1173#endif /* LWIP_AUTOIP */
1174err_t
1175etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
1176 const struct eth_addr *ethdst_addr,
1177 const struct eth_addr *hwsrc_addr, const ip_addr_t *ipsrc_addr,
1178 const struct eth_addr *hwdst_addr, const ip_addr_t *ipdst_addr,
1179 const u16_t opcode)
1180{
1181 struct pbuf *p;
1183 struct eth_hdr *ethhdr;
1184 struct etharp_hdr *hdr;
1185#if LWIP_AUTOIP
1186 const u8_t * ethdst_hwaddr;
1187#endif /* LWIP_AUTOIP */
1188
1189 LWIP_ASSERT("netif != NULL", netif != NULL);
1190
1191 /* allocate a pbuf for the outgoing ARP request packet */
1192 p = pbuf_alloc(PBUF_RAW, SIZEOF_ETHARP_PACKET, PBUF_RAM);
1193 /* could allocate a pbuf for an ARP request? */
1194 if (p == NULL) {
1196 ("etharp_raw: could not allocate pbuf for ARP request.\n"));
1197 ETHARP_STATS_INC(etharp.memerr);
1198 return ERR_MEM;
1199 }
1200 LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr",
1201 (p->len >= SIZEOF_ETHARP_PACKET));
1202
1203 ethhdr = (struct eth_hdr *)p->payload;
1204 hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
1205 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n"));
1206 hdr->opcode = htons(opcode);
1207
1208 LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",
1209 (netif->hwaddr_len == ETHARP_HWADDR_LEN));
1210#if LWIP_AUTOIP
1211 /* If we are using Link-Local, all ARP packets that contain a Link-Local
1212 * 'sender IP address' MUST be sent using link-layer broadcast instead of
1213 * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */
1214 ethdst_hwaddr = ip_addr_islinklocal(ipsrc_addr) ? (u8_t*)(ethbroadcast.addr) : ethdst_addr->addr;
1215#endif /* LWIP_AUTOIP */
1216 /* Write the ARP MAC-Addresses */
1217 ETHADDR16_COPY(&hdr->shwaddr, hwsrc_addr);
1218 ETHADDR16_COPY(&hdr->dhwaddr, hwdst_addr);
1219 /* Write the Ethernet MAC-Addresses */
1220#if LWIP_AUTOIP
1221 ETHADDR16_COPY(&ethhdr->dest, ethdst_hwaddr);
1222#else /* LWIP_AUTOIP */
1223 ETHADDR16_COPY(&ethhdr->dest, ethdst_addr);
1224#endif /* LWIP_AUTOIP */
1225 ETHADDR16_COPY(&ethhdr->src, ethsrc_addr);
1226 /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
1227 * structure packing. */
1228 IPADDR2_COPY(&hdr->sipaddr, ipsrc_addr);
1229 IPADDR2_COPY(&hdr->dipaddr, ipdst_addr);
1230
1231 hdr->hwtype = PP_HTONS(HWTYPE_ETHERNET);
1232 hdr->proto = PP_HTONS(ETHTYPE_IP);
1233 /* set hwlen and protolen */
1234 hdr->hwlen = ETHARP_HWADDR_LEN;
1235 hdr->protolen = sizeof(ip_addr_t);
1236
1237 ethhdr->type = PP_HTONS(ETHTYPE_ARP);
1238 /* send ARP query */
1240 ETHARP_STATS_INC(etharp.xmit);
1241 /* free ARP query packet */
1242 pbuf_free(p);
1243 p = NULL;
1244 /* could not allocate pbuf for ARP request */
1245
1246 return result;
1247}
1248
1258err_t
1259etharp_request(struct netif *netif, ip_addr_t *ipaddr)
1260{
1261 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_request: sending ARP request.\n"));
1262 return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, &ethbroadcast,
1263 (struct eth_addr *)netif->hwaddr, &netif->ip_addr, &ethzero,
1264 ipaddr, ARP_REQUEST);
1265}
1266#endif /* LWIP_ARP */
1267
1276err_t
1277ethernet_input(struct pbuf *p, struct netif *netif)
1278{
1279 struct eth_hdr* ethhdr;
1280 u16_t type;
1281#if LWIP_ARP || ETHARP_SUPPORT_VLAN
1282 s16_t ip_hdr_offset = SIZEOF_ETH_HDR;
1283#endif /* LWIP_ARP || ETHARP_SUPPORT_VLAN */
1284
1285 if (p->len <= SIZEOF_ETH_HDR) {
1286 /* a packet with only an ethernet header (or less) is not valid for us */
1287 ETHARP_STATS_INC(etharp.proterr);
1288 ETHARP_STATS_INC(etharp.drop);
1289 goto free_and_return;
1290 }
1291
1292 /* points to packet payload, which starts with an Ethernet header */
1293 ethhdr = (struct eth_hdr *)p->payload;
1295 ("ethernet_input: dest:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", src:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", type:%"X16_F"\n",
1296 (unsigned)ethhdr->dest.addr[0], (unsigned)ethhdr->dest.addr[1], (unsigned)ethhdr->dest.addr[2],
1297 (unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], (unsigned)ethhdr->dest.addr[5],
1298 (unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], (unsigned)ethhdr->src.addr[2],
1299 (unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5],
1300 (unsigned)htons(ethhdr->type)));
1301
1302 type = ethhdr->type;
1303#if ETHARP_SUPPORT_VLAN
1304 if (type == PP_HTONS(ETHTYPE_VLAN)) {
1305 struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr*)(((char*)ethhdr) + SIZEOF_ETH_HDR);
1306 if (p->len <= SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) {
1307 /* a packet with only an ethernet/vlan header (or less) is not valid for us */
1308 ETHARP_STATS_INC(etharp.proterr);
1309 ETHARP_STATS_INC(etharp.drop);
1310 goto free_and_return;
1311 }
1312#if defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) /* if not, allow all VLANs */
1313#ifdef ETHARP_VLAN_CHECK_FN
1314 if (!ETHARP_VLAN_CHECK_FN(ethhdr, vlan)) {
1315#elif defined(ETHARP_VLAN_CHECK)
1316 if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) {
1317#endif
1318 /* silently ignore this packet: not for our VLAN */
1319 pbuf_free(p);
1320 return ERR_OK;
1321 }
1322#endif /* defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) */
1323 type = vlan->tpid;
1324 ip_hdr_offset = SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR;
1325 }
1326#endif /* ETHARP_SUPPORT_VLAN */
1327
1328#if LWIP_ARP_FILTER_NETIF
1329 netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, htons(type));
1330#endif /* LWIP_ARP_FILTER_NETIF*/
1331
1332 if (ethhdr->dest.addr[0] & 1) {
1333 /* this might be a multicast or broadcast packet */
1334 if (ethhdr->dest.addr[0] == LL_MULTICAST_ADDR_0) {
1335 if ((ethhdr->dest.addr[1] == LL_MULTICAST_ADDR_1) &&
1336 (ethhdr->dest.addr[2] == LL_MULTICAST_ADDR_2)) {
1337 /* mark the pbuf as link-layer multicast */
1338 p->flags |= PBUF_FLAG_LLMCAST;
1339 }
1340 } else if (eth_addr_cmp(&ethhdr->dest, &ethbroadcast)) {
1341 /* mark the pbuf as link-layer broadcast */
1342 p->flags |= PBUF_FLAG_LLBCAST;
1343 }
1344 }
1345
1346 switch (type) {
1347#if LWIP_ARP
1348 /* IP packet? */
1349 case PP_HTONS(ETHTYPE_IP):
1351 goto free_and_return;
1352 }
1353#if ETHARP_TRUST_IP_MAC
1354 /* update ARP table */
1355 etharp_ip_input(netif, p);
1356#endif /* ETHARP_TRUST_IP_MAC */
1357 /* skip Ethernet header */
1358 if(pbuf_header(p, -ip_hdr_offset)) {
1359 LWIP_ASSERT("Can't move over header in packet", 0);
1360 goto free_and_return;
1361 } else {
1362 /* pass to IP layer */
1363 ip_input(p, netif);
1364 }
1365 break;
1366
1367 case PP_HTONS(ETHTYPE_ARP):
1369 goto free_and_return;
1370 }
1371 /* pass p to ARP module */
1372 etharp_arp_input(netif, (struct eth_addr*)(netif->hwaddr), p);
1373 break;
1374#endif /* LWIP_ARP */
1375#if PPPOE_SUPPORT
1376 case PP_HTONS(ETHTYPE_PPPOEDISC): /* PPP Over Ethernet Discovery Stage */
1377 pppoe_disc_input(netif, p);
1378 break;
1379
1380 case PP_HTONS(ETHTYPE_PPPOE): /* PPP Over Ethernet Session Stage */
1381 pppoe_data_input(netif, p);
1382 break;
1383#endif /* PPPOE_SUPPORT */
1384
1385 default:
1386 ETHARP_STATS_INC(etharp.proterr);
1387 ETHARP_STATS_INC(etharp.drop);
1388 goto free_and_return;
1389 }
1390
1391 /* This means the pbuf is freed or consumed,
1392 so the caller doesn't have to free it again */
1393 return ERR_OK;
1394
1395free_and_return:
1396 pbuf_free(p);
1397 return ERR_OK;
1398}
1399#endif /* LWIP_ARP || LWIP_ETHERNET */
static int state
Definition: maze.c:121
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:73
#define X8_F
Definition: arch.h:52
const WCHAR * link
Definition: db.cpp:997
#define PP_HTONS(x)
Definition: def.h:88
#define NULL
Definition: types.h:112
static const WCHAR empty[]
Definition: main.c:47
#define X16_F
Definition: cc.h:38
signed short s16_t
Definition: cc.h:29
#define U16_F
Definition: cc.h:36
#define S16_F
Definition: cc.h:37
signed char s8_t
Definition: cc.h:28
unsigned char u8_t
Definition: cc.h:23
unsigned short u16_t
Definition: cc.h:24
#define LWIP_DBG_LEVEL_SERIOUS
Definition: debug.h:47
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:95
#define LWIP_DBG_LEVEL_WARNING
Definition: debug.h:46
#define LWIP_ERROR(message, expression, handler)
Definition: debug.h:74
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:66
#define LWIP_DBG_TRACE
Definition: debug.h:57
#define ERR_MEM
Definition: err.h:53
#define ERR_ARG
Definition: err.h:70
#define ERR_OK
Definition: err.h:52
#define ERR_RTE
Definition: err.h:56
#define ERR_BUF
Definition: err.h:54
s8_t err_t
Definition: err.h:47
#define snmp_delete_arpidx_tree(ni, ip)
Definition: snmp.h:258
#define snmp_insert_arpidx_tree(ni, ip)
Definition: snmp.h:257
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
GLenum src
Definition: glext.h:6340
GLenum GLenum dst
Definition: glext.h:6340
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
char hdr[14]
Definition: iptest.cpp:33
#define ip_addr_cmp(addr1, addr2)
Definition: ip_addr.h:198
#define ip_addr_isany(addr1)
Definition: ip_addr.h:200
#define ip4_addr1_16(ipaddr)
Definition: ip_addr.h:226
#define ip_addr_ismulticast(addr1)
Definition: ip_addr.h:208
#define ip_addr_netcmp(addr1, addr2, mask)
Definition: ip_addr.h:194
#define ip4_addr2_16(ipaddr)
Definition: ip_addr.h:227
#define ip_addr_islinklocal(addr1)
Definition: ip_addr.h:210
#define ip_addr_copy(dest, src)
Definition: ip_addr.h:162
#define ip4_addr4(ipaddr)
Definition: ip_addr.h:223
typedefPACK_STRUCT_END struct ip_addr ip_addr_t
Definition: ip_addr.h:64
#define ip_addr_isbroadcast(ipaddr, netif)
Definition: ip_addr.h:202
#define ip4_addr3_16(ipaddr)
Definition: ip_addr.h:228
#define ip_addr_set_zero(ipaddr)
Definition: ip_addr.h:168
#define IPADDR2_COPY(dest, src)
Definition: ip_addr.h:158
#define ip4_addr4_16(ipaddr)
Definition: ip_addr.h:229
#define ip4_addr3(ipaddr)
Definition: ip_addr.h:222
#define ip4_addr2(ipaddr)
Definition: ip_addr.h:221
if(dx< 0)
Definition: linetemp.h:194
err_t ip_input(struct pbuf *p, struct netif *inp)
Definition: ip.c:305
struct netif * ip_route(ip_addr_t *dest)
Definition: ip.c:124
void * memp_malloc(memp_t type)
Definition: memp.c:390
void memp_free(memp_t type, void *mem)
Definition: memp.c:435
__u16 ctime
Definition: mkdosfs.c:4
#define htons(x)
Definition: module.h:215
static char * dest
Definition: rtl.c:135
#define NETIF_FLAG_ETHARP
Definition: netif.h:88
@ ARP_REQUEST
Definition: netiodef.h:772
#define ETHARP_SUPPORT_STATIC_ENTRIES
Definition: opt.h:493
#define ARP_TABLE_SIZE
Definition: opt.h:433
#define ETHARP_DEBUG
Definition: opt.h:1898
u8_t pbuf_header(struct pbuf *p, s16_t header_size_increment)
Definition: pbuf.c:511
void pbuf_ref(struct pbuf *p)
Definition: pbuf.c:723
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
Definition: pbuf.c:207
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:618
err_t pbuf_copy(struct pbuf *p_to, struct pbuf *p_from)
Definition: pbuf.c:852
#define PBUF_FLAG_LLBCAST
Definition: pbuf.h:73
@ PBUF_ROM
Definition: pbuf.h:59
@ PBUF_RAM
Definition: pbuf.h:58
#define PBUF_FLAG_LLMCAST
Definition: pbuf.h:75
@ PBUF_RAW
Definition: pbuf.h:54
#define LINK_STATS_INC(x)
Definition: stats.h:227
#define ETHARP_STATS_INC(x)
Definition: stats.h:219
Definition: ip.h:116
Definition: netif.h:136
ip_addr_t gw
Definition: netif.h:143
ip_addr_t netmask
Definition: netif.h:142
ip_addr_t ip_addr
Definition: netif.h:141
u8_t hwaddr[NETIF_MAX_HWADDR_LEN]
Definition: netif.h:190
netif_linkoutput_fn linkoutput
Definition: netif.h:155
u8_t hwaddr_len
Definition: netif.h:188
Definition: pbuf.h:79