Пример #1
0
char* get_mac_addr(int socket, char *interface) {
    uint8_t *src_mac;
    char *mac;
    struct ifreq ifr;

    memset(&ifr, 0, sizeof (ifr));
    bzero(&ifr, sizeof (ifr));

    src_mac = allocate_ustrmem(ETHER_ADDR_LEN);
    mac = allocate_strmem(MAC_ADDR_STRLEN);

    strncpy((char *) ifr.ifr_name, interface, IFNAMSIZ);

    if ((ioctl(socket, SIOCGIFHWADDR, &ifr)) == -1) {
        submit_log("create_raw_socket(): [%s]\n", "Error getting HW ADDR");
        exit(EXIT_FAILURE);
    }
    memcpy(src_mac, ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN * sizeof (uint8_t));

    sprintf(mac, "%02x:%02x:%02x:%02x:%02x:%02x", src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5]);

    submit_log("Interface: %s\n", interface);
    submit_log("MAC ADDR: %s\n", mac);

    return mac;
}
int
main (int argc, char **argv)
{
  int i, sd, status;
  uint8_t *ether_frame;
  arp_hdr *arphdr;

  // Allocate memory for various arrays.
  ether_frame = allocate_ustrmem (IP_MAXPACKET);

  // Submit request for a raw socket descriptor.
  if ((sd = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0) {
    perror ("socket() failed ");
    exit (EXIT_FAILURE);
  }

  // Listen for incoming ethernet frame from socket sd.
  // We expect an ARP ethernet frame of the form:
  //     MAC (6 bytes) + MAC (6 bytes) + ethernet type (2 bytes)
  //     + ethernet data (ARP header) (28 bytes)
  // Keep at it until we get an ARP reply.
  arphdr = (arp_hdr *) (ether_frame + 6 + 6 + 2);
  while (((((ether_frame[12]) << 8) + ether_frame[13]) != ETH_P_ARP) || (ntohs (arphdr->opcode) != ARPOP_REPLY)) {
    if ((status = recv (sd, ether_frame, IP_MAXPACKET, 0)) < 0) {
      if (errno == EINTR) {
        memset (ether_frame, 0, IP_MAXPACKET * sizeof (uint8_t));
        continue;  // Something weird happened, but let's try again.
      } else {
        perror ("recv() failed:");
        exit (EXIT_FAILURE);
      }
    }
  }
  close (sd);

  // Print out contents of received ethernet frame.
  printf ("\nEthernet frame header:\n");
  printf ("Destination MAC (this node): ");
  for (i=0; i<5; i++) {
    printf ("%02x:", ether_frame[i]);
  }
  printf ("%02x\n", ether_frame[5]);
  printf ("Source MAC: ");
  for (i=0; i<5; i++) {
    printf ("%02x:", ether_frame[i+6]);
  }
  printf ("%02x\n", ether_frame[11]);
  // Next is ethernet type code (ETH_P_ARP for ARP).
  // http://www.iana.org/assignments/ethernet-numbers
  printf ("Ethernet type code (2054 = ARP): %u\n", ((ether_frame[12]) << 8) + ether_frame[13]);
  printf ("\nEthernet data (ARP header):\n");
  printf ("Hardware type (1 = ethernet (10 Mb)): %u\n", ntohs (arphdr->htype));
  printf ("Protocol type (2048 for IPv4 addresses): %u\n", ntohs (arphdr->ptype));
  printf ("Hardware (MAC) address length (bytes): %u\n", arphdr->hlen);
  printf ("Protocol (IPv4) address length (bytes): %u\n", arphdr->plen);
  printf ("Opcode (2 = ARP reply): %u\n", ntohs (arphdr->opcode));
  printf ("Sender hardware (MAC) address: ");
  for (i=0; i<5; i++) {
    printf ("%02x:", arphdr->sender_mac[i]);
  }
  printf ("%02x\n", arphdr->sender_mac[5]);
  printf ("Sender protocol (IPv4) address: %u.%u.%u.%u\n",
    arphdr->sender_ip[0], arphdr->sender_ip[1], arphdr->sender_ip[2], arphdr->sender_ip[3]);
  printf ("Target (this node) hardware (MAC) address: ");
  for (i=0; i<5; i++) {
    printf ("%02x:", arphdr->target_mac[i]);
  }
  printf ("%02x\n", arphdr->target_mac[5]);
  printf ("Target (this node) protocol (IPv4) address: %u.%u.%u.%u\n",
    arphdr->target_ip[0], arphdr->target_ip[1], arphdr->target_ip[2], arphdr->target_ip[3]);

  free (ether_frame);

  return (EXIT_SUCCESS);
}
Пример #3
0
int
main (int argc, char **argv)
{
  int i, status, frame_length, sd, bytes;
  char *interface;
  uint8_t *src_mac, *dst_mac, *ether_frame;
  struct sockaddr_in *ipv4;
  struct sockaddr_ll device;
  struct ifreq ifr;

  // Allocate memory for various arrays.
  src_mac = allocate_ustrmem (6);
  dst_mac = allocate_ustrmem (6);
  ether_frame = allocate_ustrmem (ETH_HDRLEN);
  interface = allocate_strmem (40);

  // Interface to send packet through.
  strcpy (interface, argv[1]);

  // Submit request for a socket descriptor to look up interface.
  if ((sd = socket (AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
    perror ("socket() failed to get socket descriptor for using ioctl() ");
    exit (EXIT_FAILURE);
  }

  // Use ioctl() to look up interface name and get its MAC address.
  memset (&ifr, 0, sizeof (ifr));
  snprintf (ifr.ifr_name, sizeof (ifr.ifr_name), "%s", interface);
  if (ioctl (sd, SIOCGIFHWADDR, &ifr) < 0) {
    perror ("ioctl() failed to get source MAC address ");
    return (EXIT_FAILURE);
  }
  close (sd);

  // Copy source MAC address.
  memcpy (src_mac, ifr.ifr_hwaddr.sa_data, 6 * sizeof (uint8_t));

  // Report source MAC address to stdout.
  printf ("MAC address for interface %s is ", interface);
  for (i=0; i<5; i++) {
    printf ("%02x:", src_mac[i]);
  }
  printf ("%02x\n", src_mac[5]);

  // Find interface index from interface name and store index in
  // struct sockaddr_ll device, which will be used as an argument of sendto().
  memset (&device, 0, sizeof (device));
  if ((device.sll_ifindex = if_nametoindex (interface)) == 0) {
    perror ("if_nametoindex() failed to obtain interface index ");
    exit (EXIT_FAILURE);
  }
  printf ("Index for interface %s is %i\n", interface, device.sll_ifindex);

  // Set destination MAC address: broadcast address
  memset (dst_mac, 0xff, 6 * sizeof (uint8_t));

  // Fill out sockaddr_ll.
  device.sll_family = AF_PACKET;
  memcpy (device.sll_addr, src_mac, 6 * sizeof (uint8_t));
  device.sll_halen = 6;

  // Fill out ethernet frame header.

  // Ethernet frame length = ethernet header (MAC + MAC + ethernet type) + ethernet data (ARP header)
  frame_length = 6 + 6 + 2;

  // Destination and Source MAC addresses
  memcpy (ether_frame, dst_mac, 6 * sizeof (uint8_t));
  memcpy (ether_frame + 6, src_mac, 6 * sizeof (uint8_t));

  // Next is ethernet type code (ETH_P_ARP for ARP).
  // http://www.iana.org/assignments/ethernet-numbers
  ether_frame[12] = ETH_HLEN / 256;
  ether_frame[13] = ETH_HLEN % 256;

  // Submit request for a raw socket descriptor.
  if ((sd = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0) {
    perror ("socket() failed ");
    exit (EXIT_FAILURE);
  }

  // Send ethernet frame to socket.
  if ((bytes = sendto (sd, ether_frame, frame_length, 0, (struct sockaddr *) &device, sizeof (device))) <= 0) {
    perror ("sendto() failed");
    exit (EXIT_FAILURE);
  }

  // Close socket descriptor.
  close (sd);

  // Free allocated memory.
  free (src_mac);
  free (dst_mac);
  free (ether_frame);
  free (interface);

  return (EXIT_SUCCESS);
}
Пример #4
0
int larp_reply_pkt(struct arphdr *ar_hdr, struct sockaddr_ll *recv_addr)
{
    int send_sockfd;
    int i, send_bytes, frame_length;
    uint32_t ipaddr_n32;
    //char ipaddr_p[INET_ADDRSTRLEN]; /* to print IP address in presentation format */
    struct sockaddr_ll send_addr;
    struct arphdr send_arhdr; /* standard ARP header fields */
    struct tlv_type_len type_len; /* variable of type-len struct */
    struct label_stack *l_stack = (struct label_stack *) malloc(label_count * sizeof(struct label_stack)); /* For label stack */
    struct attr_tlv a_tlv; /* For Attributes TLV */
    char if_name[IFNAMSIZ];
    uint32_t metric_val;
    unsigned char *s_haddr = allocate_ustrmem (6);
    /*create a RAW PF_PACKET socket for sending out the reply*/
    send_sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ARP));
    if (send_sockfd < 0) { /* socket function returns negative value on error */
        printf("Sending socket creation failed\n");
        exit(1);
    }
    uint8_t *buffer = allocate_ustrmem (IP_MAXPACKET);
    /* Making the buffer all zeros */
    memset(buffer, 0, ETH_FRAME_LEN);
    /* Get the local interface MAC address based on the received interface index*/
    get_mac (recv_addr->sll_ifindex, s_haddr);
    /*zeroing out the struct sockaddr_ll structure*/
    memset(&send_addr, 0, sizeof(struct sockaddr_ll));
    /* Fill in the values for struct sockaddr_ll structure*/

    send_addr.sll_family = PF_PACKET;
    send_addr.sll_protocol = htons(ETH_P_ARP);
    send_addr.sll_ifindex = recv_addr->sll_ifindex;
    send_addr.sll_halen = ETH_ALEN; /*6 bytes for Mac address */
    /* filling target MAC address from source MAC field of received LARP req */
    send_addr.sll_addr[0] = ar_hdr->ar_sha[0];
    send_addr.sll_addr[1] = ar_hdr->ar_sha[1];
    send_addr.sll_addr[2] = ar_hdr->ar_sha[2];
    send_addr.sll_addr[3] = ar_hdr->ar_sha[3];
    send_addr.sll_addr[4] = ar_hdr->ar_sha[4];
    send_addr.sll_addr[5] = ar_hdr->ar_sha[5];
    /* Not used */
    send_addr.sll_addr[6] = 0x00;
    send_addr.sll_addr[7] = 0x00;
#if 0
    for (i=0; i<5; i++)
        printf("%02x:", s_haddr[i]);
    printf("%02x\n", s_haddr[i]);
#endif

    /* Start filling the buffer starting with Ethernet header */

    /* Fill in ethernet header*/
    memcpy(buffer, ar_hdr->ar_sha, ETH_ALEN * sizeof(uint8_t)); /* destination MAC*/
    memcpy(buffer + ETH_ALEN, s_haddr, ETH_ALEN * sizeof(uint8_t)); /* source MAC */
    /* Fill ETH_TYPE = ETH_P_ARP for ARP */
    buffer[12] = ETH_P_ARP / 256;
    buffer[13] = ETH_P_ARP % 256;
    /*Fill in ARP header fileds */
    send_arhdr.ar_htype = htons(ARPHRD_LARP);
    send_arhdr.ar_ptype = htons(ETH_P_IP); /* code for IPV6 can be added as needed*/
    send_arhdr.ar_hln = ETH_ALEN;
    send_arhdr.ar_pln = IP_ADDR_SIZE;
    send_arhdr.ar_op = htons(LARP_REPLY_OP); /* LARP reply = 2 */
    /* source and destination MAC address */
    memcpy(&send_arhdr.ar_sha, s_haddr, ETH_ALEN * sizeof(uint8_t));
    memcpy(&send_arhdr.ar_tha, ar_hdr->ar_sha, ETH_ALEN * sizeof(uint8_t));
    /* Source and destination IP filled using received LARP request */
    memcpy(&send_arhdr.ar_sip, ar_hdr->ar_tip, IP_ADDR_SIZE * sizeof(uint8_t));
    memcpy(&send_arhdr.ar_tip, ar_hdr->ar_sip, IP_ADDR_SIZE * sizeof(uint8_t));

    /* Copying ARP header to sending packet buffer */
    memcpy(buffer + ETH_HDR_SIZE, &send_arhdr, sizeof(struct arphdr));

    /*Fill in type, length and label for TLV_LST */
    fill_type_label_stack(&type_len, l_stack, ar_hdr->ar_tip);

    /* copy the tlv TLV_LST struct to sending buffer */
    memcpy(buffer + ETH_HDR_SIZE + ARP_HDR_SIZE, &type_len, TYPE_LEN_SIZE);
    memcpy(buffer + ETH_HDR_SIZE + ARP_HDR_SIZE + TYPE_LEN_SIZE, l_stack, label_count * LABEL_STACK_SIZE);

    /*Add Attribute TLV to sending buffer only if it is enabled */
    if(attr_tlv_flag) {
        /* zero the type_len struct so that now the new values can be held for attr_tlv*/
        memset (&type_len, 0, TYPE_LEN_SIZE);

        /* Fill in struct values for attributes TLV */
        fill_type_attribute_tlv(&type_len, &a_tlv, ar_hdr->ar_tip);
        /* Copy the ATTR_TLV struct to the sending buffer */
        memcpy(buffer + ETH_HDR_SIZE + ARP_HDR_SIZE + TYPE_LEN_SIZE + label_count * LABEL_STACK_SIZE, &type_len, TYPE_LEN_SIZE);
        memcpy(buffer + ETH_HDR_SIZE + ARP_HDR_SIZE + TYPE_LEN_SIZE + label_count * LABEL_STACK_SIZE + TYPE_LEN_SIZE, &a_tlv, ATTR_TLV_SIZE);
    }

    /* Frame length = Ethernet header + ARP header + type_len + label_stack */
    frame_length = ETH_HDR_SIZE + ARP_HDR_SIZE + TYPE_LEN_SIZE + label_count * LABEL_STACK_SIZE + attr_tlv_flag * (TYPE_LEN_SIZE + ATTR_TLV_SIZE);

    /* sending the filled packet buffer using sendto*/
    send_bytes = sendto(send_sockfd, buffer, frame_length, 0, (SA *) &send_addr, sizeof(send_addr));
    if(send_bytes <= 0) { /* Return value: 0 is no bytes sent and negative is error */
        perror("Sendto() for LARP reply failed\n");
        exit (1);
    }
    get_interface_name (send_addr.sll_ifindex, if_name);
    printf("Sent LARP reply to %u.%u.%u.%u for target %u.%u.%u.%u on interface: %s with label(s): ", send_arhdr.ar_tip[0], send_arhdr.ar_tip[1], send_arhdr.ar_tip[2], send_arhdr.ar_tip[3], send_arhdr.ar_sip[0], send_arhdr.ar_sip[1], send_arhdr.ar_sip[2], send_arhdr.ar_sip[3],if_name);
    u32fromu8(send_arhdr.ar_sip, &ipaddr_n32);
    uint32_t *label_stk = (uint32_t *) calloc (0, label_count * sizeof(uint32_t));
    memcpy(label_stk, find_label(ipaddr_n32), label_count * sizeof(uint32_t));
    print_label_stack(label_stk);
    metric_val = find_metric(ipaddr_n32);
    if (metric_val != 0)
        printf("and with metric: %u\n", find_metric(ipaddr_n32));
    else
        printf("and with no ATTR_TLV.\n");
    if (hex_dump_flag) /* print hex_dump of packet if flag enabled */
        hexDump (ntohs(send_arhdr.ar_op), buffer+14 , frame_length - 14);
    /* freeing dynamically allocated memory */
    free (label_stk);
    free(s_haddr);
    free(l_stack);
}
Пример #5
0
int
main (int argc, char **argv)
{
  int i, offset, sd, status;
  uint8_t *ether_frame;
  struct ip *iphdr;
  ra_hdr *rahdr;
  char *src_ip, *dst_ip;

  // Allocate memory for various arrays.
  ether_frame = allocate_ustrmem (IP_MAXPACKET);
  src_ip = allocate_strmem (INET_ADDRSTRLEN);
  dst_ip = allocate_strmem (INET_ADDRSTRLEN);

  // Submit request for a raw socket descriptor.
  if ((sd = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0) {
    perror ("socket() failed ");
    exit (EXIT_FAILURE);
  }

  // Listen for incoming ethernet frame from socket sd.
  // We expect a router advertisment ethernet frame of the form:
  //     MAC (6 bytes) + MAC (6 bytes) + ethernet type (2 bytes)
  //     + ethernet data (IPv4 header + RA header)
  // Keep at it until we get a router advertisement.
  iphdr = (struct ip *) (ether_frame + 6 + 6 +2);
  rahdr = (ra_hdr *) (ether_frame + 6 + 6 + 2 + IP4_HDRLEN);
  while (((((ether_frame[12]) << 8) + ether_frame[13]) != ETH_P_IP) || (iphdr->ip_p != IPPROTO_ICMP) ||
         (rahdr->icmp_type != ICMP_ROUTERADVERT)) {
    if ((status = recv (sd, ether_frame, IP_MAXPACKET, 0)) < 0) {
      if (errno == EINTR) {
        memset (ether_frame, 0, IP_MAXPACKET * sizeof (uint8_t));
        continue;  // Something weird happened, but let's try again.
      } else {
        perror ("recv() failed:");
        exit (EXIT_FAILURE);
      }
    }
  }
  close (sd);

  // Print out contents of received ethernet frame.
  printf ("\nEthernet frame header:\n");
  printf ("Destination MAC (this node): ");
  for (i=0; i<5; i++) {
    printf ("%02x:", ether_frame[i]);
  }
  printf ("%02x\n", ether_frame[5]);
  printf ("Source MAC: ");
  for (i=0; i<5; i++) {
    printf ("%02x:", ether_frame[i+6]);
  }
  printf ("%02x\n", ether_frame[11]);
  // Next is ethernet type code (ETH_P_IP for IPv4 packets).
  // http://www.iana.org/assignments/ethernet-numbers
  printf ("Ethernet type code (2048 = IPv4): %u\n", ((ether_frame[12]) << 8) + ether_frame[13]);
  printf ("\nEthernet data (IPv4 header + Router Advertisement header)\n");
  printf ("IPv4 transport layer protocol (1 = ICMP): %u\n", iphdr->ip_p);
  if (inet_ntop (AF_INET, &(iphdr->ip_src), src_ip, INET_ADDRSTRLEN) == NULL) {
    status = errno;
    fprintf (stderr, "inet_ntop() failed.\nError message: %s", strerror (status));
    exit (EXIT_FAILURE);
  }
  printf ("Source IPv4 address: %s\n", src_ip);
  if (inet_ntop (AF_INET, &(iphdr->ip_dst), dst_ip, INET_ADDRSTRLEN) == NULL) {
    status = errno;
    fprintf (stderr, "inet_ntop() failed.\nError message: %s", strerror (status));
    exit (EXIT_FAILURE);
  }
  printf ("Destination IPv4 address: %s\n", dst_ip);
  printf ("ICMP message type (9 = router advertisement): %u\n", rahdr->icmp_type);
  printf ("ICMP message code: %u\n", rahdr->icmp_code);
  printf ("Number of IPv4 addresses associated with router: %u\n", rahdr->num_addrs);
  printf ("Router address entry size (in units of 32 bit words): %u\n", rahdr->entry_size);
  printf ("Lifetime of validity of router advertisement (seconds): %u\n", ntohs (rahdr->lifetime));
  offset = 6 + 6 + 2 + IP4_HDRLEN + ICMP_HDRLEN;  // Start of list of addresses and preference levels within ethernet frame
  for (i=0; i<rahdr->num_addrs; i++) {
    printf ("Router %i IPv4 address: %u:%u:%u:%u\n", 
     i, ether_frame[offset + (i * rahdr->entry_size * 4) + 0],
        ether_frame[offset + (i * rahdr->entry_size * 4) + 1],
        ether_frame[offset + (i * rahdr->entry_size * 4) + 2],
        ether_frame[offset + (i * rahdr->entry_size * 4) + 3]);
    printf ("Router %i preference level: %u\n", i,  ((ether_frame[offset + (i * rahdr->entry_size * 4) + 4]) << 24) +
     ((ether_frame[offset + (i * rahdr->entry_size * 4) + 5]) << 16) +
     ((ether_frame[offset + (i * rahdr->entry_size * 4) + 6]) << 8) +
     ether_frame[offset + (i * rahdr->entry_size * 4) + 7]);
    offset += rahdr->entry_size * 4;
  }

  free (ether_frame);
  free (src_ip);
  free (dst_ip);

  return (EXIT_SUCCESS);
}
Пример #6
0
int sendRtMsgIntermediate(int sd, void * buf, ssize_t len){
	
	int status, *ip_flags;
	struct ip iphdr;
	uint8_t *data, *packet;
	struct icmp icmphdr;
	struct sockaddr_in *ipv4, sin;	
	void *tmp;

	// Allocate memory for various arrays.
	data = allocate_ustrmem (IP_MAXPACKET);
	packet = allocate_ustrmem (IP_MAXPACKET);
	ip_flags = allocate_intmem (4);
	//Unpack the tourdata 
	struct tourdata * unpack = (struct tourdata *)buf;

	subscribeToMulticast(unpack);

	//since we work and change index
	unpack->index = ntohl(unpack->index);
	printf("Index:%d, nodes in tour:%d\n", unpack->index, ntohl(unpack->nodes_in_tour));
	if((unpack->index + 1) == ntohl(unpack->nodes_in_tour)){
		//Tour has ended. Send multicast here to everyone and return actually 
		//you dont send anyting from here
		endOfTour = 1;		

		free (data);
		free (packet);
		free (ip_flags);
		return 0;		
	}			

	int itemsArrSizeBytes = ntohl(unpack->nodes_in_tour) * sizeof(struct in_addr);
	int datalen = sizeof(struct tourdata) + itemsArrSizeBytes;
	
	// IPv4 header

	// IPv4 header length (4 bits): Number of 32-bit words in header = 5
	iphdr.ip_hl = IP4_HDRLEN / sizeof (uint32_t);	
	iphdr.ip_v = 4;// Internet Protocol version (4 bits): IPv4	
	iphdr.ip_tos = 0;// Type of service (8 bits)	
	iphdr.ip_len = htons (IP4_HDRLEN + ICMP_HDRLEN + datalen);// Total length of datagram (16 bits): IP header + UDP header + datalen	
	iphdr.ip_id = htons (MY_IP_ID);// ID sequence number (16 bits): unused, since single datagram
debug("hey");
	// Flags, and Fragmentation offset (3, 13 bits): 0 since single datagram
	ip_flags[0] = 0;  
	ip_flags[1] = 0;// Do not fragment flag (1 bit)  
	ip_flags[2] = 0;// More fragments following flag (1 bit)  
	ip_flags[3] = 0;// Fragmentation offset (13 bits)

	iphdr.ip_off = htons ((ip_flags[0] << 15) + (ip_flags[1] << 14) + (ip_flags[2] << 13) +  ip_flags[3]);	
	iphdr.ip_ttl = 255;// Time-to-Live (8 bits): default to maximum value	
	iphdr.ip_p = RT_PROTO;// Transport layer protocol (8 bits): 1 for ICMP
debug("hey");
	void * ptr = buf + sizeof(struct tourdata);
	ptr = ptr + (sizeof(struct in_addr) * unpack->index); //current node-item
	iphdr.ip_src = *(struct in_addr *)ptr;
	
	unpack->index++;
	ptr = ptr + sizeof(struct in_addr); //advance the pointer to the next in_addr_t
	iphdr.ip_dst  = *(struct in_addr *)ptr;
	debug("hey. Src IP :%s\n", printIPHuman(iphdr.ip_src.s_addr));
	debug("hey. Dest IP :%s\n", printIPHuman(iphdr.ip_dst.s_addr));
	// IPv4 header checksum (16 bits): set to 0 when calculating checksum
	iphdr.ip_sum = 0;
	iphdr.ip_sum = checksum ((uint16_t *) &iphdr, IP4_HDRLEN);

	// ICMP header	
	icmphdr.icmp_type = 0;// Message Type (8 bits): echo request	
	icmphdr.icmp_code = 0;// Message Code (8 bits): echo request	
	icmphdr.icmp_id = htons (RT_ICMPID);// Identifier (16 bits): usually pid of sending process - pick a number	
	icmphdr.icmp_seq = htons (0);// Sequence Number (16 bits): starts at 0	
	icmphdr.icmp_cksum = 0;
	icmphdr.icmp_cksum = icmp4_checksum(icmphdr, data, datalen);

	// Copy tour packet to the new ICMP data payload
	unpack->index = htonl(unpack->index);
	memcpy(data, unpack, sizeof(struct tourdata));

	memcpy((void*)(data + sizeof(struct tourdata)), (void*)(buf + sizeof(struct tourdata)), itemsArrSizeBytes);	
debug("hey itemarrsizebytes %d", itemsArrSizeBytes);
	// Prepare packet.
	// First part is an IPv4 header.
	memcpy (packet, &iphdr, IP4_HDRLEN);
	// Next part of packet is upper layer protocol header.
debug("hey");
	memcpy ((packet + IP4_HDRLEN), &icmphdr, ICMP_HDRLEN);
	// Finally, add the ICMP data.
	debug("hey");
	memcpy (packet + IP4_HDRLEN + ICMP_HDRLEN, data, datalen);
	debug("hey, datalen=%d", datalen);
	memset (&sin, 0, sizeof (struct sockaddr_in));
	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = iphdr.ip_dst.s_addr;  
	debug("hey. Dest IP :%s\n", printIPHuman(ntohl(iphdr.ip_dst.s_addr)));
	printf("Gonna send...");
	// Send packet.
	if (sendto (sd, packet, IP4_HDRLEN + ICMP_HDRLEN + datalen, 0, (struct sockaddr *) &sin, sizeof (struct sockaddr)) < 0)  {
		printFailed();
		return 1;		
	}
	printOK();
	
	// Free allocated memory.
	free (data);
	free (packet);
	free (ip_flags);

	return 0;
}
Пример #7
0
int sendRtMsg(int sd){
	
	int status, datalen, *ip_flags;
	char *target, *src_ip, *dst_ip;
	struct ip iphdr;
	uint8_t *data, *packet;
	struct icmp icmphdr;
	struct addrinfo hints, *res;
	struct sockaddr_in *ipv4, sin;	
	void *tmp;

	// Allocate memory for various arrays.
	data = allocate_ustrmem (IP_MAXPACKET);
	packet = allocate_ustrmem (IP_MAXPACKET);
	target = allocate_strmem (40);
	src_ip = allocate_strmem (INET_ADDRSTRLEN);
	dst_ip = allocate_strmem (INET_ADDRSTRLEN);
	ip_flags = allocate_intmem (4);

	strcpy(src_ip, inet_ntoa(ip_list[0]));

	strcpy(target, inet_ntoa(ip_list[1]));
	debug("Source IP %s, targe IP %s", src_ip, target);

	// Fill out hints for getaddrinfo().
	memset (&hints, 0, sizeof (struct addrinfo));
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_flags = hints.ai_flags | AI_CANONNAME;

	// Resolve target using getaddrinfo().
	if ((status = getaddrinfo (target, NULL, &hints, &res)) != 0) {
		fprintf (stderr, "getaddrinfo() failed: %s\n", gai_strerror (status));
		exit (EXIT_FAILURE);
	}
	ipv4 = (struct sockaddr_in *) res->ai_addr;
	tmp = &(ipv4->sin_addr);
	if (inet_ntop (AF_INET, tmp, dst_ip, INET_ADDRSTRLEN) == NULL) {
		status = errno;
		fprintf (stderr, "inet_ntop() failed.\nError message: %s", strerror (status));
		exit (EXIT_FAILURE);
	}
	freeaddrinfo (res);	
	datalen = sizeof(struct tourdata) + (VMcount * 4);
	
	struct tourdata td;
	td.index = htonl(0);
	td.nodes_in_tour = htonl(VMcount);
	td.mult_ip = inet_addr(MULTICAST_IP);
	td.mult_port = htons(MULTICAST_PORT);
	memcpy(data, &td, sizeof(struct tourdata));

	subscribeToMulticast(&td);

	void * ptr = data;
	ptr = ptr + sizeof(struct tourdata);
	int i;
	//Add the IPs of the VMs to visit
	for(i = 1; i <=VMcount; i++){
		memcpy(ptr, &ip_list[i], 4);
		struct in_addr * temp2 = (struct in_addr *) ptr;
		ptr = ptr + 4;
	}

	// IPv4 header

	// IPv4 header length (4 bits): Number of 32-bit words in header = 5
	iphdr.ip_hl = IP4_HDRLEN / sizeof (uint32_t);	
	iphdr.ip_v = 4;// Internet Protocol version (4 bits): IPv4	
	iphdr.ip_tos = 0;// Type of service (8 bits)	
	iphdr.ip_len = htons (IP4_HDRLEN + ICMP_HDRLEN + datalen);// Total length of datagram (16 bits): IP header + UDP header + datalen	
	iphdr.ip_id = htons (MY_IP_ID);// ID sequence number (16 bits): unused, since single datagram

	// Flags, and Fragmentation offset (3, 13 bits): 0 since single datagram
	ip_flags[0] = 0;  
	ip_flags[1] = 0;// Do not fragment flag (1 bit)  
	ip_flags[2] = 0;// More fragments following flag (1 bit)  
	ip_flags[3] = 0;// Fragmentation offset (13 bits)

	iphdr.ip_off = htons ((ip_flags[0] << 15)
	                  + (ip_flags[1] << 14)
	                  + (ip_flags[2] << 13)
	                  +  ip_flags[3]);	
	iphdr.ip_ttl = 255;// Time-to-Live (8 bits): default to maximum value	
	iphdr.ip_p = RT_PROTO;// Transport layer protocol (8 bits): 1 for ICMP

	// Source IPv4 address (32 bits)
	if ((status = inet_pton (AF_INET, src_ip, &(iphdr.ip_src))) != 1) {
	fprintf (stderr, "inet_pton() failed.\nError message: %s", strerror (status));
	exit (EXIT_FAILURE);
	}

	// Destination IPv4 address (32 bits)
	if ((status = inet_pton (AF_INET, dst_ip, &(iphdr.ip_dst))) != 1) {
	fprintf (stderr, "inet_pton() failed.\nError message: %s", strerror (status));
	exit (EXIT_FAILURE);
	}

	// IPv4 header checksum (16 bits): set to 0 when calculating checksum
	iphdr.ip_sum = 0;
	iphdr.ip_sum = checksum ((uint16_t *) &iphdr, IP4_HDRLEN);

	// ICMP header	
	icmphdr.icmp_type = 0;// Message Type (8 bits): echo request	
	icmphdr.icmp_code = 0;// Message Code (8 bits): echo request	
	icmphdr.icmp_id = htons (RT_ICMPID);// Identifier (16 bits): usually pid of sending process - pick a number	
	icmphdr.icmp_seq = htons (0);// Sequence Number (16 bits): starts at 0	
	icmphdr.icmp_cksum = 0;
	icmphdr.icmp_cksum = icmp4_checksum(icmphdr, data, datalen);

	// Prepare packet.
	// First part is an IPv4 header.
	memcpy (packet, &iphdr, IP4_HDRLEN);
	// Next part of packet is upper layer protocol header.
	memcpy ((packet + IP4_HDRLEN), &icmphdr, ICMP_HDRLEN);
	// Finally, add the ICMP data.
	memcpy (packet + IP4_HDRLEN + ICMP_HDRLEN, data, datalen);
	// Calculate ICMP header checksum
	//icmphdr.icmp_cksum = 0;//checksum ((uint16_t *) (packet + IP4_HDRLEN), ICMP_HDRLEN + datalen);
	//memcpy ((packet + IP4_HDRLEN), &icmphdr, ICMP_HDRLEN);

	// The kernel is going to prepare layer 2 information (ethernet frame header) for us.
	// For that, we need to specify a destination for the kernel in order for it
	// to decide where to send the raw datagram. We fill in a struct in_addr with
	// the desired destination IP address, and pass this structure to the sendto() function.
	memset (&sin, 0, sizeof (struct sockaddr_in));
	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = iphdr.ip_dst.s_addr;  

	if (sendto (sd, packet, IP4_HDRLEN + ICMP_HDRLEN + datalen, 0, (struct sockaddr *) &sin, sizeof (struct sockaddr)) < 0)  {
		perror ("sendto() failed ");
		exit (EXIT_FAILURE);
	}
	printOK();
	
	// Free allocated memory.
	free (data);
	free (packet);
	free (target);
	free (src_ip);
	free (dst_ip);
	free (ip_flags);

	return 0;
}