Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

172 lines
4.6 KiB

  1. /*****************************************************************************
  2. *
  3. * $Workfile: PingICMP.cpp $
  4. *
  5. * Copyright (C) 1997 Hewlett-Packard Company.
  6. * Copyright (C) 1997 Microsoft Corporation.
  7. * All rights reserved.
  8. *
  9. * 11311 Chinden Blvd.
  10. * Boise, Idaho 83714
  11. *
  12. *****************************************************************************/
  13. #include "precomp.h"
  14. #include "pingicmp.h"
  15. ///////////////////////////////////////////////////////////////////////////////
  16. // CPingICMP::CPingICMP()
  17. CPingICMP::CPingICMP(const char *pHost) :
  18. hIcmp(INVALID_HANDLE_VALUE), m_iLastError(NO_ERROR)
  19. {
  20. strncpyn(m_szHost, pHost, sizeof( m_szHost));
  21. } // ::CPingICMP()
  22. ///////////////////////////////////////////////////////////////////////////////
  23. // CPingICMP::~CPingICMP()
  24. CPingICMP::~CPingICMP()
  25. {
  26. _ASSERTE(hIcmp == INVALID_HANDLE_VALUE);
  27. } // ::~CPingICMP()
  28. ///////////////////////////////////////////////////////////////////////////////
  29. // Open -- AF_INET, SOCK_RAW, IPPROTO_ICMP
  30. BOOL
  31. CPingICMP::Open()
  32. {
  33. _ASSERTE(hIcmp == INVALID_HANDLE_VALUE);
  34. if ( (hIcmp = IcmpCreateFile()) == INVALID_HANDLE_VALUE )
  35. {
  36. m_iLastError = GetLastError();
  37. return FALSE;
  38. }
  39. return TRUE;
  40. } // ::Open()
  41. ///////////////////////////////////////////////////////////////////////////////
  42. // Close
  43. BOOL
  44. CPingICMP::Close()
  45. {
  46. BOOL bRet = (hIcmp == INVALID_HANDLE_VALUE || IcmpCloseHandle(hIcmp));
  47. if ( !bRet )
  48. m_iLastError = GetLastError();
  49. else
  50. hIcmp = INVALID_HANDLE_VALUE;
  51. return bRet;
  52. } // ::Close()
  53. ///////////////////////////////////////////////////////////////////////////////
  54. // Ping -- sends an ICMP Echo Request & reads the ICMP Echo Reply back. It
  55. // records the round trip time.
  56. // Note: SOCK_RAW support is optional in WinSock V1.1, so this will not
  57. // work over all WinSock implementations.
  58. // Error Codes:
  59. // NO_ERROR if successfull
  60. // WinSock error otherwise
  61. BOOL
  62. CPingICMP::Ping()
  63. {
  64. BOOL bRet = FALSE;
  65. DWORD timeOut = 5 * 1000; // 5 seconds, 5000 milliseconds
  66. int i, nReplies, nRetries = 2; // It is not necessary to retry 3 times.
  67. // Printers need retry means they are
  68. // too far away to print
  69. char cSendBuf[4], cRcvBuf[1024];
  70. IP_OPTION_INFORMATION IpOptions;
  71. PICMP_ECHO_REPLY pReply;
  72. IPAddr IpAddr;
  73. if ( (IpAddr = ResolveAddress()) == INADDR_NONE || !Open() )
  74. return FALSE;
  75. ZeroMemory(&IpOptions, sizeof(IpOptions));
  76. IpOptions.Ttl = 128; // From ping utility (net\sockets\tcpcmd\ping)
  77. //
  78. // *** Since 0 initialized the following is not needed
  79. //
  80. // IpOptions.Tos = 0;
  81. // IpOptions.OptionsSize = 0;
  82. // IpOptions.OptionsData = NULL;
  83. // IpOptions.Flags = 0;
  84. for ( i = 0 ; i < sizeof(cSendBuf) ; ++i )
  85. cSendBuf[i] = 'a' + i;
  86. // send ICMP echo request
  87. for (i = 0; !bRet && i < nRetries; i++)
  88. {
  89. nReplies = IcmpSendEcho(hIcmp,
  90. IpAddr,
  91. cSendBuf,
  92. sizeof(cSendBuf),
  93. &IpOptions,
  94. cRcvBuf,
  95. sizeof(cRcvBuf),
  96. timeOut);
  97. pReply = (PICMP_ECHO_REPLY)cRcvBuf;
  98. while (!bRet && nReplies--)
  99. {
  100. bRet = sizeof(cSendBuf) == pReply->DataSize &&
  101. memcmp(cSendBuf, pReply->Data, sizeof(cSendBuf)) == 0;
  102. pReply++;
  103. }
  104. }
  105. Close();
  106. return bRet; // device is found
  107. } // ::Ping()
  108. ///////////////////////////////////////////////////////////////////////////////
  109. // ResolveAddress
  110. IPAddr
  111. CPingICMP::ResolveAddress()
  112. {
  113. IPAddr ipAddr = INADDR_NONE;
  114. struct hostent *h_info; /* host information */
  115. /*
  116. * m_szHost is not necessarily a host name. It could be an IP address as well
  117. */
  118. if ( (ipAddr = inet_addr(m_szHost)) == INADDR_NONE )
  119. {
  120. if ((h_info = gethostbyname(m_szHost)) != NULL)
  121. {
  122. /*
  123. * Copy the IP address to the address structure.
  124. */
  125. memcpy(&ipAddr, h_info->h_addr, sizeof(ipAddr));
  126. }
  127. }
  128. return ipAddr;
  129. }