mirror of
https://github.com/reactos/reactos.git
synced 2024-11-27 05:23:33 +08:00
[ARPING]
Implement an arping tool. Some portions of code are just plain copy/paste from ping tool code (booh, it's bad!). It was designed and tested on W2K3. It's in RosApps for two major reasons: such a tool doesn't exist by default in Windows 2K3. And it doesn't work in ReactOS. svn path=/trunk/; revision=70212
This commit is contained in:
parent
fedd88382f
commit
575842c05c
@ -1,4 +1,5 @@
|
||||
add_subdirectory(appwiz)
|
||||
add_subdirectory(arping)
|
||||
add_subdirectory(cat)
|
||||
add_subdirectory(hackssign)
|
||||
add_subdirectory(ntfsinfo)
|
||||
|
11
rosapps/applications/cmdutils/arping/CMakeLists.txt
Normal file
11
rosapps/applications/cmdutils/arping/CMakeLists.txt
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
add_definitions(-D__USE_W32_SOCKETS)
|
||||
add_executable(arping arping.c arping.rc)
|
||||
set_module_type(arping win32cui UNICODE)
|
||||
add_importlibs(arping user32 ws2_32 iphlpapi msvcrt kernel32)
|
||||
|
||||
if(MSVC)
|
||||
add_importlibs(arping ntdll)
|
||||
endif()
|
||||
|
||||
add_cd_file(TARGET arping DESTINATION reactos/system32 FOR all)
|
424
rosapps/applications/cmdutils/arping/arping.c
Normal file
424
rosapps/applications/cmdutils/arping/arping.c
Normal file
@ -0,0 +1,424 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS ping utility
|
||||
* FILE: applications/cmdutils/arping/arping.c
|
||||
* PURPOSE: Network test utility
|
||||
* PROGRAMMERS: Pierre Schweitzer <pierre@reactos.org>
|
||||
*/
|
||||
|
||||
#define WIN32_NO_STATUS
|
||||
#include <stdarg.h>
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <winuser.h>
|
||||
#include <winnls.h>
|
||||
#include <wincon.h>
|
||||
#define _INC_WINDOWS
|
||||
#include <ws2tcpip.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <ws2def.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
BOOL NeverStop;
|
||||
UINT PingCount;
|
||||
WCHAR TargetName[256];
|
||||
WCHAR SourceName[256];
|
||||
DWORD SourceAddr;
|
||||
DWORD TargetAddr;
|
||||
WCHAR TargetIP[16];
|
||||
WCHAR SourceIP[16];
|
||||
SOCKADDR_IN Target;
|
||||
HANDLE hStdOutput;
|
||||
ULONG Timeout;
|
||||
LARGE_INTEGER TicksPerMs;
|
||||
LARGE_INTEGER TicksPerUs;
|
||||
BOOL UsePerformanceCounter;
|
||||
UINT Sent;
|
||||
UINT Received;
|
||||
|
||||
void FormatOutput(UINT uID, ...)
|
||||
{
|
||||
va_list valist;
|
||||
|
||||
WCHAR Buf[1024];
|
||||
CHAR AnsiBuf[1024];
|
||||
LPWSTR pBuf = Buf;
|
||||
PCHAR pAnsiBuf = AnsiBuf;
|
||||
WCHAR Format[1024];
|
||||
DWORD written;
|
||||
UINT DataLength;
|
||||
int AnsiLength;
|
||||
|
||||
if (!LoadString(GetModuleHandle(NULL), uID,
|
||||
Format, sizeof(Format) / sizeof(WCHAR)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
va_start(valist, uID);
|
||||
|
||||
DataLength = FormatMessage(FORMAT_MESSAGE_FROM_STRING, Format, 0, 0, Buf,\
|
||||
sizeof(Buf) / sizeof(WCHAR), &valist);
|
||||
|
||||
if(!DataLength)
|
||||
{
|
||||
if(GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
va_end(valist);
|
||||
return;
|
||||
}
|
||||
|
||||
DataLength = FormatMessage(FORMAT_MESSAGE_FROM_STRING |\
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER,\
|
||||
Format, 0, 0, (LPWSTR)&pBuf, 0, &valist);
|
||||
}
|
||||
|
||||
if(!DataLength)
|
||||
{
|
||||
va_end(valist);
|
||||
return;
|
||||
}
|
||||
|
||||
if(GetFileType(hStdOutput) == FILE_TYPE_CHAR)
|
||||
{
|
||||
/* Is a console or a printer */
|
||||
WriteConsole(hStdOutput, pBuf, DataLength, &written, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Is a pipe, socket, file or other */
|
||||
AnsiLength = WideCharToMultiByte(CP_ACP, 0, pBuf, DataLength,\
|
||||
NULL, 0, NULL, NULL);
|
||||
|
||||
if(AnsiLength >= sizeof(AnsiBuf))
|
||||
pAnsiBuf = (PCHAR)HeapAlloc(GetProcessHeap(), 0, AnsiLength);
|
||||
|
||||
AnsiLength = WideCharToMultiByte(CP_OEMCP, 0, pBuf, DataLength,\
|
||||
pAnsiBuf, AnsiLength, " ", NULL);
|
||||
|
||||
WriteFile(hStdOutput, pAnsiBuf, AnsiLength, &written, NULL);
|
||||
|
||||
if(pAnsiBuf != AnsiBuf)
|
||||
HeapFree(NULL, 0, pAnsiBuf);
|
||||
}
|
||||
|
||||
if(pBuf != Buf)
|
||||
LocalFree(pBuf);
|
||||
}
|
||||
|
||||
static VOID Usage(VOID)
|
||||
{
|
||||
FormatOutput(IDS_USAGE);
|
||||
}
|
||||
|
||||
static BOOL ParseCmdline(int argc, LPWSTR argv[])
|
||||
{
|
||||
INT i;
|
||||
|
||||
if (argc < 3)
|
||||
{
|
||||
Usage();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
if (argv[i][0] == L'-' || argv[i][0] == L'/')
|
||||
{
|
||||
switch (argv[i][1])
|
||||
{
|
||||
case L't': NeverStop = TRUE; break;
|
||||
case L'n':
|
||||
if (i + 1 < argc)
|
||||
{
|
||||
PingCount = wcstoul(argv[++i], NULL, 0);
|
||||
|
||||
if (PingCount == 0)
|
||||
{
|
||||
FormatOutput(IDS_BAD_VALUE_OPTION_N, UINT_MAX);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FormatOutput(IDS_BAD_OPTION_FORMAT, argv[i]);
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case L's':
|
||||
if (SourceName[0] != 0)
|
||||
{
|
||||
FormatOutput(IDS_BAD_PARAMETER, argv[i]);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (i + 1 < argc)
|
||||
{
|
||||
wcscpy(SourceName, argv[++i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
FormatOutput(IDS_BAD_OPTION_FORMAT, argv[i]);
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case '?':
|
||||
Usage();
|
||||
return FALSE;
|
||||
|
||||
default:
|
||||
FormatOutput(IDS_BAD_OPTION, argv[i]);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (TargetName[0] != 0)
|
||||
{
|
||||
FormatOutput(IDS_BAD_PARAMETER, argv[i]);
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
wcscpy(TargetName, argv[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (TargetName[0] == 0)
|
||||
{
|
||||
FormatOutput(IDS_DEST_MUST_BE_SPECIFIED);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (SourceName[0] == 0)
|
||||
{
|
||||
FormatOutput(IDS_SRC_MUST_BE_SPECIFIED);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL WINAPI StopLoop(DWORD dwCtrlType)
|
||||
{
|
||||
NeverStop = FALSE;
|
||||
PingCount = 0;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL Setup(VOID)
|
||||
{
|
||||
WORD wVersionRequested;
|
||||
WSADATA WsaData;
|
||||
INT Status;
|
||||
PHOSTENT phe;
|
||||
CHAR aTargetName[256];
|
||||
IN_ADDR Target;
|
||||
|
||||
wVersionRequested = MAKEWORD(2, 2);
|
||||
|
||||
Status = WSAStartup(wVersionRequested, &WsaData);
|
||||
if (Status != 0)
|
||||
{
|
||||
FormatOutput(IDS_COULD_NOT_INIT_WINSOCK);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!WideCharToMultiByte(CP_ACP, 0, TargetName, -1, aTargetName,
|
||||
sizeof(aTargetName), NULL, NULL))
|
||||
{
|
||||
FormatOutput(IDS_UNKNOWN_HOST, TargetName);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
phe = NULL;
|
||||
TargetAddr = inet_addr(aTargetName);
|
||||
if (TargetAddr == INADDR_NONE)
|
||||
{
|
||||
phe = gethostbyname(aTargetName);
|
||||
if (phe == NULL)
|
||||
{
|
||||
FormatOutput(IDS_UNKNOWN_HOST, TargetName);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CopyMemory(&TargetAddr, phe->h_addr, phe->h_length);
|
||||
}
|
||||
|
||||
Target.S_un.S_addr = TargetAddr;
|
||||
swprintf(TargetIP, L"%d.%d.%d.%d", Target.S_un.S_un_b.s_b1,
|
||||
Target.S_un.S_un_b.s_b2,
|
||||
Target.S_un.S_un_b.s_b3,
|
||||
Target.S_un.S_un_b.s_b4);
|
||||
|
||||
if (!WideCharToMultiByte(CP_ACP, 0, SourceName, -1, aTargetName,
|
||||
sizeof(aTargetName), NULL, NULL))
|
||||
{
|
||||
FormatOutput(IDS_UNKNOWN_HOST, SourceName);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SourceAddr = inet_addr(aTargetName);
|
||||
if (SourceAddr == INADDR_NONE)
|
||||
{
|
||||
FormatOutput(IDS_UNKNOWN_HOST, SourceName);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SetConsoleCtrlHandler(StopLoop, TRUE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static VOID Cleanup(VOID)
|
||||
{
|
||||
WSACleanup();
|
||||
}
|
||||
|
||||
static VOID QueryTime(PLARGE_INTEGER Time)
|
||||
{
|
||||
if (UsePerformanceCounter)
|
||||
{
|
||||
if (QueryPerformanceCounter(Time) == 0)
|
||||
{
|
||||
/* This should not happen, but we fall
|
||||
back to GetCurrentTick() if it does */
|
||||
Time->u.LowPart = (ULONG)GetTickCount();
|
||||
Time->u.HighPart = 0;
|
||||
|
||||
/* 1 tick per millisecond for GetCurrentTick() */
|
||||
TicksPerMs.QuadPart = 1;
|
||||
/* GetCurrentTick() cannot handle microseconds */
|
||||
TicksPerUs.QuadPart = 1;
|
||||
|
||||
UsePerformanceCounter = FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Time->u.LowPart = (ULONG)GetTickCount();
|
||||
Time->u.HighPart = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static VOID TimeToMsString(LPWSTR String, ULONG Length, LARGE_INTEGER Time)
|
||||
{
|
||||
WCHAR Convstr[40];
|
||||
LARGE_INTEGER LargeTime;
|
||||
LPWSTR ms;
|
||||
|
||||
LargeTime.QuadPart = Time.QuadPart / TicksPerMs.QuadPart;
|
||||
|
||||
_i64tow(LargeTime.QuadPart, Convstr, 10);
|
||||
wcscpy(String, Convstr);
|
||||
ms = String + wcslen(String);
|
||||
LoadString(GetModuleHandle(NULL), IDS_MS, ms, Length - (ms - String));
|
||||
}
|
||||
|
||||
static BOOL Ping(VOID)
|
||||
{
|
||||
LARGE_INTEGER RelativeTime;
|
||||
LARGE_INTEGER LargeTime;
|
||||
LARGE_INTEGER SentTime;
|
||||
DWORD Ret;
|
||||
BYTE TargetHW[6];
|
||||
ULONG Size;
|
||||
WCHAR Sign[2];
|
||||
WCHAR Time[100];
|
||||
WCHAR StrHwAddr[18];
|
||||
|
||||
QueryTime(&SentTime);
|
||||
Size = sizeof(TargetHW);
|
||||
memset(TargetHW, 0xff, Size);
|
||||
++Sent;
|
||||
Ret = SendARP(TargetAddr, SourceAddr, (PULONG)TargetHW, &Size);
|
||||
if (Ret == ERROR_SUCCESS)
|
||||
{
|
||||
QueryTime(&LargeTime);
|
||||
|
||||
RelativeTime.QuadPart = (LargeTime.QuadPart - SentTime.QuadPart);
|
||||
|
||||
if ((RelativeTime.QuadPart / TicksPerMs.QuadPart) < 1)
|
||||
{
|
||||
wcscpy(Sign, L"<");
|
||||
LoadString(GetModuleHandle(NULL), IDS_1MS, Time, sizeof(Time) / sizeof(WCHAR));
|
||||
}
|
||||
else
|
||||
{
|
||||
wcscpy(Sign, L"=");
|
||||
TimeToMsString(Time, sizeof(Time) / sizeof(WCHAR), RelativeTime);
|
||||
}
|
||||
|
||||
swprintf(StrHwAddr, L"%02x:%02x:%02x:%02x:%02x:%02x", TargetHW[0], TargetHW[1],
|
||||
TargetHW[2], TargetHW[3],
|
||||
TargetHW[4], TargetHW[5]);
|
||||
FormatOutput(IDS_REPLY_FROM, TargetIP, StrHwAddr, Sign, Time);
|
||||
Received++;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int wmain(int argc, LPWSTR argv[])
|
||||
{
|
||||
UINT Count;
|
||||
LARGE_INTEGER PerformanceCounterFrequency;
|
||||
|
||||
PingCount = 4;
|
||||
Timeout = 1000;
|
||||
hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (!ParseCmdline(argc, argv) || !Setup())
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
FormatOutput(IDS_ARPING_TO_FROM, TargetIP, SourceName);
|
||||
|
||||
Count = 0;
|
||||
while (Count < PingCount || NeverStop)
|
||||
{
|
||||
Ping();
|
||||
Count++;
|
||||
if (Count < PingCount || NeverStop)
|
||||
Sleep(Timeout);
|
||||
}
|
||||
|
||||
Cleanup();
|
||||
|
||||
FormatOutput(IDS_ARPING_STATISTICS, Sent, Received);
|
||||
|
||||
return 0;
|
||||
}
|
15
rosapps/applications/cmdutils/arping/arping.rc
Normal file
15
rosapps/applications/cmdutils/arping/arping.rc
Normal file
@ -0,0 +1,15 @@
|
||||
#include <windef.h>
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS TCP/IPv4 Win32 ARP Ping"
|
||||
#define REACTOS_STR_INTERNAL_NAME "arpping"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "arpping.exe"
|
||||
#include <reactos/version.rc>
|
||||
|
||||
/* UTF-8 */
|
||||
#pragma code_page(65001)
|
||||
|
||||
#ifdef LANGUAGE_EN_US
|
||||
#include "lang/en-US.rc"
|
||||
#endif
|
25
rosapps/applications/cmdutils/arping/lang/en-US.rc
Normal file
25
rosapps/applications/cmdutils/arping/lang/en-US.rc
Normal file
@ -0,0 +1,25 @@
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_USAGE "\nUsage: arping [-t] [-n count] -s source-ip destination-host\n\n\
|
||||
Options:\n\
|
||||
-t Ping the specified host until stopped.\n\
|
||||
To stop - type Control-C.\n\
|
||||
-n count Number of probes to send.\n\
|
||||
-s Use this source IP.\n\n\0"
|
||||
IDS_BAD_OPTION_FORMAT "Bad option format %1.\n\0"
|
||||
IDS_BAD_OPTION "Bad option %1.\n\0"
|
||||
IDS_BAD_PARAMETER "Bad parameter %1.\n\0"
|
||||
IDS_DEST_MUST_BE_SPECIFIED "Name or IP address of destination host must be specified.\n\0"
|
||||
IDS_COULD_NOT_INIT_WINSOCK "Could not initialize winsock dll.\n\0"
|
||||
IDS_UNKNOWN_HOST "Unknown host %1.\n\0"
|
||||
IDS_SRC_MUST_BE_SPECIFIED "IP address of source host must be specified.\n\0"
|
||||
IDS_BAD_VALUE_OPTION_N "Bad value for option -n, valid range is from 1 to %1!u!.\n\0"
|
||||
IDS_ARPING_TO_FROM "ARPING %1 from %2\n\0"
|
||||
IDS_MS "ms\0"
|
||||
IDS_1MS "1ms\0"
|
||||
IDS_REPLY_FROM "Unicast reply from %1 [%2] %3%4\n\0"
|
||||
IDS_ARPING_STATISTICS "Sent %1!u! probes\n\
|
||||
Received %2!u! response(s)\n\0"
|
||||
END
|
16
rosapps/applications/cmdutils/arping/resource.h
Normal file
16
rosapps/applications/cmdutils/arping/resource.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#define IDS_USAGE 0
|
||||
#define IDS_BAD_OPTION_FORMAT 1
|
||||
#define IDS_BAD_OPTION 2
|
||||
#define IDS_BAD_PARAMETER 3
|
||||
#define IDS_DEST_MUST_BE_SPECIFIED 4
|
||||
#define IDS_COULD_NOT_INIT_WINSOCK 5
|
||||
#define IDS_UNKNOWN_HOST 6
|
||||
#define IDS_SRC_MUST_BE_SPECIFIED 7
|
||||
#define IDS_BAD_VALUE_OPTION_N 8
|
||||
#define IDS_ARPING_TO_FROM 9
|
||||
#define IDS_MS 10
|
||||
#define IDS_1MS 11
|
||||
#define IDS_REPLY_FROM 12
|
||||
#define IDS_ARPING_STATISTICS 13
|
Loading…
Reference in New Issue
Block a user