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