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