#include "lwip/pbuf.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
#include "lwip/ip.h"
Include dependency graph for etharp.h:
This graph shows which files directly or indirectly include this file:
Go to the source code of this file.
Data Structures | |
struct | eth_addr |
struct | eth_hdr |
struct | etharp_hdr |
struct | ethip_hdr |
Defines | |
#define | ARP_TMR_INTERVAL 10000 |
#define | ETHTYPE_ARP 0x0806 |
#define | ETHTYPE_IP 0x0800 |
Functions | |
void | etharp_init (void) |
void | etharp_tmr (void) |
pbuf * | etharp_ip_input (struct netif *netif, struct pbuf *p) |
pbuf * | etharp_arp_input (struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p) |
pbuf * | etharp_output (struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q) |
err_t | etharp_query (struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q) |
Variables | |
PACK_STRUCT_BEGIN struct eth_addr | PACK_STRUCT_STRUCT |
|
|
|
|
|
|
|
Responds to ARP requests, updates ARP entries and sends queued IP packets. Should be called for incoming ARP packets. The pbuf in the argument is freed by this function.
Definition at line 396 of file etharp.c. References ip_addr::addr, ARP_INSERT_FLAG, ARP_REPLY, ARP_REQUEST, ARPH_HWLEN_SET, ARPH_PROTOLEN_SET, DBG_TRACE, DEBUGF, ETHARP_DEBUG, ETHTYPE_ARP, ETHTYPE_IP, htons, netif::hwaddr_len, HWTYPE_ETHERNET, netif::ip_addr, ip_addr_cmp, ip_addr_set, netif::linkoutput, NULL, pbuf::payload, pbuf_free(), pbuf::tot_len, u8_t, and update_arp_entry(). Referenced by rt_3c905cif_input(), and rt_rtl8139if_input().
00397 { 00398 struct etharp_hdr *hdr; 00399 u8_t i; 00400 00401 /* drop short ARP packets */ 00402 if(p->tot_len < sizeof(struct etharp_hdr)) { 00403 DEBUGF(ETHARP_DEBUG | DBG_TRACE | 1, ("etharp_arp_input: packet too short (%d/%d)\n", p->tot_len, sizeof(struct etharp_hdr))); 00404 pbuf_free(p); 00405 return NULL; 00406 } 00407 00408 hdr = p->payload; 00409 00410 switch(htons(hdr->opcode)) { 00411 /* ARP request? */ 00412 case ARP_REQUEST: 00413 /* ARP request. If it asked for our address, we send out a 00414 reply. In any case, we time-stamp any existing ARP entry, 00415 and possiby send out an IP packet that was queued on it. */ 00416 00417 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP request\n")); 00418 /* we are not configured? */ 00419 if(netif->ip_addr.addr == 0) { 00420 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n")); 00421 pbuf_free(p); 00422 return NULL; 00423 } 00424 /* update the ARP cache */ 00425 update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), 0); 00426 /* ARP request for our address? */ 00427 if(ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) { 00428 00429 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: replying to ARP request for our IP address\n")); 00430 /* re-use pbuf to send ARP reply */ 00431 hdr->opcode = htons(ARP_REPLY); 00432 00433 ip_addr_set(&(hdr->dipaddr), &(hdr->sipaddr)); 00434 ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr)); 00435 00436 for(i = 0; i < netif->hwaddr_len; ++i) { 00437 hdr->dhwaddr.addr[i] = hdr->shwaddr.addr[i]; 00438 hdr->shwaddr.addr[i] = ethaddr->addr[i]; 00439 hdr->ethhdr.dest.addr[i] = hdr->dhwaddr.addr[i]; 00440 hdr->ethhdr.src.addr[i] = ethaddr->addr[i]; 00441 } 00442 00443 hdr->hwtype = htons(HWTYPE_ETHERNET); 00444 ARPH_HWLEN_SET(hdr, netif->hwaddr_len); 00445 00446 hdr->proto = htons(ETHTYPE_IP); 00447 ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr)); 00448 00449 hdr->ethhdr.type = htons(ETHTYPE_ARP); 00450 /* return ARP reply */ 00451 netif->linkoutput(netif, p); 00452 } else { 00453 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP request was not for us.\n")); 00454 } 00455 break; 00456 case ARP_REPLY: 00457 /* ARP reply. We insert or update the ARP table. */ 00458 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n")); 00459 #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK) 00460 /* DHCP needs to know about ARP replies */ 00461 dhcp_arp_reply(netif, &hdr->sipaddr); 00462 #endif 00463 /* ARP reply directed to us? */ 00464 if(ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) { 00465 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply is for us\n")); 00466 /* update_the ARP cache, ask to insert */ 00467 update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), ARP_INSERT_FLAG); 00468 /* ARP reply not directed to us */ 00469 } else { 00470 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply is not for us\n")); 00471 /* update the destination address pair */ 00472 update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), 0); 00473 /* update the destination address pair */ 00474 update_arp_entry(netif, &(hdr->dipaddr), &(hdr->dhwaddr), 0); 00475 } 00476 break; 00477 default: 00478 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %d\n", htons(hdr->opcode))); 00479 break; 00480 } 00481 /* free ARP packet */ 00482 pbuf_free(p); 00483 p = NULL; 00484 /* nothing to send, we did it! */ 00485 return NULL; 00486 } |
Here is the call graph for this function:
|
Initializes ARP module. Definition at line 128 of file etharp.c. References arp_table, ETHARP_STATE_EMPTY, NULL, etharp_entry::state, and u8_t. Referenced by rt_3c905cif_init(), and rt_rtl8139if_init().
|
|
Updates the ARP table using the given packet. Uses the incoming IP packet's source address to update the ARP cache for the local network. The function does not alter or free the packet. This function must be called before the packet p is passed to the IP layer.
Definition at line 361 of file etharp.c. References ARP_INSERT_FLAG, DBG_TRACE, DEBUGF, ETHARP_DEBUG, netif::ip_addr, ip_addr_maskcmp, netif::netmask, NULL, pbuf::payload, and update_arp_entry(). Referenced by rt_3c905cif_input(), and rt_rtl8139if_input().
00362 { 00363 struct ethip_hdr *hdr; 00364 00365 /* Only insert an entry if the source IP address of the 00366 incoming IP packet comes from a host on the local network. */ 00367 hdr = p->payload; 00368 /* source is on local network? */ 00369 if(!ip_addr_maskcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask))) { 00370 /* do nothing */ 00371 return NULL; 00372 } 00373 00374 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n")); 00375 /* update ARP table, ask to insert entry */ 00376 update_arp_entry(netif, &(hdr->ip.src), &(hdr->eth.src), ARP_INSERT_FLAG); 00377 return NULL; 00378 } |
Here is the call graph for this function:
|
Resolve and fill-in Ethernet address header for outgoing packet. If ARP has the Ethernet address in cache, the given packet is returned, ready to be sent. If ARP does not have the Ethernet address in cache the packet is queued and a ARP request is sent (on a best-effort basis). This ARP request is returned as a pbuf, which should be sent by the caller. If ARP failed to allocate resources, NULL is returned. A returned non-NULL packet should be sent by the caller and etharp_output_sent() must be called afterwards to free any ARP request.
Definition at line 513 of file etharp.c. References ip_addr::addr, arp_table, DBG_TRACE, DEBUGF, etharp_entry::ethaddr, ETHARP_DEBUG, etharp_query(), ETHARP_STATE_STABLE, ethbroadcast, ETHTYPE_IP, netif::gw, htons, netif::hwaddr, netif::hwaddr_len, ip4_addr2, ip4_addr3, ip4_addr4, netif::ip_addr, ip_addr_cmp, ip_addr_isany, ip_addr_isbroadcast, ip_addr_ismulticast, ip_addr_maskcmp, ipaddr, netif::netmask, NULL, pbuf::payload, pbuf_header(), etharp_entry::state, and u8_t. Referenced by rt_3c905cif_output(), and rt_rtl8139if_output().
00514 { 00515 struct eth_addr *dest, *srcaddr, mcastaddr; 00516 struct eth_hdr *ethhdr; 00517 u8_t i; 00518 00519 /* Make room for Ethernet header. */ 00520 if(pbuf_header(q, sizeof(struct eth_hdr)) != 0) { 00521 /* The pbuf_header() call shouldn't fail, and we'll just bail 00522 out if it does.. */ 00523 DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_output: could not allocate room for header.\n")); 00524 #ifdef LINK_STATS 00525 ++lwip_stats.link.lenerr; 00526 #endif /* LINK_STATS */ 00527 return NULL; 00528 } 00529 00530 /* obtain source Ethernet address of the given interface */ 00531 srcaddr = (struct eth_addr *)netif->hwaddr; 00532 00533 /* assume unresolved Ethernet address */ 00534 dest = NULL; 00535 /* Construct Ethernet header. Start with looking up deciding which 00536 MAC address to use as a destination address. Broadcasts and 00537 multicasts are special, all other addresses are looked up in the 00538 ARP table. */ 00539 00540 /* destination IP address is an IP broadcast address? */ 00541 if(ip_addr_isany(ipaddr) || 00542 ip_addr_isbroadcast(ipaddr, &(netif->netmask))) { 00543 /* broadcast on Ethernet also */ 00544 dest = (struct eth_addr *)ðbroadcast; 00545 } 00546 /* destination IP address is an IP multicast address? */ 00547 else if(ip_addr_ismulticast(ipaddr)) { 00548 /* Hash IP multicast address to MAC address. */ 00549 mcastaddr.addr[0] = 0x01; 00550 mcastaddr.addr[1] = 0x0; 00551 mcastaddr.addr[2] = 0x5e; 00552 mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f; 00553 mcastaddr.addr[4] = ip4_addr3(ipaddr); 00554 mcastaddr.addr[5] = ip4_addr4(ipaddr); 00555 /* destination Ethernet address is multicast */ 00556 dest = &mcastaddr; 00557 } 00558 /* destination IP address is an IP unicast address */ 00559 else { 00560 /* destination IP network address not on local network? */ 00561 /* this occurs if the packet is routed to the default gateway on this interface */ 00562 if(!ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) { 00563 /* gateway available? */ 00564 if (netif->gw.addr != 0) 00565 { 00566 /* use the gateway IP address */ 00567 ipaddr = &(netif->gw); 00568 } 00569 /* no gateway available? */ 00570 else 00571 { 00572 /* IP destination address outside local network, but no gateway available */ 00573 return NULL; 00574 } 00575 } 00576 00577 /* Ethernet address for IP destination address is in ARP cache? */ 00578 for(i = 0; i < ARP_TABLE_SIZE; ++i) { 00579 /* match found? */ 00580 if(arp_table[i].state == ETHARP_STATE_STABLE && 00581 ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) { 00582 dest = &arp_table[i].ethaddr; 00583 break; 00584 } 00585 } 00586 /* could not find the destination Ethernet address in ARP cache? */ 00587 if (dest == NULL) { 00588 /* ARP query for the IP address, submit this IP packet for queueing */ 00589 etharp_query(netif, ipaddr, q); 00590 /* return nothing */ 00591 return NULL; 00592 } 00593 /* destination Ethernet address resolved from ARP cache */ 00594 else 00595 { 00596 /* fallthrough */ 00597 } 00598 } 00599 00600 /* destination Ethernet address known */ 00601 if (dest != NULL) { 00602 /* A valid IP->MAC address mapping was found, so we construct the 00603 Ethernet header for the outgoing packet. */ 00604 ethhdr = q->payload; 00605 00606 for(i = 0; i < netif->hwaddr_len; i++) { 00607 ethhdr->dest.addr[i] = dest->addr[i]; 00608 ethhdr->src.addr[i] = srcaddr->addr[i]; 00609 } 00610 00611 ethhdr->type = htons(ETHTYPE_IP); 00612 /* return the outgoing packet */ 00613 return q; 00614 } 00615 /* never reached; here for safety */ 00616 return NULL; 00617 } |
Here is the call graph for this function:
|
Send an ARP request for the given IP address. Sends an ARP request for the given IP address, unless a request for this address is already pending. Optionally queues an outgoing packet on the resulting ARP entry.
Definition at line 644 of file etharp.c. References ARP_REQUEST, arp_table, ARPH_HWLEN_SET, ARPH_PROTOLEN_SET, etharp_entry::ctime, DBG_STATE, DBG_TRACE, DEBUGF, ERR_MEM, ERR_OK, err_t, ETHARP_DEBUG, ETHARP_STATE_PENDING, ETHARP_STATE_STABLE, ETHTYPE_ARP, ETHTYPE_IP, find_arp_entry(), htons, netif::hwaddr, netif::hwaddr_len, HWTYPE_ETHERNET, netif::ip_addr, ip_addr_cmp, ip_addr_set, ipaddr, netif::linkoutput, NULL, pbuf_alloc(), pbuf_free(), PBUF_LINK, PBUF_RAM, pbuf_ref(), pbuf_take(), etharp_entry::state, and u8_t. Referenced by dhcp_check(), and etharp_output().
00645 { 00646 struct eth_addr *srcaddr; 00647 struct etharp_hdr *hdr; 00648 struct pbuf *p; 00649 err_t result = ERR_OK; 00650 u8_t i; 00651 u8_t perform_arp_request = 1; 00652 /* prevent warning if ARP_QUEUEING == 0 */ 00653 if (q); 00654 00655 srcaddr = (struct eth_addr *)netif->hwaddr; 00656 /* bail out if this IP address is pending */ 00657 for(i = 0; i < ARP_TABLE_SIZE; ++i) { 00658 if(ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) { 00659 if (arp_table[i].state == ETHARP_STATE_PENDING) { 00660 DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: requested IP already pending as entry %u\n", i)); 00661 /* break out of for-loop, user may wish to queue a packet on a stable entry */ 00662 break; 00663 } 00664 else if (arp_table[i].state == ETHARP_STATE_STABLE) { 00665 DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: requested IP already stable as entry %u\n", i)); 00666 /* user may wish to queue a packet on a stable entry, so we proceed without ARP requesting */ 00667 /* TODO: even if the ARP entry is stable, we might do an ARP request anyway in some cases? */ 00668 perform_arp_request = 0; 00669 break; 00670 } 00671 } 00672 } 00673 /* queried address not yet in ARP table? */ 00674 if (i == ARP_TABLE_SIZE) { 00675 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: IP address not found in ARP table\n")); 00676 /* find an available entry */ 00677 i = find_arp_entry(); 00678 /* bail out if no ARP entries are available */ 00679 if (i == ARP_TABLE_SIZE) { 00680 DEBUGF(ETHARP_DEBUG | 2, ("etharp_query: no more ARP entries available.\n")); 00681 return ERR_MEM; 00682 } 00683 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: created ARP table entry %u.\n", i)); 00684 /* i is available, create ARP entry */ 00685 ip_addr_set(&arp_table[i].ipaddr, ipaddr); 00686 arp_table[i].ctime = 0; 00687 arp_table[i].state = ETHARP_STATE_PENDING; 00688 #if ARP_QUEUEING 00689 /* free queued packet, as entry is now invalidated */ 00690 if (arp_table[i].p != NULL) { 00691 pbuf_free(arp_table[i].p); 00692 arp_table[i].p = NULL; 00693 DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("etharp_query: dropped packet on ARP queue. Should not occur.\n")); 00694 } 00695 #endif 00696 } 00697 #if ARP_QUEUEING 00698 /* any pbuf to queue and queue is empty? */ 00699 if (q != NULL) { 00700 /* yield later packets over older packets? */ 00701 #if ARP_QUEUE_FIRST == 0 00702 /* earlier queued packet on this entry? */ 00703 if (arp_table[i].p != NULL) { 00704 pbuf_free(arp_table[i].p); 00705 arp_table[i].p = NULL; 00706 DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("etharp_query: dropped packet on ARP queue. Should not occur.\n")); 00707 } 00708 #endif 00709 /* packet can be queued? */ 00710 if (arp_table[i].p == NULL) { 00711 /* copy PBUF_REF referenced payloads to PBUF_RAM */ 00712 q = pbuf_take(q); 00713 /* remember pbuf to queue, if any */ 00714 arp_table[i].p = q; 00715 /* pbufs are queued, increase the reference count */ 00716 pbuf_ref(q); 00717 DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: queued packet %p on ARP entry %u.\n", (void *)q, i)); 00718 } 00719 } 00720 #endif 00721 /* ARP request? */ 00722 if (perform_arp_request) 00723 { 00724 /* allocate a pbuf for the outgoing ARP request packet */ 00725 p = pbuf_alloc(PBUF_LINK, sizeof(struct etharp_hdr), PBUF_RAM); 00726 /* could allocate pbuf? */ 00727 if (p != NULL) { 00728 u8_t j; 00729 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: sending ARP request.\n")); 00730 hdr = p->payload; 00731 hdr->opcode = htons(ARP_REQUEST); 00732 for(j = 0; j < netif->hwaddr_len; ++j) 00733 { 00734 hdr->dhwaddr.addr[j] = 0x00; 00735 hdr->shwaddr.addr[j] = srcaddr->addr[j]; 00736 } 00737 ip_addr_set(&(hdr->dipaddr), ipaddr); 00738 ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr)); 00739 00740 hdr->hwtype = htons(HWTYPE_ETHERNET); 00741 ARPH_HWLEN_SET(hdr, netif->hwaddr_len); 00742 00743 hdr->proto = htons(ETHTYPE_IP); 00744 ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr)); 00745 for(j = 0; j < netif->hwaddr_len; ++j) 00746 { 00747 hdr->ethhdr.dest.addr[j] = 0xff; 00748 hdr->ethhdr.src.addr[j] = srcaddr->addr[j]; 00749 } 00750 hdr->ethhdr.type = htons(ETHTYPE_ARP); 00751 /* send ARP query */ 00752 result = netif->linkoutput(netif, p); 00753 /* free ARP query packet */ 00754 pbuf_free(p); 00755 p = NULL; 00756 } else { 00757 result = ERR_MEM; 00758 DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_query: could not allocate pbuf for ARP request.\n")); 00759 } 00760 } 00761 return result; 00762 } |
Here is the call graph for this function:
|
Clears expired entries in the ARP table. This function should be called every ETHARP_TMR_INTERVAL microseconds (10 seconds), in order to expire entries in the ARP table. Definition at line 147 of file etharp.c. References ARP_MAXAGE, ARP_MAXPENDING, arp_table, etharp_entry::ctime, DEBUGF, ETHARP_DEBUG, ETHARP_STATE_EMPTY, ETHARP_STATE_PENDING, ETHARP_STATE_STABLE, NULL, pbuf_free(), etharp_entry::state, and u8_t. Referenced by rt_3com905cif_etharp_timer(), and rt_rtl8139_ifetharp_timer().
00148 { 00149 u8_t i; 00150 00151 DEBUGF(ETHARP_DEBUG, ("etharp_timer\n")); 00152 /* remove expired entries from the ARP table */ 00153 for(i = 0; i < ARP_TABLE_SIZE; ++i) { 00154 arp_table[i].ctime++; 00155 if((arp_table[i].state == ETHARP_STATE_STABLE) && 00156 (arp_table[i].ctime >= ARP_MAXAGE)) { 00157 DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired stable entry %u.\n", i)); 00158 arp_table[i].state = ETHARP_STATE_EMPTY; 00159 #if ARP_QUEUEING 00160 /* remove any queued packet */ 00161 pbuf_free(arp_table[i].p); 00162 arp_table[i].p = NULL; 00163 #endif 00164 } else if((arp_table[i].state == ETHARP_STATE_PENDING) && 00165 (arp_table[i].ctime >= ARP_MAXPENDING)) { 00166 arp_table[i].state = ETHARP_STATE_EMPTY; 00167 #if ARP_QUEUEING 00168 DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %u - dequeueing %p.\n", i, (void *)(arp_table[i].p))); 00169 /* remove any queued packet */ 00170 pbuf_free(arp_table[i].p); 00171 arp_table[i].p = NULL; 00172 #else 00173 DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %u.\n", i)); 00174 #endif 00175 } 00176 } 00177 } |
Here is the call graph for this function:
|
the ARP message |