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 * 4. 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/udp.h> 275 276 #ifdef IPSEC 277 #include <net/route.h> 278 #include <netipsec/ipsec.h> 279 #endif 280 281 #include "as.h" 282 283 #define DUMMY_PORT 10010 284 285 #define MAXPACKET 65535 /* max ip packet size */ 286 287 #ifndef HAVE_GETIPNODEBYNAME 288 #define getipnodebyname(x, y, z, u) gethostbyname2((x), (y)) 289 #define freehostent(x) 290 #endif 291 292 /* 293 * format of a (udp) probe packet. 294 */ 295 struct tv32 { 296 u_int32_t tv32_sec; 297 u_int32_t tv32_usec; 298 }; 299 300 struct opacket { 301 u_char seq; /* sequence number of this packet */ 302 u_char hops; /* hop limit of the packet */ 303 u_char pad[2]; 304 struct tv32 tv; /* time packet left */ 305 } __attribute__((__packed__)); 306 307 u_char packet[512]; /* last inbound (icmp) packet */ 308 struct opacket *outpacket; /* last output (udp) packet */ 309 310 int main(int, char *[]); 311 int wait_for_reply(int, struct msghdr *); 312 #ifdef IPSEC 313 #ifdef IPSEC_POLICY_IPSEC 314 int setpolicy(int so, char *policy); 315 #endif 316 #endif 317 void send_probe(int, u_long); 318 void *get_uphdr(struct ip6_hdr *, u_char *); 319 int get_hoplim(struct msghdr *); 320 double deltaT(struct timeval *, struct timeval *); 321 const char *pr_type(int); 322 int packet_ok(struct msghdr *, int, int); 323 void print(struct msghdr *, int); 324 const char *inetname(struct sockaddr *); 325 void usage(void); 326 327 int rcvsock; /* receive (icmp) socket file descriptor */ 328 int sndsock; /* send (udp) socket file descriptor */ 329 330 struct msghdr rcvmhdr; 331 struct iovec rcviov[2]; 332 int rcvhlim; 333 struct in6_pktinfo *rcvpktinfo; 334 335 struct sockaddr_in6 Src, Dst, Rcv; 336 u_long datalen; /* How much data */ 337 #define ICMP6ECHOLEN 8 338 /* XXX: 2064 = 127(max hops in type 0 rthdr) * sizeof(ip6_hdr) + 16(margin) */ 339 char rtbuf[2064]; 340 #ifdef USE_RFC2292BIS 341 struct ip6_rthdr *rth; 342 #endif 343 struct cmsghdr *cmsg; 344 345 char *source = NULL; 346 char *hostname; 347 348 u_long nprobes = 3; 349 u_long first_hop = 1; 350 u_long max_hops = 30; 351 u_int16_t srcport; 352 u_int16_t port = 32768+666; /* start udp dest port # for probe packets */ 353 u_int16_t ident; 354 int options; /* socket options */ 355 int verbose; 356 int waittime = 5; /* time to wait for response (in seconds) */ 357 int nflag; /* print addresses numerically */ 358 int useproto = IPPROTO_UDP; /* protocol to use to send packet */ 359 int lflag; /* print both numerical address & hostname */ 360 int as_path; /* print as numbers for each hop */ 361 char *as_server = NULL; 362 void *asn; 363 364 int 365 main(argc, argv) 366 int argc; 367 char *argv[]; 368 { 369 int mib[4] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_DEFHLIM }; 370 char hbuf[NI_MAXHOST], src0[NI_MAXHOST], *ep; 371 int ch, i, on = 1, seq, rcvcmsglen, error; 372 struct addrinfo hints, *res; 373 static u_char *rcvcmsgbuf; 374 u_long probe, hops, lport; 375 struct hostent *hp; 376 size_t size, minlen; 377 uid_t uid; 378 379 /* 380 * Receive ICMP 381 */ 382 if ((rcvsock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) { 383 perror("socket(ICMPv6)"); 384 exit(5); 385 } 386 387 size = sizeof(i); 388 (void) sysctl(mib, sizeof(mib)/sizeof(mib[0]), &i, &size, NULL, 0); 389 max_hops = i; 390 391 /* specify to tell receiving interface */ 392 #ifdef IPV6_RECVPKTINFO 393 if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, 394 sizeof(on)) < 0) 395 err(1, "setsockopt(IPV6_RECVPKTINFO)"); 396 #else /* old adv. API */ 397 if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_PKTINFO, &on, 398 sizeof(on)) < 0) 399 err(1, "setsockopt(IPV6_PKTINFO)"); 400 #endif 401 402 /* specify to tell value of hoplimit field of received IP6 hdr */ 403 #ifdef IPV6_RECVHOPLIMIT 404 if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, 405 sizeof(on)) < 0) 406 err(1, "setsockopt(IPV6_RECVHOPLIMIT)"); 407 #else /* old adv. API */ 408 if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_HOPLIMIT, &on, 409 sizeof(on)) < 0) 410 err(1, "setsockopt(IPV6_HOPLIMIT)"); 411 #endif 412 413 seq = 0; 414 415 while ((ch = getopt(argc, argv, "aA:df:g:Ilm:nNp:q:rs:Uvw:")) != -1) 416 switch (ch) { 417 case 'a': 418 as_path = 1; 419 break; 420 case 'A': 421 as_path = 1; 422 as_server = optarg; 423 break; 424 case 'd': 425 options |= SO_DEBUG; 426 break; 427 case 'f': 428 ep = NULL; 429 errno = 0; 430 first_hop = strtoul(optarg, &ep, 0); 431 if (errno || !*optarg || *ep || first_hop > 255) { 432 fprintf(stderr, 433 "traceroute6: invalid min hoplimit.\n"); 434 exit(1); 435 } 436 break; 437 case 'g': 438 hp = getipnodebyname(optarg, AF_INET6, 0, &h_errno); 439 if (hp == NULL) { 440 fprintf(stderr, 441 "traceroute6: unknown host %s\n", optarg); 442 exit(1); 443 } 444 #ifdef USE_RFC2292BIS 445 if (rth == NULL) { 446 /* 447 * XXX: We can't detect the number of 448 * intermediate nodes yet. 449 */ 450 if ((rth = inet6_rth_init((void *)rtbuf, 451 sizeof(rtbuf), IPV6_RTHDR_TYPE_0, 452 0)) == NULL) { 453 fprintf(stderr, 454 "inet6_rth_init failed.\n"); 455 exit(1); 456 } 457 } 458 if (inet6_rth_add((void *)rth, 459 (struct in6_addr *)hp->h_addr)) { 460 fprintf(stderr, 461 "inet6_rth_add failed for %s\n", 462 optarg); 463 exit(1); 464 } 465 #else /* old advanced API */ 466 if (cmsg == NULL) 467 cmsg = inet6_rthdr_init(rtbuf, IPV6_RTHDR_TYPE_0); 468 inet6_rthdr_add(cmsg, (struct in6_addr *)hp->h_addr, 469 IPV6_RTHDR_LOOSE); 470 #endif 471 freehostent(hp); 472 break; 473 case 'I': 474 useproto = IPPROTO_ICMPV6; 475 ident = htons(getpid() & 0xffff); /* same as ping6 */ 476 break; 477 case 'l': 478 lflag++; 479 break; 480 case 'm': 481 ep = NULL; 482 errno = 0; 483 max_hops = strtoul(optarg, &ep, 0); 484 if (errno || !*optarg || *ep || max_hops > 255) { 485 fprintf(stderr, 486 "traceroute6: invalid max hoplimit.\n"); 487 exit(1); 488 } 489 break; 490 case 'n': 491 nflag++; 492 break; 493 case 'N': 494 useproto = IPPROTO_NONE; 495 break; 496 case 'p': 497 ep = NULL; 498 errno = 0; 499 lport = strtoul(optarg, &ep, 0); 500 if (errno || !*optarg || *ep) { 501 fprintf(stderr, "traceroute6: invalid port.\n"); 502 exit(1); 503 } 504 if (lport == 0 || lport != (lport & 0xffff)) { 505 fprintf(stderr, 506 "traceroute6: port out of range.\n"); 507 exit(1); 508 } 509 port = lport & 0xffff; 510 break; 511 case 'q': 512 ep = NULL; 513 errno = 0; 514 nprobes = strtoul(optarg, &ep, 0); 515 if (errno || !*optarg || *ep) { 516 fprintf(stderr, 517 "traceroute6: invalid nprobes.\n"); 518 exit(1); 519 } 520 if (nprobes < 1) { 521 fprintf(stderr, 522 "traceroute6: nprobes must be >0.\n"); 523 exit(1); 524 } 525 break; 526 case 'r': 527 options |= SO_DONTROUTE; 528 break; 529 case 's': 530 /* 531 * set the ip source address of the outbound 532 * probe (e.g., on a multi-homed host). 533 */ 534 source = optarg; 535 break; 536 case 'v': 537 verbose++; 538 break; 539 case 'U': 540 useproto = IPPROTO_UDP; 541 break; 542 case 'w': 543 ep = NULL; 544 errno = 0; 545 waittime = strtoul(optarg, &ep, 0); 546 if (errno || !*optarg || *ep) { 547 fprintf(stderr, 548 "traceroute6: invalid wait time.\n"); 549 exit(1); 550 } 551 if (waittime < 1) { 552 fprintf(stderr, 553 "traceroute6: wait must be >= 1 sec.\n"); 554 exit(1); 555 } 556 break; 557 default: 558 usage(); 559 } 560 argc -= optind; 561 argv += optind; 562 563 /* 564 * Open socket to send probe packets. 565 */ 566 switch (useproto) { 567 case IPPROTO_ICMPV6: 568 sndsock = rcvsock; 569 break; 570 case IPPROTO_UDP: 571 if ((sndsock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 572 perror("socket(SOCK_DGRAM)"); 573 exit(5); 574 } 575 break; 576 case IPPROTO_NONE: 577 if ((sndsock = socket(AF_INET6, SOCK_RAW, IPPROTO_NONE)) < 0) { 578 perror("socket(SOCK_RAW)"); 579 exit(5); 580 } 581 break; 582 default: 583 fprintf(stderr, "traceroute6: unknown probe protocol %d", 584 useproto); 585 exit(5); 586 } 587 if (max_hops < first_hop) { 588 fprintf(stderr, 589 "traceroute6: max hoplimit must be larger than first hoplimit.\n"); 590 exit(1); 591 } 592 593 /* revoke privs */ 594 uid = getuid(); 595 if (setresuid(uid, uid, uid) == -1) { 596 perror("setresuid"); 597 exit(1); 598 } 599 600 601 if (argc < 1 || argc > 2) 602 usage(); 603 604 #if 1 605 setvbuf(stdout, NULL, _IOLBF, BUFSIZ); 606 #else 607 setlinebuf(stdout); 608 #endif 609 610 memset(&hints, 0, sizeof(hints)); 611 hints.ai_family = PF_INET6; 612 hints.ai_socktype = SOCK_RAW; 613 hints.ai_protocol = IPPROTO_ICMPV6; 614 hints.ai_flags = AI_CANONNAME; 615 error = getaddrinfo(*argv, NULL, &hints, &res); 616 if (error) { 617 fprintf(stderr, 618 "traceroute6: %s\n", gai_strerror(error)); 619 exit(1); 620 } 621 if (res->ai_addrlen != sizeof(Dst)) { 622 fprintf(stderr, 623 "traceroute6: size of sockaddr mismatch\n"); 624 exit(1); 625 } 626 memcpy(&Dst, res->ai_addr, res->ai_addrlen); 627 hostname = res->ai_canonname ? strdup(res->ai_canonname) : *argv; 628 if (!hostname) { 629 fprintf(stderr, "traceroute6: not enough core\n"); 630 exit(1); 631 } 632 if (res->ai_next) { 633 if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, 634 sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) 635 strlcpy(hbuf, "?", sizeof(hbuf)); 636 fprintf(stderr, "traceroute6: Warning: %s has multiple " 637 "addresses; using %s\n", hostname, hbuf); 638 } 639 640 if (*++argv) { 641 ep = NULL; 642 errno = 0; 643 datalen = strtoul(*argv, &ep, 0); 644 if (errno || !*argv || *ep) { 645 fprintf(stderr, 646 "traceroute6: invalid packet length.\n"); 647 exit(1); 648 } 649 } 650 switch (useproto) { 651 case IPPROTO_ICMPV6: 652 minlen = ICMP6ECHOLEN + sizeof(struct tv32); 653 break; 654 case IPPROTO_UDP: 655 minlen = sizeof(struct opacket); 656 break; 657 case IPPROTO_NONE: 658 minlen = 0; 659 datalen = 0; 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 outpacket = malloc(datalen); 675 if (!outpacket) { 676 perror("malloc"); 677 exit(1); 678 } 679 (void) bzero((char *)outpacket, datalen); 680 681 /* initialize msghdr for receiving packets */ 682 rcviov[0].iov_base = (caddr_t)packet; 683 rcviov[0].iov_len = sizeof(packet); 684 rcvmhdr.msg_name = (caddr_t)&Rcv; 685 rcvmhdr.msg_namelen = sizeof(Rcv); 686 rcvmhdr.msg_iov = rcviov; 687 rcvmhdr.msg_iovlen = 1; 688 rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + 689 CMSG_SPACE(sizeof(int)); 690 if ((rcvcmsgbuf = malloc(rcvcmsglen)) == NULL) { 691 fprintf(stderr, "traceroute6: malloc failed\n"); 692 exit(1); 693 } 694 rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf; 695 rcvmhdr.msg_controllen = rcvcmsglen; 696 697 if (options & SO_DEBUG) 698 (void) setsockopt(rcvsock, SOL_SOCKET, SO_DEBUG, 699 (char *)&on, sizeof(on)); 700 if (options & SO_DONTROUTE) 701 (void) setsockopt(rcvsock, SOL_SOCKET, SO_DONTROUTE, 702 (char *)&on, sizeof(on)); 703 #ifdef IPSEC 704 #ifdef IPSEC_POLICY_IPSEC 705 /* 706 * do not raise error even if setsockopt fails, kernel may have ipsec 707 * turned off. 708 */ 709 if (setpolicy(rcvsock, "in bypass") < 0) 710 errx(1, "%s", ipsec_strerror()); 711 if (setpolicy(rcvsock, "out bypass") < 0) 712 errx(1, "%s", ipsec_strerror()); 713 #else 714 { 715 int level = IPSEC_LEVEL_NONE; 716 717 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, &level, 718 sizeof(level)); 719 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_ESP_NETWORK_LEVEL, &level, 720 sizeof(level)); 721 #ifdef IP_AUTH_TRANS_LEVEL 722 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, &level, 723 sizeof(level)); 724 #else 725 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_LEVEL, &level, 726 sizeof(level)); 727 #endif 728 #ifdef IP_AUTH_NETWORK_LEVEL 729 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_NETWORK_LEVEL, &level, 730 sizeof(level)); 731 #endif 732 } 733 #endif /*IPSEC_POLICY_IPSEC*/ 734 #endif /*IPSEC*/ 735 736 #ifdef SO_SNDBUF 737 i = datalen; 738 if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&i, 739 sizeof(i)) < 0 && useproto != IPPROTO_NONE) { 740 perror("setsockopt(SO_SNDBUF)"); 741 exit(6); 742 } 743 #endif /* SO_SNDBUF */ 744 if (options & SO_DEBUG) 745 (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, 746 (char *)&on, sizeof(on)); 747 if (options & SO_DONTROUTE) 748 (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, 749 (char *)&on, sizeof(on)); 750 #ifdef USE_RFC2292BIS 751 if (rth) {/* XXX: there is no library to finalize the header... */ 752 rth->ip6r_len = rth->ip6r_segleft * 2; 753 if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_RTHDR, 754 (void *)rth, (rth->ip6r_len + 1) << 3)) { 755 fprintf(stderr, "setsockopt(IPV6_RTHDR): %s\n", 756 strerror(errno)); 757 exit(1); 758 } 759 } 760 #else /* old advanced API */ 761 if (cmsg != NULL) { 762 inet6_rthdr_lasthop(cmsg, IPV6_RTHDR_LOOSE); 763 if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_PKTOPTIONS, 764 rtbuf, cmsg->cmsg_len) < 0) { 765 fprintf(stderr, "setsockopt(IPV6_PKTOPTIONS): %s\n", 766 strerror(errno)); 767 exit(1); 768 } 769 } 770 #endif /* USE_RFC2292BIS */ 771 #ifdef IPSEC 772 #ifdef IPSEC_POLICY_IPSEC 773 /* 774 * do not raise error even if setsockopt fails, kernel may have ipsec 775 * turned off. 776 */ 777 if (setpolicy(sndsock, "in bypass") < 0) 778 errx(1, "%s", ipsec_strerror()); 779 if (setpolicy(sndsock, "out bypass") < 0) 780 errx(1, "%s", ipsec_strerror()); 781 #else 782 { 783 int level = IPSEC_LEVEL_BYPASS; 784 785 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, &level, 786 sizeof(level)); 787 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_ESP_NETWORK_LEVEL, &level, 788 sizeof(level)); 789 #ifdef IP_AUTH_TRANS_LEVEL 790 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, &level, 791 sizeof(level)); 792 #else 793 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_LEVEL, &level, 794 sizeof(level)); 795 #endif 796 #ifdef IP_AUTH_NETWORK_LEVEL 797 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_NETWORK_LEVEL, &level, 798 sizeof(level)); 799 #endif 800 } 801 #endif /*IPSEC_POLICY_IPSEC*/ 802 #endif /*IPSEC*/ 803 804 /* 805 * Source selection 806 */ 807 bzero(&Src, sizeof(Src)); 808 if (source) { 809 struct addrinfo hints, *res; 810 int error; 811 812 memset(&hints, 0, sizeof(hints)); 813 hints.ai_family = AF_INET6; 814 hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 815 hints.ai_flags = AI_NUMERICHOST; 816 error = getaddrinfo(source, "0", &hints, &res); 817 if (error) { 818 printf("traceroute6: %s: %s\n", source, 819 gai_strerror(error)); 820 exit(1); 821 } 822 if (res->ai_addrlen > sizeof(Src)) { 823 printf("traceroute6: %s: %s\n", source, 824 gai_strerror(error)); 825 exit(1); 826 } 827 memcpy(&Src, res->ai_addr, res->ai_addrlen); 828 freeaddrinfo(res); 829 } else { 830 struct sockaddr_in6 Nxt; 831 int dummy; 832 socklen_t len; 833 834 Nxt = Dst; 835 Nxt.sin6_port = htons(DUMMY_PORT); 836 if (cmsg != NULL) 837 bcopy(inet6_rthdr_getaddr(cmsg, 1), &Nxt.sin6_addr, 838 sizeof(Nxt.sin6_addr)); 839 if ((dummy = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 840 perror("socket"); 841 exit(1); 842 } 843 if (connect(dummy, (struct sockaddr *)&Nxt, Nxt.sin6_len) < 0) { 844 perror("connect"); 845 exit(1); 846 } 847 len = sizeof(Src); 848 if (getsockname(dummy, (struct sockaddr *)&Src, &len) < 0) { 849 perror("getsockname"); 850 exit(1); 851 } 852 if (getnameinfo((struct sockaddr *)&Src, Src.sin6_len, 853 src0, sizeof(src0), NULL, 0, NI_NUMERICHOST)) { 854 fprintf(stderr, "getnameinfo failed for source\n"); 855 exit(1); 856 } 857 source = src0; 858 close(dummy); 859 } 860 861 Src.sin6_port = htons(0); 862 if (bind(sndsock, (struct sockaddr *)&Src, Src.sin6_len) < 0) { 863 perror("bind"); 864 exit(1); 865 } 866 867 { 868 socklen_t len; 869 870 len = sizeof(Src); 871 if (getsockname(sndsock, (struct sockaddr *)&Src, &len) < 0) { 872 perror("getsockname"); 873 exit(1); 874 } 875 srcport = ntohs(Src.sin6_port); 876 } 877 878 if (as_path) { 879 asn = as_setup(as_server); 880 if (asn == NULL) { 881 fprintf(stderr, 882 "traceroute6: as_setup failed, AS# lookups" 883 " disabled\n"); 884 (void)fflush(stderr); 885 as_path = 0; 886 } 887 } 888 889 /* 890 * Message to users 891 */ 892 if (getnameinfo((struct sockaddr *)&Dst, Dst.sin6_len, hbuf, 893 sizeof(hbuf), NULL, 0, NI_NUMERICHOST)) 894 strlcpy(hbuf, "(invalid)", sizeof(hbuf)); 895 fprintf(stderr, "traceroute6"); 896 fprintf(stderr, " to %s (%s)", hostname, hbuf); 897 if (source) 898 fprintf(stderr, " from %s", source); 899 fprintf(stderr, ", %lu hops max, %lu byte packets\n", 900 max_hops, datalen); 901 (void) fflush(stderr); 902 903 if (first_hop > 1) 904 printf("Skipping %lu intermediate hops\n", first_hop - 1); 905 906 /* 907 * Main loop 908 */ 909 for (hops = first_hop; hops <= max_hops; ++hops) { 910 struct in6_addr lastaddr; 911 int got_there = 0; 912 unsigned unreachable = 0; 913 914 printf("%2lu ", hops); 915 bzero(&lastaddr, sizeof(lastaddr)); 916 for (probe = 0; probe < nprobes; ++probe) { 917 int cc; 918 struct timeval t1, t2; 919 920 (void) gettimeofday(&t1, NULL); 921 send_probe(++seq, hops); 922 while ((cc = wait_for_reply(rcvsock, &rcvmhdr))) { 923 (void) gettimeofday(&t2, NULL); 924 if ((i = packet_ok(&rcvmhdr, cc, seq))) { 925 if (!IN6_ARE_ADDR_EQUAL(&Rcv.sin6_addr, 926 &lastaddr)) { 927 if (probe > 0) 928 fputs("\n ", stdout); 929 print(&rcvmhdr, cc); 930 lastaddr = Rcv.sin6_addr; 931 } 932 printf(" %.3f ms", deltaT(&t1, &t2)); 933 switch (i - 1) { 934 case ICMP6_DST_UNREACH_NOROUTE: 935 ++unreachable; 936 printf(" !N"); 937 break; 938 case ICMP6_DST_UNREACH_ADMIN: 939 ++unreachable; 940 printf(" !P"); 941 break; 942 case ICMP6_DST_UNREACH_NOTNEIGHBOR: 943 ++unreachable; 944 printf(" !S"); 945 break; 946 case ICMP6_DST_UNREACH_ADDR: 947 ++unreachable; 948 printf(" !A"); 949 break; 950 case ICMP6_DST_UNREACH_NOPORT: 951 if (rcvhlim >= 0 && 952 rcvhlim <= 1) 953 printf(" !"); 954 ++got_there; 955 break; 956 } 957 break; 958 } else if (deltaT(&t1, &t2) > waittime * 1000) { 959 cc = 0; 960 break; 961 } 962 } 963 if (cc == 0) 964 printf(" *"); 965 (void) fflush(stdout); 966 } 967 putchar('\n'); 968 if (got_there || 969 (unreachable > 0 && unreachable >= ((nprobes + 1) / 2))) { 970 exit(0); 971 } 972 } 973 if (as_path) 974 as_shutdown(asn); 975 976 exit(0); 977 } 978 979 int 980 wait_for_reply(sock, mhdr) 981 int sock; 982 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 #ifdef IPSEC 1017 #ifdef IPSEC_POLICY_IPSEC 1018 int 1019 setpolicy(so, policy) 1020 int so; 1021 char *policy; 1022 { 1023 char *buf; 1024 1025 buf = ipsec_set_policy(policy, strlen(policy)); 1026 if (buf == NULL) { 1027 warnx("%s", ipsec_strerror()); 1028 return -1; 1029 } 1030 (void)setsockopt(so, IPPROTO_IPV6, IPV6_IPSEC_POLICY, 1031 buf, ipsec_get_policylen(buf)); 1032 1033 free(buf); 1034 1035 return 0; 1036 } 1037 #endif 1038 #endif 1039 1040 void 1041 send_probe(seq, hops) 1042 int seq; 1043 u_long hops; 1044 { 1045 struct icmp6_hdr *icp; 1046 struct opacket *op; 1047 struct timeval tv; 1048 struct tv32 tv32; 1049 int i; 1050 1051 i = hops; 1052 if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 1053 (char *)&i, sizeof(i)) < 0) { 1054 perror("setsockopt IPV6_UNICAST_HOPS"); 1055 } 1056 1057 Dst.sin6_port = htons(port + seq); 1058 (void) gettimeofday(&tv, NULL); 1059 tv32.tv32_sec = htonl(tv.tv_sec); 1060 tv32.tv32_usec = htonl(tv.tv_usec); 1061 1062 switch (useproto) { 1063 case IPPROTO_ICMPV6: 1064 icp = (struct icmp6_hdr *)outpacket; 1065 1066 icp->icmp6_type = ICMP6_ECHO_REQUEST; 1067 icp->icmp6_code = 0; 1068 icp->icmp6_cksum = 0; 1069 icp->icmp6_id = ident; 1070 icp->icmp6_seq = htons(seq); 1071 bcopy(&tv32, ((u_int8_t *)outpacket + ICMP6ECHOLEN), 1072 sizeof(tv32)); 1073 break; 1074 case IPPROTO_UDP: 1075 op = outpacket; 1076 1077 op->seq = seq; 1078 op->hops = hops; 1079 bcopy(&tv32, &op->tv, sizeof tv32); 1080 break; 1081 case IPPROTO_NONE: 1082 /* No space for anything. No harm as seq/tv32 are decorative. */ 1083 break; 1084 default: 1085 fprintf(stderr, "Unknown probe protocol %d.\n", useproto); 1086 exit(1); 1087 } 1088 1089 i = sendto(sndsock, (char *)outpacket, datalen, 0, 1090 (struct sockaddr *)&Dst, Dst.sin6_len); 1091 if (i < 0 || (u_long)i != datalen) { 1092 if (i < 0) 1093 perror("sendto"); 1094 printf("traceroute6: wrote %s %lu chars, ret=%d\n", 1095 hostname, datalen, i); 1096 (void) fflush(stdout); 1097 } 1098 } 1099 1100 int 1101 get_hoplim(mhdr) 1102 struct msghdr *mhdr; 1103 { 1104 struct cmsghdr *cm; 1105 1106 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; 1107 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { 1108 if (cm->cmsg_level == IPPROTO_IPV6 && 1109 cm->cmsg_type == IPV6_HOPLIMIT && 1110 cm->cmsg_len == CMSG_LEN(sizeof(int))) 1111 return(*(int *)CMSG_DATA(cm)); 1112 } 1113 1114 return(-1); 1115 } 1116 1117 double 1118 deltaT(t1p, t2p) 1119 struct timeval *t1p, *t2p; 1120 { 1121 double dt; 1122 1123 dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 + 1124 (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0; 1125 return (dt); 1126 } 1127 1128 /* 1129 * Convert an ICMP "type" field to a printable string. 1130 */ 1131 const char * 1132 pr_type(int t0) 1133 { 1134 u_char t = t0 & 0xff; 1135 const char *cp; 1136 1137 switch (t) { 1138 case ICMP6_DST_UNREACH: 1139 cp = "Destination Unreachable"; 1140 break; 1141 case ICMP6_PACKET_TOO_BIG: 1142 cp = "Packet Too Big"; 1143 break; 1144 case ICMP6_TIME_EXCEEDED: 1145 cp = "Time Exceeded"; 1146 break; 1147 case ICMP6_PARAM_PROB: 1148 cp = "Parameter Problem"; 1149 break; 1150 case ICMP6_ECHO_REQUEST: 1151 cp = "Echo Request"; 1152 break; 1153 case ICMP6_ECHO_REPLY: 1154 cp = "Echo Reply"; 1155 break; 1156 case ICMP6_MEMBERSHIP_QUERY: 1157 cp = "Group Membership Query"; 1158 break; 1159 case ICMP6_MEMBERSHIP_REPORT: 1160 cp = "Group Membership Report"; 1161 break; 1162 case ICMP6_MEMBERSHIP_REDUCTION: 1163 cp = "Group Membership Reduction"; 1164 break; 1165 case ND_ROUTER_SOLICIT: 1166 cp = "Router Solicitation"; 1167 break; 1168 case ND_ROUTER_ADVERT: 1169 cp = "Router Advertisement"; 1170 break; 1171 case ND_NEIGHBOR_SOLICIT: 1172 cp = "Neighbor Solicitation"; 1173 break; 1174 case ND_NEIGHBOR_ADVERT: 1175 cp = "Neighbor Advertisement"; 1176 break; 1177 case ND_REDIRECT: 1178 cp = "Redirect"; 1179 break; 1180 default: 1181 cp = "Unknown"; 1182 break; 1183 } 1184 return cp; 1185 } 1186 1187 int 1188 packet_ok(mhdr, cc, seq) 1189 struct msghdr *mhdr; 1190 int cc; 1191 int seq; 1192 { 1193 struct icmp6_hdr *icp; 1194 struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name; 1195 u_char type, code; 1196 char *buf = (char *)mhdr->msg_iov[0].iov_base; 1197 struct cmsghdr *cm; 1198 int *hlimp; 1199 char hbuf[NI_MAXHOST]; 1200 1201 #ifdef OLDRAWSOCKET 1202 int hlen; 1203 struct ip6_hdr *ip; 1204 #endif 1205 1206 #ifdef OLDRAWSOCKET 1207 ip = (struct ip6_hdr *) buf; 1208 hlen = sizeof(struct ip6_hdr); 1209 if (cc < hlen + sizeof(struct icmp6_hdr)) { 1210 if (verbose) { 1211 if (getnameinfo((struct sockaddr *)from, from->sin6_len, 1212 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) 1213 strlcpy(hbuf, "invalid", sizeof(hbuf)); 1214 printf("packet too short (%d bytes) from %s\n", cc, 1215 hbuf); 1216 } 1217 return (0); 1218 } 1219 cc -= hlen; 1220 icp = (struct icmp6_hdr *)(buf + hlen); 1221 #else 1222 if (cc < (int)sizeof(struct icmp6_hdr)) { 1223 if (verbose) { 1224 if (getnameinfo((struct sockaddr *)from, from->sin6_len, 1225 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) 1226 strlcpy(hbuf, "invalid", sizeof(hbuf)); 1227 printf("data too short (%d bytes) from %s\n", cc, hbuf); 1228 } 1229 return(0); 1230 } 1231 icp = (struct icmp6_hdr *)buf; 1232 #endif 1233 /* get optional information via advanced API */ 1234 rcvpktinfo = NULL; 1235 hlimp = NULL; 1236 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; 1237 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { 1238 if (cm->cmsg_level == IPPROTO_IPV6 && 1239 cm->cmsg_type == IPV6_PKTINFO && 1240 cm->cmsg_len == 1241 CMSG_LEN(sizeof(struct in6_pktinfo))) 1242 rcvpktinfo = (struct in6_pktinfo *)(CMSG_DATA(cm)); 1243 1244 if (cm->cmsg_level == IPPROTO_IPV6 && 1245 cm->cmsg_type == IPV6_HOPLIMIT && 1246 cm->cmsg_len == CMSG_LEN(sizeof(int))) 1247 hlimp = (int *)CMSG_DATA(cm); 1248 } 1249 if (rcvpktinfo == NULL || hlimp == NULL) { 1250 warnx("failed to get received hop limit or packet info"); 1251 #if 0 1252 return(0); 1253 #else 1254 rcvhlim = 0; /*XXX*/ 1255 #endif 1256 } 1257 else 1258 rcvhlim = *hlimp; 1259 1260 type = icp->icmp6_type; 1261 code = icp->icmp6_code; 1262 if ((type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT) 1263 || type == ICMP6_DST_UNREACH) { 1264 struct ip6_hdr *hip; 1265 void *up; 1266 1267 hip = (struct ip6_hdr *)(icp + 1); 1268 if ((up = get_uphdr(hip, (u_char *)(buf + cc))) == NULL) { 1269 if (verbose) 1270 warnx("failed to get upper layer header"); 1271 return(0); 1272 } 1273 switch (useproto) { 1274 case IPPROTO_ICMPV6: 1275 if (((struct icmp6_hdr *)up)->icmp6_id == ident && 1276 ((struct icmp6_hdr *)up)->icmp6_seq == htons(seq)) 1277 return (type == ICMP6_TIME_EXCEEDED ? 1278 -1 : code + 1); 1279 break; 1280 case IPPROTO_UDP: 1281 if (((struct udphdr *)up)->uh_sport == htons(srcport) && 1282 ((struct udphdr *)up)->uh_dport == htons(port + seq)) 1283 return (type == ICMP6_TIME_EXCEEDED ? 1284 -1 : code + 1); 1285 break; 1286 case IPPROTO_NONE: 1287 return (type == ICMP6_TIME_EXCEEDED ? -1 : code + 1); 1288 default: 1289 fprintf(stderr, "Unknown probe proto %d.\n", useproto); 1290 break; 1291 } 1292 } else if (useproto == IPPROTO_ICMPV6 && type == ICMP6_ECHO_REPLY) { 1293 if (icp->icmp6_id == ident && 1294 icp->icmp6_seq == htons(seq)) 1295 return (ICMP6_DST_UNREACH_NOPORT + 1); 1296 } 1297 if (verbose) { 1298 char sbuf[NI_MAXHOST+1], dbuf[INET6_ADDRSTRLEN]; 1299 u_int8_t *p; 1300 int i; 1301 1302 if (getnameinfo((struct sockaddr *)from, from->sin6_len, 1303 sbuf, sizeof(sbuf), NULL, 0, NI_NUMERICHOST) != 0) 1304 strlcpy(sbuf, "invalid", sizeof(sbuf)); 1305 printf("\n%d bytes from %s to %s", cc, sbuf, 1306 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr, 1307 dbuf, sizeof(dbuf)) : "?"); 1308 printf(": icmp type %d (%s) code %d\n", type, pr_type(type), 1309 icp->icmp6_code); 1310 p = (u_int8_t *)(icp + 1); 1311 #define WIDTH 16 1312 for (i = 0; i < cc; i++) { 1313 if (i % WIDTH == 0) 1314 printf("%04x:", i); 1315 if (i % 4 == 0) 1316 printf(" "); 1317 printf("%02x", p[i]); 1318 if (i % WIDTH == WIDTH - 1) 1319 printf("\n"); 1320 } 1321 if (cc % WIDTH != 0) 1322 printf("\n"); 1323 } 1324 return(0); 1325 } 1326 1327 /* 1328 * Increment pointer until find the UDP or ICMP header. 1329 */ 1330 void * 1331 get_uphdr(ip6, lim) 1332 struct ip6_hdr *ip6; 1333 u_char *lim; 1334 { 1335 u_char *cp = (u_char *)ip6, nh; 1336 int hlen; 1337 static u_char none_hdr[1]; /* Fake pointer for IPPROTO_NONE. */ 1338 1339 if (cp + sizeof(*ip6) > lim) 1340 return(NULL); 1341 1342 nh = ip6->ip6_nxt; 1343 cp += sizeof(struct ip6_hdr); 1344 1345 while (lim - cp >= (nh == IPPROTO_NONE ? 0 : 8)) { 1346 switch (nh) { 1347 case IPPROTO_ESP: 1348 case IPPROTO_TCP: 1349 return(NULL); 1350 case IPPROTO_ICMPV6: 1351 return(useproto == nh ? cp : NULL); 1352 case IPPROTO_UDP: 1353 return(useproto == nh ? cp : NULL); 1354 case IPPROTO_NONE: 1355 return(useproto == nh ? none_hdr : NULL); 1356 case IPPROTO_FRAGMENT: 1357 hlen = sizeof(struct ip6_frag); 1358 nh = ((struct ip6_frag *)cp)->ip6f_nxt; 1359 break; 1360 case IPPROTO_AH: 1361 hlen = (((struct ip6_ext *)cp)->ip6e_len + 2) << 2; 1362 nh = ((struct ip6_ext *)cp)->ip6e_nxt; 1363 break; 1364 default: 1365 hlen = (((struct ip6_ext *)cp)->ip6e_len + 1) << 3; 1366 nh = ((struct ip6_ext *)cp)->ip6e_nxt; 1367 break; 1368 } 1369 1370 cp += hlen; 1371 } 1372 1373 return(NULL); 1374 } 1375 1376 void 1377 print(mhdr, cc) 1378 struct msghdr *mhdr; 1379 int cc; 1380 { 1381 struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name; 1382 char hbuf[NI_MAXHOST]; 1383 1384 if (getnameinfo((struct sockaddr *)from, from->sin6_len, 1385 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) 1386 strlcpy(hbuf, "invalid", sizeof(hbuf)); 1387 if (as_path) 1388 printf(" [AS%u]", as_lookup(asn, hbuf, AF_INET6)); 1389 if (nflag) 1390 printf(" %s", hbuf); 1391 else if (lflag) 1392 printf(" %s (%s)", inetname((struct sockaddr *)from), hbuf); 1393 else 1394 printf(" %s", inetname((struct sockaddr *)from)); 1395 1396 if (verbose) { 1397 #ifdef OLDRAWSOCKET 1398 printf(" %d bytes to %s", cc, 1399 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr, 1400 hbuf, sizeof(hbuf)) : "?"); 1401 #else 1402 printf(" %d bytes of data to %s", cc, 1403 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr, 1404 hbuf, sizeof(hbuf)) : "?"); 1405 #endif 1406 } 1407 } 1408 1409 /* 1410 * Construct an Internet address representation. 1411 * If the nflag has been supplied, give 1412 * numeric value, otherwise try for symbolic name. 1413 */ 1414 const char * 1415 inetname(sa) 1416 struct sockaddr *sa; 1417 { 1418 static char line[NI_MAXHOST], domain[MAXHOSTNAMELEN + 1]; 1419 static int first = 1; 1420 char *cp; 1421 1422 if (first && !nflag) { 1423 first = 0; 1424 if (gethostname(domain, sizeof(domain)) == 0 && 1425 (cp = strchr(domain, '.'))) 1426 (void) strlcpy(domain, cp + 1, sizeof(domain)); 1427 else 1428 domain[0] = 0; 1429 } 1430 cp = NULL; 1431 if (!nflag) { 1432 if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0, 1433 NI_NAMEREQD) == 0) { 1434 if ((cp = strchr(line, '.')) && 1435 !strcmp(cp + 1, domain)) 1436 *cp = 0; 1437 cp = line; 1438 } 1439 } 1440 if (cp) 1441 return cp; 1442 1443 if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0, 1444 NI_NUMERICHOST) != 0) 1445 strlcpy(line, "invalid", sizeof(line)); 1446 return line; 1447 } 1448 1449 void 1450 usage() 1451 { 1452 1453 fprintf(stderr, 1454 "usage: traceroute6 [-adIlnNrUv] [-A as_server] [-f firsthop] [-g gateway]\n" 1455 " [-m hoplimit] [-p port] [-q probes] [-s src] [-w waittime] target\n" 1456 " [datalen]\n"); 1457 exit(1); 1458 } 1459