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