]> git.sur5r.net Git - freertos/blob - Demo/Common/ethernet/lwIP/netif/etharp.c
9787f6d8d681950fa3da040f0134210ccdaff1bd
[freertos] / Demo / Common / ethernet / lwIP / 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). It supports
10  * Gratuitious ARP from RFC3220 (IP Mobility Support for IPv4) section 4.6
11  * if an interface calls etharp_query(our_netif, its_ip_addr, NULL) upon
12  * address change.
13  */
14
15 /*
16  * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
17  * Copyright (c) 2003-2004 Leon Woestenberg <leon.woestenberg@axon.tv>
18  * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands.
19  * All rights reserved.
20  *
21  * Redistribution and use in source and binary forms, with or without modification,
22  * are permitted provided that the following conditions are met:
23  *
24  * 1. Redistributions of source code must retain the above copyright notice,
25  *    this list of conditions and the following disclaimer.
26  * 2. Redistributions in binary form must reproduce the above copyright notice,
27  *    this list of conditions and the following disclaimer in the documentation
28  *    and/or other materials provided with the distribution.
29  * 3. The name of the author may not be used to endorse or promote products
30  *    derived from this software without specific prior written permission.
31  *
32  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
33  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
34  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
35  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
36  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
37  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
39  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
41  * OF SUCH DAMAGE.
42  *
43  * This file is part of the lwIP TCP/IP stack.
44  *
45  */
46 #include <string.h>
47 #include "lwip/opt.h"
48 #include "lwip/inet.h"
49 #include "netif/etharp.h"
50 #include "lwip/ip.h"
51 #include "lwip/stats.h"
52 #include "lwip/snmp.h"
53
54 /* ARP needs to inform DHCP of any ARP replies? */
55 #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
56 #  include "lwip/dhcp.h"
57 #endif
58
59 /** the time an ARP entry stays valid after its last update,
60  * (240 * 5) seconds = 20 minutes.
61  */
62 #define ARP_MAXAGE 240
63 /** the time an ARP entry stays pending after first request,
64  * (2 * 5) seconds = 10 seconds.
65  * 
66  * @internal Keep this number at least 2, otherwise it might
67  * run out instantly if the timeout occurs directly after a request.
68  */
69 #define ARP_MAXPENDING 2
70
71 #define HWTYPE_ETHERNET 1
72
73 /** ARP message types */
74 #define ARP_REQUEST 1
75 #define ARP_REPLY 2
76
77 #define ARPH_HWLEN(hdr) (ntohs((hdr)->_hwlen_protolen) >> 8)
78 #define ARPH_PROTOLEN(hdr) (ntohs((hdr)->_hwlen_protolen) & 0xff)
79
80 #define ARPH_HWLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons(ARPH_PROTOLEN(hdr) | ((len) << 8))
81 #define ARPH_PROTOLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons((len) | (ARPH_HWLEN(hdr) << 8))
82
83 enum etharp_state {
84   ETHARP_STATE_EMPTY,
85   ETHARP_STATE_PENDING,
86   ETHARP_STATE_STABLE,
87   /** @internal transitional state used in etharp_tmr() for convenience*/
88   ETHARP_STATE_EXPIRED
89 };
90
91 struct etharp_entry {
92 #if ARP_QUEUEING
93   /** 
94    * Pointer to queue of pending outgoing packets on this ARP entry.
95    */
96    struct pbuf *p;
97 #endif
98   struct ip_addr ipaddr;
99   struct eth_addr ethaddr;
100   enum etharp_state state;
101   u8_t ctime;
102   struct netif *netif;
103 };
104
105 static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
106 static struct etharp_entry arp_table[ARP_TABLE_SIZE];
107
108 /**
109  * Try hard to create a new entry - we want the IP address to appear in
110  * the cache (even if this means removing an active entry or so). */
111 #define ETHARP_TRY_HARD 1
112
113 static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags);
114 static err_t update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags);
115 /**
116  * Initializes ARP module.
117  */
118 void
119 etharp_init(void)
120 {
121   u8_t i;
122   /* clear ARP entries */
123   for(i = 0; i < ARP_TABLE_SIZE; ++i) {
124     arp_table[i].state = ETHARP_STATE_EMPTY;
125 #if ARP_QUEUEING
126     arp_table[i].p = NULL;
127 #endif
128     arp_table[i].ctime = 0;
129     arp_table[i].netif = NULL;
130   }
131 }
132
133 /**
134  * Clears expired entries in the ARP table.
135  *
136  * This function should be called every ETHARP_TMR_INTERVAL microseconds (5 seconds),
137  * in order to expire entries in the ARP table.
138  */
139 void
140 etharp_tmr(void)
141 {
142   u8_t i;
143
144   LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n"));
145   /* remove expired entries from the ARP table */
146   for (i = 0; i < ARP_TABLE_SIZE; ++i) {
147     arp_table[i].ctime++;
148     /* stable entry? */
149     if ((arp_table[i].state == ETHARP_STATE_STABLE) &&
150          /* entry has become old? */
151         (arp_table[i].ctime >= ARP_MAXAGE)) {
152       LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired stable entry %"U16_F".\n", (u16_t)i));
153       arp_table[i].state = ETHARP_STATE_EXPIRED;
154     /* pending entry? */
155     } else if (arp_table[i].state == ETHARP_STATE_PENDING) {
156       /* entry unresolved/pending for too long? */
157       if (arp_table[i].ctime >= ARP_MAXPENDING) {
158         LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %"U16_F".\n", (u16_t)i));
159         arp_table[i].state = ETHARP_STATE_EXPIRED;
160 #if ARP_QUEUEING
161       } else if (arp_table[i].p != NULL) {
162         /* resend an ARP query here */
163 #endif
164       }
165     }
166     /* clean up entries that have just been expired */
167     if (arp_table[i].state == ETHARP_STATE_EXPIRED) {
168       /* remove from SNMP ARP index tree */
169       snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr);
170 #if ARP_QUEUEING
171       /* and empty packet queue */
172       if (arp_table[i].p != NULL) {
173         /* remove all queued packets */
174         LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].p)));
175         pbuf_free(arp_table[i].p);
176         arp_table[i].p = NULL;
177       }
178 #endif
179       /* recycle entry for re-use */      
180       arp_table[i].state = ETHARP_STATE_EMPTY;
181     }
182   }
183 }
184
185 /**
186  * Search the ARP table for a matching or new entry.
187  * 
188  * If an IP address is given, return a pending or stable ARP entry that matches
189  * the address. If no match is found, create a new entry with this address set,
190  * but in state ETHARP_EMPTY. The caller must check and possibly change the
191  * state of the returned entry.
192  * 
193  * If ipaddr is NULL, return a initialized new entry in state ETHARP_EMPTY.
194  * 
195  * In all cases, attempt to create new entries from an empty entry. If no
196  * empty entries are available and ETHARP_TRY_HARD flag is set, recycle
197  * old entries. Heuristic choose the least important entry for recycling.
198  *
199  * @param ipaddr IP address to find in ARP cache, or to add if not found.
200  * @param flags
201  * - ETHARP_TRY_HARD: Try hard to create a entry by allowing recycling of
202  * active (stable or pending) entries.
203  *  
204  * @return The ARP entry index that matched or is created, ERR_MEM if no
205  * entry is found or could be recycled.
206  */
207 static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags)
208 {
209   s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE;
210   s8_t empty = ARP_TABLE_SIZE;
211   u8_t i = 0, age_pending = 0, age_stable = 0;
212 #if ARP_QUEUEING
213   /* oldest entry with packets on queue */
214   s8_t old_queue = ARP_TABLE_SIZE;
215   /* its age */
216   u8_t age_queue = 0;
217 #endif
218
219   /**
220    * a) do a search through the cache, remember candidates
221    * b) select candidate entry
222    * c) create new entry
223    */
224
225   /* a) in a single search sweep, do all of this
226    * 1) remember the first empty entry (if any)
227    * 2) remember the oldest stable entry (if any)
228    * 3) remember the oldest pending entry without queued packets (if any)
229    * 4) remember the oldest pending entry with queued packets (if any)
230    * 5) search for a matching IP entry, either pending or stable
231    *    until 5 matches, or all entries are searched for.
232    */
233
234   for (i = 0; i < ARP_TABLE_SIZE; ++i) {
235     /* no empty entry found yet and now we do find one? */
236     if ((empty == ARP_TABLE_SIZE) && (arp_table[i].state == ETHARP_STATE_EMPTY)) {
237       LWIP_DEBUGF(ETHARP_DEBUG, ("find_entry: found empty entry %"U16_F"\n", (u16_t)i));
238       /* remember first empty entry */
239       empty = i;
240     }
241     /* pending entry? */
242     else if (arp_table[i].state == ETHARP_STATE_PENDING) {
243       /* if given, does IP address match IP address in ARP entry? */
244       if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
245         LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: found matching pending entry %"U16_F"\n", (u16_t)i));
246         /* found exact IP address match, simply bail out */
247         return i;
248 #if ARP_QUEUEING
249       /* pending with queued packets? */
250       } else if (arp_table[i].p != NULL) {
251         if (arp_table[i].ctime >= age_queue) {
252           old_queue = i;
253           age_queue = arp_table[i].ctime;
254         }
255 #endif
256       /* pending without queued packets? */
257       } else {
258         if (arp_table[i].ctime >= age_pending) {
259           old_pending = i;
260           age_pending = arp_table[i].ctime;
261         }
262       }        
263     }
264     /* stable entry? */
265     else if (arp_table[i].state == ETHARP_STATE_STABLE) {
266       /* if given, does IP address match IP address in ARP entry? */
267       if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
268         LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: found matching stable entry %"U16_F"\n", (u16_t)i));
269         /* found exact IP address match, simply bail out */
270         return i;
271       /* remember entry with oldest stable entry in oldest, its age in maxtime */
272       } else if (arp_table[i].ctime >= age_stable) {
273         old_stable = i;
274         age_stable = arp_table[i].ctime;
275       }
276     }
277   }
278   /* { we have no match } => try to create a new entry */
279    
280   /* no empty entry found and not allowed to recycle? */
281   if ((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_TRY_HARD) == 0))
282   {
283     return (s8_t)ERR_MEM;
284   }
285   
286   /* b) choose the least destructive entry to recycle:
287    * 1) empty entry
288    * 2) oldest stable entry
289    * 3) oldest pending entry without queued packets
290    * 4) oldest pending entry without queued packets
291    * 
292    * { ETHARP_TRY_HARD is set at this point }
293    */ 
294
295   /* 1) empty entry available? */
296   if (empty < ARP_TABLE_SIZE) {
297     i = empty;
298     LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: selecting empty entry %"U16_F"\n", (u16_t)i));
299   }
300   /* 2) found recyclable stable entry? */
301   else if (old_stable < ARP_TABLE_SIZE) {
302     /* recycle oldest stable*/
303     i = old_stable;
304     LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i));
305 #if ARP_QUEUEING
306     /* no queued packets should exist on stable entries */
307     LWIP_ASSERT("arp_table[i].p == NULL", arp_table[i].p == NULL);
308 #endif
309   /* 3) found recyclable pending entry without queued packets? */
310   } else if (old_pending < ARP_TABLE_SIZE) {
311     /* recycle oldest pending */
312     i = old_pending;
313     LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i));
314 #if ARP_QUEUEING
315   /* 4) found recyclable pending entry with queued packets? */
316   } else if (old_queue < ARP_TABLE_SIZE) {
317     /* recycle oldest pending */
318     i = old_queue;
319     LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].p)));
320     pbuf_free(arp_table[i].p);
321     arp_table[i].p = NULL;
322 #endif
323     /* no empty or recyclable entries found */
324   } else {
325     return (s8_t)ERR_MEM;
326   }
327
328   /* { empty or recyclable entry found } */
329   LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE);
330
331   if (arp_table[i].state != ETHARP_STATE_EMPTY)
332   {
333     snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr);
334   }
335   /* recycle entry (no-op for an already empty entry) */
336   arp_table[i].state = ETHARP_STATE_EMPTY;
337
338   /* IP address given? */
339   if (ipaddr != NULL) {
340     /* set IP address */
341     ip_addr_set(&arp_table[i].ipaddr, ipaddr);
342   }
343   arp_table[i].ctime = 0;
344   return (err_t)i;
345 }
346
347 /**
348  * Update (or insert) a IP/MAC address pair in the ARP cache.
349  *
350  * If a pending entry is resolved, any queued packets will be sent
351  * at this point.
352  * 
353  * @param ipaddr IP address of the inserted ARP entry.
354  * @param ethaddr Ethernet address of the inserted ARP entry.
355  * @param flags Defines behaviour:
356  * - ETHARP_TRY_HARD Allows ARP to insert this as a new item. If not specified,
357  * only existing ARP entries will be updated.
358  *
359  * @return
360  * - ERR_OK Succesfully updated ARP cache.
361  * - ERR_MEM If we could not add a new ARP entry when ETHARP_TRY_HARD was set.
362  * - ERR_ARG Non-unicast address given, those will not appear in ARP cache.
363  *
364  * @see pbuf_free()
365  */
366 static err_t
367 update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags)
368 {
369   s8_t i;
370   u8_t k;
371   LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("update_arp_entry()\n"));
372   LWIP_ASSERT("netif->hwaddr_len != 0", netif->hwaddr_len != 0);
373   LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n",
374                                         ip4_addr1(ipaddr), ip4_addr2(ipaddr), ip4_addr3(ipaddr), ip4_addr4(ipaddr), 
375                                         ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2],
376                                         ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5]));
377   /* non-unicast address? */
378   if (ip_addr_isany(ipaddr) ||
379       ip_addr_isbroadcast(ipaddr, netif) ||
380       ip_addr_ismulticast(ipaddr)) {
381     LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: will not add non-unicast IP address to ARP cache\n"));
382     return ERR_ARG;
383   }
384   /* find or create ARP entry */
385   i = find_entry(ipaddr, flags);
386   /* bail out if no entry could be found */
387   if (i < 0) return (err_t)i;
388   
389   /* mark it stable */
390   arp_table[i].state = ETHARP_STATE_STABLE;
391   /* record network interface */
392   arp_table[i].netif = netif;
393
394   /* insert in SNMP ARP index tree */
395   snmp_insert_arpidx_tree(netif, &arp_table[i].ipaddr);
396
397   LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i));
398   /* update address */
399   k = netif->hwaddr_len;
400   while (k > 0) {
401     k--;
402     arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
403   }
404   /* reset time stamp */
405   arp_table[i].ctime = 0;
406 /* this is where we will send out queued packets! */
407 #if ARP_QUEUEING
408   while (arp_table[i].p != NULL) {
409     /* get the first packet on the queue */
410     struct pbuf *p = arp_table[i].p;
411     /* Ethernet header */
412     struct eth_hdr *ethhdr = p->payload;
413     /* remember (and reference) remainder of queue */
414     /* note: this will also terminate the p pbuf chain */
415     arp_table[i].p = pbuf_dequeue(p);
416     /* fill-in Ethernet header */
417     k = netif->hwaddr_len;
418     while(k > 0) {
419       k--;
420       ethhdr->dest.addr[k] = ethaddr->addr[k];
421       ethhdr->src.addr[k] = netif->hwaddr[k];
422     }
423     ethhdr->type = htons(ETHTYPE_IP);
424     LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: sending queued IP packet %p.\n", (void *)p));
425     /* send the queued IP packet */
426     netif->linkoutput(netif, p);
427     /* free the queued IP packet */
428     pbuf_free(p);
429   }
430 #endif
431   return ERR_OK;
432 }
433
434 /**
435  * Finds (stable) ethernet/IP address pair from ARP table
436  * using interface and IP address index.
437  * @note the addresses in the ARP table are in network order!
438  *
439  * @param netif points to interface index
440  * @param ipaddr points to the (network order) IP address index
441  * @param eth_ret points to return pointer
442  * @param ip_ret points to return pointer
443  * @return table index if found, -1 otherwise
444  */
445 s8_t
446 etharp_find_addr(struct netif *netif, struct ip_addr *ipaddr,
447          struct eth_addr **eth_ret, struct ip_addr **ip_ret)
448 {
449   s8_t i;
450
451   i = 0;
452   while (i < ARP_TABLE_SIZE)
453   {
454     if ((arp_table[i].state == ETHARP_STATE_STABLE) &&
455         (arp_table[i].netif == netif) && 
456         ip_addr_cmp(ipaddr, &arp_table[i].ipaddr) )
457     {
458       *eth_ret = &arp_table[i].ethaddr;
459       *ip_ret = &arp_table[i].ipaddr;
460       return i;
461     }
462     i++;
463   }
464   return -1;
465 }
466
467 /**
468  * Updates the ARP table using the given IP packet.
469  *
470  * Uses the incoming IP packet's source address to update the
471  * ARP cache for the local network. The function does not alter
472  * or free the packet. This function must be called before the
473  * packet p is passed to the IP layer.
474  *
475  * @param netif The lwIP network interface on which the IP packet pbuf arrived.
476  * @param pbuf The IP packet that arrived on netif.
477  *
478  * @return NULL
479  *
480  * @see pbuf_free()
481  */
482 void
483 etharp_ip_input(struct netif *netif, struct pbuf *p)
484 {
485   struct ethip_hdr *hdr;
486   LWIP_ASSERT("netif != NULL", netif != NULL);
487   /* Only insert an entry if the source IP address of the
488      incoming IP packet comes from a host on the local network. */
489   hdr = p->payload;
490   /* source is not on the local network? */
491   if (!ip_addr_netcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask))) {
492     /* do nothing */
493     return;
494   }
495
496   LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n"));
497   /* update ARP table */
498   /* @todo We could use ETHARP_TRY_HARD if we think we are going to talk
499    * back soon (for example, if the destination IP address is ours. */
500   update_arp_entry(netif, &(hdr->ip.src), &(hdr->eth.src), 0);
501 }
502
503
504 /**
505  * Responds to ARP requests to us. Upon ARP replies to us, add entry to cache  
506  * send out queued IP packets. Updates cache with snooped address pairs.
507  *
508  * Should be called for incoming ARP packets. The pbuf in the argument
509  * is freed by this function.
510  *
511  * @param netif The lwIP network interface on which the ARP packet pbuf arrived.
512  * @param pbuf The ARP packet that arrived on netif. Is freed by this function.
513  * @param ethaddr Ethernet address of netif.
514  *
515  * @return NULL
516  *
517  * @see pbuf_free()
518  */
519 void
520 etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
521 {
522   struct etharp_hdr *hdr;
523   /* these are aligned properly, whereas the ARP header fields might not be */
524   struct ip_addr sipaddr, dipaddr;
525   u8_t i;
526   u8_t for_us;
527
528   LWIP_ASSERT("netif != NULL", netif != NULL);
529   
530   /* drop short ARP packets */
531   if (p->tot_len < sizeof(struct etharp_hdr)) {
532     LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 1, ("etharp_arp_input: packet dropped, too short (%"S16_F"/%"S16_F")\n", p->tot_len, (s16_t)sizeof(struct etharp_hdr)));
533     pbuf_free(p);
534     return;
535   }
536
537   hdr = p->payload;
538  
539   /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
540    * structure packing (not using structure copy which breaks strict-aliasing rules). */
541   memcpy(&sipaddr, &hdr->sipaddr, sizeof(sipaddr));
542   memcpy(&dipaddr, &hdr->dipaddr, sizeof(dipaddr));
543
544   /* this interface is not configured? */
545   if (netif->ip_addr.addr == 0) {
546     for_us = 0;
547   } else {
548     /* ARP packet directed to us? */
549     for_us = ip_addr_cmp(&dipaddr, &(netif->ip_addr));
550   }
551
552   /* ARP message directed to us? */
553   if (for_us) {
554     /* add IP address in ARP cache; assume requester wants to talk to us.
555      * can result in directly sending the queued packets for this host. */
556     update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), ETHARP_TRY_HARD);
557   /* ARP message not directed to us? */
558   } else {
559     /* update the source IP address in the cache, if present */
560     update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), 0);
561   }
562
563   /* now act on the message itself */
564   switch (htons(hdr->opcode)) {
565   /* ARP request? */
566   case ARP_REQUEST:
567     /* ARP request. If it asked for our address, we send out a
568      * reply. In any case, we time-stamp any existing ARP entry,
569      * and possiby send out an IP packet that was queued on it. */
570
571     LWIP_DEBUGF (ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP request\n"));
572     /* ARP request for our address? */
573     if (for_us) {
574
575       LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: replying to ARP request for our IP address\n"));
576       /* re-use pbuf to send ARP reply */
577       hdr->opcode = htons(ARP_REPLY);
578
579       hdr->dipaddr = hdr->sipaddr;
580       hdr->sipaddr = *(struct ip_addr2 *)&netif->ip_addr;
581
582       i = netif->hwaddr_len;
583       while(i > 0) {
584         i--;
585         hdr->dhwaddr.addr[i] = hdr->shwaddr.addr[i];
586         hdr->shwaddr.addr[i] = ethaddr->addr[i];
587         hdr->ethhdr.dest.addr[i] = hdr->dhwaddr.addr[i];
588         hdr->ethhdr.src.addr[i] = ethaddr->addr[i];
589       }
590
591       hdr->hwtype = htons(HWTYPE_ETHERNET);
592       ARPH_HWLEN_SET(hdr, netif->hwaddr_len);
593
594       hdr->proto = htons(ETHTYPE_IP);
595       ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
596
597       hdr->ethhdr.type = htons(ETHTYPE_ARP);
598       /* return ARP reply */
599       netif->linkoutput(netif, p);
600     /* we are not configured? */
601     } else if (netif->ip_addr.addr == 0) {
602       /* { for_us == 0 and netif->ip_addr.addr == 0 } */
603       LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n"));
604     /* request was not directed to us */
605     } else {
606       /* { for_us == 0 and netif->ip_addr.addr != 0 } */
607       LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: ARP request was not for us.\n"));
608     }
609     break;
610   case ARP_REPLY:
611     /* ARP reply. We already updated the ARP cache earlier. */
612     LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n"));
613 #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
614     /* DHCP wants to know about ARP replies from any host with an
615      * IP address also offered to us by the DHCP server. We do not
616      * want to take a duplicate IP address on a single network.
617      * @todo How should we handle redundant (fail-over) interfaces?
618      * */
619     dhcp_arp_reply(netif, &sipaddr);
620 #endif
621     break;
622   default:
623     LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %"S16_F"\n", htons(hdr->opcode)));
624     break;
625   }
626   /* free ARP packet */
627   pbuf_free(p);
628 }
629
630 /**
631  * Resolve and fill-in Ethernet address header for outgoing packet.
632  *
633  * For IP multicast and broadcast, corresponding Ethernet addresses
634  * are selected and the packet is transmitted on the link.
635  *
636  * For unicast addresses, the packet is submitted to etharp_query(). In
637  * case the IP address is outside the local network, the IP address of
638  * the gateway is used.
639  *
640  * @param netif The lwIP network interface which the IP packet will be sent on.
641  * @param ipaddr The IP address of the packet destination.
642  * @param pbuf The pbuf(s) containing the IP packet to be sent.
643  *
644  * @return
645  * - ERR_RTE No route to destination (no gateway to external networks),
646  * or the return type of either etharp_query() or netif->linkoutput().
647  */
648 err_t
649 etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
650 {
651   struct eth_addr *dest, *srcaddr, mcastaddr;
652   struct eth_hdr *ethhdr;
653   u8_t i;
654
655   /* make room for Ethernet header - should not fail */
656   if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
657     /* bail out */
658     LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_output: could not allocate room for header.\n"));
659     LINK_STATS_INC(link.lenerr);
660     return ERR_BUF;
661   }
662
663   /* assume unresolved Ethernet address */
664   dest = NULL;
665   /* Determine on destination hardware address. Broadcasts and multicasts
666    * are special, other IP addresses are looked up in the ARP table. */
667
668   /* broadcast destination IP address? */
669   if (ip_addr_isbroadcast(ipaddr, netif)) {
670     /* broadcast on Ethernet also */
671     dest = (struct eth_addr *)&ethbroadcast;
672   /* multicast destination IP address? */
673   } else if (ip_addr_ismulticast(ipaddr)) {
674     /* Hash IP multicast address to MAC address.*/
675     mcastaddr.addr[0] = 0x01;
676     mcastaddr.addr[1] = 0x00;
677     mcastaddr.addr[2] = 0x5e;
678     mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
679     mcastaddr.addr[4] = ip4_addr3(ipaddr);
680     mcastaddr.addr[5] = ip4_addr4(ipaddr);
681     /* destination Ethernet address is multicast */
682     dest = &mcastaddr;
683   /* unicast destination IP address? */
684   } else {
685     /* outside local network? */
686     if (!ip_addr_netcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {
687       /* interface has default gateway? */
688       if (netif->gw.addr != 0) {
689         /* send to hardware address of default gateway IP address */
690         ipaddr = &(netif->gw);
691       /* no default gateway available */
692       } else {
693         /* no route to destination error (default gateway missing) */
694         return ERR_RTE;
695       }
696     }
697     /* queue on destination Ethernet address belonging to ipaddr */
698     return etharp_query(netif, ipaddr, q);
699   }
700
701   /* continuation for multicast/broadcast destinations */
702   /* obtain source Ethernet address of the given interface */
703   srcaddr = (struct eth_addr *)netif->hwaddr;
704   ethhdr = q->payload;
705   i = netif->hwaddr_len;
706   while(i > 0) {
707     i--;
708     ethhdr->dest.addr[i] = dest->addr[i];
709     ethhdr->src.addr[i] = srcaddr->addr[i];
710   }
711   ethhdr->type = htons(ETHTYPE_IP);
712   /* send packet directly on the link */
713   return netif->linkoutput(netif, q);
714 }
715
716 /**
717  * Send an ARP request for the given IP address and/or queue a packet.
718  *
719  * If the IP address was not yet in the cache, a pending ARP cache entry
720  * is added and an ARP request is sent for the given address. The packet
721  * is queued on this entry.
722  *
723  * If the IP address was already pending in the cache, a new ARP request
724  * is sent for the given address. The packet is queued on this entry.
725  *
726  * If the IP address was already stable in the cache, and a packet is
727  * given, it is directly sent and no ARP request is sent out. 
728  * 
729  * If the IP address was already stable in the cache, and no packet is
730  * given, an ARP request is sent out.
731  * 
732  * @param netif The lwIP network interface on which ipaddr
733  * must be queried for.
734  * @param ipaddr The IP address to be resolved.
735  * @param q If non-NULL, a pbuf that must be delivered to the IP address.
736  * q is not freed by this function.
737  *
738  * @return
739  * - ERR_BUF Could not make room for Ethernet header.
740  * - ERR_MEM Hardware address unknown, and no more ARP entries available
741  *   to query for address or queue the packet.
742  * - ERR_MEM Could not queue packet due to memory shortage.
743  * - ERR_RTE No route to destination (no gateway to external networks).
744  * - ERR_ARG Non-unicast address given, those will not appear in ARP cache.
745  *
746  */
747 err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
748 {
749   struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr;
750   err_t result = ERR_MEM;
751   s8_t i; /* ARP entry index */
752   u8_t k; /* Ethernet address octet index */
753
754   /* non-unicast address? */
755   if (ip_addr_isbroadcast(ipaddr, netif) ||
756       ip_addr_ismulticast(ipaddr) ||
757       ip_addr_isany(ipaddr)) {
758     LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n"));
759     return ERR_ARG;
760   }
761
762   /* find entry in ARP cache, ask to create entry if queueing packet */
763   i = find_entry(ipaddr, ETHARP_TRY_HARD);
764
765   /* could not find or create entry? */
766   if (i < 0)
767   {
768     LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: could not create ARP entry\n"));
769     if (q) LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: packet dropped\n"));
770     return (err_t)i;
771   }
772
773   /* mark a fresh entry as pending (we just sent a request) */
774   if (arp_table[i].state == ETHARP_STATE_EMPTY) {
775     arp_table[i].state = ETHARP_STATE_PENDING;
776   }
777
778   /* { i is either a STABLE or (new or existing) PENDING entry } */
779   LWIP_ASSERT("arp_table[i].state == PENDING or STABLE",
780   ((arp_table[i].state == ETHARP_STATE_PENDING) ||
781    (arp_table[i].state == ETHARP_STATE_STABLE)));
782
783   /* do we have a pending entry? or an implicit query request? */
784   if ((arp_table[i].state == ETHARP_STATE_PENDING) || (q == NULL)) {
785     /* try to resolve it; send out ARP request */
786     result = etharp_request(netif, ipaddr);
787   }
788   
789   /* packet given? */
790   if (q != NULL) {
791     /* stable entry? */
792     if (arp_table[i].state == ETHARP_STATE_STABLE) {
793       /* we have a valid IP->Ethernet address mapping,
794        * fill in the Ethernet header for the outgoing packet */
795       struct eth_hdr *ethhdr = q->payload;
796       k = netif->hwaddr_len;
797       while(k > 0) {
798         k--;
799         ethhdr->dest.addr[k] = arp_table[i].ethaddr.addr[k];
800         ethhdr->src.addr[k]  = srcaddr->addr[k];
801       }
802       ethhdr->type = htons(ETHTYPE_IP);
803       LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: sending packet %p\n", (void *)q));
804       /* send the packet */
805       result = netif->linkoutput(netif, q);
806     /* pending entry? (either just created or already pending */
807     } else if (arp_table[i].state == ETHARP_STATE_PENDING) {
808 #if ARP_QUEUEING /* queue the given q packet */
809       struct pbuf *p;
810       /* copy any PBUF_REF referenced payloads into PBUF_RAM */
811       /* (the caller of lwIP assumes the referenced payload can be
812        * freed after it returns from the lwIP call that brought us here) */
813       p = pbuf_take(q);
814       /* packet could be taken over? */
815       if (p != NULL) {
816         /* queue packet ... */
817         if (arp_table[i].p == NULL) {
818           /* ... in the empty queue */
819           pbuf_ref(p);
820           arp_table[i].p = p;
821 #if 0 /* multi-packet-queueing disabled, see bug #11400 */
822         } else {
823           /* ... at tail of non-empty queue */
824           pbuf_queue(arp_table[i].p, p);
825 #endif
826         }
827         LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
828         result = ERR_OK;
829       } else {
830         LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));
831         /* { result == ERR_MEM } through initialization */
832       }
833 #else /* ARP_QUEUEING == 0 */
834       /* q && state == PENDING && ARP_QUEUEING == 0 => result = ERR_MEM */
835       /* { result == ERR_MEM } through initialization */
836       LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: Ethernet destination address unknown, queueing disabled, packet %p dropped\n", (void *)q));
837 #endif
838     }
839   }
840   return result;
841 }
842
843 err_t etharp_request(struct netif *netif, struct ip_addr *ipaddr)
844 {
845   struct pbuf *p;
846   struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr;
847   err_t result = ERR_OK;
848   u8_t k; /* ARP entry index */
849
850   /* allocate a pbuf for the outgoing ARP request packet */
851   p = pbuf_alloc(PBUF_LINK, sizeof(struct etharp_hdr), PBUF_RAM);
852   /* could allocate a pbuf for an ARP request? */
853   if (p != NULL) {
854     struct etharp_hdr *hdr = p->payload;
855     LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_request: sending ARP request.\n"));
856     hdr->opcode = htons(ARP_REQUEST);
857     k = netif->hwaddr_len;
858     while(k > 0) {
859       k--;
860       hdr->shwaddr.addr[k] = srcaddr->addr[k];
861       /* the hardware address is what we ask for, in
862        * a request it is a don't-care value, we use zeroes */
863       hdr->dhwaddr.addr[k] = 0x00;
864     }
865     hdr->dipaddr = *(struct ip_addr2 *)ipaddr;
866     hdr->sipaddr = *(struct ip_addr2 *)&netif->ip_addr;
867
868     hdr->hwtype = htons(HWTYPE_ETHERNET);
869     ARPH_HWLEN_SET(hdr, netif->hwaddr_len);
870
871     hdr->proto = htons(ETHTYPE_IP);
872     ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
873     k = netif->hwaddr_len;
874     while(k > 0) {
875       k--;
876       /* broadcast to all network interfaces on the local network */
877       hdr->ethhdr.dest.addr[k] = 0xff;
878       hdr->ethhdr.src.addr[k] = srcaddr->addr[k];
879     }
880     hdr->ethhdr.type = htons(ETHTYPE_ARP);
881     /* send ARP query */
882     result = netif->linkoutput(netif, p);
883     /* free ARP query packet */
884     pbuf_free(p);
885     p = NULL;
886   /* could not allocate pbuf for ARP request */
887   } else {
888     result = ERR_MEM;
889     LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_request: could not allocate pbuf for ARP request.\n"));
890   }
891   return result;
892 }