📄 ping.c
字号:
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS ping utility
* FILE: apps/net/ping/ping.c
* PURPOSE: Network test utility
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 01/09/2000 Created
*/
#include <winsock2.h>
#include <tchar.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#ifndef _MSC_VER
/* FIXME: Where should this be? */
#ifdef CopyMemory
#undef CopyMemory
#endif
#define CopyMemory(Destination, Source, Length) memcpy(Destination, Source, Length);
/* Should be in the header files somewhere (exported by ntdll.dll) */
long atol(const char *str);
#ifndef __int64
typedef long long __int64;
#endif
char * _i64toa(__int64 value, char *string, int radix);
#endif /* _MSC_VER */
#ifdef DBG
#undef DBG
#endif
/* General ICMP constants */
#define ICMP_MINSIZE 8 /* Minimum ICMP packet size */
#define ICMP_MAXSIZE 65535 /* Maximum ICMP packet size */
/* ICMP message types */
#define ICMPMSG_ECHOREQUEST 8 /* ICMP ECHO request message */
#define ICMPMSG_ECHOREPLY 0 /* ICMP ECHO reply message */
#pragma pack(4)
/* IPv4 header structure */
typedef struct _IPv4_HEADER {
unsigned char IHL:4;
unsigned char Version:4;
unsigned char TOS;
unsigned short Length;
unsigned short Id;
unsigned short FragFlags;
unsigned char TTL;
unsigned char Protocol;
unsigned short Checksum;
unsigned int SrcAddress;
unsigned int DstAddress;
} IPv4_HEADER, *PIPv4_HEADER;
/* ICMP echo request/reply header structure */
typedef struct _ICMP_HEADER {
unsigned char Type;
unsigned char Code;
unsigned short Checksum;
unsigned short Id;
unsigned short SeqNum;
} ICMP_HEADER, *PICMP_HEADER;
typedef struct _ICMP_ECHO_PACKET {
ICMP_HEADER Icmp;
LARGE_INTEGER Timestamp;
} ICMP_ECHO_PACKET, *PICMP_ECHO_PACKET;
#pragma pack(1)
BOOL InvalidOption;
BOOL NeverStop;
BOOL ResolveAddresses;
UINT PingCount;
UINT DataSize; /* ICMP echo request data size */
BOOL DontFragment;
ULONG TTLValue;
ULONG TOSValue;
ULONG Timeout;
CHAR TargetName[256];
SOCKET IcmpSock;
SOCKADDR_IN Target;
LPSTR TargetIP;
FD_SET Fds;
TIMEVAL Timeval;
UINT CurrentSeqNum;
UINT SentCount;
UINT LostCount;
BOOL MinRTTSet;
LARGE_INTEGER MinRTT; /* Minimum round trip time in microseconds */
LARGE_INTEGER MaxRTT;
LARGE_INTEGER SumRTT;
LARGE_INTEGER AvgRTT;
LARGE_INTEGER TicksPerMs; /* Ticks per millisecond */
LARGE_INTEGER TicksPerUs; /* Ticks per microsecond */
BOOL UsePerformanceCounter;
#ifdef DBG
/* Display the contents of a buffer */
static VOID DisplayBuffer(
PVOID Buffer,
DWORD Size)
{
UINT i;
PCHAR p;
printf("Buffer (0x%p) Size (0x%lX).\n", Buffer, Size);
p = (PCHAR)Buffer;
for (i = 0; i < Size; i++) {
if (i % 16 == 0) {
printf("\n");
}
printf("%02X ", (p[i]) & 0xFF);
}
}
#endif /* DBG */
/* Display usage information on screen */
static VOID Usage(VOID)
{
printf("\nUsage: ping [-t] [-n count] [-l size] [-w timeout] destination-host\n\n");
printf("Options:\n");
printf(" -t Ping the specified host until stopped.\n");
printf(" To stop - type Control-C.\n");
printf(" -n count Number of echo requests to send.\n");
printf(" -l size Send buffer size.\n");
printf(" -w timeout Timeout in milliseconds to wait for each reply.\n\n");
}
/* Reset configuration to default values */
static VOID Reset(VOID)
{
LARGE_INTEGER PerformanceCounterFrequency;
NeverStop = FALSE;
ResolveAddresses = FALSE;
PingCount = 4;
DataSize = 32;
DontFragment = FALSE;
TTLValue = 128;
TOSValue = 0;
Timeout = 1000;
UsePerformanceCounter = QueryPerformanceFrequency(&PerformanceCounterFrequency);
if (UsePerformanceCounter) {
/* Performance counters may return incorrect results on some multiprocessor
platforms so we restrict execution on the first processor. This may fail
on Windows NT so we fall back to GetCurrentTick() for timing */
if (SetThreadAffinityMask (GetCurrentThread(), 1) == 0) {
UsePerformanceCounter = FALSE;
}
/* Convert frequency to ticks per millisecond */
TicksPerMs.QuadPart = PerformanceCounterFrequency.QuadPart / 1000;
/* And to ticks per microsecond */
TicksPerUs.QuadPart = PerformanceCounterFrequency.QuadPart / 1000000;
}
if (!UsePerformanceCounter) {
/* 1 tick per millisecond for GetCurrentTick() */
TicksPerMs.QuadPart = 1;
/* GetCurrentTick() cannot handle microseconds */
TicksPerUs.QuadPart = 1;
}
}
/* Return ULONG in a string */
static ULONG GetULONG(LPSTR String)
{
UINT i, Length;
ULONG Value;
LPSTR StopString;
i = 0;
Length = (UINT)_tcslen(String);
while ((i < Length) && ((String[i] < '0') || (String[i] > '9'))) i++;
if ((i >= Length) || ((String[i] < '0') || (String[i] > '9'))) {
InvalidOption = TRUE;
return 0;
}
Value = strtoul(&String[i], &StopString, 10);
return Value;
}
/* Return ULONG in a string. Try next paramter if not successful */
static ULONG GetULONG2(LPSTR String1, LPSTR String2, PINT i)
{
ULONG Value;
Value = GetULONG(String1);
if (InvalidOption) {
InvalidOption = FALSE;
if (String2[0] != '-') {
Value = GetULONG(String2);
if (!InvalidOption)
*i += 1;
}
}
return Value;
}
/* Parse command line parameters */
static BOOL ParseCmdline(int argc, char* argv[])
{
INT i;
BOOL ShowUsage;
BOOL FoundTarget;
//#if 1
// lstrcpy(TargetName, "127.0.0.1");
// PingCount = 1;
// return TRUE;
//#endif
if (argc < 2) {
ShowUsage = TRUE;
} else {
ShowUsage = FALSE;
}
FoundTarget = FALSE;
InvalidOption = FALSE;
for (i = 1; i < argc; i++) {
if (argv[i][0] == '-') {
switch (argv[i][1]) {
case 't': NeverStop = TRUE; break;
case 'a': ResolveAddresses = TRUE; break;
case 'n': PingCount = GetULONG2(&argv[i][2], argv[i + 1], &i); break;
case 'l':
DataSize = GetULONG2(&argv[i][2], argv[i + 1], &i);
if (DataSize > ICMP_MAXSIZE - sizeof(ICMP_ECHO_PACKET)) {
printf("Bad value for option -l, valid range is from 0 to %d.\n",
ICMP_MAXSIZE - sizeof(ICMP_ECHO_PACKET));
return FALSE;
}
break;
case 'f': DontFragment = TRUE; break;
case 'i': TTLValue = GetULONG2(&argv[i][2], argv[i + 1], &i); break;
case 'v': TOSValue = GetULONG2(&argv[i][2], argv[i + 1], &i); break;
case 'w': Timeout = GetULONG2(&argv[i][2], argv[i + 1], &i); break;
default:
printf("Bad option %s.\n", argv[i]);
Usage();
return FALSE;
}
if (InvalidOption) {
printf("Bad option format %s.\n", argv[i]);
return FALSE;
}
} else {
if (FoundTarget) {
printf("Bad parameter %s.\n", argv[i]);
return FALSE;
} else {
lstrcpy(TargetName, argv[i]);
FoundTarget = TRUE;
}
}
}
if ((!ShowUsage) && (!FoundTarget)) {
printf("Name or IP address of destination host must be specified.\n");
return FALSE;
}
if (ShowUsage) {
Usage();
return FALSE;
}
return TRUE;
}
/* Calculate checksum of data */
static WORD Checksum(PUSHORT data, UINT size)
{
ULONG sum = 0;
while (size > 1) {
sum += *data++;
size -= sizeof(USHORT);
}
if (size)
sum += *(UCHAR*)data;
sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);
return (USHORT)(~sum);
}
/* Prepare to ping target */
static BOOL Setup(VOID)
{
WORD wVersionRequested;
WSADATA WsaData;
INT Status;
ULONG Addr;
PHOSTENT phe;
wVersionRequested = MAKEWORD(2, 2);
Status = WSAStartup(wVersionRequested, &WsaData);
if (Status != 0) {
printf("Could not initialize winsock dll.\n");
return FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -