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
172 lines
4.6 KiB
/*****************************************************************************
|
|
*
|
|
* $Workfile: PingICMP.cpp $
|
|
*
|
|
* Copyright (C) 1997 Hewlett-Packard Company.
|
|
* Copyright (C) 1997 Microsoft Corporation.
|
|
* All rights reserved.
|
|
*
|
|
* 11311 Chinden Blvd.
|
|
* Boise, Idaho 83714
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#include "pingicmp.h"
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CPingICMP::CPingICMP()
|
|
|
|
CPingICMP::CPingICMP(const char *pHost) :
|
|
hIcmp(INVALID_HANDLE_VALUE), m_iLastError(NO_ERROR)
|
|
{
|
|
strncpyn(m_szHost, pHost, sizeof( m_szHost));
|
|
} // ::CPingICMP()
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CPingICMP::~CPingICMP()
|
|
|
|
CPingICMP::~CPingICMP()
|
|
{
|
|
_ASSERTE(hIcmp == INVALID_HANDLE_VALUE);
|
|
} // ::~CPingICMP()
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Open -- AF_INET, SOCK_RAW, IPPROTO_ICMP
|
|
|
|
BOOL
|
|
CPingICMP::Open()
|
|
{
|
|
_ASSERTE(hIcmp == INVALID_HANDLE_VALUE);
|
|
|
|
if ( (hIcmp = IcmpCreateFile()) == INVALID_HANDLE_VALUE )
|
|
{
|
|
m_iLastError = GetLastError();
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
} // ::Open()
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Close
|
|
|
|
BOOL
|
|
CPingICMP::Close()
|
|
{
|
|
BOOL bRet = (hIcmp == INVALID_HANDLE_VALUE || IcmpCloseHandle(hIcmp));
|
|
|
|
if ( !bRet )
|
|
m_iLastError = GetLastError();
|
|
else
|
|
hIcmp = INVALID_HANDLE_VALUE;
|
|
|
|
return bRet;
|
|
|
|
} // ::Close()
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Ping -- sends an ICMP Echo Request & reads the ICMP Echo Reply back. It
|
|
// records the round trip time.
|
|
// Note: SOCK_RAW support is optional in WinSock V1.1, so this will not
|
|
// work over all WinSock implementations.
|
|
// Error Codes:
|
|
// NO_ERROR if successfull
|
|
// WinSock error otherwise
|
|
|
|
BOOL
|
|
CPingICMP::Ping()
|
|
{
|
|
BOOL bRet = FALSE;
|
|
DWORD timeOut = 5 * 1000; // 5 seconds, 5000 milliseconds
|
|
int i, nReplies, nRetries = 2; // It is not necessary to retry 3 times.
|
|
// Printers need retry means they are
|
|
// too far away to print
|
|
|
|
char cSendBuf[4], cRcvBuf[1024];
|
|
IP_OPTION_INFORMATION IpOptions;
|
|
PICMP_ECHO_REPLY pReply;
|
|
IPAddr IpAddr;
|
|
|
|
|
|
if ( (IpAddr = ResolveAddress()) == INADDR_NONE || !Open() )
|
|
return FALSE;
|
|
|
|
ZeroMemory(&IpOptions, sizeof(IpOptions));
|
|
IpOptions.Ttl = 128; // From ping utility (net\sockets\tcpcmd\ping)
|
|
|
|
//
|
|
// *** Since 0 initialized the following is not needed
|
|
//
|
|
// IpOptions.Tos = 0;
|
|
// IpOptions.OptionsSize = 0;
|
|
// IpOptions.OptionsData = NULL;
|
|
// IpOptions.Flags = 0;
|
|
|
|
for ( i = 0 ; i < sizeof(cSendBuf) ; ++i )
|
|
cSendBuf[i] = 'a' + i;
|
|
|
|
|
|
// send ICMP echo request
|
|
for (i = 0; !bRet && i < nRetries; i++)
|
|
{
|
|
|
|
nReplies = IcmpSendEcho(hIcmp,
|
|
IpAddr,
|
|
cSendBuf,
|
|
sizeof(cSendBuf),
|
|
&IpOptions,
|
|
cRcvBuf,
|
|
sizeof(cRcvBuf),
|
|
timeOut);
|
|
|
|
|
|
|
|
pReply = (PICMP_ECHO_REPLY)cRcvBuf;
|
|
while (!bRet && nReplies--)
|
|
{
|
|
bRet = sizeof(cSendBuf) == pReply->DataSize &&
|
|
memcmp(cSendBuf, pReply->Data, sizeof(cSendBuf)) == 0;
|
|
pReply++;
|
|
}
|
|
}
|
|
|
|
Close();
|
|
|
|
return bRet; // device is found
|
|
|
|
} // ::Ping()
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// ResolveAddress
|
|
|
|
IPAddr
|
|
CPingICMP::ResolveAddress()
|
|
{
|
|
IPAddr ipAddr = INADDR_NONE;
|
|
struct hostent *h_info; /* host information */
|
|
|
|
/*
|
|
* m_szHost is not necessarily a host name. It could be an IP address as well
|
|
*/
|
|
|
|
if ( (ipAddr = inet_addr(m_szHost)) == INADDR_NONE )
|
|
{
|
|
if ((h_info = gethostbyname(m_szHost)) != NULL)
|
|
{
|
|
/*
|
|
* Copy the IP address to the address structure.
|
|
*/
|
|
memcpy(&ipAddr, h_info->h_addr, sizeof(ipAddr));
|
|
}
|
|
}
|
|
|
|
return ipAddr;
|
|
}
|
|
|