3 * Address Resolution Protocol module for IP over Ethernet
5 * Functionally, ARP is divided into two parts. The first maps an IP address
6 * to a physical address when sending a packet, and the second part answers
7 * requests from other machines for our physical address.
9 * This implementation complies with RFC 826 (Ethernet ARP) and supports
10 * Gratuitious ARP from RFC3220 (IP Mobility Support for IPv4) section 4.6.
14 * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
15 * Copyright (c) 2003-2004 Leon Woestenberg <leon.woestenberg@axon.tv>
16 * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands.
17 * All rights reserved.
19 * Redistribution and use in source and binary forms, with or without modification,
20 * are permitted provided that the following conditions are met:
22 * 1. Redistributions of source code must retain the above copyright notice,
23 * this list of conditions and the following disclaimer.
24 * 2. Redistributions in binary form must reproduce the above copyright notice,
25 * this list of conditions and the following disclaimer in the documentation
26 * and/or other materials provided with the distribution.
27 * 3. The name of the author may not be used to endorse or promote products
28 * derived from this software without specific prior written permission.
30 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
31 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
32 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
33 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
34 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
35 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
38 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
41 * This file is part of the lwIP TCP/IP stack.
43 * Author: Adam Dunkels <adam@sics.se>
49 * - pbufs should be sent from the queue once an ARP entry state
50 * goes from PENDING to STABLE.
51 * - Non-PENDING entries MUST NOT have queued packets.
57 RFC 3220 4.6 IP Mobility Support for IPv4 January 2002
59 - A Gratuitous ARP [45] is an ARP packet sent by a node in order
60 to spontaneously cause other nodes to update an entry in their
61 ARP cache. A gratuitous ARP MAY use either an ARP Request or
62 an ARP Reply packet. In either case, the ARP Sender Protocol
63 Address and ARP Target Protocol Address are both set to the IP
64 address of the cache entry to be updated, and the ARP Sender
65 Hardware Address is set to the link-layer address to which this
66 cache entry should be updated. When using an ARP Reply packet,
67 the Target Hardware Address is also set to the link-layer
68 address to which this cache entry should be updated (this field
69 is not used in an ARP Request packet).
71 In either case, for a gratuitous ARP, the ARP packet MUST be
72 transmitted as a local broadcast packet on the local link. As
73 specified in [36], any node receiving any ARP packet (Request
74 or Reply) MUST update its local ARP cache with the Sender
75 Protocol and Hardware Addresses in the ARP packet, if the
76 receiving node has an entry for that IP address already in its
77 ARP cache. This requirement in the ARP protocol applies even
78 for ARP Request packets, and for ARP Reply packets that do not
79 match any ARP Request transmitted by the receiving node [36].
81 My suggestion would be to send a ARP request for our newly obtained
82 address upon configuration of an Ethernet interface.
87 #include "lwip/inet.h"
88 #include "netif/etharp.h"
90 #include "lwip/stats.h"
92 /* ARP needs to inform DHCP of any ARP replies? */
93 #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
94 # include "lwip/dhcp.h"
97 /* allows new queueing code to be disabled (0) for regression testing */
98 #define ARP_NEW_QUEUE 1
100 /** the time an ARP entry stays valid after its last update, (120 * 10) seconds = 20 minutes. */
101 #define ARP_MAXAGE 120
102 /** the time an ARP entry stays pending after first request, (1 * 10) seconds = 10 seconds. */
103 #define ARP_MAXPENDING 1
105 #define HWTYPE_ETHERNET 1
107 /** ARP message types */
108 #define ARP_REQUEST 1
111 #define ARPH_HWLEN(hdr) (ntohs((hdr)->_hwlen_protolen) >> 8)
112 #define ARPH_PROTOLEN(hdr) (ntohs((hdr)->_hwlen_protolen) & 0xff)
114 #define ARPH_HWLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons(ARPH_PROTOLEN(hdr) | ((len) << 8))
115 #define ARPH_PROTOLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons((len) | (ARPH_HWLEN(hdr) << 8))
119 ETHARP_STATE_PENDING,
121 /** @internal convenience transitional state used in etharp_tmr() */
125 struct etharp_entry {
126 struct ip_addr ipaddr;
127 struct eth_addr ethaddr;
128 enum etharp_state state;
131 * Pointer to queue of pending outgoing packets on this ARP entry.
132 * Must be at most a single packet for now. */
138 static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
139 static struct etharp_entry arp_table[ARP_TABLE_SIZE];
141 static s8_t find_arp_entry(void);
142 /** ask update_arp_entry() to add instead of merely update an ARP entry */
143 #define ARP_INSERT_FLAG 1
144 static struct pbuf *update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags);
146 * Initializes ARP module.
152 /* clear ARP entries */
153 for(i = 0; i < ARP_TABLE_SIZE; ++i) {
154 arp_table[i].state = ETHARP_STATE_EMPTY;
156 arp_table[i].p = NULL;
158 arp_table[i].ctime = 0;
163 * Clears expired entries in the ARP table.
165 * This function should be called every ETHARP_TMR_INTERVAL microseconds (10 seconds),
166 * in order to expire entries in the ARP table.
173 LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n"));
174 /* remove expired entries from the ARP table */
175 for (i = 0; i < ARP_TABLE_SIZE; ++i) {
176 arp_table[i].ctime++;
177 /* a resolved/stable entry? */
178 if ((arp_table[i].state == ETHARP_STATE_STABLE) &&
179 /* entry has become old? */
180 (arp_table[i].ctime >= ARP_MAXAGE)) {
181 LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired stable entry %u.\n", i));
182 arp_table[i].state = ETHARP_STATE_EXPIRED;
183 /* an unresolved/pending entry? */
184 } else if ((arp_table[i].state == ETHARP_STATE_PENDING) &&
185 /* entry unresolved/pending for too long? */
186 (arp_table[i].ctime >= ARP_MAXPENDING)) {
187 LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %u.\n", i));
188 arp_table[i].state = ETHARP_STATE_EXPIRED;
190 /* clean up entries that have just been expired */
191 if (arp_table[i].state == ETHARP_STATE_EXPIRED) {
193 /* and empty packet queue */
194 if (arp_table[i].p != NULL) {
195 /* remove all queued packets */
196 LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing entry %u, packet queue %p.\n", i, (void *)(arp_table[i].p)));
197 pbuf_free(arp_table[i].p);
198 arp_table[i].p = NULL;
201 /* recycle entry for re-use */
202 arp_table[i].state = ETHARP_STATE_EMPTY;
208 * Return an empty ARP entry (possibly recycling the oldest stable entry).
210 * @return The ARP entry index that is available, ERR_MEM if no usable
220 /* search ARP table for an unused or old entry */
221 for (i = 0; i < ARP_TABLE_SIZE; ++i) {
223 if (arp_table[i].state == ETHARP_STATE_EMPTY) {
224 LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: returning empty entry %u\n", i));
227 } else if (arp_table[i].state == ETHARP_STATE_STABLE) {
228 /* remember entry with oldest stable entry in j */
229 if (arp_table[i].ctime >= maxtime) maxtime = arp_table[j = i].ctime;
232 /* no empty entry found? */
233 if (i == ARP_TABLE_SIZE) {
234 LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: found oldest stable entry %u\n", j));
235 /* fall-back to oldest stable */
238 /* no available entry found? */
239 if (i == ARP_TABLE_SIZE) {
240 LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: no replacable entry could be found\n"));
245 /* clean up the recycled stable entry */
246 if (arp_table[i].state == ETHARP_STATE_STABLE) {
248 /* and empty the packet queue */
249 if (arp_table[i].p != NULL) {
250 /* remove all queued packets */
251 LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: freeing entry %u, packet queue %p.\n", i, (void *)(arp_table[i].p)));
252 pbuf_free(arp_table[i].p);
253 arp_table[i].p = NULL;
256 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_arp_entry: recycling oldest stable entry %u\n", i));
257 arp_table[i].state = ETHARP_STATE_EMPTY;
259 LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: returning %u\n", i));
264 * Update (or insert) a IP/MAC address pair in the ARP cache.
266 * If a pending entry is resolved, any queued packets will be sent
269 * @param ipaddr IP address of the inserted ARP entry.
270 * @param ethaddr Ethernet address of the inserted ARP entry.
271 * @param flags Defines behaviour:
272 * - ARP_INSERT_FLAG Allows ARP to insert this as a new item. If not specified,
273 * only existing ARP entries will be updated.
275 * @return pbuf If non-NULL, a packet that was queued on a pending entry.
276 * You should sent it and must call pbuf_free() afterwards.
281 update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags)
284 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("update_arp_entry()\n"));
285 LWIP_ASSERT("netif->hwaddr_len != 0", netif->hwaddr_len != 0);
286 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: %u.%u.%u.%u - %02x:%02x:%02x:%02x:%02x:%02x\n",
287 ip4_addr1(ipaddr), ip4_addr2(ipaddr), ip4_addr3(ipaddr), ip4_addr4(ipaddr),
288 ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2],
289 ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5]));
290 /* do not update for 0.0.0.0 addresses */
291 if (ipaddr->addr == 0) {
292 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: will not add 0.0.0.0 to ARP cache\n"));
295 /* Walk through the ARP mapping table and try to find an entry to
296 update. If none is found, the IP -> MAC address mapping is
297 inserted in the ARP table. */
298 for (i = 0; i < ARP_TABLE_SIZE; ++i) {
299 /* Check if the source IP address of the incoming packet matches
300 the IP address in this ARP table entry. */
301 if (arp_table[i].state != ETHARP_STATE_EMPTY &&
302 ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
304 if (arp_table[i].state == ETHARP_STATE_PENDING) {
305 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: pending entry %u goes stable\n", i));
306 /* A pending entry was found, mark it stable */
307 arp_table[i].state = ETHARP_STATE_STABLE;
308 /* fall-through to next if */
310 /* stable entry? (possibly just marked to become stable) */
311 if (arp_table[i].state == ETHARP_STATE_STABLE) {
314 struct eth_hdr *ethhdr;
316 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: updating stable entry %u\n", i));
317 /* An old entry found, update this and return. */
318 for (k = 0; k < netif->hwaddr_len; ++k) {
319 arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
321 /* reset time stamp */
322 arp_table[i].ctime = 0;
323 /* this is where we will send out queued packets! */
325 while (arp_table[i].p != NULL) {
326 /* get the first packet on the queue (if any) */
328 /* remember (and reference) remainder of queue */
329 arp_table[i].p = pbuf_dequeue(p);
330 /* fill-in Ethernet header */
332 for (k = 0; k < netif->hwaddr_len; ++k) {
333 ethhdr->dest.addr[k] = ethaddr->addr[k];
334 ethhdr->src.addr[k] = netif->hwaddr[k];
336 ethhdr->type = htons(ETHTYPE_IP);
337 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: sending queued IP packet %p.\n", (void *)p));
338 /* send the queued IP packet */
339 netif->linkoutput(netif, p);
340 /* free the queued IP packet */
344 /* IP addresses should only occur once in the ARP entry, we are done */
348 } /* for all ARP entries */
350 /* no matching ARP entry was found */
351 LWIP_ASSERT("update_arp_entry: i == ARP_TABLE_SIZE", i == ARP_TABLE_SIZE);
353 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: IP address not yet in table\n"));
354 /* allowed to insert a new entry? */
355 if (flags & ARP_INSERT_FLAG)
357 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: adding entry to table\n"));
358 /* find an empty or old entry. */
359 i = find_arp_entry();
361 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: no available entry found\n"));
365 ip_addr_set(&arp_table[i].ipaddr, ipaddr);
366 /* set Ethernet hardware address */
367 for (k = 0; k < netif->hwaddr_len; ++k) {
368 arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
370 /* reset time-stamp */
371 arp_table[i].ctime = 0;
373 arp_table[i].state = ETHARP_STATE_STABLE;
374 /* no queued packet */
376 arp_table[i].p = NULL;
381 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: no matching stable entry to update\n"));
387 * Updates the ARP table using the given IP packet.
389 * Uses the incoming IP packet's source address to update the
390 * ARP cache for the local network. The function does not alter
391 * or free the packet. This function must be called before the
392 * packet p is passed to the IP layer.
394 * @param netif The lwIP network interface on which the IP packet pbuf arrived.
395 * @param pbuf The IP packet that arrived on netif.
402 etharp_ip_input(struct netif *netif, struct pbuf *p)
404 struct ethip_hdr *hdr;
406 /* Only insert an entry if the source IP address of the
407 incoming IP packet comes from a host on the local network. */
409 /* source is on local network? */
410 if (!ip_addr_maskcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask))) {
415 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n"));
416 /* update ARP table, ask to insert entry */
417 update_arp_entry(netif, &(hdr->ip.src), &(hdr->eth.src), ARP_INSERT_FLAG);
423 * Responds to ARP requests to us. Upon ARP replies to us, add entry to cache
424 * send out queued IP packets. Updates cache with snooped address pairs.
426 * Should be called for incoming ARP packets. The pbuf in the argument
427 * is freed by this function.
429 * @param netif The lwIP network interface on which the ARP packet pbuf arrived.
430 * @param pbuf The ARP packet that arrived on netif. Is freed by this function.
431 * @param ethaddr Ethernet address of netif.
438 etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
440 struct etharp_hdr *hdr;
441 /* these are aligned properly, whereas the ARP header fields might not be */
442 struct ip_addr sipaddr, dipaddr;
446 /* drop short ARP packets */
447 if (p->tot_len < sizeof(struct etharp_hdr)) {
448 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 1, ("etharp_arp_input: packet dropped, too short (%d/%d)\n", p->tot_len, sizeof(struct etharp_hdr)));
455 /* get aligned copies of addresses */
456 *(struct ip_addr2 *)&sipaddr = hdr->sipaddr;
457 *(struct ip_addr2 *)&dipaddr = hdr->dipaddr;
459 /* this interface is not configured? */
460 if (netif->ip_addr.addr == 0) {
463 /* ARP packet directed to us? */
464 for_us = ip_addr_cmp(&dipaddr, &(netif->ip_addr));
467 /* ARP message directed to us? */
469 /* add IP address in ARP cache; assume requester wants to talk to us.
470 * can result in directly sending the queued packets for this host. */
471 update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), ARP_INSERT_FLAG);
472 /* ARP message not directed to us? */
474 /* update the source IP address in the cache, if present */
475 update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), 0);
478 /* now act on the message itself */
479 switch (htons(hdr->opcode)) {
482 /* ARP request. If it asked for our address, we send out a
483 * reply. In any case, we time-stamp any existing ARP entry,
484 * and possiby send out an IP packet that was queued on it. */
486 LWIP_DEBUGF (ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP request\n"));
487 /* ARP request for our address? */
490 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: replying to ARP request for our IP address\n"));
491 /* re-use pbuf to send ARP reply */
492 hdr->opcode = htons(ARP_REPLY);
494 hdr->dipaddr = hdr->sipaddr;
495 hdr->sipaddr = *(struct ip_addr2 *)&netif->ip_addr;
497 for(i = 0; i < netif->hwaddr_len; ++i) {
498 hdr->dhwaddr.addr[i] = hdr->shwaddr.addr[i];
499 hdr->shwaddr.addr[i] = ethaddr->addr[i];
500 hdr->ethhdr.dest.addr[i] = hdr->dhwaddr.addr[i];
501 hdr->ethhdr.src.addr[i] = ethaddr->addr[i];
504 hdr->hwtype = htons(HWTYPE_ETHERNET);
505 ARPH_HWLEN_SET(hdr, netif->hwaddr_len);
507 hdr->proto = htons(ETHTYPE_IP);
508 ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
510 hdr->ethhdr.type = htons(ETHTYPE_ARP);
511 /* return ARP reply */
512 netif->linkoutput(netif, p);
513 /* we are not configured? */
514 } else if (netif->ip_addr.addr == 0) {
515 /* { for_us == 0 and netif->ip_addr.addr == 0 } */
516 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n"));
517 /* request was not directed to us */
519 /* { for_us == 0 and netif->ip_addr.addr != 0 } */
520 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: ARP request was not for us.\n"));
524 /* ARP reply. We insert or update the ARP table later. */
525 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n"));
526 #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
527 /* DHCP wants to know about ARP replies to our wanna-have-address */
528 if (for_us) dhcp_arp_reply(netif, &sipaddr);
532 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %d\n", htons(hdr->opcode)));
535 /* free ARP packet */
538 /* nothing to send, we did it! */
543 * Resolve and fill-in Ethernet address header for outgoing packet.
545 * If ARP has the Ethernet address in cache, the given packet is
546 * returned, ready to be sent.
548 * If ARP does not have the Ethernet address in cache the packet is
549 * queued (if enabled and space available) and a ARP request is sent.
550 * This ARP request is returned as a pbuf, which should be sent by
553 * A returned non-NULL packet should be sent by the caller.
555 * If ARP failed to allocate resources, NULL is returned.
557 * @param netif The lwIP network interface which the IP packet will be sent on.
558 * @param ipaddr The IP address of the packet destination.
559 * @param pbuf The pbuf(s) containing the IP packet to be sent.
561 * @return If non-NULL, a packet ready to be sent by caller.
565 etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
567 struct eth_addr *dest, *srcaddr, mcastaddr;
568 struct eth_hdr *ethhdr;
571 /* make room for Ethernet header */
572 if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
573 /* The pbuf_header() call shouldn't fail, and we'll just bail
575 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_output: could not allocate room for header.\n"));
576 LINK_STATS_INC(link.lenerr);
580 /* assume unresolved Ethernet address */
582 /* Construct Ethernet header. Start with looking up deciding which
583 MAC address to use as a destination address. Broadcasts and
584 multicasts are special, all other addresses are looked up in the
587 /* destination IP address is an IP broadcast address? */
588 if (ip_addr_isany(ipaddr) || ip_addr_isbroadcast(ipaddr, netif)) {
589 /* broadcast on Ethernet also */
590 dest = (struct eth_addr *)ðbroadcast;
592 /* destination IP address is an IP multicast address? */
593 else if (ip_addr_ismulticast(ipaddr)) {
594 /* Hash IP multicast address to MAC address. */
595 mcastaddr.addr[0] = 0x01;
596 mcastaddr.addr[1] = 0x00;
597 mcastaddr.addr[2] = 0x5e;
598 mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
599 mcastaddr.addr[4] = ip4_addr3(ipaddr);
600 mcastaddr.addr[5] = ip4_addr4(ipaddr);
601 /* destination Ethernet address is multicast */
604 /* destination IP address is an IP unicast address */
606 /* destination IP network address not on local network?
607 * IP layer wants us to forward to the default gateway */
608 if (!ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {
609 /* interface has default gateway? */
610 if (netif->gw.addr != 0)
612 /* route to default gateway IP address */
613 ipaddr = &(netif->gw);
615 /* no gateway available? */
618 /* IP destination address outside local network, but no gateway available */
619 /* { packet is discarded } */
624 /* Ethernet address for IP destination address is in ARP cache? */
625 for (i = 0; i < ARP_TABLE_SIZE; ++i) {
627 if (arp_table[i].state == ETHARP_STATE_STABLE &&
628 ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
629 dest = &arp_table[i].ethaddr;
633 /* could not find the destination Ethernet address in ARP cache? */
635 /* ARP query for the IP address, submit this IP packet for queueing */
636 /* TODO: How do we handle netif->ipaddr == ipaddr? */
637 etharp_query(netif, ipaddr, q);
638 /* { packet was queued (ERR_OK), or discarded } */
642 /* destination Ethernet address resolved from ARP cache */
649 /* destination Ethernet address known */
651 /* obtain source Ethernet address of the given interface */
652 srcaddr = (struct eth_addr *)netif->hwaddr;
654 /* A valid IP->MAC address mapping was found, fill in the
655 * Ethernet header for the outgoing packet */
658 for(i = 0; i < netif->hwaddr_len; i++) {
659 ethhdr->dest.addr[i] = dest->addr[i];
660 ethhdr->src.addr[i] = srcaddr->addr[i];
663 ethhdr->type = htons(ETHTYPE_IP);
664 /* return the outgoing packet */
667 /* never reached; here for safety */
672 * Send an ARP request for the given IP address.
674 * Sends an ARP request for the given IP address, unless
675 * a request for this address is already pending. Optionally
676 * queues an outgoing packet on the resulting ARP entry.
678 * @param netif The lwIP network interface where ipaddr
679 * must be queried for.
680 * @param ipaddr The IP address to be resolved.
681 * @param q If non-NULL, a pbuf that must be queued on the
682 * ARP entry for the ipaddr IP address.
686 * @note Might be used in the future by manual IP configuration
689 * TODO: use the ctime field to see how long ago an ARP request was sent,
692 err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
694 struct eth_addr *srcaddr;
695 struct etharp_hdr *hdr;
696 err_t result = ERR_OK;
698 u8_t perform_arp_request = 1;
699 /* prevent 'unused argument' warning if ARP_QUEUEING == 0 */
701 srcaddr = (struct eth_addr *)netif->hwaddr;
702 /* bail out if this IP address is pending */
703 for (i = 0; i < ARP_TABLE_SIZE; ++i) {
704 if (arp_table[i].state != ETHARP_STATE_EMPTY &&
705 ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
706 if (arp_table[i].state == ETHARP_STATE_PENDING) {
707 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: requested IP already pending as entry %u\n", i));
708 /* break out of for-loop, user may wish to queue a packet on a pending entry */
709 /* TODO: we will issue a new ARP request, which should not occur too often */
710 /* we might want to run a faster timer on ARP to limit this */
713 else if (arp_table[i].state == ETHARP_STATE_STABLE) {
714 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: requested IP already stable as entry %u\n", i));
715 /* User wishes to queue a packet on a stable entry (or does she want to send
716 * out the packet immediately, we will not know), so we force an ARP request.
717 * Upon response we will send out the queued packet in etharp_update().
719 * Alternatively, we could accept the stable entry, and just send out the packet
720 * immediately. I chose to implement the former approach.
722 perform_arp_request = (q?1:0);
727 /* queried address not yet in ARP table? */
728 if (i == ARP_TABLE_SIZE) {
729 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: IP address not found in ARP table\n"));
730 /* find an available (unused or old) entry */
731 i = find_arp_entry();
732 /* bail out if no ARP entries are available */
734 LWIP_DEBUGF(ETHARP_DEBUG | 2, ("etharp_query: no more ARP entries available. Should seldom occur.\n"));
737 /* i is available, create ARP entry */
738 arp_table[i].state = ETHARP_STATE_PENDING;
739 ip_addr_set(&arp_table[i].ipaddr, ipaddr);
741 /* { i is now valid } */
742 #if ARP_QUEUEING /* queue packet (even on a stable entry, see above) */
743 /* copy any PBUF_REF referenced payloads into PBUF_RAM */
745 pbuf_queue(arp_table[i].p, q);
748 if (perform_arp_request)
751 /* allocate a pbuf for the outgoing ARP request packet */
752 p = pbuf_alloc(PBUF_LINK, sizeof(struct etharp_hdr), PBUF_RAM);
753 /* could allocate pbuf? */
756 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: sending ARP request.\n"));
758 hdr->opcode = htons(ARP_REQUEST);
759 for (j = 0; j < netif->hwaddr_len; ++j)
761 hdr->shwaddr.addr[j] = srcaddr->addr[j];
762 /* the hardware address is what we ask for, in
763 * a request it is a don't-care, we use 0's */
764 hdr->dhwaddr.addr[j] = 0x00;
766 hdr->dipaddr = *(struct ip_addr2 *)ipaddr;
767 hdr->sipaddr = *(struct ip_addr2 *)&netif->ip_addr;
769 hdr->hwtype = htons(HWTYPE_ETHERNET);
770 ARPH_HWLEN_SET(hdr, netif->hwaddr_len);
772 hdr->proto = htons(ETHTYPE_IP);
773 ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
774 for (j = 0; j < netif->hwaddr_len; ++j)
776 hdr->ethhdr.dest.addr[j] = 0xff;
777 hdr->ethhdr.src.addr[j] = srcaddr->addr[j];
779 hdr->ethhdr.type = htons(ETHTYPE_ARP);
781 result = netif->linkoutput(netif, p);
782 /* free ARP query packet */
787 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_query: could not allocate pbuf for ARP request.\n"));