1
#include "ping_common.h"
14
int mx_dup_ck = MAX_DUP_CHK;
15
char rcvd_tbl[MAX_DUP_CHK / 8];
19
long npackets; /* max packets to transmit */
20
long nreceived; /* # of packets we got back */
21
long nrepeats; /* number of duplicates */
22
long ntransmitted; /* sequence # for outbound packets = #sent */
23
long nchecksum; /* replies with bad checksum */
24
long nerrors; /* icmp errors */
25
int interval = 1000; /* interval between packets (msec) */
27
int deadline = 0; /* time to die */
28
struct timeval start_time, cur_time;
30
volatile int status_snapshot;
33
/* Stupid workarounds for bugs/missing functionality in older linuces.
34
* confirm_flag fixes refusing service of kernels without MSG_CONFIRM.
35
* i.e. for linux-2.2 */
36
int confirm_flag = MSG_CONFIRM;
37
/* And this is workaround for bug in IP_RECVERR on raw sockets which is present
38
* in linux-2.2.[0-19], linux-2.4.[0-7] */
42
int timing; /* flag to do timing */
43
long tmin = LONG_MAX; /* minimum round trip time */
44
long tmax; /* maximum round trip time */
45
long long tsum; /* sum of all times, for doing average */
49
int datalen = DEFDATALEN;
53
int ident; /* process id to identify our packets */
55
static int screen_width = INT_MAX;
57
/* Fills all the outpack, excluding ICMP header, but _including_
58
* timestamp area with supplied pattern.
60
static void fill(char *patp)
67
for (cp = patp; *cp; cp++) {
70
"ping: patterns must be specified as hex digits.\n");
75
"%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
76
&pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6],
77
&pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12],
78
&pat[13], &pat[14], &pat[15]);
81
for (kk = 0; kk <= maxpacket - (8 + ii); kk += ii)
82
for (jj = 0; jj < ii; ++jj)
83
bp[jj + kk] = pat[jj];
85
if (!(options & F_QUIET)) {
86
printf("PATTERN: 0x");
87
for (jj = 0; jj < ii; ++jj)
88
printf("%02x", bp[jj] & 0xFF);
93
void common_options(int ch)
100
options |= F_ADAPTIVE;
103
npackets = atoi(optarg);
105
fprintf(stderr, "ping: bad number of packets to transmit.\n");
110
options |= F_SO_DEBUG;
114
setbuf(stdout, (char *)NULL);
116
case 'i': /* wait between sending packets */
118
if (strchr(optarg, '.')) {
120
if (sscanf(optarg, "%f", &t) != 1) {
121
fprintf(stderr, "ping: bad timing interval.\n");
124
interval = (int)(t*1000);
125
} else if (sscanf(optarg, "%d", &interval) == 1) {
128
fprintf(stderr, "ping: bad timing interval.\n");
133
fprintf(stderr, "ping: bad timing interval.\n");
136
options |= F_INTERVAL;
140
deadline = atoi(optarg);
142
fprintf(stderr, "ping: bad wait time.\n");
147
preload = atoi(optarg);
148
if (preload <= 0 || preload>mx_dup_ck) {
149
fprintf(stderr, "ping: bad preload value, should be 1..%d\n", mx_dup_ck);
152
if (uid && preload>3) {
153
fprintf(stderr, "ping: cannot set preload to value > 3\n");
158
sndbuf = atoi(optarg);
160
fprintf(stderr, "ping: bad sndbuf value.\n");
165
options |= F_NUMERIC;
167
case 'p': /* fill buffer with user pattern */
168
options |= F_PINGFILLED;
175
options |= F_SO_DONTROUTE;
177
case 's': /* size of packet to send */
178
datalen = atoi(optarg);
180
fprintf(stderr, "ping: illegal negative packet size %d.\n", datalen);
185
options |= F_VERBOSE;
188
moptions |= MULTICAST_NOLOOP;
192
moptions |= MULTICAST_TTL;
194
if (ttl < 0 || ttl > 255) {
195
fprintf(stderr, "ping: ttl %u out of range\n", ttl);
200
options |= F_LATENCY;
203
printf("ping utility, iputils-ss%s\n", SNAPSHOT);
211
static void sigexit(int signo)
216
static void sigstatus(int signo)
222
int __schedule_exit(int next)
224
unsigned long waittime;
229
if (waittime<1000000)
232
waittime = MAXWAIT*1000000;
234
if (next<0 || next < waittime/1000)
235
next = waittime/1000;
237
it.it_interval.tv_sec = 0;
238
it.it_interval.tv_usec = 0;
239
it.it_value.tv_sec = waittime/1000000;
240
it.it_value.tv_usec = waittime%1000000;
241
setitimer(ITIMER_REAL, &it, NULL);
245
static inline void update_interval(void)
247
int est = rtt ? rtt/8 : interval*1000;
249
interval = (est+rtt_addend+500)/1000;
250
if (uid && interval < MINUSERINTERVAL)
251
interval = MINUSERINTERVAL;
256
* Compose and transmit an ICMP ECHO REQUEST packet. The IP packet
257
* will be added on by the kernel. The ID field is our UNIX process ID,
258
* and the sequence number is an ascending integer. The first 8 bytes
259
* of the data portion are used to hold a UNIX "timeval" struct in VAX
260
* byte-order, to compute the round-trip time.
267
/* Have we already sent enough? If we have, return an arbitrary positive value. */
268
if (exiting || (npackets && ntransmitted >= npackets && !deadline))
271
/* Check that packets < rate*time + preload */
272
if (cur_time.tv_sec == 0) {
273
gettimeofday(&cur_time, NULL);
274
tokens = interval*(preload-1);
279
gettimeofday(&tv, NULL);
280
ntokens = (tv.tv_sec - cur_time.tv_sec)*1000 +
281
(tv.tv_usec-cur_time.tv_usec)/1000;
283
/* Case of unlimited flood is special;
284
* if we see no reply, they are limited to 100pps */
285
if (ntokens < MININTERVAL && in_flight() >= preload)
286
return MININTERVAL-ntokens;
289
if (ntokens > interval*preload)
290
ntokens = interval*preload;
291
if (ntokens < interval)
292
return interval - ntokens;
295
tokens = ntokens - interval;
302
advance_ntransmitted();
303
if (!(options & F_QUIET) && (options & F_FLOOD)) {
304
/* Very silly, but without this output with
305
* high preload or pipe size is very confusing. */
306
if ((preload < screen_width && pipesize < screen_width) ||
307
in_flight() < screen_width)
308
write(STDOUT_FILENO, ".", 1);
310
return interval - tokens;
313
/* And handle various errors... */
315
/* Apparently, it is some fatal bug. */
317
} else if (errno == ENOBUFS || errno == ENOMEM) {
318
/* Device queue overflow or OOM. Packet is not sent. */
320
/* Slowdown. This works only in adaptive mode (option -A) */
321
rtt_addend += (rtt < 8*50000 ? rtt/8 : 50000);
322
if (options&F_ADAPTIVE)
324
return SCHINT(interval);
325
} else if (errno == EAGAIN) {
326
/* Socket buffer is full. */
330
if ((i=receive_error_msg()) > 0) {
331
/* An ICMP error arrived. */
335
/* Compatibility with old linuces. */
336
if (i == 0 && confirm_flag && errno == EINVAL) {
343
/* Hard local error. Pretend we sent packet. */
344
advance_ntransmitted();
346
if (i == 0 && !(options & F_QUIET)) {
347
if (options & F_FLOOD)
348
write(STDOUT_FILENO, "E", 1);
350
perror("ping: sendmsg");
353
return SCHINT(interval);
357
/* Set socket buffers, "alloc" is an esimate of memory taken by single packet. */
359
void sock_setbufs(int icmp_sock, int alloc)
362
int tmplen = sizeof(hold);
366
setsockopt(icmp_sock, SOL_SOCKET, SO_SNDBUF, (char *)&sndbuf, sizeof(sndbuf));
368
rcvbuf = hold = alloc * preload;
371
setsockopt(icmp_sock, SOL_SOCKET, SO_RCVBUF, (char *)&hold, sizeof(hold));
372
if (getsockopt(icmp_sock, SOL_SOCKET, SO_RCVBUF, (char *)&hold, &tmplen) == 0) {
374
fprintf(stderr, "WARNING: probably, rcvbuf is not enough to hold preload.\n");
378
/* Protocol independent setup and parameter checks. */
380
void setup(int icmp_sock)
385
if ((options & F_FLOOD) && !(options & F_INTERVAL))
388
if (uid && interval < MINUSERINTERVAL) {
389
fprintf(stderr, "ping: cannot flood; minimal interval, allowed for user, is %dms\n", MINUSERINTERVAL);
393
if (interval >= INT_MAX/preload) {
394
fprintf(stderr, "ping: illegal preload and/or interval\n");
399
if (options & F_SO_DEBUG)
400
setsockopt(icmp_sock, SOL_SOCKET, SO_DEBUG, (char *)&hold, sizeof(hold));
401
if (options & F_SO_DONTROUTE)
402
setsockopt(icmp_sock, SOL_SOCKET, SO_DONTROUTE, (char *)&hold, sizeof(hold));
405
if (!(options&F_LATENCY)) {
407
if (setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)))
408
fprintf(stderr, "Warning: no SO_TIMESTAMP support, falling back to SIOCGSTAMP\n");
412
/* Set some SNDTIMEO to prevent blocking forever
413
* on sends, when device is too slow or stalls. Just put limit
414
* of one second, or "interval", if it is less.
418
if (interval < 1000) {
420
tv.tv_usec = 1000 * SCHINT(interval);
422
setsockopt(icmp_sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(tv));
424
/* Set RCVTIMEO to "interval". Note, it is just an optimization
425
* allowing to avoid redundant poll(). */
426
tv.tv_sec = SCHINT(interval)/1000;
427
tv.tv_usec = 1000*(SCHINT(interval)%1000);
428
if (setsockopt(icmp_sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(tv)))
429
options |= F_FLOOD_POLL;
431
if (!(options & F_PINGFILLED)) {
435
/* Do not forget about case of small datalen,
436
* fill timestamp area too!
438
for (i = 0; i < datalen; ++i)
442
ident = getpid() & 0xFFFF;
444
set_signal(SIGINT, sigexit);
445
set_signal(SIGALRM, sigexit);
446
set_signal(SIGQUIT, sigstatus);
448
gettimeofday(&start_time, NULL);
453
it.it_interval.tv_sec = 0;
454
it.it_interval.tv_usec = 0;
455
it.it_value.tv_sec = deadline;
456
it.it_value.tv_usec = 0;
457
setitimer(ITIMER_REAL, &it, NULL);
460
if (isatty(STDOUT_FILENO)) {
463
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1) {
465
screen_width = w.ws_col;
470
void main_loop(int icmp_sock, __u8 *packet, int packlen)
481
iov.iov_base = (char *)packet;
484
/* Check exit conditions. */
487
if (npackets && nreceived >= npackets)
489
if (deadline && nerrors)
491
/* Check for and do special actions. */
495
/* Send probes scheduled to this time. */
498
next = schedule_exit(next);
501
/* "next" is time to send next probe, if positive.
502
* If next<=0 send now or as soon as possible. */
504
/* Technical part. Looks wicked. Could be dropped,
505
* if everyone used the newest kernel. :-)
507
* 1. Provide intervals less than resolution of scheduler.
508
* Solution: spinning.
509
* 2. Avoid use of poll(), when recvmsg() can provide
510
* timed waiting (SO_RCVTIMEO). */
512
if ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || next<SCHINT(interval)) {
513
int recv_expected = in_flight();
515
/* If we are here, recvmsg() is unable to wait for
516
* required timeout. */
517
if (1000*next <= 1000000/(int)HZ) {
518
/* Very short timeout... So, if we wait for
519
* something, we sleep for MININTERVAL.
520
* Otherwise, spin! */
525
/* When spinning, no reasons to poll.
526
* Use nonblocking recvmsg() instead. */
527
polling = MSG_DONTWAIT;
534
((options & (F_ADAPTIVE|F_FLOOD_POLL)) || interval)) {
537
pset.events = POLLIN|POLLERR;
539
if (poll(&pset, 1, next) < 1 ||
540
!(pset.revents&(POLLIN|POLLERR)))
542
polling = MSG_DONTWAIT;
547
struct timeval *recv_timep = NULL;
548
struct timeval recv_time;
549
int not_ours = 0; /* Raw socket can receive messages
550
* destined to other running pings. */
552
iov.iov_len = packlen;
553
msg.msg_name = addrbuf;
554
msg.msg_namelen = sizeof(addrbuf);
557
msg.msg_control = ans_data;
558
msg.msg_controllen = sizeof(ans_data);
560
cc = recvmsg(icmp_sock, &msg, polling);
561
polling = MSG_DONTWAIT;
564
if (errno == EAGAIN || errno == EINTR)
566
if (!receive_error_msg()) {
568
perror("ping: recvmsg");
576
for (c = CMSG_FIRSTHDR(&msg); c; c = CMSG_NXTHDR(&msg, c)) {
577
if (c->cmsg_level != SOL_SOCKET ||
578
c->cmsg_type != SO_TIMESTAMP)
580
if (c->cmsg_len < CMSG_LEN(sizeof(struct timeval)))
582
recv_timep = (struct timeval*)CMSG_DATA(c);
586
if ((options&F_LATENCY) || recv_timep == NULL) {
587
if ((options&F_LATENCY) ||
588
ioctl(icmp_sock, SIOCGSTAMP, &recv_time))
589
gettimeofday(&recv_time, NULL);
590
recv_timep = &recv_time;
593
not_ours = parse_reply(&msg, cc, addrbuf, recv_timep);
596
/* See? ... someone runs another ping on this host. */
600
/* If nothing is in flight, "break" returns us to pinger. */
601
if (in_flight() == 0)
604
/* Otherwise, try to recvmsg() again. recvmsg()
605
* is nonblocking after the first iteration, so that
606
* if nothing is queued, it will receive EAGAIN
607
* and return to pinger. */
613
int gather_statistics(__u8 *ptr, int cc, __u16 seq, int hops,
614
int csfailed, struct timeval *tv, char *from)
623
if (timing && cc >= 8+sizeof(struct timeval)) {
624
struct timeval tmp_tv;
625
memcpy(&tmp_tv, ptr, sizeof(tmp_tv));
629
triptime = tv->tv_sec * 1000000 + tv->tv_usec;
631
fprintf(stderr, "Warning: time of day goes back (%ldus), taking countermeasures.\n", triptime);
633
if (!(options & F_LATENCY)) {
634
gettimeofday(tv, NULL);
635
options |= F_LATENCY;
641
tsum2 += (long long)triptime * (long long)triptime;
649
rtt += triptime-rtt/8;
650
if (options&F_ADAPTIVE)
658
} else if (TST(seq % mx_dup_ck)) {
663
SET(seq % mx_dup_ck);
666
confirm = confirm_flag;
668
if (options & F_QUIET)
671
if (options & F_FLOOD) {
673
write(STDOUT_FILENO, "\b \b", 3);
675
write(STDOUT_FILENO, "\bC", 1);
679
printf("%d bytes from %s: icmp_seq=%u", cc, from, seq);
682
printf(" ttl=%d", hops);
684
if (cc < datalen+8) {
685
printf(" (truncated)\n");
689
if (triptime >= 100000)
690
printf(" time=%ld ms", triptime/1000);
691
else if (triptime >= 10000)
692
printf(" time=%ld.%01ld ms", triptime/1000,
693
(triptime%1000)/100);
694
else if (triptime >= 1000)
695
printf(" time=%ld.%02ld ms", triptime/1000,
698
printf(" time=%ld.%03ld ms", triptime/1000,
704
printf(" (BAD CHECKSUM!)");
707
cp = ((u_char*)ptr) + sizeof(struct timeval);
708
dp = &outpack[8 + sizeof(struct timeval)];
709
for (i = sizeof(struct timeval); i < datalen; ++i, ++cp, ++dp) {
711
printf("\nwrong data byte #%d should be 0x%x but was 0x%x",
713
cp = (u_char*)ptr + sizeof(struct timeval);
714
for (i = sizeof(struct timeval); i < datalen; ++i, ++cp) {
715
if ((i % 32) == sizeof(struct timeval))
716
printf("\n#%d\t", i);
726
static long llsqrt(long long a)
728
long long prev = ~((long long)1 << 63);
743
* Print out statistics, and give up.
747
struct timeval tv = cur_time;
749
tvsub(&tv, &start_time);
753
printf("--- %s ping statistics ---\n", hostname);
754
printf("%ld packets transmitted, ", ntransmitted);
755
printf("%ld received", nreceived);
757
printf(", +%ld duplicates", nrepeats);
759
printf(", +%ld corrupted", nchecksum);
761
printf(", +%ld errors", nerrors);
763
printf(", %d%% loss",
764
(int) ((((long long)(ntransmitted - nreceived)) * 100) /
766
printf(", time %ldms", 1000*tv.tv_sec+tv.tv_usec/1000);
770
if (nreceived && timing) {
773
tsum /= nreceived + nrepeats;
774
tsum2 /= nreceived + nrepeats;
775
tmdev = llsqrt(tsum2 - tsum * tsum);
777
printf("rtt min/avg/max/mdev = %ld.%03ld/%lu.%03ld/%ld.%03ld/%ld.%03ld ms",
778
tmin/1000, tmin%1000,
779
(unsigned long)(tsum/1000), (long)(tsum%1000),
780
tmax/1000, tmax%1000,
781
tmdev/1000, tmdev%1000
785
printf(", pipe %d", pipesize);
786
if (ntransmitted > 1 && (!interval || (options&(F_FLOOD|F_ADAPTIVE)))) {
787
int ipg = (1000000*(long long)tv.tv_sec+tv.tv_usec)/(ntransmitted-1);
788
printf(", ipg/ewma %d.%03d/%d.%03d ms",
789
ipg/1000, ipg%1000, rtt/8000, (rtt/8)%1000);
792
exit(deadline ? nreceived<npackets : nreceived==0);
804
loss = (((long long)(ntransmitted - nreceived)) * 100) / ntransmitted;
806
fprintf(stderr, "\r%ld/%ld packets, %d%% loss", ntransmitted, nreceived, loss);
808
if (nreceived && timing) {
809
tavg = tsum / (nreceived + nrepeats);
811
fprintf(stderr, ", min/avg/ewma/max = %ld.%03ld/%lu.%03ld/%d.%03d/%ld.%03ld ms",
812
tmin/1000, tmin%1000,
813
tavg/1000, tavg%1000,
814
rtt/8000, (rtt/8)%1000,
818
fprintf(stderr, "\n");