]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lwip.git/blob - src/netif/etharp.c
Merged from DEVEL into main tree.
[pes-rpp/rpp-lwip.git] / src / netif / etharp.c
1 /**
2  * @file
3  * Address Resolution Protocol module for IP over Ethernet
4  *
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.
8  *
9  * This implementation complies with RFC 826 (Ethernet ARP) and supports
10  * Gratuitious ARP from RFC3220 (IP Mobility Support for IPv4) section 4.6.
11  */
12
13 /*
14  * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
15  * All rights reserved.
16  *
17  * Redistribution and use in source and binary forms, with or without modification,
18  * are permitted provided that the following conditions are met:
19  *
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.
27  *
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
37  * OF SUCH DAMAGE.
38  *
39  * This file is part of the lwIP TCP/IP stack.
40  *
41  * Author: Adam Dunkels <adam@sics.se>
42  *
43  */
44
45 /*
46  * TODO:
47  *
48 RFC 3220 4.6          IP Mobility Support for IPv4          January 2002
49
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).
61
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].
71 *
72   My suggestion would be to send a ARP request for our newly obtained
73   address upon configuration of an Ethernet interface.
74
75 */
76
77 #include "lwip/opt.h"
78 #include "lwip/inet.h"
79 #include "netif/etharp.h"
80 #include "lwip/ip.h"
81 #include "lwip/stats.h"
82
83 /* ARP needs to inform DHCP of any ARP replies? */
84 #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
85 #  include "lwip/dhcp.h"
86 #endif
87
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
92
93 #define HWTYPE_ETHERNET 1
94
95 /** ARP message types */
96 #define ARP_REQUEST 1
97 #define ARP_REPLY 2
98
99 #define ARPH_HWLEN(hdr) (ntohs((hdr)->_hwlen_protolen) >> 8)
100 #define ARPH_PROTOLEN(hdr) (ntohs((hdr)->_hwlen_protolen) & 0xff)
101
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))
104
105 enum etharp_state {
106   ETHARP_STATE_EMPTY,
107   ETHARP_STATE_PENDING,
108   ETHARP_STATE_STABLE
109 };
110
111 struct etharp_entry {
112   struct ip_addr ipaddr;
113   struct eth_addr ethaddr;
114   enum etharp_state state;
115 #if ARP_QUEUEING
116   struct pbuf *p;
117 #endif
118   u8_t ctime;
119 };
120
121 static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
122 static struct etharp_entry arp_table[ARP_TABLE_SIZE];
123
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
126
127 /**
128  * Initializes ARP module.
129  */
130 void
131 etharp_init(void)
132 {
133   u8_t i;
134   /* clear ARP entries */
135   for(i = 0; i < ARP_TABLE_SIZE; ++i) {
136     arp_table[i].state = ETHARP_STATE_EMPTY;
137 #if ARP_QUEUEING
138     arp_table[i].p = NULL;
139 #endif
140   }
141 }
142
143 /**
144  * Clears expired entries in the ARP table.
145  *
146  * This function should be called every ETHARP_TMR_INTERVAL microseconds (10 seconds),
147  * in order to expire entries in the ARP table.
148  */
149 void
150 etharp_tmr(void)
151 {
152   u8_t i;
153
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));
161       goto empty;
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));
165   empty:      
166       arp_table[i].state = ETHARP_STATE_EMPTY;
167 #if ARP_QUEUEING
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;
173       }
174 #endif
175     }
176   }
177 }
178
179 /**
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.
182  *
183  * @return The ARP entry index that is available, ARP_TABLE_SIZE if no usable
184  * entry is found.
185  */
186 static u8_t
187 find_arp_entry(void)
188 {
189   u8_t i, j, maxtime;
190
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));
195       break;
196     }
197   }
198
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) {
202     maxtime = 0;
203     j = 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) &&
209 #endif
210       (arp_table[i].ctime >= maxtime)) {
211         maxtime = arp_table[i].ctime;
212         j = i;
213       }
214     }
215     if (j != ARP_TABLE_SIZE) {
216       LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: found oldest stable entry %u\n", j));
217     } else {
218       LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: no replacable entry could be found\n"));
219     }
220     i = j;
221   }
222   LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: returning %u, state %u\n", i, arp_table[i].state));
223   return i;
224 }
225
226 /**
227  * Update (or insert) a IP/MAC address pair in the ARP cache.
228  *
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.
234  *
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.
237  *
238  * @see pbuf_free()
239  */
240 static struct pbuf *
241 update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags)
242 {
243   u8_t i, k;
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"));
251     return NULL;
252   }
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)) {
260       /* pending entry? */
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 */
266       }
267       /* stable entry? (possible just marked to become stable) */
268       if (arp_table[i].state == ETHARP_STATE_STABLE) {
269 #if ARP_QUEUEING
270         struct pbuf *p;
271         struct eth_hdr *ethhdr;
272 #endif
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];
277         }
278         /* reset time stamp */
279         arp_table[i].ctime = 0;
280 #if ARP_QUEUEING
281         p = arp_table[i].p;
282         /* queued packet present? */
283         if (p != NULL) {
284           /* NULL attached buffer immediately */
285           arp_table[i].p = NULL;
286           /* fill-in Ethernet header */
287           ethhdr = p->payload;
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];
291           }
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 */
297           pbuf_free(p);
298         }
299 #endif
300         return NULL;
301       }
302     } /* if */
303   } /* for */
304
305   /* no matching ARP entry was found */
306   LWIP_ASSERT("update_arp_entry: i == ARP_TABLE_SIZE", i == ARP_TABLE_SIZE);
307
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))
311   {
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"));
317       return NULL;
318     }
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) */
323 #if ARP_QUEUEING
324       LWIP_ASSERT("update_arp_entry: arp_table[i].p == NULL", arp_table[i].p == NULL);
325 #endif
326     } else {
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);
329     }
330     /* set IP address */
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];
335     }
336     /* reset time-stamp */
337     arp_table[i].ctime = 0;
338     /* mark as stable */
339     arp_table[i].state = ETHARP_STATE_STABLE;
340     /* no queued packet */
341 #if ARP_QUEUEING
342     arp_table[i].p = NULL;
343 #endif
344   }
345   else
346   {
347     LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: no matching stable entry to update\n"));
348   }
349   return NULL;
350 }
351
352 /**
353  * Updates the ARP table using the given packet.
354  *
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.
359  *
360  * @param netif The lwIP network interface on which the IP packet pbuf arrived.
361  * @param pbuf The IP packet that arrived on netif.
362  *
363  * @return NULL
364  *
365  * @see pbuf_free()
366  */
367 struct pbuf *
368 etharp_ip_input(struct netif *netif, struct pbuf *p)
369 {
370   struct ethip_hdr *hdr;
371
372   /* Only insert an entry if the source IP address of the
373      incoming IP packet comes from a host on the local network. */
374   hdr = p->payload;
375   /* source is on local network? */
376   if (!ip_addr_maskcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask))) {
377     /* do nothing */
378     return NULL;
379   }
380
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);
384   return NULL;
385 }
386
387
388 /**
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.
391  *
392  * Should be called for incoming ARP packets. The pbuf in the argument
393  * is freed by this function.
394  *
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.
398  *
399  * @return NULL
400  *
401  * @see pbuf_free()
402  */
403 struct pbuf *
404 etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
405 {
406   struct etharp_hdr *hdr;
407   u8_t i;
408   u8_t for_us;
409
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)));
413     pbuf_free(p);
414     return NULL;
415   }
416
417   hdr = p->payload;
418  
419   /* this interface is not configured? */
420   if (netif->ip_addr.addr == 0) {
421     for_us = 0;
422   } else {
423     /* ARP packet directed to us? */
424     for_us = ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr));
425   }
426
427   switch (htons(hdr->opcode)) {
428   /* ARP request? */
429   case ARP_REQUEST:
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. */
433
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"));
438       pbuf_free(p);
439       return NULL;
440     }
441     /* ARP request for our address? */
442     if (for_us) {
443
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);
447
448       ip_addr_set(&(hdr->dipaddr), &(hdr->sipaddr));
449       ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr));
450
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];
456       }
457
458       hdr->hwtype = htons(HWTYPE_ETHERNET);
459       ARPH_HWLEN_SET(hdr, netif->hwaddr_len);
460
461       hdr->proto = htons(ETHTYPE_IP);
462       ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
463
464       hdr->ethhdr.type = htons(ETHTYPE_ARP);
465       /* return ARP reply */
466       netif->linkoutput(netif, p);
467
468     /* request was not directed to us */
469     } else {
470       LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP request was not for us.\n"));
471     }
472     break;
473   case ARP_REPLY:
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);
479 #endif
480     break;
481   default:
482     LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %d\n", htons(hdr->opcode)));
483     break;
484   }
485   /* add or update entries in the ARP cache */
486   if (for_us) {
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 */
491   } else {
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);
496   }
497   /* free ARP packet */
498   pbuf_free(p);
499   p = NULL;
500   /* nothing to send, we did it! */
501   return NULL;
502 }
503
504 /**
505  * Resolve and fill-in Ethernet address header for outgoing packet.
506  *
507  * If ARP has the Ethernet address in cache, the given packet is
508  * returned, ready to be sent.
509  *
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
513  * the caller.
514  *
515  * If ARP failed to allocate resources, NULL is returned.
516  *
517  * A returned non-NULL packet should be sent by the caller.
518  *
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.
522  *
523  * @return If non-NULL, a packet ready to be sent by caller.
524  *
525  */
526 struct pbuf *
527 etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
528 {
529   struct eth_addr *dest, *srcaddr, mcastaddr;
530   struct eth_hdr *ethhdr;
531   u8_t i;
532
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
536     out if it does.. */
537     LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_output: could not allocate room for header.\n"));
538     LINK_STATS_INC(link.lenerr);
539     return NULL;
540   }
541
542   /* obtain source Ethernet address of the given interface */
543   srcaddr = (struct eth_addr *)netif->hwaddr;
544
545   /* assume unresolved Ethernet address */
546   dest = NULL;
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
550      ARP table. */
551
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 *)&ethbroadcast;
557   }
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 */
568     dest = &mcastaddr;
569   }
570   /* destination IP address is an IP unicast address */
571   else {
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)
577       {
578         /* use the gateway IP address */
579         ipaddr = &(netif->gw);
580       }
581       /* no gateway available? */
582       else
583       {
584         /* IP destination address outside local network, but no gateway available */
585         return NULL;
586       }
587     }
588
589     /* Ethernet address for IP destination address is in ARP cache? */
590     for (i = 0; i < ARP_TABLE_SIZE; ++i) {
591       /* match found? */
592       if (arp_table[i].state == ETHARP_STATE_STABLE &&
593         ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
594         dest = &arp_table[i].ethaddr;
595         break;
596       }
597     }
598     /* could not find the destination Ethernet address in ARP cache? */
599     if (dest == NULL) {
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);
603       /* return nothing */
604       return NULL;
605     }
606     /* destination Ethernet address resolved from ARP cache */
607     else
608     {
609       /* fallthrough */
610     }
611   }
612
613   /* destination Ethernet address known */
614   if (dest != NULL) {
615     /* A valid IP->MAC address mapping was found, so we construct the
616     Ethernet header for the outgoing packet. */
617     ethhdr = q->payload;
618
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];
622     }
623
624     ethhdr->type = htons(ETHTYPE_IP);
625     /* return the outgoing packet */
626     return q;
627   }
628   /* never reached; here for safety */
629   return NULL;
630 }
631
632 /**
633  * Send an ARP request for the given IP address.
634  *
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.
638  *
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.
644  *
645  * @return NULL.
646  *
647  * @note Might be used in the future by manual IP configuration
648  * as well.
649  *
650  * TODO: use the ctime field to see how long ago an ARP request was sent,
651  * possibly retry.
652  */
653 err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
654 {
655   struct eth_addr *srcaddr;
656   struct etharp_hdr *hdr;
657   struct pbuf *p;
658   err_t result = ERR_OK;
659   u8_t i;
660   u8_t perform_arp_request = 1;
661   /* prevent 'unused argument' warning if ARP_QUEUEING == 0 */
662   (void)q;
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 */
672         break;
673       }
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;
679         break;
680       }
681     }
682   }
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"));
691       return ERR_MEM;
692     }
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;
699 #if ARP_QUEUEING
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"));
705     }
706 #endif
707   }
708 #if ARP_QUEUEING
709   /* any pbuf to queue and queue is empty? */
710   if (q != NULL) {
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 */
719     }
720 #endif
721     /* packet can be queued? */
722     if (arp_table[i].p == NULL) {
723       /* copy PBUF_REF referenced payloads into PBUF_RAM */
724       q = pbuf_take(q);
725       /* remember pbuf to queue, if any */
726       arp_table[i].p = q;
727       /* pbufs are queued, increase the reference count */
728       pbuf_ref(q);
729       LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: queued packet %p on ARP entry %u.\n", (void *)q, i));
730     }
731   }
732 #endif
733   /* ARP request? */
734   if (perform_arp_request)
735   {
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? */
739     if (p != NULL) {
740       u8_t j;
741       LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: sending ARP request.\n"));
742       hdr = p->payload;
743       hdr->opcode = htons(ARP_REQUEST);
744       for (j = 0; j < netif->hwaddr_len; ++j)
745       {
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;
750       }
751       ip_addr_set(&(hdr->dipaddr), ipaddr);
752       ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr));
753
754       hdr->hwtype = htons(HWTYPE_ETHERNET);
755       ARPH_HWLEN_SET(hdr, netif->hwaddr_len);
756
757       hdr->proto = htons(ETHTYPE_IP);
758       ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
759       for (j = 0; j < netif->hwaddr_len; ++j)
760       {
761         hdr->ethhdr.dest.addr[j] = 0xff;
762         hdr->ethhdr.src.addr[j] = srcaddr->addr[j];
763       }
764       hdr->ethhdr.type = htons(ETHTYPE_ARP);
765       /* send ARP query */
766       result = netif->linkoutput(netif, p);
767       /* free ARP query packet */
768       pbuf_free(p);
769       p = NULL;
770     } else {
771       result = ERR_MEM;
772       LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_query: could not allocate pbuf for ARP request.\n"));
773     }
774   }
775   return result;
776 }