Advertisement
Guest User

Untitled

a guest
Nov 25th, 2012
2,064
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*  Copyright (C) 2011  P.D. Buchan (pdbuchan@yahoo.com)
  2.  
  3.     This program is free software: you can redistribute it and/or modify
  4.     it under the terms of the GNU General Public License as published by
  5.     the Free Software Foundation, either version 3 of the License, or
  6.     (at your option) any later version.
  7.  
  8.     This program is distributed in the hope that it will be useful,
  9.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.     GNU General Public License for more details.
  12.  
  13.     You should have received a copy of the GNU General Public License
  14.     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  15. */
  16.  
  17. // Send an IPv4 ICMP packet via raw socket.
  18. // Stack fills out layer 2 (data link) information (MAC addresses) for us.
  19. // Values set for echo request packet, includes some ICMP data.
  20.  
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <unistd.h>           // close()
  24. #include <string.h>           // strcpy, memset(), and memcpy()
  25.  
  26. #include <netdb.h>            // struct addrinfo
  27. #include <sys/types.h>        // needed for socket()
  28. #include <sys/socket.h>       // needed for socket()
  29. #include <netinet/in.h>       // IPPROTO_RAW, IPPROTO_IP, IPPROTO_ICMP
  30. #include <netinet/ip.h>       // struct ip and IP_MAXPACKET (which is 65535)
  31. #include <netinet/ip_icmp.h>  // struct icmp, ICMP_ECHO
  32. #include <arpa/inet.h>        // inet_pton() and inet_ntop()
  33. #include <sys/ioctl.h>        // macro ioctl is defined
  34. #include <bits/ioctls.h>      // defines values for argument "request" of ioctl.
  35. #include <net/if.h>           // struct ifreq
  36.  
  37. #include <errno.h>            // errno, perror()
  38.  
  39. // Define some constants.
  40. #define IP4_HDRLEN 20         // IPv4 header length
  41. #define ICMP_HDRLEN 8         // ICMP header length for echo request, excludes data
  42.  
  43. // Function prototypes
  44. unsigned short int checksum (unsigned short int *, int);
  45.  
  46. int
  47. main (int argc, char **argv)
  48. {
  49.   int status, datalen, sd, *ip_flags;
  50.   const int on = 1;
  51.   char *interface, *target, *src_ip, *dst_ip;
  52.   struct ip iphdr;
  53.   struct icmp icmphdr;
  54.   unsigned char *data, *packet;
  55.   struct addrinfo hints, *res;
  56.   struct sockaddr_in *ipv4, sin;
  57.   struct ifreq ifr;
  58.   void *tmp;
  59.  
  60. // Allocate memory for various arrays.
  61.  
  62.   // Maximum ICMP payload size = 65535 - IPv4 header (20 bytes) - ICMP header (8 bytes)
  63.   tmp = (unsigned char *) malloc ((IP_MAXPACKET - IP4_HDRLEN - ICMP_HDRLEN) * sizeof (unsigned char));
  64.   if (tmp != NULL) {
  65.     data = tmp;
  66.   } else {
  67.     fprintf (stderr, "ERROR: Cannot allocate memory for array 'data'.\n");
  68.     exit (EXIT_FAILURE);
  69.   }
  70.   memset (data, 0, (IP_MAXPACKET - IP4_HDRLEN - ICMP_HDRLEN) * sizeof (unsigned char));
  71.  
  72.   tmp = (unsigned char *) malloc (IP_MAXPACKET * sizeof (unsigned char));
  73.   if (tmp != NULL) {
  74.     packet = tmp;
  75.   } else {
  76.     fprintf (stderr, "ERROR: Cannot allocate memory for array 'packet'.\n");
  77.     exit (EXIT_FAILURE);
  78.   }
  79.   memset (packet, 0, IP_MAXPACKET * sizeof (unsigned char));
  80.  
  81.   tmp = (char *) malloc (40 * sizeof (char));
  82.   if (tmp != NULL) {
  83.     interface = tmp;
  84.   } else {
  85.     fprintf (stderr, "ERROR: Cannot allocate memory for array 'interface'.\n");
  86.     exit (EXIT_FAILURE);
  87.   }
  88.   memset (interface, 0, 40 * sizeof (char));
  89.  
  90.   tmp = (char *) malloc (40 * sizeof (char));
  91.   if (tmp != NULL) {
  92.     target = tmp;
  93.   } else {
  94.     fprintf (stderr, "ERROR: Cannot allocate memory for array 'target'.\n");
  95.     exit (EXIT_FAILURE);
  96.   }
  97.   memset (target, 0, 40 * sizeof (char));
  98.  
  99.   tmp = (char *) malloc (16 * sizeof (char));
  100.   if (tmp != NULL) {
  101.     src_ip = tmp;
  102.   } else {
  103.     fprintf (stderr, "ERROR: Cannot allocate memory for array 'src_ip'.\n");
  104.     exit (EXIT_FAILURE);
  105.   }
  106.   memset (src_ip, 0, 16 * sizeof (char));
  107.  
  108.   tmp = (char *) malloc (16 * sizeof (char));
  109.   if (tmp != NULL) {
  110.     dst_ip = tmp;
  111.   } else {
  112.     fprintf (stderr, "ERROR: Cannot allocate memory for array 'dst_ip'.\n");
  113.     exit (EXIT_FAILURE);
  114.   }
  115.   memset (dst_ip, 0, 16 * sizeof (char));
  116.  
  117.   tmp = (int *) malloc (4 * sizeof (int));
  118.   if (tmp != NULL) {
  119.     ip_flags = tmp;
  120.   } else {
  121.     fprintf (stderr, "ERROR: Cannot allocate memory for array 'ip_flags'.\n");
  122.     exit (EXIT_FAILURE);
  123.   }
  124.   memset (ip_flags, 0, 4 * sizeof (int));
  125.  
  126. // Interface to send packet through.
  127.   strcpy (interface, "eth0");
  128.  
  129. // Submit request for a socket descriptor to lookup interface.
  130.   if ((sd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
  131.     perror ("socket() failed to get socket descriptor for using ioctl() ");
  132.     exit (EXIT_FAILURE);
  133.   }
  134.  
  135. // Use ioctl() to lookup interface.
  136.   memset (&ifr, 0, sizeof (ifr));
  137.   snprintf (ifr.ifr_name, sizeof (ifr.ifr_name), "%s", interface);
  138.   if (ioctl (sd, SIOCGIFINDEX, &ifr) < 0) {
  139.     perror ("ioctl() failed to find interface ");
  140.     return (EXIT_FAILURE);
  141.   }
  142.   close (sd);
  143.   printf ("Index for interface %s is %i\n", interface, ifr.ifr_ifindex);
  144.  
  145. // Source IPv4 address: you need to fill this out
  146.   strcpy (src_ip, "192.168.1.123");
  147.  
  148. // Destination URL or IPv4 address
  149.   strcpy (target, "www.google.com");
  150.  
  151. // Fill out hints for getaddrinfo().
  152.   memset (&hints, 0, sizeof (struct addrinfo));
  153.   hints.ai_family = AF_INET;
  154.   hints.ai_socktype = SOCK_STREAM;
  155.   hints.ai_flags = hints.ai_flags | AI_CANONNAME;
  156.  
  157. // Resolve target using getaddrinfo().
  158.   if ((status = getaddrinfo (target, NULL, &hints, &res)) != 0) {
  159.     fprintf (stderr, "getaddrinfo() failed: %s\n", gai_strerror (status));
  160.     exit (EXIT_FAILURE);
  161.   }
  162.   ipv4 = (struct sockaddr_in *) res->ai_addr;
  163.   tmp = &(ipv4->sin_addr);
  164.   inet_ntop (AF_INET, tmp, dst_ip, 40);
  165.   freeaddrinfo (res);
  166.  
  167. // ICMP data
  168.   datalen = 4;
  169.   data[0] = 'T';
  170.   data[1] = 'e';
  171.   data[2] = 's';
  172.   data[3] = 't';
  173.  
  174. // IPv4 header
  175.  
  176. // IPv4 header length (4 bits): Number of 32-bit words in header = 5
  177.   iphdr.ip_hl = IP4_HDRLEN / 4;
  178.  
  179. // Internet Protocol version (4 bits): IPv4
  180.   iphdr.ip_v = 4;
  181.  
  182. // Type of service (8 bits)
  183.   iphdr.ip_tos = 0;
  184.  
  185. // Total length of datagram (16 bits): IP header + ICMP header + ICMP data
  186.   iphdr.ip_len = htons (IP4_HDRLEN + ICMP_HDRLEN + datalen);
  187.  
  188. // ID sequence number (16 bits): unused, since single datagram
  189.   iphdr.ip_id = htons (0);
  190.  
  191. // Flags, and Fragmentation offset (3, 13 bits): 0 since single datagram
  192.  
  193.   // Zero (1 bit)
  194.   ip_flags[0] = 0;
  195.  
  196.   // Do not fragment flag (1 bit)
  197.   ip_flags[1] = 0;
  198.  
  199.   // More fragments following flag (1 bit)
  200.   ip_flags[2] = 0;
  201.  
  202.   // Fragmentation offset (13 bits)
  203.   ip_flags[3] = 0;
  204.  
  205.   iphdr.ip_off = htons ((ip_flags[0] << 15)
  206.                       + (ip_flags[1] << 14)
  207.                       + (ip_flags[2] << 13)
  208.                       +  ip_flags[3]);
  209.  
  210. // Time-to-Live (8 bits): default to maximum value
  211.   iphdr.ip_ttl = 255;
  212.  
  213. // Transport layer protocol (8 bits): 1 for ICMP
  214.   iphdr.ip_p = IPPROTO_ICMP;
  215.  
  216. // Source IPv4 address (32 bits)
  217.   inet_pton (AF_INET, src_ip, &(iphdr.ip_src));
  218.  
  219. // Destination IPv4 address (32 bits)
  220.   inet_pton (AF_INET, dst_ip, &iphdr.ip_dst);
  221.  
  222. // IPv4 header checksum (16 bits): set to 0 when calculating checksum
  223.   iphdr.ip_sum = 0;
  224.   iphdr.ip_sum = checksum ((unsigned short int *) &iphdr, IP4_HDRLEN);
  225.  
  226. // ICMP header
  227.  
  228. // Message Type (8 bits): echo request
  229.   icmphdr.icmp_type = ICMP_ECHO;
  230.  
  231. // Message Code (8 bits): echo request
  232.   icmphdr.icmp_code = 0;
  233.  
  234. // Identifier (16 bits): usually pid of sending process - pick a number
  235.   icmphdr.icmp_id = htons (1000);
  236.  
  237. // Sequence Number (16 bits): starts at 0
  238.   icmphdr.icmp_seq = htons (0);
  239.  
  240. // ICMP header checksum (16 bits): set to 0 when calculating checksum
  241.   icmphdr.icmp_cksum = 0;
  242.  
  243. // Prepare packet.
  244.  
  245.  
  246.  
  247. // Next part of packet is upper layer protocol header.
  248.   memcpy ((packet ), &icmphdr, ICMP_HDRLEN);
  249.  
  250. // Finally, add the ICMP data.
  251.   memcpy (packet  + ICMP_HDRLEN, data, datalen);
  252.  
  253. // Calculate ICMP header checksum
  254.   icmphdr.icmp_cksum = checksum ((unsigned short int *) (packet ), ICMP_HDRLEN + datalen);
  255.   memcpy ((packet ), &icmphdr, ICMP_HDRLEN);
  256.  
  257.  
  258. // The kernel is going to prepare layer 2 information (ethernet frame header) for us.
  259. // For that, we need to specify a destination for the kernel in order for it
  260. // to decide where to send the raw datagram. We fill in a struct in_addr with
  261. // the desired destination IP address, and pass this structure to the sendto() function.
  262.   memset (&sin, 0, sizeof (struct sockaddr_in));
  263.   sin.sin_family = AF_INET;
  264.   sin.sin_addr.s_addr = iphdr.ip_dst.s_addr;
  265.  
  266. // Submit request for a raw socket descriptor.
  267.   if ((sd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
  268.     perror ("socket() failed ");
  269.     exit (EXIT_FAILURE);
  270.   }
  271.  
  272.  
  273. // Bind socket to interface index
  274.   if (setsockopt (sd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof (ifr)) < 0) {
  275.     perror ("setsockopt() failed to bind to interface ");
  276.     exit (EXIT_FAILURE);
  277.   }
  278.    
  279. bind(sd,(struct sockaddr*)&sin,sizeof(sin));
  280. // Send packet.
  281.   if (sendto (sd, packet, ICMP_HDRLEN + datalen, 0, (struct sockaddr *) &sin, sizeof (struct sockaddr)) < 0)  {
  282.     perror ("sendto() failed ");
  283.     exit (EXIT_FAILURE);
  284.   }
  285. /*******/
  286.   struct sockaddr_in rec;
  287.  
  288.   unsigned char * pkt = (unsigned char *) malloc (2048);
  289.  
  290.   if (recvfrom (sd, (void*)pkt, sizeof(struct ip) + sizeof(struct icmp)+datalen , 0, NULL, (socklen_t*)sizeof (struct sockaddr)) < 0)  {
  291.     perror ("recvfrom() failed ");
  292.     exit (EXIT_FAILURE);
  293.   }
  294.   struct ip *ip = (struct ip *)pkt;
  295.   struct icmp *icmp = (struct icmp *)(pkt + sizeof(struct ip));
  296.  
  297.  
  298.  
  299.   printf("%s %s %d\n",(char*)inet_ntoa(*(struct in_addr*)&ip->ip_dst),
  300.                       (char*)inet_ntoa(*(struct in_addr*)&ip->ip_src),
  301.                       icmp->icmp_type);
  302.   free (pkt);
  303.  /******/
  304. // Close socket descriptor.
  305.   close (sd);
  306.  
  307. // Free allocated memory.
  308.   free (data);
  309.   free (packet);
  310.   free (interface);
  311.   free (target);
  312.   free (src_ip);
  313.   free (dst_ip);
  314.   free (ip_flags);
  315.  
  316.   return (EXIT_SUCCESS);
  317. }
  318.  
  319. // Checksum function
  320. unsigned short int
  321. checksum (unsigned short int *addr, int len)
  322. {
  323.   int nleft = len;
  324.   int sum = 0;
  325.   unsigned short int *w = addr;
  326.   unsigned short int answer = 0;
  327.  
  328.   while (nleft > 1) {
  329.     sum += *w++;
  330.     nleft -= sizeof (unsigned short int);
  331.   }
  332.  
  333.   if (nleft == 1) {
  334.     *(unsigned char *) (&answer) = *(unsigned char *) w;
  335.     sum += answer;
  336.   }
  337.  
  338.   sum = (sum >> 16) + (sum & 0xFFFF);
  339.   sum += (sum >> 16);
  340.   answer = ~sum;
  341.   return (answer);
  342. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement