1 /* $KAME: traceroute6.c,v 1.68 2004/01/25 11:16:12 suz 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
35 * Copyright (c) 1990, 1993
36 * The Regents of the University of California. All rights reserved.
38 * This code is derived from software contributed to Berkeley by
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
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. Neither the name of the University nor the names of its contributors
50 * may be used to endorse or promote products derived from this software
51 * without specific prior written permission.
53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
67 static const char copyright[] =
68 "@(#) Copyright (c) 1990, 1993\n\
69 The Regents of the University of California. All rights reserved.\n";
74 static char sccsid[] = "@(#)traceroute.c 8.1 (Berkeley) 6/6/93";
79 * traceroute host - trace the route ip packets follow going to "host".
81 * Attempt to trace the route an ip packet would follow to some
82 * internet host. We find out intermediate hops by launching probe
83 * packets with a small ttl (time to live) then listening for an
84 * icmp "time exceeded" reply from a gateway. We start our probes
85 * with a ttl of one and increase by one until we get an icmp "port
86 * unreachable" (which means we got to "host") or hit a max (which
87 * defaults to 30 hops & can be changed with the -m flag). Three
88 * probes (change with -q flag) are sent at each ttl setting and a
89 * line is printed showing the ttl, address of the gateway and
90 * round trip time of each probe. If the probe answers come from
91 * different gateways, the address of each responding system will
92 * be printed. If there is no response within a 5 sec. timeout
93 * interval (changed with the -w flag), a "*" is printed for that
96 * Probe packets are UDP format. We don't want the destination
97 * host to process them so the destination port is set to an
98 * unlikely value (if some clod on the destination is using that
99 * value, it can be changed with the -p flag).
101 * A sample use might be:
103 * [yak 71]% traceroute nis.nsf.net.
104 * traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 56 byte packet
105 * 1 helios.ee.lbl.gov (128.3.112.1) 19 ms 19 ms 0 ms
106 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
107 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
108 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 39 ms
109 * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 39 ms 39 ms 39 ms
110 * 6 128.32.197.4 (128.32.197.4) 40 ms 59 ms 59 ms
111 * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 59 ms
112 * 8 129.140.70.13 (129.140.70.13) 99 ms 99 ms 80 ms
113 * 9 129.140.71.6 (129.140.71.6) 139 ms 239 ms 319 ms
114 * 10 129.140.81.7 (129.140.81.7) 220 ms 199 ms 199 ms
115 * 11 nic.merit.edu (35.1.1.48) 239 ms 239 ms 239 ms
117 * Note that lines 2 & 3 are the same. This is due to a buggy
118 * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
119 * packets with a zero ttl.
121 * A more interesting example is:
123 * [yak 72]% traceroute allspice.lcs.mit.edu.
124 * traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max
125 * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
126 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 19 ms 19 ms
127 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 19 ms
128 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 19 ms 39 ms 39 ms
129 * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 20 ms 39 ms 39 ms
130 * 6 128.32.197.4 (128.32.197.4) 59 ms 119 ms 39 ms
131 * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 39 ms
132 * 8 129.140.70.13 (129.140.70.13) 80 ms 79 ms 99 ms
133 * 9 129.140.71.6 (129.140.71.6) 139 ms 139 ms 159 ms
134 * 10 129.140.81.7 (129.140.81.7) 199 ms 180 ms 300 ms
135 * 11 129.140.72.17 (129.140.72.17) 300 ms 239 ms 239 ms
137 * 13 128.121.54.72 (128.121.54.72) 259 ms 499 ms 279 ms
142 * 18 ALLSPICE.LCS.MIT.EDU (18.26.0.115) 339 ms 279 ms 279 ms
144 * (I start to see why I'm having so much trouble with mail to
145 * MIT.) Note that the gateways 12, 14, 15, 16 & 17 hops away
146 * either don't send ICMP "time exceeded" messages or send them
147 * with a ttl too small to reach us. 14 - 17 are running the
148 * MIT C Gateway code that doesn't send "time exceeded"s. God
149 * only knows what's going on with 12.
151 * The silent gateway 12 in the above may be the result of a bug in
152 * the 4.[23]BSD network code (and its derivatives): 4.x (x <= 3)
153 * sends an unreachable message using whatever ttl remains in the
154 * original datagram. Since, for gateways, the remaining ttl is
155 * zero, the icmp "time exceeded" is guaranteed to not make it back
156 * to us. The behavior of this bug is slightly more interesting
157 * when it appears on the destination system:
159 * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
160 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 39 ms
161 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 39 ms 19 ms
162 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 19 ms
163 * 5 ccn-nerif35.Berkeley.EDU (128.32.168.35) 39 ms 39 ms 39 ms
164 * 6 csgw.Berkeley.EDU (128.32.133.254) 39 ms 59 ms 39 ms
171 * 13 rip.Berkeley.EDU (128.32.131.22) 59 ms ! 39 ms ! 39 ms !
173 * Notice that there are 12 "gateways" (13 is the final
174 * destination) and exactly the last half of them are "missing".
175 * What's really happening is that rip (a Sun-3 running Sun OS3.5)
176 * is using the ttl from our arriving datagram as the ttl in its
177 * icmp reply. So, the reply will time out on the return path
178 * (with no notice sent to anyone since icmp's aren't sent for
179 * icmp's) until we probe with a ttl that's at least twice the path
180 * length. I.e., rip is really only 7 hops away. A reply that
181 * returns with a ttl of 1 is a clue this problem exists.
182 * Traceroute prints a "!" after the time if the ttl is <= 1.
183 * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
184 * non-standard (HPUX) software, expect to see this problem
185 * frequently and/or take care picking the target host of your
188 * Other possible annotations after the time are !H, !N, !P (got a host,
189 * network or protocol unreachable, respectively), !S or !F (source
190 * route failed or fragmentation needed -- neither of these should
191 * ever occur and the associated gateway is busted if you see one). If
192 * almost all the probes result in some kind of unreachable, traceroute
193 * will give up and exit.
197 * This program must be run by root or be setuid. (I suggest that
198 * you *don't* make it setuid -- casual use could result in a lot
199 * of unnecessary traffic on our poor, congested nets.)
201 * This program requires a kernel mod that does not appear in any
202 * system available from Berkeley: A raw ip socket using proto
203 * IPPROTO_RAW must interpret the data sent as an ip datagram (as
204 * opposed to data to be wrapped in an ip datagram). See the README
205 * file that came with the source to this program for a description
206 * of the mods I made to /sys/netinet/raw_ip.c. Your mileage may
207 * vary. But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
208 * MODIFIED TO RUN THIS PROGRAM.
210 * The udp port usage may appear bizarre (well, ok, it is bizarre).
211 * The problem is that an icmp message only contains 8 bytes of
212 * data from the original datagram. 8 bytes is the size of a udp
213 * header so, if we want to associate replies with the original
214 * datagram, the necessary information must be encoded into the
215 * udp header (the ip id could be used but there's no way to
216 * interlock with the kernel's assignment of ip id's and, anyway,
217 * it would have taken a lot more kernel hacking to allow this
218 * code to set the ip id). So, to allow two or more users to
219 * use traceroute simultaneously, we use this task's pid as the
220 * source port (the high bit is set to move the port number out
221 * of the "likely" range). To keep track of which probe is being
222 * replied to (so times and/or hop counts don't get confused by a
223 * reply that was delayed in transit), we increment the destination
224 * port number before each probe.
226 * Don't use this as a coding example. I was trying to find a
227 * routing problem and this code sort-of popped out after 48 hours
228 * without sleep. I was amazed it ever compiled, much less ran.
230 * I stole the idea for this program from Steve Deering. Since
231 * the first release, I've learned that had I attended the right
232 * IETF working group meetings, I also could have stolen it from Guy
233 * Almes or Matt Mathis. I don't know (or care) who came up with
234 * the idea first. I envy the originators' perspicacity and I'm
235 * glad they didn't keep the idea a secret.
237 * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
238 * enhancements to the original distribution.
240 * I've hacked up a round-trip-route version of this that works by
241 * sending a loose-source-routed udp datagram through the destination
242 * back to yourself. Unfortunately, SO many gateways botch source
243 * routing, the thing is almost worthless. Maybe one day...
245 * -- Van Jacobson (van@helios.ee.lbl.gov)
246 * Tue Dec 20 03:50:13 PST 1988
249 #include <sys/param.h>
250 #include <sys/capsicum.h>
251 #include <sys/time.h>
252 #include <sys/socket.h>
254 #include <sys/file.h>
255 #include <sys/ioctl.h>
256 #include <sys/sysctl.h>
258 #include <netinet/in.h>
260 #include <arpa/inet.h>
262 #include <libcasper.h>
263 #include <casper/cap_dns.h>
264 #include <capsicum_helpers.h>
277 #include <netinet/ip6.h>
278 #include <netinet/icmp6.h>
279 #include <netinet/sctp.h>
280 #include <netinet/sctp_header.h>
281 #include <netinet/tcp.h>
282 #include <netinet/udp.h>
285 #include <net/route.h>
286 #include <netipsec/ipsec.h>
291 #define DUMMY_PORT 10010
293 #define MAXPACKET 65535 /* max ip packet size */
295 static u_char packet[512]; /* last inbound (icmp) packet */
296 static char *outpacket; /* last output packet */
298 int main(int, char *[]);
299 int wait_for_reply(int, struct msghdr *);
300 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
301 int setpolicy(int so, char *policy);
303 void send_probe(int, u_long);
304 void *get_uphdr(struct ip6_hdr *, u_char *);
305 void capdns_open(void);
306 int get_hoplim(struct msghdr *);
307 double deltaT(struct timeval *, struct timeval *);
308 const char *pr_type(int);
309 int packet_ok(struct msghdr *, int, int, u_char *, u_char *);
310 void print(struct msghdr *, int);
311 const char *inetname(struct sockaddr *);
312 u_int32_t sctp_crc32c(void *, u_int32_t);
313 u_int16_t in_cksum(u_int16_t *addr, int);
314 u_int16_t udp_cksum(struct sockaddr_in6 *, struct sockaddr_in6 *,
316 u_int16_t tcp_chksum(struct sockaddr_in6 *, struct sockaddr_in6 *,
320 static int rcvsock; /* receive (icmp) socket file descriptor */
321 static int sndsock; /* send (raw/udp) socket file descriptor */
323 static struct msghdr rcvmhdr;
324 static struct iovec rcviov[2];
326 static struct in6_pktinfo *rcvpktinfo;
328 static struct sockaddr_in6 Src, Dst, Rcv;
329 static u_long datalen = 20; /* How much data */
330 #define ICMP6ECHOLEN 8
331 /* XXX: 2064 = 127(max hops in type 0 rthdr) * sizeof(ip6_hdr) + 16(margin) */
332 static char rtbuf[2064];
333 static struct ip6_rthdr *rth;
334 static struct cmsghdr *cmsg;
336 static char *source = NULL;
337 static char *hostname;
339 static cap_channel_t *capdns;
341 static u_long nprobes = 3;
342 static u_long first_hop = 1;
343 static u_long max_hops = 30;
344 static u_int16_t srcport;
345 static u_int16_t port = 32768+666; /* start udp dest port # for probe packets */
346 static u_int16_t ident;
347 static int tclass = -1;
348 static int options; /* socket options */
350 static int waittime = 5; /* time to wait for response (in seconds) */
351 static int nflag; /* print addresses numerically */
352 static int useproto = IPPROTO_UDP; /* protocol to use to send packet */
353 static int lflag; /* print both numerical address & hostname */
354 static int as_path; /* print as numbers for each hop */
355 static char *as_server = NULL;
359 main(int argc, char *argv[])
361 int mib[4] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_DEFHLIM };
362 char hbuf[NI_MAXHOST], src0[NI_MAXHOST], *ep;
363 int ch, i, on = 1, seq, rcvcmsglen, error;
364 struct addrinfo hints, *res;
365 static u_char *rcvcmsgbuf;
366 u_long probe, hops, lport, ltclass;
371 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
372 char ipsec_inpolicy[] = "in bypass";
373 char ipsec_outpolicy[] = "out bypass";
382 if ((rcvsock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) {
383 perror("socket(ICMPv6)");
388 (void) sysctl(mib, sizeof(mib)/sizeof(mib[0]), &i, &size, NULL, 0);
391 /* specify to tell receiving interface */
392 #ifdef IPV6_RECVPKTINFO
393 if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
395 err(1, "setsockopt(IPV6_RECVPKTINFO)");
396 #else /* old adv. API */
397 if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_PKTINFO, &on,
399 err(1, "setsockopt(IPV6_PKTINFO)");
402 /* specify to tell value of hoplimit field of received IP6 hdr */
403 #ifdef IPV6_RECVHOPLIMIT
404 if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on,
406 err(1, "setsockopt(IPV6_RECVHOPLIMIT)");
407 #else /* old adv. API */
408 if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_HOPLIMIT, &on,
410 err(1, "setsockopt(IPV6_HOPLIMIT)");
414 ident = htons(getpid() & 0xffff); /* same as ping6 */
416 while ((ch = getopt(argc, argv, "aA:df:g:Ilm:nNp:q:rs:St:TUvw:")) != -1)
431 first_hop = strtoul(optarg, &ep, 0);
432 if (errno || !*optarg || *ep || first_hop > 255) {
434 "traceroute6: invalid min hoplimit.\n");
439 /* XXX use after capability mode is entered */
440 hp = getipnodebyname(optarg, AF_INET6, 0, &h_errno);
443 "traceroute6: unknown host %s\n", optarg);
448 * XXX: We can't detect the number of
449 * intermediate nodes yet.
451 if ((rth = inet6_rth_init((void *)rtbuf,
452 sizeof(rtbuf), IPV6_RTHDR_TYPE_0,
455 "inet6_rth_init failed.\n");
459 if (inet6_rth_add((void *)rth,
460 (struct in6_addr *)hp->h_addr)) {
462 "inet6_rth_add failed for %s\n",
469 useproto = IPPROTO_ICMPV6;
477 max_hops = strtoul(optarg, &ep, 0);
478 if (errno || !*optarg || *ep || max_hops > 255) {
480 "traceroute6: invalid max hoplimit.\n");
488 useproto = IPPROTO_NONE;
493 lport = strtoul(optarg, &ep, 0);
494 if (errno || !*optarg || *ep) {
495 fprintf(stderr, "traceroute6: invalid port.\n");
498 if (lport == 0 || lport != (lport & 0xffff)) {
500 "traceroute6: port out of range.\n");
503 port = lport & 0xffff;
508 nprobes = strtoul(optarg, &ep, 0);
509 if (errno || !*optarg || *ep) {
511 "traceroute6: invalid nprobes.\n");
516 "traceroute6: nprobes must be >0.\n");
521 options |= SO_DONTROUTE;
525 * set the ip source address of the outbound
526 * probe (e.g., on a multi-homed host).
531 useproto = IPPROTO_SCTP;
536 ltclass = strtoul(optarg, &ep, 0);
537 if (errno || !*optarg || *ep || ltclass > 255) {
539 "traceroute6: invalid traffic class.\n");
542 tclass = (int)ltclass;
545 useproto = IPPROTO_TCP;
548 useproto = IPPROTO_UDP;
556 waittime = strtoul(optarg, &ep, 0);
557 if (errno || !*optarg || *ep) {
559 "traceroute6: invalid wait time.\n");
564 "traceroute6: wait must be >= 1 sec.\n");
575 * Open socket to send probe packets.
583 if ((sndsock = socket(AF_INET6, SOCK_RAW, useproto)) < 0) {
584 perror("socket(SOCK_RAW)");
589 fprintf(stderr, "traceroute6: unknown probe protocol %d\n",
593 if (max_hops < first_hop) {
595 "traceroute6: max hoplimit must be larger than first hoplimit.\n");
601 if (setresuid(uid, uid, uid) == -1) {
607 if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_TCLASS, &tclass,
608 sizeof(int)) == -1) {
609 perror("setsockopt(IPV6_TCLASS)");
614 if (argc < 1 || argc > 2)
618 setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
623 memset(&hints, 0, sizeof(hints));
624 hints.ai_family = PF_INET6;
625 hints.ai_socktype = SOCK_RAW;
626 hints.ai_protocol = IPPROTO_ICMPV6;
627 hints.ai_flags = AI_CANONNAME;
629 error = cap_getaddrinfo(capdns, *argv, NULL, &hints, &res);
633 "traceroute6: %s\n", gai_strerror(error));
636 if (res->ai_addrlen != sizeof(Dst)) {
638 "traceroute6: size of sockaddr mismatch\n");
641 memcpy(&Dst, res->ai_addr, res->ai_addrlen);
642 hostname = res->ai_canonname ? strdup(res->ai_canonname) : *argv;
644 fprintf(stderr, "traceroute6: not enough core\n");
648 if (cap_getnameinfo(capdns, res->ai_addr, res->ai_addrlen, hbuf,
649 sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
650 strlcpy(hbuf, "?", sizeof(hbuf));
651 fprintf(stderr, "traceroute6: Warning: %s has multiple "
652 "addresses; using %s\n", hostname, hbuf);
658 datalen = strtoul(*argv, &ep, 0);
661 "traceroute6: invalid packet length.\n");
667 minlen = ICMP6ECHOLEN;
670 minlen = sizeof(struct udphdr);
677 minlen = sizeof(struct sctphdr);
680 minlen = sizeof(struct tcphdr);
683 fprintf(stderr, "traceroute6: unknown probe protocol %d.\n",
687 if (datalen < minlen)
689 else if (datalen >= MAXPACKET) {
691 "traceroute6: packet size must be %zu <= s < %d.\n",
695 if ((useproto == IPPROTO_SCTP) && (datalen & 3)) {
697 "traceroute6: packet size must be a multiple of 4.\n");
700 outpacket = malloc(datalen);
705 (void) bzero((char *)outpacket, datalen);
707 /* initialize msghdr for receiving packets */
708 rcviov[0].iov_base = (caddr_t)packet;
709 rcviov[0].iov_len = sizeof(packet);
710 rcvmhdr.msg_name = (caddr_t)&Rcv;
711 rcvmhdr.msg_namelen = sizeof(Rcv);
712 rcvmhdr.msg_iov = rcviov;
713 rcvmhdr.msg_iovlen = 1;
714 rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
715 CMSG_SPACE(sizeof(int));
716 if ((rcvcmsgbuf = malloc(rcvcmsglen)) == NULL) {
717 fprintf(stderr, "traceroute6: malloc failed\n");
720 rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf;
721 rcvmhdr.msg_controllen = rcvcmsglen;
723 if (options & SO_DEBUG)
724 (void) setsockopt(rcvsock, SOL_SOCKET, SO_DEBUG,
725 (char *)&on, sizeof(on));
726 if (options & SO_DONTROUTE)
727 (void) setsockopt(rcvsock, SOL_SOCKET, SO_DONTROUTE,
728 (char *)&on, sizeof(on));
729 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
731 * do not raise error even if setsockopt fails, kernel may have ipsec
734 if (setpolicy(rcvsock, ipsec_inpolicy) < 0)
735 errx(1, "%s", ipsec_strerror());
736 if (setpolicy(rcvsock, ipsec_outpolicy) < 0)
737 errx(1, "%s", ipsec_strerror());
740 int level = IPSEC_LEVEL_NONE;
742 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, &level,
744 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_ESP_NETWORK_LEVEL, &level,
746 #ifdef IP_AUTH_TRANS_LEVEL
747 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, &level,
750 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_LEVEL, &level,
753 #ifdef IP_AUTH_NETWORK_LEVEL
754 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_NETWORK_LEVEL, &level,
758 #endif /* !(IPSEC && IPSEC_POLICY_IPSEC) */
764 if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&i,
766 perror("setsockopt(SO_SNDBUF)");
769 #endif /* SO_SNDBUF */
770 if (options & SO_DEBUG)
771 (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG,
772 (char *)&on, sizeof(on));
773 if (options & SO_DONTROUTE)
774 (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE,
775 (char *)&on, sizeof(on));
776 if (rth) {/* XXX: there is no library to finalize the header... */
777 rth->ip6r_len = rth->ip6r_segleft * 2;
778 if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_RTHDR,
779 (void *)rth, (rth->ip6r_len + 1) << 3)) {
780 fprintf(stderr, "setsockopt(IPV6_RTHDR): %s\n",
785 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
787 * do not raise error even if setsockopt fails, kernel may have ipsec
790 if (setpolicy(sndsock, ipsec_inpolicy) < 0)
791 errx(1, "%s", ipsec_strerror());
792 if (setpolicy(sndsock, ipsec_outpolicy) < 0)
793 errx(1, "%s", ipsec_strerror());
796 int level = IPSEC_LEVEL_BYPASS;
798 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, &level,
800 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_ESP_NETWORK_LEVEL, &level,
802 #ifdef IP_AUTH_TRANS_LEVEL
803 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, &level,
806 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_LEVEL, &level,
809 #ifdef IP_AUTH_NETWORK_LEVEL
810 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_NETWORK_LEVEL, &level,
814 #endif /* !(IPSEC && IPSEC_POLICY_IPSEC) */
819 bzero(&Src, sizeof(Src));
821 memset(&hints, 0, sizeof(hints));
822 hints.ai_family = AF_INET6;
823 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
824 hints.ai_flags = AI_NUMERICHOST;
825 error = cap_getaddrinfo(capdns, source, "0", &hints, &res);
827 printf("traceroute6: %s: %s\n", source,
828 gai_strerror(error));
831 if (res->ai_addrlen > sizeof(Src)) {
832 printf("traceroute6: %s: %s\n", source,
833 gai_strerror(error));
836 memcpy(&Src, res->ai_addr, res->ai_addrlen);
839 struct sockaddr_in6 Nxt;
844 Nxt.sin6_port = htons(DUMMY_PORT);
846 bcopy(inet6_rthdr_getaddr(cmsg, 1), &Nxt.sin6_addr,
847 sizeof(Nxt.sin6_addr));
848 if ((dummy = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
852 if (connect(dummy, (struct sockaddr *)&Nxt, Nxt.sin6_len) < 0) {
857 if (getsockname(dummy, (struct sockaddr *)&Src, &len) < 0) {
858 perror("getsockname");
861 if (cap_getnameinfo(capdns, (struct sockaddr *)&Src, Src.sin6_len,
862 src0, sizeof(src0), NULL, 0, NI_NUMERICHOST)) {
863 fprintf(stderr, "getnameinfo failed for source\n");
870 Src.sin6_port = htons(0);
871 if (bind(sndsock, (struct sockaddr *)&Src, Src.sin6_len) < 0) {
880 if (getsockname(sndsock, (struct sockaddr *)&Src, &len) < 0) {
881 perror("getsockname");
884 srcport = ntohs(Src.sin6_port);
888 asn = as_setup(as_server);
891 "traceroute6: as_setup failed, AS# lookups"
893 (void)fflush(stderr);
901 if (cap_getnameinfo(capdns, (struct sockaddr *)&Dst, Dst.sin6_len, hbuf,
902 sizeof(hbuf), NULL, 0, NI_NUMERICHOST))
903 strlcpy(hbuf, "(invalid)", sizeof(hbuf));
904 fprintf(stderr, "traceroute6");
905 fprintf(stderr, " to %s (%s)", hostname, hbuf);
907 fprintf(stderr, " from %s", source);
908 fprintf(stderr, ", %lu hops max, %lu byte packets\n",
910 datalen + ((useproto == IPPROTO_UDP) ? sizeof(struct udphdr) : 0));
911 (void) fflush(stderr);
914 printf("Skipping %lu intermediate hops\n", first_hop - 1);
916 if (connect(sndsock, (struct sockaddr *)&Dst,
918 fprintf(stderr, "connect: %s\n", strerror(errno));
923 * Here we enter capability mode. Further down access to global
924 * namespaces (e.g filesystem) is restricted (see capsicum(4)).
925 * We must connect(2) our socket before this point.
927 if (caph_enter_casper() < 0) {
928 fprintf(stderr, "caph_enter_casper: %s\n", strerror(errno));
932 cap_rights_init(&rights, CAP_SEND, CAP_SETSOCKOPT);
933 if (caph_rights_limit(sndsock, &rights) < 0) {
934 fprintf(stderr, "caph_rights_limit sndsock: %s\n",
938 cap_rights_init(&rights, CAP_RECV, CAP_EVENT);
939 if (caph_rights_limit(rcvsock, &rights) < 0) {
940 fprintf(stderr, "caph_rights_limit rcvsock: %s\n",
948 for (hops = first_hop; hops <= max_hops; ++hops) {
949 struct in6_addr lastaddr;
951 unsigned unreachable = 0;
953 printf("%2lu ", hops);
954 bzero(&lastaddr, sizeof(lastaddr));
955 for (probe = 0; probe < nprobes; ++probe) {
957 struct timeval t1, t2;
959 (void) gettimeofday(&t1, NULL);
960 send_probe(++seq, hops);
961 while ((cc = wait_for_reply(rcvsock, &rcvmhdr))) {
962 (void) gettimeofday(&t2, NULL);
963 if (packet_ok(&rcvmhdr, cc, seq, &type, &code)) {
964 if (!IN6_ARE_ADDR_EQUAL(&Rcv.sin6_addr,
967 fputs("\n ", stdout);
969 lastaddr = Rcv.sin6_addr;
971 printf(" %.3f ms", deltaT(&t1, &t2));
972 if (type == ICMP6_DST_UNREACH) {
974 case ICMP6_DST_UNREACH_NOROUTE:
978 case ICMP6_DST_UNREACH_ADMIN:
982 case ICMP6_DST_UNREACH_NOTNEIGHBOR:
986 case ICMP6_DST_UNREACH_ADDR:
990 case ICMP6_DST_UNREACH_NOPORT:
997 } else if (type == ICMP6_PARAM_PROB &&
998 code == ICMP6_PARAMPROB_NEXTHEADER) {
1001 } else if (type == ICMP6_ECHO_REPLY) {
1008 } else if (deltaT(&t1, &t2) > waittime * 1000) {
1015 (void) fflush(stdout);
1019 (unreachable > 0 && unreachable >= ((nprobes + 1) / 2))) {
1030 wait_for_reply(int sock, struct msghdr *mhdr)
1033 struct pollfd pfd[1];
1037 pfd[0].events = POLLIN;
1040 if (poll(pfd, 1, waittime * 1000) > 0 &&
1041 pfd[0].revents & POLLIN)
1042 cc = recvmsg(rcvsock, mhdr, 0);
1047 struct timeval wait;
1050 fdsn = howmany(sock + 1, NFDBITS) * sizeof(fd_mask);
1051 if ((fdsp = (fd_set *)malloc(fdsn)) == NULL)
1053 memset(fdsp, 0, fdsn);
1055 wait.tv_sec = waittime; wait.tv_usec = 0;
1057 if (select(sock+1, fdsp, (fd_set *)0, (fd_set *)0, &wait) > 0)
1058 cc = recvmsg(rcvsock, mhdr, 0);
1065 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
1067 setpolicy(int so, char *policy)
1071 buf = ipsec_set_policy(policy, strlen(policy));
1073 warnx("%s", ipsec_strerror());
1076 (void)setsockopt(so, IPPROTO_IPV6, IPV6_IPSEC_POLICY,
1077 buf, ipsec_get_policylen(buf));
1086 send_probe(int seq, u_long hops)
1088 struct icmp6_hdr *icp;
1089 struct sctphdr *sctp;
1090 struct udphdr *outudp;
1091 struct sctp_chunkhdr *chk;
1092 struct sctp_init_chunk *init;
1093 struct sctp_paramhdr *param;
1098 if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
1099 (char *)&i, sizeof(i)) < 0) {
1100 perror("setsockopt IPV6_UNICAST_HOPS");
1103 Dst.sin6_port = htons(port + seq);
1106 case IPPROTO_ICMPV6:
1107 icp = (struct icmp6_hdr *)outpacket;
1109 icp->icmp6_type = ICMP6_ECHO_REQUEST;
1110 icp->icmp6_code = 0;
1111 icp->icmp6_cksum = 0;
1112 icp->icmp6_id = ident;
1113 icp->icmp6_seq = htons(seq);
1116 outudp = (struct udphdr *) outpacket;
1117 outudp->uh_sport = htons(ident);
1118 outudp->uh_dport = htons(port+seq);
1119 outudp->uh_ulen = htons(datalen);
1121 outudp->uh_sum = udp_cksum(&Src, &Dst, outpacket, datalen);
1124 /* No space for anything. No harm as seq/tv32 are decorative. */
1127 sctp = (struct sctphdr *)outpacket;
1129 sctp->src_port = htons(ident);
1130 sctp->dest_port = htons(port + seq);
1131 if (datalen >= (u_long)(sizeof(struct sctphdr) +
1132 sizeof(struct sctp_init_chunk))) {
1135 sctp->v_tag = (sctp->src_port << 16) | sctp->dest_port;
1137 sctp->checksum = htonl(0);
1138 if (datalen >= (u_long)(sizeof(struct sctphdr) +
1139 sizeof(struct sctp_init_chunk))) {
1141 * Send a packet containing an INIT chunk. This works
1142 * better in case of firewalls on the path, but
1143 * results in a probe packet containing at least
1144 * 32 bytes of payload. For shorter payloads, use
1145 * SHUTDOWN-ACK chunks.
1147 init = (struct sctp_init_chunk *)(sctp + 1);
1148 init->ch.chunk_type = SCTP_INITIATION;
1149 init->ch.chunk_flags = 0;
1150 init->ch.chunk_length = htons((u_int16_t)(datalen -
1151 sizeof(struct sctphdr)));
1152 init->init.initiate_tag = (sctp->src_port << 16) |
1154 init->init.a_rwnd = htonl(1500);
1155 init->init.num_outbound_streams = htons(1);
1156 init->init.num_inbound_streams = htons(1);
1157 init->init.initial_tsn = htonl(0);
1158 if (datalen >= (u_long)(sizeof(struct sctphdr) +
1159 sizeof(struct sctp_init_chunk) +
1160 sizeof(struct sctp_paramhdr))) {
1161 param = (struct sctp_paramhdr *)(init + 1);
1162 param->param_type = htons(SCTP_PAD);
1163 param->param_length =
1164 htons((u_int16_t)(datalen -
1165 sizeof(struct sctphdr) -
1166 sizeof(struct sctp_init_chunk)));
1170 * Send a packet containing a SHUTDOWN-ACK chunk,
1171 * possibly followed by a PAD chunk.
1173 if (datalen >= (u_long)(sizeof(struct sctphdr) +
1174 sizeof(struct sctp_chunkhdr))) {
1175 chk = (struct sctp_chunkhdr *)(sctp + 1);
1176 chk->chunk_type = SCTP_SHUTDOWN_ACK;
1177 chk->chunk_flags = 0;
1178 chk->chunk_length = htons(4);
1180 if (datalen >= (u_long)(sizeof(struct sctphdr) +
1181 2 * sizeof(struct sctp_chunkhdr))) {
1183 chk->chunk_type = SCTP_PAD_CHUNK;
1184 chk->chunk_flags = 0;
1185 chk->chunk_length = htons((u_int16_t)(datalen -
1186 sizeof(struct sctphdr) -
1187 sizeof(struct sctp_chunkhdr)));
1190 sctp->checksum = sctp_crc32c(outpacket, datalen);
1193 tcp = (struct tcphdr *)outpacket;
1195 tcp->th_sport = htons(ident);
1196 tcp->th_dport = htons(port + seq);
1197 tcp->th_seq = (tcp->th_sport << 16) | tcp->th_dport;
1200 tcp->th_flags = TH_SYN;
1202 tcp->th_sum = tcp_chksum(&Src, &Dst, outpacket, datalen);
1205 fprintf(stderr, "Unknown probe protocol %d.\n", useproto);
1209 i = send(sndsock, (char *)outpacket, datalen, 0);
1210 if (i < 0 || (u_long)i != datalen) {
1213 printf("traceroute6: wrote %s %lu chars, ret=%d\n",
1214 hostname, datalen, i);
1215 (void) fflush(stdout);
1220 get_hoplim(struct msghdr *mhdr)
1224 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
1225 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
1226 if (cm->cmsg_level == IPPROTO_IPV6 &&
1227 cm->cmsg_type == IPV6_HOPLIMIT &&
1228 cm->cmsg_len == CMSG_LEN(sizeof(int)))
1229 return (*(int *)CMSG_DATA(cm));
1236 deltaT(struct timeval *t1p, struct timeval *t2p)
1240 dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
1241 (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
1246 * Convert an ICMP "type" field to a printable string.
1251 u_char t = t0 & 0xff;
1255 case ICMP6_DST_UNREACH:
1256 cp = "Destination Unreachable";
1258 case ICMP6_PACKET_TOO_BIG:
1259 cp = "Packet Too Big";
1261 case ICMP6_TIME_EXCEEDED:
1262 cp = "Time Exceeded";
1264 case ICMP6_PARAM_PROB:
1265 cp = "Parameter Problem";
1267 case ICMP6_ECHO_REQUEST:
1268 cp = "Echo Request";
1270 case ICMP6_ECHO_REPLY:
1273 case ICMP6_MEMBERSHIP_QUERY:
1274 cp = "Group Membership Query";
1276 case ICMP6_MEMBERSHIP_REPORT:
1277 cp = "Group Membership Report";
1279 case ICMP6_MEMBERSHIP_REDUCTION:
1280 cp = "Group Membership Reduction";
1282 case ND_ROUTER_SOLICIT:
1283 cp = "Router Solicitation";
1285 case ND_ROUTER_ADVERT:
1286 cp = "Router Advertisement";
1288 case ND_NEIGHBOR_SOLICIT:
1289 cp = "Neighbor Solicitation";
1291 case ND_NEIGHBOR_ADVERT:
1292 cp = "Neighbor Advertisement";
1305 packet_ok(struct msghdr *mhdr, int cc, int seq, u_char *type, u_char *code)
1307 struct icmp6_hdr *icp;
1308 struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name;
1309 char *buf = (char *)mhdr->msg_iov[0].iov_base;
1312 char hbuf[NI_MAXHOST];
1320 ip = (struct ip6_hdr *) buf;
1321 hlen = sizeof(struct ip6_hdr);
1322 if (cc < hlen + sizeof(struct icmp6_hdr)) {
1324 if (cap_getnameinfo(capdns, (struct sockaddr *)from, from->sin6_len,
1325 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
1326 strlcpy(hbuf, "invalid", sizeof(hbuf));
1327 printf("packet too short (%d bytes) from %s\n", cc,
1333 icp = (struct icmp6_hdr *)(buf + hlen);
1335 if (cc < (int)sizeof(struct icmp6_hdr)) {
1337 if (cap_getnameinfo(capdns, (struct sockaddr *)from, from->sin6_len,
1338 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
1339 strlcpy(hbuf, "invalid", sizeof(hbuf));
1340 printf("data too short (%d bytes) from %s\n", cc, hbuf);
1344 icp = (struct icmp6_hdr *)buf;
1346 /* get optional information via advanced API */
1349 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
1350 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
1351 if (cm->cmsg_level == IPPROTO_IPV6 &&
1352 cm->cmsg_type == IPV6_PKTINFO &&
1354 CMSG_LEN(sizeof(struct in6_pktinfo)))
1355 rcvpktinfo = (struct in6_pktinfo *)(CMSG_DATA(cm));
1357 if (cm->cmsg_level == IPPROTO_IPV6 &&
1358 cm->cmsg_type == IPV6_HOPLIMIT &&
1359 cm->cmsg_len == CMSG_LEN(sizeof(int)))
1360 hlimp = (int *)CMSG_DATA(cm);
1362 if (rcvpktinfo == NULL || hlimp == NULL) {
1363 warnx("failed to get received hop limit or packet info");
1367 rcvhlim = 0; /*XXX*/
1373 *type = icp->icmp6_type;
1374 *code = icp->icmp6_code;
1375 if ((*type == ICMP6_TIME_EXCEEDED &&
1376 *code == ICMP6_TIME_EXCEED_TRANSIT) ||
1377 (*type == ICMP6_DST_UNREACH) ||
1378 (*type == ICMP6_PARAM_PROB &&
1379 *code == ICMP6_PARAMPROB_NEXTHEADER)) {
1380 struct ip6_hdr *hip;
1381 struct icmp6_hdr *icmp;
1382 struct sctp_init_chunk *init;
1383 struct sctphdr *sctp;
1388 hip = (struct ip6_hdr *)(icp + 1);
1389 if ((up = get_uphdr(hip, (u_char *)(buf + cc))) == NULL) {
1391 warnx("failed to get upper layer header");
1395 case IPPROTO_ICMPV6:
1396 icmp = (struct icmp6_hdr *)up;
1397 if (icmp->icmp6_id == ident &&
1398 icmp->icmp6_seq == htons(seq))
1402 udp = (struct udphdr *)up;
1403 if (udp->uh_sport == htons(ident) &&
1404 udp->uh_dport == htons(port + seq))
1408 sctp = (struct sctphdr *)up;
1409 if (sctp->src_port != htons(ident) ||
1410 sctp->dest_port != htons(port + seq)) {
1413 if (datalen >= (u_long)(sizeof(struct sctphdr) +
1414 sizeof(struct sctp_init_chunk))) {
1415 if (sctp->v_tag != 0) {
1418 init = (struct sctp_init_chunk *)(sctp + 1);
1419 /* Check the initiate tag, if available. */
1420 if ((char *)&init->init.a_rwnd > buf + cc) {
1423 if (init->init.initiate_tag == (u_int32_t)
1424 ((sctp->src_port << 16) | sctp->dest_port)) {
1429 (u_int32_t)((sctp->src_port << 16) |
1436 tcp = (struct tcphdr *)up;
1437 if (tcp->th_sport == htons(ident) &&
1438 tcp->th_dport == htons(port + seq) &&
1440 (tcp_seq)((tcp->th_sport << 16) | tcp->th_dport))
1446 fprintf(stderr, "Unknown probe proto %d.\n", useproto);
1449 } else if (useproto == IPPROTO_ICMPV6 && *type == ICMP6_ECHO_REPLY) {
1450 if (icp->icmp6_id == ident &&
1451 icp->icmp6_seq == htons(seq))
1455 char sbuf[NI_MAXHOST+1], dbuf[INET6_ADDRSTRLEN];
1459 if (cap_getnameinfo(capdns, (struct sockaddr *)from, from->sin6_len,
1460 sbuf, sizeof(sbuf), NULL, 0, NI_NUMERICHOST) != 0)
1461 strlcpy(sbuf, "invalid", sizeof(sbuf));
1462 printf("\n%d bytes from %s to %s", cc, sbuf,
1463 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,
1464 dbuf, sizeof(dbuf)) : "?");
1465 printf(": icmp type %d (%s) code %d\n", *type, pr_type(*type),
1467 p = (u_int8_t *)(icp + 1);
1469 for (i = 0; i < cc; i++) {
1474 printf("%02x", p[i]);
1475 if (i % WIDTH == WIDTH - 1)
1478 if (cc % WIDTH != 0)
1485 * Increment pointer until find the UDP or ICMP header.
1488 get_uphdr(struct ip6_hdr *ip6, u_char *lim)
1490 u_char *cp = (u_char *)ip6, nh;
1492 static u_char none_hdr[1]; /* Fake pointer for IPPROTO_NONE. */
1494 if (cp + sizeof(*ip6) > lim)
1498 cp += sizeof(struct ip6_hdr);
1500 while (lim - cp >= (nh == IPPROTO_NONE ? 0 : 8)) {
1504 case IPPROTO_ICMPV6:
1505 return (useproto == nh ? cp : NULL);
1509 return (useproto == nh ? cp : NULL);
1511 return (useproto == nh ? none_hdr : NULL);
1512 case IPPROTO_FRAGMENT:
1513 hlen = sizeof(struct ip6_frag);
1514 nh = ((struct ip6_frag *)cp)->ip6f_nxt;
1517 hlen = (((struct ip6_ext *)cp)->ip6e_len + 2) << 2;
1518 nh = ((struct ip6_ext *)cp)->ip6e_nxt;
1521 hlen = (((struct ip6_ext *)cp)->ip6e_len + 1) << 3;
1522 nh = ((struct ip6_ext *)cp)->ip6e_nxt;
1536 const char *types[] = { "NAME", "ADDR" };
1538 cap_channel_t *casper;
1540 casper = cap_init();
1542 errx(1, "unable to create casper process");
1543 capdns = cap_service_open(casper, "system.dns");
1545 errx(1, "unable to open system.dns service");
1546 if (cap_dns_type_limit(capdns, types, nitems(types)) < 0)
1547 errx(1, "unable to limit access to system.dns service");
1548 families[0] = AF_INET6;
1549 if (cap_dns_family_limit(capdns, families, nitems(families)) < 0)
1550 errx(1, "unable to limit access to system.dns service");
1552 #endif /* WITH_CASPER */
1556 print(struct msghdr *mhdr, int cc)
1558 struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name;
1559 char hbuf[NI_MAXHOST];
1561 if (cap_getnameinfo(capdns, (struct sockaddr *)from, from->sin6_len,
1562 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
1563 strlcpy(hbuf, "invalid", sizeof(hbuf));
1565 printf(" [AS%u]", as_lookup(asn, hbuf, AF_INET6));
1567 printf(" %s", hbuf);
1569 printf(" %s (%s)", inetname((struct sockaddr *)from), hbuf);
1571 printf(" %s", inetname((struct sockaddr *)from));
1575 printf(" %d bytes to %s", cc,
1576 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,
1577 hbuf, sizeof(hbuf)) : "?");
1579 printf(" %d bytes of data to %s", cc,
1580 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,
1581 hbuf, sizeof(hbuf)) : "?");
1587 * Construct an Internet address representation.
1588 * If the nflag has been supplied, give
1589 * numeric value, otherwise try for symbolic name.
1592 inetname(struct sockaddr *sa)
1594 static char line[NI_MAXHOST], domain[MAXHOSTNAMELEN + 1];
1595 static int first = 1;
1598 if (first && !nflag) {
1600 if (gethostname(domain, sizeof(domain)) == 0 &&
1601 (cp = strchr(domain, '.')))
1602 (void) strlcpy(domain, cp + 1, sizeof(domain));
1608 if (cap_getnameinfo(capdns, sa, sa->sa_len, line, sizeof(line), NULL, 0,
1609 NI_NAMEREQD) == 0) {
1610 if ((cp = strchr(line, '.')) &&
1611 !strcmp(cp + 1, domain))
1619 if (cap_getnameinfo(capdns, sa, sa->sa_len, line, sizeof(line), NULL, 0,
1620 NI_NUMERICHOST) != 0)
1621 strlcpy(line, "invalid", sizeof(line));
1626 * CRC32C routine for the Stream Control Transmission Protocol
1629 #define CRC32C(c, d) (c = (c>>8) ^ crc_c[(c^(d))&0xFF])
1631 static u_int32_t crc_c[256] = {
1632 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
1633 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
1634 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
1635 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
1636 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
1637 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
1638 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
1639 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
1640 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
1641 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
1642 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
1643 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
1644 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
1645 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
1646 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
1647 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
1648 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
1649 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
1650 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
1651 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
1652 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
1653 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
1654 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
1655 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
1656 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
1657 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
1658 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
1659 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
1660 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
1661 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
1662 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
1663 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
1664 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
1665 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
1666 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
1667 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
1668 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
1669 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
1670 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
1671 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
1672 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
1673 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
1674 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
1675 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
1676 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
1677 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
1678 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
1679 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
1680 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
1681 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
1682 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
1683 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
1684 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
1685 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
1686 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
1687 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
1688 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
1689 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
1690 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
1691 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
1692 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
1693 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
1694 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
1695 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
1699 sctp_crc32c(void *pack, u_int32_t len)
1701 u_int32_t i, crc32c;
1702 u_int8_t byte0, byte1, byte2, byte3;
1703 u_int8_t *buf = (u_int8_t *)pack;
1706 for (i = 0; i < len; i++)
1707 CRC32C(crc32c, buf[i]);
1709 byte0 = crc32c & 0xff;
1710 byte1 = (crc32c>>8) & 0xff;
1711 byte2 = (crc32c>>16) & 0xff;
1712 byte3 = (crc32c>>24) & 0xff;
1713 crc32c = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
1714 return htonl(crc32c);
1718 in_cksum(u_int16_t *addr, int len)
1721 u_int16_t *w = addr;
1726 * Our algorithm is simple, using a 32 bit accumulator (sum),
1727 * we add sequential 16 bit words to it, and at the end, fold
1728 * back all the carry bits from the top 16 bits into the lower
1736 /* mop up an odd byte, if necessary */
1738 sum += *(u_char *)w;
1741 * add back carry outs from top 16 bits to low 16 bits
1743 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
1744 sum += (sum >> 16); /* add carry */
1745 answer = ~sum; /* truncate to 16 bits */
1750 udp_cksum(struct sockaddr_in6 *src, struct sockaddr_in6 *dst,
1751 void *payload, u_int32_t len)
1754 struct in6_addr src;
1755 struct in6_addr dst;
1762 pseudo_hdr.src = src->sin6_addr;
1763 pseudo_hdr.dst = dst->sin6_addr;
1764 pseudo_hdr.len = htonl(len);
1765 pseudo_hdr.zero[0] = 0;
1766 pseudo_hdr.zero[1] = 0;
1767 pseudo_hdr.zero[2] = 0;
1768 pseudo_hdr.next = IPPROTO_UDP;
1770 sum[1] = in_cksum((u_int16_t *)&pseudo_hdr, sizeof(pseudo_hdr));
1771 sum[0] = in_cksum(payload, len);
1773 return (~in_cksum(sum, sizeof(sum)));
1777 tcp_chksum(struct sockaddr_in6 *src, struct sockaddr_in6 *dst,
1778 void *payload, u_int32_t len)
1781 struct in6_addr src;
1782 struct in6_addr dst;
1789 pseudo_hdr.src = src->sin6_addr;
1790 pseudo_hdr.dst = dst->sin6_addr;
1791 pseudo_hdr.len = htonl(len);
1792 pseudo_hdr.zero[0] = 0;
1793 pseudo_hdr.zero[1] = 0;
1794 pseudo_hdr.zero[2] = 0;
1795 pseudo_hdr.next = IPPROTO_TCP;
1797 sum[1] = in_cksum((u_int16_t *)&pseudo_hdr, sizeof(pseudo_hdr));
1798 sum[0] = in_cksum(payload, len);
1800 return (~in_cksum(sum, sizeof(sum)));
1808 "usage: traceroute6 [-adIlnNrSTUv] [-A as_server] [-f firsthop] [-g gateway]\n"
1809 " [-m hoplimit] [-p port] [-q probes] [-s src] [-w waittime] target\n"