2 * Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the University of California,
13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21 * @(#) Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996 The Regents of the University of California. All rights reserved.
22 * @(#)$Header: traceroute.c,v 1.43 96/09/27 20:08:10 leres Exp $ (LBL)
23 * $FreeBSD: src/contrib/traceroute/traceroute.c,v 1.11.2.6 2002/08/05 23:37:16 fenner Exp $
24 * $DragonFly: src/contrib/traceroute/Attic/traceroute.c,v 1.2 2003/06/17 04:24:07 dillon Exp $
28 * traceroute host - trace the route ip packets follow going to "host".
30 * Attempt to trace the route an ip packet would follow to some
31 * internet host. We find out intermediate hops by launching probe
32 * packets with a small ttl (time to live) then listening for an
33 * icmp "time exceeded" reply from a gateway. We start our probes
34 * with a ttl of one and increase by one until we get an icmp "port
35 * unreachable" (which means we got to "host") or hit a max (which
36 * defaults to net.inet.ip.ttl hops & can be changed with the -m flag).
37 * Three probes (change with -q flag) are sent at each ttl setting and
38 * a line is printed showing the ttl, address of the gateway and
39 * round trip time of each probe. If the probe answers come from
40 * different gateways, the address of each responding system will
41 * be printed. If there is no response within a 5 sec. timeout
42 * interval (changed with the -w flag), a "*" is printed for that
45 * Probe packets are UDP format. We don't want the destination
46 * host to process them so the destination port is set to an
47 * unlikely value (if some clod on the destination is using that
48 * value, it can be changed with the -p flag).
50 * A sample use might be:
52 * [yak 71]% traceroute nis.nsf.net.
53 * traceroute to nis.nsf.net (35.1.1.48), 64 hops max, 56 byte packet
54 * 1 helios.ee.lbl.gov (128.3.112.1) 19 ms 19 ms 0 ms
55 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
56 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
57 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 39 ms
58 * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 39 ms 39 ms 39 ms
59 * 6 128.32.197.4 (128.32.197.4) 40 ms 59 ms 59 ms
60 * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 59 ms
61 * 8 129.140.70.13 (129.140.70.13) 99 ms 99 ms 80 ms
62 * 9 129.140.71.6 (129.140.71.6) 139 ms 239 ms 319 ms
63 * 10 129.140.81.7 (129.140.81.7) 220 ms 199 ms 199 ms
64 * 11 nic.merit.edu (35.1.1.48) 239 ms 239 ms 239 ms
66 * Note that lines 2 & 3 are the same. This is due to a buggy
67 * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
68 * packets with a zero ttl.
70 * A more interesting example is:
72 * [yak 72]% traceroute allspice.lcs.mit.edu.
73 * traceroute to allspice.lcs.mit.edu (18.26.0.115), 64 hops max
74 * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
75 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 19 ms 19 ms
76 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 19 ms
77 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 19 ms 39 ms 39 ms
78 * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 20 ms 39 ms 39 ms
79 * 6 128.32.197.4 (128.32.197.4) 59 ms 119 ms 39 ms
80 * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 39 ms
81 * 8 129.140.70.13 (129.140.70.13) 80 ms 79 ms 99 ms
82 * 9 129.140.71.6 (129.140.71.6) 139 ms 139 ms 159 ms
83 * 10 129.140.81.7 (129.140.81.7) 199 ms 180 ms 300 ms
84 * 11 129.140.72.17 (129.140.72.17) 300 ms 239 ms 239 ms
86 * 13 128.121.54.72 (128.121.54.72) 259 ms 499 ms 279 ms
91 * 18 ALLSPICE.LCS.MIT.EDU (18.26.0.115) 339 ms 279 ms 279 ms
93 * (I start to see why I'm having so much trouble with mail to
94 * MIT.) Note that the gateways 12, 14, 15, 16 & 17 hops away
95 * either don't send ICMP "time exceeded" messages or send them
96 * with a ttl too small to reach us. 14 - 17 are running the
97 * MIT C Gateway code that doesn't send "time exceeded"s. God
98 * only knows what's going on with 12.
100 * The silent gateway 12 in the above may be the result of a bug in
101 * the 4.[23]BSD network code (and its derivatives): 4.x (x <= 3)
102 * sends an unreachable message using whatever ttl remains in the
103 * original datagram. Since, for gateways, the remaining ttl is
104 * zero, the icmp "time exceeded" is guaranteed to not make it back
105 * to us. The behavior of this bug is slightly more interesting
106 * when it appears on the destination system:
108 * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
109 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 39 ms
110 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 39 ms 19 ms
111 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 19 ms
112 * 5 ccn-nerif35.Berkeley.EDU (128.32.168.35) 39 ms 39 ms 39 ms
113 * 6 csgw.Berkeley.EDU (128.32.133.254) 39 ms 59 ms 39 ms
120 * 13 rip.Berkeley.EDU (128.32.131.22) 59 ms ! 39 ms ! 39 ms !
122 * Notice that there are 12 "gateways" (13 is the final
123 * destination) and exactly the last half of them are "missing".
124 * What's really happening is that rip (a Sun-3 running Sun OS3.5)
125 * is using the ttl from our arriving datagram as the ttl in its
126 * icmp reply. So, the reply will time out on the return path
127 * (with no notice sent to anyone since icmp's aren't sent for
128 * icmp's) until we probe with a ttl that's at least twice the path
129 * length. I.e., rip is really only 7 hops away. A reply that
130 * returns with a ttl of 1 is a clue this problem exists.
131 * Traceroute prints a "!" after the time if the ttl is <= 1.
132 * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
133 * non-standard (HPUX) software, expect to see this problem
134 * frequently and/or take care picking the target host of your
137 * Other possible annotations after the time are !H, !N, !P (got a host,
138 * network or protocol unreachable, respectively), !S or !F (source
139 * route failed or fragmentation needed -- neither of these should
140 * ever occur and the associated gateway is busted if you see one). If
141 * almost all the probes result in some kind of unreachable, traceroute
142 * will give up and exit.
146 * This program must be run by root or be setuid. (I suggest that
147 * you *don't* make it setuid -- casual use could result in a lot
148 * of unnecessary traffic on our poor, congested nets.)
150 * This program requires a kernel mod that does not appear in any
151 * system available from Berkeley: A raw ip socket using proto
152 * IPPROTO_RAW must interpret the data sent as an ip datagram (as
153 * opposed to data to be wrapped in a ip datagram). See the README
154 * file that came with the source to this program for a description
155 * of the mods I made to /sys/netinet/raw_ip.c. Your mileage may
156 * vary. But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
157 * MODIFIED TO RUN THIS PROGRAM.
159 * The udp port usage may appear bizarre (well, ok, it is bizarre).
160 * The problem is that an icmp message only contains 8 bytes of
161 * data from the original datagram. 8 bytes is the size of a udp
162 * header so, if we want to associate replies with the original
163 * datagram, the necessary information must be encoded into the
164 * udp header (the ip id could be used but there's no way to
165 * interlock with the kernel's assignment of ip id's and, anyway,
166 * it would have taken a lot more kernel hacking to allow this
167 * code to set the ip id). So, to allow two or more users to
168 * use traceroute simultaneously, we use this task's pid as the
169 * source port (the high bit is set to move the port number out
170 * of the "likely" range). To keep track of which probe is being
171 * replied to (so times and/or hop counts don't get confused by a
172 * reply that was delayed in transit), we increment the destination
173 * port number before each probe.
175 * Don't use this as a coding example. I was trying to find a
176 * routing problem and this code sort-of popped out after 48 hours
177 * without sleep. I was amazed it ever compiled, much less ran.
179 * I stole the idea for this program from Steve Deering. Since
180 * the first release, I've learned that had I attended the right
181 * IETF working group meetings, I also could have stolen it from Guy
182 * Almes or Matt Mathis. I don't know (or care) who came up with
183 * the idea first. I envy the originators' perspicacity and I'm
184 * glad they didn't keep the idea a secret.
186 * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
187 * enhancements to the original distribution.
189 * I've hacked up a round-trip-route version of this that works by
190 * sending a loose-source-routed udp datagram through the destination
191 * back to yourself. Unfortunately, SO many gateways botch source
192 * routing, the thing is almost worthless. Maybe one day...
194 * -- Van Jacobson (van@ee.lbl.gov)
195 * Tue Dec 20 03:50:13 PST 1988
198 #include <sys/param.h>
199 #include <sys/file.h>
200 #include <sys/ioctl.h>
201 #ifdef HAVE_SYS_SELECT_H
202 #include <sys/select.h>
204 #include <sys/socket.h>
205 #ifdef HAVE_SYS_SYSCTL_H
206 #include <sys/sysctl.h>
208 #include <sys/time.h>
210 #include <netinet/in_systm.h>
211 #include <netinet/in.h>
212 #include <netinet/ip.h>
213 #include <netinet/ip_var.h>
214 #include <netinet/ip_icmp.h>
215 #include <netinet/udp.h>
216 #include <netinet/tcp.h>
218 #include <arpa/inet.h>
221 #include <net/route.h>
222 #include <netinet6/ipsec.h> /* XXX */
238 #ifdef HAVE_OS_PROTO_H
239 #include "os-proto.h"
242 /* Maximum number of gateways (include room for one noop) */
243 #define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t)))
245 #ifndef MAXHOSTNAMELEN
246 #define MAXHOSTNAMELEN 64
249 #define Fprintf (void)fprintf
250 #define Printf (void)printf
252 /* What a GRE packet header looks like */
256 u_int16_t length; /* PPTP version of these fields */
260 #define IPPROTO_GRE 47
263 /* For GRE, we prepare what looks like a PPTP packet */
264 #define GRE_PPTP_PROTO 0x880b
266 /* Data section of the probe packet */
268 u_char seq; /* sequence number of this packet */
269 u_char ttl; /* ttl packet left with */
270 struct timeval tv; /* time packet left */
271 int optlen; /* length of ip options */
274 /* Descriptor structure for each outgoing protocol we support */
276 char *name; /* name of protocol */
277 u_char num; /* IP protocol number */
278 u_short hdrlen; /* max size of protocol header */
279 u_short port; /* default base protocol-specific "port" */
280 void (*prepare)(struct outdata *);
281 /* finish preparing an outgoing packet */
282 int (*check)(const u_char *, int);
283 /* check an incoming packet */
286 u_char packet[512]; /* last inbound (icmp) packet */
288 struct ip *outip; /* last output ip packet */
289 u_char *outprot; /* last output inner protocol packet */
291 /* loose source route gateway list (including room for final destination) */
292 u_int32_t gwlist[NGATEWAYS + 1];
294 int s; /* receive (icmp) socket file descriptor */
295 int sndsock; /* send (udp) socket file descriptor */
297 struct sockaddr whereto; /* Who to try to reach */
298 int packlen; /* total length of packet */
299 int protlen; /* length of protocol part of packet */
300 int maxpacket = 32 * 1024; /* max ip packet size */
310 u_short port; /* protocol specific base "port" */
312 int options; /* socket options */
314 int waittime = 5; /* time to wait for response (in seconds) */
315 int nflag; /* print addresses numerically */
322 double deltaT(struct timeval *, struct timeval *);
323 u_short in_cksum(u_short *, int);
324 char *inetname(struct in_addr);
325 int main(int, char **);
326 int packet_ok(u_char *, int, struct sockaddr_in *, int);
327 char *pr_type(u_char);
328 void print(u_char *, int, struct sockaddr_in *);
329 char *getaddr(u_int32_t *, char *);
330 char *getsin(struct sockaddr_in *, char *);
331 char *savestr(const char *);
333 int setpolicy __P((int so, char *policy));
335 void send_probe(int, int);
336 void tvsub(struct timeval *, struct timeval *);
337 __dead void usage(void);
338 int wait_for_reply(int, struct sockaddr_in *, struct timeval *);
340 void udp_prep(struct outdata *);
341 int udp_check(const u_char *, int);
342 void tcp_prep(struct outdata *);
343 int tcp_check(const u_char *, int);
344 void gre_prep(struct outdata *);
345 int gre_check(const u_char *, int);
346 void gen_prep(struct outdata *);
347 int gen_check(const u_char *, int);
348 void icmp_prep(struct outdata *);
349 int icmp_check(const u_char *, int);
351 /* List of supported protocols. The first one is the default. The last
352 one is the handler for generic protocols not explicitly listed. */
353 struct outproto protos[] = {
357 sizeof(struct udphdr),
365 sizeof(struct tcphdr),
373 sizeof(struct grehdr),
395 struct outproto *proto = &protos[0];
398 main(int argc, char **argv)
400 register int op, code;
402 struct sockaddr_in from;
403 register struct sockaddr_in *to = (struct sockaddr_in *)&whereto;
405 register struct protoent *pe;
406 register int ttl, probe, i;
407 register int seq = 0;
408 register int tos = 0;
409 register int lsrr = 0;
410 register int optlen = 0;
411 int requestPort = -1;
416 * Do the setuid-required stuff first, then lose priveleges ASAP.
417 * Do error checking for these two calls where they appeared in
421 pe = getprotobyname(cp);
423 if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0)
425 else if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
433 int mib[4] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_DEFTTL };
434 size_t sz = sizeof(max_ttl);
436 if (sysctl(mib, 4, &max_ttl, &sz, NULL, 0) == -1)
437 err(1, "sysctl(net.inet.ip.ttl)");
443 if ((cp = strrchr(argv[0], '/')) != NULL)
449 while ((op = getopt(argc, argv, "Sdnrvg:M:m:P:p:q:s:t:w:")) != EOF)
460 if (lsrr >= NGATEWAYS) {
462 "%s: No more than %d gateways\n",
466 (void)getaddr(gwlist + lsrr, optarg);
471 min_ttl = atoi(optarg);
472 if (min_ttl < 1 || min_ttl > 0xff) {
473 Fprintf(stderr, "%s: invalid ttl value %s\n",
480 max_ttl = atoi(optarg);
481 if (max_ttl < 1 || max_ttl > 0xff) {
482 Fprintf(stderr, "%s: invalid ttl value %s\n",
493 for (i = 0; protos[i].name != NULL; i++) {
494 if (strcasecmp(protos[i].name, optarg) == 0) {
499 if (proto->name == NULL) { /* generic handler */
504 /* Determine the IP protocol number */
505 if ((pe = getprotobyname(optarg)) != NULL)
508 pnum = strtoul(optarg, &eptr, 10);
512 Fprintf(stderr, "%s: unknown "
523 requestPort = atoi(optarg);
524 if (requestPort <= 0) {
525 Fprintf(stderr, "%s: port must be > 0\n", prog);
531 nprobes = atoi(optarg);
533 Fprintf(stderr, "%s: nprobes must be > 0\n",
540 options |= SO_DONTROUTE;
545 * set the ip source address of the outbound
546 * probe (e.g., on a multi-homed host).
553 if (tos < 0 || tos > 255) {
554 Fprintf(stderr, "%s: tos must be 0 to 255\n",
565 waittime = atoi(optarg);
566 if (waittime <= 1 || waittime >= 24L * 60 * 60) {
568 "%s: wait must be > 1 sec and < 1 day\n",
578 /* Set requested port, if any, else default for this protocol */
579 port = (requestPort != -1) ? requestPort : proto->port;
581 /* Check min vs. max TTL */
582 if (min_ttl > max_ttl) {
583 Fprintf(stderr, "%s: min ttl must be <= max ttl\n", prog);
587 /* Process destination and optional packet size */
588 switch (argc - optind) {
591 packlen = atoi(argv[optind + 1]);
595 hostname = savestr(getsin(to, argv[optind]));
602 #ifdef HAVE_SETLINEBUF
605 setvbuf(stdout, NULL, _IOLBF, 0);
609 optlen = (lsrr + 1) * sizeof(gwlist[0]);
610 i = sizeof(*outip) + proto->hdrlen + sizeof(struct outdata) + optlen;
612 packlen = i; /* minimum sized packet */
613 else if (i > packlen || packlen > maxpacket) {
614 Fprintf(stderr, "%s: packet size must be %d <= s <= %d\n",
618 protlen = packlen - sizeof(*outip) - optlen;
620 outip = (struct ip *)malloc((unsigned)packlen);
622 Fprintf(stderr, "%s: malloc: %s\n", prog, strerror(errno));
625 memset((char *)outip, 0, packlen);
627 outip->ip_v = IPVERSION;
629 #ifdef BYTESWAP_IP_LEN
630 outip->ip_len = htons(packlen);
632 outip->ip_len = packlen;
634 outip->ip_p = proto->num;
635 outprot = (u_char *)(outip + 1);
636 #ifdef HAVE_RAW_OPTIONS
638 register u_char *optlist;
640 optlist = (u_char *)outprot;
641 (u_char *)outprot += optlen;
644 gwlist[lsrr] = to->sin_addr.s_addr;
646 outip->ip_dst.s_addr = gwlist[0];
648 /* force 4 byte alignment */
649 optlist[0] = IPOPT_NOP;
650 /* loose source route option */
651 optlist[1] = IPOPT_LSRR;
652 i = lsrr * sizeof(gwlist[0]);
654 /* Pointer to LSRR addresses */
655 optlist[3] = IPOPT_MINOFF;
656 memcpy(optlist + 4, gwlist + 1, i);
659 outip->ip_dst = to->sin_addr;
661 outip->ip_hl = ((u_char *)outprot - (u_char *)outip) >> 2;
663 ident = (getpid() & 0xffff) | 0x8000;
666 Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp);
671 Fprintf(stderr, "%s: icmp socket: %s\n", prog, strerror(errno));
674 if (options & SO_DEBUG)
675 (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on,
677 if (options & SO_DONTROUTE)
678 (void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
681 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
682 if (setpolicy(s, "in bypass") < 0)
683 errx(1, "%s", ipsec_strerror());
685 if (setpolicy(s, "out bypass") < 0)
686 errx(1, "%s", ipsec_strerror());
687 #endif /* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */
691 Fprintf(stderr, "%s: raw socket: %s\n", prog, strerror(errno));
695 #if defined(IP_OPTIONS) && !defined(HAVE_RAW_OPTIONS)
697 u_char optlist[MAX_IPOPTLEN];
700 if ((pe = getprotobyname(cp)) == NULL) {
701 Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp);
706 gwlist[lsrr] = to->sin_addr.s_addr;
709 /* force 4 byte alignment */
710 optlist[0] = IPOPT_NOP;
711 /* loose source route option */
712 optlist[1] = IPOPT_LSRR;
713 i = lsrr * sizeof(gwlist[0]);
715 /* Pointer to LSRR addresses */
716 optlist[3] = IPOPT_MINOFF;
717 memcpy(optlist + 4, gwlist, i);
719 if ((setsockopt(sndsock, pe->p_proto, IP_OPTIONS, optlist,
720 i + sizeof(gwlist[0]))) < 0) {
721 Fprintf(stderr, "%s: IP_OPTIONS: %s\n",
722 prog, strerror(errno));
729 if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&packlen,
730 sizeof(packlen)) < 0) {
731 Fprintf(stderr, "%s: SO_SNDBUF: %s\n", prog, strerror(errno));
736 if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on,
738 Fprintf(stderr, "%s: IP_HDRINCL: %s\n", prog, strerror(errno));
742 if (options & SO_DEBUG)
743 (void)setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on,
745 if (options & SO_DONTROUTE)
746 (void)setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
749 if (source != NULL) {
750 source = savestr(getsin(&from, source));
751 outip->ip_src = from.sin_addr;
753 if (bind(sndsock, (struct sockaddr *)&from, sizeof(from)) < 0) {
754 Fprintf(stderr, "%s: bind: %s\n",
755 prog, strerror(errno));
761 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
762 if (setpolicy(sndsock, "in bypass") < 0)
763 errx(1, "%s", ipsec_strerror());
765 if (setpolicy(sndsock, "out bypass") < 0)
766 errx(1, "%s", ipsec_strerror());
767 #endif /* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */
769 Fprintf(stderr, "%s to %s (%s)",
770 prog, hostname, inet_ntoa(to->sin_addr));
772 Fprintf(stderr, " from %s", source);
773 Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, packlen);
774 (void)fflush(stderr);
776 for (ttl = min_ttl; ttl <= max_ttl; ++ttl) {
777 u_int32_t lastaddr = 0;
783 for (probe = 0, loss = 0; probe < nprobes; ++probe) {
785 struct timeval t1, t2;
787 register struct ip *ip;
788 struct outdata outdata;
790 /* Prepare outgoing data */
793 outdata.optlen = optlen;
795 /* Avoid alignment problems by copying bytewise: */
796 (void)gettimeofday(&t1, &tz);
797 memcpy(&outdata.tv, &t1, sizeof(outdata.tv));
799 /* Finalize and send packet */
800 (*proto->prepare)(&outdata);
801 send_probe(seq, ttl);
803 /* Wait for a reply */
804 while ((cc = wait_for_reply(s, &from, &t1)) != 0) {
808 (void)gettimeofday(&t2, &tz);
809 i = packet_ok(packet, cc, &from, seq);
810 /* Skip short packet */
813 if (from.sin_addr.s_addr != lastaddr) {
814 print(packet, cc, &from);
815 lastaddr = from.sin_addr.s_addr;
817 T = deltaT(&t1, &t2);
818 #ifdef SANE_PRECISION
828 Printf(" %.*f ms", precis, T);
831 ip = (struct ip *)packet;
840 /* time exceeded in transit */
847 case ICMP_UNREACH_PORT:
849 ip = (struct ip *)packet;
856 case ICMP_UNREACH_NET:
861 case ICMP_UNREACH_HOST:
866 case ICMP_UNREACH_PROTOCOL:
871 case ICMP_UNREACH_NEEDFRAG:
876 case ICMP_UNREACH_SRCFAIL:
882 #ifndef ICMP_UNREACH_FILTER_PROHIB
883 #define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohibited filter */
885 case ICMP_UNREACH_FILTER_PROHIB:
892 Printf(" !<%d>", code);
901 (void)fflush(stdout);
904 Printf(" (%d%% loss)", (loss * 100) / nprobes);
908 (unreachable > 0 && unreachable >= nprobes - 1))
915 wait_for_reply(register int sock, register struct sockaddr_in *fromp,
916 register struct timeval *tp)
920 struct timeval now, wait;
924 int fromlen = sizeof(*fromp);
926 nfds = howmany(sock + 1, NFDBITS);
927 if ((fdsp = malloc(nfds * sizeof(fd_mask))) == NULL)
929 memset(fdsp, 0, nfds * sizeof(fd_mask));
932 wait.tv_sec = tp->tv_sec + waittime;
933 wait.tv_usec = tp->tv_usec;
934 (void)gettimeofday(&now, &tz);
936 if (wait.tv_sec < 0) {
941 error = select(sock + 1, fdsp, NULL, NULL, &wait);
942 if (error == -1 && errno == EINVAL) {
943 Fprintf(stderr, "%s: botched select() args\n", prog);
947 cc = recvfrom(s, (char *)packet, sizeof(packet), 0,
948 (struct sockaddr *)fromp, &fromlen);
954 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
956 setpolicy(so, policy)
962 buf = ipsec_set_policy(policy, strlen(policy));
964 warnx("%s", ipsec_strerror());
967 (void)setsockopt(so, IPPROTO_IP, IP_IPSEC_POLICY,
968 buf, ipsec_get_policylen(buf));
977 send_probe(int seq, int ttl)
982 outip->ip_id = htons(ident + seq);
984 i = sendto(sndsock, (char *)outip, packlen, 0, &whereto,
986 if (i < 0 || i != packlen) {
988 Fprintf(stderr, "%s: sendto: %s\n",
989 prog, strerror(errno));
990 Printf("%s: wrote %s %d chars, ret=%d\n",
991 prog, hostname, packlen, i);
992 (void)fflush(stdout);
997 deltaT(struct timeval *t1p, struct timeval *t2p)
1001 dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
1002 (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
1007 * Convert an ICMP "type" field to a printable string.
1010 pr_type(register u_char t)
1012 static char *ttab[] = {
1013 "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable",
1014 "Source Quench", "Redirect", "ICMP 6", "ICMP 7",
1015 "Echo", "ICMP 9", "ICMP 10", "Time Exceeded",
1016 "Param Problem", "Timestamp", "Timestamp Reply", "Info Request",
1021 return("OUT-OF-RANGE");
1027 packet_ok(register u_char *buf, int cc, register struct sockaddr_in *from,
1030 register struct icmp *icp;
1031 register u_char type, code;
1034 register struct ip *ip;
1036 ip = (struct ip *) buf;
1037 hlen = ip->ip_hl << 2;
1038 if (cc < hlen + ICMP_MINLEN) {
1040 Printf("packet too short (%d bytes) from %s\n", cc,
1041 inet_ntoa(from->sin_addr));
1045 icp = (struct icmp *)(buf + hlen);
1047 icp = (struct icmp *)buf;
1049 type = icp->icmp_type;
1050 code = icp->icmp_code;
1051 if (type == ICMP_ECHOREPLY
1052 && proto->num == IPPROTO_ICMP
1053 && (*proto->check)((u_char *)icp,seq))
1055 if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
1056 type == ICMP_UNREACH) {
1060 hip = &icp->icmp_ip;
1061 hlen = hip->ip_hl << 2;
1062 inner = (u_char *)((u_char *)hip + hlen);
1064 && hip->ip_p == proto->num
1065 && (*proto->check)(inner, seq))
1066 return (type == ICMP_TIMXCEED ? -1 : code + 1);
1071 u_int32_t *lp = (u_int32_t *)&icp->icmp_ip;
1073 Printf("\n%d bytes from %s to ", cc, inet_ntoa(from->sin_addr));
1074 Printf("%s: icmp type %d (%s) code %d\n",
1075 inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code);
1076 for (i = 4; i < cc ; i += sizeof(*lp))
1077 Printf("%2d: x%8.8x\n", i, *lp++);
1084 icmp_prep(struct outdata *outdata)
1086 struct icmp *const icmpheader = (struct icmp *) outprot;
1088 icmpheader->icmp_type = ICMP_ECHO;
1089 icmpheader->icmp_id = htons(ident);
1090 icmpheader->icmp_seq = htons(outdata->seq);
1092 icmpheader->icmp_cksum = 0;
1093 icmpheader->icmp_cksum = in_cksum((u_short *)icmpheader,
1094 packlen - (sizeof(*outip) + outdata->optlen));
1095 if (icmpheader->icmp_cksum == 0)
1096 icmpheader->icmp_cksum = 0xffff;
1101 icmp_check(const u_char *data, int seq)
1103 struct icmp *const icmpheader = (struct icmp *) data;
1105 return (icmpheader->icmp_id == htons(ident)
1106 && icmpheader->icmp_seq == htons(seq));
1110 udp_prep(struct outdata *outdata)
1112 struct udphdr *const udp = (struct udphdr *) outprot;
1114 udp->uh_sport = htons(ident);
1115 udp->uh_dport = htons(port + outdata->seq);
1116 udp->uh_ulen = htons((u_short)protlen);
1120 udp_check(const u_char *data, int seq)
1122 struct udphdr *const udp = (struct udphdr *) data;
1124 return (ntohs(udp->uh_sport) == ident
1125 && ntohs(udp->uh_dport) == port + seq);
1129 tcp_prep(struct outdata *outdata)
1131 struct tcphdr *const tcp = (struct tcphdr *) outprot;
1133 tcp->th_sport = htons(ident);
1134 tcp->th_dport = htons(port + outdata->seq);
1135 tcp->th_seq = (tcp->th_sport << 16) | tcp->th_dport;
1138 tcp->th_flags = TH_SYN;
1142 tcp_check(const u_char *data, int seq)
1144 struct tcphdr *const tcp = (struct tcphdr *) data;
1146 return (ntohs(tcp->th_sport) == ident
1147 && ntohs(tcp->th_dport) == port + seq);
1151 gre_prep(struct outdata *outdata)
1153 struct grehdr *const gre = (struct grehdr *) outprot;
1155 gre->flags = htons(0x2001);
1156 gre->proto = htons(port);
1158 gre->callId = htons(ident + outdata->seq);
1162 gre_check(const u_char *data, int seq)
1164 struct grehdr *const gre = (struct grehdr *) data;
1166 return(ntohs(gre->proto) == port
1167 && ntohs(gre->callId) == ident + seq);
1171 gen_prep(struct outdata *outdata)
1173 u_int16_t *const ptr = (u_int16_t *) outprot;
1175 ptr[0] = htons(ident);
1176 ptr[1] = htons(port + outdata->seq);
1180 gen_check(const u_char *data, int seq)
1182 u_int16_t *const ptr = (u_int16_t *) data;
1184 return(ntohs(ptr[0]) == ident
1185 && ntohs(ptr[1]) == port + seq);
1189 print(register u_char *buf, register int cc, register struct sockaddr_in *from)
1191 register struct ip *ip;
1194 ip = (struct ip *) buf;
1195 hlen = ip->ip_hl << 2;
1199 Printf(" %s", inet_ntoa(from->sin_addr));
1201 Printf(" %s (%s)", inetname(from->sin_addr),
1202 inet_ntoa(from->sin_addr));
1205 Printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
1209 * Checksum routine for Internet Protocol family headers (C Version)
1212 in_cksum(register u_short *addr, register int len)
1214 register int nleft = len;
1215 register u_short *w = addr;
1216 register u_short answer;
1217 register int sum = 0;
1220 * Our algorithm is simple, using a 32 bit accumulator (sum),
1221 * we add sequential 16 bit words to it, and at the end, fold
1222 * back all the carry bits from the top 16 bits into the lower
1230 /* mop up an odd byte, if necessary */
1232 sum += *(u_char *)w;
1235 * add back carry outs from top 16 bits to low 16 bits
1237 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
1238 sum += (sum >> 16); /* add carry */
1239 answer = ~sum; /* truncate to 16 bits */
1244 * Subtract 2 timeval structs: out = out - in.
1245 * Out is assumed to be within about LONG_MAX seconds of in.
1248 tvsub(register struct timeval *out, register struct timeval *in)
1251 if ((out->tv_usec -= in->tv_usec) < 0) {
1253 out->tv_usec += 1000000;
1255 out->tv_sec -= in->tv_sec;
1259 * Construct an Internet address representation.
1260 * If the nflag has been supplied, give
1261 * numeric value, otherwise try for symbolic name.
1264 inetname(struct in_addr in)
1267 register struct hostent *hp;
1268 static int first = 1;
1269 static char domain[MAXHOSTNAMELEN + 1], line[MAXHOSTNAMELEN + 1];
1271 if (first && !nflag) {
1273 if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
1274 (cp = strchr(domain, '.')) != NULL) {
1275 (void)strncpy(domain, cp + 1, sizeof(domain) - 1);
1276 domain[sizeof(domain) - 1] = '\0';
1280 if (!nflag && in.s_addr != INADDR_ANY) {
1281 hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET);
1283 if ((cp = strchr(hp->h_name, '.')) != NULL &&
1284 strcmp(cp + 1, domain) == 0)
1286 (void)strncpy(line, hp->h_name, sizeof(line) - 1);
1287 line[sizeof(line) - 1] = '\0';
1291 return (inet_ntoa(in));
1295 getaddr(register u_int32_t *ap, register char *hostname)
1297 register struct hostent *hp;
1299 *ap = inet_addr(hostname);
1300 if ((int32_t)*ap != -1)
1303 hp = gethostbyname(hostname);
1305 Fprintf(stderr, "%s: unknown host %s\n", prog, hostname);
1308 if (hp->h_addrtype != AF_INET || hp->h_length != 4) {
1309 Fprintf(stderr, "%s: bad host %s\n", prog, hostname);
1312 memcpy((caddr_t)ap, hp->h_addr, hp->h_length);
1313 return (hp->h_name);
1317 getsin(register struct sockaddr_in *sin, register char *hostname)
1320 memset(sin, 0, sizeof(*sin));
1321 sin->sin_family = AF_INET;
1322 return (getaddr((u_int32_t *)&sin->sin_addr.s_addr, hostname));
1326 savestr(register const char *str)
1332 Fprintf(stderr, "%s: strdup: %s\n", prog, strerror(errno));
1341 extern char version[];
1343 Fprintf(stderr, "Version %s\n", version);
1344 Fprintf(stderr, "Usage: %s [-Sdnrv] [-w wait] [-m max_ttl] [-M min_ttl] \
1345 [-P proto]\n\t [-p port#] [-q nqueries] [-t tos] [-s src_addr] [-g gateway] \
1346 \n\t host [data_size]\n", prog);