コード例 #1
0
ファイル: sr_rt.c プロジェクト: radialglo/potential-cyril
struct sr_rt* sr_get_rt_entry(struct sr_instance *sr, uint32_t dest_ip) {

    /*
      note that in_addr_t s_addr
      is equivalent to uint32_t
    */
    sr_rt_t* entry =  sr->routing_table;
    sr_rt_t* best_match = NULL;
    while (entry != NULL) {

        /*
           make sure that the CIDR or network id matches the network id of the entry
           In other words make sure both ip addresses belog to same subnet
           finally choose the greatest netmask, which produces the longest prefix match
         */
        if((dest_ip & entry->mask.s_addr) == (entry->dest.s_addr & entry->mask.s_addr)) {

            /*
              print_addr_ip_int(entry->dest.s_addr);
              print_addr_ip_int(dest_ip);
            */
            if(best_match == NULL) {
                best_match = entry;
            } else {
                /*
                  since the the dest_ip may fall under multiple subnets choose
                  the one with the largest mask which produces the longest prefix match
                */
                if(entry->mask.s_addr > best_match->mask.s_addr) {
                    best_match = entry;
                }
            }
        }

        entry = entry->next;
    }


    if (best_match != NULL) {
        fprintf(stderr,"\n\n/* ---- Router Entry Lookup-----*/");
        fprintf(stderr,"INTERFACE: %s\n",best_match->interface);
        fprintf(stderr,"DESTINATION:\n");
        print_addr_ip_int(dest_ip);
        printf("GATEWAY:\n");
        print_addr_ip_int(best_match->gw.s_addr);
        fprintf(stderr,"MASK:\n");
        print_addr_ip_int(best_match->mask.s_addr);
        fprintf(stderr,"/* ---- End Router Lookup-----*/\n\n");
    }

    return best_match;
}
コード例 #2
0
ファイル: sr_arpcache.c プロジェクト: rmacqueen/router
/* Tries to find ip address in arp cache. If found, sends ethernet frame. If not found,
adds packet to arp queue */
void sr_attempt_send(struct sr_instance *sr, uint32_t ip_dest, 
                                        uint8_t *frame,           
                                       unsigned int frame_len,
                                       char *iface){


   struct sr_arpentry *entry = sr_arpcache_lookup(&(sr->cache), ip_dest);

   if (entry){

        unsigned char *mac_address = entry->mac;
        memcpy( ((sr_ethernet_hdr_t *)frame)->ether_dhost, mac_address, ETHER_ADDR_LEN);
        //free packet??
        sr_send_packet(sr, frame, frame_len, iface);

        free(entry);


   }else{
        fprintf(stderr, "Couldn't find entry for: ");
        print_addr_ip_int(ntohl(ip_dest));

       struct sr_arpreq *req = sr_arpcache_queuereq(&(sr->cache), ip_dest, frame, frame_len, iface);
       sr_handle_arpreq(sr, req);
   }
}
コード例 #3
0
ファイル: unit.c プロジェクト: popacai/TRouter
int main()
{
    uint32_t ip1;
    uint32_t ip2;
    uint32_t mask;

    unsigned char* p;
    int i;
    p = &ip1;
    for (i = 0; i < 4; i++)
    {
        *(p++) = i;
    }

    p = &ip2;
    for (i = 0; i < 4; i++)
    {
        *(p++) = i;
    }


    p = &mask;
    p++;
    *(p++) = 128;
    for (i = 2; i < 4; i++)
    {
        *(p++) = 255;
    }


    print_addr_ip_int(ip1 & mask);
    print_addr_ip_int(ip2 & mask);
    print_addr_ip_int(mask);


    printf("%d\n", prefix_match(ip1, ip2, mask));
    return 0;
}
コード例 #4
0
ファイル: sr_arpcache.c プロジェクト: rmacqueen/router
void sr_print_queue(struct sr_arpcache *cache){
    fprintf(stderr, "------------------printing ARP Queue------------------\n");
    struct sr_arpreq *request = cache->requests;
    while(request){
        print_addr_ip_int(ntohl(request->ip));
        struct sr_packet *packet = request->packets;
        while(packet){
            fprintf(stderr, "len: %u \t outgoing interface: %s\n", packet->len, packet->iface);
            packet = packet->next;
        }
        fprintf(stderr, "\n");
        request = request->next;
    }
}
コード例 #5
0
ファイル: sr_ip.c プロジェクト: Josh-Dykstra/CS118-Router
void sr_handle_ip(struct sr_instance* sr, uint8_t* packet,
                  unsigned int len, char* iface)
{
  struct sr_if* interface = sr_get_interface(sr, iface);
  struct sr_ip_hdr* ipHeader = (struct sr_ip_hdr*)(packet + sizeof(sr_ethernet_hdr_t));

  /* Verify the checksum */
  uint16_t check = cksum(ipHeader, sizeof(sr_ip_hdr_t));
  if(check != 0xFFFF)
  {
    printf("Packet Corrupted!\n");  
    return;
  }

  /* Check destination */
  if(ipHeader->ip_dst == interface->ip)
  {
    /* Check protocol */
    if(ipHeader->ip_p == ip_protocol_icmp)
    {
      /* Process ICMP message */
      struct sr_icmp_hdr* icmpHeader = (struct sr_icmp_hdr*)(packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t));
      if(icmpHeader->icmp_type == icmp_type_echorequest)
      {
        printf("Echo Request...\n");  
        sr_send_icmp(sr, packet, len, icmp_type_echoreply, 0);
      }
    }
    else
    {
      /* Send port unreachable ICMP message  */
      printf("Port Unreachable\n");  
      sr_send_icmp(sr, packet, len, icmp_type_destunreachable, icmp_code_portunreachable);
    }

  }
  else
  {
    printf("Processing Packet for forwarding...\n");
    /* Forward the packet accordingly */
    /* Decrement TTL */
    ipHeader->ip_ttl = ipHeader->ip_ttl-1;

    if(ipHeader->ip_ttl == 0)
    {
      /* Send ICMP time exceeded */
      printf("TTL expired! Returning ICMP timeexceeded\n");
      sr_send_icmp(sr, packet, len, icmp_type_timeexceeded, 0);
      return;
    }

    /* Check if the destination is in our routing table */
    char * iface = sr_get_routing_entry_interface(sr, ipHeader->ip_dst);
    if(iface == NULL)
    {
      /* Send a network unreachable message */
      printf("No route! Returning ICMP netUnreachable\n");
      sr_send_icmp(sr, packet, len, icmp_type_destunreachable, icmp_code_netunreachable);
      return;
    }

    /* Recalculate the  checksum */
    ipHeader->ip_sum = 0x0000;
    ipHeader->ip_sum = cksum(ipHeader, sizeof(sr_ip_hdr_t));

    /* Look up in the ARP table */
    struct sr_arpentry * arpCacheEntry = sr_arpcache_lookup(&(sr->cache), ipHeader->ip_dst);

    /* At this point we know we're going to send it, so make a copy */
    uint8_t* copy = (uint8_t*)malloc(len);
    memcpy(copy, packet, len);
    struct sr_ip_hdr* copyIPHeader = (struct sr_ip_hdr*)(copy + sizeof(sr_ethernet_hdr_t));

    /* See if there was an entry */
    if(arpCacheEntry == NULL)
    {
      /* No entry, so queue up for ARP request */
      printf("ARP MISS!\n");
      sr_arpcache_queuereq(&(sr->cache), copyIPHeader->ip_dst, copy, len, iface);
      printf("Added ARP req for ");
      print_addr_ip_int(htonl(copyIPHeader->ip_dst));
      printf(" to queue\n");
      return;
    }
    printf("ARP HIT!\n");
    /* Forward the IP message using the ARP Cache info */
    sr_send_ip(sr, copy, len, iface);

    free(arpCacheEntry);

  }
}/* -- sr_handle_ip -- */
コード例 #6
0
void process_ether_type_arp(struct sr_instance* sr,
        uint8_t * packet/* lent */,
        unsigned int len,
        char* iface/* lent */)
{
/* Router receives an ARP packet  */
  assert(sr);
  assert(packet);
  assert(iface);

  printf("ARP Packet Received...\n");
  /* Create ARP Header and find interface */
  sr_arp_hdr_t* arp_header = (sr_arp_hdr_t*)(packet + sizeof(sr_ethernet_hdr_t));
  fprintf(stderr, "\tsender hardware address: ");
  print_addr_eth(arp_header->ar_sha);
  fprintf(stderr, "\tsender ip address: ");
  print_addr_ip_int(ntohl(arp_header->ar_sip));
  fprintf(stderr, "\ttarget hardware address: ");
  print_addr_eth(arp_header->ar_tha);
  fprintf(stderr, "\ttarget ip address: ");
  print_addr_ip_int(ntohl(arp_header->ar_tip));

  struct sr_if* interface = NULL;
  struct sr_if* interface_list_iterator = sr->if_list;

  while (interface_list_iterator!=NULL) 
  {
    if (arp_header->ar_tip == interface_list_iterator->ip) 
        interface = interface_list_iterator;
    interface_list_iterator = interface_list_iterator->next;
  }

  unsigned short op_code = ntohs(arp_header->ar_op);

  /* If ARP req/response is meant for router the process else drop/forward */
  /* The following code gets executed when you first PING to a router's interface
    and the client does not know the router's MAC */

  if (interface!=0)
  {
    if (op_code == 0x0001) 
    { 
      printf("ARP Request for Router detected...\n");

      sr_ethernet_hdr_t* ethernet_hdr = (sr_ethernet_hdr_t*)(packet);
      memcpy(arp_header->ar_tha, arp_header->ar_sha, 6);
      memcpy(arp_header->ar_sha, interface->addr, 6);
      memcpy(ethernet_hdr->ether_dhost, arp_header->ar_tha, 6);
      memcpy(ethernet_hdr->ether_shost, arp_header->ar_sha, 6);
      arp_header->ar_tip = arp_header->ar_sip;
      arp_header->ar_sip = interface->ip;
      arp_header->ar_op = htons(0x0002);

      printf("Router sent ARP Reply...\n");
      sr_send_packet(sr, packet, len, iface);
    }

    if (op_code == 0x0002) 
    {
      printf("Router received ARP Reply...\n");

      /* See if there's an ARP request in the queue. */
      struct sr_arpreq* req = sr_arpcache_insert(&(sr->cache), arp_header->ar_sha, arp_header->ar_sip);

      struct sr_packet* pckt = NULL;
      if (req!=NULL)
      {
        pckt = req->packets;
      }  
      else
      {  
        pckt = NULL;
      }  

      while (pckt != NULL) 
      {
        printf("Forwarding all packets waiting for this Reply...\n");
        sr_ethernet_hdr_t* ethernet_hdr = (sr_ethernet_hdr_t *)(pckt->buf);
        struct sr_if* sending_interface = sr_get_interface(sr, pckt->iface);
        memcpy(ethernet_hdr->ether_dhost, arp_header->ar_sha, 6);
        memcpy(ethernet_hdr->ether_shost, sending_interface->addr, 6);
        sr_send_packet(sr, pckt->buf, pckt->len, pckt->iface);
        pckt = pckt->next;
      }
    } 
  }
}
コード例 #7
0
void process_ether_type_ip(struct sr_instance* sr,
        uint8_t * packet/* lent */,
        unsigned int len,
        char* interface/* lent */)
{
  assert(sr);
  assert(packet);
  assert(interface);

  /* Create IP header struct for further processing */
  sr_ip_hdr_t *ip_header = (sr_ip_hdr_t *)(packet + sizeof(sr_ethernet_hdr_t));
  sr_ethernet_hdr_t *eth_header = (sr_ethernet_hdr_t *)(packet);

  printf("IP Packet Received...\n");
  fprintf(stderr, "\tsource IP: ");
  print_addr_ip_int(ntohl(ip_header->ip_src));
  fprintf(stderr, "\tsource MAC: ");
  print_addr_eth(eth_header->ether_shost);
  fprintf(stderr, "\tdestination IP: ");
  print_addr_ip_int(ntohl(ip_header->ip_dst));
  fprintf(stderr, "\tdestination MAC: ");
  print_addr_eth(eth_header->ether_dhost);

  /* Decrement TTL and recompute checksum */
  ip_header->ip_sum = 0;
  ip_header->ip_sum = cksum((const void*)ip_header, sizeof(sr_ip_hdr_t));  

  struct sr_if* pkt_interface = 0;
  struct sr_if* interface_list_iterator = sr->if_list;

  /* If destination address belongs to Router's if_list */
  while (interface_list_iterator!=NULL) 
  {
    if (ip_header->ip_dst == interface_list_iterator->ip) 
        pkt_interface = interface_list_iterator;
    interface_list_iterator = interface_list_iterator->next;
  }

  /* IP packet destined for router's interface - NO GO */
  /* Processing only for ICMP echo request-reply otherwise no go */
  
  if (pkt_interface!=0) /* Interface record exists */
  { 
    printf("IP Packet meant for Router...\n");
    if (ip_header->ip_p == ip_protocol_icmp) /* echo req/reply */
    {
      printf("IP Packet contains ICMP...\n");
      sr_icmp_hdr_t* icmp_header = (sr_icmp_hdr_t *)(packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t));
      if (icmp_header->icmp_type == 8) /* PING */
      {
          printf("ICMP Echo request to Router...\n");

          uint8_t* send_packet = (uint8_t *)malloc(len);
          /* Same content as packet */
          memcpy(send_packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t), packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t),len - sizeof(sr_ethernet_hdr_t) - sizeof(sr_ip_hdr_t));
          /* ICMP header */
          sr_icmp_hdr_t* new_icmp = (sr_icmp_hdr_t *)(send_packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t));
          new_icmp->icmp_type = 0;
          new_icmp->icmp_code = 0;
          new_icmp->icmp_sum = cksum(send_packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t), len - sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t));
          /* Ethernet header */
          sr_ethernet_hdr_t *new_ethhdr = (sr_ethernet_hdr_t *) send_packet;
          new_ethhdr->ether_type = ntohs(0x0800);
          /* IP header */
          sr_ip_hdr_t *new_iphdr = (sr_ip_hdr_t *)(send_packet + sizeof(sr_ethernet_hdr_t));
          new_iphdr->ip_len = ntohs(len - sizeof(sr_ethernet_hdr_t));
          new_iphdr->ip_ttl = 64; /* 64 */
          new_iphdr->ip_v = 4;
          new_iphdr->ip_hl = 5;
          new_iphdr->ip_dst = ip_header->ip_src;
          new_iphdr->ip_src = ip_header->ip_dst;
          new_iphdr->ip_p = 0x0001;
          new_iphdr->ip_sum = 0;
          new_iphdr->ip_sum = cksum(send_packet + sizeof(sr_ethernet_hdr_t), sizeof(sr_ip_hdr_t));

          printf("ICMP Echo response prepared...\n");
          struct sr_arpentry* entry = sr_arpcache_lookup(&(sr->cache), new_iphdr->ip_dst);
          if (entry)
          {
            memcpy(new_ethhdr->ether_dhost, entry->mac, 6);
            struct sr_if* sending_interface = sr_get_interface(sr, interface);
            memcpy(new_ethhdr->ether_shost, sending_interface->addr, 6);
            sr_send_packet(sr, send_packet, len, interface);
            printf("ICMP Echo response sent (Cache lookup successful)...\n");
            free(entry);
          }
          else
          {
            printf("Entry not found in Cache for ICMP Echo response (Preparing ARP Request)...\n");
            struct sr_arpreq* req = sr_arpcache_queuereq(&(sr->cache), new_iphdr->ip_dst, send_packet, len, interface);
            req->iface = interface;
            handle_arpreq(sr, req);
          }
          free (send_packet);
          return;
      }
      else 
      {
        /* Drop DA packet*/
        printf("Non-PING ICMP to Router. Packet will be dropped...\n");
      }
    } 

    /*receive a TCP/UDP packet, send ICMP port unreachable back*/

    else if(ip_header->ip_p == 0x06 || ip_header->ip_p == 0x11)
    {
        printf("TCP/UDP packet to Router...\n");

        size_t tulen = sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_t3_hdr_t);
        uint8_t* send_packet = malloc(tulen);
        sr_ethernet_hdr_t* new_ether_header = (sr_ethernet_hdr_t*)send_packet;
        sr_ip_hdr_t* new_ip_header = (sr_ip_hdr_t*)(send_packet + sizeof(sr_ethernet_hdr_t));
        sr_icmp_t3_hdr_t* new_icmp_header = (sr_icmp_t3_hdr_t*)(send_packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t));

        /*write ethernet header*/
        struct sr_if* sending_interface = sr_get_interface(sr, interface);
        memcpy(new_ether_header->ether_dhost, eth_header->ether_shost, 6);
        memcpy(new_ether_header->ether_shost, sending_interface->addr, 6);
        new_ether_header->ether_type = htons(0x0800);

        /*write ip header*/
        new_ip_header->ip_hl = 5;
        new_ip_header->ip_v = 4;
        new_ip_header->ip_tos = ip_header->ip_tos;
        new_ip_header->ip_len = htons( sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_t3_hdr_t));
        new_ip_header->ip_id = ip_header->ip_id;
        new_ip_header->ip_off = htons(0x4000);
        new_ip_header->ip_ttl = 64;
        new_ip_header->ip_p = ip_protocol_icmp;
        new_ip_header->ip_sum = 0;
        new_ip_header->ip_src = sending_interface->ip;
        new_ip_header->ip_dst = ip_header->ip_src;
        new_ip_header->ip_sum = cksum(new_ip_header, sizeof(sr_ip_hdr_t));

        /*write icmp header*/
        new_icmp_header->icmp_type = 3;
        new_icmp_header->icmp_code = 3;
        new_icmp_header->icmp_sum = 0;
        new_icmp_header->next_mtu = htons(512);
        memcpy(new_icmp_header->data, (uint8_t *)ip_header, 28);
        /*memcpy(new_icmp_header->data + sizeof(sr_ip_hdr_t), send_packet + sizeof(sr_ip_hdr_t) + sizeof(sr_ethernet_hdr_t), 8);*/
        new_icmp_header->icmp_sum = cksum(send_packet + sizeof(sr_ip_hdr_t) + sizeof(sr_ethernet_hdr_t), sizeof(sr_icmp_t3_hdr_t));

        printf("Port Unreachable: Sending ICMP (3,3)...\n");
        /*send packet*/
        sr_send_packet(sr, send_packet, tulen, interface);
        free(send_packet);
        return;
    } 
    else
    {
      printf("Unknown IP protocol number to Router. Packet will be dropeed...\n");
    }
  } 


  else 
  {
     printf("IP Packet not meant for router...\n");
    /* Forward the Packet  */
    printf("Preparing to forward...\n");

    struct sr_rt* next_hop = NULL;
    struct sr_rt* table_iterator = sr->routing_table;
    while (table_iterator) 
    {
      if ((ip_header->ip_dst & (table_iterator->mask).s_addr) == ((table_iterator->dest).s_addr & (table_iterator->mask).s_addr)) 
        next_hop = table_iterator;
      table_iterator = table_iterator->next;
    }

    /* If no matching entry in Routing Table. Send Destination Net Unreachable */

    if (next_hop == NULL)
    {
        printf("Non existent route to destination IP...\n");

        size_t tulen = sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_t3_hdr_t);
        uint8_t* send_packet = malloc(tulen);
        sr_ethernet_hdr_t* new_ether_header = (sr_ethernet_hdr_t*)send_packet;
        sr_ip_hdr_t* new_ip_header = (sr_ip_hdr_t*)(send_packet + sizeof(sr_ethernet_hdr_t));
        sr_icmp_t3_hdr_t* new_icmp_header = (sr_icmp_t3_hdr_t*)(send_packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t));

        /*write ethernet header*/
        struct sr_if* sending_interface = sr_get_interface(sr, interface);
        memcpy(new_ether_header->ether_dhost, eth_header->ether_shost, 6);
        memcpy(new_ether_header->ether_shost, sending_interface->addr, 6);
        new_ether_header->ether_type = htons(0x0800);

        /*write ip header*/
        new_ip_header->ip_hl = 5;
        new_ip_header->ip_v = 4;
        new_ip_header->ip_tos = ip_header->ip_tos;
        new_ip_header->ip_len = htons( sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_t3_hdr_t));
        new_ip_header->ip_id = ip_header->ip_id;
        new_ip_header->ip_off = 0;
        new_ip_header->ip_ttl = 64;
        new_ip_header->ip_p = ip_protocol_icmp;
        new_ip_header->ip_sum = 0;
        new_ip_header->ip_src = sending_interface->ip;
        new_ip_header->ip_dst = ip_header->ip_src;
        new_ip_header->ip_sum = cksum(new_ip_header, sizeof(sr_ip_hdr_t));

        /*write icmp header*/
        new_icmp_header->icmp_type = 3;
        new_icmp_header->icmp_code = 0;
        new_icmp_header->icmp_sum = 0;
        new_icmp_header->next_mtu = htons(512);
        memcpy(new_icmp_header->data, (uint8_t *)ip_header, 28);
        /*memcpy(new_icmp_header->data + sizeof(sr_ip_hdr_t), send_packet + sizeof(sr_ip_hdr_t) + sizeof(sr_ethernet_hdr_t), 8);*/
        new_icmp_header->icmp_sum = cksum(send_packet + sizeof(sr_ip_hdr_t) + sizeof(sr_ethernet_hdr_t), sizeof(sr_icmp_t3_hdr_t));

        printf("Net Unreachable: Sending ICMP (3,0)...\n");
        /*send packet*/
        sr_send_packet(sr, send_packet, tulen, interface);
        free(send_packet);
        return;
    }

    /* Continue Forwarding otherwise */
    ip_header->ip_ttl--;

    if (ip_header->ip_ttl == 0) 
    {
        printf("Timed out (TTL = 0). IP packet will be discarded MUAHAHAHAH! ...\n");

        size_t tulen = sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_hdr_t);
        uint8_t* send_packet = malloc(tulen);
        sr_ethernet_hdr_t* new_ether_header = (sr_ethernet_hdr_t*)send_packet;
        sr_ip_hdr_t* new_ip_header = (sr_ip_hdr_t*)(send_packet + sizeof(sr_ethernet_hdr_t));
        sr_icmp_hdr_t* new_icmp_header = (sr_icmp_hdr_t*)(send_packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t));

        /*write ethernet header*/
        struct sr_if* sending_interface = sr_get_interface(sr, interface);
        memcpy(new_ether_header->ether_dhost, eth_header->ether_shost, 6);
        memcpy(new_ether_header->ether_shost, sending_interface->addr, 6);
        new_ether_header->ether_type = htons(0x0800);

        /*write ip header*/
        new_ip_header->ip_hl = 5;
        new_ip_header->ip_v = 4;
        new_ip_header->ip_tos = ip_header->ip_tos;
        new_ip_header->ip_len = htons( sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_t3_hdr_t));
        new_ip_header->ip_id = ip_header->ip_id;
        new_ip_header->ip_off = 0;
        new_ip_header->ip_ttl = 64;
        new_ip_header->ip_p = ip_protocol_icmp;
        new_ip_header->ip_sum = 0;
        new_ip_header->ip_src = sending_interface->ip;
        new_ip_header->ip_dst = ip_header->ip_src;
        new_ip_header->ip_sum = cksum(new_ip_header, sizeof(sr_ip_hdr_t));

        /*write icmp header*/
        new_icmp_header->icmp_type = 11;
        new_icmp_header->icmp_code = 0;
        new_icmp_header->icmp_sum = 0;
        new_icmp_header->icmp_sum = cksum(send_packet + sizeof(sr_ip_hdr_t) + sizeof(sr_ethernet_hdr_t), sizeof(sr_icmp_t3_hdr_t));

        printf("Time Exceeded: Sending ICMP (11,0)...\n");
        /*send packet*/
        sr_send_packet(sr, send_packet, tulen, interface);
        free(send_packet);
        return;      
    }

    ip_header->ip_sum = 0;
    ip_header->ip_sum = cksum((uint8_t*) ip_header, sizeof(sr_ip_hdr_t));

    struct sr_arpentry* entry = sr_arpcache_lookup(&(sr->cache), next_hop->gw.s_addr);
    if (entry) 
    {
      sr_ethernet_hdr_t* new_etheader = (sr_ethernet_hdr_t *)(packet);
      struct sr_if* interface = sr_get_interface(sr, next_hop->interface);
      memcpy(new_etheader->ether_dhost, entry->mac, 6);
      memcpy(new_etheader->ether_shost, interface->addr, 6);
      printf("Packet forwarded (Cache lookup successful)...\n");
      sr_send_packet(sr, packet, len, next_hop->interface);
      free(entry);
    }
    else 
    {
      printf("Forwarding Entry not found in Cache (Preparing ARP Request)...\n");
      struct sr_arpreq* req = sr_arpcache_queuereq(&(sr->cache), next_hop->gw.s_addr, packet, len, next_hop->interface);
      req->iface = next_hop->interface;
      handle_arpreq(sr, req);
    }
  }              
}