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