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 }
1013 } else if (type == ICMP6_PARAM_PROB &&
1014 code == ICMP6_PARAMPROB_NEXTHEADER) {
1015 printf(" !H");
1016 ++got_there;
1017 } else if (type == ICMP6_ECHO_REPLY) {
1018 if (rcvhlim >= 0 &&
1019 rcvhlim <= 1)
1020 printf(" !");
1021 ++got_there;
1022 }
1023 break;
1024 } else if (deltaT(&t1, &t2) > waittime * 1000) {
1025 cc = 0;
1026 break;
1027 }
1028 }
1029 if (cc == 0)
1030 printf(" *");
1031 (void) fflush(stdout);
1032 }
1033 putchar('\n');
1034 if (got_there ||
1035 (unreachable > 0 && unreachable >= ((nprobes + 1) / 2))) {
1036 exit(0);
1037 }
1038 }
1039 if (as_path)
1040 as_shutdown(asn);
1041
1042 exit(0);
1043 }
1044
1045 int
wait_for_reply(int sock,struct msghdr * mhdr)1046 wait_for_reply(int sock, struct msghdr *mhdr)
1047 {
1048 #ifdef HAVE_POLL
1049 struct pollfd pfd[1];
1050 int cc = 0;
1051
1052 pfd[0].fd = sock;
1053 pfd[0].events = POLLIN;
1054 pfd[0].revents = 0;
1055
1056 if (poll(pfd, 1, waittime * 1000) > 0 &&
1057 pfd[0].revents & POLLIN)
1058 cc = recvmsg(rcvsock, mhdr, 0);
1059
1060 return (cc);
1061 #else
1062 fd_set *fdsp;
1063 struct timeval wait;
1064 int cc = 0, fdsn;
1065
1066 fdsn = howmany(sock + 1, NFDBITS) * sizeof(fd_mask);
1067 if ((fdsp = (fd_set *)malloc(fdsn)) == NULL)
1068 err(1, "malloc");
1069 memset(fdsp, 0, fdsn);
1070 FD_SET(sock, fdsp);
1071 wait.tv_sec = waittime; wait.tv_usec = 0;
1072
1073 if (select(sock + 1, fdsp, (fd_set *)0, (fd_set *)0, &wait) > 0)
1074 cc = recvmsg(rcvsock, mhdr, 0);
1075
1076 free(fdsp);
1077 return (cc);
1078 #endif
1079 }
1080
1081 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
1082 int
setpolicy(int so,char * policy)1083 setpolicy(int so, char *policy)
1084 {
1085 char *buf;
1086
1087 buf = ipsec_set_policy(policy, strlen(policy));
1088 if (buf == NULL) {
1089 warnx("%s", ipsec_strerror());
1090 return (-1);
1091 }
1092 (void)setsockopt(so, IPPROTO_IPV6, IPV6_IPSEC_POLICY,
1093 buf, ipsec_get_policylen(buf));
1094
1095 free(buf);
1096
1097 return (0);
1098 }
1099 #endif
1100
1101 void
send_probe(int seq,u_long hops)1102 send_probe(int seq, u_long hops)
1103 {
1104 struct icmp6_hdr *icp;
1105 struct sctphdr *sctp;
1106 struct udphdr *outudp;
1107 struct sctp_chunkhdr *chk;
1108 struct sctp_init_chunk *init;
1109 struct sctp_paramhdr *param;
1110 struct tcphdr *tcp;
1111 int i;
1112
1113 i = hops;
1114 if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
1115 (char *)&i, sizeof(i)) < 0) {
1116 perror("setsockopt IPV6_UNICAST_HOPS");
1117 }
1118
1119 Dst.sin6_port = htons(port + seq);
1120
1121 switch (useproto) {
1122 case IPPROTO_ICMPV6:
1123 icp = (struct icmp6_hdr *)outpacket;
1124
1125 icp->icmp6_type = ICMP6_ECHO_REQUEST;
1126 icp->icmp6_code = 0;
1127 icp->icmp6_cksum = 0;
1128 icp->icmp6_id = ident;
1129 icp->icmp6_seq = htons(seq);
1130 break;
1131 case IPPROTO_UDP:
1132 outudp = (struct udphdr *) outpacket;
1133 outudp->uh_sport = htons(ident);
1134 outudp->uh_dport = htons(port + seq);
1135 outudp->uh_ulen = htons(datalen);
1136 outudp->uh_sum = 0;
1137 outudp->uh_sum = udp_cksum(&Src, &Dst, outpacket, datalen);
1138 break;
1139 case IPPROTO_NONE:
1140 /* No space for anything. No harm as seq/tv32 are decorative. */
1141 break;
1142 case IPPROTO_SCTP:
1143 sctp = (struct sctphdr *)outpacket;
1144
1145 sctp->src_port = htons(ident);
1146 sctp->dest_port = htons(port + seq);
1147 if (datalen >= (u_long)(sizeof(struct sctphdr) +
1148 sizeof(struct sctp_init_chunk))) {
1149 sctp->v_tag = 0;
1150 } else {
1151 sctp->v_tag = (sctp->src_port << 16) | sctp->dest_port;
1152 }
1153 sctp->checksum = htonl(0);
1154 if (datalen >= (u_long)(sizeof(struct sctphdr) +
1155 sizeof(struct sctp_init_chunk))) {
1156 /*
1157 * Send a packet containing an INIT chunk. This works
1158 * better in case of firewalls on the path, but
1159 * results in a probe packet containing at least
1160 * 32 bytes of payload. For shorter payloads, use
1161 * SHUTDOWN-ACK chunks.
1162 */
1163 init = (struct sctp_init_chunk *)(sctp + 1);
1164 init->ch.chunk_type = SCTP_INITIATION;
1165 init->ch.chunk_flags = 0;
1166 init->ch.chunk_length = htons((u_int16_t)(datalen -
1167 sizeof(struct sctphdr)));
1168 init->init.initiate_tag = (sctp->src_port << 16) |
1169 sctp->dest_port;
1170 init->init.a_rwnd = htonl(1500);
1171 init->init.num_outbound_streams = htons(1);
1172 init->init.num_inbound_streams = htons(1);
1173 init->init.initial_tsn = htonl(0);
1174 if (datalen >= (u_long)(sizeof(struct sctphdr) +
1175 sizeof(struct sctp_init_chunk) +
1176 sizeof(struct sctp_paramhdr))) {
1177 param = (struct sctp_paramhdr *)(init + 1);
1178 param->param_type = htons(SCTP_PAD);
1179 param->param_length =
1180 htons((u_int16_t)(datalen -
1181 sizeof(struct sctphdr) -
1182 sizeof(struct sctp_init_chunk)));
1183 }
1184 } else {
1185 /*
1186 * Send a packet containing a SHUTDOWN-ACK chunk,
1187 * possibly followed by a PAD chunk.
1188 */
1189 if (datalen >= (u_long)(sizeof(struct sctphdr) +
1190 sizeof(struct sctp_chunkhdr))) {
1191 chk = (struct sctp_chunkhdr *)(sctp + 1);
1192 chk->chunk_type = SCTP_SHUTDOWN_ACK;
1193 chk->chunk_flags = 0;
1194 chk->chunk_length = htons(4);
1195 }
1196 if (datalen >= (u_long)(sizeof(struct sctphdr) +
1197 2 * sizeof(struct sctp_chunkhdr))) {
1198 chk = chk + 1;
1199 chk->chunk_type = SCTP_PAD_CHUNK;
1200 chk->chunk_flags = 0;
1201 chk->chunk_length = htons((u_int16_t)(datalen -
1202 sizeof(struct sctphdr) -
1203 sizeof(struct sctp_chunkhdr)));
1204 }
1205 }
1206 sctp->checksum = sctp_crc32c(outpacket, datalen);
1207 break;
1208 case IPPROTO_TCP:
1209 tcp = (struct tcphdr *)outpacket;
1210
1211 tcp->th_sport = htons(ident);
1212 tcp->th_dport = htons(port + seq);
1213 tcp->th_seq = (tcp->th_sport << 16) | tcp->th_dport;
1214 tcp->th_ack = 0;
1215 tcp->th_off = 5;
1216 __tcp_set_flags(tcp, TH_SYN);
1217 tcp->th_sum = 0;
1218 tcp->th_sum = tcp_chksum(&Src, &Dst, outpacket, datalen);
1219 break;
1220 default:
1221 fprintf(stderr, "Unknown probe protocol %d.\n", useproto);
1222 exit(1);
1223 }
1224
1225 i = send(sndsock, (char *)outpacket, datalen, 0);
1226 if (i < 0 || (u_long)i != datalen) {
1227 if (i < 0)
1228 perror("send");
1229 printf("traceroute6: wrote %s %lu chars, ret=%d\n",
1230 hostname, datalen, i);
1231 (void) fflush(stdout);
1232 }
1233 }
1234
1235 int
get_hoplim(struct msghdr * mhdr)1236 get_hoplim(struct msghdr *mhdr)
1237 {
1238 struct cmsghdr *cm;
1239
1240 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
1241 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
1242 if (cm->cmsg_level == IPPROTO_IPV6 &&
1243 cm->cmsg_type == IPV6_HOPLIMIT &&
1244 cm->cmsg_len == CMSG_LEN(sizeof(int)))
1245 return (*(int *)CMSG_DATA(cm));
1246 }
1247
1248 return (-1);
1249 }
1250
1251 double
deltaT(struct timeval * t1p,struct timeval * t2p)1252 deltaT(struct timeval *t1p, struct timeval *t2p)
1253 {
1254 double dt;
1255
1256 dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
1257 (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
1258 return (dt);
1259 }
1260
1261 /*
1262 * Convert an ICMP "type" field to a printable string.
1263 */
1264 const char *
pr_type(int t0)1265 pr_type(int t0)
1266 {
1267 u_char t = t0 & 0xff;
1268 const char *cp;
1269
1270 switch (t) {
1271 case ICMP6_DST_UNREACH:
1272 cp = "Destination Unreachable";
1273 break;
1274 case ICMP6_PACKET_TOO_BIG:
1275 cp = "Packet Too Big";
1276 break;
1277 case ICMP6_TIME_EXCEEDED:
1278 cp = "Time Exceeded";
1279 break;
1280 case ICMP6_PARAM_PROB:
1281 cp = "Parameter Problem";
1282 break;
1283 case ICMP6_ECHO_REQUEST:
1284 cp = "Echo Request";
1285 break;
1286 case ICMP6_ECHO_REPLY:
1287 cp = "Echo Reply";
1288 break;
1289 case ICMP6_MEMBERSHIP_QUERY:
1290 cp = "Group Membership Query";
1291 break;
1292 case ICMP6_MEMBERSHIP_REPORT:
1293 cp = "Group Membership Report";
1294 break;
1295 case ICMP6_MEMBERSHIP_REDUCTION:
1296 cp = "Group Membership Reduction";
1297 break;
1298 case ND_ROUTER_SOLICIT:
1299 cp = "Router Solicitation";
1300 break;
1301 case ND_ROUTER_ADVERT:
1302 cp = "Router Advertisement";
1303 break;
1304 case ND_NEIGHBOR_SOLICIT:
1305 cp = "Neighbor Solicitation";
1306 break;
1307 case ND_NEIGHBOR_ADVERT:
1308 cp = "Neighbor Advertisement";
1309 break;
1310 case ND_REDIRECT:
1311 cp = "Redirect";
1312 break;
1313 default:
1314 cp = "Unknown";
1315 break;
1316 }
1317 return (cp);
1318 }
1319
1320 int
packet_ok(struct msghdr * mhdr,int cc,int seq,u_char * type,u_char * code,u_char * ecn)1321 packet_ok(struct msghdr *mhdr, int cc, int seq, u_char *type, u_char *code,
1322 u_char *ecn)
1323 {
1324 struct icmp6_hdr *icp;
1325 struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name;
1326 char *buf = (char *)mhdr->msg_iov[0].iov_base;
1327 struct cmsghdr *cm;
1328 int *hlimp;
1329 char hbuf[NI_MAXHOST];
1330
1331 #ifdef OLDRAWSOCKET
1332 int hlen;
1333 struct ip6_hdr *ip;
1334 #endif
1335
1336 #ifdef OLDRAWSOCKET
1337 ip = (struct ip6_hdr *) buf;
1338 hlen = sizeof(struct ip6_hdr);
1339 if (cc < hlen + sizeof(struct icmp6_hdr)) {
1340 if (verbose) {
1341 if (cap_getnameinfo(capdns, (struct sockaddr *)from, from->sin6_len,
1342 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
1343 strlcpy(hbuf, "invalid", sizeof(hbuf));
1344 printf("packet too short (%d bytes) from %s\n", cc,
1345 hbuf);
1346 }
1347 return (0);
1348 }
1349 cc -= hlen;
1350 icp = (struct icmp6_hdr *)(buf + hlen);
1351 #else
1352 if (cc < (int)sizeof(struct icmp6_hdr)) {
1353 if (verbose) {
1354 if (cap_getnameinfo(capdns, (struct sockaddr *)from, from->sin6_len,
1355 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
1356 strlcpy(hbuf, "invalid", sizeof(hbuf));
1357 printf("data too short (%d bytes) from %s\n", cc, hbuf);
1358 }
1359 return (0);
1360 }
1361 icp = (struct icmp6_hdr *)buf;
1362 #endif
1363 /* get optional information via advanced API */
1364 rcvpktinfo = NULL;
1365 hlimp = NULL;
1366 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
1367 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
1368 if (cm->cmsg_level == IPPROTO_IPV6 &&
1369 cm->cmsg_type == IPV6_PKTINFO &&
1370 cm->cmsg_len ==
1371 CMSG_LEN(sizeof(struct in6_pktinfo)))
1372 rcvpktinfo = (struct in6_pktinfo *)(CMSG_DATA(cm));
1373
1374 if (cm->cmsg_level == IPPROTO_IPV6 &&
1375 cm->cmsg_type == IPV6_HOPLIMIT &&
1376 cm->cmsg_len == CMSG_LEN(sizeof(int)))
1377 hlimp = (int *)CMSG_DATA(cm);
1378 }
1379 if (rcvpktinfo == NULL || hlimp == NULL) {
1380 warnx("failed to get received hop limit or packet info");
1381 #if 0
1382 return (0);
1383 #else
1384 rcvhlim = 0; /*XXX*/
1385 #endif
1386 } else
1387 rcvhlim = *hlimp;
1388
1389 *type = icp->icmp6_type;
1390 *code = icp->icmp6_code;
1391 if ((*type == ICMP6_TIME_EXCEEDED &&
1392 *code == ICMP6_TIME_EXCEED_TRANSIT) ||
1393 (*type == ICMP6_DST_UNREACH) ||
1394 (*type == ICMP6_PARAM_PROB &&
1395 *code == ICMP6_PARAMPROB_NEXTHEADER)) {
1396 struct ip6_hdr *hip;
1397 struct icmp6_hdr *icmp;
1398 struct sctp_init_chunk *init;
1399 struct sctphdr *sctp;
1400 struct tcphdr *tcp;
1401 struct udphdr *udp;
1402 void *up;
1403
1404 hip = (struct ip6_hdr *)(icp + 1);
1405 *ecn = ntohl(hip->ip6_flow & IPV6_ECN_MASK) >> 20;
1406 if ((up = get_uphdr(hip, (u_char *)(buf + cc))) == NULL) {
1407 if (verbose)
1408 warnx("failed to get upper layer header");
1409 return (0);
1410 }
1411 switch (useproto) {
1412 case IPPROTO_ICMPV6:
1413 icmp = (struct icmp6_hdr *)up;
1414 if (icmp->icmp6_id == ident &&
1415 icmp->icmp6_seq == htons(seq))
1416 return (1);
1417 break;
1418 case IPPROTO_UDP:
1419 udp = (struct udphdr *)up;
1420 if (udp->uh_sport == htons(ident) &&
1421 udp->uh_dport == htons(port + seq))
1422 return (1);
1423 break;
1424 case IPPROTO_SCTP:
1425 sctp = (struct sctphdr *)up;
1426 if (sctp->src_port != htons(ident) ||
1427 sctp->dest_port != htons(port + seq)) {
1428 break;
1429 }
1430 if (datalen >= (u_long)(sizeof(struct sctphdr) +
1431 sizeof(struct sctp_init_chunk))) {
1432 if (sctp->v_tag != 0) {
1433 break;
1434 }
1435 init = (struct sctp_init_chunk *)(sctp + 1);
1436 /* Check the initiate tag, if available. */
1437 if ((char *)&init->init.a_rwnd > buf + cc) {
1438 return (1);
1439 }
1440 if (init->init.initiate_tag == (u_int32_t)
1441 ((sctp->src_port << 16) | sctp->dest_port)) {
1442 return (1);
1443 }
1444 } else {
1445 if (sctp->v_tag ==
1446 (u_int32_t)((sctp->src_port << 16) |
1447 sctp->dest_port)) {
1448 return (1);
1449 }
1450 }
1451 break;
1452 case IPPROTO_TCP:
1453 tcp = (struct tcphdr *)up;
1454 if (tcp->th_sport == htons(ident) &&
1455 tcp->th_dport == htons(port + seq) &&
1456 tcp->th_seq ==
1457 (tcp_seq)((tcp->th_sport << 16) | tcp->th_dport))
1458 return (1);
1459 break;
1460 case IPPROTO_NONE:
1461 return (1);
1462 default:
1463 fprintf(stderr, "Unknown probe proto %d.\n", useproto);
1464 break;
1465 }
1466 } else if (useproto == IPPROTO_ICMPV6 && *type == ICMP6_ECHO_REPLY) {
1467 if (icp->icmp6_id == ident &&
1468 icp->icmp6_seq == htons(seq))
1469 return (1);
1470 }
1471 if (verbose) {
1472 char sbuf[NI_MAXHOST + 1], dbuf[INET6_ADDRSTRLEN];
1473 u_int8_t *p;
1474 int i;
1475
1476 if (cap_getnameinfo(capdns, (struct sockaddr *)from, from->sin6_len,
1477 sbuf, sizeof(sbuf), NULL, 0, NI_NUMERICHOST) != 0)
1478 strlcpy(sbuf, "invalid", sizeof(sbuf));
1479 printf("\n%d bytes from %s to %s", cc, sbuf,
1480 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,
1481 dbuf, sizeof(dbuf)) : "?");
1482 printf(": icmp type %d (%s) code %d\n", *type, pr_type(*type),
1483 *code);
1484 p = (u_int8_t *)(icp + 1);
1485 #define WIDTH 16
1486 for (i = 0; i < cc; i++) {
1487 if (i % WIDTH == 0)
1488 printf("%04x:", i);
1489 if (i % 4 == 0)
1490 printf(" ");
1491 printf("%02x", p[i]);
1492 if (i % WIDTH == WIDTH - 1)
1493 printf("\n");
1494 }
1495 if (cc % WIDTH != 0)
1496 printf("\n");
1497 }
1498 return (0);
1499 }
1500
1501 /*
1502 * Increment pointer until find the UDP or ICMP header.
1503 */
1504 void *
get_uphdr(struct ip6_hdr * ip6,u_char * lim)1505 get_uphdr(struct ip6_hdr *ip6, u_char *lim)
1506 {
1507 u_char *cp = (u_char *)ip6, nh;
1508 int hlen;
1509 static u_char none_hdr[1]; /* Fake pointer for IPPROTO_NONE. */
1510
1511 if (cp + sizeof(*ip6) > lim)
1512 return (NULL);
1513
1514 nh = ip6->ip6_nxt;
1515 cp += sizeof(struct ip6_hdr);
1516
1517 while (lim - cp >= (nh == IPPROTO_NONE ? 0 : 8)) {
1518 switch (nh) {
1519 case IPPROTO_ESP:
1520 return (NULL);
1521 case IPPROTO_ICMPV6:
1522 return (useproto == nh ? cp : NULL);
1523 case IPPROTO_SCTP:
1524 case IPPROTO_TCP:
1525 case IPPROTO_UDP:
1526 return (useproto == nh ? cp : NULL);
1527 case IPPROTO_NONE:
1528 return (useproto == nh ? none_hdr : NULL);
1529 case IPPROTO_FRAGMENT:
1530 hlen = sizeof(struct ip6_frag);
1531 nh = ((struct ip6_frag *)cp)->ip6f_nxt;
1532 break;
1533 case IPPROTO_AH:
1534 hlen = (((struct ip6_ext *)cp)->ip6e_len + 2) << 2;
1535 nh = ((struct ip6_ext *)cp)->ip6e_nxt;
1536 break;
1537 default:
1538 hlen = (((struct ip6_ext *)cp)->ip6e_len + 1) << 3;
1539 nh = ((struct ip6_ext *)cp)->ip6e_nxt;
1540 break;
1541 }
1542
1543 cp += hlen;
1544 }
1545
1546 return (NULL);
1547 }
1548
1549 void
capdns_open(void)1550 capdns_open(void)
1551 {
1552 #ifdef WITH_CASPER
1553 const char *types[] = { "NAME", "ADDR" };
1554 int families[1];
1555 cap_channel_t *casper;
1556
1557 casper = cap_init();
1558 if (casper == NULL)
1559 errx(1, "unable to create casper process");
1560 capdns = cap_service_open(casper, "system.dns");
1561 if (capdns == NULL)
1562 errx(1, "unable to open system.dns service");
1563 if (cap_dns_type_limit(capdns, types, nitems(types)) < 0)
1564 errx(1, "unable to limit access to system.dns service");
1565 families[0] = AF_INET6;
1566 if (cap_dns_family_limit(capdns, families, nitems(families)) < 0)
1567 errx(1, "unable to limit access to system.dns service");
1568 cap_close(casper);
1569 #endif /* WITH_CASPER */
1570 }
1571
1572 void
print(struct msghdr * mhdr,int cc)1573 print(struct msghdr *mhdr, int cc)
1574 {
1575 struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name;
1576 char hbuf[NI_MAXHOST];
1577
1578 if (cap_getnameinfo(capdns, (struct sockaddr *)from, from->sin6_len,
1579 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
1580 strlcpy(hbuf, "invalid", sizeof(hbuf));
1581 if (as_path)
1582 printf(" [AS%u]", as_lookup(asn, hbuf, AF_INET6));
1583 if (nflag)
1584 printf(" %s", hbuf);
1585 else
1586 printf(" %s (%s)", inetname((struct sockaddr *)from), hbuf);
1587
1588 if (verbose) {
1589 #ifdef OLDRAWSOCKET
1590 printf(" %d bytes to %s", cc,
1591 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,
1592 hbuf, sizeof(hbuf)) : "?");
1593 #else
1594 printf(" %d bytes of data to %s", cc,
1595 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,
1596 hbuf, sizeof(hbuf)) : "?");
1597 #endif
1598 }
1599 }
1600
1601 /*
1602 * Construct an Internet address representation.
1603 * If the nflag has been supplied, give
1604 * numeric value, otherwise try for symbolic name.
1605 */
1606 const char *
inetname(struct sockaddr * sa)1607 inetname(struct sockaddr *sa)
1608 {
1609 static char line[NI_MAXHOST], domain[MAXHOSTNAMELEN + 1];
1610 static int first = 1;
1611 char *cp;
1612
1613 if (first && !nflag) {
1614 first = 0;
1615 if (gethostname(domain, sizeof(domain)) == 0 &&
1616 (cp = strchr(domain, '.')))
1617 (void) strlcpy(domain, cp + 1, sizeof(domain));
1618 else
1619 domain[0] = 0;
1620 }
1621 cp = NULL;
1622 if (!nflag) {
1623 if (cap_getnameinfo(capdns, sa, sa->sa_len, line, sizeof(line), NULL, 0,
1624 NI_NAMEREQD) == 0) {
1625 if ((cp = strchr(line, '.')) &&
1626 !strcmp(cp + 1, domain))
1627 *cp = 0;
1628 cp = line;
1629 }
1630 }
1631 if (cp)
1632 return (cp);
1633
1634 if (cap_getnameinfo(capdns, sa, sa->sa_len, line, sizeof(line), NULL, 0,
1635 NI_NUMERICHOST) != 0)
1636 strlcpy(line, "invalid", sizeof(line));
1637 return (line);
1638 }
1639
1640 /*
1641 * CRC32C routine for the Stream Control Transmission Protocol
1642 */
1643
1644 #define CRC32C(c, d) (c = (c >> 8) ^ crc_c[(c ^ (d)) & 0xFF])
1645
1646 static u_int32_t crc_c[256] = {
1647 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
1648 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
1649 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
1650 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
1651 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
1652 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
1653 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
1654 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
1655 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
1656 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
1657 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
1658 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
1659 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
1660 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
1661 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
1662 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
1663 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
1664 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
1665 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
1666 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
1667 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
1668 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
1669 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
1670 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
1671 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
1672 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
1673 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
1674 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
1675 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
1676 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
1677 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
1678 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
1679 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
1680 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
1681 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
1682 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
1683 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
1684 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
1685 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
1686 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
1687 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
1688 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
1689 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
1690 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
1691 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
1692 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
1693 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
1694 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
1695 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
1696 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
1697 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
1698 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
1699 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
1700 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
1701 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
1702 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
1703 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
1704 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
1705 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
1706 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
1707 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
1708 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
1709 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
1710 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
1711 };
1712
1713 u_int32_t
sctp_crc32c(void * pack,u_int32_t len)1714 sctp_crc32c(void *pack, u_int32_t len)
1715 {
1716 u_int32_t i, crc32c;
1717 u_int8_t byte0, byte1, byte2, byte3;
1718 u_int8_t *buf = (u_int8_t *)pack;
1719
1720 crc32c = ~0;
1721 for (i = 0; i < len; i++)
1722 CRC32C(crc32c, buf[i]);
1723 crc32c = ~crc32c;
1724 byte0 = crc32c & 0xff;
1725 byte1 = (crc32c >> 8) & 0xff;
1726 byte2 = (crc32c >> 16) & 0xff;
1727 byte3 = (crc32c >> 24) & 0xff;
1728 crc32c = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
1729 return (htonl(crc32c));
1730 }
1731
1732 u_int16_t
in_cksum(u_int16_t * addr,int len)1733 in_cksum(u_int16_t *addr, int len)
1734 {
1735 int nleft = len;
1736 u_int16_t *w = addr;
1737 u_int16_t answer;
1738 int sum = 0;
1739
1740 /*
1741 * Our algorithm is simple, using a 32 bit accumulator (sum),
1742 * we add sequential 16 bit words to it, and at the end, fold
1743 * back all the carry bits from the top 16 bits into the lower
1744 * 16 bits.
1745 */
1746 while (nleft > 1) {
1747 sum += *w++;
1748 nleft -= 2;
1749 }
1750
1751 /* mop up an odd byte, if necessary */
1752 if (nleft == 1)
1753 sum += *(u_char *)w;
1754
1755 /*
1756 * add back carry outs from top 16 bits to low 16 bits
1757 */
1758 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
1759 sum += (sum >> 16); /* add carry */
1760 answer = ~sum; /* truncate to 16 bits */
1761 return (answer);
1762 }
1763
1764 u_int16_t
udp_cksum(struct sockaddr_in6 * src,struct sockaddr_in6 * dst,void * payload,u_int32_t len)1765 udp_cksum(struct sockaddr_in6 *src, struct sockaddr_in6 *dst,
1766 void *payload, u_int32_t len)
1767 {
1768 struct {
1769 struct in6_addr src;
1770 struct in6_addr dst;
1771 u_int32_t len;
1772 u_int8_t zero[3];
1773 u_int8_t next;
1774 } pseudo_hdr;
1775 u_int16_t sum[2];
1776
1777 pseudo_hdr.src = src->sin6_addr;
1778 pseudo_hdr.dst = dst->sin6_addr;
1779 pseudo_hdr.len = htonl(len);
1780 pseudo_hdr.zero[0] = 0;
1781 pseudo_hdr.zero[1] = 0;
1782 pseudo_hdr.zero[2] = 0;
1783 pseudo_hdr.next = IPPROTO_UDP;
1784
1785 sum[1] = in_cksum((u_int16_t *)&pseudo_hdr, sizeof(pseudo_hdr));
1786 sum[0] = in_cksum(payload, len);
1787
1788 return (~in_cksum(sum, sizeof(sum)));
1789 }
1790
1791 u_int16_t
tcp_chksum(struct sockaddr_in6 * src,struct sockaddr_in6 * dst,void * payload,u_int32_t len)1792 tcp_chksum(struct sockaddr_in6 *src, struct sockaddr_in6 *dst,
1793 void *payload, u_int32_t len)
1794 {
1795 struct {
1796 struct in6_addr src;
1797 struct in6_addr dst;
1798 u_int32_t len;
1799 u_int8_t zero[3];
1800 u_int8_t next;
1801 } pseudo_hdr;
1802 u_int16_t sum[2];
1803
1804 pseudo_hdr.src = src->sin6_addr;
1805 pseudo_hdr.dst = dst->sin6_addr;
1806 pseudo_hdr.len = htonl(len);
1807 pseudo_hdr.zero[0] = 0;
1808 pseudo_hdr.zero[1] = 0;
1809 pseudo_hdr.zero[2] = 0;
1810 pseudo_hdr.next = IPPROTO_TCP;
1811
1812 sum[1] = in_cksum((u_int16_t *)&pseudo_hdr, sizeof(pseudo_hdr));
1813 sum[0] = in_cksum(payload, len);
1814
1815 return (~in_cksum(sum, sizeof(sum)));
1816 }
1817
1818 void
usage(void)1819 usage(void)
1820 {
1821 fprintf(stderr,
1822 "Usage: traceroute6 [-adEIlnNrSTUv] [-A as_server] [-f firsthop] [-g gateway]\n"
1823 "\t[-m hoplimit] [-p port] [-q probes] [-s src] [-t tclass]\n"
1824 "\t[-w waittime] target [datalen]\n");
1825 exit(1);
1826 }
1827