source: arduino-1-6-7/trunk/fuentes/arduino-ide-amd64/hardware/arduino/avr/firmwares/wifishield/wifiHD/src/SOFTWARE_FRAMEWORK/SERVICES/LWIP/lwip-1.3.2/src/netif/etharp.c @ 4837

Last change on this file since 4837 was 4837, checked in by daduve, 2 years ago

Adding new version

File size: 44.1 KB
Line 
1/* This source file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */
2
3/**
4 * @file
5 * Address Resolution Protocol module for IP over Ethernet
6 *
7 * Functionally, ARP is divided into two parts. The first maps an IP address
8 * to a physical address when sending a packet, and the second part answers
9 * requests from other machines for our physical address.
10 *
11 * This implementation complies with RFC 826 (Ethernet ARP). It supports
12 * Gratuitious ARP from RFC3220 (IP Mobility Support for IPv4) section 4.6
13 * if an interface calls etharp_gratuitous(our_netif) upon address change.
14 */
15
16/*
17 * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
18 * Copyright (c) 2003-2004 Leon Woestenberg <leon.woestenberg@axon.tv>
19 * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands.
20 * All rights reserved.
21 *
22 * Redistribution and use in source and binary forms, with or without modification,
23 * are permitted provided that the following conditions are met:
24 *
25 * 1. Redistributions of source code must retain the above copyright notice,
26 *    this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright notice,
28 *    this list of conditions and the following disclaimer in the documentation
29 *    and/or other materials provided with the distribution.
30 * 3. The name of the author may not be used to endorse or promote products
31 *    derived from this software without specific prior written permission.
32 *
33 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
34 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
35 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
36 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
37 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
38 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
39 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
40 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
42 * OF SUCH DAMAGE.
43 *
44 * This file is part of the lwIP TCP/IP stack.
45 *
46 */
47 
48#include "lwip/opt.h"
49
50#if LWIP_ARP /* don't build if not configured for use in lwipopts.h */
51
52#include "lwip/inet.h"
53#include "lwip/ip.h"
54#include "lwip/stats.h"
55#include "lwip/snmp.h"
56#include "lwip/dhcp.h"
57#include "lwip/autoip.h"
58#include "netif/etharp.h"
59
60#if PPPOE_SUPPORT
61#include "netif/ppp_oe.h"
62#endif /* PPPOE_SUPPORT */
63
64#include <string.h>
65
66/** the time an ARP entry stays valid after its last update,
67 *  for ARP_TMR_INTERVAL = 5000, this is
68 *  (240 * 5) seconds = 20 minutes.
69 */
70#define ARP_MAXAGE 240
71/** the time an ARP entry stays pending after first request,
72 *  for ARP_TMR_INTERVAL = 5000, this is
73 *  (2 * 5) seconds = 10 seconds.
74 *
75 *  @internal Keep this number at least 2, otherwise it might
76 *  run out instantly if the timeout occurs directly after a request.
77 */
78#define ARP_MAXPENDING 2
79
80#define HWTYPE_ETHERNET 1
81
82#define ARPH_HWLEN(hdr) (ntohs((hdr)->_hwlen_protolen) >> 8)
83#define ARPH_PROTOLEN(hdr) (ntohs((hdr)->_hwlen_protolen) & 0xff)
84
85#define ARPH_HWLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons(ARPH_PROTOLEN(hdr) | ((len) << 8))
86#define ARPH_PROTOLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons((len) | (ARPH_HWLEN(hdr) << 8))
87
88enum etharp_state {
89  ETHARP_STATE_EMPTY = 0,
90  ETHARP_STATE_PENDING,
91  ETHARP_STATE_STABLE
92};
93
94struct etharp_entry {
95#if ARP_QUEUEING
96  /**
97   * Pointer to queue of pending outgoing packets on this ARP entry.
98   */
99  struct etharp_q_entry *q;
100#endif
101  struct ip_addr ipaddr;
102  struct eth_addr ethaddr;
103  enum etharp_state state;
104  u8_t ctime;
105  struct netif *netif;
106};
107
108const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
109const struct eth_addr ethzero = {{0,0,0,0,0,0}};
110static struct etharp_entry arp_table[ARP_TABLE_SIZE];
111#if !LWIP_NETIF_HWADDRHINT
112static u8_t etharp_cached_entry;
113#endif
114
115/**
116 * Try hard to create a new entry - we want the IP address to appear in
117 * the cache (even if this means removing an active entry or so). */
118#define ETHARP_TRY_HARD 1
119#define ETHARP_FIND_ONLY  2
120
121#if LWIP_NETIF_HWADDRHINT
122#define NETIF_SET_HINT(netif, hint)  if (((netif) != NULL) && ((netif)->addr_hint != NULL))  \
123                                      *((netif)->addr_hint) = (hint);
124static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags, struct netif *netif);
125#else /* LWIP_NETIF_HWADDRHINT */
126static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags);
127#endif /* LWIP_NETIF_HWADDRHINT */
128
129static err_t update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags);
130
131
132/* Some checks, instead of etharp_init(): */
133#if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f))
134  #error "If you want to use ARP, ARP_TABLE_SIZE must fit in an s8_t, so, you have to reduce it in your lwipopts.h"
135#endif
136
137
138#if ARP_QUEUEING
139/**
140 * Free a complete queue of etharp entries
141 *
142 * @param q a qeueue of etharp_q_entry's to free
143 */
144static void
145free_etharp_q(struct etharp_q_entry *q)
146{
147  struct etharp_q_entry *r;
148  LWIP_ASSERT("q != NULL", q != NULL);
149  LWIP_ASSERT("q->p != NULL", q->p != NULL);
150  while (q) {
151    r = q;
152    q = q->next;
153    LWIP_ASSERT("r->p != NULL", (r->p != NULL));
154    pbuf_free(r->p);
155    memp_free(MEMP_ARP_QUEUE, r);
156  }
157}
158#endif
159
160/**
161 * Clears expired entries in the ARP table.
162 *
163 * This function should be called every ETHARP_TMR_INTERVAL microseconds (5 seconds),
164 * in order to expire entries in the ARP table.
165 */
166void
167etharp_tmr(void)
168{
169  u8_t i;
170
171  LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n"));
172  /* remove expired entries from the ARP table */
173  for (i = 0; i < ARP_TABLE_SIZE; ++i) {
174    arp_table[i].ctime++;
175    if (((arp_table[i].state == ETHARP_STATE_STABLE) &&
176         (arp_table[i].ctime >= ARP_MAXAGE)) ||
177        ((arp_table[i].state == ETHARP_STATE_PENDING)  &&
178         (arp_table[i].ctime >= ARP_MAXPENDING))) {
179         /* pending or stable entry has become old! */
180      LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n",
181           arp_table[i].state == ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i));
182      /* clean up entries that have just been expired */
183      /* remove from SNMP ARP index tree */
184      snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr);
185#if ARP_QUEUEING
186      /* and empty packet queue */
187      if (arp_table[i].q != NULL) {
188        /* remove all queued packets */
189        LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].q)));
190        free_etharp_q(arp_table[i].q);
191        arp_table[i].q = NULL;
192      }
193#endif
194      /* recycle entry for re-use */     
195      arp_table[i].state = ETHARP_STATE_EMPTY;
196    }
197#if ARP_QUEUEING
198    /* still pending entry? (not expired) */
199    if (arp_table[i].state == ETHARP_STATE_PENDING) {
200        /* resend an ARP query here? */
201    }
202#endif
203  }
204}
205
206/**
207 * Search the ARP table for a matching or new entry.
208 *
209 * If an IP address is given, return a pending or stable ARP entry that matches
210 * the address. If no match is found, create a new entry with this address set,
211 * but in state ETHARP_EMPTY. The caller must check and possibly change the
212 * state of the returned entry.
213 *
214 * If ipaddr is NULL, return a initialized new entry in state ETHARP_EMPTY.
215 *
216 * In all cases, attempt to create new entries from an empty entry. If no
217 * empty entries are available and ETHARP_TRY_HARD flag is set, recycle
218 * old entries. Heuristic choose the least important entry for recycling.
219 *
220 * @param ipaddr IP address to find in ARP cache, or to add if not found.
221 * @param flags
222 * - ETHARP_TRY_HARD: Try hard to create a entry by allowing recycling of
223 * active (stable or pending) entries.
224 * 
225 * @return The ARP entry index that matched or is created, ERR_MEM if no
226 * entry is found or could be recycled.
227 */
228static s8_t
229#if LWIP_NETIF_HWADDRHINT
230find_entry(struct ip_addr *ipaddr, u8_t flags, struct netif *netif)
231#else /* LWIP_NETIF_HWADDRHINT */
232find_entry(struct ip_addr *ipaddr, u8_t flags)
233#endif /* LWIP_NETIF_HWADDRHINT */
234{
235  s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE;
236  s8_t empty = ARP_TABLE_SIZE;
237  u8_t i = 0, age_pending = 0, age_stable = 0;
238#if ARP_QUEUEING
239  /* oldest entry with packets on queue */
240  s8_t old_queue = ARP_TABLE_SIZE;
241  /* its age */
242  u8_t age_queue = 0;
243#endif
244
245  /* First, test if the last call to this function asked for the
246   * same address. If so, we're really fast! */
247  if (ipaddr) {
248    /* ipaddr to search for was given */
249#if LWIP_NETIF_HWADDRHINT
250    if ((netif != NULL) && (netif->addr_hint != NULL)) {
251      /* per-pcb cached entry was given */
252      u8_t per_pcb_cache = *(netif->addr_hint);
253      if ((per_pcb_cache < ARP_TABLE_SIZE) && arp_table[per_pcb_cache].state == ETHARP_STATE_STABLE) {
254        /* the per-pcb-cached entry is stable */
255        if (ip_addr_cmp(ipaddr, &arp_table[per_pcb_cache].ipaddr)) {
256          /* per-pcb cached entry was the right one! */
257          ETHARP_STATS_INC(etharp.cachehit);
258          return per_pcb_cache;
259        }
260      }
261    }
262#else /* #if LWIP_NETIF_HWADDRHINT */
263    if (arp_table[etharp_cached_entry].state == ETHARP_STATE_STABLE) {
264      /* the cached entry is stable */
265      if (ip_addr_cmp(ipaddr, &arp_table[etharp_cached_entry].ipaddr)) {
266        /* cached entry was the right one! */
267        ETHARP_STATS_INC(etharp.cachehit);
268        return etharp_cached_entry;
269      }
270    }
271#endif /* #if LWIP_NETIF_HWADDRHINT */
272  }
273
274  /**
275   * a) do a search through the cache, remember candidates
276   * b) select candidate entry
277   * c) create new entry
278   */
279
280  /* a) in a single search sweep, do all of this
281   * 1) remember the first empty entry (if any)
282   * 2) remember the oldest stable entry (if any)
283   * 3) remember the oldest pending entry without queued packets (if any)
284   * 4) remember the oldest pending entry with queued packets (if any)
285   * 5) search for a matching IP entry, either pending or stable
286   *    until 5 matches, or all entries are searched for.
287   */
288
289  for (i = 0; i < ARP_TABLE_SIZE; ++i) {
290    /* no empty entry found yet and now we do find one? */
291    if ((empty == ARP_TABLE_SIZE) && (arp_table[i].state == ETHARP_STATE_EMPTY)) {
292      LWIP_DEBUGF(ETHARP_DEBUG, ("find_entry: found empty entry %"U16_F"\n", (u16_t)i));
293      /* remember first empty entry */
294      empty = i;
295    }
296    /* pending entry? */
297    else if (arp_table[i].state == ETHARP_STATE_PENDING) {
298      /* if given, does IP address match IP address in ARP entry? */
299      if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
300        LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: found matching pending entry %"U16_F"\n", (u16_t)i));
301        /* found exact IP address match, simply bail out */
302#if LWIP_NETIF_HWADDRHINT
303        NETIF_SET_HINT(netif, i);
304#else /* #if LWIP_NETIF_HWADDRHINT */
305        etharp_cached_entry = i;
306#endif /* #if LWIP_NETIF_HWADDRHINT */
307        return i;
308#if ARP_QUEUEING
309      /* pending with queued packets? */
310      } else if (arp_table[i].q != NULL) {
311        if (arp_table[i].ctime >= age_queue) {
312          old_queue = i;
313          age_queue = arp_table[i].ctime;
314        }
315#endif
316      /* pending without queued packets? */
317      } else {
318        if (arp_table[i].ctime >= age_pending) {
319          old_pending = i;
320          age_pending = arp_table[i].ctime;
321        }
322      }       
323    }
324    /* stable entry? */
325    else if (arp_table[i].state == ETHARP_STATE_STABLE) {
326      /* if given, does IP address match IP address in ARP entry? */
327      if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
328        LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: found matching stable entry %"U16_F"\n", (u16_t)i));
329        /* found exact IP address match, simply bail out */
330#if LWIP_NETIF_HWADDRHINT
331        NETIF_SET_HINT(netif, i);
332#else /* #if LWIP_NETIF_HWADDRHINT */
333        etharp_cached_entry = i;
334#endif /* #if LWIP_NETIF_HWADDRHINT */
335        return i;
336      /* remember entry with oldest stable entry in oldest, its age in maxtime */
337      } else if (arp_table[i].ctime >= age_stable) {
338        old_stable = i;
339        age_stable = arp_table[i].ctime;
340      }
341    }
342  }
343  /* { we have no match } => try to create a new entry */
344   
345  /* no empty entry found and not allowed to recycle? */
346  if (((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_TRY_HARD) == 0))
347      /* or don't create new entry, only search? */
348      || ((flags & ETHARP_FIND_ONLY) != 0)) {
349    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: no empty entry found and not allowed to recycle\n"));
350    return (s8_t)ERR_MEM;
351  }
352 
353  /* b) choose the least destructive entry to recycle:
354   * 1) empty entry
355   * 2) oldest stable entry
356   * 3) oldest pending entry without queued packets
357   * 4) oldest pending entry with queued packets
358   *
359   * { ETHARP_TRY_HARD is set at this point }
360   */ 
361
362  /* 1) empty entry available? */
363  if (empty < ARP_TABLE_SIZE) {
364    i = empty;
365    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting empty entry %"U16_F"\n", (u16_t)i));
366  }
367  /* 2) found recyclable stable entry? */
368  else if (old_stable < ARP_TABLE_SIZE) {
369    /* recycle oldest stable*/
370    i = old_stable;
371    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i));
372#if ARP_QUEUEING
373    /* no queued packets should exist on stable entries */
374    LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL);
375#endif
376  /* 3) found recyclable pending entry without queued packets? */
377  } else if (old_pending < ARP_TABLE_SIZE) {
378    /* recycle oldest pending */
379    i = old_pending;
380    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i));
381#if ARP_QUEUEING
382  /* 4) found recyclable pending entry with queued packets? */
383  } else if (old_queue < ARP_TABLE_SIZE) {
384    /* recycle oldest pending */
385    i = old_queue;
386    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q)));
387    free_etharp_q(arp_table[i].q);
388    arp_table[i].q = NULL;
389#endif
390    /* no empty or recyclable entries found */
391  } else {
392    return (s8_t)ERR_MEM;
393  }
394
395  /* { empty or recyclable entry found } */
396  LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE);
397
398  if (arp_table[i].state != ETHARP_STATE_EMPTY)
399  {
400    snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr);
401  }
402  /* recycle entry (no-op for an already empty entry) */
403  arp_table[i].state = ETHARP_STATE_EMPTY;
404
405  /* IP address given? */
406  if (ipaddr != NULL) {
407    /* set IP address */
408    ip_addr_set(&arp_table[i].ipaddr, ipaddr);
409  }
410  arp_table[i].ctime = 0;
411#if LWIP_NETIF_HWADDRHINT
412  NETIF_SET_HINT(netif, i);
413#else /* #if LWIP_NETIF_HWADDRHINT */
414  etharp_cached_entry = i;
415#endif /* #if LWIP_NETIF_HWADDRHINT */
416  return (err_t)i;
417}
418
419/**
420 * Send an IP packet on the network using netif->linkoutput
421 * The ethernet header is filled in before sending.
422 *
423 * @params netif the lwIP network interface on which to send the packet
424 * @params p the packet to send, p->payload pointing to the (uninitialized) ethernet header
425 * @params src the source MAC address to be copied into the ethernet header
426 * @params dst the destination MAC address to be copied into the ethernet header
427 * @return ERR_OK if the packet was sent, any other err_t on failure
428 */
429static err_t
430etharp_send_ip(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst)
431{
432  struct eth_hdr *ethhdr = p->payload;
433  u8_t k;
434
435  LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",
436              (netif->hwaddr_len == ETHARP_HWADDR_LEN));
437  k = ETHARP_HWADDR_LEN;
438  while(k > 0) {
439    k--;
440    ethhdr->dest.addr[k] = dst->addr[k];
441    ethhdr->src.addr[k]  = src->addr[k];
442  }
443  ethhdr->type = htons(ETHTYPE_IP);
444  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_send_ip: sending packet %p\n", (void *)p));
445  /* send the packet */
446  return netif->linkoutput(netif, p);
447}
448
449/**
450 * Update (or insert) a IP/MAC address pair in the ARP cache.
451 *
452 * If a pending entry is resolved, any queued packets will be sent
453 * at this point.
454 *
455 * @param ipaddr IP address of the inserted ARP entry.
456 * @param ethaddr Ethernet address of the inserted ARP entry.
457 * @param flags Defines behaviour:
458 * - ETHARP_TRY_HARD Allows ARP to insert this as a new item. If not specified,
459 * only existing ARP entries will be updated.
460 *
461 * @return
462 * - ERR_OK Succesfully updated ARP cache.
463 * - ERR_MEM If we could not add a new ARP entry when ETHARP_TRY_HARD was set.
464 * - ERR_ARG Non-unicast address given, those will not appear in ARP cache.
465 *
466 * @see pbuf_free()
467 */
468static err_t
469update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags)
470{
471  s8_t i;
472  u8_t k;
473  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry()\n"));
474  LWIP_ASSERT("netif->hwaddr_len == ETHARP_HWADDR_LEN", netif->hwaddr_len == ETHARP_HWADDR_LEN);
475  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_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",
476                                        ip4_addr1(ipaddr), ip4_addr2(ipaddr), ip4_addr3(ipaddr), ip4_addr4(ipaddr), 
477                                        ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2],
478                                        ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5]));
479  /* non-unicast address? */
480  if (ip_addr_isany(ipaddr) ||
481      ip_addr_isbroadcast(ipaddr, netif) ||
482      ip_addr_ismulticast(ipaddr)) {
483    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: will not add non-unicast IP address to ARP cache\n"));
484    return ERR_ARG;
485  }
486  /* find or create ARP entry */
487#if LWIP_NETIF_HWADDRHINT
488  i = find_entry(ipaddr, flags, netif);
489#else /* LWIP_NETIF_HWADDRHINT */
490  i = find_entry(ipaddr, flags);
491#endif /* LWIP_NETIF_HWADDRHINT */
492  /* bail out if no entry could be found */
493  if (i < 0)
494    return (err_t)i;
495 
496  /* mark it stable */
497  arp_table[i].state = ETHARP_STATE_STABLE;
498  /* record network interface */
499  arp_table[i].netif = netif;
500
501  /* insert in SNMP ARP index tree */
502  snmp_insert_arpidx_tree(netif, &arp_table[i].ipaddr);
503
504  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i));
505  /* update address */
506  k = ETHARP_HWADDR_LEN;
507  while (k > 0) {
508    k--;
509    arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
510  }
511  /* reset time stamp */
512  arp_table[i].ctime = 0;
513#if ARP_QUEUEING
514  /* this is where we will send out queued packets! */
515  while (arp_table[i].q != NULL) {
516    struct pbuf *p;
517    /* remember remainder of queue */
518    struct etharp_q_entry *q = arp_table[i].q;
519    /* pop first item off the queue */
520    arp_table[i].q = q->next;
521    /* get the packet pointer */
522    p = q->p;
523    /* now queue entry can be freed */
524    memp_free(MEMP_ARP_QUEUE, q);
525    /* send the queued IP packet */
526    etharp_send_ip(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr);
527    /* free the queued IP packet */
528    pbuf_free(p);
529  }
530#endif
531  return ERR_OK;
532}
533
534/**
535 * Finds (stable) ethernet/IP address pair from ARP table
536 * using interface and IP address index.
537 * @note the addresses in the ARP table are in network order!
538 *
539 * @param netif points to interface index
540 * @param ipaddr points to the (network order) IP address index
541 * @param eth_ret points to return pointer
542 * @param ip_ret points to return pointer
543 * @return table index if found, -1 otherwise
544 */
545s8_t
546etharp_find_addr(struct netif *netif, struct ip_addr *ipaddr,
547         struct eth_addr **eth_ret, struct ip_addr **ip_ret)
548{
549  s8_t i;
550
551  LWIP_UNUSED_ARG(netif);
552
553#if LWIP_NETIF_HWADDRHINT
554  i = find_entry(ipaddr, ETHARP_FIND_ONLY, NULL);
555#else /* LWIP_NETIF_HWADDRHINT */
556  i = find_entry(ipaddr, ETHARP_FIND_ONLY);
557#endif /* LWIP_NETIF_HWADDRHINT */
558  if((i >= 0) && arp_table[i].state == ETHARP_STATE_STABLE) {
559      *eth_ret = &arp_table[i].ethaddr;
560      *ip_ret = &arp_table[i].ipaddr;
561      return i;
562  }
563  return -1;
564}
565
566/**
567 * Updates the ARP table using the given IP packet.
568 *
569 * Uses the incoming IP packet's source address to update the
570 * ARP cache for the local network. The function does not alter
571 * or free the packet. This function must be called before the
572 * packet p is passed to the IP layer.
573 *
574 * @param netif The lwIP network interface on which the IP packet pbuf arrived.
575 * @param p The IP packet that arrived on netif.
576 *
577 * @return NULL
578 *
579 * @see pbuf_free()
580 */
581void
582etharp_ip_input(struct netif *netif, struct pbuf *p)
583{
584  struct eth_hdr *ethhdr;
585  struct ip_hdr *iphdr;
586  LWIP_ERROR("netif != NULL", (netif != NULL), return;);
587  /* Only insert an entry if the source IP address of the
588     incoming IP packet comes from a host on the local network. */
589  ethhdr = p->payload;
590  iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
591#if ETHARP_SUPPORT_VLAN
592  if (ethhdr->type == ETHTYPE_VLAN) {
593    iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);
594  }
595#endif /* ETHARP_SUPPORT_VLAN */
596
597  /* source is not on the local network? */
598  if (!ip_addr_netcmp(&(iphdr->src), &(netif->ip_addr), &(netif->netmask))) {
599    /* do nothing */
600    return;
601  }
602
603  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n"));
604  /* update ARP table */
605  /* @todo We could use ETHARP_TRY_HARD if we think we are going to talk
606   * back soon (for example, if the destination IP address is ours. */
607  update_arp_entry(netif, &(iphdr->src), &(ethhdr->src), 0);
608}
609
610
611/**
612 * Responds to ARP requests to us. Upon ARP replies to us, add entry to cache 
613 * send out queued IP packets. Updates cache with snooped address pairs.
614 *
615 * Should be called for incoming ARP packets. The pbuf in the argument
616 * is freed by this function.
617 *
618 * @param netif The lwIP network interface on which the ARP packet pbuf arrived.
619 * @param ethaddr Ethernet address of netif.
620 * @param p The ARP packet that arrived on netif. Is freed by this function.
621 *
622 * @return NULL
623 *
624 * @see pbuf_free()
625 */
626void
627etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
628{
629  struct etharp_hdr *hdr;
630  struct eth_hdr *ethhdr;
631  /* these are aligned properly, whereas the ARP header fields might not be */
632  struct ip_addr sipaddr, dipaddr;
633  u8_t i;
634  u8_t for_us;
635#if LWIP_AUTOIP
636  const u8_t * ethdst_hwaddr;
637#endif /* LWIP_AUTOIP */
638
639  LWIP_ERROR("netif != NULL", (netif != NULL), return;);
640 
641  /* drop short ARP packets: we have to check for p->len instead of p->tot_len here
642     since a struct etharp_hdr is pointed to p->payload, so it musn't be chained! */
643  if (p->len < SIZEOF_ETHARP_PACKET) {
644    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
645      ("etharp_arp_input: packet dropped, too short (%"S16_F"/%"S16_F")\n", p->tot_len,
646      (s16_t)SIZEOF_ETHARP_PACKET));
647    ETHARP_STATS_INC(etharp.lenerr);
648    ETHARP_STATS_INC(etharp.drop);
649    pbuf_free(p);
650    return;
651  }
652
653  ethhdr = p->payload;
654  hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
655#if ETHARP_SUPPORT_VLAN
656  if (ethhdr->type == ETHTYPE_VLAN) {
657    hdr = (struct etharp_hdr *)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);
658  }
659#endif /* ETHARP_SUPPORT_VLAN */
660
661  /* RFC 826 "Packet Reception": */
662  if ((hdr->hwtype != htons(HWTYPE_ETHERNET)) ||
663      (hdr->_hwlen_protolen != htons((ETHARP_HWADDR_LEN << 8) | sizeof(struct ip_addr))) ||
664      (hdr->proto != htons(ETHTYPE_IP)) ||
665      (ethhdr->type != htons(ETHTYPE_ARP)))  {
666    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
667      ("etharp_arp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n",
668      hdr->hwtype, ARPH_HWLEN(hdr), hdr->proto, ARPH_PROTOLEN(hdr), ethhdr->type));
669    ETHARP_STATS_INC(etharp.proterr);
670    ETHARP_STATS_INC(etharp.drop);
671    pbuf_free(p);
672    return;
673  }
674  ETHARP_STATS_INC(etharp.recv);
675
676#if LWIP_AUTOIP
677  /* We have to check if a host already has configured our random
678   * created link local address and continously check if there is
679   * a host with this IP-address so we can detect collisions */
680  autoip_arp_reply(netif, hdr);
681#endif /* LWIP_AUTOIP */
682
683  /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
684   * structure packing (not using structure copy which breaks strict-aliasing rules). */
685  SMEMCPY(&sipaddr, &hdr->sipaddr, sizeof(sipaddr));
686  SMEMCPY(&dipaddr, &hdr->dipaddr, sizeof(dipaddr));
687
688  /* this interface is not configured? */
689  if (netif->ip_addr.addr == 0) {
690    for_us = 0;
691  } else {
692    /* ARP packet directed to us? */
693    for_us = ip_addr_cmp(&dipaddr, &(netif->ip_addr));
694  }
695
696  /* ARP message directed to us? */
697  if (for_us) {
698    /* add IP address in ARP cache; assume requester wants to talk to us.
699     * can result in directly sending the queued packets for this host. */
700    update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), ETHARP_TRY_HARD);
701  /* ARP message not directed to us? */
702  } else {
703    /* update the source IP address in the cache, if present */
704    update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), 0);
705  }
706
707  /* now act on the message itself */
708  switch (htons(hdr->opcode)) {
709  /* ARP request? */
710  case ARP_REQUEST:
711    /* ARP request. If it asked for our address, we send out a
712     * reply. In any case, we time-stamp any existing ARP entry,
713     * and possiby send out an IP packet that was queued on it. */
714
715    LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP request\n"));
716    /* ARP request for our address? */
717    if (for_us) {
718
719      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: replying to ARP request for our IP address\n"));
720      /* Re-use pbuf to send ARP reply.
721         Since we are re-using an existing pbuf, we can't call etharp_raw since
722         that would allocate a new pbuf. */
723      hdr->opcode = htons(ARP_REPLY);
724
725      hdr->dipaddr = hdr->sipaddr;
726      SMEMCPY(&hdr->sipaddr, &netif->ip_addr, sizeof(hdr->sipaddr));
727
728      LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",
729                  (netif->hwaddr_len == ETHARP_HWADDR_LEN));
730      i = ETHARP_HWADDR_LEN;
731#if LWIP_AUTOIP
732      /* If we are using Link-Local, ARP packets must be broadcast on the
733       * link layer. (See RFC3927 Section 2.5) */
734      ethdst_hwaddr = ((netif->autoip != NULL) && (netif->autoip->state != AUTOIP_STATE_OFF)) ? (u8_t*)(ethbroadcast.addr) : hdr->shwaddr.addr;
735#endif /* LWIP_AUTOIP */
736
737      while(i > 0) {
738        i--;
739        hdr->dhwaddr.addr[i] = hdr->shwaddr.addr[i];
740#if LWIP_AUTOIP
741        ethhdr->dest.addr[i] = ethdst_hwaddr[i];
742#else  /* LWIP_AUTOIP */
743        ethhdr->dest.addr[i] = hdr->shwaddr.addr[i];
744#endif /* LWIP_AUTOIP */
745        hdr->shwaddr.addr[i] = ethaddr->addr[i];
746        ethhdr->src.addr[i] = ethaddr->addr[i];
747      }
748
749      /* hwtype, hwaddr_len, proto, protolen and the type in the ethernet header
750         are already correct, we tested that before */
751
752      /* return ARP reply */
753      netif->linkoutput(netif, p);
754    /* we are not configured? */
755    } else if (netif->ip_addr.addr == 0) {
756      /* { for_us == 0 and netif->ip_addr.addr == 0 } */
757      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n"));
758    /* request was not directed to us */
759    } else {
760      /* { for_us == 0 and netif->ip_addr.addr != 0 } */
761      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP request was not for us.\n"));
762    }
763    break;
764  case ARP_REPLY:
765    /* ARP reply. We already updated the ARP cache earlier. */
766    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n"));
767#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
768    /* DHCP wants to know about ARP replies from any host with an
769     * IP address also offered to us by the DHCP server. We do not
770     * want to take a duplicate IP address on a single network.
771     * @todo How should we handle redundant (fail-over) interfaces? */
772    dhcp_arp_reply(netif, &sipaddr);
773#endif
774    break;
775  default:
776    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %"S16_F"\n", htons(hdr->opcode)));
777    ETHARP_STATS_INC(etharp.err);
778    break;
779  }
780  /* free ARP packet */
781  pbuf_free(p);
782}
783
784/**
785 * Resolve and fill-in Ethernet address header for outgoing IP packet.
786 *
787 * For IP multicast and broadcast, corresponding Ethernet addresses
788 * are selected and the packet is transmitted on the link.
789 *
790 * For unicast addresses, the packet is submitted to etharp_query(). In
791 * case the IP address is outside the local network, the IP address of
792 * the gateway is used.
793 *
794 * @param netif The lwIP network interface which the IP packet will be sent on.
795 * @param q The pbuf(s) containing the IP packet to be sent.
796 * @param ipaddr The IP address of the packet destination.
797 *
798 * @return
799 * - ERR_RTE No route to destination (no gateway to external networks),
800 * or the return type of either etharp_query() or etharp_send_ip().
801 */
802err_t
803etharp_output(struct netif *netif, struct pbuf *q, struct ip_addr *ipaddr)
804{
805  struct eth_addr *dest, mcastaddr;
806
807  /* make room for Ethernet header - should not fail */
808  if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
809    /* bail out */
810    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
811      ("etharp_output: could not allocate room for header.\n"));
812    LINK_STATS_INC(link.lenerr);
813    return ERR_BUF;
814  }
815
816  /* assume unresolved Ethernet address */
817  dest = NULL;
818  /* Determine on destination hardware address. Broadcasts and multicasts
819   * are special, other IP addresses are looked up in the ARP table. */
820
821  /* broadcast destination IP address? */
822  if (ip_addr_isbroadcast(ipaddr, netif)) {
823    /* broadcast on Ethernet also */
824    dest = (struct eth_addr *)&ethbroadcast;
825  /* multicast destination IP address? */
826  } else if (ip_addr_ismulticast(ipaddr)) {
827    /* Hash IP multicast address to MAC address.*/
828    mcastaddr.addr[0] = 0x01;
829    mcastaddr.addr[1] = 0x00;
830    mcastaddr.addr[2] = 0x5e;
831    mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
832    mcastaddr.addr[4] = ip4_addr3(ipaddr);
833    mcastaddr.addr[5] = ip4_addr4(ipaddr);
834    /* destination Ethernet address is multicast */
835    dest = &mcastaddr;
836  /* unicast destination IP address? */
837  } else {
838    /* outside local network? */
839    if (!ip_addr_netcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {
840      /* interface has default gateway? */
841      if (netif->gw.addr != 0) {
842        /* send to hardware address of default gateway IP address */
843        ipaddr = &(netif->gw);
844      /* no default gateway available */
845      } else {
846        /* no route to destination error (default gateway missing) */
847        return ERR_RTE;
848      }
849    }
850    /* queue on destination Ethernet address belonging to ipaddr */
851    return etharp_query(netif, ipaddr, q);
852  }
853
854  /* continuation for multicast/broadcast destinations */
855  /* obtain source Ethernet address of the given interface */
856  /* send packet directly on the link */
857  return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr), dest);
858}
859
860/**
861 * Send an ARP request for the given IP address and/or queue a packet.
862 *
863 * If the IP address was not yet in the cache, a pending ARP cache entry
864 * is added and an ARP request is sent for the given address. The packet
865 * is queued on this entry.
866 *
867 * If the IP address was already pending in the cache, a new ARP request
868 * is sent for the given address. The packet is queued on this entry.
869 *
870 * If the IP address was already stable in the cache, and a packet is
871 * given, it is directly sent and no ARP request is sent out.
872 *
873 * If the IP address was already stable in the cache, and no packet is
874 * given, an ARP request is sent out.
875 *
876 * @param netif The lwIP network interface on which ipaddr
877 * must be queried for.
878 * @param ipaddr The IP address to be resolved.
879 * @param q If non-NULL, a pbuf that must be delivered to the IP address.
880 * q is not freed by this function.
881 *
882 * @note q must only be ONE packet, not a packet queue!
883 *
884 * @return
885 * - ERR_BUF Could not make room for Ethernet header.
886 * - ERR_MEM Hardware address unknown, and no more ARP entries available
887 *   to query for address or queue the packet.
888 * - ERR_MEM Could not queue packet due to memory shortage.
889 * - ERR_RTE No route to destination (no gateway to external networks).
890 * - ERR_ARG Non-unicast address given, those will not appear in ARP cache.
891 *
892 */
893err_t
894etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
895{
896  struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr;
897  err_t result = ERR_MEM;
898  s8_t i; /* ARP entry index */
899
900  /* non-unicast address? */
901  if (ip_addr_isbroadcast(ipaddr, netif) ||
902      ip_addr_ismulticast(ipaddr) ||
903      ip_addr_isany(ipaddr)) {
904    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n"));
905    return ERR_ARG;
906  }
907
908  /* find entry in ARP cache, ask to create entry if queueing packet */
909#if LWIP_NETIF_HWADDRHINT
910  i = find_entry(ipaddr, ETHARP_TRY_HARD, netif);
911#else /* LWIP_NETIF_HWADDRHINT */
912  i = find_entry(ipaddr, ETHARP_TRY_HARD);
913#endif /* LWIP_NETIF_HWADDRHINT */
914
915  /* could not find or create entry? */
916  if (i < 0) {
917    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not create ARP entry\n"));
918    if (q) {
919      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: packet dropped\n"));
920      ETHARP_STATS_INC(etharp.memerr);
921    }
922    return (err_t)i;
923  }
924
925  /* mark a fresh entry as pending (we just sent a request) */
926  if (arp_table[i].state == ETHARP_STATE_EMPTY) {
927    arp_table[i].state = ETHARP_STATE_PENDING;
928  }
929
930  /* { i is either a STABLE or (new or existing) PENDING entry } */
931  LWIP_ASSERT("arp_table[i].state == PENDING or STABLE",
932  ((arp_table[i].state == ETHARP_STATE_PENDING) ||
933   (arp_table[i].state == ETHARP_STATE_STABLE)));
934
935  /* do we have a pending entry? or an implicit query request? */
936  if ((arp_table[i].state == ETHARP_STATE_PENDING) || (q == NULL)) {
937    /* try to resolve it; send out ARP request */
938    result = etharp_request(netif, ipaddr);
939    if (result != ERR_OK) {
940      /* ARP request couldn't be sent */
941      /* We don't re-send arp request in etharp_tmr, but we still queue packets,
942         since this failure could be temporary, and the next packet calling
943         etharp_query again could lead to sending the queued packets. */
944    }
945  }
946 
947  /* packet given? */
948  if (q != NULL) {
949    /* stable entry? */
950    if (arp_table[i].state == ETHARP_STATE_STABLE) {
951      /* we have a valid IP->Ethernet address mapping */
952      /* send the packet */
953      result = etharp_send_ip(netif, q, srcaddr, &(arp_table[i].ethaddr));
954    /* pending entry? (either just created or already pending */
955    } else if (arp_table[i].state == ETHARP_STATE_PENDING) {
956#if ARP_QUEUEING /* queue the given q packet */
957      struct pbuf *p;
958      int copy_needed = 0;
959      /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but
960       * to copy the whole queue into a new PBUF_RAM (see bug #11400)
961       * PBUF_ROMs can be left as they are, since ROM must not get changed. */
962      p = q;
963      while (p) {
964        LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == 0));
965        if(p->type != PBUF_ROM) {
966          copy_needed = 1;
967          break;
968        }
969        p = p->next;
970      }
971      if(copy_needed) {
972        /* copy the whole packet into new pbufs */
973        p = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
974        if(p != NULL) {
975          if (pbuf_copy(p, q) != ERR_OK) {
976            pbuf_free(p);
977            p = NULL;
978          }
979        }
980      } else {
981        /* referencing the old pbuf is enough */
982        p = q;
983        pbuf_ref(p);
984      }
985      /* packet could be taken over? */
986      if (p != NULL) {
987        /* queue packet ... */
988        struct etharp_q_entry *new_entry;
989        /* allocate a new arp queue entry */
990        new_entry = memp_malloc(MEMP_ARP_QUEUE);
991        if (new_entry != NULL) {
992          new_entry->next = 0;
993          new_entry->p = p;
994          if(arp_table[i].q != NULL) {
995            /* queue was already existent, append the new entry to the end */
996            struct etharp_q_entry *r;
997            r = arp_table[i].q;
998            while (r->next != NULL) {
999              r = r->next;
1000            }
1001            r->next = new_entry;
1002          } else {
1003            /* queue did not exist, first item in queue */
1004            arp_table[i].q = new_entry;
1005          }
1006          LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
1007          result = ERR_OK;
1008        } else {
1009          /* the pool MEMP_ARP_QUEUE is empty */
1010          pbuf_free(p);
1011          LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));
1012          /* { result == ERR_MEM } through initialization */
1013        }
1014      } else {
1015        ETHARP_STATS_INC(etharp.memerr);
1016        LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));
1017        /* { result == ERR_MEM } through initialization */
1018      }
1019#else /* ARP_QUEUEING == 0 */
1020      /* q && state == PENDING && ARP_QUEUEING == 0 => result = ERR_MEM */
1021      /* { result == ERR_MEM } through initialization */
1022      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: Ethernet destination address unknown, queueing disabled, packet %p dropped\n", (void *)q));
1023#endif
1024    }
1025  }
1026  return result;
1027}
1028
1029/**
1030 * Send a raw ARP packet (opcode and all addresses can be modified)
1031 *
1032 * @param netif the lwip network interface on which to send the ARP packet
1033 * @param ethsrc_addr the source MAC address for the ethernet header
1034 * @param ethdst_addr the destination MAC address for the ethernet header
1035 * @param hwsrc_addr the source MAC address for the ARP protocol header
1036 * @param ipsrc_addr the source IP address for the ARP protocol header
1037 * @param hwdst_addr the destination MAC address for the ARP protocol header
1038 * @param ipdst_addr the destination IP address for the ARP protocol header
1039 * @param opcode the type of the ARP packet
1040 * @return ERR_OK if the ARP packet has been sent
1041 *         ERR_MEM if the ARP packet couldn't be allocated
1042 *         any other err_t on failure
1043 */
1044#if !LWIP_AUTOIP
1045static
1046#endif /* LWIP_AUTOIP */
1047err_t
1048etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
1049           const struct eth_addr *ethdst_addr,
1050           const struct eth_addr *hwsrc_addr, const struct ip_addr *ipsrc_addr,
1051           const struct eth_addr *hwdst_addr, const struct ip_addr *ipdst_addr,
1052           const u16_t opcode)
1053{
1054  struct pbuf *p;
1055  err_t result = ERR_OK;
1056  u8_t k; /* ARP entry index */
1057  struct eth_hdr *ethhdr;
1058  struct etharp_hdr *hdr;
1059#if LWIP_AUTOIP
1060  const u8_t * ethdst_hwaddr;
1061#endif /* LWIP_AUTOIP */
1062
1063  /* allocate a pbuf for the outgoing ARP request packet */
1064  p = pbuf_alloc(PBUF_RAW, SIZEOF_ETHARP_PACKET, PBUF_RAM);
1065  /* could allocate a pbuf for an ARP request? */
1066  if (p == NULL) {
1067    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
1068      ("etharp_raw: could not allocate pbuf for ARP request.\n"));
1069    ETHARP_STATS_INC(etharp.memerr);
1070    return ERR_MEM;
1071  }
1072  LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr",
1073              (p->len >= SIZEOF_ETHARP_PACKET));
1074
1075  ethhdr = p->payload;
1076  hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
1077  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n"));
1078  hdr->opcode = htons(opcode);
1079
1080  LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",
1081              (netif->hwaddr_len == ETHARP_HWADDR_LEN));
1082  k = ETHARP_HWADDR_LEN;
1083#if LWIP_AUTOIP
1084  /* If we are using Link-Local, ARP packets must be broadcast on the
1085   * link layer. (See RFC3927 Section 2.5) */
1086  ethdst_hwaddr = ((netif->autoip != NULL) && (netif->autoip->state != AUTOIP_STATE_OFF)) ? (u8_t*)(ethbroadcast.addr) : ethdst_addr->addr;
1087#endif /* LWIP_AUTOIP */
1088  /* Write MAC-Addresses (combined loop for both headers) */
1089  while(k > 0) {
1090    k--;
1091    /* Write the ARP MAC-Addresses */
1092    hdr->shwaddr.addr[k] = hwsrc_addr->addr[k];
1093    hdr->dhwaddr.addr[k] = hwdst_addr->addr[k];
1094    /* Write the Ethernet MAC-Addresses */
1095#if LWIP_AUTOIP
1096    ethhdr->dest.addr[k] = ethdst_hwaddr[k];
1097#else  /* LWIP_AUTOIP */
1098    ethhdr->dest.addr[k] = ethdst_addr->addr[k];
1099#endif /* LWIP_AUTOIP */
1100    ethhdr->src.addr[k]  = ethsrc_addr->addr[k];
1101  }
1102  hdr->sipaddr = *(struct ip_addr2 *)ipsrc_addr;
1103  hdr->dipaddr = *(struct ip_addr2 *)ipdst_addr;
1104
1105  hdr->hwtype = htons(HWTYPE_ETHERNET);
1106  hdr->proto = htons(ETHTYPE_IP);
1107  /* set hwlen and protolen together */
1108  hdr->_hwlen_protolen = htons((ETHARP_HWADDR_LEN << 8) | sizeof(struct ip_addr));
1109
1110  ethhdr->type = htons(ETHTYPE_ARP);
1111  /* send ARP query */
1112  result = netif->linkoutput(netif, p);
1113  ETHARP_STATS_INC(etharp.xmit);
1114  /* free ARP query packet */
1115  pbuf_free(p);
1116  p = NULL;
1117  /* could not allocate pbuf for ARP request */
1118
1119  return result;
1120}
1121
1122/**
1123 * Send an ARP request packet asking for ipaddr.
1124 *
1125 * @param netif the lwip network interface on which to send the request
1126 * @param ipaddr the IP address for which to ask
1127 * @return ERR_OK if the request has been sent
1128 *         ERR_MEM if the ARP packet couldn't be allocated
1129 *         any other err_t on failure
1130 */
1131err_t
1132etharp_request(struct netif *netif, struct ip_addr *ipaddr)
1133{
1134  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_request: sending ARP request.\n"));
1135  return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, &ethbroadcast,
1136                    (struct eth_addr *)netif->hwaddr, &netif->ip_addr, &ethzero,
1137                    ipaddr, ARP_REQUEST);
1138}
1139
1140/**
1141 * Process received ethernet frames. Using this function instead of directly
1142 * calling ip_input and passing ARP frames through etharp in ethernetif_input,
1143 * the ARP cache is protected from concurrent access.
1144 *
1145 * @param p the recevied packet, p->payload pointing to the ethernet header
1146 * @param netif the network interface on which the packet was received
1147 */
1148err_t
1149ethernet_input(struct pbuf *p, struct netif *netif)
1150{
1151  struct eth_hdr* ethhdr;
1152  u16_t type;
1153
1154  /* points to packet payload, which starts with an Ethernet header */
1155  ethhdr = p->payload;
1156  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE,
1157    ("ethernet_input: dest:%02x:%02x:%02x:%02x:%02x:%02x, src:%02x:%02x:%02x:%02x:%02x:%02x, type:%2hx\n",
1158     (unsigned)ethhdr->dest.addr[0], (unsigned)ethhdr->dest.addr[1], (unsigned)ethhdr->dest.addr[2],
1159     (unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], (unsigned)ethhdr->dest.addr[5],
1160     (unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], (unsigned)ethhdr->src.addr[2],
1161     (unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5],
1162     (unsigned)htons(ethhdr->type)));
1163
1164  type = htons(ethhdr->type);
1165#if ETHARP_SUPPORT_VLAN
1166  if (type == ETHTYPE_VLAN) {
1167    struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr*)(((char*)ethhdr) + SIZEOF_ETH_HDR);
1168#ifdef ETHARP_VLAN_CHECK /* if not, allow all VLANs */
1169    if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) {
1170      /* silently ignore this packet: not for our VLAN */
1171      pbuf_free(p);
1172      return ERR_OK;
1173    }
1174#endif /* ETHARP_VLAN_CHECK */
1175    type = htons(vlan->tpid);
1176  }
1177#endif /* ETHARP_SUPPORT_VLAN */
1178
1179  switch (type) {
1180    /* IP packet? */
1181    case ETHTYPE_IP:
1182#if ETHARP_TRUST_IP_MAC
1183      /* update ARP table */
1184      etharp_ip_input(netif, p);
1185#endif /* ETHARP_TRUST_IP_MAC */
1186      /* skip Ethernet header */
1187      if(pbuf_header(p, -(s16_t)SIZEOF_ETH_HDR)) {
1188        LWIP_ASSERT("Can't move over header in packet", 0);
1189        pbuf_free(p);
1190        p = NULL;
1191      } else {
1192        /* pass to IP layer */
1193        ip_input(p, netif);
1194      }
1195      break;
1196     
1197    case ETHTYPE_ARP:
1198      /* pass p to ARP module */
1199      etharp_arp_input(netif, (struct eth_addr*)(netif->hwaddr), p);
1200      break;
1201
1202#if PPPOE_SUPPORT
1203    case ETHTYPE_PPPOEDISC: /* PPP Over Ethernet Discovery Stage */
1204      pppoe_disc_input(netif, p);
1205      break;
1206
1207    case ETHTYPE_PPPOE: /* PPP Over Ethernet Session Stage */
1208      pppoe_data_input(netif, p);
1209      break;
1210#endif /* PPPOE_SUPPORT */
1211
1212    default:
1213      ETHARP_STATS_INC(etharp.proterr);
1214      ETHARP_STATS_INC(etharp.drop);
1215      pbuf_free(p);
1216      p = NULL;
1217      break;
1218  }
1219
1220  /* This means the pbuf is freed or consumed,
1221     so the caller doesn't have to free it again */
1222  return ERR_OK;
1223}
1224#endif /* LWIP_ARP */
Note: See TracBrowser for help on using the repository browser.