void sr_handle_arpreq(struct sr_instance *sr, struct sr_arpreq *req){
    /*Debug("\nsr_handle_arpreq called\n");*/
    time_t     now;
    now = time(NULL);
    
    struct sr_arpcache *cache = &(sr->cache);
    /*if the arp_request has never been sent before or if the last time the 
    arp_request was sent was more than 1 second ago*/

    if ((req->times_sent == 0)||(difftime(now, req->sent)> 1.0)){
        /*Debug("\nARP request not previously sent or have not been sent within the last second\n");*/
        if (req->times_sent >= 5)
		{
            /*Debug("\nARP request was sent 5 times previously; destroy ARP request\n");*/
            /*loop through all of the IP packets waiting for the request,
            call function to send ICMP msg -> host_unreachable*/
            struct sr_packet *packet;
            for(packet = req->packets; packet != NULL; packet = packet->next)
			{
				/*这里的interface是outgoing interface,有问题,send_icmp_message要的是in_interface*/
				send_icmp_message(sr, packet->buf, sizeof(struct sr_packet), sr_get_interface(sr, req->packets->iface), ICMP_DESTINATION_UNREACHABLE_TYPE, ICMP_HOST_UNREACHABLE_CODE);
            }
            sr_arpreq_destroy(cache, req);
        }
        else
		{
            /*Debug("\nSending ARP request\n");*/
			/*这里的interface是outgoing interface,有问题,send_icmp_message要的是in_interface*/
			printf("interface: %s", req->packets->iface);
			send_arp_request(sr, sr_get_interface(sr, req->packets->iface), req->ip);
			req->sent = now;
            req->times_sent++;
		}
    }
}
Exemple #2
0
int sr_handle_arp_req (struct sr_instance * sr, struct sr_arpreq * arpreq) {

      assert(arpreq);
      time_t now;
      time(&now);
      int res;
      if (difftime(now, arpreq->sent) <= 1.0){

            return 0;
      }

      if (arpreq->times_sent >= 5){
      /* send icmp host unreachable to source addr of 
      all pkts waiting on this request type 3 code 1*/
            struct sr_packet *packet_walker = arpreq->packets;
            while (packet_walker){
                  res = send_icmp_message(sr, packet_walker->buf, 3,  1);
                  if (res == -1){

                        return -1;
                  }
            }
            sr_arpreq_destroy(&(sr->cache), arpreq);
      }
      int minlength = sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t);
      uint8_t arpbuf[minlength];
      memset(arpbuf, 0, minlength);
      struct sr_ethernet_hdr * eth_hdr = (struct sr_ethernet_hdr *) arpbuf;
      struct sr_arp_hdr * arp_hdr = (struct sr_arp_hdr *) (arpbuf + sizeof(sr_ethernet_hdr_t));

      /* make sure its an ARP ethernet packet */
      eth_hdr->ether_type = ntohs(ethertype_arp);

      /* make the dest address FF:FF:FF:FF:FF:FF */
      int i;
      for (i = 0; i < ETHER_ADDR_LEN; i++){
            eth_hdr->ether_dhost[i] = 0xff;
      }

      struct sr_rt* best_rt = find_best_rt(sr->routing_table, ntohl( arpreq->ip));

      if (!best_rt) {
      /* TODO: didn't find an interface, send an ICMP message type 3 
      code 0, also if there are any errors above */

            return 0;
      }
      struct sr_if* best_if = sr_get_interface(sr, best_rt->interface);

      /* set arp hdr params */
      arp_hdr->ar_hrd = ntohs(1);
      arp_hdr->ar_pro = ntohs(2048);
      arp_hdr->ar_hln = 6;
      arp_hdr->ar_pln = 4;
      arp_hdr->ar_op = ntohs(arp_op_request);

      /* set eth hdr source mac address */ 
      memcpy(eth_hdr->ether_shost, best_if->addr, ETHER_ADDR_LEN);

      /* set arp hdr source mac address */ 
      memcpy(arp_hdr->ar_sha, best_if->addr, ETHER_ADDR_LEN);

      /* set arp hdr dest mac address to  FF:FF:FF:FF:FF:FF */ 
      memcpy(arp_hdr->ar_tha, eth_hdr->ether_dhost, ETHER_ADDR_LEN);

      /* set appropriate IPs */
      arp_hdr->ar_sip = best_if->ip;
      arp_hdr->ar_tip = arpreq->ip;

      /* send packet using correct interface */
      res = 0; 

      
      res = sr_send_packet(sr, arpbuf, minlength,best_if->name );

      if (res != 0) {

            return -1;
      }

      arpreq->sent = now;
      arpreq->times_sent++;  
      return 0;

}
Exemple #3
0
int handle_ip_packet(struct sr_instance * sr, uint8_t * packet, unsigned int len ) {


      sr_ip_hdr_t *iphdr = (sr_ip_hdr_t *)(packet + sizeof(sr_ethernet_hdr_t));

      /* validate checksum. */
      uint16_t checksum;

      checksum = cksum(iphdr, sizeof(*iphdr));
      if (checksum != 0xffff) {

            return -1;
      } 


      
      uint8_t * newpacket_for_ip = (uint8_t *) malloc(len);
      memcpy(newpacket_for_ip, packet, len);
      sr_ip_hdr_t *new_iphdr = (sr_ip_hdr_t *)(newpacket_for_ip + sizeof(sr_ethernet_hdr_t));

      /* Decrement the TTL by 1, and recompute the packet 
      checksum over the modified header. */

      /* decrement ttl */
      new_iphdr->ip_ttl--;

      if (new_iphdr->ip_ttl <= 0) {
          /* check ttl, less than zero */
            send_icmp_message(sr,packet, 11, 0);
            return -1;
      }

      /* update checksum. */
      new_iphdr->ip_sum = 0;
      checksum = cksum(new_iphdr, sizeof(*new_iphdr));
      new_iphdr->ip_sum = checksum;
      checksum = cksum(new_iphdr, sizeof(*new_iphdr));

      struct sr_if* assoc_iface = validate_ip(sr->if_list, iphdr->ip_dst);
      if (assoc_iface) {
            /*it's destined to one of our IPs */
            /* ICMP */
            uint8_t ip_proto = ip_protocol(packet + sizeof(sr_ethernet_hdr_t));
            if (ip_proto == ip_protocol_icmp) { 

                
                  int minlength = sizeof(sr_icmp_hdr_t) + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t);
                  if (len < minlength){
                  
                        return -1;
                  }

                  struct sr_icmp_hdr * icmp_hdr =  (struct sr_icmp_hdr *) (packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t));

                  if(icmp_hdr->icmp_type == 8){
                        /* is an echo request */

                        int res;
                        res = make_echo_request(&newpacket_for_ip, len);

                        if (res == -1){
                              
                              return -1;
                        }
                  }
                  /* end ICMP */
            } else {
                  /* got a udp payload to a rounter interface */
                  int res;
                  res = send_icmp_message(sr, packet, 3,  3);
                  if (res == -1){
                        
                        return -1;
                  }
            }
      }


      /* Find out which entry in the routing table has 
      the longest prefix match with the 
      destination IP address. */
      struct sr_rt* best_rt = find_best_rt(sr->routing_table,  ntohl(new_iphdr->ip_dst));         
      if (!best_rt) {
            /* didn't find an interface, send an ICMP message type 3 
            code 0, also if there are any errors above */
            int res = send_icmp_message(sr, packet, 3,  0);
            if (res == -1){
                 
                  return -1;
            }
            
            return 0;
      }

      /* found an interface */

      struct sr_if * best_iface = sr_get_interface(sr, best_rt->interface);
      if (!best_iface){
           
            return -1;
      }
      struct sr_arpentry * forward_arp_entry = sr_arpcache_lookup(&(sr->cache), best_rt->gw.s_addr);
      
      struct sr_ethernet_hdr * new_ether_hdr = (struct sr_ethernet_hdr * ) newpacket_for_ip; 

      /* ethernet -- update the source address */
      memcpy(new_ether_hdr->ether_shost, best_iface->addr,  ETHER_ADDR_LEN);

      if (forward_arp_entry) {
            /* we have a MAC address */
           

            /* update packet */
            /* ethernet -- set the dest address */
            memcpy(new_ether_hdr->ether_dhost, forward_arp_entry->mac, ETHER_ADDR_LEN);

            /* send packet using correct interface */
            int res = 0; 

            
            res = sr_send_packet(sr, newpacket_for_ip, len, best_rt->interface);

            if (res != 0) {
                 
                  return -1;
            }

            free(forward_arp_entry);
      } else {
            /* we dont have a MAC address, add to arp queue */
            
            struct sr_arpreq * arpreq;
            arpreq = sr_arpcache_queuereq(&(sr->cache), best_rt->gw.s_addr, newpacket_for_ip, 
                  len, best_rt->interface );
            if (!arpreq){
                 
                  return -1;
            }
            uint32_t ip, dest;
           
            ip = ntohl(best_iface->ip);

            dest = ntohl(best_rt->dest.s_addr);
            sr_handle_arp_req(sr, arpreq); 
      } 
      return 0;      
}