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 360709 2020-05-06 22:13:08Z 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/sctp.h> 275#include <netinet/sctp_header.h> 276#include <netinet/tcp.h> 277#include <netinet/udp.h> 278 279#ifdef IPSEC 280#include <net/route.h> 281#include <netipsec/ipsec.h> 282#endif 283 284#include "as.h" 285 286#define DUMMY_PORT 10010 287 288#define MAXPACKET 65535 /* max ip packet size */ 289 290#ifndef HAVE_GETIPNODEBYNAME 291#define getipnodebyname(x, y, z, u) gethostbyname2((x), (y)) 292#define freehostent(x) 293#endif 294 295u_char packet[512]; /* last inbound (icmp) packet */ 296char *outpacket; /* last output packet */ 297 298int main(int, char *[]); 299int wait_for_reply(int, struct msghdr *); 300#ifdef IPSEC 301#ifdef IPSEC_POLICY_IPSEC 302int setpolicy(int so, char *policy); 303#endif 304#endif 305void send_probe(int, u_long); 306void *get_uphdr(struct ip6_hdr *, u_char *); 307int get_hoplim(struct msghdr *); 308double deltaT(struct timeval *, struct timeval *); 309const char *pr_type(int); 310int packet_ok(struct msghdr *, int, int, u_char *, u_char *); 311void print(struct msghdr *, int); 312const char *inetname(struct sockaddr *); 313u_int32_t sctp_crc32c(void *, u_int32_t); 314u_int16_t in_cksum(u_int16_t *addr, int); 315u_int16_t tcp_chksum(struct sockaddr_in6 *, struct sockaddr_in6 *, 316 void *, u_int32_t); 317void usage(void); 318 319int rcvsock; /* receive (icmp) socket file descriptor */ 320int sndsock; /* send (raw/udp) socket file descriptor */ 321 322struct msghdr rcvmhdr; 323struct iovec rcviov[2]; 324int rcvhlim; 325struct in6_pktinfo *rcvpktinfo; 326 327struct sockaddr_in6 Src, Dst, Rcv; 328u_long datalen = 20; /* How much data */ 329#define ICMP6ECHOLEN 8 330/* XXX: 2064 = 127(max hops in type 0 rthdr) * sizeof(ip6_hdr) + 16(margin) */ 331char rtbuf[2064]; 332#ifdef USE_RFC2292BIS 333struct ip6_rthdr *rth; 334#endif 335struct cmsghdr *cmsg; 336 337char *source = NULL; 338char *hostname; 339 340u_long nprobes = 3; 341u_long first_hop = 1; 342u_long max_hops = 30; 343u_int16_t srcport; 344u_int16_t port = 32768+666; /* start udp dest port # for probe packets */ 345u_int16_t ident; 346int options; /* socket options */ 347int verbose; 348int waittime = 5; /* time to wait for response (in seconds) */ 349int nflag; /* print addresses numerically */ 350int useproto = IPPROTO_UDP; /* protocol to use to send packet */ 351int lflag; /* print both numerical address & hostname */ 352int as_path; /* print as numbers for each hop */ 353char *as_server = NULL; 354void *asn; 355 356int 357main(int argc, char *argv[]) 358{ 359 int mib[4] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_DEFHLIM }; 360 char hbuf[NI_MAXHOST], src0[NI_MAXHOST], *ep; 361 int ch, i, on = 1, seq, rcvcmsglen, error; 362 struct addrinfo hints, *res; 363 static u_char *rcvcmsgbuf; 364 u_long probe, hops, lport; 365 struct hostent *hp; 366 size_t size, minlen; 367 uid_t uid; 368 u_char type, code; 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 if ((useproto == IPPROTO_SCTP) && (datalen & 3)) { 682 fprintf(stderr, 683 "traceroute6: packet size must be a multiple of 4.\n"); 684 exit(1); 685 } 686 outpacket = malloc(datalen); 687 if (!outpacket) { 688 perror("malloc"); 689 exit(1); 690 } 691 (void) bzero((char *)outpacket, datalen); 692 693 /* initialize msghdr for receiving packets */ 694 rcviov[0].iov_base = (caddr_t)packet; 695 rcviov[0].iov_len = sizeof(packet); 696 rcvmhdr.msg_name = (caddr_t)&Rcv; 697 rcvmhdr.msg_namelen = sizeof(Rcv); 698 rcvmhdr.msg_iov = rcviov; 699 rcvmhdr.msg_iovlen = 1; 700 rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + 701 CMSG_SPACE(sizeof(int)); 702 if ((rcvcmsgbuf = malloc(rcvcmsglen)) == NULL) { 703 fprintf(stderr, "traceroute6: malloc failed\n"); 704 exit(1); 705 } 706 rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf; 707 rcvmhdr.msg_controllen = rcvcmsglen; 708 709 if (options & SO_DEBUG) 710 (void) setsockopt(rcvsock, SOL_SOCKET, SO_DEBUG, 711 (char *)&on, sizeof(on)); 712 if (options & SO_DONTROUTE) 713 (void) setsockopt(rcvsock, SOL_SOCKET, SO_DONTROUTE, 714 (char *)&on, sizeof(on)); 715#ifdef IPSEC 716#ifdef IPSEC_POLICY_IPSEC 717 /* 718 * do not raise error even if setsockopt fails, kernel may have ipsec 719 * turned off. 720 */ 721 if (setpolicy(rcvsock, "in bypass") < 0) 722 errx(1, "%s", ipsec_strerror()); 723 if (setpolicy(rcvsock, "out bypass") < 0) 724 errx(1, "%s", ipsec_strerror()); 725#else 726 { 727 int level = IPSEC_LEVEL_NONE; 728 729 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, &level, 730 sizeof(level)); 731 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_ESP_NETWORK_LEVEL, &level, 732 sizeof(level)); 733#ifdef IP_AUTH_TRANS_LEVEL 734 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, &level, 735 sizeof(level)); 736#else 737 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_LEVEL, &level, 738 sizeof(level)); 739#endif 740#ifdef IP_AUTH_NETWORK_LEVEL 741 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_NETWORK_LEVEL, &level, 742 sizeof(level)); 743#endif 744 } 745#endif /*IPSEC_POLICY_IPSEC*/ 746#endif /*IPSEC*/ 747 748#ifdef SO_SNDBUF 749 i = datalen; 750 if (i == 0) 751 i = 1; 752 if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&i, 753 sizeof(i)) < 0) { 754 perror("setsockopt(SO_SNDBUF)"); 755 exit(6); 756 } 757#endif /* SO_SNDBUF */ 758 if (options & SO_DEBUG) 759 (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, 760 (char *)&on, sizeof(on)); 761 if (options & SO_DONTROUTE) 762 (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, 763 (char *)&on, sizeof(on)); 764#ifdef USE_RFC2292BIS 765 if (rth) {/* XXX: there is no library to finalize the header... */ 766 rth->ip6r_len = rth->ip6r_segleft * 2; 767 if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_RTHDR, 768 (void *)rth, (rth->ip6r_len + 1) << 3)) { 769 fprintf(stderr, "setsockopt(IPV6_RTHDR): %s\n", 770 strerror(errno)); 771 exit(1); 772 } 773 } 774#else /* old advanced API */ 775 if (cmsg != NULL) { 776 inet6_rthdr_lasthop(cmsg, IPV6_RTHDR_LOOSE); 777 if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_PKTOPTIONS, 778 rtbuf, cmsg->cmsg_len) < 0) { 779 fprintf(stderr, "setsockopt(IPV6_PKTOPTIONS): %s\n", 780 strerror(errno)); 781 exit(1); 782 } 783 } 784#endif /* USE_RFC2292BIS */ 785#ifdef IPSEC 786#ifdef IPSEC_POLICY_IPSEC 787 /* 788 * do not raise error even if setsockopt fails, kernel may have ipsec 789 * turned off. 790 */ 791 if (setpolicy(sndsock, "in bypass") < 0) 792 errx(1, "%s", ipsec_strerror()); 793 if (setpolicy(sndsock, "out bypass") < 0) 794 errx(1, "%s", ipsec_strerror()); 795#else 796 { 797 int level = IPSEC_LEVEL_BYPASS; 798 799 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, &level, 800 sizeof(level)); 801 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_ESP_NETWORK_LEVEL, &level, 802 sizeof(level)); 803#ifdef IP_AUTH_TRANS_LEVEL 804 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, &level, 805 sizeof(level)); 806#else 807 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_LEVEL, &level, 808 sizeof(level)); 809#endif 810#ifdef IP_AUTH_NETWORK_LEVEL 811 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_NETWORK_LEVEL, &level, 812 sizeof(level)); 813#endif 814 } 815#endif /*IPSEC_POLICY_IPSEC*/ 816#endif /*IPSEC*/ 817 818 /* 819 * Source selection 820 */ 821 bzero(&Src, sizeof(Src)); 822 if (source) { 823 struct addrinfo hints, *res; 824 int error; 825 826 memset(&hints, 0, sizeof(hints)); 827 hints.ai_family = AF_INET6; 828 hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 829 hints.ai_flags = AI_NUMERICHOST; 830 error = getaddrinfo(source, "0", &hints, &res); 831 if (error) { 832 printf("traceroute6: %s: %s\n", source, 833 gai_strerror(error)); 834 exit(1); 835 } 836 if (res->ai_addrlen > sizeof(Src)) { 837 printf("traceroute6: %s: %s\n", source, 838 gai_strerror(error)); 839 exit(1); 840 } 841 memcpy(&Src, res->ai_addr, res->ai_addrlen); 842 freeaddrinfo(res); 843 } else { 844 struct sockaddr_in6 Nxt; 845 int dummy; 846 socklen_t len; 847 848 Nxt = Dst; 849 Nxt.sin6_port = htons(DUMMY_PORT); 850 if (cmsg != NULL) 851 bcopy(inet6_rthdr_getaddr(cmsg, 1), &Nxt.sin6_addr, 852 sizeof(Nxt.sin6_addr)); 853 if ((dummy = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 854 perror("socket"); 855 exit(1); 856 } 857 if (connect(dummy, (struct sockaddr *)&Nxt, Nxt.sin6_len) < 0) { 858 perror("connect"); 859 exit(1); 860 } 861 len = sizeof(Src); 862 if (getsockname(dummy, (struct sockaddr *)&Src, &len) < 0) { 863 perror("getsockname"); 864 exit(1); 865 } 866 if (getnameinfo((struct sockaddr *)&Src, Src.sin6_len, 867 src0, sizeof(src0), NULL, 0, NI_NUMERICHOST)) { 868 fprintf(stderr, "getnameinfo failed for source\n"); 869 exit(1); 870 } 871 source = src0; 872 close(dummy); 873 } 874 875 Src.sin6_port = htons(0); 876 if (bind(sndsock, (struct sockaddr *)&Src, Src.sin6_len) < 0) { 877 perror("bind"); 878 exit(1); 879 } 880 881 { 882 socklen_t len; 883 884 len = sizeof(Src); 885 if (getsockname(sndsock, (struct sockaddr *)&Src, &len) < 0) { 886 perror("getsockname"); 887 exit(1); 888 } 889 srcport = ntohs(Src.sin6_port); 890 } 891 892 if (as_path) { 893 asn = as_setup(as_server); 894 if (asn == NULL) { 895 fprintf(stderr, 896 "traceroute6: as_setup failed, AS# lookups" 897 " disabled\n"); 898 (void)fflush(stderr); 899 as_path = 0; 900 } 901 } 902 903 /* 904 * Message to users 905 */ 906 if (getnameinfo((struct sockaddr *)&Dst, Dst.sin6_len, hbuf, 907 sizeof(hbuf), NULL, 0, NI_NUMERICHOST)) 908 strlcpy(hbuf, "(invalid)", sizeof(hbuf)); 909 fprintf(stderr, "traceroute6"); 910 fprintf(stderr, " to %s (%s)", hostname, hbuf); 911 if (source) 912 fprintf(stderr, " from %s", source); 913 fprintf(stderr, ", %lu hops max, %lu byte packets\n", 914 max_hops, 915 datalen + ((useproto == IPPROTO_UDP) ? sizeof(struct udphdr) : 0)); 916 (void) fflush(stderr); 917 918 if (first_hop > 1) 919 printf("Skipping %lu intermediate hops\n", first_hop - 1); 920 921 /* 922 * Main loop 923 */ 924 for (hops = first_hop; hops <= max_hops; ++hops) { 925 struct in6_addr lastaddr; 926 int got_there = 0; 927 unsigned unreachable = 0; 928 929 printf("%2lu ", hops); 930 bzero(&lastaddr, sizeof(lastaddr)); 931 for (probe = 0; probe < nprobes; ++probe) { 932 int cc; 933 struct timeval t1, t2; 934 935 (void) gettimeofday(&t1, NULL); 936 send_probe(++seq, hops); 937 while ((cc = wait_for_reply(rcvsock, &rcvmhdr))) { 938 (void) gettimeofday(&t2, NULL); 939 if (packet_ok(&rcvmhdr, cc, seq, &type, &code)) { 940 if (!IN6_ARE_ADDR_EQUAL(&Rcv.sin6_addr, 941 &lastaddr)) { 942 if (probe > 0) 943 fputs("\n ", stdout); 944 print(&rcvmhdr, cc); 945 lastaddr = Rcv.sin6_addr; 946 } 947 printf(" %.3f ms", deltaT(&t1, &t2)); 948 if (type == ICMP6_DST_UNREACH) { 949 switch (code) { 950 case ICMP6_DST_UNREACH_NOROUTE: 951 ++unreachable; 952 printf(" !N"); 953 break; 954 case ICMP6_DST_UNREACH_ADMIN: 955 ++unreachable; 956 printf(" !P"); 957 break; 958 case ICMP6_DST_UNREACH_NOTNEIGHBOR: 959 ++unreachable; 960 printf(" !S"); 961 break; 962 case ICMP6_DST_UNREACH_ADDR: 963 ++unreachable; 964 printf(" !A"); 965 break; 966 case ICMP6_DST_UNREACH_NOPORT: 967 if (rcvhlim >= 0 && 968 rcvhlim <= 1) 969 printf(" !"); 970 ++got_there; 971 break; 972 } 973 } else if (type == ICMP6_PARAM_PROB && 974 code == ICMP6_PARAMPROB_NEXTHEADER) { 975 printf(" !H"); 976 ++got_there; 977 } else if (type == ICMP6_ECHO_REPLY) { 978 if (rcvhlim >= 0 && 979 rcvhlim <= 1) 980 printf(" !"); 981 ++got_there; 982 } 983 break; 984 } else if (deltaT(&t1, &t2) > waittime * 1000) { 985 cc = 0; 986 break; 987 } 988 } 989 if (cc == 0) 990 printf(" *"); 991 (void) fflush(stdout); 992 } 993 putchar('\n'); 994 if (got_there || 995 (unreachable > 0 && unreachable >= ((nprobes + 1) / 2))) { 996 exit(0); 997 } 998 } 999 if (as_path) 1000 as_shutdown(asn); 1001 1002 exit(0); 1003} 1004 1005int 1006wait_for_reply(int sock, struct msghdr *mhdr) 1007{ 1008#ifdef HAVE_POLL 1009 struct pollfd pfd[1]; 1010 int cc = 0; 1011 1012 pfd[0].fd = sock; 1013 pfd[0].events = POLLIN; 1014 pfd[0].revents = 0; 1015 1016 if (poll(pfd, 1, waittime * 1000) > 0) 1017 cc = recvmsg(rcvsock, mhdr, 0); 1018 1019 return (cc); 1020#else 1021 fd_set *fdsp; 1022 struct timeval wait; 1023 int cc = 0, fdsn; 1024 1025 fdsn = howmany(sock + 1, NFDBITS) * sizeof(fd_mask); 1026 if ((fdsp = (fd_set *)malloc(fdsn)) == NULL) 1027 err(1, "malloc"); 1028 memset(fdsp, 0, fdsn); 1029 FD_SET(sock, fdsp); 1030 wait.tv_sec = waittime; wait.tv_usec = 0; 1031 1032 if (select(sock+1, fdsp, (fd_set *)0, (fd_set *)0, &wait) > 0) 1033 cc = recvmsg(rcvsock, mhdr, 0); 1034 1035 free(fdsp); 1036 return (cc); 1037#endif 1038} 1039 1040#ifdef IPSEC 1041#ifdef IPSEC_POLICY_IPSEC 1042int 1043setpolicy(so, policy) 1044 int so; 1045 char *policy; 1046{ 1047 char *buf; 1048 1049 buf = ipsec_set_policy(policy, strlen(policy)); 1050 if (buf == NULL) { 1051 warnx("%s", ipsec_strerror()); 1052 return -1; 1053 } 1054 (void)setsockopt(so, IPPROTO_IPV6, IPV6_IPSEC_POLICY, 1055 buf, ipsec_get_policylen(buf)); 1056 1057 free(buf); 1058 1059 return 0; 1060} 1061#endif 1062#endif 1063 1064void 1065send_probe(int seq, u_long hops) 1066{ 1067 struct icmp6_hdr *icp; 1068 struct sctphdr *sctp; 1069 struct sctp_chunkhdr *chk; 1070 struct sctp_init_chunk *init; 1071 struct sctp_paramhdr *param; 1072 struct tcphdr *tcp; 1073 int i; 1074 1075 i = hops; 1076 if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 1077 (char *)&i, sizeof(i)) < 0) { 1078 perror("setsockopt IPV6_UNICAST_HOPS"); 1079 } 1080 1081 Dst.sin6_port = htons(port + seq); 1082 1083 switch (useproto) { 1084 case IPPROTO_ICMPV6: 1085 icp = (struct icmp6_hdr *)outpacket; 1086 1087 icp->icmp6_type = ICMP6_ECHO_REQUEST; 1088 icp->icmp6_code = 0; 1089 icp->icmp6_cksum = 0; 1090 icp->icmp6_id = ident; 1091 icp->icmp6_seq = htons(seq); 1092 break; 1093 case IPPROTO_UDP: 1094 break; 1095 case IPPROTO_NONE: 1096 /* No space for anything. No harm as seq/tv32 are decorative. */ 1097 break; 1098 case IPPROTO_SCTP: 1099 sctp = (struct sctphdr *)outpacket; 1100 1101 sctp->src_port = htons(ident); 1102 sctp->dest_port = htons(port + seq); 1103 if (datalen >= (u_long)(sizeof(struct sctphdr) + 1104 sizeof(struct sctp_init_chunk))) { 1105 sctp->v_tag = 0; 1106 } else { 1107 sctp->v_tag = (sctp->src_port << 16) | sctp->dest_port; 1108 } 1109 sctp->checksum = htonl(0); 1110 if (datalen >= (u_long)(sizeof(struct sctphdr) + 1111 sizeof(struct sctp_init_chunk))) { 1112 /* 1113 * Send a packet containing an INIT chunk. This works 1114 * better in case of firewalls on the path, but 1115 * results in a probe packet containing at least 1116 * 32 bytes of payload. For shorter payloads, use 1117 * SHUTDOWN-ACK chunks. 1118 */ 1119 init = (struct sctp_init_chunk *)(sctp + 1); 1120 init->ch.chunk_type = SCTP_INITIATION; 1121 init->ch.chunk_flags = 0; 1122 init->ch.chunk_length = htons((u_int16_t)(datalen - 1123 sizeof(struct sctphdr))); 1124 init->init.initiate_tag = (sctp->src_port << 16) | 1125 sctp->dest_port; 1126 init->init.a_rwnd = htonl(1500); 1127 init->init.num_outbound_streams = htons(1); 1128 init->init.num_inbound_streams = htons(1); 1129 init->init.initial_tsn = htonl(0); 1130 if (datalen >= (u_long)(sizeof(struct sctphdr) + 1131 sizeof(struct sctp_init_chunk) + 1132 sizeof(struct sctp_paramhdr))) { 1133 param = (struct sctp_paramhdr *)(init + 1); 1134 param->param_type = htons(SCTP_PAD); 1135 param->param_length = 1136 htons((u_int16_t)(datalen - 1137 sizeof(struct sctphdr) - 1138 sizeof(struct sctp_init_chunk))); 1139 } 1140 } else { 1141 /* 1142 * Send a packet containing a SHUTDOWN-ACK chunk, 1143 * possibly followed by a PAD chunk. 1144 */ 1145 if (datalen >= (u_long)(sizeof(struct sctphdr) + 1146 sizeof(struct sctp_chunkhdr))) { 1147 chk = (struct sctp_chunkhdr *)(sctp + 1); 1148 chk->chunk_type = SCTP_SHUTDOWN_ACK; 1149 chk->chunk_flags = 0; 1150 chk->chunk_length = htons(4); 1151 } 1152 if (datalen >= (u_long)(sizeof(struct sctphdr) + 1153 2 * sizeof(struct sctp_chunkhdr))) { 1154 chk = chk + 1; 1155 chk->chunk_type = SCTP_PAD_CHUNK; 1156 chk->chunk_flags = 0; 1157 chk->chunk_length = htons((u_int16_t)(datalen - 1158 sizeof(struct sctphdr) - 1159 sizeof(struct sctp_chunkhdr))); 1160 } 1161 } 1162 sctp->checksum = sctp_crc32c(outpacket, datalen); 1163 break; 1164 case IPPROTO_TCP: 1165 tcp = (struct tcphdr *)outpacket; 1166 1167 tcp->th_sport = htons(ident); 1168 tcp->th_dport = htons(port + seq); 1169 tcp->th_seq = (tcp->th_sport << 16) | tcp->th_dport; 1170 tcp->th_ack = 0; 1171 tcp->th_off = 5; 1172 tcp->th_flags = TH_SYN; 1173 tcp->th_sum = 0; 1174 tcp->th_sum = tcp_chksum(&Src, &Dst, outpacket, datalen); 1175 break; 1176 default: 1177 fprintf(stderr, "Unknown probe protocol %d.\n", useproto); 1178 exit(1); 1179 } 1180 1181 i = sendto(sndsock, (char *)outpacket, datalen, 0, 1182 (struct sockaddr *)&Dst, Dst.sin6_len); 1183 if (i < 0 || (u_long)i != datalen) { 1184 if (i < 0) 1185 perror("sendto"); 1186 printf("traceroute6: wrote %s %lu chars, ret=%d\n", 1187 hostname, datalen, i); 1188 (void) fflush(stdout); 1189 } 1190} 1191 1192int 1193get_hoplim(struct msghdr *mhdr) 1194{ 1195 struct cmsghdr *cm; 1196 1197 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; 1198 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { 1199 if (cm->cmsg_level == IPPROTO_IPV6 && 1200 cm->cmsg_type == IPV6_HOPLIMIT && 1201 cm->cmsg_len == CMSG_LEN(sizeof(int))) 1202 return (*(int *)CMSG_DATA(cm)); 1203 } 1204 1205 return (-1); 1206} 1207 1208double 1209deltaT(struct timeval *t1p, struct timeval *t2p) 1210{ 1211 double dt; 1212 1213 dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 + 1214 (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0; 1215 return (dt); 1216} 1217 1218/* 1219 * Convert an ICMP "type" field to a printable string. 1220 */ 1221const char * 1222pr_type(int t0) 1223{ 1224 u_char t = t0 & 0xff; 1225 const char *cp; 1226 1227 switch (t) { 1228 case ICMP6_DST_UNREACH: 1229 cp = "Destination Unreachable"; 1230 break; 1231 case ICMP6_PACKET_TOO_BIG: 1232 cp = "Packet Too Big"; 1233 break; 1234 case ICMP6_TIME_EXCEEDED: 1235 cp = "Time Exceeded"; 1236 break; 1237 case ICMP6_PARAM_PROB: 1238 cp = "Parameter Problem"; 1239 break; 1240 case ICMP6_ECHO_REQUEST: 1241 cp = "Echo Request"; 1242 break; 1243 case ICMP6_ECHO_REPLY: 1244 cp = "Echo Reply"; 1245 break; 1246 case ICMP6_MEMBERSHIP_QUERY: 1247 cp = "Group Membership Query"; 1248 break; 1249 case ICMP6_MEMBERSHIP_REPORT: 1250 cp = "Group Membership Report"; 1251 break; 1252 case ICMP6_MEMBERSHIP_REDUCTION: 1253 cp = "Group Membership Reduction"; 1254 break; 1255 case ND_ROUTER_SOLICIT: 1256 cp = "Router Solicitation"; 1257 break; 1258 case ND_ROUTER_ADVERT: 1259 cp = "Router Advertisement"; 1260 break; 1261 case ND_NEIGHBOR_SOLICIT: 1262 cp = "Neighbor Solicitation"; 1263 break; 1264 case ND_NEIGHBOR_ADVERT: 1265 cp = "Neighbor Advertisement"; 1266 break; 1267 case ND_REDIRECT: 1268 cp = "Redirect"; 1269 break; 1270 default: 1271 cp = "Unknown"; 1272 break; 1273 } 1274 return cp; 1275} 1276 1277int 1278packet_ok(struct msghdr *mhdr, int cc, int seq, u_char *type, u_char *code) 1279{ 1280 struct icmp6_hdr *icp; 1281 struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name; 1282 char *buf = (char *)mhdr->msg_iov[0].iov_base; 1283 struct cmsghdr *cm; 1284 int *hlimp; 1285 char hbuf[NI_MAXHOST]; 1286 1287#ifdef OLDRAWSOCKET 1288 int hlen; 1289 struct ip6_hdr *ip; 1290#endif 1291 1292#ifdef OLDRAWSOCKET 1293 ip = (struct ip6_hdr *) buf; 1294 hlen = sizeof(struct ip6_hdr); 1295 if (cc < hlen + sizeof(struct icmp6_hdr)) { 1296 if (verbose) { 1297 if (getnameinfo((struct sockaddr *)from, from->sin6_len, 1298 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) 1299 strlcpy(hbuf, "invalid", sizeof(hbuf)); 1300 printf("packet too short (%d bytes) from %s\n", cc, 1301 hbuf); 1302 } 1303 return (0); 1304 } 1305 cc -= hlen; 1306 icp = (struct icmp6_hdr *)(buf + hlen); 1307#else 1308 if (cc < (int)sizeof(struct icmp6_hdr)) { 1309 if (verbose) { 1310 if (getnameinfo((struct sockaddr *)from, from->sin6_len, 1311 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) 1312 strlcpy(hbuf, "invalid", sizeof(hbuf)); 1313 printf("data too short (%d bytes) from %s\n", cc, hbuf); 1314 } 1315 return (0); 1316 } 1317 icp = (struct icmp6_hdr *)buf; 1318#endif 1319 /* get optional information via advanced API */ 1320 rcvpktinfo = NULL; 1321 hlimp = NULL; 1322 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; 1323 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { 1324 if (cm->cmsg_level == IPPROTO_IPV6 && 1325 cm->cmsg_type == IPV6_PKTINFO && 1326 cm->cmsg_len == 1327 CMSG_LEN(sizeof(struct in6_pktinfo))) 1328 rcvpktinfo = (struct in6_pktinfo *)(CMSG_DATA(cm)); 1329 1330 if (cm->cmsg_level == IPPROTO_IPV6 && 1331 cm->cmsg_type == IPV6_HOPLIMIT && 1332 cm->cmsg_len == CMSG_LEN(sizeof(int))) 1333 hlimp = (int *)CMSG_DATA(cm); 1334 } 1335 if (rcvpktinfo == NULL || hlimp == NULL) { 1336 warnx("failed to get received hop limit or packet info"); 1337#if 0 1338 return (0); 1339#else 1340 rcvhlim = 0; /*XXX*/ 1341#endif 1342 } 1343 else 1344 rcvhlim = *hlimp; 1345 1346 *type = icp->icmp6_type; 1347 *code = icp->icmp6_code; 1348 if ((*type == ICMP6_TIME_EXCEEDED && 1349 *code == ICMP6_TIME_EXCEED_TRANSIT) || 1350 (*type == ICMP6_DST_UNREACH) || 1351 (*type == ICMP6_PARAM_PROB && 1352 *code == ICMP6_PARAMPROB_NEXTHEADER)) { 1353 struct ip6_hdr *hip; 1354 struct icmp6_hdr *icmp; 1355 struct sctp_init_chunk *init; 1356 struct sctphdr *sctp; 1357 struct tcphdr *tcp; 1358 struct udphdr *udp; 1359 void *up; 1360 1361 hip = (struct ip6_hdr *)(icp + 1); 1362 if ((up = get_uphdr(hip, (u_char *)(buf + cc))) == NULL) { 1363 if (verbose) 1364 warnx("failed to get upper layer header"); 1365 return (0); 1366 } 1367 switch (useproto) { 1368 case IPPROTO_ICMPV6: 1369 icmp = (struct icmp6_hdr *)up; 1370 if (icmp->icmp6_id == ident && 1371 icmp->icmp6_seq == htons(seq)) 1372 return (1); 1373 break; 1374 case IPPROTO_UDP: 1375 udp = (struct udphdr *)up; 1376 if (udp->uh_sport == htons(srcport) && 1377 udp->uh_dport == htons(port + seq)) 1378 return (1); 1379 break; 1380 case IPPROTO_SCTP: 1381 sctp = (struct sctphdr *)up; 1382 if (sctp->src_port != htons(ident) || 1383 sctp->dest_port != htons(port + seq)) { 1384 break; 1385 } 1386 if (datalen >= (u_long)(sizeof(struct sctphdr) + 1387 sizeof(struct sctp_init_chunk))) { 1388 if (sctp->v_tag != 0) { 1389 break; 1390 } 1391 init = (struct sctp_init_chunk *)(sctp + 1); 1392 /* Check the initiate tag, if available. */ 1393 if ((char *)&init->init.a_rwnd > buf + cc) { 1394 return (1); 1395 } 1396 if (init->init.initiate_tag == (u_int32_t) 1397 ((sctp->src_port << 16) | sctp->dest_port)) { 1398 return (1); 1399 } 1400 } else { 1401 if (sctp->v_tag == 1402 (u_int32_t)((sctp->src_port << 16) | 1403 sctp->dest_port)) { 1404 return (1); 1405 } 1406 } 1407 break; 1408 case IPPROTO_TCP: 1409 tcp = (struct tcphdr *)up; 1410 if (tcp->th_sport == htons(ident) && 1411 tcp->th_dport == htons(port + seq) && 1412 tcp->th_seq == 1413 (tcp_seq)((tcp->th_sport << 16) | tcp->th_dport)) 1414 return (1); 1415 break; 1416 case IPPROTO_NONE: 1417 return (1); 1418 default: 1419 fprintf(stderr, "Unknown probe proto %d.\n", useproto); 1420 break; 1421 } 1422 } else if (useproto == IPPROTO_ICMPV6 && *type == ICMP6_ECHO_REPLY) { 1423 if (icp->icmp6_id == ident && 1424 icp->icmp6_seq == htons(seq)) 1425 return (1); 1426 } 1427 if (verbose) { 1428 char sbuf[NI_MAXHOST+1], dbuf[INET6_ADDRSTRLEN]; 1429 u_int8_t *p; 1430 int i; 1431 1432 if (getnameinfo((struct sockaddr *)from, from->sin6_len, 1433 sbuf, sizeof(sbuf), NULL, 0, NI_NUMERICHOST) != 0) 1434 strlcpy(sbuf, "invalid", sizeof(sbuf)); 1435 printf("\n%d bytes from %s to %s", cc, sbuf, 1436 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr, 1437 dbuf, sizeof(dbuf)) : "?"); 1438 printf(": icmp type %d (%s) code %d\n", *type, pr_type(*type), 1439 *code); 1440 p = (u_int8_t *)(icp + 1); 1441#define WIDTH 16 1442 for (i = 0; i < cc; i++) { 1443 if (i % WIDTH == 0) 1444 printf("%04x:", i); 1445 if (i % 4 == 0) 1446 printf(" "); 1447 printf("%02x", p[i]); 1448 if (i % WIDTH == WIDTH - 1) 1449 printf("\n"); 1450 } 1451 if (cc % WIDTH != 0) 1452 printf("\n"); 1453 } 1454 return (0); 1455} 1456 1457/* 1458 * Increment pointer until find the UDP or ICMP header. 1459 */ 1460void * 1461get_uphdr(struct ip6_hdr *ip6, u_char *lim) 1462{ 1463 u_char *cp = (u_char *)ip6, nh; 1464 int hlen; 1465 static u_char none_hdr[1]; /* Fake pointer for IPPROTO_NONE. */ 1466 1467 if (cp + sizeof(*ip6) > lim) 1468 return (NULL); 1469 1470 nh = ip6->ip6_nxt; 1471 cp += sizeof(struct ip6_hdr); 1472 1473 while (lim - cp >= (nh == IPPROTO_NONE ? 0 : 8)) { 1474 switch (nh) { 1475 case IPPROTO_ESP: 1476 return (NULL); 1477 case IPPROTO_ICMPV6: 1478 return (useproto == nh ? cp : NULL); 1479 case IPPROTO_SCTP: 1480 case IPPROTO_TCP: 1481 case IPPROTO_UDP: 1482 return (useproto == nh ? cp : NULL); 1483 case IPPROTO_NONE: 1484 return (useproto == nh ? none_hdr : NULL); 1485 case IPPROTO_FRAGMENT: 1486 hlen = sizeof(struct ip6_frag); 1487 nh = ((struct ip6_frag *)cp)->ip6f_nxt; 1488 break; 1489 case IPPROTO_AH: 1490 hlen = (((struct ip6_ext *)cp)->ip6e_len + 2) << 2; 1491 nh = ((struct ip6_ext *)cp)->ip6e_nxt; 1492 break; 1493 default: 1494 hlen = (((struct ip6_ext *)cp)->ip6e_len + 1) << 3; 1495 nh = ((struct ip6_ext *)cp)->ip6e_nxt; 1496 break; 1497 } 1498 1499 cp += hlen; 1500 } 1501 1502 return (NULL); 1503} 1504 1505void 1506print(struct msghdr *mhdr, int cc) 1507{ 1508 struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name; 1509 char hbuf[NI_MAXHOST]; 1510 1511 if (getnameinfo((struct sockaddr *)from, from->sin6_len, 1512 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) 1513 strlcpy(hbuf, "invalid", sizeof(hbuf)); 1514 if (as_path) 1515 printf(" [AS%u]", as_lookup(asn, hbuf, AF_INET6)); 1516 if (nflag) 1517 printf(" %s", hbuf); 1518 else if (lflag) 1519 printf(" %s (%s)", inetname((struct sockaddr *)from), hbuf); 1520 else 1521 printf(" %s", inetname((struct sockaddr *)from)); 1522 1523 if (verbose) { 1524#ifdef OLDRAWSOCKET 1525 printf(" %d bytes to %s", cc, 1526 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr, 1527 hbuf, sizeof(hbuf)) : "?"); 1528#else 1529 printf(" %d bytes of data to %s", cc, 1530 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr, 1531 hbuf, sizeof(hbuf)) : "?"); 1532#endif 1533 } 1534} 1535 1536/* 1537 * Construct an Internet address representation. 1538 * If the nflag has been supplied, give 1539 * numeric value, otherwise try for symbolic name. 1540 */ 1541const char * 1542inetname(struct sockaddr *sa) 1543{ 1544 static char line[NI_MAXHOST], domain[MAXHOSTNAMELEN + 1]; 1545 static int first = 1; 1546 char *cp; 1547 1548 if (first && !nflag) { 1549 first = 0; 1550 if (gethostname(domain, sizeof(domain)) == 0 && 1551 (cp = strchr(domain, '.'))) 1552 (void) strlcpy(domain, cp + 1, sizeof(domain)); 1553 else 1554 domain[0] = 0; 1555 } 1556 cp = NULL; 1557 if (!nflag) { 1558 if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0, 1559 NI_NAMEREQD) == 0) { 1560 if ((cp = strchr(line, '.')) && 1561 !strcmp(cp + 1, domain)) 1562 *cp = 0; 1563 cp = line; 1564 } 1565 } 1566 if (cp) 1567 return cp; 1568 1569 if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0, 1570 NI_NUMERICHOST) != 0) 1571 strlcpy(line, "invalid", sizeof(line)); 1572 return line; 1573} 1574 1575/* 1576 * CRC32C routine for the Stream Control Transmission Protocol 1577 */ 1578 1579#define CRC32C(c, d) (c = (c>>8) ^ crc_c[(c^(d))&0xFF]) 1580 1581static u_int32_t crc_c[256] = { 1582 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 1583 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, 1584 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 1585 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, 1586 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 1587 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, 1588 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 1589 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, 1590 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 1591 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, 1592 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 1593 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, 1594 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 1595 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, 1596 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 1597 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, 1598 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 1599 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, 1600 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 1601 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, 1602 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 1603 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, 1604 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 1605 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, 1606 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 1607 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, 1608 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 1609 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, 1610 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 1611 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, 1612 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 1613 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, 1614 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 1615 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, 1616 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 1617 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, 1618 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 1619 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, 1620 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 1621 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, 1622 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 1623 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, 1624 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 1625 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, 1626 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 1627 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, 1628 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 1629 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, 1630 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 1631 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, 1632 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 1633 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, 1634 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 1635 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, 1636 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 1637 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, 1638 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 1639 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, 1640 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 1641 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, 1642 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 1643 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, 1644 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 1645 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351 1646}; 1647 1648u_int32_t 1649sctp_crc32c(void *packet, u_int32_t len) 1650{ 1651 u_int32_t i, crc32c; 1652 u_int8_t byte0, byte1, byte2, byte3; 1653 u_int8_t *buf = (u_int8_t *)packet; 1654 1655 crc32c = ~0; 1656 for (i = 0; i < len; i++) 1657 CRC32C(crc32c, buf[i]); 1658 crc32c = ~crc32c; 1659 byte0 = crc32c & 0xff; 1660 byte1 = (crc32c>>8) & 0xff; 1661 byte2 = (crc32c>>16) & 0xff; 1662 byte3 = (crc32c>>24) & 0xff; 1663 crc32c = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3); 1664 return htonl(crc32c); 1665} 1666 1667u_int16_t 1668in_cksum(u_int16_t *addr, int len) 1669{ 1670 int nleft = len; 1671 u_int16_t *w = addr; 1672 u_int16_t answer; 1673 int sum = 0; 1674 1675 /* 1676 * Our algorithm is simple, using a 32 bit accumulator (sum), 1677 * we add sequential 16 bit words to it, and at the end, fold 1678 * back all the carry bits from the top 16 bits into the lower 1679 * 16 bits. 1680 */ 1681 while (nleft > 1) { 1682 sum += *w++; 1683 nleft -= 2; 1684 } 1685 1686 /* mop up an odd byte, if necessary */ 1687 if (nleft == 1) 1688 sum += *(u_char *)w; 1689 1690 /* 1691 * add back carry outs from top 16 bits to low 16 bits 1692 */ 1693 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 1694 sum += (sum >> 16); /* add carry */ 1695 answer = ~sum; /* truncate to 16 bits */ 1696 return (answer); 1697} 1698 1699u_int16_t 1700tcp_chksum(struct sockaddr_in6 *src, struct sockaddr_in6 *dst, 1701 void *payload, u_int32_t len) 1702{ 1703 struct { 1704 struct in6_addr src; 1705 struct in6_addr dst; 1706 u_int32_t len; 1707 u_int8_t zero[3]; 1708 u_int8_t next; 1709 } pseudo_hdr; 1710 u_int16_t sum[2]; 1711 1712 pseudo_hdr.src = src->sin6_addr; 1713 pseudo_hdr.dst = dst->sin6_addr; 1714 pseudo_hdr.len = htonl(len); 1715 pseudo_hdr.zero[0] = 0; 1716 pseudo_hdr.zero[1] = 0; 1717 pseudo_hdr.zero[2] = 0; 1718 pseudo_hdr.next = IPPROTO_TCP; 1719 1720 sum[1] = in_cksum((u_int16_t *)&pseudo_hdr, sizeof(pseudo_hdr)); 1721 sum[0] = in_cksum(payload, len); 1722 1723 return (~in_cksum(sum, sizeof(sum))); 1724} 1725 1726void 1727usage(void) 1728{ 1729 1730 fprintf(stderr, 1731"usage: traceroute6 [-adIlnNrSTUv] [-A as_server] [-f firsthop] [-g gateway]\n" 1732" [-m hoplimit] [-p port] [-q probes] [-s src] [-w waittime] target\n" 1733" [datalen]\n"); 1734 exit(1); 1735} 1736