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