386 |
|
|
387 |
|
|
388 |
/** |
/** |
389 |
* Responds to ARP requests, updates ARP entries and sends queued IP packets. |
* Responds to ARP requests to us. Upon ARP replies to us, add entry to cache |
390 |
|
* send out queued IP packets. Updates cache with snooped address pairs. |
391 |
* |
* |
392 |
* Should be called for incoming ARP packets. The pbuf in the argument |
* Should be called for incoming ARP packets. The pbuf in the argument |
393 |
* is freed by this function. |
* is freed by this function. |
405 |
{ |
{ |
406 |
struct etharp_hdr *hdr; |
struct etharp_hdr *hdr; |
407 |
u8_t i; |
u8_t i; |
408 |
|
u8_t for_us; |
409 |
|
|
410 |
/* drop short ARP packets */ |
/* drop short ARP packets */ |
411 |
if (p->tot_len < sizeof(struct etharp_hdr)) { |
if (p->tot_len < sizeof(struct etharp_hdr)) { |
412 |
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 1, ("etharp_arp_input: packet too short (%d/%d)\n", p->tot_len, sizeof(struct etharp_hdr))); |
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 1, ("etharp_arp_input: packet dropped, too short (%d/%d)\n", p->tot_len, sizeof(struct etharp_hdr))); |
413 |
pbuf_free(p); |
pbuf_free(p); |
414 |
return NULL; |
return NULL; |
415 |
} |
} |
416 |
|
|
417 |
hdr = p->payload; |
hdr = p->payload; |
418 |
|
|
419 |
|
/* this interface is not configured? */ |
420 |
|
if (netif->ip_addr.addr == 0) { |
421 |
|
for_us = 0; |
422 |
|
} else { |
423 |
|
/* ARP packet directed to us? */ |
424 |
|
for_us = ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr)); |
425 |
|
} |
426 |
|
|
427 |
switch (htons(hdr->opcode)) { |
switch (htons(hdr->opcode)) { |
428 |
/* ARP request? */ |
/* ARP request? */ |
438 |
pbuf_free(p); |
pbuf_free(p); |
439 |
return NULL; |
return NULL; |
440 |
} |
} |
|
/* update the ARP cache */ |
|
|
update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), 0); |
|
441 |
/* ARP request for our address? */ |
/* ARP request for our address? */ |
442 |
if (ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) { |
if (for_us) { |
443 |
|
|
444 |
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: replying to ARP request for our IP address\n")); |
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: replying to ARP request for our IP address\n")); |
445 |
/* re-use pbuf to send ARP reply */ |
/* re-use pbuf to send ARP reply */ |
458 |
hdr->hwtype = htons(HWTYPE_ETHERNET); |
hdr->hwtype = htons(HWTYPE_ETHERNET); |
459 |
ARPH_HWLEN_SET(hdr, netif->hwaddr_len); |
ARPH_HWLEN_SET(hdr, netif->hwaddr_len); |
460 |
|
|
461 |
hdr->proto = htons(ETHTYPE_IP); |
hdr->proto = htons(ETHTYPE_IP); |
462 |
ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr)); |
ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr)); |
463 |
|
|
464 |
hdr->ethhdr.type = htons(ETHTYPE_ARP); |
hdr->ethhdr.type = htons(ETHTYPE_ARP); |
465 |
/* return ARP reply */ |
/* return ARP reply */ |
466 |
netif->linkoutput(netif, p); |
netif->linkoutput(netif, p); |
467 |
|
|
468 |
|
/* request was not directed to us */ |
469 |
} else { |
} else { |
470 |
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP request was not for us.\n")); |
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP request was not for us.\n")); |
471 |
} |
} |
472 |
break; |
break; |
473 |
case ARP_REPLY: |
case ARP_REPLY: |
474 |
/* ARP reply. We insert or update the ARP table. */ |
/* ARP reply. We insert or update the ARP table later. */ |
475 |
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n")); |
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n")); |
476 |
#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK) |
#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK) |
477 |
/* DHCP needs to know about ARP replies */ |
/* DHCP needs to know about ARP replies to our address */ |
478 |
dhcp_arp_reply(netif, &hdr->sipaddr); |
if (for_us) dhcp_arp_reply(netif, &hdr->sipaddr); |
479 |
#endif |
#endif |
|
/* ARP reply directed to us? */ |
|
|
if (ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) { |
|
|
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply is for us\n")); |
|
|
/* update_the ARP cache, ask to insert */ |
|
|
update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), ARP_INSERT_FLAG); |
|
|
/* ARP reply not directed to us */ |
|
|
} else { |
|
|
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply is not for us\n")); |
|
|
/* update the destination address pair */ |
|
|
update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), 0); |
|
|
/* update the destination address pair */ |
|
|
update_arp_entry(netif, &(hdr->dipaddr), &(hdr->dhwaddr), 0); |
|
|
} |
|
480 |
break; |
break; |
481 |
default: |
default: |
482 |
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %d\n", htons(hdr->opcode))); |
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %d\n", htons(hdr->opcode))); |
483 |
break; |
break; |
484 |
} |
} |
485 |
|
/* add or update entries in the ARP cache */ |
486 |
|
if (for_us) { |
487 |
|
/* insert IP address in ARP cache (assume requester wants to talk to us) |
488 |
|
* we might even send out a queued packet to this host */ |
489 |
|
update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), ARP_INSERT_FLAG); |
490 |
|
/* request was not directed to us, but snoop anyway */ |
491 |
|
} else { |
492 |
|
/* update or insert the source IP address in the cache */ |
493 |
|
update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), 0); |
494 |
|
/* update or insert the destination IP address pair in the cache */ |
495 |
|
update_arp_entry(netif, &(hdr->dipaddr), &(hdr->dhwaddr), 0); |
496 |
|
} |
497 |
/* free ARP packet */ |
/* free ARP packet */ |
498 |
pbuf_free(p); |
pbuf_free(p); |
499 |
p = NULL; |
p = NULL; |
743 |
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: sending ARP request.\n")); |
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: sending ARP request.\n")); |
744 |
hdr = p->payload; |
hdr = p->payload; |
745 |
hdr->opcode = htons(ARP_REQUEST); |
hdr->opcode = htons(ARP_REQUEST); |
746 |
for(j = 0; j < netif->hwaddr_len; ++j) |
for (j = 0; j < netif->hwaddr_len; ++j) |
747 |
{ |
{ |
|
hdr->dhwaddr.addr[j] = 0x00; |
|
748 |
hdr->shwaddr.addr[j] = srcaddr->addr[j]; |
hdr->shwaddr.addr[j] = srcaddr->addr[j]; |
749 |
|
/* the hardware address is what we ask for, in |
750 |
|
* a request it is a don't-care, we use 0's */ |
751 |
|
hdr->dhwaddr.addr[j] = 0x00; |
752 |
} |
} |
753 |
ip_addr_set(&(hdr->dipaddr), ipaddr); |
ip_addr_set(&(hdr->dipaddr), ipaddr); |
754 |
ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr)); |
ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr)); |
758 |
|
|
759 |
hdr->proto = htons(ETHTYPE_IP); |
hdr->proto = htons(ETHTYPE_IP); |
760 |
ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr)); |
ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr)); |
761 |
for(j = 0; j < netif->hwaddr_len; ++j) |
for (j = 0; j < netif->hwaddr_len; ++j) |
762 |
{ |
{ |
763 |
hdr->ethhdr.dest.addr[j] = 0xff; |
hdr->ethhdr.dest.addr[j] = 0xff; |
764 |
hdr->ethhdr.src.addr[j] = srcaddr->addr[j]; |
hdr->ethhdr.src.addr[j] = srcaddr->addr[j]; |