void uip_build_arp_request(struct uip_stack *ustack, u16_t *ipaddr) { struct arp_hdr *arp; struct uip_eth_hdr *eth; arp = (struct arp_hdr *)ustack->network_layer; eth = (struct uip_eth_hdr *)ustack->data_link_layer; /* The destination address was not in our ARP table, so we overwrite the IP packet with an ARP request. */ memset(eth->dest.addr, 0xff, 6); memset(arp->dhwaddr.addr, 0x00, 6); memcpy(eth->src.addr, ustack->uip_ethaddr.addr, 6); memcpy(arp->shwaddr.addr, ustack->uip_ethaddr.addr, 6); uip_ip4addr_copy(arp->dipaddr, ipaddr); uip_ip4addr_copy(arp->sipaddr, ustack->hostaddr); arp->opcode = const_htons(ARP_REQUEST); /* ARP request. */ arp->hwtype = const_htons(ARP_HWTYPE_ETH); arp->protocol = const_htons(UIP_ETHTYPE_IPv4); arp->hwlen = 6; arp->protolen = 4; eth->type = const_htons(UIP_ETHTYPE_ARP); ustack->uip_appdata = &ustack->uip_buf[UIP_TCP_IPv4_HLEN + UIP_LLH_LEN]; ustack->uip_len = sizeof(*arp) + sizeof(*eth); }
void uip_arp_arpin(nic_interface_t *nic_iface, struct uip_stack *ustack, packet_t *pkt) { struct arp_hdr *arp; struct uip_eth_hdr *eth; if (pkt->buf_size < sizeof(struct arp_hdr)) { pkt->buf_size = 0; return; } pkt->buf_size = 0; eth = (struct uip_eth_hdr *)pkt->data_link_layer; arp = (struct arp_hdr *)pkt->network_layer; switch (arp->opcode) { case const_htons(ARP_REQUEST): /* ARP request. If it asked for our address, we send out a reply. */ if (uip_ip4addr_cmp(arp->dipaddr, ustack->hostaddr)) { /* 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(arp->sipaddr, &arp->shwaddr); /* The reply opcode is 2. */ arp->opcode = htons(2); memcpy(arp->dhwaddr.addr, arp->shwaddr.addr, 6); memcpy(arp->shwaddr.addr, ustack->uip_ethaddr.addr, 6); memcpy(eth->src.addr, ustack->uip_ethaddr.addr, 6); memcpy(eth->dest.addr, arp->dhwaddr.addr, 6); arp->dipaddr[0] = arp->sipaddr[0]; arp->dipaddr[1] = arp->sipaddr[1]; arp->sipaddr[0] = ustack->hostaddr[0]; arp->sipaddr[1] = ustack->hostaddr[1]; if (nic_iface->vlan_id == 0) { eth->type = htons(UIP_ETHTYPE_ARP); pkt->buf_size = sizeof(*arp) + sizeof(*eth); } else { eth->type = htons(UIP_ETHTYPE_8021Q); pkt->buf_size = sizeof(*arp) + sizeof(struct uip_vlan_eth_hdr); } } break; case const_htons(ARP_REPLY): uip_arp_update(arp->sipaddr, &arp->shwaddr); break; default: LOG_WARN("Unknown ARP opcode: %d", ntohs(arp->opcode)); break; } return; }
int is_vlan_packet(struct uip_vlan_eth_hdr *hdr) { /* The TPID field in a 802.1Q Header must be 0x8100 */ if (hdr->tpid == const_htons(UIP_ETHTYPE_8021Q)) return 1; return 0; }