ping_common.c revision 313379eb6b9da55f7371adef39a92153a0707d4a
1#include "ping_common.h" 2#include <ctype.h> 3#include <sched.h> 4#include <math.h> 5 6int options; 7 8int mark; 9int sndbuf; 10int ttl; 11int rtt; 12int rtt_addend; 13__u16 acked; 14 15struct rcvd_table rcvd_tbl; 16 17 18/* counters */ 19long npackets; /* max packets to transmit */ 20long nreceived; /* # of packets we got back */ 21long nrepeats; /* number of duplicates */ 22long ntransmitted; /* sequence # for outbound packets = #sent */ 23long nchecksum; /* replies with bad checksum */ 24long nerrors; /* icmp errors */ 25int interval = 1000; /* interval between packets (msec) */ 26int preload; 27int deadline = 0; /* time to die */ 28int lingertime = MAXWAIT*1000; 29struct timeval start_time, cur_time; 30volatile int exiting; 31volatile int status_snapshot; 32int confirm = 0; 33volatile int in_pr_addr = 0; /* pr_addr() is executing */ 34jmp_buf pr_addr_jmp; 35 36/* Stupid workarounds for bugs/missing functionality in older linuces. 37 * confirm_flag fixes refusing service of kernels without MSG_CONFIRM. 38 * i.e. for linux-2.2 */ 39int confirm_flag = MSG_CONFIRM; 40/* And this is workaround for bug in IP_RECVERR on raw sockets which is present 41 * in linux-2.2.[0-19], linux-2.4.[0-7] */ 42int working_recverr; 43 44/* timing */ 45int timing; /* flag to do timing */ 46long tmin = LONG_MAX; /* minimum round trip time */ 47long tmax; /* maximum round trip time */ 48/* Message for rpm maintainers: have _shame_. If you want 49 * to fix something send the patch to me for sanity checking. 50 * "sparcfix" patch is a complete non-sense, apparenly the person 51 * prepared it was stoned. 52 */ 53long long tsum; /* sum of all times, for doing average */ 54long long tsum2; 55int pipesize = -1; 56 57int datalen = DEFDATALEN; 58 59char *hostname; 60int uid; 61uid_t euid; 62int ident; /* process id to identify our packets */ 63 64static int screen_width = INT_MAX; 65 66#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 67 68#ifdef CAPABILITIES 69static cap_value_t cap_raw = CAP_NET_RAW; 70static cap_value_t cap_admin = CAP_NET_ADMIN; 71#endif 72 73void limit_capabilities(void) 74{ 75#ifdef CAPABILITIES 76 cap_t cap_cur_p; 77 cap_t cap_p; 78 cap_flag_value_t cap_ok; 79 80 cap_cur_p = cap_get_proc(); 81 if (!cap_cur_p) { 82 perror("ping: cap_get_proc"); 83 exit(-1); 84 } 85 86 cap_p = cap_init(); 87 if (!cap_p) { 88 perror("ping: cap_init"); 89 exit(-1); 90 } 91 92 cap_ok = CAP_CLEAR; 93 cap_get_flag(cap_cur_p, CAP_NET_ADMIN, CAP_PERMITTED, &cap_ok); 94 95 if (cap_ok != CAP_CLEAR) 96 cap_set_flag(cap_p, CAP_PERMITTED, 1, &cap_admin, CAP_SET); 97 98 cap_ok = CAP_CLEAR; 99 cap_get_flag(cap_cur_p, CAP_NET_RAW, CAP_PERMITTED, &cap_ok); 100 101 if (cap_ok != CAP_CLEAR) 102 cap_set_flag(cap_p, CAP_PERMITTED, 1, &cap_raw, CAP_SET); 103 104 if (cap_set_proc(cap_p) < 0) { 105 perror("ping: cap_set_proc"); 106 exit(-1); 107 } 108 109 if (prctl(PR_SET_KEEPCAPS, 1) < 0) { 110 perror("ping: prctl"); 111 exit(-1); 112 } 113 114 if (setuid(getuid()) < 0) { 115 perror("setuid"); 116 exit(-1); 117 } 118 119 if (prctl(PR_SET_KEEPCAPS, 0) < 0) { 120 perror("ping: prctl"); 121 exit(-1); 122 } 123 124 cap_free(cap_p); 125 cap_free(cap_cur_p); 126#endif 127 uid = getuid(); 128 euid = geteuid(); 129#ifndef CAPABILITIES 130 if (seteuid(uid)) { 131 perror("ping: setuid"); 132 exit(-1); 133 } 134#endif 135} 136 137#ifdef CAPABILITIES 138int modify_capability(cap_value_t cap, cap_flag_value_t on) 139{ 140 cap_t cap_p = cap_get_proc(); 141 cap_flag_value_t cap_ok; 142 int rc = -1; 143 144 if (!cap_p) { 145 perror("ping: cap_get_proc"); 146 goto out; 147 } 148 149 cap_ok = CAP_CLEAR; 150 cap_get_flag(cap_p, cap, CAP_PERMITTED, &cap_ok); 151 if (cap_ok == CAP_CLEAR) { 152 rc = on ? -1 : 0; 153 goto out; 154 } 155 156 cap_set_flag(cap_p, CAP_EFFECTIVE, 1, &cap, on); 157 158 if (cap_set_proc(cap_p) < 0) { 159 perror("ping: cap_set_proc"); 160 goto out; 161 } 162 163 cap_free(cap_p); 164 165 rc = 0; 166out: 167 if (cap_p) 168 cap_free(cap_p); 169 return rc; 170} 171#else 172int modify_capability(int on) 173{ 174 if (seteuid(on ? euid : getuid())) { 175 perror("seteuid"); 176 return -1; 177 } 178 179 return 0; 180} 181#endif 182 183void drop_capabilities(void) 184{ 185#ifdef CAPABILITIES 186 cap_t cap = cap_init(); 187 if (cap_set_proc(cap) < 0) { 188 perror("ping: cap_set_proc"); 189 exit(-1); 190 } 191 cap_free(cap); 192#else 193 if (setuid(getuid())) { 194 perror("ping: setuid"); 195 exit(-1); 196 } 197#endif 198} 199 200/* Fills all the outpack, excluding ICMP header, but _including_ 201 * timestamp area with supplied pattern. 202 */ 203static void fill(char *patp) 204{ 205 int ii, jj, kk; 206 int pat[16]; 207 char *cp; 208 u_char *bp = outpack+8; 209 210#ifdef USE_IDN 211 setlocale(LC_ALL, "C"); 212#endif 213 214 for (cp = patp; *cp; cp++) { 215 if (!isxdigit(*cp)) { 216 fprintf(stderr, 217 "ping: patterns must be specified as hex digits.\n"); 218 exit(2); 219 } 220 } 221 ii = sscanf(patp, 222 "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x", 223 &pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6], 224 &pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12], 225 &pat[13], &pat[14], &pat[15]); 226 227 if (ii > 0) { 228 for (kk = 0; kk <= maxpacket - (8 + ii); kk += ii) 229 for (jj = 0; jj < ii; ++jj) 230 bp[jj + kk] = pat[jj]; 231 } 232 if (!(options & F_QUIET)) { 233 printf("PATTERN: 0x"); 234 for (jj = 0; jj < ii; ++jj) 235 printf("%02x", bp[jj] & 0xFF); 236 printf("\n"); 237 } 238 239#ifdef USE_IDN 240 setlocale(LC_ALL, ""); 241#endif 242} 243 244void common_options(int ch) 245{ 246 switch(ch) { 247 case 'a': 248 options |= F_AUDIBLE; 249 break; 250 case 'A': 251 options |= F_ADAPTIVE; 252 break; 253 case 'c': 254 npackets = atoi(optarg); 255 if (npackets <= 0) { 256 fprintf(stderr, "ping: bad number of packets to transmit.\n"); 257 exit(2); 258 } 259 break; 260 case 'd': 261 options |= F_SO_DEBUG; 262 break; 263 case 'D': 264 options |= F_PTIMEOFDAY; 265 break; 266 case 'i': /* wait between sending packets */ 267 { 268 double dbl; 269 char *ep; 270 271 errno = 0; 272 dbl = strtod(optarg, &ep); 273 274 if (errno || *ep != '\0' || 275 !finite(dbl) || dbl < 0.0 || dbl >= (double)INT_MAX / 1000 - 1.0) { 276 fprintf(stderr, "ping: bad timing interval\n"); 277 exit(2); 278 } 279 280 interval = (int)(dbl * 1000); 281 282 options |= F_INTERVAL; 283 break; 284 } 285 case 'm': 286 { 287 char *endp; 288 mark = (int)strtoul(optarg, &endp, 10); 289 if (mark < 0 || *endp != '\0') { 290 fprintf(stderr, "mark cannot be negative\n"); 291 exit(2); 292 } 293 options |= F_MARK; 294 break; 295 } 296 case 'w': 297 deadline = atoi(optarg); 298 if (deadline < 0) { 299 fprintf(stderr, "ping: bad wait time.\n"); 300 exit(2); 301 } 302 break; 303 case 'l': 304 preload = atoi(optarg); 305 if (preload <= 0) { 306 fprintf(stderr, "ping: bad preload value, should be 1..%d\n", MAX_DUP_CHK); 307 exit(2); 308 } 309 if (preload > MAX_DUP_CHK) 310 preload = MAX_DUP_CHK; 311 if (uid && preload > 3) { 312 fprintf(stderr, "ping: cannot set preload to value > 3\n"); 313 exit(2); 314 } 315 break; 316 case 'O': 317 options |= F_OUTSTANDING; 318 break; 319 case 'S': 320 sndbuf = atoi(optarg); 321 if (sndbuf <= 0) { 322 fprintf(stderr, "ping: bad sndbuf value.\n"); 323 exit(2); 324 } 325 break; 326 case 'f': 327 options |= F_FLOOD; 328 setbuf(stdout, (char *)NULL); 329 /* fallthrough to numeric - avoid gethostbyaddr during flood */ 330 case 'n': 331 options |= F_NUMERIC; 332 break; 333 case 'p': /* fill buffer with user pattern */ 334 options |= F_PINGFILLED; 335 fill(optarg); 336 break; 337 case 'q': 338 options |= F_QUIET; 339 break; 340 case 'r': 341 options |= F_SO_DONTROUTE; 342 break; 343 case 's': /* size of packet to send */ 344 datalen = atoi(optarg); 345 if (datalen < 0) { 346 fprintf(stderr, "ping: illegal negative packet size %d.\n", datalen); 347 exit(2); 348 } 349 if (datalen > maxpacket - 8) { 350 fprintf(stderr, "ping: packet size too large: %d\n", 351 datalen); 352 exit(2); 353 } 354 break; 355 case 'v': 356 options |= F_VERBOSE; 357 break; 358 case 'L': 359 options |= F_NOLOOP; 360 break; 361 case 't': 362 options |= F_TTL; 363 ttl = atoi(optarg); 364 if (ttl < 0 || ttl > 255) { 365 fprintf(stderr, "ping: ttl %u out of range\n", ttl); 366 exit(2); 367 } 368 break; 369 case 'U': 370 options |= F_LATENCY; 371 break; 372 case 'B': 373 options |= F_STRICTSOURCE; 374 break; 375 case 'W': 376 lingertime = atoi(optarg); 377 if (lingertime < 0 || lingertime > INT_MAX/1000000) { 378 fprintf(stderr, "ping: bad linger time.\n"); 379 exit(2); 380 } 381 lingertime *= 1000; 382 break; 383 case 'V': 384 printf("ping utility, iputils-%s\n", SNAPSHOT); 385 exit(0); 386 default: 387 abort(); 388 } 389} 390 391 392static void sigexit(int signo) 393{ 394 exiting = 1; 395 if (in_pr_addr) 396 longjmp(pr_addr_jmp, 0); 397} 398 399static void sigstatus(int signo) 400{ 401 status_snapshot = 1; 402} 403 404 405int __schedule_exit(int next) 406{ 407 static unsigned long waittime; 408 struct itimerval it; 409 410 if (waittime) 411 return next; 412 413 if (nreceived) { 414 waittime = 2 * tmax; 415 if (waittime < 1000*interval) 416 waittime = 1000*interval; 417 } else 418 waittime = lingertime*1000; 419 420 if (next < 0 || next < waittime/1000) 421 next = waittime/1000; 422 423 it.it_interval.tv_sec = 0; 424 it.it_interval.tv_usec = 0; 425 it.it_value.tv_sec = waittime/1000000; 426 it.it_value.tv_usec = waittime%1000000; 427 setitimer(ITIMER_REAL, &it, NULL); 428 return next; 429} 430 431static inline void update_interval(void) 432{ 433 int est = rtt ? rtt/8 : interval*1000; 434 435 interval = (est+rtt_addend+500)/1000; 436 if (uid && interval < MINUSERINTERVAL) 437 interval = MINUSERINTERVAL; 438} 439 440/* 441 * Print timestamp 442 */ 443void print_timestamp(void) 444{ 445 if (options & F_PTIMEOFDAY) { 446 struct timeval tv; 447 gettimeofday(&tv, NULL); 448 printf("[%lu.%06lu] ", 449 (unsigned long)tv.tv_sec, (unsigned long)tv.tv_usec); 450 } 451} 452 453/* 454 * pinger -- 455 * Compose and transmit an ICMP ECHO REQUEST packet. The IP packet 456 * will be added on by the kernel. The ID field is our UNIX process ID, 457 * and the sequence number is an ascending integer. The first 8 bytes 458 * of the data portion are used to hold a UNIX "timeval" struct in VAX 459 * byte-order, to compute the round-trip time. 460 */ 461int pinger(void) 462{ 463 static int oom_count; 464 static int tokens; 465 int i; 466 467 /* Have we already sent enough? If we have, return an arbitrary positive value. */ 468 if (exiting || (npackets && ntransmitted >= npackets && !deadline)) 469 return 1000; 470 471 /* Check that packets < rate*time + preload */ 472 if (cur_time.tv_sec == 0) { 473 gettimeofday(&cur_time, NULL); 474 tokens = interval*(preload-1); 475 } else { 476 long ntokens; 477 struct timeval tv; 478 479 gettimeofday(&tv, NULL); 480 ntokens = (tv.tv_sec - cur_time.tv_sec)*1000 + 481 (tv.tv_usec-cur_time.tv_usec)/1000; 482 if (!interval) { 483 /* Case of unlimited flood is special; 484 * if we see no reply, they are limited to 100pps */ 485 if (ntokens < MININTERVAL && in_flight() >= preload) 486 return MININTERVAL-ntokens; 487 } 488 ntokens += tokens; 489 if (ntokens > interval*preload) 490 ntokens = interval*preload; 491 if (ntokens < interval) 492 return interval - ntokens; 493 494 cur_time = tv; 495 tokens = ntokens - interval; 496 } 497 498 if (options & F_OUTSTANDING) { 499 if (ntransmitted > 0 && !rcvd_test(ntransmitted)) { 500 print_timestamp(); 501 printf("no answer yet for icmp_seq=%lu\n", (ntransmitted % MAX_DUP_CHK)); 502 fflush(stdout); 503 } 504 } 505 506resend: 507 i = send_probe(); 508 509 if (i == 0) { 510 oom_count = 0; 511 advance_ntransmitted(); 512 if (!(options & F_QUIET) && (options & F_FLOOD)) { 513 /* Very silly, but without this output with 514 * high preload or pipe size is very confusing. */ 515 if ((preload < screen_width && pipesize < screen_width) || 516 in_flight() < screen_width) 517 write_stdout(".", 1); 518 } 519 return interval - tokens; 520 } 521 522 /* And handle various errors... */ 523 if (i > 0) { 524 /* Apparently, it is some fatal bug. */ 525 abort(); 526 } else if (errno == ENOBUFS || errno == ENOMEM) { 527 int nores_interval; 528 529 /* Device queue overflow or OOM. Packet is not sent. */ 530 tokens = 0; 531 /* Slowdown. This works only in adaptive mode (option -A) */ 532 rtt_addend += (rtt < 8*50000 ? rtt/8 : 50000); 533 if (options&F_ADAPTIVE) 534 update_interval(); 535 nores_interval = SCHINT(interval/2); 536 if (nores_interval > 500) 537 nores_interval = 500; 538 oom_count++; 539 if (oom_count*nores_interval < lingertime) 540 return nores_interval; 541 i = 0; 542 /* Fall to hard error. It is to avoid complete deadlock 543 * on stuck output device even when dealine was not requested. 544 * Expected timings are screwed up in any case, but we will 545 * exit some day. :-) */ 546 } else if (errno == EAGAIN) { 547 /* Socket buffer is full. */ 548 tokens += interval; 549 return MININTERVAL; 550 } else { 551 if ((i=receive_error_msg()) > 0) { 552 /* An ICMP error arrived. */ 553 tokens += interval; 554 return MININTERVAL; 555 } 556 /* Compatibility with old linuces. */ 557 if (i == 0 && confirm_flag && errno == EINVAL) { 558 confirm_flag = 0; 559 errno = 0; 560 } 561 if (!errno) 562 goto resend; 563 } 564 565 /* Hard local error. Pretend we sent packet. */ 566 advance_ntransmitted(); 567 568 if (i == 0 && !(options & F_QUIET)) { 569 if (options & F_FLOOD) 570 write_stdout("E", 1); 571 else 572 perror("ping: sendmsg"); 573 } 574 tokens = 0; 575 return SCHINT(interval); 576} 577 578/* Set socket buffers, "alloc" is an estimate of memory taken by single packet. */ 579 580void sock_setbufs(int icmp_sock, int alloc) 581{ 582 int rcvbuf, hold; 583 socklen_t tmplen = sizeof(hold); 584 585 if (!sndbuf) 586 sndbuf = alloc; 587 setsockopt(icmp_sock, SOL_SOCKET, SO_SNDBUF, (char *)&sndbuf, sizeof(sndbuf)); 588 589 rcvbuf = hold = alloc * preload; 590 if (hold < 65536) 591 hold = 65536; 592 setsockopt(icmp_sock, SOL_SOCKET, SO_RCVBUF, (char *)&hold, sizeof(hold)); 593 if (getsockopt(icmp_sock, SOL_SOCKET, SO_RCVBUF, (char *)&hold, &tmplen) == 0) { 594 if (hold < rcvbuf) 595 fprintf(stderr, "WARNING: probably, rcvbuf is not enough to hold preload.\n"); 596 } 597} 598 599/* Protocol independent setup and parameter checks. */ 600 601void setup(int icmp_sock) 602{ 603 int hold; 604 struct timeval tv; 605 sigset_t sset; 606 607 if ((options & F_FLOOD) && !(options & F_INTERVAL)) 608 interval = 0; 609 610 if (uid && interval < MINUSERINTERVAL) { 611 fprintf(stderr, "ping: cannot flood; minimal interval, allowed for user, is %dms\n", MINUSERINTERVAL); 612 exit(2); 613 } 614 615 if (interval >= INT_MAX/preload) { 616 fprintf(stderr, "ping: illegal preload and/or interval\n"); 617 exit(2); 618 } 619 620 hold = 1; 621 if (options & F_SO_DEBUG) 622 setsockopt(icmp_sock, SOL_SOCKET, SO_DEBUG, (char *)&hold, sizeof(hold)); 623 if (options & F_SO_DONTROUTE) 624 setsockopt(icmp_sock, SOL_SOCKET, SO_DONTROUTE, (char *)&hold, sizeof(hold)); 625 626#ifdef SO_TIMESTAMP 627 if (!(options&F_LATENCY)) { 628 int on = 1; 629 if (setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on))) 630 fprintf(stderr, "Warning: no SO_TIMESTAMP support, falling back to SIOCGSTAMP\n"); 631 } 632#endif 633#ifdef SO_MARK 634 if (options & F_MARK) { 635 int ret; 636 637 enable_capability_admin(); 638 ret = setsockopt(icmp_sock, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)); 639 disable_capability_admin(); 640 641 if (ret == -1) { 642 /* we probably dont wanna exit since old kernels 643 * dont support mark .. 644 */ 645 fprintf(stderr, "Warning: Failed to set mark %d\n", mark); 646 } 647 } 648#endif 649 650 /* Set some SNDTIMEO to prevent blocking forever 651 * on sends, when device is too slow or stalls. Just put limit 652 * of one second, or "interval", if it is less. 653 */ 654 tv.tv_sec = 1; 655 tv.tv_usec = 0; 656 if (interval < 1000) { 657 tv.tv_sec = 0; 658 tv.tv_usec = 1000 * SCHINT(interval); 659 } 660 setsockopt(icmp_sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(tv)); 661 662 /* Set RCVTIMEO to "interval". Note, it is just an optimization 663 * allowing to avoid redundant poll(). */ 664 tv.tv_sec = SCHINT(interval)/1000; 665 tv.tv_usec = 1000*(SCHINT(interval)%1000); 666 if (setsockopt(icmp_sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(tv))) 667 options |= F_FLOOD_POLL; 668 669 if (!(options & F_PINGFILLED)) { 670 int i; 671 u_char *p = outpack+8; 672 673 /* Do not forget about case of small datalen, 674 * fill timestamp area too! 675 */ 676 for (i = 0; i < datalen; ++i) 677 *p++ = i; 678 } 679 680 ident = htons(getpid() & 0xFFFF); 681 682 set_signal(SIGINT, sigexit); 683 set_signal(SIGALRM, sigexit); 684 set_signal(SIGQUIT, sigstatus); 685 686 sigemptyset(&sset); 687 sigprocmask(SIG_SETMASK, &sset, NULL); 688 689 gettimeofday(&start_time, NULL); 690 691 if (deadline) { 692 struct itimerval it; 693 694 it.it_interval.tv_sec = 0; 695 it.it_interval.tv_usec = 0; 696 it.it_value.tv_sec = deadline; 697 it.it_value.tv_usec = 0; 698 setitimer(ITIMER_REAL, &it, NULL); 699 } 700 701 if (isatty(STDOUT_FILENO)) { 702 struct winsize w; 703 704 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1) { 705 if (w.ws_col > 0) 706 screen_width = w.ws_col; 707 } 708 } 709} 710 711void main_loop(int icmp_sock, __u8 *packet, int packlen) 712{ 713 char addrbuf[128]; 714 char ans_data[4096]; 715 struct iovec iov; 716 struct msghdr msg; 717 struct cmsghdr *c; 718 int cc; 719 int next; 720 int polling; 721 722 iov.iov_base = (char *)packet; 723 724 for (;;) { 725 /* Check exit conditions. */ 726 if (exiting) 727 break; 728 if (npackets && nreceived + nerrors >= npackets) 729 break; 730 if (deadline && nerrors) 731 break; 732 /* Check for and do special actions. */ 733 if (status_snapshot) 734 status(); 735 736 /* Send probes scheduled to this time. */ 737 do { 738 next = pinger(); 739 next = schedule_exit(next); 740 } while (next <= 0); 741 742 /* "next" is time to send next probe, if positive. 743 * If next<=0 send now or as soon as possible. */ 744 745 /* Technical part. Looks wicked. Could be dropped, 746 * if everyone used the newest kernel. :-) 747 * Its purpose is: 748 * 1. Provide intervals less than resolution of scheduler. 749 * Solution: spinning. 750 * 2. Avoid use of poll(), when recvmsg() can provide 751 * timed waiting (SO_RCVTIMEO). */ 752 polling = 0; 753 if ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || next<SCHINT(interval)) { 754 int recv_expected = in_flight(); 755 756 /* If we are here, recvmsg() is unable to wait for 757 * required timeout. */ 758 if (1000 % HZ == 0 ? next <= 1000 / HZ : (next < INT_MAX / HZ && next * HZ <= 1000)) { 759 /* Very short timeout... So, if we wait for 760 * something, we sleep for MININTERVAL. 761 * Otherwise, spin! */ 762 if (recv_expected) { 763 next = MININTERVAL; 764 } else { 765 next = 0; 766 /* When spinning, no reasons to poll. 767 * Use nonblocking recvmsg() instead. */ 768 polling = MSG_DONTWAIT; 769 /* But yield yet. */ 770 sched_yield(); 771 } 772 } 773 774 if (!polling && 775 ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || interval)) { 776 struct pollfd pset; 777 pset.fd = icmp_sock; 778 pset.events = POLLIN|POLLERR; 779 pset.revents = 0; 780 if (poll(&pset, 1, next) < 1 || 781 !(pset.revents&(POLLIN|POLLERR))) 782 continue; 783 polling = MSG_DONTWAIT; 784 } 785 } 786 787 for (;;) { 788 struct timeval *recv_timep = NULL; 789 struct timeval recv_time; 790 int not_ours = 0; /* Raw socket can receive messages 791 * destined to other running pings. */ 792 793 iov.iov_len = packlen; 794 memset(&msg, 0, sizeof(msg)); 795 msg.msg_name = addrbuf; 796 msg.msg_namelen = sizeof(addrbuf); 797 msg.msg_iov = &iov; 798 msg.msg_iovlen = 1; 799 msg.msg_control = ans_data; 800 msg.msg_controllen = sizeof(ans_data); 801 802 cc = recvmsg(icmp_sock, &msg, polling); 803 polling = MSG_DONTWAIT; 804 805 if (cc < 0) { 806 if (errno == EAGAIN || errno == EINTR) 807 break; 808 if (!receive_error_msg()) { 809 if (errno) { 810 perror("ping: recvmsg"); 811 break; 812 } 813 not_ours = 1; 814 } 815 } else { 816 817#ifdef SO_TIMESTAMP 818 for (c = CMSG_FIRSTHDR(&msg); c; c = CMSG_NXTHDR(&msg, c)) { 819 if (c->cmsg_level != SOL_SOCKET || 820 c->cmsg_type != SO_TIMESTAMP) 821 continue; 822 if (c->cmsg_len < CMSG_LEN(sizeof(struct timeval))) 823 continue; 824 recv_timep = (struct timeval*)CMSG_DATA(c); 825 } 826#endif 827 828 if ((options&F_LATENCY) || recv_timep == NULL) { 829 if ((options&F_LATENCY) || 830 ioctl(icmp_sock, SIOCGSTAMP, &recv_time)) 831 gettimeofday(&recv_time, NULL); 832 recv_timep = &recv_time; 833 } 834 835 not_ours = parse_reply(&msg, cc, addrbuf, recv_timep); 836 } 837 838 /* See? ... someone runs another ping on this host. */ 839 if (not_ours) 840 install_filter(); 841 842 /* If nothing is in flight, "break" returns us to pinger. */ 843 if (in_flight() == 0) 844 break; 845 846 /* Otherwise, try to recvmsg() again. recvmsg() 847 * is nonblocking after the first iteration, so that 848 * if nothing is queued, it will receive EAGAIN 849 * and return to pinger. */ 850 } 851 } 852 finish(); 853} 854 855int gather_statistics(__u8 *icmph, int icmplen, 856 int cc, __u16 seq, int hops, 857 int csfailed, struct timeval *tv, char *from, 858 void (*pr_reply)(__u8 *icmph, int cc)) 859{ 860 int dupflag = 0; 861 long triptime = 0; 862 __u8 *ptr = icmph + icmplen; 863 864 ++nreceived; 865 if (!csfailed) 866 acknowledge(seq); 867 868 if (timing && cc >= 8+sizeof(struct timeval)) { 869 struct timeval tmp_tv; 870 memcpy(&tmp_tv, ptr, sizeof(tmp_tv)); 871 872restamp: 873 tvsub(tv, &tmp_tv); 874 triptime = tv->tv_sec * 1000000 + tv->tv_usec; 875 if (triptime < 0) { 876 fprintf(stderr, "Warning: time of day goes back (%ldus), taking countermeasures.\n", triptime); 877 triptime = 0; 878 if (!(options & F_LATENCY)) { 879 gettimeofday(tv, NULL); 880 options |= F_LATENCY; 881 goto restamp; 882 } 883 } 884 if (!csfailed) { 885 tsum += triptime; 886 tsum2 += (long long)triptime * (long long)triptime; 887 if (triptime < tmin) 888 tmin = triptime; 889 if (triptime > tmax) 890 tmax = triptime; 891 if (!rtt) 892 rtt = triptime*8; 893 else 894 rtt += triptime-rtt/8; 895 if (options&F_ADAPTIVE) 896 update_interval(); 897 } 898 } 899 900 if (csfailed) { 901 ++nchecksum; 902 --nreceived; 903 } else if (rcvd_test(seq)) { 904 ++nrepeats; 905 --nreceived; 906 dupflag = 1; 907 } else { 908 rcvd_set(seq); 909 dupflag = 0; 910 } 911 confirm = confirm_flag; 912 913 if (options & F_QUIET) 914 return 1; 915 916 if (options & F_FLOOD) { 917 if (!csfailed) 918 write_stdout("\b \b", 3); 919 else 920 write_stdout("\bC", 2); 921 } else { 922 int i; 923 __u8 *cp, *dp; 924 925 print_timestamp(); 926 printf("%d bytes from %s:", cc, from); 927 928 if (pr_reply) 929 pr_reply(icmph, cc); 930 931 if (hops >= 0) 932 printf(" ttl=%d", hops); 933 934 if (cc < datalen+8) { 935 printf(" (truncated)\n"); 936 return 1; 937 } 938 if (timing) { 939 if (triptime >= 100000) 940 printf(" time=%ld ms", triptime/1000); 941 else if (triptime >= 10000) 942 printf(" time=%ld.%01ld ms", triptime/1000, 943 (triptime%1000)/100); 944 else if (triptime >= 1000) 945 printf(" time=%ld.%02ld ms", triptime/1000, 946 (triptime%1000)/10); 947 else 948 printf(" time=%ld.%03ld ms", triptime/1000, 949 triptime%1000); 950 } 951 if (dupflag) 952 printf(" (DUP!)"); 953 if (csfailed) 954 printf(" (BAD CHECKSUM!)"); 955 956 /* check the data */ 957 cp = ((u_char*)ptr) + sizeof(struct timeval); 958 dp = &outpack[8 + sizeof(struct timeval)]; 959 for (i = sizeof(struct timeval); i < datalen; ++i, ++cp, ++dp) { 960 if (*cp != *dp) { 961 printf("\nwrong data byte #%d should be 0x%x but was 0x%x", 962 i, *dp, *cp); 963 cp = (u_char*)ptr + sizeof(struct timeval); 964 for (i = sizeof(struct timeval); i < datalen; ++i, ++cp) { 965 if ((i % 32) == sizeof(struct timeval)) 966 printf("\n#%d\t", i); 967 printf("%x ", *cp); 968 } 969 break; 970 } 971 } 972 } 973 return 0; 974} 975 976static long llsqrt(long long a) 977{ 978 long long prev = ~((long long)1 << 63); 979 long long x = a; 980 981 if (x > 0) { 982 while (x < prev) { 983 prev = x; 984 x = (x+(a/x))/2; 985 } 986 } 987 988 return (long)x; 989} 990 991/* 992 * finish -- 993 * Print out statistics, and give up. 994 */ 995void finish(void) 996{ 997 struct timeval tv = cur_time; 998 char *comma = ""; 999 1000 tvsub(&tv, &start_time); 1001 1002 putchar('\n'); 1003 fflush(stdout); 1004 printf("--- %s ping statistics ---\n", hostname); 1005 printf("%ld packets transmitted, ", ntransmitted); 1006 printf("%ld received", nreceived); 1007 if (nrepeats) 1008 printf(", +%ld duplicates", nrepeats); 1009 if (nchecksum) 1010 printf(", +%ld corrupted", nchecksum); 1011 if (nerrors) 1012 printf(", +%ld errors", nerrors); 1013 if (ntransmitted) { 1014 printf(", %d%% packet loss", 1015 (int) ((((long long)(ntransmitted - nreceived)) * 100) / 1016 ntransmitted)); 1017 printf(", time %ldms", 1000*tv.tv_sec+tv.tv_usec/1000); 1018 } 1019 putchar('\n'); 1020 1021 if (nreceived && timing) { 1022 long tmdev; 1023 1024 tsum /= nreceived + nrepeats; 1025 tsum2 /= nreceived + nrepeats; 1026 tmdev = llsqrt(tsum2 - tsum * tsum); 1027 1028 printf("rtt min/avg/max/mdev = %ld.%03ld/%lu.%03ld/%ld.%03ld/%ld.%03ld ms", 1029 (long)tmin/1000, (long)tmin%1000, 1030 (unsigned long)(tsum/1000), (long)(tsum%1000), 1031 (long)tmax/1000, (long)tmax%1000, 1032 (long)tmdev/1000, (long)tmdev%1000 1033 ); 1034 comma = ", "; 1035 } 1036 if (pipesize > 1) { 1037 printf("%spipe %d", comma, pipesize); 1038 comma = ", "; 1039 } 1040 if (nreceived && (!interval || (options&(F_FLOOD|F_ADAPTIVE))) && ntransmitted > 1) { 1041 int ipg = (1000000*(long long)tv.tv_sec+tv.tv_usec)/(ntransmitted-1); 1042 printf("%sipg/ewma %d.%03d/%d.%03d ms", 1043 comma, ipg/1000, ipg%1000, rtt/8000, (rtt/8)%1000); 1044 } 1045 putchar('\n'); 1046 exit(!nreceived || (deadline && nreceived < npackets)); 1047} 1048 1049 1050void status(void) 1051{ 1052 int loss = 0; 1053 long tavg = 0; 1054 1055 status_snapshot = 0; 1056 1057 if (ntransmitted) 1058 loss = (((long long)(ntransmitted - nreceived)) * 100) / ntransmitted; 1059 1060 fprintf(stderr, "\r%ld/%ld packets, %d%% loss", ntransmitted, nreceived, loss); 1061 1062 if (nreceived && timing) { 1063 tavg = tsum / (nreceived + nrepeats); 1064 1065 fprintf(stderr, ", min/avg/ewma/max = %ld.%03ld/%lu.%03ld/%d.%03d/%ld.%03ld ms", 1066 (long)tmin/1000, (long)tmin%1000, 1067 tavg/1000, tavg%1000, 1068 rtt/8000, (rtt/8)%1000, 1069 (long)tmax/1000, (long)tmax%1000 1070 ); 1071 } 1072 fprintf(stderr, "\n"); 1073} 1074 1075