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/time.h> 253 #include <sys/socket.h> 254 #include <sys/uio.h> 255 #include <sys/file.h> 256 #include <sys/ioctl.h> 257 #include <sys/sysctl.h> 258 259 #include <netinet/in.h> 260 261 #include <arpa/inet.h> 262 263 #include <netdb.h> 264 #include <stdio.h> 265 #include <err.h> 266 #ifdef HAVE_POLL 267 #include <poll.h> 268 #endif 269 #include <errno.h> 270 #include <stdlib.h> 271 #include <string.h> 272 #include <unistd.h> 273 274 #include <netinet/ip6.h> 275 #include <netinet/icmp6.h> 276 #include <netinet/sctp.h> 277 #include <netinet/sctp_header.h> 278 #include <netinet/tcp.h> 279 #include <netinet/udp.h> 280 281 #ifdef IPSEC 282 #include <net/route.h> 283 #include <netipsec/ipsec.h> 284 #endif 285 286 #include "as.h" 287 288 #define DUMMY_PORT 10010 289 290 #define MAXPACKET 65535 /* max ip packet size */ 291 292 #ifndef HAVE_GETIPNODEBYNAME 293 #define getipnodebyname(x, y, z, u) gethostbyname2((x), (y)) 294 #define freehostent(x) 295 #endif 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 int get_hoplim(struct msghdr *); 308 double deltaT(struct timeval *, struct timeval *); 309 const char *pr_type(int); 310 int packet_ok(struct msghdr *, int, int, u_char *, u_char *); 311 void print(struct msghdr *, int); 312 const char *inetname(struct sockaddr *); 313 u_int32_t sctp_crc32c(void *, u_int32_t); 314 u_int16_t in_cksum(u_int16_t *addr, int); 315 u_int16_t tcp_chksum(struct sockaddr_in6 *, struct sockaddr_in6 *, 316 void *, u_int32_t); 317 void usage(void); 318 319 static int rcvsock; /* receive (icmp) socket file descriptor */ 320 static int sndsock; /* send (raw/udp) socket file descriptor */ 321 322 static struct msghdr rcvmhdr; 323 static struct iovec rcviov[2]; 324 static int rcvhlim; 325 static struct in6_pktinfo *rcvpktinfo; 326 327 static struct sockaddr_in6 Src, Dst, Rcv; 328 static u_long datalen = 20; /* How much data */ 329 #define ICMP6ECHOLEN 8 330 /* XXX: 2064 = 127(max hops in type 0 rthdr) * sizeof(ip6_hdr) + 16(margin) */ 331 static char rtbuf[2064]; 332 static struct ip6_rthdr *rth; 333 static struct cmsghdr *cmsg; 334 335 static char *source = NULL; 336 static char *hostname; 337 338 static u_long nprobes = 3; 339 static u_long first_hop = 1; 340 static u_long max_hops = 30; 341 static u_int16_t srcport; 342 static u_int16_t port = 32768+666; /* start udp dest port # for probe packets */ 343 static u_int16_t ident; 344 static int options; /* socket options */ 345 static int verbose; 346 static int waittime = 5; /* time to wait for response (in seconds) */ 347 static int nflag; /* print addresses numerically */ 348 static int useproto = IPPROTO_UDP; /* protocol to use to send packet */ 349 static int lflag; /* print both numerical address & hostname */ 350 static int as_path; /* print as numbers for each hop */ 351 static char *as_server = NULL; 352 static void *asn; 353 354 int 355 main(int argc, char *argv[]) 356 { 357 int mib[4] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_DEFHLIM }; 358 char hbuf[NI_MAXHOST], src0[NI_MAXHOST], *ep; 359 int ch, i, on = 1, seq, rcvcmsglen, error; 360 struct addrinfo hints, *res; 361 static u_char *rcvcmsgbuf; 362 u_long probe, hops, lport; 363 struct hostent *hp; 364 size_t size, minlen; 365 uid_t uid; 366 u_char type, code; 367 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) 368 char ipsec_inpolicy[] = "in bypass"; 369 char ipsec_outpolicy[] = "out bypass"; 370 #endif 371 372 /* 373 * Receive ICMP 374 */ 375 if ((rcvsock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) { 376 perror("socket(ICMPv6)"); 377 exit(5); 378 } 379 380 size = sizeof(i); 381 (void) sysctl(mib, sizeof(mib)/sizeof(mib[0]), &i, &size, NULL, 0); 382 max_hops = i; 383 384 /* specify to tell receiving interface */ 385 #ifdef IPV6_RECVPKTINFO 386 if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, 387 sizeof(on)) < 0) 388 err(1, "setsockopt(IPV6_RECVPKTINFO)"); 389 #else /* old adv. API */ 390 if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_PKTINFO, &on, 391 sizeof(on)) < 0) 392 err(1, "setsockopt(IPV6_PKTINFO)"); 393 #endif 394 395 /* specify to tell value of hoplimit field of received IP6 hdr */ 396 #ifdef IPV6_RECVHOPLIMIT 397 if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, 398 sizeof(on)) < 0) 399 err(1, "setsockopt(IPV6_RECVHOPLIMIT)"); 400 #else /* old adv. API */ 401 if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_HOPLIMIT, &on, 402 sizeof(on)) < 0) 403 err(1, "setsockopt(IPV6_HOPLIMIT)"); 404 #endif 405 406 seq = 0; 407 ident = htons(getpid() & 0xffff); /* same as ping6 */ 408 409 while ((ch = getopt(argc, argv, "aA:df:g:Ilm:nNp:q:rs:STUvw:")) != -1) 410 switch (ch) { 411 case 'a': 412 as_path = 1; 413 break; 414 case 'A': 415 as_path = 1; 416 as_server = optarg; 417 break; 418 case 'd': 419 options |= SO_DEBUG; 420 break; 421 case 'f': 422 ep = NULL; 423 errno = 0; 424 first_hop = strtoul(optarg, &ep, 0); 425 if (errno || !*optarg || *ep || first_hop > 255) { 426 fprintf(stderr, 427 "traceroute6: invalid min hoplimit.\n"); 428 exit(1); 429 } 430 break; 431 case 'g': 432 hp = getipnodebyname(optarg, AF_INET6, 0, &h_errno); 433 if (hp == NULL) { 434 fprintf(stderr, 435 "traceroute6: unknown host %s\n", optarg); 436 exit(1); 437 } 438 if (rth == NULL) { 439 /* 440 * XXX: We can't detect the number of 441 * intermediate nodes yet. 442 */ 443 if ((rth = inet6_rth_init((void *)rtbuf, 444 sizeof(rtbuf), IPV6_RTHDR_TYPE_0, 445 0)) == NULL) { 446 fprintf(stderr, 447 "inet6_rth_init failed.\n"); 448 exit(1); 449 } 450 } 451 if (inet6_rth_add((void *)rth, 452 (struct in6_addr *)hp->h_addr)) { 453 fprintf(stderr, 454 "inet6_rth_add failed for %s\n", 455 optarg); 456 exit(1); 457 } 458 freehostent(hp); 459 break; 460 case 'I': 461 useproto = IPPROTO_ICMPV6; 462 break; 463 case 'l': 464 lflag++; 465 break; 466 case 'm': 467 ep = NULL; 468 errno = 0; 469 max_hops = strtoul(optarg, &ep, 0); 470 if (errno || !*optarg || *ep || max_hops > 255) { 471 fprintf(stderr, 472 "traceroute6: invalid max hoplimit.\n"); 473 exit(1); 474 } 475 break; 476 case 'n': 477 nflag++; 478 break; 479 case 'N': 480 useproto = IPPROTO_NONE; 481 break; 482 case 'p': 483 ep = NULL; 484 errno = 0; 485 lport = strtoul(optarg, &ep, 0); 486 if (errno || !*optarg || *ep) { 487 fprintf(stderr, "traceroute6: invalid port.\n"); 488 exit(1); 489 } 490 if (lport == 0 || lport != (lport & 0xffff)) { 491 fprintf(stderr, 492 "traceroute6: port out of range.\n"); 493 exit(1); 494 } 495 port = lport & 0xffff; 496 break; 497 case 'q': 498 ep = NULL; 499 errno = 0; 500 nprobes = strtoul(optarg, &ep, 0); 501 if (errno || !*optarg || *ep) { 502 fprintf(stderr, 503 "traceroute6: invalid nprobes.\n"); 504 exit(1); 505 } 506 if (nprobes < 1) { 507 fprintf(stderr, 508 "traceroute6: nprobes must be >0.\n"); 509 exit(1); 510 } 511 break; 512 case 'r': 513 options |= SO_DONTROUTE; 514 break; 515 case 's': 516 /* 517 * set the ip source address of the outbound 518 * probe (e.g., on a multi-homed host). 519 */ 520 source = optarg; 521 break; 522 case 'S': 523 useproto = IPPROTO_SCTP; 524 break; 525 case 'T': 526 useproto = IPPROTO_TCP; 527 break; 528 case 'U': 529 useproto = IPPROTO_UDP; 530 break; 531 case 'v': 532 verbose++; 533 break; 534 case 'w': 535 ep = NULL; 536 errno = 0; 537 waittime = strtoul(optarg, &ep, 0); 538 if (errno || !*optarg || *ep) { 539 fprintf(stderr, 540 "traceroute6: invalid wait time.\n"); 541 exit(1); 542 } 543 if (waittime < 1) { 544 fprintf(stderr, 545 "traceroute6: wait must be >= 1 sec.\n"); 546 exit(1); 547 } 548 break; 549 default: 550 usage(); 551 } 552 argc -= optind; 553 argv += optind; 554 555 /* 556 * Open socket to send probe packets. 557 */ 558 switch (useproto) { 559 case IPPROTO_ICMPV6: 560 sndsock = rcvsock; 561 break; 562 case IPPROTO_UDP: 563 if ((sndsock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 564 perror("socket(SOCK_DGRAM)"); 565 exit(5); 566 } 567 break; 568 case IPPROTO_NONE: 569 case IPPROTO_SCTP: 570 case IPPROTO_TCP: 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 595 if (argc < 1 || argc > 2) 596 usage(); 597 598 #if 1 599 setvbuf(stdout, NULL, _IOLBF, BUFSIZ); 600 #else 601 setlinebuf(stdout); 602 #endif 603 604 memset(&hints, 0, sizeof(hints)); 605 hints.ai_family = PF_INET6; 606 hints.ai_socktype = SOCK_RAW; 607 hints.ai_protocol = IPPROTO_ICMPV6; 608 hints.ai_flags = AI_CANONNAME; 609 error = getaddrinfo(*argv, NULL, &hints, &res); 610 if (error) { 611 fprintf(stderr, 612 "traceroute6: %s\n", gai_strerror(error)); 613 exit(1); 614 } 615 if (res->ai_addrlen != sizeof(Dst)) { 616 fprintf(stderr, 617 "traceroute6: size of sockaddr mismatch\n"); 618 exit(1); 619 } 620 memcpy(&Dst, res->ai_addr, res->ai_addrlen); 621 hostname = res->ai_canonname ? strdup(res->ai_canonname) : *argv; 622 if (!hostname) { 623 fprintf(stderr, "traceroute6: not enough core\n"); 624 exit(1); 625 } 626 if (res->ai_next) { 627 if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, 628 sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) 629 strlcpy(hbuf, "?", sizeof(hbuf)); 630 fprintf(stderr, "traceroute6: Warning: %s has multiple " 631 "addresses; using %s\n", hostname, hbuf); 632 } 633 freeaddrinfo(res); 634 if (*++argv) { 635 ep = NULL; 636 errno = 0; 637 datalen = strtoul(*argv, &ep, 0); 638 if (errno || *ep) { 639 fprintf(stderr, 640 "traceroute6: invalid packet length.\n"); 641 exit(1); 642 } 643 } 644 switch (useproto) { 645 case IPPROTO_ICMPV6: 646 minlen = ICMP6ECHOLEN; 647 break; 648 case IPPROTO_UDP: 649 minlen = sizeof(struct udphdr); 650 break; 651 case IPPROTO_NONE: 652 minlen = 0; 653 datalen = 0; 654 break; 655 case IPPROTO_SCTP: 656 minlen = sizeof(struct sctphdr); 657 break; 658 case IPPROTO_TCP: 659 minlen = sizeof(struct tcphdr); 660 break; 661 default: 662 fprintf(stderr, "traceroute6: unknown probe protocol %d.\n", 663 useproto); 664 exit(1); 665 } 666 if (datalen < minlen) 667 datalen = minlen; 668 else if (datalen >= MAXPACKET) { 669 fprintf(stderr, 670 "traceroute6: packet size must be %zu <= s < %d.\n", 671 minlen, MAXPACKET); 672 exit(1); 673 } 674 if (useproto == IPPROTO_UDP) 675 datalen -= sizeof(struct udphdr); 676 if ((useproto == IPPROTO_SCTP) && (datalen & 3)) { 677 fprintf(stderr, 678 "traceroute6: packet size must be a multiple of 4.\n"); 679 exit(1); 680 } 681 outpacket = malloc(datalen); 682 if (!outpacket) { 683 perror("malloc"); 684 exit(1); 685 } 686 (void) bzero((char *)outpacket, datalen); 687 688 /* initialize msghdr for receiving packets */ 689 rcviov[0].iov_base = (caddr_t)packet; 690 rcviov[0].iov_len = sizeof(packet); 691 rcvmhdr.msg_name = (caddr_t)&Rcv; 692 rcvmhdr.msg_namelen = sizeof(Rcv); 693 rcvmhdr.msg_iov = rcviov; 694 rcvmhdr.msg_iovlen = 1; 695 rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + 696 CMSG_SPACE(sizeof(int)); 697 if ((rcvcmsgbuf = malloc(rcvcmsglen)) == NULL) { 698 fprintf(stderr, "traceroute6: malloc failed\n"); 699 exit(1); 700 } 701 rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf; 702 rcvmhdr.msg_controllen = rcvcmsglen; 703 704 if (options & SO_DEBUG) 705 (void) setsockopt(rcvsock, SOL_SOCKET, SO_DEBUG, 706 (char *)&on, sizeof(on)); 707 if (options & SO_DONTROUTE) 708 (void) setsockopt(rcvsock, SOL_SOCKET, SO_DONTROUTE, 709 (char *)&on, sizeof(on)); 710 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) 711 /* 712 * do not raise error even if setsockopt fails, kernel may have ipsec 713 * turned off. 714 */ 715 if (setpolicy(rcvsock, ipsec_inpolicy) < 0) 716 errx(1, "%s", ipsec_strerror()); 717 if (setpolicy(rcvsock, ipsec_outpolicy) < 0) 718 errx(1, "%s", ipsec_strerror()); 719 #else 720 { 721 int level = IPSEC_LEVEL_NONE; 722 723 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, &level, 724 sizeof(level)); 725 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_ESP_NETWORK_LEVEL, &level, 726 sizeof(level)); 727 #ifdef IP_AUTH_TRANS_LEVEL 728 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, &level, 729 sizeof(level)); 730 #else 731 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_LEVEL, &level, 732 sizeof(level)); 733 #endif 734 #ifdef IP_AUTH_NETWORK_LEVEL 735 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_NETWORK_LEVEL, &level, 736 sizeof(level)); 737 #endif 738 } 739 #endif /* !(IPSEC && IPSEC_POLICY_IPSEC) */ 740 741 #ifdef SO_SNDBUF 742 i = datalen; 743 if (i == 0) 744 i = 1; 745 if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&i, 746 sizeof(i)) < 0) { 747 perror("setsockopt(SO_SNDBUF)"); 748 exit(6); 749 } 750 #endif /* SO_SNDBUF */ 751 if (options & SO_DEBUG) 752 (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, 753 (char *)&on, sizeof(on)); 754 if (options & SO_DONTROUTE) 755 (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, 756 (char *)&on, sizeof(on)); 757 if (rth) {/* XXX: there is no library to finalize the header... */ 758 rth->ip6r_len = rth->ip6r_segleft * 2; 759 if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_RTHDR, 760 (void *)rth, (rth->ip6r_len + 1) << 3)) { 761 fprintf(stderr, "setsockopt(IPV6_RTHDR): %s\n", 762 strerror(errno)); 763 exit(1); 764 } 765 } 766 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) 767 /* 768 * do not raise error even if setsockopt fails, kernel may have ipsec 769 * turned off. 770 */ 771 if (setpolicy(sndsock, ipsec_inpolicy) < 0) 772 errx(1, "%s", ipsec_strerror()); 773 if (setpolicy(sndsock, ipsec_outpolicy) < 0) 774 errx(1, "%s", ipsec_strerror()); 775 #else 776 { 777 int level = IPSEC_LEVEL_BYPASS; 778 779 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, &level, 780 sizeof(level)); 781 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_ESP_NETWORK_LEVEL, &level, 782 sizeof(level)); 783 #ifdef IP_AUTH_TRANS_LEVEL 784 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, &level, 785 sizeof(level)); 786 #else 787 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_LEVEL, &level, 788 sizeof(level)); 789 #endif 790 #ifdef IP_AUTH_NETWORK_LEVEL 791 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_NETWORK_LEVEL, &level, 792 sizeof(level)); 793 #endif 794 } 795 #endif /* !(IPSEC && IPSEC_POLICY_IPSEC) */ 796 797 /* 798 * Source selection 799 */ 800 bzero(&Src, sizeof(Src)); 801 if (source) { 802 memset(&hints, 0, sizeof(hints)); 803 hints.ai_family = AF_INET6; 804 hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 805 hints.ai_flags = AI_NUMERICHOST; 806 error = getaddrinfo(source, "0", &hints, &res); 807 if (error) { 808 printf("traceroute6: %s: %s\n", source, 809 gai_strerror(error)); 810 exit(1); 811 } 812 if (res->ai_addrlen > sizeof(Src)) { 813 printf("traceroute6: %s: %s\n", source, 814 gai_strerror(error)); 815 exit(1); 816 } 817 memcpy(&Src, res->ai_addr, res->ai_addrlen); 818 freeaddrinfo(res); 819 } else { 820 struct sockaddr_in6 Nxt; 821 int dummy; 822 socklen_t len; 823 824 Nxt = Dst; 825 Nxt.sin6_port = htons(DUMMY_PORT); 826 if (cmsg != NULL) 827 bcopy(inet6_rthdr_getaddr(cmsg, 1), &Nxt.sin6_addr, 828 sizeof(Nxt.sin6_addr)); 829 if ((dummy = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 830 perror("socket"); 831 exit(1); 832 } 833 if (connect(dummy, (struct sockaddr *)&Nxt, Nxt.sin6_len) < 0) { 834 perror("connect"); 835 exit(1); 836 } 837 len = sizeof(Src); 838 if (getsockname(dummy, (struct sockaddr *)&Src, &len) < 0) { 839 perror("getsockname"); 840 exit(1); 841 } 842 if (getnameinfo((struct sockaddr *)&Src, Src.sin6_len, 843 src0, sizeof(src0), NULL, 0, NI_NUMERICHOST)) { 844 fprintf(stderr, "getnameinfo failed for source\n"); 845 exit(1); 846 } 847 source = src0; 848 close(dummy); 849 } 850 851 Src.sin6_port = htons(0); 852 if (bind(sndsock, (struct sockaddr *)&Src, Src.sin6_len) < 0) { 853 perror("bind"); 854 exit(1); 855 } 856 857 { 858 socklen_t len; 859 860 len = sizeof(Src); 861 if (getsockname(sndsock, (struct sockaddr *)&Src, &len) < 0) { 862 perror("getsockname"); 863 exit(1); 864 } 865 srcport = ntohs(Src.sin6_port); 866 } 867 868 if (as_path) { 869 asn = as_setup(as_server); 870 if (asn == NULL) { 871 fprintf(stderr, 872 "traceroute6: as_setup failed, AS# lookups" 873 " disabled\n"); 874 (void)fflush(stderr); 875 as_path = 0; 876 } 877 } 878 879 /* 880 * Message to users 881 */ 882 if (getnameinfo((struct sockaddr *)&Dst, Dst.sin6_len, hbuf, 883 sizeof(hbuf), NULL, 0, NI_NUMERICHOST)) 884 strlcpy(hbuf, "(invalid)", sizeof(hbuf)); 885 fprintf(stderr, "traceroute6"); 886 fprintf(stderr, " to %s (%s)", hostname, hbuf); 887 if (source) 888 fprintf(stderr, " from %s", source); 889 fprintf(stderr, ", %lu hops max, %lu byte packets\n", 890 max_hops, 891 datalen + ((useproto == IPPROTO_UDP) ? sizeof(struct udphdr) : 0)); 892 (void) fflush(stderr); 893 894 if (first_hop > 1) 895 printf("Skipping %lu intermediate hops\n", first_hop - 1); 896 897 /* 898 * Main loop 899 */ 900 for (hops = first_hop; hops <= max_hops; ++hops) { 901 struct in6_addr lastaddr; 902 int got_there = 0; 903 unsigned unreachable = 0; 904 905 printf("%2lu ", hops); 906 bzero(&lastaddr, sizeof(lastaddr)); 907 for (probe = 0; probe < nprobes; ++probe) { 908 int cc; 909 struct timeval t1, t2; 910 911 (void) gettimeofday(&t1, NULL); 912 send_probe(++seq, hops); 913 while ((cc = wait_for_reply(rcvsock, &rcvmhdr))) { 914 (void) gettimeofday(&t2, NULL); 915 if (packet_ok(&rcvmhdr, cc, seq, &type, &code)) { 916 if (!IN6_ARE_ADDR_EQUAL(&Rcv.sin6_addr, 917 &lastaddr)) { 918 if (probe > 0) 919 fputs("\n ", stdout); 920 print(&rcvmhdr, cc); 921 lastaddr = Rcv.sin6_addr; 922 } 923 printf(" %.3f ms", deltaT(&t1, &t2)); 924 if (type == ICMP6_DST_UNREACH) { 925 switch (code) { 926 case ICMP6_DST_UNREACH_NOROUTE: 927 ++unreachable; 928 printf(" !N"); 929 break; 930 case ICMP6_DST_UNREACH_ADMIN: 931 ++unreachable; 932 printf(" !P"); 933 break; 934 case ICMP6_DST_UNREACH_NOTNEIGHBOR: 935 ++unreachable; 936 printf(" !S"); 937 break; 938 case ICMP6_DST_UNREACH_ADDR: 939 ++unreachable; 940 printf(" !A"); 941 break; 942 case ICMP6_DST_UNREACH_NOPORT: 943 if (rcvhlim >= 0 && 944 rcvhlim <= 1) 945 printf(" !"); 946 ++got_there; 947 break; 948 } 949 } else if (type == ICMP6_PARAM_PROB && 950 code == ICMP6_PARAMPROB_NEXTHEADER) { 951 printf(" !H"); 952 ++got_there; 953 } else if (type == ICMP6_ECHO_REPLY) { 954 if (rcvhlim >= 0 && 955 rcvhlim <= 1) 956 printf(" !"); 957 ++got_there; 958 } 959 break; 960 } else if (deltaT(&t1, &t2) > waittime * 1000) { 961 cc = 0; 962 break; 963 } 964 } 965 if (cc == 0) 966 printf(" *"); 967 (void) fflush(stdout); 968 } 969 putchar('\n'); 970 if (got_there || 971 (unreachable > 0 && unreachable >= ((nprobes + 1) / 2))) { 972 exit(0); 973 } 974 } 975 if (as_path) 976 as_shutdown(asn); 977 978 exit(0); 979 } 980 981 int 982 wait_for_reply(int sock, struct msghdr *mhdr) 983 { 984 #ifdef HAVE_POLL 985 struct pollfd pfd[1]; 986 int cc = 0; 987 988 pfd[0].fd = sock; 989 pfd[0].events = POLLIN; 990 pfd[0].revents = 0; 991 992 if (poll(pfd, 1, waittime * 1000) > 0) 993 cc = recvmsg(rcvsock, mhdr, 0); 994 995 return (cc); 996 #else 997 fd_set *fdsp; 998 struct timeval wait; 999 int cc = 0, fdsn; 1000 1001 fdsn = howmany(sock + 1, NFDBITS) * sizeof(fd_mask); 1002 if ((fdsp = (fd_set *)malloc(fdsn)) == NULL) 1003 err(1, "malloc"); 1004 memset(fdsp, 0, fdsn); 1005 FD_SET(sock, fdsp); 1006 wait.tv_sec = waittime; wait.tv_usec = 0; 1007 1008 if (select(sock+1, fdsp, (fd_set *)0, (fd_set *)0, &wait) > 0) 1009 cc = recvmsg(rcvsock, mhdr, 0); 1010 1011 free(fdsp); 1012 return (cc); 1013 #endif 1014 } 1015 1016 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) 1017 int 1018 setpolicy(int so, char *policy) 1019 { 1020 char *buf; 1021 1022 buf = ipsec_set_policy(policy, strlen(policy)); 1023 if (buf == NULL) { 1024 warnx("%s", ipsec_strerror()); 1025 return -1; 1026 } 1027 (void)setsockopt(so, IPPROTO_IPV6, IPV6_IPSEC_POLICY, 1028 buf, ipsec_get_policylen(buf)); 1029 1030 free(buf); 1031 1032 return 0; 1033 } 1034 #endif 1035 1036 void 1037 send_probe(int seq, u_long hops) 1038 { 1039 struct icmp6_hdr *icp; 1040 struct sctphdr *sctp; 1041 struct sctp_chunkhdr *chk; 1042 struct sctp_init_chunk *init; 1043 struct sctp_paramhdr *param; 1044 struct tcphdr *tcp; 1045 int i; 1046 1047 i = hops; 1048 if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 1049 (char *)&i, sizeof(i)) < 0) { 1050 perror("setsockopt IPV6_UNICAST_HOPS"); 1051 } 1052 1053 Dst.sin6_port = htons(port + seq); 1054 1055 switch (useproto) { 1056 case IPPROTO_ICMPV6: 1057 icp = (struct icmp6_hdr *)outpacket; 1058 1059 icp->icmp6_type = ICMP6_ECHO_REQUEST; 1060 icp->icmp6_code = 0; 1061 icp->icmp6_cksum = 0; 1062 icp->icmp6_id = ident; 1063 icp->icmp6_seq = htons(seq); 1064 break; 1065 case IPPROTO_UDP: 1066 break; 1067 case IPPROTO_NONE: 1068 /* No space for anything. No harm as seq/tv32 are decorative. */ 1069 break; 1070 case IPPROTO_SCTP: 1071 sctp = (struct sctphdr *)outpacket; 1072 1073 sctp->src_port = htons(ident); 1074 sctp->dest_port = htons(port + seq); 1075 if (datalen >= (u_long)(sizeof(struct sctphdr) + 1076 sizeof(struct sctp_init_chunk))) { 1077 sctp->v_tag = 0; 1078 } else { 1079 sctp->v_tag = (sctp->src_port << 16) | sctp->dest_port; 1080 } 1081 sctp->checksum = htonl(0); 1082 if (datalen >= (u_long)(sizeof(struct sctphdr) + 1083 sizeof(struct sctp_init_chunk))) { 1084 /* 1085 * Send a packet containing an INIT chunk. This works 1086 * better in case of firewalls on the path, but 1087 * results in a probe packet containing at least 1088 * 32 bytes of payload. For shorter payloads, use 1089 * SHUTDOWN-ACK chunks. 1090 */ 1091 init = (struct sctp_init_chunk *)(sctp + 1); 1092 init->ch.chunk_type = SCTP_INITIATION; 1093 init->ch.chunk_flags = 0; 1094 init->ch.chunk_length = htons((u_int16_t)(datalen - 1095 sizeof(struct sctphdr))); 1096 init->init.initiate_tag = (sctp->src_port << 16) | 1097 sctp->dest_port; 1098 init->init.a_rwnd = htonl(1500); 1099 init->init.num_outbound_streams = htons(1); 1100 init->init.num_inbound_streams = htons(1); 1101 init->init.initial_tsn = htonl(0); 1102 if (datalen >= (u_long)(sizeof(struct sctphdr) + 1103 sizeof(struct sctp_init_chunk) + 1104 sizeof(struct sctp_paramhdr))) { 1105 param = (struct sctp_paramhdr *)(init + 1); 1106 param->param_type = htons(SCTP_PAD); 1107 param->param_length = 1108 htons((u_int16_t)(datalen - 1109 sizeof(struct sctphdr) - 1110 sizeof(struct sctp_init_chunk))); 1111 } 1112 } else { 1113 /* 1114 * Send a packet containing a SHUTDOWN-ACK chunk, 1115 * possibly followed by a PAD chunk. 1116 */ 1117 if (datalen >= (u_long)(sizeof(struct sctphdr) + 1118 sizeof(struct sctp_chunkhdr))) { 1119 chk = (struct sctp_chunkhdr *)(sctp + 1); 1120 chk->chunk_type = SCTP_SHUTDOWN_ACK; 1121 chk->chunk_flags = 0; 1122 chk->chunk_length = htons(4); 1123 } 1124 if (datalen >= (u_long)(sizeof(struct sctphdr) + 1125 2 * sizeof(struct sctp_chunkhdr))) { 1126 chk = chk + 1; 1127 chk->chunk_type = SCTP_PAD_CHUNK; 1128 chk->chunk_flags = 0; 1129 chk->chunk_length = htons((u_int16_t)(datalen - 1130 sizeof(struct sctphdr) - 1131 sizeof(struct sctp_chunkhdr))); 1132 } 1133 } 1134 sctp->checksum = sctp_crc32c(outpacket, datalen); 1135 break; 1136 case IPPROTO_TCP: 1137 tcp = (struct tcphdr *)outpacket; 1138 1139 tcp->th_sport = htons(ident); 1140 tcp->th_dport = htons(port + seq); 1141 tcp->th_seq = (tcp->th_sport << 16) | tcp->th_dport; 1142 tcp->th_ack = 0; 1143 tcp->th_off = 5; 1144 tcp->th_flags = TH_SYN; 1145 tcp->th_sum = 0; 1146 tcp->th_sum = tcp_chksum(&Src, &Dst, outpacket, datalen); 1147 break; 1148 default: 1149 fprintf(stderr, "Unknown probe protocol %d.\n", useproto); 1150 exit(1); 1151 } 1152 1153 i = sendto(sndsock, (char *)outpacket, datalen, 0, 1154 (struct sockaddr *)&Dst, Dst.sin6_len); 1155 if (i < 0 || (u_long)i != datalen) { 1156 if (i < 0) 1157 perror("sendto"); 1158 printf("traceroute6: wrote %s %lu chars, ret=%d\n", 1159 hostname, datalen, i); 1160 (void) fflush(stdout); 1161 } 1162 } 1163 1164 int 1165 get_hoplim(struct msghdr *mhdr) 1166 { 1167 struct cmsghdr *cm; 1168 1169 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; 1170 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { 1171 if (cm->cmsg_level == IPPROTO_IPV6 && 1172 cm->cmsg_type == IPV6_HOPLIMIT && 1173 cm->cmsg_len == CMSG_LEN(sizeof(int))) 1174 return (*(int *)CMSG_DATA(cm)); 1175 } 1176 1177 return (-1); 1178 } 1179 1180 double 1181 deltaT(struct timeval *t1p, struct timeval *t2p) 1182 { 1183 double dt; 1184 1185 dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 + 1186 (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0; 1187 return (dt); 1188 } 1189 1190 /* 1191 * Convert an ICMP "type" field to a printable string. 1192 */ 1193 const char * 1194 pr_type(int t0) 1195 { 1196 u_char t = t0 & 0xff; 1197 const char *cp; 1198 1199 switch (t) { 1200 case ICMP6_DST_UNREACH: 1201 cp = "Destination Unreachable"; 1202 break; 1203 case ICMP6_PACKET_TOO_BIG: 1204 cp = "Packet Too Big"; 1205 break; 1206 case ICMP6_TIME_EXCEEDED: 1207 cp = "Time Exceeded"; 1208 break; 1209 case ICMP6_PARAM_PROB: 1210 cp = "Parameter Problem"; 1211 break; 1212 case ICMP6_ECHO_REQUEST: 1213 cp = "Echo Request"; 1214 break; 1215 case ICMP6_ECHO_REPLY: 1216 cp = "Echo Reply"; 1217 break; 1218 case ICMP6_MEMBERSHIP_QUERY: 1219 cp = "Group Membership Query"; 1220 break; 1221 case ICMP6_MEMBERSHIP_REPORT: 1222 cp = "Group Membership Report"; 1223 break; 1224 case ICMP6_MEMBERSHIP_REDUCTION: 1225 cp = "Group Membership Reduction"; 1226 break; 1227 case ND_ROUTER_SOLICIT: 1228 cp = "Router Solicitation"; 1229 break; 1230 case ND_ROUTER_ADVERT: 1231 cp = "Router Advertisement"; 1232 break; 1233 case ND_NEIGHBOR_SOLICIT: 1234 cp = "Neighbor Solicitation"; 1235 break; 1236 case ND_NEIGHBOR_ADVERT: 1237 cp = "Neighbor Advertisement"; 1238 break; 1239 case ND_REDIRECT: 1240 cp = "Redirect"; 1241 break; 1242 default: 1243 cp = "Unknown"; 1244 break; 1245 } 1246 return cp; 1247 } 1248 1249 int 1250 packet_ok(struct msghdr *mhdr, int cc, int seq, u_char *type, u_char *code) 1251 { 1252 struct icmp6_hdr *icp; 1253 struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name; 1254 char *buf = (char *)mhdr->msg_iov[0].iov_base; 1255 struct cmsghdr *cm; 1256 int *hlimp; 1257 char hbuf[NI_MAXHOST]; 1258 1259 #ifdef OLDRAWSOCKET 1260 int hlen; 1261 struct ip6_hdr *ip; 1262 #endif 1263 1264 #ifdef OLDRAWSOCKET 1265 ip = (struct ip6_hdr *) buf; 1266 hlen = sizeof(struct ip6_hdr); 1267 if (cc < hlen + sizeof(struct icmp6_hdr)) { 1268 if (verbose) { 1269 if (getnameinfo((struct sockaddr *)from, from->sin6_len, 1270 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) 1271 strlcpy(hbuf, "invalid", sizeof(hbuf)); 1272 printf("packet too short (%d bytes) from %s\n", cc, 1273 hbuf); 1274 } 1275 return (0); 1276 } 1277 cc -= hlen; 1278 icp = (struct icmp6_hdr *)(buf + hlen); 1279 #else 1280 if (cc < (int)sizeof(struct icmp6_hdr)) { 1281 if (verbose) { 1282 if (getnameinfo((struct sockaddr *)from, from->sin6_len, 1283 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) 1284 strlcpy(hbuf, "invalid", sizeof(hbuf)); 1285 printf("data too short (%d bytes) from %s\n", cc, hbuf); 1286 } 1287 return (0); 1288 } 1289 icp = (struct icmp6_hdr *)buf; 1290 #endif 1291 /* get optional information via advanced API */ 1292 rcvpktinfo = NULL; 1293 hlimp = NULL; 1294 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; 1295 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { 1296 if (cm->cmsg_level == IPPROTO_IPV6 && 1297 cm->cmsg_type == IPV6_PKTINFO && 1298 cm->cmsg_len == 1299 CMSG_LEN(sizeof(struct in6_pktinfo))) 1300 rcvpktinfo = (struct in6_pktinfo *)(CMSG_DATA(cm)); 1301 1302 if (cm->cmsg_level == IPPROTO_IPV6 && 1303 cm->cmsg_type == IPV6_HOPLIMIT && 1304 cm->cmsg_len == CMSG_LEN(sizeof(int))) 1305 hlimp = (int *)CMSG_DATA(cm); 1306 } 1307 if (rcvpktinfo == NULL || hlimp == NULL) { 1308 warnx("failed to get received hop limit or packet info"); 1309 #if 0 1310 return (0); 1311 #else 1312 rcvhlim = 0; /*XXX*/ 1313 #endif 1314 } 1315 else 1316 rcvhlim = *hlimp; 1317 1318 *type = icp->icmp6_type; 1319 *code = icp->icmp6_code; 1320 if ((*type == ICMP6_TIME_EXCEEDED && 1321 *code == ICMP6_TIME_EXCEED_TRANSIT) || 1322 (*type == ICMP6_DST_UNREACH) || 1323 (*type == ICMP6_PARAM_PROB && 1324 *code == ICMP6_PARAMPROB_NEXTHEADER)) { 1325 struct ip6_hdr *hip; 1326 struct icmp6_hdr *icmp; 1327 struct sctp_init_chunk *init; 1328 struct sctphdr *sctp; 1329 struct tcphdr *tcp; 1330 struct udphdr *udp; 1331 void *up; 1332 1333 hip = (struct ip6_hdr *)(icp + 1); 1334 if ((up = get_uphdr(hip, (u_char *)(buf + cc))) == NULL) { 1335 if (verbose) 1336 warnx("failed to get upper layer header"); 1337 return (0); 1338 } 1339 switch (useproto) { 1340 case IPPROTO_ICMPV6: 1341 icmp = (struct icmp6_hdr *)up; 1342 if (icmp->icmp6_id == ident && 1343 icmp->icmp6_seq == htons(seq)) 1344 return (1); 1345 break; 1346 case IPPROTO_UDP: 1347 udp = (struct udphdr *)up; 1348 if (udp->uh_sport == htons(srcport) && 1349 udp->uh_dport == htons(port + seq)) 1350 return (1); 1351 break; 1352 case IPPROTO_SCTP: 1353 sctp = (struct sctphdr *)up; 1354 if (sctp->src_port != htons(ident) || 1355 sctp->dest_port != htons(port + seq)) { 1356 break; 1357 } 1358 if (datalen >= (u_long)(sizeof(struct sctphdr) + 1359 sizeof(struct sctp_init_chunk))) { 1360 if (sctp->v_tag != 0) { 1361 break; 1362 } 1363 init = (struct sctp_init_chunk *)(sctp + 1); 1364 /* Check the initiate tag, if available. */ 1365 if ((char *)&init->init.a_rwnd > buf + cc) { 1366 return (1); 1367 } 1368 if (init->init.initiate_tag == (u_int32_t) 1369 ((sctp->src_port << 16) | sctp->dest_port)) { 1370 return (1); 1371 } 1372 } else { 1373 if (sctp->v_tag == 1374 (u_int32_t)((sctp->src_port << 16) | 1375 sctp->dest_port)) { 1376 return (1); 1377 } 1378 } 1379 break; 1380 case IPPROTO_TCP: 1381 tcp = (struct tcphdr *)up; 1382 if (tcp->th_sport == htons(ident) && 1383 tcp->th_dport == htons(port + seq) && 1384 tcp->th_seq == 1385 (tcp_seq)((tcp->th_sport << 16) | tcp->th_dport)) 1386 return (1); 1387 break; 1388 case IPPROTO_NONE: 1389 return (1); 1390 default: 1391 fprintf(stderr, "Unknown probe proto %d.\n", useproto); 1392 break; 1393 } 1394 } else if (useproto == IPPROTO_ICMPV6 && *type == ICMP6_ECHO_REPLY) { 1395 if (icp->icmp6_id == ident && 1396 icp->icmp6_seq == htons(seq)) 1397 return (1); 1398 } 1399 if (verbose) { 1400 char sbuf[NI_MAXHOST+1], dbuf[INET6_ADDRSTRLEN]; 1401 u_int8_t *p; 1402 int i; 1403 1404 if (getnameinfo((struct sockaddr *)from, from->sin6_len, 1405 sbuf, sizeof(sbuf), NULL, 0, NI_NUMERICHOST) != 0) 1406 strlcpy(sbuf, "invalid", sizeof(sbuf)); 1407 printf("\n%d bytes from %s to %s", cc, sbuf, 1408 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr, 1409 dbuf, sizeof(dbuf)) : "?"); 1410 printf(": icmp type %d (%s) code %d\n", *type, pr_type(*type), 1411 *code); 1412 p = (u_int8_t *)(icp + 1); 1413 #define WIDTH 16 1414 for (i = 0; i < cc; i++) { 1415 if (i % WIDTH == 0) 1416 printf("%04x:", i); 1417 if (i % 4 == 0) 1418 printf(" "); 1419 printf("%02x", p[i]); 1420 if (i % WIDTH == WIDTH - 1) 1421 printf("\n"); 1422 } 1423 if (cc % WIDTH != 0) 1424 printf("\n"); 1425 } 1426 return (0); 1427 } 1428 1429 /* 1430 * Increment pointer until find the UDP or ICMP header. 1431 */ 1432 void * 1433 get_uphdr(struct ip6_hdr *ip6, u_char *lim) 1434 { 1435 u_char *cp = (u_char *)ip6, nh; 1436 int hlen; 1437 static u_char none_hdr[1]; /* Fake pointer for IPPROTO_NONE. */ 1438 1439 if (cp + sizeof(*ip6) > lim) 1440 return (NULL); 1441 1442 nh = ip6->ip6_nxt; 1443 cp += sizeof(struct ip6_hdr); 1444 1445 while (lim - cp >= (nh == IPPROTO_NONE ? 0 : 8)) { 1446 switch (nh) { 1447 case IPPROTO_ESP: 1448 return (NULL); 1449 case IPPROTO_ICMPV6: 1450 return (useproto == nh ? cp : NULL); 1451 case IPPROTO_SCTP: 1452 case IPPROTO_TCP: 1453 case IPPROTO_UDP: 1454 return (useproto == nh ? cp : NULL); 1455 case IPPROTO_NONE: 1456 return (useproto == nh ? none_hdr : NULL); 1457 case IPPROTO_FRAGMENT: 1458 hlen = sizeof(struct ip6_frag); 1459 nh = ((struct ip6_frag *)cp)->ip6f_nxt; 1460 break; 1461 case IPPROTO_AH: 1462 hlen = (((struct ip6_ext *)cp)->ip6e_len + 2) << 2; 1463 nh = ((struct ip6_ext *)cp)->ip6e_nxt; 1464 break; 1465 default: 1466 hlen = (((struct ip6_ext *)cp)->ip6e_len + 1) << 3; 1467 nh = ((struct ip6_ext *)cp)->ip6e_nxt; 1468 break; 1469 } 1470 1471 cp += hlen; 1472 } 1473 1474 return (NULL); 1475 } 1476 1477 void 1478 print(struct msghdr *mhdr, int cc) 1479 { 1480 struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name; 1481 char hbuf[NI_MAXHOST]; 1482 1483 if (getnameinfo((struct sockaddr *)from, from->sin6_len, 1484 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) 1485 strlcpy(hbuf, "invalid", sizeof(hbuf)); 1486 if (as_path) 1487 printf(" [AS%u]", as_lookup(asn, hbuf, AF_INET6)); 1488 if (nflag) 1489 printf(" %s", hbuf); 1490 else if (lflag) 1491 printf(" %s (%s)", inetname((struct sockaddr *)from), hbuf); 1492 else 1493 printf(" %s", inetname((struct sockaddr *)from)); 1494 1495 if (verbose) { 1496 #ifdef OLDRAWSOCKET 1497 printf(" %d bytes to %s", cc, 1498 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr, 1499 hbuf, sizeof(hbuf)) : "?"); 1500 #else 1501 printf(" %d bytes of data to %s", cc, 1502 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr, 1503 hbuf, sizeof(hbuf)) : "?"); 1504 #endif 1505 } 1506 } 1507 1508 /* 1509 * Construct an Internet address representation. 1510 * If the nflag has been supplied, give 1511 * numeric value, otherwise try for symbolic name. 1512 */ 1513 const char * 1514 inetname(struct sockaddr *sa) 1515 { 1516 static char line[NI_MAXHOST], domain[MAXHOSTNAMELEN + 1]; 1517 static int first = 1; 1518 char *cp; 1519 1520 if (first && !nflag) { 1521 first = 0; 1522 if (gethostname(domain, sizeof(domain)) == 0 && 1523 (cp = strchr(domain, '.'))) 1524 (void) strlcpy(domain, cp + 1, sizeof(domain)); 1525 else 1526 domain[0] = 0; 1527 } 1528 cp = NULL; 1529 if (!nflag) { 1530 if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0, 1531 NI_NAMEREQD) == 0) { 1532 if ((cp = strchr(line, '.')) && 1533 !strcmp(cp + 1, domain)) 1534 *cp = 0; 1535 cp = line; 1536 } 1537 } 1538 if (cp) 1539 return cp; 1540 1541 if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0, 1542 NI_NUMERICHOST) != 0) 1543 strlcpy(line, "invalid", sizeof(line)); 1544 return line; 1545 } 1546 1547 /* 1548 * CRC32C routine for the Stream Control Transmission Protocol 1549 */ 1550 1551 #define CRC32C(c, d) (c = (c>>8) ^ crc_c[(c^(d))&0xFF]) 1552 1553 static u_int32_t crc_c[256] = { 1554 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 1555 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, 1556 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 1557 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, 1558 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 1559 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, 1560 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 1561 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, 1562 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 1563 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, 1564 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 1565 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, 1566 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 1567 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, 1568 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 1569 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, 1570 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 1571 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, 1572 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 1573 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, 1574 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 1575 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, 1576 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 1577 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, 1578 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 1579 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, 1580 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 1581 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, 1582 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 1583 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, 1584 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 1585 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, 1586 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 1587 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, 1588 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 1589 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, 1590 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 1591 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, 1592 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 1593 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, 1594 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 1595 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, 1596 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 1597 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, 1598 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 1599 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, 1600 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 1601 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, 1602 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 1603 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, 1604 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 1605 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, 1606 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 1607 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, 1608 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 1609 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, 1610 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 1611 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, 1612 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 1613 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, 1614 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 1615 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, 1616 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 1617 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351 1618 }; 1619 1620 u_int32_t 1621 sctp_crc32c(void *pack, u_int32_t len) 1622 { 1623 u_int32_t i, crc32c; 1624 u_int8_t byte0, byte1, byte2, byte3; 1625 u_int8_t *buf = (u_int8_t *)pack; 1626 1627 crc32c = ~0; 1628 for (i = 0; i < len; i++) 1629 CRC32C(crc32c, buf[i]); 1630 crc32c = ~crc32c; 1631 byte0 = crc32c & 0xff; 1632 byte1 = (crc32c>>8) & 0xff; 1633 byte2 = (crc32c>>16) & 0xff; 1634 byte3 = (crc32c>>24) & 0xff; 1635 crc32c = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3); 1636 return htonl(crc32c); 1637 } 1638 1639 u_int16_t 1640 in_cksum(u_int16_t *addr, int len) 1641 { 1642 int nleft = len; 1643 u_int16_t *w = addr; 1644 u_int16_t answer; 1645 int sum = 0; 1646 1647 /* 1648 * Our algorithm is simple, using a 32 bit accumulator (sum), 1649 * we add sequential 16 bit words to it, and at the end, fold 1650 * back all the carry bits from the top 16 bits into the lower 1651 * 16 bits. 1652 */ 1653 while (nleft > 1) { 1654 sum += *w++; 1655 nleft -= 2; 1656 } 1657 1658 /* mop up an odd byte, if necessary */ 1659 if (nleft == 1) 1660 sum += *(u_char *)w; 1661 1662 /* 1663 * add back carry outs from top 16 bits to low 16 bits 1664 */ 1665 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 1666 sum += (sum >> 16); /* add carry */ 1667 answer = ~sum; /* truncate to 16 bits */ 1668 return (answer); 1669 } 1670 1671 u_int16_t 1672 tcp_chksum(struct sockaddr_in6 *src, struct sockaddr_in6 *dst, 1673 void *payload, u_int32_t len) 1674 { 1675 struct { 1676 struct in6_addr src; 1677 struct in6_addr dst; 1678 u_int32_t len; 1679 u_int8_t zero[3]; 1680 u_int8_t next; 1681 } pseudo_hdr; 1682 u_int16_t sum[2]; 1683 1684 pseudo_hdr.src = src->sin6_addr; 1685 pseudo_hdr.dst = dst->sin6_addr; 1686 pseudo_hdr.len = htonl(len); 1687 pseudo_hdr.zero[0] = 0; 1688 pseudo_hdr.zero[1] = 0; 1689 pseudo_hdr.zero[2] = 0; 1690 pseudo_hdr.next = IPPROTO_TCP; 1691 1692 sum[1] = in_cksum((u_int16_t *)&pseudo_hdr, sizeof(pseudo_hdr)); 1693 sum[0] = in_cksum(payload, len); 1694 1695 return (~in_cksum(sum, sizeof(sum))); 1696 } 1697 1698 void 1699 usage(void) 1700 { 1701 1702 fprintf(stderr, 1703 "usage: traceroute6 [-adIlnNrSTUv] [-A as_server] [-f firsthop] [-g gateway]\n" 1704 " [-m hoplimit] [-p port] [-q probes] [-s src] [-w waittime] target\n" 1705 " [datalen]\n"); 1706 exit(1); 1707 } 1708