traceroute6.c revision 332237
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 332237 2018-04-07 20:44:30Z 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); 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 369 /* 370 * Receive ICMP 371 */ 372 if ((rcvsock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) { 373 perror("socket(ICMPv6)"); 374 exit(5); 375 } 376 377 size = sizeof(i); 378 (void) sysctl(mib, sizeof(mib)/sizeof(mib[0]), &i, &size, NULL, 0); 379 max_hops = i; 380 381 /* specify to tell receiving interface */ 382#ifdef IPV6_RECVPKTINFO 383 if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, 384 sizeof(on)) < 0) 385 err(1, "setsockopt(IPV6_RECVPKTINFO)"); 386#else /* old adv. API */ 387 if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_PKTINFO, &on, 388 sizeof(on)) < 0) 389 err(1, "setsockopt(IPV6_PKTINFO)"); 390#endif 391 392 /* specify to tell value of hoplimit field of received IP6 hdr */ 393#ifdef IPV6_RECVHOPLIMIT 394 if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, 395 sizeof(on)) < 0) 396 err(1, "setsockopt(IPV6_RECVHOPLIMIT)"); 397#else /* old adv. API */ 398 if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_HOPLIMIT, &on, 399 sizeof(on)) < 0) 400 err(1, "setsockopt(IPV6_HOPLIMIT)"); 401#endif 402 403 seq = 0; 404 ident = htons(getpid() & 0xffff); /* same as ping6 */ 405 406 while ((ch = getopt(argc, argv, "aA:df:g:Ilm:nNp:q:rs:STUvw:")) != -1) 407 switch (ch) { 408 case 'a': 409 as_path = 1; 410 break; 411 case 'A': 412 as_path = 1; 413 as_server = optarg; 414 break; 415 case 'd': 416 options |= SO_DEBUG; 417 break; 418 case 'f': 419 ep = NULL; 420 errno = 0; 421 first_hop = strtoul(optarg, &ep, 0); 422 if (errno || !*optarg || *ep || first_hop > 255) { 423 fprintf(stderr, 424 "traceroute6: invalid min hoplimit.\n"); 425 exit(1); 426 } 427 break; 428 case 'g': 429 hp = getipnodebyname(optarg, AF_INET6, 0, &h_errno); 430 if (hp == NULL) { 431 fprintf(stderr, 432 "traceroute6: unknown host %s\n", optarg); 433 exit(1); 434 } 435#ifdef USE_RFC2292BIS 436 if (rth == NULL) { 437 /* 438 * XXX: We can't detect the number of 439 * intermediate nodes yet. 440 */ 441 if ((rth = inet6_rth_init((void *)rtbuf, 442 sizeof(rtbuf), IPV6_RTHDR_TYPE_0, 443 0)) == NULL) { 444 fprintf(stderr, 445 "inet6_rth_init failed.\n"); 446 exit(1); 447 } 448 } 449 if (inet6_rth_add((void *)rth, 450 (struct in6_addr *)hp->h_addr)) { 451 fprintf(stderr, 452 "inet6_rth_add failed for %s\n", 453 optarg); 454 exit(1); 455 } 456#else /* old advanced API */ 457 if (cmsg == NULL) 458 cmsg = inet6_rthdr_init(rtbuf, IPV6_RTHDR_TYPE_0); 459 inet6_rthdr_add(cmsg, (struct in6_addr *)hp->h_addr, 460 IPV6_RTHDR_LOOSE); 461#endif 462 freehostent(hp); 463 break; 464 case 'I': 465 useproto = IPPROTO_ICMPV6; 466 break; 467 case 'l': 468 lflag++; 469 break; 470 case 'm': 471 ep = NULL; 472 errno = 0; 473 max_hops = strtoul(optarg, &ep, 0); 474 if (errno || !*optarg || *ep || max_hops > 255) { 475 fprintf(stderr, 476 "traceroute6: invalid max hoplimit.\n"); 477 exit(1); 478 } 479 break; 480 case 'n': 481 nflag++; 482 break; 483 case 'N': 484 useproto = IPPROTO_NONE; 485 break; 486 case 'p': 487 ep = NULL; 488 errno = 0; 489 lport = strtoul(optarg, &ep, 0); 490 if (errno || !*optarg || *ep) { 491 fprintf(stderr, "traceroute6: invalid port.\n"); 492 exit(1); 493 } 494 if (lport == 0 || lport != (lport & 0xffff)) { 495 fprintf(stderr, 496 "traceroute6: port out of range.\n"); 497 exit(1); 498 } 499 port = lport & 0xffff; 500 break; 501 case 'q': 502 ep = NULL; 503 errno = 0; 504 nprobes = strtoul(optarg, &ep, 0); 505 if (errno || !*optarg || *ep) { 506 fprintf(stderr, 507 "traceroute6: invalid nprobes.\n"); 508 exit(1); 509 } 510 if (nprobes < 1) { 511 fprintf(stderr, 512 "traceroute6: nprobes must be >0.\n"); 513 exit(1); 514 } 515 break; 516 case 'r': 517 options |= SO_DONTROUTE; 518 break; 519 case 's': 520 /* 521 * set the ip source address of the outbound 522 * probe (e.g., on a multi-homed host). 523 */ 524 source = optarg; 525 break; 526 case 'S': 527 useproto = IPPROTO_SCTP; 528 break; 529 case 'T': 530 useproto = IPPROTO_TCP; 531 break; 532 case 'U': 533 useproto = IPPROTO_UDP; 534 break; 535 case 'v': 536 verbose++; 537 break; 538 case 'w': 539 ep = NULL; 540 errno = 0; 541 waittime = strtoul(optarg, &ep, 0); 542 if (errno || !*optarg || *ep) { 543 fprintf(stderr, 544 "traceroute6: invalid wait time.\n"); 545 exit(1); 546 } 547 if (waittime < 1) { 548 fprintf(stderr, 549 "traceroute6: wait must be >= 1 sec.\n"); 550 exit(1); 551 } 552 break; 553 default: 554 usage(); 555 } 556 argc -= optind; 557 argv += optind; 558 559 /* 560 * Open socket to send probe packets. 561 */ 562 switch (useproto) { 563 case IPPROTO_ICMPV6: 564 sndsock = rcvsock; 565 break; 566 case IPPROTO_UDP: 567 if ((sndsock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 568 perror("socket(SOCK_DGRAM)"); 569 exit(5); 570 } 571 break; 572 case IPPROTO_NONE: 573 case IPPROTO_SCTP: 574 case IPPROTO_TCP: 575 if ((sndsock = socket(AF_INET6, SOCK_RAW, useproto)) < 0) { 576 perror("socket(SOCK_RAW)"); 577 exit(5); 578 } 579 break; 580 default: 581 fprintf(stderr, "traceroute6: unknown probe protocol %d\n", 582 useproto); 583 exit(5); 584 } 585 if (max_hops < first_hop) { 586 fprintf(stderr, 587 "traceroute6: max hoplimit must be larger than first hoplimit.\n"); 588 exit(1); 589 } 590 591 /* revoke privs */ 592 uid = getuid(); 593 if (setresuid(uid, uid, uid) == -1) { 594 perror("setresuid"); 595 exit(1); 596 } 597 598 599 if (argc < 1 || argc > 2) 600 usage(); 601 602#if 1 603 setvbuf(stdout, NULL, _IOLBF, BUFSIZ); 604#else 605 setlinebuf(stdout); 606#endif 607 608 memset(&hints, 0, sizeof(hints)); 609 hints.ai_family = PF_INET6; 610 hints.ai_socktype = SOCK_RAW; 611 hints.ai_protocol = IPPROTO_ICMPV6; 612 hints.ai_flags = AI_CANONNAME; 613 error = getaddrinfo(*argv, NULL, &hints, &res); 614 if (error) { 615 fprintf(stderr, 616 "traceroute6: %s\n", gai_strerror(error)); 617 exit(1); 618 } 619 if (res->ai_addrlen != sizeof(Dst)) { 620 fprintf(stderr, 621 "traceroute6: size of sockaddr mismatch\n"); 622 exit(1); 623 } 624 memcpy(&Dst, res->ai_addr, res->ai_addrlen); 625 hostname = res->ai_canonname ? strdup(res->ai_canonname) : *argv; 626 if (!hostname) { 627 fprintf(stderr, "traceroute6: not enough core\n"); 628 exit(1); 629 } 630 if (res->ai_next) { 631 if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, 632 sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) 633 strlcpy(hbuf, "?", sizeof(hbuf)); 634 fprintf(stderr, "traceroute6: Warning: %s has multiple " 635 "addresses; using %s\n", hostname, hbuf); 636 } 637 638 if (*++argv) { 639 ep = NULL; 640 errno = 0; 641 datalen = strtoul(*argv, &ep, 0); 642 if (errno || *ep) { 643 fprintf(stderr, 644 "traceroute6: invalid packet length.\n"); 645 exit(1); 646 } 647 } 648 switch (useproto) { 649 case IPPROTO_ICMPV6: 650 minlen = ICMP6ECHOLEN; 651 break; 652 case IPPROTO_UDP: 653 minlen = sizeof(struct udphdr); 654 break; 655 case IPPROTO_NONE: 656 minlen = 0; 657 datalen = 0; 658 break; 659 case IPPROTO_SCTP: 660 minlen = sizeof(struct sctphdr); 661 break; 662 case IPPROTO_TCP: 663 minlen = sizeof(struct tcphdr); 664 break; 665 default: 666 fprintf(stderr, "traceroute6: unknown probe protocol %d.\n", 667 useproto); 668 exit(1); 669 } 670 if (datalen < minlen) 671 datalen = minlen; 672 else if (datalen >= MAXPACKET) { 673 fprintf(stderr, 674 "traceroute6: packet size must be %zu <= s < %d.\n", 675 minlen, MAXPACKET); 676 exit(1); 677 } 678 if (useproto == IPPROTO_UDP) 679 datalen -= sizeof(struct udphdr); 680 if ((useproto == IPPROTO_SCTP) && (datalen & 3)) { 681 fprintf(stderr, 682 "traceroute6: packet size must be a multiple of 4.\n"); 683 exit(1); 684 } 685 outpacket = malloc(datalen); 686 if (!outpacket) { 687 perror("malloc"); 688 exit(1); 689 } 690 (void) bzero((char *)outpacket, datalen); 691 692 /* initialize msghdr for receiving packets */ 693 rcviov[0].iov_base = (caddr_t)packet; 694 rcviov[0].iov_len = sizeof(packet); 695 rcvmhdr.msg_name = (caddr_t)&Rcv; 696 rcvmhdr.msg_namelen = sizeof(Rcv); 697 rcvmhdr.msg_iov = rcviov; 698 rcvmhdr.msg_iovlen = 1; 699 rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + 700 CMSG_SPACE(sizeof(int)); 701 if ((rcvcmsgbuf = malloc(rcvcmsglen)) == NULL) { 702 fprintf(stderr, "traceroute6: malloc failed\n"); 703 exit(1); 704 } 705 rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf; 706 rcvmhdr.msg_controllen = rcvcmsglen; 707 708 if (options & SO_DEBUG) 709 (void) setsockopt(rcvsock, SOL_SOCKET, SO_DEBUG, 710 (char *)&on, sizeof(on)); 711 if (options & SO_DONTROUTE) 712 (void) setsockopt(rcvsock, SOL_SOCKET, SO_DONTROUTE, 713 (char *)&on, sizeof(on)); 714#ifdef IPSEC 715#ifdef IPSEC_POLICY_IPSEC 716 /* 717 * do not raise error even if setsockopt fails, kernel may have ipsec 718 * turned off. 719 */ 720 if (setpolicy(rcvsock, "in bypass") < 0) 721 errx(1, "%s", ipsec_strerror()); 722 if (setpolicy(rcvsock, "out bypass") < 0) 723 errx(1, "%s", ipsec_strerror()); 724#else 725 { 726 int level = IPSEC_LEVEL_NONE; 727 728 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, &level, 729 sizeof(level)); 730 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_ESP_NETWORK_LEVEL, &level, 731 sizeof(level)); 732#ifdef IP_AUTH_TRANS_LEVEL 733 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, &level, 734 sizeof(level)); 735#else 736 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_LEVEL, &level, 737 sizeof(level)); 738#endif 739#ifdef IP_AUTH_NETWORK_LEVEL 740 (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_NETWORK_LEVEL, &level, 741 sizeof(level)); 742#endif 743 } 744#endif /*IPSEC_POLICY_IPSEC*/ 745#endif /*IPSEC*/ 746 747#ifdef SO_SNDBUF 748 i = datalen; 749 if (i == 0) 750 i = 1; 751 if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&i, 752 sizeof(i)) < 0) { 753 perror("setsockopt(SO_SNDBUF)"); 754 exit(6); 755 } 756#endif /* SO_SNDBUF */ 757 if (options & SO_DEBUG) 758 (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, 759 (char *)&on, sizeof(on)); 760 if (options & SO_DONTROUTE) 761 (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, 762 (char *)&on, sizeof(on)); 763#ifdef USE_RFC2292BIS 764 if (rth) {/* XXX: there is no library to finalize the header... */ 765 rth->ip6r_len = rth->ip6r_segleft * 2; 766 if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_RTHDR, 767 (void *)rth, (rth->ip6r_len + 1) << 3)) { 768 fprintf(stderr, "setsockopt(IPV6_RTHDR): %s\n", 769 strerror(errno)); 770 exit(1); 771 } 772 } 773#else /* old advanced API */ 774 if (cmsg != NULL) { 775 inet6_rthdr_lasthop(cmsg, IPV6_RTHDR_LOOSE); 776 if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_PKTOPTIONS, 777 rtbuf, cmsg->cmsg_len) < 0) { 778 fprintf(stderr, "setsockopt(IPV6_PKTOPTIONS): %s\n", 779 strerror(errno)); 780 exit(1); 781 } 782 } 783#endif /* USE_RFC2292BIS */ 784#ifdef IPSEC 785#ifdef IPSEC_POLICY_IPSEC 786 /* 787 * do not raise error even if setsockopt fails, kernel may have ipsec 788 * turned off. 789 */ 790 if (setpolicy(sndsock, "in bypass") < 0) 791 errx(1, "%s", ipsec_strerror()); 792 if (setpolicy(sndsock, "out bypass") < 0) 793 errx(1, "%s", ipsec_strerror()); 794#else 795 { 796 int level = IPSEC_LEVEL_BYPASS; 797 798 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, &level, 799 sizeof(level)); 800 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_ESP_NETWORK_LEVEL, &level, 801 sizeof(level)); 802#ifdef IP_AUTH_TRANS_LEVEL 803 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, &level, 804 sizeof(level)); 805#else 806 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_LEVEL, &level, 807 sizeof(level)); 808#endif 809#ifdef IP_AUTH_NETWORK_LEVEL 810 (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_NETWORK_LEVEL, &level, 811 sizeof(level)); 812#endif 813 } 814#endif /*IPSEC_POLICY_IPSEC*/ 815#endif /*IPSEC*/ 816 817 /* 818 * Source selection 819 */ 820 bzero(&Src, sizeof(Src)); 821 if (source) { 822 struct addrinfo hints, *res; 823 int error; 824 825 memset(&hints, 0, sizeof(hints)); 826 hints.ai_family = AF_INET6; 827 hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 828 hints.ai_flags = AI_NUMERICHOST; 829 error = getaddrinfo(source, "0", &hints, &res); 830 if (error) { 831 printf("traceroute6: %s: %s\n", source, 832 gai_strerror(error)); 833 exit(1); 834 } 835 if (res->ai_addrlen > sizeof(Src)) { 836 printf("traceroute6: %s: %s\n", source, 837 gai_strerror(error)); 838 exit(1); 839 } 840 memcpy(&Src, res->ai_addr, res->ai_addrlen); 841 freeaddrinfo(res); 842 } else { 843 struct sockaddr_in6 Nxt; 844 int dummy; 845 socklen_t len; 846 847 Nxt = Dst; 848 Nxt.sin6_port = htons(DUMMY_PORT); 849 if (cmsg != NULL) 850 bcopy(inet6_rthdr_getaddr(cmsg, 1), &Nxt.sin6_addr, 851 sizeof(Nxt.sin6_addr)); 852 if ((dummy = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 853 perror("socket"); 854 exit(1); 855 } 856 if (connect(dummy, (struct sockaddr *)&Nxt, Nxt.sin6_len) < 0) { 857 perror("connect"); 858 exit(1); 859 } 860 len = sizeof(Src); 861 if (getsockname(dummy, (struct sockaddr *)&Src, &len) < 0) { 862 perror("getsockname"); 863 exit(1); 864 } 865 if (getnameinfo((struct sockaddr *)&Src, Src.sin6_len, 866 src0, sizeof(src0), NULL, 0, NI_NUMERICHOST)) { 867 fprintf(stderr, "getnameinfo failed for source\n"); 868 exit(1); 869 } 870 source = src0; 871 close(dummy); 872 } 873 874 Src.sin6_port = htons(0); 875 if (bind(sndsock, (struct sockaddr *)&Src, Src.sin6_len) < 0) { 876 perror("bind"); 877 exit(1); 878 } 879 880 { 881 socklen_t len; 882 883 len = sizeof(Src); 884 if (getsockname(sndsock, (struct sockaddr *)&Src, &len) < 0) { 885 perror("getsockname"); 886 exit(1); 887 } 888 srcport = ntohs(Src.sin6_port); 889 } 890 891 if (as_path) { 892 asn = as_setup(as_server); 893 if (asn == NULL) { 894 fprintf(stderr, 895 "traceroute6: as_setup failed, AS# lookups" 896 " disabled\n"); 897 (void)fflush(stderr); 898 as_path = 0; 899 } 900 } 901 902 /* 903 * Message to users 904 */ 905 if (getnameinfo((struct sockaddr *)&Dst, Dst.sin6_len, hbuf, 906 sizeof(hbuf), NULL, 0, NI_NUMERICHOST)) 907 strlcpy(hbuf, "(invalid)", sizeof(hbuf)); 908 fprintf(stderr, "traceroute6"); 909 fprintf(stderr, " to %s (%s)", hostname, hbuf); 910 if (source) 911 fprintf(stderr, " from %s", source); 912 fprintf(stderr, ", %lu hops max, %lu byte packets\n", 913 max_hops, 914 datalen + ((useproto == IPPROTO_UDP) ? sizeof(struct udphdr) : 0)); 915 (void) fflush(stderr); 916 917 if (first_hop > 1) 918 printf("Skipping %lu intermediate hops\n", first_hop - 1); 919 920 /* 921 * Main loop 922 */ 923 for (hops = first_hop; hops <= max_hops; ++hops) { 924 struct in6_addr lastaddr; 925 int got_there = 0; 926 unsigned unreachable = 0; 927 928 printf("%2lu ", hops); 929 bzero(&lastaddr, sizeof(lastaddr)); 930 for (probe = 0; probe < nprobes; ++probe) { 931 int cc; 932 struct timeval t1, t2; 933 934 (void) gettimeofday(&t1, NULL); 935 send_probe(++seq, hops); 936 while ((cc = wait_for_reply(rcvsock, &rcvmhdr))) { 937 (void) gettimeofday(&t2, NULL); 938 if ((i = packet_ok(&rcvmhdr, cc, seq))) { 939 if (!IN6_ARE_ADDR_EQUAL(&Rcv.sin6_addr, 940 &lastaddr)) { 941 if (probe > 0) 942 fputs("\n ", stdout); 943 print(&rcvmhdr, cc); 944 lastaddr = Rcv.sin6_addr; 945 } 946 printf(" %.3f ms", deltaT(&t1, &t2)); 947 switch (i - 1) { 948 case ICMP6_DST_UNREACH_NOROUTE: 949 ++unreachable; 950 printf(" !N"); 951 break; 952 case ICMP6_DST_UNREACH_ADMIN: 953 ++unreachable; 954 printf(" !P"); 955 break; 956 case ICMP6_DST_UNREACH_NOTNEIGHBOR: 957 ++unreachable; 958 printf(" !S"); 959 break; 960 case ICMP6_DST_UNREACH_ADDR: 961 ++unreachable; 962 printf(" !A"); 963 break; 964 case ICMP6_DST_UNREACH_NOPORT: 965 if (rcvhlim >= 0 && 966 rcvhlim <= 1) 967 printf(" !"); 968 ++got_there; 969 break; 970 } 971 break; 972 } else if (deltaT(&t1, &t2) > waittime * 1000) { 973 cc = 0; 974 break; 975 } 976 } 977 if (cc == 0) 978 printf(" *"); 979 (void) fflush(stdout); 980 } 981 putchar('\n'); 982 if (got_there || 983 (unreachable > 0 && unreachable >= ((nprobes + 1) / 2))) { 984 exit(0); 985 } 986 } 987 if (as_path) 988 as_shutdown(asn); 989 990 exit(0); 991} 992 993int 994wait_for_reply(int sock, struct msghdr *mhdr) 995{ 996#ifdef HAVE_POLL 997 struct pollfd pfd[1]; 998 int cc = 0; 999 1000 pfd[0].fd = sock; 1001 pfd[0].events = POLLIN; 1002 pfd[0].revents = 0; 1003 1004 if (poll(pfd, 1, waittime * 1000) > 0) 1005 cc = recvmsg(rcvsock, mhdr, 0); 1006 1007 return(cc); 1008#else 1009 fd_set *fdsp; 1010 struct timeval wait; 1011 int cc = 0, fdsn; 1012 1013 fdsn = howmany(sock + 1, NFDBITS) * sizeof(fd_mask); 1014 if ((fdsp = (fd_set *)malloc(fdsn)) == NULL) 1015 err(1, "malloc"); 1016 memset(fdsp, 0, fdsn); 1017 FD_SET(sock, fdsp); 1018 wait.tv_sec = waittime; wait.tv_usec = 0; 1019 1020 if (select(sock+1, fdsp, (fd_set *)0, (fd_set *)0, &wait) > 0) 1021 cc = recvmsg(rcvsock, mhdr, 0); 1022 1023 free(fdsp); 1024 return(cc); 1025#endif 1026} 1027 1028#ifdef IPSEC 1029#ifdef IPSEC_POLICY_IPSEC 1030int 1031setpolicy(so, policy) 1032 int so; 1033 char *policy; 1034{ 1035 char *buf; 1036 1037 buf = ipsec_set_policy(policy, strlen(policy)); 1038 if (buf == NULL) { 1039 warnx("%s", ipsec_strerror()); 1040 return -1; 1041 } 1042 (void)setsockopt(so, IPPROTO_IPV6, IPV6_IPSEC_POLICY, 1043 buf, ipsec_get_policylen(buf)); 1044 1045 free(buf); 1046 1047 return 0; 1048} 1049#endif 1050#endif 1051 1052void 1053send_probe(int seq, u_long hops) 1054{ 1055 struct icmp6_hdr *icp; 1056 struct sctphdr *sctp; 1057 struct sctp_chunkhdr *chk; 1058 struct sctp_init_chunk *init; 1059 struct sctp_paramhdr *param; 1060 struct tcphdr *tcp; 1061 int i; 1062 1063 i = hops; 1064 if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 1065 (char *)&i, sizeof(i)) < 0) { 1066 perror("setsockopt IPV6_UNICAST_HOPS"); 1067 } 1068 1069 Dst.sin6_port = htons(port + seq); 1070 1071 switch (useproto) { 1072 case IPPROTO_ICMPV6: 1073 icp = (struct icmp6_hdr *)outpacket; 1074 1075 icp->icmp6_type = ICMP6_ECHO_REQUEST; 1076 icp->icmp6_code = 0; 1077 icp->icmp6_cksum = 0; 1078 icp->icmp6_id = ident; 1079 icp->icmp6_seq = htons(seq); 1080 break; 1081 case IPPROTO_UDP: 1082 break; 1083 case IPPROTO_NONE: 1084 /* No space for anything. No harm as seq/tv32 are decorative. */ 1085 break; 1086 case IPPROTO_SCTP: 1087 sctp = (struct sctphdr *)outpacket; 1088 1089 sctp->src_port = htons(ident); 1090 sctp->dest_port = htons(port + seq); 1091 if (datalen >= (u_long)(sizeof(struct sctphdr) + 1092 sizeof(struct sctp_init_chunk))) { 1093 sctp->v_tag = 0; 1094 } else { 1095 sctp->v_tag = (sctp->src_port << 16) | sctp->dest_port; 1096 } 1097 sctp->checksum = htonl(0); 1098 if (datalen >= (u_long)(sizeof(struct sctphdr) + 1099 sizeof(struct sctp_init_chunk))) { 1100 /* 1101 * Send a packet containing an INIT chunk. This works 1102 * better in case of firewalls on the path, but 1103 * results in a probe packet containing at least 1104 * 32 bytes of payload. For shorter payloads, use 1105 * SHUTDOWN-ACK chunks. 1106 */ 1107 init = (struct sctp_init_chunk *)(sctp + 1); 1108 init->ch.chunk_type = SCTP_INITIATION; 1109 init->ch.chunk_flags = 0; 1110 init->ch.chunk_length = htons((u_int16_t)(datalen - 1111 sizeof(struct sctphdr))); 1112 init->init.initiate_tag = (sctp->src_port << 16) | 1113 sctp->dest_port; 1114 init->init.a_rwnd = htonl(1500); 1115 init->init.num_outbound_streams = htons(1); 1116 init->init.num_inbound_streams = htons(1); 1117 init->init.initial_tsn = htonl(0); 1118 if (datalen >= (u_long)(sizeof(struct sctphdr) + 1119 sizeof(struct sctp_init_chunk) + 1120 sizeof(struct sctp_paramhdr))) { 1121 param = (struct sctp_paramhdr *)(init + 1); 1122 param->param_type = htons(SCTP_PAD); 1123 param->param_length = 1124 htons((u_int16_t)(datalen - 1125 sizeof(struct sctphdr) - 1126 sizeof(struct sctp_init_chunk))); 1127 } 1128 } else { 1129 /* 1130 * Send a packet containing a SHUTDOWN-ACK chunk, 1131 * possibly followed by a PAD chunk. 1132 */ 1133 if (datalen >= (u_long)(sizeof(struct sctphdr) + 1134 sizeof(struct sctp_chunkhdr))) { 1135 chk = (struct sctp_chunkhdr *)(sctp + 1); 1136 chk->chunk_type = SCTP_SHUTDOWN_ACK; 1137 chk->chunk_flags = 0; 1138 chk->chunk_length = htons(4); 1139 } 1140 if (datalen >= (u_long)(sizeof(struct sctphdr) + 1141 2 * sizeof(struct sctp_chunkhdr))) { 1142 chk = chk + 1; 1143 chk->chunk_type = SCTP_PAD_CHUNK; 1144 chk->chunk_flags = 0; 1145 chk->chunk_length = htons((u_int16_t)(datalen - 1146 sizeof(struct sctphdr) - 1147 sizeof(struct sctp_chunkhdr))); 1148 } 1149 } 1150 sctp->checksum = sctp_crc32c(outpacket, datalen); 1151 break; 1152 case IPPROTO_TCP: 1153 tcp = (struct tcphdr *)outpacket; 1154 1155 tcp->th_sport = htons(ident); 1156 tcp->th_dport = htons(port + seq); 1157 tcp->th_seq = (tcp->th_sport << 16) | tcp->th_dport; 1158 tcp->th_ack = 0; 1159 tcp->th_off = 5; 1160 tcp->th_flags = TH_SYN; 1161 tcp->th_sum = 0; 1162 tcp->th_sum = tcp_chksum(&Src, &Dst, outpacket, datalen); 1163 break; 1164 default: 1165 fprintf(stderr, "Unknown probe protocol %d.\n", useproto); 1166 exit(1); 1167 } 1168 1169 i = sendto(sndsock, (char *)outpacket, datalen, 0, 1170 (struct sockaddr *)&Dst, Dst.sin6_len); 1171 if (i < 0 || (u_long)i != datalen) { 1172 if (i < 0) 1173 perror("sendto"); 1174 printf("traceroute6: wrote %s %lu chars, ret=%d\n", 1175 hostname, datalen, i); 1176 (void) fflush(stdout); 1177 } 1178} 1179 1180int 1181get_hoplim(struct msghdr *mhdr) 1182{ 1183 struct cmsghdr *cm; 1184 1185 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; 1186 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { 1187 if (cm->cmsg_level == IPPROTO_IPV6 && 1188 cm->cmsg_type == IPV6_HOPLIMIT && 1189 cm->cmsg_len == CMSG_LEN(sizeof(int))) 1190 return(*(int *)CMSG_DATA(cm)); 1191 } 1192 1193 return(-1); 1194} 1195 1196double 1197deltaT(struct timeval *t1p, struct timeval *t2p) 1198{ 1199 double dt; 1200 1201 dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 + 1202 (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0; 1203 return (dt); 1204} 1205 1206/* 1207 * Convert an ICMP "type" field to a printable string. 1208 */ 1209const char * 1210pr_type(int t0) 1211{ 1212 u_char t = t0 & 0xff; 1213 const char *cp; 1214 1215 switch (t) { 1216 case ICMP6_DST_UNREACH: 1217 cp = "Destination Unreachable"; 1218 break; 1219 case ICMP6_PACKET_TOO_BIG: 1220 cp = "Packet Too Big"; 1221 break; 1222 case ICMP6_TIME_EXCEEDED: 1223 cp = "Time Exceeded"; 1224 break; 1225 case ICMP6_PARAM_PROB: 1226 cp = "Parameter Problem"; 1227 break; 1228 case ICMP6_ECHO_REQUEST: 1229 cp = "Echo Request"; 1230 break; 1231 case ICMP6_ECHO_REPLY: 1232 cp = "Echo Reply"; 1233 break; 1234 case ICMP6_MEMBERSHIP_QUERY: 1235 cp = "Group Membership Query"; 1236 break; 1237 case ICMP6_MEMBERSHIP_REPORT: 1238 cp = "Group Membership Report"; 1239 break; 1240 case ICMP6_MEMBERSHIP_REDUCTION: 1241 cp = "Group Membership Reduction"; 1242 break; 1243 case ND_ROUTER_SOLICIT: 1244 cp = "Router Solicitation"; 1245 break; 1246 case ND_ROUTER_ADVERT: 1247 cp = "Router Advertisement"; 1248 break; 1249 case ND_NEIGHBOR_SOLICIT: 1250 cp = "Neighbor Solicitation"; 1251 break; 1252 case ND_NEIGHBOR_ADVERT: 1253 cp = "Neighbor Advertisement"; 1254 break; 1255 case ND_REDIRECT: 1256 cp = "Redirect"; 1257 break; 1258 default: 1259 cp = "Unknown"; 1260 break; 1261 } 1262 return cp; 1263} 1264 1265int 1266packet_ok(struct msghdr *mhdr, int cc, int seq) 1267{ 1268 struct icmp6_hdr *icp; 1269 struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name; 1270 u_char type, code; 1271 char *buf = (char *)mhdr->msg_iov[0].iov_base; 1272 struct cmsghdr *cm; 1273 int *hlimp; 1274 char hbuf[NI_MAXHOST]; 1275 1276#ifdef OLDRAWSOCKET 1277 int hlen; 1278 struct ip6_hdr *ip; 1279#endif 1280 1281#ifdef OLDRAWSOCKET 1282 ip = (struct ip6_hdr *) buf; 1283 hlen = sizeof(struct ip6_hdr); 1284 if (cc < hlen + sizeof(struct icmp6_hdr)) { 1285 if (verbose) { 1286 if (getnameinfo((struct sockaddr *)from, from->sin6_len, 1287 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) 1288 strlcpy(hbuf, "invalid", sizeof(hbuf)); 1289 printf("packet too short (%d bytes) from %s\n", cc, 1290 hbuf); 1291 } 1292 return (0); 1293 } 1294 cc -= hlen; 1295 icp = (struct icmp6_hdr *)(buf + hlen); 1296#else 1297 if (cc < (int)sizeof(struct icmp6_hdr)) { 1298 if (verbose) { 1299 if (getnameinfo((struct sockaddr *)from, from->sin6_len, 1300 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) 1301 strlcpy(hbuf, "invalid", sizeof(hbuf)); 1302 printf("data too short (%d bytes) from %s\n", cc, hbuf); 1303 } 1304 return(0); 1305 } 1306 icp = (struct icmp6_hdr *)buf; 1307#endif 1308 /* get optional information via advanced API */ 1309 rcvpktinfo = NULL; 1310 hlimp = NULL; 1311 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; 1312 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { 1313 if (cm->cmsg_level == IPPROTO_IPV6 && 1314 cm->cmsg_type == IPV6_PKTINFO && 1315 cm->cmsg_len == 1316 CMSG_LEN(sizeof(struct in6_pktinfo))) 1317 rcvpktinfo = (struct in6_pktinfo *)(CMSG_DATA(cm)); 1318 1319 if (cm->cmsg_level == IPPROTO_IPV6 && 1320 cm->cmsg_type == IPV6_HOPLIMIT && 1321 cm->cmsg_len == CMSG_LEN(sizeof(int))) 1322 hlimp = (int *)CMSG_DATA(cm); 1323 } 1324 if (rcvpktinfo == NULL || hlimp == NULL) { 1325 warnx("failed to get received hop limit or packet info"); 1326#if 0 1327 return(0); 1328#else 1329 rcvhlim = 0; /*XXX*/ 1330#endif 1331 } 1332 else 1333 rcvhlim = *hlimp; 1334 1335 type = icp->icmp6_type; 1336 code = icp->icmp6_code; 1337 if ((type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT) 1338 || type == ICMP6_DST_UNREACH) { 1339 struct ip6_hdr *hip; 1340 struct icmp6_hdr *icmp; 1341 struct sctp_init_chunk *init; 1342 struct sctphdr *sctp; 1343 struct tcphdr *tcp; 1344 struct udphdr *udp; 1345 void *up; 1346 1347 hip = (struct ip6_hdr *)(icp + 1); 1348 if ((up = get_uphdr(hip, (u_char *)(buf + cc))) == NULL) { 1349 if (verbose) 1350 warnx("failed to get upper layer header"); 1351 return(0); 1352 } 1353 switch (useproto) { 1354 case IPPROTO_ICMPV6: 1355 icmp = (struct icmp6_hdr *)up; 1356 if (icmp->icmp6_id == ident && 1357 icmp->icmp6_seq == htons(seq)) 1358 return (type == ICMP6_TIME_EXCEEDED ? 1359 -1 : code + 1); 1360 break; 1361 case IPPROTO_UDP: 1362 udp = (struct udphdr *)up; 1363 if (udp->uh_sport == htons(srcport) && 1364 udp->uh_dport == htons(port + seq)) 1365 return (type == ICMP6_TIME_EXCEEDED ? 1366 -1 : code + 1); 1367 break; 1368 case IPPROTO_SCTP: 1369 sctp = (struct sctphdr *)up; 1370 if (sctp->src_port != htons(ident) || 1371 sctp->dest_port != htons(port + seq)) { 1372 break; 1373 } 1374 if (datalen >= (u_long)(sizeof(struct sctphdr) + 1375 sizeof(struct sctp_init_chunk))) { 1376 if (sctp->v_tag != 0) { 1377 break; 1378 } 1379 init = (struct sctp_init_chunk *)(sctp + 1); 1380 /* Check the initiate tag, if available. */ 1381 if ((char *)&init->init.a_rwnd > buf + cc) { 1382 return (type == ICMP6_TIME_EXCEEDED ? 1383 -1 : code + 1); 1384 } 1385 if (init->init.initiate_tag == (u_int32_t) 1386 ((sctp->src_port << 16) | sctp->dest_port)) { 1387 return (type == ICMP6_TIME_EXCEEDED ? 1388 -1 : code + 1); 1389 } 1390 } else { 1391 if (sctp->v_tag == 1392 (u_int32_t)((sctp->src_port << 16) | 1393 sctp->dest_port)) { 1394 return (type == ICMP6_TIME_EXCEEDED ? 1395 -1 : code + 1); 1396 } 1397 } 1398 break; 1399 case IPPROTO_TCP: 1400 tcp = (struct tcphdr *)up; 1401 if (tcp->th_sport == htons(ident) && 1402 tcp->th_dport == htons(port + seq) && 1403 tcp->th_seq == 1404 (tcp_seq)((tcp->th_sport << 16) | tcp->th_dport)) 1405 return (type == ICMP6_TIME_EXCEEDED ? 1406 -1 : code + 1); 1407 break; 1408 case IPPROTO_NONE: 1409 return (type == ICMP6_TIME_EXCEEDED ? -1 : code + 1); 1410 default: 1411 fprintf(stderr, "Unknown probe proto %d.\n", useproto); 1412 break; 1413 } 1414 } else if (useproto == IPPROTO_ICMPV6 && type == ICMP6_ECHO_REPLY) { 1415 if (icp->icmp6_id == ident && 1416 icp->icmp6_seq == htons(seq)) 1417 return (ICMP6_DST_UNREACH_NOPORT + 1); 1418 } 1419 if (verbose) { 1420 char sbuf[NI_MAXHOST+1], dbuf[INET6_ADDRSTRLEN]; 1421 u_int8_t *p; 1422 int i; 1423 1424 if (getnameinfo((struct sockaddr *)from, from->sin6_len, 1425 sbuf, sizeof(sbuf), NULL, 0, NI_NUMERICHOST) != 0) 1426 strlcpy(sbuf, "invalid", sizeof(sbuf)); 1427 printf("\n%d bytes from %s to %s", cc, sbuf, 1428 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr, 1429 dbuf, sizeof(dbuf)) : "?"); 1430 printf(": icmp type %d (%s) code %d\n", type, pr_type(type), 1431 icp->icmp6_code); 1432 p = (u_int8_t *)(icp + 1); 1433#define WIDTH 16 1434 for (i = 0; i < cc; i++) { 1435 if (i % WIDTH == 0) 1436 printf("%04x:", i); 1437 if (i % 4 == 0) 1438 printf(" "); 1439 printf("%02x", p[i]); 1440 if (i % WIDTH == WIDTH - 1) 1441 printf("\n"); 1442 } 1443 if (cc % WIDTH != 0) 1444 printf("\n"); 1445 } 1446 return(0); 1447} 1448 1449/* 1450 * Increment pointer until find the UDP or ICMP header. 1451 */ 1452void * 1453get_uphdr(struct ip6_hdr *ip6, u_char *lim) 1454{ 1455 u_char *cp = (u_char *)ip6, nh; 1456 int hlen; 1457 static u_char none_hdr[1]; /* Fake pointer for IPPROTO_NONE. */ 1458 1459 if (cp + sizeof(*ip6) > lim) 1460 return(NULL); 1461 1462 nh = ip6->ip6_nxt; 1463 cp += sizeof(struct ip6_hdr); 1464 1465 while (lim - cp >= (nh == IPPROTO_NONE ? 0 : 8)) { 1466 switch (nh) { 1467 case IPPROTO_ESP: 1468 return(NULL); 1469 case IPPROTO_ICMPV6: 1470 return(useproto == nh ? cp : NULL); 1471 case IPPROTO_SCTP: 1472 case IPPROTO_TCP: 1473 case IPPROTO_UDP: 1474 return(useproto == nh ? cp : NULL); 1475 case IPPROTO_NONE: 1476 return(useproto == nh ? none_hdr : NULL); 1477 case IPPROTO_FRAGMENT: 1478 hlen = sizeof(struct ip6_frag); 1479 nh = ((struct ip6_frag *)cp)->ip6f_nxt; 1480 break; 1481 case IPPROTO_AH: 1482 hlen = (((struct ip6_ext *)cp)->ip6e_len + 2) << 2; 1483 nh = ((struct ip6_ext *)cp)->ip6e_nxt; 1484 break; 1485 default: 1486 hlen = (((struct ip6_ext *)cp)->ip6e_len + 1) << 3; 1487 nh = ((struct ip6_ext *)cp)->ip6e_nxt; 1488 break; 1489 } 1490 1491 cp += hlen; 1492 } 1493 1494 return(NULL); 1495} 1496 1497void 1498print(struct msghdr *mhdr, int cc) 1499{ 1500 struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name; 1501 char hbuf[NI_MAXHOST]; 1502 1503 if (getnameinfo((struct sockaddr *)from, from->sin6_len, 1504 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) 1505 strlcpy(hbuf, "invalid", sizeof(hbuf)); 1506 if (as_path) 1507 printf(" [AS%u]", as_lookup(asn, hbuf, AF_INET6)); 1508 if (nflag) 1509 printf(" %s", hbuf); 1510 else if (lflag) 1511 printf(" %s (%s)", inetname((struct sockaddr *)from), hbuf); 1512 else 1513 printf(" %s", inetname((struct sockaddr *)from)); 1514 1515 if (verbose) { 1516#ifdef OLDRAWSOCKET 1517 printf(" %d bytes to %s", cc, 1518 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr, 1519 hbuf, sizeof(hbuf)) : "?"); 1520#else 1521 printf(" %d bytes of data to %s", cc, 1522 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr, 1523 hbuf, sizeof(hbuf)) : "?"); 1524#endif 1525 } 1526} 1527 1528/* 1529 * Construct an Internet address representation. 1530 * If the nflag has been supplied, give 1531 * numeric value, otherwise try for symbolic name. 1532 */ 1533const char * 1534inetname(struct sockaddr *sa) 1535{ 1536 static char line[NI_MAXHOST], domain[MAXHOSTNAMELEN + 1]; 1537 static int first = 1; 1538 char *cp; 1539 1540 if (first && !nflag) { 1541 first = 0; 1542 if (gethostname(domain, sizeof(domain)) == 0 && 1543 (cp = strchr(domain, '.'))) 1544 (void) strlcpy(domain, cp + 1, sizeof(domain)); 1545 else 1546 domain[0] = 0; 1547 } 1548 cp = NULL; 1549 if (!nflag) { 1550 if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0, 1551 NI_NAMEREQD) == 0) { 1552 if ((cp = strchr(line, '.')) && 1553 !strcmp(cp + 1, domain)) 1554 *cp = 0; 1555 cp = line; 1556 } 1557 } 1558 if (cp) 1559 return cp; 1560 1561 if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0, 1562 NI_NUMERICHOST) != 0) 1563 strlcpy(line, "invalid", sizeof(line)); 1564 return line; 1565} 1566 1567/* 1568 * CRC32C routine for the Stream Control Transmission Protocol 1569 */ 1570 1571#define CRC32C(c, d) (c = (c>>8) ^ crc_c[(c^(d))&0xFF]) 1572 1573static u_int32_t crc_c[256] = { 1574 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 1575 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, 1576 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 1577 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, 1578 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 1579 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, 1580 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 1581 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, 1582 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 1583 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, 1584 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 1585 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, 1586 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 1587 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, 1588 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 1589 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, 1590 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 1591 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, 1592 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 1593 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, 1594 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 1595 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, 1596 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 1597 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, 1598 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 1599 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, 1600 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 1601 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, 1602 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 1603 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, 1604 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 1605 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, 1606 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 1607 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, 1608 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 1609 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, 1610 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 1611 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, 1612 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 1613 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, 1614 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 1615 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, 1616 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 1617 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, 1618 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 1619 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, 1620 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 1621 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, 1622 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 1623 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, 1624 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 1625 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, 1626 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 1627 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, 1628 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 1629 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, 1630 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 1631 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, 1632 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 1633 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, 1634 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 1635 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, 1636 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 1637 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351 1638}; 1639 1640u_int32_t 1641sctp_crc32c(void *packet, u_int32_t len) 1642{ 1643 u_int32_t i, crc32c; 1644 u_int8_t byte0, byte1, byte2, byte3; 1645 u_int8_t *buf = (u_int8_t *)packet; 1646 1647 crc32c = ~0; 1648 for (i = 0; i < len; i++) 1649 CRC32C(crc32c, buf[i]); 1650 crc32c = ~crc32c; 1651 byte0 = crc32c & 0xff; 1652 byte1 = (crc32c>>8) & 0xff; 1653 byte2 = (crc32c>>16) & 0xff; 1654 byte3 = (crc32c>>24) & 0xff; 1655 crc32c = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3); 1656 return htonl(crc32c); 1657} 1658 1659u_int16_t 1660in_cksum(u_int16_t *addr, int len) 1661{ 1662 int nleft = len; 1663 u_int16_t *w = addr; 1664 u_int16_t answer; 1665 int sum = 0; 1666 1667 /* 1668 * Our algorithm is simple, using a 32 bit accumulator (sum), 1669 * we add sequential 16 bit words to it, and at the end, fold 1670 * back all the carry bits from the top 16 bits into the lower 1671 * 16 bits. 1672 */ 1673 while (nleft > 1) { 1674 sum += *w++; 1675 nleft -= 2; 1676 } 1677 1678 /* mop up an odd byte, if necessary */ 1679 if (nleft == 1) 1680 sum += *(u_char *)w; 1681 1682 /* 1683 * add back carry outs from top 16 bits to low 16 bits 1684 */ 1685 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 1686 sum += (sum >> 16); /* add carry */ 1687 answer = ~sum; /* truncate to 16 bits */ 1688 return (answer); 1689} 1690 1691u_int16_t 1692tcp_chksum(struct sockaddr_in6 *src, struct sockaddr_in6 *dst, 1693 void *payload, u_int32_t len) 1694{ 1695 struct { 1696 struct in6_addr src; 1697 struct in6_addr dst; 1698 u_int32_t len; 1699 u_int8_t zero[3]; 1700 u_int8_t next; 1701 } pseudo_hdr; 1702 u_int16_t sum[2]; 1703 1704 pseudo_hdr.src = src->sin6_addr; 1705 pseudo_hdr.dst = dst->sin6_addr; 1706 pseudo_hdr.len = htonl(len); 1707 pseudo_hdr.zero[0] = 0; 1708 pseudo_hdr.zero[1] = 0; 1709 pseudo_hdr.zero[2] = 0; 1710 pseudo_hdr.next = IPPROTO_TCP; 1711 1712 sum[1] = in_cksum((u_int16_t *)&pseudo_hdr, sizeof(pseudo_hdr)); 1713 sum[0] = in_cksum(payload, len); 1714 1715 return (~in_cksum(sum, sizeof(sum))); 1716} 1717 1718void 1719usage(void) 1720{ 1721 1722 fprintf(stderr, 1723"usage: traceroute6 [-adIlnNrSTUv] [-A as_server] [-f firsthop] [-g gateway]\n" 1724" [-m hoplimit] [-p port] [-q probes] [-s src] [-w waittime] target\n" 1725" [datalen]\n"); 1726 exit(1); 1727} 1728