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