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 int lingertime = MAXWAIT*1000;
29 struct timeval start_time, cur_time;
31 volatile int status_snapshot;
34 /* Stupid workarounds for bugs/missing functionality in older linuces.
35 * confirm_flag fixes refusing service of kernels without MSG_CONFIRM.
36 * i.e. for linux-2.2 */
37 int confirm_flag = MSG_CONFIRM;
38 /* And this is workaround for bug in IP_RECVERR on raw sockets which is present
39 * in linux-2.2.[0-19], linux-2.4.[0-7] */
43 int timing; /* flag to do timing */
44 long tmin = LONG_MAX; /* minimum round trip time */
45 long tmax; /* maximum round trip time */
46 /* Message for rpm maintainers: have _shame_. If you want
47 * to fix something send the patch to me for sanity checking.
48 * "sparcfix" patch is a complete non-sense, apparenly the person
49 * prepared it was stoned.
51 long long tsum; /* sum of all times, for doing average */
55 int datalen = DEFDATALEN;
59 int ident; /* process id to identify our packets */
61 static int screen_width = INT_MAX;
63 /* Fills all the outpack, excluding ICMP header, but _including_
64 * timestamp area with supplied pattern.
66 static void fill(char *patp)
71 u_char *bp = outpack+8;
73 for (cp = patp; *cp; cp++) {
76 "ping: patterns must be specified as hex digits.\n");
81 "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
82 &pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6],
83 &pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12],
84 &pat[13], &pat[14], &pat[15]);
87 for (kk = 0; kk <= maxpacket - (8 + ii); kk += ii)
88 for (jj = 0; jj < ii; ++jj)
89 bp[jj + kk] = pat[jj];
91 if (!(options & F_QUIET)) {
92 printf("PATTERN: 0x");
93 for (jj = 0; jj < ii; ++jj)
94 printf("%02x", bp[jj] & 0xFF);
99 void common_options(int ch)
103 options |= F_AUDIBLE;
106 options |= F_ADAPTIVE;
109 npackets = atoi(optarg);
111 fprintf(stderr, "ping: bad number of packets to transmit.\n");
116 options |= F_SO_DEBUG;
119 options |= F_PTIMEOFDAY;
121 case 'i': /* wait between sending packets */
123 if (strchr(optarg, '.')) {
125 if (sscanf(optarg, "%f", &t) != 1) {
126 fprintf(stderr, "ping: bad timing interval.\n");
129 interval = (int)(t*1000);
130 } else if (sscanf(optarg, "%d", &interval) == 1) {
133 fprintf(stderr, "ping: bad timing interval.\n");
138 fprintf(stderr, "ping: bad timing interval.\n");
141 options |= F_INTERVAL;
147 mark = (int)strtoul(optarg, &endp, 10);
148 if (mark < 0 || *endp != '\0') {
149 fprintf(stderr, "mark cannot be negative");
156 deadline = atoi(optarg);
158 fprintf(stderr, "ping: bad wait time.\n");
163 preload = atoi(optarg);
165 fprintf(stderr, "ping: bad preload value, should be 1..%d\n", mx_dup_ck);
168 if (preload > mx_dup_ck)
170 if (uid && preload > 3) {
171 fprintf(stderr, "ping: cannot set preload to value > 3\n");
176 sndbuf = atoi(optarg);
178 fprintf(stderr, "ping: bad sndbuf value.\n");
184 setbuf(stdout, (char *)NULL);
185 /* fallthrough to numeric - avoid gethostbyaddr during flood */
187 options |= F_NUMERIC;
189 case 'p': /* fill buffer with user pattern */
190 options |= F_PINGFILLED;
197 options |= F_SO_DONTROUTE;
199 case 's': /* size of packet to send */
200 datalen = atoi(optarg);
202 fprintf(stderr, "ping: illegal negative packet size %d.\n", datalen);
205 if (datalen > maxpacket - 8) {
206 fprintf(stderr, "ping: packet size too large: %d\n",
212 options |= F_VERBOSE;
220 if (ttl < 0 || ttl > 255) {
221 fprintf(stderr, "ping: ttl %u out of range\n", ttl);
226 options |= F_LATENCY;
229 options |= F_STRICTSOURCE;
232 lingertime = atoi(optarg);
233 if (lingertime < 0 || lingertime > INT_MAX/1000000) {
234 fprintf(stderr, "ping: bad linger time.\n");
240 printf("ping utility, iputils-ss%s\n", SNAPSHOT);
248 static void sigexit(int signo)
253 static void sigstatus(int signo)
259 int __schedule_exit(int next)
261 static unsigned long waittime;
269 if (waittime < 1000*interval)
270 waittime = 1000*interval;
272 waittime = lingertime*1000;
274 if (next < 0 || next < waittime/1000)
275 next = waittime/1000;
277 it.it_interval.tv_sec = 0;
278 it.it_interval.tv_usec = 0;
279 it.it_value.tv_sec = waittime/1000000;
280 it.it_value.tv_usec = waittime%1000000;
281 setitimer(ITIMER_REAL, &it, NULL);
285 static inline void update_interval(void)
287 int est = rtt ? rtt/8 : interval*1000;
289 interval = (est+rtt_addend+500)/1000;
290 if (uid && interval < MINUSERINTERVAL)
291 interval = MINUSERINTERVAL;
297 void print_timestamp(void)
299 if (options & F_PTIMEOFDAY) {
301 gettimeofday(&tv, NULL);
302 printf("[%lu.%06lu] ",
303 (unsigned long)tv.tv_sec, (unsigned long)tv.tv_usec);
309 * Compose and transmit an ICMP ECHO REQUEST packet. The IP packet
310 * will be added on by the kernel. The ID field is our UNIX process ID,
311 * and the sequence number is an ascending integer. The first 8 bytes
312 * of the data portion are used to hold a UNIX "timeval" struct in VAX
313 * byte-order, to compute the round-trip time.
317 static int oom_count;
321 /* Have we already sent enough? If we have, return an arbitrary positive value. */
322 if (exiting || (npackets && ntransmitted >= npackets && !deadline))
325 /* Check that packets < rate*time + preload */
326 if (cur_time.tv_sec == 0) {
327 gettimeofday(&cur_time, NULL);
328 tokens = interval*(preload-1);
333 gettimeofday(&tv, NULL);
334 ntokens = (tv.tv_sec - cur_time.tv_sec)*1000 +
335 (tv.tv_usec-cur_time.tv_usec)/1000;
337 /* Case of unlimited flood is special;
338 * if we see no reply, they are limited to 100pps */
339 if (ntokens < MININTERVAL && in_flight() >= preload)
340 return MININTERVAL-ntokens;
343 if (ntokens > interval*preload)
344 ntokens = interval*preload;
345 if (ntokens < interval)
346 return interval - ntokens;
349 tokens = ntokens - interval;
357 advance_ntransmitted();
358 if (!(options & F_QUIET) && (options & F_FLOOD)) {
359 /* Very silly, but without this output with
360 * high preload or pipe size is very confusing. */
361 if ((preload < screen_width && pipesize < screen_width) ||
362 in_flight() < screen_width)
363 write(STDOUT_FILENO, ".", 1);
365 return interval - tokens;
368 /* And handle various errors... */
370 /* Apparently, it is some fatal bug. */
372 } else if (errno == ENOBUFS || errno == ENOMEM) {
375 /* Device queue overflow or OOM. Packet is not sent. */
377 /* Slowdown. This works only in adaptive mode (option -A) */
378 rtt_addend += (rtt < 8*50000 ? rtt/8 : 50000);
379 if (options&F_ADAPTIVE)
381 nores_interval = SCHINT(interval/2);
382 if (nores_interval > 500)
383 nores_interval = 500;
385 if (oom_count*nores_interval < lingertime)
386 return nores_interval;
388 /* Fall to hard error. It is to avoid complete deadlock
389 * on stuck output device even when dealine was not requested.
390 * Expected timings are screwed up in any case, but we will
391 * exit some day. :-) */
392 } else if (errno == EAGAIN) {
393 /* Socket buffer is full. */
397 if ((i=receive_error_msg()) > 0) {
398 /* An ICMP error arrived. */
402 /* Compatibility with old linuces. */
403 if (i == 0 && confirm_flag && errno == EINVAL) {
411 /* Hard local error. Pretend we sent packet. */
412 advance_ntransmitted();
414 if (i == 0 && !(options & F_QUIET)) {
415 if (options & F_FLOOD)
416 write(STDOUT_FILENO, "E", 1);
418 perror("ping: sendmsg");
421 return SCHINT(interval);
424 /* Set socket buffers, "alloc" is an estimate of memory taken by single packet. */
426 void sock_setbufs(int icmp_sock, int alloc)
429 socklen_t tmplen = sizeof(hold);
433 setsockopt(icmp_sock, SOL_SOCKET, SO_SNDBUF, (char *)&sndbuf, sizeof(sndbuf));
435 rcvbuf = hold = alloc * preload;
438 setsockopt(icmp_sock, SOL_SOCKET, SO_RCVBUF, (char *)&hold, sizeof(hold));
439 if (getsockopt(icmp_sock, SOL_SOCKET, SO_RCVBUF, (char *)&hold, &tmplen) == 0) {
441 fprintf(stderr, "WARNING: probably, rcvbuf is not enough to hold preload.\n");
445 /* Protocol independent setup and parameter checks. */
447 void setup(int icmp_sock)
452 if ((options & F_FLOOD) && !(options & F_INTERVAL))
455 if (uid && interval < MINUSERINTERVAL) {
456 fprintf(stderr, "ping: cannot flood; minimal interval, allowed for user, is %dms\n", MINUSERINTERVAL);
460 if (interval >= INT_MAX/preload) {
461 fprintf(stderr, "ping: illegal preload and/or interval\n");
466 if (options & F_SO_DEBUG)
467 setsockopt(icmp_sock, SOL_SOCKET, SO_DEBUG, (char *)&hold, sizeof(hold));
468 if (options & F_SO_DONTROUTE)
469 setsockopt(icmp_sock, SOL_SOCKET, SO_DONTROUTE, (char *)&hold, sizeof(hold));
472 if (!(options&F_LATENCY)) {
474 if (setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)))
475 fprintf(stderr, "Warning: no SO_TIMESTAMP support, falling back to SIOCGSTAMP\n");
478 if (options & F_MARK) {
479 if (setsockopt(icmp_sock, SOL_SOCKET, SO_MARK,
480 &mark, sizeof(mark)) == -1) {
481 /* we probably dont wanna exit since old kernels
482 * dont support mark ..
484 fprintf(stderr, "Warning: Failed to set mark %d\n", mark);
488 /* Set some SNDTIMEO to prevent blocking forever
489 * on sends, when device is too slow or stalls. Just put limit
490 * of one second, or "interval", if it is less.
494 if (interval < 1000) {
496 tv.tv_usec = 1000 * SCHINT(interval);
498 setsockopt(icmp_sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(tv));
500 /* Set RCVTIMEO to "interval". Note, it is just an optimization
501 * allowing to avoid redundant poll(). */
502 tv.tv_sec = SCHINT(interval)/1000;
503 tv.tv_usec = 1000*(SCHINT(interval)%1000);
504 if (setsockopt(icmp_sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(tv)))
505 options |= F_FLOOD_POLL;
507 if (!(options & F_PINGFILLED)) {
509 u_char *p = outpack+8;
511 /* Do not forget about case of small datalen,
512 * fill timestamp area too!
514 for (i = 0; i < datalen; ++i)
518 ident = htons(getpid() & 0xFFFF);
520 set_signal(SIGINT, sigexit);
521 set_signal(SIGALRM, sigexit);
522 set_signal(SIGQUIT, sigstatus);
524 gettimeofday(&start_time, NULL);
529 it.it_interval.tv_sec = 0;
530 it.it_interval.tv_usec = 0;
531 it.it_value.tv_sec = deadline;
532 it.it_value.tv_usec = 0;
533 setitimer(ITIMER_REAL, &it, NULL);
536 if (isatty(STDOUT_FILENO)) {
539 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1) {
541 screen_width = w.ws_col;
546 void main_loop(int icmp_sock, __u8 *packet, int packlen)
557 iov.iov_base = (char *)packet;
560 /* Check exit conditions. */
563 if (npackets && nreceived + nerrors >= npackets)
565 if (deadline && nerrors)
567 /* Check for and do special actions. */
571 /* Send probes scheduled to this time. */
574 next = schedule_exit(next);
577 /* "next" is time to send next probe, if positive.
578 * If next<=0 send now or as soon as possible. */
580 /* Technical part. Looks wicked. Could be dropped,
581 * if everyone used the newest kernel. :-)
583 * 1. Provide intervals less than resolution of scheduler.
584 * Solution: spinning.
585 * 2. Avoid use of poll(), when recvmsg() can provide
586 * timed waiting (SO_RCVTIMEO). */
588 if ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || next<SCHINT(interval)) {
589 int recv_expected = in_flight();
591 /* If we are here, recvmsg() is unable to wait for
592 * required timeout. */
593 if (1000*next <= 1000000/(int)HZ) {
594 /* Very short timeout... So, if we wait for
595 * something, we sleep for MININTERVAL.
596 * Otherwise, spin! */
601 /* When spinning, no reasons to poll.
602 * Use nonblocking recvmsg() instead. */
603 polling = MSG_DONTWAIT;
610 ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || interval)) {
613 pset.events = POLLIN|POLLERR;
615 if (poll(&pset, 1, next) < 1 ||
616 !(pset.revents&(POLLIN|POLLERR)))
618 polling = MSG_DONTWAIT;
623 struct timeval *recv_timep = NULL;
624 struct timeval recv_time;
625 int not_ours = 0; /* Raw socket can receive messages
626 * destined to other running pings. */
628 iov.iov_len = packlen;
629 memset(&msg, 0, sizeof(msg));
630 msg.msg_name = addrbuf;
631 msg.msg_namelen = sizeof(addrbuf);
634 msg.msg_control = ans_data;
635 msg.msg_controllen = sizeof(ans_data);
637 cc = recvmsg(icmp_sock, &msg, polling);
638 polling = MSG_DONTWAIT;
641 if (errno == EAGAIN || errno == EINTR)
643 if (!receive_error_msg()) {
645 perror("ping: recvmsg");
653 for (c = CMSG_FIRSTHDR(&msg); c; c = CMSG_NXTHDR(&msg, c)) {
654 if (c->cmsg_level != SOL_SOCKET ||
655 c->cmsg_type != SO_TIMESTAMP)
657 if (c->cmsg_len < CMSG_LEN(sizeof(struct timeval)))
659 recv_timep = (struct timeval*)CMSG_DATA(c);
663 if ((options&F_LATENCY) || recv_timep == NULL) {
664 if ((options&F_LATENCY) ||
665 ioctl(icmp_sock, SIOCGSTAMP, &recv_time))
666 gettimeofday(&recv_time, NULL);
667 recv_timep = &recv_time;
670 not_ours = parse_reply(&msg, cc, addrbuf, recv_timep);
673 /* See? ... someone runs another ping on this host. */
677 /* If nothing is in flight, "break" returns us to pinger. */
678 if (in_flight() == 0)
681 /* Otherwise, try to recvmsg() again. recvmsg()
682 * is nonblocking after the first iteration, so that
683 * if nothing is queued, it will receive EAGAIN
684 * and return to pinger. */
690 int gather_statistics(__u8 *icmph, int icmplen,
691 int cc, __u16 seq, int hops,
692 int csfailed, struct timeval *tv, char *from,
693 void (*pr_reply)(__u8 *icmph, int cc))
697 __u8 *ptr = icmph + icmplen;
703 if (timing && cc >= 8+sizeof(struct timeval)) {
704 struct timeval tmp_tv;
705 memcpy(&tmp_tv, ptr, sizeof(tmp_tv));
709 triptime = tv->tv_sec * 1000000 + tv->tv_usec;
711 fprintf(stderr, "Warning: time of day goes back (%ldus), taking countermeasures.\n", triptime);
713 if (!(options & F_LATENCY)) {
714 gettimeofday(tv, NULL);
715 options |= F_LATENCY;
721 tsum2 += (long long)triptime * (long long)triptime;
729 rtt += triptime-rtt/8;
730 if (options&F_ADAPTIVE)
738 } else if (TST(seq % mx_dup_ck)) {
743 SET(seq % mx_dup_ck);
746 confirm = confirm_flag;
748 if (options & F_QUIET)
751 if (options & F_FLOOD) {
753 write(STDOUT_FILENO, "\b \b", 3);
755 write(STDOUT_FILENO, "\bC", 1);
761 printf("%d bytes from %s:", cc, from);
767 printf(" ttl=%d", hops);
769 if (cc < datalen+8) {
770 printf(" (truncated)\n");
774 if (triptime >= 100000)
775 printf(" time=%ld ms", triptime/1000);
776 else if (triptime >= 10000)
777 printf(" time=%ld.%01ld ms", triptime/1000,
778 (triptime%1000)/100);
779 else if (triptime >= 1000)
780 printf(" time=%ld.%02ld ms", triptime/1000,
783 printf(" time=%ld.%03ld ms", triptime/1000,
789 printf(" (BAD CHECKSUM!)");
792 cp = ((u_char*)ptr) + sizeof(struct timeval);
793 dp = &outpack[8 + sizeof(struct timeval)];
794 for (i = sizeof(struct timeval); i < datalen; ++i, ++cp, ++dp) {
796 printf("\nwrong data byte #%d should be 0x%x but was 0x%x",
798 cp = (u_char*)ptr + sizeof(struct timeval);
799 for (i = sizeof(struct timeval); i < datalen; ++i, ++cp) {
800 if ((i % 32) == sizeof(struct timeval))
801 printf("\n#%d\t", i);
811 static long llsqrt(long long a)
813 long long prev = ~((long long)1 << 63);
828 * Print out statistics, and give up.
832 struct timeval tv = cur_time;
835 tvsub(&tv, &start_time);
839 printf("--- %s ping statistics ---\n", hostname);
840 printf("%ld packets transmitted, ", ntransmitted);
841 printf("%ld received", nreceived);
843 printf(", +%ld duplicates", nrepeats);
845 printf(", +%ld corrupted", nchecksum);
847 printf(", +%ld errors", nerrors);
849 printf(", %d%% packet loss",
850 (int) ((((long long)(ntransmitted - nreceived)) * 100) /
852 printf(", time %ldms", 1000*tv.tv_sec+tv.tv_usec/1000);
856 if (nreceived && timing) {
859 tsum /= nreceived + nrepeats;
860 tsum2 /= nreceived + nrepeats;
861 tmdev = llsqrt(tsum2 - tsum * tsum);
863 printf("rtt min/avg/max/mdev = %ld.%03ld/%lu.%03ld/%ld.%03ld/%ld.%03ld ms",
864 (long)tmin/1000, (long)tmin%1000,
865 (unsigned long)(tsum/1000), (long)(tsum%1000),
866 (long)tmax/1000, (long)tmax%1000,
867 (long)tmdev/1000, (long)tmdev%1000
872 printf("%spipe %d", comma, pipesize);
875 if (ntransmitted > 1 && (!interval || (options&(F_FLOOD|F_ADAPTIVE)))) {
876 int ipg = (1000000*(long long)tv.tv_sec+tv.tv_usec)/(ntransmitted-1);
877 printf("%sipg/ewma %d.%03d/%d.%03d ms",
878 comma, ipg/1000, ipg%1000, rtt/8000, (rtt/8)%1000);
881 exit(!nreceived || (deadline && nreceived < npackets));
893 loss = (((long long)(ntransmitted - nreceived)) * 100) / ntransmitted;
895 fprintf(stderr, "\r%ld/%ld packets, %d%% loss", ntransmitted, nreceived, loss);
897 if (nreceived && timing) {
898 tavg = tsum / (nreceived + nrepeats);
900 fprintf(stderr, ", min/avg/ewma/max = %ld.%03ld/%lu.%03ld/%d.%03d/%ld.%03ld ms",
901 (long)tmin/1000, (long)tmin%1000,
902 tavg/1000, tavg%1000,
903 rtt/8000, (rtt/8)%1000,
904 (long)tmax/1000, (long)tmax%1000
907 fprintf(stderr, "\n");