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