Module: wine Branch: master Commit: b1e9177c13990f7b03ac470aeb1b68eb99dc6180 URL: https://source.winehq.org/git/wine.git/?a=commit;h=b1e9177c13990f7b03ac470ae...
Author: Isira Seneviratne isirasen96@gmail.com Date: Sat Feb 17 10:40:55 2018 +0530
ping: Implement -l, -w, -n using IcmpSendEcho.
Signed-off-by: Isira Seneviratne isirasen96@gmail.com Signed-off-by: Alexandre Julliard julliard@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; }