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