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