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