Advertisement
hhac

Ping socket c

Oct 8th, 2022
991
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.81 KB | Source Code | 0 0
  1. // C program to Implement Ping
  2.  
  3. // compile as -o ping
  4. // run as sudo ./ping <hostname>
  5.  
  6. #include <stdio.h>
  7. #include <sys/types.h>
  8. #include <sys/socket.h>
  9. #include <netinet/in.h>
  10. #include <arpa/inet.h>
  11. #include <netdb.h>
  12. #include <unistd.h>
  13. #include <string.h>
  14. #include <stdlib.h>
  15. #include <netinet/ip_icmp.h>
  16. #include <time.h>
  17. #include <fcntl.h>
  18. #include <signal.h>
  19. #include <time.h>
  20.  
  21. // Define the Packet Constants
  22. // ping packet size
  23. #define PING_PKT_S 64
  24.  
  25. // Automatic port number
  26. #define PORT_NO 0
  27.  
  28. // Automatic port number
  29. #define PING_SLEEP_RATE 1000000 x
  30.  
  31. // Gives the timeout delay for receiving packets
  32. // in seconds
  33. #define RECV_TIMEOUT 1
  34.  
  35. // Define the Ping Loop
  36. int pingloop=1;
  37.  
  38.  
  39. // ping packet structure
  40. struct ping_pkt
  41. {
  42.     struct icmphdr hdr;
  43.     char msg[PING_PKT_S-sizeof(struct icmphdr)];
  44. };
  45.  
  46. // Calculating the Check Sum
  47. unsigned short checksum(void *b, int len)
  48. {    unsigned short *buf = b;
  49.     unsigned int sum=0;
  50.     unsigned short result;
  51.  
  52.     for ( sum = 0; len > 1; len -= 2 )
  53.         sum += *buf++;
  54.     if ( len == 1 )
  55.         sum += *(unsigned char*)buf;
  56.     sum = (sum >> 16) + (sum & 0xFFFF);
  57.     sum += (sum >> 16);
  58.     result = ~sum;
  59.     return result;
  60. }
  61.  
  62.  
  63. // Interrupt handler
  64. void intHandler(int dummy)
  65. {
  66.     pingloop=0;
  67. }
  68.  
  69. // Performs a DNS lookup
  70. char *dns_lookup(char *addr_host, struct sockaddr_in *addr_con)
  71. {
  72.     printf("\nResolving DNS..\n");
  73.     struct hostent *host_entity;
  74.     char *ip=(char*)malloc(NI_MAXHOST*sizeof(char));
  75.     int i;
  76.  
  77.     if ((host_entity = gethostbyname(addr_host)) == NULL)
  78.     {
  79.         // No ip found for hostname
  80.         return NULL;
  81.     }
  82.      
  83.     //filling up address structure
  84.     strcpy(ip, inet_ntoa(*(struct in_addr *)
  85.                           host_entity->h_addr));
  86.  
  87.     (*addr_con).sin_family = host_entity->h_addrtype;
  88.     (*addr_con).sin_port = htons (PORT_NO);
  89.     (*addr_con).sin_addr.s_addr  = *(long*)host_entity->h_addr;
  90.  
  91.     return ip;
  92.      
  93. }
  94.  
  95. // Resolves the reverse lookup of the hostname
  96. char* reverse_dns_lookup(char *ip_addr)
  97. {
  98.     struct sockaddr_in temp_addr;  
  99.     socklen_t len;
  100.     char buf[NI_MAXHOST], *ret_buf;
  101.  
  102.     temp_addr.sin_family = AF_INET;
  103.     temp_addr.sin_addr.s_addr = inet_addr(ip_addr);
  104.     len = sizeof(struct sockaddr_in);
  105.  
  106.     if (getnameinfo((struct sockaddr *) &temp_addr, len, buf,
  107.                     sizeof(buf), NULL, 0, NI_NAMEREQD))
  108.     {
  109.         printf("Could not resolve reverse lookup of hostname\n");
  110.         return NULL;
  111.     }
  112.     ret_buf = (char*)malloc((strlen(buf) +1)*sizeof(char) );
  113.     strcpy(ret_buf, buf);
  114.     return ret_buf;
  115. }
  116.  
  117. // make a ping request
  118. void send_ping(int ping_sockfd, struct sockaddr_in *ping_addr,
  119.                 char *ping_dom, char *ping_ip, char *rev_host)
  120. {
  121.     int ttl_val=64, msg_count=0, i, addr_len, flag=1,
  122.                msg_received_count=0;
  123.      
  124.     struct ping_pkt pckt;
  125.     struct sockaddr_in r_addr;
  126.     struct timespec time_start, time_end, tfs, tfe;
  127.     long double rtt_msec=0, total_msec=0;
  128.     struct timeval tv_out;
  129.     tv_out.tv_sec = RECV_TIMEOUT;
  130.     tv_out.tv_usec = 0;
  131.  
  132.     clock_gettime(CLOCK_MONOTONIC, &tfs);
  133.  
  134.      
  135.     // set socket options at ip to TTL and value to 64,
  136.     // change to what you want by setting ttl_val
  137.     if (setsockopt(ping_sockfd, SOL_IP, IP_TTL,
  138.                &ttl_val, sizeof(ttl_val)) != 0)
  139.     {
  140.         printf("\nSetting socket options
  141.                 to TTL failed!\n");
  142.         return;
  143.     }
  144.  
  145.     else
  146.     {
  147.         printf("\nSocket set to TTL..\n");
  148.     }
  149.  
  150.     // setting timeout of recv setting
  151.     setsockopt(ping_sockfd, SOL_SOCKET, SO_RCVTIMEO,
  152.                    (const char*)&tv_out, sizeof tv_out);
  153.  
  154.     // send icmp packet in an infinite loop
  155.     while(pingloop)
  156.     {
  157.         // flag is whether packet was sent or not
  158.         flag=1;
  159.      
  160.         //filling packet
  161.         bzero(&pckt, sizeof(pckt));
  162.          
  163.         pckt.hdr.type = ICMP_ECHO;
  164.         pckt.hdr.un.echo.id = getpid();
  165.          
  166.         for ( i = 0; i < sizeof(pckt.msg)-1; i++ )
  167.             pckt.msg[i] = i+'0';
  168.          
  169.         pckt.msg[i] = 0;
  170.         pckt.hdr.un.echo.sequence = msg_count++;
  171.         pckt.hdr.checksum = checksum(&pckt, sizeof(pckt));
  172.  
  173.  
  174.         usleep(PING_SLEEP_RATE);
  175.  
  176.         //send packet
  177.         clock_gettime(CLOCK_MONOTONIC, &time_start);
  178.         if ( sendto(ping_sockfd, &pckt, sizeof(pckt), 0,
  179.            (struct sockaddr*) ping_addr,
  180.             sizeof(*ping_addr)) <= 0)
  181.         {
  182.             printf("\nPacket Sending Failed!\n");
  183.             flag=0;
  184.         }
  185.  
  186.         //receive packet
  187.         addr_len=sizeof(r_addr);
  188.  
  189.         if ( recvfrom(ping_sockfd, &pckt, sizeof(pckt), 0,
  190.              (struct sockaddr*)&r_addr, &addr_len) <= 0
  191.               && msg_count>1)
  192.         {
  193.             printf("\nPacket receive failed!\n");
  194.         }
  195.  
  196.         else
  197.         {
  198.             clock_gettime(CLOCK_MONOTONIC, &time_end);
  199.              
  200.             double timeElapsed = ((double)(time_end.tv_nsec -
  201.                                  time_start.tv_nsec))/1000000.0
  202.             rtt_msec = (time_end.tv_sec-
  203.                           time_start.tv_sec) * 1000.0
  204.                         + timeElapsed;
  205.              
  206.             // if packet was not sent, don't receive
  207.             if(flag)
  208.             {
  209.                 if(!(pckt.hdr.type ==69 && pckt.hdr.code==0))
  210.                 {
  211.                     printf("Error..Packet received with ICMP
  212.                           type %d code %d\n",
  213.                            pckt.hdr.type, pckt.hdr.code);
  214.                 }
  215.                 else
  216.                 {
  217.                     printf("%d bytes from %s (h: %s)
  218.                          (%s) msg_seq=%d ttl=%d
  219.                          rtt = %Lf ms.\n",
  220.                           PING_PKT_S, ping_dom, rev_host,
  221.                           ping_ip, msg_count,
  222.                           ttl_val, rtt_msec);
  223.  
  224.                     msg_received_count++;
  225.                 }
  226.             }
  227.         }  
  228.     }
  229.     clock_gettime(CLOCK_MONOTONIC, &tfe);
  230.     double timeElapsed = ((double)(tfe.tv_nsec -
  231.                           tfs.tv_nsec))/1000000.0;
  232.      
  233.     total_msec = (tfe.tv_sec-tfs.tv_sec)*1000.0+
  234.                           timeElapsed
  235.                    
  236.     printf("\n===%s ping statistics===\n", ping_ip);
  237.     printf("\n%d packets sent, %d packets received, %f percent
  238.           packet loss. Total time: %Lf ms.\n\n",
  239.            msg_count, msg_received_count,
  240.            ((msg_count - msg_received_count)/msg_count) * 100.0,
  241.           total_msec);
  242. }
  243.  
  244. // Driver Code
  245. int main(int argc, char *argv[])
  246. {
  247.     int sockfd;
  248.     char *ip_addr, *reverse_hostname;
  249.     struct sockaddr_in addr_con;
  250.     int addrlen = sizeof(addr_con);
  251.     char net_buf[NI_MAXHOST];
  252.  
  253.     if(argc!=2)
  254.     {
  255.         printf("\nFormat %s <address>\n", argv[0]);
  256.         return 0;
  257.     }
  258.  
  259.     ip_addr = dns_lookup(argv[1], &addr_con);
  260.     if(ip_addr==NULL)
  261.     {
  262.         printf("\nDNS lookup failed! Could
  263.                   not resolve hostname!\n");
  264.         return 0;
  265.     }
  266.  
  267.     reverse_hostname = reverse_dns_lookup(ip_addr);
  268.     printf("\nTrying to connect to '%s' IP: %s\n",
  269.                                        argv[1], ip_addr);
  270.     printf("\nReverse Lookup domain: %s",
  271.                            reverse_hostname);
  272.  
  273.     //socket()
  274.     sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
  275.     if(sockfd<0)
  276.     {
  277.         printf("\nSocket file descriptor not received!!\n");
  278.         return 0;
  279.     }
  280.     else
  281.         printf("\nSocket file descriptor %d received\n", sockfd);
  282.  
  283.     signal(SIGINT, intHandler);//catching interrupt
  284.  
  285.     //send pings continuously
  286.     send_ping(sockfd, &addr_con, reverse_hostname,
  287.                                  ip_addr, argv[1]);
  288.      
  289.     return 0;
  290. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement