Example program with HTTPServer and sensor data streaming over TCPSockets, using Donatien Garnier's Net APIs and services code on top of LWIP. Files StreamServer.h and .cpp encapsulate streaming over TCPSockets. Broadcast is done by sendToAll(), and all incoming data is echoed back to the client. Echo code can be replaced with some remote control of the streaming interface. See main() that shows how to periodically send some data to all subscribed clients. To subscribe, a client should open a socket at <mbed_ip> port 123. I used few lines in TCL code to set up a quick sink for the data. HTTP files are served on port 80 concurrently to the streaming.

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers etharp.c Source File

etharp.c

Go to the documentation of this file.
00001 /**
00002  * @file
00003  * Address Resolution Protocol module for IP over Ethernet
00004  *
00005  * Functionally, ARP is divided into two parts. The first maps an IP address
00006  * to a physical address when sending a packet, and the second part answers
00007  * requests from other machines for our physical address.
00008  *
00009  * This implementation complies with RFC 826 (Ethernet ARP). It supports
00010  * Gratuitious ARP from RFC3220 (IP Mobility Support for IPv4) section 4.6
00011  * if an interface calls etharp_gratuitous(our_netif) upon address change.
00012  */
00013 
00014 /*
00015  * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
00016  * Copyright (c) 2003-2004 Leon Woestenberg <leon.woestenberg@axon.tv>
00017  * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands.
00018  * All rights reserved.
00019  *
00020  * Redistribution and use in source and binary forms, with or without modification,
00021  * are permitted provided that the following conditions are met:
00022  *
00023  * 1. Redistributions of source code must retain the above copyright notice,
00024  *    this list of conditions and the following disclaimer.
00025  * 2. Redistributions in binary form must reproduce the above copyright notice,
00026  *    this list of conditions and the following disclaimer in the documentation
00027  *    and/or other materials provided with the distribution.
00028  * 3. The name of the author may not be used to endorse or promote products
00029  *    derived from this software without specific prior written permission.
00030  *
00031  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
00032  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00033  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
00034  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00035  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
00036  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00037  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00038  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
00039  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
00040  * OF SUCH DAMAGE.
00041  *
00042  * This file is part of the lwIP TCP/IP stack.
00043  *
00044  */
00045  
00046 #include "lwip/opt.h"
00047 
00048 #if LWIP_ARP || LWIP_ETHERNET
00049 
00050 #include "lwip/ip_addr.h"
00051 #include "lwip/def.h"
00052 #include "lwip/ip.h"
00053 #include "lwip/stats.h"
00054 #include "lwip/snmp.h"
00055 #include "lwip/dhcp.h "
00056 #include "lwip/autoip.h"
00057 #include "netif/etharp.h"
00058 
00059 #if PPPOE_SUPPORT
00060 #include "netif/ppp_oe.h"
00061 #endif /* PPPOE_SUPPORT */
00062 
00063 #include <string.h>
00064 
00065 const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
00066 const struct eth_addr ethzero = {{0,0,0,0,0,0}};
00067 
00068 #if LWIP_ARP /* don't build if not configured for use in lwipopts.h */
00069 
00070 /** the time an ARP entry stays valid after its last update,
00071  *  for ARP_TMR_INTERVAL = 5000, this is
00072  *  (240 * 5) seconds = 20 minutes.
00073  */
00074 #define ARP_MAXAGE 240
00075 /** the time an ARP entry stays pending after first request,
00076  *  for ARP_TMR_INTERVAL = 5000, this is
00077  *  (2 * 5) seconds = 10 seconds.
00078  * 
00079  *  @internal Keep this number at least 2, otherwise it might
00080  *  run out instantly if the timeout occurs directly after a request.
00081  */
00082 #define ARP_MAXPENDING 2
00083 
00084 #define HWTYPE_ETHERNET 1
00085 
00086 #define ARPH_HWLEN(hdr) (ntohs((hdr)->_hwlen_protolen) >> 8)
00087 #define ARPH_PROTOLEN(hdr) (ntohs((hdr)->_hwlen_protolen) & 0xff)
00088 
00089 #define ARPH_HWLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons(ARPH_PROTOLEN(hdr) | ((len) << 8))
00090 #define ARPH_PROTOLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons((len) | (ARPH_HWLEN(hdr) << 8))
00091 
00092 enum etharp_state {
00093   ETHARP_STATE_EMPTY = 0,
00094   ETHARP_STATE_PENDING,
00095   ETHARP_STATE_STABLE
00096 };
00097 
00098 struct etharp_entry {
00099 #if ARP_QUEUEING
00100   /** 
00101    * Pointer to queue of pending outgoing packets on this ARP entry.
00102    */
00103   struct etharp_q_entry *q;
00104 #endif /* ARP_QUEUEING */
00105   ip_addr_t ipaddr;
00106   struct eth_addr ethaddr;
00107   enum etharp_state state;
00108   u8_t ctime;
00109   struct netif *netif;
00110 };
00111 
00112 static struct etharp_entry arp_table[ARP_TABLE_SIZE];
00113 #if !LWIP_NETIF_HWADDRHINT
00114 static u8_t etharp_cached_entry;
00115 #endif /* !LWIP_NETIF_HWADDRHINT */
00116 
00117 /**
00118  * Try hard to create a new entry - we want the IP address to appear in
00119  * the cache (even if this means removing an active entry or so). */
00120 #define ETHARP_TRY_HARD 1
00121 #define ETHARP_FIND_ONLY  2
00122 
00123 #if LWIP_NETIF_HWADDRHINT
00124 #define NETIF_SET_HINT(netif, hint)  if (((netif) != NULL) && ((netif)->addr_hint != NULL))  \
00125                                       *((netif)->addr_hint) = (hint);
00126 static s8_t find_entry(ip_addr_t *ipaddr, u8_t flags, struct netif *netif);
00127 #else /* LWIP_NETIF_HWADDRHINT */
00128 static s8_t find_entry(ip_addr_t *ipaddr, u8_t flags);
00129 #endif /* LWIP_NETIF_HWADDRHINT */
00130 
00131 static err_t update_arp_entry(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags);
00132 
00133 
00134 /* Some checks, instead of etharp_init(): */
00135 #if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f))
00136   #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"
00137 #endif
00138 
00139 
00140 #if ARP_QUEUEING
00141 /**
00142  * Free a complete queue of etharp entries
00143  *
00144  * @param q a qeueue of etharp_q_entry's to free
00145  */
00146 static void
00147 free_etharp_q(struct etharp_q_entry *q)
00148 {
00149   struct etharp_q_entry *r;
00150   LWIP_ASSERT("q != NULL", q != NULL);
00151   LWIP_ASSERT("q->p != NULL", q->p != NULL);
00152   while (q) {
00153     r = q;
00154     q = q->next;
00155     LWIP_ASSERT("r->p != NULL", (r->p != NULL));
00156     pbuf_free(r->p);
00157     memp_free(MEMP_ARP_QUEUE, r);
00158   }
00159 }
00160 #endif /* ARP_QUEUEING */
00161 
00162 /**
00163  * Clears expired entries in the ARP table.
00164  *
00165  * This function should be called every ETHARP_TMR_INTERVAL microseconds (5 seconds),
00166  * in order to expire entries in the ARP table.
00167  */
00168 void
00169 etharp_tmr(void)
00170 {
00171   u8_t i;
00172 
00173   LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n"));
00174   /* remove expired entries from the ARP table */
00175   for (i = 0; i < ARP_TABLE_SIZE; ++i) {
00176     arp_table[i].ctime++;
00177     if (((arp_table[i].state == ETHARP_STATE_STABLE) &&
00178          (arp_table[i].ctime >= ARP_MAXAGE)) ||
00179         ((arp_table[i].state == ETHARP_STATE_PENDING)  &&
00180          (arp_table[i].ctime >= ARP_MAXPENDING))) {
00181          /* pending or stable entry has become old! */
00182       LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n",
00183            arp_table[i].state == ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i));
00184       /* clean up entries that have just been expired */
00185       /* remove from SNMP ARP index tree */
00186       snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr);
00187 #if ARP_QUEUEING
00188       /* and empty packet queue */
00189       if (arp_table[i].q != NULL) {
00190         /* remove all queued packets */
00191         LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].q)));
00192         free_etharp_q(arp_table[i].q);
00193         arp_table[i].q = NULL;
00194       }
00195 #endif /* ARP_QUEUEING */
00196       /* recycle entry for re-use */      
00197       arp_table[i].state = ETHARP_STATE_EMPTY;
00198     }
00199 #if ARP_QUEUEING
00200     /* still pending entry? (not expired) */
00201     if (arp_table[i].state == ETHARP_STATE_PENDING) {
00202         /* resend an ARP query here? */
00203     }
00204 #endif /* ARP_QUEUEING */
00205   }
00206 }
00207 
00208 /**
00209  * Search the ARP table for a matching or new entry.
00210  * 
00211  * If an IP address is given, return a pending or stable ARP entry that matches
00212  * the address. If no match is found, create a new entry with this address set,
00213  * but in state ETHARP_EMPTY. The caller must check and possibly change the
00214  * state of the returned entry.
00215  * 
00216  * If ipaddr is NULL, return a initialized new entry in state ETHARP_EMPTY.
00217  * 
00218  * In all cases, attempt to create new entries from an empty entry. If no
00219  * empty entries are available and ETHARP_TRY_HARD flag is set, recycle
00220  * old entries. Heuristic choose the least important entry for recycling.
00221  *
00222  * @param ipaddr IP address to find in ARP cache, or to add if not found.
00223  * @param flags
00224  * - ETHARP_TRY_HARD: Try hard to create a entry by allowing recycling of
00225  * active (stable or pending) entries.
00226  *  
00227  * @return The ARP entry index that matched or is created, ERR_MEM if no
00228  * entry is found or could be recycled.
00229  */
00230 static s8_t
00231 #if LWIP_NETIF_HWADDRHINT
00232 find_entry(ip_addr_t *ipaddr, u8_t flags, struct netif *netif)
00233 #else /* LWIP_NETIF_HWADDRHINT */
00234 find_entry(ip_addr_t *ipaddr, u8_t flags)
00235 #endif /* LWIP_NETIF_HWADDRHINT */
00236 {
00237   s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE;
00238   s8_t empty = ARP_TABLE_SIZE;
00239   u8_t i = 0, age_pending = 0, age_stable = 0;
00240 #if ARP_QUEUEING
00241   /* oldest entry with packets on queue */
00242   s8_t old_queue = ARP_TABLE_SIZE;
00243   /* its age */
00244   u8_t age_queue = 0;
00245 #endif /* ARP_QUEUEING */
00246 
00247   /* First, test if the last call to this function asked for the
00248    * same address. If so, we're really fast! */
00249   if (ipaddr) {
00250     /* ipaddr to search for was given */
00251 #if LWIP_NETIF_HWADDRHINT
00252     if ((netif != NULL) && (netif->addr_hint != NULL)) {
00253       /* per-pcb cached entry was given */
00254       u8_t per_pcb_cache = *(netif->addr_hint);
00255       if ((per_pcb_cache < ARP_TABLE_SIZE) && arp_table[per_pcb_cache].state == ETHARP_STATE_STABLE) {
00256         /* the per-pcb-cached entry is stable */
00257         if (ip_addr_cmp(ipaddr, &arp_table[per_pcb_cache].ipaddr)) {
00258           /* per-pcb cached entry was the right one! */
00259           ETHARP_STATS_INC(etharp.cachehit);
00260           return per_pcb_cache;
00261         }
00262       }
00263     }
00264 #else /* #if LWIP_NETIF_HWADDRHINT */
00265     if (arp_table[etharp_cached_entry].state == ETHARP_STATE_STABLE) {
00266       /* the cached entry is stable */
00267       if (ip_addr_cmp(ipaddr, &arp_table[etharp_cached_entry].ipaddr)) {
00268         /* cached entry was the right one! */
00269         ETHARP_STATS_INC(etharp.cachehit);
00270         return etharp_cached_entry;
00271       }
00272     }
00273 #endif /* #if LWIP_NETIF_HWADDRHINT */
00274   }
00275 
00276   /**
00277    * a) do a search through the cache, remember candidates
00278    * b) select candidate entry
00279    * c) create new entry
00280    */
00281 
00282   /* a) in a single search sweep, do all of this
00283    * 1) remember the first empty entry (if any)
00284    * 2) remember the oldest stable entry (if any)
00285    * 3) remember the oldest pending entry without queued packets (if any)
00286    * 4) remember the oldest pending entry with queued packets (if any)
00287    * 5) search for a matching IP entry, either pending or stable
00288    *    until 5 matches, or all entries are searched for.
00289    */
00290 
00291   for (i = 0; i < ARP_TABLE_SIZE; ++i) {
00292     /* no empty entry found yet and now we do find one? */
00293     if ((empty == ARP_TABLE_SIZE) && (arp_table[i].state == ETHARP_STATE_EMPTY)) {
00294       LWIP_DEBUGF(ETHARP_DEBUG, ("find_entry: found empty entry %"U16_F"\n", (u16_t)i));
00295       /* remember first empty entry */
00296       empty = i;
00297     }
00298     /* pending entry? */
00299     else if (arp_table[i].state == ETHARP_STATE_PENDING) {
00300       /* if given, does IP address match IP address in ARP entry? */
00301       if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
00302         LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: found matching pending entry %"U16_F"\n", (u16_t)i));
00303         /* found exact IP address match, simply bail out */
00304 #if LWIP_NETIF_HWADDRHINT
00305         NETIF_SET_HINT(netif, i);
00306 #else /* #if LWIP_NETIF_HWADDRHINT */
00307         etharp_cached_entry = i;
00308 #endif /* #if LWIP_NETIF_HWADDRHINT */
00309         return i;
00310 #if ARP_QUEUEING
00311       /* pending with queued packets? */
00312       } else if (arp_table[i].q != NULL) {
00313         if (arp_table[i].ctime >= age_queue) {
00314           old_queue = i;
00315           age_queue = arp_table[i].ctime;
00316         }
00317 #endif /* ARP_QUEUEING */
00318       /* pending without queued packets? */
00319       } else {
00320         if (arp_table[i].ctime >= age_pending) {
00321           old_pending = i;
00322           age_pending = arp_table[i].ctime;
00323         }
00324       }        
00325     }
00326     /* stable entry? */
00327     else if (arp_table[i].state == ETHARP_STATE_STABLE) {
00328       /* if given, does IP address match IP address in ARP entry? */
00329       if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
00330         LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: found matching stable entry %"U16_F"\n", (u16_t)i));
00331         /* found exact IP address match, simply bail out */
00332 #if LWIP_NETIF_HWADDRHINT
00333         NETIF_SET_HINT(netif, i);
00334 #else /* #if LWIP_NETIF_HWADDRHINT */
00335         etharp_cached_entry = i;
00336 #endif /* #if LWIP_NETIF_HWADDRHINT */
00337         return i;
00338       /* remember entry with oldest stable entry in oldest, its age in maxtime */
00339       } else if (arp_table[i].ctime >= age_stable) {
00340         old_stable = i;
00341         age_stable = arp_table[i].ctime;
00342       }
00343     }
00344   }
00345   /* { we have no match } => try to create a new entry */
00346    
00347   /* don't create new entry, only search? */
00348   if (((flags & ETHARP_FIND_ONLY) != 0) ||
00349       /* or no empty entry found and not allowed to recycle? */
00350       ((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_TRY_HARD) == 0))) {
00351     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: no empty entry found and not allowed to recycle\n"));
00352     return (s8_t)ERR_MEM;
00353   }
00354   
00355   /* b) choose the least destructive entry to recycle:
00356    * 1) empty entry
00357    * 2) oldest stable entry
00358    * 3) oldest pending entry without queued packets
00359    * 4) oldest pending entry with queued packets
00360    * 
00361    * { ETHARP_TRY_HARD is set at this point }
00362    */ 
00363 
00364   /* 1) empty entry available? */
00365   if (empty < ARP_TABLE_SIZE) {
00366     i = empty;
00367     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting empty entry %"U16_F"\n", (u16_t)i));
00368   }
00369   /* 2) found recyclable stable entry? */
00370   else if (old_stable < ARP_TABLE_SIZE) {
00371     /* recycle oldest stable*/
00372     i = old_stable;
00373     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i));
00374 #if ARP_QUEUEING
00375     /* no queued packets should exist on stable entries */
00376     LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL);
00377 #endif /* ARP_QUEUEING */
00378   /* 3) found recyclable pending entry without queued packets? */
00379   } else if (old_pending < ARP_TABLE_SIZE) {
00380     /* recycle oldest pending */
00381     i = old_pending;
00382     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i));
00383 #if ARP_QUEUEING
00384   /* 4) found recyclable pending entry with queued packets? */
00385   } else if (old_queue < ARP_TABLE_SIZE) {
00386     /* recycle oldest pending */
00387     i = old_queue;
00388     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)));
00389     free_etharp_q(arp_table[i].q);
00390     arp_table[i].q = NULL;
00391 #endif /* ARP_QUEUEING */
00392     /* no empty or recyclable entries found */
00393   } else {
00394     return (s8_t)ERR_MEM;
00395   }
00396 
00397   /* { empty or recyclable entry found } */
00398   LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE);
00399 
00400   if (arp_table[i].state != ETHARP_STATE_EMPTY)
00401   {
00402     snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr);
00403   }
00404   /* recycle entry (no-op for an already empty entry) */
00405   arp_table[i].state = ETHARP_STATE_EMPTY;
00406 
00407   /* IP address given? */
00408   if (ipaddr != NULL) {
00409     /* set IP address */
00410     ip_addr_copy(arp_table[i].ipaddr, *ipaddr);
00411   }
00412   arp_table[i].ctime = 0;
00413 #if LWIP_NETIF_HWADDRHINT
00414   NETIF_SET_HINT(netif, i);
00415 #else /* #if LWIP_NETIF_HWADDRHINT */
00416   etharp_cached_entry = i;
00417 #endif /* #if LWIP_NETIF_HWADDRHINT */
00418   return (err_t)i;
00419 }
00420 
00421 /**
00422  * Send an IP packet on the network using netif->linkoutput
00423  * The ethernet header is filled in before sending.
00424  *
00425  * @params netif the lwIP network interface on which to send the packet
00426  * @params p the packet to send, p->payload pointing to the (uninitialized) ethernet header
00427  * @params src the source MAC address to be copied into the ethernet header
00428  * @params dst the destination MAC address to be copied into the ethernet header
00429  * @return ERR_OK if the packet was sent, any other err_t on failure
00430  */
00431 static err_t
00432 etharp_send_ip(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst)
00433 {
00434   struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload;
00435   u8_t k;
00436 
00437   LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",
00438               (netif->hwaddr_len == ETHARP_HWADDR_LEN));
00439   k = ETHARP_HWADDR_LEN;
00440   while(k > 0) {
00441     k--;
00442     ethhdr->dest.addr[k] = dst->addr[k];
00443     ethhdr->src.addr[k]  = src->addr[k];
00444   }
00445   ethhdr->type = htons(ETHTYPE_IP);
00446   LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_send_ip: sending packet %p\n", (void *)p));
00447   /* send the packet */
00448   return netif->linkoutput(netif, p);
00449 }
00450 
00451 /**
00452  * Update (or insert) a IP/MAC address pair in the ARP cache.
00453  *
00454  * If a pending entry is resolved, any queued packets will be sent
00455  * at this point.
00456  * 
00457  * @param ipaddr IP address of the inserted ARP entry.
00458  * @param ethaddr Ethernet address of the inserted ARP entry.
00459  * @param flags Defines behaviour:
00460  * - ETHARP_TRY_HARD Allows ARP to insert this as a new item. If not specified,
00461  * only existing ARP entries will be updated.
00462  *
00463  * @return
00464  * - ERR_OK Succesfully updated ARP cache.
00465  * - ERR_MEM If we could not add a new ARP entry when ETHARP_TRY_HARD was set.
00466  * - ERR_ARG Non-unicast address given, those will not appear in ARP cache.
00467  *
00468  * @see pbuf_free()
00469  */
00470 static err_t
00471 update_arp_entry(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags)
00472 {
00473   s8_t i;
00474   u8_t k;
00475   LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry()\n"));
00476   LWIP_ASSERT("netif->hwaddr_len == ETHARP_HWADDR_LEN", netif->hwaddr_len == ETHARP_HWADDR_LEN);
00477   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",
00478     ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr),
00479     ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2],
00480     ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5]));
00481   /* non-unicast address? */
00482   if (ip_addr_isany(ipaddr) ||
00483       ip_addr_isbroadcast(ipaddr, netif) ||
00484       ip_addr_ismulticast(ipaddr)) {
00485     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: will not add non-unicast IP address to ARP cache\n"));
00486     return ERR_ARG;
00487   }
00488   /* find or create ARP entry */
00489 #if LWIP_NETIF_HWADDRHINT
00490   i = find_entry(ipaddr, flags, netif);
00491 #else /* LWIP_NETIF_HWADDRHINT */
00492   i = find_entry(ipaddr, flags);
00493 #endif /* LWIP_NETIF_HWADDRHINT */
00494   /* bail out if no entry could be found */
00495   if (i < 0)
00496     return (err_t)i;
00497   
00498   /* mark it stable */
00499   arp_table[i].state = ETHARP_STATE_STABLE;
00500   /* record network interface */
00501   arp_table[i].netif = netif;
00502 
00503   /* insert in SNMP ARP index tree */
00504   snmp_insert_arpidx_tree(netif, &arp_table[i].ipaddr);
00505 
00506   LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i));
00507   /* update address */
00508   k = ETHARP_HWADDR_LEN;
00509   while (k > 0) {
00510     k--;
00511     arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
00512   }
00513   /* reset time stamp */
00514   arp_table[i].ctime = 0;
00515 #if ARP_QUEUEING
00516   /* this is where we will send out queued packets! */
00517   while (arp_table[i].q != NULL) {
00518     struct pbuf *p;
00519     /* remember remainder of queue */
00520     struct etharp_q_entry *q = arp_table[i].q;
00521     /* pop first item off the queue */
00522     arp_table[i].q = q->next;
00523     /* get the packet pointer */
00524     p = q->p;
00525     /* now queue entry can be freed */
00526     memp_free(MEMP_ARP_QUEUE, q);
00527     /* send the queued IP packet */
00528     etharp_send_ip(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr);
00529     /* free the queued IP packet */
00530     pbuf_free(p);
00531   }
00532 #endif /* ARP_QUEUEING */
00533   return ERR_OK;
00534 }
00535 
00536 /**
00537  * Finds (stable) ethernet/IP address pair from ARP table
00538  * using interface and IP address index.
00539  * @note the addresses in the ARP table are in network order!
00540  *
00541  * @param netif points to interface index
00542  * @param ipaddr points to the (network order) IP address index
00543  * @param eth_ret points to return pointer
00544  * @param ip_ret points to return pointer
00545  * @return table index if found, -1 otherwise
00546  */
00547 s8_t
00548 etharp_find_addr(struct netif *netif, ip_addr_t *ipaddr,
00549          struct eth_addr **eth_ret, ip_addr_t **ip_ret)
00550 {
00551   s8_t i;
00552 
00553   LWIP_UNUSED_ARG(netif);
00554 
00555 #if LWIP_NETIF_HWADDRHINT
00556   i = find_entry(ipaddr, ETHARP_FIND_ONLY, NULL);
00557 #else /* LWIP_NETIF_HWADDRHINT */
00558   i = find_entry(ipaddr, ETHARP_FIND_ONLY);
00559 #endif /* LWIP_NETIF_HWADDRHINT */
00560   if((i >= 0) && arp_table[i].state == ETHARP_STATE_STABLE) {
00561       *eth_ret = &arp_table[i].ethaddr;
00562       *ip_ret = &arp_table[i].ipaddr;
00563       return i;
00564   }
00565   return -1;
00566 }
00567 #if ETHARP_TRUST_IP_MAC
00568 /**
00569  * Updates the ARP table using the given IP packet.
00570  *
00571  * Uses the incoming IP packet's source address to update the
00572  * ARP cache for the local network. The function does not alter
00573  * or free the packet. This function must be called before the
00574  * packet p is passed to the IP layer.
00575  *
00576  * @param netif The lwIP network interface on which the IP packet pbuf arrived.
00577  * @param p The IP packet that arrived on netif.
00578  *
00579  * @return NULL
00580  *
00581  * @see pbuf_free()
00582  */
00583 static void
00584 etharp_ip_input(struct netif *netif, struct pbuf *p)
00585 {
00586   struct eth_hdr *ethhdr;
00587   struct ip_hdr *iphdr;
00588   LWIP_ERROR("netif != NULL", (netif != NULL), return;);
00589 
00590   /* Only insert an entry if the source IP address of the
00591      incoming IP packet comes from a host on the local network. */
00592   ethhdr = (struct eth_hdr *)p->payload;
00593   iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
00594 #if ETHARP_SUPPORT_VLAN
00595   if (ethhdr->type == ETHTYPE_VLAN) {
00596     iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);
00597   }
00598 #endif /* ETHARP_SUPPORT_VLAN */
00599 
00600   /* source is not on the local network? */
00601   if (!ip_addr_netcmp(&(iphdr->src), &(netif->ip_addr), &(netif->netmask))) {
00602     /* do nothing */
00603     return;
00604   }
00605 
00606   LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n"));
00607   /* update the source IP address in the cache, if present */
00608   /* @todo We could use ETHARP_TRY_HARD if we think we are going to talk
00609    * back soon (for example, if the destination IP address is ours. */
00610   update_arp_entry(netif, &(iphdr->src), &(ethhdr->src), ETHARP_FIND_ONLY);
00611 }
00612 #endif /* ETHARP_TRUST_IP_MAC */
00613 
00614 /**
00615  * Responds to ARP requests to us. Upon ARP replies to us, add entry to cache  
00616  * send out queued IP packets. Updates cache with snooped address pairs.
00617  *
00618  * Should be called for incoming ARP packets. The pbuf in the argument
00619  * is freed by this function.
00620  *
00621  * @param netif The lwIP network interface on which the ARP packet pbuf arrived.
00622  * @param ethaddr Ethernet address of netif.
00623  * @param p The ARP packet that arrived on netif. Is freed by this function.
00624  *
00625  * @return NULL
00626  *
00627  * @see pbuf_free()
00628  */
00629 static void
00630 etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
00631 {
00632   struct etharp_hdr *hdr;
00633   struct eth_hdr *ethhdr;
00634   /* these are aligned properly, whereas the ARP header fields might not be */
00635   ip_addr_t sipaddr, dipaddr;
00636   u8_t i;
00637   u8_t for_us;
00638 #if LWIP_AUTOIP
00639   const u8_t * ethdst_hwaddr;
00640 #endif /* LWIP_AUTOIP */
00641 
00642   LWIP_ERROR("netif != NULL", (netif != NULL), return;);
00643 
00644   /* drop short ARP packets: we have to check for p->len instead of p->tot_len here
00645      since a struct etharp_hdr is pointed to p->payload, so it musn't be chained! */
00646   if (p->len < SIZEOF_ETHARP_PACKET) {
00647     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
00648       ("etharp_arp_input: packet dropped, too short (%"S16_F"/%"S16_F")\n", p->tot_len,
00649       (s16_t)SIZEOF_ETHARP_PACKET));
00650     ETHARP_STATS_INC(etharp.lenerr);
00651     ETHARP_STATS_INC(etharp.drop);
00652     pbuf_free(p);
00653     return;
00654   }
00655 
00656   ethhdr = (struct eth_hdr *)p->payload;
00657   hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
00658 #if ETHARP_SUPPORT_VLAN
00659   if (ethhdr->type == ETHTYPE_VLAN) {
00660     hdr = (struct etharp_hdr *)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);
00661   }
00662 #endif /* ETHARP_SUPPORT_VLAN */
00663 
00664   /* RFC 826 "Packet Reception": */
00665   if ((hdr->hwtype != htons(HWTYPE_ETHERNET)) ||
00666       (hdr->_hwlen_protolen != htons((ETHARP_HWADDR_LEN << 8) | sizeof(ip_addr_t))) ||
00667       (hdr->proto != htons(ETHTYPE_IP)) ||
00668       (ethhdr->type != htons(ETHTYPE_ARP)))  {
00669     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
00670       ("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",
00671       hdr->hwtype, ARPH_HWLEN(hdr), hdr->proto, ARPH_PROTOLEN(hdr), ethhdr->type));
00672     ETHARP_STATS_INC(etharp.proterr);
00673     ETHARP_STATS_INC(etharp.drop);
00674     pbuf_free(p);
00675     return;
00676   }
00677   ETHARP_STATS_INC(etharp.recv);
00678 
00679 #if LWIP_AUTOIP
00680   /* We have to check if a host already has configured our random
00681    * created link local address and continously check if there is
00682    * a host with this IP-address so we can detect collisions */
00683   autoip_arp_reply(netif, hdr);
00684 #endif /* LWIP_AUTOIP */
00685 
00686   /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
00687    * structure packing (not using structure copy which breaks strict-aliasing rules). */
00688   SMEMCPY(&sipaddr, &hdr->sipaddr, sizeof(sipaddr));
00689   SMEMCPY(&dipaddr, &hdr->dipaddr, sizeof(dipaddr));
00690 
00691   /* this interface is not configured? */
00692   if (ip_addr_isany(&netif->ip_addr)) {
00693     for_us = 0;
00694   } else {
00695     /* ARP packet directed to us? */
00696     for_us = (u8_t)ip_addr_cmp(&dipaddr, &(netif->ip_addr));
00697   }
00698 
00699   /* ARP message directed to us? */
00700   if (for_us) {
00701     /* add IP address in ARP cache; assume requester wants to talk to us.
00702      * can result in directly sending the queued packets for this host. */
00703     update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), ETHARP_TRY_HARD);
00704   /* ARP message not directed to us? */
00705   } else {
00706     /* update the source IP address in the cache, if present */
00707     update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), ETHARP_FIND_ONLY);
00708   }
00709 
00710   /* now act on the message itself */
00711   switch (htons(hdr->opcode)) {
00712   /* ARP request? */
00713   case ARP_REQUEST:
00714     /* ARP request. If it asked for our address, we send out a
00715      * reply. In any case, we time-stamp any existing ARP entry,
00716      * and possiby send out an IP packet that was queued on it. */
00717 
00718     LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP request\n"));
00719     /* ARP request for our address? */
00720     if (for_us) {
00721 
00722       LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: replying to ARP request for our IP address\n"));
00723       /* Re-use pbuf to send ARP reply.
00724          Since we are re-using an existing pbuf, we can't call etharp_raw since
00725          that would allocate a new pbuf. */
00726       hdr->opcode = htons(ARP_REPLY);
00727 
00728       SMEMCPY(&hdr->dipaddr, &hdr->sipaddr, sizeof(ip_addr_t));
00729       SMEMCPY(&hdr->sipaddr, &netif->ip_addr, sizeof(ip_addr_t));
00730 
00731       LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",
00732                   (netif->hwaddr_len == ETHARP_HWADDR_LEN));
00733       i = ETHARP_HWADDR_LEN;
00734 #if LWIP_AUTOIP
00735       /* If we are using Link-Local, all ARP packets that contain a Link-Local
00736        * 'sender IP address' MUST be sent using link-layer broadcast instead of
00737        * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */
00738       ethdst_hwaddr = ip_addr_islinklocal(&netif->ip_addr) ? (u8_t*)(ethbroadcast.addr) : hdr->shwaddr.addr;
00739 #endif /* LWIP_AUTOIP */
00740 
00741       while(i > 0) {
00742         i--;
00743         hdr->dhwaddr.addr[i] = hdr->shwaddr.addr[i];
00744 #if LWIP_AUTOIP
00745         ethhdr->dest.addr[i] = ethdst_hwaddr[i];
00746 #else  /* LWIP_AUTOIP */
00747         ethhdr->dest.addr[i] = hdr->shwaddr.addr[i];
00748 #endif /* LWIP_AUTOIP */
00749         hdr->shwaddr.addr[i] = ethaddr->addr[i];
00750         ethhdr->src.addr[i] = ethaddr->addr[i];
00751       }
00752 
00753       /* hwtype, hwaddr_len, proto, protolen and the type in the ethernet header
00754          are already correct, we tested that before */
00755 
00756       /* return ARP reply */
00757       netif->linkoutput(netif, p);
00758     /* we are not configured? */
00759     } else if (ip_addr_isany(&netif->ip_addr)) {
00760       /* { for_us == 0 and netif->ip_addr.addr == 0 } */
00761       LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n"));
00762     /* request was not directed to us */
00763     } else {
00764       /* { for_us == 0 and netif->ip_addr.addr != 0 } */
00765       LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP request was not for us.\n"));
00766     }
00767     break;
00768   case ARP_REPLY:
00769     /* ARP reply. We already updated the ARP cache earlier. */
00770     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n"));
00771 #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
00772     /* DHCP wants to know about ARP replies from any host with an
00773      * IP address also offered to us by the DHCP server. We do not
00774      * want to take a duplicate IP address on a single network.
00775      * @todo How should we handle redundant (fail-over) interfaces? */
00776     dhcp_arp_reply(netif, &sipaddr);
00777 #endif /* (LWIP_DHCP && DHCP_DOES_ARP_CHECK) */
00778     break;
00779   default:
00780     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %"S16_F"\n", htons(hdr->opcode)));
00781     ETHARP_STATS_INC(etharp.err);
00782     break;
00783   }
00784   /* free ARP packet */
00785   pbuf_free(p);
00786 }
00787 
00788 /**
00789  * Resolve and fill-in Ethernet address header for outgoing IP packet.
00790  *
00791  * For IP multicast and broadcast, corresponding Ethernet addresses
00792  * are selected and the packet is transmitted on the link.
00793  *
00794  * For unicast addresses, the packet is submitted to etharp_query(). In
00795  * case the IP address is outside the local network, the IP address of
00796  * the gateway is used.
00797  *
00798  * @param netif The lwIP network interface which the IP packet will be sent on.
00799  * @param q The pbuf(s) containing the IP packet to be sent.
00800  * @param ipaddr The IP address of the packet destination.
00801  *
00802  * @return
00803  * - ERR_RTE No route to destination (no gateway to external networks),
00804  * or the return type of either etharp_query() or etharp_send_ip().
00805  */
00806 err_t
00807 etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr)
00808 {
00809   struct eth_addr *dest, mcastaddr;
00810 
00811   /* make room for Ethernet header - should not fail */
00812   if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
00813     /* bail out */
00814     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
00815       ("etharp_output: could not allocate room for header.\n"));
00816     LINK_STATS_INC(link.lenerr);
00817     return ERR_BUF;
00818   }
00819 
00820   /* assume unresolved Ethernet address */
00821   dest = NULL;
00822   /* Determine on destination hardware address. Broadcasts and multicasts
00823    * are special, other IP addresses are looked up in the ARP table. */
00824 
00825   /* broadcast destination IP address? */
00826   if (ip_addr_isbroadcast(ipaddr, netif)) {
00827     /* broadcast on Ethernet also */
00828     dest = (struct eth_addr *)&ethbroadcast;
00829   /* multicast destination IP address? */
00830   } else if (ip_addr_ismulticast(ipaddr)) {
00831     /* Hash IP multicast address to MAC address.*/
00832     mcastaddr.addr[0] = 0x01;
00833     mcastaddr.addr[1] = 0x00;
00834     mcastaddr.addr[2] = 0x5e;
00835     mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
00836     mcastaddr.addr[4] = ip4_addr3(ipaddr);
00837     mcastaddr.addr[5] = ip4_addr4(ipaddr);
00838     /* destination Ethernet address is multicast */
00839     dest = &mcastaddr;
00840   /* unicast destination IP address? */
00841   } else {
00842     /* outside local network? */
00843     if (!ip_addr_netcmp(ipaddr, &(netif->ip_addr), &(netif->netmask)) &&
00844         !ip_addr_islinklocal(ipaddr)) {
00845       /* interface has default gateway? */
00846       if (!ip_addr_isany(&netif->gw)) {
00847         /* send to hardware address of default gateway IP address */
00848         ipaddr = &(netif->gw);
00849       /* no default gateway available */
00850       } else {
00851         /* no route to destination error (default gateway missing) */
00852         return ERR_RTE;
00853       }
00854     }
00855     /* queue on destination Ethernet address belonging to ipaddr */
00856     return etharp_query(netif, ipaddr, q);
00857   }
00858 
00859   /* continuation for multicast/broadcast destinations */
00860   /* obtain source Ethernet address of the given interface */
00861   /* send packet directly on the link */
00862   return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr), dest);
00863 }
00864 
00865 /**
00866  * Send an ARP request for the given IP address and/or queue a packet.
00867  *
00868  * If the IP address was not yet in the cache, a pending ARP cache entry
00869  * is added and an ARP request is sent for the given address. The packet
00870  * is queued on this entry.
00871  *
00872  * If the IP address was already pending in the cache, a new ARP request
00873  * is sent for the given address. The packet is queued on this entry.
00874  *
00875  * If the IP address was already stable in the cache, and a packet is
00876  * given, it is directly sent and no ARP request is sent out. 
00877  * 
00878  * If the IP address was already stable in the cache, and no packet is
00879  * given, an ARP request is sent out.
00880  * 
00881  * @param netif The lwIP network interface on which ipaddr
00882  * must be queried for.
00883  * @param ipaddr The IP address to be resolved.
00884  * @param q If non-NULL, a pbuf that must be delivered to the IP address.
00885  * q is not freed by this function.
00886  *
00887  * @note q must only be ONE packet, not a packet queue!
00888  *
00889  * @return
00890  * - ERR_BUF Could not make room for Ethernet header.
00891  * - ERR_MEM Hardware address unknown, and no more ARP entries available
00892  *   to query for address or queue the packet.
00893  * - ERR_MEM Could not queue packet due to memory shortage.
00894  * - ERR_RTE No route to destination (no gateway to external networks).
00895  * - ERR_ARG Non-unicast address given, those will not appear in ARP cache.
00896  *
00897  */
00898 err_t
00899 etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q)
00900 {
00901   struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr;
00902   err_t result = ERR_MEM;
00903   s8_t i; /* ARP entry index */
00904 
00905   /* non-unicast address? */
00906   if (ip_addr_isbroadcast(ipaddr, netif) ||
00907       ip_addr_ismulticast(ipaddr) ||
00908       ip_addr_isany(ipaddr)) {
00909     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n"));
00910     return ERR_ARG;
00911   }
00912 
00913   /* find entry in ARP cache, ask to create entry if queueing packet */
00914 #if LWIP_NETIF_HWADDRHINT
00915   i = find_entry(ipaddr, ETHARP_TRY_HARD, netif);
00916 #else /* LWIP_NETIF_HWADDRHINT */
00917   i = find_entry(ipaddr, ETHARP_TRY_HARD);
00918 #endif /* LWIP_NETIF_HWADDRHINT */
00919 
00920   /* could not find or create entry? */
00921   if (i < 0) {
00922     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not create ARP entry\n"));
00923     if (q) {
00924       LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: packet dropped\n"));
00925       ETHARP_STATS_INC(etharp.memerr);
00926     }
00927     return (err_t)i;
00928   }
00929 
00930   /* mark a fresh entry as pending (we just sent a request) */
00931   if (arp_table[i].state == ETHARP_STATE_EMPTY) {
00932     arp_table[i].state = ETHARP_STATE_PENDING;
00933   }
00934 
00935   /* { i is either a STABLE or (new or existing) PENDING entry } */
00936   LWIP_ASSERT("arp_table[i].state == PENDING or STABLE",
00937   ((arp_table[i].state == ETHARP_STATE_PENDING) ||
00938    (arp_table[i].state == ETHARP_STATE_STABLE)));
00939 
00940   /* do we have a pending entry? or an implicit query request? */
00941   if ((arp_table[i].state == ETHARP_STATE_PENDING) || (q == NULL)) {
00942     /* try to resolve it; send out ARP request */
00943     result = etharp_request(netif, ipaddr);
00944     if (result != ERR_OK) {
00945       /* ARP request couldn't be sent */
00946       /* We don't re-send arp request in etharp_tmr, but we still queue packets,
00947          since this failure could be temporary, and the next packet calling
00948          etharp_query again could lead to sending the queued packets. */
00949     }
00950   }
00951   
00952   /* packet given? */
00953   if (q != NULL) {
00954     /* stable entry? */
00955     if (arp_table[i].state == ETHARP_STATE_STABLE) {
00956       /* we have a valid IP->Ethernet address mapping */
00957       /* send the packet */
00958       result = etharp_send_ip(netif, q, srcaddr, &(arp_table[i].ethaddr));
00959     /* pending entry? (either just created or already pending */
00960     } else if (arp_table[i].state == ETHARP_STATE_PENDING) {
00961 #if ARP_QUEUEING /* queue the given q packet */
00962       struct pbuf *p;
00963       int copy_needed = 0;
00964       /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but
00965        * to copy the whole queue into a new PBUF_RAM (see bug #11400) 
00966        * PBUF_ROMs can be left as they are, since ROM must not get changed. */
00967       p = q;
00968       while (p) {
00969         LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == 0));
00970         if(p->type != PBUF_ROM) {
00971           copy_needed = 1;
00972           break;
00973         }
00974         p = p->next;
00975       }
00976       if(copy_needed) {
00977         /* copy the whole packet into new pbufs */
00978         p = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
00979         if(p != NULL) {
00980           if (pbuf_copy(p, q) != ERR_OK) {
00981             pbuf_free(p);
00982             p = NULL;
00983           }
00984         }
00985       } else {
00986         /* referencing the old pbuf is enough */
00987         p = q;
00988         pbuf_ref(p);
00989       }
00990       /* packet could be taken over? */
00991       if (p != NULL) {
00992         /* queue packet ... */
00993         struct etharp_q_entry *new_entry;
00994         /* allocate a new arp queue entry */
00995         new_entry = (struct etharp_q_entry *)memp_malloc(MEMP_ARP_QUEUE);
00996         if (new_entry != NULL) {
00997           new_entry->next = 0;
00998           new_entry->p = p;
00999           if(arp_table[i].q != NULL) {
01000             /* queue was already existent, append the new entry to the end */
01001             struct etharp_q_entry *r;
01002             r = arp_table[i].q;
01003             while (r->next != NULL) {
01004               r = r->next;
01005             }
01006             r->next = new_entry;
01007           } else {
01008             /* queue did not exist, first item in queue */
01009             arp_table[i].q = new_entry;
01010           }
01011           LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
01012           result = ERR_OK;
01013         } else {
01014           /* the pool MEMP_ARP_QUEUE is empty */
01015           pbuf_free(p);
01016           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));
01017           /* { result == ERR_MEM } through initialization */
01018         }
01019       } else {
01020         ETHARP_STATS_INC(etharp.memerr);
01021         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));
01022         /* { result == ERR_MEM } through initialization */
01023       }
01024 #else /* ARP_QUEUEING */
01025       /* q && state == PENDING && ARP_QUEUEING == 0 => result = ERR_MEM */
01026       /* { result == ERR_MEM } through initialization */
01027       LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: Ethernet destination address unknown, queueing disabled, packet %p dropped\n", (void *)q));
01028 #endif /* ARP_QUEUEING */
01029     }
01030   }
01031   return result;
01032 }
01033 
01034 /**
01035  * Send a raw ARP packet (opcode and all addresses can be modified)
01036  *
01037  * @param netif the lwip network interface on which to send the ARP packet
01038  * @param ethsrc_addr the source MAC address for the ethernet header
01039  * @param ethdst_addr the destination MAC address for the ethernet header
01040  * @param hwsrc_addr the source MAC address for the ARP protocol header
01041  * @param ipsrc_addr the source IP address for the ARP protocol header
01042  * @param hwdst_addr the destination MAC address for the ARP protocol header
01043  * @param ipdst_addr the destination IP address for the ARP protocol header
01044  * @param opcode the type of the ARP packet
01045  * @return ERR_OK if the ARP packet has been sent
01046  *         ERR_MEM if the ARP packet couldn't be allocated
01047  *         any other err_t on failure
01048  */
01049 #if !LWIP_AUTOIP
01050 static
01051 #endif /* LWIP_AUTOIP */
01052 err_t
01053 etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
01054            const struct eth_addr *ethdst_addr,
01055            const struct eth_addr *hwsrc_addr, const ip_addr_t *ipsrc_addr,
01056            const struct eth_addr *hwdst_addr, const ip_addr_t *ipdst_addr,
01057            const u16_t opcode)
01058 {
01059   struct pbuf *p;
01060   err_t result = ERR_OK;
01061   u8_t k; /* ARP entry index */
01062   struct eth_hdr *ethhdr;
01063   struct etharp_hdr *hdr;
01064 #if LWIP_AUTOIP
01065   const u8_t * ethdst_hwaddr;
01066 #endif /* LWIP_AUTOIP */
01067 
01068   /* allocate a pbuf for the outgoing ARP request packet */
01069   p = pbuf_alloc(PBUF_RAW, SIZEOF_ETHARP_PACKET, PBUF_RAM);
01070   /* could allocate a pbuf for an ARP request? */
01071   if (p == NULL) {
01072     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
01073       ("etharp_raw: could not allocate pbuf for ARP request.\n"));
01074     ETHARP_STATS_INC(etharp.memerr);
01075     return ERR_MEM;
01076   }
01077   LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr",
01078               (p->len >= SIZEOF_ETHARP_PACKET));
01079 
01080   ethhdr = (struct eth_hdr *)p->payload;
01081   hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
01082   LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n"));
01083   hdr->opcode = htons(opcode);
01084 
01085   LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",
01086               (netif->hwaddr_len == ETHARP_HWADDR_LEN));
01087   k = ETHARP_HWADDR_LEN;
01088 #if LWIP_AUTOIP
01089   /* If we are using Link-Local, all ARP packets that contain a Link-Local
01090    * 'sender IP address' MUST be sent using link-layer broadcast instead of
01091    * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */
01092   ethdst_hwaddr = ip_addr_islinklocal(ipsrc_addr) ? (u8_t*)(ethbroadcast.addr) : ethdst_addr->addr;
01093 #endif /* LWIP_AUTOIP */
01094   /* Write MAC-Addresses (combined loop for both headers) */
01095   while(k > 0) {
01096     k--;
01097     /* Write the ARP MAC-Addresses */
01098     hdr->shwaddr.addr[k] = hwsrc_addr->addr[k];
01099     hdr->dhwaddr.addr[k] = hwdst_addr->addr[k];
01100     /* Write the Ethernet MAC-Addresses */
01101 #if LWIP_AUTOIP
01102     ethhdr->dest.addr[k] = ethdst_hwaddr[k];
01103 #else  /* LWIP_AUTOIP */
01104     ethhdr->dest.addr[k] = ethdst_addr->addr[k];
01105 #endif /* LWIP_AUTOIP */
01106     ethhdr->src.addr[k]  = ethsrc_addr->addr[k];
01107   }
01108   /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
01109    * structure packing. */ 
01110   SMEMCPY(&hdr->sipaddr, ipsrc_addr, sizeof(ip_addr_t));
01111   SMEMCPY(&hdr->dipaddr, ipdst_addr, sizeof(ip_addr_t));
01112 
01113   hdr->hwtype = htons(HWTYPE_ETHERNET);
01114   hdr->proto = htons(ETHTYPE_IP);
01115   /* set hwlen and protolen together */
01116   hdr->_hwlen_protolen = htons((ETHARP_HWADDR_LEN << 8) | sizeof(ip_addr_t));
01117 
01118   ethhdr->type = htons(ETHTYPE_ARP);
01119   /* send ARP query */
01120   result = netif->linkoutput(netif, p);
01121   ETHARP_STATS_INC(etharp.xmit);
01122   /* free ARP query packet */
01123   pbuf_free(p);
01124   p = NULL;
01125   /* could not allocate pbuf for ARP request */
01126 
01127   return result;
01128 }
01129 
01130 /**
01131  * Send an ARP request packet asking for ipaddr.
01132  *
01133  * @param netif the lwip network interface on which to send the request
01134  * @param ipaddr the IP address for which to ask
01135  * @return ERR_OK if the request has been sent
01136  *         ERR_MEM if the ARP packet couldn't be allocated
01137  *         any other err_t on failure
01138  */
01139 err_t
01140 etharp_request(struct netif *netif, ip_addr_t *ipaddr)
01141 {
01142   LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_request: sending ARP request.\n"));
01143   return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, &ethbroadcast,
01144                     (struct eth_addr *)netif->hwaddr, &netif->ip_addr, &ethzero,
01145                     ipaddr, ARP_REQUEST);
01146 }
01147 #endif /* LWIP_ARP */
01148 
01149 /**
01150  * Process received ethernet frames. Using this function instead of directly
01151  * calling ip_input and passing ARP frames through etharp in ethernetif_input,
01152  * the ARP cache is protected from concurrent access.
01153  *
01154  * @param p the recevied packet, p->payload pointing to the ethernet header
01155  * @param netif the network interface on which the packet was received
01156  */
01157 err_t
01158 ethernet_input(struct pbuf *p, struct netif *netif)
01159 {
01160   struct eth_hdr* ethhdr;
01161   u16_t type;
01162 
01163   /* points to packet payload, which starts with an Ethernet header */
01164   ethhdr = (struct eth_hdr *)p->payload;
01165   LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE,
01166     ("ethernet_input: dest:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", src:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", type:%"X16_F"\n",
01167      (unsigned)ethhdr->dest.addr[0], (unsigned)ethhdr->dest.addr[1], (unsigned)ethhdr->dest.addr[2],
01168      (unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], (unsigned)ethhdr->dest.addr[5],
01169      (unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], (unsigned)ethhdr->src.addr[2],
01170      (unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5],
01171      (unsigned)htons(ethhdr->type)));
01172 
01173   type = htons(ethhdr->type);
01174 #if ETHARP_SUPPORT_VLAN
01175   if (type == ETHTYPE_VLAN) {
01176     struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr*)(((char*)ethhdr) + SIZEOF_ETH_HDR);
01177 #ifdef ETHARP_VLAN_CHECK /* if not, allow all VLANs */
01178     if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) {
01179       /* silently ignore this packet: not for our VLAN */
01180       pbuf_free(p);
01181       return ERR_OK;
01182     }
01183 #endif /* ETHARP_VLAN_CHECK */
01184     type = htons(vlan->tpid);
01185   }
01186 #endif /* ETHARP_SUPPORT_VLAN */
01187 
01188   switch (type) {
01189 #if LWIP_ARP
01190     /* IP packet? */
01191     case ETHTYPE_IP:
01192       if (!(netif->flags & NETIF_FLAG_ETHARP)) {
01193         goto free_and_return;
01194       }
01195 #if ETHARP_TRUST_IP_MAC
01196       /* update ARP table */
01197       etharp_ip_input(netif, p);
01198 #endif /* ETHARP_TRUST_IP_MAC */
01199       /* skip Ethernet header */
01200       if(pbuf_header(p, -(s16_t)SIZEOF_ETH_HDR)) {
01201         LWIP_ASSERT("Can't move over header in packet", 0);
01202         goto free_and_return;
01203       } else {
01204         /* pass to IP layer */
01205         ip_input(p, netif);
01206       }
01207       break;
01208       
01209     case ETHTYPE_ARP:
01210       if (!(netif->flags & NETIF_FLAG_ETHARP)) {
01211         goto free_and_return;
01212       }
01213       /* pass p to ARP module */
01214       etharp_arp_input(netif, (struct eth_addr*)(netif->hwaddr), p);
01215       break;
01216 #endif /* LWIP_ARP */
01217 #if PPPOE_SUPPORT
01218     case ETHTYPE_PPPOEDISC: /* PPP Over Ethernet Discovery Stage */
01219       pppoe_disc_input(netif, p);
01220       break;
01221 
01222     case ETHTYPE_PPPOE: /* PPP Over Ethernet Session Stage */
01223       pppoe_data_input(netif, p);
01224       break;
01225 #endif /* PPPOE_SUPPORT */
01226 
01227     default:
01228       ETHARP_STATS_INC(etharp.proterr);
01229       ETHARP_STATS_INC(etharp.drop);
01230       goto free_and_return;
01231   }
01232 
01233   /* This means the pbuf is freed or consumed,
01234      so the caller doesn't have to free it again */
01235   return ERR_OK;
01236 
01237 free_and_return:
01238   pbuf_free(p);
01239   return ERR_OK;
01240 }
01241 #endif /* LWIP_ARP || LWIP_ETHERNET */