Exemplo n.º 1
0
void* router_pthread_main( void* vpacket ) {
    static unsigned id = 0;
    char name[15];
    snprintf( name, 15, "PHandler %u", id++ );
    debug_pthread_init( name, "Packet Handler Thread" );
    pthread_detach( pthread_self() );
    router_handle_packet( (packet_info_t*)vpacket );
    debug_println( "Packet Handler Thread is shutting down" );
    return NULL;
}
Exemplo n.º 2
0
void router_handle_work( work_t* work ) {
    /* process the work */
    switch( work->type ) {
    case WORK_NEW_PACKET:
        router_handle_packet( (packet_info_t*)work->work );
        break;

    default:
        die( "Error: unknown work type %u", work->type );
    }
}
Exemplo n.º 3
0
void sr_handlepacket(struct sr_instance* sr,
        uint8_t * packet/* lent */,
        unsigned int len,
        char* interface/* lent */)
{
  	/* REQUIRES */
	assert(sr);
	assert(packet);
	assert(interface);
	
	printf("*** -> Received packet of length %d \n",len);

	sr_ethernet_hdr_t* eth_header = (sr_ethernet_hdr_t*)packet;
	/* printf("The type is %x\n",ntohs(eth_header->ether_type));*/

	if( ntohs(eth_header->ether_type) == IP_PROTOCOL)
	{
		/* Its an IP Packet */
		printf("Its an IP Packet\n");
		/* Check the checksum of the packet */
		uint8_t* ip_packet = packet + sizeof(sr_ethernet_hdr_t);
		if(check_checksum(ip_packet,sizeof(sr_ip_hdr_t)) == 0)
		{
			/* Handle ICMP Error message */
			return;
		}
		else
		{
			/* Checksum is fine, Now do the functions */
			sr_ip_hdr_t* ip_header = (sr_ip_hdr_t*)ip_packet;
			/*print_hdr_ip(ip_packet);*/
			if( decrement_TTL(ip_header) == 0 )
			{
				/* Send ICMP packet for Time Limit Exceeded*/
				
				ip_header->ip_sum = 0;
				ip_header->ip_ttl = 1;
				ip_header->ip_sum = cksum(ip_packet,sizeof(sr_ip_hdr_t));
				/*make_ICMP_packet();
				make_IP_packet();*/
				/* Check wheather the Destination is this router  */
				if( check_match_all_interfaces ( sr->if_list, ip_header->ip_dst) == 1 )
				{
					printf("I am here in TTL 0 \n\n\\n");
					uint8_t protocol = ip_header->ip_p;
					if( protocol == TCP_PROTOCOL || protocol == UDP_PROTOCOL)
					{
						/* This is having UDP or TCP as payload */
						/* So, just include this packet as payload and send the ICMP packet */
						handle_ICMP(sr,ip_packet,len-sizeof(sr_ethernet_hdr_t),3,3,interface,1);
					}
					else
					{
						/* Its ICMP protocol */
						/* Check if it is echo request , If it is then send echo reply */
						sr_icmp_hdr_t* icmp = (sr_icmp_hdr_t*)(ip_packet+sizeof(sr_ip_hdr_t));
						if( icmp->icmp_type == 8 && icmp->icmp_code == 0)
						{
							
							int length = len - sizeof(sr_ethernet_hdr_t);
							uint8_t* data = 0;
			uint8_t* icmp_start = make_ICMP_packet_echo(ip_packet+sizeof(sr_ip_hdr_t),length-sizeof(sr_ip_hdr_t));
			uint8_t* ip_start = make_IP_packet( *((uint8_t*)ip_header), ip_header->ip_tos, htons(length), \
							ip_header->ip_id,ip_header->ip_off, 64, ip_header->ip_p,\
							ip_header->ip_dst, ip_header->ip_src);
							uint8_t* final_packet = (uint8_t*)malloc(len);
							memcpy(final_packet,ip_start,sizeof(sr_ip_hdr_t));
						memcpy(final_packet + sizeof(sr_ip_hdr_t),icmp_start,\
								length-sizeof(sr_ip_hdr_t));
						free(ip_start);
						free(icmp_start);	
						forward_packet(sr,final_packet,length,interface);
						}
						else
							handle_ICMP(sr,ip_packet,len-sizeof(sr_ethernet_hdr_t),11,0,interface,1);
					}
				}
				else
				{
					handle_ICMP(sr,ip_packet,len-sizeof(sr_ethernet_hdr_t),11,0,interface,0);
				}
				return;
			}
			/* Calculate new checksum after TTL updation */
			ip_header->ip_sum = 0;
			ip_header->ip_sum = cksum(ip_packet,sizeof(sr_ip_hdr_t));

			/*print_hdr_ip(ip_packet);*/
			/* Check if the packet is destined to any of its interfaces */
			/* Dont free this */
			if( check_match_all_interfaces ( sr->if_list, ip_header->ip_dst) == 1 )
			{
				/* Now its destined to router, so router should handle it 
				It Should check for the Transport layer protocol and should appropriately send ICMP packets*/
				router_handle_packet(sr,ip_packet,len-sizeof(sr_ethernet_hdr_t),interface);
			}
			else
			{
				/* 
					Packet is subjected to NAT translation first and then forwarded 
					1) Check if there are any existing sessions for this packet, if any use them to translate the packets
					2) If there aren't any, then allocate a new session and translate the packet.
				*/
				
				forward_packet(sr,ip_packet,len,interface);
			}
		}
	}
	else
	{
		printf("Its an ARP Packet\n");
		/* Its an ARP Packet */

		uint8_t* arp_packet = packet + sizeof(sr_ethernet_hdr_t);
		/* Construct ARP structure */
		sr_arp_hdr_t* arp_header = (sr_arp_hdr_t*)arp_packet;
		
		/* Check if the packet is request to the router */
		int dst_ip = ntohl(arp_header->ar_tip);
		
		struct sr_if* arp_interface = sr_get_interface(sr,interface);
		int interface_ip = ntohl(arp_interface->ip);

		if( dst_ip == interface_ip )
		{
			/* It is destined correctly */

			uint8_t op_code = ntohs(arp_header->ar_op);
		
			if( op_code == 1 )
			{
				/* ARP Request */
				uint8_t* arp_reply_packet;
				arp_reply_packet = (uint8_t*)malloc(sizeof(sr_ethernet_hdr_t)+1500);
				bzero(arp_reply_packet,sizeof(sr_ethernet_hdr_t)+1500);
				/* Create both ethernet and ARP structures */
				sr_ethernet_hdr_t* new_eth = (sr_ethernet_hdr_t*)arp_reply_packet;
				/* Fill in all the details of ethernet frame */
				memcpy(new_eth->ether_dhost,eth_header->ether_shost,sizeof(uint8_t)*6);
				memcpy(new_eth->ether_shost,arp_interface->addr,sizeof(uint8_t)*6);
				new_eth->ether_type = htons(ARP_PROTOCOL);

				/* Fill in all the details of ARP */
				uint8_t* arp_reply_segment  = arp_reply_packet+ sizeof(sr_ethernet_hdr_t);
				memcpy(arp_reply_segment,arp_packet,sizeof(sr_arp_hdr_t));
				sr_arp_hdr_t* arp_reply_structure = (sr_arp_hdr_t*)arp_reply_segment;
				arp_reply_structure->ar_op = htons(2);
				memcpy(arp_reply_structure->ar_sha,arp_interface->addr,sizeof(uint8_t)*6);
				memcpy(arp_reply_structure->ar_tha,eth_header->ether_shost,sizeof(uint8_t)*6);
				arp_reply_structure->ar_sip = arp_interface->ip;
				arp_reply_structure->ar_tip = arp_header->ar_sip;
				/* Now send the packet */
				/* Beaware of the size of the frame, it should not be sizeof(arp_reply_packet)
				But the size used below */
				sr_send_packet(sr,arp_reply_packet,sizeof(sr_ethernet_hdr_t)+1500,interface);
			}
			else if( op_code == 2 )
			{
				/* ARP Reply */
				uint8_t* MAC = (uint8_t*)malloc(sizeof(uint8_t)*6);
				uint32_t IP;
				memcpy(MAC,arp_header->ar_sha,sizeof(uint8_t)*6);
				IP = arp_header->ar_sip;
				struct sr_arpreq* queue = sr_arpcache_insert(&sr->cache,MAC,IP);
				if( queue == NULL )
				{
					assert(queue!=NULL);
				}
				else
				{
					struct sr_packet* packet_i = queue->packets;
					while( packet_i!= NULL )
					{
						sr_ethernet_hdr_t* head = (sr_ethernet_hdr_t*)(packet_i->buf);
						memcpy(head->ether_dhost,MAC,sizeof(uint8_t)*6);
						sr_send_packet(sr,packet_i->buf,packet_i->len,packet_i->iface);
						packet_i = packet_i->next;
					}
					sr_arpreq_destroy(&sr->cache,queue);
				}
			}
		}
	}
}/* end sr_ForwardPacket */