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