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