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