📄 ping.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Module Name:
ping.c
Abstract:
Packet INternet Groper utility for TCP/IP. This is a command line
sample program to demonstrate the use of the icmplib. Since there
is no console in a Windows CE system (at least not now) this needs
to be run under the debugger to view the output.
Functions:
Notes:
--*/
#include <windows.h>
#include "winsock2.h"
#include "Ws2tcpip.h"
#include <memory.h>
#include "icmpapi.h"
#include "ntddip6.h"
#define DECLARE_OUTMSG
#include "outmsg.h"
#include "lmemdebug.h"
#ifdef DEBUG
DBGPARAM dpCurSettings =
{
TEXT("Ping"), {
TEXT("Unused"),TEXT("Unused"),TEXT("Unused"),TEXT("Unused"),
TEXT("Unused"),TEXT("Unused"),TEXT("Unused"),TEXT("Unused"),
TEXT("Unused"),TEXT("Unused"),TEXT("Unused"),TEXT("Unused"),
TEXT("Unused"),TEXT("Unused"),TEXT("Unused"),TEXT("Unused") },
0x00000000
};
#endif
#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
uchar SendOptions[MAX_OPT_SIZE];
WSADATA WsaData;
TCHAR szOutBuf[1024];
LPADDRINFO g_AI; // List of ADDRINFOs from getaddrinfo
LPADDRINFO g_NextAI; // Next ADDRINFO to try
char g_TargetString[NI_MAXHOST+1];
__inline int
IsLinkLocal(const IPv6Addr *Addr)
{
return ((Addr->s6_bytes[0] == 0xfe) &&
((Addr->s6_bytes[1] & 0xc0) == 0x80));
}
void
PrintUsage(
void
)
{
OutputMessage(TEXT("Usage: ping [-l size] [-n count] [-d] [-i TTL] ")
TEXT("[-v TOS] [-w timeout] address\r\n"));
OutputMessage(TEXT("\r\n"));
OutputMessage(TEXT("Options:\r\n"));
OutputMessage(TEXT(" -d Send output to the debug output port.\r\n"));
OutputMessage(TEXT(" -t Ping the specifed host ")
TEXT("until interrupted.\r\n"));
OutputMessage(TEXT(" -l size Send buffer size.\r\n"));
OutputMessage(TEXT(" -n count Send count.\r\n"));
OutputMessage(TEXT(" -f Don't fragment.\r\n"));
OutputMessage(TEXT(" -i TTL Time to live.\r\n"));
OutputMessage(TEXT(" -v TOS Type of service\r\n"));
OutputMessage(TEXT(" -w timeout Timeout (in milliseconds)\r\n"));
OutputMessage(TEXT(" -r count Record route for count hops.\r\n"));
OutputMessage(TEXT(" -s count Timestamp route for count hops.\r\n"));
OutputMessage(TEXT(" -S address Source address to use (IPv6-only).\r\n"));
OutputMessage(TEXT(" -4 Force using IPv4.\r\n"));
OutputMessage(TEXT(" -6 Force using IPv6.\r\n"));
// OutputMessage(TEXT(" -j ipaddress Loose source route.\r\n")));
// OutputMessage(TEXT(" -k ipaddress Strict source route.\r\n")));
OutputMessage(TEXT("\r\n"));
}
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) {
OutputMessage (TEXT("Invalid RR option\r\n"));
done = TRUE;
break;
}
optionLength = optionPtr[1];
if (((optionPtr + optionLength) > endPtr) ||
(optionLength < 3)) {
OutputMessage (TEXT("Invalid RR option\r\n"));
done = TRUE;
break;
}
entryEndPtr = optionPtr[2];
if (entryEndPtr < 4) {
OutputMessage (TEXT("Invalid RR option\r\n"));
optionPtr += optionLength;
break;
}
if (entryEndPtr > (optionLength + 1)) {
entryEndPtr = optionLength + 1;
}
entryPtr = 4;
entryCount = 0;
OutputMessage (TEXT("Route Header --- \r\n"));
while ((entryPtr + 3) < entryEndPtr) {
struct in_addr routeAddress;
if (entryCount) {
OutputMessage (TEXT("\r\n"));
if (entryCount == 1) {
OutputMessage (TEXT("\r\n"));
OutputMessage (TEXT("Route Header2 --\r\n"));
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) {
OutputMessage (TEXT("Route %hs %hs "),hostEntry->h_name,
inet_ntoa(routeAddress));
}
else {
OutputMessage (TEXT("Route %hs "),
inet_ntoa(routeAddress));
}
}
else {
OutputMessage (TEXT("Route %hs "),
inet_ntoa(routeAddress));
}
entryPtr += 4;
}
OutputMessage (TEXT("\r\n"));
optionPtr += optionLength;
break;
case IP_OPT_TS:
if ((optionPtr + 4) > endPtr) {
OutputMessage (TEXT("Invalid TS Option\r\n"));
done = TRUE;
break;
}
optionLength = optionPtr[1];
entryEndPtr = optionPtr[2];
if (entryEndPtr < 5) {
OutputMessage (TEXT("Invalid TS Option\r\n"));
optionPtr += optionLength;
break;
}
addressMode = optionPtr[3] & 1;
if (entryEndPtr > (optionLength + 1)) {
entryEndPtr = optionLength + 1;
}
entryPtr = 5;
entryCount = 0;
OutputMessage (TEXT("\tTimestamp:\t"));
while ((entryPtr + 3) < entryEndPtr) {
struct in_addr routeAddress;
ULONG timeStamp;
if (entryCount) {
OutputMessage (TEXT("\r\n\t\t\t"));
if (entryCount == 1) {
OutputMessage (TEXT("\r\n"));
OutputMessage (TEXT("Timestamp Hd2 \r\n"));
}
}
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) {
OutputMessage (TEXT("TS %hs %hs "),
hostEntry->h_name,
inet_ntoa(routeAddress));
} else {
OutputMessage (TEXT("TS %hs "),
inet_ntoa(routeAddress));
}
} else {
OutputMessage (TEXT("TS %hs "),
inet_ntoa(routeAddress));
}
entryPtr += 4;
}
timeStamp = *( (ULONG UNALIGNED *)
(optionPtr + entryPtr - 1));
OutputMessage (TEXT("TimeStamp %u "),
ntohl(timeStamp));
entryPtr += 4;
}
OutputMessage (TEXT("\r\n"));
optionPtr += optionLength;
break;
default:
if ((optionPtr + 2) > endPtr) {
done = TRUE;
break;
}
optionPtr += optionPtr[1];
break;
}
}
}
BOOLEAN
ResolveTarget(
int Family,
wchar_t *wTargetString,
SOCKADDR *TargetAddress,
socklen_t *TargetAddressLen,
char *TargetName,
int TargetNameLen,
BOOLEAN DoReverseLookup
)
{
int i;
struct addrinfo hints, *ai;
if (0 == WideCharToMultiByte(CP_ACP, 0, wTargetString, -1, g_TargetString, sizeof(g_TargetString), NULL, NULL))
return FALSE;
TargetName[0] = '\0';
memset(&hints, 0, sizeof(hints));
hints.ai_family = Family;
hints.ai_flags = AI_NUMERICHOST;
i = getaddrinfo(g_TargetString, "", &hints, &ai);
if(i == NO_ERROR)
{
*TargetAddressLen = ai->ai_addrlen;
memcpy(TargetAddress, ai->ai_addr, ai->ai_addrlen);
if (DoReverseLookup)
{
getnameinfo(ai->ai_addr, ai->ai_addrlen,
TargetName, TargetNameLen,
NULL, 0, NI_NAMEREQD);
}
freeaddrinfo(ai);
return(TRUE);
}
else
{
hints.ai_flags = AI_CANONNAME;
if (getaddrinfo(g_TargetString, NULL, &hints, &ai) == 0)
{
*TargetAddressLen = ai->ai_addrlen;
memcpy(TargetAddress, ai->ai_addr, ai->ai_addrlen);
strcpy(TargetName, (ai->ai_canonname)? ai->ai_canonname : g_TargetString);
g_AI = ai;
g_NextAI = ai->ai_next;
return(TRUE);
}
}
return(FALSE);
} // ResolveTarget
//
// GetNextAddress - Return the name and address of the current ADDRINFO and advance to the next ADDRINFO.
//
BOOLEAN
GetNextAddress(
SOCKADDR *TargetAddress,
socklen_t *TargetAddressLen,
char *TargetName,
int TargetNameLen
)
{
if (g_NextAI) {
*TargetAddressLen = g_NextAI->ai_addrlen;
memcpy(TargetAddress, g_NextAI->ai_addr, g_NextAI->ai_addrlen);
strcpy(TargetName, (g_NextAI->ai_canonname)? g_NextAI->ai_canonname : g_TargetString);
g_NextAI = g_NextAI->ai_next;
return TRUE;
}
return FALSE;
} // GetNextAddress
ulong
param(TCHAR **argv, int argc, int current, ulong min, ulong max, BOOL *Valid)
{
ulong temp = 0;
if (current == (argc - 1) ) {
OutputMessage(TEXT( "Value must be supplied for option %s.\r\n"),
argv[current]);
*Valid = FALSE;
} else {
temp = _ttol(argv[current+1]);
if (temp < min || temp > max) {
OutputMessage(TEXT( "Bad value for option %s.\r\n"),
argv[current]);
*Valid = FALSE;
}
}
return temp;
}
int WinMain( int argc, TCHAR *argv[] )
{
BOOL ValidParms = TRUE;
uint i;
uint j;
int found_addr = 0;
BOOLEAN dnsreq = FALSE;
char hostname[NI_MAXHOST] = "", literal[INET6_ADDRSTRLEN] = "", source[NI_MAXHOST] = "";
SOCKADDR_STORAGE address;
SOCKADDR_STORAGE sourceAddress;
DWORD numberOfReplies;
DWORD totalReplies;
uint Count = DEFAULT_COUNT;
uchar TTL = DEFAULT_TTL;
uchar *Opt = (uchar *)0; // Pointer to send options
uint OptLength = 0;
int OptIndex = 0; // Current index into SendOptions
uchar TOS = DEFAULT_TOS;
uchar Flags = 0;
ulong Timeout = DEFAULT_TIMEOUT;
IP_OPTION_INFORMATION SendOpts;
uchar TempCount;
DWORD errorCode;
int err;
PICMP_ECHO_REPLY reply4;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -