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