예제 #1
0
/* when an outbound packet comes, check the cached packets, 
	if ip_dst and port_server matches, drop the cached unsolicited packets
 */
void drop_unsolicited_packet(struct sr_nat *nat, uint8_t *packet) {
	pthread_mutex_lock(&(nat->lock));
	
	/* get ip hdr and tcp hdr */
	sr_ip_hdr_t *ip_hdr = get_ip_hdr(packet);
	sr_tcp_hdr_t *tcp_hdr = get_tcp_hdr(packet);

	struct sr_tcp_unsolicited_packet *my_pkt = nat->unsolicited_packet;

	if (my_pkt != NULL) {
		struct sr_tcp_unsolicited_packet *next_pkt = my_pkt->next;
		
		if (next_pkt == NULL) {
			sr_ip_hdr_t *my_pkt_ip_hdr = get_ip_hdr(my_pkt->buf);
			sr_tcp_hdr_t *my_pkt_tcp_hdr = get_tcp_hdr(my_pkt->buf);

			if (ip_hdr->ip_dst == my_pkt_ip_hdr->ip_src && tcp_hdr->dst_port == my_pkt_tcp_hdr->src_port) {
				nat->unsolicited_packet = NULL;
			}
		}
		else {
			struct sr_tcp_unsolicited_packet *prev_pkt = my_pkt;
	
			while (next_pkt != NULL) {
				sr_ip_hdr_t *my_pkt_ip_hdr = get_ip_hdr(my_pkt->buf);
				sr_tcp_hdr_t *my_pkt_tcp_hdr = get_tcp_hdr(my_pkt->buf);

				if (ip_hdr->ip_dst == my_pkt_ip_hdr->ip_src && tcp_hdr->dst_port == my_pkt_tcp_hdr->src_port) {
					if (my_pkt == nat->unsolicited_packet) {
						nat->unsolicited_packet = next_pkt;
						prev_pkt = next_pkt;
						my_pkt = next_pkt;
						next_pkt = next_pkt->next;
					} else {
						prev_pkt->next = next_pkt;
						my_pkt = next_pkt;
						next_pkt = next_pkt->next;
					}
				}
				prev_pkt = my_pkt;
				my_pkt = next_pkt;
				next_pkt = next_pkt->next;
			}
			/* check the last packet */
			sr_ip_hdr_t *my_pkt_ip_hdr = get_ip_hdr(my_pkt->buf);
			sr_tcp_hdr_t *my_pkt_tcp_hdr = get_tcp_hdr(my_pkt->buf);
			if (ip_hdr->ip_dst == my_pkt_ip_hdr->ip_src && tcp_hdr->dst_port == my_pkt_tcp_hdr->src_port) {
				prev_pkt->next = NULL;
			}
		}
	}
	
	pthread_mutex_unlock(&(nat->lock));

	return;
}
예제 #2
0
/*
Expects everything but len in network order
 */
void send_time_exceeded(struct sr_instance *sr, uint8_t *pkt) {

  /* Need to buffer enough space to include the unused 32 bits, the IP
  header length, and 64 bits first bits of original datagrams data  */
  unsigned int packet_size = sizeof(sr_ethernet_hdr_t) +
			      sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_hdr_t)
			      + UNUSED_BYTE_LENGTH_TIME_EXCEEDED_ICMP + ICMP_DATA_SIZE; 

  uint8_t *outgoing_pkt = malloc(packet_size);
  
  sr_ethernet_hdr_t *outgoing_eth_hdr = get_ethernet_hdr(outgoing_pkt);
  sr_ip_hdr_t *outgoing_ip_hdr = get_ip_hdr(outgoing_pkt);
  sr_icmp_hdr_t *outgoing_icmp_hdr = get_icmp_hdr(outgoing_pkt);

  uint32_t ip_dst = get_ip_hdr(pkt)->ip_src;
  struct sr_rt *outgoing_routing_entry = find_lpm_in_routing_table(sr->routing_table, ntohl(ip_dst));
  if (!outgoing_routing_entry) {
    free(pkt);
    free(outgoing_pkt);
    return;
  }
  struct sr_if *outgoing_inf = sr_get_interface(sr, outgoing_routing_entry->interface);

  /*Ethernet*/
  memcpy(outgoing_eth_hdr->ether_shost, outgoing_inf->addr, ETHER_ADDR_LEN);
  outgoing_eth_hdr->ether_type = htons(ethertype_ip);

  /*IP*/
  populate_ip_hdr_normal(outgoing_ip_hdr);
  outgoing_ip_hdr->ip_len = htons(packet_size - sizeof(sr_ethernet_hdr_t));
  outgoing_ip_hdr->ip_p = ip_protocol_icmp;
  outgoing_ip_hdr->ip_sum = 0;
  outgoing_ip_hdr->ip_src = outgoing_inf->ip;
  outgoing_ip_hdr->ip_dst = ip_dst;
  outgoing_ip_hdr->ip_sum = cksum(outgoing_ip_hdr, sizeof(sr_ip_hdr_t));

  /*ICMP*/
  outgoing_icmp_hdr->icmp_type = ICMP_TYPE_TIME_EXCEEDED;
  outgoing_icmp_hdr->icmp_code = ICMP_CODE_TIME_EXCEEDED;
  outgoing_icmp_hdr->icmp_sum = 0;
  memset((char *)outgoing_icmp_hdr + sizeof(sr_icmp_hdr_t), 0, UNUSED_BYTE_LENGTH_TIME_EXCEEDED_ICMP); 
  memcpy((char *)outgoing_icmp_hdr + sizeof(sr_icmp_hdr_t) + UNUSED_BYTE_LENGTH_TIME_EXCEEDED_ICMP, 
	 get_ip_hdr(pkt), ICMP_DATA_SIZE);
  outgoing_icmp_hdr->icmp_sum = cksum(outgoing_icmp_hdr,
				      sizeof(sr_icmp_hdr_t) + UNUSED_BYTE_LENGTH_TIME_EXCEEDED_ICMP + ICMP_DATA_SIZE);

  send_or_queue_packet_based_on_arp_entry_existence(sr, outgoing_routing_entry,
						    outgoing_pkt, packet_size);
}
예제 #3
0
void print_packet(const uint8_t *packet, unsigned int len)
{

	assert(packet);

	printf("\n");
	print_eth_hdr(packet, len);
	printf("\n");

	eth_hdr *eth = (eth_hdr *)packet;
	if (ntohs(eth->eth_type) == ETH_TYPE_ARP) {
		print_arp_hdr(packet, len);
		printf("\n");
	} else if (ntohs(eth->eth_type) == ETH_TYPE_IP) {
		ip_hdr *ip = get_ip_hdr(packet, len);
		indent(1);
		printf("IPv4 Packet (%d bytes)\n", len - sizeof(eth_hdr));
		print_ip_hdr(packet, len);
		switch(ip->ip_p) {
			case 1:
			{ print_icmp_load(packet, len); break; }
			case 6:
			{ print_tcp_load(packet, len); break; }
			case 89:
			{ print_pwospf_load(packet, len); break; }
			default:
			{ printf("UNRECOGNIZABLE PROTOCOL\n"); break;}
		}
	}
}
예제 #4
0
파일: rapist.c 프로젝트: CM44/data_pirate
// return false to exit this stalker thread
unsigned int
stalker_callback(void *si, void *pi)
{
    // uri_logout(pi);
    // http_hdr_logout(pi);

    void    *tr = stalker_get_exptr(si);
    if(!tr)
    {
        struct _tcphdr  *tcp    = get_tcp_hdr(pi);
        tr  = tr_init_c2s(pi);
        if(!tr) return false;
        stalker_set_exptr(si, tr);
#if 1
        struct _iphdr   *ip     = get_ip_hdr(pi);
        _MESSAGE_OUT("\033[1mlog out switch in file : %s:%d\n",
                            __FILE__, __LINE__ - 3);
        _MESSAGE_OUT("ip.addr == %s && tcp.port == %u\033[0m\n",
                            _netint32toip(ip->daddr), _ntoh16(tcp->source));
#endif 
    }
    tr_receive(tr, pi);

    // route_packet(pi);
    pi_destory(pi);
    return true;
}
예제 #5
0
파일: rapist.c 프로젝트: CM44/data_pirate
unsigned int
i_wanna_fuck_this_beauty(void *pi)
{
    unsigned char   *http   = get_http_ptr(pi);
    unsigned int    tdl     = get_tcp_data_len(pi);

    if(!http || !tdl) return false;
    if(http - get_pkt_ptr(pi) + 4 >= tdl) return false;


    if('G'==http[0] && 'E'==http[1] && 'T'==http[2] && ' '==http[3])
    {
#if 0
        static int i = 0;
        if(i) return false;
        struct _tcphdr  *tcp    = get_tcp_hdr(pi);
        struct _iphdr   *ip     = get_ip_hdr(pi);
        _MESSAGE_OUT("Hook one ip test !!! switch in file : %s:%d\n",
                            __FILE__, __LINE__ - 6);
        _MESSAGE_OUT("=============\nip.addr == %s && tcp.port == %u\n",
                            _netint32toip(ip->daddr), _ntoh16(tcp->source));
        i = 1;
#endif
        return true;
    }

    return false;
}
예제 #6
0
struct sr_tcp_unsolicited_packet *sr_nat_unsolicited_queue(struct sr_nat *nat, uint8_t *packet, unsigned int packet_len) {
    pthread_mutex_lock(&(nat->lock));
    
	/* get ethernet header, ip header, tcp header */
	/*sr_ethernet_hdr_t *eth_hdr = get_eth_hdr(packet);*/
	sr_ip_hdr_t *ip_hdr = get_ip_hdr(packet);
	sr_tcp_hdr_t *tcp_hdr = get_tcp_hdr(packet);

    struct sr_tcp_unsolicited_packet *my_pkt = NULL;

	int found = 0;

    for (my_pkt = nat->unsolicited_packet; my_pkt != NULL; my_pkt = my_pkt->next) {

		/*sr_ethernet_hdr_t *my_pkt_eth_hdr = get_eth_hdr(my_pkt->buf);*/
		sr_ip_hdr_t *my_pkt_ip_hdr = get_ip_hdr(my_pkt->buf);
		sr_tcp_hdr_t *my_pkt_tcp_hdr = get_tcp_hdr(my_pkt->buf);
		
		/* check if the ip_src/dst and src/dst_port match */
		if (ip_hdr->ip_src == my_pkt_ip_hdr->ip_src && ip_hdr->ip_dst == my_pkt_ip_hdr->ip_dst 
		&& tcp_hdr->src_port == my_pkt_tcp_hdr->src_port && tcp_hdr->dst_port == my_pkt_tcp_hdr->dst_port) {
			found = 1;
			break;
		}
    }
    
    /* If the packet wasn't found, add it */
    if (found == 0) {
		struct sr_tcp_unsolicited_packet *new_pkt = (struct sr_tcp_unsolicited_packet *)malloc(sizeof(struct sr_tcp_unsolicited_packet));
		new_pkt->buf = (uint8_t *)malloc(packet_len);
		memcpy(new_pkt->buf, packet, packet_len);
		new_pkt->len = packet_len;
		new_pkt->time_updated = time(NULL);
		new_pkt->next = nat->unsolicited_packet;
		nat->unsolicited_packet = new_pkt;
		
		pthread_mutex_unlock(&(nat->lock));
		return new_pkt;
    }
    
    pthread_mutex_unlock(&(nat->lock));

	return my_pkt;

}
예제 #7
0
/*
Expects everything but len in network order
 */
void send_echo_reply(struct sr_instance *sr, uint8_t *pkt, unsigned int len) {
  uint8_t *outgoing_pkt = malloc(len);
  
  sr_ethernet_hdr_t *outgoing_eth_hdr = get_ethernet_hdr(outgoing_pkt);
  sr_ip_hdr_t *outgoing_ip_hdr = get_ip_hdr(outgoing_pkt);
  sr_icmp_hdr_t *outgoing_icmp_hdr = get_icmp_hdr(outgoing_pkt);

  uint32_t ip_dst = get_ip_hdr(pkt)->ip_src;
  struct sr_rt *outgoing_routing_entry = find_lpm_in_routing_table(sr->routing_table, ntohl(ip_dst));
  if (!outgoing_routing_entry) {
    free(pkt);
    free(outgoing_pkt);
    return;
  }
  struct sr_if *outgoing_inf = sr_get_interface(sr, outgoing_routing_entry->interface);

  /*Ethernet*/
  memcpy(outgoing_eth_hdr->ether_shost, outgoing_inf->addr, ETHER_ADDR_LEN);
  outgoing_eth_hdr->ether_type = htons(ethertype_ip);

  /*IP*/
  populate_ip_hdr_normal(outgoing_ip_hdr);
  outgoing_ip_hdr->ip_len = htons(len - sizeof(sr_ethernet_hdr_t));
  outgoing_ip_hdr->ip_p = ip_protocol_icmp;
  outgoing_ip_hdr->ip_sum = 0;
  outgoing_ip_hdr->ip_src = get_ip_hdr(pkt)->ip_dst;
  outgoing_ip_hdr->ip_dst = ip_dst;
  outgoing_ip_hdr->ip_sum = cksum(outgoing_ip_hdr, sizeof(sr_ip_hdr_t));

  /*ICMP*/
  outgoing_icmp_hdr->icmp_type = ICMP_TYPE_ECHO_REPLY;
  outgoing_icmp_hdr->icmp_code = ICMP_CODE_ECHO_REPLY;
  outgoing_icmp_hdr->icmp_sum = 0;
  memcpy((char *)outgoing_icmp_hdr + sizeof(sr_icmp_hdr_t), pkt +
	 sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t) +
	 sizeof(sr_icmp_hdr_t), len - sizeof(sr_ethernet_hdr_t) - sizeof(sr_ip_hdr_t) -
	 sizeof(sr_icmp_hdr_t));
  outgoing_icmp_hdr->icmp_sum = cksum(outgoing_icmp_hdr,
				      ntohs(outgoing_ip_hdr->ip_len) - sizeof(sr_ip_hdr_t));


  send_or_queue_packet_based_on_arp_entry_existence(sr, outgoing_routing_entry,
						    outgoing_pkt, len);
}
예제 #8
0
/*
Expects entire ethernet frame, still in network order, and ip destination
in host order
 */
void handle_ip_packet_not_destined_to_router(struct sr_instance *sr, uint8_t
					     *pkt, uint32_t ip_dst, unsigned int len) {
  struct sr_rt *table_match = find_lpm_in_routing_table(sr->routing_table,ip_dst);
  
  if (table_match) {
    send_or_queue_packet_based_on_arp_entry_existence(sr, table_match, pkt, len);
  } else {
    sr_ip_hdr_t *ip_hdr = get_ip_hdr(pkt);
    
    send_icmp_type3_pkt(sr, ip_hdr->ip_src, ip_hdr, ICMP_CODE_NETWORK_UNREACHABLE); 
  }
}
예제 #9
0
/*All passed in params are lent and will not be modified, all in network order*/
void send_icmp_type3_pkt(struct sr_instance *sr, uint32_t ip_dst, void
*icmp3_data, uint8_t icmp_code) {
  uint8_t *outgoing_pkt = malloc(sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_t3_hdr_t));

  sr_ethernet_hdr_t *outgoing_eth_hdr = get_ethernet_hdr(outgoing_pkt);
  sr_ip_hdr_t *outgoing_ip_hdr = get_ip_hdr(outgoing_pkt);
  sr_icmp_t3_hdr_t *outgoing_icmp_hdr = get_icmp_t3_hdr(outgoing_pkt);

  struct sr_rt *outgoing_routing_entry = find_lpm_in_routing_table(sr->routing_table, ntohl(ip_dst));
  if (!outgoing_routing_entry) {
    /*Drop constructed packet if not possible to send from routing table*/
    return;
  }
  struct sr_if *outgoing_inf = sr_get_interface(sr, outgoing_routing_entry->interface);

  /*Ethernet*/
  /*Find destination MAC later, source MAC is outgoing interface MAC*/
  memcpy(outgoing_eth_hdr->ether_shost, outgoing_inf->addr, ETHER_ADDR_LEN);
  outgoing_eth_hdr->ether_type = htons(ethertype_ip);

  /*IP*/
  /*IP src is outgoing interface's source*/
  populate_ip_hdr_normal(outgoing_ip_hdr);
  outgoing_ip_hdr->ip_len = htons(sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_t3_hdr_t));
  outgoing_ip_hdr->ip_p = ip_protocol_icmp;
  outgoing_ip_hdr->ip_sum = 0;
  outgoing_ip_hdr->ip_src = outgoing_inf->ip;
  outgoing_ip_hdr->ip_dst = ip_dst;
  outgoing_ip_hdr->ip_sum = cksum(outgoing_ip_hdr, sizeof(sr_ip_hdr_t));

  /*ICMP*/
  outgoing_icmp_hdr->icmp_type = 3; /*OK to hardcode because of function name*/
  outgoing_icmp_hdr->icmp_code = icmp_code;
  outgoing_icmp_hdr->icmp_sum = 0;

  /*Specifics to an ICMP type 3 packet- hence stylistically decided not to
    combine this function with other ICMP creation functions*/
  memset((char *)outgoing_icmp_hdr + sizeof(sr_icmp_hdr_t), 0, UNUSED_BYTE_LENGTH_TYPE_3_ICMP); 
  memcpy(outgoing_icmp_hdr->data, icmp3_data, ICMP_DATA_SIZE);
  outgoing_icmp_hdr->icmp_sum = cksum(outgoing_icmp_hdr,
				      ntohs(outgoing_ip_hdr->ip_len) - sizeof(sr_ip_hdr_t));

  send_or_queue_packet_based_on_arp_entry_existence(sr, outgoing_routing_entry, outgoing_pkt, sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_t3_hdr_t));
}
예제 #10
0
/*
Expects entire ethernet frame, still in network order.
 */
void handle_ip(struct sr_instance *sr, uint8_t *pkt, unsigned int len) {
  sr_ip_hdr_t *ip_hdr = get_ip_hdr(pkt);

  uint32_t ip_dst = ntohl(ip_hdr->ip_dst);

  if (!ip_packet_sanity_check(pkt, ip_hdr)) {
    free(pkt);
    return;
  }

  if (find_interface_with_ip(sr, ip_dst)) {
    handle_ip_packet_destined_to_router(sr, pkt, ip_hdr, len);
  } else {
    /*Endian conversion not necessary because only 1 byte*/
    if (ip_hdr->ip_ttl == 1) {
      send_time_exceeded(sr, pkt);
      return;
    }
    ip_hdr->ip_ttl--;
    ip_hdr->ip_sum = 0;
    ip_hdr->ip_sum = cksum(ip_hdr, sizeof(sr_ip_hdr_t));
    handle_ip_packet_not_destined_to_router(sr, pkt, ip_dst, len);
  }
}
예제 #11
0
void print_ip_hdr(const uint8_t *packet, unsigned int len)
{
	assert(packet);

	ip_hdr *ip = get_ip_hdr(packet, len);

	indent(1);
	printf("IPv4 Packet Header (%d bytes)\n", 4*ip->ip_hl);
	indent(2);
	printf("Version = %d\n", ip->ip_v);
	indent(2);
	printf("Header Length = %d\n", 4*ip->ip_hl);
	indent(2);
	printf("Terms of Service = 0x%X\n", ip->ip_tos);
	indent(2);
	printf("Total Length = %d\n", ntohs(ip->ip_len));
	indent(2);
	printf("Identification = 0x%X\n", ntohs(ip->ip_id));
	indent(2);
	printf("Fragment Offset Field = 0x%X\n", ntohs(ip->ip_off));
	indent(2);
	printf("TTL (Time to Live) = %d\n", ip->ip_ttl);
	indent(2);
	printf("Protocol = ");
	switch(ip->ip_p) {
		case 1: { printf("ICMP\n"); break; }
		case 6: { printf("TCP\n"); break; }
		default: { printf("%d\n", ip->ip_p); break; }
	}
	indent(2);
	printf("Header Checksum = 0x%X\n", ntohs(ip->ip_sum));
	indent(2);
	print_ip_address("Src IP Address", ip->ip_src);
	indent(2);
	print_ip_address("Dst IP Address", ip->ip_dst);
}
예제 #12
0
/*
Expects everything but len in network order
 */
void send_icmp_port_unreachable(struct sr_instance *sr, uint8_t *pkt, unsigned int len) {
  sr_ip_hdr_t *ip_hdr = get_ip_hdr(pkt);
  send_icmp_type3_pkt(sr, ip_hdr->ip_src, ip_hdr, ICMP_CODE_PORT_UNREACHABLE);
}
예제 #13
0
/* Send ARP request if the request in our cache is not sent more than 5 times */
void handle_arpreq (struct sr_arpreq * req, struct sr_instance *sr) {
    struct sr_arpcache *sr_cache = &sr->cache;
    time_t curr_time;
    time(&curr_time);
    double one_sec = 1.0;
    if (difftime(curr_time, req->sent) >  one_sec){
        struct sr_packet *packet = req->packets; 
        /* If packet is sent more than equal or more than 5 times, send ICMP host unreachable message */
        if ((req->times_sent) >= 5) {
            printf("Packet sent more than 5 times\n");
            while (packet) {
                uint8_t *buf = packet->buf;
                char *interface = packet->iface;
                int packet_len  = sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_t3_hdr_t);
                uint8_t *new_packet = malloc(packet_len);  

                /* Get Ethernet header */
                sr_ethernet_hdr_t* eth_hdr = get_eth_hdr(buf);

                /* Get IP header */
                sr_ip_hdr_t * ip_hdr = get_ip_hdr(buf);

                /* Create ethernet header */
                create_ethernet_header (eth_hdr, new_packet, eth_hdr->ether_dhost, eth_hdr->ether_shost, htons(ethertype_ip));
                
                /* Create IP header */
                create_ip_header (ip_hdr, new_packet, sr_get_interface(sr, interface)->ip, ip_hdr->ip_src);

                /* Create ICMP Header */
                create_icmp_type3_header (ip_hdr, new_packet, dest_host_unreachable_type, dest_host_unreachable_code);
     
                /* Look up routing table for rt entry that is mapped to the source of received packet */
                struct sr_rt *src_lpm = sr_routing_lpm(sr, ip_hdr->ip_src);

                /* Send ICMP host unreachable message */
                send_icmp_type3_msg (new_packet, src_lpm, sr_cache, sr, interface, packet_len); 
                
                free(new_packet);

                packet = packet->next;
            }
            sr_arpreq_destroy(sr_cache, req); 
        } else {
            /* Send out arp request */
            struct sr_if *target_iface = sr_get_interface(sr, packet->iface);
            int packet_len = sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t);
            uint8_t *new_packet = malloc(packet_len);

            /* Createn ethernet header */
            sr_ethernet_hdr_t *new_eth_hdr = (sr_ethernet_hdr_t *) new_packet;
            memset(new_eth_hdr->ether_dhost, 255, sizeof(uint8_t)*ETHER_ADDR_LEN);
            memcpy(new_eth_hdr->ether_shost, target_iface->addr, sizeof(uint8_t)*ETHER_ADDR_LEN);
            new_eth_hdr->ether_type = htons(ethertype_arp);

            /* Create ARP header */
            sr_arp_hdr_t *new_arp_hdr = (sr_arp_hdr_t *)(new_packet + sizeof(sr_ethernet_hdr_t));
            new_arp_hdr->ar_hrd = htons(arp_hrd_ethernet);
            new_arp_hdr->ar_pro = htons(ethertype_ip);
            new_arp_hdr->ar_hln = ETHER_ADDR_LEN;
            new_arp_hdr->ar_pln = sizeof(uint32_t);
            new_arp_hdr->ar_op = htons(arp_op_request);
            memcpy(new_arp_hdr->ar_sha, target_iface->addr, sizeof(unsigned char)*ETHER_ADDR_LEN);
            new_arp_hdr->ar_sip = target_iface->ip;
            memset(new_arp_hdr->ar_tha, 255, sizeof(unsigned char)*ETHER_ADDR_LEN);
            new_arp_hdr->ar_tip = req->ip;

            sr_send_packet(sr, new_packet, packet_len, target_iface->name);            
            free(new_packet);
        }
            req->sent = curr_time;
            req->times_sent = req->times_sent + 1;
    }   
}
예제 #14
0
/*
 * HELPER function called from arp_thread
 */
void process_arp_queue(struct sr_instance* sr) {
	router_state* rs = get_router_state(sr);
	node* n = get_router_state(sr)->arp_queue;
	node* next = NULL;
	time_t now;
	double diff;

	while (n) {
		next = n->next;

		arp_queue_entry* aqe = (arp_queue_entry*)n->data;

		/* has it been over a second since the last arp request was sent? */
		time(&now);
		diff = difftime(now, aqe->last_req_time);
		if (diff > 1) {
			/* have we sent less than 5 arp requests? */
			if (aqe->requests < 5) {
				/* send another */
				time(&(aqe->last_req_time));
				++(aqe->requests);
				send_arp_request(sr, aqe->next_hop.s_addr, aqe->out_iface_name);
			} else {
				/* we have exceeded the max arp requests, return packets to sender */
				node* cur_packet_node = aqe->head;
				node* next_packet_node = NULL;

				while (cur_packet_node) {
					/* send icmp for the packet, free it, and its encasing entry */
					arp_queue_packet_entry* aqpe = (arp_queue_packet_entry*)cur_packet_node->data;

					/* only send an icmp error if the packet is not icmp, or if it is, its an echo request or reply
					 * also ensure we don't send an icmp error back to one of our interfaces
					 */
					if ((get_ip_hdr(aqpe->packet, aqpe->len)->ip_p != IP_PROTO_ICMP) ||
							(get_icmp_hdr(aqpe->packet, aqpe->len)->icmp_type == ICMP_TYPE_ECHO_REPLY) ||
							(get_icmp_hdr(aqpe->packet, aqpe->len)->icmp_type == ICMP_TYPE_ECHO_REQUEST)) {

					 	/* also ensure we don't send an icmp error back to one of our interfaces */
						if (!iface_match_ip(rs, get_ip_hdr(aqpe->packet, aqpe->len)->ip_src.s_addr)) {
							/* Total hack here to increment the TTL since we already decremented it earlier in the pipeline
							 * and the ICMP error should return the original packet.
							 * TODO: Don't decrement the TTL until the packet is ready to be put on the wire
							 * and we have the next hop ARP address, although checking should be done
							 * where it is currently being decremented to minimize effort on a doomed packet */
							ip_hdr *ip = get_ip_hdr(aqpe->packet, aqpe->len);
							if (ip->ip_ttl < 255) {
								ip->ip_ttl++;

								/* recalculate checksum */
								bzero(&ip->ip_sum, sizeof(uint16_t));
								uint16_t checksum = htons(compute_ip_checksum(ip));
								ip->ip_sum = checksum;
							}

							send_icmp_packet(sr, aqpe->packet, aqpe->len, ICMP_TYPE_DESTINATION_UNREACHABLE, ICMP_CODE_HOST_UNREACHABLE);
						}
					}

					free(aqpe->packet);
					next_packet_node = cur_packet_node->next;
					//free(cur_packet_node);   /* IS THIS CORRECT TO FREE IT ? */
					node_remove(&(aqe->head), cur_packet_node);
					cur_packet_node = next_packet_node;
				}

				/* free the arp queue entry for this destination ip, and patch the list */
				node_remove(&(get_router_state(sr)->arp_queue), n);
			}
		}

		n = next;
	}
}
예제 #15
0
파일: sr_router.c 프로젝트: z23han/router
/* Handle IP packet */
void sr_handle_ippacket(struct sr_instance* sr,
        uint8_t * packet/* lent */,
        unsigned int len,
        char* interface/* lent */) 
{
    assert(sr);
    assert(packet);
    assert(interface);

    /* Get ethernet header */
    sr_ethernet_hdr_t *eth_hdr = get_eth_hdr(packet);
	if (eth_hdr == NULL) {
		printf("ethernet header NULL!!!\n");
		return;
	}

    /* Get ip header */
    sr_ip_hdr_t *ip_hdr = get_ip_hdr(packet);
	if (ip_hdr == NULL) {
		printf("ip header NULL!!!\n");
		return;
	}

	/* Before doing ttl decrement, check checksum */
	uint16_t old_ip_sum = ip_hdr->ip_sum;
	ip_hdr->ip_sum = 0;

	if (!verify_checksum(ip_hdr, sizeof(sr_ip_hdr_t), old_ip_sum)) {
		fprintf(stderr, "CHECKSUM FAILED!!\n");
		return;
	}
	ip_hdr->ip_sum = old_ip_sum;

    /* Get the arp cache */
    struct sr_arpcache *sr_arp_cache = &sr->cache;

    /* Get the destination interface on the router */
	struct sr_if *sr_iface = sr_get_router_if(sr, ip_hdr->ip_dst);
	/* Get the connected interface on the router */
	struct sr_if *sr_con_if = sr_get_interface(sr, interface);

    /* Check the time exceeded condition, if ttl==0, we need to form icmp 11 and send back */
    if (ip_hdr->ip_ttl <= 1) {
        /* time exceeded message and icmp type 11 */
        printf("TTL time exceeded\n");
        int packet_len = ICMP_T3_PACKET_LEN;
        uint8_t *icmp_t3_hdr = (uint8_t *)malloc(packet_len);

        create_ethernet_hdr(eth_hdr, (sr_ethernet_hdr_t *)icmp_t3_hdr, sr_con_if);
        /* Create ip header */
        create_echo_ip_hdr(ip_hdr, (sr_ip_hdr_t *)((char *)icmp_t3_hdr+ETHER_PACKET_LEN), sr_con_if);

        /* Send icmp type 11 time exceeded */
        /* icmp_t3 type=11, code=0 */
        create_icmp_t3_hdr(ip_hdr, (sr_icmp_t3_hdr_t *)((char *)icmp_t3_hdr+IP_PACKET_LEN), 11, 0);

        /* Send icmp type 11 packet */
		struct sr_arpentry *arp_entry = sr_arpcache_lookup(sr_arp_cache, ip_hdr->ip_src);
		if (arp_entry != NULL) {
			sr_send_packet(sr, icmp_t3_hdr, packet_len, sr_con_if->name);
			free(icmp_t3_hdr);
		} else {
			struct sr_arpreq *arp_req = sr_arpcache_queuereq(sr_arp_cache, ip_hdr->ip_src, icmp_t3_hdr, packet_len, sr_con_if->name);
			handle_arpreq(arp_req, sr);
		}
        return;
    }

    /* Get the protocol from IP */
    uint8_t ip_p = ip_hdr->ip_p;

    /* If the packet is sent to self, meaning the ip is sent to the router */
    if (sr_iface) {
        /* Check the protocol if it is icmp */
        if (ip_p == ip_protocol_icmp) {
            /* Get the icmp header */
            sr_icmp_hdr_t *icmp_hdr = get_icmp_hdr(packet);

            /* Check if it is ICMP echo request */
            /* icmp_echo_req = 8 */
            if (icmp_hdr->icmp_type == 8) {
				/* Do LPM on the routing table */
        		/* Check the routing table and see if the incoming ip matches the routing table ip, and find LPM router entry */
        		struct sr_rt *longest_pref_match = sr_lpm(sr, ip_hdr->ip_src);

				if (longest_pref_match) {
					/* check ARP cache */
					struct sr_arpentry *arp_entry = sr_arpcache_lookup(&sr->cache, longest_pref_match->gw.s_addr);
					struct sr_if *out_iface = sr_get_interface(sr, longest_pref_match->interface);

					/* If hit, meaning the arp mapping has been cached */
					if (arp_entry != NULL) {
						/* We need to send the icmp echo reply */
				        /* Modify ethernet header */
						memcpy(eth_hdr->ether_dhost, eth_hdr->ether_shost, ETHER_ADDR_LEN);
						memcpy(eth_hdr->ether_shost, out_iface->addr, ETHER_ADDR_LEN);

				        /* Modify ip header */
						ip_hdr->ip_off = htons(0b0100000000000000);        /* fragment offset field */
						ip_hdr->ip_ttl = 100;                    			/* time to live */
						uint32_t temp = ip_hdr->ip_src;
						ip_hdr->ip_src = ip_hdr->ip_dst;        /* source address */
						ip_hdr->ip_dst = temp;        			/* dest address */
						ip_hdr->ip_sum = 0;
						ip_hdr->ip_sum = cksum(ip_hdr, sizeof(sr_ip_hdr_t));			/* checksum */

				        /* Modify icmp header */
						unsigned int icmp_whole_size = len - IP_PACKET_LEN;
						icmp_hdr->icmp_type = 0;
						icmp_hdr->icmp_code = 0;
						icmp_hdr->icmp_sum = 0;
						icmp_hdr->icmp_sum = cksum(icmp_hdr, icmp_whole_size);

				        /* Send icmp echo reply */
				        sr_send_packet(sr, packet, len, out_iface->name);
				        return;
					}
					/* Else no hit, we cache it to the queue and send arp request */ 
					else {
						/* Add reply to the ARP queue */
						/* We need to send the icmp echo reply */
				        /* Modify ethernet header */
						memcpy(eth_hdr->ether_dhost, eth_hdr->ether_shost, ETHER_ADDR_LEN);
						memcpy(eth_hdr->ether_shost, sr_con_if->addr, ETHER_ADDR_LEN);

				        /* Modify ip header */
						ip_hdr->ip_off = htons(0b0100000000000000);        /* fragment offset field */
						ip_hdr->ip_ttl = 100;                    			/* time to live */
						uint32_t temp = ip_hdr->ip_src;
						ip_hdr->ip_src = ip_hdr->ip_dst;        /* source address */
						ip_hdr->ip_dst = temp;        			/* dest address */
						ip_hdr->ip_sum = 0;
						ip_hdr->ip_sum = cksum(ip_hdr, sizeof(sr_ip_hdr_t));			/* checksum */

				        /* Modify icmp header */
						unsigned int icmp_whole_size = len - IP_PACKET_LEN;
						icmp_hdr->icmp_type = 0;
						icmp_hdr->icmp_code = 0;
						icmp_hdr->icmp_sum = 0;
						icmp_hdr->icmp_sum = cksum(icmp_hdr, icmp_whole_size);
						struct sr_arpreq *arp_req = sr_arpcache_queuereq(sr_arp_cache, ip_hdr->ip_dst, packet, len, out_iface->name);
						/* Send ARP request, which is a broadcast */
						handle_arpreq(arp_req, sr);
						return;
					}
				} else {
					fprintf(stderr, "Longest prefix doesnt match!!\n");
                	return;
				}

            } else {
                fprintf(stderr, "Not an ICMP request!\n");
                return;
            }
        }
        /* Else it is TCP/UDP request */
        else {
            fprintf(stderr, "*** -> Received TCP/UDP!\n");

			/* Do LPM on the routing table */
    		/* Check the routing table and see if the incoming ip matches the routing table ip, and find LPM router entry */
    		struct sr_rt *longest_pref_match = sr_lpm(sr, ip_hdr->ip_src);

			if (longest_pref_match) {
				/* check ARP cache */
				struct sr_arpentry *arp_entry = sr_arpcache_lookup(&sr->cache, longest_pref_match->gw.s_addr);
				struct sr_if *out_iface = sr_get_interface(sr, longest_pref_match->interface);
				
				/* Send ICMP port unreachable */
				if (arp_entry != NULL) {

					int packet_len = ICMP_T3_PACKET_LEN;
				    uint8_t *icmp_t3_hdr = (uint8_t *)malloc(packet_len);

				    /* Create ethernet header */
				    create_ethernet_hdr(eth_hdr, (sr_ethernet_hdr_t *)icmp_t3_hdr, sr_iface);
					/*memcpy(((sr_ethernet_hdr_t *)icmp_t3_hdr)->ether_dhost, eth_hdr->ether_shost, ETHER_ADDR_LEN);
					memcpy(((sr_ethernet_hdr_t *)icmp_t3_hdr)->ether_shost, eth_hdr->ether_dhost, ETHER_ADDR_LEN);*/

				    /* Create ip header */
				    create_echo_ip_hdr(ip_hdr, (sr_ip_hdr_t *)((char *)icmp_t3_hdr+ETHER_PACKET_LEN), sr_iface);
					/*sr_ip_hdr_t *icmp_t3_hdr_ip = (sr_ip_hdr_t *)((char *)icmp_t3_hdr+ETHER_PACKET_LEN);
					icmp_t3_hdr_ip->ip_src = ip_hdr->ip_dst;
					icmp_t3_hdr_ip->ip_sum = 0;
					icmp_t3_hdr_ip->ip_sum = cksum(icmp_t3_hdr_ip, sizeof(sr_ip_hdr_t));*/
					

					/* Should update source address to be interface address */

				    /* Send icmp type 3 port unreachable */
				    /* Create icmp port unreachable packet */
				    /* icmp_t3 type=3, code=3 */
				    create_icmp_t3_hdr(ip_hdr, (sr_icmp_t3_hdr_t *)((char *)icmp_t3_hdr+IP_PACKET_LEN), 3, 3);

				    /* Send icmp type 3 packet */
				    sr_send_packet(sr, icmp_t3_hdr, packet_len, out_iface->name);

				    free(icmp_t3_hdr);
				    return;
				} else {
				
					int packet_len = ICMP_T3_PACKET_LEN;
				    uint8_t *icmp_t3_hdr = (uint8_t *)malloc(packet_len);

				    /* Create ethernet header */
				    create_ethernet_hdr(eth_hdr, (sr_ethernet_hdr_t *)icmp_t3_hdr, sr_iface);
					/*memcpy(((sr_ethernet_hdr_t *)icmp_t3_hdr)->ether_dhost, eth_hdr->ether_shost, ETHER_ADDR_LEN);
					memcpy(((sr_ethernet_hdr_t *)icmp_t3_hdr)->ether_shost, eth_hdr->ether_dhost, ETHER_ADDR_LEN);*/

				    /* Create ip header */
				    create_echo_ip_hdr(ip_hdr, (sr_ip_hdr_t *)((char *)icmp_t3_hdr+ETHER_PACKET_LEN), sr_iface);
					/*sr_ip_hdr_t *icmp_t3_hdr_ip = (sr_ip_hdr_t *)((char *)icmp_t3_hdr+ETHER_PACKET_LEN);
					icmp_t3_hdr_ip->ip_src = ip_hdr->ip_dst;
					icmp_t3_hdr_ip->ip_sum = 0;
					icmp_t3_hdr_ip->ip_sum = cksum(icmp_t3_hdr_ip, sizeof(sr_ip_hdr_t));*/

				    /* Send icmp type 3 port unreachable */
				    /* Create icmp port unreachable packet */
				    /* icmp_t3 type=3, code=3 */
				    create_icmp_t3_hdr(ip_hdr, (sr_icmp_t3_hdr_t *)((char *)icmp_t3_hdr+IP_PACKET_LEN), 3, 3);

					struct sr_arpreq *arp_req = sr_arpcache_queuereq(sr_arp_cache, ip_hdr->ip_src, icmp_t3_hdr, packet_len, out_iface->name);
					/* Send ARP request, which is a broadcast */
					handle_arpreq(arp_req, sr);
					return;
				}
			} else {
				fprintf(stderr, "Longest prefix doesnt match!!\n");
                return;
			}            
            
        }
    }
    /* Else Check the routing table, perfomr LPM */
    else {
        /* Sanity-check the packet */
        /* minimum length */
        if (!check_min_length(len, IP_PACKET_LEN)) {
            fprintf(stderr, "The packet length is not enough:(\n");
            return;
        }
		
        /* Do LPM on the routing table */
        /* Check the routing table and see if the incoming ip matches the routing table ip, and find LPM router entry */
        struct sr_rt *longest_pref_match = sr_lpm(sr, ip_hdr->ip_dst);
        if (longest_pref_match) {
            /* check ARP cache */
			struct sr_if *out_iface = sr_get_interface(sr, longest_pref_match->interface);

            struct sr_arpentry *arp_entry = sr_arpcache_lookup(&sr->cache, longest_pref_match->gw.s_addr); /* ip_hdr->ip_dst */
         
			/* If hit, meaning the arp_entry is found */
            if (arp_entry) {

				/*fprintf(stderr, "************ found the lpm router entry ***********\n");*/
                /* Send frame to next hop */
                /* update the eth_hdr source and destination ethernet address */
                /* use next_hop_ip->mac mapping in the entry to send the packet */

                ip_hdr->ip_ttl--;

                /* recompute the packet checksum over the modified header */
                ip_hdr->ip_sum = 0;
                uint16_t new_ip_sum = cksum(ip_hdr, sizeof(sr_ip_hdr_t));
                ip_hdr->ip_sum = new_ip_sum;

                memcpy(eth_hdr->ether_shost, out_iface->addr, ETHER_ADDR_LEN);
                memcpy(eth_hdr->ether_dhost, arp_entry->mac, ETHER_ADDR_LEN);
                sr_send_packet(sr, packet, len, out_iface->name);
				print_hdr_ip((uint8_t*)ip_hdr);
                /* free the entry */
                free(arp_entry);
                return;
            } else/* No Hit */ {
                /* send an ARP request for the next-hop IP */
                /* add the packet to the queue of packets waiting on this ARP request */
                /* Add request to ARP queue*/

                ip_hdr->ip_ttl--;

                /* recompute the packet checksum over the modified header */
                ip_hdr->ip_sum = 0;
                uint16_t new_ip_sum = cksum(ip_hdr, sizeof(sr_ip_hdr_t));
                ip_hdr->ip_sum = new_ip_sum;

                struct sr_arpreq *arp_req = sr_arpcache_queuereq(sr_arp_cache, ip_hdr->ip_dst, packet, len, out_iface->name);
                /* send ARP request, this is a broadcast */
                handle_arpreq(arp_req, sr);
                return;
            }
        } else /* if not matched */ {
            /* Send ICMP net unreachable */
			printf("--------------- Net Unreachable ---------------\n");

			/* Do LPM on the routing table */
    		/* Check the routing table and see if the incoming ip matches the routing table ip, and find LPM router entry */
    		struct sr_rt *longest_pref_match = sr_lpm(sr, ip_hdr->ip_src);

			if (longest_pref_match) {
				/* check ARP cache */
				struct sr_arpentry *arp_entry = sr_arpcache_lookup(&sr->cache, longest_pref_match->gw.s_addr);
				struct sr_if *out_iface = sr_get_interface(sr, longest_pref_match->interface);

				if (arp_entry) {
					int packet_len = ICMP_T3_PACKET_LEN;
				    uint8_t *icmp_t3_hdr = (uint8_t *)malloc(packet_len);

				    /* Create ethernet header */
				    create_ethernet_hdr(eth_hdr, (sr_ethernet_hdr_t *)icmp_t3_hdr, out_iface);

				    /* Create ip header */
				    create_echo_ip_hdr(ip_hdr, (sr_ip_hdr_t *)((char *)icmp_t3_hdr+ETHER_PACKET_LEN), out_iface);

				    /* Create icmp net unreachable */
				    /* icmp_t3 type=3, code=0 */
				    create_icmp_t3_hdr(ip_hdr, (sr_icmp_t3_hdr_t *)((char *)icmp_t3_hdr+IP_PACKET_LEN), 3, 0);

				    /* Send icmp type 3 packet */
				    sr_send_packet(sr, icmp_t3_hdr, packet_len, out_iface->name);

				    free(icmp_t3_hdr);
				    return;
				} else {

					int packet_len = ICMP_T3_PACKET_LEN;
				    uint8_t *icmp_t3_hdr = (uint8_t *)malloc(packet_len);

				    /* Create ethernet header */
				    create_ethernet_hdr(eth_hdr, (sr_ethernet_hdr_t *)icmp_t3_hdr, out_iface);

				    /* Create ip header */
				    create_echo_ip_hdr(ip_hdr, (sr_ip_hdr_t *)((char *)icmp_t3_hdr+ETHER_PACKET_LEN), out_iface);
					/*	((sr_ip_hdr_t *)((char *)icmp_t3_hdr+ETHER_PACKET_LEN))->ip_ttl += 1; */

				    /* Send icmp type 3 net unreachable */
				    /* Create icmp net unreachable packet */
				    /* icmp_t3 type=3, code=0 */
				    create_icmp_t3_hdr(ip_hdr, (sr_icmp_t3_hdr_t *)((char *)icmp_t3_hdr+IP_PACKET_LEN), 3, 0);

					struct sr_arpreq *arp_req = sr_arpcache_queuereq(sr_arp_cache, ip_hdr->ip_src, icmp_t3_hdr, packet_len, out_iface->name);
					/* Send ARP request, which is a broadcast */
					handle_arpreq(arp_req, sr);
					return;
				}
			} else {
				fprintf(stderr, "Longest prefix doesnt match!!\n");
                return;
			}
        }
    }

    return;
}
예제 #16
0
void *sr_nat_timeout(void *sr_ptr) {  /* Periodic Timout handling */
	struct sr_instance *sr = (struct sr_instance *)sr_ptr;
  struct sr_nat *nat = sr->nat;
  while (1) {
    sleep(1.0);
    pthread_mutex_lock(&(nat->lock));

    /* handle periodic tasks here */
	time_t curtime = time(NULL);

	struct sr_tcp_unsolicited_packet *my_pkt = nat->unsolicited_packet;
	/* if my_pkt is NULL, finish! */
	if (my_pkt == NULL) {
		pthread_mutex_unlock(&(nat->lock));
	}
	else {
        /* get the next packet */
        struct sr_tcp_unsolicited_packet *next_pkt = my_pkt->next;

        /* if next pkt is NULL, only check my_pkt */
        if (next_pkt == NULL) {
            time_t pkt_time = my_pkt->time_updated;

            /* if the time difference is bigger than 6 seconds */
            if (difftime(curtime, pkt_time) >= 6) {
                /* get all the headers */
                uint8_t *packet = my_pkt->buf;
                sr_ethernet_hdr_t *eth_hdr = get_eth_hdr(packet);
                sr_ip_hdr_t *ip_hdr = get_ip_hdr(packet);

                /* create a new icmp t3 port unreachable */
                int packet_len = ICMP_T3_PACKET_LEN;
                uint8_t *icmp_t3_hdr = (uint8_t *)malloc(packet_len);
                /* create ethernet header */
                sr_ethernet_hdr_t *new_eth_hdr = (sr_ethernet_hdr_t *)icmp_t3_hdr;
                memcpy(new_eth_hdr->ether_dhost, eth_hdr->ether_shost, ETHER_ADDR_LEN);
                memcpy(new_eth_hdr->ether_shost, eth_hdr->ether_dhost, ETHER_ADDR_LEN);
                /* create ip header */
                sr_ip_hdr_t *new_ip_hdr = (sr_ip_hdr_t *)((char *)icmp_t3_hdr + ETHER_PACKET_LEN);
                new_ip_hdr->ip_hl = ip_hdr->ip_hl;          /* header length */
                new_ip_hdr->ip_v = ip_hdr->ip_v;            /* header version */
                new_ip_hdr->ip_tos = ip_hdr->ip_tos;        /* type of service */
                new_ip_hdr->ip_len = htons(56);             /* total length */
                new_ip_hdr->ip_id = 0;              /* identification */
                new_ip_hdr->ip_off = htons(0b0100000000000000);        /* fragment offset field */
                new_ip_hdr->ip_ttl = 64;                    /* time to live */
                new_ip_hdr->ip_p = ip_protocol_icmp;            /* protocol */
                new_ip_hdr->ip_src =  ip_hdr->ip_dst;       /* source address */
                new_ip_hdr->ip_dst = ip_hdr->ip_src;        /* dest address */
                new_ip_hdr->ip_sum = 0;
                new_ip_hdr->ip_sum = cksum(new_ip_hdr, sizeof(sr_ip_hdr_t));;   /* checksum */
                /* create icmp t3 header */
                sr_icmp_t3_hdr_t *new_icmp_t3_hdr = (sr_icmp_t3_hdr_t *)((char *)icmp_t3_hdr + IP_PACKET_LEN);
                new_icmp_t3_hdr->icmp_type = htons(3);
                new_icmp_t3_hdr->icmp_code = htons(3);
                new_icmp_t3_hdr->unused = 0;
                new_icmp_t3_hdr->next_mtu = 0;
                memcpy(new_icmp_t3_hdr->data, new_ip_hdr, ICMP_DATA_SIZE); 
                new_icmp_t3_hdr->icmp_sum = 0;
                new_icmp_t3_hdr->icmp_sum = cksum(new_icmp_t3_hdr, sizeof(sr_icmp_t3_hdr_t));

                struct sr_if *out_iface = sr_get_router_if(sr, ip_hdr->ip_dst);

				sr_send_packet(sr, icmp_t3_hdr, packet_len, out_iface->name);

                /* set unsolicited_packet to be NULL */
                nat->unsolicited_packet = NULL;
            }
            pthread_mutex_unlock(&(nat->lock));
        }
        /* otherwise we need to loop through the packets */
        else {
			
			struct sr_tcp_unsolicited_packet *prev_pkt = my_pkt;

            while (next_pkt != NULL) {

                time_t pkt_time = my_pkt->time_updated;

                /* if the time difference is bigger than 6 seconds */
                if (difftime(curtime, pkt_time) >= 6) {
                    /* get all the headers */
                    uint8_t *packet = my_pkt->buf;
                    sr_ethernet_hdr_t *eth_hdr = get_eth_hdr(packet);
                    sr_ip_hdr_t *ip_hdr = get_ip_hdr(packet);

                    /* create a new icmp t3 port unreachable */
                    int packet_len = ICMP_T3_PACKET_LEN;
                    uint8_t *icmp_t3_hdr = (uint8_t *)malloc(packet_len);
                    /* create ethernet header */
                    sr_ethernet_hdr_t *new_eth_hdr = (sr_ethernet_hdr_t *)icmp_t3_hdr;
                    memcpy(new_eth_hdr->ether_dhost, eth_hdr->ether_shost, ETHER_ADDR_LEN);
                    memcpy(new_eth_hdr->ether_shost, eth_hdr->ether_dhost, ETHER_ADDR_LEN);
                    /* create ip header */
                    sr_ip_hdr_t *new_ip_hdr = (sr_ip_hdr_t *)((char *)icmp_t3_hdr + ETHER_PACKET_LEN);
                    new_ip_hdr->ip_hl = ip_hdr->ip_hl;          /* header length */
                    new_ip_hdr->ip_v = ip_hdr->ip_v;            /* header version */
                    new_ip_hdr->ip_tos = ip_hdr->ip_tos;        /* type of service */
                    new_ip_hdr->ip_len = htons(56);             /* total length */
                    new_ip_hdr->ip_id = 0;              /* identification */
                    new_ip_hdr->ip_off = htons(0b0100000000000000);        /* fragment offset field */
                    new_ip_hdr->ip_ttl = 64;                    /* time to live */
                    new_ip_hdr->ip_p = ip_protocol_icmp;            /* protocol */
                    new_ip_hdr->ip_src =  ip_hdr->ip_dst;       /* source address */
                    new_ip_hdr->ip_dst = ip_hdr->ip_src;        /* dest address */
                    new_ip_hdr->ip_sum = 0;
                    new_ip_hdr->ip_sum = cksum(new_ip_hdr, sizeof(sr_ip_hdr_t));;   /* checksum */
                    /* create icmp t3 header */
                    sr_icmp_t3_hdr_t *new_icmp_t3_hdr = (sr_icmp_t3_hdr_t *)((char *)icmp_t3_hdr + IP_PACKET_LEN);
                    new_icmp_t3_hdr->icmp_type = htons(3);
                    new_icmp_t3_hdr->icmp_code = htons(3);
                    new_icmp_t3_hdr->unused = 0;
                    new_icmp_t3_hdr->next_mtu = 0;
                    memcpy(new_icmp_t3_hdr->data, new_ip_hdr, ICMP_DATA_SIZE); 
                    new_icmp_t3_hdr->icmp_sum = 0;
                    new_icmp_t3_hdr->icmp_sum = cksum(new_icmp_t3_hdr, sizeof(sr_icmp_t3_hdr_t));

                    struct sr_if *out_iface = sr_get_router_if(sr, ip_hdr->ip_dst);

					sr_send_packet(sr, icmp_t3_hdr, packet_len, out_iface->name);

                    /* unlist the my_pkt */
                    if (my_pkt == nat->unsolicited_packet) {
                        nat->unsolicited_packet = next_pkt;
                        prev_pkt = next_pkt;
						my_pkt = next_pkt;
                        next_pkt = next_pkt->next;
                    } else {
                        prev_pkt->next = next_pkt;
                        my_pkt = next_pkt;
						next_pkt = next_pkt->next;
                    }
                }
				prev_pkt = my_pkt;
				my_pkt = next_pkt;
				next_pkt = next_pkt->next;
            }
			time_t pkt_time = my_pkt->time_updated;

			/* if the time difference is bigger than 6 seconds */
            if (difftime(curtime, pkt_time) >= 6) {
                /* get all the headers */
                uint8_t *packet = my_pkt->buf;
                sr_ethernet_hdr_t *eth_hdr = get_eth_hdr(packet);
                sr_ip_hdr_t *ip_hdr = get_ip_hdr(packet);

                /* create a new icmp t3 port unreachable */
                int packet_len = ICMP_T3_PACKET_LEN;
                uint8_t *icmp_t3_hdr = (uint8_t *)malloc(packet_len);
                /* create ethernet header */
                sr_ethernet_hdr_t *new_eth_hdr = (sr_ethernet_hdr_t *)icmp_t3_hdr;
                memcpy(new_eth_hdr->ether_dhost, eth_hdr->ether_shost, ETHER_ADDR_LEN);
                memcpy(new_eth_hdr->ether_shost, eth_hdr->ether_dhost, ETHER_ADDR_LEN);
                /* create ip header */
                sr_ip_hdr_t *new_ip_hdr = (sr_ip_hdr_t *)((char *)icmp_t3_hdr + ETHER_PACKET_LEN);
                new_ip_hdr->ip_hl = ip_hdr->ip_hl;          /* header length */
                new_ip_hdr->ip_v = ip_hdr->ip_v;            /* header version */
                new_ip_hdr->ip_tos = ip_hdr->ip_tos;        /* type of service */
                new_ip_hdr->ip_len = htons(56);             /* total length */
                new_ip_hdr->ip_id = 0;              /* identification */
                new_ip_hdr->ip_off = htons(0b0100000000000000);        /* fragment offset field */
                new_ip_hdr->ip_ttl = 64;                    /* time to live */
                new_ip_hdr->ip_p = ip_protocol_icmp;            /* protocol */
                new_ip_hdr->ip_src =  ip_hdr->ip_dst;       /* source address */
                new_ip_hdr->ip_dst = ip_hdr->ip_src;        /* dest address */
                new_ip_hdr->ip_sum = 0;
                new_ip_hdr->ip_sum = cksum(new_ip_hdr, sizeof(sr_ip_hdr_t));;   /* checksum */
                /* create icmp t3 header */
                sr_icmp_t3_hdr_t *new_icmp_t3_hdr = (sr_icmp_t3_hdr_t *)((char *)icmp_t3_hdr + IP_PACKET_LEN);
                new_icmp_t3_hdr->icmp_type = htons(3);
                new_icmp_t3_hdr->icmp_code = htons(3);
                new_icmp_t3_hdr->unused = 0;
                new_icmp_t3_hdr->next_mtu = 0;
                memcpy(new_icmp_t3_hdr->data, new_ip_hdr, ICMP_DATA_SIZE); 
                new_icmp_t3_hdr->icmp_sum = 0;
                new_icmp_t3_hdr->icmp_sum = cksum(new_icmp_t3_hdr, sizeof(sr_icmp_t3_hdr_t));

                struct sr_if *out_iface = sr_get_router_if(sr, ip_hdr->ip_dst);

				sr_send_packet(sr, icmp_t3_hdr, packet_len, out_iface->name);

				/* set the last packet to be NULL */
                prev_pkt->next = NULL;

			}
		pthread_mutex_unlock(&(nat->lock));
        }		
	}
  }
  return NULL;
}