1 /* $OpenBSD: ping.c,v 1.240 2020/02/11 18:41:39 deraadt Exp $ */ 2 3 /* 4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the project nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 /* 33 * Copyright (c) 1989, 1993 34 * The Regents of the University of California. All rights reserved. 35 * 36 * This code is derived from software contributed to Berkeley by 37 * Mike Muuss. 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 3. Neither the name of the University nor the names of its contributors 48 * may be used to endorse or promote products derived from this software 49 * without specific prior written permission. 50 * 51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 61 * SUCH DAMAGE. 62 */ 63 64 /* 65 * Using the InterNet Control Message Protocol (ICMP) "ECHO" facility, 66 * measure round-trip-delays and packet loss across network paths. 67 * 68 * Author - 69 * Mike Muuss 70 * U. S. Army Ballistic Research Laboratory 71 * December, 1983 72 * 73 * Status - 74 * Public Domain. Distribution Unlimited. 75 * Bugs - 76 * More statistics could always be gathered. 77 * This program has to run SUID to ROOT to access the ICMP socket. 78 */ 79 80 #include <sys/types.h> 81 #include <sys/socket.h> 82 #include <sys/time.h> 83 #include <sys/uio.h> 84 85 #include <netinet/in.h> 86 #include <netinet/ip.h> 87 #include <netinet/ip_icmp.h> 88 #include <netinet/ip_var.h> 89 #include <netinet/ip6.h> 90 #include <netinet/icmp6.h> 91 #include <netinet/ip_ah.h> 92 #include <arpa/inet.h> 93 #include <netdb.h> 94 95 #include <ctype.h> 96 #include <err.h> 97 #include <errno.h> 98 #include <limits.h> 99 #include <math.h> 100 #include <poll.h> 101 #include <pwd.h> 102 #include <signal.h> 103 #include <siphash.h> 104 #include <stdint.h> 105 #include <stdio.h> 106 #include <stdlib.h> 107 #include <string.h> 108 #include <time.h> 109 #include <unistd.h> 110 111 struct tv64 { 112 u_int64_t tv64_sec; 113 u_int64_t tv64_nsec; 114 }; 115 116 struct payload { 117 struct tv64 tv64; 118 u_int8_t mac[SIPHASH_DIGEST_LENGTH]; 119 }; 120 121 #define ECHOLEN 8 /* icmp echo header len excluding time */ 122 #define ECHOTMLEN sizeof(struct payload) 123 #define DEFDATALEN (64 - ECHOLEN) /* default data length */ 124 #define MAXIPLEN 60 125 #define MAXICMPLEN 76 126 #define MAXPAYLOAD (IP_MAXPACKET - MAXIPLEN - ECHOLEN) 127 #define IP6LEN 40 128 #define EXTRA 256 /* for AH and various other headers. weird. */ 129 #define MAXPAYLOAD6 IPV6_MAXPACKET - IP6LEN - ECHOLEN 130 #define MAXWAIT_DEFAULT 10 /* secs to wait for response */ 131 #define NROUTES 9 /* number of record route slots */ 132 133 #define A(bit) rcvd_tbl[(bit)>>3] /* identify byte in array */ 134 #define B(bit) (1 << ((bit) & 0x07)) /* identify bit in byte */ 135 #define SET(bit) (A(bit) |= B(bit)) 136 #define CLR(bit) (A(bit) &= (~B(bit))) 137 #define TST(bit) (A(bit) & B(bit)) 138 139 /* various options */ 140 int options; 141 #define F_FLOOD 0x0001 142 #define F_INTERVAL 0x0002 143 #define F_HOSTNAME 0x0004 144 #define F_PINGFILLED 0x0008 145 #define F_QUIET 0x0010 146 #define F_RROUTE 0x0020 147 #define F_SO_DEBUG 0x0040 148 /* 0x0080 */ 149 #define F_VERBOSE 0x0100 150 /* 0x0200 */ 151 #define F_HDRINCL 0x0400 152 #define F_TTL 0x0800 153 #define F_TOS 0x1000 154 #define F_AUD_RECV 0x2000 155 #define F_AUD_MISS 0x4000 156 157 /* multicast options */ 158 int moptions; 159 #define MULTICAST_NOLOOP 0x001 160 #define MULTICAST_TTL 0x002 161 162 #define DUMMY_PORT 10101 163 #define PING_USER "_ping" 164 165 /* 166 * MAX_DUP_CHK is the number of bits in received table, i.e. the maximum 167 * number of received sequence numbers we can keep track of. Change 128 168 * to 8192 for complete accuracy... 169 */ 170 #define MAX_DUP_CHK (8 * 8192) 171 int mx_dup_ck = MAX_DUP_CHK; 172 char rcvd_tbl[MAX_DUP_CHK / 8]; 173 174 int datalen = DEFDATALEN; 175 int maxpayload = MAXPAYLOAD; 176 u_char outpackhdr[IP_MAXPACKET+sizeof(struct ip)]; 177 u_char *outpack = outpackhdr+sizeof(struct ip); 178 char BSPACE = '\b'; /* characters written for flood */ 179 char DOT = '.'; 180 char *hostname; 181 int ident; /* random number to identify our packets */ 182 int v6flag; /* are we ping6? */ 183 184 /* counters */ 185 int64_t npackets; /* max packets to transmit */ 186 int64_t nreceived; /* # of packets we got back */ 187 int64_t nrepeats; /* number of duplicates */ 188 int64_t ntransmitted; /* sequence # for outbound packets = #sent */ 189 int64_t nmissedmax = 1; /* max value of ntransmitted - nreceived - 1 */ 190 struct timeval interval = {1, 0}; /* interval between packets */ 191 192 /* timing */ 193 int timing; /* flag to do timing */ 194 int timinginfo; 195 unsigned int maxwait = MAXWAIT_DEFAULT; /* max seconds to wait for response */ 196 double tmin = 999999999.0; /* minimum round trip time */ 197 double tmax; /* maximum round trip time */ 198 double tsum; /* sum of all times, for doing average */ 199 double tsumsq; /* sum of all times squared, for std. dev. */ 200 201 struct tv64 tv64_offset; 202 SIPHASH_KEY mac_key; 203 204 struct msghdr smsghdr; 205 struct iovec smsgiov; 206 207 volatile sig_atomic_t seenalrm; 208 volatile sig_atomic_t seenint; 209 volatile sig_atomic_t seeninfo; 210 211 void fill(char *, char *); 212 void summary(void); 213 void onsignal(int); 214 void retransmit(int); 215 int pinger(int); 216 const char *pr_addr(struct sockaddr *, socklen_t); 217 void pr_pack(u_char *, int, struct msghdr *); 218 __dead void usage(void); 219 220 /* IPv4 specific functions */ 221 void pr_ipopt(int, u_char *); 222 int in_cksum(u_short *, int); 223 void pr_icmph(struct icmp *); 224 void pr_retip(struct ip *); 225 void pr_iph(struct ip *); 226 #ifndef SMALL 227 int map_tos(char *, int *); 228 #endif /* SMALL */ 229 230 /* IPv6 specific functions */ 231 int get_hoplim(struct msghdr *); 232 int get_pathmtu(struct msghdr *, struct sockaddr_in6 *); 233 void pr_icmph6(struct icmp6_hdr *, u_char *); 234 void pr_iph6(struct ip6_hdr *); 235 void pr_exthdrs(struct msghdr *); 236 void pr_ip6opt(void *); 237 void pr_rthdr(void *); 238 void pr_retip6(struct ip6_hdr *, u_char *); 239 240 int 241 main(int argc, char *argv[]) 242 { 243 struct addrinfo hints, *res; 244 struct itimerval itimer; 245 struct sockaddr *from, *dst; 246 struct sockaddr_in from4, dst4; 247 struct sockaddr_in6 from6, dst6; 248 struct cmsghdr *scmsg = NULL; 249 struct in6_pktinfo *pktinfo = NULL; 250 struct icmp6_filter filt; 251 struct passwd *pw; 252 socklen_t maxsizelen; 253 int64_t preload; 254 int ch, i, optval = 1, packlen, maxsize, error, s; 255 int df = 0, tos = 0, bufspace = IP_MAXPACKET, hoplimit = -1, mflag = 0; 256 u_char *datap, *packet; 257 u_char ttl = MAXTTL; 258 char *e, *target, hbuf[NI_MAXHOST], *source = NULL; 259 char rspace[3 + 4 * NROUTES + 1]; /* record route space */ 260 const char *errstr; 261 double fraction, integral, seconds; 262 uid_t ouid, uid; 263 gid_t gid; 264 u_int rtableid = 0; 265 extern char *__progname; 266 267 /* Cannot pledge due to special setsockopt()s below */ 268 if (unveil("/", "r") == -1) 269 err(1, "unveil"); 270 if (unveil(NULL, NULL) == -1) 271 err(1, "unveil"); 272 273 if (strcmp("ping6", __progname) == 0) { 274 v6flag = 1; 275 maxpayload = MAXPAYLOAD6; 276 if ((s = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) == -1) 277 err(1, "socket"); 278 } else { 279 if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1) 280 err(1, "socket"); 281 } 282 283 /* revoke privs */ 284 ouid = getuid(); 285 if (ouid == 0 && (pw = getpwnam(PING_USER)) != NULL) { 286 uid = pw->pw_uid; 287 gid = pw->pw_gid; 288 } else { 289 uid = getuid(); 290 gid = getgid(); 291 } 292 if (ouid && (setgroups(1, &gid) || 293 setresgid(gid, gid, gid) || 294 setresuid(uid, uid, uid))) 295 err(1, "unable to revoke privs"); 296 297 preload = 0; 298 datap = &outpack[ECHOLEN + ECHOTMLEN]; 299 while ((ch = getopt(argc, argv, v6flag ? 300 "c:DdEefHh:I:i:Ll:mNnp:qS:s:T:V:vw:" : 301 "DEI:LRS:c:defHi:l:np:qs:T:t:V:vw:")) != -1) { 302 switch(ch) { 303 case 'c': 304 npackets = strtonum(optarg, 0, INT64_MAX, &errstr); 305 if (errstr) 306 errx(1, 307 "number of packets to transmit is %s: %s", 308 errstr, optarg); 309 break; 310 case 'D': 311 options |= F_HDRINCL; 312 df = 1; 313 break; 314 case 'd': 315 options |= F_SO_DEBUG; 316 break; 317 case 'E': 318 options |= F_AUD_MISS; 319 break; 320 case 'e': 321 options |= F_AUD_RECV; 322 break; 323 case 'f': 324 if (ouid) 325 errc(1, EPERM, NULL); 326 options |= F_FLOOD; 327 setvbuf(stdout, NULL, _IONBF, 0); 328 break; 329 case 'H': 330 options |= F_HOSTNAME; 331 break; 332 case 'h': /* hoplimit */ 333 hoplimit = strtonum(optarg, 0, IPV6_MAXHLIM, &errstr); 334 if (errstr) 335 errx(1, "hoplimit is %s: %s", errstr, optarg); 336 break; 337 case 'I': 338 case 'S': /* deprecated */ 339 source = optarg; 340 break; 341 case 'i': /* interval between packets */ 342 seconds = strtod(optarg, &e); 343 if (*optarg == '\0' || *e != '\0' || seconds < 0.0) 344 errx(1, "interval is invalid: %s", optarg); 345 fraction = modf(seconds, &integral); 346 if (integral > UINT_MAX) 347 errx(1, "interval is too large: %s", optarg); 348 interval.tv_sec = integral; 349 interval.tv_usec = fraction * 1000000.0; 350 if (!timerisset(&interval)) 351 errx(1, "interval is too small: %s", optarg); 352 if (interval.tv_sec < 1 && ouid != 0) { 353 errx(1, "only root may use an interval smaller" 354 "than one second"); 355 } 356 options |= F_INTERVAL; 357 break; 358 case 'L': 359 moptions |= MULTICAST_NOLOOP; 360 break; 361 case 'l': 362 if (ouid) 363 errc(1, EPERM, NULL); 364 preload = strtonum(optarg, 1, INT64_MAX, &errstr); 365 if (errstr) 366 errx(1, "preload value is %s: %s", errstr, 367 optarg); 368 break; 369 case 'm': 370 mflag++; 371 break; 372 case 'n': 373 options &= ~F_HOSTNAME; 374 break; 375 case 'p': /* fill buffer with user pattern */ 376 options |= F_PINGFILLED; 377 fill((char *)datap, optarg); 378 break; 379 case 'q': 380 options |= F_QUIET; 381 break; 382 case 'R': 383 options |= F_RROUTE; 384 break; 385 case 's': /* size of packet to send */ 386 datalen = strtonum(optarg, 0, maxpayload, &errstr); 387 if (errstr) 388 errx(1, "packet size is %s: %s", errstr, 389 optarg); 390 break; 391 #ifndef SMALL 392 case 'T': 393 options |= F_HDRINCL; 394 options |= F_TOS; 395 errno = 0; 396 errstr = NULL; 397 if (map_tos(optarg, &tos)) 398 break; 399 if (strlen(optarg) > 1 && optarg[0] == '0' && 400 optarg[1] == 'x') 401 tos = (int)strtol(optarg, NULL, 16); 402 else 403 tos = strtonum(optarg, 0, 255, &errstr); 404 if (tos < 0 || tos > 255 || errstr || errno) 405 errx(1, "illegal tos value %s", optarg); 406 break; 407 #endif /* SMALL */ 408 case 't': 409 options |= F_TTL; 410 ttl = strtonum(optarg, 0, MAXTTL, &errstr); 411 if (errstr) 412 errx(1, "ttl value is %s: %s", errstr, optarg); 413 break; 414 case 'V': 415 rtableid = strtonum(optarg, 0, RT_TABLEID_MAX, &errstr); 416 if (errstr) 417 errx(1, "rtable value is %s: %s", errstr, 418 optarg); 419 if (setsockopt(s, SOL_SOCKET, SO_RTABLE, &rtableid, 420 sizeof(rtableid)) == -1) 421 err(1, "setsockopt SO_RTABLE"); 422 break; 423 case 'v': 424 options |= F_VERBOSE; 425 break; 426 case 'w': 427 maxwait = strtonum(optarg, 1, INT_MAX, &errstr); 428 if (errstr) 429 errx(1, "maxwait value is %s: %s", 430 errstr, optarg); 431 break; 432 default: 433 usage(); 434 } 435 } 436 437 if (ouid == 0 && (setgroups(1, &gid) || 438 setresgid(gid, gid, gid) || 439 setresuid(uid, uid, uid))) 440 err(1, "unable to revoke privs"); 441 442 argc -= optind; 443 argv += optind; 444 445 if (argc != 1) 446 usage(); 447 448 memset(&dst4, 0, sizeof(dst4)); 449 memset(&dst6, 0, sizeof(dst6)); 450 451 target = *argv; 452 453 memset(&hints, 0, sizeof(hints)); 454 hints.ai_family = v6flag ? AF_INET6 : AF_INET; 455 hints.ai_socktype = SOCK_RAW; 456 hints.ai_protocol = 0; 457 hints.ai_flags = AI_CANONNAME; 458 if ((error = getaddrinfo(target, NULL, &hints, &res))) 459 errx(1, "%s", gai_strerror(error)); 460 461 switch (res->ai_family) { 462 case AF_INET: 463 dst = (struct sockaddr *)&dst4; 464 from = (struct sockaddr *)&from4; 465 break; 466 case AF_INET6: 467 dst = (struct sockaddr *)&dst6; 468 from = (struct sockaddr *)&from6; 469 break; 470 default: 471 errx(1, "unsupported AF: %d", res->ai_family); 472 break; 473 } 474 475 memcpy(dst, res->ai_addr, res->ai_addrlen); 476 477 if (!hostname) { 478 hostname = res->ai_canonname ? strdup(res->ai_canonname) : 479 target; 480 if (!hostname) 481 err(1, "malloc"); 482 } 483 484 if (res->ai_next) { 485 if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, 486 sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) 487 strlcpy(hbuf, "?", sizeof(hbuf)); 488 warnx("Warning: %s has multiple " 489 "addresses; using %s", hostname, hbuf); 490 } 491 freeaddrinfo(res); 492 493 if (source) { 494 memset(&hints, 0, sizeof(hints)); 495 hints.ai_family = dst->sa_family; 496 if ((error = getaddrinfo(source, NULL, &hints, &res))) 497 errx(1, "%s: %s", source, gai_strerror(error)); 498 memcpy(from, res->ai_addr, res->ai_addrlen); 499 freeaddrinfo(res); 500 501 if (!v6flag && IN_MULTICAST(ntohl(dst4.sin_addr.s_addr))) { 502 if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, 503 &from4.sin_addr, sizeof(from4.sin_addr)) == -1) 504 err(1, "setsockopt IP_MULTICAST_IF"); 505 } else { 506 if (bind(s, from, from->sa_len) == -1) 507 err(1, "bind"); 508 } 509 } else if (options & F_VERBOSE) { 510 /* 511 * get the source address. XXX since we revoked the root 512 * privilege, we cannot use a raw socket for this. 513 */ 514 int dummy; 515 socklen_t len = dst->sa_len; 516 517 if ((dummy = socket(dst->sa_family, SOCK_DGRAM, 0)) == -1) 518 err(1, "UDP socket"); 519 520 memcpy(from, dst, dst->sa_len); 521 if (v6flag) { 522 from6.sin6_port = ntohs(DUMMY_PORT); 523 if (pktinfo && 524 setsockopt(dummy, IPPROTO_IPV6, IPV6_PKTINFO, 525 pktinfo, sizeof(*pktinfo))) 526 err(1, "UDP setsockopt(IPV6_PKTINFO)"); 527 528 if (hoplimit != -1 && 529 setsockopt(dummy, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 530 &hoplimit, sizeof(hoplimit))) 531 err(1, "UDP setsockopt(IPV6_UNICAST_HOPS)"); 532 533 if (hoplimit != -1 && 534 setsockopt(dummy, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 535 &hoplimit, sizeof(hoplimit))) 536 err(1, "UDP setsockopt(IPV6_MULTICAST_HOPS)"); 537 } else { 538 u_char loop = 0; 539 540 from4.sin_port = ntohs(DUMMY_PORT); 541 542 if ((moptions & MULTICAST_NOLOOP) && setsockopt(dummy, 543 IPPROTO_IP, IP_MULTICAST_LOOP, &loop, 544 sizeof(loop)) == -1) 545 err(1, "setsockopt IP_MULTICAST_LOOP"); 546 if ((moptions & MULTICAST_TTL) && setsockopt(dummy, 547 IPPROTO_IP, IP_MULTICAST_TTL, &ttl, 548 sizeof(ttl)) == -1) 549 err(1, "setsockopt IP_MULTICAST_TTL"); 550 } 551 552 if (rtableid > 0 && 553 setsockopt(dummy, SOL_SOCKET, SO_RTABLE, &rtableid, 554 sizeof(rtableid)) == -1) 555 err(1, "setsockopt(SO_RTABLE)"); 556 557 if (connect(dummy, from, len) == -1) 558 err(1, "UDP connect"); 559 560 if (getsockname(dummy, from, &len) == -1) 561 err(1, "getsockname"); 562 563 close(dummy); 564 } 565 566 if (options & F_SO_DEBUG) 567 (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, &optval, 568 sizeof(optval)); 569 570 if ((options & F_FLOOD) && (options & F_INTERVAL)) 571 errx(1, "-f and -i options are incompatible"); 572 573 if ((options & F_FLOOD) && (options & (F_AUD_RECV | F_AUD_MISS))) 574 warnx("No audible output for flood pings"); 575 576 if (datalen >= sizeof(struct payload)) /* can we time transfer */ 577 timing = 1; 578 579 if (v6flag) { 580 /* in F_VERBOSE case, we may get non-echoreply packets*/ 581 if ((options & F_VERBOSE) && datalen < 2048) /* XXX 2048? */ 582 packlen = 2048 + IP6LEN + ECHOLEN + EXTRA; 583 else 584 packlen = datalen + IP6LEN + ECHOLEN + EXTRA; 585 } else 586 packlen = datalen + MAXIPLEN + MAXICMPLEN; 587 if (!(packet = malloc(packlen))) 588 err(1, "malloc"); 589 590 if (!(options & F_PINGFILLED)) 591 for (i = ECHOTMLEN; i < datalen; ++i) 592 *datap++ = i; 593 594 ident = arc4random() & 0xFFFF; 595 596 /* 597 * When trying to send large packets, you must increase the 598 * size of both the send and receive buffers... 599 */ 600 maxsizelen = sizeof maxsize; 601 if (getsockopt(s, SOL_SOCKET, SO_SNDBUF, &maxsize, &maxsizelen) == -1) 602 err(1, "getsockopt"); 603 if (maxsize < packlen && 604 setsockopt(s, SOL_SOCKET, SO_SNDBUF, &packlen, sizeof(maxsize)) == -1) 605 err(1, "setsockopt"); 606 607 /* 608 * When pinging the broadcast address, you can get a lot of answers. 609 * Doing something so evil is useful if you are trying to stress the 610 * ethernet, or just want to fill the arp cache to get some stuff for 611 * /etc/ethers. 612 */ 613 while (setsockopt(s, SOL_SOCKET, SO_RCVBUF, 614 &bufspace, sizeof(bufspace)) == -1) { 615 if ((bufspace -= 1024) <= 0) 616 err(1, "Cannot set the receive buffer size"); 617 } 618 if (bufspace < IP_MAXPACKET) 619 warnx("Could only allocate a receive buffer of %d bytes " 620 "(default %d)", bufspace, IP_MAXPACKET); 621 622 if (v6flag) { 623 unsigned int loop = 0; 624 625 /* 626 * let the kernel pass extension headers of incoming packets, 627 * for privileged socket options 628 */ 629 if (options & F_VERBOSE) { 630 int opton = 1; 631 632 if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPOPTS, 633 &opton, sizeof(opton))) 634 err(1, "setsockopt(IPV6_RECVHOPOPTS)"); 635 if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVDSTOPTS, 636 &opton, sizeof(opton))) 637 err(1, "setsockopt(IPV6_RECVDSTOPTS)"); 638 if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVRTHDR, 639 &opton, sizeof(opton))) 640 err(1, "setsockopt(IPV6_RECVRTHDR)"); 641 ICMP6_FILTER_SETPASSALL(&filt); 642 } else { 643 ICMP6_FILTER_SETBLOCKALL(&filt); 644 ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &filt); 645 } 646 647 if ((moptions & MULTICAST_NOLOOP) && 648 setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, 649 &loop, sizeof(loop)) == -1) 650 err(1, "setsockopt IPV6_MULTICAST_LOOP"); 651 652 optval = IPV6_DEFHLIM; 653 if (IN6_IS_ADDR_MULTICAST(&dst6.sin6_addr)) { 654 if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 655 &optval, sizeof(optval)) == -1) 656 err(1, "IPV6_MULTICAST_HOPS"); 657 } 658 if (mflag != 1) { 659 optval = mflag > 1 ? 0 : 1; 660 661 if (setsockopt(s, IPPROTO_IPV6, IPV6_USE_MIN_MTU, 662 &optval, sizeof(optval)) == -1) 663 err(1, "setsockopt(IPV6_USE_MIN_MTU)"); 664 } else { 665 optval = 1; 666 if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPATHMTU, 667 &optval, sizeof(optval)) == -1) 668 err(1, "setsockopt(IPV6_RECVPATHMTU)"); 669 } 670 671 if (setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, 672 &filt, sizeof(filt)) == -1) 673 err(1, "setsockopt(ICMP6_FILTER)"); 674 675 if (hoplimit != -1) { 676 /* set IP6 packet options */ 677 if ((scmsg = malloc( CMSG_SPACE(sizeof(int)))) == NULL) 678 err(1, "malloc"); 679 smsghdr.msg_control = (caddr_t)scmsg; 680 smsghdr.msg_controllen = CMSG_SPACE(sizeof(int)); 681 682 scmsg->cmsg_len = CMSG_LEN(sizeof(int)); 683 scmsg->cmsg_level = IPPROTO_IPV6; 684 scmsg->cmsg_type = IPV6_HOPLIMIT; 685 *(int *)(CMSG_DATA(scmsg)) = hoplimit; 686 } 687 688 if (options & F_TOS) { 689 optval = tos; 690 if (setsockopt(s, IPPROTO_IPV6, IPV6_TCLASS, 691 &optval, sizeof(optval)) == -1) 692 err(1, "setsockopt(IPV6_TCLASS)"); 693 } 694 695 if (df) { 696 optval = 1; 697 if (setsockopt(s, IPPROTO_IPV6, IPV6_DONTFRAG, 698 &optval, sizeof(optval)) == -1) 699 err(1, "setsockopt(IPV6_DONTFRAG)"); 700 } 701 702 optval = 1; 703 if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, 704 &optval, sizeof(optval)) == -1) 705 err(1, "setsockopt(IPV6_RECVPKTINFO)"); 706 if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, 707 &optval, sizeof(optval)) == -1) 708 err(1, "setsockopt(IPV6_RECVHOPLIMIT)"); 709 } else { 710 u_char loop = 0; 711 712 if (options & F_TTL) { 713 if (IN_MULTICAST(ntohl(dst4.sin_addr.s_addr))) 714 moptions |= MULTICAST_TTL; 715 else 716 options |= F_HDRINCL; 717 } 718 719 if ((options & F_RROUTE) && (options & F_HDRINCL)) 720 errx(1, "-R option and -D or -T, or -t to unicast" 721 " destinations are incompatible"); 722 723 if (options & F_HDRINCL) { 724 struct ip *ip = (struct ip *)outpackhdr; 725 726 if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, 727 &optval, sizeof(optval)) == -1) 728 err(1, "setsockopt(IP_HDRINCL)"); 729 ip->ip_v = IPVERSION; 730 ip->ip_hl = sizeof(struct ip) >> 2; 731 ip->ip_tos = tos; 732 ip->ip_id = 0; 733 ip->ip_off = htons(df ? IP_DF : 0); 734 ip->ip_ttl = ttl; 735 ip->ip_p = IPPROTO_ICMP; 736 if (source) 737 ip->ip_src = from4.sin_addr; 738 else 739 ip->ip_src.s_addr = INADDR_ANY; 740 ip->ip_dst = dst4.sin_addr; 741 } 742 743 /* record route option */ 744 if (options & F_RROUTE) { 745 if (IN_MULTICAST(ntohl(dst4.sin_addr.s_addr))) 746 errx(1, "record route not valid to multicast" 747 " destinations"); 748 memset(rspace, 0, sizeof(rspace)); 749 rspace[IPOPT_OPTVAL] = IPOPT_RR; 750 rspace[IPOPT_OLEN] = sizeof(rspace)-1; 751 rspace[IPOPT_OFFSET] = IPOPT_MINOFF; 752 if (setsockopt(s, IPPROTO_IP, IP_OPTIONS, 753 rspace, sizeof(rspace)) == -1) 754 err(1, "record route"); 755 } 756 757 if ((moptions & MULTICAST_NOLOOP) && 758 setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, 759 &loop, sizeof(loop)) == -1) 760 err(1, "setsockopt IP_MULTICAST_LOOP"); 761 if ((moptions & MULTICAST_TTL) && 762 setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, 763 &ttl, sizeof(ttl)) == -1) 764 err(1, "setsockopt IP_MULTICAST_TTL"); 765 } 766 767 if (options & F_HOSTNAME) { 768 if (pledge("stdio inet dns", NULL) == -1) 769 err(1, "pledge"); 770 } else { 771 if (pledge("stdio inet", NULL) == -1) 772 err(1, "pledge"); 773 } 774 775 arc4random_buf(&tv64_offset, sizeof(tv64_offset)); 776 arc4random_buf(&mac_key, sizeof(mac_key)); 777 778 printf("PING %s (", hostname); 779 if (options & F_VERBOSE) 780 printf("%s --> ", pr_addr(from, from->sa_len)); 781 printf("%s): %d data bytes\n", pr_addr(dst, dst->sa_len), datalen); 782 783 smsghdr.msg_name = dst; 784 smsghdr.msg_namelen = dst->sa_len; 785 smsgiov.iov_base = (caddr_t)outpack; 786 smsghdr.msg_iov = &smsgiov; 787 smsghdr.msg_iovlen = 1; 788 789 while (preload--) /* Fire off them quickies. */ 790 pinger(s); 791 792 (void)signal(SIGINT, onsignal); 793 (void)signal(SIGINFO, onsignal); 794 795 if (!(options & F_FLOOD)) { 796 (void)signal(SIGALRM, onsignal); 797 itimer.it_interval = interval; 798 itimer.it_value = interval; 799 (void)setitimer(ITIMER_REAL, &itimer, NULL); 800 if (ntransmitted == 0) 801 retransmit(s); 802 } 803 804 seenalrm = seenint = 0; 805 seeninfo = 0; 806 807 for (;;) { 808 struct msghdr m; 809 union { 810 struct cmsghdr hdr; 811 u_char buf[CMSG_SPACE(1024)]; 812 } cmsgbuf; 813 struct iovec iov[1]; 814 struct pollfd pfd; 815 struct sockaddr_in peer4; 816 struct sockaddr_in6 peer6; 817 ssize_t cc; 818 int timeout; 819 820 /* signal handling */ 821 if (seenint) 822 break; 823 if (seenalrm) { 824 retransmit(s); 825 seenalrm = 0; 826 if (ntransmitted - nreceived - 1 > nmissedmax) { 827 nmissedmax = ntransmitted - nreceived - 1; 828 if (!(options & F_FLOOD) && 829 (options & F_AUD_MISS)) 830 fputc('\a', stderr); 831 } 832 continue; 833 } 834 if (seeninfo) { 835 summary(); 836 seeninfo = 0; 837 continue; 838 } 839 840 if (options & F_FLOOD) { 841 if (pinger(s) != 0) { 842 (void)signal(SIGALRM, onsignal); 843 timeout = INFTIM; 844 memset(&itimer, 0, sizeof(itimer)); 845 if (nreceived) { 846 itimer.it_value.tv_sec = 2 * tmax / 847 1000; 848 if (itimer.it_value.tv_sec == 0) 849 itimer.it_value.tv_sec = 1; 850 } else 851 itimer.it_value.tv_sec = maxwait; 852 (void)setitimer(ITIMER_REAL, &itimer, NULL); 853 854 /* When the alarm goes off we are done. */ 855 seenint = 1; 856 } else 857 timeout = 10; 858 } else 859 timeout = INFTIM; 860 861 pfd.fd = s; 862 pfd.events = POLLIN; 863 864 if (poll(&pfd, 1, timeout) <= 0) 865 continue; 866 867 if (v6flag) { 868 m.msg_name = &peer6; 869 m.msg_namelen = sizeof(peer6); 870 } else { 871 m.msg_name = &peer4; 872 m.msg_namelen = sizeof(peer4); 873 } 874 memset(&iov, 0, sizeof(iov)); 875 iov[0].iov_base = (caddr_t)packet; 876 iov[0].iov_len = packlen; 877 m.msg_iov = iov; 878 m.msg_iovlen = 1; 879 m.msg_control = (caddr_t)&cmsgbuf.buf; 880 m.msg_controllen = sizeof(cmsgbuf.buf); 881 882 cc = recvmsg(s, &m, 0); 883 if (cc == -1) { 884 if (errno != EINTR) { 885 warn("recvmsg"); 886 sleep(1); 887 } 888 continue; 889 } else if (cc == 0) { 890 int mtu; 891 892 /* 893 * receive control messages only. Process the 894 * exceptions (currently the only possibility is 895 * a path MTU notification.) 896 */ 897 if ((mtu = get_pathmtu(&m, &dst6)) > 0) { 898 if (options & F_VERBOSE) { 899 printf("new path MTU (%d) is " 900 "notified\n", mtu); 901 } 902 } 903 continue; 904 } else 905 pr_pack(packet, cc, &m); 906 907 if (npackets && nreceived >= npackets) 908 break; 909 } 910 summary(); 911 exit(nreceived == 0); 912 } 913 914 void 915 onsignal(int sig) 916 { 917 switch (sig) { 918 case SIGALRM: 919 seenalrm++; 920 break; 921 case SIGINT: 922 seenint++; 923 break; 924 case SIGINFO: 925 seeninfo++; 926 break; 927 } 928 } 929 930 void 931 fill(char *bp, char *patp) 932 { 933 int ii, jj, kk; 934 int pat[16]; 935 char *cp; 936 937 for (cp = patp; *cp; cp++) 938 if (!isxdigit((unsigned char)*cp)) 939 errx(1, "patterns must be specified as hex digits"); 940 ii = sscanf(patp, 941 "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x", 942 &pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6], 943 &pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12], 944 &pat[13], &pat[14], &pat[15]); 945 946 if (ii > 0) 947 for (kk = 0; 948 kk <= maxpayload - (ECHOLEN + ECHOTMLEN + ii); 949 kk += ii) 950 for (jj = 0; jj < ii; ++jj) 951 bp[jj + kk] = pat[jj]; 952 if (!(options & F_QUIET)) { 953 printf("PATTERN: 0x"); 954 for (jj = 0; jj < ii; ++jj) 955 printf("%02x", bp[jj] & 0xFF); 956 printf("\n"); 957 } 958 } 959 960 void 961 summary(void) 962 { 963 printf("\n--- %s ping statistics ---\n", hostname); 964 printf("%lld packets transmitted, ", ntransmitted); 965 printf("%lld packets received, ", nreceived); 966 967 if (nrepeats) 968 printf("%lld duplicates, ", nrepeats); 969 if (ntransmitted) { 970 if (nreceived > ntransmitted) 971 printf("-- somebody's duplicating packets!"); 972 else 973 printf("%.1f%% packet loss", 974 ((((double)ntransmitted - nreceived) * 100) / 975 ntransmitted)); 976 } 977 printf("\n"); 978 if (timinginfo) { 979 /* Only display average to microseconds */ 980 double num = nreceived + nrepeats; 981 double avg = tsum / num; 982 double dev = sqrt(fmax(0, tsumsq / num - avg * avg)); 983 printf("round-trip min/avg/max/std-dev = %.3f/%.3f/%.3f/%.3f ms\n", 984 tmin, avg, tmax, dev); 985 } 986 } 987 988 /* 989 * pr_addr -- 990 * Return address in numeric form or a host name 991 */ 992 const char * 993 pr_addr(struct sockaddr *addr, socklen_t addrlen) 994 { 995 static char buf[NI_MAXHOST]; 996 int flag = 0; 997 998 if (!(options & F_HOSTNAME)) 999 flag |= NI_NUMERICHOST; 1000 1001 if (getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0, flag) == 0) 1002 return (buf); 1003 else 1004 return "?"; 1005 } 1006 1007 /* 1008 * retransmit -- 1009 * This routine transmits another ping. 1010 */ 1011 void 1012 retransmit(int s) 1013 { 1014 struct itimerval itimer; 1015 static int last_time; 1016 1017 if (last_time) { 1018 seenint = 1; /* break out of ping event loop */ 1019 return; 1020 } 1021 1022 if (pinger(s) == 0) 1023 return; 1024 1025 /* 1026 * If we're not transmitting any more packets, change the timer 1027 * to wait two round-trip times if we've received any packets or 1028 * maxwait seconds if we haven't. 1029 */ 1030 memset(&itimer, 0, sizeof(itimer)); 1031 if (nreceived) { 1032 itimer.it_value.tv_sec = 2 * tmax / 1000; 1033 if (itimer.it_value.tv_sec == 0) 1034 itimer.it_value.tv_sec = 1; 1035 } else 1036 itimer.it_value.tv_sec = maxwait; 1037 (void)setitimer(ITIMER_REAL, &itimer, NULL); 1038 1039 /* When the alarm goes off we are done. */ 1040 last_time = 1; 1041 } 1042 1043 /* 1044 * pinger -- 1045 * Compose and transmit an ICMP ECHO REQUEST packet. The IP packet 1046 * will be added on by the kernel. The ID field is a random number, 1047 * and the sequence number is an ascending integer. The first 8 bytes 1048 * of the data portion are used to hold a UNIX "timeval" struct in VAX 1049 * byte-order, to compute the round-trip time. 1050 */ 1051 int 1052 pinger(int s) 1053 { 1054 struct icmp *icp = NULL; 1055 struct icmp6_hdr *icp6 = NULL; 1056 int cc, i; 1057 u_int16_t seq; 1058 1059 if (npackets && ntransmitted >= npackets) 1060 return(-1); /* no more transmission */ 1061 1062 seq = htons(ntransmitted++); 1063 1064 if (v6flag) { 1065 icp6 = (struct icmp6_hdr *)outpack; 1066 memset(icp6, 0, sizeof(*icp6)); 1067 icp6->icmp6_cksum = 0; 1068 icp6->icmp6_type = ICMP6_ECHO_REQUEST; 1069 icp6->icmp6_code = 0; 1070 icp6->icmp6_id = ident; 1071 icp6->icmp6_seq = seq; 1072 } else { 1073 icp = (struct icmp *)outpack; 1074 icp->icmp_type = ICMP_ECHO; 1075 icp->icmp_code = 0; 1076 icp->icmp_cksum = 0; 1077 icp->icmp_seq = seq; 1078 icp->icmp_id = ident; 1079 } 1080 CLR(ntohs(seq) % mx_dup_ck); 1081 1082 if (timing) { 1083 SIPHASH_CTX ctx; 1084 struct timespec ts; 1085 struct payload payload; 1086 struct tv64 *tv64 = &payload.tv64; 1087 1088 if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) 1089 err(1, "clock_gettime(CLOCK_MONOTONIC)"); 1090 tv64->tv64_sec = htobe64((u_int64_t)ts.tv_sec + 1091 tv64_offset.tv64_sec); 1092 tv64->tv64_nsec = htobe64((u_int64_t)ts.tv_nsec + 1093 tv64_offset.tv64_nsec); 1094 1095 SipHash24_Init(&ctx, &mac_key); 1096 SipHash24_Update(&ctx, tv64, sizeof(*tv64)); 1097 SipHash24_Update(&ctx, &ident, sizeof(ident)); 1098 SipHash24_Update(&ctx, &seq, sizeof(seq)); 1099 SipHash24_Final(&payload.mac, &ctx); 1100 1101 memcpy(&outpack[ECHOLEN], &payload, sizeof(payload)); 1102 } 1103 1104 cc = ECHOLEN + datalen; 1105 1106 if (!v6flag) { 1107 /* compute ICMP checksum here */ 1108 icp->icmp_cksum = in_cksum((u_short *)icp, cc); 1109 1110 if (options & F_HDRINCL) { 1111 struct ip *ip = (struct ip *)outpackhdr; 1112 1113 smsgiov.iov_base = (caddr_t)outpackhdr; 1114 cc += sizeof(struct ip); 1115 ip->ip_len = htons(cc); 1116 ip->ip_sum = in_cksum((u_short *)outpackhdr, cc); 1117 } 1118 } 1119 1120 smsgiov.iov_len = cc; 1121 1122 i = sendmsg(s, &smsghdr, 0); 1123 1124 if (i == -1 || i != cc) { 1125 if (i == -1) 1126 warn("sendmsg"); 1127 printf("ping: wrote %s %d chars, ret=%d\n", hostname, cc, i); 1128 } 1129 if (!(options & F_QUIET) && (options & F_FLOOD)) 1130 write(STDOUT_FILENO, &DOT, 1); 1131 1132 return (0); 1133 } 1134 1135 /* 1136 * pr_pack -- 1137 * Print out the packet, if it came from us. This logic is necessary 1138 * because ALL readers of the ICMP socket get a copy of ALL ICMP packets 1139 * which arrive ('tis only fair). This permits multiple copies of this 1140 * program to be run without having intermingled output (or statistics!). 1141 */ 1142 void 1143 pr_pack(u_char *buf, int cc, struct msghdr *mhdr) 1144 { 1145 struct ip *ip = NULL; 1146 struct icmp *icp = NULL; 1147 struct icmp6_hdr *icp6 = NULL; 1148 struct timespec ts, tp; 1149 struct payload payload; 1150 struct sockaddr *from; 1151 socklen_t fromlen; 1152 double triptime = 0; 1153 int i, dupflag; 1154 int hlen = -1, hoplim = -1, echo_reply = 0; 1155 u_int16_t seq; 1156 u_char *cp, *dp; 1157 char* pkttime; 1158 1159 if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) 1160 err(1, "clock_gettime(CLOCK_MONOTONIC)"); 1161 1162 if (v6flag) { 1163 if (!mhdr || !mhdr->msg_name || 1164 mhdr->msg_namelen != sizeof(struct sockaddr_in6) || 1165 ((struct sockaddr *)mhdr->msg_name)->sa_family != 1166 AF_INET6) { 1167 if (options & F_VERBOSE) 1168 warnx("invalid peername"); 1169 return; 1170 } 1171 from = (struct sockaddr *)mhdr->msg_name; 1172 fromlen = mhdr->msg_namelen; 1173 1174 if (cc < sizeof(struct icmp6_hdr)) { 1175 if (options & F_VERBOSE) 1176 warnx("packet too short (%d bytes) from %s", cc, 1177 pr_addr(from, fromlen)); 1178 return; 1179 } 1180 icp6 = (struct icmp6_hdr *)buf; 1181 1182 if ((hoplim = get_hoplim(mhdr)) == -1) { 1183 warnx("failed to get receiving hop limit"); 1184 return; 1185 } 1186 1187 if (icp6->icmp6_type == ICMP6_ECHO_REPLY) { 1188 if (icp6->icmp6_id != ident) 1189 return; /* 'Twas not our ECHO */ 1190 seq = icp6->icmp6_seq; 1191 echo_reply = 1; 1192 pkttime = (char *)(icp6 + 1); 1193 } 1194 } else { 1195 if (!mhdr || !mhdr->msg_name || 1196 mhdr->msg_namelen != sizeof(struct sockaddr_in) || 1197 ((struct sockaddr *)mhdr->msg_name)->sa_family != AF_INET) { 1198 if (options & F_VERBOSE) 1199 warnx("invalid peername"); 1200 return; 1201 } 1202 1203 from = (struct sockaddr *)mhdr->msg_name; 1204 fromlen = mhdr->msg_namelen; 1205 1206 /* Check the IP header */ 1207 ip = (struct ip *)buf; 1208 hlen = ip->ip_hl << 2; 1209 if (cc < hlen + ICMP_MINLEN) { 1210 if (options & F_VERBOSE) 1211 warnx("packet too short (%d bytes) from %s", cc, 1212 pr_addr(from, fromlen)); 1213 return; 1214 } 1215 1216 /* Now the ICMP part */ 1217 cc -= hlen; 1218 icp = (struct icmp *)(buf + hlen); 1219 if (icp->icmp_type == ICMP_ECHOREPLY) { 1220 if (icp->icmp_id != ident) 1221 return; /* 'Twas not our ECHO */ 1222 seq = icp->icmp_seq; 1223 echo_reply = 1; 1224 pkttime = (char *)icp->icmp_data; 1225 } 1226 } 1227 1228 if (echo_reply) { 1229 ++nreceived; 1230 if (cc >= ECHOLEN + ECHOTMLEN) { 1231 SIPHASH_CTX ctx; 1232 struct tv64 *tv64; 1233 u_int8_t mac[SIPHASH_DIGEST_LENGTH]; 1234 1235 memcpy(&payload, pkttime, sizeof(payload)); 1236 tv64 = &payload.tv64; 1237 1238 SipHash24_Init(&ctx, &mac_key); 1239 SipHash24_Update(&ctx, tv64, sizeof(*tv64)); 1240 SipHash24_Update(&ctx, &ident, sizeof(ident)); 1241 SipHash24_Update(&ctx, &seq, sizeof(seq)); 1242 SipHash24_Final(mac, &ctx); 1243 1244 if (timingsafe_memcmp(mac, &payload.mac, 1245 sizeof(mac)) != 0) { 1246 printf("signature mismatch!\n"); 1247 return; 1248 } 1249 timinginfo=1; 1250 1251 tp.tv_sec = betoh64(tv64->tv64_sec) - 1252 tv64_offset.tv64_sec; 1253 tp.tv_nsec = betoh64(tv64->tv64_nsec) - 1254 tv64_offset.tv64_nsec; 1255 1256 timespecsub(&ts, &tp, &ts); 1257 triptime = ((double)ts.tv_sec) * 1000.0 + 1258 ((double)ts.tv_nsec) / 1000000.0; 1259 tsum += triptime; 1260 tsumsq += triptime * triptime; 1261 if (triptime < tmin) 1262 tmin = triptime; 1263 if (triptime > tmax) 1264 tmax = triptime; 1265 } 1266 1267 if (TST(ntohs(seq) % mx_dup_ck)) { 1268 ++nrepeats; 1269 --nreceived; 1270 dupflag = 1; 1271 } else { 1272 SET(ntohs(seq) % mx_dup_ck); 1273 dupflag = 0; 1274 } 1275 1276 if (options & F_QUIET) 1277 return; 1278 1279 if (options & F_FLOOD) 1280 write(STDOUT_FILENO, &BSPACE, 1); 1281 else { 1282 printf("%d bytes from %s: icmp_seq=%u", cc, 1283 pr_addr(from, fromlen), ntohs(seq)); 1284 if (v6flag) 1285 printf(" hlim=%d", hoplim); 1286 else 1287 printf(" ttl=%d", ip->ip_ttl); 1288 if (cc >= ECHOLEN + ECHOTMLEN) 1289 printf(" time=%.3f ms", triptime); 1290 if (dupflag) 1291 printf(" (DUP!)"); 1292 /* check the data */ 1293 if (cc - ECHOLEN < datalen) 1294 printf(" (TRUNC!)"); 1295 if (v6flag) 1296 cp = buf + ECHOLEN + ECHOTMLEN; 1297 else 1298 cp = (u_char *)&icp->icmp_data[ECHOTMLEN]; 1299 dp = &outpack[ECHOLEN + ECHOTMLEN]; 1300 for (i = ECHOLEN + ECHOTMLEN; 1301 i < cc && i < datalen; 1302 ++i, ++cp, ++dp) { 1303 if (*cp != *dp) { 1304 printf("\nwrong data byte #%d " 1305 "should be 0x%x but was 0x%x", 1306 i - ECHOLEN, *dp, *cp); 1307 if (v6flag) 1308 cp = buf + ECHOLEN; 1309 else 1310 cp = (u_char *) 1311 &icp->icmp_data[0]; 1312 for (i = ECHOLEN; i < cc && i < datalen; 1313 ++i, ++cp) { 1314 if ((i % 32) == 8) 1315 printf("\n\t"); 1316 printf("%x ", *cp); 1317 } 1318 break; 1319 } 1320 } 1321 } 1322 } else { 1323 /* We've got something other than an ECHOREPLY */ 1324 if (!(options & F_VERBOSE)) 1325 return; 1326 printf("%d bytes from %s: ", cc, pr_addr(from, fromlen)); 1327 if (v6flag) 1328 pr_icmph6(icp6, buf + cc); 1329 else 1330 pr_icmph(icp); 1331 } 1332 1333 /* Display any IP options */ 1334 if (!v6flag && hlen > sizeof(struct ip)) 1335 pr_ipopt(hlen, buf); 1336 1337 if (!(options & F_FLOOD)) { 1338 putchar('\n'); 1339 if (v6flag && (options & F_VERBOSE)) 1340 pr_exthdrs(mhdr); 1341 fflush(stdout); 1342 if (options & F_AUD_RECV) 1343 fputc('\a', stderr); 1344 } 1345 } 1346 1347 void 1348 pr_ipopt(int hlen, u_char *buf) 1349 { 1350 static int old_rrlen; 1351 static char old_rr[MAX_IPOPTLEN]; 1352 struct sockaddr_in s_in; 1353 in_addr_t l; 1354 u_int i, j; 1355 u_char *cp; 1356 1357 cp = buf + sizeof(struct ip); 1358 1359 s_in.sin_len = sizeof(s_in); 1360 s_in.sin_family = AF_INET; 1361 1362 for (; hlen > (int)sizeof(struct ip); --hlen, ++cp) { 1363 switch (*cp) { 1364 case IPOPT_EOL: 1365 hlen = 0; 1366 break; 1367 case IPOPT_LSRR: 1368 printf("\nLSRR: "); 1369 hlen -= 2; 1370 j = *++cp; 1371 ++cp; 1372 i = 0; 1373 if (j > IPOPT_MINOFF) { 1374 for (;;) { 1375 l = *++cp; 1376 l = (l<<8) + *++cp; 1377 l = (l<<8) + *++cp; 1378 l = (l<<8) + *++cp; 1379 if (l == 0) 1380 printf("\t0.0.0.0"); 1381 else { 1382 s_in.sin_addr.s_addr = ntohl(l); 1383 printf("\t%s", 1384 pr_addr((struct sockaddr*) 1385 &s_in, sizeof(s_in))); 1386 } 1387 hlen -= 4; 1388 j -= 4; 1389 i += 4; 1390 if (j <= IPOPT_MINOFF) 1391 break; 1392 if (i >= MAX_IPOPTLEN) { 1393 printf("\t(truncated route)"); 1394 break; 1395 } 1396 putchar('\n'); 1397 } 1398 } 1399 break; 1400 case IPOPT_RR: 1401 j = *++cp; /* get length */ 1402 i = *++cp; /* and pointer */ 1403 hlen -= 2; 1404 if (i > j) 1405 i = j; 1406 i -= IPOPT_MINOFF; 1407 if (i <= 0) 1408 continue; 1409 if (i == old_rrlen && 1410 cp == buf + sizeof(struct ip) + 2 && 1411 !memcmp(cp, old_rr, i) && 1412 !(options & F_FLOOD)) { 1413 printf("\t(same route)"); 1414 i = (i + 3) & ~0x3; 1415 hlen -= i; 1416 cp += i; 1417 break; 1418 } 1419 if (i < MAX_IPOPTLEN) { 1420 old_rrlen = i; 1421 memcpy(old_rr, cp, i); 1422 } else 1423 old_rrlen = 0; 1424 1425 printf("\nRR: "); 1426 j = 0; 1427 for (;;) { 1428 l = *++cp; 1429 l = (l<<8) + *++cp; 1430 l = (l<<8) + *++cp; 1431 l = (l<<8) + *++cp; 1432 if (l == 0) 1433 printf("\t0.0.0.0"); 1434 else { 1435 s_in.sin_addr.s_addr = ntohl(l); 1436 printf("\t%s", 1437 pr_addr((struct sockaddr*)&s_in, 1438 sizeof(s_in))); 1439 } 1440 hlen -= 4; 1441 i -= 4; 1442 j += 4; 1443 if (i <= 0) 1444 break; 1445 if (j >= MAX_IPOPTLEN) { 1446 printf("\t(truncated route)"); 1447 break; 1448 } 1449 putchar('\n'); 1450 } 1451 break; 1452 case IPOPT_NOP: 1453 printf("\nNOP"); 1454 break; 1455 default: 1456 printf("\nunknown option %x", *cp); 1457 hlen = hlen - (cp[IPOPT_OLEN] - 1); 1458 cp = cp + (cp[IPOPT_OLEN] - 1); 1459 break; 1460 } 1461 } 1462 } 1463 1464 /* 1465 * in_cksum -- 1466 * Checksum routine for Internet Protocol family headers (C Version) 1467 */ 1468 int 1469 in_cksum(u_short *addr, int len) 1470 { 1471 int nleft = len; 1472 u_short *w = addr; 1473 int sum = 0; 1474 u_short answer = 0; 1475 1476 /* 1477 * Our algorithm is simple, using a 32 bit accumulator (sum), we add 1478 * sequential 16 bit words to it, and at the end, fold back all the 1479 * carry bits from the top 16 bits into the lower 16 bits. 1480 */ 1481 while (nleft > 1) { 1482 sum += *w++; 1483 nleft -= 2; 1484 } 1485 1486 /* mop up an odd byte, if necessary */ 1487 if (nleft == 1) { 1488 *(u_char *)(&answer) = *(u_char *)w ; 1489 sum += answer; 1490 } 1491 1492 /* add back carry outs from top 16 bits to low 16 bits */ 1493 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 1494 sum += (sum >> 16); /* add carry */ 1495 answer = ~sum; /* truncate to 16 bits */ 1496 return(answer); 1497 } 1498 1499 /* 1500 * pr_icmph -- 1501 * Print a descriptive string about an ICMP header. 1502 */ 1503 void 1504 pr_icmph(struct icmp *icp) 1505 { 1506 switch(icp->icmp_type) { 1507 case ICMP_ECHOREPLY: 1508 printf("Echo Reply\n"); 1509 /* XXX ID + Seq + Data */ 1510 break; 1511 case ICMP_UNREACH: 1512 switch(icp->icmp_code) { 1513 case ICMP_UNREACH_NET: 1514 printf("Destination Net Unreachable\n"); 1515 break; 1516 case ICMP_UNREACH_HOST: 1517 printf("Destination Host Unreachable\n"); 1518 break; 1519 case ICMP_UNREACH_PROTOCOL: 1520 printf("Destination Protocol Unreachable\n"); 1521 break; 1522 case ICMP_UNREACH_PORT: 1523 printf("Destination Port Unreachable\n"); 1524 break; 1525 case ICMP_UNREACH_NEEDFRAG: 1526 if (icp->icmp_nextmtu != 0) 1527 printf("frag needed and DF set (MTU %d)\n", 1528 ntohs(icp->icmp_nextmtu)); 1529 else 1530 printf("frag needed and DF set\n"); 1531 break; 1532 case ICMP_UNREACH_SRCFAIL: 1533 printf("Source Route Failed\n"); 1534 break; 1535 case ICMP_UNREACH_NET_UNKNOWN: 1536 printf("Network Unknown\n"); 1537 break; 1538 case ICMP_UNREACH_HOST_UNKNOWN: 1539 printf("Host Unknown\n"); 1540 break; 1541 case ICMP_UNREACH_ISOLATED: 1542 printf("Source Isolated\n"); 1543 break; 1544 case ICMP_UNREACH_NET_PROHIB: 1545 printf("Dest. Net Administratively Prohibited\n"); 1546 break; 1547 case ICMP_UNREACH_HOST_PROHIB: 1548 printf("Dest. Host Administratively Prohibited\n"); 1549 break; 1550 case ICMP_UNREACH_TOSNET: 1551 printf("Destination Net Unreachable for TOS\n"); 1552 break; 1553 case ICMP_UNREACH_TOSHOST: 1554 printf("Destination Host Unreachable for TOS\n"); 1555 break; 1556 case ICMP_UNREACH_FILTER_PROHIB: 1557 printf("Route administratively prohibited\n"); 1558 break; 1559 case ICMP_UNREACH_HOST_PRECEDENCE: 1560 printf("Host Precedence Violation\n"); 1561 break; 1562 case ICMP_UNREACH_PRECEDENCE_CUTOFF: 1563 printf("Precedence Cutoff\n"); 1564 break; 1565 default: 1566 printf("Dest Unreachable, Unknown Code: %d\n", 1567 icp->icmp_code); 1568 break; 1569 } 1570 /* Print returned IP header information */ 1571 pr_retip((struct ip *)icp->icmp_data); 1572 break; 1573 case ICMP_SOURCEQUENCH: 1574 printf("Source Quench\n"); 1575 pr_retip((struct ip *)icp->icmp_data); 1576 break; 1577 case ICMP_REDIRECT: 1578 switch(icp->icmp_code) { 1579 case ICMP_REDIRECT_NET: 1580 printf("Redirect Network"); 1581 break; 1582 case ICMP_REDIRECT_HOST: 1583 printf("Redirect Host"); 1584 break; 1585 case ICMP_REDIRECT_TOSNET: 1586 printf("Redirect Type of Service and Network"); 1587 break; 1588 case ICMP_REDIRECT_TOSHOST: 1589 printf("Redirect Type of Service and Host"); 1590 break; 1591 default: 1592 printf("Redirect, Unknown Code: %d", icp->icmp_code); 1593 break; 1594 } 1595 printf("(New addr: %s)\n", 1596 inet_ntoa(icp->icmp_gwaddr)); 1597 pr_retip((struct ip *)icp->icmp_data); 1598 break; 1599 case ICMP_ECHO: 1600 printf("Echo Request\n"); 1601 /* XXX ID + Seq + Data */ 1602 break; 1603 case ICMP_ROUTERADVERT: 1604 /* RFC1256 */ 1605 printf("Router Discovery Advertisement\n"); 1606 printf("(%d entries, lifetime %d seconds)\n", 1607 icp->icmp_num_addrs, ntohs(icp->icmp_lifetime)); 1608 break; 1609 case ICMP_ROUTERSOLICIT: 1610 /* RFC1256 */ 1611 printf("Router Discovery Solicitation\n"); 1612 break; 1613 case ICMP_TIMXCEED: 1614 switch(icp->icmp_code) { 1615 case ICMP_TIMXCEED_INTRANS: 1616 printf("Time to live exceeded\n"); 1617 break; 1618 case ICMP_TIMXCEED_REASS: 1619 printf("Frag reassembly time exceeded\n"); 1620 break; 1621 default: 1622 printf("Time exceeded, Unknown Code: %d\n", 1623 icp->icmp_code); 1624 break; 1625 } 1626 pr_retip((struct ip *)icp->icmp_data); 1627 break; 1628 case ICMP_PARAMPROB: 1629 switch(icp->icmp_code) { 1630 case ICMP_PARAMPROB_OPTABSENT: 1631 printf("Parameter problem, required option " 1632 "absent: pointer = 0x%02x\n", 1633 ntohs(icp->icmp_hun.ih_pptr)); 1634 break; 1635 default: 1636 printf("Parameter problem: pointer = 0x%02x\n", 1637 ntohs(icp->icmp_hun.ih_pptr)); 1638 break; 1639 } 1640 pr_retip((struct ip *)icp->icmp_data); 1641 break; 1642 case ICMP_TSTAMP: 1643 printf("Timestamp\n"); 1644 /* XXX ID + Seq + 3 timestamps */ 1645 break; 1646 case ICMP_TSTAMPREPLY: 1647 printf("Timestamp Reply\n"); 1648 /* XXX ID + Seq + 3 timestamps */ 1649 break; 1650 case ICMP_IREQ: 1651 printf("Information Request\n"); 1652 /* XXX ID + Seq */ 1653 break; 1654 case ICMP_IREQREPLY: 1655 printf("Information Reply\n"); 1656 /* XXX ID + Seq */ 1657 break; 1658 case ICMP_MASKREQ: 1659 printf("Address Mask Request\n"); 1660 break; 1661 case ICMP_MASKREPLY: 1662 printf("Address Mask Reply (Mask 0x%08x)\n", 1663 ntohl(icp->icmp_mask)); 1664 break; 1665 default: 1666 printf("Unknown ICMP type: %d\n", icp->icmp_type); 1667 } 1668 } 1669 1670 /* 1671 * pr_iph -- 1672 * Print an IP header with options. 1673 */ 1674 void 1675 pr_iph(struct ip *ip) 1676 { 1677 int hlen; 1678 u_char *cp; 1679 1680 hlen = ip->ip_hl << 2; 1681 cp = (u_char *)ip + 20; /* point to options */ 1682 1683 printf("Vr HL TOS Len ID Flg off TTL Pro cks Src Dst Data\n"); 1684 printf(" %1x %1x %02x %04x %04x", 1685 ip->ip_v, ip->ip_hl, ip->ip_tos, ip->ip_len, ip->ip_id); 1686 printf(" %1x %04x", ((ip->ip_off) & 0xe000) >> 13, 1687 (ip->ip_off) & 0x1fff); 1688 printf(" %02x %02x %04x", ip->ip_ttl, ip->ip_p, ip->ip_sum); 1689 printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->ip_src.s_addr)); 1690 printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->ip_dst.s_addr)); 1691 /* dump and option bytes */ 1692 while (hlen-- > 20) { 1693 printf("%02x", *cp++); 1694 } 1695 putchar('\n'); 1696 } 1697 1698 /* 1699 * pr_retip -- 1700 * Dump some info on a returned (via ICMP) IP packet. 1701 */ 1702 void 1703 pr_retip(struct ip *ip) 1704 { 1705 int hlen; 1706 u_char *cp; 1707 1708 pr_iph(ip); 1709 hlen = ip->ip_hl << 2; 1710 cp = (u_char *)ip + hlen; 1711 1712 if (ip->ip_p == 6) 1713 printf("TCP: from port %u, to port %u (decimal)\n", 1714 (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3))); 1715 else if (ip->ip_p == 17) 1716 printf("UDP: from port %u, to port %u (decimal)\n", 1717 (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3))); 1718 } 1719 1720 #ifndef SMALL 1721 int 1722 map_tos(char *key, int *val) 1723 { 1724 /* DiffServ Codepoints and other TOS mappings */ 1725 const struct toskeywords { 1726 const char *keyword; 1727 int val; 1728 } *t, toskeywords[] = { 1729 { "af11", IPTOS_DSCP_AF11 }, 1730 { "af12", IPTOS_DSCP_AF12 }, 1731 { "af13", IPTOS_DSCP_AF13 }, 1732 { "af21", IPTOS_DSCP_AF21 }, 1733 { "af22", IPTOS_DSCP_AF22 }, 1734 { "af23", IPTOS_DSCP_AF23 }, 1735 { "af31", IPTOS_DSCP_AF31 }, 1736 { "af32", IPTOS_DSCP_AF32 }, 1737 { "af33", IPTOS_DSCP_AF33 }, 1738 { "af41", IPTOS_DSCP_AF41 }, 1739 { "af42", IPTOS_DSCP_AF42 }, 1740 { "af43", IPTOS_DSCP_AF43 }, 1741 { "critical", IPTOS_PREC_CRITIC_ECP }, 1742 { "cs0", IPTOS_DSCP_CS0 }, 1743 { "cs1", IPTOS_DSCP_CS1 }, 1744 { "cs2", IPTOS_DSCP_CS2 }, 1745 { "cs3", IPTOS_DSCP_CS3 }, 1746 { "cs4", IPTOS_DSCP_CS4 }, 1747 { "cs5", IPTOS_DSCP_CS5 }, 1748 { "cs6", IPTOS_DSCP_CS6 }, 1749 { "cs7", IPTOS_DSCP_CS7 }, 1750 { "ef", IPTOS_DSCP_EF }, 1751 { "inetcontrol", IPTOS_PREC_INTERNETCONTROL }, 1752 { "lowdelay", IPTOS_LOWDELAY }, 1753 { "netcontrol", IPTOS_PREC_NETCONTROL }, 1754 { "reliability", IPTOS_RELIABILITY }, 1755 { "throughput", IPTOS_THROUGHPUT }, 1756 { NULL, -1 }, 1757 }; 1758 1759 for (t = toskeywords; t->keyword != NULL; t++) { 1760 if (strcmp(key, t->keyword) == 0) { 1761 *val = t->val; 1762 return (1); 1763 } 1764 } 1765 1766 return (0); 1767 } 1768 #endif /* SMALL */ 1769 1770 void 1771 pr_exthdrs(struct msghdr *mhdr) 1772 { 1773 struct cmsghdr *cm; 1774 1775 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; 1776 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { 1777 if (cm->cmsg_level != IPPROTO_IPV6) 1778 continue; 1779 1780 switch (cm->cmsg_type) { 1781 case IPV6_HOPOPTS: 1782 printf(" HbH Options: "); 1783 pr_ip6opt(CMSG_DATA(cm)); 1784 break; 1785 case IPV6_DSTOPTS: 1786 case IPV6_RTHDRDSTOPTS: 1787 printf(" Dst Options: "); 1788 pr_ip6opt(CMSG_DATA(cm)); 1789 break; 1790 case IPV6_RTHDR: 1791 printf(" Routing: "); 1792 pr_rthdr(CMSG_DATA(cm)); 1793 break; 1794 } 1795 } 1796 } 1797 1798 void 1799 pr_ip6opt(void *extbuf) 1800 { 1801 struct ip6_hbh *ext; 1802 int currentlen; 1803 u_int8_t type; 1804 size_t extlen; 1805 socklen_t len; 1806 void *databuf; 1807 u_int16_t value2; 1808 u_int32_t value4; 1809 1810 ext = (struct ip6_hbh *)extbuf; 1811 extlen = (ext->ip6h_len + 1) * 8; 1812 printf("nxt %u, len %u (%lu bytes)\n", ext->ip6h_nxt, 1813 (unsigned int)ext->ip6h_len, (unsigned long)extlen); 1814 1815 currentlen = 0; 1816 while (1) { 1817 currentlen = inet6_opt_next(extbuf, extlen, currentlen, 1818 &type, &len, &databuf); 1819 if (currentlen == -1) 1820 break; 1821 switch (type) { 1822 /* 1823 * Note that inet6_opt_next automatically skips any padding 1824 * options. 1825 */ 1826 case IP6OPT_JUMBO: 1827 inet6_opt_get_val(databuf, 0, &value4, sizeof(value4)); 1828 printf(" Jumbo Payload Opt: Length %u\n", 1829 (u_int32_t)ntohl(value4)); 1830 break; 1831 case IP6OPT_ROUTER_ALERT: 1832 inet6_opt_get_val(databuf, 0, &value2, sizeof(value2)); 1833 printf(" Router Alert Opt: Type %u\n", 1834 ntohs(value2)); 1835 break; 1836 default: 1837 printf(" Received Opt %u len %lu\n", 1838 type, (unsigned long)len); 1839 break; 1840 } 1841 } 1842 return; 1843 } 1844 1845 void 1846 pr_rthdr(void *extbuf) 1847 { 1848 struct in6_addr *in6; 1849 char ntopbuf[INET6_ADDRSTRLEN]; 1850 struct ip6_rthdr *rh = (struct ip6_rthdr *)extbuf; 1851 int i, segments; 1852 1853 /* print fixed part of the header */ 1854 printf("nxt %u, len %u (%d bytes), type %u, ", rh->ip6r_nxt, 1855 rh->ip6r_len, (rh->ip6r_len + 1) << 3, rh->ip6r_type); 1856 if ((segments = inet6_rth_segments(extbuf)) >= 0) 1857 printf("%d segments, ", segments); 1858 else 1859 printf("segments unknown, "); 1860 printf("%d left\n", rh->ip6r_segleft); 1861 1862 for (i = 0; i < segments; i++) { 1863 in6 = inet6_rth_getaddr(extbuf, i); 1864 if (in6 == NULL) 1865 printf(" [%d]<NULL>\n", i); 1866 else { 1867 if (!inet_ntop(AF_INET6, in6, ntopbuf, 1868 sizeof(ntopbuf))) 1869 strncpy(ntopbuf, "?", sizeof(ntopbuf)); 1870 printf(" [%d]%s\n", i, ntopbuf); 1871 } 1872 } 1873 1874 return; 1875 1876 } 1877 1878 int 1879 get_hoplim(struct msghdr *mhdr) 1880 { 1881 struct cmsghdr *cm; 1882 1883 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; 1884 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { 1885 if (cm->cmsg_len == 0) 1886 return(-1); 1887 1888 if (cm->cmsg_level == IPPROTO_IPV6 && 1889 cm->cmsg_type == IPV6_HOPLIMIT && 1890 cm->cmsg_len == CMSG_LEN(sizeof(int))) 1891 return(*(int *)CMSG_DATA(cm)); 1892 } 1893 1894 return(-1); 1895 } 1896 1897 int 1898 get_pathmtu(struct msghdr *mhdr, struct sockaddr_in6 *dst) 1899 { 1900 struct cmsghdr *cm; 1901 struct ip6_mtuinfo *mtuctl = NULL; 1902 1903 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; 1904 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { 1905 if (cm->cmsg_len == 0) 1906 return(0); 1907 1908 if (cm->cmsg_level == IPPROTO_IPV6 && 1909 cm->cmsg_type == IPV6_PATHMTU && 1910 cm->cmsg_len == CMSG_LEN(sizeof(struct ip6_mtuinfo))) { 1911 mtuctl = (struct ip6_mtuinfo *)CMSG_DATA(cm); 1912 1913 /* 1914 * If the notified destination is different from 1915 * the one we are pinging, just ignore the info. 1916 * We check the scope ID only when both notified value 1917 * and our own value have non-0 values, because we may 1918 * have used the default scope zone ID for sending, 1919 * in which case the scope ID value is 0. 1920 */ 1921 if (!IN6_ARE_ADDR_EQUAL(&mtuctl->ip6m_addr.sin6_addr, 1922 &dst->sin6_addr) || 1923 (mtuctl->ip6m_addr.sin6_scope_id && 1924 dst->sin6_scope_id && 1925 mtuctl->ip6m_addr.sin6_scope_id != 1926 dst->sin6_scope_id)) { 1927 if (options & F_VERBOSE) { 1928 printf("path MTU for %s is notified. " 1929 "(ignored)\n", 1930 pr_addr((struct sockaddr *) 1931 &mtuctl->ip6m_addr, 1932 sizeof(mtuctl->ip6m_addr))); 1933 } 1934 return(0); 1935 } 1936 1937 /* 1938 * Ignore an invalid MTU. XXX: can we just believe 1939 * the kernel check? 1940 */ 1941 if (mtuctl->ip6m_mtu < IPV6_MMTU) 1942 return(0); 1943 1944 /* notification for our destination. return the MTU. */ 1945 return((int)mtuctl->ip6m_mtu); 1946 } 1947 } 1948 return(0); 1949 } 1950 1951 /* 1952 * pr_icmph6 -- 1953 * Print a descriptive string about an ICMP header. 1954 */ 1955 void 1956 pr_icmph6(struct icmp6_hdr *icp, u_char *end) 1957 { 1958 char ntop_buf[INET6_ADDRSTRLEN]; 1959 struct nd_redirect *red; 1960 1961 switch (icp->icmp6_type) { 1962 case ICMP6_DST_UNREACH: 1963 switch (icp->icmp6_code) { 1964 case ICMP6_DST_UNREACH_NOROUTE: 1965 printf("No Route to Destination\n"); 1966 break; 1967 case ICMP6_DST_UNREACH_ADMIN: 1968 printf("Destination Administratively " 1969 "Unreachable\n"); 1970 break; 1971 case ICMP6_DST_UNREACH_BEYONDSCOPE: 1972 printf("Destination Unreachable Beyond Scope\n"); 1973 break; 1974 case ICMP6_DST_UNREACH_ADDR: 1975 printf("Destination Host Unreachable\n"); 1976 break; 1977 case ICMP6_DST_UNREACH_NOPORT: 1978 printf("Destination Port Unreachable\n"); 1979 break; 1980 default: 1981 printf("Destination Unreachable, Bad Code: %d\n", 1982 icp->icmp6_code); 1983 break; 1984 } 1985 /* Print returned IP header information */ 1986 pr_retip6((struct ip6_hdr *)(icp + 1), end); 1987 break; 1988 case ICMP6_PACKET_TOO_BIG: 1989 printf("Packet too big mtu = %d\n", 1990 (int)ntohl(icp->icmp6_mtu)); 1991 pr_retip6((struct ip6_hdr *)(icp + 1), end); 1992 break; 1993 case ICMP6_TIME_EXCEEDED: 1994 switch (icp->icmp6_code) { 1995 case ICMP6_TIME_EXCEED_TRANSIT: 1996 printf("Time to live exceeded\n"); 1997 break; 1998 case ICMP6_TIME_EXCEED_REASSEMBLY: 1999 printf("Frag reassembly time exceeded\n"); 2000 break; 2001 default: 2002 printf("Time exceeded, Bad Code: %d\n", 2003 icp->icmp6_code); 2004 break; 2005 } 2006 pr_retip6((struct ip6_hdr *)(icp + 1), end); 2007 break; 2008 case ICMP6_PARAM_PROB: 2009 printf("Parameter problem: "); 2010 switch (icp->icmp6_code) { 2011 case ICMP6_PARAMPROB_HEADER: 2012 printf("Erroneous Header "); 2013 break; 2014 case ICMP6_PARAMPROB_NEXTHEADER: 2015 printf("Unknown Nextheader "); 2016 break; 2017 case ICMP6_PARAMPROB_OPTION: 2018 printf("Unrecognized Option "); 2019 break; 2020 default: 2021 printf("Bad code(%d) ", icp->icmp6_code); 2022 break; 2023 } 2024 printf("pointer = 0x%02x\n", 2025 (u_int32_t)ntohl(icp->icmp6_pptr)); 2026 pr_retip6((struct ip6_hdr *)(icp + 1), end); 2027 break; 2028 case ICMP6_ECHO_REQUEST: 2029 printf("Echo Request"); 2030 /* XXX ID + Seq + Data */ 2031 break; 2032 case ICMP6_ECHO_REPLY: 2033 printf("Echo Reply"); 2034 /* XXX ID + Seq + Data */ 2035 break; 2036 case ICMP6_MEMBERSHIP_QUERY: 2037 printf("Listener Query"); 2038 break; 2039 case ICMP6_MEMBERSHIP_REPORT: 2040 printf("Listener Report"); 2041 break; 2042 case ICMP6_MEMBERSHIP_REDUCTION: 2043 printf("Listener Done"); 2044 break; 2045 case ND_ROUTER_SOLICIT: 2046 printf("Router Solicitation"); 2047 break; 2048 case ND_ROUTER_ADVERT: 2049 printf("Router Advertisement"); 2050 break; 2051 case ND_NEIGHBOR_SOLICIT: 2052 printf("Neighbor Solicitation"); 2053 break; 2054 case ND_NEIGHBOR_ADVERT: 2055 printf("Neighbor Advertisement"); 2056 break; 2057 case ND_REDIRECT: 2058 red = (struct nd_redirect *)icp; 2059 printf("Redirect\n"); 2060 if (!inet_ntop(AF_INET6, &red->nd_rd_dst, ntop_buf, 2061 sizeof(ntop_buf))) 2062 strncpy(ntop_buf, "?", sizeof(ntop_buf)); 2063 printf("Destination: %s", ntop_buf); 2064 if (!inet_ntop(AF_INET6, &red->nd_rd_target, ntop_buf, 2065 sizeof(ntop_buf))) 2066 strncpy(ntop_buf, "?", sizeof(ntop_buf)); 2067 printf(" New Target: %s", ntop_buf); 2068 break; 2069 default: 2070 printf("Bad ICMP type: %d", icp->icmp6_type); 2071 } 2072 } 2073 2074 /* 2075 * pr_iph6 -- 2076 * Print an IP6 header. 2077 */ 2078 void 2079 pr_iph6(struct ip6_hdr *ip6) 2080 { 2081 u_int32_t flow = ip6->ip6_flow & IPV6_FLOWLABEL_MASK; 2082 u_int8_t tc; 2083 char ntop_buf[INET6_ADDRSTRLEN]; 2084 2085 tc = *(&ip6->ip6_vfc + 1); /* XXX */ 2086 tc = (tc >> 4) & 0x0f; 2087 tc |= (ip6->ip6_vfc << 4); 2088 2089 printf("Vr TC Flow Plen Nxt Hlim\n"); 2090 printf(" %1x %02x %05x %04x %02x %02x\n", 2091 (ip6->ip6_vfc & IPV6_VERSION_MASK) >> 4, tc, (u_int32_t)ntohl(flow), 2092 ntohs(ip6->ip6_plen), ip6->ip6_nxt, ip6->ip6_hlim); 2093 if (!inet_ntop(AF_INET6, &ip6->ip6_src, ntop_buf, sizeof(ntop_buf))) 2094 strncpy(ntop_buf, "?", sizeof(ntop_buf)); 2095 printf("%s->", ntop_buf); 2096 if (!inet_ntop(AF_INET6, &ip6->ip6_dst, ntop_buf, sizeof(ntop_buf))) 2097 strncpy(ntop_buf, "?", sizeof(ntop_buf)); 2098 printf("%s\n", ntop_buf); 2099 } 2100 2101 /* 2102 * pr_retip6 -- 2103 * Dump some info on a returned (via ICMPv6) IPv6 packet. 2104 */ 2105 void 2106 pr_retip6(struct ip6_hdr *ip6, u_char *end) 2107 { 2108 u_char *cp = (u_char *)ip6, nh; 2109 int hlen; 2110 2111 if (end - (u_char *)ip6 < sizeof(*ip6)) { 2112 printf("IP6"); 2113 goto trunc; 2114 } 2115 pr_iph6(ip6); 2116 hlen = sizeof(*ip6); 2117 2118 nh = ip6->ip6_nxt; 2119 cp += hlen; 2120 while (end - cp >= 8) { 2121 switch (nh) { 2122 case IPPROTO_HOPOPTS: 2123 printf("HBH "); 2124 hlen = (((struct ip6_hbh *)cp)->ip6h_len+1) << 3; 2125 nh = ((struct ip6_hbh *)cp)->ip6h_nxt; 2126 break; 2127 case IPPROTO_DSTOPTS: 2128 printf("DSTOPT "); 2129 hlen = (((struct ip6_dest *)cp)->ip6d_len+1) << 3; 2130 nh = ((struct ip6_dest *)cp)->ip6d_nxt; 2131 break; 2132 case IPPROTO_FRAGMENT: 2133 printf("FRAG "); 2134 hlen = sizeof(struct ip6_frag); 2135 nh = ((struct ip6_frag *)cp)->ip6f_nxt; 2136 break; 2137 case IPPROTO_ROUTING: 2138 printf("RTHDR "); 2139 hlen = (((struct ip6_rthdr *)cp)->ip6r_len+1) << 3; 2140 nh = ((struct ip6_rthdr *)cp)->ip6r_nxt; 2141 break; 2142 case IPPROTO_AH: 2143 printf("AH "); 2144 hlen = (((struct ah *)cp)->ah_hl+2) << 2; 2145 nh = ((struct ah *)cp)->ah_nh; 2146 break; 2147 case IPPROTO_ICMPV6: 2148 printf("ICMP6: type = %d, code = %d\n", 2149 *cp, *(cp + 1)); 2150 return; 2151 case IPPROTO_ESP: 2152 printf("ESP\n"); 2153 return; 2154 case IPPROTO_TCP: 2155 printf("TCP: from port %u, to port %u (decimal)\n", 2156 (*cp * 256 + *(cp + 1)), 2157 (*(cp + 2) * 256 + *(cp + 3))); 2158 return; 2159 case IPPROTO_UDP: 2160 printf("UDP: from port %u, to port %u (decimal)\n", 2161 (*cp * 256 + *(cp + 1)), 2162 (*(cp + 2) * 256 + *(cp + 3))); 2163 return; 2164 default: 2165 printf("Unknown Header(%d)\n", nh); 2166 return; 2167 } 2168 2169 if ((cp += hlen) >= end) 2170 goto trunc; 2171 } 2172 if (end - cp < 8) 2173 goto trunc; 2174 2175 putchar('\n'); 2176 return; 2177 2178 trunc: 2179 printf("...\n"); 2180 return; 2181 } 2182 2183 __dead void 2184 usage(void) 2185 { 2186 if (v6flag) { 2187 fprintf(stderr, 2188 "usage: ping6 [-DdEefHLmnqv] [-c count] [-h hoplimit] " 2189 "[-I sourceaddr]\n\t[-i interval] [-l preload] " 2190 "[-p pattern] [-s packetsize] [-T toskeyword]\n" 2191 "\t[-V rtable] [-w maxwait] host\n"); 2192 } else { 2193 fprintf(stderr, 2194 "usage: ping [-DdEefHLnqRv] [-c count] [-I sourceaddr] " 2195 "[-i interval]\n\t[-l preload] [-p pattern] [-s packetsize]" 2196 #ifndef SMALL 2197 " [-T toskeyword]" 2198 #endif /* SMALL */ 2199 "\n\t[-t ttl] [-V rtable] [-w maxwait] host\n"); 2200 } 2201 exit(1); 2202 } 2203