501 lines
15 KiB
C++
501 lines
15 KiB
C++
|
|
#include "diagnostics.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <winsock2.h>
|
|
#include <Ipexport.h>
|
|
#include <icmpapi.h>
|
|
#include <ctype.h>
|
|
|
|
#define DEFAULT_SEND_SIZE 32
|
|
#define DEFAULT_TTL 128
|
|
#define DEFAULT_TOS 0
|
|
#define DEFAULT_COUNT 4
|
|
#define DEFAULT_TIMEOUT 4000L
|
|
#define DEFAULT_BUFFER_SIZE (0x2000 - 8)
|
|
#define MIN_INTERVAL 1000L
|
|
|
|
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}
|
|
};
|
|
|
|
UINT num_send=0, num_recv=0, time_min=(UINT)-1, time_max=0, time_total=0;
|
|
IPAddr address=0;
|
|
|
|
|
|
|
|
LPWSTR NlsPutMsg(HMODULE Handle, unsigned usMsgNum, ...);
|
|
|
|
|
|
unsigned long get_pingee(char *ahstr, char **hstr, int *was_inaddr, int dnsreq);
|
|
|
|
//void print_statistics();
|
|
|
|
int CDiagnostics::Ping2(WCHAR *warg)
|
|
{
|
|
HANDLE IcmpHandle;
|
|
IP_OPTION_INFORMATION SendOpts;
|
|
UCHAR *Opt = NULL; // Pointer to send options
|
|
UCHAR Flags = 0;
|
|
char SendBuffer[DEFAULT_SEND_SIZE];
|
|
char RcvBuffer[DEFAULT_BUFFER_SIZE];
|
|
UINT SendSize = DEFAULT_SEND_SIZE;
|
|
UINT RcvSize = DEFAULT_BUFFER_SIZE;
|
|
UINT i;
|
|
UINT j;
|
|
char *hostname = NULL;
|
|
int was_inaddr;
|
|
int dnsreq = 0;
|
|
struct in_addr addr;
|
|
DWORD numberOfReplies;
|
|
UINT Count = DEFAULT_COUNT;
|
|
DWORD errorCode;
|
|
PICMP_ECHO_REPLY reply;
|
|
LPWSTR wszMsg, wszMsg2, wszMsg3, wszMsg4, wszMsg5;
|
|
int SuccessCount = 0;
|
|
char *arg;
|
|
|
|
num_send=0;
|
|
num_recv=0,
|
|
time_min=(UINT)-1;
|
|
time_max=0;
|
|
time_total=0;
|
|
address=0;
|
|
|
|
if( warg == NULL )
|
|
{
|
|
wszMsg = NlsPutMsg(g_hModule,PING_NO_MEMORY,GetLastError());
|
|
FormatPing(wszMsg);
|
|
LocalFree(wszMsg);
|
|
return FALSE;
|
|
}
|
|
|
|
int len = lstrlen(warg);
|
|
if( len == 0 )
|
|
{
|
|
wszMsg = NlsPutMsg(g_hModule, IDS_PINGMSG_2,warg);
|
|
FormatPing(wszMsg);
|
|
LocalFree(wszMsg);
|
|
return FALSE;
|
|
}
|
|
|
|
// Add the '\0' char
|
|
len++;
|
|
|
|
arg = (CHAR *)HeapAlloc(GetProcessHeap(),0,len * sizeof(WCHAR));
|
|
if( !arg )
|
|
{
|
|
wszMsg = NlsPutMsg(g_hModule,IDS_PINGMSG_1,GetLastError());
|
|
FormatPing(wszMsg);
|
|
LocalFree(wszMsg);
|
|
return FALSE;
|
|
}
|
|
if( -1 == wcstombs(arg,warg,len) )
|
|
{
|
|
wszMsg = NlsPutMsg(g_hModule, IDS_PINGMSG_2,warg);
|
|
FormatPing(wszMsg);
|
|
LocalFree(wszMsg);
|
|
HeapFree(GetProcessHeap(),0,arg);
|
|
return FALSE;
|
|
}
|
|
|
|
FormatPing(NULL);
|
|
|
|
address = get_pingee(arg, &hostname, &was_inaddr, dnsreq);
|
|
if ( !address || (address == INADDR_NONE) ) {
|
|
wszMsg = NlsPutMsg(g_hModule, IDS_PINGMSG_2,warg);
|
|
FormatPing(wszMsg);
|
|
LocalFree(wszMsg);
|
|
return 0;
|
|
/*
|
|
printf("Ping request could not find host %s. Please check the name and try again.\n",arg);
|
|
exit(1);
|
|
*/
|
|
}
|
|
|
|
|
|
IcmpHandle = IcmpCreateFile();
|
|
|
|
if (IcmpHandle == INVALID_HANDLE_VALUE) {
|
|
wszMsg = NlsPutMsg(g_hModule, IDS_PINGMSG_3,GetLastError());
|
|
FormatPing(wszMsg);
|
|
LocalFree(wszMsg);
|
|
return 0;
|
|
|
|
/*
|
|
printf( "Unable to contact IP driver, error code %d.\n",
|
|
GetLastError() );
|
|
exit(1);
|
|
*/
|
|
}
|
|
|
|
//
|
|
// Initialize the send buffer pattern.
|
|
//
|
|
for (i = 0; i < SendSize; i++) {
|
|
SendBuffer[i] = 'a' + (i % 23);
|
|
}
|
|
|
|
|
|
//
|
|
// Initialize the send options
|
|
//
|
|
SendOpts.OptionsData = NULL;
|
|
SendOpts.OptionsSize = 0;
|
|
SendOpts.Ttl = DEFAULT_TTL;
|
|
SendOpts.Tos = DEFAULT_TOS;
|
|
SendOpts.Flags = Flags;
|
|
|
|
addr.s_addr = address;
|
|
|
|
|
|
if (hostname) {
|
|
wszMsg = NlsPutMsg(g_hModule, IDS_PINGMSG_4,hostname,inet_ntoa(addr),SendSize);
|
|
FormatPing(wszMsg);
|
|
LocalFree(wszMsg);
|
|
/*
|
|
printf("\nPinging %s [%s] with %d bytes of data:\n\n",hostname,inet_ntoa(addr),SendSize);
|
|
*/
|
|
}
|
|
else
|
|
{
|
|
wszMsg = NlsPutMsg(g_hModule, IDS_PINGMSG_5,inet_ntoa(addr),SendSize);
|
|
FormatPing(wszMsg);
|
|
LocalFree(wszMsg);
|
|
|
|
/*
|
|
printf("\nPinging %s with %d bytes of data:\n\n",inet_ntoa(addr), SendSize);
|
|
*/
|
|
}
|
|
|
|
for (i = 0; i < Count; i++) {
|
|
|
|
if( ShouldTerminate() ) goto end;
|
|
|
|
numberOfReplies = IcmpSendEcho2(IcmpHandle,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
address,
|
|
SendBuffer,
|
|
(unsigned short) SendSize,
|
|
&SendOpts,
|
|
RcvBuffer,
|
|
RcvSize,
|
|
DEFAULT_TIMEOUT);
|
|
|
|
num_send++;
|
|
|
|
if (numberOfReplies == 0) {
|
|
|
|
errorCode = GetLastError();
|
|
|
|
if (errorCode < IP_STATUS_BASE) {
|
|
wszMsg = NlsPutMsg(g_hModule, IDS_PINGMSG_6,errorCode);
|
|
FormatPing(wszMsg);
|
|
LocalFree(wszMsg);
|
|
|
|
/*
|
|
printf("PING: transmit failed, error code %d.\n",errorCode);
|
|
*/
|
|
} else {
|
|
for (j = 0; ErrorTable[j].Error != errorCode &&
|
|
ErrorTable[j].Error != IP_GENERAL_FAILURE;j++)
|
|
;
|
|
|
|
wszMsg = NlsPutMsg(g_hModule, ErrorTable[j].ErrorNlsID);
|
|
FormatPing(wszMsg);
|
|
LocalFree(wszMsg);
|
|
|
|
/*
|
|
printf("%s\n",ErrorTable[j].ErrorNlsID);
|
|
*/
|
|
}
|
|
|
|
if (i < (Count - 1)) {
|
|
Sleep(MIN_INTERVAL);
|
|
}
|
|
|
|
} else {
|
|
|
|
/*
|
|
wszMsg = NlsPutMsg(g_hModule, ErrorTable[j].ErrorNlsID);
|
|
FormatPing(wszMsg);
|
|
LocalFree(wszMsg);
|
|
*/
|
|
|
|
reply = (PICMP_ECHO_REPLY) RcvBuffer;
|
|
|
|
while (numberOfReplies--) {
|
|
struct in_addr addr;
|
|
|
|
addr.S_un.S_addr = reply->Address;
|
|
|
|
wszMsg = NlsPutMsg(g_hModule, IDS_PINGMSG_7, inet_ntoa(addr));
|
|
/*
|
|
printf("Reply from %s: ",inet_ntoa(addr));
|
|
*/
|
|
if (reply->Status == IP_SUCCESS) {
|
|
|
|
wszMsg2 = NlsPutMsg(g_hModule, IDS_PINGMSG_8, wszMsg, (int) reply->DataSize);
|
|
/*
|
|
printf("bytes=%d ",(int) reply->DataSize);
|
|
*/
|
|
if (reply->DataSize != SendSize) {
|
|
wszMsg3 = NlsPutMsg(g_hModule, IDS_PINGMSG_9, wszMsg2, (int) reply->DataSize);
|
|
/*
|
|
printf("(sent %d) ",SendSize);
|
|
*/
|
|
} else {
|
|
char *sendptr, *recvptr;
|
|
|
|
sendptr = &(SendBuffer[0]);
|
|
recvptr = (char *) reply->Data;
|
|
|
|
wszMsg3 = NlsPutMsg(g_hModule, IDS_PINGMSG_14, wszMsg2);
|
|
for (j = 0; j < SendSize; j++)
|
|
if (*sendptr++ != *recvptr++) {
|
|
wszMsg3 = NlsPutMsg(g_hModule, IDS_PINGMSG_10, wszMsg2,j);
|
|
/*
|
|
printf("- MISCOMPARE at offset %d - ",j);
|
|
*/
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
if (reply->RoundTripTime) {
|
|
|
|
wszMsg4 = NlsPutMsg(g_hModule, IDS_PINGMSG_11, wszMsg3,reply->RoundTripTime);
|
|
/*
|
|
printf("time=%dms ",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 {
|
|
|
|
wszMsg4 = NlsPutMsg(g_hModule, IDS_PINGMSG_12,wszMsg3);
|
|
/*
|
|
printf("time<1ms ");
|
|
*/
|
|
time_min = 0;
|
|
}
|
|
|
|
wszMsg5 = NlsPutMsg(g_hModule, IDS_PINGMSG_13, wszMsg4,reply->RoundTripTime);
|
|
|
|
/*
|
|
printf("TTL=%d\n",(UINT)reply->Options.Ttl);
|
|
*/
|
|
if (reply->Options.OptionsSize) {
|
|
// void, we have no options
|
|
//ProcessOptions(reply, (BOOLEAN) dnsreq);
|
|
}
|
|
|
|
FormatPing(wszMsg5);
|
|
if(wszMsg) LocalFree(wszMsg);
|
|
if(wszMsg2) LocalFree(wszMsg2);
|
|
if(wszMsg3) LocalFree(wszMsg3);
|
|
if(wszMsg4) LocalFree(wszMsg4);
|
|
if(wszMsg5) LocalFree(wszMsg5);
|
|
SuccessCount++;
|
|
} else {
|
|
for (j=0; ErrorTable[j].Error != IP_GENERAL_FAILURE; j++) {
|
|
if (ErrorTable[j].Error == reply->Status) {
|
|
break;
|
|
}
|
|
}
|
|
wszMsg = NlsPutMsg(g_hModule, ErrorTable[j].ErrorNlsID);
|
|
FormatPing(wszMsg);
|
|
LocalFree(wszMsg);
|
|
/*
|
|
printf("%s",ErrorTable[j].ErrorNlsID);
|
|
*/
|
|
}
|
|
|
|
num_recv++;
|
|
reply++;
|
|
}
|
|
|
|
if (i < (Count - 1)) {
|
|
reply--;
|
|
|
|
if (reply->RoundTripTime < MIN_INTERVAL) {
|
|
Sleep(MIN_INTERVAL - reply->RoundTripTime);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
print_statistics();
|
|
|
|
end:
|
|
|
|
(void)IcmpCloseHandle(IcmpHandle);
|
|
|
|
HeapFree(GetProcessHeap(),0,arg);
|
|
return SuccessCount == Count;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
|
|
void
|
|
CDiagnostics::print_statistics( )
|
|
{
|
|
struct in_addr addr;
|
|
LPWSTR wszMsg;
|
|
|
|
if (num_send > 0) {
|
|
addr.s_addr = address;
|
|
|
|
if (time_min == (UINT) -1) { // all times were off.
|
|
time_min = 0;
|
|
}
|
|
|
|
wszMsg = NlsPutMsg(g_hModule, IDS_PINGMSG_15,inet_ntoa(addr));
|
|
FormatPing(wszMsg);
|
|
LocalFree(wszMsg);
|
|
|
|
/*
|
|
printf("\n");
|
|
printf("Ping statistics for %s:\n",inet_ntoa(addr));
|
|
*/
|
|
|
|
wszMsg = NlsPutMsg(g_hModule, IDS_PINGMSG_16,
|
|
num_send, num_recv,num_send - num_recv,(UINT) ( 100 * (num_send - num_recv) / num_send ));
|
|
FormatPing(wszMsg);
|
|
LocalFree(wszMsg);
|
|
|
|
/*
|
|
printf(" Packets: Sent = %d, Received = %d, Lost = %d (%u%% loss)\n",
|
|
num_send, num_recv,num_send - num_recv,(UINT) ( 100 * (num_send - num_recv) / num_send ));
|
|
*/
|
|
if (num_recv > 0) {
|
|
|
|
wszMsg = NlsPutMsg(g_hModule, IDS_PINGMSG_17);
|
|
FormatPing(wszMsg);
|
|
LocalFree(wszMsg);
|
|
|
|
/*
|
|
printf("Approximate round trip times in milli-seconds:\n");
|
|
*/
|
|
|
|
wszMsg = NlsPutMsg(g_hModule, IDS_PINGMSG_18,
|
|
time_min, time_max, time_total / num_recv);
|
|
FormatPing(wszMsg);
|
|
LocalFree(wszMsg);
|
|
|
|
/*
|
|
printf(" Minimum = %dms, Maximum = %dms, Average = %dms\n",time_min, time_max, time_total / num_recv);
|
|
*/
|
|
}
|
|
}
|
|
}
|
|
|
|
LPWSTR
|
|
NlsPutMsg(HMODULE Handle, unsigned usMsgNum, ...)
|
|
{
|
|
unsigned msglen;
|
|
VOID * vp = NULL;
|
|
va_list arglist;
|
|
DWORD StrLen;
|
|
WCHAR wszFormat[5000]; //BUGBUG hardcode value
|
|
int ret;
|
|
|
|
if( (ret=LoadString(Handle,usMsgNum,wszFormat,5000))!=0 )
|
|
{
|
|
va_start(arglist, usMsgNum);
|
|
if (!(msglen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
FORMAT_MESSAGE_FROM_STRING,
|
|
wszFormat,
|
|
0,
|
|
0L, // Default country ID.
|
|
(LPTSTR)&vp,
|
|
0,
|
|
&arglist)))
|
|
|
|
{
|
|
return NULL;
|
|
|
|
}
|
|
}
|
|
return (LPWSTR)vp;
|
|
|
|
/*
|
|
// Convert vp to oem
|
|
StrLen=strlen(vp);
|
|
CharToOemBuff((LPCTSTR)vp,(LPSTR)vp,StrLen);
|
|
|
|
msglen = _write(Handle, vp, StrLen);
|
|
LocalFree(vp);
|
|
|
|
return(msglen);
|
|
*/
|
|
}
|