1 /* $KAME: traceroute6.c,v 1.68 2004/01/25 11:16:12 suz Exp $ */
2
3 /*-
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
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.
20 *
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
31 * SUCH DAMAGE.
32 */
33
34 /*-
35 * Copyright (c) 1990, 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 * Van Jacobson.
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. Neither the name of the University nor the names of its contributors
50 * may be used to endorse or promote products derived from this software
51 * without specific prior written permission.
52 *
53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 * SUCH DAMAGE.
64 */
65
66 /*
67 * traceroute host - trace the route ip packets follow going to "host".
68 *
69 * Attempt to trace the route an ip packet would follow to some
70 * internet host. We find out intermediate hops by launching probe
71 * packets with a small ttl (time to live) then listening for an
72 * icmp "time exceeded" reply from a gateway. We start our probes
73 * with a ttl of one and increase by one until we get an icmp "port
74 * unreachable" (which means we got to "host") or hit a max (which
75 * defaults to net.inet.ip.ttl hops & can be changed with the -m flag).
76 * Three probes (change with -q flag) are sent at each ttl setting and
77 * a line is printed showing the ttl, address of the gateway and
78 * round trip time of each probe. If the probe answers come from
79 * different gateways, the address of each responding system will
80 * be printed. If there is no response within a 5 sec. timeout
81 * interval (changed with the -w flag), a "*" is printed for that
82 * probe.
83 *
84 * Probe packets are UDP format. We don't want the destination
85 * host to process them so the destination port is set to an
86 * unlikely value (if some clod on the destination is using that
87 * value, it can be changed with the -p flag).
88 *
89 * A sample use might be:
90 *
91 * [yak 71]% traceroute nis.nsf.net.
92 * traceroute to nis.nsf.net (35.1.1.48), 64 hops max, 40 byte packets
93 * 1 helios.ee.lbl.gov (128.3.112.1) 19 ms 19 ms 0 ms
94 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
95 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
96 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 39 ms
97 * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 39 ms 39 ms 39 ms
98 * 6 128.32.197.4 (128.32.197.4) 40 ms 59 ms 59 ms
99 * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 59 ms
100 * 8 129.140.70.13 (129.140.70.13) 99 ms 99 ms 80 ms
101 * 9 129.140.71.6 (129.140.71.6) 139 ms 239 ms 319 ms
102 * 10 129.140.81.7 (129.140.81.7) 220 ms 199 ms 199 ms
103 * 11 nic.merit.edu (35.1.1.48) 239 ms 239 ms 239 ms
104 *
105 * Note that lines 2 & 3 are the same. This is due to a buggy
106 * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
107 * packets with a zero ttl.
108 *
109 * A more interesting example is:
110 *
111 * [yak 72]% traceroute allspice.lcs.mit.edu.
112 * traceroute to allspice.lcs.mit.edu (18.26.0.115), 64 hops max, 40 byte packets
113 * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
114 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 19 ms 19 ms
115 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 19 ms
116 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 19 ms 39 ms 39 ms
117 * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 20 ms 39 ms 39 ms
118 * 6 128.32.197.4 (128.32.197.4) 59 ms 119 ms 39 ms
119 * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 39 ms
120 * 8 129.140.70.13 (129.140.70.13) 80 ms 79 ms 99 ms
121 * 9 129.140.71.6 (129.140.71.6) 139 ms 139 ms 159 ms
122 * 10 129.140.81.7 (129.140.81.7) 199 ms 180 ms 300 ms
123 * 11 129.140.72.17 (129.140.72.17) 300 ms 239 ms 239 ms
124 * 12 * * *
125 * 13 128.121.54.72 (128.121.54.72) 259 ms 499 ms 279 ms
126 * 14 * * *
127 * 15 * * *
128 * 16 * * *
129 * 17 * * *
130 * 18 ALLSPICE.LCS.MIT.EDU (18.26.0.115) 339 ms 279 ms 279 ms
131 *
132 * (I start to see why I'm having so much trouble with mail to
133 * MIT.) Note that the gateways 12, 14, 15, 16 & 17 hops away
134 * either don't send ICMP "time exceeded" messages or send them
135 * with a ttl too small to reach us. 14 - 17 are running the
136 * MIT C Gateway code that doesn't send "time exceeded"s. God
137 * only knows what's going on with 12.
138 *
139 * The silent gateway 12 in the above may be the result of a bug in
140 * the 4.[23]BSD network code (and its derivatives): 4.x (x <= 3)
141 * sends an unreachable message using whatever ttl remains in the
142 * original datagram. Since, for gateways, the remaining ttl is
143 * zero, the icmp "time exceeded" is guaranteed to not make it back
144 * to us. The behavior of this bug is slightly more interesting
145 * when it appears on the destination system:
146 *
147 * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
148 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 39 ms
149 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 39 ms 19 ms
150 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 19 ms
151 * 5 ccn-nerif35.Berkeley.EDU (128.32.168.35) 39 ms 39 ms 39 ms
152 * 6 csgw.Berkeley.EDU (128.32.133.254) 39 ms 59 ms 39 ms
153 * 7 * * *
154 * 8 * * *
155 * 9 * * *
156 * 10 * * *
157 * 11 * * *
158 * 12 * * *
159 * 13 rip.Berkeley.EDU (128.32.131.22) 59 ms ! 39 ms ! 39 ms !
160 *
161 * Notice that there are 12 "gateways" (13 is the final
162 * destination) and exactly the last half of them are "missing".
163 * What's really happening is that rip (a Sun-3 running Sun OS3.5)
164 * is using the ttl from our arriving datagram as the ttl in its
165 * icmp reply. So, the reply will time out on the return path
166 * (with no notice sent to anyone since icmp's aren't sent for
167 * icmp's) until we probe with a ttl that's at least twice the path
168 * length. I.e., rip is really only 7 hops away. A reply that
169 * returns with a ttl of 1 is a clue this problem exists.
170 * Traceroute prints a "!" after the time if the ttl is <= 1.
171 * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
172 * non-standard (HPUX) software, expect to see this problem
173 * frequently and/or take care picking the target host of your
174 * probes.
175 *
176 * Other possible annotations after the time are !H, !N, !P (got a host,
177 * network or protocol unreachable, respectively), !S or !F (source
178 * route failed or fragmentation needed -- neither of these should
179 * ever occur and the associated gateway is busted if you see one). If
180 * almost all the probes result in some kind of unreachable, traceroute
181 * will give up and exit.
182 *
183 * Notes
184 * -----
185 * This program must be run by root or be setuid. (I suggest that
186 * you *don't* make it setuid -- casual use could result in a lot
187 * of unnecessary traffic on our poor, congested nets.)
188 *
189 * This program requires a kernel mod that does not appear in any
190 * system available from Berkeley: A raw ip socket using proto
191 * IPPROTO_RAW must interpret the data sent as an ip datagram (as
192 * opposed to data to be wrapped in an ip datagram). See the README
193 * file that came with the source to this program for a description
194 * of the mods I made to /sys/netinet/raw_ip.c. Your mileage may
195 * vary. But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
196 * MODIFIED TO RUN THIS PROGRAM.
197 *
198 * The udp port usage may appear bizarre (well, ok, it is bizarre).
199 * The problem is that an icmp message only contains 8 bytes of
200 * data from the original datagram. 8 bytes is the size of a udp
201 * header so, if we want to associate replies with the original
202 * datagram, the necessary information must be encoded into the
203 * udp header (the ip id could be used but there's no way to
204 * interlock with the kernel's assignment of ip id's and, anyway,
205 * it would have taken a lot more kernel hacking to allow this
206 * code to set the ip id). So, to allow two or more users to
207 * use traceroute simultaneously, we use this task's pid as the
208 * source port (the high bit is set to move the port number out
209 * of the "likely" range). To keep track of which probe is being
210 * replied to (so times and/or hop counts don't get confused by a
211 * reply that was delayed in transit), we increment the destination
212 * port number before each probe.
213 *
214 * Don't use this as a coding example. I was trying to find a
215 * routing problem and this code sort-of popped out after 48 hours
216 * without sleep. I was amazed it ever compiled, much less ran.
217 *
218 * I stole the idea for this program from Steve Deering. Since
219 * the first release, I've learned that had I attended the right
220 * IETF working group meetings, I also could have stolen it from Guy
221 * Almes or Matt Mathis. I don't know (or care) who came up with
222 * the idea first. I envy the originators' perspicacity and I'm
223 * glad they didn't keep the idea a secret.
224 *
225 * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
226 * enhancements to the original distribution.
227 *
228 * I've hacked up a round-trip-route version of this that works by
229 * sending a loose-source-routed udp datagram through the destination
230 * back to yourself. Unfortunately, SO many gateways botch source
231 * routing, the thing is almost worthless. Maybe one day...
232 *
233 * -- Van Jacobson (van@ee.lbl.gov)
234 * Tue Dec 20 03:50:13 PST 1988
235 */
236
237 #include <sys/param.h>
238 #include <sys/capsicum.h>
239 #include <sys/time.h>
240 #include <sys/socket.h>
241 #include <sys/uio.h>
242 #include <sys/file.h>
243 #include <sys/ioctl.h>
244 #include <sys/sysctl.h>
245
246 #include <netinet/in.h>
247
248 #include <arpa/inet.h>
249
250 #include <libcasper.h>
251 #include <casper/cap_dns.h>
252 #include <capsicum_helpers.h>
253
254 #include <netdb.h>
255 #include <stdio.h>
256 #include <err.h>
257 #ifdef HAVE_POLL
258 #include <poll.h>
259 #endif
260 #include <errno.h>
261 #include <stdlib.h>
262 #include <string.h>
263 #include <unistd.h>
264
265 #include <netinet/ip.h>
266 #include <netinet/ip6.h>
267 #include <netinet/icmp6.h>
268 #include <netinet/sctp.h>
269 #include <netinet/sctp_header.h>
270 #include <netinet/tcp.h>
271 #include <netinet/udp.h>
272
273 #ifdef IPSEC
274 #include <net/route.h>
275 #include <netipsec/ipsec.h>
276 #endif
277
278 #include "as.h"
279
280 #define DUMMY_PORT 10010
281
282 #define MAXPACKET 65535 /* max ip packet size */
283
284 static u_char packet[512]; /* last inbound (icmp) packet */
285 static char *outpacket; /* last output packet */
286
287 int main(int, char *[]);
288 int wait_for_reply(int, struct msghdr *);
289 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
290 int setpolicy(int so, char *policy);
291 #endif
292 void send_probe(int, u_long);
293 void *get_uphdr(struct ip6_hdr *, u_char *);
294 void capdns_open(void);
295 int get_hoplim(struct msghdr *);
296 double deltaT(struct timeval *, struct timeval *);
297 const char *pr_type(int);
298 int packet_ok(struct msghdr *, int, int, u_char *, u_char *, u_char *);
299 void print(struct msghdr *, int);
300 const char *inetname(struct sockaddr *);
301 u_int32_t sctp_crc32c(void *, u_int32_t);
302 u_int16_t in_cksum(u_int16_t *addr, int);
303 u_int16_t udp_cksum(struct sockaddr_in6 *, struct sockaddr_in6 *,
304 void *, u_int32_t);
305 u_int16_t tcp_chksum(struct sockaddr_in6 *, struct sockaddr_in6 *,
306 void *, u_int32_t);
307 void usage(void);
308
309 static int rcvsock; /* receive (icmp) socket file descriptor */
310 static int sndsock; /* send (raw/udp) socket file descriptor */
311
312 static struct msghdr rcvmhdr;
313 static struct iovec rcviov[2];
314 static int rcvhlim;
315 static struct in6_pktinfo *rcvpktinfo;
316
317 static struct sockaddr_in6 Src, Dst, Rcv;
318 static u_long datalen = 20; /* How much data */
319 #define ICMP6ECHOLEN 8
320 /* XXX: 2064 = 127(max hops in type 0 rthdr) * sizeof(ip6_hdr) + 16(margin) */
321 static char rtbuf[2064];
322 static struct ip6_rthdr *rth;
323 static struct cmsghdr *cmsg;
324
325 static char *source = NULL;
326 static char *hostname;
327
328 static cap_channel_t *capdns;
329
330 static u_long nprobes = 3;
331 static u_long first_hop = 1;
332 static u_long max_hops = 30;
333 static u_int16_t srcport;
334 static u_int16_t port = 32768 + 666; /* start udp dest port # for probe packets */
335 static u_int16_t ident;
336 static int tclass = -1;
337 static int options; /* socket options */
338 static int verbose;
339 static int waittime = 5; /* time to wait for response (in seconds) */
340 static int nflag; /* print addresses numerically */
341 static int useproto = IPPROTO_UDP; /* protocol to use to send packet */
342 static int as_path; /* print as numbers for each hop */
343 static int ecnflag; /* ECN bleaching detection flag */
344 static char *as_server = NULL;
345 static void *asn;
346
347 int
main(int argc,char * argv[])348 main(int argc, char *argv[])
349 {
350 int mib[4] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_DEFHLIM };
351 char hbuf[NI_MAXHOST], src0[NI_MAXHOST], *ep;
352 int ch, i, on = 1, seq, rcvcmsglen, error;
353 struct addrinfo hints, *res;
354 static u_char *rcvcmsgbuf;
355 u_long probe, hops, lport, ltclass;
356 struct hostent *hp;
357 size_t size, minlen;
358 uid_t uid;
359 u_char type, code, ecn;
360 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
361 char ipsec_inpolicy[] = "in bypass";
362 char ipsec_outpolicy[] = "out bypass";
363 #endif
364 cap_rights_t rights;
365
366 capdns_open();
367
368 /*
369 * Receive ICMP
370 */
371 if ((rcvsock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) {
372 perror("socket(ICMPv6)");
373 exit(5);
374 }
375
376 size = sizeof(i);
377 (void) sysctl(mib, sizeof(mib) / sizeof(mib[0]), &i, &size, NULL, 0);
378 max_hops = i;
379
380 /* specify to tell receiving interface */
381 #ifdef IPV6_RECVPKTINFO
382 if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
383 sizeof(on)) < 0)
384 err(1, "setsockopt(IPV6_RECVPKTINFO)");
385 #else /* old adv. API */
386 if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_PKTINFO, &on,
387 sizeof(on)) < 0)
388 err(1, "setsockopt(IPV6_PKTINFO)");
389 #endif
390
391 /* specify to tell value of hoplimit field of received IP6 hdr */
392 #ifdef IPV6_RECVHOPLIMIT
393 if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on,
394 sizeof(on)) < 0)
395 err(1, "setsockopt(IPV6_RECVHOPLIMIT)");
396 #else /* old adv. API */
397 if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_HOPLIMIT, &on,
398 sizeof(on)) < 0)
399 err(1, "setsockopt(IPV6_HOPLIMIT)");
400 #endif
401
402 seq = 0;
403 ident = htons(getpid() & 0xffff); /* same as ping6 */
404
405 while ((ch = getopt(argc, argv, "aA:dEf:g:Ilm:nNp:q:rs:St:TUvw:")) != -1)
406 switch (ch) {
407 case 'a':
408 as_path = 1;
409 break;
410 case 'A':
411 as_path = 1;
412 as_server = optarg;
413 break;
414 case 'd':
415 options |= SO_DEBUG;
416 break;
417 case 'E':
418 ecnflag = 1;
419 break;
420 case 'f':
421 ep = NULL;
422 errno = 0;
423 first_hop = strtoul(optarg, &ep, 0);
424 if (errno || !*optarg || *ep || first_hop > 255) {
425 fprintf(stderr,
426 "traceroute6: invalid min hoplimit.\n");
427 exit(1);
428 }
429 break;
430 case 'g':
431 /* XXX use after capability mode is entered */
432 hp = getipnodebyname(optarg, AF_INET6, 0, &h_errno);
433 if (hp == NULL) {
434 fprintf(stderr,
435 "traceroute6: unknown host %s\n", optarg);
436 exit(1);
437 }
438 if (rth == NULL) {
439 /*
440 * XXX: We can't detect the number of
441 * intermediate nodes yet.
442 */
443 if ((rth = inet6_rth_init((void *)rtbuf,
444 sizeof(rtbuf), IPV6_RTHDR_TYPE_0,
445 0)) == NULL) {
446 fprintf(stderr,
447 "inet6_rth_init failed.\n");
448 exit(1);
449 }
450 }
451 if (inet6_rth_add((void *)rth,
452 (struct in6_addr *)hp->h_addr)) {
453 fprintf(stderr,
454 "inet6_rth_add failed for %s\n",
455 optarg);
456 exit(1);
457 }
458 freehostent(hp);
459 break;
460 case 'I':
461 useproto = IPPROTO_ICMPV6;
462 break;
463 case 'l':
464 break;
465 case 'm':
466 ep = NULL;
467 errno = 0;
468 max_hops = strtoul(optarg, &ep, 0);
469 if (errno || !*optarg || *ep || max_hops > 255) {
470 fprintf(stderr,
471 "traceroute6: invalid max hoplimit.\n");
472 exit(1);
473 }
474 break;
475 case 'n':
476 nflag++;
477 break;
478 case 'N':
479 useproto = IPPROTO_NONE;
480 break;
481 case 'p':
482 ep = NULL;
483 errno = 0;
484 lport = strtoul(optarg, &ep, 0);
485 if (errno || !*optarg || *ep) {
486 fprintf(stderr, "traceroute6: invalid port.\n");
487 exit(1);
488 }
489 if (lport == 0 || lport != (lport & 0xffff)) {
490 fprintf(stderr,
491 "traceroute6: port out of range.\n");
492 exit(1);
493 }
494 port = lport & 0xffff;
495 break;
496 case 'q':
497 ep = NULL;
498 errno = 0;
499 nprobes = strtoul(optarg, &ep, 0);
500 if (errno || !*optarg || *ep) {
501 fprintf(stderr,
502 "traceroute6: invalid nprobes.\n");
503 exit(1);
504 }
505 if (nprobes < 1) {
506 fprintf(stderr,
507 "traceroute6: nprobes must be >0.\n");
508 exit(1);
509 }
510 break;
511 case 'r':
512 options |= SO_DONTROUTE;
513 break;
514 case 's':
515 /*
516 * set the ip source address of the outbound
517 * probe (e.g., on a multi-homed host).
518 */
519 source = optarg;
520 break;
521 case 'S':
522 useproto = IPPROTO_SCTP;
523 break;
524 case 't':
525 ep = NULL;
526 errno = 0;
527 ltclass = strtoul(optarg, &ep, 0);
528 if (errno || !*optarg || *ep || ltclass > 255) {
529 fprintf(stderr,
530 "traceroute6: invalid traffic class.\n");
531 exit(1);
532 }
533 tclass = (int)ltclass;
534 break;
535 case 'T':
536 useproto = IPPROTO_TCP;
537 break;
538 case 'U':
539 useproto = IPPROTO_UDP;
540 break;
541 case 'v':
542 verbose++;
543 break;
544 case 'w':
545 ep = NULL;
546 errno = 0;
547 waittime = strtoul(optarg, &ep, 0);
548 if (errno || !*optarg || *ep) {
549 fprintf(stderr,
550 "traceroute6: invalid wait time.\n");
551 exit(1);
552 }
553 if (waittime < 1) {
554 fprintf(stderr,
555 "traceroute6: wait must be >= 1 sec.\n");
556 exit(1);
557 }
558 break;
559 default:
560 usage();
561 }
562 argc -= optind;
563 argv += optind;
564
565 /*
566 * Open socket to send probe packets.
567 */
568 switch (useproto) {
569 case IPPROTO_ICMPV6:
570 case IPPROTO_NONE:
571 case IPPROTO_SCTP:
572 case IPPROTO_TCP:
573 case IPPROTO_UDP:
574 if ((sndsock = socket(AF_INET6, SOCK_RAW, useproto)) < 0) {
575 perror("socket(SOCK_RAW)");
576 exit(5);
577 }
578 break;
579 default:
580 fprintf(stderr, "traceroute6: unknown probe protocol %d\n",
581 useproto);
582 exit(5);
583 }
584 if (max_hops < first_hop) {
585 fprintf(stderr,
586 "traceroute6: max hoplimit must be larger than first hoplimit.\n");
587 exit(1);
588 }
589
590 if (ecnflag) {
591 if (tclass != -1) {
592 tclass &= ~IPTOS_ECN_MASK;
593 } else {
594 tclass = 0;
595 }
596 tclass |= IPTOS_ECN_ECT1;
597 }
598
599 /* revoke privs */
600 uid = getuid();
601 if (setresuid(uid, uid, uid) == -1) {
602 perror("setresuid");
603 exit(1);
604 }
605
606 if (tclass != -1) {
607 if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_TCLASS, &tclass,
608 sizeof(int)) == -1) {
609 perror("setsockopt(IPV6_TCLASS)");
610 exit(7);
611 }
612 }
613
614 if (argc < 1 || argc > 2)
615 usage();
616
617 #if 1
618 setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
619 #else
620 setlinebuf(stdout);
621 #endif
622
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;
628
629 error = cap_getaddrinfo(capdns, *argv, NULL, &hints, &res);
630
631 if (error) {
632 fprintf(stderr,
633 "traceroute6: %s\n", gai_strerror(error));
634 exit(1);
635 }
636 if (res->ai_addrlen != sizeof(Dst)) {
637 fprintf(stderr,
638 "traceroute6: size of sockaddr mismatch\n");
639 exit(1);
640 }
641 memcpy(&Dst, res->ai_addr, res->ai_addrlen);
642 hostname = res->ai_canonname ? strdup(res->ai_canonname) : *argv;
643 if (!hostname) {
644 fprintf(stderr, "traceroute6: not enough core\n");
645 exit(1);
646 }
647 if (res->ai_next) {
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);
653 }
654 freeaddrinfo(res);
655 if (*++argv) {
656 ep = NULL;
657 errno = 0;
658 datalen = strtoul(*argv, &ep, 0);
659 if (errno || *ep) {
660 fprintf(stderr,
661 "traceroute6: invalid packet length.\n");
662 exit(1);
663 }
664 }
665 switch (useproto) {
666 case IPPROTO_ICMPV6:
667 minlen = ICMP6ECHOLEN;
668 break;
669 case IPPROTO_UDP:
670 minlen = sizeof(struct udphdr);
671 break;
672 case IPPROTO_NONE:
673 minlen = 0;
674 datalen = 0;
675 break;
676 case IPPROTO_SCTP:
677 minlen = sizeof(struct sctphdr);
678 break;
679 case IPPROTO_TCP:
680 minlen = sizeof(struct tcphdr);
681 break;
682 default:
683 fprintf(stderr, "traceroute6: unknown probe protocol %d.\n",
684 useproto);
685 exit(1);
686 }
687 if (datalen < minlen)
688 datalen = minlen;
689 else if (datalen >= MAXPACKET) {
690 fprintf(stderr,
691 "traceroute6: packet size must be %zu <= s < %d.\n",
692 minlen, MAXPACKET);
693 exit(1);
694 }
695 if ((useproto == IPPROTO_SCTP) && (datalen & 3)) {
696 fprintf(stderr,
697 "traceroute6: packet size must be a multiple of 4.\n");
698 exit(1);
699 }
700 outpacket = malloc(datalen);
701 if (!outpacket) {
702 perror("malloc");
703 exit(1);
704 }
705 (void) bzero((char *)outpacket, datalen);
706
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");
718 exit(1);
719 }
720 rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf;
721 rcvmhdr.msg_controllen = rcvcmsglen;
722
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)
730 /*
731 * do not raise error even if setsockopt fails, kernel may have ipsec
732 * turned off.
733 */
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());
738 #else
739 {
740 int level = IPSEC_LEVEL_NONE;
741
742 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, &level,
743 sizeof(level));
744 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_ESP_NETWORK_LEVEL, &level,
745 sizeof(level));
746 #ifdef IP_AUTH_TRANS_LEVEL
747 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, &level,
748 sizeof(level));
749 #else
750 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_LEVEL, &level,
751 sizeof(level));
752 #endif
753 #ifdef IP_AUTH_NETWORK_LEVEL
754 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_NETWORK_LEVEL, &level,
755 sizeof(level));
756 #endif
757 }
758 #endif /* !(IPSEC && IPSEC_POLICY_IPSEC) */
759
760 #ifdef SO_SNDBUF
761 i = datalen;
762 if (i == 0)
763 i = 1;
764 if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&i,
765 sizeof(i)) < 0) {
766 perror("setsockopt(SO_SNDBUF)");
767 exit(6);
768 }
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",
781 strerror(errno));
782 exit(1);
783 }
784 }
785 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
786 /*
787 * do not raise error even if setsockopt fails, kernel may have ipsec
788 * turned off.
789 */
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());
794 #else
795 {
796 int level = IPSEC_LEVEL_BYPASS;
797
798 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, &level,
799 sizeof(level));
800 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_ESP_NETWORK_LEVEL, &level,
801 sizeof(level));
802 #ifdef IP_AUTH_TRANS_LEVEL
803 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, &level,
804 sizeof(level));
805 #else
806 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_LEVEL, &level,
807 sizeof(level));
808 #endif
809 #ifdef IP_AUTH_NETWORK_LEVEL
810 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_NETWORK_LEVEL, &level,
811 sizeof(level));
812 #endif
813 }
814 #endif /* !(IPSEC && IPSEC_POLICY_IPSEC) */
815
816 /*
817 * Source selection
818 */
819 bzero(&Src, sizeof(Src));
820 if (source) {
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);
826 if (error) {
827 printf("traceroute6: %s: %s\n", source,
828 gai_strerror(error));
829 exit(1);
830 }
831 if (res->ai_addrlen > sizeof(Src)) {
832 printf("traceroute6: %s: %s\n", source,
833 gai_strerror(error));
834 exit(1);
835 }
836 memcpy(&Src, res->ai_addr, res->ai_addrlen);
837 freeaddrinfo(res);
838 } else {
839 struct sockaddr_in6 Nxt;
840 int dummy;
841 socklen_t len;
842
843 Nxt = Dst;
844 Nxt.sin6_port = htons(DUMMY_PORT);
845 if (cmsg != NULL)
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) {
849 perror("socket");
850 exit(1);
851 }
852 if (connect(dummy, (struct sockaddr *)&Nxt, Nxt.sin6_len) < 0) {
853 perror("connect");
854 exit(1);
855 }
856 len = sizeof(Src);
857 if (getsockname(dummy, (struct sockaddr *)&Src, &len) < 0) {
858 perror("getsockname");
859 exit(1);
860 }
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");
864 exit(1);
865 }
866 source = src0;
867 close(dummy);
868 }
869
870 Src.sin6_port = htons(0);
871 if (bind(sndsock, (struct sockaddr *)&Src, Src.sin6_len) < 0) {
872 perror("bind");
873 exit(1);
874 }
875
876 {
877 socklen_t len;
878
879 len = sizeof(Src);
880 if (getsockname(sndsock, (struct sockaddr *)&Src, &len) < 0) {
881 perror("getsockname");
882 exit(1);
883 }
884 srcport = ntohs(Src.sin6_port);
885 }
886
887 if (as_path) {
888 asn = as_setup(as_server);
889 if (asn == NULL) {
890 fprintf(stderr,
891 "traceroute6: as_setup failed, AS# lookups"
892 " disabled\n");
893 (void)fflush(stderr);
894 as_path = 0;
895 }
896 }
897
898 /*
899 * Message to users
900 */
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);
906 if (source)
907 fprintf(stderr, " from %s", source);
908 fprintf(stderr, ", %lu hops max, %lu byte packets\n",
909 max_hops,
910 datalen + ((useproto == IPPROTO_UDP) ? sizeof(struct udphdr) : 0));
911 (void) fflush(stderr);
912
913 if (first_hop > 1)
914 printf("Skipping %lu intermediate hops\n", first_hop - 1);
915
916 if (connect(sndsock, (struct sockaddr *)&Dst,
917 sizeof(Dst)) != 0) {
918 fprintf(stderr, "connect: %s\n", strerror(errno));
919 exit(1);
920 }
921
922 /*
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.
926 */
927 if (caph_enter_casper() < 0) {
928 fprintf(stderr, "caph_enter_casper: %s\n", strerror(errno));
929 exit(1);
930 }
931
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",
935 strerror(errno));
936 exit(1);
937 }
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",
941 strerror(errno));
942 exit(1);
943 }
944
945 /*
946 * Main loop
947 */
948 for (hops = first_hop; hops <= max_hops; ++hops) {
949 struct in6_addr lastaddr;
950 int got_there = 0;
951 unsigned unreachable = 0;
952
953 printf("%2lu ", hops);
954 bzero(&lastaddr, sizeof(lastaddr));
955 for (probe = 0; probe < nprobes; ++probe) {
956 int cc;
957 struct timeval t1, t2;
958
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, &ecn)) {
964 if (!IN6_ARE_ADDR_EQUAL(&Rcv.sin6_addr,
965 &lastaddr)) {
966 if (probe > 0)
967 fputs("\n ", stdout);
968 print(&rcvmhdr, cc);
969 lastaddr = Rcv.sin6_addr;
970 }
971 printf(" %.3f ms", deltaT(&t1, &t2));
972 if (ecnflag) {
973 switch (ecn) {
974 case IPTOS_ECN_ECT1:
975 printf(" (ecn=passed)");
976 break;
977 case IPTOS_ECN_NOTECT:
978 printf(" (ecn=bleached)");
979 break;
980 case IPTOS_ECN_CE:
981 printf(" (ecn=congested)");
982 break;
983 default:
984 printf(" (ecn=mangled)");
985 break;
986 }
987 }
988 if (type == ICMP6_DST_UNREACH) {
989 switch (code) {
990 case ICMP6_DST_UNREACH_NOROUTE:
991 ++unreachable;
992 printf(" !N");
993 break;
994 case ICMP6_DST_UNREACH_ADMIN:
995 ++unreachable;
996 printf(" !P");
997 break;
998 case ICMP6_DST_UNREACH_NOTNEIGHBOR:
999 ++unreachable;
1000 printf(" !S");
1001 break;
1002 case ICMP6_DST_UNREACH_ADDR:
1003 ++unreachable;
1004 printf(" !A");
1005 break;
1006 case ICMP6_DST_UNREACH_NOPORT:
1007 if (rcvhlim >= 0 &&
1008 rcvhlim <= 1)
1009 printf(" !");
1010 ++got_there;
1011 break;
1012 default:
1013 ++unreachable;
1014 printf(" !<%d>", code & 0xff);
1015 break;
1016 }
1017 } else if (type == ICMP6_PARAM_PROB &&
1018 code == ICMP6_PARAMPROB_NEXTHEADER) {
1019 printf(" !H");
1020 ++got_there;
1021 } else if (type == ICMP6_ECHO_REPLY) {
1022 if (rcvhlim >= 0 &&
1023 rcvhlim <= 1)
1024 printf(" !");
1025 ++got_there;
1026 }
1027 break;
1028 } else if (deltaT(&t1, &t2) > waittime * 1000) {
1029 cc = 0;
1030 break;
1031 }
1032 }
1033 if (cc == 0)
1034 printf(" *");
1035 (void) fflush(stdout);
1036 }
1037 putchar('\n');
1038 if (got_there ||
1039 (unreachable > 0 && unreachable >= ((nprobes + 1) / 2))) {
1040 exit(0);
1041 }
1042 }
1043 if (as_path)
1044 as_shutdown(asn);
1045
1046 exit(0);
1047 }
1048
1049 int
wait_for_reply(int sock,struct msghdr * mhdr)1050 wait_for_reply(int sock, struct msghdr *mhdr)
1051 {
1052 #ifdef HAVE_POLL
1053 struct pollfd pfd[1];
1054 int cc = 0;
1055
1056 pfd[0].fd = sock;
1057 pfd[0].events = POLLIN;
1058 pfd[0].revents = 0;
1059
1060 if (poll(pfd, 1, waittime * 1000) > 0 &&
1061 pfd[0].revents & POLLIN)
1062 cc = recvmsg(rcvsock, mhdr, 0);
1063
1064 return (cc);
1065 #else
1066 fd_set *fdsp;
1067 struct timeval wait;
1068 int cc = 0, fdsn;
1069
1070 fdsn = howmany(sock + 1, NFDBITS) * sizeof(fd_mask);
1071 if ((fdsp = (fd_set *)malloc(fdsn)) == NULL)
1072 err(1, "malloc");
1073 memset(fdsp, 0, fdsn);
1074 FD_SET(sock, fdsp);
1075 wait.tv_sec = waittime; wait.tv_usec = 0;
1076
1077 if (select(sock + 1, fdsp, (fd_set *)0, (fd_set *)0, &wait) > 0)
1078 cc = recvmsg(rcvsock, mhdr, 0);
1079
1080 free(fdsp);
1081 return (cc);
1082 #endif
1083 }
1084
1085 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
1086 int
setpolicy(int so,char * policy)1087 setpolicy(int so, char *policy)
1088 {
1089 char *buf;
1090
1091 buf = ipsec_set_policy(policy, strlen(policy));
1092 if (buf == NULL) {
1093 warnx("%s", ipsec_strerror());
1094 return (-1);
1095 }
1096 (void)setsockopt(so, IPPROTO_IPV6, IPV6_IPSEC_POLICY,
1097 buf, ipsec_get_policylen(buf));
1098
1099 free(buf);
1100
1101 return (0);
1102 }
1103 #endif
1104
1105 void
send_probe(int seq,u_long hops)1106 send_probe(int seq, u_long hops)
1107 {
1108 struct icmp6_hdr *icp;
1109 struct sctphdr *sctp;
1110 struct udphdr *outudp;
1111 struct sctp_chunkhdr *chk;
1112 struct sctp_init_chunk *init;
1113 struct sctp_paramhdr *param;
1114 struct tcphdr *tcp;
1115 int i;
1116
1117 i = hops;
1118 if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
1119 (char *)&i, sizeof(i)) < 0) {
1120 perror("setsockopt IPV6_UNICAST_HOPS");
1121 }
1122
1123 Dst.sin6_port = htons(port + seq);
1124
1125 switch (useproto) {
1126 case IPPROTO_ICMPV6:
1127 icp = (struct icmp6_hdr *)outpacket;
1128
1129 icp->icmp6_type = ICMP6_ECHO_REQUEST;
1130 icp->icmp6_code = 0;
1131 icp->icmp6_cksum = 0;
1132 icp->icmp6_id = ident;
1133 icp->icmp6_seq = htons(seq);
1134 break;
1135 case IPPROTO_UDP:
1136 outudp = (struct udphdr *) outpacket;
1137 outudp->uh_sport = htons(ident);
1138 outudp->uh_dport = htons(port + seq);
1139 outudp->uh_ulen = htons(datalen);
1140 outudp->uh_sum = 0;
1141 outudp->uh_sum = udp_cksum(&Src, &Dst, outpacket, datalen);
1142 break;
1143 case IPPROTO_NONE:
1144 /* No space for anything. No harm as seq/tv32 are decorative. */
1145 break;
1146 case IPPROTO_SCTP:
1147 sctp = (struct sctphdr *)outpacket;
1148
1149 sctp->src_port = htons(ident);
1150 sctp->dest_port = htons(port + seq);
1151 if (datalen >= (u_long)(sizeof(struct sctphdr) +
1152 sizeof(struct sctp_init_chunk))) {
1153 sctp->v_tag = 0;
1154 } else {
1155 sctp->v_tag = (sctp->src_port << 16) | sctp->dest_port;
1156 }
1157 sctp->checksum = htonl(0);
1158 if (datalen >= (u_long)(sizeof(struct sctphdr) +
1159 sizeof(struct sctp_init_chunk))) {
1160 /*
1161 * Send a packet containing an INIT chunk. This works
1162 * better in case of firewalls on the path, but
1163 * results in a probe packet containing at least
1164 * 32 bytes of payload. For shorter payloads, use
1165 * SHUTDOWN-ACK chunks.
1166 */
1167 init = (struct sctp_init_chunk *)(sctp + 1);
1168 init->ch.chunk_type = SCTP_INITIATION;
1169 init->ch.chunk_flags = 0;
1170 init->ch.chunk_length = htons((u_int16_t)(datalen -
1171 sizeof(struct sctphdr)));
1172 init->init.initiate_tag = (sctp->src_port << 16) |
1173 sctp->dest_port;
1174 init->init.a_rwnd = htonl(1500);
1175 init->init.num_outbound_streams = htons(1);
1176 init->init.num_inbound_streams = htons(1);
1177 init->init.initial_tsn = htonl(0);
1178 if (datalen >= (u_long)(sizeof(struct sctphdr) +
1179 sizeof(struct sctp_init_chunk) +
1180 sizeof(struct sctp_paramhdr))) {
1181 param = (struct sctp_paramhdr *)(init + 1);
1182 param->param_type = htons(SCTP_PAD);
1183 param->param_length =
1184 htons((u_int16_t)(datalen -
1185 sizeof(struct sctphdr) -
1186 sizeof(struct sctp_init_chunk)));
1187 }
1188 } else {
1189 /*
1190 * Send a packet containing a SHUTDOWN-ACK chunk,
1191 * possibly followed by a PAD chunk.
1192 */
1193 if (datalen >= (u_long)(sizeof(struct sctphdr) +
1194 sizeof(struct sctp_chunkhdr))) {
1195 chk = (struct sctp_chunkhdr *)(sctp + 1);
1196 chk->chunk_type = SCTP_SHUTDOWN_ACK;
1197 chk->chunk_flags = 0;
1198 chk->chunk_length = htons(4);
1199 }
1200 if (datalen >= (u_long)(sizeof(struct sctphdr) +
1201 2 * sizeof(struct sctp_chunkhdr))) {
1202 chk = chk + 1;
1203 chk->chunk_type = SCTP_PAD_CHUNK;
1204 chk->chunk_flags = 0;
1205 chk->chunk_length = htons((u_int16_t)(datalen -
1206 sizeof(struct sctphdr) -
1207 sizeof(struct sctp_chunkhdr)));
1208 }
1209 }
1210 sctp->checksum = sctp_crc32c(outpacket, datalen);
1211 break;
1212 case IPPROTO_TCP:
1213 tcp = (struct tcphdr *)outpacket;
1214
1215 tcp->th_sport = htons(ident);
1216 tcp->th_dport = htons(port + seq);
1217 tcp->th_seq = (tcp->th_sport << 16) | tcp->th_dport;
1218 tcp->th_ack = 0;
1219 tcp->th_off = 5;
1220 __tcp_set_flags(tcp, TH_SYN);
1221 tcp->th_sum = 0;
1222 tcp->th_sum = tcp_chksum(&Src, &Dst, outpacket, datalen);
1223 break;
1224 default:
1225 fprintf(stderr, "Unknown probe protocol %d.\n", useproto);
1226 exit(1);
1227 }
1228
1229 i = send(sndsock, (char *)outpacket, datalen, 0);
1230 if (i < 0 || (u_long)i != datalen) {
1231 if (i < 0)
1232 perror("send");
1233 printf("traceroute6: wrote %s %lu chars, ret=%d\n",
1234 hostname, datalen, i);
1235 (void) fflush(stdout);
1236 }
1237 }
1238
1239 int
get_hoplim(struct msghdr * mhdr)1240 get_hoplim(struct msghdr *mhdr)
1241 {
1242 struct cmsghdr *cm;
1243
1244 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
1245 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
1246 if (cm->cmsg_level == IPPROTO_IPV6 &&
1247 cm->cmsg_type == IPV6_HOPLIMIT &&
1248 cm->cmsg_len == CMSG_LEN(sizeof(int)))
1249 return (*(int *)CMSG_DATA(cm));
1250 }
1251
1252 return (-1);
1253 }
1254
1255 double
deltaT(struct timeval * t1p,struct timeval * t2p)1256 deltaT(struct timeval *t1p, struct timeval *t2p)
1257 {
1258 double dt;
1259
1260 dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
1261 (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
1262 return (dt);
1263 }
1264
1265 /*
1266 * Convert an ICMP "type" field to a printable string.
1267 */
1268 const char *
pr_type(int t0)1269 pr_type(int t0)
1270 {
1271 u_char t = t0 & 0xff;
1272 const char *cp;
1273
1274 switch (t) {
1275 case ICMP6_DST_UNREACH:
1276 cp = "Destination Unreachable";
1277 break;
1278 case ICMP6_PACKET_TOO_BIG:
1279 cp = "Packet Too Big";
1280 break;
1281 case ICMP6_TIME_EXCEEDED:
1282 cp = "Time Exceeded";
1283 break;
1284 case ICMP6_PARAM_PROB:
1285 cp = "Parameter Problem";
1286 break;
1287 case ICMP6_ECHO_REQUEST:
1288 cp = "Echo Request";
1289 break;
1290 case ICMP6_ECHO_REPLY:
1291 cp = "Echo Reply";
1292 break;
1293 case ICMP6_MEMBERSHIP_QUERY:
1294 cp = "Group Membership Query";
1295 break;
1296 case ICMP6_MEMBERSHIP_REPORT:
1297 cp = "Group Membership Report";
1298 break;
1299 case ICMP6_MEMBERSHIP_REDUCTION:
1300 cp = "Group Membership Reduction";
1301 break;
1302 case ND_ROUTER_SOLICIT:
1303 cp = "Router Solicitation";
1304 break;
1305 case ND_ROUTER_ADVERT:
1306 cp = "Router Advertisement";
1307 break;
1308 case ND_NEIGHBOR_SOLICIT:
1309 cp = "Neighbor Solicitation";
1310 break;
1311 case ND_NEIGHBOR_ADVERT:
1312 cp = "Neighbor Advertisement";
1313 break;
1314 case ND_REDIRECT:
1315 cp = "Redirect";
1316 break;
1317 default:
1318 cp = "Unknown";
1319 break;
1320 }
1321 return (cp);
1322 }
1323
1324 int
packet_ok(struct msghdr * mhdr,int cc,int seq,u_char * type,u_char * code,u_char * ecn)1325 packet_ok(struct msghdr *mhdr, int cc, int seq, u_char *type, u_char *code,
1326 u_char *ecn)
1327 {
1328 struct icmp6_hdr *icp;
1329 struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name;
1330 char *buf = (char *)mhdr->msg_iov[0].iov_base;
1331 struct cmsghdr *cm;
1332 int *hlimp;
1333 char hbuf[NI_MAXHOST];
1334
1335 #ifdef OLDRAWSOCKET
1336 int hlen;
1337 struct ip6_hdr *ip;
1338 #endif
1339
1340 #ifdef OLDRAWSOCKET
1341 ip = (struct ip6_hdr *) buf;
1342 hlen = sizeof(struct ip6_hdr);
1343 if (cc < hlen + sizeof(struct icmp6_hdr)) {
1344 if (verbose) {
1345 if (cap_getnameinfo(capdns, (struct sockaddr *)from, from->sin6_len,
1346 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
1347 strlcpy(hbuf, "invalid", sizeof(hbuf));
1348 printf("packet too short (%d bytes) from %s\n", cc,
1349 hbuf);
1350 }
1351 return (0);
1352 }
1353 cc -= hlen;
1354 icp = (struct icmp6_hdr *)(buf + hlen);
1355 #else
1356 if (cc < (int)sizeof(struct icmp6_hdr)) {
1357 if (verbose) {
1358 if (cap_getnameinfo(capdns, (struct sockaddr *)from, from->sin6_len,
1359 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
1360 strlcpy(hbuf, "invalid", sizeof(hbuf));
1361 printf("data too short (%d bytes) from %s\n", cc, hbuf);
1362 }
1363 return (0);
1364 }
1365 icp = (struct icmp6_hdr *)buf;
1366 #endif
1367 /* get optional information via advanced API */
1368 rcvpktinfo = NULL;
1369 hlimp = NULL;
1370 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
1371 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
1372 if (cm->cmsg_level == IPPROTO_IPV6 &&
1373 cm->cmsg_type == IPV6_PKTINFO &&
1374 cm->cmsg_len ==
1375 CMSG_LEN(sizeof(struct in6_pktinfo)))
1376 rcvpktinfo = (struct in6_pktinfo *)(CMSG_DATA(cm));
1377
1378 if (cm->cmsg_level == IPPROTO_IPV6 &&
1379 cm->cmsg_type == IPV6_HOPLIMIT &&
1380 cm->cmsg_len == CMSG_LEN(sizeof(int)))
1381 hlimp = (int *)CMSG_DATA(cm);
1382 }
1383 if (rcvpktinfo == NULL || hlimp == NULL) {
1384 warnx("failed to get received hop limit or packet info");
1385 #if 0
1386 return (0);
1387 #else
1388 rcvhlim = 0; /*XXX*/
1389 #endif
1390 } else
1391 rcvhlim = *hlimp;
1392
1393 *type = icp->icmp6_type;
1394 *code = icp->icmp6_code;
1395 if ((*type == ICMP6_TIME_EXCEEDED &&
1396 *code == ICMP6_TIME_EXCEED_TRANSIT) ||
1397 (*type == ICMP6_DST_UNREACH) ||
1398 (*type == ICMP6_PARAM_PROB &&
1399 *code == ICMP6_PARAMPROB_NEXTHEADER)) {
1400 struct ip6_hdr *hip;
1401 struct icmp6_hdr *icmp;
1402 struct sctp_init_chunk *init;
1403 struct sctphdr *sctp;
1404 struct tcphdr *tcp;
1405 struct udphdr *udp;
1406 void *up;
1407
1408 hip = (struct ip6_hdr *)(icp + 1);
1409 *ecn = ntohl(hip->ip6_flow & IPV6_ECN_MASK) >> 20;
1410 if ((up = get_uphdr(hip, (u_char *)(buf + cc))) == NULL) {
1411 if (verbose)
1412 warnx("failed to get upper layer header");
1413 return (0);
1414 }
1415 switch (useproto) {
1416 case IPPROTO_ICMPV6:
1417 icmp = (struct icmp6_hdr *)up;
1418 if (icmp->icmp6_id == ident &&
1419 icmp->icmp6_seq == htons(seq))
1420 return (1);
1421 break;
1422 case IPPROTO_UDP:
1423 udp = (struct udphdr *)up;
1424 if (udp->uh_sport == htons(ident) &&
1425 udp->uh_dport == htons(port + seq))
1426 return (1);
1427 break;
1428 case IPPROTO_SCTP:
1429 sctp = (struct sctphdr *)up;
1430 if (sctp->src_port != htons(ident) ||
1431 sctp->dest_port != htons(port + seq)) {
1432 break;
1433 }
1434 if (datalen >= (u_long)(sizeof(struct sctphdr) +
1435 sizeof(struct sctp_init_chunk))) {
1436 if (sctp->v_tag != 0) {
1437 break;
1438 }
1439 init = (struct sctp_init_chunk *)(sctp + 1);
1440 /* Check the initiate tag, if available. */
1441 if ((char *)&init->init.a_rwnd > buf + cc) {
1442 return (1);
1443 }
1444 if (init->init.initiate_tag == (u_int32_t)
1445 ((sctp->src_port << 16) | sctp->dest_port)) {
1446 return (1);
1447 }
1448 } else {
1449 if (sctp->v_tag ==
1450 (u_int32_t)((sctp->src_port << 16) |
1451 sctp->dest_port)) {
1452 return (1);
1453 }
1454 }
1455 break;
1456 case IPPROTO_TCP:
1457 tcp = (struct tcphdr *)up;
1458 if (tcp->th_sport == htons(ident) &&
1459 tcp->th_dport == htons(port + seq) &&
1460 tcp->th_seq ==
1461 (tcp_seq)((tcp->th_sport << 16) | tcp->th_dport))
1462 return (1);
1463 break;
1464 case IPPROTO_NONE:
1465 return (1);
1466 default:
1467 fprintf(stderr, "Unknown probe proto %d.\n", useproto);
1468 break;
1469 }
1470 } else if (useproto == IPPROTO_ICMPV6 && *type == ICMP6_ECHO_REPLY) {
1471 if (icp->icmp6_id == ident &&
1472 icp->icmp6_seq == htons(seq))
1473 return (1);
1474 }
1475 if (verbose) {
1476 char sbuf[NI_MAXHOST + 1], dbuf[INET6_ADDRSTRLEN];
1477 u_int8_t *p;
1478 int i;
1479
1480 if (cap_getnameinfo(capdns, (struct sockaddr *)from, from->sin6_len,
1481 sbuf, sizeof(sbuf), NULL, 0, NI_NUMERICHOST) != 0)
1482 strlcpy(sbuf, "invalid", sizeof(sbuf));
1483 printf("\n%d bytes from %s to %s", cc, sbuf,
1484 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,
1485 dbuf, sizeof(dbuf)) : "?");
1486 printf(": icmp type %d (%s) code %d\n", *type, pr_type(*type),
1487 *code);
1488 p = (u_int8_t *)(icp + 1);
1489 #define WIDTH 16
1490 for (i = 0; i < cc; i++) {
1491 if (i % WIDTH == 0)
1492 printf("%04x:", i);
1493 if (i % 4 == 0)
1494 printf(" ");
1495 printf("%02x", p[i]);
1496 if (i % WIDTH == WIDTH - 1)
1497 printf("\n");
1498 }
1499 if (cc % WIDTH != 0)
1500 printf("\n");
1501 }
1502 return (0);
1503 }
1504
1505 /*
1506 * Increment pointer until find the UDP or ICMP header.
1507 */
1508 void *
get_uphdr(struct ip6_hdr * ip6,u_char * lim)1509 get_uphdr(struct ip6_hdr *ip6, u_char *lim)
1510 {
1511 u_char *cp = (u_char *)ip6, nh;
1512 int hlen;
1513 static u_char none_hdr[1]; /* Fake pointer for IPPROTO_NONE. */
1514
1515 if (cp + sizeof(*ip6) > lim)
1516 return (NULL);
1517
1518 nh = ip6->ip6_nxt;
1519 cp += sizeof(struct ip6_hdr);
1520
1521 while (lim - cp >= (nh == IPPROTO_NONE ? 0 : 8)) {
1522 switch (nh) {
1523 case IPPROTO_ESP:
1524 return (NULL);
1525 case IPPROTO_ICMPV6:
1526 return (useproto == nh ? cp : NULL);
1527 case IPPROTO_SCTP:
1528 case IPPROTO_TCP:
1529 case IPPROTO_UDP:
1530 return (useproto == nh ? cp : NULL);
1531 case IPPROTO_NONE:
1532 return (useproto == nh ? none_hdr : NULL);
1533 case IPPROTO_FRAGMENT:
1534 hlen = sizeof(struct ip6_frag);
1535 nh = ((struct ip6_frag *)cp)->ip6f_nxt;
1536 break;
1537 case IPPROTO_AH:
1538 hlen = (((struct ip6_ext *)cp)->ip6e_len + 2) << 2;
1539 nh = ((struct ip6_ext *)cp)->ip6e_nxt;
1540 break;
1541 default:
1542 hlen = (((struct ip6_ext *)cp)->ip6e_len + 1) << 3;
1543 nh = ((struct ip6_ext *)cp)->ip6e_nxt;
1544 break;
1545 }
1546
1547 cp += hlen;
1548 }
1549
1550 return (NULL);
1551 }
1552
1553 void
capdns_open(void)1554 capdns_open(void)
1555 {
1556 #ifdef WITH_CASPER
1557 const char *types[] = { "NAME", "ADDR" };
1558 int families[1];
1559 cap_channel_t *casper;
1560
1561 casper = cap_init();
1562 if (casper == NULL)
1563 errx(1, "unable to create casper process");
1564 capdns = cap_service_open(casper, "system.dns");
1565 if (capdns == NULL)
1566 errx(1, "unable to open system.dns service");
1567 if (cap_dns_type_limit(capdns, types, nitems(types)) < 0)
1568 errx(1, "unable to limit access to system.dns service");
1569 families[0] = AF_INET6;
1570 if (cap_dns_family_limit(capdns, families, nitems(families)) < 0)
1571 errx(1, "unable to limit access to system.dns service");
1572 cap_close(casper);
1573 #endif /* WITH_CASPER */
1574 }
1575
1576 void
print(struct msghdr * mhdr,int cc)1577 print(struct msghdr *mhdr, int cc)
1578 {
1579 struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name;
1580 char hbuf[NI_MAXHOST];
1581
1582 if (cap_getnameinfo(capdns, (struct sockaddr *)from, from->sin6_len,
1583 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
1584 strlcpy(hbuf, "invalid", sizeof(hbuf));
1585 if (as_path)
1586 printf(" [AS%u]", as_lookup(asn, hbuf, AF_INET6));
1587 if (nflag)
1588 printf(" %s", hbuf);
1589 else
1590 printf(" %s (%s)", inetname((struct sockaddr *)from), hbuf);
1591
1592 if (verbose) {
1593 #ifdef OLDRAWSOCKET
1594 printf(" %d bytes to %s", cc,
1595 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,
1596 hbuf, sizeof(hbuf)) : "?");
1597 #else
1598 printf(" %d bytes of data to %s", cc,
1599 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,
1600 hbuf, sizeof(hbuf)) : "?");
1601 #endif
1602 }
1603 }
1604
1605 /*
1606 * Construct an Internet address representation.
1607 * If the nflag has been supplied, give
1608 * numeric value, otherwise try for symbolic name.
1609 */
1610 const char *
inetname(struct sockaddr * sa)1611 inetname(struct sockaddr *sa)
1612 {
1613 static char line[NI_MAXHOST], domain[MAXHOSTNAMELEN + 1];
1614 static int first = 1;
1615 char *cp;
1616
1617 if (first && !nflag) {
1618 first = 0;
1619 if (gethostname(domain, sizeof(domain)) == 0 &&
1620 (cp = strchr(domain, '.')))
1621 (void) strlcpy(domain, cp + 1, sizeof(domain));
1622 else
1623 domain[0] = 0;
1624 }
1625 cp = NULL;
1626 if (!nflag) {
1627 if (cap_getnameinfo(capdns, sa, sa->sa_len, line, sizeof(line), NULL, 0,
1628 NI_NAMEREQD) == 0) {
1629 if ((cp = strchr(line, '.')) &&
1630 !strcmp(cp + 1, domain))
1631 *cp = 0;
1632 cp = line;
1633 }
1634 }
1635 if (cp)
1636 return (cp);
1637
1638 if (cap_getnameinfo(capdns, sa, sa->sa_len, line, sizeof(line), NULL, 0,
1639 NI_NUMERICHOST) != 0)
1640 strlcpy(line, "invalid", sizeof(line));
1641 return (line);
1642 }
1643
1644 /*
1645 * CRC32C routine for the Stream Control Transmission Protocol
1646 */
1647
1648 #define CRC32C(c, d) (c = (c >> 8) ^ crc_c[(c ^ (d)) & 0xFF])
1649
1650 static u_int32_t crc_c[256] = {
1651 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
1652 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
1653 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
1654 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
1655 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
1656 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
1657 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
1658 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
1659 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
1660 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
1661 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
1662 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
1663 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
1664 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
1665 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
1666 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
1667 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
1668 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
1669 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
1670 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
1671 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
1672 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
1673 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
1674 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
1675 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
1676 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
1677 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
1678 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
1679 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
1680 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
1681 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
1682 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
1683 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
1684 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
1685 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
1686 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
1687 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
1688 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
1689 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
1690 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
1691 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
1692 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
1693 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
1694 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
1695 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
1696 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
1697 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
1698 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
1699 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
1700 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
1701 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
1702 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
1703 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
1704 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
1705 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
1706 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
1707 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
1708 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
1709 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
1710 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
1711 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
1712 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
1713 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
1714 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
1715 };
1716
1717 u_int32_t
sctp_crc32c(void * pack,u_int32_t len)1718 sctp_crc32c(void *pack, u_int32_t len)
1719 {
1720 u_int32_t i, crc32c;
1721 u_int8_t byte0, byte1, byte2, byte3;
1722 u_int8_t *buf = (u_int8_t *)pack;
1723
1724 crc32c = ~0;
1725 for (i = 0; i < len; i++)
1726 CRC32C(crc32c, buf[i]);
1727 crc32c = ~crc32c;
1728 byte0 = crc32c & 0xff;
1729 byte1 = (crc32c >> 8) & 0xff;
1730 byte2 = (crc32c >> 16) & 0xff;
1731 byte3 = (crc32c >> 24) & 0xff;
1732 crc32c = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
1733 return (htonl(crc32c));
1734 }
1735
1736 u_int16_t
in_cksum(u_int16_t * addr,int len)1737 in_cksum(u_int16_t *addr, int len)
1738 {
1739 int nleft = len;
1740 u_int16_t *w = addr;
1741 u_int16_t answer;
1742 int sum = 0;
1743
1744 /*
1745 * Our algorithm is simple, using a 32 bit accumulator (sum),
1746 * we add sequential 16 bit words to it, and at the end, fold
1747 * back all the carry bits from the top 16 bits into the lower
1748 * 16 bits.
1749 */
1750 while (nleft > 1) {
1751 sum += *w++;
1752 nleft -= 2;
1753 }
1754
1755 /* mop up an odd byte, if necessary */
1756 if (nleft == 1)
1757 sum += *(u_char *)w;
1758
1759 /*
1760 * add back carry outs from top 16 bits to low 16 bits
1761 */
1762 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
1763 sum += (sum >> 16); /* add carry */
1764 answer = ~sum; /* truncate to 16 bits */
1765 return (answer);
1766 }
1767
1768 u_int16_t
udp_cksum(struct sockaddr_in6 * src,struct sockaddr_in6 * dst,void * payload,u_int32_t len)1769 udp_cksum(struct sockaddr_in6 *src, struct sockaddr_in6 *dst,
1770 void *payload, u_int32_t len)
1771 {
1772 struct {
1773 struct in6_addr src;
1774 struct in6_addr dst;
1775 u_int32_t len;
1776 u_int8_t zero[3];
1777 u_int8_t next;
1778 } pseudo_hdr;
1779 u_int16_t sum[2];
1780
1781 pseudo_hdr.src = src->sin6_addr;
1782 pseudo_hdr.dst = dst->sin6_addr;
1783 pseudo_hdr.len = htonl(len);
1784 pseudo_hdr.zero[0] = 0;
1785 pseudo_hdr.zero[1] = 0;
1786 pseudo_hdr.zero[2] = 0;
1787 pseudo_hdr.next = IPPROTO_UDP;
1788
1789 sum[1] = in_cksum((u_int16_t *)&pseudo_hdr, sizeof(pseudo_hdr));
1790 sum[0] = in_cksum(payload, len);
1791
1792 return (~in_cksum(sum, sizeof(sum)));
1793 }
1794
1795 u_int16_t
tcp_chksum(struct sockaddr_in6 * src,struct sockaddr_in6 * dst,void * payload,u_int32_t len)1796 tcp_chksum(struct sockaddr_in6 *src, struct sockaddr_in6 *dst,
1797 void *payload, u_int32_t len)
1798 {
1799 struct {
1800 struct in6_addr src;
1801 struct in6_addr dst;
1802 u_int32_t len;
1803 u_int8_t zero[3];
1804 u_int8_t next;
1805 } pseudo_hdr;
1806 u_int16_t sum[2];
1807
1808 pseudo_hdr.src = src->sin6_addr;
1809 pseudo_hdr.dst = dst->sin6_addr;
1810 pseudo_hdr.len = htonl(len);
1811 pseudo_hdr.zero[0] = 0;
1812 pseudo_hdr.zero[1] = 0;
1813 pseudo_hdr.zero[2] = 0;
1814 pseudo_hdr.next = IPPROTO_TCP;
1815
1816 sum[1] = in_cksum((u_int16_t *)&pseudo_hdr, sizeof(pseudo_hdr));
1817 sum[0] = in_cksum(payload, len);
1818
1819 return (~in_cksum(sum, sizeof(sum)));
1820 }
1821
1822 void
usage(void)1823 usage(void)
1824 {
1825 fprintf(stderr,
1826 "Usage: traceroute6 [-adEIlnNrSTUv] [-A as_server] [-f firsthop] [-g gateway]\n"
1827 "\t[-m hoplimit] [-p port] [-q probes] [-s src] [-t tclass]\n"
1828 "\t[-w waittime] target [datalen]\n");
1829 exit(1);
1830 }
1831