1 /* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. 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 * 4. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #if 0 34 #ifndef lint 35 static const char copyright[] = 36 "@(#) Copyright (c) 1989, 1993\n\ 37 The Regents of the University of California. All rights reserved.\n"; 38 #endif /* not lint */ 39 40 #ifndef lint 41 static char sccsid[] = "@(#)ping.c 8.1 (Berkeley) 6/5/93"; 42 #endif /* not lint */ 43 #endif 44 #include <sys/cdefs.h> 45 __FBSDID("$FreeBSD$"); 46 47 /* 48 * P I N G . C 49 * 50 * Using the Internet Control Message Protocol (ICMP) "ECHO" facility, 51 * measure round-trip-delays and packet loss across network paths. 52 * 53 * Author - 54 * Mike Muuss 55 * U. S. Army Ballistic Research Laboratory 56 * December, 1983 57 * 58 * Status - 59 * Public Domain. Distribution Unlimited. 60 * Bugs - 61 * More statistics could always be gathered. 62 * This program has to run SUID to ROOT to access the ICMP socket. 63 */ 64 65 #include <sys/param.h> /* NB: we rely on this for <sys/types.h> */ 66 #include <sys/socket.h> 67 #include <sys/sysctl.h> 68 #include <sys/time.h> 69 #include <sys/uio.h> 70 71 #include <netinet/in.h> 72 #include <netinet/in_systm.h> 73 #include <netinet/ip.h> 74 #include <netinet/ip_icmp.h> 75 #include <netinet/ip_var.h> 76 #include <arpa/inet.h> 77 78 #ifdef IPSEC 79 #include <netipsec/ipsec.h> 80 #endif /*IPSEC*/ 81 82 #include <ctype.h> 83 #include <err.h> 84 #include <errno.h> 85 #include <math.h> 86 #include <netdb.h> 87 #include <signal.h> 88 #include <stdio.h> 89 #include <stdlib.h> 90 #include <string.h> 91 #include <sysexits.h> 92 #include <unistd.h> 93 94 #define INADDR_LEN ((int)sizeof(in_addr_t)) 95 #define TIMEVAL_LEN ((int)sizeof(struct tv32)) 96 #define MASK_LEN (ICMP_MASKLEN - ICMP_MINLEN) 97 #define TS_LEN (ICMP_TSLEN - ICMP_MINLEN) 98 #define DEFDATALEN 56 /* default data length */ 99 #define FLOOD_BACKOFF 20000 /* usecs to back off if F_FLOOD mode */ 100 /* runs out of buffer space */ 101 #define MAXIPLEN (sizeof(struct ip) + MAX_IPOPTLEN) 102 #define MAXICMPLEN (ICMP_ADVLENMIN + MAX_IPOPTLEN) 103 #define MAXWAIT 10000 /* max ms to wait for response */ 104 #define MAXALARM (60 * 60) /* max seconds for alarm timeout */ 105 #define MAXTOS 255 106 107 #define A(bit) rcvd_tbl[(bit)>>3] /* identify byte in array */ 108 #define B(bit) (1 << ((bit) & 0x07)) /* identify bit in byte */ 109 #define SET(bit) (A(bit) |= B(bit)) 110 #define CLR(bit) (A(bit) &= (~B(bit))) 111 #define TST(bit) (A(bit) & B(bit)) 112 113 struct tv32 { 114 int32_t tv32_sec; 115 int32_t tv32_usec; 116 }; 117 118 /* various options */ 119 int options; 120 #define F_FLOOD 0x0001 121 #define F_INTERVAL 0x0002 122 #define F_NUMERIC 0x0004 123 #define F_PINGFILLED 0x0008 124 #define F_QUIET 0x0010 125 #define F_RROUTE 0x0020 126 #define F_SO_DEBUG 0x0040 127 #define F_SO_DONTROUTE 0x0080 128 #define F_VERBOSE 0x0100 129 #define F_QUIET2 0x0200 130 #define F_NOLOOP 0x0400 131 #define F_MTTL 0x0800 132 #define F_MIF 0x1000 133 #define F_AUDIBLE 0x2000 134 #ifdef IPSEC 135 #ifdef IPSEC_POLICY_IPSEC 136 #define F_POLICY 0x4000 137 #endif /*IPSEC_POLICY_IPSEC*/ 138 #endif /*IPSEC*/ 139 #define F_TTL 0x8000 140 #define F_MISSED 0x10000 141 #define F_ONCE 0x20000 142 #define F_HDRINCL 0x40000 143 #define F_MASK 0x80000 144 #define F_TIME 0x100000 145 #define F_SWEEP 0x200000 146 #define F_WAITTIME 0x400000 147 148 /* 149 * MAX_DUP_CHK is the number of bits in received table, i.e. the maximum 150 * number of received sequence numbers we can keep track of. Change 128 151 * to 8192 for complete accuracy... 152 */ 153 #define MAX_DUP_CHK (8 * 128) 154 int mx_dup_ck = MAX_DUP_CHK; 155 char rcvd_tbl[MAX_DUP_CHK / 8]; 156 157 struct sockaddr_in whereto; /* who to ping */ 158 int datalen = DEFDATALEN; 159 int maxpayload; 160 int s; /* socket file descriptor */ 161 u_char outpackhdr[IP_MAXPACKET], *outpack; 162 char BBELL = '\a'; /* characters written for MISSED and AUDIBLE */ 163 char BSPACE = '\b'; /* characters written for flood */ 164 char DOT = '.'; 165 char *hostname; 166 char *shostname; 167 int ident; /* process id to identify our packets */ 168 int uid; /* cached uid for micro-optimization */ 169 u_char icmp_type = ICMP_ECHO; 170 u_char icmp_type_rsp = ICMP_ECHOREPLY; 171 int phdr_len = 0; 172 int send_len; 173 174 /* counters */ 175 long nmissedmax; /* max value of ntransmitted - nreceived - 1 */ 176 long npackets; /* max packets to transmit */ 177 long nreceived; /* # of packets we got back */ 178 long nrepeats; /* number of duplicates */ 179 long ntransmitted; /* sequence # for outbound packets = #sent */ 180 long snpackets; /* max packets to transmit in one sweep */ 181 long snreceived; /* # of packets we got back in this sweep */ 182 long sntransmitted; /* # of packets we sent in this sweep */ 183 int sweepmax; /* max value of payload in sweep */ 184 int sweepmin = 0; /* start value of payload in sweep */ 185 int sweepincr = 1; /* payload increment in sweep */ 186 int interval = 1000; /* interval between packets, ms */ 187 int waittime = MAXWAIT; /* timeout for each packet */ 188 long nrcvtimeout = 0; /* # of packets we got back after waittime */ 189 190 /* timing */ 191 int timing; /* flag to do timing */ 192 double tmin = 999999999.0; /* minimum round trip time */ 193 double tmax = 0.0; /* maximum round trip time */ 194 double tsum = 0.0; /* sum of all times, for doing average */ 195 double tsumsq = 0.0; /* sum of all times squared, for std. dev. */ 196 197 volatile sig_atomic_t finish_up; /* nonzero if we've been told to finish up */ 198 volatile sig_atomic_t siginfo_p; 199 200 static void fill(char *, char *); 201 static u_short in_cksum(u_short *, int); 202 static void check_status(void); 203 static void finish(void) __dead2; 204 static void pinger(void); 205 static char *pr_addr(struct in_addr); 206 static char *pr_ntime(n_time); 207 static void pr_icmph(struct icmp *); 208 static void pr_iph(struct ip *); 209 static void pr_pack(char *, int, struct sockaddr_in *, struct timeval *); 210 static void pr_retip(struct ip *); 211 static void status(int); 212 static void stopit(int); 213 static void tvsub(struct timeval *, const struct timeval *); 214 static void usage(void) __dead2; 215 216 int 217 main(int argc, char *const *argv) 218 { 219 struct sockaddr_in from, sock_in; 220 struct in_addr ifaddr; 221 struct timeval last, intvl; 222 struct iovec iov; 223 struct ip *ip; 224 struct msghdr msg; 225 struct sigaction si_sa; 226 size_t sz; 227 u_char *datap, packet[IP_MAXPACKET] __aligned(4); 228 char *ep, *source, *target, *payload; 229 struct hostent *hp; 230 #ifdef IPSEC_POLICY_IPSEC 231 char *policy_in, *policy_out; 232 #endif 233 struct sockaddr_in *to; 234 double t; 235 u_long alarmtimeout, ultmp; 236 int almost_done, ch, df, hold, i, icmp_len, mib[4], preload, sockerrno, 237 tos, ttl; 238 char ctrl[CMSG_SPACE(sizeof(struct timeval))]; 239 char hnamebuf[MAXHOSTNAMELEN], snamebuf[MAXHOSTNAMELEN]; 240 #ifdef IP_OPTIONS 241 char rspace[MAX_IPOPTLEN]; /* record route space */ 242 #endif 243 unsigned char loop, mttl; 244 245 payload = source = NULL; 246 #ifdef IPSEC_POLICY_IPSEC 247 policy_in = policy_out = NULL; 248 #endif 249 250 /* 251 * Do the stuff that we need root priv's for *first*, and 252 * then drop our setuid bit. Save error reporting for 253 * after arg parsing. 254 */ 255 s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); 256 sockerrno = errno; 257 258 if (setuid(getuid()) != 0) 259 err(EX_NOPERM, "setuid() failed"); 260 uid = getuid(); 261 262 alarmtimeout = df = preload = tos = 0; 263 264 outpack = outpackhdr + sizeof(struct ip); 265 while ((ch = getopt(argc, argv, 266 "Aac:DdfG:g:h:I:i:Ll:M:m:nop:QqRrS:s:T:t:vW:z:" 267 #ifdef IPSEC 268 #ifdef IPSEC_POLICY_IPSEC 269 "P:" 270 #endif /*IPSEC_POLICY_IPSEC*/ 271 #endif /*IPSEC*/ 272 )) != -1) 273 { 274 switch(ch) { 275 case 'A': 276 options |= F_MISSED; 277 break; 278 case 'a': 279 options |= F_AUDIBLE; 280 break; 281 case 'c': 282 ultmp = strtoul(optarg, &ep, 0); 283 if (*ep || ep == optarg || ultmp > LONG_MAX || !ultmp) 284 errx(EX_USAGE, 285 "invalid count of packets to transmit: `%s'", 286 optarg); 287 npackets = ultmp; 288 break; 289 case 'D': 290 options |= F_HDRINCL; 291 df = 1; 292 break; 293 case 'd': 294 options |= F_SO_DEBUG; 295 break; 296 case 'f': 297 if (uid) { 298 errno = EPERM; 299 err(EX_NOPERM, "-f flag"); 300 } 301 options |= F_FLOOD; 302 setbuf(stdout, (char *)NULL); 303 break; 304 case 'G': /* Maximum packet size for ping sweep */ 305 ultmp = strtoul(optarg, &ep, 0); 306 if (*ep || ep == optarg) 307 errx(EX_USAGE, "invalid packet size: `%s'", 308 optarg); 309 if (uid != 0 && ultmp > DEFDATALEN) { 310 errno = EPERM; 311 err(EX_NOPERM, 312 "packet size too large: %lu > %u", 313 ultmp, DEFDATALEN); 314 } 315 options |= F_SWEEP; 316 sweepmax = ultmp; 317 break; 318 case 'g': /* Minimum packet size for ping sweep */ 319 ultmp = strtoul(optarg, &ep, 0); 320 if (*ep || ep == optarg) 321 errx(EX_USAGE, "invalid packet size: `%s'", 322 optarg); 323 if (uid != 0 && ultmp > DEFDATALEN) { 324 errno = EPERM; 325 err(EX_NOPERM, 326 "packet size too large: %lu > %u", 327 ultmp, DEFDATALEN); 328 } 329 options |= F_SWEEP; 330 sweepmin = ultmp; 331 break; 332 case 'h': /* Packet size increment for ping sweep */ 333 ultmp = strtoul(optarg, &ep, 0); 334 if (*ep || ep == optarg || ultmp < 1) 335 errx(EX_USAGE, "invalid increment size: `%s'", 336 optarg); 337 if (uid != 0 && ultmp > DEFDATALEN) { 338 errno = EPERM; 339 err(EX_NOPERM, 340 "packet size too large: %lu > %u", 341 ultmp, DEFDATALEN); 342 } 343 options |= F_SWEEP; 344 sweepincr = ultmp; 345 break; 346 case 'I': /* multicast interface */ 347 if (inet_aton(optarg, &ifaddr) == 0) 348 errx(EX_USAGE, 349 "invalid multicast interface: `%s'", 350 optarg); 351 options |= F_MIF; 352 break; 353 case 'i': /* wait between sending packets */ 354 t = strtod(optarg, &ep) * 1000.0; 355 if (*ep || ep == optarg || t > (double)INT_MAX) 356 errx(EX_USAGE, "invalid timing interval: `%s'", 357 optarg); 358 options |= F_INTERVAL; 359 interval = (int)t; 360 if (uid && interval < 1000) { 361 errno = EPERM; 362 err(EX_NOPERM, "-i interval too short"); 363 } 364 break; 365 case 'L': 366 options |= F_NOLOOP; 367 loop = 0; 368 break; 369 case 'l': 370 ultmp = strtoul(optarg, &ep, 0); 371 if (*ep || ep == optarg || ultmp > INT_MAX) 372 errx(EX_USAGE, 373 "invalid preload value: `%s'", optarg); 374 if (uid) { 375 errno = EPERM; 376 err(EX_NOPERM, "-l flag"); 377 } 378 preload = ultmp; 379 break; 380 case 'M': 381 switch(optarg[0]) { 382 case 'M': 383 case 'm': 384 options |= F_MASK; 385 break; 386 case 'T': 387 case 't': 388 options |= F_TIME; 389 break; 390 default: 391 errx(EX_USAGE, "invalid message: `%c'", optarg[0]); 392 break; 393 } 394 break; 395 case 'm': /* TTL */ 396 ultmp = strtoul(optarg, &ep, 0); 397 if (*ep || ep == optarg || ultmp > MAXTTL) 398 errx(EX_USAGE, "invalid TTL: `%s'", optarg); 399 ttl = ultmp; 400 options |= F_TTL; 401 break; 402 case 'n': 403 options |= F_NUMERIC; 404 break; 405 case 'o': 406 options |= F_ONCE; 407 break; 408 #ifdef IPSEC 409 #ifdef IPSEC_POLICY_IPSEC 410 case 'P': 411 options |= F_POLICY; 412 if (!strncmp("in", optarg, 2)) 413 policy_in = strdup(optarg); 414 else if (!strncmp("out", optarg, 3)) 415 policy_out = strdup(optarg); 416 else 417 errx(1, "invalid security policy"); 418 break; 419 #endif /*IPSEC_POLICY_IPSEC*/ 420 #endif /*IPSEC*/ 421 case 'p': /* fill buffer with user pattern */ 422 options |= F_PINGFILLED; 423 payload = optarg; 424 break; 425 case 'Q': 426 options |= F_QUIET2; 427 break; 428 case 'q': 429 options |= F_QUIET; 430 break; 431 case 'R': 432 options |= F_RROUTE; 433 break; 434 case 'r': 435 options |= F_SO_DONTROUTE; 436 break; 437 case 'S': 438 source = optarg; 439 break; 440 case 's': /* size of packet to send */ 441 ultmp = strtoul(optarg, &ep, 0); 442 if (*ep || ep == optarg) 443 errx(EX_USAGE, "invalid packet size: `%s'", 444 optarg); 445 if (uid != 0 && ultmp > DEFDATALEN) { 446 errno = EPERM; 447 err(EX_NOPERM, 448 "packet size too large: %lu > %u", 449 ultmp, DEFDATALEN); 450 } 451 datalen = ultmp; 452 break; 453 case 'T': /* multicast TTL */ 454 ultmp = strtoul(optarg, &ep, 0); 455 if (*ep || ep == optarg || ultmp > MAXTTL) 456 errx(EX_USAGE, "invalid multicast TTL: `%s'", 457 optarg); 458 mttl = ultmp; 459 options |= F_MTTL; 460 break; 461 case 't': 462 alarmtimeout = strtoul(optarg, &ep, 0); 463 if ((alarmtimeout < 1) || (alarmtimeout == ULONG_MAX)) 464 errx(EX_USAGE, "invalid timeout: `%s'", 465 optarg); 466 if (alarmtimeout > MAXALARM) 467 errx(EX_USAGE, "invalid timeout: `%s' > %d", 468 optarg, MAXALARM); 469 alarm((int)alarmtimeout); 470 break; 471 case 'v': 472 options |= F_VERBOSE; 473 break; 474 case 'W': /* wait ms for answer */ 475 t = strtod(optarg, &ep); 476 if (*ep || ep == optarg || t > (double)INT_MAX) 477 errx(EX_USAGE, "invalid timing interval: `%s'", 478 optarg); 479 options |= F_WAITTIME; 480 waittime = (int)t; 481 break; 482 case 'z': 483 options |= F_HDRINCL; 484 ultmp = strtoul(optarg, &ep, 0); 485 if (*ep || ep == optarg || ultmp > MAXTOS) 486 errx(EX_USAGE, "invalid TOS: `%s'", optarg); 487 tos = ultmp; 488 break; 489 default: 490 usage(); 491 } 492 } 493 494 if (argc - optind != 1) 495 usage(); 496 target = argv[optind]; 497 498 switch (options & (F_MASK|F_TIME)) { 499 case 0: break; 500 case F_MASK: 501 icmp_type = ICMP_MASKREQ; 502 icmp_type_rsp = ICMP_MASKREPLY; 503 phdr_len = MASK_LEN; 504 if (!(options & F_QUIET)) 505 (void)printf("ICMP_MASKREQ\n"); 506 break; 507 case F_TIME: 508 icmp_type = ICMP_TSTAMP; 509 icmp_type_rsp = ICMP_TSTAMPREPLY; 510 phdr_len = TS_LEN; 511 if (!(options & F_QUIET)) 512 (void)printf("ICMP_TSTAMP\n"); 513 break; 514 default: 515 errx(EX_USAGE, "ICMP_TSTAMP and ICMP_MASKREQ are exclusive."); 516 break; 517 } 518 icmp_len = sizeof(struct ip) + ICMP_MINLEN + phdr_len; 519 if (options & F_RROUTE) 520 icmp_len += MAX_IPOPTLEN; 521 maxpayload = IP_MAXPACKET - icmp_len; 522 if (datalen > maxpayload) 523 errx(EX_USAGE, "packet size too large: %d > %d", datalen, 524 maxpayload); 525 send_len = icmp_len + datalen; 526 datap = &outpack[ICMP_MINLEN + phdr_len + TIMEVAL_LEN]; 527 if (options & F_PINGFILLED) { 528 fill((char *)datap, payload); 529 } 530 if (source) { 531 bzero((char *)&sock_in, sizeof(sock_in)); 532 sock_in.sin_family = AF_INET; 533 if (inet_aton(source, &sock_in.sin_addr) != 0) { 534 shostname = source; 535 } else { 536 hp = gethostbyname2(source, AF_INET); 537 if (!hp) 538 errx(EX_NOHOST, "cannot resolve %s: %s", 539 source, hstrerror(h_errno)); 540 541 sock_in.sin_len = sizeof sock_in; 542 if ((unsigned)hp->h_length > sizeof(sock_in.sin_addr) || 543 hp->h_length < 0) 544 errx(1, "gethostbyname2: illegal address"); 545 memcpy(&sock_in.sin_addr, hp->h_addr_list[0], 546 sizeof(sock_in.sin_addr)); 547 (void)strncpy(snamebuf, hp->h_name, 548 sizeof(snamebuf) - 1); 549 snamebuf[sizeof(snamebuf) - 1] = '\0'; 550 shostname = snamebuf; 551 } 552 if (bind(s, (struct sockaddr *)&sock_in, sizeof sock_in) == -1) 553 err(1, "bind"); 554 } 555 556 bzero(&whereto, sizeof(whereto)); 557 to = &whereto; 558 to->sin_family = AF_INET; 559 to->sin_len = sizeof *to; 560 if (inet_aton(target, &to->sin_addr) != 0) { 561 hostname = target; 562 } else { 563 hp = gethostbyname2(target, AF_INET); 564 if (!hp) 565 errx(EX_NOHOST, "cannot resolve %s: %s", 566 target, hstrerror(h_errno)); 567 568 if ((unsigned)hp->h_length > sizeof(to->sin_addr)) 569 errx(1, "gethostbyname2 returned an illegal address"); 570 memcpy(&to->sin_addr, hp->h_addr_list[0], sizeof to->sin_addr); 571 (void)strncpy(hnamebuf, hp->h_name, sizeof(hnamebuf) - 1); 572 hnamebuf[sizeof(hnamebuf) - 1] = '\0'; 573 hostname = hnamebuf; 574 } 575 576 if (options & F_FLOOD && options & F_INTERVAL) 577 errx(EX_USAGE, "-f and -i: incompatible options"); 578 579 if (options & F_FLOOD && IN_MULTICAST(ntohl(to->sin_addr.s_addr))) 580 errx(EX_USAGE, 581 "-f flag cannot be used with multicast destination"); 582 if (options & (F_MIF | F_NOLOOP | F_MTTL) 583 && !IN_MULTICAST(ntohl(to->sin_addr.s_addr))) 584 errx(EX_USAGE, 585 "-I, -L, -T flags cannot be used with unicast destination"); 586 587 if (datalen >= TIMEVAL_LEN) /* can we time transfer */ 588 timing = 1; 589 590 if (!(options & F_PINGFILLED)) 591 for (i = TIMEVAL_LEN; i < datalen; ++i) 592 *datap++ = i; 593 594 ident = getpid() & 0xFFFF; 595 596 if (s < 0) { 597 errno = sockerrno; 598 err(EX_OSERR, "socket"); 599 } 600 hold = 1; 601 if (options & F_SO_DEBUG) 602 (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&hold, 603 sizeof(hold)); 604 if (options & F_SO_DONTROUTE) 605 (void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&hold, 606 sizeof(hold)); 607 #ifdef IPSEC 608 #ifdef IPSEC_POLICY_IPSEC 609 if (options & F_POLICY) { 610 char *buf; 611 if (policy_in != NULL) { 612 buf = ipsec_set_policy(policy_in, strlen(policy_in)); 613 if (buf == NULL) 614 errx(EX_CONFIG, "%s", ipsec_strerror()); 615 if (setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY, 616 buf, ipsec_get_policylen(buf)) < 0) 617 err(EX_CONFIG, 618 "ipsec policy cannot be configured"); 619 free(buf); 620 } 621 622 if (policy_out != NULL) { 623 buf = ipsec_set_policy(policy_out, strlen(policy_out)); 624 if (buf == NULL) 625 errx(EX_CONFIG, "%s", ipsec_strerror()); 626 if (setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY, 627 buf, ipsec_get_policylen(buf)) < 0) 628 err(EX_CONFIG, 629 "ipsec policy cannot be configured"); 630 free(buf); 631 } 632 } 633 #endif /*IPSEC_POLICY_IPSEC*/ 634 #endif /*IPSEC*/ 635 636 if (options & F_HDRINCL) { 637 ip = (struct ip*)outpackhdr; 638 if (!(options & (F_TTL | F_MTTL))) { 639 mib[0] = CTL_NET; 640 mib[1] = PF_INET; 641 mib[2] = IPPROTO_IP; 642 mib[3] = IPCTL_DEFTTL; 643 sz = sizeof(ttl); 644 if (sysctl(mib, 4, &ttl, &sz, NULL, 0) == -1) 645 err(1, "sysctl(net.inet.ip.ttl)"); 646 } 647 setsockopt(s, IPPROTO_IP, IP_HDRINCL, &hold, sizeof(hold)); 648 ip->ip_v = IPVERSION; 649 ip->ip_hl = sizeof(struct ip) >> 2; 650 ip->ip_tos = tos; 651 ip->ip_id = 0; 652 ip->ip_off = df ? IP_DF : 0; 653 ip->ip_ttl = ttl; 654 ip->ip_p = IPPROTO_ICMP; 655 ip->ip_src.s_addr = source ? sock_in.sin_addr.s_addr : INADDR_ANY; 656 ip->ip_dst = to->sin_addr; 657 } 658 /* record route option */ 659 if (options & F_RROUTE) { 660 #ifdef IP_OPTIONS 661 bzero(rspace, sizeof(rspace)); 662 rspace[IPOPT_OPTVAL] = IPOPT_RR; 663 rspace[IPOPT_OLEN] = sizeof(rspace) - 1; 664 rspace[IPOPT_OFFSET] = IPOPT_MINOFF; 665 rspace[sizeof(rspace) - 1] = IPOPT_EOL; 666 if (setsockopt(s, IPPROTO_IP, IP_OPTIONS, rspace, 667 sizeof(rspace)) < 0) 668 err(EX_OSERR, "setsockopt IP_OPTIONS"); 669 #else 670 errx(EX_UNAVAILABLE, 671 "record route not available in this implementation"); 672 #endif /* IP_OPTIONS */ 673 } 674 675 if (options & F_TTL) { 676 if (setsockopt(s, IPPROTO_IP, IP_TTL, &ttl, 677 sizeof(ttl)) < 0) { 678 err(EX_OSERR, "setsockopt IP_TTL"); 679 } 680 } 681 if (options & F_NOLOOP) { 682 if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, 683 sizeof(loop)) < 0) { 684 err(EX_OSERR, "setsockopt IP_MULTICAST_LOOP"); 685 } 686 } 687 if (options & F_MTTL) { 688 if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &mttl, 689 sizeof(mttl)) < 0) { 690 err(EX_OSERR, "setsockopt IP_MULTICAST_TTL"); 691 } 692 } 693 if (options & F_MIF) { 694 if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &ifaddr, 695 sizeof(ifaddr)) < 0) { 696 err(EX_OSERR, "setsockopt IP_MULTICAST_IF"); 697 } 698 } 699 #ifdef SO_TIMESTAMP 700 { int on = 1; 701 if (setsockopt(s, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)) < 0) 702 err(EX_OSERR, "setsockopt SO_TIMESTAMP"); 703 } 704 #endif 705 if (sweepmax) { 706 if (sweepmin >= sweepmax) 707 errx(EX_USAGE, "Maximum packet size must be greater than the minimum packet size"); 708 709 if (datalen != DEFDATALEN) 710 errx(EX_USAGE, "Packet size and ping sweep are mutually exclusive"); 711 712 if (npackets > 0) { 713 snpackets = npackets; 714 npackets = 0; 715 } else 716 snpackets = 1; 717 datalen = sweepmin; 718 send_len = icmp_len + sweepmin; 719 } 720 if (options & F_SWEEP && !sweepmax) 721 errx(EX_USAGE, "Maximum sweep size must be specified"); 722 723 /* 724 * When pinging the broadcast address, you can get a lot of answers. 725 * Doing something so evil is useful if you are trying to stress the 726 * ethernet, or just want to fill the arp cache to get some stuff for 727 * /etc/ethers. But beware: RFC 1122 allows hosts to ignore broadcast 728 * or multicast pings if they wish. 729 */ 730 731 /* 732 * XXX receive buffer needs undetermined space for mbuf overhead 733 * as well. 734 */ 735 hold = IP_MAXPACKET + 128; 736 (void)setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&hold, 737 sizeof(hold)); 738 if (uid == 0) 739 (void)setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&hold, 740 sizeof(hold)); 741 742 if (to->sin_family == AF_INET) { 743 (void)printf("PING %s (%s)", hostname, 744 inet_ntoa(to->sin_addr)); 745 if (source) 746 (void)printf(" from %s", shostname); 747 if (sweepmax) 748 (void)printf(": (%d ... %d) data bytes\n", 749 sweepmin, sweepmax); 750 else 751 (void)printf(": %d data bytes\n", datalen); 752 753 } else { 754 if (sweepmax) 755 (void)printf("PING %s: (%d ... %d) data bytes\n", 756 hostname, sweepmin, sweepmax); 757 else 758 (void)printf("PING %s: %d data bytes\n", hostname, datalen); 759 } 760 761 /* 762 * Use sigaction() instead of signal() to get unambiguous semantics, 763 * in particular with SA_RESTART not set. 764 */ 765 766 sigemptyset(&si_sa.sa_mask); 767 si_sa.sa_flags = 0; 768 769 si_sa.sa_handler = stopit; 770 if (sigaction(SIGINT, &si_sa, 0) == -1) { 771 err(EX_OSERR, "sigaction SIGINT"); 772 } 773 774 si_sa.sa_handler = status; 775 if (sigaction(SIGINFO, &si_sa, 0) == -1) { 776 err(EX_OSERR, "sigaction"); 777 } 778 779 if (alarmtimeout > 0) { 780 si_sa.sa_handler = stopit; 781 if (sigaction(SIGALRM, &si_sa, 0) == -1) 782 err(EX_OSERR, "sigaction SIGALRM"); 783 } 784 785 bzero(&msg, sizeof(msg)); 786 msg.msg_name = (caddr_t)&from; 787 msg.msg_iov = &iov; 788 msg.msg_iovlen = 1; 789 #ifdef SO_TIMESTAMP 790 msg.msg_control = (caddr_t)ctrl; 791 #endif 792 iov.iov_base = packet; 793 iov.iov_len = IP_MAXPACKET; 794 795 if (preload == 0) 796 pinger(); /* send the first ping */ 797 else { 798 if (npackets != 0 && preload > npackets) 799 preload = npackets; 800 while (preload--) /* fire off them quickies */ 801 pinger(); 802 } 803 (void)gettimeofday(&last, NULL); 804 805 if (options & F_FLOOD) { 806 intvl.tv_sec = 0; 807 intvl.tv_usec = 10000; 808 } else { 809 intvl.tv_sec = interval / 1000; 810 intvl.tv_usec = interval % 1000 * 1000; 811 } 812 813 almost_done = 0; 814 while (!finish_up) { 815 struct timeval now, timeout; 816 fd_set rfds; 817 int cc, n; 818 819 check_status(); 820 if ((unsigned)s >= FD_SETSIZE) 821 errx(EX_OSERR, "descriptor too large"); 822 FD_ZERO(&rfds); 823 FD_SET(s, &rfds); 824 (void)gettimeofday(&now, NULL); 825 timeout.tv_sec = last.tv_sec + intvl.tv_sec - now.tv_sec; 826 timeout.tv_usec = last.tv_usec + intvl.tv_usec - now.tv_usec; 827 while (timeout.tv_usec < 0) { 828 timeout.tv_usec += 1000000; 829 timeout.tv_sec--; 830 } 831 while (timeout.tv_usec >= 1000000) { 832 timeout.tv_usec -= 1000000; 833 timeout.tv_sec++; 834 } 835 if (timeout.tv_sec < 0) 836 timerclear(&timeout); 837 n = select(s + 1, &rfds, NULL, NULL, &timeout); 838 if (n < 0) 839 continue; /* Must be EINTR. */ 840 if (n == 1) { 841 struct timeval *tv = NULL; 842 #ifdef SO_TIMESTAMP 843 struct cmsghdr *cmsg = (struct cmsghdr *)&ctrl; 844 845 msg.msg_controllen = sizeof(ctrl); 846 #endif 847 msg.msg_namelen = sizeof(from); 848 if ((cc = recvmsg(s, &msg, 0)) < 0) { 849 if (errno == EINTR) 850 continue; 851 warn("recvmsg"); 852 continue; 853 } 854 #ifdef SO_TIMESTAMP 855 if (cmsg->cmsg_level == SOL_SOCKET && 856 cmsg->cmsg_type == SCM_TIMESTAMP && 857 cmsg->cmsg_len == CMSG_LEN(sizeof *tv)) { 858 /* Copy to avoid alignment problems: */ 859 memcpy(&now, CMSG_DATA(cmsg), sizeof(now)); 860 tv = &now; 861 } 862 #endif 863 if (tv == NULL) { 864 (void)gettimeofday(&now, NULL); 865 tv = &now; 866 } 867 pr_pack((char *)packet, cc, &from, tv); 868 if ((options & F_ONCE && nreceived) || 869 (npackets && nreceived >= npackets)) 870 break; 871 } 872 if (n == 0 || options & F_FLOOD) { 873 if (sweepmax && sntransmitted == snpackets) { 874 for (i = 0; i < sweepincr ; ++i) 875 *datap++ = i; 876 datalen += sweepincr; 877 if (datalen > sweepmax) 878 break; 879 send_len = icmp_len + datalen; 880 sntransmitted = 0; 881 } 882 if (!npackets || ntransmitted < npackets) 883 pinger(); 884 else { 885 if (almost_done) 886 break; 887 almost_done = 1; 888 intvl.tv_usec = 0; 889 if (nreceived) { 890 intvl.tv_sec = 2 * tmax / 1000; 891 if (!intvl.tv_sec) 892 intvl.tv_sec = 1; 893 } else { 894 intvl.tv_sec = waittime / 1000; 895 intvl.tv_usec = waittime % 1000 * 1000; 896 } 897 } 898 (void)gettimeofday(&last, NULL); 899 if (ntransmitted - nreceived - 1 > nmissedmax) { 900 nmissedmax = ntransmitted - nreceived - 1; 901 if (options & F_MISSED) 902 (void)write(STDOUT_FILENO, &BBELL, 1); 903 } 904 } 905 } 906 finish(); 907 /* NOTREACHED */ 908 exit(0); /* Make the compiler happy */ 909 } 910 911 /* 912 * stopit -- 913 * Set the global bit that causes the main loop to quit. 914 * Do NOT call finish() from here, since finish() does far too much 915 * to be called from a signal handler. 916 */ 917 void 918 stopit(int sig __unused) 919 { 920 921 /* 922 * When doing reverse DNS lookups, the finish_up flag might not 923 * be noticed for a while. Just exit if we get a second SIGINT. 924 */ 925 if (!(options & F_NUMERIC) && finish_up) 926 _exit(nreceived ? 0 : 2); 927 finish_up = 1; 928 } 929 930 /* 931 * pinger -- 932 * Compose and transmit an ICMP ECHO REQUEST packet. The IP packet 933 * will be added on by the kernel. The ID field is our UNIX process ID, 934 * and the sequence number is an ascending integer. The first TIMEVAL_LEN 935 * bytes of the data portion are used to hold a UNIX "timeval" struct in 936 * host byte-order, to compute the round-trip time. 937 */ 938 static void 939 pinger(void) 940 { 941 struct timeval now; 942 struct tv32 tv32; 943 struct ip *ip; 944 struct icmp *icp; 945 int cc, i; 946 u_char *packet; 947 948 packet = outpack; 949 icp = (struct icmp *)outpack; 950 icp->icmp_type = icmp_type; 951 icp->icmp_code = 0; 952 icp->icmp_cksum = 0; 953 icp->icmp_seq = htons(ntransmitted); 954 icp->icmp_id = ident; /* ID */ 955 956 CLR(ntransmitted % mx_dup_ck); 957 958 if ((options & F_TIME) || timing) { 959 (void)gettimeofday(&now, NULL); 960 961 tv32.tv32_sec = htonl(now.tv_sec); 962 tv32.tv32_usec = htonl(now.tv_usec); 963 if (options & F_TIME) 964 icp->icmp_otime = htonl((now.tv_sec % (24*60*60)) 965 * 1000 + now.tv_usec / 1000); 966 if (timing) 967 bcopy((void *)&tv32, 968 (void *)&outpack[ICMP_MINLEN + phdr_len], 969 sizeof(tv32)); 970 } 971 972 cc = ICMP_MINLEN + phdr_len + datalen; 973 974 /* compute ICMP checksum here */ 975 icp->icmp_cksum = in_cksum((u_short *)icp, cc); 976 977 if (options & F_HDRINCL) { 978 cc += sizeof(struct ip); 979 ip = (struct ip *)outpackhdr; 980 ip->ip_len = cc; 981 ip->ip_sum = in_cksum((u_short *)outpackhdr, cc); 982 packet = outpackhdr; 983 } 984 i = sendto(s, (char *)packet, cc, 0, (struct sockaddr *)&whereto, 985 sizeof(whereto)); 986 987 if (i < 0 || i != cc) { 988 if (i < 0) { 989 if (options & F_FLOOD && errno == ENOBUFS) { 990 usleep(FLOOD_BACKOFF); 991 return; 992 } 993 warn("sendto"); 994 } else { 995 warn("%s: partial write: %d of %d bytes", 996 hostname, i, cc); 997 } 998 } 999 ntransmitted++; 1000 sntransmitted++; 1001 if (!(options & F_QUIET) && options & F_FLOOD) 1002 (void)write(STDOUT_FILENO, &DOT, 1); 1003 } 1004 1005 /* 1006 * pr_pack -- 1007 * Print out the packet, if it came from us. This logic is necessary 1008 * because ALL readers of the ICMP socket get a copy of ALL ICMP packets 1009 * which arrive ('tis only fair). This permits multiple copies of this 1010 * program to be run without having intermingled output (or statistics!). 1011 */ 1012 static void 1013 pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timeval *tv) 1014 { 1015 struct in_addr ina; 1016 u_char *cp, *dp; 1017 struct icmp *icp; 1018 struct ip *ip; 1019 const void *tp; 1020 double triptime; 1021 int dupflag, hlen, i, j, recv_len, seq; 1022 static int old_rrlen; 1023 static char old_rr[MAX_IPOPTLEN]; 1024 1025 /* Check the IP header */ 1026 ip = (struct ip *)buf; 1027 hlen = ip->ip_hl << 2; 1028 recv_len = cc; 1029 if (cc < hlen + ICMP_MINLEN) { 1030 if (options & F_VERBOSE) 1031 warn("packet too short (%d bytes) from %s", cc, 1032 inet_ntoa(from->sin_addr)); 1033 return; 1034 } 1035 1036 /* Now the ICMP part */ 1037 cc -= hlen; 1038 icp = (struct icmp *)(buf + hlen); 1039 if (icp->icmp_type == icmp_type_rsp) { 1040 if (icp->icmp_id != ident) 1041 return; /* 'Twas not our ECHO */ 1042 ++nreceived; 1043 triptime = 0.0; 1044 if (timing) { 1045 struct timeval tv1; 1046 struct tv32 tv32; 1047 #ifndef icmp_data 1048 tp = &icp->icmp_ip; 1049 #else 1050 tp = icp->icmp_data; 1051 #endif 1052 tp = (const char *)tp + phdr_len; 1053 1054 if (cc - ICMP_MINLEN - phdr_len >= sizeof(tv1)) { 1055 /* Copy to avoid alignment problems: */ 1056 memcpy(&tv32, tp, sizeof(tv32)); 1057 tv1.tv_sec = ntohl(tv32.tv32_sec); 1058 tv1.tv_usec = ntohl(tv32.tv32_usec); 1059 tvsub(tv, &tv1); 1060 triptime = ((double)tv->tv_sec) * 1000.0 + 1061 ((double)tv->tv_usec) / 1000.0; 1062 tsum += triptime; 1063 tsumsq += triptime * triptime; 1064 if (triptime < tmin) 1065 tmin = triptime; 1066 if (triptime > tmax) 1067 tmax = triptime; 1068 } else 1069 timing = 0; 1070 } 1071 1072 seq = ntohs(icp->icmp_seq); 1073 1074 if (TST(seq % mx_dup_ck)) { 1075 ++nrepeats; 1076 --nreceived; 1077 dupflag = 1; 1078 } else { 1079 SET(seq % mx_dup_ck); 1080 dupflag = 0; 1081 } 1082 1083 if (options & F_QUIET) 1084 return; 1085 1086 if (options & F_WAITTIME && triptime > waittime) { 1087 ++nrcvtimeout; 1088 return; 1089 } 1090 1091 if (options & F_FLOOD) 1092 (void)write(STDOUT_FILENO, &BSPACE, 1); 1093 else { 1094 (void)printf("%d bytes from %s: icmp_seq=%u", cc, 1095 inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr), 1096 seq); 1097 (void)printf(" ttl=%d", ip->ip_ttl); 1098 if (timing) 1099 (void)printf(" time=%.3f ms", triptime); 1100 if (dupflag) 1101 (void)printf(" (DUP!)"); 1102 if (options & F_AUDIBLE) 1103 (void)write(STDOUT_FILENO, &BBELL, 1); 1104 if (options & F_MASK) { 1105 /* Just prentend this cast isn't ugly */ 1106 (void)printf(" mask=%s", 1107 pr_addr(*(struct in_addr *)&(icp->icmp_mask))); 1108 } 1109 if (options & F_TIME) { 1110 (void)printf(" tso=%s", pr_ntime(icp->icmp_otime)); 1111 (void)printf(" tsr=%s", pr_ntime(icp->icmp_rtime)); 1112 (void)printf(" tst=%s", pr_ntime(icp->icmp_ttime)); 1113 } 1114 if (recv_len != send_len) { 1115 (void)printf( 1116 "\nwrong total length %d instead of %d", 1117 recv_len, send_len); 1118 } 1119 /* check the data */ 1120 cp = (u_char*)&icp->icmp_data[phdr_len]; 1121 dp = &outpack[ICMP_MINLEN + phdr_len]; 1122 cc -= ICMP_MINLEN + phdr_len; 1123 i = 0; 1124 if (timing) { /* don't check variable timestamp */ 1125 cp += TIMEVAL_LEN; 1126 dp += TIMEVAL_LEN; 1127 cc -= TIMEVAL_LEN; 1128 i += TIMEVAL_LEN; 1129 } 1130 for (; i < datalen && cc > 0; ++i, ++cp, ++dp, --cc) { 1131 if (*cp != *dp) { 1132 (void)printf("\nwrong data byte #%d should be 0x%x but was 0x%x", 1133 i, *dp, *cp); 1134 (void)printf("\ncp:"); 1135 cp = (u_char*)&icp->icmp_data[0]; 1136 for (i = 0; i < datalen; ++i, ++cp) { 1137 if ((i % 16) == 8) 1138 (void)printf("\n\t"); 1139 (void)printf("%2x ", *cp); 1140 } 1141 (void)printf("\ndp:"); 1142 cp = &outpack[ICMP_MINLEN]; 1143 for (i = 0; i < datalen; ++i, ++cp) { 1144 if ((i % 16) == 8) 1145 (void)printf("\n\t"); 1146 (void)printf("%2x ", *cp); 1147 } 1148 break; 1149 } 1150 } 1151 } 1152 } else { 1153 /* 1154 * We've got something other than an ECHOREPLY. 1155 * See if it's a reply to something that we sent. 1156 * We can compare IP destination, protocol, 1157 * and ICMP type and ID. 1158 * 1159 * Only print all the error messages if we are running 1160 * as root to avoid leaking information not normally 1161 * available to those not running as root. 1162 */ 1163 #ifndef icmp_data 1164 struct ip *oip = &icp->icmp_ip; 1165 #else 1166 struct ip *oip = (struct ip *)icp->icmp_data; 1167 #endif 1168 struct icmp *oicmp = (struct icmp *)(oip + 1); 1169 1170 if (((options & F_VERBOSE) && uid == 0) || 1171 (!(options & F_QUIET2) && 1172 (oip->ip_dst.s_addr == whereto.sin_addr.s_addr) && 1173 (oip->ip_p == IPPROTO_ICMP) && 1174 (oicmp->icmp_type == ICMP_ECHO) && 1175 (oicmp->icmp_id == ident))) { 1176 (void)printf("%d bytes from %s: ", cc, 1177 pr_addr(from->sin_addr)); 1178 pr_icmph(icp); 1179 } else 1180 return; 1181 } 1182 1183 /* Display any IP options */ 1184 cp = (u_char *)buf + sizeof(struct ip); 1185 1186 for (; hlen > (int)sizeof(struct ip); --hlen, ++cp) 1187 switch (*cp) { 1188 case IPOPT_EOL: 1189 hlen = 0; 1190 break; 1191 case IPOPT_LSRR: 1192 case IPOPT_SSRR: 1193 (void)printf(*cp == IPOPT_LSRR ? 1194 "\nLSRR: " : "\nSSRR: "); 1195 j = cp[IPOPT_OLEN] - IPOPT_MINOFF + 1; 1196 hlen -= 2; 1197 cp += 2; 1198 if (j >= INADDR_LEN && 1199 j <= hlen - (int)sizeof(struct ip)) { 1200 for (;;) { 1201 bcopy(++cp, &ina.s_addr, INADDR_LEN); 1202 if (ina.s_addr == 0) 1203 (void)printf("\t0.0.0.0"); 1204 else 1205 (void)printf("\t%s", 1206 pr_addr(ina)); 1207 hlen -= INADDR_LEN; 1208 cp += INADDR_LEN - 1; 1209 j -= INADDR_LEN; 1210 if (j < INADDR_LEN) 1211 break; 1212 (void)putchar('\n'); 1213 } 1214 } else 1215 (void)printf("\t(truncated route)\n"); 1216 break; 1217 case IPOPT_RR: 1218 j = cp[IPOPT_OLEN]; /* get length */ 1219 i = cp[IPOPT_OFFSET]; /* and pointer */ 1220 hlen -= 2; 1221 cp += 2; 1222 if (i > j) 1223 i = j; 1224 i = i - IPOPT_MINOFF + 1; 1225 if (i < 0 || i > (hlen - (int)sizeof(struct ip))) { 1226 old_rrlen = 0; 1227 continue; 1228 } 1229 if (i == old_rrlen 1230 && !bcmp((char *)cp, old_rr, i) 1231 && !(options & F_FLOOD)) { 1232 (void)printf("\t(same route)"); 1233 hlen -= i; 1234 cp += i; 1235 break; 1236 } 1237 old_rrlen = i; 1238 bcopy((char *)cp, old_rr, i); 1239 (void)printf("\nRR: "); 1240 if (i >= INADDR_LEN && 1241 i <= hlen - (int)sizeof(struct ip)) { 1242 for (;;) { 1243 bcopy(++cp, &ina.s_addr, INADDR_LEN); 1244 if (ina.s_addr == 0) 1245 (void)printf("\t0.0.0.0"); 1246 else 1247 (void)printf("\t%s", 1248 pr_addr(ina)); 1249 hlen -= INADDR_LEN; 1250 cp += INADDR_LEN - 1; 1251 i -= INADDR_LEN; 1252 if (i < INADDR_LEN) 1253 break; 1254 (void)putchar('\n'); 1255 } 1256 } else 1257 (void)printf("\t(truncated route)"); 1258 break; 1259 case IPOPT_NOP: 1260 (void)printf("\nNOP"); 1261 break; 1262 default: 1263 (void)printf("\nunknown option %x", *cp); 1264 break; 1265 } 1266 if (!(options & F_FLOOD)) { 1267 (void)putchar('\n'); 1268 (void)fflush(stdout); 1269 } 1270 } 1271 1272 /* 1273 * in_cksum -- 1274 * Checksum routine for Internet Protocol family headers (C Version) 1275 */ 1276 u_short 1277 in_cksum(u_short *addr, int len) 1278 { 1279 int nleft, sum; 1280 u_short *w; 1281 union { 1282 u_short us; 1283 u_char uc[2]; 1284 } last; 1285 u_short answer; 1286 1287 nleft = len; 1288 sum = 0; 1289 w = addr; 1290 1291 /* 1292 * Our algorithm is simple, using a 32 bit accumulator (sum), we add 1293 * sequential 16 bit words to it, and at the end, fold back all the 1294 * carry bits from the top 16 bits into the lower 16 bits. 1295 */ 1296 while (nleft > 1) { 1297 sum += *w++; 1298 nleft -= 2; 1299 } 1300 1301 /* mop up an odd byte, if necessary */ 1302 if (nleft == 1) { 1303 last.uc[0] = *(u_char *)w; 1304 last.uc[1] = 0; 1305 sum += last.us; 1306 } 1307 1308 /* add back carry outs from top 16 bits to low 16 bits */ 1309 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 1310 sum += (sum >> 16); /* add carry */ 1311 answer = ~sum; /* truncate to 16 bits */ 1312 return(answer); 1313 } 1314 1315 /* 1316 * tvsub -- 1317 * Subtract 2 timeval structs: out = out - in. Out is assumed to 1318 * be >= in. 1319 */ 1320 static void 1321 tvsub(struct timeval *out, const struct timeval *in) 1322 { 1323 1324 if ((out->tv_usec -= in->tv_usec) < 0) { 1325 --out->tv_sec; 1326 out->tv_usec += 1000000; 1327 } 1328 out->tv_sec -= in->tv_sec; 1329 } 1330 1331 /* 1332 * status -- 1333 * Print out statistics when SIGINFO is received. 1334 */ 1335 1336 static void 1337 status(int sig __unused) 1338 { 1339 1340 siginfo_p = 1; 1341 } 1342 1343 static void 1344 check_status(void) 1345 { 1346 1347 if (siginfo_p) { 1348 siginfo_p = 0; 1349 (void)fprintf(stderr, "\r%ld/%ld packets received (%.1f%%)", 1350 nreceived, ntransmitted, 1351 ntransmitted ? nreceived * 100.0 / ntransmitted : 0.0); 1352 if (nreceived && timing) 1353 (void)fprintf(stderr, " %.3f min / %.3f avg / %.3f max", 1354 tmin, tsum / (nreceived + nrepeats), tmax); 1355 (void)fprintf(stderr, "\n"); 1356 } 1357 } 1358 1359 /* 1360 * finish -- 1361 * Print out statistics, and give up. 1362 */ 1363 static void 1364 finish(void) 1365 { 1366 1367 (void)signal(SIGINT, SIG_IGN); 1368 (void)signal(SIGALRM, SIG_IGN); 1369 (void)putchar('\n'); 1370 (void)fflush(stdout); 1371 (void)printf("--- %s ping statistics ---\n", hostname); 1372 (void)printf("%ld packets transmitted, ", ntransmitted); 1373 (void)printf("%ld packets received, ", nreceived); 1374 if (nrepeats) 1375 (void)printf("+%ld duplicates, ", nrepeats); 1376 if (ntransmitted) { 1377 if (nreceived > ntransmitted) 1378 (void)printf("-- somebody's printing up packets!"); 1379 else 1380 (void)printf("%.1f%% packet loss", 1381 ((ntransmitted - nreceived) * 100.0) / 1382 ntransmitted); 1383 } 1384 if (nrcvtimeout) 1385 (void)printf(", %ld packets out of wait time", nrcvtimeout); 1386 (void)putchar('\n'); 1387 if (nreceived && timing) { 1388 double n = nreceived + nrepeats; 1389 double avg = tsum / n; 1390 double vari = tsumsq / n - avg * avg; 1391 (void)printf( 1392 "round-trip min/avg/max/stddev = %.3f/%.3f/%.3f/%.3f ms\n", 1393 tmin, avg, tmax, sqrt(vari)); 1394 } 1395 1396 if (nreceived) 1397 exit(0); 1398 else 1399 exit(2); 1400 } 1401 1402 #ifdef notdef 1403 static char *ttab[] = { 1404 "Echo Reply", /* ip + seq + udata */ 1405 "Dest Unreachable", /* net, host, proto, port, frag, sr + IP */ 1406 "Source Quench", /* IP */ 1407 "Redirect", /* redirect type, gateway, + IP */ 1408 "Echo", 1409 "Time Exceeded", /* transit, frag reassem + IP */ 1410 "Parameter Problem", /* pointer + IP */ 1411 "Timestamp", /* id + seq + three timestamps */ 1412 "Timestamp Reply", /* " */ 1413 "Info Request", /* id + sq */ 1414 "Info Reply" /* " */ 1415 }; 1416 #endif 1417 1418 /* 1419 * pr_icmph -- 1420 * Print a descriptive string about an ICMP header. 1421 */ 1422 static void 1423 pr_icmph(struct icmp *icp) 1424 { 1425 1426 switch(icp->icmp_type) { 1427 case ICMP_ECHOREPLY: 1428 (void)printf("Echo Reply\n"); 1429 /* XXX ID + Seq + Data */ 1430 break; 1431 case ICMP_UNREACH: 1432 switch(icp->icmp_code) { 1433 case ICMP_UNREACH_NET: 1434 (void)printf("Destination Net Unreachable\n"); 1435 break; 1436 case ICMP_UNREACH_HOST: 1437 (void)printf("Destination Host Unreachable\n"); 1438 break; 1439 case ICMP_UNREACH_PROTOCOL: 1440 (void)printf("Destination Protocol Unreachable\n"); 1441 break; 1442 case ICMP_UNREACH_PORT: 1443 (void)printf("Destination Port Unreachable\n"); 1444 break; 1445 case ICMP_UNREACH_NEEDFRAG: 1446 (void)printf("frag needed and DF set (MTU %d)\n", 1447 ntohs(icp->icmp_nextmtu)); 1448 break; 1449 case ICMP_UNREACH_SRCFAIL: 1450 (void)printf("Source Route Failed\n"); 1451 break; 1452 case ICMP_UNREACH_FILTER_PROHIB: 1453 (void)printf("Communication prohibited by filter\n"); 1454 break; 1455 default: 1456 (void)printf("Dest Unreachable, Bad Code: %d\n", 1457 icp->icmp_code); 1458 break; 1459 } 1460 /* Print returned IP header information */ 1461 #ifndef icmp_data 1462 pr_retip(&icp->icmp_ip); 1463 #else 1464 pr_retip((struct ip *)icp->icmp_data); 1465 #endif 1466 break; 1467 case ICMP_SOURCEQUENCH: 1468 (void)printf("Source Quench\n"); 1469 #ifndef icmp_data 1470 pr_retip(&icp->icmp_ip); 1471 #else 1472 pr_retip((struct ip *)icp->icmp_data); 1473 #endif 1474 break; 1475 case ICMP_REDIRECT: 1476 switch(icp->icmp_code) { 1477 case ICMP_REDIRECT_NET: 1478 (void)printf("Redirect Network"); 1479 break; 1480 case ICMP_REDIRECT_HOST: 1481 (void)printf("Redirect Host"); 1482 break; 1483 case ICMP_REDIRECT_TOSNET: 1484 (void)printf("Redirect Type of Service and Network"); 1485 break; 1486 case ICMP_REDIRECT_TOSHOST: 1487 (void)printf("Redirect Type of Service and Host"); 1488 break; 1489 default: 1490 (void)printf("Redirect, Bad Code: %d", icp->icmp_code); 1491 break; 1492 } 1493 (void)printf("(New addr: %s)\n", inet_ntoa(icp->icmp_gwaddr)); 1494 #ifndef icmp_data 1495 pr_retip(&icp->icmp_ip); 1496 #else 1497 pr_retip((struct ip *)icp->icmp_data); 1498 #endif 1499 break; 1500 case ICMP_ECHO: 1501 (void)printf("Echo Request\n"); 1502 /* XXX ID + Seq + Data */ 1503 break; 1504 case ICMP_TIMXCEED: 1505 switch(icp->icmp_code) { 1506 case ICMP_TIMXCEED_INTRANS: 1507 (void)printf("Time to live exceeded\n"); 1508 break; 1509 case ICMP_TIMXCEED_REASS: 1510 (void)printf("Frag reassembly time exceeded\n"); 1511 break; 1512 default: 1513 (void)printf("Time exceeded, Bad Code: %d\n", 1514 icp->icmp_code); 1515 break; 1516 } 1517 #ifndef icmp_data 1518 pr_retip(&icp->icmp_ip); 1519 #else 1520 pr_retip((struct ip *)icp->icmp_data); 1521 #endif 1522 break; 1523 case ICMP_PARAMPROB: 1524 (void)printf("Parameter problem: pointer = 0x%02x\n", 1525 icp->icmp_hun.ih_pptr); 1526 #ifndef icmp_data 1527 pr_retip(&icp->icmp_ip); 1528 #else 1529 pr_retip((struct ip *)icp->icmp_data); 1530 #endif 1531 break; 1532 case ICMP_TSTAMP: 1533 (void)printf("Timestamp\n"); 1534 /* XXX ID + Seq + 3 timestamps */ 1535 break; 1536 case ICMP_TSTAMPREPLY: 1537 (void)printf("Timestamp Reply\n"); 1538 /* XXX ID + Seq + 3 timestamps */ 1539 break; 1540 case ICMP_IREQ: 1541 (void)printf("Information Request\n"); 1542 /* XXX ID + Seq */ 1543 break; 1544 case ICMP_IREQREPLY: 1545 (void)printf("Information Reply\n"); 1546 /* XXX ID + Seq */ 1547 break; 1548 case ICMP_MASKREQ: 1549 (void)printf("Address Mask Request\n"); 1550 break; 1551 case ICMP_MASKREPLY: 1552 (void)printf("Address Mask Reply\n"); 1553 break; 1554 case ICMP_ROUTERADVERT: 1555 (void)printf("Router Advertisement\n"); 1556 break; 1557 case ICMP_ROUTERSOLICIT: 1558 (void)printf("Router Solicitation\n"); 1559 break; 1560 default: 1561 (void)printf("Bad ICMP type: %d\n", icp->icmp_type); 1562 } 1563 } 1564 1565 /* 1566 * pr_iph -- 1567 * Print an IP header with options. 1568 */ 1569 static void 1570 pr_iph(struct ip *ip) 1571 { 1572 u_char *cp; 1573 int hlen; 1574 1575 hlen = ip->ip_hl << 2; 1576 cp = (u_char *)ip + 20; /* point to options */ 1577 1578 (void)printf("Vr HL TOS Len ID Flg off TTL Pro cks Src Dst\n"); 1579 (void)printf(" %1x %1x %02x %04x %04x", 1580 ip->ip_v, ip->ip_hl, ip->ip_tos, ntohs(ip->ip_len), 1581 ntohs(ip->ip_id)); 1582 (void)printf(" %1lx %04lx", 1583 (u_long) (ntohl(ip->ip_off) & 0xe000) >> 13, 1584 (u_long) ntohl(ip->ip_off) & 0x1fff); 1585 (void)printf(" %02x %02x %04x", ip->ip_ttl, ip->ip_p, 1586 ntohs(ip->ip_sum)); 1587 (void)printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->ip_src.s_addr)); 1588 (void)printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->ip_dst.s_addr)); 1589 /* dump any option bytes */ 1590 while (hlen-- > 20) { 1591 (void)printf("%02x", *cp++); 1592 } 1593 (void)putchar('\n'); 1594 } 1595 1596 /* 1597 * pr_addr -- 1598 * Return an ascii host address as a dotted quad and optionally with 1599 * a hostname. 1600 */ 1601 static char * 1602 pr_addr(struct in_addr ina) 1603 { 1604 struct hostent *hp; 1605 static char buf[16 + 3 + MAXHOSTNAMELEN]; 1606 1607 if ((options & F_NUMERIC) || 1608 !(hp = gethostbyaddr((char *)&ina, 4, AF_INET))) 1609 return inet_ntoa(ina); 1610 else 1611 (void)snprintf(buf, sizeof(buf), "%s (%s)", hp->h_name, 1612 inet_ntoa(ina)); 1613 return(buf); 1614 } 1615 1616 /* 1617 * pr_retip -- 1618 * Dump some info on a returned (via ICMP) IP packet. 1619 */ 1620 static void 1621 pr_retip(struct ip *ip) 1622 { 1623 u_char *cp; 1624 int hlen; 1625 1626 pr_iph(ip); 1627 hlen = ip->ip_hl << 2; 1628 cp = (u_char *)ip + hlen; 1629 1630 if (ip->ip_p == 6) 1631 (void)printf("TCP: from port %u, to port %u (decimal)\n", 1632 (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3))); 1633 else if (ip->ip_p == 17) 1634 (void)printf("UDP: from port %u, to port %u (decimal)\n", 1635 (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3))); 1636 } 1637 1638 static char * 1639 pr_ntime(n_time timestamp) 1640 { 1641 static char buf[10]; 1642 int hour, min, sec; 1643 1644 sec = ntohl(timestamp) / 1000; 1645 hour = sec / 60 / 60; 1646 min = (sec % (60 * 60)) / 60; 1647 sec = (sec % (60 * 60)) % 60; 1648 1649 (void)snprintf(buf, sizeof(buf), "%02d:%02d:%02d", hour, min, sec); 1650 1651 return (buf); 1652 } 1653 1654 static void 1655 fill(char *bp, char *patp) 1656 { 1657 char *cp; 1658 int pat[16]; 1659 u_int ii, jj, kk; 1660 1661 for (cp = patp; *cp; cp++) { 1662 if (!isxdigit(*cp)) 1663 errx(EX_USAGE, 1664 "patterns must be specified as hex digits"); 1665 1666 } 1667 ii = sscanf(patp, 1668 "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x", 1669 &pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6], 1670 &pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12], 1671 &pat[13], &pat[14], &pat[15]); 1672 1673 if (ii > 0) 1674 for (kk = 0; kk <= maxpayload - (TIMEVAL_LEN + ii); kk += ii) 1675 for (jj = 0; jj < ii; ++jj) 1676 bp[jj + kk] = pat[jj]; 1677 if (!(options & F_QUIET)) { 1678 (void)printf("PATTERN: 0x"); 1679 for (jj = 0; jj < ii; ++jj) 1680 (void)printf("%02x", bp[jj] & 0xFF); 1681 (void)printf("\n"); 1682 } 1683 } 1684 1685 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) 1686 #define SECOPT " [-P policy]" 1687 #else 1688 #define SECOPT "" 1689 #endif 1690 static void 1691 usage(void) 1692 { 1693 1694 (void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n", 1695 "usage: ping [-AaDdfnoQqRrv] [-c count] [-G sweepmaxsize] [-g sweepminsize]", 1696 " [-h sweepincrsize] [-i wait] [-l preload] [-M mask | time] [-m ttl]", 1697 " " SECOPT " [-p pattern] [-S src_addr] [-s packetsize] [-t timeout]", 1698 " [-W waittime] [-z tos] host", 1699 " ping [-AaDdfLnoQqRrv] [-c count] [-I iface] [-i wait] [-l preload]", 1700 " [-M mask | time] [-m ttl]" SECOPT " [-p pattern] [-S src_addr]", 1701 " [-s packetsize] [-T ttl] [-t timeout] [-W waittime]", 1702 " [-z tos] mcast-group"); 1703 exit(EX_USAGE); 1704 } 1705