1 /* $KAME: traceroute6.c,v 1.68 2004/01/25 11:16:12 suz Exp $ */
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
33 * Copyright (c) 1990, 1993
34 * The Regents of the University of California. All rights reserved.
36 * This code is derived from software contributed to Berkeley by
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
42 * 1. Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution.
47 * 4. Neither the name of the University nor the names of its contributors
48 * may be used to endorse or promote products derived from this software
49 * without specific prior written permission.
51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
65 static const char copyright[] =
66 "@(#) Copyright (c) 1990, 1993\n\
67 The Regents of the University of California. All rights reserved.\n";
72 static char sccsid[] = "@(#)traceroute.c 8.1 (Berkeley) 6/6/93";
74 static const char rcsid[] =
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/time.h>
251 #include <sys/socket.h>
253 #include <sys/file.h>
254 #include <sys/ioctl.h>
255 #include <sys/sysctl.h>
257 #include <netinet/in.h>
259 #include <arpa/inet.h>
272 #include <netinet/ip6.h>
273 #include <netinet/icmp6.h>
274 #include <netinet/sctp.h>
275 #include <netinet/sctp_header.h>
276 #include <netinet/tcp.h>
277 #include <netinet/udp.h>
280 #include <net/route.h>
281 #include <netipsec/ipsec.h>
286 #define DUMMY_PORT 10010
288 #define MAXPACKET 65535 /* max ip packet size */
290 #ifndef HAVE_GETIPNODEBYNAME
291 #define getipnodebyname(x, y, z, u) gethostbyname2((x), (y))
292 #define freehostent(x)
295 u_char packet[512]; /* last inbound (icmp) packet */
296 char *outpacket; /* last output packet */
298 int main(int, char *[]);
299 int wait_for_reply(int, struct msghdr *);
301 #ifdef IPSEC_POLICY_IPSEC
302 int setpolicy(int so, char *policy);
305 void send_probe(int, u_long);
306 void *get_uphdr(struct ip6_hdr *, u_char *);
307 int get_hoplim(struct msghdr *);
308 double deltaT(struct timeval *, struct timeval *);
309 const char *pr_type(int);
310 int packet_ok(struct msghdr *, int, int);
311 void print(struct msghdr *, int);
312 const char *inetname(struct sockaddr *);
313 u_int32_t sctp_crc32c(void *, u_int32_t);
314 u_int16_t in_cksum(u_int16_t *addr, int);
315 u_int16_t tcp_chksum(struct sockaddr_in6 *, struct sockaddr_in6 *,
319 int rcvsock; /* receive (icmp) socket file descriptor */
320 int sndsock; /* send (raw/udp) socket file descriptor */
322 struct msghdr rcvmhdr;
323 struct iovec rcviov[2];
325 struct in6_pktinfo *rcvpktinfo;
327 struct sockaddr_in6 Src, Dst, Rcv;
328 u_long datalen = 20; /* How much data */
329 #define ICMP6ECHOLEN 8
330 /* XXX: 2064 = 127(max hops in type 0 rthdr) * sizeof(ip6_hdr) + 16(margin) */
332 #ifdef USE_RFC2292BIS
333 struct ip6_rthdr *rth;
335 struct cmsghdr *cmsg;
341 u_long first_hop = 1;
342 u_long max_hops = 30;
344 u_int16_t port = 32768+666; /* start udp dest port # for probe packets */
346 int options; /* socket options */
348 int waittime = 5; /* time to wait for response (in seconds) */
349 int nflag; /* print addresses numerically */
350 int useproto = IPPROTO_UDP; /* protocol to use to send packet */
351 int lflag; /* print both numerical address & hostname */
352 int as_path; /* print as numbers for each hop */
353 char *as_server = NULL;
357 main(int argc, char *argv[])
359 int mib[4] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_DEFHLIM };
360 char hbuf[NI_MAXHOST], src0[NI_MAXHOST], *ep;
361 int ch, i, on = 1, seq, rcvcmsglen, error;
362 struct addrinfo hints, *res;
363 static u_char *rcvcmsgbuf;
364 u_long probe, hops, lport;
372 if ((rcvsock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) {
373 perror("socket(ICMPv6)");
378 (void) sysctl(mib, sizeof(mib)/sizeof(mib[0]), &i, &size, NULL, 0);
381 /* specify to tell receiving interface */
382 #ifdef IPV6_RECVPKTINFO
383 if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
385 err(1, "setsockopt(IPV6_RECVPKTINFO)");
386 #else /* old adv. API */
387 if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_PKTINFO, &on,
389 err(1, "setsockopt(IPV6_PKTINFO)");
392 /* specify to tell value of hoplimit field of received IP6 hdr */
393 #ifdef IPV6_RECVHOPLIMIT
394 if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on,
396 err(1, "setsockopt(IPV6_RECVHOPLIMIT)");
397 #else /* old adv. API */
398 if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_HOPLIMIT, &on,
400 err(1, "setsockopt(IPV6_HOPLIMIT)");
404 ident = htons(getpid() & 0xffff); /* same as ping6 */
406 while ((ch = getopt(argc, argv, "aA:df:g:Ilm:nNp:q:rs:STUvw:")) != -1)
421 first_hop = strtoul(optarg, &ep, 0);
422 if (errno || !*optarg || *ep || first_hop > 255) {
424 "traceroute6: invalid min hoplimit.\n");
429 hp = getipnodebyname(optarg, AF_INET6, 0, &h_errno);
432 "traceroute6: unknown host %s\n", optarg);
435 #ifdef USE_RFC2292BIS
438 * XXX: We can't detect the number of
439 * intermediate nodes yet.
441 if ((rth = inet6_rth_init((void *)rtbuf,
442 sizeof(rtbuf), IPV6_RTHDR_TYPE_0,
445 "inet6_rth_init failed.\n");
449 if (inet6_rth_add((void *)rth,
450 (struct in6_addr *)hp->h_addr)) {
452 "inet6_rth_add failed for %s\n",
456 #else /* old advanced API */
458 cmsg = inet6_rthdr_init(rtbuf, IPV6_RTHDR_TYPE_0);
459 inet6_rthdr_add(cmsg, (struct in6_addr *)hp->h_addr,
465 useproto = IPPROTO_ICMPV6;
473 max_hops = strtoul(optarg, &ep, 0);
474 if (errno || !*optarg || *ep || max_hops > 255) {
476 "traceroute6: invalid max hoplimit.\n");
484 useproto = IPPROTO_NONE;
489 lport = strtoul(optarg, &ep, 0);
490 if (errno || !*optarg || *ep) {
491 fprintf(stderr, "traceroute6: invalid port.\n");
494 if (lport == 0 || lport != (lport & 0xffff)) {
496 "traceroute6: port out of range.\n");
499 port = lport & 0xffff;
504 nprobes = strtoul(optarg, &ep, 0);
505 if (errno || !*optarg || *ep) {
507 "traceroute6: invalid nprobes.\n");
512 "traceroute6: nprobes must be >0.\n");
517 options |= SO_DONTROUTE;
521 * set the ip source address of the outbound
522 * probe (e.g., on a multi-homed host).
527 useproto = IPPROTO_SCTP;
530 useproto = IPPROTO_TCP;
533 useproto = IPPROTO_UDP;
541 waittime = strtoul(optarg, &ep, 0);
542 if (errno || !*optarg || *ep) {
544 "traceroute6: invalid wait time.\n");
549 "traceroute6: wait must be >= 1 sec.\n");
560 * Open socket to send probe packets.
567 if ((sndsock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
568 perror("socket(SOCK_DGRAM)");
575 if ((sndsock = socket(AF_INET6, SOCK_RAW, useproto)) < 0) {
576 perror("socket(SOCK_RAW)");
581 fprintf(stderr, "traceroute6: unknown probe protocol %d\n",
585 if (max_hops < first_hop) {
587 "traceroute6: max hoplimit must be larger than first hoplimit.\n");
593 if (setresuid(uid, uid, uid) == -1) {
599 if (argc < 1 || argc > 2)
603 setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
608 memset(&hints, 0, sizeof(hints));
609 hints.ai_family = PF_INET6;
610 hints.ai_socktype = SOCK_RAW;
611 hints.ai_protocol = IPPROTO_ICMPV6;
612 hints.ai_flags = AI_CANONNAME;
613 error = getaddrinfo(*argv, NULL, &hints, &res);
616 "traceroute6: %s\n", gai_strerror(error));
619 if (res->ai_addrlen != sizeof(Dst)) {
621 "traceroute6: size of sockaddr mismatch\n");
624 memcpy(&Dst, res->ai_addr, res->ai_addrlen);
625 hostname = res->ai_canonname ? strdup(res->ai_canonname) : *argv;
627 fprintf(stderr, "traceroute6: not enough core\n");
631 if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf,
632 sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
633 strlcpy(hbuf, "?", sizeof(hbuf));
634 fprintf(stderr, "traceroute6: Warning: %s has multiple "
635 "addresses; using %s\n", hostname, hbuf);
641 datalen = strtoul(*argv, &ep, 0);
644 "traceroute6: invalid packet length.\n");
650 minlen = ICMP6ECHOLEN;
653 minlen = sizeof(struct udphdr);
660 minlen = sizeof(struct sctphdr);
663 minlen = sizeof(struct tcphdr);
666 fprintf(stderr, "traceroute6: unknown probe protocol %d.\n",
670 if (datalen < minlen)
672 else if (datalen >= MAXPACKET) {
674 "traceroute6: packet size must be %zu <= s < %d.\n",
678 if (useproto == IPPROTO_UDP)
679 datalen -= sizeof(struct udphdr);
680 if ((useproto == IPPROTO_SCTP) && (datalen & 3)) {
682 "traceroute6: packet size must be a multiple of 4.\n");
685 outpacket = malloc(datalen);
690 (void) bzero((char *)outpacket, datalen);
692 /* initialize msghdr for receiving packets */
693 rcviov[0].iov_base = (caddr_t)packet;
694 rcviov[0].iov_len = sizeof(packet);
695 rcvmhdr.msg_name = (caddr_t)&Rcv;
696 rcvmhdr.msg_namelen = sizeof(Rcv);
697 rcvmhdr.msg_iov = rcviov;
698 rcvmhdr.msg_iovlen = 1;
699 rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
700 CMSG_SPACE(sizeof(int));
701 if ((rcvcmsgbuf = malloc(rcvcmsglen)) == NULL) {
702 fprintf(stderr, "traceroute6: malloc failed\n");
705 rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf;
706 rcvmhdr.msg_controllen = rcvcmsglen;
708 if (options & SO_DEBUG)
709 (void) setsockopt(rcvsock, SOL_SOCKET, SO_DEBUG,
710 (char *)&on, sizeof(on));
711 if (options & SO_DONTROUTE)
712 (void) setsockopt(rcvsock, SOL_SOCKET, SO_DONTROUTE,
713 (char *)&on, sizeof(on));
715 #ifdef IPSEC_POLICY_IPSEC
717 * do not raise error even if setsockopt fails, kernel may have ipsec
720 if (setpolicy(rcvsock, "in bypass") < 0)
721 errx(1, "%s", ipsec_strerror());
722 if (setpolicy(rcvsock, "out bypass") < 0)
723 errx(1, "%s", ipsec_strerror());
726 int level = IPSEC_LEVEL_NONE;
728 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, &level,
730 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_ESP_NETWORK_LEVEL, &level,
732 #ifdef IP_AUTH_TRANS_LEVEL
733 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, &level,
736 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_LEVEL, &level,
739 #ifdef IP_AUTH_NETWORK_LEVEL
740 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_NETWORK_LEVEL, &level,
744 #endif /*IPSEC_POLICY_IPSEC*/
751 if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&i,
753 perror("setsockopt(SO_SNDBUF)");
756 #endif /* SO_SNDBUF */
757 if (options & SO_DEBUG)
758 (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG,
759 (char *)&on, sizeof(on));
760 if (options & SO_DONTROUTE)
761 (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE,
762 (char *)&on, sizeof(on));
763 #ifdef USE_RFC2292BIS
764 if (rth) {/* XXX: there is no library to finalize the header... */
765 rth->ip6r_len = rth->ip6r_segleft * 2;
766 if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_RTHDR,
767 (void *)rth, (rth->ip6r_len + 1) << 3)) {
768 fprintf(stderr, "setsockopt(IPV6_RTHDR): %s\n",
773 #else /* old advanced API */
775 inet6_rthdr_lasthop(cmsg, IPV6_RTHDR_LOOSE);
776 if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_PKTOPTIONS,
777 rtbuf, cmsg->cmsg_len) < 0) {
778 fprintf(stderr, "setsockopt(IPV6_PKTOPTIONS): %s\n",
783 #endif /* USE_RFC2292BIS */
785 #ifdef IPSEC_POLICY_IPSEC
787 * do not raise error even if setsockopt fails, kernel may have ipsec
790 if (setpolicy(sndsock, "in bypass") < 0)
791 errx(1, "%s", ipsec_strerror());
792 if (setpolicy(sndsock, "out bypass") < 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_POLICY_IPSEC*/
820 bzero(&Src, sizeof(Src));
822 struct addrinfo hints, *res;
825 memset(&hints, 0, sizeof(hints));
826 hints.ai_family = AF_INET6;
827 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
828 hints.ai_flags = AI_NUMERICHOST;
829 error = getaddrinfo(source, "0", &hints, &res);
831 printf("traceroute6: %s: %s\n", source,
832 gai_strerror(error));
835 if (res->ai_addrlen > sizeof(Src)) {
836 printf("traceroute6: %s: %s\n", source,
837 gai_strerror(error));
840 memcpy(&Src, res->ai_addr, res->ai_addrlen);
843 struct sockaddr_in6 Nxt;
848 Nxt.sin6_port = htons(DUMMY_PORT);
850 bcopy(inet6_rthdr_getaddr(cmsg, 1), &Nxt.sin6_addr,
851 sizeof(Nxt.sin6_addr));
852 if ((dummy = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
856 if (connect(dummy, (struct sockaddr *)&Nxt, Nxt.sin6_len) < 0) {
861 if (getsockname(dummy, (struct sockaddr *)&Src, &len) < 0) {
862 perror("getsockname");
865 if (getnameinfo((struct sockaddr *)&Src, Src.sin6_len,
866 src0, sizeof(src0), NULL, 0, NI_NUMERICHOST)) {
867 fprintf(stderr, "getnameinfo failed for source\n");
874 Src.sin6_port = htons(0);
875 if (bind(sndsock, (struct sockaddr *)&Src, Src.sin6_len) < 0) {
884 if (getsockname(sndsock, (struct sockaddr *)&Src, &len) < 0) {
885 perror("getsockname");
888 srcport = ntohs(Src.sin6_port);
892 asn = as_setup(as_server);
895 "traceroute6: as_setup failed, AS# lookups"
897 (void)fflush(stderr);
905 if (getnameinfo((struct sockaddr *)&Dst, Dst.sin6_len, hbuf,
906 sizeof(hbuf), NULL, 0, NI_NUMERICHOST))
907 strlcpy(hbuf, "(invalid)", sizeof(hbuf));
908 fprintf(stderr, "traceroute6");
909 fprintf(stderr, " to %s (%s)", hostname, hbuf);
911 fprintf(stderr, " from %s", source);
912 fprintf(stderr, ", %lu hops max, %lu byte packets\n",
914 datalen + ((useproto == IPPROTO_UDP) ? sizeof(struct udphdr) : 0));
915 (void) fflush(stderr);
918 printf("Skipping %lu intermediate hops\n", first_hop - 1);
923 for (hops = first_hop; hops <= max_hops; ++hops) {
924 struct in6_addr lastaddr;
926 unsigned unreachable = 0;
928 printf("%2lu ", hops);
929 bzero(&lastaddr, sizeof(lastaddr));
930 for (probe = 0; probe < nprobes; ++probe) {
932 struct timeval t1, t2;
934 (void) gettimeofday(&t1, NULL);
935 send_probe(++seq, hops);
936 while ((cc = wait_for_reply(rcvsock, &rcvmhdr))) {
937 (void) gettimeofday(&t2, NULL);
938 if ((i = packet_ok(&rcvmhdr, cc, seq))) {
939 if (!IN6_ARE_ADDR_EQUAL(&Rcv.sin6_addr,
942 fputs("\n ", stdout);
944 lastaddr = Rcv.sin6_addr;
946 printf(" %.3f ms", deltaT(&t1, &t2));
948 case ICMP6_DST_UNREACH_NOROUTE:
952 case ICMP6_DST_UNREACH_ADMIN:
956 case ICMP6_DST_UNREACH_NOTNEIGHBOR:
960 case ICMP6_DST_UNREACH_ADDR:
964 case ICMP6_DST_UNREACH_NOPORT:
972 } else if (deltaT(&t1, &t2) > waittime * 1000) {
979 (void) fflush(stdout);
983 (unreachable > 0 && unreachable >= ((nprobes + 1) / 2))) {
994 wait_for_reply(int sock, struct msghdr *mhdr)
997 struct pollfd pfd[1];
1001 pfd[0].events = POLLIN;
1004 if (poll(pfd, 1, waittime * 1000) > 0)
1005 cc = recvmsg(rcvsock, mhdr, 0);
1010 struct timeval wait;
1013 fdsn = howmany(sock + 1, NFDBITS) * sizeof(fd_mask);
1014 if ((fdsp = (fd_set *)malloc(fdsn)) == NULL)
1016 memset(fdsp, 0, fdsn);
1018 wait.tv_sec = waittime; wait.tv_usec = 0;
1020 if (select(sock+1, fdsp, (fd_set *)0, (fd_set *)0, &wait) > 0)
1021 cc = recvmsg(rcvsock, mhdr, 0);
1029 #ifdef IPSEC_POLICY_IPSEC
1031 setpolicy(so, policy)
1037 buf = ipsec_set_policy(policy, strlen(policy));
1039 warnx("%s", ipsec_strerror());
1042 (void)setsockopt(so, IPPROTO_IPV6, IPV6_IPSEC_POLICY,
1043 buf, ipsec_get_policylen(buf));
1053 send_probe(int seq, u_long hops)
1055 struct icmp6_hdr *icp;
1056 struct sctphdr *sctp;
1057 struct sctp_chunkhdr *chk;
1058 struct sctp_init_chunk *init;
1059 struct sctp_paramhdr *param;
1064 if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
1065 (char *)&i, sizeof(i)) < 0) {
1066 perror("setsockopt IPV6_UNICAST_HOPS");
1069 Dst.sin6_port = htons(port + seq);
1072 case IPPROTO_ICMPV6:
1073 icp = (struct icmp6_hdr *)outpacket;
1075 icp->icmp6_type = ICMP6_ECHO_REQUEST;
1076 icp->icmp6_code = 0;
1077 icp->icmp6_cksum = 0;
1078 icp->icmp6_id = ident;
1079 icp->icmp6_seq = htons(seq);
1084 /* No space for anything. No harm as seq/tv32 are decorative. */
1087 sctp = (struct sctphdr *)outpacket;
1089 sctp->src_port = htons(ident);
1090 sctp->dest_port = htons(port + seq);
1091 if (datalen >= (u_long)(sizeof(struct sctphdr) +
1092 sizeof(struct sctp_init_chunk))) {
1095 sctp->v_tag = (sctp->src_port << 16) | sctp->dest_port;
1097 sctp->checksum = htonl(0);
1098 if (datalen >= (u_long)(sizeof(struct sctphdr) +
1099 sizeof(struct sctp_init_chunk))) {
1101 * Send a packet containing an INIT chunk. This works
1102 * better in case of firewalls on the path, but
1103 * results in a probe packet containing at least
1104 * 32 bytes of payload. For shorter payloads, use
1105 * SHUTDOWN-ACK chunks.
1107 init = (struct sctp_init_chunk *)(sctp + 1);
1108 init->ch.chunk_type = SCTP_INITIATION;
1109 init->ch.chunk_flags = 0;
1110 init->ch.chunk_length = htons((u_int16_t)(datalen -
1111 sizeof(struct sctphdr)));
1112 init->init.initiate_tag = (sctp->src_port << 16) |
1114 init->init.a_rwnd = htonl(1500);
1115 init->init.num_outbound_streams = htons(1);
1116 init->init.num_inbound_streams = htons(1);
1117 init->init.initial_tsn = htonl(0);
1118 if (datalen >= (u_long)(sizeof(struct sctphdr) +
1119 sizeof(struct sctp_init_chunk) +
1120 sizeof(struct sctp_paramhdr))) {
1121 param = (struct sctp_paramhdr *)(init + 1);
1122 param->param_type = htons(SCTP_PAD);
1123 param->param_length =
1124 htons((u_int16_t)(datalen -
1125 sizeof(struct sctphdr) -
1126 sizeof(struct sctp_init_chunk)));
1130 * Send a packet containing a SHUTDOWN-ACK chunk,
1131 * possibly followed by a PAD chunk.
1133 if (datalen >= (u_long)(sizeof(struct sctphdr) +
1134 sizeof(struct sctp_chunkhdr))) {
1135 chk = (struct sctp_chunkhdr *)(sctp + 1);
1136 chk->chunk_type = SCTP_SHUTDOWN_ACK;
1137 chk->chunk_flags = 0;
1138 chk->chunk_length = htons(4);
1140 if (datalen >= (u_long)(sizeof(struct sctphdr) +
1141 2 * sizeof(struct sctp_chunkhdr))) {
1143 chk->chunk_type = SCTP_PAD_CHUNK;
1144 chk->chunk_flags = 0;
1145 chk->chunk_length = htons((u_int16_t)(datalen -
1146 sizeof(struct sctphdr) -
1147 sizeof(struct sctp_chunkhdr)));
1150 sctp->checksum = sctp_crc32c(outpacket, datalen);
1153 tcp = (struct tcphdr *)outpacket;
1155 tcp->th_sport = htons(ident);
1156 tcp->th_dport = htons(port + seq);
1157 tcp->th_seq = (tcp->th_sport << 16) | tcp->th_dport;
1160 tcp->th_flags = TH_SYN;
1162 tcp->th_sum = tcp_chksum(&Src, &Dst, outpacket, datalen);
1165 fprintf(stderr, "Unknown probe protocol %d.\n", useproto);
1169 i = sendto(sndsock, (char *)outpacket, datalen, 0,
1170 (struct sockaddr *)&Dst, Dst.sin6_len);
1171 if (i < 0 || (u_long)i != datalen) {
1174 printf("traceroute6: wrote %s %lu chars, ret=%d\n",
1175 hostname, datalen, i);
1176 (void) fflush(stdout);
1181 get_hoplim(struct msghdr *mhdr)
1185 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
1186 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
1187 if (cm->cmsg_level == IPPROTO_IPV6 &&
1188 cm->cmsg_type == IPV6_HOPLIMIT &&
1189 cm->cmsg_len == CMSG_LEN(sizeof(int)))
1190 return(*(int *)CMSG_DATA(cm));
1197 deltaT(struct timeval *t1p, struct timeval *t2p)
1201 dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
1202 (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
1207 * Convert an ICMP "type" field to a printable string.
1212 u_char t = t0 & 0xff;
1216 case ICMP6_DST_UNREACH:
1217 cp = "Destination Unreachable";
1219 case ICMP6_PACKET_TOO_BIG:
1220 cp = "Packet Too Big";
1222 case ICMP6_TIME_EXCEEDED:
1223 cp = "Time Exceeded";
1225 case ICMP6_PARAM_PROB:
1226 cp = "Parameter Problem";
1228 case ICMP6_ECHO_REQUEST:
1229 cp = "Echo Request";
1231 case ICMP6_ECHO_REPLY:
1234 case ICMP6_MEMBERSHIP_QUERY:
1235 cp = "Group Membership Query";
1237 case ICMP6_MEMBERSHIP_REPORT:
1238 cp = "Group Membership Report";
1240 case ICMP6_MEMBERSHIP_REDUCTION:
1241 cp = "Group Membership Reduction";
1243 case ND_ROUTER_SOLICIT:
1244 cp = "Router Solicitation";
1246 case ND_ROUTER_ADVERT:
1247 cp = "Router Advertisement";
1249 case ND_NEIGHBOR_SOLICIT:
1250 cp = "Neighbor Solicitation";
1252 case ND_NEIGHBOR_ADVERT:
1253 cp = "Neighbor Advertisement";
1266 packet_ok(struct msghdr *mhdr, int cc, int seq)
1268 struct icmp6_hdr *icp;
1269 struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name;
1271 char *buf = (char *)mhdr->msg_iov[0].iov_base;
1274 char hbuf[NI_MAXHOST];
1282 ip = (struct ip6_hdr *) buf;
1283 hlen = sizeof(struct ip6_hdr);
1284 if (cc < hlen + sizeof(struct icmp6_hdr)) {
1286 if (getnameinfo((struct sockaddr *)from, from->sin6_len,
1287 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
1288 strlcpy(hbuf, "invalid", sizeof(hbuf));
1289 printf("packet too short (%d bytes) from %s\n", cc,
1295 icp = (struct icmp6_hdr *)(buf + hlen);
1297 if (cc < (int)sizeof(struct icmp6_hdr)) {
1299 if (getnameinfo((struct sockaddr *)from, from->sin6_len,
1300 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
1301 strlcpy(hbuf, "invalid", sizeof(hbuf));
1302 printf("data too short (%d bytes) from %s\n", cc, hbuf);
1306 icp = (struct icmp6_hdr *)buf;
1308 /* get optional information via advanced API */
1311 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
1312 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
1313 if (cm->cmsg_level == IPPROTO_IPV6 &&
1314 cm->cmsg_type == IPV6_PKTINFO &&
1316 CMSG_LEN(sizeof(struct in6_pktinfo)))
1317 rcvpktinfo = (struct in6_pktinfo *)(CMSG_DATA(cm));
1319 if (cm->cmsg_level == IPPROTO_IPV6 &&
1320 cm->cmsg_type == IPV6_HOPLIMIT &&
1321 cm->cmsg_len == CMSG_LEN(sizeof(int)))
1322 hlimp = (int *)CMSG_DATA(cm);
1324 if (rcvpktinfo == NULL || hlimp == NULL) {
1325 warnx("failed to get received hop limit or packet info");
1329 rcvhlim = 0; /*XXX*/
1335 type = icp->icmp6_type;
1336 code = icp->icmp6_code;
1337 if ((type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT)
1338 || type == ICMP6_DST_UNREACH) {
1339 struct ip6_hdr *hip;
1340 struct icmp6_hdr *icmp;
1341 struct sctp_init_chunk *init;
1342 struct sctphdr *sctp;
1347 hip = (struct ip6_hdr *)(icp + 1);
1348 if ((up = get_uphdr(hip, (u_char *)(buf + cc))) == NULL) {
1350 warnx("failed to get upper layer header");
1354 case IPPROTO_ICMPV6:
1355 icmp = (struct icmp6_hdr *)up;
1356 if (icmp->icmp6_id == ident &&
1357 icmp->icmp6_seq == htons(seq))
1358 return (type == ICMP6_TIME_EXCEEDED ?
1362 udp = (struct udphdr *)up;
1363 if (udp->uh_sport == htons(srcport) &&
1364 udp->uh_dport == htons(port + seq))
1365 return (type == ICMP6_TIME_EXCEEDED ?
1369 sctp = (struct sctphdr *)up;
1370 if (sctp->src_port != htons(ident) ||
1371 sctp->dest_port != htons(port + seq)) {
1374 if (datalen >= (u_long)(sizeof(struct sctphdr) +
1375 sizeof(struct sctp_init_chunk))) {
1376 if (sctp->v_tag != 0) {
1379 init = (struct sctp_init_chunk *)(sctp + 1);
1380 /* Check the initiate tag, if available. */
1381 if ((char *)&init->init.a_rwnd > buf + cc) {
1382 return (type == ICMP6_TIME_EXCEEDED ?
1385 if (init->init.initiate_tag == (u_int32_t)
1386 ((sctp->src_port << 16) | sctp->dest_port)) {
1387 return (type == ICMP6_TIME_EXCEEDED ?
1392 (u_int32_t)((sctp->src_port << 16) |
1394 return (type == ICMP6_TIME_EXCEEDED ?
1400 tcp = (struct tcphdr *)up;
1401 if (tcp->th_sport == htons(ident) &&
1402 tcp->th_dport == htons(port + seq) &&
1404 (tcp_seq)((tcp->th_sport << 16) | tcp->th_dport))
1405 return (type == ICMP6_TIME_EXCEEDED ?
1409 return (type == ICMP6_TIME_EXCEEDED ? -1 : code + 1);
1411 fprintf(stderr, "Unknown probe proto %d.\n", useproto);
1414 } else if (useproto == IPPROTO_ICMPV6 && type == ICMP6_ECHO_REPLY) {
1415 if (icp->icmp6_id == ident &&
1416 icp->icmp6_seq == htons(seq))
1417 return (ICMP6_DST_UNREACH_NOPORT + 1);
1420 char sbuf[NI_MAXHOST+1], dbuf[INET6_ADDRSTRLEN];
1424 if (getnameinfo((struct sockaddr *)from, from->sin6_len,
1425 sbuf, sizeof(sbuf), NULL, 0, NI_NUMERICHOST) != 0)
1426 strlcpy(sbuf, "invalid", sizeof(sbuf));
1427 printf("\n%d bytes from %s to %s", cc, sbuf,
1428 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,
1429 dbuf, sizeof(dbuf)) : "?");
1430 printf(": icmp type %d (%s) code %d\n", type, pr_type(type),
1432 p = (u_int8_t *)(icp + 1);
1434 for (i = 0; i < cc; i++) {
1439 printf("%02x", p[i]);
1440 if (i % WIDTH == WIDTH - 1)
1443 if (cc % WIDTH != 0)
1450 * Increment pointer until find the UDP or ICMP header.
1453 get_uphdr(struct ip6_hdr *ip6, u_char *lim)
1455 u_char *cp = (u_char *)ip6, nh;
1457 static u_char none_hdr[1]; /* Fake pointer for IPPROTO_NONE. */
1459 if (cp + sizeof(*ip6) > lim)
1463 cp += sizeof(struct ip6_hdr);
1465 while (lim - cp >= (nh == IPPROTO_NONE ? 0 : 8)) {
1469 case IPPROTO_ICMPV6:
1470 return(useproto == nh ? cp : NULL);
1474 return(useproto == nh ? cp : NULL);
1476 return(useproto == nh ? none_hdr : NULL);
1477 case IPPROTO_FRAGMENT:
1478 hlen = sizeof(struct ip6_frag);
1479 nh = ((struct ip6_frag *)cp)->ip6f_nxt;
1482 hlen = (((struct ip6_ext *)cp)->ip6e_len + 2) << 2;
1483 nh = ((struct ip6_ext *)cp)->ip6e_nxt;
1486 hlen = (((struct ip6_ext *)cp)->ip6e_len + 1) << 3;
1487 nh = ((struct ip6_ext *)cp)->ip6e_nxt;
1498 print(struct msghdr *mhdr, int cc)
1500 struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name;
1501 char hbuf[NI_MAXHOST];
1503 if (getnameinfo((struct sockaddr *)from, from->sin6_len,
1504 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
1505 strlcpy(hbuf, "invalid", sizeof(hbuf));
1507 printf(" [AS%u]", as_lookup(asn, hbuf, AF_INET6));
1509 printf(" %s", hbuf);
1511 printf(" %s (%s)", inetname((struct sockaddr *)from), hbuf);
1513 printf(" %s", inetname((struct sockaddr *)from));
1517 printf(" %d bytes to %s", cc,
1518 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,
1519 hbuf, sizeof(hbuf)) : "?");
1521 printf(" %d bytes of data to %s", cc,
1522 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,
1523 hbuf, sizeof(hbuf)) : "?");
1529 * Construct an Internet address representation.
1530 * If the nflag has been supplied, give
1531 * numeric value, otherwise try for symbolic name.
1534 inetname(struct sockaddr *sa)
1536 static char line[NI_MAXHOST], domain[MAXHOSTNAMELEN + 1];
1537 static int first = 1;
1540 if (first && !nflag) {
1542 if (gethostname(domain, sizeof(domain)) == 0 &&
1543 (cp = strchr(domain, '.')))
1544 (void) strlcpy(domain, cp + 1, sizeof(domain));
1550 if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0,
1551 NI_NAMEREQD) == 0) {
1552 if ((cp = strchr(line, '.')) &&
1553 !strcmp(cp + 1, domain))
1561 if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0,
1562 NI_NUMERICHOST) != 0)
1563 strlcpy(line, "invalid", sizeof(line));
1568 * CRC32C routine for the Stream Control Transmission Protocol
1571 #define CRC32C(c, d) (c = (c>>8) ^ crc_c[(c^(d))&0xFF])
1573 static u_int32_t crc_c[256] = {
1574 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
1575 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
1576 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
1577 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
1578 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
1579 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
1580 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
1581 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
1582 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
1583 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
1584 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
1585 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
1586 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
1587 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
1588 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
1589 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
1590 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
1591 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
1592 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
1593 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
1594 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
1595 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
1596 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
1597 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
1598 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
1599 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
1600 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
1601 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
1602 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
1603 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
1604 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
1605 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
1606 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
1607 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
1608 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
1609 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
1610 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
1611 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
1612 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
1613 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
1614 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
1615 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
1616 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
1617 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
1618 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
1619 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
1620 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
1621 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
1622 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
1623 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
1624 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
1625 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
1626 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
1627 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
1628 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
1629 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
1630 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
1631 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
1632 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
1633 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
1634 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
1635 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
1636 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
1637 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
1641 sctp_crc32c(void *packet, u_int32_t len)
1643 u_int32_t i, crc32c;
1644 u_int8_t byte0, byte1, byte2, byte3;
1645 u_int8_t *buf = (u_int8_t *)packet;
1648 for (i = 0; i < len; i++)
1649 CRC32C(crc32c, buf[i]);
1651 byte0 = crc32c & 0xff;
1652 byte1 = (crc32c>>8) & 0xff;
1653 byte2 = (crc32c>>16) & 0xff;
1654 byte3 = (crc32c>>24) & 0xff;
1655 crc32c = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
1656 return htonl(crc32c);
1660 in_cksum(u_int16_t *addr, int len)
1663 u_int16_t *w = addr;
1668 * Our algorithm is simple, using a 32 bit accumulator (sum),
1669 * we add sequential 16 bit words to it, and at the end, fold
1670 * back all the carry bits from the top 16 bits into the lower
1678 /* mop up an odd byte, if necessary */
1680 sum += *(u_char *)w;
1683 * add back carry outs from top 16 bits to low 16 bits
1685 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
1686 sum += (sum >> 16); /* add carry */
1687 answer = ~sum; /* truncate to 16 bits */
1692 tcp_chksum(struct sockaddr_in6 *src, struct sockaddr_in6 *dst,
1693 void *payload, u_int32_t len)
1696 struct in6_addr src;
1697 struct in6_addr dst;
1704 pseudo_hdr.src = src->sin6_addr;
1705 pseudo_hdr.dst = dst->sin6_addr;
1706 pseudo_hdr.len = htonl(len);
1707 pseudo_hdr.zero[0] = 0;
1708 pseudo_hdr.zero[1] = 0;
1709 pseudo_hdr.zero[2] = 0;
1710 pseudo_hdr.next = IPPROTO_TCP;
1712 sum[1] = in_cksum((u_int16_t *)&pseudo_hdr, sizeof(pseudo_hdr));
1713 sum[0] = in_cksum(payload, len);
1715 return (~in_cksum(sum, sizeof(sum)));
1723 "usage: traceroute6 [-adIlnNrSTUv] [-A as_server] [-f firsthop] [-g gateway]\n"
1724 " [-m hoplimit] [-p port] [-q probes] [-s src] [-w waittime] target\n"