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