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 /* Protocol independent setup and parameter checks. */ 609 610 void setup(int icmp_sock) 611 { 612 int hold; 613 struct timeval tv; 614 sigset_t sset; 615 616 if ((options & F_FLOOD) && !(options & F_INTERVAL)) 617 interval = 0; 618 619 if (uid && interval < MINUSERINTERVAL) { 620 fprintf(stderr, "ping: cannot flood; minimal interval, allowed for user, is %dms\n", MINUSERINTERVAL); 621 exit(2); 622 } 623 624 if (interval >= INT_MAX/preload) { 625 fprintf(stderr, "ping: illegal preload and/or interval\n"); 626 exit(2); 627 } 628 629 hold = 1; 630 if (options & F_SO_DEBUG) 631 setsockopt(icmp_sock, SOL_SOCKET, SO_DEBUG, (char *)&hold, sizeof(hold)); 632 if (options & F_SO_DONTROUTE) 633 setsockopt(icmp_sock, SOL_SOCKET, SO_DONTROUTE, (char *)&hold, sizeof(hold)); 634 635 #ifdef SO_TIMESTAMP 636 if (!(options&F_LATENCY)) { 637 int on = 1; 638 if (setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on))) 639 fprintf(stderr, "Warning: no SO_TIMESTAMP support, falling back to SIOCGSTAMP\n"); 640 } 641 #endif 642 #ifdef SO_MARK 643 if (options & F_MARK) { 644 int ret; 645 646 enable_capability_admin(); 647 ret = setsockopt(icmp_sock, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)); 648 disable_capability_admin(); 649 650 if (ret == -1) { 651 /* we probably dont wanna exit since old kernels 652 * dont support mark .. 653 */ 654 fprintf(stderr, "Warning: Failed to set mark %d\n", mark); 655 } 656 } 657 #endif 658 659 /* Set some SNDTIMEO to prevent blocking forever 660 * on sends, when device is too slow or stalls. Just put limit 661 * of one second, or "interval", if it is less. 662 */ 663 tv.tv_sec = 1; 664 tv.tv_usec = 0; 665 if (interval < 1000) { 666 tv.tv_sec = 0; 667 tv.tv_usec = 1000 * SCHINT(interval); 668 } 669 setsockopt(icmp_sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(tv)); 670 671 /* Set RCVTIMEO to "interval". Note, it is just an optimization 672 * allowing to avoid redundant poll(). */ 673 tv.tv_sec = SCHINT(interval)/1000; 674 tv.tv_usec = 1000*(SCHINT(interval)%1000); 675 if (setsockopt(icmp_sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(tv))) 676 options |= F_FLOOD_POLL; 677 678 if (!(options & F_PINGFILLED)) { 679 int i; 680 u_char *p = outpack+8; 681 682 /* Do not forget about case of small datalen, 683 * fill timestamp area too! 684 */ 685 for (i = 0; i < datalen; ++i) 686 *p++ = i; 687 } 688 689 if (!using_ping_socket) 690 ident = htons(getpid() & 0xFFFF); 691 692 set_signal(SIGINT, sigexit); 693 set_signal(SIGALRM, sigexit); 694 set_signal(SIGQUIT, sigstatus); 695 696 sigemptyset(&sset); 697 sigprocmask(SIG_SETMASK, &sset, NULL); 698 699 gettimeofday(&start_time, NULL); 700 701 if (deadline) { 702 struct itimerval it; 703 704 it.it_interval.tv_sec = 0; 705 it.it_interval.tv_usec = 0; 706 it.it_value.tv_sec = deadline; 707 it.it_value.tv_usec = 0; 708 setitimer(ITIMER_REAL, &it, NULL); 709 } 710 711 if (isatty(STDOUT_FILENO)) { 712 struct winsize w; 713 714 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1) { 715 if (w.ws_col > 0) 716 screen_width = w.ws_col; 717 } 718 } 719 } 720 721 void main_loop(int icmp_sock, __u8 *packet, int packlen) 722 { 723 char addrbuf[128]; 724 char ans_data[4096]; 725 struct iovec iov; 726 struct msghdr msg; 727 struct cmsghdr *c; 728 int cc; 729 int next; 730 int polling; 731 732 iov.iov_base = (char *)packet; 733 734 for (;;) { 735 /* Check exit conditions. */ 736 if (exiting) 737 break; 738 if (npackets && nreceived + nerrors >= npackets) 739 break; 740 if (deadline && nerrors) 741 break; 742 /* Check for and do special actions. */ 743 if (status_snapshot) 744 status(); 745 746 /* Send probes scheduled to this time. */ 747 do { 748 next = pinger(); 749 next = schedule_exit(next); 750 } while (next <= 0); 751 752 /* "next" is time to send next probe, if positive. 753 * If next<=0 send now or as soon as possible. */ 754 755 /* Technical part. Looks wicked. Could be dropped, 756 * if everyone used the newest kernel. :-) 757 * Its purpose is: 758 * 1. Provide intervals less than resolution of scheduler. 759 * Solution: spinning. 760 * 2. Avoid use of poll(), when recvmsg() can provide 761 * timed waiting (SO_RCVTIMEO). */ 762 polling = 0; 763 if ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || next<SCHINT(interval)) { 764 int recv_expected = in_flight(); 765 766 /* If we are here, recvmsg() is unable to wait for 767 * required timeout. */ 768 if (1000 % HZ == 0 ? next <= 1000 / HZ : (next < INT_MAX / HZ && next * HZ <= 1000)) { 769 /* Very short timeout... So, if we wait for 770 * something, we sleep for MININTERVAL. 771 * Otherwise, spin! */ 772 if (recv_expected) { 773 next = MININTERVAL; 774 } else { 775 next = 0; 776 /* When spinning, no reasons to poll. 777 * Use nonblocking recvmsg() instead. */ 778 polling = MSG_DONTWAIT; 779 /* But yield yet. */ 780 sched_yield(); 781 } 782 } 783 784 if (!polling && 785 ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || interval)) { 786 struct pollfd pset; 787 pset.fd = icmp_sock; 788 pset.events = POLLIN|POLLERR; 789 pset.revents = 0; 790 if (poll(&pset, 1, next) < 1 || 791 !(pset.revents&(POLLIN|POLLERR))) 792 continue; 793 polling = MSG_DONTWAIT; 794 } 795 } 796 797 for (;;) { 798 struct timeval *recv_timep = NULL; 799 struct timeval recv_time; 800 int not_ours = 0; /* Raw socket can receive messages 801 * destined to other running pings. */ 802 803 iov.iov_len = packlen; 804 memset(&msg, 0, sizeof(msg)); 805 msg.msg_name = addrbuf; 806 msg.msg_namelen = sizeof(addrbuf); 807 msg.msg_iov = &iov; 808 msg.msg_iovlen = 1; 809 msg.msg_control = ans_data; 810 msg.msg_controllen = sizeof(ans_data); 811 812 cc = recvmsg(icmp_sock, &msg, polling); 813 polling = MSG_DONTWAIT; 814 815 if (cc < 0) { 816 if (errno == EAGAIN || errno == EINTR) 817 break; 818 if (!receive_error_msg()) { 819 if (errno) { 820 perror("ping: recvmsg"); 821 break; 822 } 823 not_ours = 1; 824 } 825 } else { 826 827 #ifdef SO_TIMESTAMP 828 for (c = CMSG_FIRSTHDR(&msg); c; c = CMSG_NXTHDR(&msg, c)) { 829 if (c->cmsg_level != SOL_SOCKET || 830 c->cmsg_type != SO_TIMESTAMP) 831 continue; 832 if (c->cmsg_len < CMSG_LEN(sizeof(struct timeval))) 833 continue; 834 recv_timep = (struct timeval*)CMSG_DATA(c); 835 } 836 #endif 837 838 if ((options&F_LATENCY) || recv_timep == NULL) { 839 if ((options&F_LATENCY) || 840 ioctl(icmp_sock, SIOCGSTAMP, &recv_time)) 841 gettimeofday(&recv_time, NULL); 842 recv_timep = &recv_time; 843 } 844 845 not_ours = parse_reply(&msg, cc, addrbuf, recv_timep); 846 } 847 848 /* See? ... someone runs another ping on this host. */ 849 if (not_ours && !using_ping_socket) 850 install_filter(); 851 852 /* If nothing is in flight, "break" returns us to pinger. */ 853 if (in_flight() == 0) 854 break; 855 856 /* Otherwise, try to recvmsg() again. recvmsg() 857 * is nonblocking after the first iteration, so that 858 * if nothing is queued, it will receive EAGAIN 859 * and return to pinger. */ 860 } 861 } 862 finish(); 863 } 864 865 int gather_statistics(__u8 *icmph, int icmplen, 866 int cc, __u16 seq, int hops, 867 int csfailed, struct timeval *tv, char *from, 868 void (*pr_reply)(__u8 *icmph, int cc)) 869 { 870 int dupflag = 0; 871 long triptime = 0; 872 __u8 *ptr = icmph + icmplen; 873 874 ++nreceived; 875 if (!csfailed) 876 acknowledge(seq); 877 878 if (timing && cc >= 8+sizeof(struct timeval)) { 879 struct timeval tmp_tv; 880 memcpy(&tmp_tv, ptr, sizeof(tmp_tv)); 881 882 restamp: 883 tvsub(tv, &tmp_tv); 884 triptime = tv->tv_sec * 1000000 + tv->tv_usec; 885 if (triptime < 0) { 886 fprintf(stderr, "Warning: time of day goes back (%ldus), taking countermeasures.\n", triptime); 887 triptime = 0; 888 if (!(options & F_LATENCY)) { 889 gettimeofday(tv, NULL); 890 options |= F_LATENCY; 891 goto restamp; 892 } 893 } 894 if (!csfailed) { 895 tsum += triptime; 896 tsum2 += (long long)triptime * (long long)triptime; 897 if (triptime < tmin) 898 tmin = triptime; 899 if (triptime > tmax) 900 tmax = triptime; 901 if (!rtt) 902 rtt = triptime*8; 903 else 904 rtt += triptime-rtt/8; 905 if (options&F_ADAPTIVE) 906 update_interval(); 907 } 908 } 909 910 if (csfailed) { 911 ++nchecksum; 912 --nreceived; 913 } else if (rcvd_test(seq)) { 914 ++nrepeats; 915 --nreceived; 916 dupflag = 1; 917 } else { 918 rcvd_set(seq); 919 dupflag = 0; 920 } 921 confirm = confirm_flag; 922 923 if (options & F_QUIET) 924 return 1; 925 926 if (options & F_FLOOD) { 927 if (!csfailed) 928 write_stdout("\b \b", 3); 929 else 930 write_stdout("\bC", 2); 931 } else { 932 int i; 933 __u8 *cp, *dp; 934 935 print_timestamp(); 936 printf("%d bytes from %s:", cc, from); 937 938 if (pr_reply) 939 pr_reply(icmph, cc); 940 941 if (hops >= 0) 942 printf(" ttl=%d", hops); 943 944 if (cc < datalen+8) { 945 printf(" (truncated)\n"); 946 return 1; 947 } 948 if (timing) { 949 if (triptime >= 100000) 950 printf(" time=%ld ms", triptime/1000); 951 else if (triptime >= 10000) 952 printf(" time=%ld.%01ld ms", triptime/1000, 953 (triptime%1000)/100); 954 else if (triptime >= 1000) 955 printf(" time=%ld.%02ld ms", triptime/1000, 956 (triptime%1000)/10); 957 else 958 printf(" time=%ld.%03ld ms", triptime/1000, 959 triptime%1000); 960 } 961 if (dupflag) 962 printf(" (DUP!)"); 963 if (csfailed) 964 printf(" (BAD CHECKSUM!)"); 965 966 /* check the data */ 967 cp = ((u_char*)ptr) + sizeof(struct timeval); 968 dp = &outpack[8 + sizeof(struct timeval)]; 969 for (i = sizeof(struct timeval); i < datalen; ++i, ++cp, ++dp) { 970 if (*cp != *dp) { 971 printf("\nwrong data byte #%d should be 0x%x but was 0x%x", 972 i, *dp, *cp); 973 cp = (u_char*)ptr + sizeof(struct timeval); 974 for (i = sizeof(struct timeval); i < datalen; ++i, ++cp) { 975 if ((i % 32) == sizeof(struct timeval)) 976 printf("\n#%d\t", i); 977 printf("%x ", *cp); 978 } 979 break; 980 } 981 } 982 } 983 return 0; 984 } 985 986 static long llsqrt(long long a) 987 { 988 long long prev = ~((long long)1 << 63); 989 long long x = a; 990 991 if (x > 0) { 992 while (x < prev) { 993 prev = x; 994 x = (x+(a/x))/2; 995 } 996 } 997 998 return (long)x; 999 } 1000 1001 /* 1002 * finish -- 1003 * Print out statistics, and give up. 1004 */ 1005 void finish(void) 1006 { 1007 struct timeval tv = cur_time; 1008 char *comma = ""; 1009 1010 tvsub(&tv, &start_time); 1011 1012 putchar('\n'); 1013 fflush(stdout); 1014 printf("--- %s ping statistics ---\n", hostname); 1015 printf("%ld packets transmitted, ", ntransmitted); 1016 printf("%ld received", nreceived); 1017 if (nrepeats) 1018 printf(", +%ld duplicates", nrepeats); 1019 if (nchecksum) 1020 printf(", +%ld corrupted", nchecksum); 1021 if (nerrors) 1022 printf(", +%ld errors", nerrors); 1023 if (ntransmitted) { 1024 printf(", %d%% packet loss", 1025 (int) ((((long long)(ntransmitted - nreceived)) * 100) / 1026 ntransmitted)); 1027 printf(", time %ldms", 1000*tv.tv_sec+tv.tv_usec/1000); 1028 } 1029 putchar('\n'); 1030 1031 if (nreceived && timing) { 1032 long tmdev; 1033 1034 tsum /= nreceived + nrepeats; 1035 tsum2 /= nreceived + nrepeats; 1036 tmdev = llsqrt(tsum2 - tsum * tsum); 1037 1038 printf("rtt min/avg/max/mdev = %ld.%03ld/%lu.%03ld/%ld.%03ld/%ld.%03ld ms", 1039 (long)tmin/1000, (long)tmin%1000, 1040 (unsigned long)(tsum/1000), (long)(tsum%1000), 1041 (long)tmax/1000, (long)tmax%1000, 1042 (long)tmdev/1000, (long)tmdev%1000 1043 ); 1044 comma = ", "; 1045 } 1046 if (pipesize > 1) { 1047 printf("%spipe %d", comma, pipesize); 1048 comma = ", "; 1049 } 1050 if (nreceived && (!interval || (options&(F_FLOOD|F_ADAPTIVE))) && ntransmitted > 1) { 1051 int ipg = (1000000*(long long)tv.tv_sec+tv.tv_usec)/(ntransmitted-1); 1052 printf("%sipg/ewma %d.%03d/%d.%03d ms", 1053 comma, ipg/1000, ipg%1000, rtt/8000, (rtt/8)%1000); 1054 } 1055 putchar('\n'); 1056 exit(!nreceived || (deadline && nreceived < npackets)); 1057 } 1058 1059 1060 void status(void) 1061 { 1062 int loss = 0; 1063 long tavg = 0; 1064 1065 status_snapshot = 0; 1066 1067 if (ntransmitted) 1068 loss = (((long long)(ntransmitted - nreceived)) * 100) / ntransmitted; 1069 1070 fprintf(stderr, "\r%ld/%ld packets, %d%% loss", ntransmitted, nreceived, loss); 1071 1072 if (nreceived && timing) { 1073 tavg = tsum / (nreceived + nrepeats); 1074 1075 fprintf(stderr, ", min/avg/ewma/max = %ld.%03ld/%lu.%03ld/%d.%03d/%ld.%03ld ms", 1076 (long)tmin/1000, (long)tmin%1000, 1077 tavg/1000, tavg%1000, 1078 rtt/8000, (rtt/8)%1000, 1079 (long)tmax/1000, (long)tmax%1000 1080 ); 1081 } 1082 fprintf(stderr, "\n"); 1083 } 1084 1085 inline int is_ours(uint16_t id) { 1086 return using_ping_socket || id == ident; 1087 } 1088 1089