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.
1368 lines
44 KiB
1368 lines
44 KiB
/*++
|
|
|
|
Copyright (c) 1991-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ping.c
|
|
|
|
Abstract:
|
|
|
|
Packet INternet Groper utility for TCP/IP.
|
|
|
|
Author:
|
|
|
|
Numerous TCP/IP folks.
|
|
|
|
Revision History:
|
|
|
|
Who When What
|
|
-------- -------- ----------------------------------------------
|
|
MohsinA, 21-Oct-96. INADDR_NONE check to avoid broadcast.
|
|
MohsinA, 13-Nov-96. Max packet size < 64K.
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
//:ts=4
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
#include <time.h>
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <snmp.h>
|
|
#include <winsock2.h>
|
|
#include <ws2tcpip.h>
|
|
#include <ntddip6.h>
|
|
#include <winnlsp.h>
|
|
#include <iphlpapi.h>
|
|
|
|
#include "llinfo.h"
|
|
#include "tcpcmd.h"
|
|
#include "ipexport.h"
|
|
#include "icmpapi.h"
|
|
#include "nlstxt.h"
|
|
|
|
|
|
#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 128
|
|
#define DEFAULT_TOS 0
|
|
#define DEFAULT_TIMEOUT 4000L
|
|
#define MIN_INTERVAL 1000L
|
|
#define STDOUT 1
|
|
|
|
uchar SendOptions[MAX_OPT_SIZE];
|
|
|
|
WSADATA WsaData;
|
|
|
|
struct IPErrorTable {
|
|
IP_STATUS Error; // The IP Error
|
|
DWORD ErrorNlsID; // NLS string ID
|
|
} ErrorTable[] =
|
|
{
|
|
{ IP_BUF_TOO_SMALL, PING_BUF_TOO_SMALL},
|
|
{ IP_DEST_NET_UNREACHABLE, PING_DEST_NET_UNREACHABLE},
|
|
{ IP_DEST_HOST_UNREACHABLE, PING_DEST_HOST_UNREACHABLE},
|
|
{ IP_DEST_PROT_UNREACHABLE, PING_DEST_PROT_UNREACHABLE},
|
|
{ IP_DEST_PORT_UNREACHABLE, PING_DEST_PORT_UNREACHABLE},
|
|
{ IP_NO_RESOURCES, PING_NO_RESOURCES},
|
|
{ IP_BAD_OPTION, PING_BAD_OPTION},
|
|
{ IP_HW_ERROR, PING_HW_ERROR},
|
|
{ IP_PACKET_TOO_BIG, PING_PACKET_TOO_BIG},
|
|
{ IP_REQ_TIMED_OUT, PING_REQ_TIMED_OUT},
|
|
{ IP_BAD_REQ, PING_BAD_REQ},
|
|
{ IP_BAD_ROUTE, PING_BAD_ROUTE},
|
|
{ IP_TTL_EXPIRED_TRANSIT, PING_TTL_EXPIRED_TRANSIT},
|
|
{ IP_TTL_EXPIRED_REASSEM, PING_TTL_EXPIRED_REASSEM},
|
|
{ IP_PARAM_PROBLEM, PING_PARAM_PROBLEM},
|
|
{ IP_SOURCE_QUENCH, PING_SOURCE_QUENCH},
|
|
{ IP_OPTION_TOO_BIG, PING_OPTION_TOO_BIG},
|
|
{ IP_BAD_DESTINATION, PING_BAD_DESTINATION},
|
|
{ IP_NEGOTIATING_IPSEC, PING_NEGOTIATING_IPSEC},
|
|
{ IP_GENERAL_FAILURE, PING_GENERAL_FAILURE}
|
|
};
|
|
|
|
|
|
PWCHAR
|
|
GetErrorString(int ErrorCode)
|
|
{
|
|
DWORD Status;
|
|
DWORD Length;
|
|
static WCHAR ErrorString[2048]; // a 2K static buffer should suffice
|
|
|
|
Length = 2048;
|
|
Status = GetIpErrorString(ErrorCode, ErrorString, &Length);
|
|
|
|
if (Status == NO_ERROR) {
|
|
return ErrorString; // success
|
|
}
|
|
|
|
return L""; // return a null string
|
|
}
|
|
|
|
|
|
unsigned
|
|
NlsPutMsg(unsigned Handle, unsigned usMsgNum, ...)
|
|
{
|
|
unsigned msglen;
|
|
VOID * vp;
|
|
va_list arglist;
|
|
DWORD StrLen;
|
|
|
|
va_start(arglist, usMsgNum);
|
|
if ((msglen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
FORMAT_MESSAGE_FROM_HMODULE,
|
|
NULL,
|
|
usMsgNum,
|
|
0L, // Default country ID.
|
|
(LPTSTR)&vp,
|
|
0,
|
|
&arglist)) == 0)
|
|
return(0);
|
|
|
|
// Convert vp to oem
|
|
StrLen=(DWORD)strlen(vp);
|
|
CharToOemBuff((LPCTSTR)vp,(LPSTR)vp,StrLen);
|
|
|
|
msglen = _write(Handle, vp, StrLen);
|
|
LocalFree(vp);
|
|
|
|
return(msglen);
|
|
}
|
|
|
|
void
|
|
PrintUsage(void)
|
|
{
|
|
NlsPutMsg( STDOUT, PING_USAGE );
|
|
|
|
// printf(
|
|
// "Usage: ping [-s size] [-c count] [-d] [-l TTL] [-o options] [-t TOS]\n"
|
|
// " [-w timeout] address.\n"
|
|
// "Options:\n"
|
|
// " -t Ping the specifed host until interrupted.\n"
|
|
// " -l size Send buffer size.\n"
|
|
// " -n count Send count.\n"
|
|
// " -f Don't fragment.\n"
|
|
// " -i TTL Time to live.\n"
|
|
// " -v TOS Type of service\n"
|
|
// " -w timeout Timeout (in milliseconds)\n"
|
|
// " -r routes Record route.\n"
|
|
// " -s routes Timestamp route.\n"
|
|
// " -j ipaddress Loose source route.\n"
|
|
// " -k ipaddress Strict source route.\n"
|
|
// " -o IP options:\n"
|
|
// " -ol hop list Loose source route.\n"
|
|
// " -ot Timestamp.\n"
|
|
// " -or Record route\n"
|
|
// );
|
|
|
|
}
|
|
|
|
// ========================================================================
|
|
// Note: old code would reject "255.255.255.255" string, but not
|
|
// other aliases. However, the caller checks for that address returned,
|
|
// so this function doesn't need to check for it. On the other hand,
|
|
// no other broadcast addresses were disallowed (224.0.0.1, subnet
|
|
// broadcast, etc). Why?
|
|
|
|
BOOLEAN
|
|
ResolveTarget(
|
|
int Family,
|
|
char *TargetString,
|
|
SOCKADDR *TargetAddress,
|
|
socklen_t *TargetAddressLen,
|
|
char *TargetName,
|
|
int TargetNameLen,
|
|
BOOLEAN DoReverseLookup
|
|
)
|
|
{
|
|
int i;
|
|
struct addrinfo hints, *ai;
|
|
|
|
TargetName[0] = '\0';
|
|
|
|
memset(&hints, 0, sizeof(hints));
|
|
hints.ai_family = Family;
|
|
hints.ai_flags = AI_NUMERICHOST;
|
|
i = getaddrinfo(TargetString, NULL, &hints, &ai);
|
|
if (i == NO_ERROR) {
|
|
*TargetAddressLen = (int)ai->ai_addrlen;
|
|
memcpy(TargetAddress, ai->ai_addr, ai->ai_addrlen);
|
|
|
|
if (DoReverseLookup) {
|
|
getnameinfo(ai->ai_addr, (socklen_t)ai->ai_addrlen,
|
|
TargetName, TargetNameLen,
|
|
NULL, 0, NI_NAMEREQD);
|
|
}
|
|
|
|
freeaddrinfo(ai);
|
|
return(TRUE);
|
|
} else {
|
|
hints.ai_flags = AI_CANONNAME;
|
|
if (getaddrinfo(TargetString, NULL, &hints, &ai) == 0) {
|
|
*TargetAddressLen = (socklen_t)ai->ai_addrlen;
|
|
memcpy(TargetAddress, ai->ai_addr, ai->ai_addrlen);
|
|
strcpy(TargetName,
|
|
(ai->ai_canonname)? ai->ai_canonname : TargetString);
|
|
freeaddrinfo(ai);
|
|
return(TRUE);
|
|
}
|
|
}
|
|
|
|
return(FALSE);
|
|
|
|
} // ResolveTarget
|
|
|
|
unsigned long
|
|
str2ip(char *addr, int *EndOffset)
|
|
{
|
|
char *endptr = NULL;
|
|
char *start = addr;
|
|
int i; // Counter variable.
|
|
unsigned long curaddr = 0;
|
|
unsigned long temp;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
temp = strtoul(addr, &endptr, 10);
|
|
if (temp > 255)
|
|
return 0L;
|
|
if (endptr[0] != '.')
|
|
if (i != 3)
|
|
return 0L;
|
|
else
|
|
if (endptr[0] != '\0' && endptr[0] != ' ')
|
|
return 0L;
|
|
addr = endptr+1;
|
|
curaddr = (curaddr << 8) + temp;
|
|
}
|
|
|
|
*EndOffset += (int)(endptr - start);
|
|
return net_long(curaddr);
|
|
}
|
|
|
|
ulong
|
|
param(char **argv, int argc, int current, ulong min, ulong max)
|
|
{
|
|
ulong temp;
|
|
char *dummy;
|
|
|
|
if (current == (argc - 1) ) {
|
|
NlsPutMsg( STDOUT, PING_MESSAGE_1, argv[current] );
|
|
// printf( "Value must be supplied for option %s.\n", argv[current]);
|
|
exit(1);
|
|
}
|
|
|
|
temp = strtoul(argv[current+1], &dummy, 0);
|
|
if (temp < min || temp > max) {
|
|
NlsPutMsg( STDOUT, PING_MESSAGE_2, argv[current], min, max );
|
|
// printf( "Bad value for option %s. range min..max\n",
|
|
// argv[current], min, max );
|
|
exit(1);
|
|
}
|
|
|
|
return temp;
|
|
}
|
|
|
|
void
|
|
ProcessOptions(
|
|
ICMP_ECHO_REPLY *reply,
|
|
BOOLEAN DoReverseLookup)
|
|
{
|
|
UCHAR *optionPtr;
|
|
UCHAR *endPtr;
|
|
BOOLEAN done = FALSE;
|
|
UCHAR optionLength;
|
|
UCHAR entryEndPtr;
|
|
UCHAR entryPtr;
|
|
UCHAR addressMode;
|
|
int entryCount = 0;
|
|
|
|
|
|
optionPtr = reply->Options.OptionsData;
|
|
endPtr = optionPtr + reply->Options.OptionsSize;
|
|
|
|
while ((optionPtr < endPtr) && !done) {
|
|
switch (*optionPtr) {
|
|
case IP_OPT_EOL:
|
|
done = TRUE;
|
|
break;
|
|
|
|
case IP_OPT_NOP:
|
|
optionPtr++;
|
|
break;
|
|
|
|
case IP_OPT_SECURITY:
|
|
optionPtr += 11;
|
|
break;
|
|
|
|
case IP_OPT_SID:
|
|
optionPtr += 4;
|
|
break;
|
|
|
|
case IP_OPT_RR:
|
|
case IP_OPT_LSRR:
|
|
case IP_OPT_SSRR:
|
|
if ((optionPtr + 3) > endPtr) {
|
|
NlsPutMsg(STDOUT, PING_INVALID_RR_OPTION);
|
|
done = TRUE;
|
|
break;
|
|
}
|
|
|
|
optionLength = optionPtr[1];
|
|
|
|
if (((optionPtr + optionLength) > endPtr) ||
|
|
(optionLength < 3)
|
|
) {
|
|
NlsPutMsg(STDOUT, PING_INVALID_RR_OPTION);
|
|
done = TRUE;
|
|
break;
|
|
}
|
|
|
|
entryEndPtr = optionPtr[2];
|
|
|
|
if (entryEndPtr < 4) {
|
|
NlsPutMsg(STDOUT, PING_INVALID_RR_OPTION);
|
|
optionPtr += optionLength;
|
|
break;
|
|
}
|
|
|
|
if (entryEndPtr > (optionLength + 1)) {
|
|
entryEndPtr = optionLength + 1;
|
|
}
|
|
|
|
entryPtr = 4;
|
|
entryCount = 0;
|
|
|
|
NlsPutMsg(STDOUT, PING_ROUTE_HEADER1);
|
|
|
|
while ((entryPtr + 3) < entryEndPtr) {
|
|
struct in_addr routeAddress;
|
|
|
|
if (entryCount) {
|
|
NlsPutMsg(
|
|
STDOUT,
|
|
PING_ROUTE_SEPARATOR
|
|
);
|
|
|
|
if (entryCount == 1) {
|
|
NlsPutMsg(STDOUT, PING_CR);
|
|
NlsPutMsg(
|
|
STDOUT,
|
|
PING_ROUTE_HEADER2
|
|
);
|
|
entryCount = 0;
|
|
}
|
|
}
|
|
|
|
entryCount++;
|
|
|
|
routeAddress.S_un.S_addr =
|
|
*( (IPAddr UNALIGNED *)
|
|
(optionPtr + entryPtr - 1)
|
|
);
|
|
|
|
if (DoReverseLookup) {
|
|
struct hostent *hostEntry;
|
|
|
|
hostEntry = gethostbyaddr(
|
|
(char *) &routeAddress,
|
|
sizeof(routeAddress),
|
|
AF_INET
|
|
);
|
|
|
|
if (hostEntry != NULL) {
|
|
NlsPutMsg(
|
|
STDOUT,
|
|
PING_FULL_ROUTE_ENTRY,
|
|
hostEntry->h_name,
|
|
inet_ntoa(routeAddress)
|
|
);
|
|
} else {
|
|
NlsPutMsg(
|
|
STDOUT,
|
|
PING_ROUTE_ENTRY,
|
|
inet_ntoa(routeAddress)
|
|
);
|
|
}
|
|
} else {
|
|
NlsPutMsg(
|
|
STDOUT,
|
|
PING_ROUTE_ENTRY,
|
|
inet_ntoa(routeAddress)
|
|
);
|
|
}
|
|
|
|
entryPtr += 4;
|
|
}
|
|
|
|
NlsPutMsg(STDOUT, PING_CR);
|
|
|
|
optionPtr += optionLength;
|
|
break;
|
|
|
|
case IP_OPT_TS:
|
|
if ((optionPtr + 4) > endPtr) {
|
|
NlsPutMsg(STDOUT, PING_INVALID_TS_OPTION);
|
|
done = TRUE;
|
|
break;
|
|
}
|
|
|
|
optionLength = optionPtr[1];
|
|
entryEndPtr = optionPtr[2];
|
|
|
|
if (entryEndPtr < 5) {
|
|
NlsPutMsg(STDOUT, PING_INVALID_TS_OPTION);
|
|
optionPtr += optionLength;
|
|
break;
|
|
}
|
|
|
|
addressMode = optionPtr[3] & 1;
|
|
|
|
if (entryEndPtr > (optionLength + 1)) {
|
|
entryEndPtr = optionLength + 1;
|
|
}
|
|
|
|
entryPtr = 5;
|
|
entryCount = 0;
|
|
NlsPutMsg(STDOUT, PING_TS_HEADER1);
|
|
|
|
while ((entryPtr + 3) < entryEndPtr) {
|
|
struct in_addr routeAddress;
|
|
ULONG timeStamp;
|
|
|
|
if (entryCount) {
|
|
NlsPutMsg(
|
|
STDOUT,
|
|
PING_ROUTE_SEPARATOR
|
|
);
|
|
|
|
if (entryCount == 1) {
|
|
NlsPutMsg(STDOUT, PING_CR);
|
|
NlsPutMsg(STDOUT, PING_TS_HEADER2);
|
|
entryCount = 0;
|
|
}
|
|
}
|
|
|
|
entryCount++;
|
|
|
|
if (addressMode) {
|
|
if ((entryPtr + 8) > entryEndPtr) {
|
|
break;
|
|
}
|
|
|
|
routeAddress.S_un.S_addr =
|
|
*( (IPAddr UNALIGNED *)
|
|
(optionPtr + entryPtr - 1)
|
|
);
|
|
|
|
if (DoReverseLookup) {
|
|
struct hostent *hostEntry;
|
|
|
|
hostEntry = gethostbyaddr(
|
|
(char *) &routeAddress,
|
|
sizeof(routeAddress),
|
|
AF_INET
|
|
);
|
|
|
|
if (hostEntry != NULL) {
|
|
NlsPutMsg(
|
|
STDOUT,
|
|
PING_FULL_TS_ADDRESS,
|
|
hostEntry->h_name,
|
|
inet_ntoa(routeAddress)
|
|
);
|
|
} else {
|
|
NlsPutMsg(
|
|
STDOUT,
|
|
PING_TS_ADDRESS,
|
|
inet_ntoa(routeAddress)
|
|
);
|
|
}
|
|
} else {
|
|
NlsPutMsg(
|
|
STDOUT,
|
|
PING_TS_ADDRESS,
|
|
inet_ntoa(routeAddress)
|
|
);
|
|
}
|
|
|
|
entryPtr += 4;
|
|
|
|
}
|
|
|
|
timeStamp = *( (ULONG UNALIGNED *)
|
|
(optionPtr + entryPtr - 1)
|
|
);
|
|
timeStamp = net_long(timeStamp);
|
|
|
|
NlsPutMsg(
|
|
STDOUT,
|
|
PING_TS_TIMESTAMP,
|
|
timeStamp
|
|
);
|
|
|
|
entryPtr += 4;
|
|
}
|
|
|
|
NlsPutMsg(STDOUT, PING_CR);
|
|
|
|
optionPtr += optionLength;
|
|
break;
|
|
|
|
default:
|
|
if ((optionPtr + 2) > endPtr) {
|
|
done = TRUE;
|
|
break;
|
|
}
|
|
|
|
optionPtr += optionPtr[1];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// ========================================================================
|
|
// MohsinA, 05-Dec-96.
|
|
|
|
SOCKADDR_STORAGE address; // was local to main earlier.
|
|
socklen_t addressLen;
|
|
uint num_send=0, num_recv=0,
|
|
time_min=(uint)-1, time_max=0, time_total=0;
|
|
|
|
void
|
|
print_statistics( )
|
|
{
|
|
if (num_send > 0) {
|
|
char literal[INET6_ADDRSTRLEN];
|
|
|
|
if (time_min == (uint) -1) { // all times were off.
|
|
time_min = 0;
|
|
}
|
|
|
|
getnameinfo((LPSOCKADDR)&address, addressLen, literal, sizeof(literal),
|
|
NULL, 0, NI_NUMERICHOST);
|
|
|
|
// printf
|
|
// "Ping statistics for %s:\n"
|
|
// "Packets: Sent=%ul, received=%ul, lost=%d (%u%% loss),\n"
|
|
// "Round trip times in milli-seconds: "
|
|
// "minimum=%dms, maximum=%dms, average=%dms\n" ....
|
|
|
|
NlsPutMsg(STDOUT, PING_STATISTICS,
|
|
literal,
|
|
num_send, num_recv, num_send - num_recv,
|
|
(uint) ( 100 * (num_send - num_recv) / num_send ));
|
|
|
|
if (num_recv > 0) {
|
|
NlsPutMsg(STDOUT, PING_STATISTICS2,
|
|
time_min, time_max, time_total / num_recv );
|
|
}
|
|
}
|
|
}
|
|
|
|
// ========================================================================
|
|
// MohsinA, 05-Dec-96.
|
|
// Press C-c to print and abort.
|
|
// Press C-break to print and continue.
|
|
|
|
BOOL
|
|
ConsoleControlHandler(DWORD dwCtrlType)
|
|
{
|
|
print_statistics();
|
|
switch ( dwCtrlType ) {
|
|
case CTRL_BREAK_EVENT:
|
|
NlsPutMsg( STDOUT, PING_BREAK );
|
|
return TRUE;
|
|
break;
|
|
case CTRL_C_EVENT:
|
|
NlsPutMsg( STDOUT, PING_INTERRUPT );
|
|
default: break;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
uchar
|
|
GetDefaultTTL(void)
|
|
{
|
|
HKEY registry=0;
|
|
DWORD DefaultTTL=0;
|
|
DWORD key_type;
|
|
DWORD key_size = sizeof(DWORD);
|
|
uchar TTL;
|
|
DWORD Stat;
|
|
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
|
|
0,
|
|
KEY_QUERY_VALUE,
|
|
®istry) == ERROR_SUCCESS) {
|
|
|
|
|
|
Stat=RegQueryValueEx(registry,
|
|
"DefaultTTL",
|
|
0,
|
|
&key_type,
|
|
(unsigned char *)&DefaultTTL,
|
|
&key_size);
|
|
}
|
|
if (DefaultTTL) {
|
|
TTL = (unsigned char)DefaultTTL;
|
|
} else {
|
|
TTL = DEFAULT_TTL;
|
|
}
|
|
if (registry) {
|
|
RegCloseKey(registry);
|
|
}
|
|
|
|
return TTL;
|
|
}
|
|
|
|
int
|
|
GetSource(int family, char *astr, struct sockaddr *address)
|
|
{
|
|
struct addrinfo hints;
|
|
struct addrinfo *result;
|
|
|
|
memset(&hints, 0, sizeof hints);
|
|
hints.ai_flags = AI_PASSIVE;
|
|
hints.ai_family = family;
|
|
|
|
if (getaddrinfo(astr, NULL, &hints, &result) != 0)
|
|
return FALSE;
|
|
|
|
RtlCopyMemory(address, result->ai_addr, result->ai_addrlen);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOLEAN
|
|
SetFamily(DWORD *Family, DWORD Value, char *arg)
|
|
{
|
|
if ((*Family != AF_UNSPEC) && (*Family != Value)) {
|
|
NlsPutMsg(STDOUT, PING_FAMILY, arg,
|
|
(Value==AF_INET)? "IPv4" : "IPv6");
|
|
return FALSE;
|
|
}
|
|
|
|
*Family = Value;
|
|
return TRUE;
|
|
}
|
|
|
|
// ========================================================================
|
|
|
|
void
|
|
__cdecl
|
|
main(int argc, char **argv)
|
|
{
|
|
SOCKADDR_STORAGE sourceAddress;
|
|
char *arg;
|
|
uint i;
|
|
uint j;
|
|
int found_addr = 0;
|
|
BOOLEAN dnsreq = FALSE;
|
|
char hostname[NI_MAXHOST], literal[INET6_ADDRSTRLEN];
|
|
DWORD numberOfReplies;
|
|
uint Count = DEFAULT_COUNT;
|
|
uchar TTL = 0;
|
|
uchar *Opt = NULL; // 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; // For options specific to IPv4 or IPv6
|
|
ulong Timeout = DEFAULT_TIMEOUT;
|
|
IP_OPTION_INFORMATION SendOpts;
|
|
int EndOffset;
|
|
ulong TempAddr;
|
|
uchar TempCount;
|
|
DWORD errorCode;
|
|
HANDLE IcmpHandle;
|
|
int err;
|
|
// struct in_addr addr;
|
|
BOOL result;
|
|
PICMP_ECHO_REPLY reply4;
|
|
PICMPV6_ECHO_REPLY reply6;
|
|
BOOL sourceRouting = FALSE;
|
|
char *SendBuffer, *RcvBuffer;
|
|
uint RcvSize;
|
|
uint SendSize = DEFAULT_SEND_SIZE;
|
|
DWORD Family = AF_UNSPEC;
|
|
|
|
//
|
|
// This will ensure the correct language message is displayed when
|
|
// NlsPutMsg is called.
|
|
//
|
|
SetThreadUILanguage(0);
|
|
|
|
err = WSAStartup(MAKEWORD(2, 0), &WsaData);
|
|
|
|
if (err) {
|
|
NlsPutMsg(STDOUT, PING_WSASTARTUP_FAILED, GetLastError());
|
|
exit(1);
|
|
}
|
|
|
|
memset(&sourceAddress, 0, sizeof sourceAddress);
|
|
|
|
TTL = GetDefaultTTL();
|
|
|
|
if (argc < 2) {
|
|
PrintUsage();
|
|
goto error_exit;
|
|
} else {
|
|
i = 1;
|
|
while (i < (uint) argc) {
|
|
arg = argv[i];
|
|
if ( (arg[0] == '-') || (arg[0] == '/') ) { // Have an option
|
|
switch (arg[1]) {
|
|
case '?':
|
|
PrintUsage();
|
|
exit(0);
|
|
|
|
case 'l':
|
|
// SendSize = (uint)param(argv, argc, i++, 0, 0xfff7);
|
|
// A ping with packet size >= 64K can crash
|
|
// some tcpip stacks during re-assembly,
|
|
// So changed 'max' from 0xfff7 to 65500
|
|
// - MohsinA, 13-Nov-96.
|
|
|
|
SendSize = (uint)param(argv, argc, i++, 0, 65500 );
|
|
break;
|
|
|
|
case 't':
|
|
Count = (uint)-1;
|
|
break;
|
|
|
|
case 'n':
|
|
Count = (uint)param(argv, argc, i++, 1, 0xffffffff);
|
|
break;
|
|
|
|
case 'f':
|
|
// Only implemented for IPv4.
|
|
if (!SetFamily(&Family, AF_INET, arg)) {
|
|
goto error_exit;
|
|
}
|
|
Flags |= IP_FLAG_DF;
|
|
break;
|
|
|
|
case 'i':
|
|
// TTL of zero is invalid, MohsinA, 13-Mar-97.
|
|
TTL = (uchar)param(argv, argc, i++, 1, 0xff);
|
|
break;
|
|
|
|
case 'v':
|
|
// Only implemented for IPv4.
|
|
if (!SetFamily(&Family, AF_INET, arg)) {
|
|
goto error_exit;
|
|
}
|
|
TOS = (uchar)param(argv, argc, i++, 0, 0xff);
|
|
break;
|
|
|
|
case 'w':
|
|
Timeout = param(argv, argc, i++, 0, 0xffffffff);
|
|
break;
|
|
|
|
case 'a':
|
|
dnsreq = TRUE;
|
|
break;
|
|
|
|
case 'r': // Record Route
|
|
// Only implemented for IPv4.
|
|
if (!SetFamily(&Family, AF_INET, arg)) {
|
|
goto error_exit;
|
|
}
|
|
|
|
if ((OptIndex + 3) > MAX_OPT_SIZE) {
|
|
NlsPutMsg(STDOUT, PING_TOO_MANY_OPTIONS);
|
|
goto error_exit;
|
|
}
|
|
|
|
Opt = SendOptions;
|
|
Opt[OptIndex] = IP_OPT_RR;
|
|
Opt[OptIndex + 2] = 4; // Set initial pointer value
|
|
// min is 1 not zero, MohsinA, 16-4-97.
|
|
TempCount = (uchar)param(argv, argc, i++, 1, 9);
|
|
TempCount = (TempCount * sizeof(ulong)) + 3;
|
|
|
|
if ((TempCount + OptIndex) > MAX_OPT_SIZE) {
|
|
NlsPutMsg(STDOUT, PING_TOO_MANY_OPTIONS);
|
|
goto error_exit;
|
|
}
|
|
|
|
Opt[OptIndex+1] = TempCount;
|
|
OptLength += TempCount;
|
|
OptIndex += TempCount;
|
|
break;
|
|
|
|
case 's': // Timestamp
|
|
// Only implemented for IPv4.
|
|
if (!SetFamily(&Family, AF_INET, arg)) {
|
|
goto error_exit;
|
|
}
|
|
if ((OptIndex + 4) > MAX_OPT_SIZE) {
|
|
NlsPutMsg(STDOUT, PING_TOO_MANY_OPTIONS);
|
|
goto error_exit;
|
|
}
|
|
|
|
Opt = SendOptions;
|
|
Opt[OptIndex] = IP_OPT_TS;
|
|
Opt[OptIndex + 2] = 5; // Set initial pointer value
|
|
TempCount = (uchar)param(argv, argc, i++, 1, 4);
|
|
TempCount = (TempCount * (sizeof(ulong) * 2)) + 4;
|
|
|
|
if ((TempCount + OptIndex) > MAX_OPT_SIZE) {
|
|
NlsPutMsg(STDOUT, PING_TOO_MANY_OPTIONS);
|
|
goto error_exit;
|
|
}
|
|
|
|
Opt[OptIndex+1] = TempCount;
|
|
Opt[OptIndex+3] = 1;
|
|
OptLength += TempCount;
|
|
OptIndex += TempCount;
|
|
break;
|
|
|
|
case 'j': // Loose source routing
|
|
// Only implemented for IPv4.
|
|
if (!SetFamily(&Family, AF_INET, arg)) {
|
|
goto error_exit;
|
|
}
|
|
|
|
if (sourceRouting) {
|
|
NlsPutMsg(STDOUT, PING_BAD_OPTION_COMBO);
|
|
goto error_exit;
|
|
}
|
|
|
|
if ((OptIndex + 3) > MAX_OPT_SIZE) {
|
|
NlsPutMsg(STDOUT, PING_TOO_MANY_OPTIONS);
|
|
goto error_exit;
|
|
}
|
|
|
|
Opt = SendOptions;
|
|
Opt[OptIndex] = IP_OPT_LSRR;
|
|
Opt[OptIndex+1] = 3;
|
|
Opt[OptIndex + 2] = 4; // Set initial pointer value
|
|
OptLength += 3;
|
|
while ( (i < (uint)(argc - 2)) && (*argv[i+1] != '-')) {
|
|
if ((OptIndex + 3) > (MAX_OPT_SIZE - 4)) {
|
|
NlsPutMsg(STDOUT, PING_TOO_MANY_OPTIONS);
|
|
goto error_exit;
|
|
}
|
|
|
|
arg = argv[++i];
|
|
EndOffset = 0;
|
|
do {
|
|
TempAddr = str2ip(arg + EndOffset, &EndOffset);
|
|
if (!TempAddr) {
|
|
NlsPutMsg( STDOUT, PING_MESSAGE_4 );
|
|
// printf("Bad route specified for loose source route");
|
|
goto error_exit;
|
|
}
|
|
j = Opt[OptIndex+1];
|
|
*(ulong UNALIGNED *)&Opt[j+OptIndex] = TempAddr;
|
|
Opt[OptIndex+1] += 4;
|
|
OptLength += 4;
|
|
while (arg[EndOffset] != '\0' && isspace((unsigned char)arg[EndOffset]))
|
|
EndOffset++;
|
|
} while (arg[EndOffset] != '\0');
|
|
}
|
|
SRIndex = Opt[OptIndex+1] + OptIndex;
|
|
Opt[OptIndex+1] += 4; // Save space for dest. addr
|
|
OptIndex += Opt[OptIndex+1];
|
|
OptLength += 4;
|
|
sourceRouting = TRUE;
|
|
break;
|
|
|
|
case 'k': // Strict source routing
|
|
// Only implemented for IPv4.
|
|
if (!SetFamily(&Family, AF_INET, arg)) {
|
|
goto error_exit;
|
|
}
|
|
|
|
if (sourceRouting) {
|
|
NlsPutMsg(STDOUT, PING_BAD_OPTION_COMBO);
|
|
goto error_exit;
|
|
}
|
|
|
|
if ((OptIndex + 3) > MAX_OPT_SIZE) {
|
|
NlsPutMsg(STDOUT, PING_TOO_MANY_OPTIONS);
|
|
goto error_exit;
|
|
}
|
|
|
|
Opt = SendOptions;
|
|
Opt[OptIndex] = IP_OPT_SSRR;
|
|
Opt[OptIndex+1] = 3;
|
|
Opt[OptIndex + 2] = 4; // Set initial pointer value
|
|
OptLength += 3;
|
|
while ( (i < (uint)(argc - 2)) && (*argv[i+1] != '-')) {
|
|
if ((OptIndex + 3) > (MAX_OPT_SIZE - 4)) {
|
|
NlsPutMsg(STDOUT, PING_TOO_MANY_OPTIONS);
|
|
goto error_exit;
|
|
}
|
|
|
|
arg = argv[++i];
|
|
EndOffset = 0;
|
|
do {
|
|
TempAddr = str2ip(arg + EndOffset, &EndOffset);
|
|
if (!TempAddr) {
|
|
NlsPutMsg( STDOUT, PING_MESSAGE_4 );
|
|
// printf("Bad route specified for loose source route");
|
|
goto error_exit;
|
|
}
|
|
j = Opt[OptIndex+1];
|
|
*(ulong UNALIGNED *)&Opt[j+OptIndex] = TempAddr;
|
|
Opt[OptIndex+1] += 4;
|
|
OptLength += 4;
|
|
while (arg[EndOffset] != '\0' && isspace((unsigned char)arg[EndOffset]))
|
|
EndOffset++;
|
|
} while (arg[EndOffset] != '\0');
|
|
}
|
|
SRIndex = Opt[OptIndex+1] + OptIndex;
|
|
Opt[OptIndex+1] += 4; // Save space for dest. addr
|
|
OptIndex += Opt[OptIndex+1];
|
|
OptLength += 4;
|
|
sourceRouting = TRUE;
|
|
break;
|
|
|
|
case 'R':
|
|
// Only implemented for IPv6 so far
|
|
if (!SetFamily(&Family, AF_INET6, arg)) {
|
|
goto error_exit;
|
|
}
|
|
Flags |= ICMPV6_ECHO_REQUEST_FLAG_REVERSE;
|
|
break;
|
|
|
|
case 'S':
|
|
// Only implemented for IPv6 so far
|
|
if (!SetFamily(&Family, AF_INET6, arg)) {
|
|
goto error_exit;
|
|
}
|
|
|
|
if (!GetSource(Family, argv[++i], (LPSOCKADDR)&sourceAddress)) {
|
|
NlsPutMsg(STDOUT, PING_BAD_ADDRESS, argv[i]);
|
|
goto error_exit;
|
|
}
|
|
break;
|
|
|
|
case '4':
|
|
if (!SetFamily(&Family, AF_INET, arg)) {
|
|
goto error_exit;
|
|
}
|
|
break;
|
|
|
|
case '6':
|
|
if (!SetFamily(&Family, AF_INET6, arg)) {
|
|
goto error_exit;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
NlsPutMsg( STDOUT, PING_MESSAGE_11, arg );
|
|
// printf( "Bad option %s.\n\n", arg);
|
|
PrintUsage();
|
|
goto error_exit;
|
|
break;
|
|
}
|
|
i++;
|
|
} else { // Not an option, must be an IP address.
|
|
if (found_addr) {
|
|
NlsPutMsg( STDOUT, PING_MESSAGE_12, arg );
|
|
// printf( "Bad parameter %s.\n", arg);
|
|
goto error_exit;
|
|
}
|
|
|
|
// Added check for INADDR_NONE, MohsinA, 21-Oct-96.
|
|
if (ResolveTarget(Family, arg, (LPSOCKADDR)&address,
|
|
&addressLen, hostname, sizeof(hostname),
|
|
dnsreq) &&
|
|
((address.ss_family != AF_INET) || (((LPSOCKADDR_IN)&address)->sin_addr.s_addr != INADDR_NONE))) {
|
|
found_addr = 1;
|
|
i++;
|
|
} else {
|
|
NlsPutMsg( STDOUT, PING_MESSAGE_13, arg );
|
|
// printf( "Bad IP address %s.\n", arg);
|
|
// "Unknown host %s.", was Bug 1368.
|
|
goto error_exit;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!found_addr) {
|
|
NlsPutMsg( STDOUT, PING_MESSAGE_14 );
|
|
// printf("IP address must be specified.\n");
|
|
goto error_exit;
|
|
}
|
|
|
|
Family = address.ss_family;
|
|
if (Family == AF_INET) {
|
|
if (SRIndex != -1) {
|
|
*(ulong UNALIGNED *)&SendOptions[SRIndex] = ((LPSOCKADDR_IN)&address)->sin_addr.s_addr;
|
|
}
|
|
|
|
IcmpHandle = IcmpCreateFile();
|
|
} else {
|
|
if (sourceAddress.ss_family == AF_UNSPEC) {
|
|
SOCKET s;
|
|
DWORD BytesReturned;
|
|
|
|
//
|
|
// A source address was not specified.
|
|
// Get the preferred source address for this destination.
|
|
//
|
|
// If you want each individual echo request
|
|
// to select a source address, use "-S ::".
|
|
//
|
|
|
|
s = socket(address.ss_family, 0, 0);
|
|
if (s == INVALID_SOCKET) {
|
|
NlsPutMsg(STDOUT, PING_SOCKET_FAILED, WSAGetLastError());
|
|
exit(1);
|
|
}
|
|
|
|
(void) WSAIoctl(s, SIO_ROUTING_INTERFACE_QUERY,
|
|
&address, sizeof address,
|
|
&sourceAddress, sizeof sourceAddress,
|
|
&BytesReturned, NULL, NULL);
|
|
|
|
closesocket(s);
|
|
}
|
|
|
|
IcmpHandle = Icmp6CreateFile();
|
|
}
|
|
|
|
if (IcmpHandle == INVALID_HANDLE_VALUE) {
|
|
NlsPutMsg( STDOUT, PING_MESSAGE_15, GetLastError() );
|
|
|
|
// printf( "Unable to contact IP driver, error code %d.\n",
|
|
// GetLastError() );
|
|
|
|
goto error_exit;
|
|
}
|
|
|
|
SendBuffer = LocalAlloc(LMEM_FIXED, SendSize);
|
|
|
|
if (SendBuffer == NULL) {
|
|
NlsPutMsg(STDOUT, PING_NO_MEMORY);
|
|
goto error_exit;
|
|
}
|
|
|
|
//
|
|
// Calculate receive buffer size and try to allocate it.
|
|
//
|
|
if (SendSize <= DEFAULT_SEND_SIZE) {
|
|
RcvSize = DEFAULT_BUFFER_SIZE;
|
|
} else {
|
|
RcvSize = MAX_BUFFER_SIZE;
|
|
}
|
|
|
|
RcvBuffer = LocalAlloc(LMEM_FIXED, RcvSize);
|
|
|
|
if (RcvBuffer == NULL) {
|
|
NlsPutMsg(STDOUT, PING_NO_MEMORY);
|
|
LocalFree(SendBuffer);
|
|
goto error_exit;
|
|
}
|
|
|
|
//
|
|
// Initialize the send buffer pattern.
|
|
//
|
|
for (i = 0; i < SendSize; i++) {
|
|
SendBuffer[i] = (char)('a' + (i % 23));
|
|
}
|
|
|
|
//
|
|
// Initialize the send options
|
|
//
|
|
SendOpts.OptionsData = Opt;
|
|
SendOpts.OptionsSize = (uchar)OptLength;
|
|
SendOpts.Ttl = TTL;
|
|
SendOpts.Tos = TOS;
|
|
SendOpts.Flags = Flags;
|
|
|
|
getnameinfo((LPSOCKADDR)&address, addressLen, literal, sizeof(literal),
|
|
NULL, 0, NI_NUMERICHOST);
|
|
|
|
if (hostname[0]) {
|
|
NlsPutMsg(
|
|
STDOUT,
|
|
PING_HEADER1,
|
|
hostname,
|
|
literal
|
|
);
|
|
// printf("Pinging Host %s [%s]\n", hostname, literal);
|
|
} else {
|
|
NlsPutMsg(
|
|
STDOUT,
|
|
PING_HEADER2,
|
|
literal
|
|
);
|
|
// printf("Pinging Host [%s]\n", literal);
|
|
}
|
|
|
|
if (sourceAddress.ss_family == AF_INET6) {
|
|
getnameinfo((LPSOCKADDR)&sourceAddress, sizeof(SOCKADDR_IN6), literal,
|
|
sizeof(literal), NULL, 0, NI_NUMERICHOST);
|
|
NlsPutMsg(STDOUT, PING_SOURCE_ADDRESS, literal);
|
|
}
|
|
|
|
NlsPutMsg(STDOUT, PING_WITH_DATA, SendSize);
|
|
|
|
SetConsoleCtrlHandler( &ConsoleControlHandler, TRUE );
|
|
|
|
for (i = 0; i < Count; i++) {
|
|
if (Family == AF_INET) {
|
|
numberOfReplies = IcmpSendEcho2(IcmpHandle,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
((LPSOCKADDR_IN)&address)->sin_addr.s_addr,
|
|
SendBuffer,
|
|
(unsigned short) SendSize,
|
|
&SendOpts,
|
|
RcvBuffer,
|
|
RcvSize,
|
|
Timeout);
|
|
|
|
num_send++;
|
|
|
|
if (numberOfReplies == 0) {
|
|
|
|
errorCode = GetLastError();
|
|
|
|
if (errorCode < IP_STATUS_BASE) {
|
|
NlsPutMsg( STDOUT, PING_MESSAGE_18, errorCode );
|
|
// printf("PING: transmit failed, error code %lu\n", errorCode);
|
|
} else {
|
|
for (j = 0; ErrorTable[j].Error != errorCode &&
|
|
ErrorTable[j].Error != IP_GENERAL_FAILURE;j++)
|
|
;
|
|
|
|
NlsPutMsg( STDOUT, ErrorTable[j].ErrorNlsID );
|
|
// printf("PING: %s.\n", ErrorTable[j].ErrorString);
|
|
}
|
|
|
|
if (i < (Count - 1)) {
|
|
Sleep(MIN_INTERVAL);
|
|
}
|
|
|
|
} else {
|
|
|
|
reply4 = (PICMP_ECHO_REPLY) RcvBuffer;
|
|
|
|
while (numberOfReplies--) {
|
|
struct in_addr addr;
|
|
|
|
addr.S_un.S_addr = reply4->Address;
|
|
|
|
NlsPutMsg(STDOUT, PING_MESSAGE_19, inet_ntoa(addr));
|
|
// printf(
|
|
// "Reply from %s:",
|
|
// inet_ntoa(addr),
|
|
// );
|
|
|
|
if (reply4->Status == IP_SUCCESS) {
|
|
|
|
NlsPutMsg( STDOUT, PING_MESSAGE_25, (int) reply4->DataSize);
|
|
// printf(
|
|
// "Echo size=%d ",
|
|
// reply4->DataSize
|
|
// );
|
|
|
|
if (reply4->DataSize != SendSize) {
|
|
NlsPutMsg( STDOUT, PING_MESSAGE_20, SendSize );
|
|
// printf("(sent %d) ", SendSize);
|
|
} else {
|
|
char *sendptr, *recvptr;
|
|
|
|
sendptr = &(SendBuffer[0]);
|
|
recvptr = (char *) reply4->Data;
|
|
|
|
for (j = 0; j < SendSize; j++)
|
|
if (*sendptr++ != *recvptr++) {
|
|
NlsPutMsg( STDOUT, PING_MESSAGE_21, j );
|
|
// printf("- MISCOMPARE at offset %d - ", j);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (reply4->RoundTripTime) {
|
|
NlsPutMsg( STDOUT, PING_MESSAGE_22, reply4->RoundTripTime );
|
|
// Collect stats.
|
|
|
|
time_total += reply4->RoundTripTime;
|
|
if ( reply4->RoundTripTime < time_min ) {
|
|
time_min = reply4->RoundTripTime;
|
|
}
|
|
if ( reply4->RoundTripTime > time_max ) {
|
|
time_max = reply4->RoundTripTime;
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
NlsPutMsg( STDOUT, PING_MESSAGE_23 );
|
|
// printf("time<1ms ");
|
|
|
|
time_min = 0;
|
|
}
|
|
|
|
|
|
// printf("\n time rt=%dms min %d, max %d, total %d\n",
|
|
// reply4->RoundTripTime,
|
|
// time_min, time_max, time_total );
|
|
|
|
NlsPutMsg( STDOUT, PING_MESSAGE_24, (uint)reply4->Options.Ttl );
|
|
// printf("TTL=%u\n", (uint)reply4->Options.Ttl);
|
|
|
|
if (reply4->Options.OptionsSize) {
|
|
ProcessOptions(reply4, dnsreq);
|
|
}
|
|
} else {
|
|
for (j=0; ErrorTable[j].Error != IP_GENERAL_FAILURE; j++) {
|
|
if (ErrorTable[j].Error == reply4->Status) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
NlsPutMsg( STDOUT, ErrorTable[j].ErrorNlsID);
|
|
}
|
|
|
|
num_recv++;
|
|
reply4++;
|
|
}
|
|
|
|
if (i < (Count - 1)) {
|
|
reply4--;
|
|
|
|
if (reply4->RoundTripTime < MIN_INTERVAL) {
|
|
Sleep(MIN_INTERVAL - reply4->RoundTripTime);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
// AF_INET6
|
|
numberOfReplies = Icmp6SendEcho2(IcmpHandle,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
(LPSOCKADDR_IN6)&sourceAddress,
|
|
(LPSOCKADDR_IN6)&address,
|
|
SendBuffer,
|
|
(unsigned short) SendSize,
|
|
&SendOpts,
|
|
RcvBuffer,
|
|
RcvSize,
|
|
Timeout);
|
|
|
|
num_send++;
|
|
|
|
if (numberOfReplies == 0) {
|
|
|
|
errorCode = GetLastError();
|
|
|
|
if (errorCode < IP_STATUS_BASE) {
|
|
NlsPutMsg( STDOUT, PING_MESSAGE_18, errorCode );
|
|
// printf("PING: transmit failed, error code %lu\n", errorCode);
|
|
} else {
|
|
for (j = 0; ErrorTable[j].Error != errorCode &&
|
|
ErrorTable[j].Error != IP_GENERAL_FAILURE;j++)
|
|
;
|
|
|
|
NlsPutMsg( STDOUT, ErrorTable[j].ErrorNlsID );
|
|
// printf("PING: %s.\n", ErrorTable[j].ErrorString);
|
|
}
|
|
|
|
if (i < (Count - 1)) {
|
|
Sleep(MIN_INTERVAL);
|
|
}
|
|
|
|
} else {
|
|
|
|
reply6 = (PICMPV6_ECHO_REPLY) RcvBuffer;
|
|
|
|
while (numberOfReplies--) {
|
|
|
|
getnameinfo((LPSOCKADDR)&address, addressLen, literal,
|
|
sizeof(literal), NULL, 0, NI_NUMERICHOST);
|
|
|
|
NlsPutMsg(STDOUT, PING_MESSAGE_19, literal);
|
|
|
|
// printf(
|
|
// "Reply from %s:",
|
|
// inet_ntoa(addr),
|
|
// );
|
|
|
|
if (reply6->Status == IP_SUCCESS) {
|
|
|
|
if (reply6->RoundTripTime) {
|
|
NlsPutMsg( STDOUT, PING_MESSAGE_22, reply6->RoundTripTime );
|
|
// Collect stats.
|
|
|
|
time_total += reply6->RoundTripTime;
|
|
if ( reply6->RoundTripTime < time_min ) {
|
|
time_min = reply6->RoundTripTime;
|
|
}
|
|
if ( reply6->RoundTripTime > time_max ) {
|
|
time_max = reply6->RoundTripTime;
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
NlsPutMsg( STDOUT, PING_MESSAGE_23 );
|
|
// printf("time<1ms ");
|
|
|
|
time_min = 0;
|
|
}
|
|
|
|
|
|
// printf("\n time rt=%dms min %d, max %d, total %d\n",
|
|
// reply6->RoundTripTime,
|
|
// time_min, time_max, time_total );
|
|
|
|
NlsPutMsg(STDOUT, PING_CR);
|
|
|
|
} else {
|
|
for (j=0; ErrorTable[j].Error != IP_GENERAL_FAILURE; j++) {
|
|
if (ErrorTable[j].Error == reply6->Status) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
NlsPutMsg( STDOUT, ErrorTable[j].ErrorNlsID);
|
|
}
|
|
|
|
num_recv++;
|
|
reply6++;
|
|
}
|
|
|
|
if (i < (Count - 1)) {
|
|
reply6--;
|
|
|
|
if (reply6->RoundTripTime < MIN_INTERVAL) {
|
|
Sleep(MIN_INTERVAL - reply6->RoundTripTime);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// MohsinA, 05-Dec-96. DCR # 65503.
|
|
print_statistics();
|
|
|
|
result = IcmpCloseHandle(IcmpHandle);
|
|
|
|
LocalFree(SendBuffer);
|
|
LocalFree(RcvBuffer);
|
|
|
|
WSACleanup();
|
|
exit(0 == num_recv);
|
|
|
|
error_exit:
|
|
WSACleanup();
|
|
exit(1);
|
|
}
|