Exemplo n.º 1
0
/*---------------------------------------------------------------------
 * Method: handle_incoming_icmp
 *
 * Scope:  Global
 *
 * This function contains the logic for handling inbound ICMP packets.
 * in concludes the appropriate response to take, either to route, drop
 * or generate a host unreachable ICMP error. It also translates the
 * incoming packet if necessary. The router will then implement 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_incoming_icmp(struct sr_nat *nat, sr_ip_hdr_t *iphdr) 
{
	DebugNAT("+++ NAT handling inbound ICMP +++\n");
	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 = ntohl(iphdr->ip_src);
	//uint32_t ip_dst = ntohl(iphdr->ip_dst);
	uint16_t aux_dst = icmphdr->icmp_id;

	sr_nat_mapping_t *map = sr_nat_lookup_external(nat,aux_dst,nat_mapping_icmp);

	//do not accept connections from unmapped ports
	if (map == NULL) {
		DebugNAT("+++ Segment addressed to unmapped id ++\n");
		return nat_action_route; //packet addressed to router itself
	}

	//translate entry
	translate_incoming_icmp(iphdr,map);
	//update connection state
	update_icmp_connection(map);	


	return nat_action_route;

}
Exemplo n.º 2
0
/*---------------------------------------------------------------------
 * Method: nat_timeout_pending_syns
 *
 * Scope:  Local
 *
 * This function is a helper function for the connection garbage collector
 * thread. It cycles through the list of unsolicited syns received, and
 * generates an ICMP host unreachable message if enough time has elapsed
 * since each packet was received.
 *
 *  parameters:
 *    sr       - a reference to the router structure
 *    curtime       - the current time.
 *
 *---------------------------------------------------------------------*/
void nat_timeout_pending_syns(struct sr_instance *sr, time_t curtime)
{
  struct sr_nat *nat = &sr->nat;
  for (sr_nat_pending_syn_t *prevsyn = NULL, *cursyn = nat->pending_syns; cursyn != NULL;) {
    
    if (difftime(curtime, cursyn->time_received) > UNSOLICITED_SYN_TIMEOUT) {
      //time is up. remove from list and potentially generate responts
      DebugNATTimeout("+++&& Unsolicited SYN to port: [%d] timed out &&+++\n",ntohs(cursyn->aux_ext));
      if (sr_nat_lookup_external(nat,cursyn->aux_ext,nat_mapping_tcp) == NULL) {
        //mapping does not exist. send ICMP port unreachable
        DebugNATTimeout("+++&& Generating ICMP port unreachable message &&+++\n");
        sr_if_t *iface = get_external_iface(sr);
        send_ICMP_port_unreachable(sr,cursyn->iphdr,iface);
      }

      //free stored ip packet
      free(cursyn->iphdr);

      //remove entry from list
      if (prevsyn != NULL)
        prevsyn->next = cursyn->next;
      else
        nat->pending_syns = cursyn->next;

      sr_nat_pending_syn_t *oldcur = cursyn;
      cursyn = cursyn->next;
      free(oldcur);
      continue;
      
    }
    prevsyn = cursyn;
    cursyn = cursyn->next;
  }

}
Exemplo n.º 3
0
Arquivo: sr_nat_icmp.c Projeto: 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;
}
Exemplo n.º 4
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);
            }
        }
    }
}