Beispiel #1
0
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;
}
Beispiel #2
0
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);
}