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