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