コード例 #1
0
ファイル: sr_arpcache.c プロジェクト: Shihao66/Mininet_Router
void handle_arpreq(struct sr_instance *sr, struct sr_arpreq *req) {
        time_t now = time(NULL);
        if(difftime(now, req->sent) > 1.0) {
                /* request timeout */
                if(req->times_sent > 5) {
                        
                        struct sr_packet *packets = req->packets;
                        
                        /* iterate through all packets on queue */
                        while(packets) {
                                uint8_t *reply_packet = 0;
                                sr_ip_hdr_t *ip_hdr = (sr_ip_hdr_t *)(packets->buf+sizeof(sr_ethernet_hdr_t));
                                reply_packet = sr_generate_icmp((sr_ethernet_hdr_t *)packets->buf, ip_hdr, sr_get_interface(sr, packets->iface), 3, 1); /* create ICMP type 3, code 1 (host unreachable) */
                                /* if ICMP packet fails to generate */
                                if(reply_packet == 0) {
                                        fprintf(stderr, "Error: failed to generate ICMP packet\n");
                                }
                                
                                
                                /* send ICMP packet to ip of packet in queue */
                                if(sr_send_packet(sr, reply_packet, sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_t3_hdr_t), (const char*)(packets->iface)) == -1) {
                                        fprintf(stderr, "Error: sending packet failed (handle_arpreq)");
                                }
                                packets = packets->next;
                                free(reply_packet);
                        }
            sr_arpreq_destroy(&(sr->cache), req);
                } else {
                        
                        /* generate ARP packet */
                        struct sr_if *iface = 0;
                        
                        /* if interface is not found */
                        if((iface = sr_get_interface(sr, req->packets->iface)) == 0) {
                                fprintf(stderr, "Error: interface does not exist (handle_arpreq)");
                                return;
                        }
                        
                        uint8_t *arp_pkt = sr_new_arpreq_packet(NULL, iface->addr, req->ip, iface->ip); /* create ARP request packet to re-send */

                        /* send ARP request packet */
                        if (sr_send_packet(sr, arp_pkt, sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t), (const char*)(iface->name))==-1) {
                                fprintf(stderr, "Error: sending packet failed.");
                        }

                        /* update arpreq fields */
                        req->times_sent++;
                        req->sent = now;
                        
                        free(arp_pkt);
                }
        }
}
コード例 #2
0
ファイル: sr_router.c プロジェクト: yufengli71/Mininet_Router
void sr_handleip(struct sr_instance* sr,
        uint8_t * packet/* lent */,
        unsigned int len,
        char* interface/* lent */)
{
	sr_ip_hdr_t *ip_hdr = 0;
	struct sr_if *iface = 0;
	sr_icmp_hdr_t *icmp_hdr = 0;
	uint8_t *reply_packet = 0;
	struct sr_rt *rt = 0;
	uint32_t nexthop_ip, longest_mask = 0;
	struct sr_arpentry *arp_entry = 0;
	struct sr_arpreq *arp_req = 0;
	sr_ethernet_hdr_t *ether_hdr = 0;
	int matched = 0;
	
	/* check if header has the correct size */
	if (len < sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t)) {
		fprintf(stderr, "Error: invalid IP header length\n");
		return;
	}
	
	ip_hdr = (sr_ip_hdr_t*)(packet + sizeof(sr_ethernet_hdr_t));
	
	/* perform ip header checksum */
	if (cksum(ip_hdr, ip_hdr->ip_hl) != 0xffff) {
		fprintf(stderr, "Error: IP checksum failed\n");
		return;
	}
	
	/* grab the receiving interface */
	if ((iface = sr_get_interface(sr, interface)) == 0) {
		fprintf(stderr, "Error: interface does not exist (sr_handleip)\n");
		return;
	}
	
	/* if the packet is destined to our ip */
	if (ip_hdr->ip_dst == htonl(iface->ip)) {
	
		/* if it is an ICMP */
		if (ip_hdr->ip_p == htons(ip_protocol_icmp)) {
			
			/* check if header has the correct size */
			if (len < sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_hdr_t)) {
				fprintf(stderr, "Error: invalid ICMP header length\n");
				return;
			}
			
			icmp_hdr = (sr_icmp_hdr_t*)(packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t));
			
			/* if it is an ICMP echo request, send an ICMP echo reply */
			if (icmp_hdr->icmp_type == htons(8) && icmp_hdr->icmp_code == htons(0)) {
				
				/* perform ICMP header checksum */
				if (cksum(icmp_hdr, sizeof(icmp_hdr)) != 0xffff) {
					fprintf(stderr, "Error: ICMP checksum failed\n");
					return;
				}
				
				/* generate an echo reply packet */
				if ((reply_packet = sr_generate_icmp((sr_ethernet_hdr_t *)packet, ip_hdr, iface, 0, 0)) == 0) {
					fprintf(stderr, "Error: failed to generate ICMP echo reply packet\n");
					return;
				}
				
				/* send an ICMP echo reply */
				if (sr_send_packet(sr, reply_packet, sizeof(reply_packet), (const char*)interface) == -1) {
					fprintf(stderr, "Error: sending packet failed (sr_handleip)\n");
				}
				
				free(reply_packet);				
			}
		}
		/* if it contains a TCP or UDP payload */
		else {
		
			/* generate Destination net unreachable (type 3, code 0) reply packet */
			if ((reply_packet = sr_generate_icmp((sr_ethernet_hdr_t *)packet, ip_hdr, iface, 3, 3)) == 0) {
				fprintf(stderr, "Error: failed to generate ICMP packet\n");
				return;
			}
			
			/* send an ICMP */
			if (sr_send_packet(sr, reply_packet, sizeof(reply_packet), (const char*)interface) == -1) {
				fprintf(stderr, "Error: sending packet failed (sr_handleip)\n");
			}
			
			free(reply_packet);		
		}
	}
	/* packet not for us, forward it */
	else {
		
		/* if TTL reaches 0 */
		if (ip_hdr->ip_ttl <= htons(1)) {
		
			/* generate Time exceeded (type 11, code 0) reply packet */
			if ((reply_packet = sr_generate_icmp((sr_ethernet_hdr_t *)packet, ip_hdr, iface, 11, 0)) == 0) {
				fprintf(stderr, "Error: failed to generate ICMP packet\n");
				return;
			}
			
			/* send an ICMP */
			if (sr_send_packet(sr, reply_packet, sizeof(reply_packet), (const char*)interface) == -1) {
				fprintf(stderr, "Error: sending packet failed (sr_handleip)\n");
			}
			
			free(reply_packet);
		}
		/* if packet has enough TTL */
		else {
			
			/* decrement the TTL by 1 */
			ip_hdr->ip_ttl --;
			
			/* recompute the packet checksum */
			ip_hdr->ip_sum = htons(0);
			ip_hdr->ip_sum = cksum(ip_hdr, sizeof(sr_ip_hdr_t));
			
			/* Find entry in the routing table with the longest prefix match */
			rt = sr->routing_table;
			while (rt != NULL) {
				
				/* update the gateway ip and the longest mask so far */
				if ((rt->dest.s_addr & rt->mask.s_addr) == (ntohl(ip_hdr->ip_dst) & rt->mask.s_addr) &&
					rt->mask.s_addr > longest_mask) {
					nexthop_ip = rt->gw.s_addr;
					longest_mask = rt->mask.s_addr;
					matched = 1;
				}
				
				rt = rt->next;
			}
			
			/* if a matching routing table entry was NOT found */
			if (matched == 0) {
				
				/* generate Destination net unreachable (type 3, code 0) reply packet */
				if ((reply_packet = sr_generate_icmp((sr_ethernet_hdr_t *)packet, ip_hdr, iface, 3, 0)) == 0) {
					fprintf(stderr, "Error: failed to generate ICMP packet\n");
					return;
				}
				
				/* send an ICMP */
				if (sr_send_packet(sr, reply_packet, sizeof(reply_packet), (const char*)interface) == -1) {
					fprintf(stderr, "Error: sending packet failed (sr_handleip)\n");
				}
				
				free(reply_packet);
			}
			/* if a matching routing table entry was found */
			else {
				/* if the next hop is 0.0.0.0 */
				if(nexthop_ip == 0) {
					nexthop_ip = ip_hdr->ip_dst;
				}
				
				/* set the source MAC of ethernet header */
				ether_hdr = (sr_ethernet_hdr_t*)packet;
				memcpy(ether_hdr->ether_shost, iface->addr, ETHER_ADDR_LEN);
				
				/* if the next-hop IP CANNOT be found in ARP cache */
				if ((arp_entry = sr_arpcache_lookup(&(sr->cache), htonl(nexthop_ip))) == NULL) {
					
					/* send an ARP request */
					arp_req = sr_arpcache_queuereq(&(sr->cache), nexthop_ip, packet, len, iface);
					handle_arpreq(sr, arp_req);
				}
				/* if the next-hop IP can be found in ARP cache */
				else {
					
					/* set the destination MAC of ethernet header */
					memcpy(ether_hdr->ether_dhost, arp_entry->mac, ETHER_ADDR_LEN);
					
					/* send the packet */
					if (sr_send_packet(sr, packet, sizeof(packet), (const char*)interface) == -1) {
						fprintf(stderr, "Error: sending packet failed (sr_handlearp)\n");
					}
					
					free(arp_entry);
				}
			}
		}
	}
}