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