Author: pschweitzer Date: Sun Nov 29 19:44:29 2015 New Revision: 70212
URL: http://svn.reactos.org/svn/reactos?rev=70212&view=rev Log: [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.
Added: trunk/rosapps/applications/cmdutils/arping/ trunk/rosapps/applications/cmdutils/arping/CMakeLists.txt (with props) trunk/rosapps/applications/cmdutils/arping/arping.c (with props) trunk/rosapps/applications/cmdutils/arping/arping.rc (with props) trunk/rosapps/applications/cmdutils/arping/lang/ trunk/rosapps/applications/cmdutils/arping/lang/en-US.rc (with props) trunk/rosapps/applications/cmdutils/arping/resource.h (with props) Modified: trunk/rosapps/applications/cmdutils/CMakeLists.txt
Modified: trunk/rosapps/applications/cmdutils/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/rosapps/applications/cmdutils/CMake... ============================================================================== --- trunk/rosapps/applications/cmdutils/CMakeLists.txt [iso-8859-1] (original) +++ trunk/rosapps/applications/cmdutils/CMakeLists.txt [iso-8859-1] Sun Nov 29 19:44:29 2015 @@ -1,4 +1,5 @@ add_subdirectory(appwiz) +add_subdirectory(arping) add_subdirectory(cat) add_subdirectory(hackssign) add_subdirectory(ntfsinfo)
Added: trunk/rosapps/applications/cmdutils/arping/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/rosapps/applications/cmdutils/arpin... ============================================================================== --- trunk/rosapps/applications/cmdutils/arping/CMakeLists.txt (added) +++ trunk/rosapps/applications/cmdutils/arping/CMakeLists.txt [iso-8859-1] Sun Nov 29 19:44:29 2015 @@ -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)
Propchange: trunk/rosapps/applications/cmdutils/arping/CMakeLists.txt ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/rosapps/applications/cmdutils/arping/arping.c URL: http://svn.reactos.org/svn/reactos/trunk/rosapps/applications/cmdutils/arpin... ============================================================================== --- trunk/rosapps/applications/cmdutils/arping/arping.c (added) +++ trunk/rosapps/applications/cmdutils/arping/arping.c [iso-8859-1] Sun Nov 29 19:44:29 2015 @@ -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; +}
Propchange: trunk/rosapps/applications/cmdutils/arping/arping.c ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/rosapps/applications/cmdutils/arping/arping.rc URL: http://svn.reactos.org/svn/reactos/trunk/rosapps/applications/cmdutils/arpin... ============================================================================== --- trunk/rosapps/applications/cmdutils/arping/arping.rc (added) +++ trunk/rosapps/applications/cmdutils/arping/arping.rc [iso-8859-1] Sun Nov 29 19:44:29 2015 @@ -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
Propchange: trunk/rosapps/applications/cmdutils/arping/arping.rc ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/rosapps/applications/cmdutils/arping/lang/en-US.rc URL: http://svn.reactos.org/svn/reactos/trunk/rosapps/applications/cmdutils/arpin... ============================================================================== --- trunk/rosapps/applications/cmdutils/arping/lang/en-US.rc (added) +++ trunk/rosapps/applications/cmdutils/arping/lang/en-US.rc [iso-8859-1] Sun Nov 29 19:44:29 2015 @@ -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
Propchange: trunk/rosapps/applications/cmdutils/arping/lang/en-US.rc ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/rosapps/applications/cmdutils/arping/resource.h URL: http://svn.reactos.org/svn/reactos/trunk/rosapps/applications/cmdutils/arpin... ============================================================================== --- trunk/rosapps/applications/cmdutils/arping/resource.h (added) +++ trunk/rosapps/applications/cmdutils/arping/resource.h [iso-8859-1] Sun Nov 29 19:44:29 2015 @@ -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
Propchange: trunk/rosapps/applications/cmdutils/arping/resource.h ------------------------------------------------------------------------------ svn:eol-style = native