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 * All rights reserved.
17 * Redistribution and use in source and binary forms, with or without modification,
18 * are permitted provided that the following conditions are met:
20 * 1. Redistributions of source code must retain the above copyright notice,
21 * this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright notice,
23 * this list of conditions and the following disclaimer in the documentation
24 * and/or other materials provided with the distribution.
25 * 3. The name of the author may not be used to endorse or promote products
26 * derived from this software without specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
31 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
33 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
36 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
39 * This file is part of the lwIP TCP/IP stack.
41 * Author: Adam Dunkels <adam@sics.se>
48 RFC 3220 4.6 IP Mobility Support for IPv4 January 2002
50 - A Gratuitous ARP [45] is an ARP packet sent by a node in order
51 to spontaneously cause other nodes to update an entry in their
52 ARP cache. A gratuitous ARP MAY use either an ARP Request or
53 an ARP Reply packet. In either case, the ARP Sender Protocol
54 Address and ARP Target Protocol Address are both set to the IP
55 address of the cache entry to be updated, and the ARP Sender
56 Hardware Address is set to the link-layer address to which this
57 cache entry should be updated. When using an ARP Reply packet,
58 the Target Hardware Address is also set to the link-layer
59 address to which this cache entry should be updated (this field
60 is not used in an ARP Request packet).
62 In either case, for a gratuitous ARP, the ARP packet MUST be
63 transmitted as a local broadcast packet on the local link. As
64 specified in [36], any node receiving any ARP packet (Request
65 or Reply) MUST update its local ARP cache with the Sender
66 Protocol and Hardware Addresses in the ARP packet, if the
67 receiving node has an entry for that IP address already in its
68 ARP cache. This requirement in the ARP protocol applies even
69 for ARP Request packets, and for ARP Reply packets that do not
70 match any ARP Request transmitted by the receiving node [36].
72 My suggestion would be to send a ARP request for our newly obtained
73 address upon configuration of an Ethernet interface.
78 #include "lwip/inet.h"
79 #include "netif/etharp.h"
81 #include "lwip/stats.h"
83 /* ARP needs to inform DHCP of any ARP replies? */
84 #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
85 # include "lwip/dhcp.h"
88 /** the time an ARP entry stays valid after its last update, (120 * 10) seconds = 20 minutes. */
89 #define ARP_MAXAGE 120
90 /** the time an ARP entry stays pending after first request, (2 * 10) seconds = 20 seconds. */
91 #define ARP_MAXPENDING 2
93 #define HWTYPE_ETHERNET 1
95 /** ARP message types */
99 #define ARPH_HWLEN(hdr) (ntohs((hdr)->_hwlen_protolen) >> 8)
100 #define ARPH_PROTOLEN(hdr) (ntohs((hdr)->_hwlen_protolen) & 0xff)
102 #define ARPH_HWLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons(ARPH_PROTOLEN(hdr) | ((len) << 8))
103 #define ARPH_PROTOLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons((len) | (ARPH_HWLEN(hdr) << 8))
107 ETHARP_STATE_PENDING,
111 struct etharp_entry {
112 struct ip_addr ipaddr;
113 struct eth_addr ethaddr;
114 enum etharp_state state;
121 static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
122 static struct etharp_entry arp_table[ARP_TABLE_SIZE];
124 static struct pbuf *update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags);
125 #define ARP_INSERT_FLAG 1
128 * Initializes ARP module.
134 /* clear ARP entries */
135 for(i = 0; i < ARP_TABLE_SIZE; ++i) {
136 arp_table[i].state = ETHARP_STATE_EMPTY;
138 arp_table[i].p = NULL;
144 * Clears expired entries in the ARP table.
146 * This function should be called every ETHARP_TMR_INTERVAL microseconds (10 seconds),
147 * in order to expire entries in the ARP table.
154 LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n"));
155 /* remove expired entries from the ARP table */
156 for (i = 0; i < ARP_TABLE_SIZE; ++i) {
157 arp_table[i].ctime++;
158 if ((arp_table[i].state == ETHARP_STATE_STABLE) &&
159 (arp_table[i].ctime >= ARP_MAXAGE)) {
160 LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired stable entry %u.\n", i));
162 } else if ((arp_table[i].state == ETHARP_STATE_PENDING) &&
163 (arp_table[i].ctime >= ARP_MAXPENDING)) {
164 LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %u.\n", i));
166 arp_table[i].state = ETHARP_STATE_EMPTY;
168 if (arp_table[i].p != NULL) {
169 /* remove any queued packet */
170 LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing entry %u, packet queue %p.\n", i, (void *)(arp_table[i].p)));
171 pbuf_free(arp_table[i].p);
172 arp_table[i].p = NULL;
180 * Return an empty ARP entry or, if the table is full, ARP_TABLE_SIZE if all
181 * entries are pending, otherwise the oldest entry.
183 * @return The ARP entry index that is available, ARP_TABLE_SIZE if no usable
191 /* Try to find an unused entry in the ARP table. */
192 for (i = 0; i < ARP_TABLE_SIZE; ++i) {
193 if (arp_table[i].state == ETHARP_STATE_EMPTY) {
194 LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: found empty entry %u\n", i));
199 /* If no unused entry is found, we try to find the oldest entry and
200 throw it away. If all entries are new and have 0 ctime drop one */
201 if (i == ARP_TABLE_SIZE) {
204 for (i = 0; i < ARP_TABLE_SIZE; ++i) {
205 /* remember entry with oldest stable entry in j*/
206 if ((arp_table[i].state == ETHARP_STATE_STABLE) &&
207 #if ARP_QUEUEING /* do not want to re-use an entry with queued packets */
208 (arp_table[i].p == NULL) &&
210 (arp_table[i].ctime >= maxtime)) {
211 maxtime = arp_table[i].ctime;
215 if (j != ARP_TABLE_SIZE) {
216 LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: found oldest stable entry %u\n", j));
218 LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: no replacable entry could be found\n"));
222 LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: returning %u, state %u\n", i, arp_table[i].state));
227 * Update (or insert) a IP/MAC address pair in the ARP cache.
229 * @param ipaddr IP address of the inserted ARP entry.
230 * @param ethaddr Ethernet address of the inserted ARP entry.
231 * @param flags Defines behaviour:
232 * - ARP_INSERT_FLAG Allows ARP to insert this as a new item. If not specified,
233 * only existing ARP entries will be updated.
235 * @return pbuf If non-NULL, a packet that was queued on a pending entry.
236 * You should sent it and must call pbuf_free() afterwards.
241 update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags)
244 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("update_arp_entry()\n"));
245 LWIP_ASSERT("netif->hwaddr_len != 0", netif->hwaddr_len != 0);
246 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: %u.%u.%u.%u - %02x:%02x:%02x:%02x:%02x:%02x\n", ip4_addr1(ipaddr), ip4_addr2(ipaddr), ip4_addr3(ipaddr), ip4_addr4(ipaddr),
247 ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2], ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5]));
248 /* do not update for 0.0.0.0 addresses */
249 if (ipaddr->addr == 0) {
250 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: will not add 0.0.0.0 to ARP cache\n"));
253 /* Walk through the ARP mapping table and try to find an entry to
254 update. If none is found, the IP -> MAC address mapping is
255 inserted in the ARP table. */
256 for (i = 0; i < ARP_TABLE_SIZE; ++i) {
257 /* Check if the source IP address of the incoming packet matches
258 the IP address in this ARP table entry. */
259 if (ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
261 if (arp_table[i].state == ETHARP_STATE_PENDING) {
262 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: pending entry %u goes stable\n", i));
263 /* A pending entry was found, mark it stable */
264 arp_table[i].state = ETHARP_STATE_STABLE;
265 /* fall-through to next if */
267 /* stable entry? (possible just marked to become stable) */
268 if (arp_table[i].state == ETHARP_STATE_STABLE) {
271 struct eth_hdr *ethhdr;
273 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: updating stable entry %u\n", i));
274 /* An old entry found, update this and return. */
275 for (k = 0; k < netif->hwaddr_len; ++k) {
276 arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
278 /* reset time stamp */
279 arp_table[i].ctime = 0;
282 /* queued packet present? */
284 /* NULL attached buffer immediately */
285 arp_table[i].p = NULL;
286 /* fill-in Ethernet header */
288 for (k = 0; k < netif->hwaddr_len; ++k) {
289 ethhdr->dest.addr[k] = ethaddr->addr[k];
290 ethhdr->src.addr[k] = netif->hwaddr[k];
292 ethhdr->type = htons(ETHTYPE_IP);
293 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: sending queued IP packet.\n"));
294 /* send the queued IP packet */
295 netif->linkoutput(netif, p);
296 /* free the queued IP packet */
305 /* no matching ARP entry was found */
306 LWIP_ASSERT("update_arp_entry: i == ARP_TABLE_SIZE", i == ARP_TABLE_SIZE);
308 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: IP address not yet in table\n"));
309 /* allowed to insert an entry? */
310 if ((ETHARP_ALWAYS_INSERT) || (flags & ARP_INSERT_FLAG))
312 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: adding entry to table\n"));
313 /* find an empty or old entry. */
314 i = find_arp_entry();
315 if (i == ARP_TABLE_SIZE) {
316 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: no available entry found\n"));
319 /* see if find_arp_entry() gave us an old stable, or empty entry to re-use */
320 if (arp_table[i].state == ETHARP_STATE_STABLE) {
321 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: overwriting old stable entry %u\n", i));
322 /* stable entries should have no queued packets (TODO: allow later) */
324 LWIP_ASSERT("update_arp_entry: arp_table[i].p == NULL", arp_table[i].p == NULL);
327 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("update_arp_entry: filling empty entry %u with state %u\n", i, arp_table[i].state));
328 LWIP_ASSERT("update_arp_entry: arp_table[i].state == ETHARP_STATE_EMPTY", arp_table[i].state == ETHARP_STATE_EMPTY);
331 ip_addr_set(&arp_table[i].ipaddr, ipaddr);
332 /* set Ethernet hardware address */
333 for (k = 0; k < netif->hwaddr_len; ++k) {
334 arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
336 /* reset time-stamp */
337 arp_table[i].ctime = 0;
339 arp_table[i].state = ETHARP_STATE_STABLE;
340 /* no queued packet */
342 arp_table[i].p = NULL;
347 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: no matching stable entry to update\n"));
353 * Updates the ARP table using the given packet.
355 * Uses the incoming IP packet's source address to update the
356 * ARP cache for the local network. The function does not alter
357 * or free the packet. This function must be called before the
358 * packet p is passed to the IP layer.
360 * @param netif The lwIP network interface on which the IP packet pbuf arrived.
361 * @param pbuf The IP packet that arrived on netif.
368 etharp_ip_input(struct netif *netif, struct pbuf *p)
370 struct ethip_hdr *hdr;
372 /* Only insert an entry if the source IP address of the
373 incoming IP packet comes from a host on the local network. */
375 /* source is on local network? */
376 if (!ip_addr_maskcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask))) {
381 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n"));
382 /* update ARP table, ask to insert entry */
383 update_arp_entry(netif, &(hdr->ip.src), &(hdr->eth.src), ARP_INSERT_FLAG);
389 * Responds to ARP requests to us. Upon ARP replies to us, add entry to cache
390 * send out queued IP packets. Updates cache with snooped address pairs.
392 * Should be called for incoming ARP packets. The pbuf in the argument
393 * is freed by this function.
395 * @param netif The lwIP network interface on which the ARP packet pbuf arrived.
396 * @param pbuf The ARP packet that arrived on netif. Is freed by this function.
397 * @param ethaddr Ethernet address of netif.
404 etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
406 struct etharp_hdr *hdr;
410 /* drop short ARP packets */
411 if (p->tot_len < sizeof(struct etharp_hdr)) {
412 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 1, ("etharp_arp_input: packet dropped, too short (%d/%d)\n", p->tot_len, sizeof(struct etharp_hdr)));
419 /* this interface is not configured? */
420 if (netif->ip_addr.addr == 0) {
423 /* ARP packet directed to us? */
424 for_us = ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr));
427 switch (htons(hdr->opcode)) {
430 /* ARP request. If it asked for our address, we send out a
431 reply. In any case, we time-stamp any existing ARP entry,
432 and possiby send out an IP packet that was queued on it. */
434 LWIP_DEBUGF (ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP request\n"));
435 /* we are not configured? */
436 if (netif->ip_addr.addr == 0) {
437 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n"));
441 /* ARP request for our address? */
444 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: replying to ARP request for our IP address\n"));
445 /* re-use pbuf to send ARP reply */
446 hdr->opcode = htons(ARP_REPLY);
448 ip_addr_set(&(hdr->dipaddr), &(hdr->sipaddr));
449 ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr));
451 for(i = 0; i < netif->hwaddr_len; ++i) {
452 hdr->dhwaddr.addr[i] = hdr->shwaddr.addr[i];
453 hdr->shwaddr.addr[i] = ethaddr->addr[i];
454 hdr->ethhdr.dest.addr[i] = hdr->dhwaddr.addr[i];
455 hdr->ethhdr.src.addr[i] = ethaddr->addr[i];
458 hdr->hwtype = htons(HWTYPE_ETHERNET);
459 ARPH_HWLEN_SET(hdr, netif->hwaddr_len);
461 hdr->proto = htons(ETHTYPE_IP);
462 ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
464 hdr->ethhdr.type = htons(ETHTYPE_ARP);
465 /* return ARP reply */
466 netif->linkoutput(netif, p);
468 /* request was not directed to us */
470 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP request was not for us.\n"));
474 /* ARP reply. We insert or update the ARP table later. */
475 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n"));
476 #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
477 /* DHCP needs to know about ARP replies to our address */
478 if (for_us) dhcp_arp_reply(netif, &hdr->sipaddr);
482 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %d\n", htons(hdr->opcode)));
485 /* add or update entries in the ARP cache */
487 /* insert IP address in ARP cache (assume requester wants to talk to us)
488 * we might even send out a queued packet to this host */
489 update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), ARP_INSERT_FLAG);
490 /* request was not directed to us, but snoop anyway */
492 /* update or insert the source IP address in the cache */
493 update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), 0);
494 /* update or insert the destination IP address pair in the cache */
495 update_arp_entry(netif, &(hdr->dipaddr), &(hdr->dhwaddr), 0);
497 /* free ARP packet */
500 /* nothing to send, we did it! */
505 * Resolve and fill-in Ethernet address header for outgoing packet.
507 * If ARP has the Ethernet address in cache, the given packet is
508 * returned, ready to be sent.
510 * If ARP does not have the Ethernet address in cache the packet is
511 * queued (if enabled and space available) and a ARP request is sent.
512 * This ARP request is returned as a pbuf, which should be sent by
515 * If ARP failed to allocate resources, NULL is returned.
517 * A returned non-NULL packet should be sent by the caller.
519 * @param netif The lwIP network interface which the IP packet will be sent on.
520 * @param ipaddr The IP address of the packet destination.
521 * @param pbuf The pbuf(s) containing the IP packet to be sent.
523 * @return If non-NULL, a packet ready to be sent by caller.
527 etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
529 struct eth_addr *dest, *srcaddr, mcastaddr;
530 struct eth_hdr *ethhdr;
533 /* Make room for Ethernet header. */
534 if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
535 /* The pbuf_header() call shouldn't fail, and we'll just bail
537 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_output: could not allocate room for header.\n"));
538 LINK_STATS_INC(link.lenerr);
542 /* obtain source Ethernet address of the given interface */
543 srcaddr = (struct eth_addr *)netif->hwaddr;
545 /* assume unresolved Ethernet address */
547 /* Construct Ethernet header. Start with looking up deciding which
548 MAC address to use as a destination address. Broadcasts and
549 multicasts are special, all other addresses are looked up in the
552 /* destination IP address is an IP broadcast address? */
553 if (ip_addr_isany(ipaddr) ||
554 ip_addr_isbroadcast(ipaddr, &(netif->netmask))) {
555 /* broadcast on Ethernet also */
556 dest = (struct eth_addr *)ðbroadcast;
558 /* destination IP address is an IP multicast address? */
559 else if (ip_addr_ismulticast(ipaddr)) {
560 /* Hash IP multicast address to MAC address. */
561 mcastaddr.addr[0] = 0x01;
562 mcastaddr.addr[1] = 0x00;
563 mcastaddr.addr[2] = 0x5e;
564 mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
565 mcastaddr.addr[4] = ip4_addr3(ipaddr);
566 mcastaddr.addr[5] = ip4_addr4(ipaddr);
567 /* destination Ethernet address is multicast */
570 /* destination IP address is an IP unicast address */
572 /* destination IP network address not on local network? */
573 /* this occurs if the packet is routed to the default gateway on this interface */
574 if (!ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {
575 /* gateway available? */
576 if (netif->gw.addr != 0)
578 /* use the gateway IP address */
579 ipaddr = &(netif->gw);
581 /* no gateway available? */
584 /* IP destination address outside local network, but no gateway available */
589 /* Ethernet address for IP destination address is in ARP cache? */
590 for (i = 0; i < ARP_TABLE_SIZE; ++i) {
592 if (arp_table[i].state == ETHARP_STATE_STABLE &&
593 ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
594 dest = &arp_table[i].ethaddr;
598 /* could not find the destination Ethernet address in ARP cache? */
600 /* ARP query for the IP address, submit this IP packet for queueing */
601 /* TODO: How do we handle netif->ipaddr == ipaddr? */
602 etharp_query(netif, ipaddr, q);
606 /* destination Ethernet address resolved from ARP cache */
613 /* destination Ethernet address known */
615 /* A valid IP->MAC address mapping was found, so we construct the
616 Ethernet header for the outgoing packet. */
619 for(i = 0; i < netif->hwaddr_len; i++) {
620 ethhdr->dest.addr[i] = dest->addr[i];
621 ethhdr->src.addr[i] = srcaddr->addr[i];
624 ethhdr->type = htons(ETHTYPE_IP);
625 /* return the outgoing packet */
628 /* never reached; here for safety */
633 * Send an ARP request for the given IP address.
635 * Sends an ARP request for the given IP address, unless
636 * a request for this address is already pending. Optionally
637 * queues an outgoing packet on the resulting ARP entry.
639 * @param netif The lwIP network interface where ipaddr
640 * must be queried for.
641 * @param ipaddr The IP address to be resolved.
642 * @param q If non-NULL, a pbuf that must be queued on the
643 * ARP entry for the ipaddr IP address.
647 * @note Might be used in the future by manual IP configuration
650 * TODO: use the ctime field to see how long ago an ARP request was sent,
653 err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
655 struct eth_addr *srcaddr;
656 struct etharp_hdr *hdr;
658 err_t result = ERR_OK;
660 u8_t perform_arp_request = 1;
661 /* prevent 'unused argument' warning if ARP_QUEUEING == 0 */
663 srcaddr = (struct eth_addr *)netif->hwaddr;
664 /* bail out if this IP address is pending */
665 for (i = 0; i < ARP_TABLE_SIZE; ++i) {
666 if (ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
667 if (arp_table[i].state == ETHARP_STATE_PENDING) {
668 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: requested IP already pending as entry %u\n", i));
669 /* break out of for-loop, user may wish to queue a packet on a stable entry */
670 /* TODO: we will issue a new ARP request, which should not occur too often */
671 /* we might want to run a faster timer on ARP to limit this */
674 else if (arp_table[i].state == ETHARP_STATE_STABLE) {
675 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: requested IP already stable as entry %u\n", i));
676 /* user may wish to queue a packet on a stable entry, so we proceed without ARP requesting */
677 /* TODO: even if the ARP entry is stable, we might do an ARP request anyway */
678 perform_arp_request = 0;
683 /* queried address not yet in ARP table? */
684 if (i == ARP_TABLE_SIZE) {
685 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: IP address not found in ARP table\n"));
686 /* find an available entry */
687 i = find_arp_entry();
688 /* bail out if no ARP entries are available */
689 if (i == ARP_TABLE_SIZE) {
690 LWIP_DEBUGF(ETHARP_DEBUG | 2, ("etharp_query: no more ARP entries available.\n"));
693 /* we will now recycle entry i */
694 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: created ARP table entry %u.\n", i));
695 /* i is available, create ARP entry */
696 ip_addr_set(&arp_table[i].ipaddr, ipaddr);
697 arp_table[i].ctime = 0;
698 arp_table[i].state = ETHARP_STATE_PENDING;
700 /* free queued packet, as entry is now invalidated */
701 if (arp_table[i].p != NULL) {
702 pbuf_free(arp_table[i].p);
703 arp_table[i].p = NULL;
704 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("etharp_query: dropped packet on ARP queue. Should not occur.\n"));
709 /* any pbuf to queue and queue is empty? */
711 /* yield later packets over older packets? */
712 #if ARP_QUEUE_FIRST == 0
713 /* earlier queued packet on this entry? */
714 if (arp_table[i].p != NULL) {
715 pbuf_free(arp_table[i].p);
716 arp_table[i].p = NULL;
717 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("etharp_query: dropped packet on ARP queue. Should not occur.\n"));
718 /* fall-through into next if */
721 /* packet can be queued? */
722 if (arp_table[i].p == NULL) {
723 /* copy PBUF_REF referenced payloads into PBUF_RAM */
725 /* remember pbuf to queue, if any */
727 /* pbufs are queued, increase the reference count */
729 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: queued packet %p on ARP entry %u.\n", (void *)q, i));
734 if (perform_arp_request)
736 /* allocate a pbuf for the outgoing ARP request packet */
737 p = pbuf_alloc(PBUF_LINK, sizeof(struct etharp_hdr), PBUF_RAM);
738 /* could allocate pbuf? */
741 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: sending ARP request.\n"));
743 hdr->opcode = htons(ARP_REQUEST);
744 for (j = 0; j < netif->hwaddr_len; ++j)
746 hdr->shwaddr.addr[j] = srcaddr->addr[j];
747 /* the hardware address is what we ask for, in
748 * a request it is a don't-care, we use 0's */
749 hdr->dhwaddr.addr[j] = 0x00;
751 ip_addr_set(&(hdr->dipaddr), ipaddr);
752 ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr));
754 hdr->hwtype = htons(HWTYPE_ETHERNET);
755 ARPH_HWLEN_SET(hdr, netif->hwaddr_len);
757 hdr->proto = htons(ETHTYPE_IP);
758 ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
759 for (j = 0; j < netif->hwaddr_len; ++j)
761 hdr->ethhdr.dest.addr[j] = 0xff;
762 hdr->ethhdr.src.addr[j] = srcaddr->addr[j];
764 hdr->ethhdr.type = htons(ETHTYPE_ARP);
766 result = netif->linkoutput(netif, p);
767 /* free ARP query packet */
772 LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_query: could not allocate pbuf for ARP request.\n"));