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