1/** 2 * @file 3 * Address Resolution Protocol module for IP over Ethernet 4 * 5 * Functionally, ARP is divided into two parts. The first maps an IP address 6 * to a physical address when sending a packet, and the second part answers 7 * requests from other machines for our physical address. 8 * 9 * This implementation complies with RFC 826 (Ethernet ARP). It supports 10 * Gratuitious ARP from RFC3220 (IP Mobility Support for IPv4) section 4.6 11 * if an interface calls etharp_gratuitous(our_netif) upon address change. 12 */ 13 14/* 15 * Copyright (c) 2001-2003 Swedish Institute of Computer Science. 16 * Copyright (c) 2003-2004 Leon Woestenberg <leon.woestenberg@axon.tv> 17 * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. 18 * All rights reserved. 19 * 20 * Redistribution and use in source and binary forms, with or without modification, 21 * are permitted provided that the following conditions are met: 22 * 23 * 1. Redistributions of source code must retain the above copyright notice, 24 * this list of conditions and the following disclaimer. 25 * 2. Redistributions in binary form must reproduce the above copyright notice, 26 * this list of conditions and the following disclaimer in the documentation 27 * and/or other materials provided with the distribution. 28 * 3. The name of the author may not be used to endorse or promote products 29 * derived from this software without specific prior written permission. 30 * 31 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 32 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 33 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 34 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 35 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 36 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 37 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 38 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 39 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 40 * OF SUCH DAMAGE. 41 * 42 * This file is part of the lwIP TCP/IP stack. 43 * 44 */ 45 46#include "lwip/opt.h" 47 48#if LWIP_ARP // don't build if not configured for use in lwipopts.h 49 50#include "lwip/inet.h" 51#include "lwip/ip.h" 52#include "lwip/stats.h" 53#include "lwip/snmp.h" 54#include "lwip/dhcp.h" 55#include "lwip/autoip.h" 56#include "netif/etharp.h" 57#include "lwip/init.h" 58 59#if PPPOE_SUPPORT 60#include "netif/ppp_oe.h" 61#endif /* PPPOE_SUPPORT */ 62 63#include <string.h> 64 65/** the time an ARP entry stays valid after its last update, 66 * for ARP_TMR_INTERVAL = 5000, this is 67 * (240 * 5) seconds = 20 minutes. 68 */ 69#define ARP_MAXAGE 240 70/** the time an ARP entry stays pending after first request, 71 * for ARP_TMR_INTERVAL = 5000, this is 72 * (2 * 5) seconds = 10 seconds. 73 * 74 * @internal Keep this number at least 2, otherwise it might 75 * run out instantly if the timeout occurs directly after a request. 76 */ 77#define ARP_MAXPENDING 2 78 79#define HWTYPE_ETHERNET 1 80 81#define ARPH_HWLEN(hdr) (ntohs((hdr)->_hwlen_protolen) >> 8) 82#define ARPH_PROTOLEN(hdr) (ntohs((hdr)->_hwlen_protolen) & 0xff) 83 84#define ARPH_HWLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons(ARPH_PROTOLEN(hdr) | ((len) << 8)) 85#define ARPH_PROTOLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons((len) | (ARPH_HWLEN(hdr) << 8)) 86 87enum etharp_state { 88 ETHARP_STATE_EMPTY = 0, 89 ETHARP_STATE_PENDING, 90 ETHARP_STATE_STABLE 91}; 92 93struct etharp_entry { 94#if ARP_QUEUEING 95 /** 96 * Pointer to queue of pending outgoing packets on this ARP entry. 97 */ 98 struct etharp_q_entry *q; 99#endif 100 struct ip_addr ipaddr; 101 struct eth_addr ethaddr; 102 enum etharp_state state; 103 u8_t ctime; 104 struct netif *netif; 105}; 106 107const struct eth_addr ethbroadcast = { {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} }; 108const struct eth_addr ethzero = { {0, 0, 0, 0, 0, 0} }; 109 110// FIXME: I need a better way to include this prototype 111// Request ARP lookup from ARP server 112uint64_t idc_ARP_lookup(uint32_t ip); 113 114// wrapper function to perform ARP lookup over arp_server 115static struct eth_addr etharp_request_via_ARP_srv(struct netif * netif, 116 struct ip_addr * ipaddr); 117 118static struct etharp_entry arp_table[ARP_TABLE_SIZE]; 119 120#if !LWIP_NETIF_HWADDRHINT 121static u8_t etharp_cached_entry; 122#endif 123 124/** 125 * Try hard to create a new entry - we want the IP address to appear in 126 * the cache (even if this means removing an active entry or so). */ 127#define ETHARP_TRY_HARD 1 128#define ETHARP_FIND_ONLY 2 129 130#if LWIP_NETIF_HWADDRHINT 131#define NETIF_SET_HINT(netif, hint) if (((netif) != NULL) && ((netif)->addr_hint != NULL)) \ 132 *((netif)->addr_hint) = (hint); 133static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags, struct netif *netif); 134#else /* LWIP_NETIF_HWADDRHINT */ 135static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags); 136#endif /* LWIP_NETIF_HWADDRHINT */ 137 138static err_t update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, 139 struct eth_addr *ethaddr, u8_t flags); 140 141 142/* Some checks, instead of etharp_init(): */ 143#if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f)) 144#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" 145#endif 146 147 148#if ARP_QUEUEING 149/** 150 * Free a complete queue of etharp entries 151 * 152 * @param q a qeueue of etharp_q_entry's to free 153 */ 154static void free_etharp_q(struct etharp_q_entry *q) 155{ 156 struct etharp_q_entry *r; 157 158 LWIP_ASSERT("q != NULL", q != NULL); 159 LWIP_ASSERT("q->p != NULL", q->p != NULL); 160 while (q) { 161 r = q; 162 q = q->next; 163 LWIP_ASSERT("r->p != NULL", (r->p != NULL)); 164 pbuf_free(r->p); 165 memp_free(MEMP_ARP_QUEUE, r); 166 } 167} 168#endif 169 170/** 171 * Clears expired entries in the ARP table. 172 * 173 * This function should be called every ETHARP_TMR_INTERVAL microseconds (5 seconds), 174 * in order to expire entries in the ARP table. 175 */ 176void etharp_tmr(void) 177{ 178 u8_t i; 179 180 LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n")); 181 /* remove expired entries from the ARP table */ 182 for (i = 0; i < ARP_TABLE_SIZE; ++i) { 183 arp_table[i].ctime++; 184 if (((arp_table[i].state == ETHARP_STATE_STABLE) && 185 (arp_table[i].ctime >= ARP_MAXAGE)) || 186 ((arp_table[i].state == ETHARP_STATE_PENDING) && 187 (arp_table[i].ctime >= ARP_MAXPENDING))) { 188 /* pending or stable entry has become old! */ 189 LWIP_DEBUGF(ETHARP_DEBUG, 190 ("etharp_timer: expired %s entry %" U16_F ".\n", 191 arp_table[i].state == 192 ETHARP_STATE_STABLE ? "stable" : "pending", 193 (u16_t) i)); 194 /* clean up entries that have just been expired */ 195 /* remove from SNMP ARP index tree */ 196 snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr); 197#if ARP_QUEUEING 198 /* and empty packet queue */ 199 if (arp_table[i].q != NULL) { 200 /* remove all queued packets */ 201 LWIP_DEBUGF(ETHARP_DEBUG, 202 ("etharp_timer: freeing entry %" U16_F 203 ", packet queue %p.\n", (u16_t) i, 204 (void *) (arp_table[i].q))); 205 free_etharp_q(arp_table[i].q); 206 arp_table[i].q = NULL; 207 } 208#endif 209 /* recycle entry for re-use */ 210 arp_table[i].state = ETHARP_STATE_EMPTY; 211 } 212#if ARP_QUEUEING 213 /* still pending entry? (not expired) */ 214 if (arp_table[i].state == ETHARP_STATE_PENDING) { 215 /* resend an ARP query here? */ 216 } 217#endif 218 } 219} 220 221/** 222 * Search the ARP table for a matching or new entry. 223 * 224 * If an IP address is given, return a pending or stable ARP entry that matches 225 * the address. If no match is found, create a new entry with this address set, 226 * but in state ETHARP_EMPTY. The caller must check and possibly change the 227 * state of the returned entry. 228 * 229 * If ipaddr is NULL, return a initialized new entry in state ETHARP_EMPTY. 230 * 231 * In all cases, attempt to create new entries from an empty entry. If no 232 * empty entries are available and ETHARP_TRY_HARD flag is set, recycle 233 * old entries. Heuristic choose the least important entry for recycling. 234 * 235 * @param ipaddr IP address to find in ARP cache, or to add if not found. 236 * @param flags 237 * - ETHARP_TRY_HARD: Try hard to create a entry by allowing recycling of 238 * active (stable or pending) entries. 239 * 240 * @return The ARP entry index that matched or is created, ERR_MEM if no 241 * entry is found or could be recycled. 242 */ 243static s8_t 244#if LWIP_NETIF_HWADDRHINT 245find_entry(struct ip_addr *ipaddr, u8_t flags, struct netif *netif) 246#else /* LWIP_NETIF_HWADDRHINT */ 247find_entry(struct ip_addr *ipaddr, u8_t flags) 248#endif /* LWIP_NETIF_HWADDRHINT */ 249{ 250 s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE; 251 s8_t empty = ARP_TABLE_SIZE; 252 u8_t i = 0, age_pending = 0, age_stable = 0; 253 254#if ARP_QUEUEING 255 /* oldest entry with packets on queue */ 256 s8_t old_queue = ARP_TABLE_SIZE; 257 258 /* its age */ 259 u8_t age_queue = 0; 260#endif 261 262 /* First, test if the last call to this function asked for the 263 * same address. If so, we're really fast! */ 264 if (ipaddr) { 265 /* ipaddr to search for was given */ 266#if LWIP_NETIF_HWADDRHINT 267 if ((netif != NULL) && (netif->addr_hint != NULL)) { 268 /* per-pcb cached entry was given */ 269 u8_t per_pcb_cache = *(netif->addr_hint); 270 271 if ((per_pcb_cache < ARP_TABLE_SIZE) 272 && arp_table[per_pcb_cache].state == ETHARP_STATE_STABLE) { 273 /* the per-pcb-cached entry is stable */ 274 if (ip_addr_cmp(ipaddr, &arp_table[per_pcb_cache].ipaddr)) { 275 /* per-pcb cached entry was the right one! */ 276 ETHARP_STATS_INC(etharp.cachehit); 277 return per_pcb_cache; 278 } 279 } 280 } 281#else /* #if LWIP_NETIF_HWADDRHINT */ 282 if (arp_table[etharp_cached_entry].state == ETHARP_STATE_STABLE) { 283 /* the cached entry is stable */ 284 if (ip_addr_cmp(ipaddr, &arp_table[etharp_cached_entry].ipaddr)) { 285 /* cached entry was the right one! */ 286 ETHARP_STATS_INC(etharp.cachehit); 287 return etharp_cached_entry; 288 } 289 } 290#endif /* #if LWIP_NETIF_HWADDRHINT */ 291 } 292 293 /** 294 * a) do a search through the cache, remember candidates 295 * b) select candidate entry 296 * c) create new entry 297 */ 298 299 /* a) in a single search sweep, do all of this 300 * 1) remember the first empty entry (if any) 301 * 2) remember the oldest stable entry (if any) 302 * 3) remember the oldest pending entry without queued packets (if any) 303 * 4) remember the oldest pending entry with queued packets (if any) 304 * 5) search for a matching IP entry, either pending or stable 305 * until 5 matches, or all entries are searched for. 306 */ 307 308 for (i = 0; i < ARP_TABLE_SIZE; ++i) { 309 /* no empty entry found yet and now we do find one? */ 310 if ((empty == ARP_TABLE_SIZE) 311 && (arp_table[i].state == ETHARP_STATE_EMPTY)) { 312 LWIP_DEBUGF(ETHARP_DEBUG, 313 ("find_entry: found empty entry %" U16_F "\n", 314 (u16_t) i)); 315 /* remember first empty entry */ 316 empty = i; 317 } 318 /* pending entry? */ 319 else if (arp_table[i].state == ETHARP_STATE_PENDING) { 320 /* if given, does IP address match IP address in ARP entry? */ 321 if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) { 322 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 323 ("find_entry: found matching pending entry %" U16_F 324 "\n", (u16_t) i)); 325 /* found exact IP address match, simply bail out */ 326#if LWIP_NETIF_HWADDRHINT 327 NETIF_SET_HINT(netif, i); 328#else /* #if LWIP_NETIF_HWADDRHINT */ 329 etharp_cached_entry = i; 330#endif /* #if LWIP_NETIF_HWADDRHINT */ 331 return i; 332#if ARP_QUEUEING 333 /* pending with queued packets? */ 334 } else if (arp_table[i].q != NULL) { 335 if (arp_table[i].ctime >= age_queue) { 336 old_queue = i; 337 age_queue = arp_table[i].ctime; 338 } 339#endif 340 /* pending without queued packets? */ 341 } else { 342 if (arp_table[i].ctime >= age_pending) { 343 old_pending = i; 344 age_pending = arp_table[i].ctime; 345 } 346 } 347 } 348 /* stable entry? */ 349 else if (arp_table[i].state == ETHARP_STATE_STABLE) { 350 /* if given, does IP address match IP address in ARP entry? */ 351 if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) { 352 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 353 ("find_entry: found matching stable entry %" U16_F 354 "\n", (u16_t) i)); 355 /* found exact IP address match, simply bail out */ 356#if LWIP_NETIF_HWADDRHINT 357 NETIF_SET_HINT(netif, i); 358#else /* #if LWIP_NETIF_HWADDRHINT */ 359 etharp_cached_entry = i; 360#endif /* #if LWIP_NETIF_HWADDRHINT */ 361 return i; 362 /* remember entry with oldest stable entry in oldest, its age in maxtime */ 363 } else if (arp_table[i].ctime >= age_stable) { 364 old_stable = i; 365 age_stable = arp_table[i].ctime; 366 } 367 } 368 } 369 /* { we have no match } => try to create a new entry */ 370 371 /* no empty entry found and not allowed to recycle? */ 372 if (((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_TRY_HARD) == 0)) 373 /* or don't create new entry, only search? */ 374 || ((flags & ETHARP_FIND_ONLY) != 0)) { 375 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 376 ("find_entry: no empty entry found and not allowed to recycle\n")); 377 return (s8_t) ERR_MEM; 378 } 379 380 /* b) choose the least destructive entry to recycle: 381 * 1) empty entry 382 * 2) oldest stable entry 383 * 3) oldest pending entry without queued packets 384 * 4) oldest pending entry with queued packets 385 * 386 * { ETHARP_TRY_HARD is set at this point } 387 */ 388 389 /* 1) empty entry available? */ 390 if (empty < ARP_TABLE_SIZE) { 391 i = empty; 392 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 393 ("find_entry: selecting empty entry %" U16_F "\n", 394 (u16_t) i)); 395 } 396 /* 2) found recyclable stable entry? */ 397 else if (old_stable < ARP_TABLE_SIZE) { 398 /* recycle oldest stable */ 399 i = old_stable; 400 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 401 ("find_entry: selecting oldest stable entry %" U16_F "\n", 402 (u16_t) i)); 403#if ARP_QUEUEING 404 /* no queued packets should exist on stable entries */ 405 LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL); 406#endif 407 /* 3) found recyclable pending entry without queued packets? */ 408 } else if (old_pending < ARP_TABLE_SIZE) { 409 /* recycle oldest pending */ 410 i = old_pending; 411 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 412 ("find_entry: selecting oldest pending entry %" U16_F 413 " (without queue)\n", (u16_t) i)); 414#if ARP_QUEUEING 415 /* 4) found recyclable pending entry with queued packets? */ 416 } else if (old_queue < ARP_TABLE_SIZE) { 417 /* recycle oldest pending */ 418 i = old_queue; 419 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 420 ("find_entry: selecting oldest pending entry %" U16_F 421 ", freeing packet queue %p\n", (u16_t) i, 422 (void *) (arp_table[i].q))); 423 free_etharp_q(arp_table[i].q); 424 arp_table[i].q = NULL; 425#endif 426 /* no empty or recyclable entries found */ 427 } else { 428 return (s8_t) ERR_MEM; 429 } 430 431 /* { empty or recyclable entry found } */ 432 LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE); 433 434 if (arp_table[i].state != ETHARP_STATE_EMPTY) { 435 snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr); 436 } 437 /* recycle entry (no-op for an already empty entry) */ 438 arp_table[i].state = ETHARP_STATE_EMPTY; 439 440 /* IP address given? */ 441 if (ipaddr != NULL) { 442 /* set IP address */ 443 ip_addr_set(&arp_table[i].ipaddr, ipaddr); 444 } 445 arp_table[i].ctime = 0; 446#if LWIP_NETIF_HWADDRHINT 447 NETIF_SET_HINT(netif, i); 448#else /* #if LWIP_NETIF_HWADDRHINT */ 449 etharp_cached_entry = i; 450#endif /* #if LWIP_NETIF_HWADDRHINT */ 451 return (err_t) i; 452} 453 454/** 455 * Send an IP packet on the network using netif->linkoutput 456 * The ethernet header is filled in before sending. 457 * 458 * @params netif the lwIP network interface on which to send the packet 459 * @params p the packet to send, p->payload pointing to the (uninitialized) ethernet header 460 * @params src the source MAC address to be copied into the ethernet header 461 * @params dst the destination MAC address to be copied into the ethernet header 462 * @return ERR_OK if the packet was sent, any other err_t on failure 463 */ 464static err_t 465etharp_send_ip(struct netif *netif, struct pbuf *p, struct eth_addr *src, 466 struct eth_addr *dst) 467{ 468 struct eth_hdr *ethhdr = p->payload; 469 u8_t k; 470 471 LWIP_ASSERT 472 ("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!", 473 (netif->hwaddr_len == ETHARP_HWADDR_LEN)); 474 k = ETHARP_HWADDR_LEN; 475 while (k > 0) { 476 k--; 477 ethhdr->dest.addr[k] = dst->addr[k]; 478 ethhdr->src.addr[k] = src->addr[k]; 479 } 480 ethhdr->type = htons(ETHTYPE_IP); 481 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 482 ("etharp_send_ip: sending packet %p\n", (void *) p)); 483 /* send the packet */ 484 return netif->linkoutput(netif, p); 485} 486 487/** 488 * Update (or insert) a IP/MAC address pair in the ARP cache. 489 * 490 * If a pending entry is resolved, any queued packets will be sent 491 * at this point. 492 * 493 * @param ipaddr IP address of the inserted ARP entry. 494 * @param ethaddr Ethernet address of the inserted ARP entry. 495 * @param flags Defines behaviour: 496 * - ETHARP_TRY_HARD Allows ARP to insert this as a new item. If not specified, 497 * only existing ARP entries will be updated. 498 * 499 * @return 500 * - ERR_OK Succesfully updated ARP cache. 501 * - ERR_MEM If we could not add a new ARP entry when ETHARP_TRY_HARD was set. 502 * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. 503 * 504 * @see pbuf_free() 505 */ 506static err_t 507update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, 508 struct eth_addr *ethaddr, u8_t flags) 509{ 510 s8_t i; 511 u8_t k; 512 513 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | 3, ("update_arp_entry()\n")); 514 LWIP_ASSERT("netif->hwaddr_len == ETHARP_HWADDR_LEN", 515 netif->hwaddr_len == ETHARP_HWADDR_LEN); 516 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 517 ("update_arp_entry: %" U16_F ".%" U16_F ".%" U16_F ".%" U16_F 518 " - %02" X16_F ":%02" X16_F ":%02" X16_F ":%02" X16_F ":%02" 519 X16_F ":%02" X16_F "\n", ip4_addr1(ipaddr), ip4_addr2(ipaddr), 520 ip4_addr3(ipaddr), ip4_addr4(ipaddr), ethaddr->addr[0], 521 ethaddr->addr[1], ethaddr->addr[2], ethaddr->addr[3], 522 ethaddr->addr[4], ethaddr->addr[5])); 523 /* non-unicast address? */ 524 if (ip_addr_isany(ipaddr) || 525 ip_addr_isbroadcast(ipaddr, netif) || ip_addr_ismulticast(ipaddr)) { 526 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 527 ("update_arp_entry: will not add non-unicast IP address to ARP cache\n")); 528 return ERR_ARG; 529 } 530 /* find or create ARP entry */ 531#if LWIP_NETIF_HWADDRHINT 532 i = find_entry(ipaddr, flags, netif); 533#else /* LWIP_NETIF_HWADDRHINT */ 534 i = find_entry(ipaddr, flags); 535#endif /* LWIP_NETIF_HWADDRHINT */ 536 /* bail out if no entry could be found */ 537 if (i < 0) 538 return (err_t) i; 539 540 /* mark it stable */ 541 arp_table[i].state = ETHARP_STATE_STABLE; 542 /* record network interface */ 543 arp_table[i].netif = netif; 544 545 /* insert in SNMP ARP index tree */ 546 snmp_insert_arpidx_tree(netif, &arp_table[i].ipaddr); 547 548 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 549 ("update_arp_entry: updating stable entry %" S16_F "\n", 550 (s16_t) i)); 551 /* update address */ 552 k = ETHARP_HWADDR_LEN; 553 while (k > 0) { 554 k--; 555 arp_table[i].ethaddr.addr[k] = ethaddr->addr[k]; 556 } 557 /* reset time stamp */ 558 arp_table[i].ctime = 0; 559#if ARP_QUEUEING 560 /* this is where we will send out queued packets! */ 561 while (arp_table[i].q != NULL) { 562 struct pbuf *p; 563 564 /* remember remainder of queue */ 565 struct etharp_q_entry *q = arp_table[i].q; 566 567 /* pop first item off the queue */ 568 arp_table[i].q = q->next; 569 /* get the packet pointer */ 570 p = q->p; 571 /* now queue entry can be freed */ 572 memp_free(MEMP_ARP_QUEUE, q); 573 /* send the queued IP packet */ 574 etharp_send_ip(netif, p, (struct eth_addr *) (netif->hwaddr), ethaddr); 575 /* free the queued IP packet */ 576 pbuf_free(p); 577 } 578#endif 579 return ERR_OK; 580} 581 582/** 583 * Finds (stable) ethernet/IP address pair from ARP table 584 * using interface and IP address index. 585 * @note the addresses in the ARP table are in network order! 586 * 587 * @param netif points to interface index 588 * @param ipaddr points to the (network order) IP address index 589 * @param eth_ret points to return pointer 590 * @param ip_ret points to return pointer 591 * @return table index if found, -1 otherwise 592 */ 593s8_t 594etharp_find_addr(struct netif * netif, struct ip_addr * ipaddr, 595 struct eth_addr ** eth_ret, struct ip_addr ** ip_ret) 596{ 597 s8_t i; 598 599 LWIP_UNUSED_ARG(netif); 600 601#if LWIP_NETIF_HWADDRHINT 602 i = find_entry(ipaddr, ETHARP_FIND_ONLY, NULL); 603#else /* LWIP_NETIF_HWADDRHINT */ 604 i = find_entry(ipaddr, ETHARP_FIND_ONLY); 605#endif /* LWIP_NETIF_HWADDRHINT */ 606 if ((i >= 0) && arp_table[i].state == ETHARP_STATE_STABLE) { 607 *eth_ret = &arp_table[i].ethaddr; 608 *ip_ret = &arp_table[i].ipaddr; 609 return i; 610 } 611 return -1; 612} 613 614/** 615 * Updates the ARP table using the given IP packet. 616 * 617 * Uses the incoming IP packet's source address to update the 618 * ARP cache for the local network. The function does not alter 619 * or free the packet. This function must be called before the 620 * packet p is passed to the IP layer. 621 * 622 * @param netif The lwIP network interface on which the IP packet pbuf arrived. 623 * @param p The IP packet that arrived on netif. 624 * 625 * @return NULL 626 * 627 * @see pbuf_free() 628 */ 629void etharp_ip_input(struct netif *netif, struct pbuf *p) 630{ 631 struct ethip_hdr *hdr; 632 633 LWIP_ERROR("netif != NULL", (netif != NULL), return; 634 ); 635 /* Only insert an entry if the source IP address of the 636 incoming IP packet comes from a host on the local network. */ 637 hdr = p->payload; 638 /* source is not on the local network? */ 639 if (!ip_addr_netcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask))) { 640 /* do nothing */ 641 return; 642 } 643 644 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 645 ("etharp_ip_input: updating ETHARP table.\n")); 646 /* update ARP table */ 647 /* @todo We could use ETHARP_TRY_HARD if we think we are going to talk 648 * back soon (for example, if the destination IP address is ours. */ 649 update_arp_entry(netif, &(hdr->ip.src), &(hdr->eth.src), 0); 650} 651 652 653/** 654 * Responds to ARP requests to us. Upon ARP replies to us, add entry to cache 655 * send out queued IP packets. Updates cache with snooped address pairs. 656 * 657 * Should be called for incoming ARP packets. The pbuf in the argument 658 * is freed by this function. 659 * 660 * @param netif The lwIP network interface on which the ARP packet pbuf arrived. 661 * @param ethaddr Ethernet address of netif. 662 * @param p The ARP packet that arrived on netif. Is freed by this function. 663 * 664 * @return NULL 665 * 666 * @see pbuf_free() 667 */ 668void 669etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p) 670{ 671 struct etharp_hdr *hdr; 672 673 /* these are aligned properly, whereas the ARP header fields might not be */ 674 struct ip_addr sipaddr, dipaddr; 675 u8_t i; 676 u8_t for_us; 677 678#if LWIP_AUTOIP 679 const u8_t *ethdst_hwaddr; 680#endif /* LWIP_AUTOIP */ 681 682 LWIP_ERROR("netif != NULL", (netif != NULL), return; 683 ); 684 685 /* drop short ARP packets: we have to check for p->len instead of p->tot_len here 686 since a struct etharp_hdr is pointed to p->payload, so it musn't be chained! */ 687 if (p->len < sizeof(struct etharp_hdr)) { 688 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | 1, 689 ("etharp_arp_input: packet dropped, too short (%" S16_F "/%" 690 S16_F ")\n", p->tot_len, 691 (s16_t) sizeof(struct etharp_hdr))); 692 ETHARP_STATS_INC(etharp.lenerr); 693 ETHARP_STATS_INC(etharp.drop); 694 pbuf_free(p); 695 return; 696 } 697 698 hdr = p->payload; 699 700 /* RFC 826 "Packet Reception": */ 701 if ((hdr->hwtype != htons(HWTYPE_ETHERNET)) || 702 (hdr->_hwlen_protolen != 703 htons((ETHARP_HWADDR_LEN << 8) | sizeof(struct ip_addr))) 704 || (hdr->proto != htons(ETHTYPE_IP)) 705 || (hdr->ethhdr.type != htons(ETHTYPE_ARP))) { 706 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | 1, 707 ("etharp_arp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%" 708 U16_F "/%" U16_F "/%" U16_F "/%" U16_F "/%" U16_F ")\n", 709 hdr->hwtype, ARPH_HWLEN(hdr), hdr->proto, 710 ARPH_PROTOLEN(hdr), hdr->ethhdr.type)); 711 ETHARP_STATS_INC(etharp.proterr); 712 ETHARP_STATS_INC(etharp.drop); 713 pbuf_free(p); 714 return; 715 } 716 ETHARP_STATS_INC(etharp.recv); 717 718#if LWIP_AUTOIP 719 /* We have to check if a host already has configured our random 720 * created link local address and continously check if there is 721 * a host with this IP-address so we can detect collisions */ 722 autoip_arp_reply(netif, hdr); 723#endif /* LWIP_AUTOIP */ 724 725 /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without 726 * structure packing (not using structure copy which breaks strict-aliasing rules). */ 727 SMEMCPY(&sipaddr, &hdr->sipaddr, sizeof(sipaddr)); 728 SMEMCPY(&dipaddr, &hdr->dipaddr, sizeof(dipaddr)); 729 730 /* this interface is not configured? */ 731 if (netif->ip_addr.addr == 0) { 732 for_us = 0; 733 } else { 734 /* ARP packet directed to us? */ 735 for_us = ip_addr_cmp(&dipaddr, &(netif->ip_addr)); 736 } 737 738 /* ARP message directed to us? */ 739 if (for_us) { 740 /* add IP address in ARP cache; assume requester wants to talk to us. 741 * can result in directly sending the queued packets for this host. */ 742 update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), ETHARP_TRY_HARD); 743 /* ARP message not directed to us? */ 744 } else { 745 /* update the source IP address in the cache, if present */ 746 update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), 0); 747 } 748 749 /* now act on the message itself */ 750 switch (htons(hdr->opcode)) { 751 /* ARP request? */ 752 case ARP_REQUEST: 753 /* ARP request. If it asked for our address, we send out a 754 * reply. In any case, we time-stamp any existing ARP entry, 755 * and possiby send out an IP packet that was queued on it. */ 756 757 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 758 ("etharp_arp_input: incoming ARP request\n")); 759 /* ARP request for our address? */ 760 if (for_us) { 761 762 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 763 ("etharp_arp_input: replying to ARP request for our IP address\n")); 764 /* Re-use pbuf to send ARP reply. 765 Since we are re-using an existing pbuf, we can't call etharp_raw since 766 that would allocate a new pbuf. */ 767 pbuf_realloc(p, sizeof(struct etharp_hdr)); 768 hdr->opcode = htons(ARP_REPLY); 769 770 hdr->dipaddr = hdr->sipaddr; 771 SMEMCPY(&hdr->sipaddr, &netif->ip_addr, sizeof(hdr->sipaddr)); 772 773 LWIP_ASSERT 774 ("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!", 775 (netif->hwaddr_len == ETHARP_HWADDR_LEN)); 776 i = ETHARP_HWADDR_LEN; 777#if LWIP_AUTOIP 778 /* If we are using Link-Local, ARP packets must be broadcast on the 779 * link layer. (See RFC3927 Section 2.5) */ 780 ethdst_hwaddr = ((netif->autoip != NULL) 781 && (netif->autoip->state != 782 AUTOIP_STATE_OFF)) ? (u8_t 783 *) (ethbroadcast. 784 addr) : hdr-> 785 shwaddr.addr; 786#endif /* LWIP_AUTOIP */ 787 788 while (i > 0) { 789 i--; 790 hdr->dhwaddr.addr[i] = hdr->shwaddr.addr[i]; 791#if LWIP_AUTOIP 792 hdr->ethhdr.dest.addr[i] = ethdst_hwaddr[i]; 793#else /* LWIP_AUTOIP */ 794 hdr->ethhdr.dest.addr[i] = hdr->shwaddr.addr[i]; 795#endif /* LWIP_AUTOIP */ 796 hdr->shwaddr.addr[i] = ethaddr->addr[i]; 797 hdr->ethhdr.src.addr[i] = ethaddr->addr[i]; 798 } 799 800 /* hwtype, hwaddr_len, proto, protolen and the type in the ethernet header 801 are already correct, we tested that before */ 802 803 /* return ARP reply */ 804 netif->linkoutput(netif, p); 805 /* we are not configured? */ 806 } else if (netif->ip_addr.addr == 0) { 807 /* { for_us == 0 and netif->ip_addr.addr == 0 } */ 808 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 809 ("etharp_arp_input: we are unconfigured, ARP request ignored.\n")); 810 /* request was not directed to us */ 811 } else { 812 /* { for_us == 0 and netif->ip_addr.addr != 0 } */ 813 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 814 ("etharp_arp_input: ARP request was not for us.\n")); 815 } 816 break; 817 case ARP_REPLY: 818 /* ARP reply. We already updated the ARP cache earlier. */ 819 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 820 ("etharp_arp_input: incoming ARP reply\n")); 821#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK) 822 /* DHCP wants to know about ARP replies from any host with an 823 * IP address also offered to us by the DHCP server. We do not 824 * want to take a duplicate IP address on a single network. 825 * @todo How should we handle redundant (fail-over) interfaces? */ 826 dhcp_arp_reply(netif, &sipaddr); 827#endif 828 break; 829 default: 830 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 831 ("etharp_arp_input: ARP unknown opcode type %" S16_F 832 "\n", htons(hdr->opcode))); 833 ETHARP_STATS_INC(etharp.err); 834 break; 835 } 836 /* free ARP packet */ 837 pbuf_free(p); 838} 839 840/** 841 * Resolve and fill-in Ethernet address header for outgoing IP packet. 842 * 843 * For IP multicast and broadcast, corresponding Ethernet addresses 844 * are selected and the packet is transmitted on the link. 845 * 846 * For unicast addresses, the packet is submitted to etharp_query(). In 847 * case the IP address is outside the local network, the IP address of 848 * the gateway is used. 849 * 850 * @param netif The lwIP network interface which the IP packet will be sent on. 851 * @param q The pbuf(s) containing the IP packet to be sent. 852 * @param ipaddr The IP address of the packet destination. 853 * 854 * @return 855 * - ERR_RTE No route to destination (no gateway to external networks), 856 * or the return type of either etharp_query() or etharp_send_ip(). 857 */ 858err_t etharp_output(struct netif *netif, struct pbuf *q, struct ip_addr *ipaddr) 859{ 860 struct eth_addr *dest, mcastaddr; 861 862 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, "etharp_output : called\n"); 863 /* make room for Ethernet header - should not fail */ 864 if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) { 865 /* bail out */ 866 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | 2, 867 ("etharp_output: could not allocate room for header.\n")); 868 LINK_STATS_INC(link.lenerr); 869 return ERR_BUF; 870 } 871 872 /* assume unresolved Ethernet address */ 873 dest = NULL; 874 /* Determine on destination hardware address. Broadcasts and multicasts 875 * are special, other IP addresses are looked up in the ARP table. */ 876 877 /* broadcast destination IP address? */ 878 if (ip_addr_isbroadcast(ipaddr, netif)) { 879 /* broadcast on Ethernet also */ 880 dest = (struct eth_addr *) ðbroadcast; 881 /* multicast destination IP address? */ 882 } else if (ip_addr_ismulticast(ipaddr)) { 883 /* Hash IP multicast address to MAC address. */ 884 mcastaddr.addr[0] = 0x01; 885 mcastaddr.addr[1] = 0x00; 886 mcastaddr.addr[2] = 0x5e; 887 mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f; 888 mcastaddr.addr[4] = ip4_addr3(ipaddr); 889 mcastaddr.addr[5] = ip4_addr4(ipaddr); 890 /* destination Ethernet address is multicast */ 891 dest = &mcastaddr; 892 /* unicast destination IP address? */ 893 } else { 894 /* outside local network? */ 895 if (!ip_addr_netcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) { 896 /* interface has default gateway? */ 897 if (netif->gw.addr != 0) { 898 /* send to hardware address of default gateway IP address */ 899 ipaddr = &(netif->gw); 900 /* no default gateway available */ 901 } else { 902 /* no route to destination error (default gateway missing) */ 903 return ERR_RTE; 904 } 905 } 906 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 907 ("%s:etharp_output : queue for etharp_query\n", disp_name())); 908 /* queue on destination Ethernet address belonging to ipaddr */ 909 return etharp_query(netif, ipaddr, q); 910 } 911 912 /* continuation for multicast/broadcast destinations */ 913 /* obtain source Ethernet address of the given interface */ 914 /* send packet directly on the link */ 915 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 916 ("%s:etharp_output : send packet directly on link\n", disp_name())); 917 return etharp_send_ip(netif, q, (struct eth_addr *) (netif->hwaddr), dest); 918} 919 920bool is_ip_present_in_arp_cache(struct ip_addr *ipaddr) 921{ 922 int i; 923 924 /* find entry in ARP cache, ask to create entry if queueing packet */ 925#if LWIP_NETIF_HWADDRHINT 926 assert(!"NYI"); 927#else /* LWIP_NETIF_HWADDRHINT */ 928 i = find_entry(ipaddr, ETHARP_TRY_HARD); 929#endif /* LWIP_NETIF_HWADDRHINT */ 930 931 if (i < 0) { 932 return false; 933 } 934 if (arp_table[i].state == ETHARP_STATE_STABLE) { 935 return true; 936 } 937 return false; 938} 939 940/** 941 * Send an ARP request for the given IP address and/or queue a packet. 942 * 943 * If the IP address was not yet in the cache, a pending ARP cache entry 944 * is added and an ARP request is sent for the given address. The packet 945 * is queued on this entry. 946 * 947 * If the IP address was already pending in the cache, a new ARP request 948 * is sent for the given address. The packet is queued on this entry. 949 * 950 * If the IP address was already stable in the cache, and a packet is 951 * given, it is directly sent and no ARP request is sent out. 952 * 953 * If the IP address was already stable in the cache, and no packet is 954 * given, an ARP request is sent out. 955 * 956 * @param netif The lwIP network interface on which ipaddr 957 * must be queried for. 958 * @param ipaddr The IP address to be resolved. 959 * @param q If non-NULL, a pbuf that must be delivered to the IP address. 960 * q is not freed by this function. 961 * 962 * @note q must only be ONE packet, not a packet queue! 963 * 964 * @return 965 * - ERR_BUF Could not make room for Ethernet header. 966 * - ERR_MEM Hardware address unknown, and no more ARP entries available 967 * to query for address or queue the packet. 968 * - ERR_MEM Could not queue packet due to memory shortage. 969 * - ERR_RTE No route to destination (no gateway to external networks). 970 * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. 971 * 972 */ 973err_t 974etharp_query(struct netif * netif, struct ip_addr * ipaddr, struct pbuf * q) 975{ 976 struct eth_addr *srcaddr = (struct eth_addr *) netif->hwaddr; 977 err_t result = ERR_MEM; 978 s8_t i; /* ARP entry index */ 979 980 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 981 ("%s:etharp_query: called\n", disp_name())); 982 983 /* non-unicast address? */ 984 if (ip_addr_isbroadcast(ipaddr, netif) || 985 ip_addr_ismulticast(ipaddr) || ip_addr_isany(ipaddr)) { 986 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 987 ("etharp_query: will not add non-unicast IP address to ARP cache\n")); 988 return ERR_ARG; 989 } 990 991 /* find entry in ARP cache, ask to create entry if queueing packet */ 992#if LWIP_NETIF_HWADDRHINT 993 i = find_entry(ipaddr, ETHARP_TRY_HARD, netif); 994#else /* LWIP_NETIF_HWADDRHINT */ 995 i = find_entry(ipaddr, ETHARP_TRY_HARD); 996#endif /* LWIP_NETIF_HWADDRHINT */ 997 998 /* could not find or create entry? */ 999 if (i < 0) { 1000 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 1001 ("etharp_query: could not create ARP entry\n")); 1002 if (q) { 1003 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 1004 ("etharp_query: packet dropped\n")); 1005 ETHARP_STATS_INC(etharp.memerr); 1006 } 1007 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 1008 ("%s:etharp_query: error: could not find/create entry\n", disp_name())); 1009 return (err_t) i; 1010 } 1011 1012 /* mark a fresh entry as pending (we just sent a request) */ 1013 if (arp_table[i].state == ETHARP_STATE_EMPTY) { 1014 arp_table[i].state = ETHARP_STATE_PENDING; 1015 } 1016 1017 /* { i is either a STABLE or (new or existing) PENDING entry } */ 1018 LWIP_ASSERT("arp_table[i].state == PENDING or STABLE", 1019 ((arp_table[i].state == ETHARP_STATE_PENDING) || 1020 (arp_table[i].state == ETHARP_STATE_STABLE))); 1021 1022 /* do we have a pending entry? or an implicit query request? */ 1023 if ((arp_table[i].state == ETHARP_STATE_PENDING) || (q == NULL)) { 1024 1025 // If this is a ARP_server 1026 if (is_this_special_app()) { 1027 // As this is ARP server, it will have to follow the normal 1028 // path of actually sending the ARP request packet 1029 /* try to resolve it; send out ARP request */ 1030 result = etharp_request(netif, ipaddr); 1031 if (result != ERR_OK) { 1032 /* ARP request couldn't be sent */ 1033 /* We don't re-send arp request in etharp_tmr, but we still queue packets, 1034 since this failure could be temporary, and the next packet calling 1035 etharp_query again could lead to sending the queued packets. */ 1036 } 1037 } else { 1038 // This is a ARP client 1039 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 1040 ("%s:etharp_query: this is ARP client\n", disp_name())); 1041 arp_table[i].ethaddr = etharp_request_via_ARP_srv(netif, ipaddr); 1042 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 1043 ("%s:etharp_query: ARP client got reply\n", disp_name())); 1044 arp_table[i].state = ETHARP_STATE_STABLE; 1045 } // end else: not a special app 1046 } // end if: ARP table state pending 1047 1048 /* packet given? */ 1049 if (q != NULL) { 1050 /* stable entry? */ 1051 if (arp_table[i].state == ETHARP_STATE_STABLE) { 1052 /* we have a valid IP->Ethernet address mapping */ 1053 /* send the packet */ 1054 result = etharp_send_ip(netif, q, srcaddr, &(arp_table[i].ethaddr)); 1055 /* pending entry? (either just created or already pending */ 1056 } else if (arp_table[i].state == ETHARP_STATE_PENDING) { 1057#if ARP_QUEUEING /* queue the given q packet */ 1058 struct pbuf *p; 1059 int copy_needed = 0; 1060 1061 /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but 1062 * to copy the whole queue into a new PBUF_RAM (see bug #11400) 1063 * PBUF_ROMs can be left as they are, since ROM must not get changed. */ 1064 p = q; 1065 while (p) { 1066 LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) 1067 || (p->next == 0)); 1068 if (p->type != PBUF_ROM) { 1069 copy_needed = 1; 1070 break; 1071 } 1072 p = p->next; 1073 } 1074 if (copy_needed) { 1075 /* copy the whole packet into new pbufs */ 1076 p = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); 1077 if (p != NULL) { 1078 if (pbuf_copy(p, q) != ERR_OK) { 1079 pbuf_free(p); 1080 p = NULL; 1081 } 1082 } 1083 } else { 1084 /* referencing the old pbuf is enough */ 1085 p = q; 1086 pbuf_ref(p); 1087 } 1088 /* packet could be taken over? */ 1089 if (p != NULL) { 1090 /* queue packet ... */ 1091 struct etharp_q_entry *new_entry; 1092 1093 /* allocate a new arp queue entry */ 1094 new_entry = memp_malloc(MEMP_ARP_QUEUE); 1095 if (new_entry != NULL) { 1096 new_entry->next = 0; 1097 new_entry->p = p; 1098 if (arp_table[i].q != NULL) { 1099 /* queue was already existent, append the new entry to the end */ 1100 struct etharp_q_entry *r; 1101 1102 r = arp_table[i].q; 1103 while (r->next != NULL) { 1104 r = r->next; 1105 } 1106 r->next = new_entry; 1107 } else { 1108 /* queue did not exist, first item in queue */ 1109 arp_table[i].q = new_entry; 1110 } 1111 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 1112 ("etharp_query: queued packet %p on ARP entry %" 1113 S16_F "\n", (void *) q, (s16_t) i)); 1114 result = ERR_OK; 1115 } else { 1116 /* the pool MEMP_ARP_QUEUE is empty */ 1117 pbuf_free(p); 1118 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 1119 ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", 1120 (void *) q)); 1121 /* { result == ERR_MEM } through initialization */ 1122 } 1123 } else { 1124 ETHARP_STATS_INC(etharp.memerr); 1125 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 1126 ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", 1127 (void *) q)); 1128 /* { result == ERR_MEM } through initialization */ 1129 } 1130#else /* ARP_QUEUEING == 0 */ 1131 /* q && state == PENDING && ARP_QUEUEING == 0 => result = ERR_MEM */ 1132 /* { result == ERR_MEM } through initialization */ 1133 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 1134 ("etharp_query: Ethernet destination address unknown, queueing disabled, packet %p dropped\n", 1135 (void *) q)); 1136#endif 1137 } 1138 } 1139 return result; 1140} 1141 1142/** 1143 * Send a raw ARP packet (opcode and all addresses can be modified) 1144 * 1145 * @param netif the lwip network interface on which to send the ARP packet 1146 * @param ethsrc_addr the source MAC address for the ethernet header 1147 * @param ethdst_addr the destination MAC address for the ethernet header 1148 * @param hwsrc_addr the source MAC address for the ARP protocol header 1149 * @param ipsrc_addr the source IP address for the ARP protocol header 1150 * @param hwdst_addr the destination MAC address for the ARP protocol header 1151 * @param ipdst_addr the destination IP address for the ARP protocol header 1152 * @param opcode the type of the ARP packet 1153 * @return ERR_OK if the ARP packet has been sent 1154 * ERR_MEM if the ARP packet couldn't be allocated 1155 * any other err_t on failure 1156 */ 1157#if !LWIP_AUTOIP 1158static 1159#endif /* LWIP_AUTOIP */ 1160 err_t 1161etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, 1162 const struct eth_addr *ethdst_addr, 1163 const struct eth_addr *hwsrc_addr, const struct ip_addr *ipsrc_addr, 1164 const struct eth_addr *hwdst_addr, const struct ip_addr *ipdst_addr, 1165 const u16_t opcode) 1166{ 1167 struct pbuf *p; 1168 err_t result = ERR_OK; 1169 u8_t k; /* ARP entry index */ 1170 struct etharp_hdr *hdr; 1171 1172#if LWIP_AUTOIP 1173 const u8_t *ethdst_hwaddr; 1174#endif /* LWIP_AUTOIP */ 1175 1176 /* allocate a pbuf for the outgoing ARP request packet */ 1177 p = pbuf_alloc(PBUF_RAW, sizeof(struct etharp_hdr), PBUF_RAM); 1178 /* could allocate a pbuf for an ARP request? */ 1179 if (p == NULL) { 1180 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | 2, 1181 ("etharp_raw: could not allocate pbuf for ARP request.\n")); 1182 ETHARP_STATS_INC(etharp.memerr); 1183 return ERR_MEM; 1184 } 1185 LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr", 1186 (p->len >= sizeof(struct etharp_hdr))); 1187 1188 hdr = p->payload; 1189 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 1190 ("etharp_raw: sending raw ARP packet.\n")); 1191 hdr->opcode = htons(opcode); 1192 1193 LWIP_ASSERT 1194 ("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!", 1195 (netif->hwaddr_len == ETHARP_HWADDR_LEN)); 1196 k = ETHARP_HWADDR_LEN; 1197#if LWIP_AUTOIP 1198 /* If we are using Link-Local, ARP packets must be broadcast on the 1199 * link layer. (See RFC3927 Section 2.5) */ 1200 ethdst_hwaddr = ((netif->autoip != NULL) 1201 && (netif->autoip->state != 1202 AUTOIP_STATE_OFF)) ? (u8_t *) (ethbroadcast. 1203 addr) : ethdst_addr-> 1204 addr; 1205#endif /* LWIP_AUTOIP */ 1206 /* Write MAC-Addresses (combined loop for both headers) */ 1207 while (k > 0) { 1208 k--; 1209 /* Write the ARP MAC-Addresses */ 1210 hdr->shwaddr.addr[k] = hwsrc_addr->addr[k]; 1211 hdr->dhwaddr.addr[k] = hwdst_addr->addr[k]; 1212 /* Write the Ethernet MAC-Addresses */ 1213#if LWIP_AUTOIP 1214 hdr->ethhdr.dest.addr[k] = ethdst_hwaddr[k]; 1215#else /* LWIP_AUTOIP */ 1216 hdr->ethhdr.dest.addr[k] = ethdst_addr->addr[k]; 1217#endif /* LWIP_AUTOIP */ 1218 hdr->ethhdr.src.addr[k] = ethsrc_addr->addr[k]; 1219 } 1220 hdr->sipaddr = *(struct ip_addr2 *) ipsrc_addr; 1221 hdr->dipaddr = *(struct ip_addr2 *) ipdst_addr; 1222 1223 hdr->hwtype = htons(HWTYPE_ETHERNET); 1224 hdr->proto = htons(ETHTYPE_IP); 1225 /* set hwlen and protolen together */ 1226 hdr->_hwlen_protolen = 1227 htons((ETHARP_HWADDR_LEN << 8) | sizeof(struct ip_addr)); 1228 1229 hdr->ethhdr.type = htons(ETHTYPE_ARP); 1230 /* send ARP query */ 1231 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 1232 ("%s: etharp_raw\n", disp_name())); 1233 result = netif->linkoutput(netif, p); 1234 ETHARP_STATS_INC(etharp.xmit); 1235 /* free ARP query packet */ 1236 pbuf_free(p); 1237 p = NULL; 1238 /* could not allocate pbuf for ARP request */ 1239 1240 return result; 1241} 1242 1243/** 1244 * Send an ARP request packet asking for ipaddr. 1245 * 1246 * @param netif the lwip network interface on which to send the request 1247 * @param ipaddr the IP address for which to ask 1248 * @return ERR_OK if the request has been sent 1249 * ERR_MEM if the ARP packet couldn't be allocated 1250 * any other err_t on failure 1251 */ 1252err_t etharp_request(struct netif * netif, struct ip_addr * ipaddr) 1253{ 1254 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 1255 ("etharp_request: sending ARP request.\n")); 1256 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 1257 ("etharp_request: sending ARP request:" "%" U16_F ".%" U16_F 1258 ".%" U16_F ".%" U16_F "\n", ip4_addr1(ipaddr), 1259 ip4_addr2(ipaddr), ip4_addr3(ipaddr), ip4_addr4(ipaddr))); 1260 return etharp_raw(netif, (struct eth_addr *) netif->hwaddr, ðbroadcast, 1261 (struct eth_addr *) netif->hwaddr, &netif->ip_addr, 1262 ðzero, ipaddr, ARP_REQUEST); 1263} 1264 1265/** 1266 * Process received ethernet frames. Using this function instead of directly 1267 * calling ip_input and passing ARP frames through etharp in ethernetif_input, 1268 * the ARP cache is protected from concurrent access. 1269 * 1270 * @param p the recevied packet, p->payload pointing to the ethernet header 1271 * @param netif the network interface on which the packet was received 1272 */ 1273err_t ethernet_input(struct pbuf *p, struct netif *netif) 1274{ 1275 struct eth_hdr *ethhdr; 1276 1277 /* points to packet payload, which starts with an Ethernet header */ 1278 ethhdr = p->payload; 1279 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 1280 ("ethernet_input: dest:%02x:%02x:%02x:%02x:%02x:%02x, src:%02x:%02x:%02x:%02x:%02x:%02x, type:%2hx\n", 1281 (unsigned) ethhdr->dest.addr[0], 1282 (unsigned) ethhdr->dest.addr[1], 1283 (unsigned) ethhdr->dest.addr[2], 1284 (unsigned) ethhdr->dest.addr[3], 1285 (unsigned) ethhdr->dest.addr[4], 1286 (unsigned) ethhdr->dest.addr[5], 1287 (unsigned) ethhdr->src.addr[0], (unsigned) ethhdr->src.addr[1], 1288 (unsigned) ethhdr->src.addr[2], (unsigned) ethhdr->src.addr[3], 1289 (unsigned) ethhdr->src.addr[4], (unsigned) ethhdr->src.addr[5], 1290 (unsigned) htons(ethhdr->type))); 1291 1292 switch (htons(ethhdr->type)) { 1293 /* IP packet? */ 1294 case ETHTYPE_IP: 1295#if ETHARP_TRUST_IP_MAC 1296 /* update ARP table */ 1297 etharp_ip_input(netif, p); 1298#endif /* ETHARP_TRUST_IP_MAC */ 1299 /* skip Ethernet header */ 1300 if (pbuf_header(p, -(s16_t) sizeof(struct eth_hdr))) { 1301// LWIP_ASSERT("Can't move over header in packet", 0); 1302 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 1303 ("ethernet_input: Can't move over header in packet %d, %p\n", 1304 p->len, p->next)); 1305 pbuf_free(p); 1306 p = NULL; 1307 } else { 1308 /* pass to IP layer */ 1309 ip_input(p, netif); 1310 } 1311 break; 1312 1313 case ETHTYPE_ARP: 1314 /* pass p to ARP module */ 1315 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 1316 ("ethernet_input: ARP packet\n")); 1317 etharp_arp_input(netif, (struct eth_addr *) (netif->hwaddr), p); 1318 break; 1319 1320#if PPPOE_SUPPORT 1321 case ETHTYPE_PPPOEDISC: /* PPP Over Ethernet Discovery Stage */ 1322 pppoe_disc_input(netif, p); 1323 break; 1324 1325 case ETHTYPE_PPPOE: /* PPP Over Ethernet Session Stage */ 1326 pppoe_data_input(netif, p); 1327 break; 1328#endif /* PPPOE_SUPPORT */ 1329 1330 default: 1331 ETHARP_STATS_INC(etharp.proterr); 1332 ETHARP_STATS_INC(etharp.drop); 1333 pbuf_free(p); 1334 p = NULL; 1335 break; 1336 } 1337 1338 /* This means the pbuf is freed or consumed, 1339 so the caller doesn't have to free it again */ 1340 return ERR_OK; 1341} 1342 1343// ************************************************************** 1344// functionality to use ARP server 1345// ************************************************************** 1346 1347 1348// ************************************************************** 1349// For ARP client 1350 1351// Union to get the MAC address from uint64_t 1352// needed for interpretetion as result provided by ARP lookup over arp_server 1353// is uint64_t 1354union mac_addr_un { 1355 struct eth_addr ethaddr; 1356 uint64_t mac_addr; 1357}; 1358 1359 1360struct eth_addr convert_uint64_to_eth_addr(uint64_t given_mac) 1361{ 1362 union mac_addr_un tmp_mac; 1363 tmp_mac.mac_addr = given_mac; 1364 1365 // FIXME: make sure that this works irrespective of endianness of a machine 1366 return tmp_mac.ethaddr; 1367} 1368 1369/** 1370 * Send an ARP request packet asking for ipaddr. 1371 * 1372 * @param netif the lwip network interface on which to send the request 1373 * @param ipaddr the IP address for which to ask 1374 * @return mac address of the IP 1375 */ 1376static struct eth_addr etharp_request_via_ARP_srv(struct netif * netif, 1377 struct ip_addr * ipaddr) 1378{ 1379 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 1380 ("etharp_request_via_ARP_srv: sending ARP request.\n" )); 1381 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, 1382 ("etharp_request_via_ARP_srv: sending ARP request:" 1383 "%" U16_F ".%" U16_F ".%" U16_F ".%" U16_F "\n", 1384 ip4_addr1(ipaddr), ip4_addr2(ipaddr), ip4_addr3(ipaddr), 1385 ip4_addr4(ipaddr))); 1386 1387 uint64_t found_mac = idc_ARP_lookup(ipaddr->addr); 1388 if (found_mac == 0) { 1389 abort(); 1390 } 1391 return (convert_uint64_to_eth_addr(found_mac)); 1392} 1393 1394// ************************************************************** 1395// For ARP server 1396 1397// Finds the given IP in ARP cache, if no entry found, returns zero 1398uint64_t find_ip_arp_cache(struct ip_addr *ipaddr) 1399{ 1400 int i; 1401 1402 /* find entry in ARP cache, ask to create entry if queueing packet */ 1403#if LWIP_NETIF_HWADDRHINT 1404 assert(!"NYI"); 1405#else /* LWIP_NETIF_HWADDRHINT */ 1406 i = find_entry(ipaddr, ETHARP_TRY_HARD); 1407#endif /* LWIP_NETIF_HWADDRHINT */ 1408 1409 union mac_addr_un tmp_mac; 1410 if (i < 0) { 1411 return 0; 1412 } 1413 if (arp_table[i].state == ETHARP_STATE_STABLE) { 1414 tmp_mac.ethaddr = arp_table[i].ethaddr; 1415 return tmp_mac.mac_addr; 1416 } 1417 return 0; 1418} 1419 1420// ************************************************************** 1421#endif // LWIP_ARP : EOF 1422