示例#1
0
文件: buffer.c 项目: mstone9/vrouter
/*******************************************************************
*   Buffers a packet that is waiting on destination MAC address from ARP.
*******************************************************************/
struct packet_buffer * buf_packet(struct packet_state *ps, uint8_t* pac, const struct in_addr dest_ip, 
                                    const struct sr_if* iface, struct sr_ethernet_hdr *orig_eth)
{
	struct packet_buffer* buf_walker=0;
	
	assert(ps);
	assert(pac);
	
	if(ps->sr->queue==0) /* If Buffer is Empty.*/
	{
		ps->sr->queue=(struct packet_buffer*)malloc(sizeof(struct packet_buffer));
		assert(ps->sr->queue);
		
		ps->sr->queue->next=0;
		ps->sr->queue->packet=(uint8_t*)malloc(ps->res_len);
		memmove(ps->sr->queue->packet, pac, ps->res_len);
		ps->sr->queue->pack_len=ps->res_len;
		
		struct sr_rt* rt_entry=get_routing_if(ps, dest_ip);
		ps->sr->queue->gw_IP=rt_entry->gw.s_addr;
		ps->sr->queue->interface=(char *)malloc(sr_IFACE_NAMELEN);
		
		memmove(ps->sr->queue->interface, rt_entry->interface, sr_IFACE_NAMELEN);
		ps->sr->queue->ip_dst=dest_ip;
		ps->sr->queue->num_arp_reqs=0;
		ps->sr->queue->old_eth=(struct sr_ethernet_hdr*)malloc(sizeof(struct sr_ethernet_hdr));
		memmove(ps->sr->queue->old_eth, orig_eth, sizeof(struct sr_ethernet_hdr));
		return ps->sr->queue;
	}
	else /* Buffer is not Empty so Add to End. */
	{
		buf_walker=ps->sr->queue;
		while(buf_walker->next)
		{
			buf_walker=buf_walker->next;
		}
		buf_walker->next=(struct packet_buffer*)malloc(sizeof(struct packet_buffer));
		assert(buf_walker->next);
		buf_walker=buf_walker->next;
		buf_walker->next=0;
		
		buf_walker->packet=(uint8_t*)malloc(ps->res_len);
		memmove(buf_walker->packet, pac, ps->res_len);
		buf_walker->pack_len=ps->res_len;
		buf_walker->interface=(char *)malloc(sr_IFACE_NAMELEN);
		memmove(buf_walker->interface, iface->name, sr_IFACE_NAMELEN); 
		buf_walker->ip_dst=dest_ip;
		ps->sr->queue->gw_IP=ps->rt_entry->gw.s_addr;
		buf_walker->num_arp_reqs=0;
		buf_walker->old_eth=(struct sr_ethernet_hdr*)malloc(sizeof(struct sr_ethernet_hdr));
		memmove(buf_walker->old_eth, orig_eth, sizeof(struct sr_ethernet_hdr));
		return buf_walker;
	}
	ps->res_len = 0; /* Reset packet state's response length to 0 */
	return NULL;
}
示例#2
0
文件: arp.c 项目: dcrankshaw/vrouter
/*******************************************************************
*   Constructs appropriate ARP Request based on a packet to be forwarded.
*******************************************************************/
void send_request(struct packet_state* ps, const uint32_t dest_ip)
{
	/*Construct ARP Header*/
	struct sr_arphdr* request;
	request=(struct sr_arphdr*)malloc(sizeof(struct sr_arphdr));
	request->ar_hrd=htons(ARP_HRD_ETH);
	request->ar_pro=htons(ARP_PRO_IP);
	request->ar_hln=ETHER_ADDR_LEN;
	request->ar_pln=ARP_IP_LEN;
	request->ar_op=htons(ARP_REQUEST);
	
	/* Find source interface */
	struct in_addr ip_d;
	ip_d.s_addr=dest_ip;
	struct sr_rt* iface_rt_entry=get_routing_if(ps, ip_d);          /*Find rt entry to send request from. */
	struct sr_if* iface=sr_get_interface(ps->sr, iface_rt_entry->interface); /*Find iface associated with rt entry */
	assert(iface); 
	memmove(request->ar_sha, iface->addr, ETHER_ADDR_LEN); /*Set ARP source address to interface's hardware address */
	request->ar_sip=iface->ip;  /*Set ARP source IP address to interface's IP address */
	
	/* Set ARP dest MAC address to 00:00:00:00:00:00 */
	int i=0;
	for(i=0; i<ETHER_ADDR_LEN; i++)
	{
		request->ar_tha[i]=0x00;
	}
	
	/*Set ARP target IP address to interface's gateway IP address */
	request->ar_tip=iface_rt_entry->gw.s_addr; 
	
	
	/*ARP Constructed, Now Construct Ethernet Header */
	struct sr_ethernet_hdr* new_eth;
	new_eth=(struct sr_ethernet_hdr*)malloc(sizeof(struct sr_ethernet_hdr));
	memmove(new_eth->ether_shost, iface->addr,ETHER_ADDR_LEN); /*Ethernet Source Address is Interface's Address */
	
	
	ps->rt_entry = iface_rt_entry; /*******************/
	
	/*Set Ethernet dest MAC address to ff:ff:ff:ff:ff:ff (Broadcast) */
	for(i=0; i<ETHER_ADDR_LEN; i++)
	{
		new_eth->ether_dhost[i]=0xff;
	}
	
	new_eth->ether_type=htons(ETHERTYPE_ARP);
	
	int eth_offset=sizeof(struct sr_ethernet_hdr);
	
	/* Put new Ethernet and ARP Header in Response */
	memmove(ps->response, new_eth, eth_offset);
	memmove((ps->response + eth_offset), request, sizeof(struct sr_arphdr));
	
	/*Free Construct ARP and Ethernet Headers */
	if(request)
		free(request);
	if(new_eth)	
		free(new_eth);
		
	ps->res_len=eth_offset + sizeof(struct sr_arphdr);
}
示例#3
0
文件: buffer.c 项目: mstone9/vrouter
/*******************************************************************
*   Every time handle_packet() is called, update_buffer() is called. The function walks through
*   the packet buffer and checks if the necessary mac address is now in the arp cache. If it is,
*   then the MAC address is added to the ethernet header and the packet is send and removed 
*   from the buffer. If the address is not in the cache and less than 5 arp requests have already
*   been sent, then another arp request is sent. Otherwise the packet is deleted from the buffer 
*   and an ICMP port unreachable is sent.
*******************************************************************/
void update_buffer(struct packet_state* ps,struct packet_buffer* queue)
{
	struct packet_buffer* buf_walker=0;
	buf_walker=queue;
	
	while(buf_walker)
	{
		uint32_t search_ip=buf_walker->gw_IP;
		struct arp_cache_entry* ent=search_cache(ps, search_ip);
		if(ent!=NULL)                   /*MAC Address is in ARP Cache. Send packet. */
		{
			struct sr_ethernet_hdr *eth = (struct sr_ethernet_hdr *)(buf_walker->packet);
			memmove(eth->ether_dhost, ent->mac, ETHER_ADDR_LEN);
			struct sr_if *iface=sr_get_interface(ps->sr, buf_walker->interface);
			memmove(eth->ether_shost, iface->addr, ETHER_ADDR_LEN);
			eth->ether_type = htons(ETHERTYPE_IP);
			
		    sr_send_packet(ps->sr, buf_walker->packet, buf_walker->pack_len, buf_walker->interface);
			buf_walker=delete_from_buffer(ps,buf_walker);
		}
		else if(buf_walker->num_arp_reqs < 5)   /*Send another arp request. */
		{
			buf_walker->num_arp_reqs++;
			sr_send_packet(ps->sr, buf_walker->arp_req, buf_walker->arp_len, buf_walker->interface);
			buf_walker=buf_walker->next;
		}
		else    /* 5 ARP Request already sent, send ICMP Port Unreachable and Delete from Buffer.*/
		{
			int off = sizeof(struct sr_ethernet_hdr) + sizeof(struct ip);
			ps->res_len=off;
			
			ps->response += sizeof(struct sr_ethernet_hdr);
			
			struct ip *res_ip = (struct ip*) ps->response; /*IP Header for ICMP Port Unreachable*/
			ps->response += sizeof(struct ip);
			
			ps->packet = buf_walker->packet;
			ps->packet += sizeof(struct sr_ethernet_hdr);
			
			struct ip *ip_hdr = (struct ip*) (ps->packet);  /*IP Header from original packet. */
			ps->packet += sizeof(struct ip);
			
			icmp_response(ps, ip_hdr, ICMPT_DESTUN, ICMPC_HOSTUN); /*Construct ICMP */
			memmove(res_ip, ip_hdr, sizeof(struct ip));
			res_ip->ip_len = htons(ps->res_len - sizeof(struct sr_ethernet_hdr));
			res_ip->ip_ttl = INIT_TTL;
			res_ip->ip_tos = ip_hdr->ip_tos;
			res_ip->ip_p = IPPROTO_ICMP;
			
			/* Finding interface to send ICMP out of*/
			struct sr_rt* iface_rt_entry=get_routing_if(ps, ip_hdr->ip_src);
			struct sr_if* iface=sr_get_interface(ps->sr, iface_rt_entry->interface);
			
			res_ip->ip_src.s_addr = iface->ip;
			res_ip->ip_dst = ip_hdr->ip_src;
			res_ip->ip_sum = 0;
			res_ip->ip_sum = cksum((uint8_t *)res_ip, sizeof(struct ip));
			res_ip->ip_sum = htons(res_ip->ip_sum);
			
			ps->response = (uint8_t *) res_ip - sizeof(struct sr_ethernet_hdr);
			struct sr_ethernet_hdr* eth_resp=(struct sr_ethernet_hdr*)ps->response;
			memmove(eth_resp->ether_dhost,buf_walker->old_eth->ether_shost,ETHER_ADDR_LEN);
			
			memmove(eth_resp->ether_shost,iface->addr, ETHER_ADDR_LEN);
			eth_resp->ether_type=htons(ETHERTYPE_IP);
			
			sr_send_packet(ps->sr, ps->response, ps->res_len, iface_rt_entry->interface);

			buf_walker=delete_from_buffer(ps,buf_walker);	
		}
	}
}