traceroute.c revision 62786
1262566Sdes/* 276259Sgreen * Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996 376259Sgreen * The Regents of the University of California. All rights reserved. 476259Sgreen * 576259Sgreen * Redistribution and use in source and binary forms, with or without 676259Sgreen * modification, are permitted provided that: (1) source code distributions 776259Sgreen * retain the above copyright notice and this paragraph in its entirety, (2) 876259Sgreen * distributions including binary code include the above copyright notice and 976259Sgreen * this paragraph in its entirety in the documentation or other materials 1076259Sgreen * provided with the distribution, and (3) all advertising materials mentioning 1176259Sgreen * features or use of this software display the following acknowledgement: 1276259Sgreen * ``This product includes software developed by the University of California, 1376259Sgreen * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1476259Sgreen * the University nor the names of its contributors may be used to endorse 1592559Sdes * or promote products derived from this software without specific prior 1698941Sdes * written permission. 1798941Sdes * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1892559Sdes * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1998941Sdes * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2098941Sdes */ 2198941Sdes 2276259Sgreen#ifndef lint 2398941Sdesstatic const char copyright[] = 2476259Sgreen "@(#) Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996\n\ 2576259SgreenThe Regents of the University of California. All rights reserved.\n"; 2676259Sgreen#if 0 2776259Sgreenstatic const char rcsid[] = 2876259Sgreen "@(#)$Header: traceroute.c,v 1.43 96/09/27 20:08:10 leres Exp $ (LBL)"; 2992559Sdes#endif 3092559Sdesstatic const char rcsid[] = 3192559Sdes "$FreeBSD: head/contrib/traceroute/traceroute.c 62786 2000-07-07 19:44:36Z ghelmer $"; 3276259Sgreen#endif 3376259Sgreen 3476259Sgreen/* 3576259Sgreen * traceroute host - trace the route ip packets follow going to "host". 3676259Sgreen * 3792559Sdes * Attempt to trace the route an ip packet would follow to some 3892559Sdes * internet host. We find out intermediate hops by launching probe 3992559Sdes * packets with a small ttl (time to live) then listening for an 4092559Sdes * icmp "time exceeded" reply from a gateway. We start our probes 41221420Sdes * with a ttl of one and increase by one until we get an icmp "port 42262566Sdes * unreachable" (which means we got to "host") or hit a max (which 4392559Sdes * defaults to 30 hops & can be changed with the -m flag). Three 4492559Sdes * probes (change with -q flag) are sent at each ttl setting and a 4592559Sdes * line is printed showing the ttl, address of the gateway and 4692559Sdes * round trip time of each probe. If the probe answers come from 4776259Sgreen * different gateways, the address of each responding system will 4898941Sdes * be printed. If there is no response within a 5 sec. timeout 4976259Sgreen * interval (changed with the -w flag), a "*" is printed for that 5098941Sdes * probe. 5176259Sgreen * 5276259Sgreen * Probe packets are UDP format. We don't want the destination 5376259Sgreen * host to process them so the destination port is set to an 5476259Sgreen * unlikely value (if some clod on the destination is using that 5576259Sgreen * value, it can be changed with the -p flag). 5676259Sgreen * 5776259Sgreen * A sample use might be: 5876259Sgreen * 59192595Sdes * [yak 71]% traceroute nis.nsf.net. 6076259Sgreen * traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 56 byte packet 6176259Sgreen * 1 helios.ee.lbl.gov (128.3.112.1) 19 ms 19 ms 0 ms 6276259Sgreen * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms 6376259Sgreen * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms 6476259Sgreen * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 39 ms 6576259Sgreen * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 39 ms 39 ms 39 ms 6676259Sgreen * 6 128.32.197.4 (128.32.197.4) 40 ms 59 ms 59 ms 6776259Sgreen * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 59 ms 6876259Sgreen * 8 129.140.70.13 (129.140.70.13) 99 ms 99 ms 80 ms 69255767Sdes * 9 129.140.71.6 (129.140.71.6) 139 ms 239 ms 319 ms 7092559Sdes * 10 129.140.81.7 (129.140.81.7) 220 ms 199 ms 199 ms 71255767Sdes * 11 nic.merit.edu (35.1.1.48) 239 ms 239 ms 239 ms 7276259Sgreen * 7376259Sgreen * Note that lines 2 & 3 are the same. This is due to a buggy 7476259Sgreen * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards 7576259Sgreen * packets with a zero ttl. 7676259Sgreen * 77255767Sdes * A more interesting example is: 78255767Sdes * 79255767Sdes * [yak 72]% traceroute allspice.lcs.mit.edu. 80255767Sdes * traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max 81262566Sdes * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms 8276259Sgreen * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 19 ms 19 ms 8376259Sgreen * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 19 ms 84192595Sdes * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 19 ms 39 ms 39 ms 8576259Sgreen * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 20 ms 39 ms 39 ms 86192595Sdes * 6 128.32.197.4 (128.32.197.4) 59 ms 119 ms 39 ms 8776259Sgreen * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 39 ms 8876259Sgreen * 8 129.140.70.13 (129.140.70.13) 80 ms 79 ms 99 ms 89255767Sdes * 9 129.140.71.6 (129.140.71.6) 139 ms 139 ms 159 ms 9076259Sgreen * 10 129.140.81.7 (129.140.81.7) 199 ms 180 ms 300 ms 9176259Sgreen * 11 129.140.72.17 (129.140.72.17) 300 ms 239 ms 239 ms 9276259Sgreen * 12 * * * 9376259Sgreen * 13 128.121.54.72 (128.121.54.72) 259 ms 499 ms 279 ms 94192595Sdes * 14 * * * 9576259Sgreen * 15 * * * 9676259Sgreen * 16 * * * 9776259Sgreen * 17 * * * 9876259Sgreen * 18 ALLSPICE.LCS.MIT.EDU (18.26.0.115) 339 ms 279 ms 279 ms 99255767Sdes * 10092559Sdes * (I start to see why I'm having so much trouble with mail to 10192559Sdes * MIT.) Note that the gateways 12, 14, 15, 16 & 17 hops away 102255767Sdes * either don't send ICMP "time exceeded" messages or send them 10376259Sgreen * with a ttl too small to reach us. 14 - 17 are running the 10476259Sgreen * MIT C Gateway code that doesn't send "time exceeded"s. God 10576259Sgreen * only knows what's going on with 12. 10676259Sgreen * 10776259Sgreen * The silent gateway 12 in the above may be the result of a bug in 10876259Sgreen * the 4.[23]BSD network code (and its derivatives): 4.x (x <= 3) 10976259Sgreen * sends an unreachable message using whatever ttl remains in the 110255767Sdes * original datagram. Since, for gateways, the remaining ttl is 11192559Sdes * zero, the icmp "time exceeded" is guaranteed to not make it back 11276259Sgreen * to us. The behavior of this bug is slightly more interesting 11376259Sgreen * when it appears on the destination system: 11476259Sgreen * 11576259Sgreen * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms 11676259Sgreen * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 39 ms 11792559Sdes * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 39 ms 19 ms 11876259Sgreen * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 19 ms 11976259Sgreen * 5 ccn-nerif35.Berkeley.EDU (128.32.168.35) 39 ms 39 ms 39 ms 12076259Sgreen * 6 csgw.Berkeley.EDU (128.32.133.254) 39 ms 59 ms 39 ms 12176259Sgreen * 7 * * * 12276259Sgreen * 8 * * * 12398941Sdes * 9 * * * 124169966Sdes * 10 * * * 12598941Sdes * 11 * * * 12676259Sgreen * 12 * * * 12798684Sdes * 13 rip.Berkeley.EDU (128.32.131.22) 59 ms ! 39 ms ! 39 ms ! 12898941Sdes * 129137019Sdes * Notice that there are 12 "gateways" (13 is the final 13098941Sdes * destination) and exactly the last half of them are "missing". 13198684Sdes * What's really happening is that rip (a Sun-3 running Sun OS3.5) 132204917Sdes * is using the ttl from our arriving datagram as the ttl in its 133204917Sdes * icmp reply. So, the reply will time out on the return path 134204917Sdes * (with no notice sent to anyone since icmp's aren't sent for 135204917Sdes * icmp's) until we probe with a ttl that's at least twice the path 136204917Sdes * length. I.e., rip is really only 7 hops away. A reply that 13792559Sdes * returns with a ttl of 1 is a clue this problem exists. 13898941Sdes * Traceroute prints a "!" after the time if the ttl is <= 1. 139169966Sdes * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or 14098941Sdes * non-standard (HPUX) software, expect to see this problem 14192559Sdes * frequently and/or take care picking the target host of your 14292559Sdes * probes. 14398941Sdes * 14492559Sdes * Other possible annotations after the time are !H, !N, !P (got a host, 14598941Sdes * network or protocol unreachable, respectively), !S or !F (source 14692559Sdes * route failed or fragmentation needed -- neither of these should 14798941Sdes * ever occur and the associated gateway is busted if you see one). If 14898941Sdes * almost all the probes result in some kind of unreachable, traceroute 14998941Sdes * will give up and exit. 15098941Sdes * 15198941Sdes * Notes 15276259Sgreen * ----- 15398941Sdes * This program must be run by root or be setuid. (I suggest that 15476259Sgreen * you *don't* make it setuid -- casual use could result in a lot 15598941Sdes * of unnecessary traffic on our poor, congested nets.) 15698684Sdes * 15798684Sdes * This program requires a kernel mod that does not appear in any 15898941Sdes * system available from Berkeley: A raw ip socket using proto 15998684Sdes * IPPROTO_RAW must interpret the data sent as an ip datagram (as 16098941Sdes * opposed to data to be wrapped in a ip datagram). See the README 16198941Sdes * file that came with the source to this program for a description 162126277Sdes * of the mods I made to /sys/netinet/raw_ip.c. Your mileage may 163126277Sdes * vary. But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE 164126277Sdes * MODIFIED TO RUN THIS PROGRAM. 165126277Sdes * 166126277Sdes * The udp port usage may appear bizarre (well, ok, it is bizarre). 16798941Sdes * The problem is that an icmp message only contains 8 bytes of 16898941Sdes * data from the original datagram. 8 bytes is the size of a udp 16998941Sdes * header so, if we want to associate replies with the original 17098941Sdes * datagram, the necessary information must be encoded into the 17198941Sdes * udp header (the ip id could be used but there's no way to 17298941Sdes * interlock with the kernel's assignment of ip id's and, anyway, 17398941Sdes * it would have taken a lot more kernel hacking to allow this 17498941Sdes * code to set the ip id). So, to allow two or more users to 17598941Sdes * use traceroute simultaneously, we use this task's pid as the 17698941Sdes * source port (the high bit is set to move the port number out 17798941Sdes * of the "likely" range). To keep track of which probe is being 17898941Sdes * replied to (so times and/or hop counts don't get confused by a 17998941Sdes * reply that was delayed in transit), we increment the destination 18098941Sdes * port number before each probe. 18198941Sdes * 18298941Sdes * Don't use this as a coding example. I was trying to find a 18398941Sdes * routing problem and this code sort-of popped out after 48 hours 184 * without sleep. I was amazed it ever compiled, much less ran. 185 * 186 * I stole the idea for this program from Steve Deering. Since 187 * the first release, I've learned that had I attended the right 188 * IETF working group meetings, I also could have stolen it from Guy 189 * Almes or Matt Mathis. I don't know (or care) who came up with 190 * the idea first. I envy the originators' perspicacity and I'm 191 * glad they didn't keep the idea a secret. 192 * 193 * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or 194 * enhancements to the original distribution. 195 * 196 * I've hacked up a round-trip-route version of this that works by 197 * sending a loose-source-routed udp datagram through the destination 198 * back to yourself. Unfortunately, SO many gateways botch source 199 * routing, the thing is almost worthless. Maybe one day... 200 * 201 * -- Van Jacobson (van@ee.lbl.gov) 202 * Tue Dec 20 03:50:13 PST 1988 203 */ 204 205#include <sys/param.h> 206#include <sys/file.h> 207#include <sys/ioctl.h> 208#ifdef HAVE_SYS_SELECT_H 209#include <sys/select.h> 210#endif 211#include <sys/socket.h> 212#include <sys/time.h> 213 214#include <netinet/in_systm.h> 215#include <netinet/in.h> 216#include <netinet/ip.h> 217#include <netinet/ip_var.h> 218#include <netinet/ip_icmp.h> 219#include <netinet/udp.h> 220#include <netinet/tcp.h> 221 222#include <arpa/inet.h> 223 224#ifdef IPSEC 225#include <net/route.h> 226#include <netinet6/ipsec.h> /* XXX */ 227#endif /* IPSEC */ 228 229#include <ctype.h> 230#include <errno.h> 231#ifdef HAVE_MALLOC_H 232#include <malloc.h> 233#endif 234#include <memory.h> 235#include <netdb.h> 236#include <stdio.h> 237#include <stdlib.h> 238#include <string.h> 239#include <unistd.h> 240 241#include "gnuc.h" 242#ifdef HAVE_OS_PROTO_H 243#include "os-proto.h" 244#endif 245 246/* Maximum number of gateways (include room for one noop) */ 247#define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t))) 248 249#ifndef MAXHOSTNAMELEN 250#define MAXHOSTNAMELEN 64 251#endif 252 253#define Fprintf (void)fprintf 254#define Printf (void)printf 255 256/* What a GRE packet header looks like */ 257struct grehdr { 258 u_int16_t flags; 259 u_int16_t proto; 260 u_int16_t length; /* PPTP version of these fields */ 261 u_int16_t callId; 262}; 263#ifndef IPPROTO_GRE 264#define IPPROTO_GRE 47 265#endif 266 267/* For GRE, we prepare what looks like a PPTP packet */ 268#define GRE_PPTP_PROTO 0x880b 269 270/* Data section of the probe packet */ 271struct outdata { 272 u_char seq; /* sequence number of this packet */ 273 u_char ttl; /* ttl packet left with */ 274 struct timeval tv; /* time packet left */ 275}; 276 277/* Descriptor structure for each outgoing protocol we support */ 278struct outproto { 279 char *name; /* name of protocol */ 280 u_char num; /* IP protocol number */ 281 u_short hdrlen; /* max size of protocol header */ 282 u_short port; /* default base protocol-specific "port" */ 283 void (*prepare)(struct outdata *); 284 /* finish preparing an outgoing packet */ 285 int (*check)(const u_char *, int); 286 /* check an incoming packet */ 287}; 288 289u_char packet[512]; /* last inbound (icmp) packet */ 290 291struct ip *outip; /* last output ip packet */ 292u_char *outprot; /* last output inner protocol packet */ 293 294/* loose source route gateway list (including room for final destination) */ 295u_int32_t gwlist[NGATEWAYS + 1]; 296 297int s; /* receive (icmp) socket file descriptor */ 298int sndsock; /* send (udp) socket file descriptor */ 299 300struct sockaddr whereto; /* Who to try to reach */ 301int packlen; /* total length of packet */ 302int protlen; /* length of protocol part of packet */ 303int maxpacket = 32 * 1024; /* max ip packet size */ 304 305char *prog; 306char *source; 307char *hostname; 308 309int nprobes = 3; 310int min_ttl = 1; 311int max_ttl = 30; 312u_short ident; 313u_short port; /* protocol specific base "port" */ 314 315int options; /* socket options */ 316int verbose; 317int waittime = 5; /* time to wait for response (in seconds) */ 318int nflag; /* print addresses numerically */ 319 320extern int optind; 321extern int opterr; 322extern char *optarg; 323 324/* Forwards */ 325double deltaT(struct timeval *, struct timeval *); 326char *inetname(struct in_addr); 327int main(int, char **); 328int packet_ok(u_char *, int, struct sockaddr_in *, int); 329char *pr_type(u_char); 330void print(u_char *, int, struct sockaddr_in *); 331char *getaddr(u_int32_t *, char *); 332char *getsin(struct sockaddr_in *, char *); 333char *savestr(const char *); 334#ifdef IPSEC 335int setpolicy __P((int so, char *policy)); 336#endif 337void send_probe(int, int); 338void tvsub(struct timeval *, struct timeval *); 339__dead void usage(void); 340int wait_for_reply(int, struct sockaddr_in *, struct timeval *); 341 342void udp_prep(struct outdata *); 343int udp_check(const u_char *, int); 344void tcp_prep(struct outdata *); 345int tcp_check(const u_char *, int); 346void gre_prep(struct outdata *); 347int gre_check(const u_char *, int); 348void gen_prep(struct outdata *); 349int gen_check(const u_char *, int); 350 351/* List of supported protocols. The first one is the default. The last 352 one is the handler for generic protocols not explicitly listed. */ 353struct outproto protos[] = { 354 { 355 "udp", 356 IPPROTO_UDP, 357 sizeof(struct udphdr), 358 32768 + 666, 359 udp_prep, 360 udp_check 361 }, 362 { 363 "tcp", 364 IPPROTO_TCP, 365 sizeof(struct tcphdr), 366 32768 + 666, 367 tcp_prep, 368 tcp_check 369 }, 370 { 371 "gre", 372 IPPROTO_GRE, 373 sizeof(struct grehdr), 374 GRE_PPTP_PROTO, 375 gre_prep, 376 gre_check 377 }, 378 { 379 NULL, 380 0, 381 2 * sizeof(u_short), 382 0, 383 gen_prep, 384 gen_check 385 }, 386}; 387struct outproto *proto = &protos[0]; 388 389int 390main(int argc, char **argv) 391{ 392 register int op, code; 393 register char *cp; 394 struct sockaddr_in from; 395 register struct sockaddr_in *to = (struct sockaddr_in *)&whereto; 396 int on = 1; 397 register struct protoent *pe; 398 register int ttl, probe, i; 399 register int seq = 0; 400 register int tos = 0; 401 register int lsrr = 0; 402 register int optlen = 0; 403 int requestPort = -1; 404 int sump = 0; 405 int sockerrno; 406 407 /* 408 * Do the setuid-required stuff first, then lose priveleges ASAP. 409 * Do error checking for these two calls where they appeared in 410 * the original code. 411 */ 412 cp = "icmp"; 413 pe = getprotobyname(cp); 414 if (pe) { 415 if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0) 416 sockerrno = errno; 417 else if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) 418 sockerrno = errno; 419 } 420 421 setuid(getuid()); 422 423 if ((cp = strrchr(argv[0], '/')) != NULL) 424 prog = cp + 1; 425 else 426 prog = argv[0]; 427 428 opterr = 0; 429 while ((op = getopt(argc, argv, "Sdnrvg:M:m:P:p:q:s:t:w:")) != EOF) 430 switch (op) { 431 432 case 'S': 433 sump = 1; 434 break; 435 case 'd': 436 options |= SO_DEBUG; 437 break; 438 439 case 'g': 440 if (lsrr >= NGATEWAYS) { 441 Fprintf(stderr, 442 "%s: No more than %d gateways\n", 443 prog, NGATEWAYS); 444 exit(1); 445 } 446 (void)getaddr(gwlist + lsrr, optarg); 447 ++lsrr; 448 break; 449 450 case 'M': 451 min_ttl = atoi(optarg); 452 if (min_ttl < 1 || min_ttl > 0xff) { 453 Fprintf(stderr, "%s: invalid ttl value %s\n", 454 prog, optarg); 455 exit(1); 456 } 457 break; 458 459 case 'm': 460 max_ttl = atoi(optarg); 461 if (max_ttl < 1 || max_ttl > 0xff) { 462 Fprintf(stderr, "%s: invalid ttl value %s\n", 463 prog, optarg); 464 exit(1); 465 } 466 break; 467 468 case 'n': 469 ++nflag; 470 break; 471 472 case 'P': 473 for (i = 0; protos[i].name != NULL; i++) { 474 if (strcasecmp(protos[i].name, optarg) == 0) { 475 proto = &protos[i]; 476 break; 477 } 478 } 479 if (protos[i].name == NULL) { /* generic handler */ 480 struct protoent *pe; 481 u_long pnum; 482 char *eptr; 483 484 /* Determine the IP protocol number */ 485 if ((pe = getprotobyname(optarg)) != NULL) 486 pnum = pe->p_proto; 487 else { 488 pnum = strtoul(optarg, &eptr, 10); 489 if (pnum > 0xff 490 || *optarg == '\0' 491 || *eptr != '\0') { 492 Fprintf(stderr, "%s: unknown " 493 "protocol \"%s\"\n", 494 prog, optarg); 495 exit(1); 496 } 497 } 498 proto->num = pnum; 499 } 500 break; 501 502 case 'p': 503 requestPort = atoi(optarg); 504 if (requestPort <= 0) { 505 Fprintf(stderr, "%s: port must be > 0\n", prog); 506 exit(1); 507 } 508 break; 509 510 case 'q': 511 nprobes = atoi(optarg); 512 if (nprobes <= 0) { 513 Fprintf(stderr, "%s: nprobes must be > 0\n", 514 prog); 515 exit(1); 516 } 517 break; 518 519 case 'r': 520 options |= SO_DONTROUTE; 521 break; 522 523 case 's': 524 /* 525 * set the ip source address of the outbound 526 * probe (e.g., on a multi-homed host). 527 */ 528 source = optarg; 529 break; 530 531 case 't': 532 tos = atoi(optarg); 533 if (tos < 0 || tos > 255) { 534 Fprintf(stderr, "%s: tos must be 0 to 255\n", 535 prog); 536 exit(1); 537 } 538 break; 539 540 case 'v': 541 ++verbose; 542 break; 543 544 case 'w': 545 waittime = atoi(optarg); 546 if (waittime <= 1 || waittime >= 24L * 60 * 60) { 547 Fprintf(stderr, 548 "%s: wait must be > 1 sec and < 1 day\n", 549 prog); 550 exit(1); 551 } 552 break; 553 554 default: 555 usage(); 556 } 557 558 /* Set requested port, if any, else default for this protocol */ 559 port = (requestPort != -1) ? requestPort : proto->port; 560 561 /* Check min vs. max TTL */ 562 if (min_ttl > max_ttl) { 563 Fprintf(stderr, "%s: min ttl must be <= max ttl\n", prog); 564 exit(1); 565 } 566 567 /* Process destination and optional packet size */ 568 switch (argc - optind) { 569 570 case 2: 571 packlen = atoi(argv[optind + 1]); 572 /* Fall thorugh */ 573 574 case 1: 575 hostname = savestr(getsin(to, argv[optind])); 576 break; 577 578 default: 579 usage(); 580 } 581 582#ifdef HAVE_SETLINEBUF 583 setlinebuf (stdout); 584#else 585 setvbuf(stdout, NULL, _IOLBF, 0); 586#endif 587 588 if (lsrr > 0) 589 optlen = (lsrr + 1) * sizeof(gwlist[0]); 590 i = sizeof(*outip) + proto->hdrlen + sizeof(struct outdata) + optlen; 591 if (packlen == 0) 592 packlen = i; /* minimum sized packet */ 593 else if (i > packlen || packlen > maxpacket) { 594 Fprintf(stderr, "%s: packet size must be %d <= s <= %d\n", 595 prog, i, maxpacket); 596 exit(1); 597 } 598 protlen = packlen - sizeof(*outip) - optlen; 599 600 outip = (struct ip *)malloc((unsigned)packlen); 601 if (outip == NULL) { 602 Fprintf(stderr, "%s: malloc: %s\n", prog, strerror(errno)); 603 exit(1); 604 } 605 memset((char *)outip, 0, packlen); 606 607 outip->ip_v = IPVERSION; 608 outip->ip_tos = tos; 609#ifdef BYTESWAP_IP_LEN 610 outip->ip_len = htons(packlen); 611#else 612 outip->ip_len = packlen; 613#endif 614 outip->ip_p = proto->num; 615 outprot = (u_char *)(outip + 1); 616#ifdef HAVE_RAW_OPTIONS 617 if (lsrr > 0) { 618 register u_char *optlist; 619 620 optlist = (u_char *)outprot; 621 (u_char *)outprot += optlen; 622 623 /* final hop */ 624 gwlist[lsrr] = to->sin_addr.s_addr; 625 626 outip->ip_dst.s_addr = gwlist[0]; 627 628 /* force 4 byte alignment */ 629 optlist[0] = IPOPT_NOP; 630 /* loose source route option */ 631 optlist[1] = IPOPT_LSRR; 632 i = lsrr * sizeof(gwlist[0]); 633 optlist[2] = i + 3; 634 /* Pointer to LSRR addresses */ 635 optlist[3] = IPOPT_MINOFF; 636 memcpy(optlist + 4, gwlist + 1, i); 637 } else 638#endif 639 outip->ip_dst = to->sin_addr; 640 641 outip->ip_hl = ((u_char *)outprot - (u_char *)outip) >> 2; 642 643 ident = (getpid() & 0xffff) | 0x8000; 644 645 if (pe == NULL) { 646 Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp); 647 exit(1); 648 } 649 if (s < 0) { 650 errno = sockerrno; 651 Fprintf(stderr, "%s: icmp socket: %s\n", prog, strerror(errno)); 652 exit(1); 653 } 654 if (options & SO_DEBUG) 655 (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on, 656 sizeof(on)); 657 if (options & SO_DONTROUTE) 658 (void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&on, 659 sizeof(on)); 660 661#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) 662 if (setpolicy(s, "in bypass") < 0) 663 errx(1, ipsec_strerror()); 664 665 if (setpolicy(s, "out bypass") < 0) 666 errx(1, ipsec_strerror()); 667#endif /* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */ 668 669 if (sndsock < 0) { 670 errno = sockerrno; 671 Fprintf(stderr, "%s: raw socket: %s\n", prog, strerror(errno)); 672 exit(1); 673 } 674 675#if defined(IP_OPTIONS) && !defined(HAVE_RAW_OPTIONS) 676 if (lsrr > 0) { 677 u_char optlist[MAX_IPOPTLEN]; 678 679 cp = "ip"; 680 if ((pe = getprotobyname(cp)) == NULL) { 681 Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp); 682 exit(1); 683 } 684 685 /* final hop */ 686 gwlist[lsrr] = to->sin_addr.s_addr; 687 ++lsrr; 688 689 /* force 4 byte alignment */ 690 optlist[0] = IPOPT_NOP; 691 /* loose source route option */ 692 optlist[1] = IPOPT_LSRR; 693 i = lsrr * sizeof(gwlist[0]); 694 optlist[2] = i + 3; 695 /* Pointer to LSRR addresses */ 696 optlist[3] = IPOPT_MINOFF; 697 memcpy(optlist + 4, gwlist, i); 698 699 if ((setsockopt(sndsock, pe->p_proto, IP_OPTIONS, optlist, 700 i + sizeof(gwlist[0]))) < 0) { 701 Fprintf(stderr, "%s: IP_OPTIONS: %s\n", 702 prog, strerror(errno)); 703 exit(1); 704 } 705 } 706#endif 707 708#ifdef SO_SNDBUF 709 if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&packlen, 710 sizeof(packlen)) < 0) { 711 Fprintf(stderr, "%s: SO_SNDBUF: %s\n", prog, strerror(errno)); 712 exit(1); 713 } 714#endif 715#ifdef IP_HDRINCL 716 if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on, 717 sizeof(on)) < 0) { 718 Fprintf(stderr, "%s: IP_HDRINCL: %s\n", prog, strerror(errno)); 719 exit(1); 720 } 721#endif 722 if (options & SO_DEBUG) 723 (void)setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on, 724 sizeof(on)); 725 if (options & SO_DONTROUTE) 726 (void)setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on, 727 sizeof(on)); 728 729 if (source != NULL) { 730 source = savestr(getsin(&from, source)); 731 outip->ip_src = from.sin_addr; 732#ifndef IP_HDRINCL 733 if (bind(sndsock, (struct sockaddr *)&from, sizeof(from)) < 0) { 734 Fprintf(stderr, "%s: bind: %s\n", 735 prog, strerror(errno)); 736 exit (1); 737 } 738#endif 739 } 740 741#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) 742 if (setpolicy(sndsock, "in bypass") < 0) 743 errx(1, ipsec_strerror()); 744 745 if (setpolicy(sndsock, "out bypass") < 0) 746 errx(1, ipsec_strerror()); 747#endif /* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */ 748 749 Fprintf(stderr, "%s to %s (%s)", 750 prog, hostname, inet_ntoa(to->sin_addr)); 751 if (source) 752 Fprintf(stderr, " from %s", source); 753 Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, packlen); 754 (void)fflush(stderr); 755 756 for (ttl = min_ttl; ttl <= max_ttl; ++ttl) { 757 u_int32_t lastaddr = 0; 758 int got_there = 0; 759 int unreachable = 0; 760 int loss; 761 762 Printf("%2d ", ttl); 763 for (probe = 0, loss = 0; probe < nprobes; ++probe) { 764 register int cc; 765 struct timeval t1, t2; 766 struct timezone tz; 767 register struct ip *ip; 768 struct outdata outdata; 769 770 /* Prepare outgoing data */ 771 outdata.seq = ++seq; 772 outdata.ttl = ttl; 773 774 /* Avoid alignment problems by copying bytewise: */ 775 (void)gettimeofday(&t1, &tz); 776 memcpy(&outdata.tv, &t1, sizeof(outdata.tv)); 777 778 /* Finalize and send packet */ 779 (*proto->prepare)(&outdata); 780 send_probe(seq, ttl); 781 782 /* Wait for a reply */ 783 while ((cc = wait_for_reply(s, &from, &t1)) != 0) { 784 double T; 785 int precis; 786 787 (void)gettimeofday(&t2, &tz); 788 i = packet_ok(packet, cc, &from, seq); 789 /* Skip short packet */ 790 if (i == 0) 791 continue; 792 if (from.sin_addr.s_addr != lastaddr) { 793 print(packet, cc, &from); 794 lastaddr = from.sin_addr.s_addr; 795 } 796 T = deltaT(&t1, &t2); 797#ifdef SANE_PRECISION 798 if (T >= 1000.0) 799 precis = 0; 800 else if (T >= 100.0) 801 precis = 1; 802 else if (T >= 10.0) 803 precis = 2; 804 else 805#endif 806 precis = 3; 807 Printf(" %.*f ms", precis, T); 808 /* time exceeded in transit */ 809 if (i == -1) 810 break; 811 code = i - 1; 812 switch (code) { 813 814 case ICMP_UNREACH_PORT: 815#ifndef ARCHAIC 816 ip = (struct ip *)packet; 817 if (ip->ip_ttl <= 1) 818 Printf(" !"); 819#endif 820 ++got_there; 821 break; 822 823 case ICMP_UNREACH_NET: 824 ++unreachable; 825 Printf(" !N"); 826 break; 827 828 case ICMP_UNREACH_HOST: 829 ++unreachable; 830 Printf(" !H"); 831 break; 832 833 case ICMP_UNREACH_PROTOCOL: 834 ++got_there; 835 Printf(" !P"); 836 break; 837 838 case ICMP_UNREACH_NEEDFRAG: 839 ++unreachable; 840 Printf(" !F"); 841 break; 842 843 case ICMP_UNREACH_SRCFAIL: 844 ++unreachable; 845 Printf(" !S"); 846 break; 847 848/* rfc1716 */ 849#ifndef ICMP_UNREACH_FILTER_PROHIB 850#define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohibited filter */ 851#endif 852 case ICMP_UNREACH_FILTER_PROHIB: 853 ++unreachable; 854 Printf(" !X"); 855 break; 856 857 default: 858 ++unreachable; 859 Printf(" !<%d>", code); 860 break; 861 } 862 break; 863 } 864 if (cc == 0) { 865 loss++; 866 Printf(" *"); 867 } 868 (void)fflush(stdout); 869 } 870 if (sump) { 871 Printf(" (%d%% loss)", (loss * 100) / nprobes); 872 } 873 putchar('\n'); 874 if (got_there || 875 (unreachable > 0 && unreachable >= nprobes - 1)) 876 break; 877 } 878 exit(0); 879} 880 881int 882wait_for_reply(register int sock, register struct sockaddr_in *fromp, 883 register struct timeval *tp) 884{ 885 fd_set fds; 886 struct timeval now, wait; 887 struct timezone tz; 888 register int cc = 0; 889 register int error; 890 int fromlen = sizeof(*fromp); 891 892 FD_ZERO(&fds); 893 FD_SET(sock, &fds); 894 895 wait.tv_sec = tp->tv_sec + waittime; 896 wait.tv_usec = tp->tv_usec; 897 (void)gettimeofday(&now, &tz); 898 tvsub(&wait, &now); 899 if (wait.tv_sec < 0) { 900 wait.tv_sec = 0; 901 wait.tv_usec = 1; 902 } 903 904 error = select(sock + 1, &fds, (fd_set *)0, (fd_set *)0, &wait); 905 if (error == -1 && errno == EINVAL) { 906 Fprintf(stderr, "%s: botched select() args\n", prog); 907 exit(1); 908 } 909 if (error > 0) 910 cc = recvfrom(s, (char *)packet, sizeof(packet), 0, 911 (struct sockaddr *)fromp, &fromlen); 912 913 return(cc); 914} 915 916#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) 917int 918setpolicy(so, policy) 919 int so; 920 char *policy; 921{ 922 char *buf; 923 924 buf = ipsec_set_policy(policy, strlen(policy)); 925 if (buf == NULL) { 926 warnx(ipsec_strerror()); 927 return -1; 928 } 929 (void)setsockopt(so, IPPROTO_IP, IP_IPSEC_POLICY, 930 buf, ipsec_get_policylen(buf)); 931 932 free(buf); 933 934 return 0; 935} 936#endif 937 938void 939send_probe(int seq, int ttl) 940{ 941 register int i; 942 943 outip->ip_ttl = ttl; 944 outip->ip_id = htons(ident + seq); 945 946 i = sendto(sndsock, (char *)outip, packlen, 0, &whereto, 947 sizeof(whereto)); 948 if (i < 0 || i != packlen) { 949 if (i < 0) 950 Fprintf(stderr, "%s: sendto: %s\n", 951 prog, strerror(errno)); 952 Printf("%s: wrote %s %d chars, ret=%d\n", 953 prog, hostname, packlen, i); 954 (void)fflush(stdout); 955 } 956} 957 958double 959deltaT(struct timeval *t1p, struct timeval *t2p) 960{ 961 register double dt; 962 963 dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 + 964 (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0; 965 return (dt); 966} 967 968/* 969 * Convert an ICMP "type" field to a printable string. 970 */ 971char * 972pr_type(register u_char t) 973{ 974 static char *ttab[] = { 975 "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable", 976 "Source Quench", "Redirect", "ICMP 6", "ICMP 7", 977 "Echo", "ICMP 9", "ICMP 10", "Time Exceeded", 978 "Param Problem", "Timestamp", "Timestamp Reply", "Info Request", 979 "Info Reply" 980 }; 981 982 if (t > 16) 983 return("OUT-OF-RANGE"); 984 985 return(ttab[t]); 986} 987 988int 989packet_ok(register u_char *buf, int cc, register struct sockaddr_in *from, 990 register int seq) 991{ 992 register struct icmp *icp; 993 register u_char type, code; 994 register int hlen; 995#ifndef ARCHAIC 996 register struct ip *ip; 997 998 ip = (struct ip *) buf; 999 hlen = ip->ip_hl << 2; 1000 if (cc < hlen + ICMP_MINLEN) { 1001 if (verbose) 1002 Printf("packet too short (%d bytes) from %s\n", cc, 1003 inet_ntoa(from->sin_addr)); 1004 return (0); 1005 } 1006 cc -= hlen; 1007 icp = (struct icmp *)(buf + hlen); 1008#else 1009 icp = (struct icmp *)buf; 1010#endif 1011 type = icp->icmp_type; 1012 code = icp->icmp_code; 1013 if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) || 1014 type == ICMP_UNREACH) { 1015 struct ip *hip; 1016 u_char *inner; 1017 1018 hip = &icp->icmp_ip; 1019 hlen = hip->ip_hl << 2; 1020 inner = (u_char *)((u_char *)hip + hlen); 1021 if (hlen + 12 <= cc 1022 && hip->ip_p == proto->num 1023 && (*proto->check)(inner, seq)) 1024 return (type == ICMP_TIMXCEED ? -1 : code + 1); 1025 } 1026#ifndef ARCHAIC 1027 if (verbose) { 1028 register int i; 1029 u_int32_t *lp = (u_int32_t *)&icp->icmp_ip; 1030 1031 Printf("\n%d bytes from %s to ", cc, inet_ntoa(from->sin_addr)); 1032 Printf("%s: icmp type %d (%s) code %d\n", 1033 inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code); 1034 for (i = 4; i < cc ; i += sizeof(*lp)) 1035 Printf("%2d: x%8.8x\n", i, *lp++); 1036 } 1037#endif 1038 return(0); 1039} 1040 1041void 1042udp_prep(struct outdata *outdata) 1043{ 1044 struct udphdr *const udp = (struct udphdr *) outprot; 1045 1046 udp->uh_sport = htons(ident); 1047 udp->uh_dport = htons(port + outdata->seq); 1048 udp->uh_ulen = htons((u_short)protlen); 1049} 1050 1051int 1052udp_check(const u_char *data, int seq) 1053{ 1054 struct udphdr *const udp = (struct udphdr *) data; 1055 1056 return (ntohs(udp->uh_sport) == ident 1057 && ntohs(udp->uh_dport) == port + seq); 1058} 1059 1060void 1061tcp_prep(struct outdata *outdata) 1062{ 1063 struct tcphdr *const tcp = (struct tcphdr *) outprot; 1064 1065 tcp->th_sport = htons(ident); 1066 tcp->th_dport = htons(port + outdata->seq); 1067 tcp->th_seq = (tcp->th_sport << 16) | tcp->th_dport; 1068 tcp->th_ack = 0; 1069 tcp->th_off = 5; 1070 tcp->th_flags = TH_SYN; 1071} 1072 1073int 1074tcp_check(const u_char *data, int seq) 1075{ 1076 struct tcphdr *const tcp = (struct tcphdr *) data; 1077 1078 return (ntohs(tcp->th_sport) == ident 1079 && ntohs(tcp->th_dport) == port + seq); 1080} 1081 1082void 1083gre_prep(struct outdata *outdata) 1084{ 1085 struct grehdr *const gre = (struct grehdr *) outprot; 1086 1087 gre->flags = htons(0x2001); 1088 gre->proto = htons(port); 1089 gre->length = 0; 1090 gre->callId = htons(ident + outdata->seq); 1091} 1092 1093int 1094gre_check(const u_char *data, int seq) 1095{ 1096 struct grehdr *const gre = (struct grehdr *) data; 1097 1098 return(ntohs(gre->proto) == port 1099 && ntohs(gre->callId) == ident + seq); 1100} 1101 1102void 1103gen_prep(struct outdata *outdata) 1104{ 1105 u_int16_t *const ptr; 1106 1107 ptr[0] = htons(ident); 1108 ptr[1] = htons(port + outdata->seq); 1109} 1110 1111int 1112gen_check(const u_char *data, int seq) 1113{ 1114 u_int16_t *const ptr = (u_int16_t *) data; 1115 1116 return(ntohs(ptr[0]) == ident 1117 && ntohs(ptr[1]) == port + seq); 1118} 1119 1120void 1121print(register u_char *buf, register int cc, register struct sockaddr_in *from) 1122{ 1123 register struct ip *ip; 1124 register int hlen; 1125 1126 ip = (struct ip *) buf; 1127 hlen = ip->ip_hl << 2; 1128 cc -= hlen; 1129 1130 if (nflag) 1131 Printf(" %s", inet_ntoa(from->sin_addr)); 1132 else 1133 Printf(" %s (%s)", inetname(from->sin_addr), 1134 inet_ntoa(from->sin_addr)); 1135 1136 if (verbose) 1137 Printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst)); 1138} 1139 1140 1141#ifdef notyet 1142/* 1143 * Checksum routine for Internet Protocol family headers (C Version) 1144 */ 1145in_cksum(register u_short *addr, register int len) 1146{ 1147 register int nleft = len; 1148 register u_short *w = addr; 1149 register u_short answer; 1150 register int sum = 0; 1151 1152 /* 1153 * Our algorithm is simple, using a 32 bit accumulator (sum), 1154 * we add sequential 16 bit words to it, and at the end, fold 1155 * back all the carry bits from the top 16 bits into the lower 1156 * 16 bits. 1157 */ 1158 while (nleft > 1) { 1159 sum += *w++; 1160 nleft -= 2; 1161 } 1162 1163 /* mop up an odd byte, if necessary */ 1164 if (nleft == 1) 1165 sum += *(u_char *)w; 1166 1167 /* 1168 * add back carry outs from top 16 bits to low 16 bits 1169 */ 1170 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 1171 sum += (sum >> 16); /* add carry */ 1172 answer = ~sum; /* truncate to 16 bits */ 1173 return (answer); 1174} 1175#endif 1176 1177/* 1178 * Subtract 2 timeval structs: out = out - in. 1179 * Out is assumed to be within about LONG_MAX seconds of in. 1180 */ 1181void 1182tvsub(register struct timeval *out, register struct timeval *in) 1183{ 1184 1185 if ((out->tv_usec -= in->tv_usec) < 0) { 1186 --out->tv_sec; 1187 out->tv_usec += 1000000; 1188 } 1189 out->tv_sec -= in->tv_sec; 1190} 1191 1192/* 1193 * Construct an Internet address representation. 1194 * If the nflag has been supplied, give 1195 * numeric value, otherwise try for symbolic name. 1196 */ 1197char * 1198inetname(struct in_addr in) 1199{ 1200 register char *cp; 1201 register struct hostent *hp; 1202 static int first = 1; 1203 static char domain[MAXHOSTNAMELEN + 1], line[MAXHOSTNAMELEN + 1]; 1204 1205 if (first && !nflag) { 1206 first = 0; 1207 if (gethostname(domain, MAXHOSTNAMELEN) == 0 && 1208 (cp = strchr(domain, '.')) != NULL) { 1209 (void)strncpy(domain, cp + 1, sizeof(domain) - 1); 1210 domain[sizeof(domain) - 1] = '\0'; 1211 } else 1212 domain[0] = '\0'; 1213 } 1214 if (!nflag && in.s_addr != INADDR_ANY) { 1215 hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET); 1216 if (hp != NULL) { 1217 if ((cp = strchr(hp->h_name, '.')) != NULL && 1218 strcmp(cp + 1, domain) == 0) 1219 *cp = '\0'; 1220 (void)strncpy(line, hp->h_name, sizeof(line) - 1); 1221 line[sizeof(line) - 1] = '\0'; 1222 return (line); 1223 } 1224 } 1225 return (inet_ntoa(in)); 1226} 1227 1228char * 1229getaddr(register u_int32_t *ap, register char *hostname) 1230{ 1231 register struct hostent *hp; 1232 1233 *ap = inet_addr(hostname); 1234 if ((int32_t)*ap != -1) 1235 return (hostname); 1236 1237 hp = gethostbyname(hostname); 1238 if (hp == NULL) { 1239 Fprintf(stderr, "%s: unknown host %s\n", prog, hostname); 1240 exit(1); 1241 } 1242 if (hp->h_addrtype != AF_INET || hp->h_length != 4) { 1243 Fprintf(stderr, "%s: bad host %s\n", prog, hostname); 1244 exit(1); 1245 } 1246 memcpy((caddr_t)ap, hp->h_addr, hp->h_length); 1247 return (hp->h_name); 1248} 1249 1250char * 1251getsin(register struct sockaddr_in *sin, register char *hostname) 1252{ 1253 1254 memset(sin, 0, sizeof(*sin)); 1255 sin->sin_family = AF_INET; 1256 return (getaddr((u_int32_t *)&sin->sin_addr.s_addr, hostname)); 1257} 1258 1259char * 1260savestr(register const char *str) 1261{ 1262 register char *cp; 1263 1264 cp = strdup(str); 1265 if (cp == NULL) { 1266 Fprintf(stderr, "%s: strdup: %s\n", prog, strerror(errno)); 1267 exit(1); 1268 } 1269 return (cp); 1270} 1271 1272__dead void 1273usage(void) 1274{ 1275 extern char version[]; 1276 1277 Fprintf(stderr, "Version %s\n", version); 1278 Fprintf(stderr, "Usage: %s [-Sdnrv] [-w wait] [-m max_ttl] [-M min_ttl] \ 1279[-P proto]\n\t [-p port#] [-q nqueries] [-t tos] [-s src_addr] [-g gateway] \ 1280\n\t host [data_size]\n", prog); 1281 exit(1); 1282} 1283