1 /* $KAME: ping6.c,v 1.169 2003/07/25 06:01:47 itojun Exp $ */
4 * SPDX-License-Identifier: BSD-3-Clause
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 /* BSDI ping.c,v 2.3 1996/01/21 17:56:50 jch Exp */
37 * Copyright (c) 1989, 1993
38 * The Regents of the University of California. All rights reserved.
40 * This code is derived from software contributed to Berkeley by
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution.
51 * 3. Neither the name of the University nor the names of its contributors
52 * may be used to endorse or promote products derived from this software
53 * without specific prior written permission.
55 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
56 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
57 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
58 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
59 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
60 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
61 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
62 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
63 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
64 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
70 static const char copyright[] =
71 "@(#) Copyright (c) 1989, 1993\n\
72 The Regents of the University of California. All rights reserved.\n";
76 static char sccsid[] = "@(#)ping.c 8.1 (Berkeley) 6/5/93";
80 #include <sys/cdefs.h>
81 __FBSDID("$FreeBSD$");
84 * Using the InterNet Control Message Protocol (ICMP) "ECHO" facility,
85 * measure round-trip-delays and packet loss across network paths.
89 * U. S. Army Ballistic Research Laboratory
93 * Public Domain. Distribution Unlimited.
95 * More statistics could always be gathered.
96 * This program has to run SUID to ROOT to access the ICMP socket.
100 * USE_SIN6_SCOPE_ID assumes that sin6_scope_id has the same semantics
101 * as IPV6_PKTINFO. Some people object it (sin6_scope_id specifies *link*
102 * while IPV6_PKTINFO specifies *interface*. Link is defined as collection of
103 * network attached to 1 or more interfaces)
106 #include <sys/param.h>
107 #include <sys/capsicum.h>
109 #include <sys/socket.h>
112 #include <net/route.h>
114 #include <netinet/in.h>
115 #include <netinet/ip6.h>
116 #include <netinet/icmp6.h>
117 #include <arpa/inet.h>
118 #include <arpa/nameser.h>
121 #include <capsicum_helpers.h>
122 #include <casper/cap_dns.h>
123 #include <libcasper.h>
134 #include <sysexits.h>
139 #include <netipsec/ah.h>
140 #include <netipsec/ipsec.h>
150 #define MAXPACKETLEN 131072
152 #define ICMP6ECHOLEN 8 /* icmp echo header len excluding time */
153 #define ICMP6ECHOTMLEN sizeof(struct tv32)
154 #define ICMP6_NIQLEN (ICMP6ECHOLEN + 8)
155 # define CONTROLLEN 10240 /* ancillary data buffer size RFC3542 20.1 */
156 /* FQDN case, 64 bits of nonce + 32 bits ttl */
157 #define ICMP6_NIRLEN (ICMP6ECHOLEN + 12)
158 #define EXTRA 256 /* for AH and various other headers. weird. */
159 #define DEFDATALEN ICMP6ECHOTMLEN
160 #define MAXDATALEN MAXPACKETLEN - IP6LEN - ICMP6ECHOLEN
161 #define NROUTES 9 /* number of record route slots */
162 #define MAXWAIT 10000 /* max ms to wait for response */
163 #define MAXALARM (60 * 60) /* max seconds for alarm timeout */
165 #define A(bit) rcvd_tbl[(bit)>>3] /* identify byte in array */
166 #define B(bit) (1 << ((bit) & 0x07)) /* identify bit in byte */
167 #define SET(bit) (A(bit) |= B(bit))
168 #define CLR(bit) (A(bit) &= (~B(bit)))
169 #define TST(bit) (A(bit) & B(bit))
171 #define F_FLOOD 0x0001
172 #define F_INTERVAL 0x0002
173 #define F_PINGFILLED 0x0008
174 #define F_QUIET 0x0010
175 #define F_RROUTE 0x0020
176 #define F_SO_DEBUG 0x0040
177 #define F_VERBOSE 0x0100
179 #ifdef IPSEC_POLICY_IPSEC
180 #define F_POLICY 0x0400
182 #define F_AUTHHDR 0x0200
183 #define F_ENCRYPT 0x0400
184 #endif /*IPSEC_POLICY_IPSEC*/
186 #define F_NODEADDR 0x0800
187 #define F_FQDN 0x1000
188 #define F_INTERFACE 0x2000
189 #define F_SRCADDR 0x4000
190 #define F_HOSTNAME 0x10000
191 #define F_FQDNOLD 0x20000
192 #define F_NIGROUP 0x40000
193 #define F_SUPTYPES 0x80000
194 #define F_NOMINMTU 0x100000
195 #define F_ONCE 0x200000
196 #define F_AUDIBLE 0x400000
197 #define F_MISSED 0x800000
198 #define F_DONTFRAG 0x1000000
199 #define F_NOUSERDATA (F_NODEADDR | F_FQDN | F_FQDNOLD | F_SUPTYPES)
200 #define F_WAITTIME 0x2000000
201 static u_int options;
203 #define IN6LEN sizeof(struct in6_addr)
204 #define SA6LEN sizeof(struct sockaddr_in6)
205 #define DUMMY_PORT 10101
207 #define SIN6(s) ((struct sockaddr_in6 *)(s))
210 * MAX_DUP_CHK is the number of bits in received table, i.e. the maximum
211 * number of received sequence numbers we can keep track of. Change 128
212 * to 8192 for complete accuracy...
214 #define MAX_DUP_CHK (8 * 8192)
215 static int mx_dup_ck = MAX_DUP_CHK;
216 static char rcvd_tbl[MAX_DUP_CHK / 8];
218 static struct sockaddr_in6 dst; /* who to ping6 */
219 static struct sockaddr_in6 src; /* src addr of this packet */
220 static socklen_t srclen;
221 static size_t datalen = DEFDATALEN;
222 static int ssend; /* send socket file descriptor */
223 static int srecv; /* receive socket file descriptor */
224 static u_char outpack[MAXPACKETLEN];
225 static char BSPACE = '\b'; /* characters written for flood */
226 static char BBELL = '\a'; /* characters written for AUDIBLE */
227 static char DOT = '.';
228 static char *hostname;
229 static int ident; /* process id to identify our packets */
230 static u_int8_t nonce[8]; /* nonce field for node information */
231 static int hoplimit = -1; /* hoplimit */
232 static int tclass = -1; /* traffic class */
233 static u_char *packet = NULL;
234 static cap_channel_t *capdns;
237 static long nmissedmax; /* max value of ntransmitted - nreceived - 1 */
238 static long npackets; /* max packets to transmit */
239 static long nreceived; /* # of packets we got back */
240 static long nrepeats; /* number of duplicates */
241 static long ntransmitted; /* sequence # for outbound packets = #sent */
242 static long ntransmitfailures; /* number of transmit failures */
243 static int interval = 1000; /* interval between packets in ms */
244 static int waittime = MAXWAIT; /* timeout for each packet */
245 static long nrcvtimeout = 0; /* # of packets we got back after waittime */
248 static int timing; /* flag to do timing */
249 static double tmin = 999999999.0; /* minimum round trip time */
250 static double tmax = 0.0; /* maximum round trip time */
251 static double tsum = 0.0; /* sum of all times, for doing average */
252 static double tsumsq = 0.0; /* sum of all times squared, for std. dev. */
254 /* for node addresses */
255 static u_short naflags;
257 /* for ancillary data(advanced API) */
258 static struct msghdr smsghdr;
259 static struct iovec smsgiov;
260 static char *scmsg = 0;
262 static volatile sig_atomic_t seenint;
264 static volatile sig_atomic_t seeninfo;
267 int main(int, char *[]);
268 static cap_channel_t *capdns_setup(void);
269 static void fill(char *, char *);
270 static int get_hoplim(struct msghdr *);
271 static int get_pathmtu(struct msghdr *);
272 static struct in6_pktinfo *get_rcvpktinfo(struct msghdr *);
273 static void onsignal(int);
274 static void onint(int);
275 static size_t pingerlen(void);
276 static int pinger(void);
277 static const char *pr_addr(struct sockaddr *, int);
278 static void pr_icmph(struct icmp6_hdr *, u_char *);
279 static void pr_iph(struct ip6_hdr *);
280 static void pr_suptypes(struct icmp6_nodeinfo *, size_t);
281 static void pr_nodeaddr(struct icmp6_nodeinfo *, int);
282 static int myechoreply(const struct icmp6_hdr *);
283 static int mynireply(const struct icmp6_nodeinfo *);
284 static const char *dnsdecode(const u_char *, const u_char *, const u_char *,
286 static void pr_pack(u_char *, int, struct msghdr *);
287 static void pr_exthdrs(struct msghdr *);
288 static void pr_ip6opt(void *, size_t);
289 static void pr_rthdr(void *, size_t);
290 static int pr_bitrange(u_int32_t, int, int);
291 static void pr_retip(struct ip6_hdr *, u_char *);
292 static void summary(void);
293 static int setpolicy(int, char *);
294 static char *nigroup(char *, int);
295 static void usage(void);
298 main(int argc, char *argv[])
300 struct timespec last, intvl;
301 struct sockaddr_in6 from, *sin6;
302 struct addrinfo hints, *res;
303 struct sigaction si_sa;
305 int almost_done, ch, hold, packlen, preload, optval, error;
306 int nig_oldmcprefix = -1;
308 char *e, *target, *ifname = NULL, *gateway = NULL;
310 struct cmsghdr *scmsgp = NULL;
311 /* For control (ancillary) data received from recvmsg() */
312 u_char cm[CONTROLLEN];
313 #if defined(SO_SNDBUF) && defined(SO_RCVBUF)
318 struct in6_pktinfo pktinfo;
319 char *cmsg_pktinfo = NULL;
320 struct ip6_rthdr *rthdr = NULL;
321 #ifdef IPSEC_POLICY_IPSEC
322 char *policy_in = NULL;
323 char *policy_out = NULL;
328 #ifdef IPV6_USE_MIN_MTU
331 cap_rights_t rights_srecv;
332 cap_rights_t rights_ssend;
333 cap_rights_t rights_stdin;
335 /* just to be sure */
336 memset(&smsghdr, 0, sizeof(smsghdr));
337 memset(&smsgiov, 0, sizeof(smsgiov));
338 memset(&pktinfo, 0, sizeof(pktinfo));
340 intvl.tv_sec = interval / 1000;
341 intvl.tv_nsec = interval % 1000 * 1000000;
343 alarmtimeout = preload = 0;
344 datap = &outpack[ICMP6ECHOLEN + ICMP6ECHOTMLEN];
345 capdns = capdns_setup();
349 #ifdef IPSEC_POLICY_IPSEC
353 #endif /*IPSEC_POLICY_IPSEC*/
355 while ((ch = getopt(argc, argv,
356 "k:b:c:DdfHe:m:I:i:l:unNop:qaAS:s:OvyYW:t:z:" ADDOPTS)) != -1) {
363 options &= ~F_NOUSERDATA;
364 options |= F_NODEADDR;
365 for (cp = optarg; *cp != '\0'; cp++) {
368 naflags |= NI_NODEADDR_FLAG_ALL;
372 naflags |= NI_NODEADDR_FLAG_COMPAT;
376 naflags |= NI_NODEADDR_FLAG_LINKLOCAL;
380 naflags |= NI_NODEADDR_FLAG_SITELOCAL;
384 naflags |= NI_NODEADDR_FLAG_GLOBAL;
386 case 'A': /* experimental. not in the spec */
387 #ifdef NI_NODEADDR_FLAG_ANYCAST
388 naflags |= NI_NODEADDR_FLAG_ANYCAST;
392 "-a A is not supported on the platform");
403 #if defined(SO_SNDBUF) && defined(SO_RCVBUF)
406 lsockbufsize = strtoul(optarg, &e, 10);
407 sockbufsize = (int)lsockbufsize;
408 if (errno || !*optarg || *e ||
409 lsockbufsize > INT_MAX)
410 errx(1, "invalid socket buffer size");
413 "-b option ignored: SO_SNDBUF/SO_RCVBUF socket options not supported");
417 npackets = strtol(optarg, &e, 10);
418 if (npackets <= 0 || *optarg == '\0' || *e != '\0')
420 "illegal number of packets -- %s", optarg);
423 options |= F_DONTFRAG;
426 options |= F_SO_DEBUG;
431 errx(1, "Must be superuser to flood ping");
434 setbuf(stdout, (char *)NULL);
440 options |= F_HOSTNAME;
442 case 'm': /* hoplimit */
443 hoplimit = strtol(optarg, &e, 10);
444 if (*optarg == '\0' || *e != '\0')
445 errx(1, "illegal hoplimit %s", optarg);
446 if (255 < hoplimit || hoplimit < -1)
448 "illegal hoplimit -- %s", optarg);
452 options |= F_INTERFACE;
453 #ifndef USE_SIN6_SCOPE_ID
457 case 'i': /* wait between sending packets */
458 t = strtod(optarg, &e);
459 if (*optarg == '\0' || *e != '\0')
460 errx(1, "illegal timing interval %s", optarg);
461 if (t < 1 && getuid()) {
462 errx(1, "%s: only root may use interval < 1s",
465 intvl.tv_sec = (time_t)t;
467 (long)((t - intvl.tv_sec) * 1000000000);
468 if (intvl.tv_sec < 0)
469 errx(1, "illegal timing interval %s", optarg);
470 /* less than 1/hz does not make sense */
471 if (intvl.tv_sec == 0 && intvl.tv_nsec < 1000) {
472 warnx("too small interval, raised to .000001");
473 intvl.tv_nsec = 1000;
475 options |= F_INTERVAL;
480 errx(1, "Must be superuser to preload");
482 preload = strtol(optarg, &e, 10);
483 if (preload < 0 || *optarg == '\0' || *e != '\0')
484 errx(1, "illegal preload value -- %s", optarg);
487 #ifdef IPV6_USE_MIN_MTU
491 errx(1, "-%c is not supported on this platform", ch);
495 options &= ~F_HOSTNAME;
498 options |= F_NIGROUP;
504 case 'p': /* fill buffer with user pattern */
505 options |= F_PINGFILLED;
506 fill((char *)datap, optarg);
512 options |= F_AUDIBLE;
518 memset(&hints, 0, sizeof(struct addrinfo));
519 hints.ai_flags = AI_NUMERICHOST; /* allow hostname? */
520 hints.ai_family = AF_INET6;
521 hints.ai_socktype = SOCK_RAW;
522 hints.ai_protocol = IPPROTO_ICMPV6;
524 error = cap_getaddrinfo(capdns, optarg, NULL, &hints, &res);
526 errx(1, "invalid source address: %s",
527 gai_strerror(error));
530 * res->ai_family must be AF_INET6 and res->ai_addrlen
531 * must be sizeof(src).
533 memcpy(&src, res->ai_addr, res->ai_addrlen);
534 srclen = res->ai_addrlen;
536 options |= F_SRCADDR;
538 case 's': /* size of packet to send */
539 datalen = strtol(optarg, &e, 10);
540 if (datalen <= 0 || *optarg == '\0' || *e != '\0')
541 errx(1, "illegal datalen value -- %s", optarg);
542 if (datalen > MAXDATALEN) {
544 "datalen value too large, maximum is %d",
549 options &= ~F_NOUSERDATA;
550 options |= F_SUPTYPES;
553 options |= F_VERBOSE;
556 options &= ~F_NOUSERDATA;
560 options &= ~F_NOUSERDATA;
561 options |= F_FQDNOLD;
564 t = strtod(optarg, &e);
565 if (*e || e == optarg || t > (double)INT_MAX)
566 err(EX_USAGE, "invalid timing interval: `%s'",
568 options |= F_WAITTIME;
572 alarmtimeout = strtoul(optarg, &e, 0);
573 if ((alarmtimeout < 1) || (alarmtimeout == ULONG_MAX))
574 errx(EX_USAGE, "invalid timeout: `%s'",
576 if (alarmtimeout > MAXALARM)
577 errx(EX_USAGE, "invalid timeout: `%s' > %d",
580 struct itimerval itv;
582 timerclear(&itv.it_interval);
583 timerclear(&itv.it_value);
584 itv.it_value.tv_sec = (time_t)alarmtimeout;
585 if (setitimer(ITIMER_REAL, &itv, NULL) != 0)
589 case 'z': /* traffic class */
590 tclass = strtol(optarg, &e, 10);
591 if (*optarg == '\0' || *e != '\0')
592 errx(1, "illegal traffic class %s", optarg);
593 if (255 < tclass || tclass < -1)
595 "illegal traffic class -- %s", optarg);
598 #ifdef IPSEC_POLICY_IPSEC
601 if (!strncmp("in", optarg, 2)) {
602 if ((policy_in = strdup(optarg)) == NULL)
604 } else if (!strncmp("out", optarg, 3)) {
605 if ((policy_out = strdup(optarg)) == NULL)
608 errx(1, "invalid security policy");
612 options |= F_AUTHHDR;
615 options |= F_ENCRYPT;
617 #endif /*IPSEC_POLICY_IPSEC*/
634 #ifdef IPV6_RECVRTHDR /* 2292bis */
635 rthlen = CMSG_SPACE(inet6_rth_space(IPV6_RTHDR_TYPE_0,
638 rthlen = inet6_rthdr_space(IPV6_RTHDR_TYPE_0, argc - 1);
641 errx(1, "too many intermediate hops");
647 if (options & F_NIGROUP) {
648 target = nigroup(argv[argc - 1], nig_oldmcprefix);
649 if (target == NULL) {
654 target = argv[argc - 1];
656 /* cap_getaddrinfo */
657 memset(&hints, 0, sizeof(struct addrinfo));
658 hints.ai_flags = AI_CANONNAME;
659 hints.ai_family = AF_INET6;
660 hints.ai_socktype = SOCK_RAW;
661 hints.ai_protocol = IPPROTO_ICMPV6;
663 error = cap_getaddrinfo(capdns, target, NULL, &hints, &res);
665 errx(1, "%s", gai_strerror(error));
666 if (res->ai_canonname)
667 hostname = strdup(res->ai_canonname);
672 errx(1, "cap_getaddrinfo failed");
674 (void)memcpy(&dst, res->ai_addr, res->ai_addrlen);
676 if ((ssend = socket(res->ai_family, res->ai_socktype,
677 res->ai_protocol)) < 0)
678 err(1, "socket ssend");
679 if ((srecv = socket(res->ai_family, res->ai_socktype,
680 res->ai_protocol)) < 0)
681 err(1, "socket srecv");
684 /* set the source address if specified. */
685 if ((options & F_SRCADDR) != 0) {
686 /* properly fill sin6_scope_id */
687 if (IN6_IS_ADDR_LINKLOCAL(&src.sin6_addr) && (
688 IN6_IS_ADDR_LINKLOCAL(&dst.sin6_addr) ||
689 IN6_IS_ADDR_MC_LINKLOCAL(&dst.sin6_addr) ||
690 IN6_IS_ADDR_MC_NODELOCAL(&dst.sin6_addr))) {
691 if (src.sin6_scope_id == 0)
692 src.sin6_scope_id = dst.sin6_scope_id;
693 if (dst.sin6_scope_id == 0)
694 dst.sin6_scope_id = src.sin6_scope_id;
696 if (bind(ssend, (struct sockaddr *)&src, srclen) != 0)
699 /* set the gateway (next hop) if specified */
701 memset(&hints, 0, sizeof(hints));
702 hints.ai_family = AF_INET6;
703 hints.ai_socktype = SOCK_RAW;
704 hints.ai_protocol = IPPROTO_ICMPV6;
706 error = cap_getaddrinfo(capdns, gateway, NULL, &hints, &res);
708 errx(1, "cap_getaddrinfo for the gateway %s: %s",
709 gateway, gai_strerror(error));
711 if (res->ai_next && (options & F_VERBOSE))
712 warnx("gateway resolves to multiple addresses");
714 if (setsockopt(ssend, IPPROTO_IPV6, IPV6_NEXTHOP,
715 res->ai_addr, res->ai_addrlen)) {
716 err(1, "setsockopt(IPV6_NEXTHOP)");
723 * let the kerel pass extension headers of incoming packets,
724 * for privileged socket options
726 if ((options & F_VERBOSE) != 0) {
729 #ifdef IPV6_RECVHOPOPTS
730 if (setsockopt(srecv, IPPROTO_IPV6, IPV6_RECVHOPOPTS, &opton,
732 err(1, "setsockopt(IPV6_RECVHOPOPTS)");
733 #else /* old adv. API */
734 if (setsockopt(srecv, IPPROTO_IPV6, IPV6_HOPOPTS, &opton,
736 err(1, "setsockopt(IPV6_HOPOPTS)");
738 #ifdef IPV6_RECVDSTOPTS
739 if (setsockopt(srecv, IPPROTO_IPV6, IPV6_RECVDSTOPTS, &opton,
741 err(1, "setsockopt(IPV6_RECVDSTOPTS)");
742 #else /* old adv. API */
743 if (setsockopt(srecv, IPPROTO_IPV6, IPV6_DSTOPTS, &opton,
745 err(1, "setsockopt(IPV6_DSTOPTS)");
747 #ifdef IPV6_RECVRTHDRDSTOPTS
748 if (setsockopt(srecv, IPPROTO_IPV6, IPV6_RECVRTHDRDSTOPTS, &opton,
750 err(1, "setsockopt(IPV6_RECVRTHDRDSTOPTS)");
754 /* revoke root privilege */
755 if (seteuid(getuid()) != 0)
756 err(1, "seteuid() failed");
757 if (setuid(getuid()) != 0)
758 err(1, "setuid() failed");
760 if ((options & F_FLOOD) && (options & F_INTERVAL))
761 errx(1, "-f and -i incompatible options");
763 if ((options & F_NOUSERDATA) == 0) {
764 if (datalen >= sizeof(struct tv32)) {
765 /* we can time transfer */
769 /* in F_VERBOSE case, we may get non-echoreply packets*/
770 if (options & F_VERBOSE)
771 packlen = 2048 + IP6LEN + ICMP6ECHOLEN + EXTRA;
773 packlen = datalen + IP6LEN + ICMP6ECHOLEN + EXTRA;
775 /* suppress timing for node information query */
778 packlen = 2048 + IP6LEN + ICMP6ECHOLEN + EXTRA;
781 if (!(packet = (u_char *)malloc((u_int)packlen)))
782 err(1, "Unable to allocate packet");
783 if (!(options & F_PINGFILLED))
784 for (i = ICMP6ECHOLEN; i < packlen; ++i)
787 ident = getpid() & 0xFFFF;
788 arc4random_buf(nonce, sizeof(nonce));
790 if (options & F_DONTFRAG)
791 if (setsockopt(ssend, IPPROTO_IPV6, IPV6_DONTFRAG,
792 &optval, sizeof(optval)) == -1)
793 err(1, "IPV6_DONTFRAG");
796 if (options & F_SO_DEBUG) {
797 (void)setsockopt(ssend, SOL_SOCKET, SO_DEBUG, (char *)&hold,
799 (void)setsockopt(srecv, SOL_SOCKET, SO_DEBUG, (char *)&hold,
802 optval = IPV6_DEFHLIM;
803 if (IN6_IS_ADDR_MULTICAST(&dst.sin6_addr))
804 if (setsockopt(ssend, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
805 &optval, sizeof(optval)) == -1)
806 err(1, "IPV6_MULTICAST_HOPS");
807 #ifdef IPV6_USE_MIN_MTU
809 optval = mflag > 1 ? 0 : 1;
811 if (setsockopt(ssend, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
812 &optval, sizeof(optval)) == -1)
813 err(1, "setsockopt(IPV6_USE_MIN_MTU)");
815 #ifdef IPV6_RECVPATHMTU
818 if (setsockopt(srecv, IPPROTO_IPV6, IPV6_RECVPATHMTU,
819 &optval, sizeof(optval)) == -1)
820 err(1, "setsockopt(IPV6_RECVPATHMTU)");
822 #endif /* IPV6_RECVPATHMTU */
823 #endif /* IPV6_USE_MIN_MTU */
826 #ifdef IPSEC_POLICY_IPSEC
827 if (options & F_POLICY) {
828 if (setpolicy(srecv, policy_in) < 0)
829 errx(1, "%s", ipsec_strerror());
830 if (setpolicy(ssend, policy_out) < 0)
831 errx(1, "%s", ipsec_strerror());
834 if (options & F_AUTHHDR) {
835 optval = IPSEC_LEVEL_REQUIRE;
836 #ifdef IPV6_AUTH_TRANS_LEVEL
837 if (setsockopt(ssend, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL,
838 &optval, sizeof(optval)) == -1)
839 err(1, "setsockopt(IPV6_AUTH_TRANS_LEVEL)");
840 if (setsockopt(srecv, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL,
841 &optval, sizeof(optval)) == -1)
842 err(1, "setsockopt(IPV6_AUTH_TRANS_LEVEL)");
844 if (setsockopt(ssend, IPPROTO_IPV6, IPV6_AUTH_LEVEL,
845 &optval, sizeof(optval)) == -1)
846 err(1, "setsockopt(IPV6_AUTH_LEVEL)");
847 if (setsockopt(srecv, IPPROTO_IPV6, IPV6_AUTH_LEVEL,
848 &optval, sizeof(optval)) == -1)
849 err(1, "setsockopt(IPV6_AUTH_LEVEL)");
852 if (options & F_ENCRYPT) {
853 optval = IPSEC_LEVEL_REQUIRE;
854 if (setsockopt(ssend, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL,
855 &optval, sizeof(optval)) == -1)
856 err(1, "setsockopt(IPV6_ESP_TRANS_LEVEL)");
857 if (setsockopt(srecv, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL,
858 &optval, sizeof(optval)) == -1)
859 err(1, "setsockopt(IPV6_ESP_TRANS_LEVEL)");
861 #endif /*IPSEC_POLICY_IPSEC*/
866 struct icmp6_filter filt;
867 if (!(options & F_VERBOSE)) {
868 ICMP6_FILTER_SETBLOCKALL(&filt);
869 if ((options & F_FQDN) || (options & F_FQDNOLD) ||
870 (options & F_NODEADDR) || (options & F_SUPTYPES))
871 ICMP6_FILTER_SETPASS(ICMP6_NI_REPLY, &filt);
873 ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &filt);
875 ICMP6_FILTER_SETPASSALL(&filt);
877 if (setsockopt(srecv, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
879 err(1, "setsockopt(ICMP6_FILTER)");
881 #endif /*ICMP6_FILTER*/
883 /* let the kerel pass extension headers of incoming packets */
884 if ((options & F_VERBOSE) != 0) {
887 #ifdef IPV6_RECVRTHDR
888 if (setsockopt(srecv, IPPROTO_IPV6, IPV6_RECVRTHDR, &opton,
890 err(1, "setsockopt(IPV6_RECVRTHDR)");
891 #else /* old adv. API */
892 if (setsockopt(srecv, IPPROTO_IPV6, IPV6_RTHDR, &opton,
894 err(1, "setsockopt(IPV6_RTHDR)");
900 if (IN6_IS_ADDR_MULTICAST(&dst.sin6_addr))
901 if (setsockopt(ssend, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
902 &optval, sizeof(optval)) == -1)
903 err(1, "IPV6_MULTICAST_LOOP");
906 /* Specify the outgoing interface and/or the source address */
908 ip6optlen += CMSG_SPACE(sizeof(struct in6_pktinfo));
911 ip6optlen += CMSG_SPACE(sizeof(int));
913 /* set IP6 packet options */
915 if ((scmsg = (char *)malloc(ip6optlen)) == NULL)
916 errx(1, "can't allocate enough memory");
917 smsghdr.msg_control = (caddr_t)scmsg;
918 smsghdr.msg_controllen = ip6optlen;
919 scmsgp = CMSG_FIRSTHDR(&smsghdr);
922 cmsg_pktinfo = CMSG_DATA(scmsgp);
923 scmsgp->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
924 scmsgp->cmsg_level = IPPROTO_IPV6;
925 scmsgp->cmsg_type = IPV6_PKTINFO;
926 scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp);
929 /* set the outgoing interface */
931 #ifndef USE_SIN6_SCOPE_ID
932 /* pktinfo must have already been allocated */
933 if ((pktinfo.ipi6_ifindex = if_nametoindex(ifname)) == 0)
934 errx(1, "%s: invalid interface name", ifname);
936 if ((dst.sin6_scope_id = if_nametoindex(ifname)) == 0)
937 errx(1, "%s: invalid interface name", ifname);
940 if (hoplimit != -1) {
941 scmsgp->cmsg_len = CMSG_LEN(sizeof(int));
942 scmsgp->cmsg_level = IPPROTO_IPV6;
943 scmsgp->cmsg_type = IPV6_HOPLIMIT;
944 memcpy(CMSG_DATA(scmsgp), &hoplimit, sizeof(hoplimit));
946 scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp);
950 if (setsockopt(ssend, IPPROTO_IPV6, IPV6_TCLASS,
951 &tclass, sizeof(tclass)) == -1)
952 err(1, "setsockopt(IPV6_TCLASS)");
955 if (argc > 1) { /* some intermediate addrs are specified */
959 rthdrlen = inet6_rth_space(IPV6_RTHDR_TYPE_0, argc - 1);
960 scmsgp->cmsg_len = CMSG_LEN(rthdrlen);
961 scmsgp->cmsg_level = IPPROTO_IPV6;
962 scmsgp->cmsg_type = IPV6_RTHDR;
963 rthdr = (struct ip6_rthdr *)CMSG_DATA(scmsgp);
964 rthdr = inet6_rth_init((void *)rthdr, rthdrlen,
965 IPV6_RTHDR_TYPE_0, argc - 1);
967 errx(1, "can't initialize rthdr");
969 for (hops = 0; hops < argc - 1; hops++) {
970 memset(&hints, 0, sizeof(hints));
971 hints.ai_family = AF_INET6;
973 if ((error = cap_getaddrinfo(capdns, argv[hops], NULL, &hints,
975 errx(1, "%s", gai_strerror(error));
976 if (res->ai_addr->sa_family != AF_INET6)
978 "bad addr family of an intermediate addr");
979 sin6 = (struct sockaddr_in6 *)(void *)res->ai_addr;
980 if (inet6_rth_add(rthdr, &sin6->sin6_addr))
981 errx(1, "can't add an intermediate node");
985 scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp);
988 /* From now on we will use only reverse DNS lookups. */
990 if (capdns != NULL) {
991 const char *types[1];
993 types[0] = "ADDR2NAME";
994 if (cap_dns_type_limit(capdns, types, nitems(types)) < 0)
995 err(1, "unable to limit access to system.dns service");
998 if (!(options & F_SRCADDR)) {
1000 * get the source address. XXX since we revoked the root
1001 * privilege, we cannot use a raw socket for this.
1004 socklen_t len = sizeof(src);
1006 if ((dummy = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
1007 err(1, "UDP socket");
1009 src.sin6_family = AF_INET6;
1010 src.sin6_addr = dst.sin6_addr;
1011 src.sin6_port = ntohs(DUMMY_PORT);
1012 src.sin6_scope_id = dst.sin6_scope_id;
1015 setsockopt(dummy, IPPROTO_IPV6, IPV6_PKTINFO,
1016 (void *)&pktinfo, sizeof(pktinfo)))
1017 err(1, "UDP setsockopt(IPV6_PKTINFO)");
1019 if (hoplimit != -1 &&
1020 setsockopt(dummy, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
1021 (void *)&hoplimit, sizeof(hoplimit)))
1022 err(1, "UDP setsockopt(IPV6_UNICAST_HOPS)");
1024 if (hoplimit != -1 &&
1025 setsockopt(dummy, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
1026 (void *)&hoplimit, sizeof(hoplimit)))
1027 err(1, "UDP setsockopt(IPV6_MULTICAST_HOPS)");
1030 setsockopt(dummy, IPPROTO_IPV6, IPV6_RTHDR,
1031 (void *)rthdr, (rthdr->ip6r_len + 1) << 3))
1032 err(1, "UDP setsockopt(IPV6_RTHDR)");
1034 if (connect(dummy, (struct sockaddr *)&src, len) < 0)
1035 err(1, "UDP connect");
1037 if (getsockname(dummy, (struct sockaddr *)&src, &len) < 0)
1038 err(1, "getsockname");
1043 /* Save pktinfo in the ancillary data. */
1045 memcpy(cmsg_pktinfo, &pktinfo, sizeof(pktinfo));
1047 if (connect(ssend, (struct sockaddr *)&dst, sizeof(dst)) != 0)
1048 err(1, "connect() ssend");
1050 caph_cache_catpages();
1051 if (caph_enter_casper() < 0)
1052 err(1, "caph_enter_casper");
1054 cap_rights_init(&rights_stdin);
1055 if (caph_rights_limit(STDIN_FILENO, &rights_stdin) < 0)
1056 err(1, "caph_rights_limit stdin");
1057 if (caph_limit_stdout() < 0)
1058 err(1, "caph_limit_stdout");
1059 if (caph_limit_stderr() < 0)
1060 err(1, "caph_limit_stderr");
1062 cap_rights_init(&rights_srecv, CAP_RECV, CAP_EVENT, CAP_SETSOCKOPT);
1063 if (caph_rights_limit(srecv, &rights_srecv) < 0)
1064 err(1, "caph_rights_limit srecv");
1065 cap_rights_init(&rights_ssend, CAP_SEND, CAP_SETSOCKOPT);
1066 if (caph_rights_limit(ssend, &rights_ssend) < 0)
1067 err(1, "caph_rights_limit ssend");
1069 #if defined(SO_SNDBUF) && defined(SO_RCVBUF)
1071 if (datalen > (size_t)sockbufsize)
1072 warnx("you need -b to increase socket buffer size");
1073 if (setsockopt(ssend, SOL_SOCKET, SO_SNDBUF, &sockbufsize,
1074 sizeof(sockbufsize)) < 0)
1075 err(1, "setsockopt(SO_SNDBUF)");
1076 if (setsockopt(srecv, SOL_SOCKET, SO_RCVBUF, &sockbufsize,
1077 sizeof(sockbufsize)) < 0)
1078 err(1, "setsockopt(SO_RCVBUF)");
1081 if (datalen > 8 * 1024) /*XXX*/
1082 warnx("you need -b to increase socket buffer size");
1084 * When pinging the broadcast address, you can get a lot of
1085 * answers. Doing something so evil is useful if you are trying
1086 * to stress the ethernet, or just want to fill the arp cache
1087 * to get some stuff for /etc/ethers.
1090 setsockopt(srecv, SOL_SOCKET, SO_RCVBUF, (char *)&hold,
1096 #ifndef USE_SIN6_SCOPE_ID
1097 #ifdef IPV6_RECVPKTINFO
1098 if (setsockopt(srecv, IPPROTO_IPV6, IPV6_RECVPKTINFO, &optval,
1099 sizeof(optval)) < 0)
1100 warn("setsockopt(IPV6_RECVPKTINFO)"); /* XXX err? */
1101 #else /* old adv. API */
1102 if (setsockopt(srecv, IPPROTO_IPV6, IPV6_PKTINFO, &optval,
1103 sizeof(optval)) < 0)
1104 warn("setsockopt(IPV6_PKTINFO)"); /* XXX err? */
1106 #endif /* USE_SIN6_SCOPE_ID */
1107 #ifdef IPV6_RECVHOPLIMIT
1108 if (setsockopt(srecv, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &optval,
1109 sizeof(optval)) < 0)
1110 warn("setsockopt(IPV6_RECVHOPLIMIT)"); /* XXX err? */
1111 #else /* old adv. API */
1112 if (setsockopt(srecv, IPPROTO_IPV6, IPV6_HOPLIMIT, &optval,
1113 sizeof(optval)) < 0)
1114 warn("setsockopt(IPV6_HOPLIMIT)"); /* XXX err? */
1117 cap_rights_clear(&rights_srecv, CAP_SETSOCKOPT);
1118 if (caph_rights_limit(srecv, &rights_srecv) < 0)
1119 err(1, "caph_rights_limit srecv setsockopt");
1120 cap_rights_clear(&rights_ssend, CAP_SETSOCKOPT);
1121 if (caph_rights_limit(ssend, &rights_ssend) < 0)
1122 err(1, "caph_rights_limit ssend setsockopt");
1124 printf("PING6(%lu=40+8+%lu bytes) ", (unsigned long)(40 + pingerlen()),
1125 (unsigned long)(pingerlen() - 8));
1126 printf("%s --> ", pr_addr((struct sockaddr *)&src, sizeof(src)));
1127 printf("%s\n", pr_addr((struct sockaddr *)&dst, sizeof(dst)));
1132 if (npackets != 0 && preload > npackets)
1137 clock_gettime(CLOCK_MONOTONIC, &last);
1139 sigemptyset(&si_sa.sa_mask);
1141 si_sa.sa_handler = onsignal;
1142 if (sigaction(SIGINT, &si_sa, 0) == -1)
1143 err(EX_OSERR, "sigaction SIGINT");
1146 if (sigaction(SIGINFO, &si_sa, 0) == -1)
1147 err(EX_OSERR, "sigaction SIGINFO");
1150 if (alarmtimeout > 0) {
1151 if (sigaction(SIGALRM, &si_sa, 0) == -1)
1152 err(EX_OSERR, "sigaction SIGALRM");
1154 if (options & F_FLOOD) {
1156 intvl.tv_nsec = 10000000;
1160 while (seenint == 0) {
1161 struct timespec now, timeout;
1163 struct iovec iov[2];
1167 /* signal handling */
1178 FD_SET(srecv, &rfds);
1179 clock_gettime(CLOCK_MONOTONIC, &now);
1180 timespecadd(&last, &intvl, &timeout);
1181 timespecsub(&timeout, &now, &timeout);
1182 if (timeout.tv_sec < 0)
1183 timespecclear(&timeout);
1185 n = pselect(srecv + 1, &rfds, NULL, NULL, &timeout, NULL);
1187 continue; /* EINTR */
1189 m.msg_name = (caddr_t)&from;
1190 m.msg_namelen = sizeof(from);
1191 memset(&iov, 0, sizeof(iov));
1192 iov[0].iov_base = (caddr_t)packet;
1193 iov[0].iov_len = packlen;
1196 memset(cm, 0, CONTROLLEN);
1197 m.msg_control = (void *)cm;
1198 m.msg_controllen = CONTROLLEN;
1200 cc = recvmsg(srecv, &m, 0);
1202 if (errno != EINTR) {
1207 } else if (cc == 0) {
1211 * receive control messages only. Process the
1212 * exceptions (currently the only possibility is
1213 * a path MTU notification.)
1215 if ((mtu = get_pathmtu(&m)) > 0) {
1216 if ((options & F_VERBOSE) != 0) {
1217 printf("new path MTU (%d) is "
1224 * an ICMPv6 message (probably an echoreply)
1227 pr_pack(packet, cc, &m);
1229 if (((options & F_ONCE) != 0 && nreceived > 0) ||
1230 (npackets > 0 && nreceived >= npackets))
1233 if (n == 0 || (options & F_FLOOD)) {
1234 if (npackets == 0 || ntransmitted < npackets)
1241 * If we're not transmitting any more packets,
1242 * change the timer to wait two round-trip times
1243 * if we've received any packets or (waittime)
1244 * milliseconds if we haven't.
1248 intvl.tv_sec = 2 * tmax / 1000;
1249 if (intvl.tv_sec == 0)
1252 intvl.tv_sec = waittime / 1000;
1254 waittime % 1000 * 1000000;
1257 clock_gettime(CLOCK_MONOTONIC, &last);
1258 if (ntransmitted - nreceived - 1 > nmissedmax) {
1259 nmissedmax = ntransmitted - nreceived - 1;
1260 if (options & F_MISSED)
1261 (void)write(STDOUT_FILENO, &BBELL, 1);
1265 sigemptyset(&si_sa.sa_mask);
1267 si_sa.sa_handler = SIG_IGN;
1268 sigaction(SIGINT, &si_sa, 0);
1269 sigaction(SIGALRM, &si_sa, 0);
1277 else if (ntransmitted > ntransmitfailures)
1302 * Compose and transmit an ICMP ECHO REQUEST packet. The IP packet
1303 * will be added on by the kernel. The ID field is our UNIX process ID,
1304 * and the sequence number is an ascending integer. The first 8 bytes
1305 * of the data portion are used to hold a UNIX "timespec" struct in VAX
1306 * byte-order, to compute the round-trip time.
1313 if (options & F_FQDN)
1314 l = ICMP6_NIQLEN + sizeof(dst.sin6_addr);
1315 else if (options & F_FQDNOLD)
1317 else if (options & F_NODEADDR)
1318 l = ICMP6_NIQLEN + sizeof(dst.sin6_addr);
1319 else if (options & F_SUPTYPES)
1322 l = ICMP6ECHOLEN + datalen;
1330 struct icmp6_hdr *icp;
1331 struct iovec iov[2];
1333 struct icmp6_nodeinfo *nip;
1336 if (npackets && ntransmitted >= npackets)
1337 return(-1); /* no more transmission */
1339 icp = (struct icmp6_hdr *)outpack;
1340 nip = (struct icmp6_nodeinfo *)outpack;
1341 memset(icp, 0, sizeof(*icp));
1342 icp->icmp6_cksum = 0;
1343 seq = ntransmitted++;
1344 CLR(seq % mx_dup_ck);
1346 if (options & F_FQDN) {
1349 icp->icmp6_type = ICMP6_NI_QUERY;
1350 icp->icmp6_code = ICMP6_NI_SUBJ_IPV6;
1351 nip->ni_qtype = htons(NI_QTYPE_FQDN);
1352 nip->ni_flags = htons(0);
1354 memcpy(nip->icmp6_ni_nonce, nonce,
1355 sizeof(nip->icmp6_ni_nonce));
1357 memcpy(nip->icmp6_ni_nonce, &s, sizeof(s));
1359 memcpy(&outpack[ICMP6_NIQLEN], &dst.sin6_addr,
1360 sizeof(dst.sin6_addr));
1361 cc = ICMP6_NIQLEN + sizeof(dst.sin6_addr);
1363 } else if (options & F_FQDNOLD) {
1365 /* packet format in 03 draft - no Subject data on queries */
1366 icp->icmp6_type = ICMP6_NI_QUERY;
1367 icp->icmp6_code = 0; /* code field is always 0 */
1368 nip->ni_qtype = htons(NI_QTYPE_FQDN);
1369 nip->ni_flags = htons(0);
1371 memcpy(nip->icmp6_ni_nonce, nonce,
1372 sizeof(nip->icmp6_ni_nonce));
1374 memcpy(nip->icmp6_ni_nonce, &s, sizeof(s));
1378 } else if (options & F_NODEADDR) {
1381 icp->icmp6_type = ICMP6_NI_QUERY;
1382 icp->icmp6_code = ICMP6_NI_SUBJ_IPV6;
1383 nip->ni_qtype = htons(NI_QTYPE_NODEADDR);
1384 nip->ni_flags = naflags;
1386 memcpy(nip->icmp6_ni_nonce, nonce,
1387 sizeof(nip->icmp6_ni_nonce));
1389 memcpy(nip->icmp6_ni_nonce, &s, sizeof(s));
1391 memcpy(&outpack[ICMP6_NIQLEN], &dst.sin6_addr,
1392 sizeof(dst.sin6_addr));
1393 cc = ICMP6_NIQLEN + sizeof(dst.sin6_addr);
1395 } else if (options & F_SUPTYPES) {
1398 icp->icmp6_type = ICMP6_NI_QUERY;
1399 icp->icmp6_code = ICMP6_NI_SUBJ_FQDN; /*empty*/
1400 nip->ni_qtype = htons(NI_QTYPE_SUPTYPES);
1401 /* we support compressed bitmap */
1402 nip->ni_flags = NI_SUPTYPE_FLAG_COMPRESS;
1404 memcpy(nip->icmp6_ni_nonce, nonce,
1405 sizeof(nip->icmp6_ni_nonce));
1407 memcpy(nip->icmp6_ni_nonce, &s, sizeof(s));
1412 icp->icmp6_type = ICMP6_ECHO_REQUEST;
1413 icp->icmp6_code = 0;
1414 icp->icmp6_id = htons(ident);
1415 icp->icmp6_seq = htons(seq);
1419 (void)clock_gettime(CLOCK_MONOTONIC, &tv);
1421 * Truncate seconds down to 32 bits in order
1422 * to fit the timestamp within 8 bytes of the
1423 * packet. We're only concerned with
1424 * durations, not absolute times.
1426 tv32.tv32_sec = (uint32_t)htonl(tv.tv_sec);
1427 tv32.tv32_nsec = (uint32_t)htonl(tv.tv_nsec);
1428 memcpy(&outpack[ICMP6ECHOLEN], &tv32, sizeof(tv32));
1430 cc = ICMP6ECHOLEN + datalen;
1434 if (pingerlen() != cc)
1435 errx(1, "internal error; length mismatch");
1438 memset(&iov, 0, sizeof(iov));
1439 iov[0].iov_base = (caddr_t)outpack;
1440 iov[0].iov_len = cc;
1441 smsghdr.msg_iov = iov;
1442 smsghdr.msg_iovlen = 1;
1444 i = sendmsg(ssend, &smsghdr, 0);
1446 if (i < 0 || i != cc) {
1448 ntransmitfailures++;
1451 (void)printf("ping6: wrote %s %d chars, ret=%d\n",
1454 if (!(options & F_QUIET) && options & F_FLOOD)
1455 (void)write(STDOUT_FILENO, &DOT, 1);
1461 myechoreply(const struct icmp6_hdr *icp)
1463 if (ntohs(icp->icmp6_id) == ident)
1470 mynireply(const struct icmp6_nodeinfo *nip)
1472 if (memcmp(nip->icmp6_ni_nonce + sizeof(u_int16_t),
1473 nonce + sizeof(u_int16_t),
1474 sizeof(nonce) - sizeof(u_int16_t)) == 0)
1481 * Decode a name from a DNS message.
1483 * Format of the message is described in RFC 1035 subsection 4.1.4.
1486 * sp - Pointer to a DNS pointer octet or to the first octet of a label
1488 * ep - Pointer to the end of the message (one step past the last octet).
1489 * base - Pointer to the beginning of the message.
1490 * buf - Buffer into which the decoded name will be saved.
1491 * bufsiz - Size of the buffer 'buf'.
1494 * Pointer to an octet immediately following the ending zero octet
1495 * of the decoded label, or NULL if an error occured.
1498 dnsdecode(const u_char *sp, const u_char *ep, const u_char *base, char *buf,
1503 char cresult[MAXDNAME + 1];
1514 if (i == 0 || cp != sp) {
1515 if (strlcat((char *)buf, ".", bufsiz) >= bufsiz)
1516 return NULL; /*result overrun*/
1522 if ((i & 0xc0) == 0xc0 && cp - base > (i & 0x3f)) {
1523 /* DNS compression */
1527 comp = base + (i & 0x3f);
1528 if (dnsdecode(comp, cp, base, cresult,
1529 sizeof(cresult)) == NULL)
1531 if (strlcat(buf, cresult, bufsiz) >= bufsiz)
1532 return NULL; /*result overrun*/
1534 } else if ((i & 0x3f) == i) {
1536 return NULL; /*source overrun*/
1537 while (i-- > 0 && cp < ep) {
1538 l = snprintf(cresult, sizeof(cresult),
1539 isprint(*cp) ? "%c" : "\\%03o", *cp & 0xff);
1540 if ((size_t)l >= sizeof(cresult) || l < 0)
1542 if (strlcat(buf, cresult, bufsiz) >= bufsiz)
1543 return NULL; /*result overrun*/
1547 return NULL; /*invalid label*/
1550 return NULL; /*not terminated*/
1557 * Print out the packet, if it came from us. This logic is necessary
1558 * because ALL readers of the ICMP socket get a copy of ALL ICMP packets
1559 * which arrive ('tis only fair). This permits multiple copies of this
1560 * program to be run without having intermingled output (or statistics!).
1563 pr_pack(u_char *buf, int cc, struct msghdr *mhdr)
1565 #define safeputc(c) printf((isprint((c)) ? "%c" : "\\%03o"), c)
1566 struct icmp6_hdr *icp;
1567 struct icmp6_nodeinfo *ni;
1570 struct sockaddr *from;
1572 const u_char *cp = NULL;
1573 u_char *dp, *end = buf + cc;
1574 struct in6_pktinfo *pktinfo = NULL;
1575 struct timespec tv, tp;
1577 double triptime = 0;
1582 char dnsname[MAXDNAME + 1];
1584 (void)clock_gettime(CLOCK_MONOTONIC, &tv);
1586 if (!mhdr || !mhdr->msg_name ||
1587 mhdr->msg_namelen != sizeof(struct sockaddr_in6) ||
1588 ((struct sockaddr *)mhdr->msg_name)->sa_family != AF_INET6) {
1589 if (options & F_VERBOSE)
1590 warnx("invalid peername");
1593 from = (struct sockaddr *)mhdr->msg_name;
1594 fromlen = mhdr->msg_namelen;
1595 if (cc < (int)sizeof(struct icmp6_hdr)) {
1596 if (options & F_VERBOSE)
1597 warnx("packet too short (%d bytes) from %s", cc,
1598 pr_addr(from, fromlen));
1601 if (((mhdr->msg_flags & MSG_CTRUNC) != 0) &&
1602 (options & F_VERBOSE) != 0)
1603 warnx("some control data discarded, insufficient buffer size");
1604 icp = (struct icmp6_hdr *)buf;
1605 ni = (struct icmp6_nodeinfo *)buf;
1608 if ((hoplim = get_hoplim(mhdr)) == -1) {
1609 warnx("failed to get receiving hop limit");
1612 if ((pktinfo = get_rcvpktinfo(mhdr)) == NULL) {
1613 warnx("failed to get receiving packet information");
1617 if (icp->icmp6_type == ICMP6_ECHO_REPLY && myechoreply(icp)) {
1618 seq = ntohs(icp->icmp6_seq);
1621 memcpy(&tpp, icp + 1, sizeof(tpp));
1622 tp.tv_sec = ntohl(tpp.tv32_sec);
1623 tp.tv_nsec = ntohl(tpp.tv32_nsec);
1624 timespecsub(&tv, &tp, &tv);
1625 triptime = ((double)tv.tv_sec) * 1000.0 +
1626 ((double)tv.tv_nsec) / 1000000.0;
1628 tsumsq += triptime * triptime;
1629 if (triptime < tmin)
1631 if (triptime > tmax)
1635 if (TST(seq % mx_dup_ck)) {
1640 SET(seq % mx_dup_ck);
1644 if (options & F_QUIET)
1647 if (options & F_WAITTIME && triptime > waittime) {
1652 if (options & F_FLOOD)
1653 (void)write(STDOUT_FILENO, &BSPACE, 1);
1655 if (options & F_AUDIBLE)
1656 (void)write(STDOUT_FILENO, &BBELL, 1);
1657 (void)printf("%d bytes from %s, icmp_seq=%u", cc,
1658 pr_addr(from, fromlen), seq);
1659 (void)printf(" hlim=%d", hoplim);
1660 if ((options & F_VERBOSE) != 0) {
1661 struct sockaddr_in6 dstsa;
1663 memset(&dstsa, 0, sizeof(dstsa));
1664 dstsa.sin6_family = AF_INET6;
1665 dstsa.sin6_len = sizeof(dstsa);
1666 dstsa.sin6_scope_id = pktinfo->ipi6_ifindex;
1667 dstsa.sin6_addr = pktinfo->ipi6_addr;
1668 (void)printf(" dst=%s",
1669 pr_addr((struct sockaddr *)&dstsa,
1673 (void)printf(" time=%.3f ms", triptime);
1675 (void)printf("(DUP!)");
1676 /* check the data */
1677 cp = buf + off + ICMP6ECHOLEN + ICMP6ECHOTMLEN;
1678 dp = outpack + ICMP6ECHOLEN + ICMP6ECHOTMLEN;
1679 for (i = 8; cp < end; ++i, ++cp, ++dp) {
1681 (void)printf("\nwrong data byte #%d should be 0x%x but was 0x%x", i, *dp, *cp);
1686 } else if (icp->icmp6_type == ICMP6_NI_REPLY && mynireply(ni)) {
1687 memcpy(&seq, ni->icmp6_ni_nonce, sizeof(seq));
1690 if (TST(seq % mx_dup_ck)) {
1695 SET(seq % mx_dup_ck);
1699 if (options & F_QUIET)
1702 (void)printf("%d bytes from %s: ", cc, pr_addr(from, fromlen));
1704 switch (ntohs(ni->ni_code)) {
1705 case ICMP6_NI_SUCCESS:
1707 case ICMP6_NI_REFUSED:
1708 printf("refused, type 0x%x", ntohs(ni->ni_type));
1710 case ICMP6_NI_UNKNOWN:
1711 printf("unknown, type 0x%x", ntohs(ni->ni_type));
1714 printf("unknown code 0x%x, type 0x%x",
1715 ntohs(ni->ni_code), ntohs(ni->ni_type));
1719 switch (ntohs(ni->ni_qtype)) {
1721 printf("NodeInfo NOOP");
1723 case NI_QTYPE_SUPTYPES:
1724 pr_suptypes(ni, end - (u_char *)ni);
1726 case NI_QTYPE_NODEADDR:
1727 pr_nodeaddr(ni, end - (u_char *)ni);
1730 default: /* XXX: for backward compatibility */
1731 cp = (u_char *)ni + ICMP6_NIRLEN;
1732 if (buf[off + ICMP6_NIRLEN] ==
1733 cc - off - ICMP6_NIRLEN - 1)
1738 cp++; /* skip length */
1740 safeputc(*cp & 0xff);
1746 cp = dnsdecode((const u_char *)cp, end,
1747 (const u_char *)(ni + 1), dnsname,
1754 * name-lookup special handling for
1757 if (cp + 1 <= end && !*cp &&
1758 strlen(dnsname) > 0) {
1759 dnsname[strlen(dnsname) - 1] = '\0';
1762 printf("%s%s", i > 0 ? "," : "",
1766 if (options & F_VERBOSE) {
1771 (void)printf(" ("); /*)*/
1773 switch (ni->ni_code) {
1774 case ICMP6_NI_REFUSED:
1775 (void)printf("refused");
1778 case ICMP6_NI_UNKNOWN:
1779 (void)printf("unknown qtype");
1784 if ((end - (u_char *)ni) < ICMP6_NIRLEN) {
1785 /* case of refusion, unknown */
1790 memcpy(&t, &buf[off+ICMP6ECHOLEN+8], sizeof(t));
1791 ttl = (int32_t)ntohl(t);
1794 if (!(ni->ni_flags & NI_FQDN_FLAG_VALIDTTL)) {
1795 (void)printf("TTL=%d:meaningless",
1799 (void)printf("TTL=%d:invalid",
1802 (void)printf("TTL=%d", ttl);
1812 cp = (u_char *)ni + ICMP6_NIRLEN;
1821 if (buf[off + ICMP6_NIRLEN] !=
1822 cc - off - ICMP6_NIRLEN - 1 && oldfqdn) {
1825 (void)printf("invalid namelen:%d/%lu",
1826 buf[off + ICMP6_NIRLEN],
1827 (u_long)cc - off - ICMP6_NIRLEN - 1);
1837 /* We've got something other than an ECHOREPLY */
1838 if (!(options & F_VERBOSE))
1840 (void)printf("%d bytes from %s: ", cc, pr_addr(from, fromlen));
1844 if (!(options & F_FLOOD)) {
1845 (void)putchar('\n');
1846 if (options & F_VERBOSE)
1848 (void)fflush(stdout);
1854 pr_exthdrs(struct msghdr *mhdr)
1861 bufp = mhdr->msg_control;
1862 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
1863 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
1864 if (cm->cmsg_level != IPPROTO_IPV6)
1867 bufsize = CONTROLLEN - ((caddr_t)CMSG_DATA(cm) - (caddr_t)bufp);
1870 switch (cm->cmsg_type) {
1872 printf(" HbH Options: ");
1873 pr_ip6opt(CMSG_DATA(cm), (size_t)bufsize);
1876 #ifdef IPV6_RTHDRDSTOPTS
1877 case IPV6_RTHDRDSTOPTS:
1879 printf(" Dst Options: ");
1880 pr_ip6opt(CMSG_DATA(cm), (size_t)bufsize);
1883 printf(" Routing: ");
1884 pr_rthdr(CMSG_DATA(cm), (size_t)bufsize);
1891 pr_ip6opt(void *extbuf, size_t bufsize)
1893 struct ip6_hbh *ext;
1896 socklen_t extlen, len;
1902 ext = (struct ip6_hbh *)extbuf;
1903 extlen = (ext->ip6h_len + 1) * 8;
1904 printf("nxt %u, len %u (%lu bytes)\n", ext->ip6h_nxt,
1905 (unsigned int)ext->ip6h_len, (unsigned long)extlen);
1908 * Bounds checking on the ancillary data buffer:
1909 * subtract the size of a cmsg structure from the buffer size.
1911 if (bufsize < (extlen + CMSG_SPACE(0))) {
1912 extlen = bufsize - CMSG_SPACE(0);
1913 warnx("options truncated, showing only %u (total=%u)",
1914 (unsigned int)(extlen / 8 - 1),
1915 (unsigned int)(ext->ip6h_len));
1920 currentlen = inet6_opt_next(extbuf, extlen, currentlen,
1921 &type, &len, &databuf);
1922 if (currentlen == -1)
1926 * Note that inet6_opt_next automatically skips any padding
1931 offset = inet6_opt_get_val(databuf, offset,
1932 &value4, sizeof(value4));
1933 printf(" Jumbo Payload Opt: Length %u\n",
1934 (u_int32_t)ntohl(value4));
1936 case IP6OPT_ROUTER_ALERT:
1938 offset = inet6_opt_get_val(databuf, offset,
1939 &value2, sizeof(value2));
1940 printf(" Router Alert Opt: Type %u\n",
1944 printf(" Received Opt %u len %lu\n",
1945 type, (unsigned long)len);
1953 pr_rthdr(void *extbuf, size_t bufsize)
1955 struct in6_addr *in6;
1956 char ntopbuf[INET6_ADDRSTRLEN];
1957 struct ip6_rthdr *rh = (struct ip6_rthdr *)extbuf;
1958 int i, segments, origsegs, rthsize, size0, size1;
1960 /* print fixed part of the header */
1961 printf("nxt %u, len %u (%d bytes), type %u, ", rh->ip6r_nxt,
1962 rh->ip6r_len, (rh->ip6r_len + 1) << 3, rh->ip6r_type);
1963 if ((segments = inet6_rth_segments(extbuf)) >= 0) {
1964 printf("%d segments, ", segments);
1965 printf("%d left\n", rh->ip6r_segleft);
1967 printf("segments unknown, ");
1968 printf("%d left\n", rh->ip6r_segleft);
1973 * Bounds checking on the ancillary data buffer. When calculating
1974 * the number of items to show keep in mind:
1975 * - The size of the cmsg structure
1976 * - The size of one segment (the size of a Type 0 routing header)
1977 * - When dividing add a fudge factor of one in case the
1978 * dividend is not evenly divisible by the divisor
1980 rthsize = (rh->ip6r_len + 1) * 8;
1981 if (bufsize < (rthsize + CMSG_SPACE(0))) {
1982 origsegs = segments;
1983 size0 = inet6_rth_space(IPV6_RTHDR_TYPE_0, 0);
1984 size1 = inet6_rth_space(IPV6_RTHDR_TYPE_0, 1);
1985 segments -= (rthsize - (bufsize - CMSG_SPACE(0))) /
1986 (size1 - size0) + 1;
1987 warnx("segments truncated, showing only %d (total=%d)",
1988 segments, origsegs);
1991 for (i = 0; i < segments; i++) {
1992 in6 = inet6_rth_getaddr(extbuf, i);
1994 printf(" [%d]<NULL>\n", i);
1996 if (!inet_ntop(AF_INET6, in6, ntopbuf,
1998 strlcpy(ntopbuf, "?", sizeof(ntopbuf));
1999 printf(" [%d]%s\n", i, ntopbuf);
2008 pr_bitrange(u_int32_t v, int soff, int ii)
2015 /* shift till we have 0x01 */
2016 if ((v & 0x01) == 0) {
2018 printf("-%u", soff + off - 1);
2029 case 0x04: case 0x0c:
2040 /* we have 0x01 with us */
2041 for (i = 0; i < 32 - off; i++) {
2042 if ((v & (0x01 << i)) == 0)
2046 printf(" %u", soff + off);
2054 pr_suptypes(struct icmp6_nodeinfo *ni, size_t nilen)
2055 /* ni->qtype must be SUPTYPES */
2059 const u_char *cp, *end;
2062 u_int16_t words; /*32bit count*/
2065 #define MAXQTYPES (1 << 16)
2069 cp = (u_char *)(ni + 1);
2070 end = ((u_char *)ni) + nilen;
2074 printf("NodeInfo Supported Qtypes");
2075 if (options & F_VERBOSE) {
2076 if (ni->ni_flags & NI_SUPTYPE_FLAG_COMPRESS)
2077 printf(", compressed bitmap");
2079 printf(", raw bitmap");
2083 clen = (size_t)(end - cp);
2084 if ((ni->ni_flags & NI_SUPTYPE_FLAG_COMPRESS) == 0) {
2085 if (clen == 0 || clen > MAXQTYPES / 8 ||
2091 if (clen < sizeof(cbit) || clen % sizeof(v))
2093 memcpy(&cbit, cp, sizeof(cbit));
2094 if (sizeof(cbit) + ntohs(cbit.words) * sizeof(v) >
2098 clen = ntohs(cbit.words) * sizeof(v);
2099 if (cur + clen * 8 + (u_long)ntohs(cbit.skip) * 32 >
2104 for (off = 0; off < clen; off += sizeof(v)) {
2105 memcpy(&v, cp + off, sizeof(v));
2106 v = (u_int32_t)ntohl(v);
2107 b = pr_bitrange(v, (int)(cur + off * 8), b);
2109 /* flush the remaining bits */
2110 b = pr_bitrange(0, (int)(cur + off * 8), b);
2114 if ((ni->ni_flags & NI_SUPTYPE_FLAG_COMPRESS) != 0)
2115 cur += ntohs(cbit.skip) * 32;
2120 pr_nodeaddr(struct icmp6_nodeinfo *ni, int nilen)
2121 /* ni->qtype must be NODEADDR */
2123 u_char *cp = (u_char *)(ni + 1);
2124 char ntop_buf[INET6_ADDRSTRLEN];
2127 nilen -= sizeof(struct icmp6_nodeinfo);
2129 if (options & F_VERBOSE) {
2130 switch (ni->ni_code) {
2131 case ICMP6_NI_REFUSED:
2132 (void)printf("refused");
2134 case ICMP6_NI_UNKNOWN:
2135 (void)printf("unknown qtype");
2138 if (ni->ni_flags & NI_NODEADDR_FLAG_TRUNCATE)
2139 (void)printf(" truncated");
2143 printf(" no address\n");
2146 * In icmp-name-lookups 05 and later, TTL of each returned address
2147 * is contained in the resposne. We try to detect the version
2148 * by the length of the data, but note that the detection algorithm
2149 * is incomplete. We assume the latest draft by default.
2151 if (nilen % (sizeof(u_int32_t) + sizeof(struct in6_addr)) == 0)
2159 memcpy(&t, cp, sizeof(t));
2160 ttl = (u_int32_t)ntohl(t);
2161 cp += sizeof(u_int32_t);
2162 nilen -= sizeof(u_int32_t);
2165 if (inet_ntop(AF_INET6, cp, ntop_buf, sizeof(ntop_buf)) ==
2167 strlcpy(ntop_buf, "?", sizeof(ntop_buf));
2168 printf(" %s", ntop_buf);
2170 if (ttl == 0xffffffff) {
2172 * XXX: can this convention be applied to all
2173 * type of TTL (i.e. non-ND TTL)?
2175 printf("(TTL=infty)");
2178 printf("(TTL=%u)", ttl);
2182 nilen -= sizeof(struct in6_addr);
2183 cp += sizeof(struct in6_addr);
2188 get_hoplim(struct msghdr *mhdr)
2192 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
2193 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
2194 if (cm->cmsg_len == 0)
2197 if (cm->cmsg_level == IPPROTO_IPV6 &&
2198 cm->cmsg_type == IPV6_HOPLIMIT &&
2199 cm->cmsg_len == CMSG_LEN(sizeof(int))) {
2202 memcpy(&r, CMSG_DATA(cm), sizeof(r));
2210 static struct in6_pktinfo *
2211 get_rcvpktinfo(struct msghdr *mhdr)
2213 static struct in6_pktinfo pi;
2216 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
2217 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
2218 if (cm->cmsg_len == 0)
2221 if (cm->cmsg_level == IPPROTO_IPV6 &&
2222 cm->cmsg_type == IPV6_PKTINFO &&
2223 cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) {
2224 memcpy(&pi, CMSG_DATA(cm), sizeof(pi));
2233 get_pathmtu(struct msghdr *mhdr)
2235 #ifdef IPV6_RECVPATHMTU
2237 struct ip6_mtuinfo mtuctl;
2239 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
2240 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
2241 if (cm->cmsg_len == 0)
2244 if (cm->cmsg_level == IPPROTO_IPV6 &&
2245 cm->cmsg_type == IPV6_PATHMTU &&
2246 cm->cmsg_len == CMSG_LEN(sizeof(struct ip6_mtuinfo))) {
2247 memcpy(&mtuctl, CMSG_DATA(cm), sizeof(mtuctl));
2250 * If the notified destination is different from
2251 * the one we are pinging, just ignore the info.
2252 * We check the scope ID only when both notified value
2253 * and our own value have non-0 values, because we may
2254 * have used the default scope zone ID for sending,
2255 * in which case the scope ID value is 0.
2257 if (!IN6_ARE_ADDR_EQUAL(&mtuctl.ip6m_addr.sin6_addr,
2259 (mtuctl.ip6m_addr.sin6_scope_id &&
2260 dst.sin6_scope_id &&
2261 mtuctl.ip6m_addr.sin6_scope_id !=
2262 dst.sin6_scope_id)) {
2263 if ((options & F_VERBOSE) != 0) {
2264 printf("path MTU for %s is notified. "
2266 pr_addr((struct sockaddr *)&mtuctl.ip6m_addr,
2267 sizeof(mtuctl.ip6m_addr)));
2273 * Ignore an invalid MTU. XXX: can we just believe
2276 if (mtuctl.ip6m_mtu < IPV6_MMTU)
2279 /* notification for our destination. return the MTU. */
2280 return((int)mtuctl.ip6m_mtu);
2293 onint(int notused __unused)
2296 * When doing reverse DNS lookups, the seenint flag might not
2297 * be noticed for a while. Just exit if we get a second SIGINT.
2299 if ((options & F_HOSTNAME) && seenint != 0)
2300 _exit(nreceived ? 0 : 2);
2305 * Print out statistics.
2311 (void)printf("\n--- %s ping6 statistics ---\n", hostname);
2312 (void)printf("%ld packets transmitted, ", ntransmitted);
2313 (void)printf("%ld packets received, ", nreceived);
2315 (void)printf("+%ld duplicates, ", nrepeats);
2317 if (nreceived > ntransmitted)
2318 (void)printf("-- somebody's duplicating packets!");
2320 (void)printf("%.1f%% packet loss",
2321 ((((double)ntransmitted - nreceived) * 100.0) /
2325 printf(", %ld packets out of wait time", nrcvtimeout);
2326 (void)putchar('\n');
2327 if (nreceived && timing) {
2328 /* Only display average to microseconds */
2329 double num = nreceived + nrepeats;
2330 double avg = tsum / num;
2331 double dev = sqrt(tsumsq / num - avg * avg);
2333 "round-trip min/avg/max/std-dev = %.3f/%.3f/%.3f/%.3f ms\n",
2334 tmin, avg, tmax, dev);
2335 (void)fflush(stdout);
2337 (void)fflush(stdout);
2341 static const char *niqcode[] = {
2343 "DNS label", /*or empty*/
2348 static const char *nircode[] = {
2349 "Success", "Refused", "Unknown",
2355 * Print a descriptive string about an ICMP header.
2358 pr_icmph(struct icmp6_hdr *icp, u_char *end)
2360 char ntop_buf[INET6_ADDRSTRLEN];
2361 struct nd_redirect *red;
2362 struct icmp6_nodeinfo *ni;
2363 char dnsname[MAXDNAME + 1];
2367 switch (icp->icmp6_type) {
2368 case ICMP6_DST_UNREACH:
2369 switch (icp->icmp6_code) {
2370 case ICMP6_DST_UNREACH_NOROUTE:
2371 (void)printf("No Route to Destination\n");
2373 case ICMP6_DST_UNREACH_ADMIN:
2374 (void)printf("Destination Administratively "
2377 case ICMP6_DST_UNREACH_BEYONDSCOPE:
2378 (void)printf("Destination Unreachable Beyond Scope\n");
2380 case ICMP6_DST_UNREACH_ADDR:
2381 (void)printf("Destination Host Unreachable\n");
2383 case ICMP6_DST_UNREACH_NOPORT:
2384 (void)printf("Destination Port Unreachable\n");
2387 (void)printf("Destination Unreachable, Bad Code: %d\n",
2391 /* Print returned IP header information */
2392 pr_retip((struct ip6_hdr *)(icp + 1), end);
2394 case ICMP6_PACKET_TOO_BIG:
2395 (void)printf("Packet too big mtu = %d\n",
2396 (int)ntohl(icp->icmp6_mtu));
2397 pr_retip((struct ip6_hdr *)(icp + 1), end);
2399 case ICMP6_TIME_EXCEEDED:
2400 switch (icp->icmp6_code) {
2401 case ICMP6_TIME_EXCEED_TRANSIT:
2402 (void)printf("Time to live exceeded\n");
2404 case ICMP6_TIME_EXCEED_REASSEMBLY:
2405 (void)printf("Frag reassembly time exceeded\n");
2408 (void)printf("Time exceeded, Bad Code: %d\n",
2412 pr_retip((struct ip6_hdr *)(icp + 1), end);
2414 case ICMP6_PARAM_PROB:
2415 (void)printf("Parameter problem: ");
2416 switch (icp->icmp6_code) {
2417 case ICMP6_PARAMPROB_HEADER:
2418 (void)printf("Erroneous Header ");
2420 case ICMP6_PARAMPROB_NEXTHEADER:
2421 (void)printf("Unknown Nextheader ");
2423 case ICMP6_PARAMPROB_OPTION:
2424 (void)printf("Unrecognized Option ");
2427 (void)printf("Bad code(%d) ", icp->icmp6_code);
2430 (void)printf("pointer = 0x%02x\n",
2431 (u_int32_t)ntohl(icp->icmp6_pptr));
2432 pr_retip((struct ip6_hdr *)(icp + 1), end);
2434 case ICMP6_ECHO_REQUEST:
2435 (void)printf("Echo Request");
2436 /* XXX ID + Seq + Data */
2438 case ICMP6_ECHO_REPLY:
2439 (void)printf("Echo Reply");
2440 /* XXX ID + Seq + Data */
2442 case ICMP6_MEMBERSHIP_QUERY:
2443 (void)printf("Listener Query");
2445 case ICMP6_MEMBERSHIP_REPORT:
2446 (void)printf("Listener Report");
2448 case ICMP6_MEMBERSHIP_REDUCTION:
2449 (void)printf("Listener Done");
2451 case ND_ROUTER_SOLICIT:
2452 (void)printf("Router Solicitation");
2454 case ND_ROUTER_ADVERT:
2455 (void)printf("Router Advertisement");
2457 case ND_NEIGHBOR_SOLICIT:
2458 (void)printf("Neighbor Solicitation");
2460 case ND_NEIGHBOR_ADVERT:
2461 (void)printf("Neighbor Advertisement");
2464 red = (struct nd_redirect *)icp;
2465 (void)printf("Redirect\n");
2466 if (!inet_ntop(AF_INET6, &red->nd_rd_dst, ntop_buf,
2468 strlcpy(ntop_buf, "?", sizeof(ntop_buf));
2469 (void)printf("Destination: %s", ntop_buf);
2470 if (!inet_ntop(AF_INET6, &red->nd_rd_target, ntop_buf,
2472 strlcpy(ntop_buf, "?", sizeof(ntop_buf));
2473 (void)printf(" New Target: %s", ntop_buf);
2475 case ICMP6_NI_QUERY:
2476 (void)printf("Node Information Query");
2477 /* XXX ID + Seq + Data */
2478 ni = (struct icmp6_nodeinfo *)icp;
2479 l = end - (u_char *)(ni + 1);
2481 switch (ntohs(ni->ni_qtype)) {
2483 (void)printf("NOOP");
2485 case NI_QTYPE_SUPTYPES:
2486 (void)printf("Supported qtypes");
2489 (void)printf("DNS name");
2491 case NI_QTYPE_NODEADDR:
2492 (void)printf("nodeaddr");
2494 case NI_QTYPE_IPV4ADDR:
2495 (void)printf("IPv4 nodeaddr");
2498 (void)printf("unknown qtype");
2501 if (options & F_VERBOSE) {
2502 switch (ni->ni_code) {
2503 case ICMP6_NI_SUBJ_IPV6:
2504 if (l == sizeof(struct in6_addr) &&
2505 inet_ntop(AF_INET6, ni + 1, ntop_buf,
2506 sizeof(ntop_buf)) != NULL) {
2507 (void)printf(", subject=%s(%s)",
2508 niqcode[ni->ni_code], ntop_buf);
2511 /* backward compat to -W */
2512 (void)printf(", oldfqdn");
2514 (void)printf(", invalid");
2518 case ICMP6_NI_SUBJ_FQDN:
2519 if (end == (u_char *)(ni + 1)) {
2520 (void)printf(", no subject");
2523 printf(", subject=%s", niqcode[ni->ni_code]);
2524 cp = (const u_char *)(ni + 1);
2525 cp = dnsdecode(cp, end, NULL, dnsname,
2528 printf("(%s)", dnsname);
2530 printf("(invalid)");
2532 case ICMP6_NI_SUBJ_IPV4:
2533 if (l == sizeof(struct in_addr) &&
2534 inet_ntop(AF_INET, ni + 1, ntop_buf,
2535 sizeof(ntop_buf)) != NULL) {
2536 (void)printf(", subject=%s(%s)",
2537 niqcode[ni->ni_code], ntop_buf);
2539 (void)printf(", invalid");
2542 (void)printf(", invalid");
2547 case ICMP6_NI_REPLY:
2548 (void)printf("Node Information Reply");
2549 /* XXX ID + Seq + Data */
2550 ni = (struct icmp6_nodeinfo *)icp;
2552 switch (ntohs(ni->ni_qtype)) {
2554 (void)printf("NOOP");
2556 case NI_QTYPE_SUPTYPES:
2557 (void)printf("Supported qtypes");
2560 (void)printf("DNS name");
2562 case NI_QTYPE_NODEADDR:
2563 (void)printf("nodeaddr");
2565 case NI_QTYPE_IPV4ADDR:
2566 (void)printf("IPv4 nodeaddr");
2569 (void)printf("unknown qtype");
2572 if (options & F_VERBOSE) {
2573 if (ni->ni_code > nitems(nircode))
2574 printf(", invalid");
2576 printf(", %s", nircode[ni->ni_code]);
2580 (void)printf("Bad ICMP type: %d", icp->icmp6_type);
2586 * Print an IP6 header.
2589 pr_iph(struct ip6_hdr *ip6)
2591 u_int32_t flow = ip6->ip6_flow & IPV6_FLOWLABEL_MASK;
2593 char ntop_buf[INET6_ADDRSTRLEN];
2595 tc = *(&ip6->ip6_vfc + 1); /* XXX */
2596 tc = (tc >> 4) & 0x0f;
2597 tc |= (ip6->ip6_vfc << 4);
2599 printf("Vr TC Flow Plen Nxt Hlim\n");
2600 printf(" %1x %02x %05x %04x %02x %02x\n",
2601 (ip6->ip6_vfc & IPV6_VERSION_MASK) >> 4, tc, (u_int32_t)ntohl(flow),
2602 ntohs(ip6->ip6_plen), ip6->ip6_nxt, ip6->ip6_hlim);
2603 if (!inet_ntop(AF_INET6, &ip6->ip6_src, ntop_buf, sizeof(ntop_buf)))
2604 strlcpy(ntop_buf, "?", sizeof(ntop_buf));
2605 printf("%s->", ntop_buf);
2606 if (!inet_ntop(AF_INET6, &ip6->ip6_dst, ntop_buf, sizeof(ntop_buf)))
2607 strlcpy(ntop_buf, "?", sizeof(ntop_buf));
2608 printf("%s\n", ntop_buf);
2613 * Return an ascii host address as a dotted quad and optionally with
2617 pr_addr(struct sockaddr *addr, int addrlen)
2619 static char buf[NI_MAXHOST];
2622 if ((options & F_HOSTNAME) == 0)
2623 flag |= NI_NUMERICHOST;
2625 if (cap_getnameinfo(capdns, addr, addrlen, buf, sizeof(buf), NULL, 0,
2634 * Dump some info on a returned (via ICMPv6) IPv6 packet.
2637 pr_retip(struct ip6_hdr *ip6, u_char *end)
2639 u_char *cp = (u_char *)ip6, nh;
2642 if ((size_t)(end - (u_char *)ip6) < sizeof(*ip6)) {
2647 hlen = sizeof(*ip6);
2651 while (end - cp >= 8) {
2655 case IPPROTO_HOPOPTS:
2657 hlen = (((struct ip6_hbh *)cp)->ip6h_len+1) << 3;
2658 nh = ((struct ip6_hbh *)cp)->ip6h_nxt;
2660 case IPPROTO_DSTOPTS:
2662 hlen = (((struct ip6_dest *)cp)->ip6d_len+1) << 3;
2663 nh = ((struct ip6_dest *)cp)->ip6d_nxt;
2665 case IPPROTO_FRAGMENT:
2667 hlen = sizeof(struct ip6_frag);
2668 nh = ((struct ip6_frag *)cp)->ip6f_nxt;
2670 case IPPROTO_ROUTING:
2672 hlen = (((struct ip6_rthdr *)cp)->ip6r_len+1) << 3;
2673 nh = ((struct ip6_rthdr *)cp)->ip6r_nxt;
2678 memcpy(&ah, cp, sizeof(ah));
2679 hlen = (ah.ah_len+2) << 2;
2683 case IPPROTO_ICMPV6:
2684 printf("ICMP6: type = %d, code = %d\n",
2691 printf("TCP: from port %u, to port %u (decimal)\n",
2692 (*cp * 256 + *(cp + 1)),
2693 (*(cp + 2) * 256 + *(cp + 3)));
2696 printf("UDP: from port %u, to port %u (decimal)\n",
2697 (*cp * 256 + *(cp + 1)),
2698 (*(cp + 2) * 256 + *(cp + 3)));
2701 printf("Unknown Header(%d)\n", nh);
2705 if ((cp += hlen) >= end)
2720 fill(char *bp, char *patp)
2726 for (cp = patp; *cp; cp++)
2728 errx(1, "patterns must be specified as hex digits");
2730 "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
2731 &pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6],
2732 &pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12],
2733 &pat[13], &pat[14], &pat[15]);
2738 (size_t)kk <= MAXDATALEN - 8 + sizeof(struct tv32) + ii;
2740 for (jj = 0; jj < ii; ++jj)
2741 bp[jj + kk] = pat[jj];
2742 if (!(options & F_QUIET)) {
2743 (void)printf("PATTERN: 0x");
2744 for (jj = 0; jj < ii; ++jj)
2745 (void)printf("%02x", bp[jj] & 0xFF);
2751 #ifdef IPSEC_POLICY_IPSEC
2753 setpolicy(int so __unused, char *policy)
2758 return 0; /* ignore */
2760 buf = ipsec_set_policy(policy, strlen(policy));
2762 errx(1, "%s", ipsec_strerror());
2763 if (setsockopt(ssend, IPPROTO_IPV6, IPV6_IPSEC_POLICY, buf,
2764 ipsec_get_policylen(buf)) < 0)
2765 warnx("Unable to set IPsec policy");
2774 nigroup(char *name, int nig_oldmcprefix)
2779 u_int8_t digest[16];
2782 char hbuf[NI_MAXHOST];
2783 struct in6_addr in6;
2786 p = strchr(name, '.');
2788 p = name + strlen(name);
2790 if (l > 63 || l > sizeof(hbuf) - 1)
2791 return NULL; /*label too long*/
2792 strncpy(hbuf, name, l);
2793 hbuf[(int)l] = '\0';
2795 for (q = name; *q; q++) {
2796 if (isupper(*(unsigned char *)q))
2797 *q = tolower(*(unsigned char *)q);
2800 /* generate 16 bytes of pseudo-random value. */
2801 memset(&ctxt, 0, sizeof(ctxt));
2804 MD5Update(&ctxt, &c, sizeof(c));
2805 MD5Update(&ctxt, (unsigned char *)name, l);
2806 MD5Final(digest, &ctxt);
2808 if (nig_oldmcprefix) {
2809 /* draft-ietf-ipngwg-icmp-name-lookup */
2810 valid = inet_pton(AF_INET6, "ff02::2:0000:0000", &in6);
2813 valid = inet_pton(AF_INET6, "ff02::2:ff00:0000", &in6);
2816 return NULL; /*XXX*/
2818 if (nig_oldmcprefix) {
2819 /* draft-ietf-ipngwg-icmp-name-lookup */
2820 bcopy(digest, &in6.s6_addr[12], 4);
2823 bcopy(digest, &in6.s6_addr[13], 3);
2826 if (inet_ntop(AF_INET6, &in6, hbuf, sizeof(hbuf)) == NULL)
2829 return strdup(hbuf);
2835 (void)fprintf(stderr,
2836 #if defined(IPSEC) && !defined(IPSEC_POLICY_IPSEC)
2841 #if defined(IPSEC) && !defined(IPSEC_POLICY_IPSEC)
2845 #ifdef IPV6_USE_MIN_MTU
2849 "[-b bufsiz] [-c count] [-e gateway]\n"
2850 " [-I interface] [-i wait] [-k addrtype] [-l preload] "
2853 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
2856 " [-S sourceaddr] [-s packetsize]\n"
2857 " [-t timeout] [-W waittime] [hops ...] host\n");
2861 static cap_channel_t *
2864 cap_channel_t *capcas, *capdnsloc;
2866 const char *types[2];
2869 capcas = cap_init();
2871 err(1, "unable to create casper process");
2872 capdnsloc = cap_service_open(capcas, "system.dns");
2873 /* Casper capability no longer needed. */
2875 if (capdnsloc == NULL)
2876 err(1, "unable to open system.dns service");
2878 types[0] = "NAME2ADDR";
2879 types[1] = "ADDR2NAME";
2880 if (cap_dns_type_limit(capdnsloc, types, nitems(types)) < 0)
2881 err(1, "unable to limit access to system.dns service");
2882 families[0] = AF_INET6;
2883 if (cap_dns_family_limit(capdnsloc, families, nitems(families)) < 0)
2884 err(1, "unable to limit access to system.dns service");