1 /* $NetBSD: ping6.c,v 1.60 2004/06/09 01:59:20 itojun Exp $ */ 2 /* $KAME: ping6.c,v 1.164 2002/11/16 14:05:37 itojun Exp $ */ 3 4 /* 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the project nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 /* BSDI ping.c,v 2.3 1996/01/21 17:56:50 jch Exp */ 34 35 /* 36 * Copyright (c) 1989, 1993 37 * The Regents of the University of California. All rights reserved. 38 * 39 * This code is derived from software contributed to Berkeley by 40 * Mike Muuss. 41 * 42 * Redistribution and use in source and binary forms, with or without 43 * modification, are permitted provided that the following conditions 44 * are met: 45 * 1. Redistributions of source code must retain the above copyright 46 * notice, this list of conditions and the following disclaimer. 47 * 2. Redistributions in binary form must reproduce the above copyright 48 * notice, this list of conditions and the following disclaimer in the 49 * documentation and/or other materials provided with the distribution. 50 * 3. Neither the name of the University nor the names of its contributors 51 * may be used to endorse or promote products derived from this software 52 * without specific prior written permission. 53 * 54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 64 * SUCH DAMAGE. 65 */ 66 67 #if 0 68 #ifndef lint 69 static char copyright[] = 70 "@(#) Copyright (c) 1989, 1993\n\ 71 The Regents of the University of California. All rights reserved.\n"; 72 #endif /* not lint */ 73 74 #ifndef lint 75 static char sccsid[] = "@(#)ping.c 8.1 (Berkeley) 6/5/93"; 76 #endif /* not lint */ 77 #else 78 #include <sys/cdefs.h> 79 #ifndef lint 80 __RCSID("$NetBSD: ping6.c,v 1.60 2004/06/09 01:59:20 itojun Exp $"); 81 #endif 82 #endif 83 84 /* 85 * Using the InterNet Control Message Protocol (ICMP) "ECHO" facility, 86 * measure round-trip-delays and packet loss across network paths. 87 * 88 * Author - 89 * Mike Muuss 90 * U. S. Army Ballistic Research Laboratory 91 * December, 1983 92 * 93 * Status - 94 * Public Domain. Distribution Unlimited. 95 * Bugs - 96 * More statistics could always be gathered. 97 * This program has to run SUID to ROOT to access the ICMP socket. 98 */ 99 /* 100 * NOTE: 101 * USE_SIN6_SCOPE_ID assumes that sin6_scope_id has the same semantics 102 * as IPV6_PKTINFO. Some people object it (sin6_scope_id specifies *link* 103 * while IPV6_PKTINFO specifies *interface*. Link is defined as collection of 104 * network attached to 1 or more interfaces) 105 */ 106 107 #include <sys/param.h> 108 #include <sys/uio.h> 109 #include <sys/socket.h> 110 #include <sys/time.h> 111 112 #include <net/if.h> 113 #include <net/route.h> 114 115 #include <netinet/in.h> 116 #include <netinet/ip6.h> 117 #include <netinet/icmp6.h> 118 #include <arpa/inet.h> 119 #include <arpa/nameser.h> 120 #include <netdb.h> 121 122 #include <ctype.h> 123 #include <err.h> 124 #include <errno.h> 125 #include <fcntl.h> 126 #include <math.h> 127 #include <signal.h> 128 #include <stdio.h> 129 #include <stdlib.h> 130 #include <string.h> 131 #include <unistd.h> 132 #include <poll.h> 133 134 #ifdef IPSEC 135 #include <netinet6/ah.h> 136 #include <netinet6/ipsec.h> 137 #endif 138 139 #include <md5.h> 140 141 struct tv32 { 142 u_int32_t tv32_sec; 143 u_int32_t tv32_usec; 144 }; 145 146 #define MAXPACKETLEN 131072 147 #define IP6LEN 40 148 #define ICMP6ECHOLEN 8 /* icmp echo header len excluding time */ 149 #define ICMP6ECHOTMLEN sizeof(struct tv32) 150 #define ICMP6_NIQLEN (ICMP6ECHOLEN + 8) 151 /* FQDN case, 64 bits of nonce + 32 bits ttl */ 152 #define ICMP6_NIRLEN (ICMP6ECHOLEN + 12) 153 #define EXTRA 256 /* for AH and various other headers. weird. */ 154 #define DEFDATALEN ICMP6ECHOTMLEN 155 #define MAXDATALEN MAXPACKETLEN - IP6LEN - ICMP6ECHOLEN 156 #define NROUTES 9 /* number of record route slots */ 157 158 #define A(bit) rcvd_tbl[(bit)>>3] /* identify byte in array */ 159 #define B(bit) (1 << ((bit) & 0x07)) /* identify bit in byte */ 160 #define SET(bit) (A(bit) |= B(bit)) 161 #define CLR(bit) (A(bit) &= (~B(bit))) 162 #define TST(bit) (A(bit) & B(bit)) 163 164 #define F_FLOOD 0x0001 165 #define F_INTERVAL 0x0002 166 #define F_PINGFILLED 0x0008 167 #define F_QUIET 0x0010 168 #define F_RROUTE 0x0020 169 #define F_SO_DEBUG 0x0040 170 #define F_VERBOSE 0x0100 171 #ifdef IPSEC 172 #ifdef IPSEC_POLICY_IPSEC 173 #define F_POLICY 0x0400 174 #else 175 #define F_AUTHHDR 0x0200 176 #define F_ENCRYPT 0x0400 177 #endif /*IPSEC_POLICY_IPSEC*/ 178 #endif /*IPSEC*/ 179 #define F_NODEADDR 0x0800 180 #define F_FQDN 0x1000 181 #define F_INTERFACE 0x2000 182 #define F_SRCADDR 0x4000 183 #ifdef IPV6_REACHCONF 184 #define F_REACHCONF 0x8000 185 #endif 186 #define F_HOSTNAME 0x10000 187 #define F_FQDNOLD 0x20000 188 #define F_NIGROUP 0x40000 189 #define F_SUPTYPES 0x80000 190 #define F_NOMINMTU 0x100000 191 #define F_NOUSERDATA (F_NODEADDR | F_FQDN | F_FQDNOLD | F_SUPTYPES) 192 u_int options; 193 194 #define IN6LEN sizeof(struct in6_addr) 195 #define SA6LEN sizeof(struct sockaddr_in6) 196 #define DUMMY_PORT 10101 197 198 #define SIN6(s) ((struct sockaddr_in6 *)(s)) 199 200 /* 201 * MAX_DUP_CHK is the number of bits in received table, i.e. the maximum 202 * number of received sequence numbers we can keep track of. Change 128 203 * to 8192 for complete accuracy... 204 */ 205 #define MAX_DUP_CHK (8 * 8192) 206 int mx_dup_ck = MAX_DUP_CHK; 207 char rcvd_tbl[MAX_DUP_CHK / 8]; 208 209 struct addrinfo *res; 210 struct sockaddr_in6 dst; /* who to ping6 */ 211 struct sockaddr_in6 src; /* src addr of this packet */ 212 socklen_t srclen; 213 int datalen = DEFDATALEN; 214 int s; /* socket file descriptor */ 215 u_char outpack[MAXPACKETLEN]; 216 char BSPACE = '\b'; /* characters written for flood */ 217 char DOT = '.'; 218 char *hostname; 219 int ident; /* process id to identify our packets */ 220 u_int8_t nonce[8]; /* nonce field for node information */ 221 int hoplimit = -1; /* hoplimit */ 222 int pathmtu = 0; /* path MTU for the destination. 0 = unspec. */ 223 224 /* counters */ 225 long npackets; /* max packets to transmit */ 226 long nreceived; /* # of packets we got back */ 227 long nrepeats; /* number of duplicates */ 228 long ntransmitted; /* sequence # for outbound packets = #sent */ 229 struct timeval interval = {1, 0}; /* interval between packets */ 230 231 /* timing */ 232 int timing; /* flag to do timing */ 233 double tmin = 999999999.0; /* minimum round trip time */ 234 double tmax = 0.0; /* maximum round trip time */ 235 double tsum = 0.0; /* sum of all times, for doing average */ 236 double tsumsq = 0.0; /* sum of all times squared, for std. dev. */ 237 238 /* for node addresses */ 239 u_short naflags; 240 241 /* for ancillary data(advanced API) */ 242 struct msghdr smsghdr; 243 struct iovec smsgiov; 244 char *scmsg = 0; 245 246 volatile sig_atomic_t seenalrm; 247 volatile sig_atomic_t seenint; 248 #ifdef SIGINFO 249 volatile sig_atomic_t seeninfo; 250 #endif 251 252 int main __P((int, char *[])); 253 void fill __P((char *, char *)); 254 int get_hoplim __P((struct msghdr *)); 255 int get_pathmtu __P((struct msghdr *)); 256 struct in6_pktinfo *get_rcvpktinfo __P((struct msghdr *)); 257 void onsignal __P((int)); 258 void retransmit __P((void)); 259 void onint __P((int)); 260 size_t pingerlen __P((void)); 261 int pinger __P((void)); 262 const char *pr_addr __P((struct sockaddr *, int)); 263 void pr_icmph __P((struct icmp6_hdr *, u_char *)); 264 void pr_iph __P((struct ip6_hdr *)); 265 void pr_suptypes __P((struct icmp6_nodeinfo *, size_t)); 266 void pr_nodeaddr __P((struct icmp6_nodeinfo *, int)); 267 int myechoreply __P((const struct icmp6_hdr *)); 268 int mynireply __P((const struct icmp6_nodeinfo *)); 269 char *dnsdecode __P((const u_char **, const u_char *, const u_char *, 270 char *, size_t)); 271 void pr_pack __P((u_char *, int, struct msghdr *)); 272 void pr_exthdrs __P((struct msghdr *)); 273 void pr_ip6opt __P((void *)); 274 void pr_rthdr __P((void *)); 275 int pr_bitrange __P((u_int32_t, int, int)); 276 void pr_retip __P((struct ip6_hdr *, u_char *)); 277 void summary __P((void)); 278 void tvsub __P((struct timeval *, struct timeval *)); 279 int setpolicy __P((int, char *)); 280 char *nigroup __P((char *)); 281 void usage __P((void)); 282 283 int 284 main(argc, argv) 285 int argc; 286 char *argv[]; 287 { 288 struct itimerval itimer; 289 struct sockaddr_in6 from; 290 int timeout; 291 struct addrinfo hints; 292 struct pollfd fdmaskp[1]; 293 int cc, i; 294 int ch, hold, packlen, preload, optval, ret_ga; 295 u_char *datap, *packet; 296 char *e, *target, *ifname = NULL, *gateway = NULL; 297 int ip6optlen = 0; 298 struct cmsghdr *scmsgp = NULL; 299 #if defined(SO_SNDBUF) && defined(SO_RCVBUF) 300 u_long lsockbufsize; 301 int sockbufsize = 0; 302 #endif 303 int usepktinfo = 0; 304 struct in6_pktinfo *pktinfo = NULL; 305 #ifdef USE_RFC2292BIS 306 struct ip6_rthdr *rthdr = NULL; 307 #endif 308 #ifdef IPSEC_POLICY_IPSEC 309 char *policy_in = NULL; 310 char *policy_out = NULL; 311 #endif 312 double intval; 313 size_t rthlen; 314 #ifdef IPV6_USE_MIN_MTU 315 int mflag = 0; 316 #endif 317 318 /* just to be sure */ 319 memset(&smsghdr, 0, sizeof(smsghdr)); 320 memset(&smsgiov, 0, sizeof(smsgiov)); 321 322 preload = 0; 323 datap = &outpack[ICMP6ECHOLEN + ICMP6ECHOTMLEN]; 324 #ifndef IPSEC 325 #define ADDOPTS 326 #else 327 #ifdef IPSEC_POLICY_IPSEC 328 #define ADDOPTS "P:" 329 #else 330 #define ADDOPTS "AE" 331 #endif /*IPSEC_POLICY_IPSEC*/ 332 #endif 333 while ((ch = getopt(argc, argv, 334 "a:b:c:dfHg:h:I:i:l:mnNp:qRS:s:tvwW" ADDOPTS)) != -1) { 335 #undef ADDOPTS 336 switch (ch) { 337 case 'a': 338 { 339 char *cp; 340 341 options &= ~F_NOUSERDATA; 342 options |= F_NODEADDR; 343 for (cp = optarg; *cp != '\0'; cp++) { 344 switch (*cp) { 345 case 'a': 346 naflags |= NI_NODEADDR_FLAG_ALL; 347 break; 348 case 'c': 349 case 'C': 350 naflags |= NI_NODEADDR_FLAG_COMPAT; 351 break; 352 case 'l': 353 case 'L': 354 naflags |= NI_NODEADDR_FLAG_LINKLOCAL; 355 break; 356 case 's': 357 case 'S': 358 naflags |= NI_NODEADDR_FLAG_SITELOCAL; 359 break; 360 case 'g': 361 case 'G': 362 naflags |= NI_NODEADDR_FLAG_GLOBAL; 363 break; 364 case 'A': /* experimental. not in the spec */ 365 #ifdef NI_NODEADDR_FLAG_ANYCAST 366 naflags |= NI_NODEADDR_FLAG_ANYCAST; 367 break; 368 #else 369 errx(1, 370 "-a A is not supported on the platform"); 371 /*NOTREACHED*/ 372 #endif 373 default: 374 usage(); 375 /*NOTREACHED*/ 376 } 377 } 378 break; 379 } 380 case 'b': 381 #if defined(SO_SNDBUF) && defined(SO_RCVBUF) 382 errno = 0; 383 e = NULL; 384 lsockbufsize = strtoul(optarg, &e, 10); 385 sockbufsize = lsockbufsize; 386 if (errno || !*optarg || *e || 387 sockbufsize != lsockbufsize) 388 errx(1, "invalid socket buffer size"); 389 #else 390 errx(1, 391 "-b option ignored: SO_SNDBUF/SO_RCVBUF socket options not supported"); 392 #endif 393 break; 394 case 'c': 395 npackets = strtol(optarg, &e, 10); 396 if (npackets <= 0 || *optarg == '\0' || *e != '\0') 397 errx(1, 398 "illegal number of packets -- %s", optarg); 399 break; 400 case 'd': 401 options |= F_SO_DEBUG; 402 break; 403 case 'f': 404 if (getuid()) { 405 errno = EPERM; 406 errx(1, "Must be superuser to flood ping"); 407 } 408 options |= F_FLOOD; 409 setbuf(stdout, (char *)NULL); 410 break; 411 case 'g': 412 gateway = optarg; 413 break; 414 case 'H': 415 options |= F_HOSTNAME; 416 break; 417 case 'h': /* hoplimit */ 418 hoplimit = strtol(optarg, &e, 10); 419 if (*optarg == '\0' || *e != '\0') 420 errx(1, "illegal hoplimit %s", optarg); 421 if (255 < hoplimit || hoplimit < -1) 422 errx(1, 423 "illegal hoplimit -- %s", optarg); 424 break; 425 case 'I': 426 ifname = optarg; 427 options |= F_INTERFACE; 428 #ifndef USE_SIN6_SCOPE_ID 429 usepktinfo++; 430 #endif 431 break; 432 case 'i': /* wait between sending packets */ 433 intval = strtod(optarg, &e); 434 if (*optarg == '\0' || *e != '\0') 435 errx(1, "illegal timing interval %s", optarg); 436 if (intval < 1 && getuid()) { 437 errx(1, "%s: only root may use interval < 1s", 438 strerror(EPERM)); 439 } 440 interval.tv_sec = (long)intval; 441 interval.tv_usec = 442 (long)((intval - interval.tv_sec) * 1000000); 443 if (interval.tv_sec < 0) 444 errx(1, "illegal timing interval %s", optarg); 445 /* less than 1/hz does not make sense */ 446 if (interval.tv_sec == 0 && interval.tv_usec < 10000) { 447 warnx("too small interval, raised to 0.01"); 448 interval.tv_usec = 10000; 449 } 450 options |= F_INTERVAL; 451 break; 452 case 'l': 453 if (getuid()) { 454 errno = EPERM; 455 errx(1, "Must be superuser to preload"); 456 } 457 preload = strtol(optarg, &e, 10); 458 if (preload < 0 || *optarg == '\0' || *e != '\0') 459 errx(1, "illegal preload value -- %s", optarg); 460 break; 461 case 'm': 462 #ifdef IPV6_USE_MIN_MTU 463 mflag++; 464 break; 465 #else 466 errx(1, "-%c is not supported on this platform", ch); 467 /*NOTREACHED*/ 468 #endif 469 case 'n': 470 options &= ~F_HOSTNAME; 471 break; 472 case 'N': 473 options |= F_NIGROUP; 474 break; 475 case 'p': /* fill buffer with user pattern */ 476 options |= F_PINGFILLED; 477 fill((char *)datap, optarg); 478 break; 479 case 'q': 480 options |= F_QUIET; 481 break; 482 case 'R': 483 #ifdef IPV6_REACHCONF 484 options |= F_REACHCONF; 485 break; 486 #else 487 errx(1, "-R is not supported in this configuration"); 488 #endif 489 case 'S': 490 memset(&hints, 0, sizeof(struct addrinfo)); 491 hints.ai_flags = AI_NUMERICHOST; /* allow hostname? */ 492 hints.ai_family = AF_INET6; 493 hints.ai_socktype = SOCK_RAW; 494 hints.ai_protocol = IPPROTO_ICMPV6; 495 496 ret_ga = getaddrinfo(optarg, NULL, &hints, &res); 497 if (ret_ga) { 498 errx(1, "invalid source address: %s", 499 gai_strerror(ret_ga)); 500 } 501 /* 502 * res->ai_family must be AF_INET6 and res->ai_addrlen 503 * must be sizeof(src). 504 */ 505 memcpy(&src, res->ai_addr, res->ai_addrlen); 506 srclen = res->ai_addrlen; 507 freeaddrinfo(res); 508 options |= F_SRCADDR; 509 break; 510 case 's': /* size of packet to send */ 511 datalen = strtol(optarg, &e, 10); 512 if (datalen <= 0 || *optarg == '\0' || *e != '\0') 513 errx(1, "illegal datalen value -- %s", optarg); 514 if (datalen > MAXDATALEN) { 515 errx(1, 516 "datalen value too large, maximum is %d", 517 MAXDATALEN); 518 } 519 break; 520 case 't': 521 options &= ~F_NOUSERDATA; 522 options |= F_SUPTYPES; 523 break; 524 case 'v': 525 options |= F_VERBOSE; 526 break; 527 case 'w': 528 options &= ~F_NOUSERDATA; 529 options |= F_FQDN; 530 break; 531 case 'W': 532 options &= ~F_NOUSERDATA; 533 options |= F_FQDNOLD; 534 break; 535 #ifdef IPSEC 536 #ifdef IPSEC_POLICY_IPSEC 537 case 'P': 538 options |= F_POLICY; 539 if (!strncmp("in", optarg, 2)) { 540 if ((policy_in = strdup(optarg)) == NULL) 541 errx(1, "strdup"); 542 } else if (!strncmp("out", optarg, 3)) { 543 if ((policy_out = strdup(optarg)) == NULL) 544 errx(1, "strdup"); 545 } else 546 errx(1, "invalid security policy"); 547 break; 548 #else 549 case 'A': 550 options |= F_AUTHHDR; 551 break; 552 case 'E': 553 options |= F_ENCRYPT; 554 break; 555 #endif /*IPSEC_POLICY_IPSEC*/ 556 #endif /*IPSEC*/ 557 default: 558 usage(); 559 /*NOTREACHED*/ 560 } 561 } 562 563 argc -= optind; 564 argv += optind; 565 566 if (argc < 1) { 567 usage(); 568 /*NOTREACHED*/ 569 } 570 571 if (argc > 1) { 572 #ifdef IPV6_RECVRTHDR /* 2292bis */ 573 rthlen = CMSG_SPACE(inet6_rth_space(IPV6_RTHDR_TYPE_0, 574 argc - 1)); 575 #else /* RFC2292 */ 576 rthlen = inet6_rthdr_space(IPV6_RTHDR_TYPE_0, argc - 1); 577 #endif 578 if (rthlen == 0) { 579 errx(1, "too many intermediate hops"); 580 /*NOTREACHED*/ 581 } 582 ip6optlen += rthlen; 583 } 584 585 if (options & F_NIGROUP) { 586 target = nigroup(argv[argc - 1]); 587 if (target == NULL) { 588 usage(); 589 /*NOTREACHED*/ 590 } 591 } else 592 target = argv[argc - 1]; 593 594 /* getaddrinfo */ 595 memset(&hints, 0, sizeof(struct addrinfo)); 596 hints.ai_flags = AI_CANONNAME; 597 hints.ai_family = AF_INET6; 598 hints.ai_socktype = SOCK_RAW; 599 hints.ai_protocol = IPPROTO_ICMPV6; 600 601 ret_ga = getaddrinfo(target, NULL, &hints, &res); 602 if (ret_ga) 603 errx(1, "%s", gai_strerror(ret_ga)); 604 if (res->ai_canonname) 605 hostname = res->ai_canonname; 606 else 607 hostname = target; 608 609 if (!res->ai_addr) 610 errx(1, "getaddrinfo failed"); 611 612 (void)memcpy(&dst, res->ai_addr, res->ai_addrlen); 613 614 if ((s = socket(res->ai_family, res->ai_socktype, 615 res->ai_protocol)) < 0) 616 err(1, "socket"); 617 618 /* set the source address if specified. */ 619 if ((options & F_SRCADDR) && 620 bind(s, (struct sockaddr *)&src, srclen) != 0) { 621 err(1, "bind"); 622 } 623 624 /* set the gateway (next hop) if specified */ 625 if (gateway) { 626 struct addrinfo ghints, *gres; 627 int error; 628 629 memset(&ghints, 0, sizeof(ghints)); 630 ghints.ai_family = AF_INET6; 631 ghints.ai_socktype = SOCK_RAW; 632 ghints.ai_protocol = IPPROTO_ICMPV6; 633 634 error = getaddrinfo(gateway, NULL, &hints, &gres); 635 if (error) { 636 errx(1, "getaddrinfo for the gateway %s: %s", 637 gateway, gai_strerror(error)); 638 } 639 if (gres->ai_next && (options & F_VERBOSE)) 640 warnx("gateway resolves to multiple addresses"); 641 642 if (setsockopt(s, IPPROTO_IPV6, IPV6_NEXTHOP, 643 gres->ai_addr, gres->ai_addrlen)) { 644 err(1, "setsockopt(IPV6_NEXTHOP)"); 645 } 646 647 freeaddrinfo(gres); 648 } 649 650 /* 651 * let the kerel pass extension headers of incoming packets, 652 * for privileged socket options 653 */ 654 if ((options & F_VERBOSE) != 0) { 655 int opton = 1; 656 657 #ifdef IPV6_RECVHOPOPTS 658 if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPOPTS, &opton, 659 sizeof(opton))) 660 err(1, "setsockopt(IPV6_RECVHOPOPTS)"); 661 #else /* old adv. API */ 662 if (setsockopt(s, IPPROTO_IPV6, IPV6_HOPOPTS, &opton, 663 sizeof(opton))) 664 err(1, "setsockopt(IPV6_HOPOPTS)"); 665 #endif 666 #ifdef IPV6_RECVDSTOPTS 667 if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVDSTOPTS, &opton, 668 sizeof(opton))) 669 err(1, "setsockopt(IPV6_RECVDSTOPTS)"); 670 #else /* old adv. API */ 671 if (setsockopt(s, IPPROTO_IPV6, IPV6_DSTOPTS, &opton, 672 sizeof(opton))) 673 err(1, "setsockopt(IPV6_DSTOPTS)"); 674 #endif 675 #ifdef IPV6_RECVRTHDRDSTOPTS 676 if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVRTHDRDSTOPTS, &opton, 677 sizeof(opton))) 678 err(1, "setsockopt(IPV6_RECVRTHDRDSTOPTS)"); 679 #endif 680 } 681 682 /* revoke root privilege */ 683 seteuid(getuid()); 684 setuid(getuid()); 685 686 if ((options & F_FLOOD) && (options & F_INTERVAL)) 687 errx(1, "-f and -i incompatible options"); 688 689 if ((options & F_NOUSERDATA) == 0) { 690 if (datalen >= sizeof(struct tv32)) { 691 /* we can time transfer */ 692 timing = 1; 693 } else 694 timing = 0; 695 /* in F_VERBOSE case, we may get non-echoreply packets*/ 696 if (options & F_VERBOSE) 697 packlen = 2048 + IP6LEN + ICMP6ECHOLEN + EXTRA; 698 else 699 packlen = datalen + IP6LEN + ICMP6ECHOLEN + EXTRA; 700 } else { 701 /* suppress timing for node information query */ 702 timing = 0; 703 datalen = 2048; 704 packlen = 2048 + IP6LEN + ICMP6ECHOLEN + EXTRA; 705 } 706 707 if (!(packet = (u_char *)malloc((u_int)packlen))) 708 err(1, "Unable to allocate packet"); 709 if (!(options & F_PINGFILLED)) 710 for (i = ICMP6ECHOLEN; i < packlen; ++i) 711 *datap++ = i; 712 713 ident = arc4random() & 0xFFFF; 714 memset(nonce, 0, sizeof(nonce)); 715 for (i = 0; i < sizeof(nonce); i += sizeof(u_int32_t)) 716 *((u_int32_t *)&nonce[i]) = arc4random(); 717 718 hold = 1; 719 720 if (options & F_SO_DEBUG) 721 (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&hold, 722 sizeof(hold)); 723 optval = IPV6_DEFHLIM; 724 if (IN6_IS_ADDR_MULTICAST(&dst.sin6_addr)) 725 if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 726 &optval, sizeof(optval)) == -1) 727 err(1, "IPV6_MULTICAST_HOPS"); 728 #ifdef IPV6_USE_MIN_MTU 729 if (mflag != 1) { 730 optval = mflag > 1 ? 0 : 1; 731 732 if (setsockopt(s, IPPROTO_IPV6, IPV6_USE_MIN_MTU, 733 &optval, sizeof(optval)) == -1) 734 err(1, "setsockopt(IPV6_USE_MIN_MTU)"); 735 } 736 #ifdef IPV6_RECVPATHMTU 737 else { 738 optval = 1; 739 if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPATHMTU, 740 &optval, sizeof(optval)) == -1) 741 err(1, "setsockopt(IPV6_RECVPATHMTU)"); 742 } 743 #endif /* IPV6_RECVPATHMTU */ 744 #endif /* IPV6_USE_MIN_MTU */ 745 746 #ifdef IPSEC 747 #ifdef IPSEC_POLICY_IPSEC 748 if (options & F_POLICY) { 749 if (setpolicy(s, policy_in) < 0) 750 errx(1, "%s", ipsec_strerror()); 751 if (setpolicy(s, policy_out) < 0) 752 errx(1, "%s", ipsec_strerror()); 753 } 754 #else 755 if (options & F_AUTHHDR) { 756 optval = IPSEC_LEVEL_REQUIRE; 757 #ifdef IPV6_AUTH_TRANS_LEVEL 758 if (setsockopt(s, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, 759 &optval, sizeof(optval)) == -1) 760 err(1, "setsockopt(IPV6_AUTH_TRANS_LEVEL)"); 761 #else /* old def */ 762 if (setsockopt(s, IPPROTO_IPV6, IPV6_AUTH_LEVEL, 763 &optval, sizeof(optval)) == -1) 764 err(1, "setsockopt(IPV6_AUTH_LEVEL)"); 765 #endif 766 } 767 if (options & F_ENCRYPT) { 768 optval = IPSEC_LEVEL_REQUIRE; 769 if (setsockopt(s, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, 770 &optval, sizeof(optval)) == -1) 771 err(1, "setsockopt(IPV6_ESP_TRANS_LEVEL)"); 772 } 773 #endif /*IPSEC_POLICY_IPSEC*/ 774 #endif 775 776 #ifdef ICMP6_FILTER 777 { 778 struct icmp6_filter filt; 779 if (!(options & F_VERBOSE)) { 780 ICMP6_FILTER_SETBLOCKALL(&filt); 781 if ((options & F_FQDN) || (options & F_FQDNOLD) || 782 (options & F_NODEADDR) || (options & F_SUPTYPES)) 783 ICMP6_FILTER_SETPASS(ICMP6_NI_REPLY, &filt); 784 else 785 ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &filt); 786 } else { 787 ICMP6_FILTER_SETPASSALL(&filt); 788 } 789 if (setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, &filt, 790 sizeof(filt)) < 0) 791 err(1, "setsockopt(ICMP6_FILTER)"); 792 } 793 #endif /*ICMP6_FILTER*/ 794 795 /* let the kerel pass extension headers of incoming packets */ 796 if ((options & F_VERBOSE) != 0) { 797 int opton = 1; 798 799 #ifdef IPV6_RECVRTHDR 800 if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVRTHDR, &opton, 801 sizeof(opton))) 802 err(1, "setsockopt(IPV6_RECVRTHDR)"); 803 #else /* old adv. API */ 804 if (setsockopt(s, IPPROTO_IPV6, IPV6_RTHDR, &opton, 805 sizeof(opton))) 806 err(1, "setsockopt(IPV6_RTHDR)"); 807 #endif 808 } 809 810 /* 811 optval = 1; 812 if (IN6_IS_ADDR_MULTICAST(&dst.sin6_addr)) 813 if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, 814 &optval, sizeof(optval)) == -1) 815 err(1, "IPV6_MULTICAST_LOOP"); 816 */ 817 818 /* Specify the outgoing interface and/or the source address */ 819 if (usepktinfo) 820 ip6optlen += CMSG_SPACE(sizeof(struct in6_pktinfo)); 821 822 if (hoplimit != -1) 823 ip6optlen += CMSG_SPACE(sizeof(int)); 824 825 #ifdef IPV6_REACHCONF 826 if (options & F_REACHCONF) 827 ip6optlen += CMSG_SPACE(0); 828 #endif 829 830 /* set IP6 packet options */ 831 if (ip6optlen) { 832 if ((scmsg = (char *)malloc(ip6optlen)) == 0) 833 errx(1, "can't allocate enough memory"); 834 smsghdr.msg_control = (caddr_t)scmsg; 835 smsghdr.msg_controllen = ip6optlen; 836 scmsgp = (struct cmsghdr *)scmsg; 837 } 838 if (usepktinfo) { 839 pktinfo = (struct in6_pktinfo *)(CMSG_DATA(scmsgp)); 840 memset(pktinfo, 0, sizeof(*pktinfo)); 841 scmsgp->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 842 scmsgp->cmsg_level = IPPROTO_IPV6; 843 scmsgp->cmsg_type = IPV6_PKTINFO; 844 scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp); 845 } 846 847 /* set the outgoing interface */ 848 if (ifname) { 849 #ifndef USE_SIN6_SCOPE_ID 850 /* pktinfo must have already been allocated */ 851 if ((pktinfo->ipi6_ifindex = if_nametoindex(ifname)) == 0) 852 errx(1, "%s: invalid interface name", ifname); 853 #else 854 if ((dst.sin6_scope_id = if_nametoindex(ifname)) == 0) 855 errx(1, "%s: invalid interface name", ifname); 856 #endif 857 } 858 if (hoplimit != -1) { 859 scmsgp->cmsg_len = CMSG_LEN(sizeof(int)); 860 scmsgp->cmsg_level = IPPROTO_IPV6; 861 scmsgp->cmsg_type = IPV6_HOPLIMIT; 862 *(int *)(CMSG_DATA(scmsgp)) = hoplimit; 863 864 scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp); 865 } 866 #ifdef IPV6_REACHCONF 867 if (options & F_REACHCONF) { 868 scmsgp->cmsg_len = CMSG_LEN(0); 869 scmsgp->cmsg_level = IPPROTO_IPV6; 870 scmsgp->cmsg_type = IPV6_REACHCONF; 871 872 scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp); 873 } 874 #endif 875 876 if (argc > 1) { /* some intermediate addrs are specified */ 877 int hops, error; 878 #ifdef USE_RFC2292BIS 879 int rthdrlen; 880 #endif 881 882 #ifdef USE_RFC2292BIS 883 rthdrlen = inet6_rth_space(IPV6_RTHDR_TYPE_0, argc - 1); 884 scmsgp->cmsg_len = CMSG_LEN(rthdrlen); 885 scmsgp->cmsg_level = IPPROTO_IPV6; 886 scmsgp->cmsg_type = IPV6_RTHDR; 887 rthdr = (struct ip6_rthdr *)CMSG_DATA(scmsgp); 888 rthdr = inet6_rth_init((void *)rthdr, rthdrlen, 889 IPV6_RTHDR_TYPE_0, argc - 1); 890 if (rthdr == NULL) 891 errx(1, "can't initialize rthdr"); 892 #else /* old advanced API */ 893 if ((scmsgp = (struct cmsghdr *)inet6_rthdr_init(scmsgp, 894 IPV6_RTHDR_TYPE_0)) == 0) 895 errx(1, "can't initialize rthdr"); 896 #endif /* USE_RFC2292BIS */ 897 898 for (hops = 0; hops < argc - 1; hops++) { 899 struct addrinfo *iaip; 900 901 if ((error = getaddrinfo(argv[hops], NULL, &hints, 902 &iaip))) 903 errx(1, "%s", gai_strerror(error)); 904 if (SIN6(iaip->ai_addr)->sin6_family != AF_INET6) 905 errx(1, 906 "bad addr family of an intermediate addr"); 907 908 #ifdef USE_RFC2292BIS 909 if (inet6_rth_add(rthdr, 910 &(SIN6(iaip->ai_addr))->sin6_addr)) 911 errx(1, "can't add an intermediate node"); 912 #else /* old advanced API */ 913 if (inet6_rthdr_add(scmsgp, 914 &(SIN6(iaip->ai_addr))->sin6_addr, 915 IPV6_RTHDR_LOOSE)) 916 errx(1, "can't add an intermediate node"); 917 #endif /* USE_RFC2292BIS */ 918 freeaddrinfo(iaip); 919 } 920 921 #ifndef USE_RFC2292BIS 922 if (inet6_rthdr_lasthop(scmsgp, IPV6_RTHDR_LOOSE)) 923 errx(1, "can't set the last flag"); 924 #endif 925 926 scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp); 927 } 928 929 if (!(options & F_SRCADDR)) { 930 /* 931 * get the source address. XXX since we revoked the root 932 * privilege, we cannot use a raw socket for this. 933 */ 934 int dummy; 935 socklen_t len = sizeof(src); 936 937 if ((dummy = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) 938 err(1, "UDP socket"); 939 940 src.sin6_family = AF_INET6; 941 src.sin6_addr = dst.sin6_addr; 942 src.sin6_port = ntohs(DUMMY_PORT); 943 src.sin6_scope_id = dst.sin6_scope_id; 944 945 #ifdef USE_RFC2292BIS 946 if (pktinfo && 947 setsockopt(dummy, IPPROTO_IPV6, IPV6_PKTINFO, 948 (void *)pktinfo, sizeof(*pktinfo))) 949 err(1, "UDP setsockopt(IPV6_PKTINFO)"); 950 951 if (hoplimit != -1 && 952 setsockopt(dummy, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 953 (void *)&hoplimit, sizeof(hoplimit))) 954 err(1, "UDP setsockopt(IPV6_UNICAST_HOPS)"); 955 956 if (hoplimit != -1 && 957 setsockopt(dummy, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 958 (void *)&hoplimit, sizeof(hoplimit))) 959 err(1, "UDP setsockopt(IPV6_MULTICAST_HOPS)"); 960 961 if (rthdr && 962 setsockopt(dummy, IPPROTO_IPV6, IPV6_RTHDR, 963 (void *)rthdr, (rthdr->ip6r_len + 1) << 3)) 964 err(1, "UDP setsockopt(IPV6_RTHDR)"); 965 #else /* old advanced API */ 966 if (smsghdr.msg_control && 967 setsockopt(dummy, IPPROTO_IPV6, IPV6_PKTOPTIONS, 968 (void *)smsghdr.msg_control, smsghdr.msg_controllen)) 969 err(1, "UDP setsockopt(IPV6_PKTOPTIONS)"); 970 #endif 971 972 if (connect(dummy, (struct sockaddr *)&src, len) < 0) 973 err(1, "UDP connect"); 974 975 if (getsockname(dummy, (struct sockaddr *)&src, &len) < 0) 976 err(1, "getsockname"); 977 978 close(dummy); 979 } 980 981 #if defined(SO_SNDBUF) && defined(SO_RCVBUF) 982 if (sockbufsize) { 983 if (datalen > sockbufsize) 984 warnx("you need -b to increase socket buffer size"); 985 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sockbufsize, 986 sizeof(sockbufsize)) < 0) 987 err(1, "setsockopt(SO_SNDBUF)"); 988 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &sockbufsize, 989 sizeof(sockbufsize)) < 0) 990 err(1, "setsockopt(SO_RCVBUF)"); 991 } 992 else { 993 if (datalen > 8 * 1024) /*XXX*/ 994 warnx("you need -b to increase socket buffer size"); 995 /* 996 * When pinging the broadcast address, you can get a lot of 997 * answers. Doing something so evil is useful if you are trying 998 * to stress the ethernet, or just want to fill the arp cache 999 * to get some stuff for /etc/ethers. 1000 */ 1001 hold = 48 * 1024; 1002 setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&hold, 1003 sizeof(hold)); 1004 } 1005 #endif 1006 1007 optval = 1; 1008 #ifndef USE_SIN6_SCOPE_ID 1009 #ifdef IPV6_RECVPKTINFO 1010 if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &optval, 1011 sizeof(optval)) < 0) 1012 warn("setsockopt(IPV6_RECVPKTINFO)"); /* XXX err? */ 1013 #else /* old adv. API */ 1014 if (setsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO, &optval, 1015 sizeof(optval)) < 0) 1016 warn("setsockopt(IPV6_PKTINFO)"); /* XXX err? */ 1017 #endif 1018 #endif /* USE_SIN6_SCOPE_ID */ 1019 #ifdef IPV6_RECVHOPLIMIT 1020 if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &optval, 1021 sizeof(optval)) < 0) 1022 warn("setsockopt(IPV6_RECVHOPLIMIT)"); /* XXX err? */ 1023 #else /* old adv. API */ 1024 if (setsockopt(s, IPPROTO_IPV6, IPV6_HOPLIMIT, &optval, 1025 sizeof(optval)) < 0) 1026 warn("setsockopt(IPV6_HOPLIMIT)"); /* XXX err? */ 1027 #endif 1028 1029 printf("PING6(%lu=40+8+%lu bytes) ", (unsigned long)(40 + pingerlen()), 1030 (unsigned long)(pingerlen() - 8)); 1031 printf("%s --> ", pr_addr((struct sockaddr *)&src, sizeof(src))); 1032 printf("%s\n", pr_addr((struct sockaddr *)&dst, sizeof(dst))); 1033 1034 while (preload--) /* Fire off them quickies. */ 1035 (void)pinger(); 1036 1037 (void)signal(SIGINT, onsignal); 1038 #ifdef SIGINFO 1039 (void)signal(SIGINFO, onsignal); 1040 #endif 1041 1042 if ((options & F_FLOOD) == 0) { 1043 (void)signal(SIGALRM, onsignal); 1044 itimer.it_interval = interval; 1045 itimer.it_value = interval; 1046 (void)setitimer(ITIMER_REAL, &itimer, NULL); 1047 if (ntransmitted) 1048 retransmit(); 1049 } 1050 1051 seenalrm = seenint = 0; 1052 #ifdef SIGINFO 1053 seeninfo = 0; 1054 #endif 1055 1056 for (;;) { 1057 struct msghdr m; 1058 struct cmsghdr *cm; 1059 u_char buf[1024]; 1060 struct iovec iov[2]; 1061 1062 /* signal handling */ 1063 if (seenalrm) { 1064 retransmit(); 1065 seenalrm = 0; 1066 continue; 1067 } 1068 if (seenint) { 1069 onint(SIGINT); 1070 seenint = 0; 1071 continue; 1072 } 1073 #ifdef SIGINFO 1074 if (seeninfo) { 1075 summary(); 1076 seeninfo = 0; 1077 continue; 1078 } 1079 #endif 1080 1081 if (options & F_FLOOD) { 1082 (void)pinger(); 1083 timeout = 10; 1084 } else { 1085 timeout = INFTIM; 1086 } 1087 fdmaskp[0].fd = s; 1088 fdmaskp[0].events = POLLIN; 1089 cc = poll(fdmaskp, 1, timeout); 1090 if (cc < 0) { 1091 if (errno != EINTR) { 1092 warn("poll"); 1093 sleep(1); 1094 } 1095 continue; 1096 } else if (cc == 0) 1097 continue; 1098 1099 m.msg_name = (caddr_t)&from; 1100 m.msg_namelen = sizeof(from); 1101 memset(&iov, 0, sizeof(iov)); 1102 iov[0].iov_base = (caddr_t)packet; 1103 iov[0].iov_len = packlen; 1104 m.msg_iov = iov; 1105 m.msg_iovlen = 1; 1106 cm = (struct cmsghdr *)buf; 1107 m.msg_control = (caddr_t)buf; 1108 m.msg_controllen = sizeof(buf); 1109 1110 cc = recvmsg(s, &m, 0); 1111 if (cc < 0) { 1112 if (errno != EINTR) { 1113 warn("recvmsg"); 1114 sleep(1); 1115 } 1116 continue; 1117 } else if (cc == 0) { 1118 int mtu; 1119 1120 /* 1121 * receive control messages only. Process the 1122 * exceptions (currently the only possiblity is 1123 * a path MTU notification.) 1124 */ 1125 if ((mtu = get_pathmtu(&m)) > 0) { 1126 if ((options & F_VERBOSE) != 0) { 1127 printf("new path MTU (%d) is " 1128 "notified\n", mtu); 1129 } 1130 } 1131 continue; 1132 } else { 1133 /* 1134 * an ICMPv6 message (probably an echoreply) arrived. 1135 */ 1136 pr_pack(packet, cc, &m); 1137 } 1138 if (npackets && nreceived >= npackets) 1139 break; 1140 } 1141 summary(); 1142 exit(nreceived == 0); 1143 } 1144 1145 void 1146 onsignal(sig) 1147 int sig; 1148 { 1149 1150 switch (sig) { 1151 case SIGALRM: 1152 seenalrm++; 1153 break; 1154 case SIGINT: 1155 seenint++; 1156 break; 1157 #ifdef SIGINFO 1158 case SIGINFO: 1159 seeninfo++; 1160 break; 1161 #endif 1162 } 1163 } 1164 1165 /* 1166 * retransmit -- 1167 * This routine transmits another ping6. 1168 */ 1169 void 1170 retransmit() 1171 { 1172 struct itimerval itimer; 1173 1174 if (pinger() == 0) 1175 return; 1176 1177 /* 1178 * If we're not transmitting any more packets, change the timer 1179 * to wait two round-trip times if we've received any packets or 1180 * ten seconds if we haven't. 1181 */ 1182 #define MAXWAIT 10 1183 if (nreceived) { 1184 itimer.it_value.tv_sec = 2 * tmax / 1000; 1185 if (itimer.it_value.tv_sec == 0) 1186 itimer.it_value.tv_sec = 1; 1187 } else 1188 itimer.it_value.tv_sec = MAXWAIT; 1189 itimer.it_interval.tv_sec = 0; 1190 itimer.it_interval.tv_usec = 0; 1191 itimer.it_value.tv_usec = 0; 1192 1193 (void)signal(SIGALRM, onint); 1194 (void)setitimer(ITIMER_REAL, &itimer, NULL); 1195 } 1196 1197 /* 1198 * pinger -- 1199 * Compose and transmit an ICMP ECHO REQUEST packet. The IP packet 1200 * will be added on by the kernel. The ID field is our UNIX process ID, 1201 * and the sequence number is an ascending integer. The first 8 bytes 1202 * of the data portion are used to hold a UNIX "timeval" struct in VAX 1203 * byte-order, to compute the round-trip time. 1204 */ 1205 size_t 1206 pingerlen() 1207 { 1208 size_t l; 1209 1210 if (options & F_FQDN) 1211 l = ICMP6_NIQLEN + sizeof(dst.sin6_addr); 1212 else if (options & F_FQDNOLD) 1213 l = ICMP6_NIQLEN; 1214 else if (options & F_NODEADDR) 1215 l = ICMP6_NIQLEN + sizeof(dst.sin6_addr); 1216 else if (options & F_SUPTYPES) 1217 l = ICMP6_NIQLEN; 1218 else 1219 l = ICMP6ECHOLEN + datalen; 1220 1221 return l; 1222 } 1223 1224 int 1225 pinger() 1226 { 1227 struct icmp6_hdr *icp; 1228 struct iovec iov[2]; 1229 int i, cc; 1230 struct icmp6_nodeinfo *nip; 1231 int seq; 1232 1233 if (npackets && ntransmitted >= npackets) 1234 return(-1); /* no more transmission */ 1235 1236 icp = (struct icmp6_hdr *)outpack; 1237 nip = (struct icmp6_nodeinfo *)outpack; 1238 memset(icp, 0, sizeof(*icp)); 1239 icp->icmp6_cksum = 0; 1240 seq = ntransmitted++; 1241 CLR(seq % mx_dup_ck); 1242 1243 if (options & F_FQDN) { 1244 icp->icmp6_type = ICMP6_NI_QUERY; 1245 icp->icmp6_code = ICMP6_NI_SUBJ_IPV6; 1246 nip->ni_qtype = htons(NI_QTYPE_FQDN); 1247 nip->ni_flags = htons(0); 1248 1249 memcpy(nip->icmp6_ni_nonce, nonce, 1250 sizeof(nip->icmp6_ni_nonce)); 1251 *(u_int16_t *)nip->icmp6_ni_nonce = ntohs(seq); 1252 1253 memcpy(&outpack[ICMP6_NIQLEN], &dst.sin6_addr, 1254 sizeof(dst.sin6_addr)); 1255 cc = ICMP6_NIQLEN + sizeof(dst.sin6_addr); 1256 datalen = 0; 1257 } else if (options & F_FQDNOLD) { 1258 /* packet format in 03 draft - no Subject data on queries */ 1259 icp->icmp6_type = ICMP6_NI_QUERY; 1260 icp->icmp6_code = 0; /* code field is always 0 */ 1261 nip->ni_qtype = htons(NI_QTYPE_FQDN); 1262 nip->ni_flags = htons(0); 1263 1264 memcpy(nip->icmp6_ni_nonce, nonce, 1265 sizeof(nip->icmp6_ni_nonce)); 1266 *(u_int16_t *)nip->icmp6_ni_nonce = ntohs(seq); 1267 1268 cc = ICMP6_NIQLEN; 1269 datalen = 0; 1270 } else if (options & F_NODEADDR) { 1271 icp->icmp6_type = ICMP6_NI_QUERY; 1272 icp->icmp6_code = ICMP6_NI_SUBJ_IPV6; 1273 nip->ni_qtype = htons(NI_QTYPE_NODEADDR); 1274 nip->ni_flags = naflags; 1275 1276 memcpy(nip->icmp6_ni_nonce, nonce, 1277 sizeof(nip->icmp6_ni_nonce)); 1278 *(u_int16_t *)nip->icmp6_ni_nonce = ntohs(seq); 1279 1280 memcpy(&outpack[ICMP6_NIQLEN], &dst.sin6_addr, 1281 sizeof(dst.sin6_addr)); 1282 cc = ICMP6_NIQLEN + sizeof(dst.sin6_addr); 1283 datalen = 0; 1284 } else if (options & F_SUPTYPES) { 1285 icp->icmp6_type = ICMP6_NI_QUERY; 1286 icp->icmp6_code = ICMP6_NI_SUBJ_FQDN; /*empty*/ 1287 nip->ni_qtype = htons(NI_QTYPE_SUPTYPES); 1288 /* we support compressed bitmap */ 1289 nip->ni_flags = NI_SUPTYPE_FLAG_COMPRESS; 1290 1291 memcpy(nip->icmp6_ni_nonce, nonce, 1292 sizeof(nip->icmp6_ni_nonce)); 1293 *(u_int16_t *)nip->icmp6_ni_nonce = ntohs(seq); 1294 cc = ICMP6_NIQLEN; 1295 datalen = 0; 1296 } else { 1297 icp->icmp6_type = ICMP6_ECHO_REQUEST; 1298 icp->icmp6_code = 0; 1299 icp->icmp6_id = htons(ident); 1300 icp->icmp6_seq = ntohs(seq); 1301 if (timing) { 1302 struct timeval tv; 1303 struct tv32 *tv32; 1304 (void)gettimeofday(&tv, NULL); 1305 tv32 = (struct tv32 *)&outpack[ICMP6ECHOLEN]; 1306 tv32->tv32_sec = htonl(tv.tv_sec); 1307 tv32->tv32_usec = htonl(tv.tv_usec); 1308 } 1309 cc = ICMP6ECHOLEN + datalen; 1310 } 1311 1312 #ifdef DIAGNOSTIC 1313 if (pingerlen() != cc) 1314 errx(1, "internal error; length mismatch"); 1315 #endif 1316 1317 smsghdr.msg_name = (caddr_t)&dst; 1318 smsghdr.msg_namelen = sizeof(dst); 1319 memset(&iov, 0, sizeof(iov)); 1320 iov[0].iov_base = (caddr_t)outpack; 1321 iov[0].iov_len = cc; 1322 smsghdr.msg_iov = iov; 1323 smsghdr.msg_iovlen = 1; 1324 1325 i = sendmsg(s, &smsghdr, 0); 1326 1327 if (i < 0 || i != cc) { 1328 if (i < 0) 1329 warn("sendmsg"); 1330 (void)printf("ping6: wrote %s %d chars, ret=%d\n", 1331 hostname, cc, i); 1332 } 1333 if (!(options & F_QUIET) && options & F_FLOOD) 1334 (void)write(STDOUT_FILENO, &DOT, 1); 1335 1336 return(0); 1337 } 1338 1339 int 1340 myechoreply(icp) 1341 const struct icmp6_hdr *icp; 1342 { 1343 if (ntohs(icp->icmp6_id) == ident) 1344 return 1; 1345 else 1346 return 0; 1347 } 1348 1349 int 1350 mynireply(nip) 1351 const struct icmp6_nodeinfo *nip; 1352 { 1353 if (memcmp(nip->icmp6_ni_nonce + sizeof(u_int16_t), 1354 nonce + sizeof(u_int16_t), 1355 sizeof(nonce) - sizeof(u_int16_t)) == 0) 1356 return 1; 1357 else 1358 return 0; 1359 } 1360 1361 char * 1362 dnsdecode(sp, ep, base, buf, bufsiz) 1363 const u_char **sp; 1364 const u_char *ep; 1365 const u_char *base; /*base for compressed name*/ 1366 char *buf; 1367 size_t bufsiz; 1368 { 1369 int i; 1370 const u_char *cp; 1371 char cresult[MAXDNAME + 1]; 1372 const u_char *comp; 1373 int l; 1374 1375 cp = *sp; 1376 *buf = '\0'; 1377 1378 if (cp >= ep) 1379 return NULL; 1380 while (cp < ep) { 1381 i = *cp; 1382 if (i == 0 || cp != *sp) { 1383 if (strlcat((char *)buf, ".", bufsiz) >= bufsiz) 1384 return NULL; /*result overrun*/ 1385 } 1386 if (i == 0) 1387 break; 1388 cp++; 1389 1390 if ((i & 0xc0) == 0xc0 && cp - base > (i & 0x3f)) { 1391 /* DNS compression */ 1392 if (!base) 1393 return NULL; 1394 1395 comp = base + (i & 0x3f); 1396 if (dnsdecode(&comp, cp, base, cresult, 1397 sizeof(cresult)) == NULL) 1398 return NULL; 1399 if (strlcat(buf, cresult, bufsiz) >= bufsiz) 1400 return NULL; /*result overrun*/ 1401 break; 1402 } else if ((i & 0x3f) == i) { 1403 if (i > ep - cp) 1404 return NULL; /*source overrun*/ 1405 while (i-- > 0 && cp < ep) { 1406 l = snprintf(cresult, sizeof(cresult), 1407 isprint(*cp) ? "%c" : "\\%03o", *cp & 0xff); 1408 if (l >= sizeof(cresult) || l < 0) 1409 return NULL; 1410 if (strlcat(buf, cresult, bufsiz) >= bufsiz) 1411 return NULL; /*result overrun*/ 1412 cp++; 1413 } 1414 } else 1415 return NULL; /*invalid label*/ 1416 } 1417 if (i != 0) 1418 return NULL; /*not terminated*/ 1419 cp++; 1420 *sp = cp; 1421 return buf; 1422 } 1423 1424 /* 1425 * pr_pack -- 1426 * Print out the packet, if it came from us. This logic is necessary 1427 * because ALL readers of the ICMP socket get a copy of ALL ICMP packets 1428 * which arrive ('tis only fair). This permits multiple copies of this 1429 * program to be run without having intermingled output (or statistics!). 1430 */ 1431 void 1432 pr_pack(buf, cc, mhdr) 1433 u_char *buf; 1434 int cc; 1435 struct msghdr *mhdr; 1436 { 1437 #define safeputc(c) printf((isprint((c)) ? "%c" : "\\%03o"), c) 1438 struct icmp6_hdr *icp; 1439 struct icmp6_nodeinfo *ni; 1440 int i; 1441 int hoplim; 1442 struct sockaddr *from; 1443 int fromlen; 1444 u_char *cp = NULL, *dp, *end = buf + cc; 1445 struct in6_pktinfo *pktinfo = NULL; 1446 struct timeval tv, tp; 1447 struct tv32 *tpp; 1448 double triptime = 0; 1449 int dupflag; 1450 size_t off; 1451 int oldfqdn; 1452 u_int16_t seq; 1453 char dnsname[MAXDNAME + 1]; 1454 1455 (void)gettimeofday(&tv, NULL); 1456 1457 if (!mhdr || !mhdr->msg_name || 1458 mhdr->msg_namelen != sizeof(struct sockaddr_in6) || 1459 ((struct sockaddr *)mhdr->msg_name)->sa_family != AF_INET6) { 1460 if (options & F_VERBOSE) 1461 warnx("invalid peername"); 1462 return; 1463 } 1464 from = (struct sockaddr *)mhdr->msg_name; 1465 fromlen = mhdr->msg_namelen; 1466 if (cc < sizeof(struct icmp6_hdr)) { 1467 if (options & F_VERBOSE) 1468 warnx("packet too short (%d bytes) from %s", cc, 1469 pr_addr(from, fromlen)); 1470 return; 1471 } 1472 icp = (struct icmp6_hdr *)buf; 1473 ni = (struct icmp6_nodeinfo *)buf; 1474 off = 0; 1475 1476 if ((hoplim = get_hoplim(mhdr)) == -1) { 1477 warnx("failed to get receiving hop limit"); 1478 return; 1479 } 1480 if ((pktinfo = get_rcvpktinfo(mhdr)) == NULL) { 1481 warnx("failed to get receiving packet information"); 1482 return; 1483 } 1484 1485 if (icp->icmp6_type == ICMP6_ECHO_REPLY && myechoreply(icp)) { 1486 seq = ntohs(icp->icmp6_seq); 1487 ++nreceived; 1488 if (timing) { 1489 tpp = (struct tv32 *)(icp + 1); 1490 tp.tv_sec = ntohl(tpp->tv32_sec); 1491 tp.tv_usec = ntohl(tpp->tv32_usec); 1492 tvsub(&tv, &tp); 1493 triptime = ((double)tv.tv_sec) * 1000.0 + 1494 ((double)tv.tv_usec) / 1000.0; 1495 tsum += triptime; 1496 tsumsq += triptime * triptime; 1497 if (triptime < tmin) 1498 tmin = triptime; 1499 if (triptime > tmax) 1500 tmax = triptime; 1501 } 1502 1503 if (TST(seq % mx_dup_ck)) { 1504 ++nrepeats; 1505 --nreceived; 1506 dupflag = 1; 1507 } else { 1508 SET(seq % mx_dup_ck); 1509 dupflag = 0; 1510 } 1511 1512 if (options & F_QUIET) 1513 return; 1514 1515 if (options & F_FLOOD) 1516 (void)write(STDOUT_FILENO, &BSPACE, 1); 1517 else { 1518 (void)printf("%d bytes from %s, icmp_seq=%u", cc, 1519 pr_addr(from, fromlen), seq); 1520 (void)printf(" hlim=%d", hoplim); 1521 if ((options & F_VERBOSE) != 0) { 1522 struct sockaddr_in6 dstsa; 1523 1524 memset(&dstsa, 0, sizeof(dstsa)); 1525 dstsa.sin6_family = AF_INET6; 1526 #ifdef SIN6_LEN 1527 dstsa.sin6_len = sizeof(dstsa); 1528 #endif 1529 dstsa.sin6_scope_id = pktinfo->ipi6_ifindex; 1530 dstsa.sin6_addr = pktinfo->ipi6_addr; 1531 (void)printf(" dst=%s", 1532 pr_addr((struct sockaddr *)&dstsa, 1533 sizeof(dstsa))); 1534 } 1535 if (timing) 1536 (void)printf(" time=%g ms", triptime); 1537 if (dupflag) 1538 (void)printf("(DUP!)"); 1539 /* check the data */ 1540 cp = buf + off + ICMP6ECHOLEN + ICMP6ECHOTMLEN; 1541 dp = outpack + ICMP6ECHOLEN + ICMP6ECHOTMLEN; 1542 for (i = 8; cp < end; ++i, ++cp, ++dp) { 1543 if (*cp != *dp) { 1544 (void)printf("\nwrong data byte #%d should be 0x%x but was 0x%x", i, *dp, *cp); 1545 break; 1546 } 1547 } 1548 } 1549 } else if (icp->icmp6_type == ICMP6_NI_REPLY && mynireply(ni)) { 1550 seq = ntohs(*(u_int16_t *)ni->icmp6_ni_nonce); 1551 ++nreceived; 1552 if (TST(seq % mx_dup_ck)) { 1553 ++nrepeats; 1554 --nreceived; 1555 dupflag = 1; 1556 } else { 1557 SET(seq % mx_dup_ck); 1558 dupflag = 0; 1559 } 1560 1561 if (options & F_QUIET) 1562 return; 1563 1564 (void)printf("%d bytes from %s: ", cc, pr_addr(from, fromlen)); 1565 1566 switch (ntohs(ni->ni_code)) { 1567 case ICMP6_NI_SUCCESS: 1568 break; 1569 case ICMP6_NI_REFUSED: 1570 printf("refused, type 0x%x", ntohs(ni->ni_type)); 1571 goto fqdnend; 1572 case ICMP6_NI_UNKNOWN: 1573 printf("unknown, type 0x%x", ntohs(ni->ni_type)); 1574 goto fqdnend; 1575 default: 1576 printf("unknown code 0x%x, type 0x%x", 1577 ntohs(ni->ni_code), ntohs(ni->ni_type)); 1578 goto fqdnend; 1579 } 1580 1581 switch (ntohs(ni->ni_qtype)) { 1582 case NI_QTYPE_NOOP: 1583 printf("NodeInfo NOOP"); 1584 break; 1585 case NI_QTYPE_SUPTYPES: 1586 pr_suptypes(ni, end - (u_char *)ni); 1587 break; 1588 case NI_QTYPE_NODEADDR: 1589 pr_nodeaddr(ni, end - (u_char *)ni); 1590 break; 1591 case NI_QTYPE_FQDN: 1592 default: /* XXX: for backward compatibility */ 1593 cp = (u_char *)ni + ICMP6_NIRLEN; 1594 if (buf[off + ICMP6_NIRLEN] == 1595 cc - off - ICMP6_NIRLEN - 1) 1596 oldfqdn = 1; 1597 else 1598 oldfqdn = 0; 1599 if (oldfqdn) { 1600 cp++; /* skip length */ 1601 while (cp < end) { 1602 safeputc(*cp & 0xff); 1603 cp++; 1604 } 1605 } else { 1606 i = 0; 1607 while (cp < end) { 1608 if (dnsdecode((const u_char **)&cp, end, 1609 (const u_char *)(ni + 1), dnsname, 1610 sizeof(dnsname)) == NULL) { 1611 printf("???"); 1612 break; 1613 } 1614 /* 1615 * name-lookup special handling for 1616 * truncated name 1617 */ 1618 if (cp + 1 <= end && !*cp && 1619 strlen(dnsname) > 0) { 1620 dnsname[strlen(dnsname) - 1] = '\0'; 1621 cp++; 1622 } 1623 printf("%s%s", i > 0 ? "," : "", 1624 dnsname); 1625 } 1626 } 1627 if (options & F_VERBOSE) { 1628 int32_t ttl; 1629 int comma = 0; 1630 1631 (void)printf(" ("); /*)*/ 1632 1633 switch (ni->ni_code) { 1634 case ICMP6_NI_REFUSED: 1635 (void)printf("refused"); 1636 comma++; 1637 break; 1638 case ICMP6_NI_UNKNOWN: 1639 (void)printf("unknown qtype"); 1640 comma++; 1641 break; 1642 } 1643 1644 if ((end - (u_char *)ni) < ICMP6_NIRLEN) { 1645 /* case of refusion, unknown */ 1646 /*(*/ 1647 putchar(')'); 1648 goto fqdnend; 1649 } 1650 ttl = (int32_t)ntohl(*(u_long *)&buf[off+ICMP6ECHOLEN+8]); 1651 if (comma) 1652 printf(","); 1653 if (!(ni->ni_flags & NI_FQDN_FLAG_VALIDTTL)) { 1654 (void)printf("TTL=%d:meaningless", 1655 (int)ttl); 1656 } else { 1657 if (ttl < 0) { 1658 (void)printf("TTL=%d:invalid", 1659 ttl); 1660 } else 1661 (void)printf("TTL=%d", ttl); 1662 } 1663 comma++; 1664 1665 if (oldfqdn) { 1666 if (comma) 1667 printf(","); 1668 printf("03 draft"); 1669 comma++; 1670 } else { 1671 cp = (u_char *)ni + ICMP6_NIRLEN; 1672 if (cp == end) { 1673 if (comma) 1674 printf(","); 1675 printf("no name"); 1676 comma++; 1677 } 1678 } 1679 1680 if (buf[off + ICMP6_NIRLEN] != 1681 cc - off - ICMP6_NIRLEN - 1 && oldfqdn) { 1682 if (comma) 1683 printf(","); 1684 (void)printf("invalid namelen:%d/%lu", 1685 buf[off + ICMP6_NIRLEN], 1686 (u_long)cc - off - ICMP6_NIRLEN - 1); 1687 comma++; 1688 } 1689 /*(*/ 1690 putchar(')'); 1691 } 1692 fqdnend: 1693 ; 1694 } 1695 } else { 1696 /* We've got something other than an ECHOREPLY */ 1697 if (!(options & F_VERBOSE)) 1698 return; 1699 (void)printf("%d bytes from %s: ", cc, pr_addr(from, fromlen)); 1700 pr_icmph(icp, end); 1701 } 1702 1703 if (!(options & F_FLOOD)) { 1704 (void)putchar('\n'); 1705 if (options & F_VERBOSE) 1706 pr_exthdrs(mhdr); 1707 (void)fflush(stdout); 1708 } 1709 #undef safeputc 1710 } 1711 1712 void 1713 pr_exthdrs(mhdr) 1714 struct msghdr *mhdr; 1715 { 1716 struct cmsghdr *cm; 1717 1718 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; 1719 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { 1720 if (cm->cmsg_level != IPPROTO_IPV6) 1721 continue; 1722 1723 switch (cm->cmsg_type) { 1724 case IPV6_HOPOPTS: 1725 printf(" HbH Options: "); 1726 pr_ip6opt(CMSG_DATA(cm)); 1727 break; 1728 case IPV6_DSTOPTS: 1729 #ifdef IPV6_RTHDRDSTOPTS 1730 case IPV6_RTHDRDSTOPTS: 1731 #endif 1732 printf(" Dst Options: "); 1733 pr_ip6opt(CMSG_DATA(cm)); 1734 break; 1735 case IPV6_RTHDR: 1736 printf(" Routing: "); 1737 pr_rthdr(CMSG_DATA(cm)); 1738 break; 1739 } 1740 } 1741 } 1742 1743 #ifdef USE_RFC2292BIS 1744 void 1745 pr_ip6opt(void *extbuf) 1746 { 1747 struct ip6_hbh *ext; 1748 int currentlen; 1749 u_int8_t type; 1750 size_t extlen, len; 1751 void *databuf; 1752 size_t offset; 1753 u_int16_t value2; 1754 u_int32_t value4; 1755 1756 ext = (struct ip6_hbh *)extbuf; 1757 extlen = (ext->ip6h_len + 1) * 8; 1758 printf("nxt %u, len %u (%lu bytes)\n", ext->ip6h_nxt, 1759 (unsigned int)ext->ip6h_len, (unsigned long)extlen); 1760 1761 currentlen = 0; 1762 while (1) { 1763 currentlen = inet6_opt_next(extbuf, extlen, currentlen, 1764 &type, &len, &databuf); 1765 if (currentlen == -1) 1766 break; 1767 switch (type) { 1768 /* 1769 * Note that inet6_opt_next automatically skips any padding 1770 * optins. 1771 */ 1772 case IP6OPT_JUMBO: 1773 offset = 0; 1774 offset = inet6_opt_get_val(databuf, offset, 1775 &value4, sizeof(value4)); 1776 printf(" Jumbo Payload Opt: Length %u\n", 1777 (u_int32_t)ntohl(value4)); 1778 break; 1779 case IP6OPT_ROUTER_ALERT: 1780 offset = 0; 1781 offset = inet6_opt_get_val(databuf, offset, 1782 &value2, sizeof(value2)); 1783 printf(" Router Alert Opt: Type %u\n", 1784 ntohs(value2)); 1785 break; 1786 default: 1787 printf(" Received Opt %u len %lu\n", 1788 type, (unsigned long)len); 1789 break; 1790 } 1791 } 1792 return; 1793 } 1794 #else /* !USE_RFC2292BIS */ 1795 /* ARGSUSED */ 1796 void 1797 pr_ip6opt(void *extbuf) 1798 { 1799 putchar('\n'); 1800 return; 1801 } 1802 #endif /* USE_RFC2292BIS */ 1803 1804 #ifdef USE_RFC2292BIS 1805 void 1806 pr_rthdr(void *extbuf) 1807 { 1808 struct in6_addr *in6; 1809 char ntopbuf[INET6_ADDRSTRLEN]; 1810 struct ip6_rthdr *rh = (struct ip6_rthdr *)extbuf; 1811 int i, segments; 1812 1813 /* print fixed part of the header */ 1814 printf("nxt %u, len %u (%d bytes), type %u, ", rh->ip6r_nxt, 1815 rh->ip6r_len, (rh->ip6r_len + 1) << 3, rh->ip6r_type); 1816 if ((segments = inet6_rth_segments(extbuf)) >= 0) 1817 printf("%d segments, ", segments); 1818 else 1819 printf("segments unknown, "); 1820 printf("%d left\n", rh->ip6r_segleft); 1821 1822 for (i = 0; i < segments; i++) { 1823 in6 = inet6_rth_getaddr(extbuf, i); 1824 if (in6 == NULL) 1825 printf(" [%d]<NULL>\n", i); 1826 else { 1827 if (!inet_ntop(AF_INET6, in6, ntopbuf, 1828 sizeof(ntopbuf))) 1829 strlcpy(ntopbuf, "?", sizeof(ntopbuf)); 1830 printf(" [%d]%s\n", i, ntopbuf); 1831 } 1832 } 1833 1834 return; 1835 1836 } 1837 1838 #else /* !USE_RFC2292BIS */ 1839 /* ARGSUSED */ 1840 void 1841 pr_rthdr(void *extbuf) 1842 { 1843 putchar('\n'); 1844 return; 1845 } 1846 #endif /* USE_RFC2292BIS */ 1847 1848 int 1849 pr_bitrange(v, soff, ii) 1850 u_int32_t v; 1851 int soff; 1852 int ii; 1853 { 1854 int off; 1855 int i; 1856 1857 off = 0; 1858 while (off < 32) { 1859 /* shift till we have 0x01 */ 1860 if ((v & 0x01) == 0) { 1861 if (ii > 1) 1862 printf("-%u", soff + off - 1); 1863 ii = 0; 1864 switch (v & 0x0f) { 1865 case 0x00: 1866 v >>= 4; 1867 off += 4; 1868 continue; 1869 case 0x08: 1870 v >>= 3; 1871 off += 3; 1872 continue; 1873 case 0x04: case 0x0c: 1874 v >>= 2; 1875 off += 2; 1876 continue; 1877 default: 1878 v >>= 1; 1879 off += 1; 1880 continue; 1881 } 1882 } 1883 1884 /* we have 0x01 with us */ 1885 for (i = 0; i < 32 - off; i++) { 1886 if ((v & (0x01 << i)) == 0) 1887 break; 1888 } 1889 if (!ii) 1890 printf(" %u", soff + off); 1891 ii += i; 1892 v >>= i; off += i; 1893 } 1894 return ii; 1895 } 1896 1897 void 1898 pr_suptypes(ni, nilen) 1899 struct icmp6_nodeinfo *ni; /* ni->qtype must be SUPTYPES */ 1900 size_t nilen; 1901 { 1902 size_t clen; 1903 u_int32_t v; 1904 const u_char *cp, *end; 1905 u_int16_t cur; 1906 struct cbit { 1907 u_int16_t words; /*32bit count*/ 1908 u_int16_t skip; 1909 } cbit; 1910 #define MAXQTYPES (1 << 16) 1911 size_t off; 1912 int b; 1913 1914 cp = (u_char *)(ni + 1); 1915 end = ((u_char *)ni) + nilen; 1916 cur = 0; 1917 b = 0; 1918 1919 printf("NodeInfo Supported Qtypes"); 1920 if (options & F_VERBOSE) { 1921 if (ni->ni_flags & NI_SUPTYPE_FLAG_COMPRESS) 1922 printf(", compressed bitmap"); 1923 else 1924 printf(", raw bitmap"); 1925 } 1926 1927 while (cp < end) { 1928 clen = (size_t)(end - cp); 1929 if ((ni->ni_flags & NI_SUPTYPE_FLAG_COMPRESS) == 0) { 1930 if (clen == 0 || clen > MAXQTYPES / 8 || 1931 clen % sizeof(v)) { 1932 printf("???"); 1933 return; 1934 } 1935 } else { 1936 if (clen < sizeof(cbit) || clen % sizeof(v)) 1937 return; 1938 memcpy(&cbit, cp, sizeof(cbit)); 1939 if (sizeof(cbit) + ntohs(cbit.words) * sizeof(v) > 1940 clen) 1941 return; 1942 cp += sizeof(cbit); 1943 clen = ntohs(cbit.words) * sizeof(v); 1944 if (cur + clen * 8 + (u_long)ntohs(cbit.skip) * 32 > 1945 MAXQTYPES) 1946 return; 1947 } 1948 1949 for (off = 0; off < clen; off += sizeof(v)) { 1950 memcpy(&v, cp + off, sizeof(v)); 1951 v = (u_int32_t)ntohl(v); 1952 b = pr_bitrange(v, (int)(cur + off * 8), b); 1953 } 1954 /* flush the remaining bits */ 1955 b = pr_bitrange(0, (int)(cur + off * 8), b); 1956 1957 cp += clen; 1958 cur += clen * 8; 1959 if ((ni->ni_flags & NI_SUPTYPE_FLAG_COMPRESS) != 0) 1960 cur += ntohs(cbit.skip) * 32; 1961 } 1962 } 1963 1964 void 1965 pr_nodeaddr(ni, nilen) 1966 struct icmp6_nodeinfo *ni; /* ni->qtype must be NODEADDR */ 1967 int nilen; 1968 { 1969 u_char *cp = (u_char *)(ni + 1); 1970 char ntop_buf[INET6_ADDRSTRLEN]; 1971 int withttl = 0; 1972 1973 nilen -= sizeof(struct icmp6_nodeinfo); 1974 1975 if (options & F_VERBOSE) { 1976 switch (ni->ni_code) { 1977 case ICMP6_NI_REFUSED: 1978 (void)printf("refused"); 1979 break; 1980 case ICMP6_NI_UNKNOWN: 1981 (void)printf("unknown qtype"); 1982 break; 1983 } 1984 if (ni->ni_flags & NI_NODEADDR_FLAG_TRUNCATE) 1985 (void)printf(" truncated"); 1986 } 1987 putchar('\n'); 1988 if (nilen <= 0) 1989 printf(" no address\n"); 1990 1991 /* 1992 * In icmp-name-lookups 05 and later, TTL of each returned address 1993 * is contained in the resposne. We try to detect the version 1994 * by the length of the data, but note that the detection algorithm 1995 * is incomplete. We assume the latest draft by default. 1996 */ 1997 if (nilen % (sizeof(u_int32_t) + sizeof(struct in6_addr)) == 0) 1998 withttl = 1; 1999 while (nilen > 0) { 2000 u_int32_t ttl; 2001 2002 if (withttl) { 2003 /* XXX: alignment? */ 2004 ttl = (u_int32_t)ntohl(*(u_int32_t *)cp); 2005 cp += sizeof(u_int32_t); 2006 nilen -= sizeof(u_int32_t); 2007 } 2008 2009 if (inet_ntop(AF_INET6, cp, ntop_buf, sizeof(ntop_buf)) == 2010 NULL) 2011 strlcpy(ntop_buf, "?", sizeof(ntop_buf)); 2012 printf(" %s", ntop_buf); 2013 if (withttl) { 2014 if (ttl == 0xffffffff) { 2015 /* 2016 * XXX: can this convention be applied to all 2017 * type of TTL (i.e. non-ND TTL)? 2018 */ 2019 printf("(TTL=infty)"); 2020 } 2021 else 2022 printf("(TTL=%u)", ttl); 2023 } 2024 putchar('\n'); 2025 2026 nilen -= sizeof(struct in6_addr); 2027 cp += sizeof(struct in6_addr); 2028 } 2029 } 2030 2031 int 2032 get_hoplim(mhdr) 2033 struct msghdr *mhdr; 2034 { 2035 struct cmsghdr *cm; 2036 2037 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; 2038 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { 2039 if (cm->cmsg_len == 0) 2040 return(-1); 2041 2042 if (cm->cmsg_level == IPPROTO_IPV6 && 2043 cm->cmsg_type == IPV6_HOPLIMIT && 2044 cm->cmsg_len == CMSG_LEN(sizeof(int))) 2045 return(*(int *)CMSG_DATA(cm)); 2046 } 2047 2048 return(-1); 2049 } 2050 2051 struct in6_pktinfo * 2052 get_rcvpktinfo(mhdr) 2053 struct msghdr *mhdr; 2054 { 2055 struct cmsghdr *cm; 2056 2057 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; 2058 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { 2059 if (cm->cmsg_len == 0) 2060 return(NULL); 2061 2062 if (cm->cmsg_level == IPPROTO_IPV6 && 2063 cm->cmsg_type == IPV6_PKTINFO && 2064 cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) 2065 return((struct in6_pktinfo *)CMSG_DATA(cm)); 2066 } 2067 2068 return(NULL); 2069 } 2070 2071 int 2072 get_pathmtu(mhdr) 2073 struct msghdr *mhdr; 2074 { 2075 #ifdef IPV6_RECVPATHMTU 2076 struct cmsghdr *cm; 2077 struct ip6_mtuinfo *mtuctl = NULL; 2078 2079 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; 2080 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { 2081 if (cm->cmsg_len == 0) 2082 return(0); 2083 2084 if (cm->cmsg_level == IPPROTO_IPV6 && 2085 cm->cmsg_type == IPV6_PATHMTU && 2086 cm->cmsg_len == CMSG_LEN(sizeof(struct ip6_mtuinfo))) { 2087 mtuctl = (struct ip6_mtuinfo *)CMSG_DATA(cm); 2088 2089 /* 2090 * If the notified destination is different from 2091 * the one we are pinging, just ignore the info. 2092 * We check the scope ID only when both notified value 2093 * and our own value have non-0 values, because we may 2094 * have used the default scope zone ID for sending, 2095 * in which case the scope ID value is 0. 2096 */ 2097 if (!IN6_ARE_ADDR_EQUAL(&mtuctl->ip6m_addr.sin6_addr, 2098 &dst.sin6_addr) || 2099 (mtuctl->ip6m_addr.sin6_scope_id && 2100 dst.sin6_scope_id && 2101 mtuctl->ip6m_addr.sin6_scope_id != 2102 dst.sin6_scope_id)) { 2103 if ((options & F_VERBOSE) != 0) { 2104 printf("path MTU for %s is notified. " 2105 "(ignored)\n", 2106 pr_addr((struct sockaddr *)&mtuctl->ip6m_addr, 2107 sizeof(mtuctl->ip6m_addr))); 2108 } 2109 return(0); 2110 } 2111 2112 /* 2113 * Ignore an invalid MTU. XXX: can we just believe 2114 * the kernel check? 2115 */ 2116 if (mtuctl->ip6m_mtu < IPV6_MMTU) 2117 return(0); 2118 2119 /* notification for our destination. return the MTU. */ 2120 return((int)mtuctl->ip6m_mtu); 2121 } 2122 } 2123 #endif 2124 return(0); 2125 } 2126 2127 /* 2128 * tvsub -- 2129 * Subtract 2 timeval structs: out = out - in. Out is assumed to 2130 * be >= in. 2131 */ 2132 void 2133 tvsub(out, in) 2134 struct timeval *out, *in; 2135 { 2136 if ((out->tv_usec -= in->tv_usec) < 0) { 2137 --out->tv_sec; 2138 out->tv_usec += 1000000; 2139 } 2140 out->tv_sec -= in->tv_sec; 2141 } 2142 2143 /* 2144 * onint -- 2145 * SIGINT handler. 2146 */ 2147 /* ARGSUSED */ 2148 void 2149 onint(notused) 2150 int notused; 2151 { 2152 summary(); 2153 2154 (void)signal(SIGINT, SIG_DFL); 2155 (void)kill(getpid(), SIGINT); 2156 2157 /* NOTREACHED */ 2158 exit(1); 2159 } 2160 2161 /* 2162 * summary -- 2163 * Print out statistics. 2164 */ 2165 void 2166 summary() 2167 { 2168 2169 (void)printf("\n--- %s ping6 statistics ---\n", hostname); 2170 (void)printf("%ld packets transmitted, ", ntransmitted); 2171 (void)printf("%ld packets received, ", nreceived); 2172 if (nrepeats) 2173 (void)printf("+%ld duplicates, ", nrepeats); 2174 if (ntransmitted) { 2175 if (nreceived > ntransmitted) 2176 (void)printf("-- somebody's duplicating packets!"); 2177 else 2178 (void)printf("%.1f%% packet loss", 2179 ((((double)ntransmitted - nreceived) * 100.0) / 2180 ntransmitted)); 2181 } 2182 (void)putchar('\n'); 2183 if (nreceived && timing) { 2184 /* Only display average to microseconds */ 2185 double num = nreceived + nrepeats; 2186 double avg = tsum / num; 2187 double dev = sqrt(tsumsq / num - avg * avg); 2188 (void)printf( 2189 "round-trip min/avg/max/std-dev = %.3f/%.3f/%.3f/%.3f ms\n", 2190 tmin, avg, tmax, dev); 2191 (void)fflush(stdout); 2192 } 2193 (void)fflush(stdout); 2194 } 2195 2196 /*subject type*/ 2197 static const char *niqcode[] = { 2198 "IPv6 address", 2199 "DNS label", /*or empty*/ 2200 "IPv4 address", 2201 }; 2202 2203 /*result code*/ 2204 static const char *nircode[] = { 2205 "Success", "Refused", "Unknown", 2206 }; 2207 2208 2209 /* 2210 * pr_icmph -- 2211 * Print a descriptive string about an ICMP header. 2212 */ 2213 void 2214 pr_icmph(icp, end) 2215 struct icmp6_hdr *icp; 2216 u_char *end; 2217 { 2218 char ntop_buf[INET6_ADDRSTRLEN]; 2219 struct nd_redirect *red; 2220 struct icmp6_nodeinfo *ni; 2221 char dnsname[MAXDNAME + 1]; 2222 const u_char *cp; 2223 size_t l; 2224 2225 switch (icp->icmp6_type) { 2226 case ICMP6_DST_UNREACH: 2227 switch (icp->icmp6_code) { 2228 case ICMP6_DST_UNREACH_NOROUTE: 2229 (void)printf("No Route to Destination\n"); 2230 break; 2231 case ICMP6_DST_UNREACH_ADMIN: 2232 (void)printf("Destination Administratively " 2233 "Unreachable\n"); 2234 break; 2235 case ICMP6_DST_UNREACH_BEYONDSCOPE: 2236 (void)printf("Destination Unreachable Beyond Scope\n"); 2237 break; 2238 case ICMP6_DST_UNREACH_ADDR: 2239 (void)printf("Destination Host Unreachable\n"); 2240 break; 2241 case ICMP6_DST_UNREACH_NOPORT: 2242 (void)printf("Destination Port Unreachable\n"); 2243 break; 2244 default: 2245 (void)printf("Destination Unreachable, Bad Code: %d\n", 2246 icp->icmp6_code); 2247 break; 2248 } 2249 /* Print returned IP header information */ 2250 pr_retip((struct ip6_hdr *)(icp + 1), end); 2251 break; 2252 case ICMP6_PACKET_TOO_BIG: 2253 (void)printf("Packet too big mtu = %d\n", 2254 (int)ntohl(icp->icmp6_mtu)); 2255 pr_retip((struct ip6_hdr *)(icp + 1), end); 2256 break; 2257 case ICMP6_TIME_EXCEEDED: 2258 switch (icp->icmp6_code) { 2259 case ICMP6_TIME_EXCEED_TRANSIT: 2260 (void)printf("Time to live exceeded\n"); 2261 break; 2262 case ICMP6_TIME_EXCEED_REASSEMBLY: 2263 (void)printf("Frag reassembly time exceeded\n"); 2264 break; 2265 default: 2266 (void)printf("Time exceeded, Bad Code: %d\n", 2267 icp->icmp6_code); 2268 break; 2269 } 2270 pr_retip((struct ip6_hdr *)(icp + 1), end); 2271 break; 2272 case ICMP6_PARAM_PROB: 2273 (void)printf("Parameter problem: "); 2274 switch (icp->icmp6_code) { 2275 case ICMP6_PARAMPROB_HEADER: 2276 (void)printf("Erroneous Header "); 2277 break; 2278 case ICMP6_PARAMPROB_NEXTHEADER: 2279 (void)printf("Unknown Nextheader "); 2280 break; 2281 case ICMP6_PARAMPROB_OPTION: 2282 (void)printf("Unrecognized Option "); 2283 break; 2284 default: 2285 (void)printf("Bad code(%d) ", icp->icmp6_code); 2286 break; 2287 } 2288 (void)printf("pointer = 0x%02x\n", 2289 (u_int32_t)ntohl(icp->icmp6_pptr)); 2290 pr_retip((struct ip6_hdr *)(icp + 1), end); 2291 break; 2292 case ICMP6_ECHO_REQUEST: 2293 (void)printf("Echo Request"); 2294 /* XXX ID + Seq + Data */ 2295 break; 2296 case ICMP6_ECHO_REPLY: 2297 (void)printf("Echo Reply"); 2298 /* XXX ID + Seq + Data */ 2299 break; 2300 case ICMP6_MEMBERSHIP_QUERY: 2301 (void)printf("Listener Query"); 2302 break; 2303 case ICMP6_MEMBERSHIP_REPORT: 2304 (void)printf("Listener Report"); 2305 break; 2306 case ICMP6_MEMBERSHIP_REDUCTION: 2307 (void)printf("Listener Done"); 2308 break; 2309 case ND_ROUTER_SOLICIT: 2310 (void)printf("Router Solicitation"); 2311 break; 2312 case ND_ROUTER_ADVERT: 2313 (void)printf("Router Advertisement"); 2314 break; 2315 case ND_NEIGHBOR_SOLICIT: 2316 (void)printf("Neighbor Solicitation"); 2317 break; 2318 case ND_NEIGHBOR_ADVERT: 2319 (void)printf("Neighbor Advertisement"); 2320 break; 2321 case ND_REDIRECT: 2322 red = (struct nd_redirect *)icp; 2323 (void)printf("Redirect\n"); 2324 if (!inet_ntop(AF_INET6, &red->nd_rd_dst, ntop_buf, 2325 sizeof(ntop_buf))) 2326 strlcpy(ntop_buf, "?", sizeof(ntop_buf)); 2327 (void)printf("Destination: %s", ntop_buf); 2328 if (!inet_ntop(AF_INET6, &red->nd_rd_target, ntop_buf, 2329 sizeof(ntop_buf))) 2330 strlcpy(ntop_buf, "?", sizeof(ntop_buf)); 2331 (void)printf(" New Target: %s", ntop_buf); 2332 break; 2333 case ICMP6_NI_QUERY: 2334 (void)printf("Node Information Query"); 2335 /* XXX ID + Seq + Data */ 2336 ni = (struct icmp6_nodeinfo *)icp; 2337 l = end - (u_char *)(ni + 1); 2338 printf(", "); 2339 switch (ntohs(ni->ni_qtype)) { 2340 case NI_QTYPE_NOOP: 2341 (void)printf("NOOP"); 2342 break; 2343 case NI_QTYPE_SUPTYPES: 2344 (void)printf("Supported qtypes"); 2345 break; 2346 case NI_QTYPE_FQDN: 2347 (void)printf("DNS name"); 2348 break; 2349 case NI_QTYPE_NODEADDR: 2350 (void)printf("nodeaddr"); 2351 break; 2352 case NI_QTYPE_IPV4ADDR: 2353 (void)printf("IPv4 nodeaddr"); 2354 break; 2355 default: 2356 (void)printf("unknown qtype"); 2357 break; 2358 } 2359 if (options & F_VERBOSE) { 2360 switch (ni->ni_code) { 2361 case ICMP6_NI_SUBJ_IPV6: 2362 if (l == sizeof(struct in6_addr) && 2363 inet_ntop(AF_INET6, ni + 1, ntop_buf, 2364 sizeof(ntop_buf)) != NULL) { 2365 (void)printf(", subject=%s(%s)", 2366 niqcode[ni->ni_code], ntop_buf); 2367 } else { 2368 #if 1 2369 /* backward compat to -W */ 2370 (void)printf(", oldfqdn"); 2371 #else 2372 (void)printf(", invalid"); 2373 #endif 2374 } 2375 break; 2376 case ICMP6_NI_SUBJ_FQDN: 2377 if (end == (u_char *)(ni + 1)) { 2378 (void)printf(", no subject"); 2379 break; 2380 } 2381 printf(", subject=%s", niqcode[ni->ni_code]); 2382 cp = (const u_char *)(ni + 1); 2383 if (dnsdecode(&cp, end, NULL, dnsname, 2384 sizeof(dnsname)) != NULL) 2385 printf("(%s)", dnsname); 2386 else 2387 printf("(invalid)"); 2388 break; 2389 case ICMP6_NI_SUBJ_IPV4: 2390 if (l == sizeof(struct in_addr) && 2391 inet_ntop(AF_INET, ni + 1, ntop_buf, 2392 sizeof(ntop_buf)) != NULL) { 2393 (void)printf(", subject=%s(%s)", 2394 niqcode[ni->ni_code], ntop_buf); 2395 } else 2396 (void)printf(", invalid"); 2397 break; 2398 default: 2399 (void)printf(", invalid"); 2400 break; 2401 } 2402 } 2403 break; 2404 case ICMP6_NI_REPLY: 2405 (void)printf("Node Information Reply"); 2406 /* XXX ID + Seq + Data */ 2407 ni = (struct icmp6_nodeinfo *)icp; 2408 printf(", "); 2409 switch (ntohs(ni->ni_qtype)) { 2410 case NI_QTYPE_NOOP: 2411 (void)printf("NOOP"); 2412 break; 2413 case NI_QTYPE_SUPTYPES: 2414 (void)printf("Supported qtypes"); 2415 break; 2416 case NI_QTYPE_FQDN: 2417 (void)printf("DNS name"); 2418 break; 2419 case NI_QTYPE_NODEADDR: 2420 (void)printf("nodeaddr"); 2421 break; 2422 case NI_QTYPE_IPV4ADDR: 2423 (void)printf("IPv4 nodeaddr"); 2424 break; 2425 default: 2426 (void)printf("unknown qtype"); 2427 break; 2428 } 2429 if (options & F_VERBOSE) { 2430 if (ni->ni_code > sizeof(nircode) / sizeof(nircode[0])) 2431 printf(", invalid"); 2432 else 2433 printf(", %s", nircode[ni->ni_code]); 2434 } 2435 break; 2436 default: 2437 (void)printf("Bad ICMP type: %d", icp->icmp6_type); 2438 } 2439 } 2440 2441 /* 2442 * pr_iph -- 2443 * Print an IP6 header. 2444 */ 2445 void 2446 pr_iph(ip6) 2447 struct ip6_hdr *ip6; 2448 { 2449 u_int32_t flow = ip6->ip6_flow & IPV6_FLOWLABEL_MASK; 2450 u_int8_t tc; 2451 char ntop_buf[INET6_ADDRSTRLEN]; 2452 2453 tc = *(&ip6->ip6_vfc + 1); /* XXX */ 2454 tc = (tc >> 4) & 0x0f; 2455 tc |= (ip6->ip6_vfc << 4); 2456 2457 printf("Vr TC Flow Plen Nxt Hlim\n"); 2458 printf(" %1x %02x %05x %04x %02x %02x\n", 2459 (ip6->ip6_vfc & IPV6_VERSION_MASK) >> 4, tc, (u_int32_t)ntohl(flow), 2460 ntohs(ip6->ip6_plen), ip6->ip6_nxt, ip6->ip6_hlim); 2461 if (!inet_ntop(AF_INET6, &ip6->ip6_src, ntop_buf, sizeof(ntop_buf))) 2462 strlcpy(ntop_buf, "?", sizeof(ntop_buf)); 2463 printf("%s->", ntop_buf); 2464 if (!inet_ntop(AF_INET6, &ip6->ip6_dst, ntop_buf, sizeof(ntop_buf))) 2465 strlcpy(ntop_buf, "?", sizeof(ntop_buf)); 2466 printf("%s\n", ntop_buf); 2467 } 2468 2469 /* 2470 * pr_addr -- 2471 * Return an ascii host address as a dotted quad and optionally with 2472 * a hostname. 2473 */ 2474 const char * 2475 pr_addr(addr, addrlen) 2476 struct sockaddr *addr; 2477 int addrlen; 2478 { 2479 static char buf[NI_MAXHOST]; 2480 int flag = 0; 2481 2482 if ((options & F_HOSTNAME) == 0) 2483 flag |= NI_NUMERICHOST; 2484 2485 if (getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0, flag) == 0) 2486 return (buf); 2487 else 2488 return "?"; 2489 } 2490 2491 /* 2492 * pr_retip -- 2493 * Dump some info on a returned (via ICMPv6) IPv6 packet. 2494 */ 2495 void 2496 pr_retip(ip6, end) 2497 struct ip6_hdr *ip6; 2498 u_char *end; 2499 { 2500 u_char *cp = (u_char *)ip6, nh; 2501 int hlen; 2502 2503 if (end - (u_char *)ip6 < sizeof(*ip6)) { 2504 printf("IP6"); 2505 goto trunc; 2506 } 2507 pr_iph(ip6); 2508 hlen = sizeof(*ip6); 2509 2510 nh = ip6->ip6_nxt; 2511 cp += hlen; 2512 while (end - cp >= 8) { 2513 switch (nh) { 2514 case IPPROTO_HOPOPTS: 2515 printf("HBH "); 2516 hlen = (((struct ip6_hbh *)cp)->ip6h_len+1) << 3; 2517 nh = ((struct ip6_hbh *)cp)->ip6h_nxt; 2518 break; 2519 case IPPROTO_DSTOPTS: 2520 printf("DSTOPT "); 2521 hlen = (((struct ip6_dest *)cp)->ip6d_len+1) << 3; 2522 nh = ((struct ip6_dest *)cp)->ip6d_nxt; 2523 break; 2524 case IPPROTO_FRAGMENT: 2525 printf("FRAG "); 2526 hlen = sizeof(struct ip6_frag); 2527 nh = ((struct ip6_frag *)cp)->ip6f_nxt; 2528 break; 2529 case IPPROTO_ROUTING: 2530 printf("RTHDR "); 2531 hlen = (((struct ip6_rthdr *)cp)->ip6r_len+1) << 3; 2532 nh = ((struct ip6_rthdr *)cp)->ip6r_nxt; 2533 break; 2534 #ifdef IPSEC 2535 case IPPROTO_AH: 2536 printf("AH "); 2537 hlen = (((struct ah *)cp)->ah_len+2) << 2; 2538 nh = ((struct ah *)cp)->ah_nxt; 2539 break; 2540 #endif 2541 case IPPROTO_ICMPV6: 2542 printf("ICMP6: type = %d, code = %d\n", 2543 *cp, *(cp + 1)); 2544 return; 2545 case IPPROTO_ESP: 2546 printf("ESP\n"); 2547 return; 2548 case IPPROTO_TCP: 2549 printf("TCP: from port %u, to port %u (decimal)\n", 2550 (*cp * 256 + *(cp + 1)), 2551 (*(cp + 2) * 256 + *(cp + 3))); 2552 return; 2553 case IPPROTO_UDP: 2554 printf("UDP: from port %u, to port %u (decimal)\n", 2555 (*cp * 256 + *(cp + 1)), 2556 (*(cp + 2) * 256 + *(cp + 3))); 2557 return; 2558 default: 2559 printf("Unknown Header(%d)\n", nh); 2560 return; 2561 } 2562 2563 if ((cp += hlen) >= end) 2564 goto trunc; 2565 } 2566 if (end - cp < 8) 2567 goto trunc; 2568 2569 putchar('\n'); 2570 return; 2571 2572 trunc: 2573 printf("...\n"); 2574 return; 2575 } 2576 2577 void 2578 fill(bp, patp) 2579 char *bp, *patp; 2580 { 2581 int ii, jj, kk; 2582 int pat[16]; 2583 char *cp; 2584 2585 for (cp = patp; *cp; cp++) 2586 if (!isxdigit(*cp)) 2587 errx(1, "patterns must be specified as hex digits"); 2588 ii = sscanf(patp, 2589 "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x", 2590 &pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6], 2591 &pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12], 2592 &pat[13], &pat[14], &pat[15]); 2593 2594 /* xxx */ 2595 if (ii > 0) 2596 for (kk = 0; 2597 kk <= MAXDATALEN - (8 + sizeof(struct tv32) + ii); 2598 kk += ii) 2599 for (jj = 0; jj < ii; ++jj) 2600 bp[jj + kk] = pat[jj]; 2601 if (!(options & F_QUIET)) { 2602 (void)printf("PATTERN: 0x"); 2603 for (jj = 0; jj < ii; ++jj) 2604 (void)printf("%02x", bp[jj] & 0xFF); 2605 (void)printf("\n"); 2606 } 2607 } 2608 2609 #ifdef IPSEC 2610 #ifdef IPSEC_POLICY_IPSEC 2611 int 2612 setpolicy(so, policy) 2613 int so; 2614 char *policy; 2615 { 2616 char *buf; 2617 2618 if (policy == NULL) 2619 return 0; /* ignore */ 2620 2621 buf = ipsec_set_policy(policy, strlen(policy)); 2622 if (buf == NULL) 2623 errx(1, "%s", ipsec_strerror()); 2624 if (setsockopt(s, IPPROTO_IPV6, IPV6_IPSEC_POLICY, buf, 2625 ipsec_get_policylen(buf)) < 0) 2626 warnx("Unable to set IPsec policy"); 2627 free(buf); 2628 2629 return 0; 2630 } 2631 #endif 2632 #endif 2633 2634 char * 2635 nigroup(name) 2636 char *name; 2637 { 2638 char *p; 2639 char *q; 2640 MD5_CTX ctxt; 2641 u_int8_t digest[16]; 2642 u_int8_t c; 2643 size_t l; 2644 char hbuf[NI_MAXHOST]; 2645 struct in6_addr in6; 2646 2647 p = strchr(name, '.'); 2648 if (!p) 2649 p = name + strlen(name); 2650 l = p - name; 2651 if (l > 63 || l > sizeof(hbuf) - 1) 2652 return NULL; /*label too long*/ 2653 strncpy(hbuf, name, l); 2654 hbuf[(int)l] = '\0'; 2655 2656 for (q = name; *q; q++) { 2657 if (isupper(*(unsigned char *)q)) 2658 *q = tolower(*(unsigned char *)q); 2659 } 2660 2661 /* generate 8 bytes of pseudo-random value. */ 2662 memset(&ctxt, 0, sizeof(ctxt)); 2663 MD5Init(&ctxt); 2664 c = l & 0xff; 2665 MD5Update(&ctxt, &c, sizeof(c)); 2666 MD5Update(&ctxt, (unsigned char *)name, l); 2667 MD5Final(digest, &ctxt); 2668 2669 if (inet_pton(AF_INET6, "ff02::2:0000:0000", &in6) != 1) 2670 return NULL; /*XXX*/ 2671 bcopy(digest, &in6.s6_addr[12], 4); 2672 2673 if (inet_ntop(AF_INET6, &in6, hbuf, sizeof(hbuf)) == NULL) 2674 return NULL; 2675 2676 return strdup(hbuf); 2677 } 2678 2679 void 2680 usage() 2681 { 2682 (void)fprintf(stderr, 2683 "usage: ping6 [-dfH" 2684 #ifdef IPV6_USE_MIN_MTU 2685 "m" 2686 #endif 2687 "nNqtvwW" 2688 #ifdef IPV6_REACHCONF 2689 "R" 2690 #endif 2691 #ifdef IPSEC 2692 #ifdef IPSEC_POLICY_IPSEC 2693 "] [-P policy" 2694 #else 2695 "AE" 2696 #endif 2697 #endif 2698 "] [-a [aAclsg]] [-b sockbufsiz] [-c count] \n" 2699 "\t[-I interface] [-i wait] [-l preload] [-p pattern] " 2700 "[-S sourceaddr]\n" 2701 "\t[-s packetsize] [-h hoplimit] [-g gateway] [hops...] host\n"); 2702 exit(1); 2703 } 2704