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