static void arp_process_func(void** state) { // Timer setting timer_init("IntelCore(TM) i5-4670 CPU @ 3.40GHz"); // Nic initialization void* malloc_pool = malloc(POOL_SIZE); init_memory_pool(POOL_SIZE, malloc_pool, 0); __nics[0] = malloc(sizeof(NIC)); __nic_count++; __nics[0]->mac = 0x74d4358f66cb; __nics[0]->pool_size = POOL_SIZE; __nics[0]->pool = malloc_pool; __nics[0]->output_buffer = fifo_create(8, malloc_pool); __nics[0]->config = map_create(8, NULL, NULL, __nics[0]->pool); // Arp request Packet* packet = nic_alloc(__nics[0], sizeof(arp_request_packet)); memcpy(packet->buffer + packet->start, arp_request_packet, sizeof(arp_request_packet)); Ether* ether = (Ether*)(packet->buffer + packet->start); ARP* arp = (ARP*)ether->payload; uint32_t addr = endian32(arp->tpa); nic_ip_add(__nics[0], addr); assert_true(arp_process(packet)); packet = fifo_pop(__nics[0]->output_buffer); assert_memory_equal(packet->buffer + packet->start, arp_reply_packet, 42); nic_free(packet); packet = NULL; // Arp response packet = nic_alloc(__nics[0], sizeof(arp_reply_packet)); memcpy(packet->buffer + packet->start, arp_reply_packet, sizeof(arp_reply_packet)); ether = (Ether*)(packet->buffer + packet->start); arp = (ARP*)ether->payload; addr = endian32(arp->tpa); nic_ip_add(__nics[0], addr); uint8_t comp_mac[6] = { 0xcb, 0x66, 0x8f, 0x35, 0xd4, 0x74 }; uint32_t sip = endian32(arp->spa); Map* arp_table = nic_config_get(packet->nic, "net.arp.arptable"); assert_true(arp_process(packet)); ARPEntity* entity = map_get(arp_table, (void*)(uintptr_t)sip); assert_memory_equal((uint8_t*)&entity->mac, comp_mac, 6); destroy_memory_pool(malloc_pool); free(malloc_pool); malloc_pool = NULL; }
void process(NIC* ni) { static uint32_t myip = 0xc0a86402; // 192.168.100.2 Packet* packet = nic_input(ni); if(!packet) return; Ether* ether = (Ether*)(packet->buffer + packet->start); if(endian16(ether->type) == ETHER_TYPE_ARP) { // ARP response ARP* arp = (ARP*)ether->payload; if(endian16(arp->operation) == 1 && endian32(arp->tpa) == myip) { ether->dmac = ether->smac; ether->smac = endian48(ni->mac); arp->operation = endian16(2); arp->tha = arp->sha; arp->tpa = arp->spa; arp->sha = ether->smac; arp->spa = endian32(myip); nic_output(ni, packet); packet = NULL; } } else if(endian16(ether->type) == ETHER_TYPE_IPv4) { IP* ip = (IP*)ether->payload; if(ip->protocol == IP_PROTOCOL_ICMP && endian32(ip->destination) == myip) { // Echo reply ICMP* icmp = (ICMP*)ip->body; icmp->type = 0; icmp->checksum = 0; icmp->checksum = endian16(checksum(icmp, packet->end - packet->start - ETHER_LEN - IP_LEN)); ip->destination = ip->source; ip->source = endian32(myip); ip->ttl = endian8(64); ip->checksum = 0; ip->checksum = endian16(checksum(ip, ip->ihl * 4)); ether->dmac = ether->smac; ether->smac = endian48(ni->mac); nic_output(ni, packet); packet = NULL; } else if(ip->protocol == IP_PROTOCOL_UDP) { UDP* udp = (UDP*)ip->body; if(endian16(udp->destination) == 9000) { reply_count = 2; // Control packet uint32_t idx = 0; seq = read_u16(udp->body, &idx); user_mac = endian48(ether->smac); user_ip = endian32(ip->source); user_port = endian16(udp->source); uint8_t msg = read_u8(udp->body, &idx); switch(msg) { case 1: // MSG_CREATE { idx++; // read ctype uint32_t clen = read_u32(udp->body, &idx); char collection[clen + 1]; collection[clen] = '\0'; memcpy(collection, udp->body + idx, clen); idx += clen; uint64_t id = newID(collection); memmove(udp->body + idx + 9, udp->body + idx, endian16(udp->length) - 8 - idx); packet->end += 9; udp->length = endian16(endian16(udp->length) + 9); ip->length = endian16(endian16(ip->length) + 9); write_u8(udp->body, 4, &idx); write_u64(udp->body, id, &idx); } break; case 2: // MSG_READ reply_count = 1; break; case 3: // MSG_RETRIEVE break; case 4: // MSG_UPDATE break; case 5: // MSG_DELETE break; case 6: // MSG_HELLO reply_count = 1; break; } udp->source = endian16(9999); udp->destination = endian16(9001); udp->checksum = 0; ip->destination = ip->source; ip->source = endian32(myip); ip->ttl = endian8(ip->ttl) - 1; ip->checksum = 0; ip->checksum = endian16(checksum(ip, ip->ihl * 4)); ether->dmac = ether->smac; ether->smac = endian48(ni->mac); nic_output_dup(ni, packet); udp->destination = endian16(9002); ip->checksum = 0; ip->checksum = endian16(checksum(ip, ip->ihl * 4)); nic_output_dup(ni, packet); udp->destination = endian16(9003); ip->checksum = 0; ip->checksum = endian16(checksum(ip, ip->ihl * 4)); nic_output(ni, packet); packet = NULL; } else if(endian16(udp->destination) == 9999) { uint32_t idx = 0; uint16_t seq2 = read_u16(udp->body, &idx); if(seq == seq2 && --reply_count == 0) { udp->checksum = 0; udp->destination = endian16(user_port); udp->source = endian16(9000); ip->destination = endian32(user_ip); ip->source = endian32(myip); ip->ttl = endian8(64); ip->checksum = 0; ip->checksum = endian16(checksum(ip, ip->ihl * 4)); ether->dmac = endian48(user_mac); ether->smac = endian48(ni->mac); nic_output(ni, packet); packet = NULL; } } } } if(packet) nic_free(packet); }