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>
47 * - pbufs should be sent from the queue once an ARP entry state
48 * goes from PENDING to STABLE.
49 * - Non-PENDING entries MUST NOT have queued packets.
55 RFC 3220 4.6 IP Mobility Support for IPv4 January 2002
57 - A Gratuitous ARP [45] is an ARP packet sent by a node in order
58 to spontaneously cause other nodes to update an entry in their
59 ARP cache. A gratuitous ARP MAY use either an ARP Request or
60 an ARP Reply packet. In either case, the ARP Sender Protocol
61 Address and ARP Target Protocol Address are both set to the IP
62 address of the cache entry to be updated, and the ARP Sender
63 Hardware Address is set to the link-layer address to which this
64 cache entry should be updated. When using an ARP Reply packet,
65 the Target Hardware Address is also set to the link-layer
66 address to which this cache entry should be updated (this field
67 is not used in an ARP Request packet).
69 In either case, for a gratuitous ARP, the ARP packet MUST be
70 transmitted as a local broadcast packet on the local link. As
71 specified in [36], any node receiving any ARP packet (Request
72 or Reply) MUST update its local ARP cache with the Sender
73 Protocol and Hardware Addresses in the ARP packet, if the
74 receiving node has an entry for that IP address already in its
75 ARP cache. This requirement in the ARP protocol applies even
76 for ARP Request packets, and for ARP Reply packets that do not
77 match any ARP Request transmitted by the receiving node [36].
79 My suggestion would be to send a ARP request for our newly obtained
80 address upon configuration of an Ethernet interface.
85 #include "lwip/inet.h"
86 #include "netif/etharp.h"
88 #include "lwip/stats.h"
90 /* ARP needs to inform DHCP of any ARP replies? */
91 #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
92 # include "lwip/dhcp.h"
95 /** the time an ARP entry stays valid after its last update, (120 * 10) seconds = 20 minutes. */
96 #define ARP_MAXAGE 120
97 /** the time an ARP entry stays pending after first request, (2 * 10) seconds = 20 seconds. */
98 #define ARP_MAXPENDING 2
100 #define HWTYPE_ETHERNET 1
102 /** ARP message types */
103 #define ARP_REQUEST 0x0100
104 #define ARP_REPLY 0x0200
106 #define ARPH_HWLEN(hdr) (ntohs((hdr)->_hwlen_protolen) >> 8)
107 #define ARPH_PROTOLEN(hdr) (ntohs((hdr)->_hwlen_protolen) & 0xff)
109 #define ARPH_HWLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons(ARPH_PROTOLEN(hdr) | ((len) << 8))
110 #define ARPH_PROTOLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons((len) | (ARPH_HWLEN(hdr) << 8))
114 ETHARP_STATE_PENDING
,
118 struct etharp_entry
{
119 struct ip_addr ipaddr
;
120 struct eth_addr ethaddr
;
121 enum etharp_state state
;
124 * Pointer to queue of pending outgoing packets on this ARP entry.
125 * Must be at most a single packet for now. */
131 static const struct eth_addr ethbroadcast
= {{0xff,0xff,0xff,0xff,0xff,0xff}};
132 static struct etharp_entry arp_table
[ARP_TABLE_SIZE
];
134 static s8_t
find_arp_entry(void);
135 #define ARP_INSERT_FLAG 1
136 static struct pbuf
*update_arp_entry(struct netif
*netif
, struct ip_addr
*ipaddr
, struct eth_addr
*ethaddr
, u8_t flags
);
138 static struct pbuf
*etharp_enqueue(s8_t i
, struct pbuf
*q
);
139 static u8_t
etharp_dequeue(s8_t i
);
142 * Initializes ARP module.
148 /* clear ARP entries */
149 for(i
= 0; i
< ARP_TABLE_SIZE
; ++i
) {
150 arp_table
[i
].state
= ETHARP_STATE_EMPTY
;
152 arp_table
[i
].p
= NULL
;
154 arp_table
[i
].ctime
= 0;
158 * Clears expired entries in the ARP table.
160 * This function should be called every ETHARP_TMR_INTERVAL microseconds (10 seconds),
161 * in order to expire entries in the ARP table.
163 void etharp_tmr ( void ) {
167 for ( i
= 0; i
< ARP_TABLE_SIZE
; ++i
) {
168 ++arp_table
[ i
].ctime
;
169 if ( arp_table
[ i
].state
== ETHARP_STATE_STABLE
&& arp_table
[ i
].ctime
>= ARP_MAXAGE
) {
171 } else if ( arp_table
[ i
].state
== ETHARP_STATE_PENDING
&& arp_table
[ i
].ctime
>= ARP_MAXPENDING
) {
173 arp_table
[ i
].state
= ETHARP_STATE_EMPTY
;
175 if ( arp_table
[ i
].p
) {
176 pbuf_free ( arp_table
[ i
].p
);
177 arp_table
[ i
].p
= NULL
;
182 } /* end etharp_tmr */
184 * Return an empty ARP entry (possibly recycling the oldest stable entry).
186 * @return The ARP entry index that is available, ERR_MEM if no usable
196 /* search ARP table for an unused or old entry */
197 for (i
= 0; i
< ARP_TABLE_SIZE
; ++i
) {
199 if (arp_table
[i
].state
== ETHARP_STATE_EMPTY
) {
200 LWIP_DEBUGF(ETHARP_DEBUG
, ("find_arp_entry: returning empty entry %u\n", i
));
203 } else if (arp_table
[i
].state
== ETHARP_STATE_STABLE
) {
204 /* remember entry with oldest stable entry in j */
205 if (arp_table
[i
].ctime
>= maxtime
) maxtime
= arp_table
[j
= i
].ctime
;
208 /* no empty entry found? */
209 if (i
== ARP_TABLE_SIZE
) {
210 LWIP_DEBUGF(ETHARP_DEBUG
, ("find_arp_entry: found oldest stable entry %u\n", j
));
211 /* fall-back to oldest stable */
214 /* no available entry found? */
215 if (i
== ARP_TABLE_SIZE
) {
216 LWIP_DEBUGF(ETHARP_DEBUG
, ("find_arp_entry: no replacable entry could be found\n"));
221 /* clean up the recycled stable entry */
222 if (arp_table
[i
].state
== ETHARP_STATE_STABLE
) {
224 /* free packets on queue */
227 LWIP_DEBUGF(ETHARP_DEBUG
| DBG_TRACE
, ("find_arp_entry: recycling oldest stable entry %u\n", i
));
228 arp_table
[i
].state
= ETHARP_STATE_EMPTY
;
229 arp_table
[i
].ctime
= 0;
231 LWIP_DEBUGF(ETHARP_DEBUG
, ("find_arp_entry: returning %u\n", i
));
237 * Enqueues a pbuf (chain) on an ARP entry.
239 * Places the pbuf (chain) on the queue (if space allows). The
240 * caller may safely free the pbuf (chain) afterwards, as the
241 * pbufs will be referenced by the queue and copies are made of
242 * pbufs referencing external payloads.
244 * @ i the ARP entry index
245 * @arg q the pbuf (chain) to be queued on the ARP entry
247 * @return Returns the new head of queue of the ARP entry.
251 etharp_enqueue(s8_t i
, struct pbuf
*q
)
253 /* any pbuf to queue? */
255 /* queue later packet over earliers? TODO: Implement multiple pbuf queue */
256 #if ARP_QUEUE_FIRST == 0
257 /* remove any pbufs on queue */
258 u8_t deq
= etharp_dequeue(i
);
259 if (deq
> 0) LWIP_DEBUGF(ETHARP_DEBUG
| DBG_TRACE
| 3, ("etharp_query: dequeued %u pbufs from ARP entry %u. Should not occur.\n", deq
, i
));
261 /* packet can be queued? TODO: Implement multiple pbuf queue */
262 if (arp_table
[i
].p
== NULL
) {
263 /* copy any PBUF_REF referenced payloads into PBUF_RAM */
265 /* add pbuf to queue */
267 /* pbuf (chain) now queued, increase the reference count */
269 LWIP_DEBUGF(ETHARP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("etharp_query: queued packet %p on ARP entry %u.\n", (void *)q
, i
));
272 return arp_table
[i
].p
;
276 * Dequeues any pbufs queued on an ARP entry
278 * @return number of pbufs removed from the queue
280 * TODO: decide what is a sensible return value?
283 etharp_dequeue(s8_t i
)
285 /* queued packets on a stable entry (work in progress) */
286 if (arp_table
[i
].p
!= NULL
) {
287 /* queue no longer references pbuf */
288 pbuf_free(arp_table
[i
].p
);
289 arp_table
[i
].p
= NULL
;
298 * Update (or insert) a IP/MAC address pair in the ARP cache.
300 * If a pending entry is resolved, any queued packets will be sent
303 * @param ipaddr IP address of the inserted ARP entry.
304 * @param ethaddr Ethernet address of the inserted ARP entry.
305 * @param flags Defines behaviour:
306 * - ARP_INSERT_FLAG Allows ARP to insert this as a new item. If not specified,
307 * only existing ARP entries will be updated.
309 * @return pbuf If non-NULL, a packet that was queued on a pending entry.
310 * You should sent it and must call pbuf_free() afterwards.
315 update_arp_entry(struct netif
*netif
, struct ip_addr
*ipaddr
, struct eth_addr
*ethaddr
, u8_t flags
)
318 LWIP_DEBUGF(ETHARP_DEBUG
| DBG_TRACE
| 3, ("update_arp_entry()\n"));
319 LWIP_ASSERT("netif->hwaddr_len != 0", netif
->hwaddr_len
!= 0);
320 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
),
321 ethaddr
->addr
[0], ethaddr
->addr
[1], ethaddr
->addr
[2], ethaddr
->addr
[3], ethaddr
->addr
[4], ethaddr
->addr
[5]));
322 /* do not update for 0.0.0.0 addresses */
323 if (ipaddr
->addr
== 0) {
324 LWIP_DEBUGF(ETHARP_DEBUG
| DBG_TRACE
, ("update_arp_entry: will not add 0.0.0.0 to ARP cache\n"));
327 /* Walk through the ARP mapping table and try to find an entry to
328 update. If none is found, the IP -> MAC address mapping is
329 inserted in the ARP table. */
330 for (i
= 0; i
< ARP_TABLE_SIZE
; ++i
) {
331 /* Check if the source IP address of the incoming packet matches
332 the IP address in this ARP table entry. */
333 if (ip_addr_cmp(ipaddr
, &arp_table
[i
].ipaddr
)) {
335 if (arp_table
[i
].state
== ETHARP_STATE_PENDING
) {
336 LWIP_DEBUGF(ETHARP_DEBUG
| DBG_TRACE
, ("update_arp_entry: pending entry %u goes stable\n", i
));
337 /* A pending entry was found, mark it stable */
338 arp_table
[i
].state
= ETHARP_STATE_STABLE
;
339 /* fall-through to next if */
341 /* stable entry? (possibly just marked to become stable) */
342 if (arp_table
[i
].state
== ETHARP_STATE_STABLE
) {
345 struct eth_hdr
*ethhdr
;
347 LWIP_DEBUGF(ETHARP_DEBUG
| DBG_TRACE
, ("update_arp_entry: updating stable entry %u\n", i
));
348 /* An old entry found, update this and return. */
349 for (k
= 0; k
< netif
->hwaddr_len
; ++k
) {
350 arp_table
[i
].ethaddr
.addr
[k
] = ethaddr
->addr
[k
];
352 /* reset time stamp */
353 arp_table
[i
].ctime
= 0;
354 /* this is where we will send out queued packets! */
356 /* get the first packet on the queue (if any) */
358 /* queued packet present? */
361 /* search for second packet on queue (n) */
363 while (q
->tot_len
> q
->len
) {
364 /* proceed to next pbuf of this packet */
365 LWIP_ASSERT("q->next ! NULL", q
->next
!= NULL
);
368 /* { q = last pbuf of first packet, q->tot_len = q->len } */
370 /* { n = first pbuf of 2nd packet, or NULL if no 2nd packet } */
371 /* terminate the first packet pbuf chain */
373 /* fill-in Ethernet header */
375 for (k
= 0; k
< netif
->hwaddr_len
; ++k
) {
376 ethhdr
->dest
.addr
[k
] = ethaddr
->addr
[k
];
377 ethhdr
->src
.addr
[k
] = netif
->hwaddr
[k
];
379 ethhdr
->type
= ETHTYPE_IP
;
380 LWIP_DEBUGF(ETHARP_DEBUG
| DBG_TRACE
, ("update_arp_entry: sending queued IP packet %p.\n",(void *)p
));
381 /* send the queued IP packet */
382 netif
->linkoutput(netif
, p
);
383 /* free the queued IP packet */
385 /* proceed to next packet on queue */
388 /* NULL attached buffer*/
389 arp_table
[i
].p
= NULL
;
396 /* no matching ARP entry was found */
397 LWIP_ASSERT("update_arp_entry: i == ARP_TABLE_SIZE", i
== ARP_TABLE_SIZE
);
399 LWIP_DEBUGF(ETHARP_DEBUG
| DBG_TRACE
, ("update_arp_entry: IP address not yet in table\n"));
400 /* allowed to insert an entry? */
401 if ((ETHARP_ALWAYS_INSERT
) || (flags
& ARP_INSERT_FLAG
))
403 LWIP_DEBUGF(ETHARP_DEBUG
| DBG_TRACE
, ("update_arp_entry: adding entry to table\n"));
404 /* find an empty or old entry. */
405 i
= find_arp_entry();
407 LWIP_DEBUGF(ETHARP_DEBUG
| DBG_TRACE
, ("update_arp_entry: no available entry found\n"));
411 ip_addr_set(&arp_table
[i
].ipaddr
, ipaddr
);
412 /* set Ethernet hardware address */
413 for (k
= 0; k
< netif
->hwaddr_len
; ++k
) {
414 arp_table
[i
].ethaddr
.addr
[k
] = ethaddr
->addr
[k
];
416 /* reset time-stamp */
417 arp_table
[i
].ctime
= 0;
419 arp_table
[i
].state
= ETHARP_STATE_STABLE
;
420 /* no queued packet */
422 arp_table
[i
].p
= NULL
;
427 LWIP_DEBUGF(ETHARP_DEBUG
| DBG_TRACE
, ("update_arp_entry: no matching stable entry to update\n"));
433 * Updates the ARP table using the given IP packet.
435 * Uses the incoming IP packet's source address to update the
436 * ARP cache for the local network. The function does not alter
437 * or free the packet. This function must be called before the
438 * packet p is passed to the IP layer.
440 * @param netif The lwIP network interface on which the IP packet pbuf arrived.
441 * @param pbuf The IP packet that arrived on netif.
448 etharp_ip_input(struct netif
*netif
, struct pbuf
*p
) {
449 struct ethip_hdr
*hdr
;
451 /* Only insert an entry if the source IP address of the
452 incoming IP packet comes from a host on the local network. */
454 /* source is on local network? */
455 if (ip_addr_maskcmp(&(hdr
->ip
.src
), &(netif
->ip_addr
), &(netif
->netmask
)))
456 update_arp_entry(netif
, &(hdr
->ip
.src
), &(hdr
->eth
.src
), ARP_INSERT_FLAG
);
460 * Responds to ARP requests to us. Upon ARP replies to us, add entry to cache
461 * send out queued IP packets. Updates cache with snooped address pairs.
463 * Should be called for incoming ARP packets. The pbuf in the argument
464 * is freed by this function.
466 * @param netif The lwIP network interface on which the ARP packet pbuf arrived.
467 * @param pbuf The ARP packet that arrived on netif. Is freed by this function.
468 * @param ethaddr Ethernet address of netif.
474 void etharp_arp_input(struct netif
*netif
, struct eth_addr
*ethaddr
, struct pbuf
*p
)
476 struct etharp_hdr
*hdr
;
480 /* drop short ARP packets */
481 if (p
->tot_len
< sizeof(struct etharp_hdr
)) return;
485 /* this interface is not configured? */
486 if (netif
->ip_addr
.addr
== 0) {
489 /* ARP packet directed to us? */
490 for_us
= ip_addr_cmp(&(hdr
->dipaddr
), &(netif
->ip_addr
));
493 /* add or update entries in the ARP cache */
495 /* insert IP address in ARP cache (assume requester wants to talk to us)
496 * we might even send out a queued packet to this host */
497 update_arp_entry(netif
, &(hdr
->sipaddr
), &(hdr
->shwaddr
), ARP_INSERT_FLAG
);
498 /* request was not directed to us, but snoop anyway */
500 /* update the source IP address in the cache */
501 update_arp_entry(netif
, &(hdr
->sipaddr
), &(hdr
->shwaddr
), 0);
504 switch (hdr
->opcode
) {
507 /* ARP request. If it asked for our address, we send out a
508 reply. In any case, we time-stamp any existing ARP entry,
509 and possiby send out an IP packet that was queued on it. */
511 LWIP_DEBUGF (ETHARP_DEBUG
| DBG_TRACE
, ("etharp_arp_input: incoming ARP request\n"));
512 /* we are not configured? */
513 if (netif
->ip_addr
.addr
== 0) return;
514 /* ARP request for our address? */
517 LWIP_DEBUGF(ETHARP_DEBUG
| DBG_TRACE
, ("etharp_arp_input: replying to ARP request for our IP address\n"));
518 /* re-use pbuf to send ARP reply */
519 hdr
->opcode
= ARP_REPLY
;
521 ip_addr_set(&(hdr
->dipaddr
), &(hdr
->sipaddr
));
522 ip_addr_set(&(hdr
->sipaddr
), &(netif
->ip_addr
));
524 for(i
= 0; i
< netif
->hwaddr_len
; ++i
) {
525 hdr
->dhwaddr
.addr
[i
] = hdr
->shwaddr
.addr
[i
];
526 hdr
->shwaddr
.addr
[i
] = ethaddr
->addr
[i
];
527 hdr
->ethhdr
.dest
.addr
[i
] = hdr
->dhwaddr
.addr
[i
];
528 hdr
->ethhdr
.src
.addr
[i
] = ethaddr
->addr
[i
];
531 hdr
->hwtype
= htons(HWTYPE_ETHERNET
);
532 ARPH_HWLEN_SET(hdr
, netif
->hwaddr_len
);
534 hdr
->proto
= ETHTYPE_IP
;
535 ARPH_PROTOLEN_SET(hdr
, sizeof(struct ip_addr
));
537 hdr
->ethhdr
.type
= ETHTYPE_ARP
;
538 /* return ARP reply */
539 netif
->linkoutput(netif
, p
);
541 /* request was not directed to us */
543 LWIP_DEBUGF(ETHARP_DEBUG
| DBG_TRACE
, ("etharp_arp_input: incoming ARP request was not for us.\n"));
547 /* ARP reply. We insert or update the ARP table later. */
548 LWIP_DEBUGF(ETHARP_DEBUG
| DBG_TRACE
, ("etharp_arp_input: incoming ARP reply\n"));
549 #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
550 /* DHCP needs to know about ARP replies to our address */
551 if (for_us
) dhcp_arp_reply(netif
, &hdr
->sipaddr
);
555 LWIP_DEBUGF(ETHARP_DEBUG
| DBG_TRACE
, ("etharp_arp_input: ARP unknown opcode type %d\n", htons(hdr
->opcode
)));
561 * Resolve and fill-in Ethernet address header for outgoing packet.
563 * If ARP has the Ethernet address in cache, the given packet is
564 * returned, ready to be sent.
566 * If ARP does not have the Ethernet address in cache the packet is
567 * queued (if enabled and space available) and a ARP request is sent.
568 * This ARP request is returned as a pbuf, which should be sent by
571 * A returned non-NULL packet should be sent by the caller.
573 * If ARP failed to allocate resources, NULL is returned.
575 * @param netif The lwIP network interface which the IP packet will be sent on.
576 * @param ipaddr The IP address of the packet destination.
577 * @param pbuf The pbuf(s) containing the IP packet to be sent.
579 * @return If non-NULL, a packet ready to be sent by caller.
583 etharp_output(struct netif
*netif
, struct ip_addr
*ipaddr
, struct pbuf
*q
)
585 struct eth_addr
*dest
, *srcaddr
, mcastaddr
;
586 struct eth_hdr
*ethhdr
;
589 /* make room for Ethernet header */
590 if (pbuf_header(q
, sizeof(struct eth_hdr
)) != 0) {
591 /* The pbuf_header() call shouldn't fail, and we'll just bail
593 LWIP_DEBUGF(ETHARP_DEBUG
| DBG_TRACE
| 2, ("etharp_output: could not allocate room for header.\n"));
594 LINK_STATS_INC(link
.lenerr
);
598 /* assume unresolved Ethernet address */
600 /* Construct Ethernet header. Start with looking up deciding which
601 MAC address to use as a destination address. Broadcasts and
602 multicasts are special, all other addresses are looked up in the
605 /* destination IP address is an IP broadcast address? */
606 if (ip_addr_isany(ipaddr
) ||
607 ip_addr_isbroadcast(ipaddr
, &(netif
->netmask
))) {
608 /* broadcast on Ethernet also */
609 dest
= (struct eth_addr
*)ðbroadcast
;
611 /* destination IP address is an IP multicast address? */
612 else if (ip_addr_ismulticast(ipaddr
)) {
613 /* Hash IP multicast address to MAC address. */
614 mcastaddr
.addr
[0] = 0x01;
615 mcastaddr
.addr
[1] = 0x00;
616 mcastaddr
.addr
[2] = 0x5e;
617 mcastaddr
.addr
[3] = ip4_addr2(ipaddr
) & 0x7f;
618 mcastaddr
.addr
[4] = ip4_addr3(ipaddr
);
619 mcastaddr
.addr
[5] = ip4_addr4(ipaddr
);
620 /* destination Ethernet address is multicast */
623 /* destination IP address is an IP unicast address */
625 /* destination IP network address not on local network?
626 * IP layer wants us to forward to the default gateway */
627 if (!ip_addr_maskcmp(ipaddr
, &(netif
->ip_addr
), &(netif
->netmask
))) {
628 /* interface has default gateway? */
629 if (netif
->gw
.addr
!= 0)
631 /* route to default gateway IP address */
632 ipaddr
= &(netif
->gw
);
634 /* no gateway available? */
637 /* IP destination address outside local network, but no gateway available */
638 /* { packet is discarded } */
643 /* Ethernet address for IP destination address is in ARP cache? */
644 for (i
= 0; i
< ARP_TABLE_SIZE
; ++i
) {
646 if (arp_table
[i
].state
== ETHARP_STATE_STABLE
&&
647 ip_addr_cmp(ipaddr
, &arp_table
[i
].ipaddr
)) {
648 dest
= &arp_table
[i
].ethaddr
;
652 /* could not find the destination Ethernet address in ARP cache? */
654 /* ARP query for the IP address, submit this IP packet for queueing */
655 /* TODO: How do we handle netif->ipaddr == ipaddr? */
656 etharp_query(netif
, ipaddr
, q
);
657 /* { packet was queued (ERR_OK), or discarded } */
661 /* destination Ethernet address resolved from ARP cache */
668 /* destination Ethernet address known */
670 /* obtain source Ethernet address of the given interface */
671 srcaddr
= (struct eth_addr
*)netif
->hwaddr
;
673 /* A valid IP->MAC address mapping was found, fill in the
674 * Ethernet header for the outgoing packet */
677 for(i
= 0; i
< netif
->hwaddr_len
; i
++) {
678 ethhdr
->dest
.addr
[i
] = dest
->addr
[i
];
679 ethhdr
->src
.addr
[i
] = srcaddr
->addr
[i
];
682 ethhdr
->type
= ETHTYPE_IP
;
683 /* return the outgoing packet */
686 /* never reached; here for safety */
691 * Send an ARP request for the given IP address.
693 * Sends an ARP request for the given IP address, unless
694 * a request for this address is already pending. Optionally
695 * queues an outgoing packet on the resulting ARP entry.
697 * @param netif The lwIP network interface where ipaddr
698 * must be queried for.
699 * @param ipaddr The IP address to be resolved.
700 * @param q If non-NULL, a pbuf that must be queued on the
701 * ARP entry for the ipaddr IP address.
705 * @note Might be used in the future by manual IP configuration
708 * TODO: use the ctime field to see how long ago an ARP request was sent,
711 err_t
etharp_query(struct netif
*netif
, struct ip_addr
*ipaddr
, struct pbuf
*q
)
713 struct eth_addr
*srcaddr
;
714 struct etharp_hdr
*hdr
;
715 err_t result
= ERR_OK
;
717 u8_t perform_arp_request
= 1;
718 /* prevent 'unused argument' warning if ARP_QUEUEING == 0 */
720 srcaddr
= (struct eth_addr
*)netif
->hwaddr
;
721 /* bail out if this IP address is pending */
722 for (i
= 0; i
< ARP_TABLE_SIZE
; ++i
) {
723 if (ip_addr_cmp(ipaddr
, &arp_table
[i
].ipaddr
)) {
724 if (arp_table
[i
].state
== ETHARP_STATE_PENDING
) {
725 LWIP_DEBUGF(ETHARP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("etharp_query: requested IP already pending as entry %u\n", i
));
726 /* break out of for-loop, user may wish to queue a packet on a pending entry */
727 /* TODO: we will issue a new ARP request, which should not occur too often */
728 /* we might want to run a faster timer on ARP to limit this */
731 else if (arp_table
[i
].state
== ETHARP_STATE_STABLE
) {
732 LWIP_DEBUGF(ETHARP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("etharp_query: requested IP already stable as entry %u\n", i
));
733 /* user may wish to queue a packet on a stable entry, so we proceed without ARP requesting */
734 /* TODO: even if the ARP entry is stable, we might do an ARP request anyway */
735 perform_arp_request
= 0;
740 /* queried address not yet in ARP table? */
741 if (i
== ARP_TABLE_SIZE
) {
742 LWIP_DEBUGF(ETHARP_DEBUG
| DBG_TRACE
, ("etharp_query: IP address not found in ARP table\n"));
743 /* find an available (unused or old) entry */
744 i
= find_arp_entry();
745 /* bail out if no ARP entries are available */
747 LWIP_DEBUGF(ETHARP_DEBUG
| 2, ("etharp_query: no more ARP entries available. Should seldom occur.\n"));
750 /* i is available, create ARP entry */
751 arp_table
[i
].state
= ETHARP_STATE_PENDING
;
752 ip_addr_set(&arp_table
[i
].ipaddr
, ipaddr
);
753 /* queried address was already in ARP table */
756 etharp_enqueue(i
, q
);
760 if (perform_arp_request
)
763 /* allocate a pbuf for the outgoing ARP request packet */
764 p
= pbuf_alloc(PBUF_LINK
, sizeof(struct etharp_hdr
), PBUF_RAM
);
765 /* could allocate pbuf? */
768 LWIP_DEBUGF(ETHARP_DEBUG
| DBG_TRACE
, ("etharp_query: sending ARP request.\n"));
770 hdr
->opcode
= ARP_REQUEST
;
771 for (j
= 0; j
< netif
->hwaddr_len
; ++j
)
773 hdr
->shwaddr
.addr
[j
] = srcaddr
->addr
[j
];
774 /* the hardware address is what we ask for, in
775 * a request it is a don't-care, we use 0's */
776 hdr
->dhwaddr
.addr
[j
] = 0x00;
778 ip_addr_set(&(hdr
->dipaddr
), ipaddr
);
779 ip_addr_set(&(hdr
->sipaddr
), &(netif
->ip_addr
));
781 hdr
->hwtype
= htons(HWTYPE_ETHERNET
);
782 ARPH_HWLEN_SET(hdr
, netif
->hwaddr_len
);
784 hdr
->proto
= ETHTYPE_IP
;
785 ARPH_PROTOLEN_SET(hdr
, sizeof(struct ip_addr
));
786 for (j
= 0; j
< netif
->hwaddr_len
; ++j
)
788 hdr
->ethhdr
.dest
.addr
[j
] = 0xff;
789 hdr
->ethhdr
.src
.addr
[j
] = srcaddr
->addr
[j
];
791 hdr
->ethhdr
.type
= ETHTYPE_ARP
;
793 result
= netif
->linkoutput(netif
, p
);
794 /* free ARP query packet */
799 LWIP_DEBUGF(ETHARP_DEBUG
| DBG_TRACE
| 2, ("etharp_query: could not allocate pbuf for ARP request.\n"));