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

/*****************************************************************************
*
* $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;
}