Пример #1
0
void sr_handleARPpacket(struct sr_instance *sr, uint8_t* packet, unsigned int len, struct sr_if * iface) {
    assert(packet);
    sr_ethernet_hdr_t* ethHeader = (sr_ethernet_hdr_t*) packet;
    sr_arp_hdr_t * arpHeader = (sr_arp_hdr_t *) (packet+14);

    enum sr_arp_opcode request = arp_op_request;
    enum sr_arp_opcode reply = arp_op_reply;

    struct sr_if *interface = sr_get_interface_from_ip(sr, htonl(arpHeader->ar_tip));

    /* handle an arp request.*/
    if (ntohs(arpHeader->ar_op) == request) {
        /* found an ip->mac mapping. send a reply to the requester's MAC addr */
        if (interface){
          arpHeader->ar_op = ntohs(reply);
          uint32_t temp = arpHeader->ar_sip;
          arpHeader->ar_sip = arpHeader->ar_tip;
          arpHeader->ar_tip = temp;
          memcpy(arpHeader->ar_tha, arpHeader->ar_sha,6);
          memcpy(arpHeader->ar_sha, iface->addr,6);

          /*swapping outgoing and incoming addr*/
          set_addr(ethHeader, iface->addr, ethHeader->ether_shost);
          sr_send_packet(sr,(uint8_t*)ethHeader,len,iface->name);
        }
    }
    /* handle an arp reply */
    else {
      struct sr_packet *req_packet = NULL;
      struct sr_arpreq *req = NULL;
      pthread_mutex_lock(&(sr->cache.lock));   
      
      for (req = sr->cache.requests; req != NULL; req = req->next){
        if(req->ip == arpHeader->ar_sip){
          /* find the interface the packets should be sent out of */
          struct sr_rt * rt = (struct sr_rt *)sr_find_routing_entry_int(sr, req->ip);
          if (rt) {
            iface = sr_get_interface(sr, rt->interface);
            /* send all packets waiting on the request that was replied to */
            for (req_packet = req->packets; req_packet != NULL; req_packet = req_packet->next) {
              sr_ethernet_hdr_t * outEther = (sr_ethernet_hdr_t *)req_packet->buf;
              memcpy(outEther->ether_shost, iface->addr,6);
              memcpy(outEther->ether_dhost, ethHeader->ether_shost,6);

              sr_ip_hdr_t * outIP = (sr_ip_hdr_t *)(req_packet->buf+14);
              outIP->ip_ttl = outIP->ip_ttl-1;
              outIP->ip_sum = 0;
              outIP->ip_sum = cksum((uint8_t *)outIP,20);
              
              sr_send_packet(sr,req_packet->buf,req_packet->len,iface->name);
            }
            sr_arpreq_destroy(&(sr->cache), req);
          }
          break;
        }
      }
      pthread_mutex_unlock(&(sr->cache.lock));
      sr_arpcache_insert(&(sr->cache),arpHeader->ar_sha,arpHeader->ar_sip);
    }
}
Пример #2
0
void handle_arp_reply(struct sr_instance *sr, uint8_t* ethernet_data_addr, struct sr_if* in_f){
  printf("in handle arp reply\n");

/*
  The ARP reply processing code should move entries from the ARP request
   queue to the ARP cache:

   # When servicing an arp reply that gives us an IP->MAC mapping
   req = arpcache_insert(ip, mac)

   if req:
       send all packets on the req->packets linked list
       arpreq_destroy(req)
*/

  /*Loop through sr_cache requests and look for an IP match to the ARP header source IP*/

  sr_arp_hdr_t *arp_header = (sr_arp_hdr_t *) ethernet_data_addr;

  struct sr_arpreq *req_ptr = sr_arpcache_insert(&(sr->cache), arp_header->ar_sha, arp_header->ar_sip);

  /*If the IP in the reply matched something in our request queue*/
  if (req_ptr) {
    struct sr_packet *req_pkts = req_ptr->packets;
    struct sr_packet *req_pkt_ptr = req_pkts;

    for (; req_pkt_ptr; req_pkt_ptr = req_pkt_ptr->next) {

      sr_ethernet_hdr_t *packet_eth_hdr = (sr_ethernet_hdr_t *) req_pkts->buf;
      sr_ip_hdr_t *packet_ip_hdr = (sr_ip_hdr_t *) (req_pkts->buf + sizeof(sr_ethernet_hdr_t));

      /*ret_if will be populated if this was originally an echo request, else 0*/
      struct sr_if* ret_if = sr_get_interface_from_ip(sr, packet_ip_hdr->ip_dst);
      
      if (ret_if) {
        /*Doesn't have a code so just passing 0 as code*/
        send_icmp_echo_reply(sr, (uint8_t *) packet_eth_hdr, req_pkt_ptr->len, in_f, arp_header->ar_sha, echo_reply_type, 0);
      }
      
      else {
        memcpy(packet_eth_hdr->ether_dhost, arp_header->ar_sha, ETHER_ADDR_LEN);
        sr_send_packet(sr, (uint8_t *) packet_eth_hdr, req_pkt_ptr->len, in_f->name);
      } 
    }
    sr_arpreq_destroy(&(sr->cache), req_ptr);
  }
  /*Otherwise do nothing, the reply wasn't about anything in our queue*/
}
Пример #3
0
/*Returns 0 on success and error code on fail*/
int sr_handlearp(struct sr_instance** sr, uint8_t** ethernet_data_addr, struct sr_if* in_f, unsigned int len){
  uint8_t *eth_pkt_buf;
  uint8_t *arp_pkt_buf; /* ARP packet buffer */
  struct sr_if* ret_if; /* return interface */
  printf("sr_handlearp");

  sr_arp_hdr_t* arp_header_buffer = (sr_arp_hdr_t*)*ethernet_data_addr;
  ntoh_arp_hdr(&arp_header_buffer); /* converts header members into host byte order where appropriate */

  /* Recieved ARP request! Reply to request. */
  if(arp_header_buffer->ar_op == arp_op_request) {
    if ((ret_if = sr_get_interface_from_ip(*sr, arp_header_buffer->ar_tip))) { /* Target IP is IP of a Router Interface*/ 
      
      /* Send an ARP reply (uint8_t*) */

      /* Create reply frame */
      eth_pkt_buf = (uint8_t *) malloc(sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t)); /* Allocate mem for reply packet buffer */
      sr_ethernet_hdr_t *req_reply_eth_header = (sr_ethernet_hdr_t *) eth_pkt_buf;

      /* Build Ethernet Header */
      memcpy(req_reply_eth_header->ether_dhost, arp_header_buffer->ar_sha, ETHER_ADDR_LEN);
      memcpy(req_reply_eth_header->ether_shost, in_f->addr, ETHER_ADDR_LEN);
      req_reply_eth_header->ether_type = ethertype_arp;
      /* Convert to network byte ordering */
      hton_eth_hdr(&req_reply_eth_header);

      /* Get the Arp Buffer and Build the Arp packet*/
      arp_pkt_buf = eth_pkt_buf + sizeof(sr_ethernet_hdr_t);
      sr_create_arp_packet(&arp_pkt_buf, arp_header_buffer, ret_if); /* Create arp packet to be sent as ARP reply, fill arp_pkt_buf with ARP reply header data */
      
      /* Send the ARP reply packet */
      sr_send_packet(*sr, eth_pkt_buf, sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t), in_f->name);
      free(eth_pkt_buf);


    } else { /* Target IP is *NOT* IP of a Router Interface */
      /* I'm not sure what to do here yet MAYBE NOTHING?!*/
    }
  }

  else if (arp_header_buffer->ar_op == arp_op_reply) {
    handle_arp_reply(*sr, *ethernet_data_addr, in_f);
  }
  


  return 0;
}
Пример #4
0
void sr_handle_ip(struct sr_instance *sr, uint8_t *packet, unsigned int len, struct sr_if *iface)
{
    assert(sr);
    assert(packet);
    assert(iface);
    
    
    if (len < sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t)) {
        fprintf(stderr, "Failed to process IP header, insufficient length\n");
        return;
    }
    
    sr_ip_hdr_t *ip_hdr = (sr_ip_hdr_t *)(packet + sizeof(sr_ethernet_hdr_t));
    
    
    if (len < sizeof(sr_ethernet_hdr_t) + (ip_hdr->ip_hl * 4)) {
        fprintf(stderr, "Failed to process IP header, insufficient length\n");
        return;
    }
    
    /* verify checksum */
    uint16_t received_cksum = ip_hdr->ip_sum;
    ip_hdr->ip_sum = 0;
    
    uint16_t computed_cksum = cksum(ip_hdr, ip_hdr->ip_hl * 4);
    ip_hdr->ip_sum = received_cksum;
    
    if (received_cksum != computed_cksum) {
        fprintf(stderr, "Failed to process IP header, incorrect checksum\n");
        return;
    }
     
    struct sr_if *diface = sr_get_interface_from_ip(sr, ip_hdr->ip_dst);
    
    if (!diface) {
        sr_forward_ip(sr, packet, len);
    } else {
        if (ip_hdr->ip_p == ip_protocol_icmp) {
            sr_handle_icmp(sr, packet, len);
        } else if (ip_hdr->ip_p == 0x0006 || ip_hdr->ip_p == 0x0011) {
            sr_send_icmp(sr, packet, len, 3, 3);
        }
    }
}
Пример #5
0
void sr_natHandleIP(struct sr_instance* sr, uint8_t* packet,unsigned int len, struct sr_if * iface){
  assert(packet);
  sr_ethernet_hdr_t* ethHeader = (sr_ethernet_hdr_t*) packet;
  uint8_t* ip_packet = packet+sizeof(sr_ethernet_hdr_t);
  sr_ip_hdr_t * ipHeader = (sr_ip_hdr_t *) (ip_packet);  

  uint16_t incm_cksum = ipHeader->ip_sum;
  ipHeader->ip_sum = 0;
  uint16_t currentChecksum = cksum(ip_packet,20);
  ipHeader->ip_sum = incm_cksum;
  uint8_t* icmp_packet;

  /* if the destination address is one of my interfaces */
  if (currentChecksum==incm_cksum && sr_get_interface_from_ip(sr,ntohl(ipHeader->ip_dst)) != NULL){
    /* check cache for ip->mac mapping for next hop */
    /*struct sr_arpentry *entry;
    entry = sr_arpcache_lookup(&sr->cache, ipHeader->ip_dst);
    struct sr_rt * rt = (struct sr_rt *)sr_find_routing_entry_int(sr, ipHeader->ip_dst);
*/
    /* found next hop. send packet */
    if (ipHeader->ip_ttl <= 1){   /* IP TTL died. send ICMP type 11, code 0 */
      icmp_packet = createICMP(11, 0, ip_packet,len-14);
      memcpy(ip_packet+20,icmp_packet,sizeof(sr_icmp_t3_hdr_t));
      ipHeader->ip_p = 1;
      ipHeader->ip_len = htons(20+8+(len-34<28?len-34:28));
      free(icmp_packet);      
    } else if(ipHeader->ip_p==6){  /* IP TCP */
      icmp_packet = createICMP(3,3,ip_packet,len-14);
      memcpy(ip_packet+20,icmp_packet,sizeof(sr_icmp_t3_hdr_t));
      
      ipHeader->ip_p = 1;
      ipHeader->ip_len = htons(20+8+(len-34<28?len-34:28));
      free(icmp_packet);
    }else if(ipHeader->ip_tos==0 && ipHeader->ip_p==1){ /* IP ping */
	    sr_icmp_hdr_t * icmp_header = (sr_icmp_hdr_t *) (packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t));
      incm_cksum = icmp_header->icmp_sum;
      icmp_header->icmp_sum = 0;
	    currentChecksum = cksum(icmp_header,len - sizeof(sr_ethernet_hdr_t) - sizeof(sr_ip_hdr_t));
	    
      if(currentChecksum == incm_cksum && icmp_header->icmp_type == 8 && icmp_header->icmp_code == 0) {
	      icmp_header->icmp_type = 0;
        ipHeader->ip_sum = 0;
	      icmp_header->icmp_sum = cksum(icmp_header,len - sizeof(sr_ethernet_hdr_t) - sizeof(sr_ip_hdr_t));
	    }
      else{
        printf("ICMP INVALID\n");
        printf("%d != %d OR %d != %d\n",currentChecksum,incm_cksum, icmp_header->icmp_type, 8);
      }
    } else {
      printf("IP Bad\n");
      ip_packet = NULL;
    }
  }
  else{
      printf("IP INVALID\n");
      ip_packet = NULL;
  }
  if(ip_packet){  /* send ICMP packet */
    ipHeader->ip_dst = ipHeader->ip_src;
    ipHeader->ip_src = iface->ip;
    ipHeader->ip_ttl = 64;
    ipHeader->ip_sum = 0;
    ipHeader->ip_sum = cksum(ip_packet,20);

    struct sr_arpentry *entry;
    entry = sr_arpcache_lookup(&sr->cache, ipHeader->ip_dst);
    struct sr_rt * rt = (struct sr_rt *)sr_find_routing_entry_int(sr, ipHeader->ip_dst);

    if (entry && rt) {    /* found next hop. send packet */
      iface = sr_get_interface(sr, rt->interface);
      set_addr(ethHeader, iface->addr, entry->mac);
      sr_send_packet(sr,packet,len,iface->name);
      free(entry);
      ip_packet = NULL;
    } else if (rt) { /* send an arp request to find out what the next hop should be */
      struct sr_arpreq *req;
      sr_arpcache_insert(&(sr->cache), ethHeader->ether_shost, ipHeader->ip_src);
      req = sr_arpcache_queuereq(&(sr->cache), ipHeader->ip_dst, packet, len, iface->name);
      /*handle_arpreq(sr, req);*/
      ip_packet = NULL;
    }
  }
}
Пример #6
0
/*Returns 0 on success and error code on fail*/
int sr_handleip(struct sr_instance* sr, 
                uint8_t* packet,
                unsigned int len, 
                struct sr_if* in_f, 
                uint8_t** ethernet_data_addr){
  sr_ip_hdr_t* ip_header_buffer = (sr_ip_hdr_t*) *ethernet_data_addr;

  /* Get headers from packet */
  /*sr_ethernet_hdr_t* eth_hdr = (sr_ethernet_hdr_t*) packet;
  uint8_t * ip_pkt_buf = packet + sizeof(sr_ethernet_hdr_t);
  sr_ip_hdr_t* ip_hdr = (sr_ip_hdr_t*) (packet + sizeof(sr_ethernet_hdr_t)); */
  uint8_t * icmp_pkt_buf = packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t);
  sr_icmp_hdr_t* icmp_hdr = (sr_icmp_hdr_t*) icmp_pkt_buf;
  struct sr_if* ret_if; /* return interface */

  if (check_ip_sum(ip_header_buffer) == 0) { /*Pass Checksum*/
    printf("Checksum Pass\n");
  }
  else { /*Fail Checksum*/
    printf("Checksum Fail\n");
    return -1;
  }

  /*If the TTL went to 0*/
  if (decrement_ttl(ip_header_buffer) == -1) {
    /*Send ICMP with the proper TTL decrease type and icmp code*/
    printf("TTL reached 0\n"); 
    send_icmp(sr, packet, len, in_f, time_exceed_type, time_exceed_code);
    return -1;
  }

  /*Check if the IP packet is for us and not a echo request*/
  ret_if = sr_get_interface_from_ip(sr, ip_header_buffer->ip_dst);
  if(ret_if &&  !(ip_header_buffer->ip_p == ip_protocol_icmp && 
      icmp_hdr->icmp_type == echo_req_type && icmp_hdr->icmp_code == echo_req_code)) {
    /* The IP packet is FOR US */    
    printf("FOR US, NOT ECHO REQ");

    /* Check if it is an echo request */
    if (ip_header_buffer->ip_p == ip_protocol_tcp || 
               ip_header_buffer->ip_p == ip_protocol_udp) {
      /* It is TCP/UDP send ICMP port unreachable 
         SEND: an ICMP port unreachable to sending host*/
      send_icmp(sr, packet, len, in_f, port_unreach_type, port_unreach_code);
    } else {
      ;
      /* According to the Assignment: IGNORE THE PACKET*/
    }

  } else {
    
    /*If it's not in the routing table, send ICMP net unreachable*/
    struct sr_rt * routing_node;

    uint32_t ip_dest;

    /*If it's for us, we want to send back to the source, so check for the source in the routing table*/
    if (ret_if) {
      /* The IP packet is FOR US */
      printf("FOR US\n");
      ip_dest = ip_header_buffer->ip_src;
    }
    /*If not for us, we want to keep forwarding to the destination so check for that in the routing table*/
    else {
      /* The IP packet is NOT FOR US */
      printf("NOT FOR US\n");
      ip_dest = ip_header_buffer->ip_dst;
    }

    if ((routing_node = check_routing_table(sr, ip_dest)) == NULL) { 
      printf("NOT in routing table\n");
      send_icmp(sr, packet, len, in_f, dest_net_unreach_type, dest_net_unreach_code);
    }
    else {
      printf("In routing table\n");
      /*Got the routing table node in routing_node */

      /*Next hop IP address is in gateway
       *Look it up in arpcache_lookup to see if we know the MAC address
      */
      uint32_t nexthopIP = routing_node->gw.s_addr;
      struct sr_arpentry *arp_dest = sr_arpcache_lookup(&(sr->cache), nexthopIP);
      struct sr_if* nexthopInterface = sr_get_interface(sr, routing_node->interface);


      /*Create an ethernet header in front of the packet to forward regardless of
        whether or not we've found the next hop IP: need it in both cases*/

      /*Allocate space for ethernet header and packet, copy in contents of packet*/
      uint8_t* eth_header_packet = malloc(len);

      uint8_t* ip_header = eth_header_packet + sizeof(sr_ethernet_hdr_t);

      uint8_t* only_packet = eth_header_packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t);

      memcpy(ip_header, ip_header_buffer, sizeof(sr_ip_hdr_t));

      memcpy(only_packet, (packet+sizeof(sr_ethernet_hdr_t)+sizeof(sr_ip_hdr_t)), len-sizeof(sr_ethernet_hdr_t)-sizeof(sr_ip_hdr_t));

      /*Save it in struct form*/
      sr_ethernet_hdr_t* packet_to_forward = (sr_ethernet_hdr_t*)eth_header_packet;

      /*Now set the actual ethernet header for the packet*/
      packet_to_forward->ether_type = htons(ethertype_ip);
      memcpy(packet_to_forward->ether_shost, nexthopInterface->addr, ETHER_ADDR_LEN);




      /*If NULL, send out the arp request*/
      if(arp_dest == NULL){
        printf("Not in arp cache: need to send an ARP request!\n");
        broadcast_arp_req(sr, nexthopIP, packet_to_forward, len, routing_node, nexthopInterface);

      }

      /*Otherwise just forward the packet to arp_dest's MAC address*/
      else {

        /*It's for us, it must be an echo request*/
        if (ret_if) {
          /*Doesn't have a code so just passing 0 as code*/
          struct sr_if *interface = sr_get_interface(sr, routing_node->interface);
          send_icmp_echo_reply(sr, packet, len, interface, arp_dest->mac, echo_reply_type, 0);
        }
        else {

          printf("In arp cache: just forwarding the packet\n");

          memcpy(packet_to_forward->ether_dhost, arp_dest->mac, ETHER_ADDR_LEN);
          sr_send_packet(sr, (uint8_t*)packet_to_forward, len, routing_node->interface);
          
          /*Free the arp_dest that sr_arpcache_lookup created*/
          free(arp_dest);
        }
      }


    }

  }

  return 0;
}
Пример #7
0
void sr_handle_arp(struct sr_instance *sr, uint8_t *packet, unsigned int len, struct sr_if *iface)
{
    assert(sr);
    assert(packet);
    assert(iface);
    
    /* check length */
    if (len < sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t)) {
        fprintf(stderr, "Failed to process ARP header, insufficient length\n");
        return;
    }
    
    sr_arp_hdr_t *arp_hdr = (sr_arp_hdr_t *)(packet + sizeof(sr_ethernet_hdr_t));
    /* print_hdr_arp((uint8_t *)arp_hdr); */
    
    /* check hardware type */
    if (ntohs(arp_hdr->ar_hrd) != arp_hrd_ethernet) {
        return;
    }
    
    /* check protocol */
    if (ntohs(arp_hdr->ar_pro) != ethertype_ip) {
        return;
    }
    
    /* is it for me? */
    struct sr_if *tiface = sr_get_interface_from_ip(sr, arp_hdr->ar_tip);
    
    if (!tiface) {
        return;
    }
    
    unsigned short arp_op = ntohs(arp_hdr->ar_op);
    
    if (arp_op == arp_op_request) {
        sr_send_arp_reply(sr, packet, iface, tiface);
    } else if (arp_op == arp_op_reply) {
        struct sr_arpreq *req = sr_arpcache_insert(&(sr->cache), arp_hdr->ar_sha, arp_hdr->ar_sip);
        
        if (req) {
            struct sr_packet *pkt = NULL;
            struct sr_if *oiface = NULL;
            sr_ethernet_hdr_t *eth_hdr = NULL;
            
            pkt = req->packets;
            
            while (pkt) {
                oiface = sr_get_interface(sr, pkt->iface);
                
                eth_hdr = (sr_ethernet_hdr_t *)(pkt->buf);
                
                memcpy(eth_hdr->ether_dhost, arp_hdr->ar_sha, ETHER_ADDR_LEN);
                memcpy(eth_hdr->ether_shost, oiface->addr, ETHER_ADDR_LEN);
                
                sr_send_packet(sr, pkt->buf, pkt->len, pkt->iface);
                
                pkt = pkt->next;
            }
            
            sr_arpreq_destroy(&(sr->cache), req);
        }
    }
} /* -- sr_handle_arp -- */