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