1085 lines
33 KiB
Plaintext
1085 lines
33 KiB
Plaintext
|
/*++
|
||
|
|
||
|
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 "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}
|
||
|
};
|
||
|
|
||
|
|
||
|
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)))
|
||
|
return(0);
|
||
|
|
||
|
// Convert vp to oem
|
||
|
StrLen=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"
|
||
|
// );
|
||
|
|
||
|
}
|
||
|
|
||
|
// ========================================================================
|
||
|
// 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);
|
||
|
}
|
||
|
|
||
|
unsigned long
|
||
|
str2ip(char *addr, int *EndOffset)
|
||
|
{
|
||
|
char *endptr;
|
||
|
char *start = addr;
|
||
|
int i; // Counter variable.
|
||
|
unsigned long curaddr = 0;
|
||
|
unsigned long temp;
|
||
|
struct hostent *hostp = NULL;
|
||
|
|
||
|
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.
|
||
|
|
||
|
IPAddr address=0; // was local to main earlier.
|
||
|
uint num_send=0, num_recv=0,
|
||
|
time_min=(uint)-1, time_max=0, time_total=0;
|
||
|
|
||
|
void
|
||
|
print_statistics( )
|
||
|
{
|
||
|
struct in_addr addr;
|
||
|
|
||
|
if (num_send > 0) {
|
||
|
addr.s_addr = address;
|
||
|
|
||
|
if (time_min == (uint) -1) { // all times were off.
|
||
|
time_min = 0;
|
||
|
}
|
||
|
|
||
|
// 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,
|
||
|
inet_ntoa(addr),
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
// ========================================================================
|
||
|
|
||
|
void
|
||
|
__cdecl
|
||
|
main(int argc, char **argv)
|
||
|
{
|
||
|
char *arg;
|
||
|
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 = 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;
|
||
|
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 reply;
|
||
|
BOOL sourceRouting = FALSE;
|
||
|
char *SendBuffer, *RcvBuffer;
|
||
|
uint RcvSize;
|
||
|
uint SendSize = DEFAULT_SEND_SIZE;
|
||
|
|
||
|
// ====================================================================
|
||
|
|
||
|
err = WSAStartup( 0x0101, &WsaData);
|
||
|
|
||
|
if (err) {
|
||
|
NlsPutMsg(STDOUT, PING_WSASTARTUP_FAILED, GetLastError());
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
TTL = GetDefaultTTL();
|
||
|
|
||
|
if (argc < 2) {
|
||
|
PrintUsage();
|
||
|
exit(1);
|
||
|
} 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':
|
||
|
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':
|
||
|
TOS = (uchar)param(argv, argc, i++, 0, 0xff);
|
||
|
break;
|
||
|
|
||
|
case 'w':
|
||
|
Timeout = param(argv, argc, i++, 0, 0xffffffff);
|
||
|
break;
|
||
|
|
||
|
case 'a':
|
||
|
dnsreq = 1;
|
||
|
break;
|
||
|
|
||
|
case 'r': // Record Route
|
||
|
if ((OptIndex + 3) > MAX_OPT_SIZE) {
|
||
|
NlsPutMsg(STDOUT, PING_TOO_MANY_OPTIONS);
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
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);
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
Opt[OptIndex+1] = TempCount;
|
||
|
OptLength += TempCount;
|
||
|
OptIndex += TempCount;
|
||
|
break;
|
||
|
|
||
|
case 's': // Timestamp
|
||
|
if ((OptIndex + 4) > MAX_OPT_SIZE) {
|
||
|
NlsPutMsg(STDOUT, PING_TOO_MANY_OPTIONS);
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
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);
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
Opt[OptIndex+1] = TempCount;
|
||
|
Opt[OptIndex+3] = 1;
|
||
|
OptLength += TempCount;
|
||
|
OptIndex += TempCount;
|
||
|
break;
|
||
|
|
||
|
case 'j': // Loose source routing
|
||
|
|
||
|
if (sourceRouting) {
|
||
|
NlsPutMsg(STDOUT, PING_BAD_OPTION_COMBO);
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
if ((OptIndex + 3) > MAX_OPT_SIZE) {
|
||
|
NlsPutMsg(STDOUT, PING_TOO_MANY_OPTIONS);
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
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);
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
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");
|
||
|
exit(1);
|
||
|
}
|
||
|
j = Opt[OptIndex+1];
|
||
|
*(ulong UNALIGNED *)&Opt[j+OptIndex] = TempAddr;
|
||
|
Opt[OptIndex+1] += 4;
|
||
|
OptLength += 4;
|
||
|
while (arg[EndOffset] != '\0' && isspace(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
|
||
|
|
||
|
if (sourceRouting) {
|
||
|
NlsPutMsg(STDOUT, PING_BAD_OPTION_COMBO);
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
if ((OptIndex + 3) > MAX_OPT_SIZE) {
|
||
|
NlsPutMsg(STDOUT, PING_TOO_MANY_OPTIONS);
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
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);
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
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");
|
||
|
exit(1);
|
||
|
}
|
||
|
j = Opt[OptIndex+1];
|
||
|
*(ulong UNALIGNED *)&Opt[j+OptIndex] = TempAddr;
|
||
|
Opt[OptIndex+1] += 4;
|
||
|
OptLength += 4;
|
||
|
while (arg[EndOffset] != '\0' && isspace(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;
|
||
|
|
||
|
default:
|
||
|
NlsPutMsg( STDOUT, PING_MESSAGE_11, arg );
|
||
|
// printf( "Bad option %s.\n\n", arg);
|
||
|
PrintUsage();
|
||
|
exit(1);
|
||
|
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);
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
// Added check for INADDR_NONE, MohsinA, 21-Oct-96.
|
||
|
|
||
|
address = get_pingee(arg, &hostname, &was_inaddr, dnsreq);
|
||
|
if ( address && (address != 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.
|
||
|
exit(1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!found_addr) {
|
||
|
NlsPutMsg( STDOUT, PING_MESSAGE_14 );
|
||
|
// printf("IP address must be specified.\n");
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
if (SRIndex != -1) {
|
||
|
*(ulong UNALIGNED *)&SendOptions[SRIndex] = address;
|
||
|
}
|
||
|
|
||
|
IcmpHandle = IcmpCreateFile();
|
||
|
|
||
|
if (IcmpHandle == INVALID_HANDLE_VALUE) {
|
||
|
NlsPutMsg( STDOUT, PING_MESSAGE_15, GetLastError() );
|
||
|
|
||
|
// printf( "Unable to contact IP driver, error code %d.\n",
|
||
|
// GetLastError() );
|
||
|
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
SendBuffer = LocalAlloc(LMEM_FIXED, SendSize);
|
||
|
|
||
|
if (SendBuffer == NULL) {
|
||
|
NlsPutMsg(STDOUT, PING_NO_MEMORY);
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// 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);
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// 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 (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));
|
||
|
}
|
||
|
|
||
|
SetConsoleCtrlHandler( &ConsoleControlHandler, TRUE );
|
||
|
|
||
|
for (i = 0; i < Count; i++) {
|
||
|
numberOfReplies = IcmpSendEcho2(IcmpHandle,
|
||
|
0,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
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 {
|
||
|
|
||
|
reply = (PICMP_ECHO_REPLY) RcvBuffer;
|
||
|
|
||
|
while (numberOfReplies--) {
|
||
|
struct in_addr addr;
|
||
|
|
||
|
addr.S_un.S_addr = reply->Address;
|
||
|
|
||
|
NlsPutMsg(STDOUT, PING_MESSAGE_19, inet_ntoa(addr));
|
||
|
// printf(
|
||
|
// "Reply from %s:",
|
||
|
// inet_ntoa(addr),
|
||
|
// );
|
||
|
|
||
|
if (reply->Status == IP_SUCCESS) {
|
||
|
|
||
|
NlsPutMsg( STDOUT, PING_MESSAGE_25, (int) reply->DataSize);
|
||
|
// printf(
|
||
|
// "Echo size=%d ",
|
||
|
// reply->DataSize
|
||
|
// );
|
||
|
|
||
|
if (reply->DataSize != SendSize) {
|
||
|
NlsPutMsg( STDOUT, PING_MESSAGE_20, SendSize );
|
||
|
// printf("(sent %d) ", SendSize);
|
||
|
} else {
|
||
|
char *sendptr, *recvptr;
|
||
|
|
||
|
sendptr = &(SendBuffer[0]);
|
||
|
recvptr = (char *) reply->Data;
|
||
|
|
||
|
for (j = 0; j < SendSize; j++)
|
||
|
if (*sendptr++ != *recvptr++) {
|
||
|
NlsPutMsg( STDOUT, PING_MESSAGE_21, j );
|
||
|
// printf("- MISCOMPARE at offset %d - ", j);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (reply->RoundTripTime) {
|
||
|
NlsPutMsg( STDOUT, PING_MESSAGE_22, reply->RoundTripTime );
|
||
|
// Collect stats.
|
||
|
|
||
|
time_total += reply->RoundTripTime;
|
||
|
if ( reply->RoundTripTime < time_min ) {
|
||
|
time_min = reply->RoundTripTime;
|
||
|
}
|
||
|
if ( reply->RoundTripTime > time_max ) {
|
||
|
time_max = reply->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",
|
||
|
// reply->RoundTripTime,
|
||
|
// time_min, time_max, time_total );
|
||
|
|
||
|
NlsPutMsg( STDOUT, PING_MESSAGE_24, (uint)reply->Options.Ttl );
|
||
|
// printf("TTL=%u\n", (uint)reply->Options.Ttl);
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
NlsPutMsg( STDOUT, ErrorTable[j].ErrorNlsID);
|
||
|
}
|
||
|
|
||
|
num_recv++;
|
||
|
reply++;
|
||
|
}
|
||
|
|
||
|
if (i < (Count - 1)) {
|
||
|
reply--;
|
||
|
|
||
|
if (reply->RoundTripTime < MIN_INTERVAL) {
|
||
|
Sleep(MIN_INTERVAL - reply->RoundTripTime);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// MohsinA, 05-Dec-96. DCR # 65503.
|
||
|
print_statistics();
|
||
|
|
||
|
result = IcmpCloseHandle(IcmpHandle);
|
||
|
|
||
|
LocalFree(SendBuffer);
|
||
|
LocalFree(RcvBuffer);
|
||
|
|
||
|
exit(0 == num_recv);
|
||
|
}
|
||
|
|