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