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