Example program with HTTPServer and sensor data streaming over TCPSockets, using Donatien Garnier's Net APIs and services code on top of LWIP. Files StreamServer.h and .cpp encapsulate streaming over TCPSockets. Broadcast is done by sendToAll(), and all incoming data is echoed back to the client. Echo code can be replaced with some remote control of the streaming interface. See main() that shows how to periodically send some data to all subscribed clients. To subscribe, a client should open a socket at <mbed_ip> port 123. I used few lines in TCL code to set up a quick sink for the data. HTTP files are served on port 80 concurrently to the streaming.
etharp.c
00001 /** 00002 * @file 00003 * Address Resolution Protocol module for IP over Ethernet 00004 * 00005 * Functionally, ARP is divided into two parts. The first maps an IP address 00006 * to a physical address when sending a packet, and the second part answers 00007 * requests from other machines for our physical address. 00008 * 00009 * This implementation complies with RFC 826 (Ethernet ARP). It supports 00010 * Gratuitious ARP from RFC3220 (IP Mobility Support for IPv4) section 4.6 00011 * if an interface calls etharp_gratuitous(our_netif) upon address change. 00012 */ 00013 00014 /* 00015 * Copyright (c) 2001-2003 Swedish Institute of Computer Science. 00016 * Copyright (c) 2003-2004 Leon Woestenberg <leon.woestenberg@axon.tv> 00017 * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. 00018 * All rights reserved. 00019 * 00020 * Redistribution and use in source and binary forms, with or without modification, 00021 * are permitted provided that the following conditions are met: 00022 * 00023 * 1. Redistributions of source code must retain the above copyright notice, 00024 * this list of conditions and the following disclaimer. 00025 * 2. Redistributions in binary form must reproduce the above copyright notice, 00026 * this list of conditions and the following disclaimer in the documentation 00027 * and/or other materials provided with the distribution. 00028 * 3. The name of the author may not be used to endorse or promote products 00029 * derived from this software without specific prior written permission. 00030 * 00031 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00032 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00033 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00034 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00035 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00036 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00037 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00038 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00039 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00040 * OF SUCH DAMAGE. 00041 * 00042 * This file is part of the lwIP TCP/IP stack. 00043 * 00044 */ 00045 00046 #include "lwip/opt.h" 00047 00048 #if LWIP_ARP || LWIP_ETHERNET 00049 00050 #include "lwip/ip_addr.h" 00051 #include "lwip/def.h" 00052 #include "lwip/ip.h" 00053 #include "lwip/stats.h" 00054 #include "lwip/snmp.h" 00055 #include "lwip/dhcp.h " 00056 #include "lwip/autoip.h" 00057 #include "netif/etharp.h" 00058 00059 #if PPPOE_SUPPORT 00060 #include "netif/ppp_oe.h" 00061 #endif /* PPPOE_SUPPORT */ 00062 00063 #include <string.h> 00064 00065 const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}}; 00066 const struct eth_addr ethzero = {{0,0,0,0,0,0}}; 00067 00068 #if LWIP_ARP /* don't build if not configured for use in lwipopts.h */ 00069 00070 /** the time an ARP entry stays valid after its last update, 00071 * for ARP_TMR_INTERVAL = 5000, this is 00072 * (240 * 5) seconds = 20 minutes. 00073 */ 00074 #define ARP_MAXAGE 240 00075 /** the time an ARP entry stays pending after first request, 00076 * for ARP_TMR_INTERVAL = 5000, this is 00077 * (2 * 5) seconds = 10 seconds. 00078 * 00079 * @internal Keep this number at least 2, otherwise it might 00080 * run out instantly if the timeout occurs directly after a request. 00081 */ 00082 #define ARP_MAXPENDING 2 00083 00084 #define HWTYPE_ETHERNET 1 00085 00086 #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 21:10:25 by 1.7.2