Functions.cpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #include "Functions.h"
  2. #include <arpa/inet.h>
  3. #include <sys/types.h>
  4. #include <sys/param.h>
  5. #include <sys/socket.h>
  6. #include <netinet/in_systm.h>
  7. #include <netinet/in.h>
  8. #include <netinet/ip.h>
  9. #include <netinet/ip_icmp.h>
  10. #include <unistd.h>
  11. #include <string>
  12. #include <stdexcept>
  13. namespace PresenceDetection {
  14. namespace WiFi {
  15. #define DEFDATALEN (64-ICMP_MINLEN)
  16. #define MAXIPLEN 60
  17. #define MAXICMPLEN 76
  18. #define MAXPACKET (65536 - 60 - ICMP_MINLEN)
  19. bool Functions::Ping(const std::string& ipAddress)
  20. {
  21. int s, i, cc, packlen, datalen = DEFDATALEN;
  22. struct hostent *hp;
  23. struct sockaddr_in to, from;
  24. struct ip *ip;
  25. u_char *packet, outpack[MAXPACKET];
  26. char hnamebuf[MAXHOSTNAMELEN];
  27. std::string hostname = ipAddress;
  28. struct icmp *icp;
  29. int ret, fromlen, hlen;
  30. fd_set rfds;
  31. struct timeval tv;
  32. int retval;
  33. to.sin_family = AF_INET;
  34. to.sin_addr.s_addr = inet_addr(ipAddress.c_str());
  35. packlen = datalen + MAXIPLEN + MAXICMPLEN;
  36. if ( (packet = (u_char *)malloc((u_int)packlen)) == NULL)
  37. throw std::runtime_error("Can't allocate Packet");
  38. if ( (s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
  39. throw std::runtime_error("Can't send on ICMP Socket");
  40. icp = (struct icmp*)outpack;
  41. icp->icmp_type = ICMP_ECHO;
  42. icp->icmp_code = 0;
  43. icp->icmp_cksum = 0;
  44. icp->icmp_seq = 12345;
  45. icp->icmp_id = getpid();
  46. cc = datalen + ICMP_MINLEN;
  47. icp->icmp_cksum = ICMPChecksum((unsigned short*)icp,cc);
  48. i = sendto(s, (char*)outpack, cc, 0, (struct sockaddr*)&to, (socklen_t)sizeof(struct sockaddr_in));
  49. if (i < 0)
  50. throw std::runtime_error("Can't send on ICMP Packet");
  51. FD_ZERO(&rfds);
  52. FD_SET(s, &rfds);
  53. tv.tv_sec = 0;
  54. tv.tv_usec = 500000;
  55. while(1)
  56. {
  57. retval = select(s+1, &rfds, NULL, NULL, &tv);
  58. if (retval == -1)
  59. throw std::runtime_error("Can't select file descriptor");
  60. if (!retval)
  61. return false;
  62. fromlen = sizeof(sockaddr_in);
  63. if ((ret = recvfrom(s, (char*)packet, packlen, 0,(struct sockaddr*)&from, (socklen_t*)&fromlen)) < 0)
  64. throw std::runtime_error("Can't receive message from socket");
  65. ip = (struct ip*)((char*)packet);
  66. hlen = sizeof(struct ip);
  67. if (ret < (hlen + ICMP_MINLEN))
  68. throw std::runtime_error("Can't allocate memory for receiving packets");
  69. icp = (struct icmp*)(packet + hlen);
  70. if (icp->icmp_type != ICMP_ECHOREPLY)
  71. continue;
  72. if (icp->icmp_seq != 12345 || icp->icmp_id != getpid())
  73. continue;
  74. return true;
  75. }
  76. return false;
  77. }
  78. uint16_t Functions::ICMPChecksum(uint16_t* addr, unsigned len)
  79. {
  80. uint16_t answer = 0;
  81. uint32_t sum = 0;
  82. while (len > 1)
  83. {
  84. sum += *addr++;
  85. len -= 2;
  86. }
  87. if (len == 1)
  88. {
  89. *(unsigned char*)&answer = *(unsigned char*)addr ;
  90. sum += answer;
  91. }
  92. sum = (sum >> 16) + (sum & 0xffff);
  93. sum += (sum >> 16);
  94. answer = ~sum;
  95. return answer;
  96. }
  97. } // namespace WiFi
  98. } // namespace PresenceDetection