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