359 lines
8.6 KiB
C++
359 lines
8.6 KiB
C++
/*++
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ping.c
|
|
|
|
Abstract:
|
|
|
|
Packet INternet Groper utility for TCP/IP.
|
|
|
|
Author:
|
|
|
|
Numerous TCP/IP folks.
|
|
|
|
Revision History:
|
|
|
|
Who When What
|
|
-------- -------- ----------------------------------------------
|
|
WeihaiC 5-Dec-98. Moved from \nt\private\net\sockets\tcpcmd\ping
|
|
MohsinA, 21-Oct-96. INADDR_NONE check to avoid broadcast.
|
|
MohsinA, 13-Nov-96. Max packet size < 64K.
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
//:ts=4
|
|
typedef unsigned long ULONG;
|
|
typedef unsigned short ushort;
|
|
typedef unsigned int UINT;
|
|
typedef unsigned char UCHAR;
|
|
|
|
#include "precomp.h"
|
|
#include "icmpapi.h"
|
|
|
|
#define NOGDI
|
|
#define NOMINMAX
|
|
|
|
|
|
#define MAX_BUFFER_SIZE (sizeof(ICMP_ECHO_REPLY) + 0xfff7 + MAX_OPT_SIZE)
|
|
#define DEFAULT_BUFFER_SIZE (0x2000 - 8)
|
|
#define DEFAULT_SEND_SIZE 32
|
|
#define DEFAULT_COUNT 4
|
|
#define DEFAULT_TTL 32
|
|
#define DEFAULT_TOS 0
|
|
#define DEFAULT_TIMEOUT 5000L
|
|
#define MIN_INTERVAL 1000L
|
|
#define TRUE 1
|
|
#define FALSE 0
|
|
#define STDOUT 1
|
|
|
|
#define net_long(x) (((((ULONG)(x))&0xffL)<<24) | \
|
|
((((ULONG)(x))&0xff00L)<<8) | \
|
|
((((ULONG)(x))&0xff0000L)>>8) | \
|
|
((((ULONG)(x))&0xff000000L)>>24))
|
|
|
|
#ifdef VXD
|
|
|
|
#define FAR _far
|
|
|
|
#endif // VXD
|
|
|
|
|
|
WSADATA WsaData;
|
|
|
|
|
|
// ========================================================================
|
|
// Caveat: return 0 for invalid, else internet address.
|
|
// I would prefer -1 for error. - MohsinA, 21-Nov-96.
|
|
|
|
unsigned long
|
|
get_pingee(char *ahstr, char **hstr, int *was_inaddr, int dnsreq)
|
|
{
|
|
struct hostent *hostp = NULL;
|
|
long inaddr;
|
|
|
|
if( strcmp( ahstr, "255.255.255.255" ) == 0 ){
|
|
return 0L;
|
|
}
|
|
|
|
if ((inaddr = inet_addr(ahstr)) == -1L) {
|
|
hostp = gethostbyname(ahstr);
|
|
if (hostp) {
|
|
/*
|
|
* If we find a host entry, set up the internet address
|
|
*/
|
|
inaddr = *(long *)hostp->h_addr;
|
|
*was_inaddr = 0;
|
|
} else {
|
|
// Neither dotted, not name.
|
|
return(0L);
|
|
}
|
|
|
|
} else {
|
|
// Is dotted.
|
|
*was_inaddr = 1;
|
|
if (dnsreq == 1) {
|
|
hostp = gethostbyaddr((char *)&inaddr,sizeof(inaddr),AF_INET);
|
|
}
|
|
}
|
|
|
|
*hstr = hostp ? hostp->h_name : (char *)NULL;
|
|
return(inaddr);
|
|
}
|
|
|
|
|
|
|
|
|
|
// ========================================================================
|
|
|
|
BOOL Ping (LPTSTR pszServerName)
|
|
{
|
|
UINT i;
|
|
UINT j;
|
|
int found_addr = 0;
|
|
int dnsreq = 0;
|
|
char *hostname = NULL;
|
|
int was_inaddr;
|
|
DWORD numberOfReplies;
|
|
UINT Count = DEFAULT_COUNT;
|
|
UCHAR TTL = DEFAULT_TTL;
|
|
UCHAR FAR *Opt = (UCHAR FAR *)0; // Pointer to send options
|
|
UINT OptLength = 0;
|
|
int OptIndex = 0; // Current index into SendOptions
|
|
int SRIndex = -1; // Where to put address, if source routing
|
|
UCHAR TOS = DEFAULT_TOS;
|
|
UCHAR Flags = 0;
|
|
ULONG Timeout = DEFAULT_TIMEOUT;
|
|
IP_OPTION_INFORMATION SendOpts;
|
|
int EndOffset;
|
|
ULONG TempAddr;
|
|
UCHAR TempCount;
|
|
DWORD errorCode;
|
|
HANDLE IcmpHandle = NULL;
|
|
int err;
|
|
struct in_addr addr;
|
|
BOOL result;
|
|
PICMP_ECHO_REPLY reply;
|
|
BOOL sourceRouting = FALSE;
|
|
char *SendBuffer = NULL;
|
|
char *RcvBuffer = NULL;
|
|
UINT RcvSize;
|
|
UINT SendSize = DEFAULT_SEND_SIZE;
|
|
BOOL bRet = FALSE;
|
|
IPAddr address = 0; // was local to main earlier.
|
|
char *arg;
|
|
|
|
// ====================================================================
|
|
|
|
#ifdef UNICODE
|
|
|
|
LPSTR pszAnsiServerName = NULL;
|
|
DWORD uSize;
|
|
|
|
if (pszServerName && (uSize = WideCharToMultiByte(CP_ACP,
|
|
0,
|
|
pszServerName,
|
|
-1,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL))) {
|
|
|
|
if (pszAnsiServerName = (LPSTR) LocalAlloc(LPTR, uSize)) {
|
|
if (!WideCharToMultiByte (CP_ACP,
|
|
0,
|
|
pszServerName,
|
|
-1,
|
|
pszAnsiServerName,
|
|
uSize,
|
|
NULL,
|
|
NULL))
|
|
|
|
goto CleanUp;
|
|
|
|
}
|
|
else
|
|
goto CleanUp;
|
|
|
|
}
|
|
|
|
arg = pszAnsiServerName;
|
|
|
|
#else
|
|
arg = pszServerName;
|
|
#endif
|
|
|
|
|
|
if (WSAStartup( 0x0101, &WsaData))
|
|
goto CleanUp;
|
|
|
|
// Added check for INADDR_NONE, MohsinA, 21-Oct-96.
|
|
|
|
address = get_pingee(arg, &hostname, &was_inaddr, dnsreq);
|
|
if(!address || (address == INADDR_NONE) ){
|
|
SetLastError (DNS_ERROR_INVALID_IP_ADDRESS);
|
|
goto CleanUp;
|
|
}
|
|
|
|
IcmpHandle = IcmpCreateFile();
|
|
|
|
if (IcmpHandle == INVALID_HANDLE_VALUE) {
|
|
goto CleanUp;
|
|
}
|
|
|
|
if (! (SendBuffer = (char *) LocalAlloc(LMEM_FIXED, SendSize))) {
|
|
goto CleanUp;
|
|
}
|
|
|
|
//
|
|
// Calculate receive buffer size and try to allocate it.
|
|
//
|
|
if (SendSize <= DEFAULT_SEND_SIZE) {
|
|
RcvSize = DEFAULT_BUFFER_SIZE;
|
|
}
|
|
else {
|
|
RcvSize = MAX_BUFFER_SIZE;
|
|
}
|
|
|
|
if (! (RcvBuffer = (char *)LocalAlloc(LMEM_FIXED, RcvSize))) {
|
|
goto CleanUp;
|
|
}
|
|
|
|
//
|
|
// Initialize the send buffer pattern.
|
|
//
|
|
for (i = 0; i < SendSize; i++) {
|
|
SendBuffer[i] = 'a' + (i % 23);
|
|
}
|
|
|
|
//
|
|
// Initialize the send options
|
|
//
|
|
SendOpts.OptionsData = Opt;
|
|
SendOpts.OptionsSize = (UCHAR)OptLength;
|
|
SendOpts.Ttl = TTL;
|
|
SendOpts.Tos = TOS;
|
|
SendOpts.Flags = Flags;
|
|
|
|
addr.s_addr = address;
|
|
|
|
#if 0
|
|
if (hostname) {
|
|
NlsPutMsg(
|
|
STDOUT,
|
|
PING_HEADER1,
|
|
hostname,
|
|
inet_ntoa(addr),
|
|
SendSize
|
|
);
|
|
// printf("Pinging Host %s [%s]\n", hostname, inet_ntoa(addr));
|
|
} else {
|
|
NlsPutMsg(
|
|
STDOUT,
|
|
PING_HEADER2,
|
|
inet_ntoa(addr),
|
|
SendSize
|
|
);
|
|
// printf("Pinging Host [%s]\n", inet_ntoa(addr));
|
|
}
|
|
#endif
|
|
|
|
// for (i = 0; i < Count; i++) {
|
|
numberOfReplies = IcmpSendEcho(
|
|
IcmpHandle,
|
|
address,
|
|
SendBuffer,
|
|
(unsigned short) SendSize,
|
|
&SendOpts,
|
|
RcvBuffer,
|
|
RcvSize,
|
|
Timeout
|
|
);
|
|
|
|
if (numberOfReplies == 0) {
|
|
|
|
errorCode = GetLastError();
|
|
|
|
goto CleanUp;
|
|
// Need to try again? - weihaic
|
|
}
|
|
else {
|
|
|
|
reply = (PICMP_ECHO_REPLY) RcvBuffer;
|
|
|
|
while (numberOfReplies--) {
|
|
struct in_addr addr;
|
|
|
|
addr.S_un.S_addr = reply->Address;
|
|
|
|
// printf(
|
|
// "Reply from %s:",
|
|
// inet_ntoa(addr),
|
|
// );
|
|
|
|
if (reply->Status == IP_SUCCESS) {
|
|
|
|
// printf(
|
|
// "Echo size=%d ",
|
|
// reply->DataSize
|
|
// );
|
|
|
|
bRet = TRUE;
|
|
break;
|
|
|
|
|
|
// printf("\n time rt=%dms min %d, max %d, total %d\n",
|
|
// reply->RoundTripTime,
|
|
// time_min, time_max, time_total );
|
|
|
|
// printf("TTL=%u\n", (UINT)reply->Options.Ttl);
|
|
|
|
//
|
|
// Ignore Option fields
|
|
// if (reply->Options.OptionsSize) {
|
|
// ProcessOptions(reply, (BOOLEAN) dnsreq);
|
|
//}
|
|
}
|
|
/* else {
|
|
for (j=0; ErrorTable[j].Error != IP_GENERAL_FAILURE; j++) {
|
|
if (ErrorTable[j].Error == reply->Status) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
} */
|
|
|
|
reply++;
|
|
}
|
|
|
|
}
|
|
// }
|
|
|
|
CleanUp:
|
|
|
|
#ifdef UNICODE
|
|
if (pszAnsiServerName) {
|
|
LocalFree(pszAnsiServerName);
|
|
}
|
|
#endif
|
|
|
|
if (IcmpHandle) {
|
|
IcmpCloseHandle(IcmpHandle);
|
|
}
|
|
|
|
if (SendBuffer) {
|
|
LocalFree(SendBuffer);
|
|
}
|
|
|
|
if (RcvBuffer) {
|
|
LocalFree(RcvBuffer);
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|