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