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