Exemple #1
0
/*---------------------------------------------------------------------
 * Method: process_arp(struct sr_instance* sr,
 *      			         uint8_t * packet,
 *      				 			 unsigned int len,
 *     			     			 char* interface)
 * Scope:  Internal
 *
 * This function processes an arp packe that was received. It handles 
 * two cases, one where it is a request and one where it is a response.
 *
 *---------------------------------------------------------------------*/
void process_arp(struct sr_instance* sr,
       			     uint8_t * packet,
        				 unsigned int len,
       			     char* interface)
{
	struct sr_arpentry *arp_entry;
	struct sr_arpreq *arp_req;
	struct sr_arp_hdr *arp_hdr;
	struct sr_if* rec_if;
	
	/* Validate the arp packet */
	if (!valid_arp(packet, len))
		return;
	
	/* Is the arp addressed to me? NOTE: I do not follow the RFC recommendation to
	 * update existing cache entries with the received arp packet's ip-mac mapping 
	 * before checking whether the packet was addressed me. This is because we do 
	 * not have a good way to strictly 'update' cache entries without inserting a new 
	 * one and I would like to avoid duplicate valid cache entries for the same ip. */
	rec_if = sr_get_interface(sr, interface);
	arp_hdr = arp_header(packet);
	if (rec_if->ip != arp_hdr->ar_tip)
		return;
		
	/* Add the sender's protocol address to my table. */
	arp_entry = sr_arpcache_lookup(&sr->cache, arp_hdr->ar_sip);
	
	/* Arp entry already exists. NOTE: arp_entry is a copy in this case so free it.*/
	if (arp_entry != 0) {
		free(arp_entry);
	
	/* Arp entry doesn't exist so add it. */
	} else {
		arp_req = sr_arpcache_insert(&sr->cache, arp_hdr->ar_sha, arp_hdr->ar_sip);
		
		/* There are packets waiting on this arp request. Send them. */
		if (arp_req != 0) {
			sr_arpreq_send_packets(sr, arp_req);
		}
	}
		
	/* Handle a request. */
	if (arp_opcode(arp_hdr) == arp_op_request) {
		process_arp_request(sr, arp_hdr, rec_if);
	}
}
Exemple #2
0
int arp_validpacket(uint8_t *packet, unsigned int len){

    /* Ensure the packet is long enough */
    if (len < sizeof(struct sr_ethernet_hdr) + sizeof(struct sr_arp_hdr)){
      return 0;
    }

    struct sr_arp_hdr *arp_hdr = arp_header(packet);

    /* Ensure the ARP header setting is correct */
    if (ntohs(arp_hdr->ar_hrd) != arp_hrd_ethernet){
      return 0;
    }
    if (ntohs(arp_hdr->ar_pro) != arp_pro_ip){
      return 0;
    }
    return 1;
}
Exemple #3
0
/*---------------------------------------------------------------------
 * Method: valid_arp(uint8_t * packet, unsigned int len)
 * Scope:  Internal
 *
 * This function processes an arp packet given the full ethernet frame. 
 * It returns true it has a valid length, valid protocol type, hardware type.
 * False otherwise. 
 *
 *---------------------------------------------------------------------*/
int valid_arp(uint8_t *packet, unsigned int len)
{
	struct sr_arp_hdr *arp_hdr;
	
	/* Ensure that the packet is long enough for an arp header */
	if (len < sizeof(struct sr_ethernet_hdr) + sizeof(struct sr_arp_hdr))
		return 0;

	/* Is the hardware type ethernet? */
	arp_hdr = arp_header(packet);
	if (arp_hrd(arp_hdr) != arp_hrd_ethernet)
		return 0;
	
	/* Is it IP? */
	if (arp_pro(arp_hdr) != arp_pro_ip)
		return 0;

	return 1;
}
Exemple #4
0
void arp_handlepacket(struct sr_instance *sr,
        uint8_t *packet,
        unsigned int len,
        char *interface) 
{
    printf("** Recieved ARP packet\n");

    /* Initalize ARP header from the Packet */
    struct sr_arp_hdr *arp_hdr = arp_header(packet);
    /* Interface the packet arrived in */
    struct sr_if *r_iface = sr_get_interface(sr,interface);

    /* Check if interface->ip = arp header->ip */
    if (r_iface->ip != arp_hdr->ar_tip){
      return;
    }

    /* validate ARP packet */
    if (!arp_validpacket(packet, len))
      return;

    if (ntohs(arp_hdr->ar_op) == arp_op_request){

      if(sr_arp_req_not_for_us(sr, packet, len, interface))
        return;

      printf("** ARP packet request to me \n");   
      
      /* Build and send ARP packet  */
      build_arp_reply(sr, arp_hdr, r_iface);
      
    } else if (ntohs(arp_hdr->ar_op) == arp_op_reply) {
        printf("** ARP packet reply to me\n");

        struct sr_arpentry *arp_entry;
        struct sr_arpreq *arp_req;
        struct sr_if *s_interface;
        struct sr_packet *pkt_wait;
        struct sr_packet *temp;
        uint8_t *send_packet;
        unsigned int eth_pkt_len;

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

        if (arp_entry != 0){
          free(arp_entry);
        } else {
            arp_req = sr_arpcache_insert(&sr->cache, arp_hdr->ar_sha, arp_hdr->ar_sip);

            printf("** ARP entry created\n");

            /* Check ARP request queue, if not empty send out packets on it*/
            if (arp_req != 0) {
              pkt_wait = arp_req->packets;

              while (pkt_wait != 0) {

                printf("** ARP resolved, sending queued packets\n");
                /* Send the packets out */
                s_interface = sr_get_interface(sr, pkt_wait->iface);
                struct sr_ethernet_hdr sr_ether_hdr;

                /* Construct the ethernet packet */
                sr_ether_hdr.ether_type = htons(ethertype_ip);
                memcpy(sr_ether_hdr.ether_shost, s_interface->addr, ETHER_ADDR_LEN);
                memcpy(sr_ether_hdr.ether_dhost, arp_hdr->ar_sha, ETHER_ADDR_LEN);

                /* Copy the packet into the sender buf */
                eth_pkt_len = pkt_wait->len + sizeof(struct sr_ethernet_hdr);
                send_packet = malloc(eth_pkt_len);
                memcpy(send_packet, &sr_ether_hdr, sizeof(struct sr_ethernet_hdr));
                memcpy(send_packet + sizeof(struct sr_ethernet_hdr), 
                      pkt_wait->buf, pkt_wait->len);

                sr_send_packet(sr, send_packet, eth_pkt_len, s_interface->name);

                temp = pkt_wait;
                pkt_wait = pkt_wait->next;
                free(temp);
              }

	    printf("** All queued packets sent\n");

            } 
          }   
      }
}