Working implementation of the ping
Devaev Maxim
mdevaev at etersoft.ru
Thu Dec 2 13:09:39 CST 2010
The implementation uses a library icmp.dll. Non-root user in Linux can
not work with icmp, special permission is required capabilities. I made
it so that in case of error simulates the ping delay.
Sorry for my English :-)
-------------- next part --------------
From 5f8ae3aa86b4c819c848913d4e06a69b1f9888fb Mon Sep 17 00:00:00 2001
From: Devaev Maxim <mdevaev at etersoft.ru>
Date: Thu, 2 Dec 2010 21:57:25 +0300
Subject: [PATCH 1/2] Working implementation of the ping
---
programs/ping/En.rc | 43 ++++++++
programs/ping/Makefile.in | 5 +
programs/ping/ping.h | 38 +++++++
programs/ping/ping_main.c | 249 +++++++++++++++++++++++++++++++++++++++------
programs/ping/ping_rc.rc | 29 +++++
5 files changed, 332 insertions(+), 32 deletions(-)
create mode 100644 programs/ping/En.rc
create mode 100644 programs/ping/ping.h
create mode 100644 programs/ping/ping_rc.rc
diff --git a/programs/ping/En.rc b/programs/ping/En.rc
new file mode 100644
index 0000000..39ac3e0
--- /dev/null
+++ b/programs/ping/En.rc
@@ -0,0 +1,43 @@
+/*
+ * ping English strings
+ * Copyright (C) 2010 Devaev Maxim
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+
+#include "ping.h"
+#pragma code_page(65001)
+
+LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
+
+STRINGTABLE
+{
+ PING_MESSAGE_CLI_SYNTAX, "Usage: ping [-t] [-n count] [-w timeout] hostname\n"
+ PING_MESSAGE_HELP, "Usage: ping [-t] [-n count] [-w timeout] hostname\n\n\
+Arguments:\n\
+ -t Sending packets to the specified host to the interrupt command;\n\
+ -n count Count of requests;\n\
+ -w Timeout for each reply in milliseconds.\n\n"
+ PING_MESSAGE_WSASTARTUP_ERROR, "WSAStartup() error: %d\n"
+ PING_MESSAGE_BAD_WINSOCK_VERSION, "WinSock version 1.1 not supported\n"
+ PING_MESSAGE_HOST_NOT_FOUND, "%s not found\n"
+ PING_MESSAGE_PINGING_HOST, "Pinging %s [%s]:\n"
+ PING_MESSAGE_ICMP_CREATE_FILE_ERROR, "IcmpCreateFile() error: %d\n"
+ PING_MESSAGE_HOST_REPLY, "Reply from %s: time=%ldms TTL=%d\n"
+ PING_MESSAGE_ICMP_ECHO_ERROR, "Error: icmp_echo.Status=%ld\n"
+ PING_MESSAGE_NEW_LINE, "\n"
+}
+
diff --git a/programs/ping/Makefile.in b/programs/ping/Makefile.in
index fea6c50..e98e306 100644
--- a/programs/ping/Makefile.in
+++ b/programs/ping/Makefile.in
@@ -1,8 +1,13 @@
EXTRADEFS = -DWINE_NO_UNICODE_MACROS
MODULE = ping.exe
APPMODE = -mconsole
+IMPORTS = advapi32 wsock32 kernel32 user32 iphlpapi
+#DELAYIMPORTS = user32
C_SRCS = \
ping_main.c
+RC_SRCS = \
+ ping_rc.rc
+
@MAKE_PROG_RULES@
diff --git a/programs/ping/ping.h b/programs/ping/ping.h
new file mode 100644
index 0000000..c86fef6
--- /dev/null
+++ b/programs/ping/ping.h
@@ -0,0 +1,38 @@
+/*
+ * ping costants
+ * Copyright (C) 2010 Devaev Maxim
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+
+#ifndef PING_H
+# define PING_H
+
+# define PING_MESSAGE_CLI_SYNTAX 1000
+# define PING_MESSAGE_HELP 1001
+# define PING_MESSAGE_WSASTARTUP_ERROR 1002
+# define PING_MESSAGE_BAD_WINSOCK_VERSION 1003
+# define PING_MESSAGE_HOST_NOT_FOUND 1004
+# define PING_MESSAGE_PINGING_HOST 1005
+# define PING_MESSAGE_ICMP_CREATE_FILE_ERROR 1006
+# define PING_MESSAGE_HOST_REPLY 1007
+# define PING_MESSAGE_ICMP_ECHO_ERROR 1008
+# define PING_MESSAGE_NEW_LINE 1009
+
+# define MAXSTRING 8192
+
+#endif // PING_H
+
diff --git a/programs/ping/ping_main.c b/programs/ping/ping_main.c
index 037fa4d..a3fd4a5 100644
--- a/programs/ping/ping_main.c
+++ b/programs/ping/ping_main.c
@@ -2,6 +2,9 @@
* ping stub
* Copyright (C) 2010 Trey Hunner
*
+ * ping
+ * Copyright (C) 2010 Devaev Maxim
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@@ -17,53 +20,235 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#include <unistd.h>
+
+#include <string.h>
#include <stdio.h>
+#include <stdlib.h>
#include <windows.h>
+#include <winsock.h>
+#include <ipexport.h>
+#include <icmpapi.h>
+#include "wine/unicode.h"
#include "wine/debug.h"
+#include "ping.h"
+
+
+#define WINSOCK_VERSION 0x0101
+
+#define DEFAULT_REQUEST_COUNT 4
+#define DEFAULT_ICMP_TTL 255
+#define DEFAULT_ICMP_TIMEOUT 5000
+
+
+#define PING_DELAY_STUB
+
WINE_DEFAULT_DEBUG_CHANNEL(ping);
-static void usage(void)
+
+static WCHAR *PING_LoadMessage(UINT id)
{
- printf("Usage: ping [-n count] [-w timeout] target_name\n\n"
- "Options:\n"
- " -n Number of echo requests to send.\n"
- " -w Timeout in milliseconds to wait for each reply.\n");
+ static const WCHAR failedStrW[] = {'L','o','a','d','M','e','s','s','a','g','e','(',')',' ',
+ 'f','a','i','l','e','d',':',' ','%','d',0};
+ static WCHAR strW[MAXSTRING];
+
+
+ if ( !LoadStringW(GetModuleHandleW(NULL), id, strW, sizeof(strW) / sizeof(WCHAR)) ) {
+ WINE_FIXME("LoadStringW() failed: %d\n", GetLastError());
+ lstrcpyW(strW, failedStrW);
+ }
+ return strW;
}
-int main(int argc, char** argv)
+static WCHAR *PING_GetWideString(const char* strA)
{
- unsigned int n = 0;
- int optc;
-
- WINE_FIXME( "this command currently just sleeps based on -n parameter\n" );
-
- while ((optc = getopt( argc, argv, "n:w:tal:fi:v:r:s:j:k:" )) != -1)
- {
- switch(optc)
- {
- case 'n':
- n = atoi(optarg);
- if (n == 0)
- {
- printf("Bad value for option -n, valid range is from 1 to 4294967295.\n");
- exit(1);
+ WCHAR *strW;
+ int strW_len;
+
+
+ strW_len = MultiByteToWideChar(CP_ACP, 0, strA, -1, NULL, 0);
+ if ( (strW = HeapAlloc(GetProcessHeap(), 0, strW_len * sizeof(WCHAR))) == NULL ) {
+ WINE_FIXME("HeapAlloc() failed: %d\n", GetLastError());
+ return NULL;
+ }
+ MultiByteToWideChar(CP_ACP, 0, strA, -1, strW, strW_len);
+ return strW;
+}
+
+static int PING_printfW(const WCHAR *strW, ...)
+{
+ va_list va_args;
+ WCHAR bufW[MAXSTRING];
+ char *strA;
+ int bufW_len;
+ int strA_len;
+ int ret_count;
+
+
+ va_start(va_args, strW);
+ vsprintfW(bufW, strW, va_args);
+ va_end(va_args);
+
+ bufW_len = lstrlenW(bufW);
+ if ( !WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), bufW, (DWORD)bufW_len, (DWORD *)&ret_count, NULL) ) {
+ strA_len = WideCharToMultiByte(GetConsoleOutputCP(), 0, bufW, bufW_len, NULL, 0, NULL, NULL);
+ if ( (strA = HeapAlloc(GetProcessHeap(), 0, strA_len * sizeof(char))) == NULL ) {
+ WINE_FIXME("HeapAlloc() failed: %d\n", GetLastError());
+ return 0;
+ }
+
+ WideCharToMultiByte(GetConsoleOutputCP(), 0, bufW, bufW_len, strA, strA_len, NULL, NULL);
+ WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), strA, strA_len, (DWORD *)&ret_count, FALSE);
+ HeapFree(GetProcessHeap(), 0, strA);
+ }
+
+ return ret_count;
+}
+
+
+int main(int argc, char **argv)
+{
+ WSADATA wsa_data;
+ IN_ADDR dest_addr;
+ HOSTENT *dest_host;
+ IP_OPTION_INFORMATION ip_info;
+ HANDLE icmp_file_handle;
+ ICMP_ECHO_REPLY icmp_echo_reply;
+
+ WCHAR *strW1, *strW2;
+
+ int request_count = DEFAULT_REQUEST_COUNT;
+ int icmp_ttl = DEFAULT_ICMP_TTL;
+ int icmp_timeout = DEFAULT_ICMP_TIMEOUT;
+
+ int argc_count;
+
+
+ if ( argc < 2 ) {
+ PING_printfW(PING_LoadMessage(PING_MESSAGE_CLI_SYNTAX));
+ return 1;
+ }
+ for (argc_count = 1; argc_count < argc; ++argc_count) {
+ if ( strlen(argv[argc_count]) != 2 || (argv[argc_count][0] != '/' && argv[argc_count][0] != '-') )
+ continue;
+
+ switch ( argv[argc_count][1] ) {
+ case '?' :
+ case 'h' : {
+ PING_printfW(PING_LoadMessage(PING_MESSAGE_HELP));
+ return 0;
+ }
+
+ case 't' : {
+ request_count = -1;
+ continue;
+ }
+
+ case 'n' : {
+ if ( argc_count + 1 <= argc && (request_count = atoi(argv[argc_count +1])) > 0 ) {
+ ++argc_count;
+ continue;
+ }
+ else {
+ PING_printfW(PING_LoadMessage(PING_MESSAGE_CLI_SYNTAX));
+ return 1;
+ }
+ }
+
+ case 'w' : {
+ if ( argc_count + 1 <= argc && (icmp_timeout = atoi(argv[argc_count +1])) > 0 ) {
+ ++argc_count;
+ continue;
}
- break;
- case '?':
- usage();
- exit(1);
- default:
- usage();
- WINE_FIXME( "this command currently only supports the -n parameter\n" );
- exit(1);
+ else {
+ PING_printfW(PING_LoadMessage(PING_MESSAGE_CLI_SYNTAX));
+ return 1;
+ }
+ }
+
+ default : {
+ PING_printfW(PING_LoadMessage(PING_MESSAGE_CLI_SYNTAX));
+ return 1;
+ }
+ }
+ }
+
+
+ if ( WSAStartup(WINSOCK_VERSION, &wsa_data) ) {
+ PING_printfW(PING_LoadMessage(PING_MESSAGE_WSASTARTUP_ERROR), WSAGetLastError());
+ return 1;
+ }
+ if ( wsa_data.wVersion != WINSOCK_VERSION ) {
+ PING_printfW(PING_LoadMessage(PING_MESSAGE_BAD_WINSOCK_VERSION));
+ WSACleanup();
+ return 1;
+ }
+
+ dest_addr.s_addr = inet_addr(argv[argc -1]);
+ if ( dest_addr.s_addr == INADDR_NONE )
+ dest_host = gethostbyname(argv[argc -1]);
+ else
+ dest_host = gethostbyaddr((char *)&dest_addr, sizeof(IN_ADDR), AF_INET);
+
+ if ( dest_host == NULL ) {
+ if ( (strW1 = PING_GetWideString(argv[1])) != NULL ) {
+ PING_printfW(PING_LoadMessage(PING_MESSAGE_HOST_NOT_FOUND), strW1);
+ HeapFree(GetProcessHeap(), 0, strW1);
+ }
+ WSACleanup();
+ return 1;
+ }
+
+
+ if ( (strW1 = PING_GetWideString(dest_host->h_name)) != NULL ) {
+ if ( (strW2 = PING_GetWideString( inet_ntoa(*(IN_ADDR *)dest_host->h_addr_list[0]) )) != NULL ) {
+ PING_printfW(PING_LoadMessage(PING_MESSAGE_PINGING_HOST), strW1, strW2);
+ HeapFree(GetProcessHeap(), 0, strW2);
+ }
+ HeapFree(GetProcessHeap(), 0, strW1);
+ }
+
+ if ( (icmp_file_handle = IcmpCreateFile()) == INVALID_HANDLE_VALUE ) {
+ PING_printfW(PING_LoadMessage(PING_MESSAGE_ICMP_CREATE_FILE_ERROR), GetLastError());
+ WSACleanup();
+#ifdef PING_DELAY_STUB
+ WINE_FIXME("IcmpCreateFile() not work, using delay stub");
+ Sleep(request_count * 1000);
+ return 0;
+#else
+ return 1;
+#endif
+ }
+ while ( request_count-- ) {
+ if ( request_count < 0 )
+ ++request_count;
+
+ ip_info.Ttl = icmp_ttl;
+ ip_info.Tos = 0;
+ ip_info.Flags = 0;
+ ip_info.OptionsSize = 0;
+ ip_info.OptionsData = NULL;
+
+ IcmpSendEcho(icmp_file_handle, *(DWORD *)(*dest_host->h_addr_list), NULL, 0, &ip_info, &icmp_echo_reply,
+ sizeof(ICMP_ECHO_REPLY), icmp_timeout);
+
+ if ( (strW1 = PING_GetWideString(inet_ntoa(dest_addr))) != NULL ) {
+ PING_printfW(PING_LoadMessage(PING_MESSAGE_HOST_REPLY), strW1,
+ icmp_echo_reply.RoundTripTime, icmp_echo_reply.Options.Ttl);
+ HeapFree(GetProcessHeap(), 0, strW1);
+ }
+ if ( icmp_echo_reply.Status ) {
+ PING_printfW(PING_LoadMessage(PING_MESSAGE_ICMP_ECHO_ERROR), icmp_echo_reply.Status);
+ break;
}
}
- if (n != 0)
- Sleep((n - 1) * 1000);
+ PING_printfW(PING_LoadMessage(PING_MESSAGE_NEW_LINE));
+
+ IcmpCloseHandle(icmp_file_handle);
+ WSACleanup();
return 0;
}
+
diff --git a/programs/ping/ping_rc.rc b/programs/ping/ping_rc.rc
new file mode 100644
index 0000000..85f769f
--- /dev/null
+++ b/programs/ping/ping_rc.rc
@@ -0,0 +1,29 @@
+/*
+ * ping resources
+ * Copyright (C) 2010 Devaev Maxim
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+
+#include <windef.h>
+#include <winuser.h>
+
+#include "ping.h"
+
+#include "En.rc"
+
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+
--
1.7.3.2
More information about the wine-patches
mailing list