PingImpl.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. //
  2. // THIS CODE IS BASED ON THE CODE FROM
  3. // THE BOOK WINSOCK 2.0 BY LEWIS NAPPER...
  4. //
  5. //
  6. #include "RestfulFunc.h"
  7. #include<sys/socket.h>
  8. #include<sys/types.h>
  9. #include<netinet/in.h>
  10. #include<netinet/ip_icmp.h>
  11. #include<arpa/inet.h>
  12. #include<unistd.h>
  13. #include<sys/time.h>
  14. typedef uint32_t DWORD;
  15. typedef int SOCKET;
  16. typedef struct sockaddr_in* LPSOCKADDR_IN;
  17. typedef struct hostent* LPHOSTENT;
  18. #define SOCKET_ERROR (-1)
  19. #define FAILURE (-1)
  20. #define SIZE_LINE_NORMAL (1024)
  21. #define SUCCESS (0)
  22. #pragma pack(1)
  23. #define ICMP_ECHOREPLY 0
  24. #define ICMP_ECHOREQ 8
  25. // IP Header -- RFC 791
  26. typedef struct tagIPHDR
  27. {
  28. u_char VIHL; // Version and IHL
  29. u_char TOS; // Type Of Service
  30. short TotLen; // Total Length
  31. short ID; // Identification
  32. short FlagOff; // Flags and Fragment Offset
  33. u_char TTL; // Time To Live
  34. u_char Protocol; // Protocol
  35. u_short Checksum; // Checksum
  36. struct in_addr iaSrc; // Internet Address - Source
  37. struct in_addr iaDst; // Internet Address - Destination
  38. } IPHDR, * PIPHDR;
  39. // ICMP Header - RFC 792
  40. typedef struct tagICMPHDR
  41. {
  42. u_char Type; // Type
  43. u_char Code; // Code
  44. u_short Checksum; // Checksum
  45. u_short ID; // Identification
  46. u_short Seq; // Sequence
  47. char Data; // Data
  48. } ICMPHDR, * PICMPHDR;
  49. #define REQ_DATASIZE 32 // Echo Request Data size
  50. // ICMP Echo Request
  51. typedef struct tagECHOREQUEST
  52. {
  53. ICMPHDR icmpHdr;
  54. DWORD dwTime;
  55. char cData[REQ_DATASIZE];
  56. } ECHOREQUEST, * PECHOREQUEST;
  57. // ICMP Echo Reply
  58. typedef struct tagECHOREPLY
  59. {
  60. IPHDR ipHdr;
  61. ECHOREQUEST echoRequest;
  62. char cFiller[256];
  63. } ECHOREPLY, * PECHOREPLY;
  64. #pragma pack()
  65. static u_short api_checksum16(u_short *buffer, int size) ;
  66. static int gen_icmp_packet(struct icmp *icmp_packet, int type, int seq);
  67. int gen_icmp_packet(struct icmp *icmp_packet, int type, int seq)
  68. {
  69. if ( !icmp_packet ) {
  70. return FAILURE;
  71. }
  72. icmp_packet->icmp_type = type;
  73. icmp_packet->icmp_code = 0;
  74. icmp_packet->icmp_cksum = 0;
  75. icmp_packet->icmp_id = htons(getpid());
  76. icmp_packet->icmp_seq = htons(seq);
  77. gettimeofday((struct timeval *)icmp_packet->icmp_data, NULL);
  78. icmp_packet->icmp_cksum = api_checksum16((unsigned short *)icmp_packet, sizeof(struct icmp));
  79. return SUCCESS;
  80. }
  81. u_short api_checksum16(u_short *buffer, int size)
  82. {
  83. u_int cksum = 0;
  84. if ( !buffer ) {
  85. printf("NULL\n");
  86. return 0;
  87. }
  88. while ( size > 1 ) {
  89. printf("1. Cksum: 0x%08x + 0x%04x\n", cksum, *buffer);
  90. cksum += *buffer++;
  91. size -= sizeof(u_short);
  92. }
  93. if ( size ) {
  94. cksum += *(u_char *)buffer;
  95. }
  96. printf("2. Cksum: 0x%08x\n", cksum);
  97. /* 32 bit change to 16 bit */
  98. while ( cksum >> 16 ) {
  99. cksum = (cksum >> 16) + (cksum & 0xFFFF);
  100. printf("3. Cksum: 0x%08x\n", cksum);
  101. }
  102. return (u_short)(~cksum);
  103. }
  104. int PingTest(const std::string& dst_ip)
  105. {
  106. int ret = FAILURE;
  107. int sd = 0;
  108. char buf[SIZE_LINE_NORMAL] = { 0 };
  109. struct ip* ip = NULL;
  110. struct sockaddr_in dst_addr = { 0 };
  111. struct icmp icmp_packet = { 0 };
  112. struct timeval tm = { .tv_sec = 1, .tv_usec = 0 };
  113. fd_set rdfds;
  114. if (dst_ip.empty()) {
  115. goto _E1;
  116. }
  117. sd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
  118. if (sd < 0) {
  119. printf("socket fail: %d\n", errno);
  120. goto _E1;
  121. }
  122. dst_addr.sin_family = AF_INET;
  123. dst_addr.sin_addr.s_addr = inet_addr(dst_ip.c_str());
  124. ret = gen_icmp_packet(&icmp_packet, 8, 1);
  125. if (SUCCESS != ret) {
  126. goto _E2;
  127. }
  128. ret = sendto(sd, &icmp_packet, sizeof(struct icmp), 0,
  129. (struct sockaddr*)&dst_addr, sizeof(struct sockaddr_in));
  130. if (ret < 0) {
  131. goto _E2;
  132. }
  133. /* Timeout 1s to recv icmp */
  134. FD_ZERO(&rdfds);
  135. FD_SET(sd, &rdfds);
  136. ret = select(sd + 1, &rdfds, NULL, NULL, &tm);
  137. if (-1 == ret && EINTR != errno) {
  138. /* if serial error */
  139. printf("select fail\n");
  140. goto _E2;
  141. } else if (0 == ret) {
  142. /* timeout */
  143. printf("recv timeout\n");
  144. ret = FAILURE;
  145. goto _E2;
  146. }
  147. if (FD_ISSET(sd, &rdfds)) {
  148. ret = recv(sd, buf, sizeof(buf), 0);
  149. if (ret <= 0) {
  150. perror("recv\n");
  151. goto _E2;
  152. }
  153. ip = (struct ip*)buf;
  154. printf("from: %s\n", inet_ntoa(ip->ip_src));
  155. printf(" to: %s\n", inet_ntoa(ip->ip_dst));
  156. }
  157. ret = SUCCESS;
  158. _E2:
  159. close(sd);
  160. _E1:
  161. return ret;
  162. }