C Program contains all the functions that interact directly with the routing table, as well as the main entry method for routing

How to write a C Program contains all the functions that interact directly with the routing table, as well as the main entry method for routing in C Programming Language ?



Solution:
/*C program contains all the functions that interact directly with the routing table, as well as the main entry method for routing.*/

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>

#include "sr_if.h"
#include "sr_rt.h"
#include "sr_router.h"
#include "sr_protocol.h"
#include "sr_arpcache.h"
#include "sr_utils.h"


void sr_handleip(struct sr_instance* sr, uint8_t * packet/* lent */, unsigned int len, char* interface/* lent */);
void sr_handlearp(struct sr_instance* sr, uint8_t * packet/* lent */, unsigned int len, char* interface/* lent */);
void sr_handlearpreq(struct sr_instance* sr, struct sr_arpreq *req);

/*---------------------------------------------------------------------
 * Method: sr_init(void)
 * Scope:  Global
 *
 * Initialize the routing subsystem
 *
 *---------------------------------------------------------------------*/

void sr_init(struct sr_instance* sr)
{
    /* REQUIRES */
    assert(sr);

    /* Initialize cache and cache cleanup thread */
    sr_arpcache_init(&(sr->cache));

    pthread_attr_init(&(sr->attr));
    pthread_attr_setdetachstate(&(sr->attr), PTHREAD_CREATE_JOINABLE);
    pthread_attr_setscope(&(sr->attr), PTHREAD_SCOPE_SYSTEM);
    pthread_attr_setscope(&(sr->attr), PTHREAD_SCOPE_SYSTEM);
    pthread_t thread;

    pthread_create(&thread, &(sr->attr), sr_arpcache_timeout, sr);
   
    /* Add initialization code here! */

} /* -- sr_init -- */

/*---------------------------------------------------------------------
 * Method: sr_handlepacket(uint8_t* p,char* interface)
 * Scope:  Global
 *
 * This method is called each time the router receives a packet on the
 * interface.  The packet buffer, the packet length and the receiving
 * interface are passed in as parameters. The packet is complete with
 * ethernet headers.
 *
 * Note: Both the packet buffer and the character's memory are handled
 * by sr_vns_comm.c that means do NOT delete either.  Make a copy of the
 * packet instead if you intend to keep it around beyond the scope of
 * the method call.
 *
 *---------------------------------------------------------------------*/

void sr_handlepacket(struct sr_instance* sr,
        uint8_t * packet/* lent */,
        unsigned int len,
        char* interface/* lent */)
{
  /* REQUIRES */
  assert(sr);
  assert(packet);
  assert(interface);

  printf("*** -> Received packet of length %d \n",len);

  /* fill in code here */

  /* Get Ethernet Header */
  sr_ethernet_hdr_t *eth_hdr;
  eth_hdr = malloc(sizeof(sr_ethernet_hdr_t));
  memcpy(eth_hdr, (sr_ethernet_hdr_t *) packet, sizeof(sr_ethernet_hdr_t));

  /* Sanity Check */
  int minlength = sizeof(sr_ethernet_hdr_t);
  if (len < minlength) {
    fprintf(stderr, "Failed to print ETHERNET header, insufficient length\n");
    return;
  }

  uint16_t ethtype = ethertype((uint8_t *)eth_hdr);
 
  print_hdr_eth((uint8_t *)eth_hdr);
  if (ethtype == ethertype_ip){ /* IP */  
    printf("Received the IP Packet!\n");
    sr_handleip(sr, packet, len, interface);
  } else if (ethtype == ethertype_arp){ /* ARP */
    printf("Received the ARP Packet!\n");
    sr_handlearp(sr, packet, len, interface);
  }

}/* end sr_ForwardPacket */

void sr_handleip(struct sr_instance* sr,
        uint8_t * packet/* lent */,
        unsigned int len,
        char* interface/* lent */)
{
  /* REQUIRES */
  assert(sr);
  assert(packet);
  assert(interface);

  /* Get ethernet header */
  sr_ethernet_hdr_t *eth_hdr = malloc(sizeof(sr_ethernet_hdr_t));
  memcpy(eth_hdr, (sr_ethernet_hdr_t *) packet, sizeof(sr_ethernet_hdr_t));

  /* Get IP header */
  sr_ip_hdr_t *ip_hdr;
  ip_hdr = malloc(sizeof(sr_ip_hdr_t));
  memcpy(ip_hdr, (sr_ip_hdr_t *) (packet + sizeof(sr_ethernet_hdr_t)), sizeof(sr_ip_hdr_t));
 
  /* Sanity Check */
  int minlength = sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t);
  if (len < minlength){
    fprintf(stderr, "Failed to print IP header, insufficient length\n");
    return;
  }
 
  print_hdr_ip((uint8_t *)ip_hdr);
  uint8_t received_cksum = ip_hdr->ip_sum;
  ip_hdr->ip_sum = 0;
  uint8_t computed_cksum = cksum(ip_hdr, ip_hdr->ip_hl * 4);
  if (received_cksum != computed_cksum){
    fprintf(stderr, "IP Header checksum varies\n");
    return;
  }

  /* Decrement TTL */
  ip_hdr->ip_ttl = ip_hdr->ip_ttl - 1;
  if (ip_hdr->ip_ttl == 0){
    fprintf(stdout, "IP TTL is now 0. Discarding the packet\n");
    return;
  } else {
    ip_hdr->ip_sum = 0;
    ip_hdr->ip_sum = cksum(ip_hdr, ip_hdr->ip_hl * 4);
  }
  /* Determine if packet is directed to this router */
  int me = 0;
  struct sr_if *if_walker = 0;
  if_walker = sr->if_list;
 
  while(if_walker){
    if(if_walker->ip == ip_hdr->ip_dst){
      me = 1;
      break;
    }
    if_walker = if_walker->next;
  }

 uint8_t ip_proto = ip_protocol(packet + sizeof(sr_ethernet_hdr_t));
 
  if (me){ /* Directed to this router */
    if (ip_proto == ip_protocol_icmp){
      /* Get ICMP header */
      sr_icmp_hdr_t *icmp_hdr;
      icmp_hdr = malloc(sizeof(sr_icmp_hdr_t));

      memcpy(icmp_hdr, (sr_icmp_hdr_t *)(packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t)), sizeof(sr_icmp_hdr_t));

      /* Sanity Check */
      minlength = sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_hdr_t);
      if (len < minlength){
        fprintf(stderr, "Failed to print ICMP header, insufficient length\n");
        return;
      }

      uint8_t received_cksum = icmp_hdr->icmp_sum;
      icmp_hdr->icmp_sum = 0;
      uint8_t computed_cksum = cksum(icmp_hdr, ntohs(ip_hdr->ip_len) - (ip_hdr->ip_hl*4));
      if(!(received_cksum != computed_cksum)){
        fprintf(stderr, "IP Header checksum varies\n");
        return;
      }

      if (icmp_hdr->icmp_type == ICMP_ECHO_REQUEST){
        int len = sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_hdr_t);
        uint8_t *reply_packet = malloc(len);

        /* Make ethernet header */
        sr_ethernet_hdr_t *reply_eth_hdr = (sr_ethernet_hdr_t *)reply_packet;
        memcpy(reply_eth_hdr->ether_dhost, eth_hdr->ether_shost, sizeof(uint8_t)*ETHER_ADDR_LEN);
        memcpy(reply_eth_hdr->ether_shost, if_walker->addr, sizeof(uint8_t)*ETHER_ADDR_LEN);
        reply_eth_hdr->ether_type = eth_hdr->ether_type;

        /* Make IP header */
        sr_ip_hdr_t *reply_ip_hdr = (sr_ip_hdr_t *)(reply_packet + sizeof(sr_ethernet_hdr_t));
        memcpy(reply_ip_hdr, ip_hdr, sizeof(sr_ip_hdr_t));
        /* Now update it */
        reply_ip_hdr->ip_src = ip_hdr->ip_dst;
        reply_ip_hdr->ip_dst = ip_hdr->ip_src;

 
        /* Make ICMP Header */
        sr_icmp_hdr_t *reply_icmp_hdr = (sr_icmp_hdr_t *)(reply_packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t));
        reply_icmp_hdr->icmp_type = ICMP_ECHO_REPLY;
        reply_icmp_hdr->icmp_code = 0;
        reply_icmp_hdr->icmp_sum = cksum(reply_icmp_hdr, ntohs(ip_hdr->ip_len) - (ip_hdr->ip_hl*4));
        sr_send_packet(sr, reply_packet, len, if_walker->name);
        free(reply_packet);

     } else {
       printf("Received ICMP packet of unknown type\n");
       return;
     }
    } else if (ip_proto == ip_protocol_tcp || ip_proto == ip_protocol_udp){
        int len = sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_hdr_t);
        uint8_t *reply_packet = malloc(len);
       
        sr_ethernet_hdr_t *eth_hdr = malloc(sizeof(sr_ethernet_hdr_t));
        memcpy(eth_hdr, (sr_ethernet_hdr_t *) packet, sizeof(sr_ethernet_hdr_t));

        /* Make ethernet header */
        sr_ethernet_hdr_t *reply_eth_hdr = (sr_ethernet_hdr_t *)reply_packet;
        memcpy(reply_eth_hdr->ether_dhost, eth_hdr->ether_shost, sizeof(uint8_t)*ETHER_ADDR_LEN);
        memcpy(reply_eth_hdr->ether_shost, if_walker->addr, sizeof(uint8_t)*ETHER_ADDR_LEN);
        reply_eth_hdr->ether_type = eth_hdr->ether_type;


        /* Make IP header */
        sr_ip_hdr_t *reply_ip_hdr = (sr_ip_hdr_t *)(reply_packet + sizeof(sr_ethernet_hdr_t));
        memcpy(reply_ip_hdr, ip_hdr, sizeof(sr_ip_hdr_t));
        /* Now update it */
        reply_ip_hdr->ip_src = ip_hdr->ip_dst;
        reply_ip_hdr->ip_dst = ip_hdr->ip_src;

        /* Make ICMP Header */
        sr_icmp_hdr_t *reply_icmp_hdr = (sr_icmp_hdr_t *)(reply_packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t));
        reply_icmp_hdr->icmp_type = ICMP_UNREACHABLE_REPLY;
        reply_icmp_hdr->icmp_code = 3;
        reply_icmp_hdr->icmp_sum = cksum(reply_icmp_hdr, ntohs(ip_hdr->ip_len) - (ip_hdr->ip_hl*4));
        sr_send_packet(sr, reply_packet, len, if_walker->name);
        free(reply_packet);
        return;
   }
  } else {
    printf("The packet wasn't directed to this router\n");
    struct sr_rt *prefix = sr_longest_prefix(sr, ip_hdr->ip_dst);
    if (prefix){
      printf("Found the match in routing table\n");
      struct sr_arpentry *entry = sr_arpcache_lookup(&sr->cache, prefix->gw.s_addr);
      if (entry){
        printf("Found the ARP in the cache\n");

        struct sr_if *router_if = sr_get_interface(sr, prefix->interface);

        /* Make ethernet header */
        sr_ethernet_hdr_t *reply_eth_hdr = (sr_ethernet_hdr_t *)packet;
        memcpy(reply_eth_hdr->ether_dhost, entry->mac, sizeof(unsigned char)*6);
        memcpy(reply_eth_hdr->ether_shost, router_if->addr, sizeof(uint8_t)*ETHER_ADDR_LEN);
        reply_eth_hdr->ether_type = eth_hdr->ether_type;

        print_hdrs(packet, len);
        sr_send_packet(sr, packet, len, router_if->name);
        free(entry);
      } else {
        printf("ARP Cache miss\n");
        struct sr_if *router_if = sr_get_interface(sr, prefix->interface);
        struct sr_arpreq *req = sr_arpcache_queuereq(&(sr->cache), ip_hdr->ip_dst, packet, len, router_if->name);
        sr_handlearpreq(sr, req);
      }
    } else {
      printf("Match not found in routing table\n");
      printf("Sending ICMP net unreachable...\n");

      int len = sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_t3_hdr_t);
      uint8_t *reply_packet = malloc(len);

      sr_ethernet_hdr_t *eth_hdr = malloc(sizeof(sr_ethernet_hdr_t));
      memcpy(eth_hdr, (sr_ethernet_hdr_t *) packet, sizeof(sr_ethernet_hdr_t));

      /* Make ethernet header */
      sr_ethernet_hdr_t *reply_eth_hdr = (sr_ethernet_hdr_t *)reply_packet;
      reply_eth_hdr->ether_type = htons(ethertype_ip);


      /* Make IP header */
      sr_ip_hdr_t *reply_ip_hdr = (sr_ip_hdr_t *)(reply_packet + sizeof(sr_ethernet_hdr_t));
      reply_ip_hdr->ip_v = 4;
      reply_ip_hdr->ip_hl = sizeof(sr_ip_hdr_t)/4;
      reply_ip_hdr->ip_tos = 0;
      reply_ip_hdr->ip_len = htons(sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_t3_hdr_t));
      reply_ip_hdr->ip_id = htons(0);
      reply_ip_hdr->ip_off = htons(IP_DF);
      reply_ip_hdr->ip_ttl = 64;
      reply_ip_hdr->ip_dst = ip_hdr->ip_src;
      reply_ip_hdr->ip_p = ip_protocol_icmp;

      /* Make ICMP Header */
      sr_icmp_t3_hdr_t *reply_icmp_hdr = (sr_icmp_t3_hdr_t *)(reply_packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t));
      reply_icmp_hdr->icmp_type = ICMP_UNREACHABLE_REPLY;
      reply_icmp_hdr->icmp_code = 0;
      reply_icmp_hdr->unused = 0;
      reply_icmp_hdr->next_mtu = 0;
      reply_icmp_hdr->icmp_sum = 0;
      memcpy(reply_icmp_hdr->data, (uint8_t *)ip_hdr, ICMP_DATA_SIZE);
      reply_icmp_hdr->icmp_sum = cksum(reply_icmp_hdr, sizeof(sr_icmp_t3_hdr_t));

      struct sr_rt *prefix = sr_longest_prefix(sr, ip_hdr->ip_src);
      if (prefix){
        printf("Found the match in routing table\n");
        struct sr_arpentry *entry = sr_arpcache_lookup(&sr->cache, prefix->gw.s_addr);
        if (entry){
          printf("Found the ARP in the cache\n");

          struct sr_if *router_if = sr_get_interface(sr, prefix->interface);

          reply_ip_hdr->ip_src = router_if->ip;
          reply_ip_hdr->ip_sum = 0;
          reply_ip_hdr->ip_sum = cksum(reply_ip_hdr, sizeof(sr_ip_hdr_t));

          /* Make ethernet header */
          memcpy(reply_eth_hdr->ether_dhost, entry->mac, sizeof(uint8_t)*ETHER_ADDR_LEN);
          memcpy(reply_eth_hdr->ether_shost, router_if->addr, sizeof(uint8_t)*ETHER_ADDR_LEN);
         
          print_hdrs(reply_packet, len);
          sr_send_packet(sr, reply_packet, len, router_if->name);
          free(entry);
        } else {
          printf("ARP Cache miss\n");
          struct sr_if *router_if = sr_get_interface(sr, prefix->interface);
          struct sr_arpreq *req = sr_arpcache_queuereq(&(sr->cache), prefix->gw.s_addr, reply_packet, len, router_if->name);
          sr_handlearpreq(sr, req);
        }  
      }
    }
  }
}

void sr_handlearp(struct sr_instance* sr,
        uint8_t * packet/* lent */,
        unsigned int len,
        char* interface/* lent */)
{
  /* REQUIRES */
  assert(sr);
  assert(packet);
  assert(interface);
 
  /* Get ARP header */
  sr_arp_hdr_t *arp_hdr;
  arp_hdr = malloc(sizeof(sr_arp_hdr_t));
  memcpy(arp_hdr, (sr_arp_hdr_t *)(packet + sizeof(sr_ethernet_hdr_t)), sizeof(sr_arp_hdr_t));
 
  /* Sanity Check */
  int minlength = sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t);
  if (len < minlength){
    fprintf(stderr, "Failed to print ARP header, insufficient length\n");
    return;
  }

  print_hdr_arp((uint8_t *)arp_hdr);
  if (ntohs(arp_hdr->ar_op) == arp_op_request){ /* ARP Request */
   
    printf("It is ARP Request\n");
    /* Determine if packet is directed to this router */
    int me = 0;
    struct sr_if *if_walker = 0;
    if_walker = sr->if_list;
   
    while(if_walker){
      if(if_walker->ip == arp_hdr->ar_tip){
        me = 1;
        break;
      }
      if_walker = if_walker->next;
    }
 
    if (me){ /* Directed to this router */
      printf("It is the ARP request directed to me\n");
      int len = sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t);
      uint8_t *reply_packet = malloc(len);

      sr_ethernet_hdr_t *eth_hdr = malloc(sizeof(sr_ethernet_hdr_t));
      memcpy(eth_hdr, (sr_ethernet_hdr_t *) packet, sizeof(sr_ethernet_hdr_t));

      /* Make ethernet header */
      sr_ethernet_hdr_t *reply_eth_hdr = (sr_ethernet_hdr_t *) reply_packet;;
      memcpy(reply_eth_hdr->ether_dhost, eth_hdr->ether_shost, sizeof(uint8_t)*ETHER_ADDR_LEN);
      memcpy(reply_eth_hdr->ether_shost, sr_get_interface(sr, interface)->addr, sizeof(uint8_t)*ETHER_ADDR_LEN);
      reply_eth_hdr->ether_type = eth_hdr->ether_type;

      /* Make ARP header */
      sr_arp_hdr_t *reply_arp_hdr = (sr_arp_hdr_t *)(reply_packet + sizeof(sr_ethernet_hdr_t));
      reply_arp_hdr->ar_hrd = arp_hdr->ar_hrd;
      reply_arp_hdr->ar_pro = arp_hdr->ar_pro;
      reply_arp_hdr->ar_hln = arp_hdr->ar_hln;
      reply_arp_hdr->ar_pln = arp_hdr->ar_pln;
      reply_arp_hdr->ar_op =  htons(arp_op_reply);
      memcpy(reply_arp_hdr->ar_sha, if_walker->addr, sizeof(unsigned char)*ETHER_ADDR_LEN);
      reply_arp_hdr->ar_sip =  if_walker->ip;
      memcpy(reply_arp_hdr->ar_tha, arp_hdr->ar_sha, sizeof(unsigned char)*ETHER_ADDR_LEN);
      reply_arp_hdr->ar_tip = arp_hdr->ar_sip;

      print_hdrs(reply_packet, len);
      sr_send_packet(sr, reply_packet, len, if_walker->name);
      free(reply_packet);
    } else {
      printf("Got ARP Request directed to other router. Dropping packet\n");
      return;
    }
  } else if (ntohs(arp_hdr->ar_op) == arp_op_reply){ /* ARP Reply */
      int me = 0;
      struct sr_if *if_walker = 0;
      if_walker = sr->if_list;

      while(if_walker){
        if(if_walker->ip == arp_hdr->ar_tip){
          me = 1;
          break;
        }
        if_walker = if_walker->next;
      }

      if (me){
        printf("Caching the request and sending reply\n");
        struct sr_arpreq *req = sr_arpcache_insert(&(sr->cache), arp_hdr->ar_sha, arp_hdr->ar_sip);
        sr_ethernet_hdr_t *eth_hdr = malloc(sizeof(sr_ethernet_hdr_t));
        memcpy(eth_hdr, (sr_ethernet_hdr_t *) packet, sizeof(sr_ethernet_hdr_t));

        if (req){
          struct sr_packet *packet = req->packets;
          while (packet){
            sr_ethernet_hdr_t *reply_eth_hdr = (sr_ethernet_hdr_t *) packet->buf;
            memcpy(reply_eth_hdr->ether_dhost, arp_hdr->ar_sha, sizeof(unsigned char)*ETHER_ADDR_LEN);
            memcpy(reply_eth_hdr->ether_shost, sr_get_interface(sr, packet->iface)->addr, sizeof(unsigned char)*ETHER_ADDR_LEN);
 
            print_hdrs(packet->buf, packet->len);
            sr_send_packet(sr, packet->buf, packet->len, packet->iface);
            packet = packet->next;
          }
        sr_arpreq_destroy(&sr->cache, req);
      }
    } else {
      printf("Got ARP Reply directed to other router. Dropping packet\n");
      return;
    }
  }
}

void sr_handlearpreq(struct sr_instance*sr, struct sr_arpreq *req)
{
  time_t curr_time;
  time(&curr_time);
  if(difftime(curr_time, req->sent) > 1){
    printf("Packet hasn't been sent since 1 sec\n");
    if((req->times_sent) >= 5){
      printf("Packet resent tried 5 times\n");
      struct sr_packet *packet = req->packets;
      while(packet){
        printf("Sending ICMP net unreachable...\n");

        sr_ip_hdr_t *ip_hdr;
        ip_hdr = malloc(sizeof(sr_ip_hdr_t));
        memcpy(ip_hdr, (struct sr_ip_hdr_t*)(packet->buf + sizeof(sr_ethernet_hdr_t)), sizeof(sr_ip_hdr_t));
       
        int len = sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_t3_hdr_t);
        uint8_t *reply_packet = malloc(len);

        /* Make ethernet header */
        sr_ethernet_hdr_t *reply_eth_hdr = (sr_ethernet_hdr_t *)reply_packet;
        reply_eth_hdr->ether_type = htons(ethertype_ip);


        /* Make IP header */
        sr_ip_hdr_t *reply_ip_hdr = (sr_ip_hdr_t *)(reply_packet + sizeof(sr_ethernet_hdr_t));
        reply_ip_hdr->ip_v = 4;
        reply_ip_hdr->ip_hl = sizeof(sr_ip_hdr_t)/4;
        reply_ip_hdr->ip_tos = 0;
        reply_ip_hdr->ip_len = htons(sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_t3_hdr_t));
        reply_ip_hdr->ip_id = htons(0);
        reply_ip_hdr->ip_off = htons(IP_DF);
        reply_ip_hdr->ip_ttl = 64;
        reply_ip_hdr->ip_dst = ip_hdr->ip_src;
        reply_ip_hdr->ip_p = ip_protocol_icmp;

        struct sr_rt *prefix = sr_longest_prefix(sr, reply_ip_hdr->ip_dst);
        if (prefix){
          printf("Found the match in routing table\n");
          struct sr_arpentry *entry = sr_arpcache_lookup(&sr->cache, prefix->gw.s_addr);
          if (entry){
            printf("Found the ARP in the cache\n");

            struct sr_if *router_if = sr_get_interface(sr, prefix->interface);

            reply_ip_hdr->ip_src = router_if->ip;
            reply_ip_hdr->ip_sum = 0;
            reply_ip_hdr->ip_sum = cksum(reply_ip_hdr, sizeof(sr_ip_hdr_t));

            /* Make ethernet header */
            memcpy(reply_eth_hdr->ether_dhost, entry->mac, sizeof(uint8_t)*ETHER_ADDR_LEN);
            memcpy(reply_eth_hdr->ether_shost, router_if->addr, sizeof(uint8_t)*ETHER_ADDR_LEN);

            print_hdrs(reply_packet, len);
            sr_send_packet(sr, reply_packet, len, router_if->name);
            free(entry);
          } else {
            printf("ARP Cache miss\n");
            struct sr_if *router_if = sr_get_interface(sr, prefix->interface);
            struct sr_arpreq *req = sr_arpcache_queuereq(&(sr->cache), prefix->gw.s_addr, reply_packet, len, router_if->name);
            sr_handlearpreq(sr, req);
          }
        }                

        packet = packet->next;
      }
      sr_arpreq_destroy(&sr->cache, req);
    } else {
      /* Send arp request */
      printf("Sending ARP Request\n");
      struct sr_packet *packet = req->packets;
   
      struct sr_if *if_walker = sr_get_interface(sr, packet->iface);
      int len = sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t);
     
      uint8_t *reply_packet = malloc(len);
      sr_ethernet_hdr_t *eth_hdr = malloc(sizeof(sr_ethernet_hdr_t));
      memcpy(eth_hdr, (sr_ethernet_hdr_t *) packet->buf, sizeof(sr_ethernet_hdr_t));

     /* Make ethernet header */
      sr_ethernet_hdr_t *reply_eth_hdr = (sr_ethernet_hdr_t *) reply_packet;
      memset(reply_eth_hdr->ether_dhost, 255, sizeof(uint8_t)*ETHER_ADDR_LEN);
      memcpy(reply_eth_hdr->ether_shost, if_walker->addr, sizeof(uint8_t)*ETHER_ADDR_LEN);
      reply_eth_hdr->ether_type = htons(ethertype_arp);
           

      /* Make ARP header */
      sr_arp_hdr_t *reply_arp_hdr = (sr_arp_hdr_t *)(reply_packet + sizeof(sr_ethernet_hdr_t));
      reply_arp_hdr->ar_hrd = htons(arp_hrd_ethernet);
      reply_arp_hdr->ar_pro = htons(ethertype_ip);
      reply_arp_hdr->ar_hln = ETHER_ADDR_LEN;
      reply_arp_hdr->ar_pln = sizeof(uint32_t);
      reply_arp_hdr->ar_op = htons(arp_op_request);
      memcpy(reply_arp_hdr->ar_sha, if_walker->addr, sizeof(unsigned char)*ETHER_ADDR_LEN);
      reply_arp_hdr->ar_sip = if_walker->ip;
      memset(reply_arp_hdr->ar_tha, 0, sizeof(unsigned char)*ETHER_ADDR_LEN);
      reply_arp_hdr->ar_tip = req->ip;
      print_hdrs(reply_packet, len);
      sr_send_packet(sr, reply_packet, len, if_walker->name);          
      free(reply_packet);
     
      }
      req->sent = curr_time;
      req->times_sent = req->times_sent + 1;
  }
}


Learn More :