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