Isira Seneviratne : ping: Implement -l, -w, -n using IcmpSendEcho.

Alexandre Julliard julliard at winehq.org
Thu Mar 1 13:34:45 CST 2018


Module: wine
Branch: master
Commit: b1e9177c13990f7b03ac470aeb1b68eb99dc6180
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=b1e9177c13990f7b03ac470aeb1b68eb99dc6180

Author: Isira Seneviratne <isirasen96 at gmail.com>
Date:   Sat Feb 17 10:40:55 2018 +0530

ping: Implement -l, -w, -n using IcmpSendEcho.

Signed-off-by: Isira Seneviratne <isirasen96 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 programs/ping/Makefile.in |   1 +
 programs/ping/ping_main.c | 146 ++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 137 insertions(+), 10 deletions(-)

diff --git a/programs/ping/Makefile.in b/programs/ping/Makefile.in
index 0eb3a90..0f87ad0 100644
--- a/programs/ping/Makefile.in
+++ b/programs/ping/Makefile.in
@@ -1,5 +1,6 @@
 MODULE    = ping.exe
 APPMODE   = -mconsole
+IMPORTS   = ws2_32 iphlpapi
 
 C_SRCS = \
 	ping_main.c
diff --git a/programs/ping/ping_main.c b/programs/ping/ping_main.c
index 997d953..74a1c71 100644
--- a/programs/ping/ping_main.c
+++ b/programs/ping/ping_main.c
@@ -1,6 +1,8 @@
 /*
- * ping stub
+ * ping program
+ *
  * Copyright (C) 2010 Trey Hunner
+ * Copyright (C) 2018 Isira Seneviratne
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -19,9 +21,15 @@
 
 #include "config.h"
 #include "wine/port.h"
+#include "winsock2.h"
+#include "ws2tcpip.h"
+#include "iphlpapi.h"
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
+#include <icmpapi.h>
+#include <limits.h>
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
@@ -29,25 +37,42 @@
 #include <windows.h>
 
 #include "wine/debug.h"
+#include "wine/heap.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(ping);
 
 static void usage(void)
 {
-    printf("Usage: ping [-n count] [-w timeout] target_name\n\n"
+    printf("Usage: ping [-n count] [-w timeout] [-l buffer_length] target_name\n\n"
            "Options:\n"
            "    -n  Number of echo requests to send.\n"
-           "    -w  Timeout in milliseconds to wait for each reply.\n");
+           "    -w  Timeout in milliseconds to wait for each reply.\n"
+           "    -l  Length of send buffer.\n");
 }
 
 int main(int argc, char** argv)
 {
-    unsigned int n = 0;
-    int optc;
+    unsigned int n = 4, i = 0, w = 4000, l = 32;
+    int optc, res;
+    int rec = 0, lost = 0, min = INT_MAX, max = 0;
+    WSADATA wsa;
+    HANDLE icmp_file;
+    unsigned long ipaddr;
+    DWORD retval, reply_size;
+    char *send_data, ip[100], *hostname, rtt[16];
+    void *reply_buffer;
+    struct in_addr addr;
+    ICMP_ECHO_REPLY *reply;
+    float avg = 0;
+    struct hostent *remote_host;
 
-    WINE_FIXME( "this command currently just sleeps based on -n parameter\n" );
+    if (argc == 1)
+    {
+        usage();
+        exit(1);
+    }
 
-    while ((optc = getopt( argc, argv, "n:w:tal:fi:v:r:s:j:k:" )) != -1)
+    while ((optc = getopt( argc, argv, "n:w:l:tal:fi:v:r:s:j:k:" )) != -1)
     {
         switch(optc)
         {
@@ -59,18 +84,119 @@ int main(int argc, char** argv)
                   exit(1);
                 }
                 break;
+            case 'w':
+                w = atoi(optarg);
+                if (w == 0)
+                {
+                    printf("Bad value for option -w.\n");
+                    exit(1);
+                }
+                break;
+            case 'l':
+                l = atoi(optarg);
+                if (l == 0)
+                {
+                    printf("Bad value for option -l.\n");
+                    exit(1);
+                }
+                break;
             case '?':
                 usage();
                 exit(1);
             default:
                 usage();
-                WINE_FIXME( "this command currently only supports the -n parameter\n" );
+                WINE_FIXME( "this command currently only supports the -n, -w and -l parameters.\n" );
                 exit(1);
         }
     }
 
-    if (n != 0)
-      Sleep((n - 1) * 1000);
+    if (argv[optind] != NULL)
+        hostname = argv[optind];
+    else
+    {
+        printf("Pass a host name.\n");
+        return 1;
+    }
+
+    res = WSAStartup(MAKEWORD(2, 2), &wsa);
+    if (res != 0)
+    {
+        printf("WSAStartup failed: %d\n", res);
+        return 1;
+    }
+
+    remote_host = gethostbyname(hostname);
+    if (remote_host == NULL)
+    {
+        printf("Ping request could not find host %s. Please check the name and try again.\n",
+               hostname);
+        return 1;
+    }
+
+    addr.s_addr = *(u_long *) remote_host->h_addr_list[0];
+    strcpy(ip, inet_ntoa(addr));
+    ipaddr = inet_addr(ip);
+    if (ipaddr == INADDR_NONE)
+    {
+        printf("Could not get IP address of host %s.", hostname);
+        return 1;
+    }
+
+    icmp_file = IcmpCreateFile();
+
+    send_data = heap_alloc_zero(l);
+    reply_size = sizeof(ICMP_ECHO_REPLY) + l + 8;
+    /* The buffer has to hold 8 more bytes of data (the size of an ICMP error message). */
+    reply_buffer = heap_alloc(reply_size);
+    if (reply_buffer == NULL)
+    {
+        printf("Unable to allocate memory to reply buffer.\n");
+        return 1;
+    }
+
+    printf("Pinging %s [%s] with %d bytes of data:\n", hostname, ip, l);
+    for (;;)
+    {
+        retval = IcmpSendEcho(icmp_file, ipaddr, send_data, l,
+            NULL, reply_buffer, reply_size, w);
+        if (retval != 0)
+        {
+            reply = (ICMP_ECHO_REPLY *) reply_buffer;
+            if (reply->RoundTripTime >= 1)
+                sprintf(rtt, "=%d", reply->RoundTripTime);
+            else
+                strcpy(rtt, "<1");
+            printf("Reply from %s: bytes=%d time%sms TTL=%d\n", ip, l,
+                rtt, reply->Options.Ttl);
+            if (reply->RoundTripTime > max)
+                max = reply->RoundTripTime;
+            if (reply->RoundTripTime < min)
+                min = reply->RoundTripTime;
+            avg += reply->RoundTripTime;
+            rec++;
+        }
+        else
+        {
+            printf("Request timed out.\n");
+            lost++;
+        }
+        i++;
+        if (i == n)
+            break;
+        Sleep(1000);
+    }
+
+    printf("\nPing statistics for %s\n", ip);
+    printf("\tPackets: Sent = %d, Received = %d, Lost = %d (%.0f%% loss)\n",
+        n, rec, lost, (float) lost / n * 100);
+    if (rec != 0)
+    {
+        avg /= rec;
+        printf("Approximate round trip times in milli-seconds:\n");
+        printf("\tMinimum = %dms, Maximum = %dms, Average = %.0fms\n",
+               min, max, avg);
+    }
 
+    heap_free(reply_buffer);
     return 0;
 }




More information about the wine-cvs mailing list