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