Example #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);
    }
}
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++;
		}
    }
}
Example #3
0
/*
Expects entire ethernet frame and ARP header still in network order.
 */
void handle_arp_reply(struct sr_instance *sr, uint8_t *pkt) {

  struct sr_if *requested_inf = find_interface_with_ip(sr, ntohl(get_arp_hdr(pkt)->ar_tip));
  if (!requested_inf) {
    /*Only cache entry if the target IP is one of the router's addresses*/
    return;
  }

  struct sr_arpreq *arpreq = sr_arpcache_insert(&(sr->cache), get_arp_hdr(pkt)->ar_sha, get_arp_hdr(pkt)->ar_sip);

  if (arpreq) {
    struct sr_packet *outgoing_pkt = arpreq->packets;
    while (outgoing_pkt) {
      sr_ethernet_hdr_t *eth_hdr = get_ethernet_hdr(outgoing_pkt->buf);
      
      sr_arp_hdr_t *incoming_arp_hdr = get_arp_hdr(pkt);
      
      memcpy(eth_hdr->ether_dhost, incoming_arp_hdr->ar_sha, ETHER_ADDR_LEN);
      sr_send_packet(sr, outgoing_pkt->buf, outgoing_pkt->len, outgoing_pkt->iface);

      outgoing_pkt = outgoing_pkt->next;
    }
    free(pkt);
    sr_arpreq_destroy(&(sr->cache), arpreq);
  }
}
Example #4
0
void processArp(struct sr_instance *sr , uint8_t *packet, unsigned int len, char *interface) {

	struct sr_arp_hdr *arpHeader = (struct sr_arp_hdr *) (packet + sizeof(struct sr_ethernet_hdr));

	/* Put ARP header into cache */
	struct sr_arpreq *req = sr_arpcache_insert(&(sr->cache), arpHeader->ar_sha, ntohl(arpHeader->ar_sip));
	if (req != NULL) {

		/* Found requests in queue waiting for this reply. Send all waiting packets */ 
		struct sr_packet *waiting = req->packets;
		struct sr_rt *rt = findLongestMatchPrefix(sr->routing_table, htonl(req->ip));

		while (waiting != NULL) {
			send_packet_to_dest(sr, waiting->buf, waiting->len, rt->interface, arpHeader->ar_sha, arpHeader->ar_sip);
			waiting = waiting->next;
		}

		/* Destroy arp request when complete */
		sr_arpreq_destroy(&(sr->cache), req);
	}

	if (ntohs(arpHeader->ar_op) == arp_op_request) {
		/* Reply to sender with our information */
		arp_send_reply(sr, packet, len, interface);
	}

}
Example #5
0
/*Does all handling of incoming ARP packets, returns 1 if successful*/
int handle_ARP_packet(struct sr_instance* sr, 
		      uint8_t* packet,
		      int len, 
		      char* interface){
  int minLenARP = sizeof(struct sr_ethernet_hdr) + sizeof(struct sr_arp_hdr); 
  if (len < minLenARP){
      fprintf(stderr, "Failed to access ARP header, too small\n");
      drop_packet = 1;
      //return;
    }
    if (drop_packet == 0){
      if (destinedToRouter(dest_ip)){
	sr_ethernet_hdr_t* ethernet_hdr = (sr_ethernet_hdr_t*)packet;
	sr_arp_hdr_t* arp_header = (sr_arp_hdr_t*)(packet + (uint8_t) eth_size);

	if (ntohl(arp_header->ar_op) == arp_op_reply){//We have a ARP reply
	  //process reply
	  //move entries from ARP request queue to ARP cache
	  struct sr_arpreq* req;
	  req = sr_arpcache_insert(&(sr->cache), arp_header->ar_sha,
				   ntohl(arp_header->ar_sip));
	  if (req!=NULL){
	     struct sr_packet* traverser = req->packets;
	     while(traverser != NULL){
	       //normal IP forward, no errors detected
	       //change old contents
	       struct sr_arpentry *arp_entry;
	       arp_entry = sr_arpcache_lookup(&(sr->cache),dest_ip);
	       sr_ip_hdr_t* ip_header = (sr_ip_hdr_t*)(packet + (uint8_t) eth_size);
	       sr_ethernet_hdr_t* out_eth = (sr_ethernet_hdr_t*)packet;
	       uint16_t modCksum = cksum(ip_header, sizeof(struct sr_ip_hdr));
	       int ret = ip_forward(sr,packet,len,out_eth,arp_entry->mac,
				    dest_ip, modCksum,interface);
	       if (ret!= 0){
		 fprintf(stderr, "Didn't send ip packet properly\n");

	       }

	       traverser = traverser->next;
	     }
	     sr_arpreq_destroy(&(sr->cache), req);
	  }
	}else{
	  //process ARP request and send reply 
	  //(they want our MAC address) so sends reply packet
	  int ret =  arp_send(sr,packet,len,
			      ethernet_hdr,arp_header,dest_ip);
	  if (ret!= 0){
	    fprintf(stderr, "Didn't send arp packet properly\n");

	  }
	}
      }else{
	//pass
	//forward packet
      }
    }
    return 1;
}
void sr_handle_arpreq(struct sr_instance *sr, struct sr_arpreq *req) {
	time_t curtime = time(NULL);
	if (difftime(curtime, req->sent) < 1.0) return;
	if (req->times_sent <= 4) {
		/* Find out which interface it's on */
		char *interface = req->packets->iface;
		struct sr_if* iface = sr_get_interface(sr, interface);

		/* Allocate a new packet */
		size_t out_len = ARP_REPLY_SIZE;
		uint8_t *packet_out = malloc(out_len);

		/* ====== Headers ====== */
		/* Allow easy access to the headers */
		sr_ethernet_hdr_t *eth_header_out = (sr_ethernet_hdr_t*) packet_out;
		sr_arp_hdr_t *arp_header_out = 
				(sr_arp_hdr_t*) (packet_out + ARP_HEAD_OFF);

		/* Create the ethernet header */
		char bcast_addr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
		memcpy(eth_header_out->ether_dhost, bcast_addr, 
				ETHER_ADDR_LEN);
		memcpy(eth_header_out->ether_shost, iface->addr, 
				ETHER_ADDR_LEN);
		eth_header_out->ether_type = htons(ethertype_arp);

		/* ====== Body ====== */
		/* Create the ARP packet */
		arp_header_out->ar_hrd = htons(0x1);
		arp_header_out->ar_pro = htons(ethertype_ip);
		arp_header_out->ar_hln = ETHER_ADDR_LEN;
		arp_header_out->ar_pln = IP_ADDR_LEN;
		arp_header_out->ar_op = htons(arp_op_request);
		memcpy(arp_header_out->ar_sha, iface->addr, ETHER_ADDR_LEN);
		arp_header_out->ar_sip = iface->ip;
		char zeroes[] = {0,0,0,0,0,0};
		memcpy(arp_header_out->ar_tha, 
				zeroes, ETHER_ADDR_LEN);
		arp_header_out->ar_tip = req->ip;

		/* Send the packet */
		sr_send_packet(sr, packet_out, out_len, interface);

		free(packet_out);

		return;
	} else {
		struct sr_packet *packet = req->packets;
		while (packet) {
			struct sr_packet *next = packet->next;
			send_icmp_error(sr, packet->buf, packet->len, packet->iface, 3, 1);
			packet = next;
		}
		sr_arpreq_destroy(&(sr->cache), req);
	}

	return;
}
Example #7
0
void handle_arpreq(struct sr_instance *sr, struct sr_arpreq *req) {
        time_t now = time(NULL);
        if(difftime(now, req->sent) > 1.0) {
                /* request timeout */
                if(req->times_sent > 5) {
                        
                        struct sr_packet *packets = req->packets;
                        
                        /* iterate through all packets on queue */
                        while(packets) {
                                uint8_t *reply_packet = 0;
                                sr_ip_hdr_t *ip_hdr = (sr_ip_hdr_t *)(packets->buf+sizeof(sr_ethernet_hdr_t));
                                reply_packet = sr_generate_icmp((sr_ethernet_hdr_t *)packets->buf, ip_hdr, sr_get_interface(sr, packets->iface), 3, 1); /* create ICMP type 3, code 1 (host unreachable) */
                                /* if ICMP packet fails to generate */
                                if(reply_packet == 0) {
                                        fprintf(stderr, "Error: failed to generate ICMP packet\n");
                                }
                                
                                
                                /* send ICMP packet to ip of packet in queue */
                                if(sr_send_packet(sr, reply_packet, sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_t3_hdr_t), (const char*)(packets->iface)) == -1) {
                                        fprintf(stderr, "Error: sending packet failed (handle_arpreq)");
                                }
                                packets = packets->next;
                                free(reply_packet);
                        }
            sr_arpreq_destroy(&(sr->cache), req);
                } else {
                        
                        /* generate ARP packet */
                        struct sr_if *iface = 0;
                        
                        /* if interface is not found */
                        if((iface = sr_get_interface(sr, req->packets->iface)) == 0) {
                                fprintf(stderr, "Error: interface does not exist (handle_arpreq)");
                                return;
                        }
                        
                        uint8_t *arp_pkt = sr_new_arpreq_packet(NULL, iface->addr, req->ip, iface->ip); /* create ARP request packet to re-send */

                        /* send ARP request packet */
                        if (sr_send_packet(sr, arp_pkt, sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t), (const char*)(iface->name))==-1) {
                                fprintf(stderr, "Error: sending packet failed.");
                        }

                        /* update arpreq fields */
                        req->times_sent++;
                        req->sent = now;
                        
                        free(arp_pkt);
                }
        }
}
Example #8
0
int sr_handle_arpreq(struct sr_instance *sr, struct sr_arpreq *request){
   time_t now = get_now(&now);
   struct sr_packet * packetptr = request->packets;
   int i;

   if(difftime(now, request->sent) > 1.0){
      if(request->times_sent >= 5){
         while(packetptr != NULL){
             icmp_send_reply(sr, (uint8_t *)packetptr, packetptr->len, packetptr->iface, 3, 1); /* send unreachable */

             packetptr = packetptr->next;
         }
         sr_arpreq_destroy(&(sr->cache), request);
         return -1;
      }else{
           struct sr_rt* entry;
           struct sr_rt* routing = sr->routing_table;

           for(entry = routing; entry != NULL; entry = routing->next){
             struct sr_if * interface2 = sr_get_interface(sr, entry->interface);
             /*create arp packet*/
             enum sr_arp_opcode opcode = arp_op_request;
             struct sr_packet *raw = malloc(sizeof(struct sr_arp_hdr) + ETHER_HDR_LEN);
             /* may need to memset here*/
             struct sr_ethernet_hdr *eth = (struct sr_ethernet_hdr *)raw;
             struct sr_arp_hdr *req = (struct sr_arp_hdr *)(raw + ETHER_HDR_LEN);

             req->ar_hrd = 0;
             req->ar_pro = 0;
             req->ar_hln = 0;
             req->ar_pln = 0;
             req->ar_op = opcode;
             req->ar_sip = sr->sr_addr.sin_addr.s_addr;
             req->ar_tip = request->ip;

             for (i = 0; i < ETHER_ADDR_LEN; i++){
                 req->ar_tha[i] = 0xff;
                 req->ar_sha[i] = interface2->addr[i];
                 eth->ether_dhost[i] = 0xff;
                 eth->ether_shost[i] = interface2->addr[i];
             }

             /*send packet to the interface on routing_table*/
             sr_send_packet(sr, (uint8_t *)raw, sizeof(struct sr_arp_hdr) + ETHER_HDR_LEN, request->packets->iface);

             free(raw);
            }
         request->sent = now;
         request->times_sent++;
      }
   }
   return 0;
}
Example #9
0
/*
The handle_arpreq() function is a function you should write, and it should
handle sending ARP requests if necessary:

function handle_arpreq(request):
    if difftime(now, request->sent) > 1.0
        if request->times_sent >= 5:
            send icmp host unreachable to source addr of all pkts waiting
              on this request
            arpreq_destroy(request)
        else:
            send arp request
            request->sent = now
            request->times_sent++

*/
void handle_arpreq(struct sr_instance *sr, struct sr_arpreq *request){
    //assert(sr);
    //assert(request);

	// If time since last sent is more than 1 second
    if (difftime(time(NULL), request->sent) >= 1.0) {

		/* If an ARP request has been sent 5 times with no response,
		a destination host unreachable should go back to all the sender of packets that were waiting on
		a reply to this ARP request. */
        if (request->times_sent >= 5) {

			// Iniitalize variables for the loop
            struct sr_packet *packetPointer = NULL;
            sr_ethernet_hdr_t *ethernetHeader = NULL;
            struct sr_if *interface = NULL;

			// get a pointer to a array of all packets waiting
            packetPointer = request->packets;

			// For every xender of packets waiting, send host unreachable
            while (packetPointer != NULL) {
                ethernetHeader = (sr_ethernet_hdr_t *)(packetPointer->buf);
                interface = getAddressInterface(sr, ethernetHeader->ether_dhost);

                /* do not send an ICMP message for an ICMP message */
				// If we got an interface of a waiting sender, send the ICMP host unreachable
                if (interface) {
                    sendICMP(sr, packetPointer->buf, packetPointer->len, DESTINATION_UNREACHABLE, HOST_UNREACHABLE_CODE);
                }

				// Go to the next exisiting packet
                packetPointer = packetPointer->next;
            }
            sr_arpreq_destroy(&(sr->cache), request);
        }

		// Otherwise, just send arp request with its sent time = now and increment times sent
		else {
            struct sr_if *sendingInterface = sr_get_interface(sr, request->packets->iface);
            arpRequest(sr, sendingInterface, request->ip);

			// Set sent time to NOW
            request->sent = time(NULL); // time(NULL) = NOW

			// Increment # of times sent
            request->times_sent = request->times_sent + 1;
        }
    }
}
Example #10
0
void handle_arpreq(struct sr_instance *sr, struct sr_arpreq *req) {
	time_t now = time(NULL);
	if (difftime(now, req->sent) >= 0.9) {
		if (req->times_sent >= 5) {
			struct sr_packet *pkt_pending = req->packets;
			struct sr_if *interface = sr_get_interface(sr, pkt_pending->iface);
			while (pkt_pending) {
				icmp_handler(sr, pkt_pending->buf, 0, interface->ip, HOST_UNREACHABLE);
				pkt_pending = pkt_pending->next;
			}
			sr_arpreq_destroy(&(sr->cache), req);
		}
		else {
			int packet_len = sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t);
			uint8_t *pkt = malloc(packet_len);

			struct sr_ethernet_hdr *eth_hdr = (struct sr_ethernet_hdr *)pkt;
			struct sr_if *interface = sr_get_interface(sr, req->packets->iface);
			uint8_t hrd_addr[ETHER_ADDR_LEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
			enum sr_ethertype eth_arp = ethertype_arp;
			enum sr_ethertype eth_ip = ethertype_ip;

			memcpy(eth_hdr->ether_dhost, hrd_addr, ETHER_ADDR_LEN);
			memcpy(eth_hdr->ether_shost, interface->addr, ETHER_ADDR_LEN);
			eth_hdr->ether_type = htons(eth_arp);

			struct sr_arp_hdr *arp_hdr = (struct sr_arp_hdr *)(sizeof(sr_ethernet_hdr_t) + pkt);
			enum sr_arp_hrd_fmt hrd_eth = arp_hrd_ethernet;
			enum sr_arp_opcode arp_op_req = arp_op_request;

			arp_hdr->ar_hrd = htons(hrd_eth);
			arp_hdr->ar_pro = htons(eth_ip);
			arp_hdr->ar_hln = ETHER_ADDR_LEN;
			arp_hdr->ar_pln = 4;
			arp_hdr->ar_op = htons(arp_op_req);
			arp_hdr->ar_sip = interface->ip;
			arp_hdr->ar_tip = req->ip;
			memcpy(arp_hdr->ar_sha, interface->addr, ETHER_ADDR_LEN);
			memcpy(arp_hdr->ar_tha, hrd_addr, ETHER_ADDR_LEN);

			printf("Sending Packets.. [3].\n");

			sr_send_packet(sr, pkt, packet_len, interface->name);
			free(pkt);
			req->sent = now;
			req->times_sent++;
		}
	}
}
Example #11
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*/
}
Example #12
0
void handle_arpreq(struct sr_instance* sr, struct sr_arpreq *cache_req_ptr) {

  char *iface_name = cache_req_ptr->packets->iface;
  struct sr_if *interface = sr_get_interface(sr, iface_name);

  /*Only broadcast if this hasn't been sent out before: 
   *Otherwise, our packet has been added to the end of the 
  * request's linkedlist in the cache: do nothing*/
  if (difftime(time(0), cache_req_ptr->sent) > 1.0) {
    if (cache_req_ptr->times_sent >= 5) {
      struct sr_packet *req_pkt_ptr = cache_req_ptr->packets;
      for (; req_pkt_ptr; req_pkt_ptr = req_pkt_ptr->next) {
        send_icmp(sr, req_pkt_ptr->buf, req_pkt_ptr->len, interface, dest_host_unreach_type, dest_host_unreach_code);
      }
      sr_arpreq_destroy(&(sr->cache), cache_req_ptr);
    }
    else {
      /*Create space for the request*/
      uint8_t* eth_pkt_buf = (uint8_t *) malloc(sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t));
      uint8_t* arp_pkt_buf;
      /*Pointers to where different header structs start in the packet*/
      sr_ethernet_hdr_t* req_eth_header = (sr_ethernet_hdr_t*) eth_pkt_buf; /* Allocate mem for reply packet buffer */
      
      /* Copy addresses and type into the ethernet header */
      uint8_t broadcast_addr[ETHER_ADDR_LEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };

      memcpy(req_eth_header->ether_dhost, broadcast_addr, ETHER_ADDR_LEN);
      memcpy(req_eth_header->ether_shost, interface->addr, ETHER_ADDR_LEN);
      req_eth_header->ether_type = ethertype_arp;
      
      /* Convert to network byte ordering */
      hton_eth_hdr(&req_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_req_packet(arp_pkt_buf, cache_req_ptr, interface);

      /* Send the ARP request packet */
      sr_send_packet(sr, eth_pkt_buf, sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t),
        interface->name);
      cache_req_ptr->sent = time(0);
      cache_req_ptr->times_sent++;

      free(eth_pkt_buf);
    }
  }
}
Example #13
0
void sr_recv_arp(struct sr_instance *sr, struct sr_arp_hdr *arp){
    struct sr_arpreq *req = sr_arpcache_insert(&(sr->cache), arp->ar_sha, arp->ar_sip);
    if(req){

        struct sr_packet *packet = req->packets;
        while(packet){

            sr_attempt_send(sr, req->ip, packet->buf, packet->len, packet->iface);


            packet = packet->next;
        }

        sr_arpreq_destroy(&(sr->cache), req);

    }

}
Example #14
0
/*
  Handle ARP request if necessary.
*/
void handle_arpreq(struct sr_instance *sr, struct sr_arpreq *req)
{
    time_t now = time(NULL);

    if (difftime(time(0), req->sent) > 1.0)
    {
        if (req->times_sent >= 5)
        {
            host_unreachable(sr, req);
            sr_arpreq_destroy(&(sr->cache), req);
        }
        else
        {
            sr_arp_request_send(sr, req->ip); 
            req->sent = now;
            req->times_sent++;
        }
    }
}
Example #15
0
void sr_handle_arpreq(struct sr_instance *sr, struct sr_arpreq *req){

    struct sr_arpcache *cache = &(sr->cache);
    time_t now = time(NULL);
    
    if(diff_time(now, req->sent) > 1.0){

        if(req->times_sent >= 5){
            fprintf(stderr, "Sent 5 times, destroying..... \n");
            // Send an ICMP host unreachable to ALL packets waiting
            sr_send_icmp_to_waiting(sr, req);
            sr_arpreq_destroy(cache, req);
        }else{
            //send ARP
            sr_send_arp_req(sr, req->ip);
            req->sent = now;
            req->times_sent++;

        }
    }
}
Example #16
0
void handle_arpreq(struct sr_instance* sr, struct sr_arpreq* req) {
    time_t curtime = time(NULL);
    
    if (difftime(curtime,req->sent) > 1.0) {
        if (req->times_sent >= 5) {
            struct sr_packet* sr_pckt = req->packets;
            
            while (sr_pckt != NULL) {
                send_icmp_destination_host_unreachable(sr, sr_pckt->buf,
                                                       sr_pckt->len);
                sr_pckt = sr_pckt->next;
            }
            sr_arpreq_destroy(&sr->cache, req);
            
            
        } else {
            send_arp_request(sr, req);
            req->sent = curtime;
            req->times_sent = req->times_sent + 1;
        }
        
    }
}
Example #17
0
/*
 * handle arp reply
 */
void sr_handle_arpreply(struct sr_instance* sr, unsigned char *mac, uint32_t ip, struct sr_if* iface)
{
	/*      
	if(ip == 167985324)
	{return;}
	*/
	 Debug("\nhandle_arpreply called\n");
	 Debug("mac: %s, ip: %d, interface: %s", mac, ip, iface->name); 
	    struct sr_arpreq *req = sr_arpcache_insert(&(sr->cache), mac, ip);

	
        struct sr_packet *packet;
        if(req)
		{
            Debug("\nhandle_arpreply -> sending out packets waiting for the arp_reply\n");
	    
            for(packet = req->packets; packet != NULL; packet = packet->next)
			{
		int i;
           	 for (i = 0; i < ETHER_ADDR_LEN; i++)
                        {
                packet->buf[i]= mac[i];
            }
                printf("---------------before send packet----------------\n");
				print_hdrs(packet->buf, packet->len);
				sr_send_packet(sr, packet->buf, packet->len, iface->name);    
                /*printf("--------------------i-------------------------: %d\n", i);i++;*/
				/*free(packet->buf);*/
		
            }

			sr_arpreq_destroy(&(sr->cache), req);
			Debug("Hey, finished sending packets");

        }
}
Example #18
0
void handle_ARP_req(struct sr_instance* sr, struct sr_arpcache* cache, struct sr_arpreq* req_queue)
{
	/* Get the current time */
	time_t time_now = time(NULL);
	if ( difftime(time_now,req_queue->sent) > 1.0 )
	{
		/* If the last request sent time is more than 1 second then send again */
		if( req_queue->times_sent >= 5)
		{
			/* ICMP error, destination host unreachable to all the packets on this queue */
			struct sr_packet* packets = req_queue->packets;
			while( packets ) 
			{
				uint8_t* ip_packet = packets->buf+sizeof(sr_ethernet_hdr_t);
				handle_ICMP(sr,ip_packet,packets->len-sizeof(sr_ethernet_hdr_t),3,1,packets->iface,0);
				packets = packets->next;
			}
			sr_arpreq_destroy(cache,req_queue);
		}
		else
		{
			/* Send ARP request */
			/* Check if there are any packets */
			if( req_queue->packets != NULL )
			{
				/* Get the interface */
				struct sr_if* interf = sr_get_interface(sr,req_queue->packets->iface);
				uint32_t gateway_IP = req_queue->ip;
				ARP_request_send(sr,gateway_IP,interf);
				req_queue->times_sent++;
				req_queue->sent = time_now;
			}
		}
	}

}
Example #19
0
void sr_handle_arpreq(struct sr_instance *sr, struct sr_arpreq *req)
{
    assert(sr);
    assert(req);
    
    if (difftime(time(NULL), req->sent) >= 1.0) {
        if (req->times_sent >= 5) {
            struct sr_packet *pkt = NULL;
            sr_ethernet_hdr_t *eth_hdr = NULL;
            struct sr_if *iface = NULL;
            
            pkt = req->packets;
            
            while (pkt) {
                eth_hdr = (sr_ethernet_hdr_t *)(pkt->buf);
                iface = sr_get_interface_from_addr(sr, eth_hdr->ether_dhost);
                
                /* do not send an ICMP message for an ICMP message */
                if (iface) {
                    sr_send_icmp(sr, pkt->buf, pkt->len, 3, 1);
                }
                
                pkt = pkt->next;
            }
            
            sr_arpreq_destroy(&(sr->cache), req);
        } else {
            struct sr_if *oiface = sr_get_interface(sr, req->packets->iface);
            
            sr_send_arp_request(sr, oiface, req->ip);
            
            req->sent = time(NULL);
            req->times_sent++;
        }
    }
} /* -- sr_handle_arpreq -- */
Example #20
0
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);

	sr_ethernet_hdr_t* eth_header = (sr_ethernet_hdr_t*)packet;
	/* printf("The type is %x\n",ntohs(eth_header->ether_type));*/

	if( ntohs(eth_header->ether_type) == IP_PROTOCOL)
	{
		/* Its an IP Packet */
		printf("Its an IP Packet\n");
		/* Check the checksum of the packet */
		uint8_t* ip_packet = packet + sizeof(sr_ethernet_hdr_t);
		if(check_checksum(ip_packet,sizeof(sr_ip_hdr_t)) == 0)
		{
			/* Handle ICMP Error message */
			return;
		}
		else
		{
			/* Checksum is fine, Now do the functions */
			sr_ip_hdr_t* ip_header = (sr_ip_hdr_t*)ip_packet;
			/*print_hdr_ip(ip_packet);*/
			if( decrement_TTL(ip_header) == 0 )
			{
				/* Send ICMP packet for Time Limit Exceeded*/
				
				ip_header->ip_sum = 0;
				ip_header->ip_ttl = 1;
				ip_header->ip_sum = cksum(ip_packet,sizeof(sr_ip_hdr_t));
				/*make_ICMP_packet();
				make_IP_packet();*/
				/* Check wheather the Destination is this router  */
				if( check_match_all_interfaces ( sr->if_list, ip_header->ip_dst) == 1 )
				{
					printf("I am here in TTL 0 \n\n\\n");
					uint8_t protocol = ip_header->ip_p;
					if( protocol == TCP_PROTOCOL || protocol == UDP_PROTOCOL)
					{
						/* This is having UDP or TCP as payload */
						/* So, just include this packet as payload and send the ICMP packet */
						handle_ICMP(sr,ip_packet,len-sizeof(sr_ethernet_hdr_t),3,3,interface,1);
					}
					else
					{
						/* Its ICMP protocol */
						/* Check if it is echo request , If it is then send echo reply */
						sr_icmp_hdr_t* icmp = (sr_icmp_hdr_t*)(ip_packet+sizeof(sr_ip_hdr_t));
						if( icmp->icmp_type == 8 && icmp->icmp_code == 0)
						{
							
							int length = len - sizeof(sr_ethernet_hdr_t);
							uint8_t* data = 0;
			uint8_t* icmp_start = make_ICMP_packet_echo(ip_packet+sizeof(sr_ip_hdr_t),length-sizeof(sr_ip_hdr_t));
			uint8_t* ip_start = make_IP_packet( *((uint8_t*)ip_header), ip_header->ip_tos, htons(length), \
							ip_header->ip_id,ip_header->ip_off, 64, ip_header->ip_p,\
							ip_header->ip_dst, ip_header->ip_src);
							uint8_t* final_packet = (uint8_t*)malloc(len);
							memcpy(final_packet,ip_start,sizeof(sr_ip_hdr_t));
						memcpy(final_packet + sizeof(sr_ip_hdr_t),icmp_start,\
								length-sizeof(sr_ip_hdr_t));
						free(ip_start);
						free(icmp_start);	
						forward_packet(sr,final_packet,length,interface);
						}
						else
							handle_ICMP(sr,ip_packet,len-sizeof(sr_ethernet_hdr_t),11,0,interface,1);
					}
				}
				else
				{
					handle_ICMP(sr,ip_packet,len-sizeof(sr_ethernet_hdr_t),11,0,interface,0);
				}
				return;
			}
			/* Calculate new checksum after TTL updation */
			ip_header->ip_sum = 0;
			ip_header->ip_sum = cksum(ip_packet,sizeof(sr_ip_hdr_t));

			/*print_hdr_ip(ip_packet);*/
			/* Check if the packet is destined to any of its interfaces */
			/* Dont free this */
			if( check_match_all_interfaces ( sr->if_list, ip_header->ip_dst) == 1 )
			{
				/* Now its destined to router, so router should handle it 
				It Should check for the Transport layer protocol and should appropriately send ICMP packets*/
				router_handle_packet(sr,ip_packet,len-sizeof(sr_ethernet_hdr_t),interface);
			}
			else
			{
				/* 
					Packet is subjected to NAT translation first and then forwarded 
					1) Check if there are any existing sessions for this packet, if any use them to translate the packets
					2) If there aren't any, then allocate a new session and translate the packet.
				*/
				
				forward_packet(sr,ip_packet,len,interface);
			}
		}
	}
	else
	{
		printf("Its an ARP Packet\n");
		/* Its an ARP Packet */

		uint8_t* arp_packet = packet + sizeof(sr_ethernet_hdr_t);
		/* Construct ARP structure */
		sr_arp_hdr_t* arp_header = (sr_arp_hdr_t*)arp_packet;
		
		/* Check if the packet is request to the router */
		int dst_ip = ntohl(arp_header->ar_tip);
		
		struct sr_if* arp_interface = sr_get_interface(sr,interface);
		int interface_ip = ntohl(arp_interface->ip);

		if( dst_ip == interface_ip )
		{
			/* It is destined correctly */

			uint8_t op_code = ntohs(arp_header->ar_op);
		
			if( op_code == 1 )
			{
				/* ARP Request */
				uint8_t* arp_reply_packet;
				arp_reply_packet = (uint8_t*)malloc(sizeof(sr_ethernet_hdr_t)+1500);
				bzero(arp_reply_packet,sizeof(sr_ethernet_hdr_t)+1500);
				/* Create both ethernet and ARP structures */
				sr_ethernet_hdr_t* new_eth = (sr_ethernet_hdr_t*)arp_reply_packet;
				/* Fill in all the details of ethernet frame */
				memcpy(new_eth->ether_dhost,eth_header->ether_shost,sizeof(uint8_t)*6);
				memcpy(new_eth->ether_shost,arp_interface->addr,sizeof(uint8_t)*6);
				new_eth->ether_type = htons(ARP_PROTOCOL);

				/* Fill in all the details of ARP */
				uint8_t* arp_reply_segment  = arp_reply_packet+ sizeof(sr_ethernet_hdr_t);
				memcpy(arp_reply_segment,arp_packet,sizeof(sr_arp_hdr_t));
				sr_arp_hdr_t* arp_reply_structure = (sr_arp_hdr_t*)arp_reply_segment;
				arp_reply_structure->ar_op = htons(2);
				memcpy(arp_reply_structure->ar_sha,arp_interface->addr,sizeof(uint8_t)*6);
				memcpy(arp_reply_structure->ar_tha,eth_header->ether_shost,sizeof(uint8_t)*6);
				arp_reply_structure->ar_sip = arp_interface->ip;
				arp_reply_structure->ar_tip = arp_header->ar_sip;
				/* Now send the packet */
				/* Beaware of the size of the frame, it should not be sizeof(arp_reply_packet)
				But the size used below */
				sr_send_packet(sr,arp_reply_packet,sizeof(sr_ethernet_hdr_t)+1500,interface);
			}
			else if( op_code == 2 )
			{
				/* ARP Reply */
				uint8_t* MAC = (uint8_t*)malloc(sizeof(uint8_t)*6);
				uint32_t IP;
				memcpy(MAC,arp_header->ar_sha,sizeof(uint8_t)*6);
				IP = arp_header->ar_sip;
				struct sr_arpreq* queue = sr_arpcache_insert(&sr->cache,MAC,IP);
				if( queue == NULL )
				{
					assert(queue!=NULL);
				}
				else
				{
					struct sr_packet* packet_i = queue->packets;
					while( packet_i!= NULL )
					{
						sr_ethernet_hdr_t* head = (sr_ethernet_hdr_t*)(packet_i->buf);
						memcpy(head->ether_dhost,MAC,sizeof(uint8_t)*6);
						sr_send_packet(sr,packet_i->buf,packet_i->len,packet_i->iface);
						packet_i = packet_i->next;
					}
					sr_arpreq_destroy(&sr->cache,queue);
				}
			}
		}
	}
}/* end sr_ForwardPacket */
Example #21
0
void sr_handle_arpreq(struct sr_instance* sr /* borrowed */,
			struct sr_arpreq* req /* borrowed */) {
	time_t now = time(NULL);
	if( 1.0 <= difftime(now,req->sent) ) {
		if( 5 <= req->times_sent ) {
			unsigned int len = sizeof(sr_ethernet_hdr_t)+sizeof(sr_ip_hdr_t)+sizeof(sr_icmp_t3_hdr_t);
			uint8_t* buf = (uint8_t*)malloc(len);
			struct sr_rt* rt_match = 0;
			sr_ip_hdr_t* ip_hdr = 0;
			sr_ethernet_hdr_t* eth_hdr = 0;
			struct sr_if* if_to_send = 0;

			assert(buf);

			while(req->packets) {
				ip_hdr = (sr_ip_hdr_t*)(req->packets->buf+sizeof(sr_ethernet_hdr_t));
				eth_hdr = (sr_ethernet_hdr_t*)(req->packets->buf);
				rt_match = sr_get_longest_rt_table_match(sr->routing_table,ip_hdr->ip_src);

				if(rt_match) {
					if_to_send = sr_get_interface(sr,rt_match->interface);
					prepare_icmp_t3_hdr( (sr_icmp_t3_hdr_t*)( buf+(len-sizeof(sr_icmp_t3_hdr_t)) ), 0x03 /* type */, 0x01/* code */, ip_hdr );
					/* Note: Not looking at rt_table for mac, just reusing mac->IP from existing queued packet */
					prepare_ipv4_hdr((sr_ip_hdr_t*)(buf+sizeof(sr_ethernet_hdr_t)),0x00 /* TOS */, len-sizeof(sr_ethernet_hdr_t), 0x0000 /* ID */, IP_DF /* offset */, ip_protocol_icmp /* protocol */, ntohl(if_to_send->ip) /* source */ ,ntohl(ip_hdr->ip_src) /* destination */);
					prepare_eth_hdr((sr_ethernet_hdr_t*)buf, eth_hdr->ether_shost /* destination */, if_to_send->addr /* sender */, ethertype_ip);
					
					sr_send_packet(sr,buf,len,rt_match->interface);
				}
				req->packets = req->packets->next;
			}
			free(buf);
			fprintf(stderr,"Sent ICMP host not reachable (type 3, code 1)\n");
			sr_arpreq_destroy(&sr->cache,req);
		}
		else {
			/* Send a ARP request */
			unsigned int len = sizeof(sr_ethernet_hdr_t)+sizeof(sr_arp_hdr_t);
            uint8_t* buf = (uint8_t*)malloc(len);
			struct sr_if* if_to_send = sr_get_interface(sr,req->packets->iface);

			assert(buf);
            sr_ethernet_hdr_t* eth_hdr = (sr_ethernet_hdr_t*)buf;
            sr_arp_hdr_t* arp_req = (sr_arp_hdr_t*)(buf+sizeof(sr_ethernet_hdr_t));

            /* Prepare Ethernet Header */
            memset(eth_hdr->ether_dhost,0xff,ETHER_ADDR_LEN);
            memcpy(eth_hdr->ether_shost,if_to_send->addr,ETHER_ADDR_LEN);
            eth_hdr->ether_type = htons(ethertype_arp);

            /* Prepare ARP request */
            arp_req->ar_hrd = htons(arp_hrd_ethernet);
            arp_req->ar_pro = htons(ethertype_ip);
            arp_req->ar_hln = ETHER_ADDR_LEN;
            arp_req->ar_pln = 0x04;
            arp_req->ar_op = htons(arp_op_request);
            memcpy(arp_req->ar_sha,if_to_send->addr,ETHER_ADDR_LEN);
            arp_req->ar_sip = if_to_send->ip;
            memset(arp_req->ar_tha,0xff,ETHER_ADDR_LEN);
            arp_req->ar_tip = req->ip;
			fprintf(stderr, "Sending ARP request\n");
			sr_send_packet(sr,buf,len,if_to_send->name);
			free(buf);

			req->sent = time(NULL);
			req->times_sent++;
		}
	}
}
Example #22
0
void sr_handle_arp_packet(struct sr_instance* sr,
        uint8_t * packet/* lent */,
        unsigned int len,
        char* interface/* lent */,
        struct sr_if* iface)
{
  if (len < (sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t)))
  {
    printf("Invalid ARP packet, insufficient length.\n");
    return;
  }

  /* ARP header */
  sr_arp_hdr_t *arp_hdr = (sr_arp_hdr_t *)(packet + sizeof(sr_ethernet_hdr_t));
  
  if (arp_hdr->ar_tip == iface->ip)
  {
    /* Received ARP Request */
    if (ntohs(arp_hdr->ar_op) == arp_op_request) 
    {
      /* Contruct ARP reply */
      printf("Received ARP request. Reply is being sent.\n");

      uint8_t* reply_arp_packet = (uint8_t *) malloc(sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t));
      sr_ethernet_hdr_t* reply_ethernet_hdr = (sr_ethernet_hdr_t*)reply_arp_packet;
      sr_arp_hdr_t* reply_arp_hdr = (sr_arp_hdr_t*)(reply_arp_packet + sizeof(sr_ethernet_hdr_t));

      /* Ethernet header */
      memcpy(reply_ethernet_hdr->ether_dhost, arp_hdr->ar_sha, ETHER_ADDR_LEN);
      memcpy(reply_ethernet_hdr->ether_shost, iface->addr, ETHER_ADDR_LEN);
      reply_ethernet_hdr->ether_type = htons(ethertype_arp);

      /* ARP Header */
      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 = IP_ADDR_LEN;
      reply_arp_hdr->ar_op = htons(arp_op_reply);
      memcpy(reply_arp_hdr->ar_sha, iface->addr, ETHER_ADDR_LEN);
      reply_arp_hdr->ar_sip = iface->ip;
      memcpy(reply_arp_hdr->ar_tha, arp_hdr->ar_sha, ETHER_ADDR_LEN);
      reply_arp_hdr->ar_tip = arp_hdr->ar_sip;

      /* Send reply packet */
      sr_send_packet(sr, (uint8_t*)reply_arp_packet, (sizeof(sr_ethernet_hdr_t) 
        + sizeof(sr_arp_hdr_t)), interface);

      free(reply_arp_packet);
    }

    /* Received ARP Reply */
    else if (ntohs(arp_hdr->ar_op) == arp_op_reply)
    {
      /* Insert into ARP cache */
      printf("Received ARP reply. \n");
      struct sr_arpreq* request_pointer = sr_arpcache_insert(&sr->cache, 
        arp_hdr->ar_sha, ntohl(arp_hdr->ar_sip));

      if (request_pointer != NULL)
      {
        /* Send all oustanding packets from request */
        while (request_pointer->packets != NULL)
        {
          /* Set new Ethernet frame destination address */
          struct sr_packet* current_packet = request_pointer->packets;
          memcpy(
            ((sr_ethernet_hdr_t*) current_packet->buf),
            arp_hdr->ar_sha, ETHER_ADDR_LEN);

          sr_send_packet(sr, (uint8_t*)current_packet->buf, current_packet->len, current_packet->iface);

           /* Iterate to the next packet */
          request_pointer->packets = request_pointer->packets->next;

          /* Free sent packets */
          free(current_packet->buf);
          free(current_packet->iface);
          free(current_packet);
        }
        sr_arpreq_destroy(&sr->cache, request_pointer);
      }
      else
      {
        printf("Received ARP reply, missing associated ARP request.");
      }
    }
  }
}
Example #23
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;

}
Example #24
0
/* Helper function to handle ARP requests */
void handle_arpreq(struct sr_instance *sr, struct sr_arpreq *req) {
  time_t curtime = time(NULL);
  struct sr_packet *packet;
  struct sr_arpcache *cache = &(sr->cache);

  if (difftime(curtime, req->sent) > 1.0) { 
    /* send icmp host unreachable to source addr of all pkts waiting on this request  */
    if (req->times_sent >= 5) {
      for (packet = req->packets; packet != NULL; packet = packet->next) {
        assert(packet->buf);
        sr_ip_hdr_t *ipDropped = (sr_ip_hdr_t *) (packet->buf + 14); 

        struct sr_if* iface;
        iface = sr_get_interface(sr, packet->iface);

        uint8_t *outgoing = malloc(sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_t3_hdr_t));
        sr_ethernet_hdr_t *ethHeader = (sr_ethernet_hdr_t *)outgoing;
        sr_ip_hdr_t *ipHeader = (sr_ip_hdr_t *) (outgoing + 14);  
        
        /* Get ICMP Packet*/
        uint8_t* icmp_packet;
        icmp_packet = createICMP(3, 1, (uint8_t *)ipDropped, ipDropped->ip_len);
        memcpy(outgoing+34, icmp_packet, sizeof(sr_icmp_t3_hdr_t));
        free(icmp_packet);

        /*Setup IP Header*/
        ipHeader->ip_hl = 5;
        ipHeader->ip_v = 4;
        ipHeader->ip_tos = 0;
        ipHeader->ip_id = ipDropped->ip_id;
        ipHeader->ip_dst = ipDropped->ip_src;
        ipHeader->ip_src = iface->ip;
        ipHeader->ip_ttl = INIT_TTL;
        ipHeader->ip_off = htons(IP_DF);
        ipHeader->ip_sum = 0;
        ipHeader->ip_p = 1;
        ipHeader->ip_len = htons(sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_t3_hdr_t));
        ipHeader->ip_sum = cksum((uint8_t *)ipHeader,20);        

        /*Setup Ethernet Header*/
        set_addr(ethHeader, iface->addr, ethHeader->ether_shost);
        ethHeader->ether_type = htons(0x0800);

        sr_send_packet(sr, outgoing, sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_t3_hdr_t), packet->iface);
        free(outgoing);
      }
      sr_arpreq_destroy(&sr->cache, req);
    }

    /* send an arp request */
    else {
      packet = req->packets;
      assert(packet->buf);
      /*struct sr_ethernet_hdr *ethIncoming = (struct sr_ethernet_hdr *)(packet->buf);*/
      sr_ip_hdr_t * ipIncoming = (sr_ip_hdr_t *)((packet->buf) + 14);

      uint8_t * outgoing = (uint8_t*)malloc(sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t));
      sr_ethernet_hdr_t *ethHeader = (sr_ethernet_hdr_t *) outgoing;
      sr_arp_hdr_t * arpHeader = (sr_arp_hdr_t *)(outgoing + sizeof(sr_ethernet_hdr_t));

      /* set ARPHeader to request */
      arpHeader->ar_hrd = htons(0x0001); 
      arpHeader->ar_pro = htons(0x800); 
      arpHeader->ar_op = htons(0x0001);
      arpHeader->ar_hln = 0x0006; 
      arpHeader->ar_pln = 0x0004;
      memset(arpHeader->ar_tha, 255, 6);
      arpHeader->ar_tip = ipIncoming->ip_dst;

      /* set Ethernet Header */
      ethHeader->ether_type = htons(0x0806);
      memset(ethHeader->ether_dhost, 255,6);

      /* get outgoing interface and send the request */
      struct sr_if* if_walker = 0;
      if_walker = sr->if_list;

      while(if_walker)
      {
        arpHeader->ar_sip = if_walker->ip;
        memcpy(arpHeader->ar_sha, if_walker->addr, 6);
        memcpy(ethHeader->ether_shost, if_walker->addr, 6);

        sr_send_packet(sr, outgoing, sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t), if_walker->name);
        
        if_walker = if_walker->next;
      }

      free(outgoing);
      req->sent = curtime;
      req->times_sent++;
    }
  }
}
Example #25
0
void sr_handle_arpreq(struct sr_instance *sr, struct sr_arpreq *req) 
{
    if (difftime(time(0), req->sent) > 0.9) {

      /* Host is not reachable */
      if (req->times_sent >= 5) {

        printf("** Host Unreachable\n");
        
        /* Send ICMP host unreachable*/
        struct sr_packet *ip_packet, *next;
        ip_packet = req->packets;

        if(ip_packet != 0){
          next = ip_packet->next;
        }
        while(ip_packet != 0){
          sr_ip_hdr_t *ip_hdr = (sr_ip_hdr_t *)(ip_packet->buf);
          struct sr_if *s_interface = sr_get_interface(sr, ip_packet->iface);
          uint32_t dst;
          
          /* Send ICMP host unreachable */
          struct sr_ip_hdr send_ip_hdr;
          
          send_ip_hdr.ip_hl = 5;
          send_ip_hdr.ip_v = ip_hdr->ip_v;
          send_ip_hdr.ip_tos = 0;
          send_ip_hdr.ip_id = 0;
          send_ip_hdr.ip_off = htons(IP_DF);
          send_ip_hdr.ip_ttl = 100;
          send_ip_hdr.ip_p = ip_protocol_icmp;
          send_ip_hdr.ip_sum = 0;
          send_ip_hdr.ip_dst = ip_hdr->ip_src;
          send_ip_hdr.ip_src = s_interface->ip;
          dst = ip_hdr->ip_src;
            
          /* Copy the packet over */
          uint8_t *cache_packet;
          uint16_t total_len;
          uint16_t icmp_len;

          icmp_len = sizeof(struct sr_icmp_t3_hdr);
          total_len = ICMP_IP_HDR_LEN_BYTE + icmp_len;
          send_ip_hdr.ip_len = htons(total_len);
          send_ip_hdr.ip_sum = cksum(&send_ip_hdr, ICMP_IP_HDR_LEN_BYTE);

          cache_packet = malloc(total_len);
          struct sr_icmp_t3_hdr icmp_error_packet = icmp_send_error_packet(ip_hdr, code_host_unreach);

          memcpy(cache_packet, &(send_ip_hdr), ICMP_IP_HDR_LEN_BYTE);
          memcpy(cache_packet + ICMP_IP_HDR_LEN_BYTE, &(icmp_error_packet), 
                sizeof(struct sr_icmp_t3_hdr));

          print_hdr_ip(cache_packet);

          struct sr_arpreq *icmp_req;
          struct sr_arpentry *arp_entry;

          /* Check ARP cache  */
          arp_entry = sr_arpcache_lookup(&sr->cache, dst);

          if (arp_entry != 0){
                
            /* Entry exists, we can send it out right now */
            sr_add_ethernet_send(sr, cache_packet, total_len, dst, ethertype_ip);
          } else {

              /* Get the interface at which the original packet arrived */
              struct sr_rt *lpmatch;
              struct sr_if *r_iface;

              lpmatch = longest_prefix_matching(sr, dst);
              r_iface = sr_get_interface(sr, lpmatch->interface);           
              icmp_req = sr_arpcache_queuereq(&sr->cache, dst, 
                                        cache_packet, total_len, r_iface->name);
              sr_handle_arpreq(sr, icmp_req);
            }
          ip_packet = next;
          if(ip_packet != 0){
            next = ip_packet->next;
          } else {
              sr_arpreq_destroy(&sr->cache, req);
          }
        }  
      } else {
          arp_boardcast(sr, req);

	  printf("** APR boardcasted\n");

          req->sent = time(0);
          req->times_sent ++;
        }
    }
}
Example #26
0
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);

  print_hdrs(packet, len);

  sr_arp_hdr_t* arpHdr = (sr_arp_hdr_t*)(packet + sizeof(sr_ethernet_hdr_t));
  sr_ethernet_hdr_t* ethHdr = (sr_ethernet_hdr_t*)packet;
  sr_ip_hdr_t* ipHdr = (sr_ip_hdr_t*)(packet + sizeof(sr_ethernet_hdr_t));
  sr_icmp_hdr_t* icmpHdr = (sr_icmp_hdr_t*)(packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t));
 

  struct sr_rt* route = sr->routing_table;
  struct sr_arpentry* ent;
  char ifBuf[INET_ADDRSTRLEN];
  char ipBuf[INET_ADDRSTRLEN];



  if(strcmp(arpHdr->ar_tha, "\0") == 0){
    sr_arpcache_queuereq(&(sr->cache), arpHdr->ar_tip, packet, len, interface);
    printf("added arpreq to queue.\n\n");
    return;
  }
  printf("arp rep: %d\n", ntohs(arpHdr->ar_op));
  printf("opcode: %d\n", arp_op_reply);
  if(ntohs(arpHdr->ar_op) == arp_op_reply){
    ent = sr_arpcache_lookup(&sr->cache, arpHdr->ar_sip);
    if( ent == NULL){
      //      printf("Added %s to cache\n", ntohl(arpHdr->ar_sip));
      printf("Incoming arp response\n");
      //      sleep(2);
      

      struct sr_arpreq* req = sr->cache.requests;
      printf("%p, %p\n", req, sr->cache.requests);
      while(req != NULL){
	if(req->ip == arpHdr->ar_sip){
	  struct sr_packet* pkt = req->packets;
	  while(pkt != NULL){
	    if(route != NULL){
	      do{
		sr_ip_hdr_t* reqIpHdr = (sr_ip_hdr_t*)(pkt->buf + sizeof(sr_ethernet_hdr_t));
		sr_ethernet_hdr_t* reqEthHdr = (sr_ethernet_hdr_t*)(pkt->buf);
		//      sr_print_routing_entry(route);
		inet_ntop(AF_INET, &route->dest, ifBuf, sizeof(char) * INET_ADDRSTRLEN);
		convert_addr_ip_int(ntohl(reqIpHdr->ip_dst), ipBuf);
		printf("%s dest: %s\n",route->interface, ifBuf);
		printf("ip dest: %s\n", ipBuf);
		if(strcmp(ifBuf, ipBuf) == 0){
		  
		  memcpy(reqEthHdr->ether_shost, (uint8_t*)(sr_get_interface(sr, route->interface)->addr), sizeof(uint8_t) * ETHER_ADDR_LEN);
		  memcpy(reqEthHdr->ether_dhost, (uint8_t*)arpHdr->ar_sha, sizeof(uint8_t) * ETHER_ADDR_LEN);
		  print_hdrs(pkt->buf, pkt->len);
		  sr_send_packet(sr, pkt->buf, pkt->len, &(route->interface));
		  printf("pkt sent down %s\n\n", route->interface);
		  //	  free(ent);
		  //return;
		  break;
		}
		route = route->next;
	      } while(route != NULL);
	      pkt = pkt->next;
	    }

	  }
	  free(ent);
	  sr_arpreq_destroy(&sr->cache, req);
	  break;
	}
	req = req->next;
      }

    }
    sr_arpcache_insert(&(sr->cache), arpHdr->ar_sha, arpHdr->ar_sip);  




    //sr_arpcache_dump(&sr->cache);
    free(ent);
    return;
  }

  ent = sr_arpcache_lookup(&sr->cache, ipHdr->ip_dst);
  route = sr->routing_table;
  //Make and queue requests if dest isn't in arpcache
  if( ent == NULL ){
    if(route != NULL){
      do{
	inet_ntop(AF_INET, &route->dest, ifBuf, 100);
	convert_addr_ip_int(ntohl(ipHdr->ip_dst), ipBuf);
	if(strcmp(ifBuf, ipBuf) == 0){
	  sr_arpcache_queuereq(&sr->cache, ipHdr->ip_dst, packet, len, route->interface);
	  free(ent);
	  return;
	}
	route = route->next;
      } while(route != NULL);
      sr_arpcache_queuereq(&sr->cache, ipHdr->ip_dst, packet, len, "eth1");

    }
  }

  //Forwards packet to interface
  if(route != NULL){
    do{
      //      sr_print_routing_entry(route);
      inet_ntop(AF_INET, &route->dest, ifBuf, sizeof(char) * INET_ADDRSTRLEN);
      convert_addr_ip_int(ntohl(ipHdr->ip_dst), ipBuf);
      printf("%s dest: %s\n",route->interface, ifBuf);
      printf("ip dest: %s\n", ipBuf);
      if(strcmp(ifBuf, ipBuf) == 0){
	
	memcpy(ethHdr->ether_shost, (uint8_t*)(sr_get_interface(sr, route->interface)->addr), sizeof(uint8_t) * ETHER_ADDR_LEN);
	memcpy(ethHdr->ether_dhost, (uint8_t*)ent->mac, sizeof(uint8_t) * ETHER_ADDR_LEN);
	print_hdrs(packet, len);
	sr_send_packet(sr, packet, len, &(route->interface));
	printf("pkt sent down %s\n\n", route->interface);
	free(ent);
	return;
      }
      route = route->next;
    } while(route != NULL);
  }

  free(ent);
  


}/* end sr_ForwardPacket */
Example #27
0
/* Send ARP request if the request in our cache is not sent more than 5 times */
void handle_arpreq (struct sr_arpreq * req, struct sr_instance *sr) {
    struct sr_arpcache *sr_cache = &sr->cache;
    time_t curr_time;
    time(&curr_time);
    double one_sec = 1.0;
    if (difftime(curr_time, req->sent) >  one_sec){
        struct sr_packet *packet = req->packets; 
        /* If packet is sent more than equal or more than 5 times, send ICMP host unreachable message */
        if ((req->times_sent) >= 5) {
            printf("Packet sent more than 5 times\n");
            while (packet) {
                uint8_t *buf = packet->buf;
                char *interface = packet->iface;
                int packet_len  = sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_t3_hdr_t);
                uint8_t *new_packet = malloc(packet_len);  

                /* Get Ethernet header */
                sr_ethernet_hdr_t* eth_hdr = get_eth_hdr(buf);

                /* Get IP header */
                sr_ip_hdr_t * ip_hdr = get_ip_hdr(buf);

                /* Create ethernet header */
                create_ethernet_header (eth_hdr, new_packet, eth_hdr->ether_dhost, eth_hdr->ether_shost, htons(ethertype_ip));
                
                /* Create IP header */
                create_ip_header (ip_hdr, new_packet, sr_get_interface(sr, interface)->ip, ip_hdr->ip_src);

                /* Create ICMP Header */
                create_icmp_type3_header (ip_hdr, new_packet, dest_host_unreachable_type, dest_host_unreachable_code);
     
                /* Look up routing table for rt entry that is mapped to the source of received packet */
                struct sr_rt *src_lpm = sr_routing_lpm(sr, ip_hdr->ip_src);

                /* Send ICMP host unreachable message */
                send_icmp_type3_msg (new_packet, src_lpm, sr_cache, sr, interface, packet_len); 
                
                free(new_packet);

                packet = packet->next;
            }
            sr_arpreq_destroy(sr_cache, req); 
        } else {
            /* Send out arp request */
            struct sr_if *target_iface = sr_get_interface(sr, packet->iface);
            int packet_len = sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t);
            uint8_t *new_packet = malloc(packet_len);

            /* Createn ethernet header */
            sr_ethernet_hdr_t *new_eth_hdr = (sr_ethernet_hdr_t *) new_packet;
            memset(new_eth_hdr->ether_dhost, 255, sizeof(uint8_t)*ETHER_ADDR_LEN);
            memcpy(new_eth_hdr->ether_shost, target_iface->addr, sizeof(uint8_t)*ETHER_ADDR_LEN);
            new_eth_hdr->ether_type = htons(ethertype_arp);

            /* Create ARP header */
            sr_arp_hdr_t *new_arp_hdr = (sr_arp_hdr_t *)(new_packet + sizeof(sr_ethernet_hdr_t));
            new_arp_hdr->ar_hrd = htons(arp_hrd_ethernet);
            new_arp_hdr->ar_pro = htons(ethertype_ip);
            new_arp_hdr->ar_hln = ETHER_ADDR_LEN;
            new_arp_hdr->ar_pln = sizeof(uint32_t);
            new_arp_hdr->ar_op = htons(arp_op_request);
            memcpy(new_arp_hdr->ar_sha, target_iface->addr, sizeof(unsigned char)*ETHER_ADDR_LEN);
            new_arp_hdr->ar_sip = target_iface->ip;
            memset(new_arp_hdr->ar_tha, 255, sizeof(unsigned char)*ETHER_ADDR_LEN);
            new_arp_hdr->ar_tip = req->ip;

            sr_send_packet(sr, new_packet, packet_len, target_iface->name);            
            free(new_packet);
        }
            req->sent = curr_time;
            req->times_sent = req->times_sent + 1;
    }   
}
Example #28
0
void sr_handlepacket(struct sr_instance* sr,
        uint8_t * packet/* lent */,
        unsigned int len,
        char* interface/* lent */)
{
  uint8_t buf[len];
  int cksumtemp = 0;
  int cksumcalculated = 0;
  struct sr_arpentry *entry;
  struct sr_arpreq *req;
  struct sr_arpcache *arp_cache = &(sr->cache);
  struct sr_if *sr_interface;
  struct sr_rt *rt_walker = 0;
  char *temp_if;

  /* REQUIRES */
  assert(sr);
  assert(packet);
  assert(interface);

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

  /* fill in code here */
  sr_ethernet_hdr_t *ethhdr = (sr_ethernet_hdr_t *)packet;
  sr_arp_hdr_t *arphdr = (sr_arp_hdr_t *)(packet + sizeof(sr_ethernet_hdr_t));
  sr_ip_hdr_t *iphdr = (sr_ip_hdr_t *)(packet + sizeof(sr_ethernet_hdr_t));
  sr_icmp_hdr_t *icmphdr = (sr_icmp_hdr_t *)(packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t));

  sr_ethernet_hdr_t *arpreply_ethhdr = (sr_ethernet_hdr_t *)buf;
  sr_arp_hdr_t *arpreply_arphdr = (sr_arp_hdr_t *)(buf + sizeof(sr_ethernet_hdr_t));

  sr_ethernet_hdr_t *tempreq;

  if (len < sizeof(sr_ethernet_hdr_t)) {
    fprintf(stderr, "ETHERNET header is insufficient length\n");
    return;
  }

  if(ethertype(packet) == ethertype_arp) { /* ARP */
    if (len < (sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t))) {
      /* todo: call sr_arp_req_not_for_us, maybe later */
      fprintf(stderr, "ARP header is insufficient length\n");
      return;
    }
    else {
      printf("ARP packet received\n");
      if(ntohs(arphdr->ar_op) == arp_op_request) { /* ARP request */
	printf("\tARP request\n");
	/* send ARP reply */
	sr_interface = sr_get_interface(sr,interface);
	memcpy(buf,packet,len);

	memset(arpreply_ethhdr->ether_dhost,0xff,6);
	memcpy(arpreply_ethhdr->ether_shost,sr_interface->addr,6);
	arpreply_ethhdr->ether_type = htons(ethertype_arp);

	arpreply_arphdr->ar_op = htons(arp_op_reply);
	memcpy(arpreply_arphdr->ar_sha,sr_interface->addr,6);
	arpreply_arphdr->ar_sip = arphdr->ar_tip;
	memcpy(arpreply_arphdr->ar_tha,arphdr->ar_sha,6);
	arpreply_arphdr->ar_tip = arphdr->ar_sip;
	sr_send_packet(sr,buf,len,interface);

	printf("\tARP reply sent\n");
		/* sr_arpcache_dump(arp_cache); */
      }
      else if(ntohs(arphdr->ar_op) == arp_op_reply) { /* ARP reply */
	printf("\tARP reply\n");
	/* cache IP->MAC mapping and check if arp req in queue */
	req = sr_arpcache_insert(arp_cache,arphdr->ar_sha,ntohs(arphdr->ar_sip));
	tempreq = (sr_ethernet_hdr_t *)req->packets->buf;
	memcpy(tempreq->ether_dhost,ethhdr->ether_shost,6);
	if(req != NULL) {
	  /* send outstanding packets by call */
	  printf("\tARP req in queue\n");
	  sr_send_packet(sr,req->packets->buf,req->packets->len,interface);
	  sr_arpreq_destroy(arp_cache,req);
	}
	else
	  printf("\tARP req not in queue\n");
      }
      else /* not ARP request or reply */
	fprintf(stderr, "Unknown ARP opcode\n");
    }
  }

  else if(ethertype(packet) == ethertype_ip) { /* IP */
    if (len < (sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t))) {
      fprintf(stderr, "IP header is insufficient length\n");
      return;
    }
    else {
      printf("IP packet received\n");
      /* check checksum */
      cksumtemp = iphdr->ip_sum;
      iphdr->ip_sum = 0;
      cksumcalculated = cksum((void *)iphdr,4*iphdr->ip_hl);

      if(cksumtemp == cksumcalculated) {
	printf("\tChecksum good!\n");

	/* this part should not be here, it should be called though */
	if(iphdr->ip_ttl <= 1) {
	  fprintf(stderr, "ICMP time exceeded\n"); /* ICMP time exceeded */
	  return;
	}
	else
	  iphdr->ip_ttl -= 1; 
	
	/* update checksum */
	iphdr->ip_sum = cksum((void *)iphdr,4*iphdr->ip_hl);

	/* todo: LPM and find next hop ip, if no match ICMP net unreachable  */

	/* check routing table, save interface */
	rt_walker = sr->routing_table;
	while(rt_walker != NULL) {
	  if(iphdr->ip_dst == (uint32_t)rt_walker->dest.s_addr) { /* checks for dest IP addr, should be LPM ip not ip_dst */
	    temp_if = rt_walker->interface;
	  }
	  rt_walker = rt_walker->next;
	}
	sr_interface = sr_get_interface(sr,temp_if);

	/* check cache to avoid unnecessary arp req */
	entry = sr_arpcache_lookup(arp_cache,ntohs(iphdr->ip_dst)); /* should be LPM ip not ip_dst, but since next hop is destination... */

	if(entry != NULL) { /* cache hit, just send ip packet to next hop*/
	  printf("\tIP->MAC hit\n");
	  sr_send_packet(sr,packet,len,sr_interface);
	  free(entry);
	}
	else { /* cache miss, send ARP req and wait for reply */
	  printf("\tIP->MAC miss\n");
	  if(sr_interface == 0) { /* no match in routing table */
	    fprintf(stderr, "ICMP host unreachable\n");
	    return;
	  }
	  else { /* match in routing table */
	    /* construct arp req with new interface */
	    memset(arpreply_ethhdr->ether_dhost,0xff,6);
	    memcpy(arpreply_ethhdr->ether_shost,sr_interface->addr,6);
	    arpreply_ethhdr->ether_type = htons(ethertype_arp);

	    arpreply_arphdr->ar_hrd = htons(arp_hrd_ethernet);
	    arpreply_arphdr->ar_pro = htons(ethertype_ip);
	    arpreply_arphdr->ar_hln = 0x6;
	    arpreply_arphdr->ar_pln = 0x4;
	    arpreply_arphdr->ar_op = htons(arp_op_request);
	    memcpy(arpreply_arphdr->ar_sha,sr_interface->addr,6);
	    arpreply_arphdr->ar_sip = sr_interface->ip;
	    memset(arpreply_arphdr->ar_tha,0x00,6);
	    arpreply_arphdr->ar_tip = iphdr->ip_dst;

	    memcpy(ethhdr->ether_shost,sr_interface->addr,6);

	    printf("\tARP request sent\n");
	    /* add packet to queue list */
	    req = sr_arpcache_queuereq(arp_cache,ntohs(iphdr->ip_dst),packet,len,sr_interface);
	    handle_arpreq(arp_cache,sr,req,buf,sr_interface);
	  }
	}
      }
      else {
	/* drop packet */
	fprintf(stderr, "\tChecksum bad!\n");
	return;
      }
    }
  }

  else /* not IP or ARP */
    printf("Unrecognized Ethernet Type 0x%X\n",ethertype(packet));
}
Example #29
0
/* 
  This function gets called every second. For each request sent out, we keep
  checking whether we should resend an request or destroy the arp request.
  See the comments in the header file for an idea of what it should look like.
*/
void sr_arpcache_sweepreqs(struct sr_instance *sr) { 
    /* Fill this in */
        /*Have to: go through each arprequest in the queue*/
      /*for each one: "handle" the arp request*/
        /*Handle: if arpreq time == current time => req just made, don't touch*/
        /*        else (time diff >= 1) : */
          /*if # times requested >= 5: need to drop request -> go through each packet for request, and tell the source that host unreachable.  Then destroy arpreq *(careful not to lose next requests on queue!)*/
          /*else(req not brand new but <5 re-sends) : send arprequest again, update time last send and sent count*/

    struct sr_arpreq *sweepreq;
    struct sr_arpreq *prevreq = sr->cache->requests;
    struct sr_nextreq *nextreq;
    /*There are no requests!*/
    if (prevreq == NULL){
      return;
    }
    
    sweepreq = prevreq;
    /*There are still request left*/
    while (sweepreq != NULL){
        if (handle_arpreq(sweepreq) == 1){
          /*request has been sent too many times. Destroy without losing the request queue. Have to point the previous req to the next req*/
          if (prevreq == sweepreq){
            /*Handle the case of the first request*/
            sr->cache->requests = sweepreq->next;
            sweepreq = sweepreq->next;
            nextreq = sweepreg->next;
            sr_arpreq_destroy(prevreq);
            prevreq = sweepreq;
          } else {
            nextreq = sweepreq->next;
            prevreq->next = nextreq;
            sr_arpreq_destroy(sweepreq);
            sweepreq = nextreq;
          }
        } else {
          /*No deletion to be made. Just update previous and current request*/
          prevreq = sweepreq;
          sweepreq = sweepreq->next;
        }
}


/* You should not need to touch the rest of this code. */

/* Checks if an IP->MAC mapping is in the cache. IP is in network byte order.
   You must free the returned structure if it is not NULL. */
struct sr_arpentry *sr_arpcache_lookup(struct sr_arpcache *cache, uint32_t ip) {
    pthread_mutex_lock(&(cache->lock));
    
    struct sr_arpentry *entry = NULL, *copy = NULL;
    
    int i;
    for (i = 0; i < SR_ARPCACHE_SZ; i++) {
        if ((cache->entries[i].valid) && (cache->entries[i].ip == ip)) {
            entry = &(cache->entries[i]);
        }
    }
    
    /* Must return a copy b/c another thread could jump in and modify
       table after we return. */
    if (entry) {
        copy = (struct sr_arpentry *) malloc(sizeof(struct sr_arpentry));
        memcpy(copy, entry, sizeof(struct sr_arpentry));
    }
        
    pthread_mutex_unlock(&(cache->lock));
    
    return copy;
}
Example #30
0
void sr_handlepacket_arp(struct sr_instance* sr,
        sr_ethernet_hdr_t* eth_hdr,
        uint8_t* packet/* not even a malloc pointer */,
        unsigned int len,
        char* interface/* lent */)
{
    /* puts("handling ARP header"); */
    sr_arp_hdr_t *arp_hdr;

    /* REQUIRES */
    assert(packet);

    if (len < sizeof(sr_arp_hdr_t)) {
        /* puts("Ethernet payload (claiming to contain ARP) is smaller than ARP header. Discarding."); */
        return;
    }

    arp_hdr = (sr_arp_hdr_t*)packet;

    char* temp_ip = ip_to_str(arp_hdr->ar_sip);
    /* printf("from (network order) %s\n",temp_ip); */
    free(temp_ip);

    /* Endianness */
    unsigned short ar_op = ntohs(arp_hdr->ar_op);

    switch (ar_op) {

        /*
         * ARP Request handling
         */

        case arp_op_request:
            {
                /* puts("received ARP OP request."); */

                /* The VNS transport layer shouldn't allow any ARP packets that aren't for our
                 * interface, but it's still worth checking, just in case something goes wrong
                 * or *gasp* we write a unit test about it */

                struct sr_if* iface = sr_get_interface(sr, interface);
                if (iface->ip == arp_hdr->ar_tip) {

                    /* Flip around the source and destination IP, keeping both in network order */

                    uint32_t ip_buf = arp_hdr->ar_tip;
                    arp_hdr->ar_tip = arp_hdr->ar_sip;
                    arp_hdr->ar_sip = ip_buf;

                    /* Flip around source and dest MAC on the ETH header */

                    uint8_t ether_buf[ETHER_ADDR_LEN];
                    memcpy(ether_buf,eth_hdr->ether_shost,ETHER_ADDR_LEN);
                    memcpy(eth_hdr->ether_shost,iface->addr,ETHER_ADDR_LEN);
                    memcpy(eth_hdr->ether_dhost,ether_buf,ETHER_ADDR_LEN);

                    /* Flip around eth on ARP header */

                    memcpy(ether_buf,arp_hdr->ar_sha,ETHER_ADDR_LEN);
                    memcpy(arp_hdr->ar_sha,iface->addr,ETHER_ADDR_LEN);
                    memcpy(arp_hdr->ar_tha,ether_buf,ETHER_ADDR_LEN);

                    /* Change ARP operation to a reply */

                    arp_hdr->ar_op = htons(arp_op_reply);

                    /* Send the modified packet back out */

                    /* puts("sending ARP OP reply"); */
                    sr_send_packet(sr, (uint8_t*)eth_hdr, len + sizeof(sr_ethernet_hdr_t), interface);
                }
                else {
                    /* puts("ARP request received that's not for us."); */
                }

                break;
            }

        /*
         * ARP Reply handling
         */

        case arp_op_reply:
            {
                /* puts("received ARP OP reply."); */

                /* Insert the new IP->MAC mapping into the cache, using network endianness for IP */

                struct sr_arpreq* req = sr_arpcache_insert(&(sr->cache),eth_hdr->ether_shost,arp_hdr->ar_sip);

                /* If there were requests waiting on this mapping */

                if (req) {
                    struct sr_packet* packet_walker = req->packets;
                    while (packet_walker) {

                        /* Send the packet, which will do the lookup against the ARP table we just filled with the answer */

                        sr_try_send_ip_packet(sr, packet_walker->ip_dst, packet_walker->ip_src, packet_walker->payload, packet_walker->ip_hdr);

                        /* Remove the reference to the packet on this buffered request */

                        packet_walker->payload = NULL;
                        
                        /* Continue walking the linked list */

                        packet_walker = packet_walker->next;
                    }

                    /* Free the memory associated with these requests */

                    sr_arpreq_destroy(&(sr->cache),req);
                }
                else {
                    /* puts("no cached requests waiting on this ARP."); */
                }
                break;
            }
    }
}