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