Advertisement
Guest User

Untitled

a guest
Nov 28th, 2017
19
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 24.22 KB | None | 0 0
  1. /**********************************************************************
  2.  * file:  sr_router.c
  3.  * date:  Mon Feb 18 12:50:42 PST 2002
  4.  * Contact: [email protected]
  5.  *
  6.  * Description:
  7.  *
  8.  * This file contains all the functions that interact directly
  9.  * with the routing table, as well as the main entry method
  10.  * for routing.
  11.  *
  12.  **********************************************************************/
  13.  
  14. #include <stdio.h>
  15. #include <assert.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18.  
  19. #include "sr_if.h"
  20. #include "sr_rt.h"
  21. #include "sr_router.h"
  22. #include "sr_protocol.h"
  23. #include "sr_arpcache.h"
  24. #include "sr_utils.h"
  25.  
  26. /* function prototypes */
  27. char *get_lpm(struct sr_instance *sr, uint32_t ip_dest);
  28. void send_icmp_msg(struct sr_instance *sr, struct sr_packet *this_packet, uint8_t type, uint8_t code);
  29.  
  30. /*---------------------------------------------------------------------
  31.  * Method: sr_init(void)
  32.  * Scope:  Global
  33.  *
  34.  * Initialize the routing subsystem
  35.  *
  36.  *---------------------------------------------------------------------*/
  37.  
  38. void sr_init(struct sr_instance *sr)
  39. {
  40.   /* REQUIRES */
  41.   assert(sr);
  42.  
  43.   /* Initialize cache and cache cleanup thread */
  44.   sr_arpcache_init(&(sr->cache));
  45.  
  46.   pthread_attr_init(&(sr->attr));
  47.   pthread_attr_setdetachstate(&(sr->attr), PTHREAD_CREATE_JOINABLE);
  48.   pthread_attr_setscope(&(sr->attr), PTHREAD_SCOPE_SYSTEM);
  49.   pthread_attr_setscope(&(sr->attr), PTHREAD_SCOPE_SYSTEM);
  50.   pthread_t thread;
  51.  
  52.   pthread_create(&thread, &(sr->attr), sr_arpcache_timeout, sr);
  53.  
  54.   /* Add initialization code here! */
  55.  
  56. } /* -- sr_init -- */
  57.  
  58. /*---------------------------------------------------------------------
  59.  * Method: sr_send_arpreply(struct sr_instance *sr, uint8_t *orig_pkt,
  60.  *             unsigned int orig_len, struct sr_if *src_iface)
  61.  * Scope:  Local
  62.  *
  63.  * Send an ARP reply packet in response to an ARP request for one of
  64.  * the router's interfaces
  65.  *---------------------------------------------------------------------*/
  66. void sr_send_arpreply(struct sr_instance *sr, uint8_t *orig_pkt,
  67.                       unsigned int orig_len, struct sr_if *src_iface)
  68. {
  69.   /* Allocate space for packet */
  70.   unsigned int reply_len = sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t);
  71.   uint8_t *reply_pkt = (uint8_t *)malloc(reply_len);
  72.   if (NULL == reply_pkt)
  73.   {
  74.     fprintf(stderr, "Failed to allocate space for ARP reply");
  75.     return;
  76.   }
  77.  
  78.   sr_ethernet_hdr_t *orig_ethhdr = (sr_ethernet_hdr_t *)orig_pkt;
  79.   sr_arp_hdr_t *orig_arphdr =
  80.       (sr_arp_hdr_t *)(orig_pkt + sizeof(sr_ethernet_hdr_t));
  81.  
  82.   sr_ethernet_hdr_t *reply_ethhdr = (sr_ethernet_hdr_t *)reply_pkt;
  83.   sr_arp_hdr_t *reply_arphdr =
  84.       (sr_arp_hdr_t *)(reply_pkt + sizeof(sr_ethernet_hdr_t));
  85.  
  86.   /* Populate Ethernet header */
  87.   memcpy(reply_ethhdr->ether_dhost, orig_ethhdr->ether_shost, ETHER_ADDR_LEN);
  88.   memcpy(reply_ethhdr->ether_shost, src_iface->addr, ETHER_ADDR_LEN);
  89.   reply_ethhdr->ether_type = orig_ethhdr->ether_type;
  90.  
  91.   /* Populate ARP header */
  92.   memcpy(reply_arphdr, orig_arphdr, sizeof(sr_arp_hdr_t));
  93.   reply_arphdr->ar_hrd = orig_arphdr->ar_hrd;
  94.   reply_arphdr->ar_pro = orig_arphdr->ar_pro;
  95.   reply_arphdr->ar_hln = orig_arphdr->ar_hln;
  96.   reply_arphdr->ar_pln = orig_arphdr->ar_pln;
  97.   reply_arphdr->ar_op = htons(arp_op_reply);
  98.   memcpy(reply_arphdr->ar_tha, orig_arphdr->ar_sha, ETHER_ADDR_LEN);
  99.   reply_arphdr->ar_tip = orig_arphdr->ar_sip;
  100.   memcpy(reply_arphdr->ar_sha, src_iface->addr, ETHER_ADDR_LEN);
  101.   reply_arphdr->ar_sip = src_iface->ip;
  102.  
  103.   /* Send ARP reply */
  104.   printf("Send ARP reply\n");
  105.   print_hdrs(reply_pkt, reply_len);
  106.   sr_send_packet(sr, reply_pkt, reply_len, src_iface->name);
  107.   free(reply_pkt);
  108. } /* -- sr_send_arpreply -- */
  109.  
  110. /*---------------------------------------------------------------------
  111.  * Method: sr_send_arprequest(struct sr_instance *sr,
  112.  *             struct sr_arpreq *req,i struct sr_if *out_iface)
  113.  * Scope:  Local
  114.  *
  115.  * Send an ARP reply packet in response to an ARP request for one of
  116.  * the router's interfaces
  117.  *---------------------------------------------------------------------*/
  118. void sr_send_arprequest(struct sr_instance *sr, struct sr_arpreq *req,
  119.                         struct sr_if *out_iface)
  120. {
  121.   /* Allocate space for ARP request packet */
  122.   unsigned int reqst_len = sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t);
  123.   uint8_t *reqst_pkt = (uint8_t *)malloc(reqst_len);
  124.   if (NULL == reqst_pkt)
  125.   {
  126.     fprintf(stderr, "Failed to allocate space for ARP reply");
  127.     return;
  128.   }
  129.  
  130.   sr_ethernet_hdr_t *reqst_ethhdr = (sr_ethernet_hdr_t *)reqst_pkt;
  131.   sr_arp_hdr_t *reqst_arphdr =
  132.       (sr_arp_hdr_t *)(reqst_pkt + sizeof(sr_ethernet_hdr_t));
  133.  
  134.   /* Populate Ethernet header */
  135.   memset(reqst_ethhdr->ether_dhost, 0xFF, ETHER_ADDR_LEN);
  136.   memcpy(reqst_ethhdr->ether_shost, out_iface->addr, ETHER_ADDR_LEN);
  137.   reqst_ethhdr->ether_type = htons(ethertype_arp);
  138.  
  139.   /* Populate ARP header */
  140.   reqst_arphdr->ar_hrd = htons(arp_hrd_ethernet);
  141.   reqst_arphdr->ar_pro = htons(ethertype_ip);
  142.   reqst_arphdr->ar_hln = ETHER_ADDR_LEN;
  143.   reqst_arphdr->ar_pln = sizeof(uint32_t);
  144.   reqst_arphdr->ar_op = htons(arp_op_request);
  145.   memcpy(reqst_arphdr->ar_sha, out_iface->addr, ETHER_ADDR_LEN);
  146.   reqst_arphdr->ar_sip = out_iface->ip;
  147.   memset(reqst_arphdr->ar_tha, 0x00, ETHER_ADDR_LEN);
  148.   reqst_arphdr->ar_tip = req->ip;
  149.  
  150.   /* Send ARP request */
  151.   printf("Send ARP request\n");
  152.   print_hdrs(reqst_pkt, reqst_len);
  153.   sr_send_packet(sr, reqst_pkt, reqst_len, out_iface->name);
  154.   free(reqst_pkt);
  155. } /* -- sr_send_arprequest -- */
  156.  
  157. /*---------------------------------------------------------------------
  158.  * Method: sr_handle_arpreq(struct sr_instance *sr,
  159.  *             struct sr_arpreq *req, struct sr_if *out_iface)
  160.  * Scope:  Global
  161.  *
  162.  * Perform processing for a pending ARP request: do nothing, timeout, or  
  163.  * or generate an ARP request packet
  164.  *---------------------------------------------------------------------*/
  165. void sr_handle_arpreq(struct sr_instance *sr, struct sr_arpreq *req,
  166.                       struct sr_if *out_iface)
  167. {
  168.   time_t now = time(NULL);
  169.   if (difftime(now, req->sent) >= 1.0)
  170.   {
  171.     if (req->times_sent >= 5)
  172.     {
  173.       /*********************************************************************/
  174.       /* TODO: send ICMP host uncreachable to the source address of all    */
  175.       /* packets waiting on this request                                   */
  176.       struct sr_packet *this_packet = req->packets;
  177.       while (this_packet != NULL)
  178.       {
  179.         send_icmp_msg(sr, this_packet, 3, 0);
  180.         this_packet = this_packet->next;
  181.       }
  182.       /*********************************************************************/
  183.  
  184.       sr_arpreq_destroy(&(sr->cache), req);
  185.     }
  186.     else
  187.     {
  188.       /* Send ARP request packet */
  189.       sr_send_arprequest(sr, req, out_iface);
  190.  
  191.       /* Update ARP request entry to indicate ARP request packet was sent */
  192.       req->sent = now;
  193.       req->times_sent++;
  194.     }
  195.   }
  196. } /* -- sr_handle_arpreq -- */
  197.  
  198. /*---------------------------------------------------------------------
  199.  * Method: void sr_waitforarp(struct sr_instance *sr, uint8_t *pkt,
  200.  *             unsigned int len, uint32_t next_hop_ip,
  201.  *             struct sr_if *out_iface)
  202.  * Scope:  Local
  203.  *
  204.  * Queue a packet to wait for an entry to be added to the ARP cache
  205.  *---------------------------------------------------------------------*/
  206. void sr_waitforarp(struct sr_instance *sr, uint8_t *pkt,
  207.                    unsigned int len, uint32_t next_hop_ip, struct sr_if *out_iface)
  208. {
  209.   struct sr_arpreq *req = sr_arpcache_queuereq(&(sr->cache), next_hop_ip,
  210.                                                pkt, len, out_iface->name);
  211.   sr_handle_arpreq(sr, req, out_iface);
  212. } /* -- sr_waitforarp -- */
  213.  
  214. /*---------------------------------------------------------------------
  215.  * Method: sr_handlepacket_arp(struct sr_instance *sr, uint8_t *pkt,
  216.  *             unsigned int len, struct sr_if *src_iface)
  217.  * Scope:  Local
  218.  *
  219.  * Handle an ARP packet that was received by the router
  220.  *---------------------------------------------------------------------*/
  221. void sr_handlepacket_arp(struct sr_instance *sr, uint8_t *pkt,
  222.                          unsigned int len, struct sr_if *src_iface)
  223. {
  224.   /* Drop packet if it is less than the size of Ethernet and ARP headers */
  225.   if (len < (sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t)))
  226.   {
  227.     printf("Packet is too short => drop packet\n");
  228.     return;
  229.   }
  230.  
  231.   sr_arp_hdr_t *arphdr = (sr_arp_hdr_t *)(pkt + sizeof(sr_ethernet_hdr_t));
  232.  
  233.   switch (ntohs(arphdr->ar_op))
  234.   {
  235.   case arp_op_request:
  236.   {
  237.     /* Check if request is for one of my interfaces */
  238.     if (arphdr->ar_tip == src_iface->ip)
  239.     {
  240.       sr_send_arpreply(sr, pkt, len, src_iface);
  241.     }
  242.     break;
  243.   }
  244.   case arp_op_reply:
  245.   {
  246.     /* Check if reply is for one of my interfaces */
  247.     if (arphdr->ar_tip != src_iface->ip)
  248.     {
  249.       break;
  250.     }
  251.  
  252.     /* Update ARP cache with contents of ARP reply */
  253.     struct sr_arpreq *req = sr_arpcache_insert(&(sr->cache), arphdr->ar_sha,
  254.                                                arphdr->ar_sip);
  255.  
  256.     /* Process pending ARP request entry, if there is one */
  257.     if (req != NULL)
  258.     {
  259.       /*********************************************************************/
  260.       /* TODO: send all packets on the req->packets linked list            */
  261.       struct sr_packet *this_packet = req->packets;
  262.       sr_ethernet_hdr_t *arp_hdr = (sr_ethernet_hdr_t *)(pkt);
  263.       while (this_packet != NULL) /* while there are more packets to handle */
  264.       {
  265.         sr_ethernet_hdr_t *this_ethernet = (sr_ethernet_hdr_t *)(this_packet->buf);
  266.         memcpy(this_ethernet->ether_dhost, arp_hdr->ether_shost, sizeof(uint8_t) * ETHER_ADDR_LEN);
  267.         memcpy(this_ethernet->ether_shost, arp_hdr->ether_dhost, sizeof(uint8_t) * ETHER_ADDR_LEN);
  268.         sr_send_packet(sr, this_packet->buf, this_packet->len, this_packet->iface); /* sending packet */
  269.         this_packet = this_packet->next;                                            /* setup to work on next packet */
  270.       }
  271.       /*********************************************************************/
  272.  
  273.       /* Release ARP request entry */
  274.       sr_arpreq_destroy(&(sr->cache), req);
  275.     }
  276.     break;
  277.   }
  278.   default:
  279.     printf("Unknown ARP opcode => drop packet\n");
  280.     return;
  281.   }
  282. } /* -- sr_handlepacket_arp -- */
  283.  
  284. /*---------------------------------------------------------------------
  285.  * Method: sr_handlepacket(uint8_t* p,char* interface)
  286.  * Scope:  Global
  287.  *
  288.  * This method is called each time the router receives a packet on the
  289.  * interface.  The packet buffer, the packet length and the receiving
  290.  * interface are passed in as parameters. The packet is complete with
  291.  * ethernet headers.
  292.  *
  293.  * Note: Both the packet buffer and the character's memory are handled
  294.  * by sr_vns_comm.c that means do NOT delete either.  Make a copy of the
  295.  * packet instead if you intend to keep it around beyond the scope of
  296.  * the method call.
  297.  *
  298.  *---------------------------------------------------------------------*/
  299.  
  300. void sr_handlepacket(struct sr_instance *sr,
  301.                      uint8_t *packet /* lent */,
  302.                      unsigned int len,
  303.                      char *interface /* lent */)
  304. {
  305.   /* REQUIRES */
  306.   assert(sr);
  307.   assert(packet);
  308.   assert(interface);
  309.  
  310.   printf("*** -> Received packet of length %d \n", len);
  311.  
  312.   /*************************************************************************/
  313.   /* TODO: Handle packets                                                  */
  314.   uint16_t ethertype1 = ethertype(packet);
  315.   struct sr_ethernet_hdr *ethernet_hdr = (struct sr_ethernet_hdr *)packet;
  316.  
  317.   /*---------------------------------------------------------------------*
  318.   *  determine if it's a broadcast pracket or not                        *
  319.   *---------------------------------------------------------------------*/
  320.   int i;
  321.   int is_bcast_pkt = 1;
  322.   for (i = 0; i < ETHER_ADDR_LEN; i++)
  323.   {
  324.     /*---------------------------------------------------------------------*
  325.      *      Check the destination host for desingated hex code 0xFF        *
  326.      *      If it does have 0xFF in it then it is a broadcast packet       *
  327.      *      If it doesn't, then it is not a broadcast packet               *
  328.      *---------------------------------------------------------------------*/
  329.     if (ethernet_hdr->ether_dhost[i] != 0xFF)
  330.     {
  331.       is_bcast_pkt = 0; /* didn't find 0xFF in destination host so its not a broadcast */
  332.     }
  333.   }
  334.  
  335.   int router_should_recieve_pkt = 0;
  336.   sr_ip_hdr_t *dest = (sr_ip_hdr_t *)((sizeof(sr_ethernet_hdr_t)) + packet);
  337.   struct sr_if *current_entry = sr->if_list;
  338.   while (current_entry != NULL) /* while there is an entry to process */
  339.   {
  340.     if (current_entry->ip == dest->ip_dst) /* indicates the packet is indeed addressed to the router */
  341.     {
  342.       router_should_recieve_pkt = 1;
  343.     }
  344.     current_entry = current_entry->next; /* goes to next entry */
  345.   }
  346.   if (is_bcast_pkt) /* if it is a broadcast packet */
  347.   {
  348.     if (ethertype1 == ethertype_arp) /* and its arp */
  349.     {
  350.       sr_handlepacket_arp(sr, packet, len, sr_get_interface(sr, interface));
  351.     }
  352.     else /* broadcast but not arp */
  353.     {
  354.       fprintf(stderr, "Error, broadcast packet but not arp packet");
  355.     }
  356.   }
  357.   else if (router_should_recieve_pkt) /* is addressed to router, but not arp */
  358.   {
  359.     if (ethertype1 == ethertype_ip) /* is IP */
  360.     {
  361.       if (dest->ip_p == ip_protocol_icmp) /* if it is an icmp packet */
  362.       {
  363.         sr_icmp_hdr_t *icmp_hdr = (sr_icmp_hdr_t *)(sizeof(sr_ip_hdr_t) + sizeof(sr_ethernet_hdr_t) + packet);
  364.         if (icmp_hdr->icmp_type == 9) /* 9 = ICMP_ECHO_REQUEST */
  365.         {
  366.           struct sr_packet *this_packet = (struct sr_packet *)malloc(sizeof(struct sr_packet));
  367.           this_packet->iface = interface;
  368.           this_packet->len = len;
  369.           this_packet->buf = packet;
  370.  
  371.           uint8_t *packet = (uint8_t *)malloc(sizeof(sr_icmp_hdr_t) + sizeof(sr_ip_hdr_t) + sizeof(sr_ethernet_hdr_t) + 60);
  372.  
  373.           sr_ethernet_hdr_t *ethernet_hdr = (sr_ethernet_hdr_t *)packet;
  374.           sr_icmp_hdr_t *icmp_hdr = (sr_icmp_hdr_t *)(sizeof(sr_ip_hdr_t) + sizeof(sr_ethernet_hdr_t) + packet);
  375.           sr_ip_hdr_t *ip_hdr = (sr_ip_hdr_t *)(packet + sizeof(sr_ethernet_hdr_t));
  376.           uint8_t *queued_packet = this_packet->buf;
  377.           sr_ip_hdr_t *queued_hdr = (sr_ip_hdr_t *)(queued_packet + sizeof(sr_ethernet_hdr_t));
  378.           sr_icmp_hdr_t *queued_icmp = (sr_icmp_hdr_t *)(queued_packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t));
  379.  
  380.           /*---------------------------------------------------------------------*
  381.            *  Creation of the IP header                                          */
  382.           ip_hdr->ip_hl = 5;
  383.           ip_hdr->ip_len = 60 + sizeof(sr_icmp_hdr_t) + htons(sizeof(sr_ip_hdr_t));
  384.           ip_hdr->ip_off = 0;
  385.           ip_hdr->ip_id = 0;
  386.           ip_hdr->ip_dst = queued_hdr->ip_src;
  387.           ip_hdr->ip_v = 4;
  388.           ip_hdr->ip_tos = 0;
  389.           ip_hdr->ip_ttl = 128; /* restricted to same continent */
  390.           ip_hdr->ip_sum = 0x0000;
  391.           ip_hdr->ip_p = ip_protocol_icmp;
  392.  
  393.           char *outbound_iface = get_lpm(sr, htonl(ip_hdr->ip_dst));
  394.           ip_hdr->ip_src = sr_get_interface(sr, outbound_iface)->ip;
  395.           ip_hdr->ip_sum = cksum((uint8_t *)ip_hdr, 60 + sizeof(sr_icmp_hdr_t) + sizeof(sr_ip_hdr_t));
  396.           /*  Done with creation of the IP header                                *
  397.            *---------------------------------------------------------------------*/
  398.  
  399.           /*---------------------------------------------------------------------*
  400.            *  Creation of the ethernet header                                    */
  401.           sr_ethernet_hdr_t *queued_eth_hdr = (sr_ethernet_hdr_t *)(queued_packet);
  402.           memcpy(ethernet_hdr->ether_dhost, queued_eth_hdr->ether_shost, sizeof(uint8_t) * ETHER_ADDR_LEN);
  403.           memcpy(ethernet_hdr->ether_shost, sr_get_interface(sr, outbound_iface)->addr, sizeof(uint8_t) * ETHER_ADDR_LEN);
  404.           ethernet_hdr->ether_type = htons(ethertype_ip);
  405.           /*  Done with Creation of the ethernet header                          *
  406.            *---------------------------------------------------------------------*/
  407.  
  408.           /*---------------------------------------------------------------------*
  409.            *  Creation of the icmp header                                        */
  410.           memcpy(icmp_hdr, queued_icmp, sizeof(sr_icmp_hdr_t) + 60);
  411.           icmp_hdr->icmp_code = 0;
  412.           icmp_hdr->icmp_type = 0;
  413.           icmp_hdr->icmp_sum = 0x0000;
  414.           icmp_hdr->icmp_sum = cksum((uint16_t *)icmp_hdr, sizeof(sr_icmp_hdr_t) + 60);
  415.           /*  Done with creation of the icmp header                              *
  416.            *---------------------------------------------------------------------*/
  417.  
  418.           /* actually send sthe packet */
  419.           sr_send_packet(sr, packet, 60 + sizeof(sr_ethernet_hdr_t) + sizeof(sr_icmp_hdr_t)  + sizeof(sr_ip_hdr_t), outbound_iface);
  420.  
  421.           /* feeing up memory */
  422.           free(this_packet);
  423.           free(packet);
  424.         }
  425.       }
  426.       else if (dest->ip_p == 6 || dest->ip_p == 17) /* TCP or UDP */
  427.       {
  428.         struct sr_packet *this_packet = (struct sr_packet *)malloc(sizeof(struct sr_packet));
  429.         this_packet->iface = interface;
  430.         this_packet->buf = packet;
  431.         this_packet->len = len;
  432.         send_icmp_msg(sr, this_packet, 3, 3);
  433.         free(this_packet); /* feeing up memory */
  434.       }
  435.     }
  436.     else
  437.     {
  438.       fprintf(stderr, "Error, Not IP packet");
  439.     }
  440.   }
  441.   else
  442.   {
  443.     /*---------------------------------------------------------------------*
  444.      *  Now we are going to forward the packet to the correct host         *
  445.      *---------------------------------------------------------------------*/
  446.     if (ethertype1 == ethertype_ip)
  447.     {
  448.       sr_ip_hdr_t *dest = (sr_ip_hdr_t *)((sizeof(sr_ethernet_hdr_t)) + packet);
  449.       if (len < sizeof(sr_ip_hdr_t) + sizeof(sr_ethernet_hdr_t)) /* if less then minimum length */
  450.       {
  451.         fprintf(stderr, "Error, IP packet < minimum length\n");
  452.         return;
  453.       }
  454.  
  455.       /*---------------------------------------------------------------------*
  456.        *  Calculate checksum and compare it to ensure packet integrity       *
  457.        *---------------------------------------------------------------------*/
  458.       if (cksum(dest, sizeof(sr_ip_hdr_t)) != 0xffff)
  459.       {
  460.         fprintf(stderr, "Error, checksum wrong, package integrity unverified, packet dropped\n");
  461.         return;
  462.       }
  463.       dest->ip_ttl--;
  464.       if (dest->ip_ttl == 0) /* time to live of packet = 0 */
  465.       {
  466.         struct sr_packet *this_packet = (struct sr_packet *)malloc(sizeof(struct sr_packet));
  467.         this_packet->iface = interface;
  468.         this_packet->buf = packet;
  469.         this_packet->len = len;
  470.  
  471.         send_icmp_msg(sr, this_packet, 11, 0); /* code 11 = Destination Network Unreachable */
  472.         return;
  473.       }
  474.  
  475.       /*---------------------------------------------------------------------*
  476.        *  Re-calculate checksum with newly found destination address         *
  477.        *---------------------------------------------------------------------*/
  478.       dest->ip_sum = 0x0000;
  479.       dest->ip_sum = cksum(dest, sizeof(sr_ip_hdr_t));
  480.       char *outbound_iface = get_lpm(sr, htonl(dest->ip_dst));
  481.       if (outbound_iface == NULL) /* prefix matching couldn't find a match */
  482.       {
  483.         struct sr_packet *this_packet = (struct sr_packet *)malloc(sizeof(struct sr_packet));
  484.         this_packet->iface = interface;
  485.         this_packet->buf = packet;
  486.         this_packet->len = len;
  487.         send_icmp_msg(sr, this_packet, 3, 0); /* code 3 = Port Unreachable */
  488.         return;
  489.       }
  490.       struct sr_arpentry *arpentry = sr_arpcache_lookup(&(sr->cache), dest->ip_dst);
  491.       if (arpentry != NULL) /* found destination mac address in arpcache */
  492.       {
  493.         memcpy(ethernet_hdr->ether_dhost, arpentry->mac, ETHER_ADDR_LEN);
  494.         memcpy(ethernet_hdr->ether_shost, (sr_get_interface(sr, outbound_iface)->addr), ETHER_ADDR_LEN);
  495.         sr_send_packet(sr, packet, len, outbound_iface);
  496.         free(arpentry);
  497.       }
  498.       else /* arpentry == NULL aka, destination mac address not found in arpcache */
  499.       {
  500.         sr_waitforarp(sr, packet, len, ntohl(htonl(dest->ip_dst)), sr_get_interface(sr, outbound_iface));
  501.       }
  502.     }
  503.     else if (ethertype1 == ethertype_arp) /* if we are handling an arp packet */
  504.     {
  505.       sr_handlepacket_arp(sr, packet, len, sr_get_interface(sr, interface));
  506.     }
  507.     else /* neither IP nor ARP packet */
  508.     {
  509.       fprintf(stderr, "Error, packet neither IP nor ARP");
  510.     }
  511.   }
  512.   /*************************************************************************/
  513.  
  514. } /* end sr_ForwardPacket */
  515.  
  516. void send_icmp_msg(struct sr_instance *sr, struct sr_packet *this_packet, uint8_t type, uint8_t code)
  517. {
  518.   int len = 8 + sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_t3_hdr_t) + sizeof(sr_ethernet_hdr_t);
  519.   uint8_t *packet = (uint8_t *)malloc(len);
  520.   sr_ip_hdr_t *ip_hdr = (sr_ip_hdr_t *)(sizeof(sr_ethernet_hdr_t) + packet);
  521.   sr_icmp_t3_hdr_t *icmp_hdr = (sr_icmp_t3_hdr_t *)(sizeof(sr_ip_hdr_t) + sizeof(sr_ethernet_hdr_t) + packet);
  522.   sr_ethernet_hdr_t *ethernet_hdr = (sr_ethernet_hdr_t *)packet;
  523.   uint8_t *queued_packet = this_packet->buf;
  524.   sr_ip_hdr_t *queued_hdr = (sr_ip_hdr_t *)(sizeof(sr_ethernet_hdr_t) + queued_packet);
  525.  
  526.   /*---------------------------------------------------------------------*
  527.  *  create ip header                                                   *
  528.  *---------------------------------------------------------------------*/
  529.   ip_hdr->ip_hl = 5;
  530.   ip_hdr->ip_v = 4;
  531.   ip_hdr->ip_tos = 0;
  532.   ip_hdr->ip_len = htons(sizeof(sr_icmp_t3_hdr_t) + sizeof(sr_ip_hdr_t));
  533.   ip_hdr->ip_sum = 0x0000;
  534.   ip_hdr->ip_id = 0;
  535.   ip_hdr->ip_off = 0;
  536.   ip_hdr->ip_ttl = 128; /* restricted to same continent */
  537.   ip_hdr->ip_p = ip_protocol_icmp;
  538.   ip_hdr->ip_dst = queued_hdr->ip_src;
  539.   char *outbound_iface = get_lpm(sr, htonl(ip_hdr->ip_dst));
  540.   ip_hdr->ip_src = sr_get_interface(sr, outbound_iface)->ip;
  541.   ip_hdr->ip_sum = cksum((uint8_t *)ip_hdr, sizeof(sr_icmp_t3_hdr_t) + sizeof(sr_ip_hdr_t)); /* compute checksum for ip header */
  542.  
  543.   /*---------------------------------------------------------------------*
  544.    *  create ethernet header                                             *
  545.    *---------------------------------------------------------------------*/
  546.   sr_ethernet_hdr_t *queued_eth_hdr = (sr_ethernet_hdr_t *)(queued_packet);
  547.   memcpy(ethernet_hdr->ether_dhost, queued_eth_hdr->ether_shost, sizeof(uint8_t) * ETHER_ADDR_LEN);
  548.   memcpy(ethernet_hdr->ether_shost, sr_get_interface(sr, outbound_iface)->addr, sizeof(uint8_t) * ETHER_ADDR_LEN);
  549.   ethernet_hdr->ether_type = htons(ethertype_ip);
  550.   sr_send_packet(sr, packet, len, outbound_iface);
  551.   free(packet);
  552.  
  553.   /*---------------------------------------------------------------------*
  554.  *  create icmp header                                                 *
  555.  *---------------------------------------------------------------------*/
  556.   memcpy(icmp_hdr->data, queued_hdr, 8 + sizeof(sr_icmp_hdr_t) + sizeof(sr_ip_hdr_t));
  557.   icmp_hdr->icmp_sum = 0x0000;
  558.   icmp_hdr->icmp_code = code;
  559.   icmp_hdr->icmp_type = type;
  560.   icmp_hdr->icmp_sum = cksum((uint16_t *)icmp_hdr, sizeof(sr_icmp_t3_hdr_t)); /* compute checksum for icmp header */
  561. }
  562.  
  563. char *get_lpm(struct sr_instance *sr, uint32_t ip_dest) /* Longest Prefix Match */
  564. {
  565.   char *iface; /* interface we want to send */
  566.   struct sr_rt *curr_entry = sr->routing_table;
  567.   int highest_bits_matched = 0;
  568.   while (curr_entry != NULL) /* while we have an entry to work with */
  569.   {
  570.     int bits_matched = 0;
  571.     int i;
  572.     for (i = 31; i >= 0; --i)
  573.     {
  574.       int ip_dest_bit = (ip_dest >> i) & 1;
  575.       int curr_entry_bit = (htonl(*(uint32_t *)&curr_entry->dest) >> i) & 1;
  576.       if (ip_dest_bit == curr_entry_bit)
  577.       {
  578.         bits_matched++;
  579.       }
  580.       else
  581.       {
  582.         break;
  583.       }
  584.     }
  585.     if (bits_matched > highest_bits_matched)
  586.     {
  587.       highest_bits_matched = bits_matched;
  588.       iface = curr_entry->interface;
  589.     }
  590.     curr_entry = curr_entry->next;
  591.   }
  592.   if (highest_bits_matched != 32)
  593.   {
  594.     return NULL;
  595.   }
  596.   return iface;
  597. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement