1 /* $KAME: traceroute6.c,v 1.68 2004/01/25 11:16:12 suz Exp $ */ 2 3 /* 4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the project nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 /*- 33 * Copyright (c) 1990, 1993 34 * The Regents of the University of California. All rights reserved. 35 * 36 * This code is derived from software contributed to Berkeley by 37 * Van Jacobson. 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 3. Neither the name of the University nor the names of its contributors 48 * may be used to endorse or promote products derived from this software 49 * without specific prior written permission. 50 * 51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 61 * SUCH DAMAGE. 62 * 63 * "@(#) Copyright (c) 1990, 1993 64 * The Regents of the University of California. All rights reserved. 65 * 66 * $FreeBSD: src/usr.sbin/traceroute6/traceroute6.c,v 1.22 2008/02/10 21:06:38 dwmalone Exp $ 67 */ 68 69 /* 70 * traceroute host - trace the route ip packets follow going to "host". 71 * 72 * Attempt to trace the route an ip packet would follow to some 73 * internet host. We find out intermediate hops by launching probe 74 * packets with a small ttl (time to live) then listening for an 75 * icmp "time exceeded" reply from a gateway. We start our probes 76 * with a ttl of one and increase by one until we get an icmp "port 77 * unreachable" (which means we got to "host") or hit a max (which 78 * defaults to 30 hops & can be changed with the -m flag). Three 79 * probes (change with -q flag) are sent at each ttl setting and a 80 * line is printed showing the ttl, address of the gateway and 81 * round trip time of each probe. If the probe answers come from 82 * different gateways, the address of each responding system will 83 * be printed. If there is no response within a 5 sec. timeout 84 * interval (changed with the -w flag), a "*" is printed for that 85 * probe. 86 * 87 * Probe packets are UDP format. We don't want the destination 88 * host to process them so the destination port is set to an 89 * unlikely value (if some clod on the destination is using that 90 * value, it can be changed with the -p flag). 91 * 92 * A sample use might be: 93 * 94 * [yak 71]% traceroute nis.nsf.net. 95 * traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 56 byte packet 96 * 1 helios.ee.lbl.gov (128.3.112.1) 19 ms 19 ms 0 ms 97 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms 98 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms 99 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 39 ms 100 * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 39 ms 39 ms 39 ms 101 * 6 128.32.197.4 (128.32.197.4) 40 ms 59 ms 59 ms 102 * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 59 ms 103 * 8 129.140.70.13 (129.140.70.13) 99 ms 99 ms 80 ms 104 * 9 129.140.71.6 (129.140.71.6) 139 ms 239 ms 319 ms 105 * 10 129.140.81.7 (129.140.81.7) 220 ms 199 ms 199 ms 106 * 11 nic.merit.edu (35.1.1.48) 239 ms 239 ms 239 ms 107 * 108 * Note that lines 2 & 3 are the same. This is due to a buggy 109 * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards 110 * packets with a zero ttl. 111 * 112 * A more interesting example is: 113 * 114 * [yak 72]% traceroute allspice.lcs.mit.edu. 115 * traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max 116 * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms 117 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 19 ms 19 ms 118 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 19 ms 119 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 19 ms 39 ms 39 ms 120 * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 20 ms 39 ms 39 ms 121 * 6 128.32.197.4 (128.32.197.4) 59 ms 119 ms 39 ms 122 * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 39 ms 123 * 8 129.140.70.13 (129.140.70.13) 80 ms 79 ms 99 ms 124 * 9 129.140.71.6 (129.140.71.6) 139 ms 139 ms 159 ms 125 * 10 129.140.81.7 (129.140.81.7) 199 ms 180 ms 300 ms 126 * 11 129.140.72.17 (129.140.72.17) 300 ms 239 ms 239 ms 127 * 12 * * * 128 * 13 128.121.54.72 (128.121.54.72) 259 ms 499 ms 279 ms 129 * 14 * * * 130 * 15 * * * 131 * 16 * * * 132 * 17 * * * 133 * 18 ALLSPICE.LCS.MIT.EDU (18.26.0.115) 339 ms 279 ms 279 ms 134 * 135 * (I start to see why I'm having so much trouble with mail to 136 * MIT.) Note that the gateways 12, 14, 15, 16 & 17 hops away 137 * either don't send ICMP "time exceeded" messages or send them 138 * with a ttl too small to reach us. 14 - 17 are running the 139 * MIT C Gateway code that doesn't send "time exceeded"s. God 140 * only knows what's going on with 12. 141 * 142 * The silent gateway 12 in the above may be the result of a bug in 143 * the 4.[23]BSD network code (and its derivatives): 4.x (x <= 3) 144 * sends an unreachable message using whatever ttl remains in the 145 * original datagram. Since, for gateways, the remaining ttl is 146 * zero, the icmp "time exceeded" is guaranteed to not make it back 147 * to us. The behavior of this bug is slightly more interesting 148 * when it appears on the destination system: 149 * 150 * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms 151 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 39 ms 152 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 39 ms 19 ms 153 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 19 ms 154 * 5 ccn-nerif35.Berkeley.EDU (128.32.168.35) 39 ms 39 ms 39 ms 155 * 6 csgw.Berkeley.EDU (128.32.133.254) 39 ms 59 ms 39 ms 156 * 7 * * * 157 * 8 * * * 158 * 9 * * * 159 * 10 * * * 160 * 11 * * * 161 * 12 * * * 162 * 13 rip.Berkeley.EDU (128.32.131.22) 59 ms ! 39 ms ! 39 ms ! 163 * 164 * Notice that there are 12 "gateways" (13 is the final 165 * destination) and exactly the last half of them are "missing". 166 * What's really happening is that rip (a Sun-3 running Sun OS3.5) 167 * is using the ttl from our arriving datagram as the ttl in its 168 * icmp reply. So, the reply will time out on the return path 169 * (with no notice sent to anyone since icmp's aren't sent for 170 * icmp's) until we probe with a ttl that's at least twice the path 171 * length. I.e., rip is really only 7 hops away. A reply that 172 * returns with a ttl of 1 is a clue this problem exists. 173 * Traceroute prints a "!" after the time if the ttl is <= 1. 174 * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or 175 * non-standard (HPUX) software, expect to see this problem 176 * frequently and/or take care picking the target host of your 177 * probes. 178 * 179 * Other possible annotations after the time are !H, !N, !P (got a host, 180 * network or protocol unreachable, respectively), !S or !F (source 181 * route failed or fragmentation needed -- neither of these should 182 * ever occur and the associated gateway is busted if you see one). If 183 * almost all the probes result in some kind of unreachable, traceroute 184 * will give up and exit. 185 * 186 * Notes 187 * ----- 188 * This program must be run by root or be setuid. (I suggest that 189 * you *don't* make it setuid -- casual use could result in a lot 190 * of unnecessary traffic on our poor, congested nets.) 191 * 192 * This program requires a kernel mod that does not appear in any 193 * system available from Berkeley: A raw ip socket using proto 194 * IPPROTO_RAW must interpret the data sent as an ip datagram (as 195 * opposed to data to be wrapped in an ip datagram). See the README 196 * file that came with the source to this program for a description 197 * of the mods I made to /sys/netinet/raw_ip.c. Your mileage may 198 * vary. But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE 199 * MODIFIED TO RUN THIS PROGRAM. 200 * 201 * The udp port usage may appear bizarre (well, ok, it is bizarre). 202 * The problem is that an icmp message only contains 8 bytes of 203 * data from the original datagram. 8 bytes is the size of a udp 204 * header so, if we want to associate replies with the original 205 * datagram, the necessary information must be encoded into the 206 * udp header (the ip id could be used but there's no way to 207 * interlock with the kernel's assignment of ip id's and, anyway, 208 * it would have taken a lot more kernel hacking to allow this 209 * code to set the ip id). So, to allow two or more users to 210 * use traceroute simultaneously, we use this task's pid as the 211 * source port (the high bit is set to move the port number out 212 * of the "likely" range). To keep track of which probe is being 213 * replied to (so times and/or hop counts don't get confused by a 214 * reply that was delayed in transit), we increment the destination 215 * port number before each probe. 216 * 217 * Don't use this as a coding example. I was trying to find a 218 * routing problem and this code sort-of popped out after 48 hours 219 * without sleep. I was amazed it ever compiled, much less ran. 220 * 221 * I stole the idea for this program from Steve Deering. Since 222 * the first release, I've learned that had I attended the right 223 * IETF working group meetings, I also could have stolen it from Guy 224 * Almes or Matt Mathis. I don't know (or care) who came up with 225 * the idea first. I envy the originators' perspicacity and I'm 226 * glad they didn't keep the idea a secret. 227 * 228 * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or 229 * enhancements to the original distribution. 230 * 231 * I've hacked up a round-trip-route version of this that works by 232 * sending a loose-source-routed udp datagram through the destination 233 * back to yourself. Unfortunately, SO many gateways botch source 234 * routing, the thing is almost worthless. Maybe one day... 235 * 236 * -- Van Jacobson (van@helios.ee.lbl.gov) 237 * Tue Dec 20 03:50:13 PST 1988 238 */ 239 240 #include <sys/param.h> 241 #include <sys/time.h> 242 #include <sys/socket.h> 243 #include <sys/uio.h> 244 #include <sys/file.h> 245 #include <sys/ioctl.h> 246 #include <sys/sysctl.h> 247 248 #include <netinet/in.h> 249 250 #include <arpa/inet.h> 251 252 #include <netdb.h> 253 #include <stdio.h> 254 #include <err.h> 255 #ifdef HAVE_POLL 256 #include <poll.h> 257 #endif 258 #include <errno.h> 259 #include <stdlib.h> 260 #include <string.h> 261 #include <unistd.h> 262 263 #include <netinet/ip6.h> 264 #include <netinet/icmp6.h> 265 #include <netinet/udp.h> 266 267 #ifdef IPSEC 268 #include <net/route.h> 269 #include <netinet6/ipsec.h> 270 #endif 271 272 #define DUMMY_PORT 10010 273 274 #define MAXPACKET 65535 /* max ip packet size */ 275 276 #ifndef HAVE_GETIPNODEBYNAME 277 #define getipnodebyname(x, y, z, u) gethostbyname2((x), (y)) 278 #define freehostent(x) 279 #endif 280 281 /* 282 * format of a (udp) probe packet. 283 */ 284 struct tv32 { 285 u_int32_t tv32_sec; 286 u_int32_t tv32_usec; 287 }; 288 289 struct opacket { 290 u_char seq; /* sequence number of this packet */ 291 u_char hops; /* hop limit of the packet */ 292 u_char pad[2]; 293 struct tv32 tv; /* time packet left */ 294 } __attribute__((__packed__)); 295 296 static u_char packet[512]; /* last inbound (icmp) packet */ 297 static struct opacket *outpacket; /* last output (udp) packet */ 298 299 static int wait_for_reply(int, struct msghdr *); 300 #ifdef IPSEC 301 #ifdef IPSEC_POLICY_IPSEC 302 static int setpolicy(int so, char *policy); 303 #endif 304 #endif 305 static void send_probe(int, u_long); 306 static void *get_uphdr(struct ip6_hdr *, u_char *); 307 static double deltaT(struct timeval *, struct timeval *); 308 static char *pr_type(int); 309 static int packet_ok(struct msghdr *, int, int); 310 static void print(struct msghdr *, int); 311 static const char *inetname(struct sockaddr *); 312 static void usage(void) __dead2; 313 314 static int rcvsock; /* receive (icmp) socket file descriptor */ 315 static int sndsock; /* send (udp) socket file descriptor */ 316 317 static struct msghdr rcvmhdr; 318 static struct iovec rcviov[2]; 319 static int rcvhlim; 320 static struct in6_pktinfo *rcvpktinfo; 321 322 static struct sockaddr_in6 Src, Dst, Rcv; 323 static u_long datalen; /* How much data */ 324 #define ICMP6ECHOLEN 8 325 326 static char *source = NULL; 327 static char *hostname; 328 329 static u_long nprobes = 3; 330 static u_long first_hop = 1; 331 static u_long max_hops = 30; 332 static u_int16_t srcport; 333 static u_int16_t port = 32768+666; /* start udp dest port # for probe packets */ 334 static u_int16_t ident; 335 static int options; /* socket options */ 336 static int verbose; 337 static int waittime = 5; /* time to wait for response (in seconds) */ 338 static int nflag; /* print addresses numerically */ 339 static int useproto = IPPROTO_UDP; /* protocol to use to send packet */ 340 static int lflag; /* print both numerical address & hostname */ 341 342 int 343 main(int argc, char **argv) 344 { 345 int mib[4] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_DEFHLIM }; 346 char hbuf[NI_MAXHOST], src0[NI_MAXHOST], *ep; 347 int ch, i, on = 1, seq, rcvcmsglen, error, minlen; 348 struct addrinfo hints, *res; 349 static u_char *rcvcmsgbuf; 350 u_long probe, hops, lport; 351 struct hostent *hp; 352 size_t size; 353 uid_t uid; 354 355 /* 356 * Receive ICMP 357 */ 358 if ((rcvsock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) { 359 perror("socket(ICMPv6)"); 360 exit(5); 361 } 362 363 size = sizeof(i); 364 (void) sysctl(mib, sizeof(mib)/sizeof(mib[0]), &i, &size, NULL, 0); 365 max_hops = i; 366 367 /* specify to tell receiving interface */ 368 #ifdef IPV6_RECVPKTINFO 369 if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, 370 sizeof(on)) < 0) 371 err(1, "setsockopt(IPV6_RECVPKTINFO)"); 372 #else /* old adv. API */ 373 if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_PKTINFO, &on, 374 sizeof(on)) < 0) 375 err(1, "setsockopt(IPV6_PKTINFO)"); 376 #endif 377 378 /* specify to tell value of hoplimit field of received IP6 hdr */ 379 #ifdef IPV6_RECVHOPLIMIT 380 if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, 381 sizeof(on)) < 0) 382 err(1, "setsockopt(IPV6_RECVHOPLIMIT)"); 383 #else /* old adv. API */ 384 if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_HOPLIMIT, &on, 385 sizeof(on)) < 0) 386 err(1, "setsockopt(IPV6_HOPLIMIT)"); 387 #endif 388 389 seq = 0; 390 391 while ((ch = getopt(argc, argv, "df:g:Ilm:nNp:q:rs:Uvw:")) != -1) 392 switch (ch) { 393 case 'd': 394 options |= SO_DEBUG; 395 break; 396 case 'f': 397 ep = NULL; 398 errno = 0; 399 first_hop = strtoul(optarg, &ep, 0); 400 if (errno || !*optarg || *ep || first_hop > 255) { 401 fprintf(stderr, 402 "traceroute6: invalid min hoplimit.\n"); 403 exit(1); 404 } 405 break; 406 case 'g': 407 hp = getipnodebyname(optarg, AF_INET6, 0, &h_errno); 408 if (hp == NULL) { 409 fprintf(stderr, 410 "traceroute6: unknown host %s\n", optarg); 411 exit(1); 412 } 413 freehostent(hp); 414 break; 415 case 'I': 416 useproto = IPPROTO_ICMPV6; 417 ident = htons(getpid() & 0xffff); /* same as ping6 */ 418 break; 419 case 'l': 420 lflag++; 421 break; 422 case 'm': 423 ep = NULL; 424 errno = 0; 425 max_hops = strtoul(optarg, &ep, 0); 426 if (errno || !*optarg || *ep || max_hops > 255) { 427 fprintf(stderr, 428 "traceroute6: invalid max hoplimit.\n"); 429 exit(1); 430 } 431 break; 432 case 'n': 433 nflag++; 434 break; 435 case 'N': 436 useproto = IPPROTO_NONE; 437 break; 438 case 'p': 439 ep = NULL; 440 errno = 0; 441 lport = strtoul(optarg, &ep, 0); 442 if (errno || !*optarg || *ep) { 443 fprintf(stderr, "traceroute6: invalid port.\n"); 444 exit(1); 445 } 446 if (lport == 0 || lport != (lport & 0xffff)) { 447 fprintf(stderr, 448 "traceroute6: port out of range.\n"); 449 exit(1); 450 } 451 port = lport & 0xffff; 452 break; 453 case 'q': 454 ep = NULL; 455 errno = 0; 456 nprobes = strtoul(optarg, &ep, 0); 457 if (errno || !*optarg || *ep) { 458 fprintf(stderr, 459 "traceroute6: invalid nprobes.\n"); 460 exit(1); 461 } 462 if (nprobes < 1) { 463 fprintf(stderr, 464 "traceroute6: nprobes must be >0.\n"); 465 exit(1); 466 } 467 break; 468 case 'r': 469 options |= SO_DONTROUTE; 470 break; 471 case 's': 472 /* 473 * set the ip source address of the outbound 474 * probe (e.g., on a multi-homed host). 475 */ 476 source = optarg; 477 break; 478 case 'v': 479 verbose++; 480 break; 481 case 'U': 482 useproto = IPPROTO_UDP; 483 break; 484 case 'w': 485 ep = NULL; 486 errno = 0; 487 waittime = strtoul(optarg, &ep, 0); 488 if (errno || !*optarg || *ep) { 489 fprintf(stderr, 490 "traceroute6: invalid wait time.\n"); 491 exit(1); 492 } 493 if (waittime < 1) { 494 fprintf(stderr, 495 "traceroute6: wait must be >= 1 sec.\n"); 496 exit(1); 497 } 498 break; 499 default: 500 usage(); 501 } 502 argc -= optind; 503 argv += optind; 504 505 /* 506 * Open socket to send probe packets. 507 */ 508 switch (useproto) { 509 case IPPROTO_ICMPV6: 510 sndsock = rcvsock; 511 break; 512 case IPPROTO_UDP: 513 if ((sndsock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 514 perror("socket(SOCK_DGRAM)"); 515 exit(5); 516 } 517 break; 518 case IPPROTO_NONE: 519 if ((sndsock = socket(AF_INET6, SOCK_RAW, IPPROTO_NONE)) < 0) { 520 perror("socket(SOCK_RAW)"); 521 exit(5); 522 } 523 break; 524 default: 525 fprintf(stderr, "traceroute6: unknown probe protocol %d", 526 useproto); 527 exit(5); 528 } 529 if (max_hops < first_hop) { 530 fprintf(stderr, 531 "traceroute6: max hoplimit must be larger than first hoplimit.\n"); 532 exit(1); 533 } 534 535 /* revoke privs */ 536 uid = getuid(); 537 if (setresuid(uid, uid, uid) == -1) { 538 perror("setresuid"); 539 exit(1); 540 } 541 542 543 if (argc < 1 || argc > 2) 544 usage(); 545 546 #if 1 547 setvbuf(stdout, NULL, _IOLBF, BUFSIZ); 548 #else 549 setlinebuf(stdout); 550 #endif 551 552 memset(&hints, 0, sizeof(hints)); 553 hints.ai_family = PF_INET6; 554 hints.ai_socktype = SOCK_RAW; 555 hints.ai_protocol = IPPROTO_ICMPV6; 556 hints.ai_flags = AI_CANONNAME; 557 error = getaddrinfo(*argv, NULL, &hints, &res); 558 if (error) { 559 fprintf(stderr, 560 "traceroute6: %s\n", gai_strerror(error)); 561 exit(1); 562 } 563 if (res->ai_addrlen != sizeof(Dst)) { 564 fprintf(stderr, 565 "traceroute6: size of sockaddr mismatch\n"); 566 exit(1); 567 } 568 memcpy(&Dst, res->ai_addr, res->ai_addrlen); 569 hostname = res->ai_canonname ? strdup(res->ai_canonname) : *argv; 570 if (!hostname) { 571 fprintf(stderr, "traceroute6: not enough core\n"); 572 exit(1); 573 } 574 if (res->ai_next) { 575 if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, 576 sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) 577 strlcpy(hbuf, "?", sizeof(hbuf)); 578 fprintf(stderr, "traceroute6: Warning: %s has multiple " 579 "addresses; using %s\n", hostname, hbuf); 580 } 581 582 if (*++argv) { 583 ep = NULL; 584 errno = 0; 585 datalen = strtoul(*argv, &ep, 0); 586 if (errno || !*argv || *ep) { 587 fprintf(stderr, 588 "traceroute6: invalid packet length.\n"); 589 exit(1); 590 } 591 } 592 switch (useproto) { 593 case IPPROTO_ICMPV6: 594 minlen = ICMP6ECHOLEN + sizeof(struct tv32); 595 break; 596 case IPPROTO_UDP: 597 minlen = sizeof(struct opacket); 598 break; 599 case IPPROTO_NONE: 600 minlen = 0; 601 datalen = 0; 602 break; 603 default: 604 fprintf(stderr, "traceroute6: unknown probe protocol %d.\n", 605 useproto); 606 exit(1); 607 } 608 if (datalen < minlen) 609 datalen = minlen; 610 else if (datalen >= MAXPACKET) { 611 fprintf(stderr, 612 "traceroute6: packet size must be %d <= s < %ld.\n", 613 minlen, (long)MAXPACKET); 614 exit(1); 615 } 616 outpacket = (struct opacket *)malloc((unsigned)datalen); 617 if (!outpacket) { 618 perror("malloc"); 619 exit(1); 620 } 621 (void) bzero((char *)outpacket, datalen); 622 623 /* initialize msghdr for receiving packets */ 624 rcviov[0].iov_base = (caddr_t)packet; 625 rcviov[0].iov_len = sizeof(packet); 626 rcvmhdr.msg_name = (caddr_t)&Rcv; 627 rcvmhdr.msg_namelen = sizeof(Rcv); 628 rcvmhdr.msg_iov = rcviov; 629 rcvmhdr.msg_iovlen = 1; 630 rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + 631 CMSG_SPACE(sizeof(int)); 632 if ((rcvcmsgbuf = malloc(rcvcmsglen)) == NULL) { 633 fprintf(stderr, "traceroute6: malloc failed\n"); 634 exit(1); 635 } 636 rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf; 637 rcvmhdr.msg_controllen = rcvcmsglen; 638 639 if (options & SO_DEBUG) 640 (void) setsockopt(rcvsock, SOL_SOCKET, SO_DEBUG, 641 (char *)&on, sizeof(on)); 642 if (options & SO_DONTROUTE) 643 (void) setsockopt(rcvsock, SOL_SOCKET, SO_DONTROUTE, 644 (char *)&on, sizeof(on)); 645 #ifdef IPSEC 646 #ifdef IPSEC_POLICY_IPSEC 647 /* 648 * do not raise error even if setsockopt fails, kernel may have ipsec 649 * turned off. 650 */ 651 if (setpolicy(rcvsock, "in bypass") < 0) 652 errx(1, "%s", ipsec_strerror()); 653 if (setpolicy(rcvsock, "out bypass") < 0) 654 errx(1, "%s", ipsec_strerror()); 655 #else 656 { 657 int level = IPSEC_LEVEL_NONE; 658 659 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, &level, 660 sizeof(level)); 661 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_ESP_NETWORK_LEVEL, &level, 662 sizeof(level)); 663 #ifdef IP_AUTH_TRANS_LEVEL 664 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, &level, 665 sizeof(level)); 666 #else 667 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_LEVEL, &level, 668 sizeof(level)); 669 #endif 670 #ifdef IP_AUTH_NETWORK_LEVEL 671 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_NETWORK_LEVEL, &level, 672 sizeof(level)); 673 #endif 674 } 675 #endif /*IPSEC_POLICY_IPSEC*/ 676 #endif /*IPSEC*/ 677 678 #ifdef SO_SNDBUF 679 i = datalen; 680 if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&i, 681 sizeof(i)) < 0 && useproto != IPPROTO_NONE) { 682 perror("setsockopt(SO_SNDBUF)"); 683 exit(6); 684 } 685 #endif /* SO_SNDBUF */ 686 if (options & SO_DEBUG) 687 (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, 688 (char *)&on, sizeof(on)); 689 if (options & SO_DONTROUTE) 690 (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, 691 (char *)&on, sizeof(on)); 692 #ifdef IPSEC 693 #ifdef IPSEC_POLICY_IPSEC 694 /* 695 * do not raise error even if setsockopt fails, kernel may have ipsec 696 * turned off. 697 */ 698 if (setpolicy(sndsock, "in bypass") < 0) 699 errx(1, "%s", ipsec_strerror()); 700 if (setpolicy(sndsock, "out bypass") < 0) 701 errx(1, "%s", ipsec_strerror()); 702 #else 703 { 704 int level = IPSEC_LEVEL_BYPASS; 705 706 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, &level, 707 sizeof(level)); 708 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_ESP_NETWORK_LEVEL, &level, 709 sizeof(level)); 710 #ifdef IP_AUTH_TRANS_LEVEL 711 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, &level, 712 sizeof(level)); 713 #else 714 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_LEVEL, &level, 715 sizeof(level)); 716 #endif 717 #ifdef IP_AUTH_NETWORK_LEVEL 718 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_NETWORK_LEVEL, &level, 719 sizeof(level)); 720 #endif 721 } 722 #endif /*IPSEC_POLICY_IPSEC*/ 723 #endif /*IPSEC*/ 724 725 /* 726 * Source selection 727 */ 728 bzero(&Src, sizeof(Src)); 729 if (source) { 730 struct addrinfo hints, *res; 731 int error; 732 733 memset(&hints, 0, sizeof(hints)); 734 hints.ai_family = AF_INET6; 735 hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 736 hints.ai_flags = AI_NUMERICHOST; 737 error = getaddrinfo(source, "0", &hints, &res); 738 if (error) { 739 printf("traceroute6: %s: %s\n", source, 740 gai_strerror(error)); 741 exit(1); 742 } 743 if (res->ai_addrlen > sizeof(Src)) { 744 printf("traceroute6: %s: %s\n", source, 745 gai_strerror(error)); 746 exit(1); 747 } 748 memcpy(&Src, res->ai_addr, res->ai_addrlen); 749 freeaddrinfo(res); 750 } else { 751 struct sockaddr_in6 Nxt; 752 int dummy; 753 socklen_t len; 754 755 Nxt = Dst; 756 Nxt.sin6_port = htons(DUMMY_PORT); 757 if ((dummy = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 758 perror("socket"); 759 exit(1); 760 } 761 if (connect(dummy, (struct sockaddr *)&Nxt, Nxt.sin6_len) < 0) { 762 perror("connect"); 763 exit(1); 764 } 765 len = sizeof(Src); 766 if (getsockname(dummy, (struct sockaddr *)&Src, &len) < 0) { 767 perror("getsockname"); 768 exit(1); 769 } 770 if (getnameinfo((struct sockaddr *)&Src, Src.sin6_len, 771 src0, sizeof(src0), NULL, 0, NI_NUMERICHOST)) { 772 fprintf(stderr, "getnameinfo failed for source\n"); 773 exit(1); 774 } 775 source = src0; 776 close(dummy); 777 } 778 779 Src.sin6_port = htons(0); 780 if (bind(sndsock, (struct sockaddr *)&Src, Src.sin6_len) < 0) { 781 perror("bind"); 782 exit(1); 783 } 784 785 { 786 socklen_t len; 787 788 len = sizeof(Src); 789 if (getsockname(sndsock, (struct sockaddr *)&Src, &len) < 0) { 790 perror("getsockname"); 791 exit(1); 792 } 793 srcport = ntohs(Src.sin6_port); 794 } 795 796 /* 797 * Message to users 798 */ 799 if (getnameinfo((struct sockaddr *)&Dst, Dst.sin6_len, hbuf, 800 sizeof(hbuf), NULL, 0, NI_NUMERICHOST)) 801 strlcpy(hbuf, "(invalid)", sizeof(hbuf)); 802 fprintf(stderr, "traceroute6"); 803 fprintf(stderr, " to %s (%s)", hostname, hbuf); 804 if (source) 805 fprintf(stderr, " from %s", source); 806 fprintf(stderr, ", %lu hops max, %lu byte packets\n", 807 max_hops, datalen); 808 (void) fflush(stderr); 809 810 if (first_hop > 1) 811 printf("Skipping %lu intermediate hops\n", first_hop - 1); 812 813 /* 814 * Main loop 815 */ 816 for (hops = first_hop; hops <= max_hops; ++hops) { 817 struct in6_addr lastaddr; 818 int got_there = 0; 819 int unreachable = 0; 820 821 printf("%2lu ", hops); 822 bzero(&lastaddr, sizeof(lastaddr)); 823 for (probe = 0; probe < nprobes; ++probe) { 824 int cc; 825 struct timeval t1, t2; 826 827 (void) gettimeofday(&t1, NULL); 828 send_probe(++seq, hops); 829 while ((cc = wait_for_reply(rcvsock, &rcvmhdr))) { 830 (void) gettimeofday(&t2, NULL); 831 if ((i = packet_ok(&rcvmhdr, cc, seq))) { 832 if (!IN6_ARE_ADDR_EQUAL(&Rcv.sin6_addr, 833 &lastaddr)) { 834 if (probe > 0) 835 fputs("\n ", stdout); 836 print(&rcvmhdr, cc); 837 lastaddr = Rcv.sin6_addr; 838 } 839 printf(" %.3f ms", deltaT(&t1, &t2)); 840 switch (i - 1) { 841 case ICMP6_DST_UNREACH_NOROUTE: 842 ++unreachable; 843 printf(" !N"); 844 break; 845 case ICMP6_DST_UNREACH_ADMIN: 846 ++unreachable; 847 printf(" !P"); 848 break; 849 case ICMP6_DST_UNREACH_NOTNEIGHBOR: 850 ++unreachable; 851 printf(" !S"); 852 break; 853 case ICMP6_DST_UNREACH_ADDR: 854 ++unreachable; 855 printf(" !A"); 856 break; 857 case ICMP6_DST_UNREACH_NOPORT: 858 if (rcvhlim >= 0 && 859 rcvhlim <= 1) 860 printf(" !"); 861 ++got_there; 862 break; 863 } 864 break; 865 } 866 } 867 if (cc == 0) 868 printf(" *"); 869 (void) fflush(stdout); 870 } 871 putchar('\n'); 872 if (got_there || 873 (unreachable > 0 && unreachable >= ((nprobes + 1) / 2))) { 874 exit(0); 875 } 876 } 877 878 exit(0); 879 } 880 881 static int 882 wait_for_reply(int sock, struct msghdr *mhdr) 883 { 884 #ifdef HAVE_POLL 885 struct pollfd pfd[1]; 886 int cc = 0; 887 888 pfd[0].fd = sock; 889 pfd[0].events = POLLIN; 890 pfd[0].revents = 0; 891 892 if (poll(pfd, 1, waittime * 1000) > 0) 893 cc = recvmsg(rcvsock, mhdr, 0); 894 895 return(cc); 896 #else 897 fd_set *fdsp; 898 struct timeval wait; 899 int cc = 0, fdsn; 900 901 fdsn = howmany(sock + 1, NFDBITS) * sizeof(fd_mask); 902 if ((fdsp = (fd_set *)malloc(fdsn)) == NULL) 903 err(1, "malloc"); 904 memset(fdsp, 0, fdsn); 905 FD_SET(sock, fdsp); 906 wait.tv_sec = waittime; wait.tv_usec = 0; 907 908 if (select(sock+1, fdsp, NULL, NULL, &wait) > 0) 909 cc = recvmsg(rcvsock, mhdr, 0); 910 911 free(fdsp); 912 return(cc); 913 #endif 914 } 915 916 #ifdef IPSEC 917 #ifdef IPSEC_POLICY_IPSEC 918 static int 919 setpolicy(int so, char *policy) 920 { 921 char *buf; 922 923 buf = ipsec_set_policy(policy, strlen(policy)); 924 if (buf == NULL) { 925 warnx("%s", ipsec_strerror()); 926 return -1; 927 } 928 (void)setsockopt(so, IPPROTO_IPV6, IPV6_IPSEC_POLICY, 929 buf, ipsec_get_policylen(buf)); 930 931 free(buf); 932 933 return 0; 934 } 935 #endif 936 #endif 937 938 static void 939 send_probe(int seq, u_long hops) 940 { 941 struct icmp6_hdr *icp; 942 struct opacket *op; 943 struct timeval tv; 944 struct tv32 tv32; 945 int i; 946 947 i = hops; 948 if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 949 (char *)&i, sizeof(i)) < 0) { 950 perror("setsockopt IPV6_UNICAST_HOPS"); 951 } 952 953 Dst.sin6_port = htons(port + seq); 954 (void) gettimeofday(&tv, NULL); 955 tv32.tv32_sec = htonl(tv.tv_sec); 956 tv32.tv32_usec = htonl(tv.tv_usec); 957 958 switch (useproto) { 959 case IPPROTO_ICMPV6: 960 icp = (struct icmp6_hdr *)outpacket; 961 962 icp->icmp6_type = ICMP6_ECHO_REQUEST; 963 icp->icmp6_code = 0; 964 icp->icmp6_cksum = 0; 965 icp->icmp6_id = ident; 966 icp->icmp6_seq = htons(seq); 967 bcopy(&tv32, ((u_int8_t *)outpacket + ICMP6ECHOLEN), 968 sizeof(tv32)); 969 break; 970 case IPPROTO_UDP: 971 op = outpacket; 972 973 op->seq = seq; 974 op->hops = hops; 975 bcopy(&tv32, &op->tv, sizeof tv32); 976 break; 977 case IPPROTO_NONE: 978 /* No space for anything. No harm as seq/tv32 are decorative. */ 979 break; 980 default: 981 fprintf(stderr, "Unknown probe protocol %d.\n", useproto); 982 exit(1); 983 } 984 985 i = sendto(sndsock, (char *)outpacket, datalen, 0, 986 (struct sockaddr *)&Dst, Dst.sin6_len); 987 if (i < 0 || i != datalen) { 988 if (i < 0) 989 perror("sendto"); 990 printf("traceroute6: wrote %s %lu chars, ret=%d\n", 991 hostname, datalen, i); 992 (void) fflush(stdout); 993 } 994 } 995 996 static double 997 deltaT(struct timeval *t1p, struct timeval *t2p) 998 { 999 double dt; 1000 1001 dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 + 1002 (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0; 1003 return (dt); 1004 } 1005 1006 /* 1007 * Convert an ICMP "type" field to a printable string. 1008 */ 1009 static char * 1010 pr_type(int t0) 1011 { 1012 u_char t = t0 & 0xff; 1013 char *cp; 1014 1015 switch (t) { 1016 case ICMP6_DST_UNREACH: 1017 cp = "Destination Unreachable"; 1018 break; 1019 case ICMP6_PACKET_TOO_BIG: 1020 cp = "Packet Too Big"; 1021 break; 1022 case ICMP6_TIME_EXCEEDED: 1023 cp = "Time Exceeded"; 1024 break; 1025 case ICMP6_PARAM_PROB: 1026 cp = "Parameter Problem"; 1027 break; 1028 case ICMP6_ECHO_REQUEST: 1029 cp = "Echo Request"; 1030 break; 1031 case ICMP6_ECHO_REPLY: 1032 cp = "Echo Reply"; 1033 break; 1034 case ICMP6_MEMBERSHIP_QUERY: 1035 cp = "Group Membership Query"; 1036 break; 1037 case ICMP6_MEMBERSHIP_REPORT: 1038 cp = "Group Membership Report"; 1039 break; 1040 case ICMP6_MEMBERSHIP_REDUCTION: 1041 cp = "Group Membership Reduction"; 1042 break; 1043 case ND_ROUTER_SOLICIT: 1044 cp = "Router Solicitation"; 1045 break; 1046 case ND_ROUTER_ADVERT: 1047 cp = "Router Advertisement"; 1048 break; 1049 case ND_NEIGHBOR_SOLICIT: 1050 cp = "Neighbor Solicitation"; 1051 break; 1052 case ND_NEIGHBOR_ADVERT: 1053 cp = "Neighbor Advertisement"; 1054 break; 1055 case ND_REDIRECT: 1056 cp = "Redirect"; 1057 break; 1058 default: 1059 cp = "Unknown"; 1060 break; 1061 } 1062 return cp; 1063 } 1064 1065 static int 1066 packet_ok(struct msghdr *mhdr, int cc, int seq) 1067 { 1068 struct icmp6_hdr *icp; 1069 struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name; 1070 u_char type, code; 1071 char *buf = (char *)mhdr->msg_iov[0].iov_base; 1072 struct cmsghdr *cm; 1073 int *hlimp; 1074 char hbuf[NI_MAXHOST]; 1075 1076 #ifdef OLDRAWSOCKET 1077 int hlen; 1078 struct ip6_hdr *ip; 1079 #endif 1080 1081 #ifdef OLDRAWSOCKET 1082 ip = (struct ip6_hdr *) buf; 1083 hlen = sizeof(struct ip6_hdr); 1084 if (cc < hlen + sizeof(struct icmp6_hdr)) { 1085 if (verbose) { 1086 if (getnameinfo((struct sockaddr *)from, from->sin6_len, 1087 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) 1088 strlcpy(hbuf, "invalid", sizeof(hbuf)); 1089 printf("packet too short (%d bytes) from %s\n", cc, 1090 hbuf); 1091 } 1092 return (0); 1093 } 1094 cc -= hlen; 1095 icp = (struct icmp6_hdr *)(buf + hlen); 1096 #else 1097 if (cc < sizeof(struct icmp6_hdr)) { 1098 if (verbose) { 1099 if (getnameinfo((struct sockaddr *)from, from->sin6_len, 1100 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) 1101 strlcpy(hbuf, "invalid", sizeof(hbuf)); 1102 printf("data too short (%d bytes) from %s\n", cc, hbuf); 1103 } 1104 return(0); 1105 } 1106 icp = (struct icmp6_hdr *)buf; 1107 #endif 1108 /* get optional information via advanced API */ 1109 rcvpktinfo = NULL; 1110 hlimp = NULL; 1111 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; 1112 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { 1113 if (cm->cmsg_level == IPPROTO_IPV6 && 1114 cm->cmsg_type == IPV6_PKTINFO && 1115 cm->cmsg_len == 1116 CMSG_LEN(sizeof(struct in6_pktinfo))) 1117 rcvpktinfo = (struct in6_pktinfo *)(CMSG_DATA(cm)); 1118 1119 if (cm->cmsg_level == IPPROTO_IPV6 && 1120 cm->cmsg_type == IPV6_HOPLIMIT && 1121 cm->cmsg_len == CMSG_LEN(sizeof(int))) 1122 hlimp = (int *)CMSG_DATA(cm); 1123 } 1124 if (rcvpktinfo == NULL || hlimp == NULL) { 1125 warnx("failed to get received hop limit or packet info"); 1126 #if 0 1127 return(0); 1128 #else 1129 rcvhlim = 0; /*XXX*/ 1130 #endif 1131 } 1132 else 1133 rcvhlim = *hlimp; 1134 1135 type = icp->icmp6_type; 1136 code = icp->icmp6_code; 1137 if ((type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT) 1138 || type == ICMP6_DST_UNREACH) { 1139 struct ip6_hdr *hip; 1140 void *up; 1141 1142 hip = (struct ip6_hdr *)(icp + 1); 1143 if ((up = get_uphdr(hip, (u_char *)(buf + cc))) == NULL) { 1144 if (verbose) 1145 warnx("failed to get upper layer header"); 1146 return(0); 1147 } 1148 switch (useproto) { 1149 case IPPROTO_ICMPV6: 1150 if (((struct icmp6_hdr *)up)->icmp6_id == ident && 1151 ((struct icmp6_hdr *)up)->icmp6_seq == htons(seq)) 1152 return (type == ICMP6_TIME_EXCEEDED ? 1153 -1 : code + 1); 1154 break; 1155 case IPPROTO_UDP: 1156 if (((struct udphdr *)up)->uh_sport == htons(srcport) && 1157 ((struct udphdr *)up)->uh_dport == htons(port + seq)) 1158 return (type == ICMP6_TIME_EXCEEDED ? 1159 -1 : code + 1); 1160 break; 1161 case IPPROTO_NONE: 1162 return (type == ICMP6_TIME_EXCEEDED ? -1 : code + 1); 1163 default: 1164 fprintf(stderr, "Unknown probe proto %d.\n", useproto); 1165 break; 1166 } 1167 } else if (useproto == IPPROTO_ICMPV6 && type == ICMP6_ECHO_REPLY) { 1168 if (icp->icmp6_id == ident && 1169 icp->icmp6_seq == htons(seq)) 1170 return (ICMP6_DST_UNREACH_NOPORT + 1); 1171 } 1172 if (verbose) { 1173 char sbuf[NI_MAXHOST+1], dbuf[INET6_ADDRSTRLEN]; 1174 u_int8_t *p; 1175 int i; 1176 1177 if (getnameinfo((struct sockaddr *)from, from->sin6_len, 1178 sbuf, sizeof(sbuf), NULL, 0, NI_NUMERICHOST) != 0) 1179 strlcpy(sbuf, "invalid", sizeof(sbuf)); 1180 printf("\n%d bytes from %s to %s", cc, sbuf, 1181 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr, 1182 dbuf, sizeof(dbuf)) : "?"); 1183 printf(": icmp type %d (%s) code %d\n", type, pr_type(type), 1184 icp->icmp6_code); 1185 p = (u_int8_t *)(icp + 1); 1186 #define WIDTH 16 1187 for (i = 0; i < cc; i++) { 1188 if (i % WIDTH == 0) 1189 printf("%04x:", i); 1190 if (i % 4 == 0) 1191 printf(" "); 1192 printf("%02x", p[i]); 1193 if (i % WIDTH == WIDTH - 1) 1194 printf("\n"); 1195 } 1196 if (cc % WIDTH != 0) 1197 printf("\n"); 1198 } 1199 return(0); 1200 } 1201 1202 /* 1203 * Increment pointer until find the UDP or ICMP header. 1204 */ 1205 static void * 1206 get_uphdr(struct ip6_hdr *ip6, u_char *lim) 1207 { 1208 u_char *cp = (u_char *)ip6, nh; 1209 int hlen; 1210 static u_char none_hdr[1]; /* Fake pointer for IPPROTO_NONE. */ 1211 1212 if (cp + sizeof(*ip6) > lim) 1213 return(NULL); 1214 1215 nh = ip6->ip6_nxt; 1216 cp += sizeof(struct ip6_hdr); 1217 1218 while (lim - cp >= (nh == IPPROTO_NONE ? 0 : 8)) { 1219 switch (nh) { 1220 case IPPROTO_ESP: 1221 case IPPROTO_TCP: 1222 return(NULL); 1223 case IPPROTO_ICMPV6: 1224 return(useproto == nh ? cp : NULL); 1225 case IPPROTO_UDP: 1226 return(useproto == nh ? cp : NULL); 1227 case IPPROTO_NONE: 1228 return(useproto == nh ? none_hdr : NULL); 1229 case IPPROTO_FRAGMENT: 1230 hlen = sizeof(struct ip6_frag); 1231 nh = ((struct ip6_frag *)cp)->ip6f_nxt; 1232 break; 1233 case IPPROTO_AH: 1234 hlen = (((struct ip6_ext *)cp)->ip6e_len + 2) << 2; 1235 nh = ((struct ip6_ext *)cp)->ip6e_nxt; 1236 break; 1237 default: 1238 hlen = (((struct ip6_ext *)cp)->ip6e_len + 1) << 3; 1239 nh = ((struct ip6_ext *)cp)->ip6e_nxt; 1240 break; 1241 } 1242 1243 cp += hlen; 1244 } 1245 1246 return(NULL); 1247 } 1248 1249 static void 1250 print(struct msghdr *mhdr, int cc) 1251 { 1252 struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name; 1253 char hbuf[NI_MAXHOST]; 1254 1255 if (getnameinfo((struct sockaddr *)from, from->sin6_len, 1256 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) 1257 strlcpy(hbuf, "invalid", sizeof(hbuf)); 1258 if (nflag) 1259 printf(" %s", hbuf); 1260 else if (lflag) 1261 printf(" %s (%s)", inetname((struct sockaddr *)from), hbuf); 1262 else 1263 printf(" %s", inetname((struct sockaddr *)from)); 1264 1265 if (verbose) { 1266 #ifdef OLDRAWSOCKET 1267 printf(" %d bytes to %s", cc, 1268 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr, 1269 hbuf, sizeof(hbuf)) : "?"); 1270 #else 1271 printf(" %d bytes of data to %s", cc, 1272 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr, 1273 hbuf, sizeof(hbuf)) : "?"); 1274 #endif 1275 } 1276 } 1277 1278 /* 1279 * Construct an Internet address representation. 1280 * If the nflag has been supplied, give 1281 * numeric value, otherwise try for symbolic name. 1282 */ 1283 static const char * 1284 inetname(struct sockaddr *sa) 1285 { 1286 static char line[NI_MAXHOST], domain[MAXHOSTNAMELEN + 1]; 1287 static int first = 1; 1288 char *cp; 1289 1290 if (first && !nflag) { 1291 first = 0; 1292 if (gethostname(domain, sizeof(domain)) == 0 && 1293 (cp = strchr(domain, '.'))) 1294 (void) strlcpy(domain, cp + 1, sizeof(domain)); 1295 else 1296 domain[0] = 0; 1297 } 1298 cp = NULL; 1299 if (!nflag) { 1300 if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0, 1301 NI_NAMEREQD) == 0) { 1302 if ((cp = strchr(line, '.')) && 1303 !strcmp(cp + 1, domain)) 1304 *cp = 0; 1305 cp = line; 1306 } 1307 } 1308 if (cp) 1309 return cp; 1310 1311 if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0, 1312 NI_NUMERICHOST) != 0) 1313 strlcpy(line, "invalid", sizeof(line)); 1314 return line; 1315 } 1316 1317 static void 1318 usage(void) 1319 { 1320 1321 fprintf(stderr, 1322 "usage: traceroute6 [-dIlnNrUv] [-f firsthop] [-g gateway] [-m hoplimit]\n" 1323 " [-p port] [-q probes] [-s src] [-w waittime] target [datalen]\n"); 1324 exit(1); 1325 } 1326