ping: Implement -l, -w, -n using IcmpSendEcho.
Signed-off-by: Isira Seneviratne <isirasen96@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
e9b3ccaca3
commit
b1e9177c13
|
@ -1,5 +1,6 @@
|
||||||
MODULE = ping.exe
|
MODULE = ping.exe
|
||||||
APPMODE = -mconsole
|
APPMODE = -mconsole
|
||||||
|
IMPORTS = ws2_32 iphlpapi
|
||||||
|
|
||||||
C_SRCS = \
|
C_SRCS = \
|
||||||
ping_main.c
|
ping_main.c
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* ping stub
|
* ping program
|
||||||
|
*
|
||||||
* Copyright (C) 2010 Trey Hunner
|
* Copyright (C) 2010 Trey Hunner
|
||||||
|
* Copyright (C) 2018 Isira Seneviratne
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
@ -19,9 +21,15 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "wine/port.h"
|
#include "wine/port.h"
|
||||||
|
#include "winsock2.h"
|
||||||
|
#include "ws2tcpip.h"
|
||||||
|
#include "iphlpapi.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <icmpapi.h>
|
||||||
|
#include <limits.h>
|
||||||
#ifdef HAVE_UNISTD_H
|
#ifdef HAVE_UNISTD_H
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -29,25 +37,42 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
#include "wine/heap.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(ping);
|
WINE_DEFAULT_DEBUG_CHANNEL(ping);
|
||||||
|
|
||||||
static void usage(void)
|
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"
|
"Options:\n"
|
||||||
" -n Number of echo requests to send.\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)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
unsigned int n = 0;
|
unsigned int n = 4, i = 0, w = 4000, l = 32;
|
||||||
int optc;
|
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)
|
switch(optc)
|
||||||
{
|
{
|
||||||
|
@ -59,18 +84,119 @@ int main(int argc, char** argv)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
break;
|
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 '?':
|
case '?':
|
||||||
usage();
|
usage();
|
||||||
exit(1);
|
exit(1);
|
||||||
default:
|
default:
|
||||||
usage();
|
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);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n != 0)
|
if (argv[optind] != NULL)
|
||||||
Sleep((n - 1) * 1000);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue