예제 #1
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);
  }
}
예제 #2
0
void process_arp_request( struct sr_instance *sr, const uint8_t *packet, unsigned int len, const char *interface)
{

	assert(sr);
	assert(packet);
	assert(interface);

	arp_hdr* arp = get_arp_hdr(packet, len);
	router_state *rs = get_router_state(sr);

	/* get interface list read lock */
	lock_if_list_rd(rs);

	/* scan the interface list
	 * match the requested ip
	 */
	node* n = get_router_state(sr)->if_list;
	while (n) {
		/* see if we have an interface matching the requested ip */
		if (((iface_entry*)n->data)->ip == arp->arp_tip.s_addr) {
			send_arp_reply(sr, packet, len, (iface_entry*)(n->data));
			break;
		}
		n = n->next;
	}

	/* release the interface list lock */
	unlock_if_list(rs);
}
예제 #3
0
/*
 * Send an arp reply out of the given interface, as a reply to the given packet
 */
void send_arp_reply(struct sr_instance *sr, const uint8_t *packet, unsigned int len, iface_entry* iface) {
	eth_hdr* eth = (eth_hdr*)packet;
	arp_hdr* arp_req = get_arp_hdr(packet, len);

	uint8_t* new_packet = (uint8_t*)malloc(sizeof(eth_hdr) + sizeof(arp_hdr));

	/* Setup the ETHERNET header */
	eth_hdr* new_eth = (eth_hdr*)new_packet;
	populate_eth_hdr(new_eth, eth->eth_shost, iface->addr, ETH_TYPE_ARP);

	/* Setup the ARP header */
	arp_hdr* new_arp = get_arp_hdr(new_packet, sizeof(eth_hdr) + sizeof(arp_hdr));
	populate_arp_hdr(new_arp, arp_req->arp_sha, arp_req->arp_sip.s_addr, iface->addr, iface->ip, ARP_OP_REPLY);

	/* Send the reply */
	if (send_packet(sr, new_packet, sizeof(eth_hdr) + sizeof(arp_hdr), iface->name) != 0) {
		printf("Error sending ARP reply\n");
	}

	free(new_packet);
}
예제 #4
0
/*
  Expects entire ethernet frame and ARP header still in network order.
*/
void handle_arp_request(struct sr_instance *sr, uint8_t *pkt, char *interface) {
  struct sr_if *requested_inf = find_interface_with_ip(sr, ntohl(get_arp_hdr(pkt)->ar_tip));
  if (!requested_inf) {
    /*Only send an arp reply if the target IP is one of the router's IP
  addresses*/
    free(pkt);
    return;
  }

  uint8_t *outgoing_pkt = malloc(sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t));

  sr_ethernet_hdr_t *outgoing_eth_hdr = get_ethernet_hdr(outgoing_pkt);
  sr_arp_hdr_t *outgoing_arp_hdr = get_arp_hdr(outgoing_pkt);

  /*Ethernet*/
  /*src MAC is the outgoing interface's MAC, dest MAC is the src MAC of
    the arp request*/
  memcpy(outgoing_eth_hdr->ether_dhost, get_ethernet_hdr(pkt)->ether_shost, ETHER_ADDR_LEN);
  memcpy(outgoing_eth_hdr->ether_shost, requested_inf->addr, ETHER_ADDR_LEN); 
  outgoing_eth_hdr->ether_type = htons(ethertype_arp);
  
  /*ARP*/
  outgoing_arp_hdr->ar_hrd = htons(arp_hrd_ethernet);
  outgoing_arp_hdr->ar_pro = htons(ethertype_ip);
  outgoing_arp_hdr->ar_hln = ETHER_ADDR_LEN;
  outgoing_arp_hdr->ar_pln = NUM_BYTES_IN_IP_ADDR;
  outgoing_arp_hdr->ar_op = htons(arp_op_reply);
  
  memcpy(outgoing_arp_hdr->ar_sha, requested_inf->addr, ETHER_ADDR_LEN);
  outgoing_arp_hdr->ar_sip = requested_inf->ip;
  memcpy(outgoing_arp_hdr->ar_tha, get_arp_hdr(pkt)->ar_sha, ETHER_ADDR_LEN);
  outgoing_arp_hdr->ar_tip = get_arp_hdr(pkt)->ar_sip;

  sr_send_packet(sr, (uint8_t *)outgoing_pkt, sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t), interface);
  
  /*No reliability guarantee, so don't keep around for a restransmit*/
  free(outgoing_pkt);
  free(pkt);
}
예제 #5
0
void process_arp_packet( struct sr_instance *sr, const uint8_t *packet, unsigned int len, const char *interface) {

	assert(sr);
	assert(packet);
	assert(interface);

	arp_hdr *arp_packet = get_arp_hdr(packet, len);
	switch(ntohs(arp_packet->arp_op)) {

		case ARP_OP_REQUEST:
			process_arp_request(sr, packet, len, interface);
			break;

		case ARP_OP_REPLY:
			process_arp_reply(sr, packet, len, interface);
			break;

		default: return;
	}
}
예제 #6
0
void process_arp_reply( struct sr_instance *sr, const uint8_t *packet, unsigned int len, const char *interface)
{

	assert(sr);
	assert(packet);
	assert(interface);

	router_state *rs = get_router_state(sr);

	/* update the arp cache */
	arp_hdr *arp = get_arp_hdr(packet, len);

	lock_arp_cache_wr(rs);
	update_arp_cache(sr, &(arp->arp_sip), arp->arp_sha, 0);
	unlock_arp_cache(rs);

	lock_arp_cache_rd(rs);
	lock_arp_queue_wr(rs);
	send_queued_packets(sr, &(arp->arp_sip), arp->arp_sha);
	unlock_arp_queue(rs);
	unlock_arp_cache(rs);
}
예제 #7
0
/*
Expects entire ethernet frame, still in network order.
 */
void handle_arp(struct sr_instance *sr, uint8_t *pkt, char* interface, unsigned int len) {
  sr_arp_hdr_t *arp_hdr = get_arp_hdr(pkt);
  unsigned short ar_op = ntohs(arp_hdr->ar_op);

  /*Should at least be this long*/
  if (len < sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t)) {
    free(pkt);
    free(interface);
    return;
  }

  if (ar_op == arp_op_request) {
    handle_arp_request(sr, pkt, interface);
  } else if (ar_op == arp_op_reply) {
    handle_arp_reply(sr, pkt);
  } else {
    free(pkt);
    fprintf(stderr, "invalid arp opcode\n");
  }

  free(interface);

}
예제 #8
0
void print_arp_hdr(const uint8_t *packet, unsigned int len)
{
	assert(packet);

	arp_hdr *arp = get_arp_hdr(packet, len);

	indent(1);
	printf("ARP Packet (%d bytes)\n", sizeof(arp_hdr));
	indent(2);
	printf("Hardware Type: ");
	switch(ntohs(arp->arp_hrd)) {
		case 1: { printf("Ethernet\n"); break; }
		default: { printf("%X\n", ntohs(arp->arp_hrd)); break; }
	}
	indent(2);
	printf("Protocol Type = %X (IP)\n", ntohs(arp->arp_pro));
	indent(2);
	printf("Hardware Address Length = %d\n", arp->arp_hln);
	indent(2);
	printf("Protocol Address Length = %d\n", arp->arp_pln);
	indent(2);
	printf("Opcode = ");
	switch(ntohs(arp->arp_op)) {
		case 1: { printf("Request\n"); break; }
		case 2: { printf("Reply\n"); break; }
		default: { printf("%X\n", arp->arp_op); break; }
	}
	indent(2);
	print_mac_address("Src Hardware Address", arp->arp_sha);
	indent(2);
	print_ip_address("Src Protocol Address", arp->arp_sip);
	indent(2);
	print_mac_address("Dst Hardware Address", arp->arp_tha);
	indent(2);
	print_ip_address("Dst Protocol Address", arp->arp_tip);
}
예제 #9
0
파일: sr_router.c 프로젝트: z23han/router
/* handle/generate ARP packet */
void sr_handle_arppacket(struct sr_instance* sr,
        uint8_t * packet/* lent */,
        unsigned int len,
        char* interface/* lent */) 
{
    assert(sr);
    assert(packet);
    assert(interface);

    /* Get ethernet header */
    sr_ethernet_hdr_t *eth_hdr = (sr_ethernet_hdr_t *)get_eth_hdr(packet);
	if (eth_hdr == NULL) {
		printf("ethernet header NULL!!!\n");
		return;
	}

    /* Get arp header */
    sr_arp_hdr_t *arp_hdr = (sr_arp_hdr_t *)get_arp_hdr(packet);
	if (arp_hdr == NULL) {
		printf("arp header NULL!!!\n");
		return;
	}

    /* Check the arp packet minimum length */
    if (!check_min_length(len, ARP_PACKET_LEN)) {
        fprintf(stderr, "arp packet length is not enough:(\n");
        return;
    }

    /* check the opcode to see if it is request or reply */
    unsigned short ar_op = ntohs(arp_hdr->ar_op);
    /* Get the connected interface in the router */
    struct sr_if *sr_con_if = sr_get_interface(sr, interface);
	/* Get the detination interface in the router */
	
	/* If the connected interface exists, because arp has to be the connected interface */
    if (sr_con_if) {
        /* ********** ARP request ********** */
        /* Construct an arp reply and send it back */
        if (ar_op == arp_op_request) {
            /*fprintf(stderr, "********** ARP REQUEST **********\n");  ar_op = 1 */
            /* Set the back-packet length */
            int packet_len = ARP_PACKET_LEN;
            uint8_t *arp_reply_hdr = (uint8_t *)malloc(packet_len);

            /* Create ethernet header */
            create_ethernet_hdr(eth_hdr, (sr_ethernet_hdr_t *)arp_reply_hdr, sr_con_if);

            /* Create arp header */
            create_back_arp_hdr(arp_hdr, (sr_arp_hdr_t *)((unsigned char *)arp_reply_hdr+ETHER_PACKET_LEN), sr_con_if);

            /* Send APR reply */
            sr_send_packet(sr, /*(sr_ethernet_hdr_t *)*/arp_reply_hdr, packet_len, sr_con_if->name);
            free(arp_reply_hdr);
            return;
        }
        /* ********** ARP reply ********** */
        /* Cache it, go thru my request queue and send outstanding packets */
        else if (ar_op == arp_op_reply) {
            /*fprintf(stderr, "********** ARP REPLY **********\n");   ar_op = 2 */
            /* cache first, and send all the packets in the queue with ip->mac mapping!!! */
            handle_arpreply(arp_hdr, sr);
            return;
        }
        /* ********** Otherwise, error! ********** */
        else {
            fprintf(stderr, "Invalid arp type!!!\n");
            return;
        }
    } else {
        fprintf(stderr, "Router doesnt have this interface, drop it!\n");
        return;
    }
    
    return;
}