Exemple #1
0
void send_icmp(void)
{
    switch(opt_icmptype)
    {
    case ICMP_ECHO:			/* type 8 */
    case ICMP_ECHOREPLY:		/* type 0 */
        send_icmp_echo();
        break;
    case ICMP_DEST_UNREACH:		/* type 3 */
    case ICMP_SOURCE_QUENCH:	/* type 4 */
    case ICMP_REDIRECT:		/* type 5 */
    case ICMP_TIME_EXCEEDED:	/* type 11 */
        send_icmp_other();
        break;
    case ICMP_TIMESTAMP:
    case ICMP_TIMESTAMPREPLY:
        send_icmp_timestamp();
        break;
    case ICMP_ADDRESS:
    case ICMP_ADDRESSREPLY:
        send_icmp_address();
        break;
    default:
        if (opt_force_icmp) {
            send_icmp_other();
            break;
        } else {
            printf("[send_icmp] Unsupported icmp type!\n");
            exit(1);
        }
    }
}
Exemple #2
0
void sr_handlepacket(struct sr_instance* sr, uint8_t * packet/* lent */,
					unsigned int len, char* interface/* lent */) {
	/* Function implemented by g1izzyw and gustan50404 */
	/* REQUIRES */
	assert(sr);
	assert(packet);
	assert(interface);
	
	struct sr_if *ether_interface = (struct sr_if *) sr_get_interface(sr, interface); 
	
	/* Check if it an ethernet interface. */
	if (ether_interface) {
		/* Now we deal with the ethernet header */
		struct sr_ethernet_hdr *ether_hdr = (struct sr_ethernet_hdr *) packet;
	    
		/* Check to see if we are dealing with an ARP request/reply */
		if (ether_hdr->ether_type == htons(ethertype_arp)) {
			
			fprintf(stderr, "We Got an ARP Packet\n");
			/* Handle ARP for ethernet */ 
			struct sr_arp_hdr * arp_hdr = (struct sr_arp_hdr *)(packet + sizeof(struct sr_ethernet_hdr));
			if (arp_hdr->ar_hrd == htons(arp_hrd_ethernet)) {

				if (arp_hdr->ar_op == htons(arp_op_request)) {
				/* arp request */
					struct sr_if *interface_for_ip = get_interface_for_ip(sr, arp_hdr->ar_tip);	
					if (interface_for_ip) {
  			
						/* Target ip is one of the router interfaces */
						fprintf(stderr, "ARP req for one of our interfaces\n");

						/* Now we want to make an arp reply and send it back */
						uint8_t *buf = (uint8_t *) malloc(len);
						memcpy(buf, packet, len);
    			
						/*Make Arp Header*/
						make_arprply_hdr(interface_for_ip->addr, arp_hdr->ar_sha, interface_for_ip->ip,
														arp_hdr->ar_sip, buf);
														
						/*Make Ethernet Header*/
						make_ether_hdr(interface_for_ip->addr, ether_hdr->ether_shost, ethertype_arp, buf);

						/* Now we send the packet */
						sr_send_packet(sr, buf, len, interface_for_ip->name);
						free(buf);
						fprintf(stderr, "ARP reply sent\n");
					}
				} else if (arp_hdr->ar_op == htons(arp_op_reply)) {

					fprintf(stderr, "We got an ARP Reply, need to check for intfc tho \n");
					/* arp reply */
					struct sr_if *interface_for_ip = get_interface_for_ip(sr, arp_hdr->ar_tip);	
					if (interface_for_ip) {
			
						fprintf(stderr, "We got an ARP Reply for one of our interfaces\n");
						/*We first want to insert into Arp cache*/
						struct sr_arpreq *request = sr_arpcache_insert(&(sr->cache), 
																		arp_hdr->ar_sha, 
																		arp_hdr->ar_sip);
						fprintf(stderr, "Signalling all waiting packets\n");
						if (request) {
							struct sr_packet *cur_packet = request->packets;
							while(cur_packet) {
								fprintf(stderr, "About to forward \n");
								print_hdrs(cur_packet->buf, cur_packet->len);
								forward_packet(sr, cur_packet->iface, arp_hdr->ar_sha, 
															cur_packet->len, cur_packet->buf); 
								fprintf(stderr, "Packet Forwarded\n");							
								cur_packet = cur_packet->next;
							}
						}
					}
				}		
			}      
    	} else if (ether_hdr->ether_type == htons(ethertype_ip)) {
					
			/* Get the ip header from the ethernet header*/
			sr_ip_hdr_t *ip_hdr = (sr_ip_hdr_t *)(packet + sizeof(sr_ethernet_hdr_t));
			/*IP Checksum Stuff*/
			uint16_t temp_ip_sum = ip_hdr->ip_sum;
			ip_hdr->ip_sum = 0;
			ip_hdr->ip_sum = cksum(packet + sizeof(sr_ethernet_hdr_t), sizeof(sr_ip_hdr_t));																	
			if (temp_ip_sum == ip_hdr->ip_sum) {
			
				/*We got here means IP Cheksum is alright, so we extract the interface*/
				struct sr_if *interface_for_ip = get_interface_for_ip(sr, ip_hdr->ip_dst);
				
				/*Check to make sure interface is one of ours*/
				if (interface_for_ip) {
					
					fprintf(stderr, "IP Packet destined towards our interface\n");
					/*Check if our IP packet is UDP or TCP*/
					if (ip_hdr->ip_p == 6 || ip_hdr->ip_p == 17) {
						fprintf(stderr, "We Got TCP or UDP, sending ICMP error msg\n");
						send_icmp_error(3, 3, sr, interface, len, packet);
					
					} else {
						
						/* Get the ICMP header */
						sr_icmp_hdr_t *icmp_hdr = (struct sr_icmp_hdr *) (packet + 
																		sizeof(sr_ethernet_hdr_t) + 
																		sizeof(sr_ip_hdr_t));
						
						/*Now we do the ICMP checksum chek*/
						/*This covers the ICMP echo case*/
						uint16_t temp_icmp_sum = icmp_hdr->icmp_sum;
						temp_icmp_sum = icmp_hdr->icmp_sum;
						icmp_hdr->icmp_sum = 0;
						if (temp_icmp_sum == cksum(packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t), 
												len - sizeof(sr_ethernet_hdr_t) - sizeof(sr_ip_hdr_t))) {
							/*Everything is fine so we send an ICMP echo back*/
							fprintf(stderr, "Sending ICMP echo reply\n");
	    					send_icmp_echo(sr, interface, len, packet);
	    				}
	    			}
				} else {
					/*IP Packet not destined towards one of our interfaces*/
					
					fprintf(stderr, "IP packet not destined to our interface\n");
					/*Decremenrt TTL by 1*/
					
					fprintf(stderr, "TTL modified \n");
					print_hdrs(packet, len);
					if (ip_hdr->ip_ttl <= 1) {
						fprintf(stderr, "Packte with TTL < 0 found, sending ICMP error \n");
						/*TTL is less than 0 so send an ICMP ERROR*/
						send_icmp_error(11, 0, sr, interface, len, packet);
						
					} else {
						
						/*Recompute Checksum over new header TTL is fine*/
						/*Check if it exists in the routing table*/
						ip_hdr->ip_ttl = ip_hdr->ip_ttl - 1;
						fprintf(stderr, "Recomputing Checksum after modifying TTl\n");
						ip_hdr->ip_sum = 0;																			
						ip_hdr->ip_sum = cksum(packet + sizeof(sr_ethernet_hdr_t), sizeof(sr_ip_hdr_t));
						struct sr_if *dst_if = (struct sr_if *)malloc(sizeof(struct sr_if));
						dst_if = next_hop(sr, interface, ip_hdr->ip_dst);
						
						if (!(dst_if)) {
						
							fprintf(stderr, "IP packet has no longest matching prefix sending ICMP error\n");
							/*dst ip has no longest macthing prefix*/
							/*So we send a type 3 code 0 ICMP error*/
							send_icmp_error(3, 0, sr, interface, len, packet);
							
						} else {
							
							/*This is the case where we do have a longest macthing prefix*/
							fprintf(stderr, "Found Longest mathcing prefix in RT\n");
							struct sr_arpcache *cache = &(sr->cache);
							struct sr_arpentry *in_cache = sr_arpcache_lookup(cache, ip_hdr->ip_dst);
							if (in_cache) {
							
								fprintf(stderr, "Found IP->MAC mapping in ARP cache forwarding packet \n");
								/*this is the case where ip->mac maping is already in cache*/
								forward_packet(sr, dst_if->name, in_cache->mac, len, packet);
								free(in_cache);
								
							} else {
							
								fprintf(stderr, "IP->MAC mapping not in ARP cache %u \n", ip_hdr->ip_dst);
								/*Case where ip->mapping is not in cache*/
								sr_arpcache_queuereq(cache, ip_hdr->ip_dst, packet, len, dst_if->name);
								fprintf(stderr, "Added Arp Req to queu \n"); 						
							}
						}					
					}
				}
			}
		}
	} 
	
} /* end sr_ForwardPacket */