Nosuid TCP/IP ping 1.6 beta by Michal Zalewski <lcamtuf@coredump.cx>
--------------------------------------------------------------------
The Nosuid TCP/IP ping and related utilities are free software; you
can redistribute it and/or modify it under the terms of the GNU Library
General Public License as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
while (!count || n++ < count) {
int csock;
char skew=0;
struct sigaction siga;
unsigned int delayed;
// First, let's get a socket.//
memcpy((void*)&s.sin_addr,hp->h_addr,hp->h_length);
s.sin_family=hp->h_addrtype;
s.sin_port=htons(port);
if ((csock=socket(AF_INET,SOCK_STREAM,0))<0) pfatal("socket");
// Get ready for SIGALRM... We need this signal not to restart
// the syscall, and this seems to be a good way to do it
siga.sa_handler=sig_alarm;
siga.sa_flags=0;
sigaction(SIGALRM,&siga,NULL);
alarm(timeout);
// Get time of day...
gettimeofday(&tv1,NULL);
sent++;
if (connect(csock,(struct sockaddr*)&s,sizeof(s))) {
if (got_alrm) {
printf("No ping reply from %s within %d second(s)...\n",iptext,
timeout);
got_alrm=0;
shutdown(csock,2);
close(csock);
continue;
} else {
if (errno != ECONNREFUSED) pfatal("connect");
received++;
}
} else {
received++;
skew=1;
port--;
}
alarm(0);
gettimeofday(&tv2,NULL);
// Can overflow with extremely large delays, but c'mon...
delayed=(tv2.tv_sec-tv1.tv_sec)*1000000 + (tv2.tv_usec - tv1.tv_usec);
if (delayed >= MS_THRES)
printf("Ping reply from %s: seq=%d, time=%.1f ms",iptext,sent-1,
(float)delayed/1000);
else
printf("Ping reply from %s: seq=%d, time<0.1 ms (%d usec)",iptext,
sent-1,delayed);
if (skew) printf(" (skewed!)\n"); else puts("");
total_rtt += delayed;
if (delayed > max_rtt) max_rtt = delayed;
if (delayed < min_rtt) min_rtt = delayed;
typedef struct tagIPINFO
{
u_char Ttl; // Time To Live
u_char Tos; // Type Of Service
u_char IPFlags; // IP flags
u_char OptSize; // Size of options data
u_char FAR *Options; // Options data buffer
}IPINFO, *PIPINFO;
typedef struct tagICMPECHO
{
u_long Source; // Source address
u_long Status; // IP status
u_long RTTime; // Round trip time in milliseconds
u_short DataSize; // Reply data size
u_short Reserved; // Unknown
void FAR *pData; // Reply data buffer
IPINFO ipInfo; // Reply options
}ICMPECHO, *PICMPECHO;
// Dynamically load the ICMP.DLL
hndlIcmp = LoadLibrary("ICMP.DLL");
if (hndlIcmp == NULL)
{
fprintf(stderr,"\nCould not load ICMP.DLL\n");
return;
}
// Retrieve ICMP function pointers
pIcmpCreateFile = (HANDLE (WINAPI *)(void))
GetProcAddress(hndlIcmp,"IcmpCreateFile");
pIcmpCloseHandle = (BOOL (WINAPI *)(HANDLE))
GetProcAddress(hndlIcmp,"IcmpCloseHandle");
pIcmpSendEcho = (DWORD (WINAPI *)
(HANDLE,DWORD,LPVOID,WORD,PIPINFO,LPVOID,DWORD,DWORD))
GetProcAddress(hndlIcmp,"IcmpSendEcho");
// Check all the function pointers
if (pIcmpCreateFile == NULL ||
pIcmpCloseHandle == NULL ||
pIcmpSendEcho == NULL)
{
fprintf(stderr,"\nError getting ICMP proc address\n");
FreeLibrary(hndlIcmp);
return;
}
// Init WinSock
nRet = WSAStartup(0x0101, &wsaData );
if (nRet)
{
fprintf(stderr,"\nWSAStartup() error: %d\n", nRet);
WSACleanup();
FreeLibrary(hndlIcmp);
return;
}
// Check WinSock version
if (0x0101 != wsaData.wVersion)
{
fprintf(stderr,"\nWinSock version 1.1 not supported\n");
WSACleanup();
FreeLibrary(hndlIcmp);
return;
}
// Lookup destination
// Use inet_addr() to determine if we're dealing with a name
// or an address
iaDest.s_addr = inet_addr(argv[1]);
if (iaDest.s_addr == INADDR_NONE)
pHost = gethostbyname(argv[1]);
else
pHost = gethostbyaddr((const char *)&iaDest,
sizeof(struct in_addr), AF_INET);
if (pHost == NULL)
{
fprintf(stderr, "\n%s not found\n", argv[1]);
WSACleanup();
FreeLibrary(hndlIcmp);
return;
}
// Tell the user what we're doing
printf("\nPinging %s [%s]", pHost->h_name,
inet_ntoa((*(LPIN_ADDR)pHost->h_addr_list[0])));
// Copy the IP address
dwAddress = (DWORD *)(*pHost->h_addr_list);
// Get an ICMP echo request handle
hndlFile = pIcmpCreateFile();
for (x = 0; x < 4; x++)
{
// Set some reasonable default values
ipInfo.Ttl = 255;
ipInfo.Tos = 0;
ipInfo.IPFlags = 0;
ipInfo.OptSize = 0;
ipInfo.Options = NULL;
//icmpEcho.ipInfo.Ttl = 256;
// Reqest an ICMP echo
dwRet = pIcmpSendEcho(
hndlFile, // Handle from IcmpCreateFile()
*dwAddress, // Destination IP address
NULL, // Pointer to buffer to send
0, // Size of buffer in bytes
&ipInfo, // Request options
&icmpEcho, // Reply buffer
sizeof(struct tagICMPECHO),
5000); // Time to wait in milliseconds
// Print the results
iaDest.s_addr = icmpEcho.Source;
printf("\nReply from %s Time=%ldms TTL=%d",
inet_ntoa(iaDest),
icmpEcho.RTTime,
icmpEcho.ipInfo.Ttl);
if (icmpEcho.Status)
{
printf("\nError: icmpEcho.Status=%ld",
icmpEcho.Status);
break;
}
}
printf("\n");
// Close the echo request file handle
pIcmpCloseHandle(hndlFile);
FreeLibrary(hndlIcmp);
WSACleanup();
}