1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Mike Muuss. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 #ifndef lint 38 char copyright[] = 39 "@(#) Copyright (c) 1989 The Regents of the University of California.\n\ 40 All rights reserved.\n"; 41 #endif /* not lint */ 42 43 /* 44 * P I N G . C 45 * 46 * Using the InterNet Control Message Protocol (ICMP) "ECHO" facility, 47 * measure round-trip-delays and packet loss across network paths. 48 * 49 * Author - 50 * Mike Muuss 51 * U. S. Army Ballistic Research Laboratory 52 * December, 1983 53 * 54 * Status - 55 * Public Domain. Distribution Unlimited. 56 * Bugs - 57 * More statistics could always be gathered. 58 * This program has to run SUID to ROOT to access the ICMP socket. 59 */ 60 61 #include "ping_common.h" 62 63 #include <netinet/ip.h> 64 #include <linux/icmp.h> 65 #include <sched.h> 66 67 #define bzero(b,sz) memset(b, 0, sz) 68 69 /* PING COMMON */ 70 71 int options; 72 73 int sndbuf; 74 int ttl; 75 int rtt; 76 int rtt_addend; 77 __u16 acked; 78 79 int mx_dup_ck = MAX_DUP_CHK; 80 char rcvd_tbl[MAX_DUP_CHK / 8]; 81 82 83 /* counters */ 84 long npackets; /* max packets to transmit */ 85 long nreceived; /* # of packets we got back */ 86 long nrepeats; /* number of duplicates */ 87 long ntransmitted; /* sequence # for outbound packets = #sent */ 88 long nchecksum; /* replies with bad checksum */ 89 long nerrors; /* icmp errors */ 90 int interval = 1000; /* interval between packets (msec) */ 91 int preload; 92 int deadline = 0; /* time to die */ 93 int lingertime = MAXWAIT*1000; 94 struct timeval start_time, cur_time; 95 volatile int exiting; 96 volatile int status_snapshot; 97 int confirm = 0; 98 99 /* Stupid workarounds for bugs/missing functionality in older linuces. 100 * confirm_flag fixes refusing service of kernels without MSG_CONFIRM. 101 * i.e. for linux-2.2 */ 102 int confirm_flag = MSG_CONFIRM; 103 /* And this is workaround for bug in IP_RECVERR on raw sockets which is present 104 * in linux-2.2.[0-19], linux-2.4.[0-7] */ 105 int working_recverr; 106 107 /* timing */ 108 int timing; /* flag to do timing */ 109 long tmin = LONG_MAX; /* minimum round trip time */ 110 long tmax; /* maximum round trip time */ 111 /* Message for rpm maintainers: have _shame_. If you want 112 * to fix something send the patch to me for sanity checking. 113 * "sparcfix" patch is a complete non-sense, apparenly the person 114 * prepared it was stoned. 115 */ 116 long long tsum; /* sum of all times, for doing average */ 117 long long tsum2; 118 int pipesize = -1; 119 120 int datalen = DEFDATALEN; 121 122 char *hostname; 123 int uid; 124 int ident; /* process id to identify our packets */ 125 126 static int screen_width = INT_MAX; 127 128 /* Fills all the outpack, excluding ICMP header, but _including_ 129 * timestamp area with supplied pattern. 130 */ 131 static void fill(char *patp) 132 { 133 int ii, jj, kk; 134 int pat[16]; 135 char *cp; 136 char *bp = outpack+8; 137 138 for (cp = patp; *cp; cp++) { 139 if (!isxdigit(*cp)) { 140 fprintf(stderr, 141 "ping: patterns must be specified as hex digits.\n"); 142 exit(2); 143 } 144 } 145 ii = sscanf(patp, 146 "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x", 147 &pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6], 148 &pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12], 149 &pat[13], &pat[14], &pat[15]); 150 151 if (ii > 0) { 152 for (kk = 0; kk <= maxpacket - (8 + ii); kk += ii) 153 for (jj = 0; jj < ii; ++jj) 154 bp[jj + kk] = pat[jj]; 155 } 156 if (!(options & F_QUIET)) { 157 printf("PATTERN: 0x"); 158 for (jj = 0; jj < ii; ++jj) 159 printf("%02x", bp[jj] & 0xFF); 160 printf("\n"); 161 } 162 } 163 164 void common_options(int ch) 165 { 166 switch(ch) { 167 case 'a': 168 options |= F_AUDIBLE; 169 break; 170 case 'A': 171 options |= F_ADAPTIVE; 172 break; 173 case 'c': 174 npackets = atoi(optarg); 175 if (npackets <= 0) { 176 fprintf(stderr, "ping: bad number of packets to transmit.\n"); 177 exit(2); 178 } 179 break; 180 case 'd': 181 options |= F_SO_DEBUG; 182 break; 183 case 'f': 184 options |= F_FLOOD; 185 //setbuf(stdout, (char *)NULL); 186 break; 187 case 'i': /* wait between sending packets */ 188 { 189 if (strchr(optarg, '.')) { 190 float t; 191 if (sscanf(optarg, "%f", &t) != 1) { 192 fprintf(stderr, "ping: bad timing interval.\n"); 193 exit(2); 194 } 195 interval = (int)(t*1000); 196 } else if (sscanf(optarg, "%d", &interval) == 1) { 197 interval *= 1000; 198 } else { 199 fprintf(stderr, "ping: bad timing interval.\n"); 200 exit(2); 201 } 202 203 if (interval < 0) { 204 fprintf(stderr, "ping: bad timing interval.\n"); 205 exit(2); 206 } 207 options |= F_INTERVAL; 208 break; 209 } 210 case 'w': 211 deadline = atoi(optarg); 212 if (deadline < 0) { 213 fprintf(stderr, "ping: bad wait time.\n"); 214 exit(2); 215 } 216 break; 217 case 'l': 218 preload = atoi(optarg); 219 if (preload <= 0) { 220 fprintf(stderr, "ping: bad preload value, should be 1..%d\n", mx_dup_ck); 221 exit(2); 222 } 223 if (preload > mx_dup_ck) 224 preload = mx_dup_ck; 225 if (uid && preload > 3) { 226 fprintf(stderr, "ping: cannot set preload to value > 3\n"); 227 exit(2); 228 } 229 break; 230 case 'S': 231 sndbuf = atoi(optarg); 232 if (sndbuf <= 0) { 233 fprintf(stderr, "ping: bad sndbuf value.\n"); 234 exit(2); 235 } 236 break; 237 case 'n': 238 options |= F_NUMERIC; 239 break; 240 case 'p': /* fill buffer with user pattern */ 241 options |= F_PINGFILLED; 242 fill(optarg); 243 break; 244 case 'q': 245 options |= F_QUIET; 246 break; 247 case 'r': 248 options |= F_SO_DONTROUTE; 249 break; 250 case 's': /* size of packet to send */ 251 datalen = atoi(optarg); 252 if (datalen < 0) { 253 fprintf(stderr, "ping: illegal negative packet size %d.\n", datalen); 254 exit(2); 255 } 256 break; 257 case 'v': 258 options |= F_VERBOSE; 259 break; 260 case 'L': 261 options |= F_NOLOOP; 262 break; 263 case 't': 264 options |= F_TTL; 265 ttl = atoi(optarg); 266 if (ttl < 0 || ttl > 255) { 267 fprintf(stderr, "ping: ttl %u out of range\n", ttl); 268 exit(2); 269 } 270 break; 271 case 'U': 272 options |= F_LATENCY; 273 break; 274 case 'B': 275 options |= F_STRICTSOURCE; 276 break; 277 case 'W': 278 lingertime = atoi(optarg); 279 if (lingertime < 0 || lingertime > INT_MAX/1000000) { 280 fprintf(stderr, "ping: bad linger time.\n"); 281 exit(2); 282 } 283 lingertime *= 1000; 284 break; 285 case 'V': 286 printf("ping utility, iputils-ss\n"); 287 exit(0); 288 default: 289 abort(); 290 } 291 } 292 293 294 static void sigexit(int signo) 295 { 296 exiting = 1; 297 } 298 299 static void sigstatus(int signo) 300 { 301 status_snapshot = 1; 302 } 303 304 305 int __schedule_exit(int next) 306 { 307 static unsigned long waittime; 308 struct itimerval it; 309 310 if (waittime) 311 return next; 312 313 if (nreceived) { 314 waittime = 2 * tmax; 315 if (waittime < 1000*interval) 316 waittime = 1000*interval; 317 } else 318 waittime = lingertime*1000; 319 320 if (next < 0 || next < waittime/1000) 321 next = waittime/1000; 322 323 it.it_interval.tv_sec = 0; 324 it.it_interval.tv_usec = 0; 325 it.it_value.tv_sec = waittime/1000000; 326 it.it_value.tv_usec = waittime%1000000; 327 setitimer(ITIMER_REAL, &it, NULL); 328 return next; 329 } 330 331 static inline void update_interval(void) 332 { 333 int est = rtt ? rtt/8 : interval*1000; 334 335 interval = (est+rtt_addend+500)/1000; 336 if (uid && interval < MINUSERINTERVAL) 337 interval = MINUSERINTERVAL; 338 } 339 340 /* 341 * pinger -- 342 * Compose and transmit an ICMP ECHO REQUEST packet. The IP packet 343 * will be added on by the kernel. The ID field is our UNIX process ID, 344 * and the sequence number is an ascending integer. The first 8 bytes 345 * of the data portion are used to hold a UNIX "timeval" struct in VAX 346 * byte-order, to compute the round-trip time. 347 */ 348 int pinger(void) 349 { 350 static int oom_count; 351 static int tokens; 352 int i; 353 354 /* Have we already sent enough? If we have, return an arbitrary positive value. */ 355 if (exiting || (npackets && ntransmitted >= npackets && !deadline)) 356 return 1000; 357 358 /* Check that packets < rate*time + preload */ 359 if (cur_time.tv_sec == 0) { 360 gettimeofday(&cur_time, NULL); 361 tokens = interval*(preload-1); 362 } else { 363 long ntokens; 364 struct timeval tv; 365 366 gettimeofday(&tv, NULL); 367 ntokens = (tv.tv_sec - cur_time.tv_sec)*1000 + 368 (tv.tv_usec-cur_time.tv_usec)/1000; 369 if (!interval) { 370 /* Case of unlimited flood is special; 371 * if we see no reply, they are limited to 100pps */ 372 if (ntokens < MININTERVAL && in_flight() >= preload) 373 return MININTERVAL-ntokens; 374 } 375 ntokens += tokens; 376 if (ntokens > interval*preload) 377 ntokens = interval*preload; 378 if (ntokens < interval) 379 return interval - ntokens; 380 381 cur_time = tv; 382 tokens = ntokens - interval; 383 } 384 385 resend: 386 i = send_probe(); 387 388 if (i == 0) { 389 oom_count = 0; 390 advance_ntransmitted(); 391 if (!(options & F_QUIET) && (options & F_FLOOD)) { 392 /* Very silly, but without this output with 393 * high preload or pipe size is very confusing. */ 394 if ((preload < screen_width && pipesize < screen_width) || 395 in_flight() < screen_width) 396 write(STDOUT_FILENO, ".", 1); 397 } 398 return interval - tokens; 399 } 400 401 /* And handle various errors... */ 402 if (i > 0) { 403 /* Apparently, it is some fatal bug. */ 404 abort(); 405 } else if (errno == ENOBUFS || errno == ENOMEM) { 406 int nores_interval; 407 408 /* Device queue overflow or OOM. Packet is not sent. */ 409 tokens = 0; 410 /* Slowdown. This works only in adaptive mode (option -A) */ 411 rtt_addend += (rtt < 8*50000 ? rtt/8 : 50000); 412 if (options&F_ADAPTIVE) 413 update_interval(); 414 nores_interval = SCHINT(interval/2); 415 if (nores_interval > 500) 416 nores_interval = 500; 417 oom_count++; 418 if (oom_count*nores_interval < lingertime) 419 return nores_interval; 420 i = 0; 421 /* Fall to hard error. It is to avoid complete deadlock 422 * on stuck output device even when dealine was not requested. 423 * Expected timings are screwed up in any case, but we will 424 * exit some day. :-) */ 425 } else if (errno == EAGAIN) { 426 /* Socket buffer is full. */ 427 tokens += interval; 428 return MININTERVAL; 429 } else { 430 if ((i=receive_error_msg()) > 0) { 431 /* An ICMP error arrived. */ 432 tokens += interval; 433 return MININTERVAL; 434 } 435 /* Compatibility with old linuces. */ 436 if (i == 0 && confirm_flag && errno == EINVAL) { 437 confirm_flag = 0; 438 errno = 0; 439 } 440 if (!errno) 441 goto resend; 442 } 443 444 /* Hard local error. Pretend we sent packet. */ 445 advance_ntransmitted(); 446 447 if (i == 0 && !(options & F_QUIET)) { 448 if (options & F_FLOOD) 449 write(STDOUT_FILENO, "E", 1); 450 else 451 perror("ping: sendmsg"); 452 } 453 tokens = 0; 454 return SCHINT(interval); 455 } 456 457 /* Set socket buffers, "alloc" is an estimate of memory taken by single packet. */ 458 459 void sock_setbufs(int icmp_sock, int alloc) 460 { 461 int rcvbuf, hold; 462 int tmplen = sizeof(hold); 463 464 if (!sndbuf) 465 sndbuf = alloc; 466 setsockopt(icmp_sock, SOL_SOCKET, SO_SNDBUF, (char *)&sndbuf, sizeof(sndbuf)); 467 468 rcvbuf = hold = alloc * preload; 469 if (hold < 65536) 470 hold = 65536; 471 setsockopt(icmp_sock, SOL_SOCKET, SO_RCVBUF, (char *)&hold, sizeof(hold)); 472 if (getsockopt(icmp_sock, SOL_SOCKET, SO_RCVBUF, (char *)&hold, &tmplen) == 0) { 473 if (hold < rcvbuf) 474 fprintf(stderr, "WARNING: probably, rcvbuf is not enough to hold preload.\n"); 475 } 476 } 477 478 /* Protocol independent setup and parameter checks. */ 479 480 void setup(int icmp_sock) 481 { 482 int hold; 483 struct timeval tv; 484 485 if ((options & F_FLOOD) && !(options & F_INTERVAL)) 486 interval = 0; 487 488 if (uid && interval < MINUSERINTERVAL) { 489 fprintf(stderr, "ping: cannot flood; minimal interval, allowed for user, is %dms\n", MINUSERINTERVAL); 490 exit(2); 491 } 492 493 if (interval >= INT_MAX/preload) { 494 fprintf(stderr, "ping: illegal preload and/or interval\n"); 495 exit(2); 496 } 497 498 hold = 1; 499 if (options & F_SO_DEBUG) 500 setsockopt(icmp_sock, SOL_SOCKET, SO_DEBUG, (char *)&hold, sizeof(hold)); 501 if (options & F_SO_DONTROUTE) 502 setsockopt(icmp_sock, SOL_SOCKET, SO_DONTROUTE, (char *)&hold, sizeof(hold)); 503 504 #ifdef SO_TIMESTAMP 505 if (!(options&F_LATENCY)) { 506 int on = 1; 507 if (setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on))) 508 fprintf(stderr, "Warning: no SO_TIMESTAMP support, falling back to SIOCGSTAMP\n"); 509 } 510 #endif 511 512 /* Set some SNDTIMEO to prevent blocking forever 513 * on sends, when device is too slow or stalls. Just put limit 514 * of one second, or "interval", if it is less. 515 */ 516 tv.tv_sec = 1; 517 tv.tv_usec = 0; 518 if (interval < 1000) { 519 tv.tv_sec = 0; 520 tv.tv_usec = 1000 * SCHINT(interval); 521 } 522 setsockopt(icmp_sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(tv)); 523 524 /* Set RCVTIMEO to "interval". Note, it is just an optimization 525 * allowing to avoid redundant poll(). */ 526 tv.tv_sec = SCHINT(interval)/1000; 527 tv.tv_usec = 1000*(SCHINT(interval)%1000); 528 if (setsockopt(icmp_sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(tv))) 529 options |= F_FLOOD_POLL; 530 531 if (!(options & F_PINGFILLED)) { 532 int i; 533 char *p = outpack+8; 534 535 /* Do not forget about case of small datalen, 536 * fill timestamp area too! 537 */ 538 for (i = 0; i < datalen; ++i) 539 *p++ = i; 540 } 541 542 ident = getpid() & 0xFFFF; 543 544 set_signal(SIGINT, sigexit); 545 set_signal(SIGALRM, sigexit); 546 set_signal(SIGQUIT, sigstatus); 547 548 gettimeofday(&start_time, NULL); 549 550 if (deadline) { 551 struct itimerval it; 552 553 it.it_interval.tv_sec = 0; 554 it.it_interval.tv_usec = 0; 555 it.it_value.tv_sec = deadline; 556 it.it_value.tv_usec = 0; 557 setitimer(ITIMER_REAL, &it, NULL); 558 } 559 560 #if 0 561 if (isatty(STDOUT_FILENO)) { 562 struct winsize w; 563 564 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1) { 565 if (w.ws_col > 0) 566 screen_width = w.ws_col; 567 } 568 } 569 #endif 570 } 571 572 void main_loop(int icmp_sock, __u8 *packet, int packlen) 573 { 574 char addrbuf[128]; 575 char ans_data[4096]; 576 struct iovec iov; 577 struct msghdr msg; 578 struct cmsghdr *c; 579 int cc; 580 int next; 581 int polling; 582 583 iov.iov_base = (char *)packet; 584 585 for (;;) { 586 /* Check exit conditions. */ 587 if (exiting) 588 break; 589 if (npackets && nreceived + nerrors >= npackets) 590 break; 591 if (deadline && nerrors) 592 break; 593 /* Check for and do special actions. */ 594 if (status_snapshot) 595 status(); 596 597 /* Send probes scheduled to this time. */ 598 do { 599 next = pinger(); 600 next = schedule_exit(next); 601 } while (next <= 0); 602 603 /* "next" is time to send next probe, if positive. 604 * If next<=0 send now or as soon as possible. */ 605 606 /* Technical part. Looks wicked. Could be dropped, 607 * if everyone used the newest kernel. :-) 608 * Its purpose is: 609 * 1. Provide intervals less than resolution of scheduler. 610 * Solution: spinning. 611 * 2. Avoid use of poll(), when recvmsg() can provide 612 * timed waiting (SO_RCVTIMEO). */ 613 polling = 0; 614 if ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || next<SCHINT(interval)) { 615 int recv_expected = in_flight(); 616 617 /* If we are here, recvmsg() is unable to wait for 618 * required timeout. */ 619 if (1000*next <= 1000000/(int)HZ) { 620 /* Very short timeout... So, if we wait for 621 * something, we sleep for MININTERVAL. 622 * Otherwise, spin! */ 623 if (recv_expected) { 624 next = MININTERVAL; 625 } else { 626 next = 0; 627 /* When spinning, no reasons to poll. 628 * Use nonblocking recvmsg() instead. */ 629 polling = MSG_DONTWAIT; 630 /* But yield yet. */ 631 sched_yield(); 632 } 633 } 634 635 if (!polling && 636 ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || interval)) { 637 struct pollfd pset; 638 pset.fd = icmp_sock; 639 pset.events = POLLIN|POLLERR; 640 pset.revents = 0; 641 if (poll(&pset, 1, next) < 1 || 642 !(pset.revents&(POLLIN|POLLERR))) 643 continue; 644 polling = MSG_DONTWAIT; 645 } 646 } 647 648 for (;;) { 649 struct timeval *recv_timep = NULL; 650 struct timeval recv_time; 651 int not_ours = 0; /* Raw socket can receive messages 652 * destined to other running pings. */ 653 654 iov.iov_len = packlen; 655 msg.msg_name = addrbuf; 656 msg.msg_namelen = sizeof(addrbuf); 657 msg.msg_iov = &iov; 658 msg.msg_iovlen = 1; 659 msg.msg_control = ans_data; 660 msg.msg_controllen = sizeof(ans_data); 661 662 cc = recvmsg(icmp_sock, &msg, polling); 663 polling = MSG_DONTWAIT; 664 665 if (cc < 0) { 666 if (errno == EAGAIN || errno == EINTR) 667 break; 668 if (!receive_error_msg()) { 669 if (errno) { 670 perror("ping: recvmsg"); 671 break; 672 } 673 not_ours = 1; 674 } 675 } else { 676 677 #ifdef SO_TIMESTAMP 678 for (c = CMSG_FIRSTHDR(&msg); c; c = CMSG_NXTHDR(&msg, c)) { 679 if (c->cmsg_level != SOL_SOCKET || 680 c->cmsg_type != SO_TIMESTAMP) 681 continue; 682 if (c->cmsg_len < CMSG_LEN(sizeof(struct timeval))) 683 continue; 684 recv_timep = (struct timeval*)CMSG_DATA(c); 685 } 686 #endif 687 688 if ((options&F_LATENCY) || recv_timep == NULL) { 689 if ((options&F_LATENCY) || 690 ioctl(icmp_sock, SIOCGSTAMP, &recv_time)) 691 gettimeofday(&recv_time, NULL); 692 recv_timep = &recv_time; 693 } 694 695 not_ours = parse_reply(&msg, cc, addrbuf, recv_timep); 696 } 697 698 /* See? ... someone runs another ping on this host. */ 699 if (not_ours) 700 install_filter(); 701 702 /* If nothing is in flight, "break" returns us to pinger. */ 703 if (in_flight() == 0) 704 break; 705 706 /* Otherwise, try to recvmsg() again. recvmsg() 707 * is nonblocking after the first iteration, so that 708 * if nothing is queued, it will receive EAGAIN 709 * and return to pinger. */ 710 } 711 } 712 finish(); 713 } 714 715 int gather_statistics(__u8 *ptr, int cc, __u16 seq, int hops, 716 int csfailed, struct timeval *tv, char *from) 717 { 718 int dupflag = 0; 719 long triptime = 0; 720 721 ++nreceived; 722 if (!csfailed) 723 acknowledge(seq); 724 725 if (timing && cc >= 8+sizeof(struct timeval)) { 726 struct timeval tmp_tv; 727 memcpy(&tmp_tv, ptr, sizeof(tmp_tv)); 728 729 restamp: 730 tvsub(tv, &tmp_tv); 731 triptime = tv->tv_sec * 1000000 + tv->tv_usec; 732 if (triptime < 0) { 733 fprintf(stderr, "Warning: time of day goes back (%ldus), taking countermeasures.\n", triptime); 734 triptime = 0; 735 if (!(options & F_LATENCY)) { 736 gettimeofday(tv, NULL); 737 options |= F_LATENCY; 738 goto restamp; 739 } 740 } 741 if (!csfailed) { 742 tsum += triptime; 743 tsum2 += (long long)triptime * (long long)triptime; 744 if (triptime < tmin) 745 tmin = triptime; 746 if (triptime > tmax) 747 tmax = triptime; 748 if (!rtt) 749 rtt = triptime*8; 750 else 751 rtt += triptime-rtt/8; 752 if (options&F_ADAPTIVE) 753 update_interval(); 754 } 755 } 756 757 if (csfailed) { 758 ++nchecksum; 759 --nreceived; 760 } else if (TST(seq % mx_dup_ck)) { 761 ++nrepeats; 762 --nreceived; 763 dupflag = 1; 764 } else { 765 SET(seq % mx_dup_ck); 766 dupflag = 0; 767 } 768 confirm = confirm_flag; 769 770 if (options & F_QUIET) 771 return 1; 772 773 if (options & F_FLOOD) { 774 if (!csfailed) 775 write(STDOUT_FILENO, "\b \b", 3); 776 else 777 write(STDOUT_FILENO, "\bC", 1); 778 } else { 779 int i; 780 __u8 *cp, *dp; 781 printf("%d bytes from %s: icmp_seq=%u", cc, from, seq); 782 783 if (hops >= 0) 784 printf(" ttl=%d", hops); 785 786 if (cc < datalen+8) { 787 printf(" (truncated)\n"); 788 return 1; 789 } 790 if (timing) { 791 if (triptime >= 100000) 792 printf(" time=%ld ms", triptime/1000); 793 else if (triptime >= 10000) 794 printf(" time=%ld.%01ld ms", triptime/1000, 795 (triptime%1000)/100); 796 else if (triptime >= 1000) 797 printf(" time=%ld.%02ld ms", triptime/1000, 798 (triptime%1000)/10); 799 else 800 printf(" time=%ld.%03ld ms", triptime/1000, 801 triptime%1000); 802 } 803 if (dupflag) 804 printf(" (DUP!)"); 805 if (csfailed) 806 printf(" (BAD CHECKSUM!)"); 807 808 /* check the data */ 809 cp = ((u_char*)ptr) + sizeof(struct timeval); 810 dp = &outpack[8 + sizeof(struct timeval)]; 811 for (i = sizeof(struct timeval); i < datalen; ++i, ++cp, ++dp) { 812 if (*cp != *dp) { 813 printf("\nwrong data byte #%d should be 0x%x but was 0x%x", 814 i, *dp, *cp); 815 cp = (u_char*)ptr + sizeof(struct timeval); 816 for (i = sizeof(struct timeval); i < datalen; ++i, ++cp) { 817 if ((i % 32) == sizeof(struct timeval)) 818 printf("\n#%d\t", i); 819 printf("%x ", *cp); 820 } 821 break; 822 } 823 } 824 } 825 return 0; 826 } 827 828 static long llsqrt(long long a) 829 { 830 long long prev = ~((long long)1 << 63); 831 long long x = a; 832 833 if (x > 0) { 834 while (x < prev) { 835 prev = x; 836 x = (x+(a/x))/2; 837 } 838 } 839 840 return (long)x; 841 } 842 843 /* 844 * finish -- 845 * Print out statistics, and give up. 846 */ 847 void finish(void) 848 { 849 struct timeval tv = cur_time; 850 851 tvsub(&tv, &start_time); 852 853 putchar('\n'); 854 fflush(stdout); 855 printf("--- %s ping statistics ---\n", hostname); 856 printf("%ld packets transmitted, ", ntransmitted); 857 printf("%ld received", nreceived); 858 if (nrepeats) 859 printf(", +%ld duplicates", nrepeats); 860 if (nchecksum) 861 printf(", +%ld corrupted", nchecksum); 862 if (nerrors) 863 printf(", +%ld errors", nerrors); 864 if (ntransmitted) { 865 printf(", %d%% packet loss", 866 (int) ((((long long)(ntransmitted - nreceived)) * 100) / 867 ntransmitted)); 868 printf(", time %ldms", 1000*tv.tv_sec+tv.tv_usec/1000); 869 } 870 putchar('\n'); 871 872 if (nreceived && timing) { 873 long tmdev; 874 875 tsum /= nreceived + nrepeats; 876 tsum2 /= nreceived + nrepeats; 877 tmdev = llsqrt(tsum2 - tsum * tsum); 878 879 printf("rtt min/avg/max/mdev = %ld.%03ld/%lu.%03ld/%ld.%03ld/%ld.%03ld ms", 880 tmin/1000, tmin%1000, 881 (unsigned long)(tsum/1000), (long)(tsum%1000), 882 tmax/1000, tmax%1000, 883 tmdev/1000, tmdev%1000 884 ); 885 } 886 if (pipesize > 1) 887 printf(", pipe %d", pipesize); 888 if (ntransmitted > 1 && (!interval || (options&(F_FLOOD|F_ADAPTIVE)))) { 889 int ipg = (1000000*(long long)tv.tv_sec+tv.tv_usec)/(ntransmitted-1); 890 printf(", ipg/ewma %d.%03d/%d.%03d ms", 891 ipg/1000, ipg%1000, rtt/8000, (rtt/8)%1000); 892 } 893 putchar('\n'); 894 exit(!nreceived || (deadline && nreceived < npackets)); 895 } 896 897 898 void status(void) 899 { 900 int loss = 0; 901 long tavg = 0; 902 903 status_snapshot = 0; 904 905 if (ntransmitted) 906 loss = (((long long)(ntransmitted - nreceived)) * 100) / ntransmitted; 907 908 fprintf(stderr, "\r%ld/%ld packets, %d%% loss", ntransmitted, nreceived, loss); 909 910 if (nreceived && timing) { 911 tavg = tsum / (nreceived + nrepeats); 912 913 fprintf(stderr, ", min/avg/ewma/max = %ld.%03ld/%lu.%03ld/%d.%03d/%ld.%03ld ms", 914 tmin/1000, tmin%1000, 915 tavg/1000, tavg%1000, 916 rtt/8000, (rtt/8)%1000, 917 tmax/1000, tmax%1000 918 ); 919 } 920 fprintf(stderr, "\n"); 921 } 922 923 /* PING COMMON */ 924 925 #define MAXIPLEN 60 926 #define MAXICMPLEN 76 927 #define NROUTES 9 /* number of record route slots */ 928 #define TOS_MAX 255 /* 8-bit TOS field */ 929 930 931 static int ts_type; 932 static int nroute = 0; 933 static __u32 route[10]; 934 935 936 937 struct sockaddr_in whereto; /* who to ping */ 938 int optlen = 0; 939 int settos = 0; /* Set TOS, Precendence or other QOS options */ 940 int icmp_sock; /* socket file descriptor */ 941 u_char outpack[0x10000]; 942 int maxpacket = sizeof(outpack); 943 944 static int broadcast_pings = 0; 945 946 static char *pr_addr(__u32); 947 static void pr_options(unsigned char * cp, int hlen); 948 static void pr_iph(struct iphdr *ip); 949 static void usage(void) __attribute__((noreturn)); 950 static u_short in_cksum(const u_short *addr, int len, u_short salt); 951 static void pr_icmph(__u8 type, __u8 code, __u32 info, struct icmphdr *icp); 952 static int parsetos(char *str); 953 954 static struct { 955 struct cmsghdr cm; 956 struct in_pktinfo ipi; 957 } cmsg = { {sizeof(struct cmsghdr) + sizeof(struct in_pktinfo), SOL_IP, IP_PKTINFO}, 958 {0, }}; 959 int cmsg_len; 960 961 struct sockaddr_in source; 962 char *device; 963 int pmtudisc = -1; 964 965 int receive_error_msg() 966 { 967 int res; 968 char cbuf[512]; 969 struct iovec iov; 970 struct msghdr msg; 971 struct cmsghdr *cmsg; 972 struct sock_extended_err *e; 973 struct icmphdr icmph; 974 struct sockaddr_in target; 975 int net_errors = 0; 976 int local_errors = 0; 977 int saved_errno = errno; 978 979 iov.iov_base = &icmph; 980 iov.iov_len = sizeof(icmph); 981 msg.msg_name = (void*)⌖ 982 msg.msg_namelen = sizeof(target); 983 msg.msg_iov = &iov; 984 msg.msg_iovlen = 1; 985 msg.msg_flags = 0; 986 msg.msg_control = cbuf; 987 msg.msg_controllen = sizeof(cbuf); 988 989 res = recvmsg(icmp_sock, &msg, MSG_ERRQUEUE|MSG_DONTWAIT); 990 if (res < 0) 991 goto out; 992 993 e = NULL; 994 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { 995 if (cmsg->cmsg_level == SOL_IP) { 996 if (cmsg->cmsg_type == IP_RECVERR) 997 e = (struct sock_extended_err *)CMSG_DATA(cmsg); 998 } 999 } 1000 if (e == NULL) 1001 abort(); 1002 1003 if (e->ee_origin == SO_EE_ORIGIN_LOCAL) { 1004 local_errors++; 1005 if (options & F_QUIET) 1006 goto out; 1007 if (options & F_FLOOD) 1008 write(STDOUT_FILENO, "E", 1); 1009 else if (e->ee_errno != EMSGSIZE) 1010 fprintf(stderr, "ping: local error: %s\n", strerror(e->ee_errno)); 1011 else 1012 fprintf(stderr, "ping: local error: Message too long, mtu=%u\n", e->ee_info); 1013 nerrors++; 1014 } else if (e->ee_origin == SO_EE_ORIGIN_ICMP) { 1015 struct sockaddr_in *sin = (struct sockaddr_in*)(e+1); 1016 1017 if (res < sizeof(icmph) || 1018 target.sin_addr.s_addr != whereto.sin_addr.s_addr || 1019 icmph.type != ICMP_ECHO || 1020 icmph.un.echo.id != ident) { 1021 /* Not our error, not an error at all. Clear. */ 1022 saved_errno = 0; 1023 goto out; 1024 } 1025 1026 acknowledge(ntohs(icmph.un.echo.sequence)); 1027 1028 if (!working_recverr) { 1029 struct icmp_filter filt; 1030 working_recverr = 1; 1031 /* OK, it works. Add stronger filter. */ 1032 filt.data = ~((1<<ICMP_SOURCE_QUENCH)| 1033 (1<<ICMP_REDIRECT)| 1034 (1<<ICMP_ECHOREPLY)); 1035 if (setsockopt(icmp_sock, SOL_RAW, ICMP_FILTER, (char*)&filt, sizeof(filt)) == -1) 1036 perror("\rWARNING: setsockopt(ICMP_FILTER)"); 1037 } 1038 1039 net_errors++; 1040 nerrors++; 1041 if (options & F_QUIET) 1042 goto out; 1043 if (options & F_FLOOD) { 1044 write(STDOUT_FILENO, "\bE", 2); 1045 } else { 1046 printf("From %s icmp_seq=%u ", pr_addr(sin->sin_addr.s_addr), ntohs(icmph.un.echo.sequence)); 1047 pr_icmph(e->ee_type, e->ee_code, e->ee_info, NULL); 1048 fflush(stdout); 1049 } 1050 } 1051 1052 out: 1053 errno = saved_errno; 1054 return net_errors ? : -local_errors; 1055 } 1056 1057 /* 1058 * pinger -- 1059 * Compose and transmit an ICMP ECHO REQUEST packet. The IP packet 1060 * will be added on by the kernel. The ID field is our UNIX process ID, 1061 * and the sequence number is an ascending integer. The first 8 bytes 1062 * of the data portion are used to hold a UNIX "timeval" struct in VAX 1063 * byte-order, to compute the round-trip time. 1064 */ 1065 int send_probe() 1066 { 1067 struct icmphdr *icp; 1068 int cc; 1069 int i; 1070 1071 icp = (struct icmphdr *)outpack; 1072 icp->type = ICMP_ECHO; 1073 icp->code = 0; 1074 icp->checksum = 0; 1075 icp->un.echo.sequence = htons(ntransmitted+1); 1076 icp->un.echo.id = ident; /* ID */ 1077 1078 CLR((ntransmitted+1) % mx_dup_ck); 1079 1080 if (timing) { 1081 if (options&F_LATENCY) { 1082 static volatile int fake_fucked_egcs = sizeof(struct timeval); 1083 struct timeval tmp_tv; 1084 gettimeofday(&tmp_tv, NULL); 1085 /* egcs is crap or glibc is crap, but memcpy 1086 does not copy anything, if len is constant! */ 1087 memcpy(icp+1, &tmp_tv, fake_fucked_egcs); 1088 } else { 1089 memset(icp+1, 0, sizeof(struct timeval)); 1090 } 1091 } 1092 1093 cc = datalen + 8; /* skips ICMP portion */ 1094 1095 /* compute ICMP checksum here */ 1096 icp->checksum = in_cksum((u_short *)icp, cc, 0); 1097 1098 if (timing && !(options&F_LATENCY)) { 1099 static volatile int fake_fucked_egcs = sizeof(struct timeval); 1100 struct timeval tmp_tv; 1101 gettimeofday(&tmp_tv, NULL); 1102 /* egcs is crap or glibc is crap, but memcpy 1103 does not copy anything, if len is constant! */ 1104 memcpy(icp+1, &tmp_tv, fake_fucked_egcs); 1105 icp->checksum = in_cksum((u_short *)(icp+1), fake_fucked_egcs, ~icp->checksum); 1106 } 1107 1108 do { 1109 static struct iovec iov = {outpack, 0}; 1110 static struct msghdr m = { &whereto, sizeof(whereto), 1111 &iov, 1, &cmsg, 0, 0 }; 1112 m.msg_controllen = cmsg_len; 1113 iov.iov_len = cc; 1114 1115 i = sendmsg(icmp_sock, &m, confirm); 1116 confirm = 0; 1117 } while (0); 1118 1119 return (cc == i ? 0 : i); 1120 } 1121 1122 /* 1123 * parse_reply -- 1124 * Print out the packet, if it came from us. This logic is necessary 1125 * because ALL readers of the ICMP socket get a copy of ALL ICMP packets 1126 * which arrive ('tis only fair). This permits multiple copies of this 1127 * program to be run without having intermingled output (or statistics!). 1128 */ 1129 int 1130 parse_reply(struct msghdr *msg, int cc, void *addr, struct timeval *tv) 1131 { 1132 struct sockaddr_in *from = addr; 1133 __u8 *buf = msg->msg_iov->iov_base; 1134 struct icmphdr *icp; 1135 struct iphdr *ip; 1136 int hlen; 1137 int csfailed; 1138 1139 /* Check the IP header */ 1140 ip = (struct iphdr *)buf; 1141 hlen = ip->ihl*4; 1142 if (cc < hlen + 8 || ip->ihl < 5) { 1143 if (options & F_VERBOSE) 1144 fprintf(stderr, "ping: packet too short (%d bytes) from %s\n", cc, 1145 pr_addr(from->sin_addr.s_addr)); 1146 return 1; 1147 } 1148 1149 /* Now the ICMP part */ 1150 cc -= hlen; 1151 icp = (struct icmphdr *)(buf + hlen); 1152 csfailed = in_cksum((u_short *)icp, cc, 0); 1153 1154 if (icp->type == ICMP_ECHOREPLY) { 1155 if (icp->un.echo.id != ident) 1156 return 1; /* 'Twas not our ECHO */ 1157 if (gather_statistics((__u8*)(icp+1), cc, 1158 ntohs(icp->un.echo.sequence), 1159 ip->ttl, 0, tv, pr_addr(from->sin_addr.s_addr))) 1160 return 0; 1161 } else { 1162 /* We fall here when a redirect or source quench arrived. 1163 * Also this branch processes icmp errors, when IP_RECVERR 1164 * is broken. */ 1165 1166 switch (icp->type) { 1167 case ICMP_ECHO: 1168 /* MUST NOT */ 1169 return 1; 1170 case ICMP_SOURCE_QUENCH: 1171 case ICMP_REDIRECT: 1172 case ICMP_DEST_UNREACH: 1173 case ICMP_TIME_EXCEEDED: 1174 case ICMP_PARAMETERPROB: 1175 { 1176 struct iphdr * iph = (struct iphdr *)(&icp[1]); 1177 struct icmphdr *icp1 = (struct icmphdr*)((unsigned char *)iph + iph->ihl*4); 1178 int error_pkt; 1179 if (cc < 8+sizeof(struct iphdr)+8 || 1180 cc < 8+iph->ihl*4+8) 1181 return 1; 1182 if (icp1->type != ICMP_ECHO || 1183 iph->daddr != whereto.sin_addr.s_addr || 1184 icp1->un.echo.id != ident) 1185 return 1; 1186 error_pkt = (icp->type != ICMP_REDIRECT && 1187 icp->type != ICMP_SOURCE_QUENCH); 1188 if (error_pkt) { 1189 acknowledge(ntohs(icp1->un.echo.sequence)); 1190 if (working_recverr) { 1191 return 0; 1192 } else { 1193 static int once; 1194 /* Sigh, IP_RECVERR for raw socket 1195 * was broken until 2.4.9. So, we ignore 1196 * the first error and warn on the second. 1197 */ 1198 if (once++ == 1) 1199 fprintf(stderr, "\rWARNING: kernel is not very fresh, upgrade is recommended.\n"); 1200 if (once == 1) 1201 return 0; 1202 } 1203 } 1204 nerrors+=error_pkt; 1205 if (options&F_QUIET) 1206 return !error_pkt; 1207 if (options & F_FLOOD) { 1208 if (error_pkt) 1209 write(STDOUT_FILENO, "\bE", 2); 1210 return !error_pkt; 1211 } 1212 printf("From %s: icmp_seq=%u ", 1213 pr_addr(from->sin_addr.s_addr), 1214 ntohs(icp1->un.echo.sequence)); 1215 if (csfailed) 1216 printf("(BAD CHECKSUM)"); 1217 pr_icmph(icp->type, icp->code, ntohl(icp->un.gateway), icp); 1218 return !error_pkt; 1219 } 1220 default: 1221 /* MUST NOT */ 1222 break; 1223 } 1224 if ((options & F_FLOOD) && !(options & (F_VERBOSE|F_QUIET))) { 1225 if (!csfailed) 1226 write(STDOUT_FILENO, "!E", 2); 1227 else 1228 write(STDOUT_FILENO, "!EC", 3); 1229 return 0; 1230 } 1231 if (!(options & F_VERBOSE) || uid) 1232 return 0; 1233 printf("From %s: ", pr_addr(from->sin_addr.s_addr)); 1234 if (csfailed) { 1235 printf("(BAD CHECKSUM)\n"); 1236 return 0; 1237 } 1238 pr_icmph(icp->type, icp->code, ntohl(icp->un.gateway), icp); 1239 return 0; 1240 } 1241 1242 if (!(options & F_FLOOD)) { 1243 pr_options(buf + sizeof(struct iphdr), hlen); 1244 1245 if (options & F_AUDIBLE) 1246 putchar('\a'); 1247 putchar('\n'); 1248 fflush(stdout); 1249 } 1250 return 0; 1251 } 1252 1253 u_short 1254 in_cksum(const u_short *addr, register int len, u_short csum) 1255 { 1256 register int nleft = len; 1257 const u_short *w = addr; 1258 register u_short answer; 1259 register int sum = csum; 1260 1261 /* 1262 * Our algorithm is simple, using a 32 bit accumulator (sum), 1263 * we add sequential 16 bit words to it, and at the end, fold 1264 * back all the carry bits from the top 16 bits into the lower 1265 * 16 bits. 1266 */ 1267 while (nleft > 1) { 1268 sum += *w++; 1269 nleft -= 2; 1270 } 1271 1272 /* mop up an odd byte, if necessary */ 1273 if (nleft == 1) 1274 sum += htons(*(u_char *)w << 8); 1275 1276 /* 1277 * add back carry outs from top 16 bits to low 16 bits 1278 */ 1279 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 1280 sum += (sum >> 16); /* add carry */ 1281 answer = ~sum; /* truncate to 16 bits */ 1282 return (answer); 1283 } 1284 1285 /* 1286 * pr_icmph -- 1287 * Print a descriptive string about an ICMP header. 1288 */ 1289 void pr_icmph(__u8 type, __u8 code, __u32 info, struct icmphdr *icp) 1290 { 1291 switch(type) { 1292 case ICMP_ECHOREPLY: 1293 printf("Echo Reply\n"); 1294 /* XXX ID + Seq + Data */ 1295 break; 1296 case ICMP_DEST_UNREACH: 1297 switch(code) { 1298 case ICMP_NET_UNREACH: 1299 printf("Destination Net Unreachable\n"); 1300 break; 1301 case ICMP_HOST_UNREACH: 1302 printf("Destination Host Unreachable\n"); 1303 break; 1304 case ICMP_PROT_UNREACH: 1305 printf("Destination Protocol Unreachable\n"); 1306 break; 1307 case ICMP_PORT_UNREACH: 1308 printf("Destination Port Unreachable\n"); 1309 break; 1310 case ICMP_FRAG_NEEDED: 1311 printf("Frag needed and DF set (mtu = %u)\n", info); 1312 break; 1313 case ICMP_SR_FAILED: 1314 printf("Source Route Failed\n"); 1315 break; 1316 case ICMP_PKT_FILTERED: 1317 printf("Packet filtered\n"); 1318 break; 1319 default: 1320 printf("Dest Unreachable, Bad Code: %d\n", code); 1321 break; 1322 } 1323 if (icp && (options & F_VERBOSE)) 1324 pr_iph((struct iphdr*)(icp + 1)); 1325 break; 1326 case ICMP_SOURCE_QUENCH: 1327 printf("Source Quench\n"); 1328 if (icp && (options & F_VERBOSE)) 1329 pr_iph((struct iphdr*)(icp + 1)); 1330 break; 1331 case ICMP_REDIRECT: 1332 switch(code) { 1333 case ICMP_REDIR_NET: 1334 printf("Redirect Network"); 1335 break; 1336 case ICMP_REDIR_HOST: 1337 printf("Redirect Host"); 1338 break; 1339 case ICMP_REDIR_NETTOS: 1340 printf("Redirect Type of Service and Network"); 1341 break; 1342 case ICMP_REDIR_HOSTTOS: 1343 printf("Redirect Type of Service and Host"); 1344 break; 1345 default: 1346 printf("Redirect, Bad Code: %d", code); 1347 break; 1348 } 1349 if (icp) 1350 printf("(New nexthop: %s)\n", pr_addr(icp->un.gateway)); 1351 if (icp && (options & F_VERBOSE)) 1352 pr_iph((struct iphdr*)(icp + 1)); 1353 break; 1354 case ICMP_ECHO: 1355 printf("Echo Request\n"); 1356 /* XXX ID + Seq + Data */ 1357 break; 1358 case ICMP_TIME_EXCEEDED: 1359 switch(code) { 1360 case ICMP_EXC_TTL: 1361 printf("Time to live exceeded\n"); 1362 break; 1363 case ICMP_EXC_FRAGTIME: 1364 printf("Frag reassembly time exceeded\n"); 1365 break; 1366 default: 1367 printf("Time exceeded, Bad Code: %d\n", code); 1368 break; 1369 } 1370 if (icp && (options & F_VERBOSE)) 1371 pr_iph((struct iphdr*)(icp + 1)); 1372 break; 1373 case ICMP_PARAMETERPROB: 1374 printf("Parameter problem: pointer = %u\n", icp ? (ntohl(icp->un.gateway)>>24) : info); 1375 if (icp && (options & F_VERBOSE)) 1376 pr_iph((struct iphdr*)(icp + 1)); 1377 break; 1378 case ICMP_TIMESTAMP: 1379 printf("Timestamp\n"); 1380 /* XXX ID + Seq + 3 timestamps */ 1381 break; 1382 case ICMP_TIMESTAMPREPLY: 1383 printf("Timestamp Reply\n"); 1384 /* XXX ID + Seq + 3 timestamps */ 1385 break; 1386 case ICMP_INFO_REQUEST: 1387 printf("Information Request\n"); 1388 /* XXX ID + Seq */ 1389 break; 1390 case ICMP_INFO_REPLY: 1391 printf("Information Reply\n"); 1392 /* XXX ID + Seq */ 1393 break; 1394 #ifdef ICMP_MASKREQ 1395 case ICMP_MASKREQ: 1396 printf("Address Mask Request\n"); 1397 break; 1398 #endif 1399 #ifdef ICMP_MASKREPLY 1400 case ICMP_MASKREPLY: 1401 printf("Address Mask Reply\n"); 1402 break; 1403 #endif 1404 default: 1405 printf("Bad ICMP type: %d\n", type); 1406 } 1407 } 1408 1409 void pr_options(unsigned char * cp, int hlen) 1410 { 1411 int i, j; 1412 int optlen, totlen; 1413 unsigned char * optptr; 1414 static int old_rrlen; 1415 static char old_rr[MAX_IPOPTLEN]; 1416 1417 totlen = hlen-sizeof(struct iphdr); 1418 optptr = cp; 1419 1420 while (totlen > 0) { 1421 if (*optptr == IPOPT_EOL) 1422 break; 1423 if (*optptr == IPOPT_NOP) { 1424 totlen--; 1425 optptr++; 1426 printf("\nNOP"); 1427 continue; 1428 } 1429 cp = optptr; 1430 optlen = optptr[1]; 1431 if (optlen < 2 || optlen > totlen) 1432 break; 1433 1434 switch (*cp) { 1435 case IPOPT_SSRR: 1436 case IPOPT_LSRR: 1437 printf("\n%cSRR: ", *cp==IPOPT_SSRR ? 'S' : 'L'); 1438 j = *++cp; 1439 i = *++cp; 1440 i -= 4; 1441 cp++; 1442 if (j > IPOPT_MINOFF) { 1443 for (;;) { 1444 __u32 address; 1445 memcpy(&address, cp, 4); 1446 cp += 4; 1447 if (address == 0) 1448 printf("\t0.0.0.0"); 1449 else 1450 printf("\t%s", pr_addr(address)); 1451 j -= 4; 1452 putchar('\n'); 1453 if (j <= IPOPT_MINOFF) 1454 break; 1455 } 1456 } 1457 break; 1458 case IPOPT_RR: 1459 j = *++cp; /* get length */ 1460 i = *++cp; /* and pointer */ 1461 if (i > j) 1462 i = j; 1463 i -= IPOPT_MINOFF; 1464 if (i <= 0) 1465 continue; 1466 if (i == old_rrlen 1467 && !memcmp((char *)cp, old_rr, i) 1468 && !(options & F_FLOOD)) { 1469 printf("\t(same route)"); 1470 i = ((i + 3) / 4) * 4; 1471 cp += i; 1472 break; 1473 } 1474 old_rrlen = i; 1475 memcpy((char *)cp, old_rr, i); 1476 printf("\nRR: "); 1477 cp++; 1478 for (;;) { 1479 __u32 address; 1480 memcpy(&address, cp, 4); 1481 cp += 4; 1482 if (address == 0) 1483 printf("\t0.0.0.0"); 1484 else 1485 printf("\t%s", pr_addr(address)); 1486 i -= 4; 1487 putchar('\n'); 1488 if (i <= 0) 1489 break; 1490 } 1491 break; 1492 case IPOPT_TS: 1493 { 1494 int stdtime = 0, nonstdtime = 0; 1495 __u8 flags; 1496 j = *++cp; /* get length */ 1497 i = *++cp; /* and pointer */ 1498 if (i > j) 1499 i = j; 1500 i -= 5; 1501 if (i <= 0) 1502 continue; 1503 flags = *++cp; 1504 printf("\nTS: "); 1505 cp++; 1506 for (;;) { 1507 long l; 1508 1509 if ((flags&0xF) != IPOPT_TS_TSONLY) { 1510 __u32 address; 1511 memcpy(&address, cp, 4); 1512 cp += 4; 1513 if (address == 0) 1514 printf("\t0.0.0.0"); 1515 else 1516 printf("\t%s", pr_addr(address)); 1517 i -= 4; 1518 if (i <= 0) 1519 break; 1520 } 1521 l = *cp++; 1522 l = (l<<8) + *cp++; 1523 l = (l<<8) + *cp++; 1524 l = (l<<8) + *cp++; 1525 1526 if (l & 0x80000000) { 1527 if (nonstdtime==0) 1528 printf("\t%ld absolute not-standard", l&0x7fffffff); 1529 else 1530 printf("\t%ld not-standard", (l&0x7fffffff) - nonstdtime); 1531 nonstdtime = l&0x7fffffff; 1532 } else { 1533 if (stdtime==0) 1534 printf("\t%ld absolute", l); 1535 else 1536 printf("\t%ld", l - stdtime); 1537 stdtime = l; 1538 } 1539 i -= 4; 1540 putchar('\n'); 1541 if (i <= 0) 1542 break; 1543 } 1544 if (flags>>4) 1545 printf("Unrecorded hops: %d\n", flags>>4); 1546 break; 1547 } 1548 default: 1549 printf("\nunknown option %x", *cp); 1550 break; 1551 } 1552 totlen -= optlen; 1553 optptr += optlen; 1554 } 1555 } 1556 1557 1558 /* 1559 * pr_iph -- 1560 * Print an IP header with options. 1561 */ 1562 void pr_iph(struct iphdr *ip) 1563 { 1564 int hlen; 1565 u_char *cp; 1566 1567 hlen = ip->ihl << 2; 1568 cp = (u_char *)ip + 20; /* point to options */ 1569 1570 printf("Vr HL TOS Len ID Flg off TTL Pro cks Src Dst Data\n"); 1571 printf(" %1x %1x %02x %04x %04x", 1572 ip->version, ip->ihl, ip->tos, ip->tot_len, ip->id); 1573 printf(" %1x %04x", ((ip->frag_off) & 0xe000) >> 13, 1574 (ip->frag_off) & 0x1fff); 1575 printf(" %02x %02x %04x", ip->ttl, ip->protocol, ip->check); 1576 printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->saddr)); 1577 printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->daddr)); 1578 printf("\n"); 1579 pr_options(cp, hlen); 1580 } 1581 1582 /* 1583 * pr_addr -- 1584 * Return an ascii host address as a dotted quad and optionally with 1585 * a hostname. 1586 */ 1587 char * 1588 pr_addr(__u32 addr) 1589 { 1590 struct hostent *hp; 1591 static char buf[4096]; 1592 1593 if ((options & F_NUMERIC) || 1594 !(hp = gethostbyaddr((char *)&addr, 4, AF_INET))) 1595 sprintf(buf, "%s", inet_ntoa(*(struct in_addr *)&addr)); 1596 else 1597 snprintf(buf, sizeof(buf), "%s (%s)", hp->h_name, 1598 inet_ntoa(*(struct in_addr *)&addr)); 1599 return(buf); 1600 } 1601 1602 1603 /* Set Type of Service (TOS) and other Quality of Service relating bits */ 1604 int parsetos(char *str) 1605 { 1606 const char *cp; 1607 int tos; 1608 char *ep; 1609 1610 /* handle both hex and decimal values */ 1611 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) { 1612 cp = str + 2; 1613 tos = (int)strtol(cp, &ep, 16); 1614 } else 1615 tos = (int)strtol(str, &ep, 10); 1616 1617 /* doesn't look like decimal or hex, eh? */ 1618 if (*ep != '\0') { 1619 fprintf(stderr, "ping: \"%s\" bad value for TOS\n", str); 1620 exit(2); 1621 } 1622 1623 if (tos > TOS_MAX) { 1624 fprintf(stderr, "ping: the decimal value of TOS bits must be 0-254 (or zero)\n"); 1625 exit(2); 1626 } 1627 return(tos); 1628 } 1629 1630 #include <linux/filter.h> 1631 1632 void install_filter(void) 1633 { 1634 static int once; 1635 static struct sock_filter insns[] = { 1636 BPF_STMT(BPF_LDX|BPF_B|BPF_MSH, 0), /* Skip IP header. F..g BSD... Look into ping6. */ 1637 BPF_STMT(BPF_LD|BPF_H|BPF_IND, 4), /* Load icmp echo ident */ 1638 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0xAAAA, 0, 1), /* Ours? */ 1639 BPF_STMT(BPF_RET|BPF_K, ~0U), /* Yes, it passes. */ 1640 BPF_STMT(BPF_LD|BPF_B|BPF_IND, 0), /* Load icmp type */ 1641 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, ICMP_ECHOREPLY, 1, 0), /* Echo? */ 1642 BPF_STMT(BPF_RET|BPF_K, 0xFFFFFFF), /* No. It passes. */ 1643 BPF_STMT(BPF_RET|BPF_K, 0) /* Echo with wrong ident. Reject. */ 1644 }; 1645 static struct sock_fprog filter = { 1646 sizeof insns / sizeof(insns[0]), 1647 insns 1648 }; 1649 1650 if (once) 1651 return; 1652 once = 1; 1653 1654 /* Patch bpflet for current identifier. */ 1655 insns[2] = (struct sock_filter)BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __constant_htons(ident), 0, 1); 1656 1657 if (setsockopt(icmp_sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter))) 1658 perror("WARNING: failed to install socket filter\n"); 1659 } 1660 1661 1662 void usage(void) 1663 { 1664 fprintf(stderr, 1665 "Usage: ping [-LRUbdfnqrvVaA] [-c count] [-i interval] [-w deadline]\n" 1666 " [-p pattern] [-s packetsize] [-t ttl] [-I interface or address]\n" 1667 " [-M mtu discovery hint] [-S sndbuf]\n" 1668 " [ -T timestamp option ] [ -Q tos ] [hop1 ...] destination\n"); 1669 exit(2); 1670 } 1671 1672 int main(int argc, char *argv[]) 1673 { 1674 struct hostent *hp; 1675 int ch, hold, packlen; 1676 int socket_errno; 1677 u_char *packet; 1678 char *target, hnamebuf[MAXHOSTNAMELEN]; 1679 char rspace[3 + 4 * NROUTES + 1]; /* record route space */ 1680 1681 icmp_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); 1682 socket_errno = errno; 1683 1684 /* if we were setuid root, undo that */ 1685 if (setuid(getuid())) return -1; 1686 1687 source.sin_family = AF_INET; 1688 1689 preload = 1; 1690 while ((ch = getopt(argc, argv, COMMON_OPTSTR "bRT:")) != EOF) { 1691 switch(ch) { 1692 case 'b': 1693 broadcast_pings = 1; 1694 break; 1695 case 'Q': 1696 settos = parsetos(optarg); 1697 if (settos && 1698 (setsockopt(icmp_sock, IPPROTO_IP, IP_TOS, 1699 (char *)&settos, sizeof(int)) < 0)) { 1700 perror("ping: error setting QOS sockopts"); 1701 exit(2); 1702 } 1703 break; 1704 case 'R': 1705 if (options & F_TIMESTAMP) { 1706 fprintf(stderr, "Only one of -T or -R may be used\n"); 1707 exit(2); 1708 } 1709 options |= F_RROUTE; 1710 break; 1711 case 'T': 1712 if (options & F_RROUTE) { 1713 fprintf(stderr, "Only one of -T or -R may be used\n"); 1714 exit(2); 1715 } 1716 options |= F_TIMESTAMP; 1717 if (strcmp(optarg, "tsonly") == 0) 1718 ts_type = IPOPT_TS_TSONLY; 1719 else if (strcmp(optarg, "tsandaddr") == 0) 1720 ts_type = IPOPT_TS_TSANDADDR; 1721 else if (strcmp(optarg, "tsprespec") == 0) 1722 ts_type = IPOPT_TS_PRESPEC; 1723 else { 1724 fprintf(stderr, "Invalid timestamp type\n"); 1725 exit(2); 1726 } 1727 break; 1728 case 'I': 1729 { 1730 char dummy; 1731 int i1, i2, i3, i4; 1732 1733 if (sscanf(optarg, "%u.%u.%u.%u%c", 1734 &i1, &i2, &i3, &i4, &dummy) == 4) { 1735 __u8 *ptr; 1736 ptr = (__u8*)&source.sin_addr; 1737 ptr[0] = i1; 1738 ptr[1] = i2; 1739 ptr[2] = i3; 1740 ptr[3] = i4; 1741 options |= F_STRICTSOURCE; 1742 } else { 1743 device = optarg; 1744 } 1745 break; 1746 } 1747 case 'M': 1748 if (strcmp(optarg, "do") == 0) 1749 pmtudisc = IP_PMTUDISC_DO; 1750 else if (strcmp(optarg, "dont") == 0) 1751 pmtudisc = IP_PMTUDISC_DONT; 1752 else if (strcmp(optarg, "want") == 0) 1753 pmtudisc = IP_PMTUDISC_WANT; 1754 else { 1755 fprintf(stderr, "ping: wrong value for -M: do, dont, want are valid ones.\n"); 1756 exit(2); 1757 } 1758 break; 1759 case 'V': 1760 printf("ping utility, iputils-ss\n"); 1761 exit(0); 1762 COMMON_OPTIONS 1763 common_options(ch); 1764 break; 1765 default: 1766 usage(); 1767 } 1768 } 1769 argc -= optind; 1770 argv += optind; 1771 1772 if (argc == 0) 1773 usage(); 1774 if (argc > 1) { 1775 if (options & F_RROUTE) 1776 usage(); 1777 else if (options & F_TIMESTAMP) { 1778 if (ts_type != IPOPT_TS_PRESPEC) 1779 usage(); 1780 if (argc > 5) 1781 usage(); 1782 } else { 1783 if (argc > 10) 1784 usage(); 1785 options |= F_SOURCEROUTE; 1786 } 1787 } 1788 while (argc > 0) { 1789 target = *argv; 1790 1791 bzero((char *)&whereto, sizeof(whereto)); 1792 whereto.sin_family = AF_INET; 1793 if (inet_aton(target, &whereto.sin_addr) == 1) { 1794 hostname = target; 1795 if (argc == 1) 1796 options |= F_NUMERIC; 1797 } else { 1798 hp = gethostbyname(target); 1799 hp = gethostbyname(target); 1800 hp = gethostbyname(target); 1801 if (!hp) { 1802 fprintf(stderr, "ping: unknown host %s\n", target); 1803 exit(2); 1804 } 1805 memcpy(&whereto.sin_addr, hp->h_addr, 4); 1806 strncpy(hnamebuf, hp->h_name, sizeof(hnamebuf) - 1); 1807 hnamebuf[sizeof(hnamebuf) - 1] = 0; 1808 hostname = hnamebuf; 1809 } 1810 if (argc > 1) 1811 route[nroute++] = whereto.sin_addr.s_addr; 1812 argc--; 1813 argv++; 1814 } 1815 1816 if (source.sin_addr.s_addr == 0) { 1817 int alen; 1818 struct sockaddr_in dst = whereto; 1819 int probe_fd = socket(AF_INET, SOCK_DGRAM, 0); 1820 1821 if (probe_fd < 0) { 1822 perror("socket"); 1823 exit(2); 1824 } 1825 if (device) { 1826 struct ifreq ifr; 1827 memset(&ifr, 0, sizeof(ifr)); 1828 strncpy(ifr.ifr_name, device, IFNAMSIZ-1); 1829 if (setsockopt(probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device)+1) == -1) { 1830 if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) { 1831 struct ip_mreqn imr; 1832 if (ioctl(probe_fd, SIOCGIFINDEX, &ifr) < 0) { 1833 fprintf(stderr, "ping: unknown iface %s\n", device); 1834 exit(2); 1835 } 1836 memset(&imr, 0, sizeof(imr)); 1837 imr.imr_ifindex = ifr.ifr_ifindex; 1838 if (setsockopt(probe_fd, SOL_IP, IP_MULTICAST_IF, &imr, sizeof(imr)) == -1) { 1839 perror("ping: IP_MULTICAST_IF"); 1840 exit(2); 1841 } 1842 } 1843 } 1844 } 1845 1846 if (settos && 1847 setsockopt(probe_fd, IPPROTO_IP, IP_TOS, (char *)&settos, sizeof(int)) < 0) 1848 perror("Warning: error setting QOS sockopts"); 1849 1850 dst.sin_port = htons(1025); 1851 if (nroute) 1852 dst.sin_addr.s_addr = route[0]; 1853 if (connect(probe_fd, (struct sockaddr*)&dst, sizeof(dst)) == -1) { 1854 if (errno == EACCES) { 1855 if (broadcast_pings == 0) { 1856 fprintf(stderr, "Do you want to ping broadcast? Then -b\n"); 1857 exit(2); 1858 } 1859 fprintf(stderr, "WARNING: pinging broadcast address\n"); 1860 if (setsockopt(probe_fd, SOL_SOCKET, SO_BROADCAST, 1861 &broadcast_pings, sizeof(broadcast_pings)) < 0) { 1862 perror ("can't set broadcasting"); 1863 exit(2); 1864 } 1865 if (connect(probe_fd, (struct sockaddr*)&dst, sizeof(dst)) == -1) { 1866 perror("connect"); 1867 exit(2); 1868 } 1869 } else { 1870 perror("connect"); 1871 exit(2); 1872 } 1873 } 1874 alen = sizeof(source); 1875 if (getsockname(probe_fd, (struct sockaddr*)&source, &alen) == -1) { 1876 perror("getsockname"); 1877 exit(2); 1878 } 1879 source.sin_port = 0; 1880 close(probe_fd); 1881 } while (0); 1882 1883 if (whereto.sin_addr.s_addr == 0) 1884 whereto.sin_addr.s_addr = source.sin_addr.s_addr; 1885 1886 if (icmp_sock < 0) { 1887 errno = socket_errno; 1888 perror("ping: icmp open socket"); 1889 exit(2); 1890 } 1891 1892 if (device) { 1893 struct ifreq ifr; 1894 1895 memset(&ifr, 0, sizeof(ifr)); 1896 strncpy(ifr.ifr_name, device, IFNAMSIZ-1); 1897 if (ioctl(icmp_sock, SIOCGIFINDEX, &ifr) < 0) { 1898 fprintf(stderr, "ping: unknown iface %s\n", device); 1899 exit(2); 1900 } 1901 cmsg.ipi.ipi_ifindex = ifr.ifr_ifindex; 1902 cmsg_len = sizeof(cmsg); 1903 } 1904 1905 if (broadcast_pings || IN_MULTICAST(ntohl(whereto.sin_addr.s_addr))) { 1906 if (uid) { 1907 if (interval < 1000) { 1908 fprintf(stderr, "ping: broadcast ping with too short interval.\n"); 1909 exit(2); 1910 } 1911 if (pmtudisc >= 0 && pmtudisc != IP_PMTUDISC_DO) { 1912 fprintf(stderr, "ping: broadcast ping does not fragment.\n"); 1913 exit(2); 1914 } 1915 } 1916 if (pmtudisc < 0) 1917 pmtudisc = IP_PMTUDISC_DO; 1918 } 1919 1920 if (pmtudisc >= 0) { 1921 if (setsockopt(icmp_sock, SOL_IP, IP_MTU_DISCOVER, &pmtudisc, sizeof(pmtudisc)) == -1) { 1922 perror("ping: IP_MTU_DISCOVER"); 1923 exit(2); 1924 } 1925 } 1926 1927 if ((options&F_STRICTSOURCE) && 1928 bind(icmp_sock, (struct sockaddr*)&source, sizeof(source)) == -1) { 1929 perror("bind"); 1930 exit(2); 1931 } 1932 1933 if (1) { 1934 struct icmp_filter filt; 1935 filt.data = ~((1<<ICMP_SOURCE_QUENCH)| 1936 (1<<ICMP_DEST_UNREACH)| 1937 (1<<ICMP_TIME_EXCEEDED)| 1938 (1<<ICMP_PARAMETERPROB)| 1939 (1<<ICMP_REDIRECT)| 1940 (1<<ICMP_ECHOREPLY)); 1941 if (setsockopt(icmp_sock, SOL_RAW, ICMP_FILTER, (char*)&filt, sizeof(filt)) == -1) 1942 perror("WARNING: setsockopt(ICMP_FILTER)"); 1943 } 1944 1945 hold = 1; 1946 if (setsockopt(icmp_sock, SOL_IP, IP_RECVERR, (char *)&hold, sizeof(hold))) 1947 fprintf(stderr, "WARNING: your kernel is veeery old. No problems.\n"); 1948 1949 /* record route option */ 1950 if (options & F_RROUTE) { 1951 bzero(rspace, sizeof(rspace)); 1952 rspace[0] = IPOPT_NOP; 1953 rspace[1+IPOPT_OPTVAL] = IPOPT_RR; 1954 rspace[1+IPOPT_OLEN] = sizeof(rspace)-1; 1955 rspace[1+IPOPT_OFFSET] = IPOPT_MINOFF; 1956 optlen = 40; 1957 if (setsockopt(icmp_sock, IPPROTO_IP, IP_OPTIONS, rspace, sizeof(rspace)) < 0) { 1958 perror("ping: record route"); 1959 exit(2); 1960 } 1961 } 1962 if (options & F_TIMESTAMP) { 1963 bzero(rspace, sizeof(rspace)); 1964 rspace[0] = IPOPT_TIMESTAMP; 1965 rspace[1] = (ts_type==IPOPT_TS_TSONLY ? 40 : 36); 1966 rspace[2] = 5; 1967 rspace[3] = ts_type; 1968 if (ts_type == IPOPT_TS_PRESPEC) { 1969 int i; 1970 rspace[1] = 4+nroute*8; 1971 for (i=0; i<nroute; i++) 1972 *(__u32*)&rspace[4+i*8] = route[i]; 1973 } 1974 if (setsockopt(icmp_sock, IPPROTO_IP, IP_OPTIONS, rspace, rspace[1]) < 0) { 1975 rspace[3] = 2; 1976 if (setsockopt(icmp_sock, IPPROTO_IP, IP_OPTIONS, rspace, rspace[1]) < 0) { 1977 perror("ping: ts option"); 1978 exit(2); 1979 } 1980 } 1981 optlen = 40; 1982 } 1983 if (options & F_SOURCEROUTE) { 1984 int i; 1985 bzero(rspace, sizeof(rspace)); 1986 rspace[0] = IPOPT_NOOP; 1987 rspace[1+IPOPT_OPTVAL] = (options & F_SO_DONTROUTE) ? IPOPT_SSRR 1988 : IPOPT_LSRR; 1989 rspace[1+IPOPT_OLEN] = 3 + nroute*4; 1990 rspace[1+IPOPT_OFFSET] = IPOPT_MINOFF; 1991 for (i=0; i<nroute; i++) 1992 *(__u32*)&rspace[4+i*4] = route[i]; 1993 1994 if (setsockopt(icmp_sock, IPPROTO_IP, IP_OPTIONS, rspace, 4 + nroute*4) < 0) { 1995 perror("ping: record route"); 1996 exit(2); 1997 } 1998 optlen = 40; 1999 } 2000 2001 /* Estimate memory eaten by single packet. It is rough estimate. 2002 * Actually, for small datalen's it depends on kernel side a lot. */ 2003 hold = datalen + 8; 2004 hold += ((hold+511)/512)*(optlen + 20 + 16 + 64 + 160); 2005 sock_setbufs(icmp_sock, hold); 2006 2007 if (broadcast_pings) { 2008 if (setsockopt(icmp_sock, SOL_SOCKET, SO_BROADCAST, 2009 &broadcast_pings, sizeof(broadcast_pings)) < 0) { 2010 perror ("ping: can't set broadcasting"); 2011 exit(2); 2012 } 2013 } 2014 2015 if (options & F_NOLOOP) { 2016 int loop = 0; 2017 if (setsockopt(icmp_sock, IPPROTO_IP, IP_MULTICAST_LOOP, 2018 &loop, 1) == -1) { 2019 perror ("ping: can't disable multicast loopback"); 2020 exit(2); 2021 } 2022 } 2023 if (options & F_TTL) { 2024 int ittl = ttl; 2025 if (setsockopt(icmp_sock, IPPROTO_IP, IP_MULTICAST_TTL, 2026 &ttl, 1) == -1) { 2027 perror ("ping: can't set multicast time-to-live"); 2028 exit(2); 2029 } 2030 if (setsockopt(icmp_sock, IPPROTO_IP, IP_TTL, 2031 &ittl, sizeof(ittl)) == -1) { 2032 perror ("ping: can't set unicast time-to-live"); 2033 exit(2); 2034 } 2035 } 2036 2037 if (datalen > 0xFFFF - 8 - optlen - 20) { 2038 if (uid || datalen > sizeof(outpack)-8) { 2039 fprintf(stderr, "Error: packet size %d is too large. Maximum is %d\n", datalen, 0xFFFF-8-20-optlen); 2040 exit(2); 2041 } 2042 /* Allow small oversize to root yet. It will cause EMSGSIZE. */ 2043 fprintf(stderr, "WARNING: packet size %d is too large. Maximum is %d\n", datalen, 0xFFFF-8-20-optlen); 2044 } 2045 2046 if (datalen >= sizeof(struct timeval)) /* can we time transfer */ 2047 timing = 1; 2048 packlen = datalen + MAXIPLEN + MAXICMPLEN; 2049 if (!(packet = (u_char *)malloc((u_int)packlen))) { 2050 fprintf(stderr, "ping: out of memory.\n"); 2051 exit(2); 2052 } 2053 2054 printf("PING %s (%s) ", hostname, inet_ntoa(whereto.sin_addr)); 2055 if (device || (options&F_STRICTSOURCE)) 2056 printf("from %s %s: ", inet_ntoa(source.sin_addr), device ?: ""); 2057 printf("%d(%d) bytes of data.\n", datalen, datalen+8+optlen+20); 2058 2059 setup(icmp_sock); 2060 2061 main_loop(icmp_sock, packet, packlen); 2062 return 0; 2063 } 2064 2065 void *dlopen(const char *filename, int flag) { return 0; } 2066 char *dlerror(void) { return 0; } 2067 void *dlsym(void *handle, const char *symbol) { return 0; } 2068 int dlclose(void *handle) { return 0; } 2069