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