Esempio n. 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);
    }
}
Esempio n. 2
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);
                }
        }
}
Esempio n. 3
0
/*
 * When we want to send an ip packet, we need to firstly check arp acache.
 */
void sr_check_and_send_arp(struct sr_instance* sr, uint8_t* packet, uint32_t next_hop_ip, struct sr_if* out_iface, unsigned int len)
{
        Debug("\ncheck_and_send_arp called\n");
        struct sr_arpentry* entry = sr_arpcache_lookup(&(sr->cache), next_hop_ip); 

        if(entry) 
		{ 
            Debug("\narp_cache hit!\n");
            next_hop_ip = entry->ip;

            int i;
            for (i = 0; i < ETHER_ADDR_LEN; i++)
			{
                packet[i] = entry->mac[i];
            }

            sr_send_packet(sr, packet, len, out_iface->name);

            free(packet);
            free(entry);
        }
        else
		{
            Debug("\narp_cache miss; call handle_arppreq\n");
			struct sr_arpreq* req = sr_arpcache_queuereq(&(sr->cache), next_hop_ip, packet, len, out_iface->name);
			free(packet);
            sr_handle_arpreq(sr, req);
        }
}
Esempio n. 4
0
void arp_respond(struct sr_instance* sr, uint8_t * req_packet, struct sr_if * sr_interface) {
	struct sr_arphdr *req_arp_hdr = (struct sr_arphdr *)(req_packet + sizeof(struct sr_ethernet_hdr));
 	
	/* Setup ethernet frame */
	unsigned int resp_len = sizeof(struct sr_ethernet_hdr) + sizeof(struct sr_arphdr);
	uint8_t *resp_packet = (uint8_t *)construct_ethernet_frame(
		sr_interface->addr, req_arp_hdr->ar_sha, ETHERTYPE_ARP, sizeof(struct sr_arphdr));
	if(resp_packet == NULL) {
		fprintf(stderr, "Failed to construct ethernet frame.\n");
		return;
	}
	
	/* Setup arp packet */
	struct sr_arphdr *resp_arp_hdr = (struct sr_arphdr *)(resp_packet+sizeof(struct sr_ethernet_hdr));
	resp_arp_hdr->ar_hrd = htons(ARPHDR_ETHER);
	resp_arp_hdr->ar_pro = htons(ETHERTYPE_IP);
	resp_arp_hdr->ar_hln = ETHER_ADDR_LEN;
	resp_arp_hdr->ar_pln = IP_ADDR_LEN;
	resp_arp_hdr->ar_op = htons(ARP_REPLY);
	memcpy(resp_arp_hdr->ar_sha, sr_interface->addr, ETHER_ADDR_LEN);
	resp_arp_hdr->ar_sip = sr_interface->ip;
	memcpy(resp_arp_hdr->ar_tha, req_arp_hdr->ar_sha, ETHER_ADDR_LEN);
	resp_arp_hdr->ar_tip = req_arp_hdr->ar_sip;
	
	/* Send packet */
	//printf("*** -> Sending ARP reply packet of length %d.\n", resp_len);
	if(sr_send_packet(sr, resp_packet, resp_len, sr_interface->name)) {
		fprintf(stderr, "Failed to send ARP response packet.\n");
	} else {
		//print_etherinfo(resp_packet);
	    dump(resp_packet, resp_len);
	}
	
	free(resp_packet);
}
Esempio n. 5
0
void cache_add_packet(struct sr_instance * sr, uint8_t * packet, unsigned int length, char * interface, struct in_addr ip) {
	struct in_addr dest_ip = next_hop_ip(sr, ip);
	struct sr_arp_record *record = cache_lookup(sr, dest_ip);
	
	if(record == NULL) {
		// Check to see if there is an outstanding ARP request
		struct sr_arp_request *request = cache_lookup_outstanding(sr, dest_ip);
		if(request == NULL) {
			// Create a new ARP request
			if(arp_request(sr, dest_ip, interface) == 0) {
				request = cache_add_request(sr, dest_ip);
				// Add the recieved message to the outstanding arp request
				cache_add_message(request, packet, length, interface, ip);
			} /* endif: arp request sent succesfully */
			
			else {
				printf("ARP request failed for address %s - dropping packet.\n", inet_ntoa(ip));
			} /* endelse: arp request not sent succesfully */
			
		} /* endif: no outstanding ARP request */
		
		else {
			cache_add_message(request, packet, length, interface, ip);
		} /* endelse: ARP request already outstanding for this ip */
		
	} /* endif: No record */
	
	else {
		// Send packet
		struct sr_ethernet_hdr *eth_hdr = (struct sr_ethernet_hdr *)packet;
		memcpy(eth_hdr->ether_dhost, record->address, ETHER_ADDR_LEN);
		sr_send_packet(sr, packet, length, interface);
	} /* endelse: ARP record already exists */
}
Esempio n. 6
0
/*forwards normal IP packet, returns 1 on success*/
int ip_forward(struct sr_instance* sr,
	       uint8_t* packet,
	       int len,
	       struct sr_ethernet_hdr* ethernet_hdr, 
	       uint8_t dest_mac[], 
	       uint32_t dest_ip,
	       uint16_t cksum,
	       char* interface){
   
   //reuse some of old contents, change some
  //uint8_t a[ETHER_ADDR_LEN];
  int j;
  for(j=0;j<ETHER_ADDR_LEN;j++){
    (ethernet_hdr->ether_dhost)[j] = dest_mac[j];
  }
  struct sr_if* ifRecord = (struct sr_if*)getIfRecord(sr, dest_ip);
 
   //unsigned char addr[ETHER_ADDR_LEN]
   uint8_t addr[ETHER_ADDR_LEN];
   convertMAC(addr, ifRecord->addr);
   //int j;
   for (j=0;j<ETHER_ADDR_LEN;j++){
     (ethernet_hdr->ether_shost)[j] = addr[j];
   }
   sr_ip_hdr_t* ip_header = (sr_ip_hdr_t*)(packet + (uint8_t)eth_size);
   ip_header->ip_sum = htonl(modCksum);
	    
   //Send packet
   int ret = sr_send_packet(sr, packet, len, interface);
   if (ret != 0){
     fprintf(stderr, "Didn't send packet properly\n");
   }
  return ret;
}
Esempio n. 7
0
void sr_send_arp_request(struct sr_instance *sr, struct sr_if *oiface, uint32_t tip)
{
    assert(sr);
    assert(oiface);
    
    unsigned int len = sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t);
    uint8_t *buf = (uint8_t *)malloc(len);
    assert(buf);
    
    sr_ethernet_hdr_t *eth_hdr = (sr_ethernet_hdr_t *)buf;
    sr_arp_hdr_t *arp_hdr = (sr_arp_hdr_t *)(buf + sizeof(sr_ethernet_hdr_t));
    
    /* ethernet header */
    memset(eth_hdr->ether_dhost, 255, ETHER_ADDR_LEN);
    memcpy(eth_hdr->ether_shost, oiface->addr, ETHER_ADDR_LEN);
    eth_hdr->ether_type = htons(ethertype_arp);
    
    /* arp header */
    arp_hdr->ar_hrd = htons(arp_hrd_ethernet);
    arp_hdr->ar_pro = htons(ethertype_ip);
    arp_hdr->ar_hln = ETHER_ADDR_LEN;
    arp_hdr->ar_pln = sizeof(uint32_t);
    arp_hdr->ar_op = htons(arp_op_request);
    memcpy(arp_hdr->ar_sha, oiface->addr, ETHER_ADDR_LEN);
    arp_hdr->ar_sip = oiface->ip;
    memset(arp_hdr->ar_tha, 0, ETHER_ADDR_LEN);
    arp_hdr->ar_tip = tip;
    
    /* print_hdrs(buf, len); */
    sr_send_packet(sr, buf, len, oiface->name);
    free(buf);
} /* -- sr_send_arp_request -- */
Esempio n. 8
0
/*
 * Send ARP request.
 */
void send_arp_request(struct sr_instance *sr, uint32_t dst_ip, char *interface) {
	
	uint8_t *packet = (uint8_t *)malloc(sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t));
	unsigned int len = sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t);
	struct sr_if *rt_if = (struct sr_if *)sr_get_interface(sr, interface);
	uint8_t brdcst_addr[ETHER_ADDR_LEN];
	
	int i = 0;
	for(i; i < ETHER_ADDR_LEN; i++){
		brdcst_addr[i] = 255;
	}
	
	/* Prepare ethernet header. */
	sr_ethernet_hdr_t *ether_hdr = (sr_ethernet_hdr_t *)(packet);
	ether_hdr->ether_type = htons(ethertype_arp);
	memcpy(ether_hdr->ether_shost, rt_if->addr, ETHER_ADDR_LEN);
	memcpy(ether_hdr->ether_dhost, brdcst_addr, ETHER_ADDR_LEN);
	
	/* Prepare ARP header. */
	sr_arp_hdr_t *arp_hdr = (sr_arp_hdr_t *)(packet + sizeof(sr_ethernet_hdr_t));
	arp_hdr->ar_hrd = htons(arp_hrd_ethernet);
	arp_hdr->ar_pro = htons(ethertype_ip);
	arp_hdr->ar_hln = ETHER_ADDR_LEN;
	arp_hdr->ar_pln = 4;
	arp_hdr->ar_op = htons(arp_op_request);
	memcpy(arp_hdr->ar_sha, rt_if->addr, ETHER_ADDR_LEN);
	arp_hdr->ar_sip = rt_if->ip;
	memcpy(arp_hdr->ar_tha, brdcst_addr, ETHER_ADDR_LEN); 
	arp_hdr->ar_tip = dst_ip;
	
	/* Send the packet. */
	sr_send_packet(sr, packet, len, interface);
}
Esempio n. 9
0
void sr_send_arpreq(struct sr_instance *sr, uint32_t ip, struct sr_if* iface) {

    assert(iface);

    const int pktlen = sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t);
    uint8_t* pktbuf = calloc(1, pktlen);

    sr_fill_eth(pktbuf, NULL, iface->addr, ethertype_arp);

    /* Fill ARP Request */
    sr_arp_hdr_t *arp_hdr = (sr_arp_hdr_t *)(pktbuf + sizeof(sr_ethernet_hdr_t));
    arp_hdr->ar_hrd = htons(1);         /* Hardware type : Ethernet(1) */
    arp_hdr->ar_pro = htons(0x0800);    /* Protocol type : ARP (0x0800) */
    arp_hdr->ar_hln = ETHER_ADDR_LEN;
    arp_hdr->ar_pln = 4;
    arp_hdr->ar_op  = htons(arp_op_request);

    /* sender hardware address */
    memcpy(arp_hdr->ar_sha, iface->addr, ETHER_ADDR_LEN);
    arp_hdr->ar_sip = iface->ip;    /* sender ip address */

    /* target hardware address */
    memset(arp_hdr->ar_tha, 0, ETHER_ADDR_LEN);
    arp_hdr->ar_tip = ip;           /* target ip address */

    /* Send ARP Request */
    sr_send_packet(sr, pktbuf, pktlen, iface->name);

    free(pktbuf);
}
Esempio n. 10
0
/*---------------------------------------------------------------------
 * Method: handle_arp_request
 * Scope: local
 *
 * Handles an ARP request sent to an interface.
 *
 *---------------------------------------------------------------------*/
static void handle_arp_request(struct sr_instance *sr, struct sr_ethernet_hdr *ethernet_header,
        struct sr_arphdr *arp_header, char *interface) {
    printf("\tIt's an ARP request!\n");

    // Get the interface address
    struct sr_if* iface = sr_get_interface(sr, interface);
    if ( iface == 0 ) {
        fprintf( stderr, "** Error, interface %s, does not exist\n", interface);
    }

    // Create ARP reply :)
    struct sr_arphdr arp_reply;
    memcpy(&arp_reply, arp_header, sizeof(struct sr_arphdr));
    arp_reply.ar_op = htons(ARP_REPLY);
    memcpy(&arp_reply.ar_sha, iface->addr, ETHER_ADDR_LEN);
    memcpy(&arp_reply.ar_tha, arp_header->ar_sha, ETHER_ADDR_LEN);
    memcpy(&arp_reply.ar_sip, &(arp_header->ar_tip), sizeof(uint32_t));
    memcpy(&arp_reply.ar_tip, &(arp_header->ar_sip), sizeof(uint32_t));

    // Send the reply
    uint8_t *buffer = pack_ethernet_packet(ethernet_header->ether_shost, iface->addr,
            ETHERTYPE_ARP, (uint8_t *) &arp_reply, sizeof(struct sr_arphdr));
    sr_send_packet(sr, buffer, sizeof(struct sr_ethernet_hdr) + sizeof(struct sr_arphdr),
            interface);
}
Esempio n. 11
0
void ARP_request_send(struct sr_instance* sr,uint32_t gateway_IP,struct sr_if* interface)
{
	/* Build both ethernet and ARP header for the request packet */
	uint8_t* packet = (uint8_t*)malloc(sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t));
	
	/* Build ethernet header */
	sr_ethernet_hdr_t* new_eth = (sr_ethernet_hdr_t*)packet;
	
	memcpy(new_eth->ether_shost,interface->addr,sizeof(uint8_t)*6);
	memset(new_eth->ether_dhost,255,sizeof(uint8_t)*6);
	new_eth->ether_type = htons(ARP_PROTOCOL);

	/* Build ARP header */
	sr_arp_hdr_t* arp_reply_structure = (sr_arp_hdr_t*)(packet+sizeof(sr_ethernet_hdr_t));
	
	arp_reply_structure->ar_op = htons(0x0001);
	memcpy(arp_reply_structure->ar_sha,interface->addr,sizeof(uint8_t)*6);
	bzero(arp_reply_structure->ar_tha,sizeof(uint8_t)*6);
	arp_reply_structure->ar_sip = interface->ip;
	arp_reply_structure->ar_tip = gateway_IP;
	arp_reply_structure->ar_pro = htons(0x0800);
	arp_reply_structure->ar_pln = 0x04;
	arp_reply_structure->ar_hrd = htons(0x0001);
	arp_reply_structure->ar_hln = 0x06;
	
	/* Now everything is complete */
	/* Now send the packet */
	sr_send_packet(sr,packet,sizeof(sr_ethernet_hdr_t)+sizeof(sr_arp_hdr_t),interface->name);
}
Esempio n. 12
0
void sr_send_arpreply(struct sr_instance* sr, 
  sr_arp_hdr_t *arp_req,
  struct sr_if* iface) {

  const int pktlen = sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t);
  uint8_t pktbuf[pktlen];

  sr_fill_eth(pktbuf, arp_req->ar_sha, iface->addr, ethertype_arp);

  /* Fill ARP Reply */
  sr_arp_hdr_t *arp_hdr = (sr_arp_hdr_t *)(pktbuf + sizeof(sr_ethernet_hdr_t));
  arp_hdr->ar_hrd = htons(1);         /* Hardware type : Ethernet(1) */
  arp_hdr->ar_pro = htons(0x0800);    /* Protocol type : ARP (0x0800) */
  arp_hdr->ar_hln = ETHER_ADDR_LEN;
  arp_hdr->ar_pln = 4;
  arp_hdr->ar_op  = htons(arp_op_reply);

  /* sender hardware address */
  memcpy(arp_hdr->ar_sha, iface->addr, ETHER_ADDR_LEN);
  arp_hdr->ar_sip = iface->ip; /* sender ip address */

  /* target hardware address */
  memcpy(arp_hdr->ar_tha, arp_req->ar_sha, ETHER_ADDR_LEN);
  arp_hdr->ar_tip = arp_req->ar_sip;     /* target ip address */

  /* Send ARP Reply */
  sr_send_packet(sr, pktbuf, pktlen, iface->name);
}
Esempio n. 13
0
/* Tries to find ip address in arp cache. If found, sends ethernet frame. If not found,
adds packet to arp queue */
void sr_attempt_send(struct sr_instance *sr, uint32_t ip_dest, 
                                        uint8_t *frame,           
                                       unsigned int frame_len,
                                       char *iface){


   struct sr_arpentry *entry = sr_arpcache_lookup(&(sr->cache), ip_dest);

   if (entry){

        unsigned char *mac_address = entry->mac;
        memcpy( ((sr_ethernet_hdr_t *)frame)->ether_dhost, mac_address, ETHER_ADDR_LEN);
        //free packet??
        sr_send_packet(sr, frame, frame_len, iface);

        free(entry);


   }else{
        fprintf(stderr, "Couldn't find entry for: ");
        print_addr_ip_int(ntohl(ip_dest));

       struct sr_arpreq *req = sr_arpcache_queuereq(&(sr->cache), ip_dest, frame, frame_len, iface);
       sr_handle_arpreq(sr, req);
   }
}
Esempio n. 14
0
void sr_icmp_echo_reply(struct sr_instance *sr, uint8_t * packet,
			unsigned int len, char* interface,
			struct sr_ethernet_hdr *e_hdr,
			struct ip *ip_hdr, struct sr_icmphdr *icmp_hdr)
{
  /* Ethernet header */
  uint8_t addr_tmp[6];
  memcpy(addr_tmp, e_hdr->ether_dhost, 6);
  memcpy(e_hdr->ether_dhost, e_hdr->ether_shost, 6);
  memcpy(e_hdr->ether_shost, addr_tmp, 6);

  /* IP header */
  struct in_addr ip_addr_tmp = ip_hdr->ip_src;
  ip_hdr->ip_src = ip_hdr->ip_dst;
  ip_hdr->ip_dst = ip_addr_tmp;
  ip_hdr->ip_sum = 0;
  ip_hdr->ip_sum = checksum(ip_hdr, sizeof(struct ip));

  /* ICMP header */
  icmp_hdr->icmp_type = 0x0;
  icmp_hdr->icmp_chksum = 0x0;
  icmp_hdr->icmp_chksum = checksum((uint16_t *)icmp_hdr,
					ntohs(ip_hdr->ip_len) - 20);
  int success = sr_send_packet(sr, packet, len, interface);
  if (success != 0) {
    fprintf(stderr, "%s: Sending packet failed!\n", __func__);
  }
}
Esempio n. 15
0
void arpq_packets_icmpsend(struct sr_instance *sr, struct packetq *arpq_packets){
    struct queued_packet *current_packet = arpq_packets->first;
    struct frame_t *ICMP_err;
    
    while(current_packet){
        //first, make sure current packet isn't an ICMP error message itself
        if (current_packet->outgoing->ip_header->ip_p == IPPROTO_ICMP){
            current_packet->outgoing->icmp_header = ((void *) current_packet->outgoing->ip_header + 
                                                     current_packet->outgoing->ip_hl);
            uint8_t code = current_packet->outgoing->icmp_header->icmp_type;
            if (code == DEST_UNREACH || code == TIME_EXCEEDED || code == 12 || code == 31)
                //12 and 31 indicate bad IP header and datagram conversion error, respectively
                continue;
        }
        //get back old info so we can send it back the way it came
        current_packet->outgoing->iface = current_packet->from_iface;
        memcpy(current_packet->outgoing->from_MAC, current_packet->from_MAC, ETHER_ADDR_LEN);
        
        ICMP_err = generate_icmp_error(current_packet->outgoing, DEST_UNREACH, HOST_UNREACH);
        
        printf("sending Host Unreachable packets\n");
        sr_send_packet(sr, (uint8_t *)current_packet->outgoing->frame, 
                       current_packet->outgoing->len, 
                       current_packet->from_iface->name);
        
        destroy_frame_t(ICMP_err);
        current_packet = current_packet->next;
    }
}
Esempio n. 16
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);
  }
}
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;
}
Esempio n. 18
0
/*sends packet, checks any errors and frees buffer
 */
void sendPacket(struct sr_instance* sr, uint8_t* buf, char* iface, int len){
  //send out icmp packet now
  //Send packet
  int ret = sr_send_packet(sr, buf, len, iface);
  if (ret != 0){
    fprintf(stderr, "Didn't send packet properly\n");
  }
  free(buf);
 
}
Esempio n. 19
0
int sr_integ_low_level_output(struct sr_instance* sr /* borrowed */,
                             uint8_t* buf /* borrowed */ ,
                             unsigned int len,
                             const char* iface /* borrowed */)
{
#ifdef _CPUMODE_
    return sr_cpu_output(sr, buf /*lent*/, len, iface);
#else
    return sr_send_packet(sr, buf /*lent*/, len, iface);
#endif /* _CPUMODE_ */
} /* -- sr_vns_integ_output -- */
Esempio n. 20
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;
}
Esempio n. 21
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++;
		}
	}
}
Esempio n. 22
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*/
}
Esempio n. 23
0
/*Returns 0 on success and error code on fail*/
int sr_handlearp(struct sr_instance** sr, uint8_t** ethernet_data_addr, struct sr_if* in_f, unsigned int len){
  uint8_t *eth_pkt_buf;
  uint8_t *arp_pkt_buf; /* ARP packet buffer */
  struct sr_if* ret_if; /* return interface */
  printf("sr_handlearp");

  sr_arp_hdr_t* arp_header_buffer = (sr_arp_hdr_t*)*ethernet_data_addr;
  ntoh_arp_hdr(&arp_header_buffer); /* converts header members into host byte order where appropriate */

  /* Recieved ARP request! Reply to request. */
  if(arp_header_buffer->ar_op == arp_op_request) {
    if ((ret_if = sr_get_interface_from_ip(*sr, arp_header_buffer->ar_tip))) { /* Target IP is IP of a Router Interface*/ 
      
      /* Send an ARP reply (uint8_t*) */

      /* Create reply frame */
      eth_pkt_buf = (uint8_t *) malloc(sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t)); /* Allocate mem for reply packet buffer */
      sr_ethernet_hdr_t *req_reply_eth_header = (sr_ethernet_hdr_t *) eth_pkt_buf;

      /* Build Ethernet Header */
      memcpy(req_reply_eth_header->ether_dhost, arp_header_buffer->ar_sha, ETHER_ADDR_LEN);
      memcpy(req_reply_eth_header->ether_shost, in_f->addr, ETHER_ADDR_LEN);
      req_reply_eth_header->ether_type = ethertype_arp;
      /* Convert to network byte ordering */
      hton_eth_hdr(&req_reply_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_packet(&arp_pkt_buf, arp_header_buffer, ret_if); /* Create arp packet to be sent as ARP reply, fill arp_pkt_buf with ARP reply header data */
      
      /* Send the ARP reply packet */
      sr_send_packet(*sr, eth_pkt_buf, sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t), in_f->name);
      free(eth_pkt_buf);


    } else { /* Target IP is *NOT* IP of a Router Interface */
      /* I'm not sure what to do here yet MAYBE NOTHING?!*/
    }
  }

  else if (arp_header_buffer->ar_op == arp_op_reply) {
    handle_arp_reply(*sr, *ethernet_data_addr, in_f);
  }
  


  return 0;
}
Esempio n. 24
0
/* prepare arp into ethernet frame and send it */
int boardcast_arpreq(struct sr_instance *sr, struct sr_arpreq *arp_req){
    struct sr_if *o_interface;
    /*first package the arp package header first...*/
    o_interface = sr_get_interface(sr, arp_req->packets->iface);
    struct sr_arp_hdr arp_hdr;
    uint8_t *arp_package;
    uint8_t *e_pack;
    arp_hdr.ar_hrd = sr_arp_hrd_fmt hfmt = arp_hrd_ethernet;             /* format of hardware address   */
    arp_hdr.ar_pro = 0X800;            /*from http:/*www.networksorcery.com/enp/protocol/arp.htm#Protocol%20address%20length*/
    arp_hdr.ar_hln = ETHER_ADDR_LEN = 8; /*from http:/*www.networksorcery.com/enp/protocol/arp.htm#Protocol%20address%20length*/
    arp_hdr.ar_pln = 8;             /*from http:/*www.networksorcery.com/enp/protocol/arp.htm#Protocol%20address%20length*/
    sr_arp_opcode code = arp_op_request;
    arp_hdr.ar_op = code;              /* ARP opcode (command)         */
    memcpy(arp_hdr.ar_sha, o_interface->addr, ETHER_ADDR_LEN); /* sender hardware address      */
    arp_hdr.ar_sip = o_interface.ip;             /* sender IP address            */
    arp_hdr.ar_tip = arp_req.ip;                 /* target IP address            */
    /*copy everything into the arp_header*/
    arp_package = malloc(sizeof(sr_arp_hdr_t));
    print_hdr_arp(arp_package);
    memcpy(arp_package, &apr_hdr, sizeof(sr_arp_hdr_t));
    /*then package the ethernet header along with the arp header...*/
    e_pack = eth_hdr_package(uint8_t  ether_dhost, sr, o_interface->addr, arp_package, sizeof(struct sr_arp_hdr));
    print_hdr_eth(e_pack);

    /*send it out*/
    sr_send_packet(sr, e_pack, sizeof(struct sr_arp_hdr) + sizeof(struct sr_ethernet_hdr), o_interface);



/* build the ethernet frame to be broadcast */
int eth_hdr_package(uint8_t  ether_dhost, uint8_t  ether_shost, uint16_t ether_type, uint8_t *content, int len){
    uint8_t *output;
    int total_length;
    struct sr_ethernet_hdr e_hdr;
    /*first step is to create a ethernet header...*/
    memcpy(e_hdr.ether_dhost,ether_dhost,ETHER_ADDR_LEN); /* destination ethernet address */
    memcpy(e_hdr.ether_shost,ether_shost,ETHER_ADDR_LEN); /* source ethernet address */
    e_hdr.ether_type = ether_type;
    /*calculate the length of the entire thing...*/
    total_length = sizeof(sr_ethernet_hdr_t) + len;
    /*put everything together*/
    output = malloc(total_length);
    /*put the ethernet header in the front*/
    memcpy(output, &e_hdr, sizeof(sr_ethernet_hdr_t));
    memcpy(output + sizeof(sr_ethernet_hdr_t), content,len);
    return output;
    
}
Esempio n. 25
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);
    }
  }
}
Esempio n. 26
0
void sr_icmp_ttl_exceeded(struct sr_instance *sr, uint8_t * packet,
			  unsigned int len, char* interface,
			  struct sr_ethernet_hdr *e_hdr, struct ip *ip_hdr)
{
  struct sr_if *iface = sr_get_interface(sr, interface);
  
  /* Send ICMP time exceeded message. This is
     need for traceroute to work. */
  uint8_t *new_pkt = (uint8_t *) calloc(1, 70);
  struct sr_ethernet_hdr *new_e_hdr = (struct sr_ethernet_hdr *) new_pkt;
  struct ip *new_ip_hdr = (struct ip *) (new_pkt + 14);
  struct sr_icmphdr *new_icmp_hdr = (struct sr_icmphdr *) (new_pkt + 34);

  /* ethernet header */
  memcpy(new_e_hdr->ether_dhost, e_hdr->ether_shost, 6);
  memcpy(new_e_hdr->ether_shost, e_hdr->ether_dhost, 6);
  new_e_hdr->ether_type = htons(0x0800);

  /* IP header */
  new_ip_hdr->ip_hl = 5;
  new_ip_hdr->ip_v = 4;
  new_ip_hdr->ip_tos = 0;
  new_ip_hdr->ip_len = htons(56);
  new_ip_hdr->ip_id = ip_hdr->ip_id;
  new_ip_hdr->ip_off = ip_hdr->ip_off;
  new_ip_hdr->ip_ttl = 64;
  new_ip_hdr->ip_p = 1;
  new_ip_hdr->ip_src.s_addr = iface->ip;
  new_ip_hdr->ip_dst = ip_hdr->ip_src;
  new_ip_hdr->ip_sum = 0;
  new_ip_hdr->ip_sum = checksum(new_ip_hdr, 20);

  /* ICMP ttl exceeded: type: 11, code: 0 */
  new_icmp_hdr->icmp_type = 11;
  new_icmp_hdr->icmp_code = 0;
  new_icmp_hdr->id = 0;
  new_icmp_hdr->seqno = 0;
  memcpy(new_pkt+42, ip_hdr, 28);
  new_icmp_hdr->icmp_chksum = 0;
  new_icmp_hdr->icmp_chksum = checksum((uint16_t *)new_icmp_hdr, 36);

  int success = sr_send_packet(sr, new_pkt, 70, interface);
  if (success != 0) {
    fprintf(stderr, "%s: Sending packet failed!\n", __func__);
  }
}
Esempio n. 27
0
/*
 * Send an ICMP Error.
 */
void send_icmp_error(uint8_t type, uint8_t code, struct sr_instance *sr, 
					char *interface, unsigned int len, uint8_t *pkt) {
	
	int new_len = sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_t3_hdr_t);
	uint8_t *packet = (uint8_t *) malloc(new_len);
	struct sr_if *rt_if = (struct sr_if *)malloc(sizeof(struct sr_if));
	rt_if = (struct sr_if *)sr_get_interface(sr, interface);
	
	/* Prepare ethernet header. */
	sr_ethernet_hdr_t *ether_hdr = (sr_ethernet_hdr_t *) pkt;
	sr_ethernet_hdr_t *ether_newhdr = (sr_ethernet_hdr_t *) packet;
	ether_newhdr->ether_type = htons(ethertype_ip);
	memcpy(ether_newhdr->ether_shost, rt_if->addr, ETHER_ADDR_LEN);
	memcpy(ether_newhdr->ether_dhost, ether_hdr->ether_shost, ETHER_ADDR_LEN); 	
	
	/* Prepare IP header. */
	sr_ip_hdr_t *ip_hdr = (sr_ip_hdr_t *)(pkt + sizeof(sr_ethernet_hdr_t));
	sr_ip_hdr_t *ip_newhdr = (sr_ip_hdr_t *)(packet + sizeof(sr_ethernet_hdr_t));
	memcpy(ip_newhdr, ip_hdr, sizeof(sr_ip_hdr_t));
	ip_newhdr->ip_src = rt_if->ip;
	ip_newhdr->ip_dst = ip_hdr->ip_src;
	ip_newhdr->ip_len = htons(56);
	ip_newhdr->ip_id = 0;
	ip_newhdr->ip_hl = 5;
	ip_newhdr->ip_off = 0;
	ip_newhdr->ip_ttl = 64;
	ip_newhdr->ip_p = ip_protocol_icmp;
	ip_newhdr->ip_sum = 0;
	ip_newhdr->ip_sum = cksum(packet + sizeof(sr_ethernet_hdr_t), sizeof(sr_ip_hdr_t));							
	
	/* Prepare the ICMP t3 header. */
	sr_icmp_t3_hdr_t *icmp_t3_hdr = (sr_icmp_t3_hdr_t *)(packet + 
									sizeof(sr_ethernet_hdr_t) + 
									sizeof(sr_ip_hdr_t));
	icmp_t3_hdr->icmp_type = type;
	icmp_t3_hdr->icmp_code = code;
	icmp_t3_hdr->icmp_sum = 0;
	memcpy(icmp_t3_hdr->data,  ip_hdr, 20);
	memcpy(icmp_t3_hdr->data + 20, pkt + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t), 8); 
	icmp_t3_hdr->icmp_sum = cksum(packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t), 
							sizeof(sr_icmp_t3_hdr_t));
	
	/* Send the ICMP error packet. */
	sr_send_packet(sr, packet, new_len, interface);
}
Esempio n. 28
0
void sr_icmp_port_unreach(struct sr_instance *sr, uint8_t * packet,
			  unsigned int len, char* interface,
			  struct sr_ethernet_hdr *e_hdr, struct ip *ip_hdr)
{
  /* 70: minimum length for ICMP port unreachable reply. */
  uint8_t *new_pkt = (uint8_t *) calloc(1, 70); // hardcoded constant! anyway...
    
  struct sr_ethernet_hdr *new_e_hdr = (struct sr_ethernet_hdr *) new_pkt;
  struct ip *new_ip_hdr = (struct ip *) (new_pkt + 14);
  struct sr_icmphdr *new_icmp_hdr = (struct sr_icmphdr *) (new_pkt + 34);

  /* ethernet header */
  memcpy(new_e_hdr->ether_dhost, e_hdr->ether_shost, 6);
  memcpy(new_e_hdr->ether_shost, e_hdr->ether_dhost, 6);
  new_e_hdr->ether_type = htons(0x0800);

  /* IP header */
  new_ip_hdr->ip_hl = 5;
  new_ip_hdr->ip_v = 4;
  new_ip_hdr->ip_tos = 0;
  new_ip_hdr->ip_len = htons(56); // hardcoded constant! anyway...
  new_ip_hdr->ip_id = ip_hdr->ip_id;
  new_ip_hdr->ip_off = ip_hdr->ip_off;
  new_ip_hdr->ip_ttl = 64;
  new_ip_hdr->ip_p = 1;
  new_ip_hdr->ip_src = ip_hdr->ip_dst;
  new_ip_hdr->ip_dst = ip_hdr->ip_src;
  new_ip_hdr->ip_sum = 0;
  new_ip_hdr->ip_sum = checksum(new_ip_hdr, 20);

  /* ICMP port unreachable */
  new_icmp_hdr->icmp_type = 3;
  new_icmp_hdr->icmp_code = 3;
  new_icmp_hdr->id = 0;
  new_icmp_hdr->seqno = 0;
  memcpy(new_pkt+42, ip_hdr, 28);
  new_icmp_hdr->icmp_chksum = 0;
  new_icmp_hdr->icmp_chksum = checksum((uint16_t *)new_icmp_hdr, 36);

  int success = sr_send_packet(sr, new_pkt, 70, interface);
  if (success != 0) {
    fprintf(stderr, "%s: Sending packet failed!\n", __func__);
  }
}
Esempio n. 29
0
/*
  Send a host unreachable ICMP to the given source address
*/
void send_echo_reply(uint8_t source_addr, uint8_t *packet, struct sr_instance *sr){
  
  /*Allocate a buffer to hold the packet*/
  uint8_t *buf = malloc(sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t) + sizeof(sr_icmp_hdr_t));
  
  /*Create and send the host unreachable ICMP TO source, telling them that dest was unreachable*/
  /*First have to create the ICMP packet*/
  sr_icmp_t3_hdr_t *icmp_packet = (sr_icmp_hdr_t *)(buf + sizeof(sr_ip_hdr_t) + sizeof(sr_ethernet_hdr_t));
  icmp_packet->icmp_type = 1;
  icmp_packet->icmp_code = 1;
  icmp_packet->icmp_sum = 0;
  icmp_packet->icmp_sum = cksum((const void *)(icmp_packet.icmp_type + icmp_packet.icmp_code), 2);
  print_hdr_icmp(icmp_packet);
  /*Have to craft data.  Data will be the original packet header plus the first 8 bytes of the packet content.*/
  memcpy(icmp_packet->data, packet, ICMP_DATA_SIZE);
  
  /*Now have to form the ip packet to encase the icmp content*/
  sr_ip_hdr_t *ip_packet = (sr_ip_hdr_t *)(buf + sizeof(sr_ethernet_hdr_t));
  ip_packet->ip_p = 1;
  ip_packet->ip_tos;            /* type of service */
  ip_packet->ip_len;            /* total length */
  ip_packet->ip_id;         /* identification */
  ip_packet->ip_off;            /* fragment offset field */
  ip_packet->ip_ttl;            /* time to live */
  ip_packet->ip_p = 1;          /* protocol */
  ip_packet->ip_sum;            /* checksum */
  ip_packet->ip_src = sr->if_list[0]->ip;  /*Assign the packet source to one of the router's interfaces*/
  ip_packet->ip_dst = get_ip_addr(packet);  /*set the packet destination to the original source IP*/
  print_hdr_ip(ip_packet);
  memcpy((void *)arp_packet->ar_sha, (void *)sender_eth, ETHER_ADDR_LEN);
  /*Now make an ethernet frame to wrap the IP packet with the ICMP packet*/
  sr_ethernet_hdr_t *ether_packet = (sr_ethernet_hdr_t *)(buf);
  ether_packet->ether_dhost = source_addr;  /*Set ethernet destination*/
  ether_packet->ether_shost = sr->if_list[0]->addr;  /*Set ethernet source*/
  ether_packet->ether_type = sr_ethertype.ethertype_ip;
  print_hdr_eth(ether_packet);
  print_hdr_icmp(uint8_t *buf);
  /*Now send off the packet*/
  int size = 32+20+8+28; /*Size of the packet. Ether header = 32, ip header = 20, ICMP header = 8, ICMP data = 28.*/
  sr_send_packet(sr, buf, size, sr->if_list);
  

}
Esempio n. 30
0
int send_arp_response(struct sr_instance * sr, struct sr_if * assoc_iface, uint8_t * packet, unsigned int len) {

      int res; 

      /* we have a MAC address */
      uint8_t newpacket[len];
      memcpy(newpacket, packet, len);
      struct sr_arp_hdr * new_arp_hdr = (sr_arp_hdr_t *)(newpacket + sizeof(sr_ethernet_hdr_t));
      struct sr_ethernet_hdr* ether_hdr = (struct sr_ethernet_hdr *) newpacket;

      /* send it back to whoever sent it (ethernet) */
      memcpy(ether_hdr->ether_dhost, ether_hdr->ether_shost, ETHER_ADDR_LEN);

      /* make sure the ethernet packet header is updated with the new mac */
      memcpy(ether_hdr->ether_shost, assoc_iface->addr, ETHER_ADDR_LEN);

      /* take the old sender address and make it the target */
      memcpy(new_arp_hdr->ar_tha, new_arp_hdr->ar_sha, ETHER_ADDR_LEN);

      /* load in the discovered MAC address as the sender address */
      memcpy(new_arp_hdr->ar_sha, assoc_iface->addr, ETHER_ADDR_LEN);

      uint32_t temp = new_arp_hdr->ar_tip;

      /* send it back to the IP we got it from */
      new_arp_hdr->ar_tip = new_arp_hdr->ar_sip;

      /* replace IP with what it was sent to */
      new_arp_hdr->ar_sip = temp;

      /* set arp op to reply */
      new_arp_hdr->ar_op = htons(arp_op_reply);

    
      res = sr_send_packet(sr, newpacket, len, assoc_iface->name);

      if (res != 0) {
          
            return -1;
      }
      return 0;
}