windows-nt/Source/XPSP1/NT/printscan/print/spooler/inetpp2/server/ping.cxx
2020-09-26 16:20:57 +08:00

359 lines
8.6 KiB
C++

/*++
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
-------- -------- ----------------------------------------------
WeihaiC 5-Dec-98. Moved from \nt\private\net\sockets\tcpcmd\ping
MohsinA, 21-Oct-96. INADDR_NONE check to avoid broadcast.
MohsinA, 13-Nov-96. Max packet size < 64K.
Notes:
--*/
//:ts=4
typedef unsigned long ULONG;
typedef unsigned short ushort;
typedef unsigned int UINT;
typedef unsigned char UCHAR;
#include "precomp.h"
#include "icmpapi.h"
#define NOGDI
#define NOMINMAX
#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 5000L
#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
WSADATA WsaData;
// ========================================================================
// 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);
}
// ========================================================================
BOOL Ping (LPTSTR pszServerName)
{
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 = 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;
DWORD errorCode;
HANDLE IcmpHandle = NULL;
int err;
struct in_addr addr;
BOOL result;
PICMP_ECHO_REPLY reply;
BOOL sourceRouting = FALSE;
char *SendBuffer = NULL;
char *RcvBuffer = NULL;
UINT RcvSize;
UINT SendSize = DEFAULT_SEND_SIZE;
BOOL bRet = FALSE;
IPAddr address = 0; // was local to main earlier.
char *arg;
// ====================================================================
#ifdef UNICODE
LPSTR pszAnsiServerName = NULL;
DWORD uSize;
if (pszServerName && (uSize = WideCharToMultiByte(CP_ACP,
0,
pszServerName,
-1,
NULL,
0,
NULL,
NULL))) {
if (pszAnsiServerName = (LPSTR) LocalAlloc(LPTR, uSize)) {
if (!WideCharToMultiByte (CP_ACP,
0,
pszServerName,
-1,
pszAnsiServerName,
uSize,
NULL,
NULL))
goto CleanUp;
}
else
goto CleanUp;
}
arg = pszAnsiServerName;
#else
arg = pszServerName;
#endif
if (WSAStartup( 0x0101, &WsaData))
goto CleanUp;
// Added check for INADDR_NONE, MohsinA, 21-Oct-96.
address = get_pingee(arg, &hostname, &was_inaddr, dnsreq);
if(!address || (address == INADDR_NONE) ){
SetLastError (DNS_ERROR_INVALID_IP_ADDRESS);
goto CleanUp;
}
IcmpHandle = IcmpCreateFile();
if (IcmpHandle == INVALID_HANDLE_VALUE) {
goto CleanUp;
}
if (! (SendBuffer = (char *) LocalAlloc(LMEM_FIXED, SendSize))) {
goto CleanUp;
}
//
// Calculate receive buffer size and try to allocate it.
//
if (SendSize <= DEFAULT_SEND_SIZE) {
RcvSize = DEFAULT_BUFFER_SIZE;
}
else {
RcvSize = MAX_BUFFER_SIZE;
}
if (! (RcvBuffer = (char *)LocalAlloc(LMEM_FIXED, RcvSize))) {
goto CleanUp;
}
//
// 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 0
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));
}
#endif
// for (i = 0; i < Count; i++) {
numberOfReplies = IcmpSendEcho(
IcmpHandle,
address,
SendBuffer,
(unsigned short) SendSize,
&SendOpts,
RcvBuffer,
RcvSize,
Timeout
);
if (numberOfReplies == 0) {
errorCode = GetLastError();
goto CleanUp;
// Need to try again? - weihaic
}
else {
reply = (PICMP_ECHO_REPLY) RcvBuffer;
while (numberOfReplies--) {
struct in_addr addr;
addr.S_un.S_addr = reply->Address;
// printf(
// "Reply from %s:",
// inet_ntoa(addr),
// );
if (reply->Status == IP_SUCCESS) {
// printf(
// "Echo size=%d ",
// reply->DataSize
// );
bRet = TRUE;
break;
// printf("\n time rt=%dms min %d, max %d, total %d\n",
// reply->RoundTripTime,
// time_min, time_max, time_total );
// printf("TTL=%u\n", (UINT)reply->Options.Ttl);
//
// Ignore Option fields
// 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;
}
}
} */
reply++;
}
}
// }
CleanUp:
#ifdef UNICODE
if (pszAnsiServerName) {
LocalFree(pszAnsiServerName);
}
#endif
if (IcmpHandle) {
IcmpCloseHandle(IcmpHandle);
}
if (SendBuffer) {
LocalFree(SendBuffer);
}
if (RcvBuffer) {
LocalFree(RcvBuffer);
}
return bRet;
}