Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/programs/ping/ping_main.c
4389 views
1
/*
2
* ping program
3
*
4
* Copyright (C) 2010 Trey Hunner
5
* Copyright (C) 2018 Isira Seneviratne
6
*
7
* This library is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public
9
* License as published by the Free Software Foundation; either
10
* version 2.1 of the License, or (at your option) any later version.
11
*
12
* This library is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
16
*
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with this library; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20
*/
21
22
#include "winsock2.h"
23
#include "ws2tcpip.h"
24
#include "iphlpapi.h"
25
26
#include <stdio.h>
27
#include <stdlib.h>
28
#include <string.h>
29
#include <icmpapi.h>
30
#include <limits.h>
31
32
#include <windows.h>
33
34
#include "wine/debug.h"
35
36
WINE_DEFAULT_DEBUG_CHANNEL(ping);
37
38
static void usage(void)
39
{
40
printf("Usage: ping [-n count] [-w timeout] [-l buffer_length] target_name\n\n"
41
"Options:\n"
42
" -n Number of echo requests to send.\n"
43
" -w Timeout in milliseconds to wait for each reply.\n"
44
" -l Length of send buffer.\n");
45
}
46
47
int __cdecl main(int argc, char** argv)
48
{
49
unsigned int n = 4, i, w = 4000, l = 32;
50
int res;
51
int rec = 0, lost = 0, min = INT_MAX, max = 0;
52
WSADATA wsa;
53
HANDLE icmp_file;
54
unsigned long ipaddr;
55
DWORD retval, reply_size;
56
char *send_data, ip[100], *hostname = NULL, rtt[16];
57
void *reply_buffer;
58
struct in_addr addr;
59
ICMP_ECHO_REPLY *reply;
60
float avg = 0;
61
struct hostent *remote_host;
62
63
if (argc == 1)
64
{
65
usage();
66
exit(1);
67
}
68
69
for (i = 1; i < argc; i++)
70
{
71
if (argv[i][0] == '-' || argv[i][0] == '/')
72
{
73
switch (argv[i][1])
74
{
75
case 'n':
76
if (i == argc - 1)
77
{
78
printf( "Missing value for option %s\n", argv[i] );
79
exit(1);
80
}
81
n = atoi(argv[++i]);
82
if (n == 0)
83
{
84
printf("Bad value for option -n, valid range is from 1 to 4294967295.\n");
85
exit(1);
86
}
87
break;
88
case 'w':
89
if (i == argc - 1)
90
{
91
printf( "Missing value for option %s\n", argv[i] );
92
exit(1);
93
}
94
w = atoi(argv[++i]);
95
if (w == 0)
96
{
97
printf("Bad value for option -w.\n");
98
exit(1);
99
}
100
break;
101
case 'l':
102
if (i == argc - 1)
103
{
104
printf( "Missing value for option %s\n", argv[i] );
105
exit(1);
106
}
107
l = atoi(argv[++i]);
108
if (l == 0)
109
{
110
printf("Bad value for option -l.\n");
111
exit(1);
112
}
113
break;
114
case '?':
115
usage();
116
exit(1);
117
default:
118
usage();
119
WINE_FIXME( "this command currently only supports the -n, -w and -l parameters.\n" );
120
exit(1);
121
}
122
}
123
else
124
{
125
if (hostname)
126
{
127
printf( "Bad argument %s\n", argv[i] );
128
exit(1);
129
}
130
hostname = argv[i];
131
}
132
}
133
134
if (!hostname)
135
{
136
printf("Pass a host name.\n");
137
return 1;
138
}
139
140
res = WSAStartup(MAKEWORD(2, 2), &wsa);
141
if (res != 0)
142
{
143
printf("WSAStartup failed: %d\n", res);
144
return 1;
145
}
146
147
remote_host = gethostbyname(hostname);
148
if (remote_host == NULL)
149
{
150
printf("Ping request could not find host %s. Please check the name and try again.\n",
151
hostname);
152
return 1;
153
}
154
155
addr.s_addr = *(u_long *) remote_host->h_addr_list[0];
156
strcpy(ip, inet_ntoa(addr));
157
ipaddr = inet_addr(ip);
158
if (ipaddr == INADDR_NONE)
159
{
160
printf("Could not get IP address of host %s.", hostname);
161
return 1;
162
}
163
164
icmp_file = IcmpCreateFile();
165
166
send_data = calloc(1, l);
167
reply_size = sizeof(ICMP_ECHO_REPLY) + l + 8;
168
/* The buffer has to hold 8 more bytes of data (the size of an ICMP error message). */
169
reply_buffer = malloc(reply_size);
170
if (reply_buffer == NULL)
171
{
172
printf("Unable to allocate memory to reply buffer.\n");
173
return 1;
174
}
175
176
printf("Pinging %s [%s] with %d bytes of data:\n", hostname, ip, l);
177
for (i = 0; i < n; i++)
178
{
179
SetLastError(0);
180
retval = IcmpSendEcho(icmp_file, ipaddr, send_data, l,
181
NULL, reply_buffer, reply_size, w);
182
if (retval != 0)
183
{
184
reply = (ICMP_ECHO_REPLY *) reply_buffer;
185
if (reply->RoundTripTime >= 1)
186
sprintf(rtt, "=%ld", reply->RoundTripTime);
187
else
188
strcpy(rtt, "<1");
189
printf("Reply from %s: bytes=%d time%sms TTL=%d\n", ip, l,
190
rtt, reply->Options.Ttl);
191
if (reply->RoundTripTime > max)
192
max = reply->RoundTripTime;
193
if (reply->RoundTripTime < min)
194
min = reply->RoundTripTime;
195
avg += reply->RoundTripTime;
196
rec++;
197
}
198
else
199
{
200
if (GetLastError() == IP_REQ_TIMED_OUT)
201
puts("Request timed out.");
202
else
203
puts("PING: transmit failed. General failure.");
204
lost++;
205
}
206
if (i < n - 1) Sleep(1000);
207
}
208
209
printf("\nPing statistics for %s\n", ip);
210
printf("\tPackets: Sent = %d, Received = %d, Lost = %d (%.0f%% loss)\n",
211
n, rec, lost, (float) lost / n * 100);
212
if (rec != 0)
213
{
214
avg /= rec;
215
printf("Approximate round trip times in milli-seconds:\n");
216
printf("\tMinimum = %dms, Maximum = %dms, Average = %.0fms\n",
217
min, max, avg);
218
}
219
220
free(reply_buffer);
221
return 0;
222
}
223
224