📄 uip-arp.c
字号:
tabptr->at_time = g_arptime;}/**************************************************************************** * Public Functions ****************************************************************************//* Initialize the ARP module. */void uip_arp_init(void){ int i; for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i) { memset(&arp_table[i].at_ipaddr, 0, sizeof(in_addr_t)); }}/* Periodic ARP processing function. * * This function performs periodic timer processing in the ARP module * and should be called at regular intervals. The recommended interval * is 10 seconds between the calls. */void uip_arp_timer(void){ struct arp_entry *tabptr; int i; ++g_arptime; for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i) { tabptr = &arp_table[i]; if (tabptr->at_ipaddr != 0 && g_arptime - tabptr->at_time >= UIP_ARP_MAXAGE) { tabptr->at_ipaddr = 0; } }}/* ARP processing for incoming ARP packets. * * This function should be called by the device driver when an ARP * packet has been received. The function will act differently * depending on the ARP packet type: if it is a reply for a request * that we previously sent out, the ARP cache will be filled in with * the values from the ARP reply. If the incoming ARP packet is an ARP * request for our IP address, an ARP reply packet is created and put * into the d_buf[] buffer. * * When the function returns, the value of the field d_len * indicates whether the device driver should send out a packet or * not. If d_len is zero, no packet should be sent. If d_len is * non-zero, it contains the length of the outbound packet that is * present in the d_buf[] buffer. * * This function expects an ARP packet with a prepended Ethernet * header in the d_buf[] buffer, and the length of the packet in the * global variable d_len. */void uip_arp_arpin(struct uip_driver_s *dev){ in_addr_t ipaddr; if (dev->d_len < (sizeof(struct arp_hdr) + UIP_LLH_LEN)) { dev->d_len = 0; return; } dev->d_len = 0; ipaddr = uip_ip4addr_conv(ARPBUF->ah_dipaddr); switch(ARPBUF->ah_opcode) { case HTONS(ARP_REQUEST): /* ARP request. If it asked for our address, we send out a reply. */ if (uip_ipaddr_cmp(ipaddr, dev->d_ipaddr)) { /* First, we register the one who made the request in our ARP * table, since it is likely that we will do more communication * with this host in the future. */ uip_arp_update(ARPBUF->ah_sipaddr, ARPBUF->ah_shwaddr); /* The reply opcode is 2. */ ARPBUF->ah_opcode = HTONS(2); memcpy(ARPBUF->ah_dhwaddr, ARPBUF->ah_shwaddr, ETHER_ADDR_LEN); memcpy(ARPBUF->ah_shwaddr, dev->d_mac.ether_addr_octet, ETHER_ADDR_LEN); memcpy(ETHBUF->src, dev->d_mac.ether_addr_octet, ETHER_ADDR_LEN); memcpy(ETHBUF->dest, ARPBUF->ah_dhwaddr, ETHER_ADDR_LEN); ARPBUF->ah_dipaddr[0] = ARPBUF->ah_sipaddr[0]; ARPBUF->ah_dipaddr[1] = ARPBUF->ah_sipaddr[1]; uiphdr_ipaddr_copy(ARPBUF->ah_sipaddr, &dev->d_ipaddr); uip_arp_dump(ARPBUF); ETHBUF->type = HTONS(UIP_ETHTYPE_ARP); dev->d_len = sizeof(struct arp_hdr) + UIP_LLH_LEN; } break; case HTONS(ARP_REPLY): /* ARP reply. We insert or update the ARP table if it was meant * for us. */ if (uip_ipaddr_cmp(ipaddr, dev->d_ipaddr)) { uip_arp_update(ARPBUF->ah_sipaddr, ARPBUF->ah_shwaddr); } break; }}/* Prepend Ethernet header to an outbound IP packet and see if we need * to send out an ARP request. * * This function should be called before sending out an IP packet. The * function checks the destination IP address of the IP packet to see * what Ethernet MAC address that should be used as a destination MAC * address on the Ethernet. * * If the destination IP address is in the local network (determined * by logical ANDing of netmask and our IP address), the function * checks the ARP cache to see if an entry for the destination IP * address is found. If so, an Ethernet header is prepended and the * function returns. If no ARP cache entry is found for the * destination IP address, the packet in the d_buf[] is replaced by * an ARP request packet for the IP address. The IP packet is dropped * and it is assumed that they higher level protocols (e.g., TCP) * eventually will retransmit the dropped packet. * * If the destination IP address is not on the local network, the IP * address of the default router is used instead. * * When the function returns, a packet is present in the d_buf[] * buffer, and the length of the packet is in the field d_len. */void uip_arp_out(struct uip_driver_s *dev){ struct arp_entry *tabptr; in_addr_t ipaddr; in_addr_t destipaddr; int i; /* Find the destination IP address in the ARP table and construct * the Ethernet header. If the destination IP addres isn't on the * local network, we use the default router's IP address instead. * * If not ARP table entry is found, we overwrite the original IP * packet with an ARP request for the IP address. */ /* First check if destination is a local broadcast. */ if (uiphdr_ipaddr_cmp(IPBUF->eh_destipaddr, broadcast_ipaddr)) { memcpy(ETHBUF->dest, broadcast_ethaddr.ether_addr_octet, ETHER_ADDR_LEN); } else { /* Check if the destination address is on the local network. */ destipaddr = uip_ip4addr_conv(IPBUF->eh_destipaddr); if (!uip_ipaddr_maskcmp(destipaddr, dev->d_ipaddr, dev->d_netmask)) { /* Destination address was not on the local network, so we need to * use the default router's IP address instead of the destination * address when determining the MAC address. */ uip_ipaddr_copy(ipaddr, dev->d_draddr); } else { /* Else, we use the destination IP address. */ uip_ipaddr_copy(ipaddr, destipaddr); } /* Check if we already have this destination address in the ARP table */ for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i) { tabptr = &arp_table[i]; if (uip_ipaddr_cmp(ipaddr, tabptr->at_ipaddr)) { break; } } if (i == CONFIG_NET_ARPTAB_SIZE) { /* The destination address was not in our ARP table, so we * overwrite the IP packet with an ARP request. */ memset(ETHBUF->dest, 0xff, ETHER_ADDR_LEN); memset(ARPBUF->ah_dhwaddr, 0x00, ETHER_ADDR_LEN); memcpy(ETHBUF->src, dev->d_mac.ether_addr_octet, ETHER_ADDR_LEN); memcpy(ARPBUF->ah_shwaddr, dev->d_mac.ether_addr_octet, ETHER_ADDR_LEN); uiphdr_ipaddr_copy(ARPBUF->ah_dipaddr, &ipaddr); uiphdr_ipaddr_copy(ARPBUF->ah_sipaddr, &dev->d_ipaddr); ARPBUF->ah_opcode = HTONS(ARP_REQUEST); ARPBUF->ah_hwtype = HTONS(ARP_HWTYPE_ETH); ARPBUF->ah_protocol = HTONS(UIP_ETHTYPE_IP); ARPBUF->ah_hwlen = ETHER_ADDR_LEN; ARPBUF->ah_protolen = 4; uip_arp_dump(ARPBUF); ETHBUF->type = HTONS(UIP_ETHTYPE_ARP); dev->d_len = sizeof(struct arp_hdr) + UIP_LLH_LEN; return; } /* Build an ethernet header. */ memcpy(ETHBUF->dest, tabptr->at_ethaddr.ether_addr_octet, ETHER_ADDR_LEN); } /* Finish populating the ethernet header */ memcpy(ETHBUF->src, dev->d_mac.ether_addr_octet, ETHER_ADDR_LEN); ETHBUF->type = HTONS(UIP_ETHTYPE_IP); dev->d_len += UIP_LLH_LEN;}#endif /* CONFIG_NET */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -