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