Example #1
0
/*---------------------------------------------------------------------
 * Method: handle_outgoing_icmp
 *
 * Scope:  Global
 *
 * This function contains the logic for handling outbound ICMP packets.
 * in concludes the appropriate response to take, either to route, drop
 * or generate a host unreachable ICMP error. It also translates the
 * outgoing packet if necessary. The router will then implements the NAT's
 * recommendation on the potentially modified ip packet.
 *
 * parameters:
 *		sr 	 		- a reference to the router structure
 *		iphdr 		- a struct containing the NAT's translation policy
 *
 *---------------------------------------------------------------------*/
nat_action_type handle_outgoing_icmp(struct sr_instance *sr, sr_ip_hdr_t *iphdr) 
{
	DebugNAT("+++ NAT handling outbound ICMP +++\n");
	struct sr_nat *nat = &sr->nat;
	unsigned int iplen = ntohs(iphdr->ip_len);
  	unsigned int icmplen = 0;
  	sr_icmp_echo_hdr_t *icmphdr = (sr_icmp_echo_hdr_t *) extract_ip_payload(iphdr, iplen, &icmplen);  

  	if ((icmphdr->icmp_type != icmp_type_echoreply) &&
  		(icmphdr->icmp_type != icmp_type_echoreq)) {
  		DebugNAT("+++ Unsupported ICMP type. +++\n");
  		return nat_action_drop; //ignore icmp packets other then echo requests/replies
  	}
	
	uint32_t ip_src = iphdr->ip_src;
	//uint32_t ip_dst = ntohl(iphdr->ip_dst);
	uint16_t aux_src = icmphdr->icmp_id;

	sr_nat_mapping_t *map = sr_nat_lookup_internal(nat,ip_src,aux_src,nat_mapping_icmp);

	if (map == NULL) {
		//insert new mapping into the translation table
		map = sr_nat_insert_mapping(sr,ip_src,aux_src,0,0,nat_mapping_icmp);
		DebugNAT("+++ Created NAT mapping from id [%d] to [%d]. +++\n",ntohs(map->aux_int),ntohs(map->aux_ext));
	}
	//translate entry
	translate_outgoing_icmp(iphdr,map);
	//update connection state
	update_icmp_connection(map);

	return nat_action_route;
}
Example #2
0
File: sr_nat_icmp.c Project: hhy/ip
/**
 * ICMP Echo reply (on receipt of an ICMP Echo request to one of the router’s interfaces)
 */
int nat_icmp(uint8_t* buf, unsigned int len, struct sr_instance* sr,
		char* interface) {

	//sr_ethernet_hdr_t *p_ehdr = (sr_ethernet_hdr_t *) buf;
	sr_ip_hdr_t* p_iphdr = (sr_ip_hdr_t *) (buf + sizeof(sr_ethernet_hdr_t));
	struct icmphdr* p_icmphdr = (struct icmphdr*) ((uint8_t *) p_iphdr
			+ 4 * (p_iphdr->ip_hl & 0x0f));

	/**
	 check sum verify, temporary set the chksum part to 0
	 */

	uint16_t lenIcmp = ntohs(p_iphdr->ip_len) - (p_iphdr->ip_hl & 0x0f) * 4;

	uint16_t calculatedsum = cksum(p_icmphdr, lenIcmp);
	if (calculatedsum + 1 != 0x010000) {
		printf("icmp sum check fails: %d, length: %d\n", calculatedsum,
				lenIcmp);
		return -1;
	}
	printf("[icmp nat]icmp sum check pass\n");



	//printf("------------------> %d, %d\n", ICMP_ECHOREPLY , p_icmphdr->type &0x0ff);

	if (p_icmphdr->type == ICMP_ECHO) {
		printf("[icmp nat info] get the request, start to nat forwarding, ip: %d, id: %d\n",ntohl(p_iphdr->ip_src), ntohs(p_icmphdr->un.echo.id));

		/* if the echo request come from external network, drop it */
		if (memcmp(if_nat->name, interface, strlen(if_nat->name)) != 0) {
			printf(
					"[warning] echo request comes from external network, drop it. source interface: %s\n",
					interface);
			return 1;
		}

		/* looking up the mapping entry, or insert a new one */
		struct sr_nat_mapping *m = sr_nat_lookup_internal(&(sr->nat),
				ntohl(p_iphdr->ip_src), ntohs(p_icmphdr->un.echo.id),
				nat_mapping_icmp);
		if (m == NULL ) {

			printf("[echo id: %d]\n", ntohs(p_icmphdr->un.echo.id));
			m = sr_nat_insert_mapping(&(sr->nat), ntohl(p_iphdr->ip_src),
					ntohs(p_icmphdr->un.echo.id), ntohl(p_iphdr->ip_dst),nat_mapping_icmp, 0, 0);
			printf("[nat-------------------------------------------------] insert new nat icmp entry, now table: \n");
			print_mapping_table(sr->nat.mappings);
		}

		assert(m);

		/* rewrite the package */

		p_icmphdr->un.echo.id = htons(m->aux_ext);
		sr_nat_update_icmp_mapping(&(sr->nat), p_icmphdr->un.echo.id);


		p_icmphdr->checksum = 0;
		p_icmphdr->checksum = cksum(p_icmphdr, lenIcmp);

		struct in_addr dest;
		//dest.s_addr = ntohl(pIpHdr->ip_dst);
		dest.s_addr =( p_iphdr->ip_dst);
		struct sr_rt *tSr = sr_find_routing_entry(sr, dest, buf, len);
		printf("[nat icmp] find exit interface: %s\n", tSr->interface);
		printf("[nat icmp] --------------find the out ip for destination ip: ");
	printf("destinate: ");
	print_ip_int(dest.s_addr);
	printf("\n");
		uint32_t ipOut = find_ip_by_interface(tSr->interface, sr->if_list);
		printf("interface: %s , exit ip ", tSr->interface);
		print_ip_int(ipOut);
		printf("\n");

		p_iphdr->ip_src = ipOut;

		sr_forward_ippacket(sr, buf, len);
		printf("[nat] forward a icmp request, [id= %d]\n", m->aux_ext);
		free(m);
		return 0;
	} else if (ICMP_ECHOREPLY == (p_icmphdr->type & 0x0ff)) {
		printf("get icmp response from ");
		print_ip_int(ntohl(p_iphdr->ip_src));
		printf("\n");

		struct sr_nat_mapping *m = sr_nat_lookup_external(&(sr->nat),
				ntohs(p_icmphdr->un.echo.id), nat_mapping_icmp);
		if (NULL == m) {
			printf("unknown icmp reply [id = %d ], drop it\n",
					ntohs(p_icmphdr->un.echo.id));
			return 1;
		}
		/* rewrite the icmp header */
		p_icmphdr->un.echo.id = htons(m->aux_int);
		p_icmphdr->checksum = 0;
		p_icmphdr->checksum = cksum(p_icmphdr, lenIcmp);


//		printf("[nat] ----------------\n");
//		print_ip_int(p_iphdr->ip_dst);
//		printf("[nat] ----------------\n");
//		print_ip_int(m->ip_int);
//		printf("[nat] ----------------\n");

		/*rewrite the dst ip */
		p_iphdr->ip_dst = htonl(m->ip_int);
		sr_forward_ippacket(sr, buf, len);
		sr_nat_update_icmp_mapping(&(sr->nat), p_icmphdr->un.echo.id);
		free(m);
		return 0;

	} else {
		printf("[nat icmp]get other type of icmp packet, type(%d), ignore\n",
				p_icmphdr->type & 0x0ff);
		return 0;
	}
	//return 1;
}
Example #3
0
// New NAT handling function
void processNatIP(struct sr_instance *sr, uint8_t *packet, unsigned int len, struct sr_if *interface){

    sr_ip_hdr_t *ipHeader = (sr_ip_hdr_t *) (packet + ethernetHeaderSize);

    uint8_t protocolType = ipHeader->ip_p;


    if (protocolType == TCP){
        // Create the tcp header and print it
        //TODO:sr_tcp_hdr_t *tcpHeader = (sr_tcp_hdr_t *) (packet + sizeof(sr_ethernet_hdr_t) + (ipHeader->ip_hl * 4));

        //TODO: Need to Update the port and Update the checksum
    }

    if (protocolType == ICMP){
        // If the interface name matches the internal nat interface
        if (!strncmp(interface->name, internalNat, sr_IFACE_NAMELEN)) {
            /* received from internal interface */

            // Check if this this router is the destination
            struct sr_if *destination = getIpInterface(sr, ipHeader->ip_dst);

            // If the destination is not for us, handle it with ICMP
            if (destination != NULL) {
                processICMP(sr, packet, len);
            }

            // Otherwise, if the destination is not for us, need to forward it
            else {
                /* outbound */

                // Construct Type 0 ICMP Header
                sr_icmp_t0_hdr_t *icmpHeader = (sr_icmp_t0_hdr_t *) (packet + ethernetHeaderSize + (ipHeader->ip_hl * 4));

                // Look up the mapping associated with given internal ip port pair
                struct sr_nat_mapping *natMapping = sr_nat_lookup_internal(&(sr->nat), ipHeader->ip_src, icmpHeader->icmp_id, nat_mapping_icmp);

                // No such nat mapping => insert into the mapping list
                if (!natMapping) {
                    natMapping = sr_nat_insert_mapping(&(sr->nat), ipHeader->ip_src, icmpHeader->icmp_id, nat_mapping_icmp);
                }

                // Get external Nat Interface
                struct sr_if *externalNatInterface = sr_get_interface(sr, externalNat);

                /* Update the ICMP and IP Header */
                ipHeader->ip_src = externalNatInterface->ip;
                ipHeader->ip_sum = 0;
                ipHeader->ip_sum = cksum(ipHeader, ipHeader->ip_hl * 4);
                icmpHeader->icmp_id = natMapping->aux_ext;
                icmpHeader->icmp_sum = 0;
                icmpHeader->icmp_sum = cksum(icmpHeader, ntohs(ipHeader->ip_len) - (ipHeader->ip_hl * 4));

                free(natMapping);

                // Forward th IP
                ipForwarding(sr, packet, len);
            }
        }

        // Otherwise: if the interface name does match external nat interface
        else if (!strncmp(interface->name, externalNat, sr_IFACE_NAMELEN)) {
            /* received from external interface */

            // Check the destination
            struct sr_if *destination = getIpInterface(sr, ipHeader->ip_dst);

            // If the destination isn't for us, just drop it
            if (destination == NULL) {
                return;
            }

            // If the destination is for us: Same behaviour
            else {
                /* inbound */

                sr_icmp_t0_hdr_t *icmpHeader = (sr_icmp_t0_hdr_t *)(packet + ethernetHeaderSize + (ipHeader->ip_hl * 4));

                struct sr_nat_mapping *natMapping = sr_nat_lookup_external(&(sr->nat), icmpHeader->icmp_id, nat_mapping_icmp);

                if (!natMapping) {
                    return;
                }

                /* Update the ICMP and IP Header */
                ipHeader->ip_dst = natMapping->ip_int;
                ipHeader->ip_sum = 0;
                ipHeader->ip_sum = cksum(ipHeader, ipHeader->ip_hl * 4);
                icmpHeader->icmp_id = natMapping->aux_int;
                icmpHeader->icmp_sum = 0;
                icmpHeader->icmp_sum = cksum(icmpHeader, ntohs(ipHeader->ip_len) - (ipHeader->ip_hl * 4));

                free(natMapping);

                ipForwarding(sr, packet, len);
            }
        }
    }
}