1 /* $OpenBSD: ping.c,v 1.248 2022/12/01 07:34:06 florian 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 from %s: " 1306 "icmp_seq=%u\n", pr_addr(from, fromlen), 1307 ntohs(seq)); 1308 --nreceived; 1309 return; 1310 } 1311 timinginfo=1; 1312 1313 tp.tv_sec = betoh64(tv64->tv64_sec) - 1314 tv64_offset.tv64_sec; 1315 tp.tv_nsec = betoh64(tv64->tv64_nsec) - 1316 tv64_offset.tv64_nsec; 1317 1318 timespecsub(&ts, &tp, &ts); 1319 triptime = ((double)ts.tv_sec) * 1000.0 + 1320 ((double)ts.tv_nsec) / 1000000.0; 1321 tsum += triptime; 1322 tsumsq += triptime * triptime; 1323 if (triptime < tmin) 1324 tmin = triptime; 1325 if (triptime > tmax) 1326 tmax = triptime; 1327 } 1328 1329 if (TST(ntohs(seq) % mx_dup_ck)) { 1330 ++nrepeats; 1331 --nreceived; 1332 dupflag = 1; 1333 } else { 1334 SET(ntohs(seq) % mx_dup_ck); 1335 dupflag = 0; 1336 } 1337 1338 if (options & F_QUIET) 1339 return; 1340 1341 if (options & F_FLOOD) 1342 write(STDOUT_FILENO, &BSPACE, 1); 1343 else if (options & F_SHOWCHAR) { 1344 if (dupflag) 1345 putchar('D'); 1346 else if (cc - ECHOLEN < datalen) 1347 putchar('T'); 1348 else 1349 putchar('!'); 1350 } else { 1351 printf("%d bytes from %s: icmp_seq=%u", cc, 1352 pr_addr(from, fromlen), ntohs(seq)); 1353 if (v6flag) 1354 printf(" hlim=%d", hoplim); 1355 else 1356 printf(" ttl=%d", ip->ip_ttl); 1357 if (cc >= ECHOLEN + ECHOTMLEN) 1358 printf(" time=%.3f ms", triptime); 1359 if (dupflag) 1360 printf(" (DUP!)"); 1361 /* check the data */ 1362 if (cc - ECHOLEN < datalen) 1363 printf(" (TRUNC!)"); 1364 if (v6flag) 1365 cp = buf + ECHOLEN + ECHOTMLEN; 1366 else 1367 cp = (u_char *)&icp->icmp_data[ECHOTMLEN]; 1368 dp = &outpack[ECHOLEN + ECHOTMLEN]; 1369 for (i = ECHOLEN + ECHOTMLEN; 1370 i < cc && i < datalen; 1371 ++i, ++cp, ++dp) { 1372 if (*cp != *dp) { 1373 printf("\nwrong data byte #%d " 1374 "should be 0x%x but was 0x%x", 1375 i - ECHOLEN, *dp, *cp); 1376 if (v6flag) 1377 cp = buf + ECHOLEN; 1378 else 1379 cp = (u_char *) 1380 &icp->icmp_data[0]; 1381 for (i = ECHOLEN; i < cc && i < datalen; 1382 ++i, ++cp) { 1383 if ((i % 32) == 8) 1384 printf("\n\t"); 1385 printf("%x ", *cp); 1386 } 1387 break; 1388 } 1389 } 1390 } 1391 } else { 1392 /* We've got something other than an ECHOREPLY */ 1393 if (!(options & F_VERBOSE)) 1394 return; 1395 printf("%d bytes from %s: ", cc, pr_addr(from, fromlen)); 1396 if (v6flag) 1397 pr_icmph6(icp6, buf + cc); 1398 else 1399 pr_icmph(icp); 1400 } 1401 1402 /* Display any IP options */ 1403 if (!v6flag && hlen > sizeof(struct ip)) 1404 pr_ipopt(hlen, buf); 1405 1406 if (!(options & F_FLOOD)) { 1407 if (!(options & F_SHOWCHAR)) { 1408 putchar('\n'); 1409 if (v6flag && (options & F_VERBOSE)) 1410 pr_exthdrs(mhdr); 1411 } 1412 fflush(stdout); 1413 if (options & F_AUD_RECV) 1414 fputc('\a', stderr); 1415 } 1416 } 1417 1418 void 1419 pr_ipopt(int hlen, u_char *buf) 1420 { 1421 static int old_rrlen; 1422 static char old_rr[MAX_IPOPTLEN]; 1423 struct sockaddr_in s_in; 1424 in_addr_t l; 1425 u_int i, j; 1426 u_char *cp; 1427 1428 cp = buf + sizeof(struct ip); 1429 1430 s_in.sin_len = sizeof(s_in); 1431 s_in.sin_family = AF_INET; 1432 1433 for (; hlen > (int)sizeof(struct ip); --hlen, ++cp) { 1434 switch (*cp) { 1435 case IPOPT_EOL: 1436 hlen = 0; 1437 break; 1438 case IPOPT_LSRR: 1439 printf("\nLSRR: "); 1440 hlen -= 2; 1441 j = *++cp; 1442 ++cp; 1443 i = 0; 1444 if (j > IPOPT_MINOFF) { 1445 for (;;) { 1446 l = *++cp; 1447 l = (l<<8) + *++cp; 1448 l = (l<<8) + *++cp; 1449 l = (l<<8) + *++cp; 1450 if (l == 0) 1451 printf("\t0.0.0.0"); 1452 else { 1453 s_in.sin_addr.s_addr = ntohl(l); 1454 printf("\t%s", 1455 pr_addr((struct sockaddr*) 1456 &s_in, sizeof(s_in))); 1457 } 1458 hlen -= 4; 1459 j -= 4; 1460 i += 4; 1461 if (j <= IPOPT_MINOFF) 1462 break; 1463 if (i >= MAX_IPOPTLEN) { 1464 printf("\t(truncated route)"); 1465 break; 1466 } 1467 putchar('\n'); 1468 } 1469 } 1470 break; 1471 case IPOPT_RR: 1472 j = *++cp; /* get length */ 1473 i = *++cp; /* and pointer */ 1474 hlen -= 2; 1475 if (i > j) 1476 i = j; 1477 i -= IPOPT_MINOFF; 1478 if (i <= 0) 1479 continue; 1480 if (i == old_rrlen && 1481 cp == buf + sizeof(struct ip) + 2 && 1482 !memcmp(cp, old_rr, i) && 1483 !(options & F_FLOOD)) { 1484 printf("\t(same route)"); 1485 i = (i + 3) & ~0x3; 1486 hlen -= i; 1487 cp += i; 1488 break; 1489 } 1490 if (i < MAX_IPOPTLEN) { 1491 old_rrlen = i; 1492 memcpy(old_rr, cp, i); 1493 } else 1494 old_rrlen = 0; 1495 1496 printf("\nRR: "); 1497 j = 0; 1498 for (;;) { 1499 l = *++cp; 1500 l = (l<<8) + *++cp; 1501 l = (l<<8) + *++cp; 1502 l = (l<<8) + *++cp; 1503 if (l == 0) 1504 printf("\t0.0.0.0"); 1505 else { 1506 s_in.sin_addr.s_addr = ntohl(l); 1507 printf("\t%s", 1508 pr_addr((struct sockaddr*)&s_in, 1509 sizeof(s_in))); 1510 } 1511 hlen -= 4; 1512 i -= 4; 1513 j += 4; 1514 if (i <= 0) 1515 break; 1516 if (j >= MAX_IPOPTLEN) { 1517 printf("\t(truncated route)"); 1518 break; 1519 } 1520 putchar('\n'); 1521 } 1522 break; 1523 case IPOPT_NOP: 1524 printf("\nNOP"); 1525 break; 1526 default: 1527 printf("\nunknown option %x", *cp); 1528 if (cp[IPOPT_OLEN] > 0 && (cp[IPOPT_OLEN] - 1) <= hlen) { 1529 hlen = hlen - (cp[IPOPT_OLEN] - 1); 1530 cp = cp + (cp[IPOPT_OLEN] - 1); 1531 } else 1532 hlen = 0; 1533 break; 1534 } 1535 } 1536 } 1537 1538 /* 1539 * in_cksum -- 1540 * Checksum routine for Internet Protocol family headers (C Version) 1541 */ 1542 int 1543 in_cksum(u_short *addr, int len) 1544 { 1545 int nleft = len; 1546 u_short *w = addr; 1547 int sum = 0; 1548 u_short answer = 0; 1549 1550 /* 1551 * Our algorithm is simple, using a 32 bit accumulator (sum), we add 1552 * sequential 16 bit words to it, and at the end, fold back all the 1553 * carry bits from the top 16 bits into the lower 16 bits. 1554 */ 1555 while (nleft > 1) { 1556 sum += *w++; 1557 nleft -= 2; 1558 } 1559 1560 /* mop up an odd byte, if necessary */ 1561 if (nleft == 1) { 1562 *(u_char *)(&answer) = *(u_char *)w ; 1563 sum += answer; 1564 } 1565 1566 /* add back carry outs from top 16 bits to low 16 bits */ 1567 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 1568 sum += (sum >> 16); /* add carry */ 1569 answer = ~sum; /* truncate to 16 bits */ 1570 return(answer); 1571 } 1572 1573 /* 1574 * pr_icmph -- 1575 * Print a descriptive string about an ICMP header. 1576 */ 1577 void 1578 pr_icmph(struct icmp *icp) 1579 { 1580 switch(icp->icmp_type) { 1581 case ICMP_ECHOREPLY: 1582 printf("Echo Reply\n"); 1583 /* XXX ID + Seq + Data */ 1584 break; 1585 case ICMP_UNREACH: 1586 switch(icp->icmp_code) { 1587 case ICMP_UNREACH_NET: 1588 printf("Destination Net Unreachable\n"); 1589 break; 1590 case ICMP_UNREACH_HOST: 1591 printf("Destination Host Unreachable\n"); 1592 break; 1593 case ICMP_UNREACH_PROTOCOL: 1594 printf("Destination Protocol Unreachable\n"); 1595 break; 1596 case ICMP_UNREACH_PORT: 1597 printf("Destination Port Unreachable\n"); 1598 break; 1599 case ICMP_UNREACH_NEEDFRAG: 1600 if (icp->icmp_nextmtu != 0) 1601 printf("frag needed and DF set (MTU %d)\n", 1602 ntohs(icp->icmp_nextmtu)); 1603 else 1604 printf("frag needed and DF set\n"); 1605 break; 1606 case ICMP_UNREACH_SRCFAIL: 1607 printf("Source Route Failed\n"); 1608 break; 1609 case ICMP_UNREACH_NET_UNKNOWN: 1610 printf("Network Unknown\n"); 1611 break; 1612 case ICMP_UNREACH_HOST_UNKNOWN: 1613 printf("Host Unknown\n"); 1614 break; 1615 case ICMP_UNREACH_ISOLATED: 1616 printf("Source Isolated\n"); 1617 break; 1618 case ICMP_UNREACH_NET_PROHIB: 1619 printf("Dest. Net Administratively Prohibited\n"); 1620 break; 1621 case ICMP_UNREACH_HOST_PROHIB: 1622 printf("Dest. Host Administratively Prohibited\n"); 1623 break; 1624 case ICMP_UNREACH_TOSNET: 1625 printf("Destination Net Unreachable for TOS\n"); 1626 break; 1627 case ICMP_UNREACH_TOSHOST: 1628 printf("Destination Host Unreachable for TOS\n"); 1629 break; 1630 case ICMP_UNREACH_FILTER_PROHIB: 1631 printf("Route administratively prohibited\n"); 1632 break; 1633 case ICMP_UNREACH_HOST_PRECEDENCE: 1634 printf("Host Precedence Violation\n"); 1635 break; 1636 case ICMP_UNREACH_PRECEDENCE_CUTOFF: 1637 printf("Precedence Cutoff\n"); 1638 break; 1639 default: 1640 printf("Dest Unreachable, Unknown Code: %d\n", 1641 icp->icmp_code); 1642 break; 1643 } 1644 /* Print returned IP header information */ 1645 pr_retip((struct ip *)icp->icmp_data); 1646 break; 1647 case ICMP_SOURCEQUENCH: 1648 printf("Source Quench\n"); 1649 pr_retip((struct ip *)icp->icmp_data); 1650 break; 1651 case ICMP_REDIRECT: 1652 switch(icp->icmp_code) { 1653 case ICMP_REDIRECT_NET: 1654 printf("Redirect Network"); 1655 break; 1656 case ICMP_REDIRECT_HOST: 1657 printf("Redirect Host"); 1658 break; 1659 case ICMP_REDIRECT_TOSNET: 1660 printf("Redirect Type of Service and Network"); 1661 break; 1662 case ICMP_REDIRECT_TOSHOST: 1663 printf("Redirect Type of Service and Host"); 1664 break; 1665 default: 1666 printf("Redirect, Unknown Code: %d", icp->icmp_code); 1667 break; 1668 } 1669 printf("(New addr: %s)\n", 1670 inet_ntoa(icp->icmp_gwaddr)); 1671 pr_retip((struct ip *)icp->icmp_data); 1672 break; 1673 case ICMP_ECHO: 1674 printf("Echo Request\n"); 1675 /* XXX ID + Seq + Data */ 1676 break; 1677 case ICMP_ROUTERADVERT: 1678 /* RFC1256 */ 1679 printf("Router Discovery Advertisement\n"); 1680 printf("(%d entries, lifetime %d seconds)\n", 1681 icp->icmp_num_addrs, ntohs(icp->icmp_lifetime)); 1682 break; 1683 case ICMP_ROUTERSOLICIT: 1684 /* RFC1256 */ 1685 printf("Router Discovery Solicitation\n"); 1686 break; 1687 case ICMP_TIMXCEED: 1688 switch(icp->icmp_code) { 1689 case ICMP_TIMXCEED_INTRANS: 1690 printf("Time to live exceeded\n"); 1691 break; 1692 case ICMP_TIMXCEED_REASS: 1693 printf("Frag reassembly time exceeded\n"); 1694 break; 1695 default: 1696 printf("Time exceeded, Unknown Code: %d\n", 1697 icp->icmp_code); 1698 break; 1699 } 1700 pr_retip((struct ip *)icp->icmp_data); 1701 break; 1702 case ICMP_PARAMPROB: 1703 switch(icp->icmp_code) { 1704 case ICMP_PARAMPROB_OPTABSENT: 1705 printf("Parameter problem, required option " 1706 "absent: pointer = 0x%02x\n", 1707 ntohs(icp->icmp_hun.ih_pptr)); 1708 break; 1709 default: 1710 printf("Parameter problem: pointer = 0x%02x\n", 1711 ntohs(icp->icmp_hun.ih_pptr)); 1712 break; 1713 } 1714 pr_retip((struct ip *)icp->icmp_data); 1715 break; 1716 case ICMP_TSTAMP: 1717 printf("Timestamp\n"); 1718 /* XXX ID + Seq + 3 timestamps */ 1719 break; 1720 case ICMP_TSTAMPREPLY: 1721 printf("Timestamp Reply\n"); 1722 /* XXX ID + Seq + 3 timestamps */ 1723 break; 1724 case ICMP_IREQ: 1725 printf("Information Request\n"); 1726 /* XXX ID + Seq */ 1727 break; 1728 case ICMP_IREQREPLY: 1729 printf("Information Reply\n"); 1730 /* XXX ID + Seq */ 1731 break; 1732 case ICMP_MASKREQ: 1733 printf("Address Mask Request\n"); 1734 break; 1735 case ICMP_MASKREPLY: 1736 printf("Address Mask Reply (Mask 0x%08x)\n", 1737 ntohl(icp->icmp_mask)); 1738 break; 1739 default: 1740 printf("Unknown ICMP type: %d\n", icp->icmp_type); 1741 } 1742 } 1743 1744 /* 1745 * pr_iph -- 1746 * Print an IP header with options. 1747 */ 1748 void 1749 pr_iph(struct ip *ip) 1750 { 1751 int hlen; 1752 u_char *cp; 1753 1754 hlen = ip->ip_hl << 2; 1755 cp = (u_char *)ip + 20; /* point to options */ 1756 1757 printf("Vr HL TOS Len ID Flg off TTL Pro cks Src Dst Data\n"); 1758 printf(" %1x %1x %02x %04x %04x", 1759 ip->ip_v, ip->ip_hl, ip->ip_tos, ip->ip_len, ip->ip_id); 1760 printf(" %1x %04x", ((ip->ip_off) & 0xe000) >> 13, 1761 (ip->ip_off) & 0x1fff); 1762 printf(" %02x %02x %04x", ip->ip_ttl, ip->ip_p, ip->ip_sum); 1763 printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->ip_src.s_addr)); 1764 printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->ip_dst.s_addr)); 1765 /* dump and option bytes */ 1766 while (hlen-- > 20) { 1767 printf("%02x", *cp++); 1768 } 1769 putchar('\n'); 1770 } 1771 1772 /* 1773 * pr_retip -- 1774 * Dump some info on a returned (via ICMP) IP packet. 1775 */ 1776 void 1777 pr_retip(struct ip *ip) 1778 { 1779 int hlen; 1780 u_char *cp; 1781 1782 pr_iph(ip); 1783 hlen = ip->ip_hl << 2; 1784 cp = (u_char *)ip + hlen; 1785 1786 if (ip->ip_p == 6) 1787 printf("TCP: from port %u, to port %u (decimal)\n", 1788 (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3))); 1789 else if (ip->ip_p == 17) 1790 printf("UDP: from port %u, to port %u (decimal)\n", 1791 (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3))); 1792 } 1793 1794 #ifndef SMALL 1795 int 1796 map_tos(char *key, int *val) 1797 { 1798 /* DiffServ Codepoints and other TOS mappings */ 1799 const struct toskeywords { 1800 const char *keyword; 1801 int val; 1802 } *t, toskeywords[] = { 1803 { "af11", IPTOS_DSCP_AF11 }, 1804 { "af12", IPTOS_DSCP_AF12 }, 1805 { "af13", IPTOS_DSCP_AF13 }, 1806 { "af21", IPTOS_DSCP_AF21 }, 1807 { "af22", IPTOS_DSCP_AF22 }, 1808 { "af23", IPTOS_DSCP_AF23 }, 1809 { "af31", IPTOS_DSCP_AF31 }, 1810 { "af32", IPTOS_DSCP_AF32 }, 1811 { "af33", IPTOS_DSCP_AF33 }, 1812 { "af41", IPTOS_DSCP_AF41 }, 1813 { "af42", IPTOS_DSCP_AF42 }, 1814 { "af43", IPTOS_DSCP_AF43 }, 1815 { "critical", IPTOS_PREC_CRITIC_ECP }, 1816 { "cs0", IPTOS_DSCP_CS0 }, 1817 { "cs1", IPTOS_DSCP_CS1 }, 1818 { "cs2", IPTOS_DSCP_CS2 }, 1819 { "cs3", IPTOS_DSCP_CS3 }, 1820 { "cs4", IPTOS_DSCP_CS4 }, 1821 { "cs5", IPTOS_DSCP_CS5 }, 1822 { "cs6", IPTOS_DSCP_CS6 }, 1823 { "cs7", IPTOS_DSCP_CS7 }, 1824 { "ef", IPTOS_DSCP_EF }, 1825 { "inetcontrol", IPTOS_PREC_INTERNETCONTROL }, 1826 { "lowdelay", IPTOS_LOWDELAY }, 1827 { "netcontrol", IPTOS_PREC_NETCONTROL }, 1828 { "reliability", IPTOS_RELIABILITY }, 1829 { "throughput", IPTOS_THROUGHPUT }, 1830 { NULL, -1 }, 1831 }; 1832 1833 for (t = toskeywords; t->keyword != NULL; t++) { 1834 if (strcmp(key, t->keyword) == 0) { 1835 *val = t->val; 1836 return (1); 1837 } 1838 } 1839 1840 return (0); 1841 } 1842 #endif /* SMALL */ 1843 1844 void 1845 pr_exthdrs(struct msghdr *mhdr) 1846 { 1847 struct cmsghdr *cm; 1848 1849 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; 1850 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { 1851 if (cm->cmsg_level != IPPROTO_IPV6) 1852 continue; 1853 1854 switch (cm->cmsg_type) { 1855 case IPV6_HOPOPTS: 1856 printf(" HbH Options: "); 1857 pr_ip6opt(CMSG_DATA(cm)); 1858 break; 1859 case IPV6_DSTOPTS: 1860 case IPV6_RTHDRDSTOPTS: 1861 printf(" Dst Options: "); 1862 pr_ip6opt(CMSG_DATA(cm)); 1863 break; 1864 case IPV6_RTHDR: 1865 printf(" Routing: "); 1866 pr_rthdr(CMSG_DATA(cm)); 1867 break; 1868 } 1869 } 1870 } 1871 1872 void 1873 pr_ip6opt(void *extbuf) 1874 { 1875 struct ip6_hbh *ext; 1876 int currentlen; 1877 u_int8_t type; 1878 size_t extlen; 1879 socklen_t len; 1880 void *databuf; 1881 u_int16_t value2; 1882 u_int32_t value4; 1883 1884 ext = (struct ip6_hbh *)extbuf; 1885 extlen = (ext->ip6h_len + 1) * 8; 1886 printf("nxt %u, len %u (%lu bytes)\n", ext->ip6h_nxt, 1887 (unsigned int)ext->ip6h_len, (unsigned long)extlen); 1888 1889 currentlen = 0; 1890 while (1) { 1891 currentlen = inet6_opt_next(extbuf, extlen, currentlen, 1892 &type, &len, &databuf); 1893 if (currentlen == -1) 1894 break; 1895 switch (type) { 1896 /* 1897 * Note that inet6_opt_next automatically skips any padding 1898 * options. 1899 */ 1900 case IP6OPT_JUMBO: 1901 inet6_opt_get_val(databuf, 0, &value4, sizeof(value4)); 1902 printf(" Jumbo Payload Opt: Length %u\n", 1903 (u_int32_t)ntohl(value4)); 1904 break; 1905 case IP6OPT_ROUTER_ALERT: 1906 inet6_opt_get_val(databuf, 0, &value2, sizeof(value2)); 1907 printf(" Router Alert Opt: Type %u\n", 1908 ntohs(value2)); 1909 break; 1910 default: 1911 printf(" Received Opt %u len %lu\n", 1912 type, (unsigned long)len); 1913 break; 1914 } 1915 } 1916 return; 1917 } 1918 1919 void 1920 pr_rthdr(void *extbuf) 1921 { 1922 struct in6_addr *in6; 1923 char ntopbuf[INET6_ADDRSTRLEN]; 1924 struct ip6_rthdr *rh = (struct ip6_rthdr *)extbuf; 1925 int i, segments; 1926 1927 /* print fixed part of the header */ 1928 printf("nxt %u, len %u (%d bytes), type %u, ", rh->ip6r_nxt, 1929 rh->ip6r_len, (rh->ip6r_len + 1) << 3, rh->ip6r_type); 1930 if ((segments = inet6_rth_segments(extbuf)) >= 0) 1931 printf("%d segments, ", segments); 1932 else 1933 printf("segments unknown, "); 1934 printf("%d left\n", rh->ip6r_segleft); 1935 1936 for (i = 0; i < segments; i++) { 1937 in6 = inet6_rth_getaddr(extbuf, i); 1938 if (in6 == NULL) 1939 printf(" [%d]<NULL>\n", i); 1940 else { 1941 if (!inet_ntop(AF_INET6, in6, ntopbuf, 1942 sizeof(ntopbuf))) 1943 strncpy(ntopbuf, "?", sizeof(ntopbuf)); 1944 printf(" [%d]%s\n", i, ntopbuf); 1945 } 1946 } 1947 1948 return; 1949 1950 } 1951 1952 int 1953 get_hoplim(struct msghdr *mhdr) 1954 { 1955 struct cmsghdr *cm; 1956 1957 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; 1958 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { 1959 if (cm->cmsg_len == 0) 1960 return(-1); 1961 1962 if (cm->cmsg_level == IPPROTO_IPV6 && 1963 cm->cmsg_type == IPV6_HOPLIMIT && 1964 cm->cmsg_len == CMSG_LEN(sizeof(int))) 1965 return(*(int *)CMSG_DATA(cm)); 1966 } 1967 1968 return(-1); 1969 } 1970 1971 int 1972 get_pathmtu(struct msghdr *mhdr, struct sockaddr_in6 *dst) 1973 { 1974 struct cmsghdr *cm; 1975 struct ip6_mtuinfo *mtuctl = NULL; 1976 1977 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; 1978 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { 1979 if (cm->cmsg_len == 0) 1980 return(0); 1981 1982 if (cm->cmsg_level == IPPROTO_IPV6 && 1983 cm->cmsg_type == IPV6_PATHMTU && 1984 cm->cmsg_len == CMSG_LEN(sizeof(struct ip6_mtuinfo))) { 1985 mtuctl = (struct ip6_mtuinfo *)CMSG_DATA(cm); 1986 1987 /* 1988 * If the notified destination is different from 1989 * the one we are pinging, just ignore the info. 1990 * We check the scope ID only when both notified value 1991 * and our own value have non-0 values, because we may 1992 * have used the default scope zone ID for sending, 1993 * in which case the scope ID value is 0. 1994 */ 1995 if (!IN6_ARE_ADDR_EQUAL(&mtuctl->ip6m_addr.sin6_addr, 1996 &dst->sin6_addr) || 1997 (mtuctl->ip6m_addr.sin6_scope_id && 1998 dst->sin6_scope_id && 1999 mtuctl->ip6m_addr.sin6_scope_id != 2000 dst->sin6_scope_id)) { 2001 if (options & F_VERBOSE) { 2002 printf("path MTU for %s is notified. " 2003 "(ignored)\n", 2004 pr_addr((struct sockaddr *) 2005 &mtuctl->ip6m_addr, 2006 sizeof(mtuctl->ip6m_addr))); 2007 } 2008 return(0); 2009 } 2010 2011 /* 2012 * Ignore an invalid MTU. XXX: can we just believe 2013 * the kernel check? 2014 */ 2015 if (mtuctl->ip6m_mtu < IPV6_MMTU) 2016 return(0); 2017 2018 /* notification for our destination. return the MTU. */ 2019 return((int)mtuctl->ip6m_mtu); 2020 } 2021 } 2022 return(0); 2023 } 2024 2025 /* 2026 * pr_icmph6 -- 2027 * Print a descriptive string about an ICMP header. 2028 */ 2029 void 2030 pr_icmph6(struct icmp6_hdr *icp, u_char *end) 2031 { 2032 char ntop_buf[INET6_ADDRSTRLEN]; 2033 struct nd_redirect *red; 2034 2035 switch (icp->icmp6_type) { 2036 case ICMP6_DST_UNREACH: 2037 switch (icp->icmp6_code) { 2038 case ICMP6_DST_UNREACH_NOROUTE: 2039 printf("No Route to Destination\n"); 2040 break; 2041 case ICMP6_DST_UNREACH_ADMIN: 2042 printf("Destination Administratively " 2043 "Unreachable\n"); 2044 break; 2045 case ICMP6_DST_UNREACH_BEYONDSCOPE: 2046 printf("Destination Unreachable Beyond Scope\n"); 2047 break; 2048 case ICMP6_DST_UNREACH_ADDR: 2049 printf("Destination Host Unreachable\n"); 2050 break; 2051 case ICMP6_DST_UNREACH_NOPORT: 2052 printf("Destination Port Unreachable\n"); 2053 break; 2054 default: 2055 printf("Destination Unreachable, Bad Code: %d\n", 2056 icp->icmp6_code); 2057 break; 2058 } 2059 /* Print returned IP header information */ 2060 pr_retip6((struct ip6_hdr *)(icp + 1), end); 2061 break; 2062 case ICMP6_PACKET_TOO_BIG: 2063 printf("Packet too big mtu = %d\n", 2064 (int)ntohl(icp->icmp6_mtu)); 2065 pr_retip6((struct ip6_hdr *)(icp + 1), end); 2066 break; 2067 case ICMP6_TIME_EXCEEDED: 2068 switch (icp->icmp6_code) { 2069 case ICMP6_TIME_EXCEED_TRANSIT: 2070 printf("Time to live exceeded\n"); 2071 break; 2072 case ICMP6_TIME_EXCEED_REASSEMBLY: 2073 printf("Frag reassembly time exceeded\n"); 2074 break; 2075 default: 2076 printf("Time exceeded, Bad Code: %d\n", 2077 icp->icmp6_code); 2078 break; 2079 } 2080 pr_retip6((struct ip6_hdr *)(icp + 1), end); 2081 break; 2082 case ICMP6_PARAM_PROB: 2083 printf("Parameter problem: "); 2084 switch (icp->icmp6_code) { 2085 case ICMP6_PARAMPROB_HEADER: 2086 printf("Erroneous Header "); 2087 break; 2088 case ICMP6_PARAMPROB_NEXTHEADER: 2089 printf("Unknown Nextheader "); 2090 break; 2091 case ICMP6_PARAMPROB_OPTION: 2092 printf("Unrecognized Option "); 2093 break; 2094 default: 2095 printf("Bad code(%d) ", icp->icmp6_code); 2096 break; 2097 } 2098 printf("pointer = 0x%02x\n", 2099 (u_int32_t)ntohl(icp->icmp6_pptr)); 2100 pr_retip6((struct ip6_hdr *)(icp + 1), end); 2101 break; 2102 case ICMP6_ECHO_REQUEST: 2103 printf("Echo Request"); 2104 /* XXX ID + Seq + Data */ 2105 break; 2106 case ICMP6_ECHO_REPLY: 2107 printf("Echo Reply"); 2108 /* XXX ID + Seq + Data */ 2109 break; 2110 case ICMP6_MEMBERSHIP_QUERY: 2111 printf("Listener Query"); 2112 break; 2113 case ICMP6_MEMBERSHIP_REPORT: 2114 printf("Listener Report"); 2115 break; 2116 case ICMP6_MEMBERSHIP_REDUCTION: 2117 printf("Listener Done"); 2118 break; 2119 case ND_ROUTER_SOLICIT: 2120 printf("Router Solicitation"); 2121 break; 2122 case ND_ROUTER_ADVERT: 2123 printf("Router Advertisement"); 2124 break; 2125 case ND_NEIGHBOR_SOLICIT: 2126 printf("Neighbor Solicitation"); 2127 break; 2128 case ND_NEIGHBOR_ADVERT: 2129 printf("Neighbor Advertisement"); 2130 break; 2131 case ND_REDIRECT: 2132 red = (struct nd_redirect *)icp; 2133 printf("Redirect\n"); 2134 if (!inet_ntop(AF_INET6, &red->nd_rd_dst, ntop_buf, 2135 sizeof(ntop_buf))) 2136 strncpy(ntop_buf, "?", sizeof(ntop_buf)); 2137 printf("Destination: %s", ntop_buf); 2138 if (!inet_ntop(AF_INET6, &red->nd_rd_target, ntop_buf, 2139 sizeof(ntop_buf))) 2140 strncpy(ntop_buf, "?", sizeof(ntop_buf)); 2141 printf(" New Target: %s", ntop_buf); 2142 break; 2143 default: 2144 printf("Bad ICMP type: %d", icp->icmp6_type); 2145 } 2146 } 2147 2148 /* 2149 * pr_iph6 -- 2150 * Print an IP6 header. 2151 */ 2152 void 2153 pr_iph6(struct ip6_hdr *ip6) 2154 { 2155 u_int32_t flow = ip6->ip6_flow & IPV6_FLOWLABEL_MASK; 2156 u_int8_t tc; 2157 char ntop_buf[INET6_ADDRSTRLEN]; 2158 2159 tc = *(&ip6->ip6_vfc + 1); /* XXX */ 2160 tc = (tc >> 4) & 0x0f; 2161 tc |= (ip6->ip6_vfc << 4); 2162 2163 printf("Vr TC Flow Plen Nxt Hlim\n"); 2164 printf(" %1x %02x %05x %04x %02x %02x\n", 2165 (ip6->ip6_vfc & IPV6_VERSION_MASK) >> 4, tc, (u_int32_t)ntohl(flow), 2166 ntohs(ip6->ip6_plen), ip6->ip6_nxt, ip6->ip6_hlim); 2167 if (!inet_ntop(AF_INET6, &ip6->ip6_src, ntop_buf, sizeof(ntop_buf))) 2168 strncpy(ntop_buf, "?", sizeof(ntop_buf)); 2169 printf("%s->", ntop_buf); 2170 if (!inet_ntop(AF_INET6, &ip6->ip6_dst, ntop_buf, sizeof(ntop_buf))) 2171 strncpy(ntop_buf, "?", sizeof(ntop_buf)); 2172 printf("%s\n", ntop_buf); 2173 } 2174 2175 /* 2176 * pr_retip6 -- 2177 * Dump some info on a returned (via ICMPv6) IPv6 packet. 2178 */ 2179 void 2180 pr_retip6(struct ip6_hdr *ip6, u_char *end) 2181 { 2182 u_char *cp = (u_char *)ip6, nh; 2183 int hlen; 2184 2185 if (end - (u_char *)ip6 < sizeof(*ip6)) { 2186 printf("IP6"); 2187 goto trunc; 2188 } 2189 pr_iph6(ip6); 2190 hlen = sizeof(*ip6); 2191 2192 nh = ip6->ip6_nxt; 2193 cp += hlen; 2194 while (end - cp >= 8) { 2195 switch (nh) { 2196 case IPPROTO_HOPOPTS: 2197 printf("HBH "); 2198 hlen = (((struct ip6_hbh *)cp)->ip6h_len+1) << 3; 2199 nh = ((struct ip6_hbh *)cp)->ip6h_nxt; 2200 break; 2201 case IPPROTO_DSTOPTS: 2202 printf("DSTOPT "); 2203 hlen = (((struct ip6_dest *)cp)->ip6d_len+1) << 3; 2204 nh = ((struct ip6_dest *)cp)->ip6d_nxt; 2205 break; 2206 case IPPROTO_FRAGMENT: 2207 printf("FRAG "); 2208 hlen = sizeof(struct ip6_frag); 2209 nh = ((struct ip6_frag *)cp)->ip6f_nxt; 2210 break; 2211 case IPPROTO_ROUTING: 2212 printf("RTHDR "); 2213 hlen = (((struct ip6_rthdr *)cp)->ip6r_len+1) << 3; 2214 nh = ((struct ip6_rthdr *)cp)->ip6r_nxt; 2215 break; 2216 case IPPROTO_AH: 2217 printf("AH "); 2218 hlen = (((struct ah *)cp)->ah_hl+2) << 2; 2219 nh = ((struct ah *)cp)->ah_nh; 2220 break; 2221 case IPPROTO_ICMPV6: 2222 printf("ICMP6: type = %d, code = %d\n", 2223 *cp, *(cp + 1)); 2224 return; 2225 case IPPROTO_ESP: 2226 printf("ESP\n"); 2227 return; 2228 case IPPROTO_TCP: 2229 printf("TCP: from port %u, to port %u (decimal)\n", 2230 (*cp * 256 + *(cp + 1)), 2231 (*(cp + 2) * 256 + *(cp + 3))); 2232 return; 2233 case IPPROTO_UDP: 2234 printf("UDP: from port %u, to port %u (decimal)\n", 2235 (*cp * 256 + *(cp + 1)), 2236 (*(cp + 2) * 256 + *(cp + 3))); 2237 return; 2238 default: 2239 printf("Unknown Header(%d)\n", nh); 2240 return; 2241 } 2242 2243 if ((cp += hlen) >= end) 2244 goto trunc; 2245 } 2246 if (end - cp < 8) 2247 goto trunc; 2248 2249 putchar('\n'); 2250 return; 2251 2252 trunc: 2253 printf("...\n"); 2254 return; 2255 } 2256 2257 __dead void 2258 usage(void) 2259 { 2260 if (v6flag) { 2261 fprintf(stderr, 2262 "usage: ping6 [-DdEefgHLmnqv] [-c count] [-h hoplimit] " 2263 "[-I sourceaddr]\n\t[-i interval] [-l preload] " 2264 "[-p pattern] [-s packetsize] [-T toskeyword]\n" 2265 "\t[-V rtable] [-w maxwait] host\n"); 2266 } else { 2267 fprintf(stderr, 2268 "usage: ping [-DdEefgHLnqRv] [-c count] [-I sourceaddr] " 2269 "[-i interval]\n\t[-l preload] [-p pattern] [-s packetsize]" 2270 #ifndef SMALL 2271 " [-T toskeyword]" 2272 #endif /* SMALL */ 2273 "\n\t[-t ttl] [-V rtable] [-w maxwait] host\n"); 2274 } 2275 exit(1); 2276 } 2277