mirror of https://github.com/lianthony/NT4.0
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.
1011 lines
27 KiB
1011 lines
27 KiB
/*++
|
|
|
|
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
|
|
-------- -------- ----------------------------------------------
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
//:ts=4
|
|
typedef unsigned long ulong;
|
|
typedef unsigned short ushort;
|
|
typedef unsigned int uint;
|
|
typedef unsigned char uchar;
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#define NOGDI
|
|
#define NOMINMAX
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
#include <io.h>
|
|
#include <winsock.h>
|
|
#include "ipexport.h"
|
|
#include "icmpapi.h"
|
|
#include "nlstxt.h"
|
|
#include <cataping.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 32
|
|
#define DEFAULT_TOS 0
|
|
#define DEFAULT_TIMEOUT 1000L
|
|
#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
|
|
|
|
|
|
uchar SendOptions[MAX_OPT_SIZE];
|
|
uchar NtoaBuffer[20];
|
|
|
|
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_GENERAL_FAILURE, PING_GENERAL_FAILURE }
|
|
};
|
|
|
|
void
|
|
PingNtoa(
|
|
IN struct in_addr in,
|
|
IN OUT char * Buffer
|
|
);
|
|
|
|
/*** ConvertArgvToOem
|
|
*
|
|
* Purpose:
|
|
* Convert all the command line arguments from Ansi to Oem.
|
|
*
|
|
* Args:
|
|
*
|
|
* argc Argument count
|
|
* argv[] Array of command-line arguments
|
|
*
|
|
* Returns:
|
|
* Nothing.
|
|
*
|
|
*/
|
|
|
|
void
|
|
ConvertArgvToOem(
|
|
int argc,
|
|
char *argv[]
|
|
)
|
|
{
|
|
int i;
|
|
|
|
for (i=1; i<argc; ++i)
|
|
CharToOemA(argv[i], argv[i]);
|
|
}
|
|
|
|
|
|
unsigned
|
|
NlsPutMsg(unsigned Handle, unsigned usMsgNum, ... )
|
|
{
|
|
unsigned msglen;
|
|
VOID * vp;
|
|
va_list arglist;
|
|
|
|
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);
|
|
|
|
msglen = _write(Handle, vp, msglen);
|
|
LocalFree(vp);
|
|
|
|
return(msglen);
|
|
}
|
|
|
|
|
|
void
|
|
PrintUsage(
|
|
void
|
|
)
|
|
{
|
|
NlsPutMsg( STDOUT, PING_USAGE );
|
|
|
|
#if 0
|
|
printf(
|
|
"Usage: ping [-s size] [-c count] [-d] [-l TTL] [-o options] [-t TOS]\n"
|
|
" [-w timeout] address.\n"
|
|
);
|
|
printf("\n");
|
|
printf("Options:\n");
|
|
printf(" -t Ping the specifed host until interrupted.\n");
|
|
printf(" -l size Send buffer size.\n");
|
|
printf(" -n count Send count.\n");
|
|
printf(" -f Don't fragment.\n");
|
|
printf(" -i TTL Time to live.\n");
|
|
printf(" -v TOS Type of service\n");
|
|
printf(" -w timeout Timeout (in milliseconds)\n");
|
|
printf(" -r routes Record route.\n");
|
|
printf(" -s routes Timestamp route.\n");
|
|
printf(" -j ipaddress Loose source route.\n");
|
|
printf(" -k ipaddress Strict source route.\n");
|
|
printf(" -o IP options:\n");
|
|
printf(" -ol hop list Loose source route.\n");
|
|
printf(" -ot Timestamp.\n");
|
|
printf(" -or Record route\n");
|
|
printf("\n");
|
|
#endif //0
|
|
}
|
|
|
|
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 += (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] );
|
|
// printf( "Bad value for option %s.\n", argv[current]);
|
|
exit(1);
|
|
}
|
|
|
|
return temp;
|
|
}
|
|
|
|
|
|
void
|
|
ProcessOptions(
|
|
ICMP_ECHO_REPLY *reply,
|
|
BOOLEAN DoReverseLookup
|
|
)
|
|
{
|
|
UCHAR FAR *optionPtr;
|
|
UCHAR FAR *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)
|
|
);
|
|
|
|
PingNtoa(
|
|
routeAddress,
|
|
NtoaBuffer);
|
|
|
|
NlsPutMsg(
|
|
STDOUT,
|
|
PING_ROUTE_ENTRY,
|
|
NtoaBuffer
|
|
);
|
|
|
|
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)
|
|
);
|
|
|
|
PingNtoa(
|
|
routeAddress,
|
|
NtoaBuffer);
|
|
|
|
NlsPutMsg(
|
|
STDOUT,
|
|
PING_TS_ADDRESS,
|
|
NtoaBuffer
|
|
);
|
|
|
|
entryPtr += 4;
|
|
|
|
}
|
|
|
|
timeStamp = *( (ULONG UNALIGNED *)
|
|
(optionPtr + entryPtr - 1)
|
|
);
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
void _CRTAPI1
|
|
main(int argc, char **argv)
|
|
{
|
|
char *arg;
|
|
uint i;
|
|
uint j;
|
|
int found_addr = 0;
|
|
int dnsreq = 0;
|
|
char *hostname = NULL;
|
|
int was_inaddr;
|
|
IPAddr address = 0;
|
|
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;
|
|
ulong RoundTrip;
|
|
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;
|
|
char *Pingee = NULL;
|
|
PPING_REQUEST hPing;
|
|
|
|
|
|
ConvertArgvToOem(argc, argv); // for NLS
|
|
|
|
if (argc < 2) {
|
|
PrintUsage();
|
|
exit(1);
|
|
} else {
|
|
i = 1;
|
|
while (i < (uint) argc) {
|
|
arg = argv[i];
|
|
if (arg[0] == '-') { // Have an option
|
|
switch (arg[1]) {
|
|
case '?':
|
|
PrintUsage();
|
|
exit(0);
|
|
|
|
case 'l':
|
|
SendSize = (uint)param(argv, argc, i++, 0, 0xfff7);
|
|
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 = (uchar)param(argv, argc, i++, 0, 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
|
|
TempCount = (uchar)param(argv, argc, i++, 0, 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;
|
|
sourceRouting = TRUE;
|
|
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;
|
|
sourceRouting = TRUE;
|
|
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);
|
|
}
|
|
#if 1
|
|
Pingee = arg;
|
|
found_addr = 1;
|
|
i++;
|
|
#else
|
|
if (address = get_pingee(arg, &hostname, &was_inaddr, dnsreq)) {
|
|
found_addr = 1;
|
|
i++;
|
|
} else {
|
|
NlsPutMsg( STDOUT, PING_MESSAGE_13, arg );
|
|
// printf( "Bad IP address %s.\n", arg);
|
|
exit(1);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
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;
|
|
|
|
#if 1
|
|
hPing = PingOpenRequest(NULL);
|
|
if (hPing == NULL) {
|
|
NlsPutMsg( STDOUT, PING_MESSAGE_15, GetLastError() );
|
|
}
|
|
#else
|
|
IcmpHandle = IcmpCreateFile();
|
|
|
|
if (IcmpHandle == INVALID_HANDLE_VALUE) {
|
|
NlsPutMsg( STDOUT, PING_MESSAGE_15, GetLastError() );
|
|
#if 0
|
|
printf( "Unable to contact IP driver, error code %d.\n",
|
|
GetLastError() );
|
|
#endif //0
|
|
exit(1);
|
|
}
|
|
#endif
|
|
|
|
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 = OptLength;
|
|
SendOpts.Ttl = TTL;
|
|
SendOpts.Tos = TOS;
|
|
SendOpts.Flags = Flags;
|
|
|
|
#if 1
|
|
NlsPutMsg(
|
|
STDOUT,
|
|
PING_HEADER2,
|
|
Pingee,
|
|
SendSize
|
|
);
|
|
#else
|
|
addr.s_addr = address;
|
|
|
|
if (hostname) {
|
|
PingNtoa(
|
|
addr,
|
|
NtoaBuffer);
|
|
|
|
NlsPutMsg(
|
|
STDOUT,
|
|
PING_HEADER1,
|
|
hostname,
|
|
NtoaBuffer,
|
|
SendSize
|
|
);
|
|
// printf("Pinging Host %s [%s]\n", hostname, inet_ntoa(addr));
|
|
} else {
|
|
PingNtoa(
|
|
addr,
|
|
NtoaBuffer);
|
|
|
|
NlsPutMsg(
|
|
STDOUT,
|
|
PING_HEADER2,
|
|
NtoaBuffer,
|
|
SendSize
|
|
);
|
|
// printf("Pinging Host [%s]\n", inet_ntoa(addr));
|
|
}
|
|
#endif
|
|
|
|
for (i = 0; i < Count; i++) {
|
|
#if 1
|
|
result =
|
|
PingSend(
|
|
hPing,
|
|
Pingee,
|
|
SendBuffer,
|
|
(unsigned short) SendSize,
|
|
&SendOpts,
|
|
RcvBuffer,
|
|
RcvSize,
|
|
Timeout,
|
|
&numberOfReplies
|
|
);
|
|
#else
|
|
numberOfReplies = IcmpSendEcho(
|
|
IcmpHandle,
|
|
address,
|
|
SendBuffer,
|
|
(unsigned short) SendSize,
|
|
&SendOpts,
|
|
RcvBuffer,
|
|
RcvSize,
|
|
Timeout
|
|
);
|
|
#endif
|
|
|
|
if (numberOfReplies == 0) {
|
|
|
|
errorCode = GetLastError();
|
|
|
|
if (errorCode == IP_BAD_DESTINATION) {
|
|
NlsPutMsg( STDOUT, PING_BAD_DESTINATION, errorCode );
|
|
exit(1);
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
else {
|
|
|
|
reply = (PICMP_ECHO_REPLY) RcvBuffer;
|
|
|
|
while (numberOfReplies--) {
|
|
struct in_addr addr;
|
|
|
|
addr.S_un.S_addr = reply->Address;
|
|
|
|
PingNtoa(
|
|
addr,
|
|
NtoaBuffer);
|
|
|
|
NlsPutMsg(STDOUT, PING_MESSAGE_19, NtoaBuffer);
|
|
// 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 );
|
|
// printf("time=%lums ", reply->RoundTripTime);
|
|
}
|
|
else {
|
|
NlsPutMsg( STDOUT, PING_MESSAGE_23 );
|
|
// printf("time<10ms ");
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
reply++;
|
|
}
|
|
|
|
if (i < (Count - 1)) {
|
|
reply--;
|
|
|
|
if (reply->RoundTripTime < MIN_INTERVAL) {
|
|
Sleep(MIN_INTERVAL - reply->RoundTripTime);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#if 1
|
|
result = PingCloseRequest(hPing);
|
|
#else
|
|
result = IcmpCloseHandle(IcmpHandle);
|
|
#endif
|
|
|
|
LocalFree(SendBuffer);
|
|
LocalFree(RcvBuffer);
|
|
|
|
return;
|
|
}
|
|
|
|
#define UC(b) (((int)b)&0xff)
|
|
|
|
void
|
|
PingNtoa(
|
|
IN struct in_addr in,
|
|
IN OUT char * Buffer
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function takes an Internet address structure specified by the
|
|
in parameter. It returns an ASCII string representing the address
|
|
in ".'' notation as "a.b.c.d". Note that the string returned by
|
|
inet_ntoa() resides in memory which is allocated by the Windows
|
|
Sockets implementation. The application should not make any
|
|
assumptions about the way in which the memory is allocated. The
|
|
data is guaranteed to be valid until the next Windows Sockets API
|
|
call within the same thread, but no longer.
|
|
|
|
Arguments:
|
|
|
|
in - A structure which represents an Internet host address.
|
|
|
|
Return Value:
|
|
|
|
If no error occurs, inet_ntoa() returns a char pointer to a static
|
|
buffer containing the text address in standard "." notation.
|
|
Otherwise, it returns NULL. The data should be copied before
|
|
another Windows Sockets call is made.
|
|
|
|
--*/
|
|
|
|
{
|
|
register char *p;
|
|
|
|
p = (char *) ∈
|
|
sprintf(Buffer, "%d.%d.%d.%d", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));
|
|
}
|