1 /* $OpenBSD: traceroute.c,v 1.61 2004/01/26 18:23:51 deraadt Exp $ */ 2 /* $NetBSD: traceroute.c,v 1.10 1995/05/21 15:50:45 mycroft Exp $ */ 3 4 /*- 5 * Copyright (c) 1990, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Van Jacobson. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * $DragonFly: src/usr.sbin/traceroute/traceroute.c,v 1.6 2004/12/18 22:48:14 swildner Exp $ 36 * @(#)traceroute.c 8.1 (Berkeley) 6/6/93 37 */ 38 39 /* 40 * traceroute host - trace the route ip packets follow going to "host". 41 * 42 * Attempt to trace the route an ip packet would follow to some 43 * internet host. We find out intermediate hops by launching probe 44 * packets with a small ttl (time to live) then listening for an 45 * icmp "time exceeded" reply from a gateway. We start our probes 46 * with a ttl of one and increase by one until we get an icmp "port 47 * unreachable" (which means we got to "host") or hit a max (which 48 * defaults to 64 hops & can be changed with the -m flag). Three 49 * probes (change with -q flag) are sent at each ttl setting and a 50 * line is printed showing the ttl, address of the gateway and 51 * round trip time of each probe. If the probe answers come from 52 * different gateways, the address of each responding system will 53 * be printed. If there is no response within a 5 sec. timeout 54 * interval (changed with the -w flag), a "*" is printed for that 55 * probe. 56 * 57 * Probe packets are UDP format. We don't want the destination 58 * host to process them so the destination port is set to an 59 * unlikely value (if some clod on the destination is using that 60 * value, it can be changed with the -p flag). 61 * 62 * A sample use might be: 63 * 64 * [yak 71]% traceroute nis.nsf.net. 65 * traceroute to nis.nsf.net (35.1.1.48), 64 hops max, 56 byte packet 66 * 1 helios.ee.lbl.gov (128.3.112.1) 19 ms 19 ms 0 ms 67 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms 68 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms 69 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 39 ms 70 * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 39 ms 39 ms 39 ms 71 * 6 128.32.197.4 (128.32.197.4) 40 ms 59 ms 59 ms 72 * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 59 ms 73 * 8 129.140.70.13 (129.140.70.13) 99 ms 99 ms 80 ms 74 * 9 129.140.71.6 (129.140.71.6) 139 ms 239 ms 319 ms 75 * 10 129.140.81.7 (129.140.81.7) 220 ms 199 ms 199 ms 76 * 11 nic.merit.edu (35.1.1.48) 239 ms 239 ms 239 ms 77 * 78 * Note that lines 2 & 3 are the same. This is due to a buggy 79 * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards 80 * packets with a zero ttl. 81 * 82 * A more interesting example is: 83 * 84 * [yak 72]% traceroute allspice.lcs.mit.edu. 85 * traceroute to allspice.lcs.mit.edu (18.26.0.115), 64 hops max 86 * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms 87 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 19 ms 19 ms 88 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 19 ms 89 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 19 ms 39 ms 39 ms 90 * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 20 ms 39 ms 39 ms 91 * 6 128.32.197.4 (128.32.197.4) 59 ms 119 ms 39 ms 92 * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 39 ms 93 * 8 129.140.70.13 (129.140.70.13) 80 ms 79 ms 99 ms 94 * 9 129.140.71.6 (129.140.71.6) 139 ms 139 ms 159 ms 95 * 10 129.140.81.7 (129.140.81.7) 199 ms 180 ms 300 ms 96 * 11 129.140.72.17 (129.140.72.17) 300 ms 239 ms 239 ms 97 * 12 * * * 98 * 13 128.121.54.72 (128.121.54.72) 259 ms 499 ms 279 ms 99 * 14 * * * 100 * 15 * * * 101 * 16 * * * 102 * 17 * * * 103 * 18 ALLSPICE.LCS.MIT.EDU (18.26.0.115) 339 ms 279 ms 279 ms 104 * 105 * (I start to see why I'm having so much trouble with mail to 106 * MIT.) Note that the gateways 12, 14, 15, 16 & 17 hops away 107 * either don't send ICMP "time exceeded" messages or send them 108 * with a ttl too small to reach us. 14 - 17 are running the 109 * MIT C Gateway code that doesn't send "time exceeded"s. God 110 * only knows what's going on with 12. 111 * 112 * The silent gateway 12 in the above may be the result of a bug in 113 * the 4.[23]BSD network code (and its derivatives): 4.x (x <= 3) 114 * sends an unreachable message using whatever ttl remains in the 115 * original datagram. Since, for gateways, the remaining ttl is 116 * zero, the icmp "time exceeded" is guaranteed to not make it back 117 * to us. The behavior of this bug is slightly more interesting 118 * when it appears on the destination system: 119 * 120 * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms 121 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 39 ms 122 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 39 ms 19 ms 123 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 19 ms 124 * 5 ccn-nerif35.Berkeley.EDU (128.32.168.35) 39 ms 39 ms 39 ms 125 * 6 csgw.Berkeley.EDU (128.32.133.254) 39 ms 59 ms 39 ms 126 * 7 * * * 127 * 8 * * * 128 * 9 * * * 129 * 10 * * * 130 * 11 * * * 131 * 12 * * * 132 * 13 rip.Berkeley.EDU (128.32.131.22) 59 ms ! 39 ms ! 39 ms ! 133 * 134 * Notice that there are 12 "gateways" (13 is the final 135 * destination) and exactly the last half of them are "missing". 136 * What's really happening is that rip (a Sun-3 running Sun OS3.5) 137 * is using the ttl from our arriving datagram as the ttl in its 138 * icmp reply. So, the reply will time out on the return path 139 * (with no notice sent to anyone since icmp's aren't sent for 140 * icmp's) until we probe with a ttl that's at least twice the path 141 * length. I.e., rip is really only 7 hops away. A reply that 142 * returns with a ttl of 1 is a clue this problem exists. 143 * Traceroute prints a "!" after the time if the ttl is <= 1. 144 * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or 145 * non-standard (HPUX) software, expect to see this problem 146 * frequently and/or take care picking the target host of your 147 * probes. 148 * 149 * Other possible annotations after the time are !H, !N, !P (got a host, 150 * network or protocol unreachable, respectively), !S or !F (source 151 * route failed or fragmentation needed -- neither of these should 152 * ever occur and the associated gateway is busted if you see one). If 153 * almost all the probes result in some kind of unreachable, traceroute 154 * will give up and exit. 155 * 156 * Notes 157 * ----- 158 * This program must be run by root or be setuid. (I suggest that 159 * you *don't* make it setuid -- casual use could result in a lot 160 * of unnecessary traffic on our poor, congested nets.) 161 * 162 * This program requires a kernel mod that does not appear in any 163 * system available from Berkeley: A raw ip socket using proto 164 * IPPROTO_RAW must interpret the data sent as an ip datagram (as 165 * opposed to data to be wrapped in a ip datagram). See the README 166 * file that came with the source to this program for a description 167 * of the mods I made to /sys/netinet/raw_ip.c. Your mileage may 168 * vary. But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE 169 * MODIFIED TO RUN THIS PROGRAM. 170 * 171 * The udp port usage may appear bizarre (well, ok, it is bizarre). 172 * The problem is that an icmp message only contains 8 bytes of 173 * data from the original datagram. 8 bytes is the size of a udp 174 * header so, if we want to associate replies with the original 175 * datagram, the necessary information must be encoded into the 176 * udp header (the ip id could be used but there's no way to 177 * interlock with the kernel's assignment of ip id's and, anyway, 178 * it would have taken a lot more kernel hacking to allow this 179 * code to set the ip id). So, to allow two or more users to 180 * use traceroute simultaneously, we use this task's pid as the 181 * source port (the high bit is set to move the port number out 182 * of the "likely" range). To keep track of which probe is being 183 * replied to (so times and/or hop counts don't get confused by a 184 * reply that was delayed in transit), we increment the destination 185 * port number before each probe. 186 * 187 * Don't use this as a coding example. I was trying to find a 188 * routing problem and this code sort-of popped out after 48 hours 189 * without sleep. I was amazed it ever compiled, much less ran. 190 * 191 * I stole the idea for this program from Steve Deering. Since 192 * the first release, I've learned that had I attended the right 193 * IETF working group meetings, I also could have stolen it from Guy 194 * Almes or Matt Mathis. I don't know (or care) who came up with 195 * the idea first. I envy the originators' perspicacity and I'm 196 * glad they didn't keep the idea a secret. 197 * 198 * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or 199 * enhancements to the original distribution. 200 * 201 * I've hacked up a round-trip-route version of this that works by 202 * sending a loose-source-routed udp datagram through the destination 203 * back to yourself. Unfortunately, SO many gateways botch source 204 * routing, the thing is almost worthless. Maybe one day... 205 * 206 * -- Van Jacobson (van@helios.ee.lbl.gov) 207 * Tue Dec 20 03:50:13 PST 1988 208 */ 209 210 #include <sys/param.h> 211 #include <sys/time.h> 212 #include <sys/socket.h> 213 #include <sys/file.h> 214 #include <sys/ioctl.h> 215 #include <sys/sysctl.h> 216 217 #include <netinet/in_systm.h> 218 #include <netinet/in.h> 219 #include <netinet/ip.h> 220 #include <netinet/ip_icmp.h> 221 #include <netinet/ip_var.h> 222 #include <netinet/udp.h> 223 224 #include <arpa/inet.h> 225 226 #include <ctype.h> 227 #include <err.h> 228 #include <errno.h> 229 #include <netdb.h> 230 #include <stdio.h> 231 #include <stdlib.h> 232 #include <string.h> 233 #include <unistd.h> 234 235 #define MAX_LSRR ((MAX_IPOPTLEN - 4) / 4) 236 237 /* 238 * Format of the data in a (udp) probe packet. 239 */ 240 struct packetdata { 241 u_char seq; /* sequence number of this packet */ 242 u_int8_t ttl; /* ttl packet left with */ 243 u_int32_t sec; /* time packet left */ 244 u_int32_t usec; 245 }; 246 247 struct in_addr gateway[MAX_LSRR + 1]; 248 int lsrrlen = 0; 249 int32_t sec_perturb; 250 int32_t usec_perturb; 251 252 u_char packet[512], *outpacket; /* last inbound (icmp) packet */ 253 254 void dump_packet(void); 255 int wait_for_reply(int, struct sockaddr_in *, struct timeval *); 256 void send_probe(int, u_int8_t, int, struct sockaddr_in *); 257 int packet_ok(u_char *, int, struct sockaddr_in *, int, int); 258 const char *pr_type(u_int8_t); 259 void print(u_char *, int, struct sockaddr_in *); 260 char *inetname(struct in_addr); 261 u_short in_cksum(u_short *, int); 262 void usage(void); 263 264 int s; /* receive (icmp) socket file descriptor */ 265 int sndsock; /* send (udp) socket file descriptor */ 266 267 int datalen; /* How much data */ 268 int headerlen; /* How long packet's header is */ 269 270 char *source = 0; 271 char *hostname; 272 273 int nprobes = 3; 274 u_int8_t max_ttl = IPDEFTTL; 275 u_int8_t first_ttl = 1; 276 u_short ident; 277 u_short port = 32768+666; /* start udp dest port # for probe packets */ 278 u_char proto = IPPROTO_UDP; 279 u_int8_t icmp_type = ICMP_ECHO; /* default ICMP code/type */ 280 u_char icmp_code = 0; 281 int options; /* socket options */ 282 int verbose; 283 int waittime = 5; /* time to wait for response (in seconds) */ 284 int nflag; /* print addresses numerically */ 285 int dump; 286 287 int 288 main(int argc, char *argv[]) 289 { 290 int mib[4] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_DEFTTL }; 291 int ttl_flag = 0, incflag = 1, protoset = 0, sump = 0; 292 int ch, i, lsrr = 0, on = 1, probe, seq = 0, tos = 0; 293 size_t size = sizeof(max_ttl); 294 struct sockaddr_in from, to; 295 struct hostent *hp; 296 u_int32_t tmprnd; 297 struct ip *ip; 298 u_int8_t ttl; 299 char *ep; 300 long l; 301 302 if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) 303 err(5, "icmp socket"); 304 if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) 305 err(5, "raw socket"); 306 307 /* revoke privs */ 308 seteuid(getuid()); 309 setuid(getuid()); 310 311 sysctl(mib, sizeof(mib)/sizeof(mib[0]), &max_ttl, &size, NULL, 0); 312 313 while ((ch = getopt(argc, argv, "SDIdg:f:m:np:q:rs:t:w:vlP:c")) != -1) 314 switch (ch) { 315 case 'S': 316 sump = 1; 317 break; 318 case 'f': 319 errno = 0; 320 ep = NULL; 321 l = strtol(optarg, &ep, 10); 322 if (errno || !*optarg || *ep || l < 1 || l > max_ttl) 323 errx(1, "min ttl must be 1 to %u.", max_ttl); 324 first_ttl = (u_int8_t)l; 325 break; 326 case 'c': 327 incflag = 0; 328 break; 329 case 'd': 330 options |= SO_DEBUG; 331 break; 332 case 'D': 333 dump = 1; 334 break; 335 case 'g': 336 if (lsrr >= MAX_LSRR) 337 errx(1, "too many gateways; max %d", MAX_LSRR); 338 if (inet_aton(optarg, &gateway[lsrr]) == 0) { 339 hp = gethostbyname(optarg); 340 if (hp == 0) 341 errx(1, "unknown host %s", optarg); 342 memcpy(&gateway[lsrr], hp->h_addr, hp->h_length); 343 } 344 if (++lsrr == 1) 345 lsrrlen = 4; 346 lsrrlen += 4; 347 break; 348 case 'I': 349 if (protoset) 350 errx(1, "protocol already set with -P"); 351 protoset = 1; 352 proto = IPPROTO_ICMP; 353 break; 354 case 'l': 355 ttl_flag++; 356 break; 357 case 'm': 358 errno = 0; 359 ep = NULL; 360 l = strtol(optarg, &ep, 10); 361 if (errno || !*optarg || *ep || l < first_ttl || 362 l > MAXTTL) 363 errx(1, "max ttl must be %u to %u.", first_ttl, 364 MAXTTL); 365 max_ttl = (u_int8_t)l; 366 break; 367 case 'n': 368 nflag++; 369 break; 370 case 'p': 371 errno = 0; 372 ep = NULL; 373 l = strtol(optarg, &ep, 10); 374 if (errno || !*optarg || *ep || l <= 0 || l >= 65536) 375 errx(1, "port must be >0, <65536."); 376 port = (int)l; 377 break; 378 case 'P': 379 if (protoset) 380 errx(1, "protocol already set with -I"); 381 protoset = 1; 382 errno = 0; 383 ep = NULL; 384 l = strtol(optarg, &ep, 10); 385 if (errno || !*optarg || *ep || l < 1 || 386 l >= IPPROTO_MAX) { 387 struct protoent *pent; 388 389 pent = getprotobyname(optarg); 390 if (pent) 391 proto = pent->p_proto; 392 else 393 errx(1, "proto must be >=1, or a name."); 394 } else 395 proto = (int)l; 396 break; 397 case 'q': 398 errno = 0; 399 ep = NULL; 400 l = strtol(optarg, &ep, 10); 401 if (errno || !*optarg || *ep || l < 1 || l > INT_MAX) 402 errx(1, "nprobes must be >0."); 403 nprobes = (int)l; 404 break; 405 case 'r': 406 options |= SO_DONTROUTE; 407 break; 408 case 's': 409 /* 410 * set the ip source address of the outbound 411 * probe (e.g., on a multi-homed host). 412 */ 413 source = optarg; 414 break; 415 case 't': 416 errno = 0; 417 ep = NULL; 418 l = strtol(optarg, &ep, 10); 419 if (errno || !*optarg || *ep || l < 0 || l > 255) 420 errx(1, "tos must be 0 to 255."); 421 tos = (int)l; 422 break; 423 case 'v': 424 verbose++; 425 break; 426 case 'w': 427 errno = 0; 428 ep = NULL; 429 l = strtol(optarg, &ep, 10); 430 if (errno || !*optarg || *ep || l <= 1 || l > INT_MAX) 431 errx(1, "wait must be >1 sec."); 432 waittime = (int)l; 433 break; 434 default: 435 usage(); 436 } 437 argc -= optind; 438 argv += optind; 439 440 if (argc < 1) 441 usage(); 442 443 setlinebuf (stdout); 444 445 memset(&to, 0, sizeof(struct sockaddr)); 446 to.sin_family = AF_INET; 447 if (inet_aton(*argv, &to.sin_addr) != 0) 448 hostname = *argv; 449 else { 450 hp = gethostbyname(*argv); 451 if (hp == 0) 452 errx(1, "unknown host %s", *argv); 453 to.sin_family = hp->h_addrtype; 454 memcpy(&to.sin_addr, hp->h_addr, hp->h_length); 455 if ((hostname = strdup(hp->h_name)) == NULL) 456 err(1, "malloc"); 457 if (hp->h_addr_list[1] != NULL) 458 warnx("Warning: %s has multiple addresses; using %s", 459 hostname, inet_ntoa(to.sin_addr)); 460 } 461 if (*++argv) { 462 errno = 0; 463 ep = NULL; 464 l = strtol(*argv, &ep, 10); 465 if (errno || !*argv || *ep || l < 0 || l > INT_MAX) 466 errx(1, "datalen out of range"); 467 datalen = (int)l; 468 } 469 470 switch (proto) { 471 case IPPROTO_UDP: 472 headerlen = (sizeof(struct ip) + lsrrlen + 473 sizeof(struct udphdr) + sizeof(struct packetdata)); 474 break; 475 case IPPROTO_ICMP: 476 headerlen = (sizeof(struct ip) + lsrrlen + 477 sizeof(struct icmp) + sizeof(struct packetdata)); 478 break; 479 default: 480 headerlen = (sizeof(struct ip) + lsrrlen + 481 sizeof(struct packetdata)); 482 } 483 484 if (datalen < 0 || datalen > IP_MAXPACKET - headerlen) 485 errx(1, "packet size must be 0 to %d.", 486 IP_MAXPACKET - headerlen); 487 488 datalen += headerlen; 489 490 outpacket = (u_char *)malloc(datalen); 491 if (outpacket == NULL) 492 err(1, "malloc"); 493 memset(outpacket, 0, datalen); 494 495 ip = (struct ip *)outpacket; 496 if (lsrr != 0) { 497 u_char *p = (u_char *)(ip + 1); 498 499 *p++ = IPOPT_NOP; 500 *p++ = IPOPT_LSRR; 501 *p++ = lsrrlen - 1; 502 *p++ = IPOPT_MINOFF; 503 gateway[lsrr] = to.sin_addr; 504 for (i = 1; i <= lsrr; i++) { 505 memcpy(p, &gateway[i], sizeof(struct in_addr)); 506 p += sizeof(struct in_addr); 507 } 508 ip->ip_dst = gateway[0]; 509 } else 510 ip->ip_dst = to.sin_addr; 511 ip->ip_off = htons(0); 512 ip->ip_hl = (sizeof(struct ip) + lsrrlen) >> 2; 513 ip->ip_p = proto; 514 ip->ip_v = IPVERSION; 515 ip->ip_tos = tos; 516 517 ident = (getpid() & 0xffff) | 0x8000; 518 tmprnd = arc4random(); 519 sec_perturb = (tmprnd & 0x80000000) ? -(tmprnd & 0x7ff) : 520 (tmprnd & 0x7ff); 521 usec_perturb = arc4random(); 522 523 if (options & SO_DEBUG) 524 setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof(on)); 525 #ifdef SO_SNDBUF 526 if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&datalen, 527 sizeof(datalen)) < 0) 528 err(6, "SO_SNDBUF"); 529 #endif /* SO_SNDBUF */ 530 #ifdef IP_HDRINCL 531 if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on, 532 sizeof(on)) < 0) 533 err(6, "IP_HDRINCL"); 534 #endif /* IP_HDRINCL */ 535 if (options & SO_DEBUG) 536 setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, 537 (char *)&on, sizeof(on)); 538 if (options & SO_DONTROUTE) 539 setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, 540 (char *)&on, sizeof(on)); 541 542 if (source) { 543 memset(&from, 0, sizeof(struct sockaddr)); 544 from.sin_family = AF_INET; 545 if (inet_aton(source, &from.sin_addr) == 0) 546 errx(1, "unknown host %s", source); 547 ip->ip_src = from.sin_addr; 548 if (getuid() != 0 && 549 (ntohl(from.sin_addr.s_addr) & 0xff000000U) == 0x7f000000U && 550 (ntohl(to.sin_addr.s_addr) & 0xff000000U) != 0x7f000000U) 551 errx(1, "source is on 127/8, destination is not"); 552 553 if (getuid() && 554 bind(sndsock, (struct sockaddr *)&from, sizeof(from)) < 0) 555 err(1, "bind"); 556 } 557 558 fprintf(stderr, "traceroute to %s (%s)", hostname, 559 inet_ntoa(to.sin_addr)); 560 if (source) 561 fprintf(stderr, " from %s", source); 562 fprintf(stderr, ", %u hops max, %d byte packets\n", max_ttl, datalen); 563 fflush(stderr); 564 565 if (first_ttl > 1) 566 printf("Skipping %u intermediate hops\n", first_ttl - 1); 567 568 for (ttl = first_ttl; ttl <= max_ttl; ++ttl) { 569 int got_there = 0, unreachable = 0, timeout = 0, loss; 570 in_addr_t lastaddr = 0; 571 quad_t dt; 572 573 printf("%2u ", ttl); 574 for (probe = 0, loss = 0; probe < nprobes; ++probe) { 575 int cc; 576 struct timeval t1, t2; 577 int code; 578 579 gettimeofday(&t1, NULL); 580 send_probe(++seq, ttl, incflag, &to); 581 while ((cc = wait_for_reply(s, &from, &t1))) { 582 gettimeofday(&t2, NULL); 583 if (t2.tv_sec - t1.tv_sec > waittime) { 584 cc = 0; 585 break; 586 } 587 i = packet_ok(packet, cc, &from, seq, incflag); 588 /* Skip short packet */ 589 if (i == 0) 590 continue; 591 if (from.sin_addr.s_addr != lastaddr) { 592 print(packet, cc, &from); 593 lastaddr = from.sin_addr.s_addr; 594 } 595 dt = (quad_t)(t2.tv_sec - t1.tv_sec) * 1000000 + 596 (quad_t)(t2.tv_usec - t1.tv_usec); 597 printf(" %u", (u_int)(dt / 1000)); 598 if (dt % 1000) 599 printf(".%u", (u_int)(dt % 1000)); 600 printf(" ms"); 601 ip = (struct ip *)packet; 602 if (ttl_flag) 603 printf(" (%u)", ip->ip_ttl); 604 if (i == -2) { 605 #ifndef ARCHAIC 606 ip = (struct ip *)packet; 607 if (ip->ip_ttl <= 1) 608 printf(" !"); 609 #endif 610 ++got_there; 611 break; 612 } 613 /* time exceeded in transit */ 614 if (i == -1) 615 break; 616 code = i - 1; 617 switch (code) { 618 case ICMP_UNREACH_PORT: 619 #ifndef ARCHAIC 620 ip = (struct ip *)packet; 621 if (ip->ip_ttl <= 1) 622 printf(" !"); 623 #endif /* ARCHAIC */ 624 ++got_there; 625 break; 626 case ICMP_UNREACH_NET: 627 ++unreachable; 628 printf(" !N"); 629 break; 630 case ICMP_UNREACH_HOST: 631 ++unreachable; 632 printf(" !H"); 633 break; 634 case ICMP_UNREACH_PROTOCOL: 635 ++got_there; 636 printf(" !P"); 637 break; 638 case ICMP_UNREACH_NEEDFRAG: 639 ++unreachable; 640 printf(" !F"); 641 break; 642 case ICMP_UNREACH_SRCFAIL: 643 ++unreachable; 644 printf(" !S"); 645 break; 646 case ICMP_UNREACH_FILTER_PROHIB: 647 ++unreachable; 648 printf(" !X"); 649 break; 650 case ICMP_UNREACH_NET_PROHIB: /*misuse*/ 651 ++unreachable; 652 printf(" !A"); 653 break; 654 case ICMP_UNREACH_HOST_PROHIB: 655 ++unreachable; 656 printf(" !C"); 657 break; 658 case ICMP_UNREACH_NET_UNKNOWN: 659 case ICMP_UNREACH_HOST_UNKNOWN: 660 ++unreachable; 661 printf(" !U"); 662 break; 663 case ICMP_UNREACH_ISOLATED: 664 ++unreachable; 665 printf(" !I"); 666 break; 667 case ICMP_UNREACH_TOSNET: 668 case ICMP_UNREACH_TOSHOST: 669 ++unreachable; 670 printf(" !T"); 671 break; 672 default: 673 ++unreachable; 674 printf(" !<%d>", i - 1); 675 break; 676 } 677 break; 678 } 679 if (cc == 0) { 680 printf(" *"); 681 timeout++; 682 loss++; 683 } 684 fflush(stdout); 685 } 686 if (sump) 687 printf(" (%d%% loss)", (loss * 100) / nprobes); 688 putchar('\n'); 689 if (got_there || (unreachable && (unreachable + timeout) >= nprobes)) 690 break; 691 } 692 exit(0); 693 } 694 695 int 696 wait_for_reply(int sock, struct sockaddr_in *from, struct timeval *sent) 697 { 698 socklen_t fromlen = sizeof (*from); 699 struct timeval now, wait; 700 int cc = 0, fdsn; 701 fd_set *fdsp; 702 703 fdsn = howmany(sock+1, NFDBITS) * sizeof(fd_mask); 704 if ((fdsp = (fd_set *)malloc(fdsn)) == NULL) 705 err(1, "malloc"); 706 memset(fdsp, 0, fdsn); 707 FD_SET(sock, fdsp); 708 gettimeofday(&now, NULL); 709 wait.tv_sec = (sent->tv_sec + waittime) - now.tv_sec; 710 wait.tv_usec = sent->tv_usec - now.tv_usec; 711 if (wait.tv_usec < 0) { 712 wait.tv_usec += 1000000; 713 wait.tv_sec--; 714 } 715 if (wait.tv_sec < 0) 716 wait.tv_sec = wait.tv_usec = 0; 717 718 if (select(sock+1, fdsp, (fd_set *)0, (fd_set *)0, &wait) > 0) 719 cc = recvfrom(s, (char *)packet, sizeof(packet), 0, 720 (struct sockaddr *)from, &fromlen); 721 722 free(fdsp); 723 return (cc); 724 } 725 726 void 727 dump_packet(void) 728 { 729 u_char *p; 730 int i; 731 732 fprintf(stderr, "packet data:"); 733 for (p = outpacket, i = 0; i < datalen; i++) { 734 if ((i % 24) == 0) 735 fprintf(stderr, "\n "); 736 fprintf(stderr, " %02x", *p++); 737 } 738 fprintf(stderr, "\n"); 739 } 740 741 void 742 send_probe(int seq, u_int8_t ttl, int iflag, struct sockaddr_in *to) 743 { 744 struct ip *ip = (struct ip *)outpacket; 745 u_char *p = (u_char *)(ip + 1); 746 struct udphdr *up = (struct udphdr *)(p + lsrrlen); 747 struct icmp *icmpp = (struct icmp *)(p + lsrrlen); 748 struct packetdata *op; 749 struct timeval tv; 750 int i; 751 752 ip->ip_len = datalen; 753 ip->ip_ttl = ttl; 754 ip->ip_id = htons(ident+seq); 755 756 switch (proto) { 757 case IPPROTO_ICMP: 758 icmpp->icmp_type = icmp_type; 759 icmpp->icmp_code = icmp_code; 760 icmpp->icmp_seq = htons(seq); 761 icmpp->icmp_id = htons(ident); 762 op = (struct packetdata *)(icmpp + 1); 763 break; 764 case IPPROTO_UDP: 765 up->uh_sport = htons(ident); 766 if (iflag) 767 up->uh_dport = htons(port+seq); 768 else 769 up->uh_dport = htons(port); 770 up->uh_ulen = htons((u_short)(datalen - sizeof(struct ip) - 771 lsrrlen)); 772 up->uh_sum = 0; 773 op = (struct packetdata *)(up + 1); 774 break; 775 default: 776 op = (struct packetdata *)(ip + 1); 777 break; 778 } 779 op->seq = seq; 780 op->ttl = ttl; 781 782 /* 783 * We don't want hostiles snooping the net to get any useful 784 * information about us. Send the timestamp in network byte order, 785 * and perturb the timestamp enough that they won't know our 786 * real clock ticker. We don't want to perturb the time by too 787 * much: being off by a suspiciously large amount might indicate 788 * OpenBSD. 789 * 790 * The timestamps in the packet are currently unused. If future 791 * work wants to use them they will have to subtract out the 792 * perturbation first. 793 */ 794 gettimeofday(&tv, NULL); 795 op->sec = htonl(tv.tv_sec + sec_perturb); 796 op->usec = htonl((tv.tv_usec + usec_perturb) % 1000000); 797 798 if (proto == IPPROTO_ICMP && icmp_type == ICMP_ECHO) { 799 icmpp->icmp_cksum = 0; 800 icmpp->icmp_cksum = in_cksum((u_short *)icmpp, 801 datalen - sizeof(struct ip) - lsrrlen); 802 if (icmpp->icmp_cksum == 0) 803 icmpp->icmp_cksum = 0xffff; 804 } 805 806 if (dump) 807 dump_packet(); 808 809 i = sendto(sndsock, outpacket, datalen, 0, (struct sockaddr *)to, 810 sizeof(struct sockaddr_in)); 811 if (i < 0 || i != datalen) { 812 if (i < 0) 813 perror("sendto"); 814 printf("traceroute: wrote %s %d chars, ret=%d\n", hostname, 815 datalen, i); 816 fflush(stdout); 817 } 818 } 819 820 static const char *ttab[] = { 821 "Echo Reply", 822 "ICMP 1", 823 "ICMP 2", 824 "Dest Unreachable", 825 "Source Quench", 826 "Redirect", 827 "ICMP 6", 828 "ICMP 7", 829 "Echo", 830 "Router Advert", 831 "Router Solicit", 832 "Time Exceeded", 833 "Param Problem", 834 "Timestamp", 835 "Timestamp Reply", 836 "Info Request", 837 "Info Reply", 838 "Mask Request", 839 "Mask Reply" 840 }; 841 842 /* 843 * Convert an ICMP "type" field to a printable string. 844 */ 845 const char * 846 pr_type(u_int8_t t) 847 { 848 if (t > 18) 849 return ("OUT-OF-RANGE"); 850 return (ttab[t]); 851 } 852 853 int 854 packet_ok(u_char *buf, int cc, struct sockaddr_in *from, int seq, int iflag) 855 { 856 struct icmp *icp; 857 u_char code; 858 u_int8_t type; 859 int hlen; 860 #ifndef ARCHAIC 861 struct ip *ip; 862 863 ip = (struct ip *) buf; 864 hlen = ip->ip_hl << 2; 865 if (cc < hlen + ICMP_MINLEN) { 866 if (verbose) 867 printf("packet too short (%d bytes) from %s\n", cc, 868 inet_ntoa(from->sin_addr)); 869 return (0); 870 } 871 cc -= hlen; 872 icp = (struct icmp *)(buf + hlen); 873 #else 874 icp = (struct icmp *)buf; 875 #endif /* ARCHAIC */ 876 type = icp->icmp_type; 877 code = icp->icmp_code; 878 if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) || 879 type == ICMP_UNREACH || type == ICMP_ECHOREPLY) { 880 struct ip *hip; 881 struct udphdr *up; 882 struct icmp *icmpp; 883 884 hip = &icp->icmp_ip; 885 hlen = hip->ip_hl << 2; 886 887 switch (proto) { 888 case IPPROTO_ICMP: 889 if (icmp_type == ICMP_ECHO && 890 type == ICMP_ECHOREPLY && 891 icp->icmp_id == htons(ident) && 892 icp->icmp_seq == htons(seq)) 893 return (-2); /* we got there */ 894 895 icmpp = (struct icmp *)((u_char *)hip + hlen); 896 if (hlen + 8 <= cc && hip->ip_p == IPPROTO_ICMP && 897 icmpp->icmp_id == htons(ident) && 898 icmpp->icmp_seq == htons(seq)) 899 return (type == ICMP_TIMXCEED? -1 : code + 1); 900 break; 901 902 case IPPROTO_UDP: 903 up = (struct udphdr *)((u_char *)hip + hlen); 904 if (hlen + 12 <= cc && hip->ip_p == proto && 905 up->uh_sport == htons(ident) && 906 ((iflag && up->uh_dport == htons(port + seq)) || 907 (!iflag && up->uh_dport == htons(port)))) 908 return (type == ICMP_TIMXCEED? -1 : code + 1); 909 break; 910 default: 911 /* this is some odd, user specified proto, 912 * how do we check it? 913 */ 914 if (hip->ip_p == proto) 915 return (type == ICMP_TIMXCEED? -1 : code + 1); 916 } 917 } 918 #ifndef ARCHAIC 919 if (verbose) { 920 int i; 921 in_addr_t *lp = (in_addr_t *)&icp->icmp_ip; 922 923 printf("\n%d bytes from %s", cc, inet_ntoa(from->sin_addr)); 924 printf(" to %s", inet_ntoa(ip->ip_dst)); 925 printf(": icmp type %u (%s) code %d\n", type, pr_type(type), 926 icp->icmp_code); 927 for (i = 4; i < cc ; i += sizeof(in_addr_t)) 928 printf("%2d: x%8.8lx\n", i, (unsigned long)*lp++); 929 } 930 #endif /* ARCHAIC */ 931 return (0); 932 } 933 934 void 935 print(u_char *buf, int cc, struct sockaddr_in *from) 936 { 937 struct ip *ip; 938 int hlen; 939 940 ip = (struct ip *) buf; 941 hlen = ip->ip_hl << 2; 942 cc -= hlen; 943 944 if (nflag) 945 printf(" %s", inet_ntoa(from->sin_addr)); 946 else 947 printf(" %s (%s)", inetname(from->sin_addr), 948 inet_ntoa(from->sin_addr)); 949 950 if (verbose) 951 printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst)); 952 } 953 954 955 /* 956 * Checksum routine for Internet Protocol family headers (C Version) 957 */ 958 u_short 959 in_cksum(u_short *addr, int len) 960 { 961 u_short *w = addr, answer; 962 int nleft = len, sum = 0; 963 964 /* 965 * Our algorithm is simple, using a 32 bit accumulator (sum), 966 * we add sequential 16 bit words to it, and at the end, fold 967 * back all the carry bits from the top 16 bits into the lower 968 * 16 bits. 969 */ 970 while (nleft > 1) { 971 sum += *w++; 972 nleft -= 2; 973 } 974 975 /* mop up an odd byte, if necessary */ 976 if (nleft == 1) 977 sum += *(u_char *)w; 978 979 /* 980 * add back carry outs from top 16 bits to low 16 bits 981 */ 982 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 983 sum += (sum >> 16); /* add carry */ 984 answer = ~sum; /* truncate to 16 bits */ 985 return (answer); 986 } 987 988 /* 989 * Construct an Internet address representation. 990 * If the nflag has been supplied, give 991 * numeric value, otherwise try for symbolic name. 992 */ 993 char * 994 inetname(struct in_addr in) 995 { 996 static char domain[MAXHOSTNAMELEN], line[MAXHOSTNAMELEN]; 997 static int first = 1; 998 struct hostent *hp; 999 char *cp; 1000 1001 if (first && !nflag) { 1002 first = 0; 1003 if (gethostname(domain, sizeof domain) == 0 && 1004 (cp = strchr(domain, '.')) != NULL) { 1005 strlcpy(domain, cp + 1, sizeof(domain)); 1006 } 1007 } 1008 if (!nflag && in.s_addr != INADDR_ANY) { 1009 hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET); 1010 if (hp != NULL) { 1011 if ((cp = strchr(hp->h_name, '.')) != NULL && 1012 strcmp(cp + 1, domain) == 0) 1013 *cp = '\0'; 1014 strlcpy(line, hp->h_name, sizeof(line)); 1015 return (line); 1016 } 1017 } 1018 return (inet_ntoa(in)); 1019 } 1020 1021 void 1022 usage(void) 1023 { 1024 fprintf(stderr, 1025 "usage: %s [-cdDIlnrSv] [-f first_ttl] [-g gateway_addr] [-m max_ttl]\n" 1026 "\t[-p port] [-P proto] [-q nqueries] [-s src_addr] [-t tos]\n" 1027 "\t[-w waittime] host [packetsize]\n", getprogname()); 1028 exit(1); 1029 } 1030