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