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.
23 static const char copyright[] =
24 "@(#) Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996\n\
25 The Regents of the University of California. All rights reserved.\n";
27 static const char rcsid[] =
28 "@(#)$Header: traceroute.c,v 1.43 96/09/27 20:08:10 leres Exp $ (LBL)";
30 static const char rcsid[] =
31 "$FreeBSD: src/contrib/traceroute/traceroute.c,v 1.11.2.6 2002/08/05 23:37:16 fenner Exp $";
35 * traceroute host - trace the route ip packets follow going to "host".
37 * Attempt to trace the route an ip packet would follow to some
38 * internet host. We find out intermediate hops by launching probe
39 * packets with a small ttl (time to live) then listening for an
40 * icmp "time exceeded" reply from a gateway. We start our probes
41 * with a ttl of one and increase by one until we get an icmp "port
42 * unreachable" (which means we got to "host") or hit a max (which
43 * defaults to net.inet.ip.ttl hops & can be changed with the -m flag).
44 * Three probes (change with -q flag) are sent at each ttl setting and
45 * a line is printed showing the ttl, address of the gateway and
46 * round trip time of each probe. If the probe answers come from
47 * different gateways, the address of each responding system will
48 * be printed. If there is no response within a 5 sec. timeout
49 * interval (changed with the -w flag), a "*" is printed for that
52 * Probe packets are UDP format. We don't want the destination
53 * host to process them so the destination port is set to an
54 * unlikely value (if some clod on the destination is using that
55 * value, it can be changed with the -p flag).
57 * A sample use might be:
59 * [yak 71]% traceroute nis.nsf.net.
60 * traceroute to nis.nsf.net (35.1.1.48), 64 hops max, 56 byte packet
61 * 1 helios.ee.lbl.gov (128.3.112.1) 19 ms 19 ms 0 ms
62 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
63 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
64 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 39 ms
65 * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 39 ms 39 ms 39 ms
66 * 6 128.32.197.4 (128.32.197.4) 40 ms 59 ms 59 ms
67 * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 59 ms
68 * 8 129.140.70.13 (129.140.70.13) 99 ms 99 ms 80 ms
69 * 9 129.140.71.6 (129.140.71.6) 139 ms 239 ms 319 ms
70 * 10 129.140.81.7 (129.140.81.7) 220 ms 199 ms 199 ms
71 * 11 nic.merit.edu (35.1.1.48) 239 ms 239 ms 239 ms
73 * Note that lines 2 & 3 are the same. This is due to a buggy
74 * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
75 * packets with a zero ttl.
77 * A more interesting example is:
79 * [yak 72]% traceroute allspice.lcs.mit.edu.
80 * traceroute to allspice.lcs.mit.edu (18.26.0.115), 64 hops max
81 * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
82 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 19 ms 19 ms
83 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 19 ms
84 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 19 ms 39 ms 39 ms
85 * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 20 ms 39 ms 39 ms
86 * 6 128.32.197.4 (128.32.197.4) 59 ms 119 ms 39 ms
87 * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 39 ms
88 * 8 129.140.70.13 (129.140.70.13) 80 ms 79 ms 99 ms
89 * 9 129.140.71.6 (129.140.71.6) 139 ms 139 ms 159 ms
90 * 10 129.140.81.7 (129.140.81.7) 199 ms 180 ms 300 ms
91 * 11 129.140.72.17 (129.140.72.17) 300 ms 239 ms 239 ms
93 * 13 128.121.54.72 (128.121.54.72) 259 ms 499 ms 279 ms
98 * 18 ALLSPICE.LCS.MIT.EDU (18.26.0.115) 339 ms 279 ms 279 ms
100 * (I start to see why I'm having so much trouble with mail to
101 * MIT.) Note that the gateways 12, 14, 15, 16 & 17 hops away
102 * either don't send ICMP "time exceeded" messages or send them
103 * with a ttl too small to reach us. 14 - 17 are running the
104 * MIT C Gateway code that doesn't send "time exceeded"s. God
105 * only knows what's going on with 12.
107 * The silent gateway 12 in the above may be the result of a bug in
108 * the 4.[23]BSD network code (and its derivatives): 4.x (x <= 3)
109 * sends an unreachable message using whatever ttl remains in the
110 * original datagram. Since, for gateways, the remaining ttl is
111 * zero, the icmp "time exceeded" is guaranteed to not make it back
112 * to us. The behavior of this bug is slightly more interesting
113 * when it appears on the destination system:
115 * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
116 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 39 ms
117 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 39 ms 19 ms
118 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 19 ms
119 * 5 ccn-nerif35.Berkeley.EDU (128.32.168.35) 39 ms 39 ms 39 ms
120 * 6 csgw.Berkeley.EDU (128.32.133.254) 39 ms 59 ms 39 ms
127 * 13 rip.Berkeley.EDU (128.32.131.22) 59 ms ! 39 ms ! 39 ms !
129 * Notice that there are 12 "gateways" (13 is the final
130 * destination) and exactly the last half of them are "missing".
131 * What's really happening is that rip (a Sun-3 running Sun OS3.5)
132 * is using the ttl from our arriving datagram as the ttl in its
133 * icmp reply. So, the reply will time out on the return path
134 * (with no notice sent to anyone since icmp's aren't sent for
135 * icmp's) until we probe with a ttl that's at least twice the path
136 * length. I.e., rip is really only 7 hops away. A reply that
137 * returns with a ttl of 1 is a clue this problem exists.
138 * Traceroute prints a "!" after the time if the ttl is <= 1.
139 * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
140 * non-standard (HPUX) software, expect to see this problem
141 * frequently and/or take care picking the target host of your
144 * Other possible annotations after the time are !H, !N, !P (got a host,
145 * network or protocol unreachable, respectively), !S or !F (source
146 * route failed or fragmentation needed -- neither of these should
147 * ever occur and the associated gateway is busted if you see one). If
148 * almost all the probes result in some kind of unreachable, traceroute
149 * will give up and exit.
153 * This program must be run by root or be setuid. (I suggest that
154 * you *don't* make it setuid -- casual use could result in a lot
155 * of unnecessary traffic on our poor, congested nets.)
157 * This program requires a kernel mod that does not appear in any
158 * system available from Berkeley: A raw ip socket using proto
159 * IPPROTO_RAW must interpret the data sent as an ip datagram (as
160 * opposed to data to be wrapped in a ip datagram). See the README
161 * file that came with the source to this program for a description
162 * of the mods I made to /sys/netinet/raw_ip.c. Your mileage may
163 * vary. But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
164 * MODIFIED TO RUN THIS PROGRAM.
166 * The udp port usage may appear bizarre (well, ok, it is bizarre).
167 * The problem is that an icmp message only contains 8 bytes of
168 * data from the original datagram. 8 bytes is the size of a udp
169 * header so, if we want to associate replies with the original
170 * datagram, the necessary information must be encoded into the
171 * udp header (the ip id could be used but there's no way to
172 * interlock with the kernel's assignment of ip id's and, anyway,
173 * it would have taken a lot more kernel hacking to allow this
174 * code to set the ip id). So, to allow two or more users to
175 * use traceroute simultaneously, we use this task's pid as the
176 * source port (the high bit is set to move the port number out
177 * of the "likely" range). To keep track of which probe is being
178 * replied to (so times and/or hop counts don't get confused by a
179 * reply that was delayed in transit), we increment the destination
180 * port number before each probe.
182 * Don't use this as a coding example. I was trying to find a
183 * routing problem and this code sort-of popped out after 48 hours
184 * without sleep. I was amazed it ever compiled, much less ran.
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.
193 * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
194 * enhancements to the original distribution.
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...
201 * -- Van Jacobson (van@ee.lbl.gov)
202 * Tue Dec 20 03:50:13 PST 1988
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>
211 #include <sys/socket.h>
212 #ifdef HAVE_SYS_SYSCTL_H
213 #include <sys/sysctl.h>
215 #include <sys/time.h>
217 #include <netinet/in_systm.h>
218 #include <netinet/in.h>
219 #include <netinet/ip.h>
220 #include <netinet/ip_var.h>
221 #include <netinet/ip_icmp.h>
222 #include <netinet/udp.h>
223 #include <netinet/tcp.h>
225 #include <arpa/inet.h>
228 #include <net/route.h>
229 #include <netinet6/ipsec.h> /* XXX */
245 #ifdef HAVE_OS_PROTO_H
246 #include "os-proto.h"
249 /* Maximum number of gateways (include room for one noop) */
250 #define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t)))
252 #ifndef MAXHOSTNAMELEN
253 #define MAXHOSTNAMELEN 64
256 #define Fprintf (void)fprintf
257 #define Printf (void)printf
259 /* What a GRE packet header looks like */
263 u_int16_t length; /* PPTP version of these fields */
267 #define IPPROTO_GRE 47
270 /* For GRE, we prepare what looks like a PPTP packet */
271 #define GRE_PPTP_PROTO 0x880b
273 /* Data section of the probe packet */
275 u_char seq; /* sequence number of this packet */
276 u_char ttl; /* ttl packet left with */
277 struct timeval tv; /* time packet left */
278 int optlen; /* length of ip options */
281 /* Descriptor structure for each outgoing protocol we support */
283 char *name; /* name of protocol */
284 u_char num; /* IP protocol number */
285 u_short hdrlen; /* max size of protocol header */
286 u_short port; /* default base protocol-specific "port" */
287 void (*prepare)(struct outdata *);
288 /* finish preparing an outgoing packet */
289 int (*check)(const u_char *, int);
290 /* check an incoming packet */
293 u_char packet[512]; /* last inbound (icmp) packet */
295 struct ip *outip; /* last output ip packet */
296 u_char *outprot; /* last output inner protocol packet */
298 /* loose source route gateway list (including room for final destination) */
299 u_int32_t gwlist[NGATEWAYS + 1];
301 int s; /* receive (icmp) socket file descriptor */
302 int sndsock; /* send (udp) socket file descriptor */
304 struct sockaddr whereto; /* Who to try to reach */
305 int packlen; /* total length of packet */
306 int protlen; /* length of protocol part of packet */
307 int maxpacket = 32 * 1024; /* max ip packet size */
317 u_short port; /* protocol specific base "port" */
319 int options; /* socket options */
321 int waittime = 5; /* time to wait for response (in seconds) */
322 int nflag; /* print addresses numerically */
329 double deltaT(struct timeval *, struct timeval *);
330 u_short in_cksum(u_short *, int);
331 char *inetname(struct in_addr);
332 int main(int, char **);
333 int packet_ok(u_char *, int, struct sockaddr_in *, int);
334 char *pr_type(u_char);
335 void print(u_char *, int, struct sockaddr_in *);
336 char *getaddr(u_int32_t *, char *);
337 char *getsin(struct sockaddr_in *, char *);
338 char *savestr(const char *);
340 int setpolicy __P((int so, char *policy));
342 void send_probe(int, int);
343 void tvsub(struct timeval *, struct timeval *);
344 __dead void usage(void);
345 int wait_for_reply(int, struct sockaddr_in *, struct timeval *);
347 void udp_prep(struct outdata *);
348 int udp_check(const u_char *, int);
349 void tcp_prep(struct outdata *);
350 int tcp_check(const u_char *, int);
351 void gre_prep(struct outdata *);
352 int gre_check(const u_char *, int);
353 void gen_prep(struct outdata *);
354 int gen_check(const u_char *, int);
355 void icmp_prep(struct outdata *);
356 int icmp_check(const u_char *, int);
358 /* List of supported protocols. The first one is the default. The last
359 one is the handler for generic protocols not explicitly listed. */
360 struct outproto protos[] = {
364 sizeof(struct udphdr),
372 sizeof(struct tcphdr),
380 sizeof(struct grehdr),
402 struct outproto *proto = &protos[0];
405 main(int argc, char **argv)
407 register int op, code;
409 struct sockaddr_in from;
410 register struct sockaddr_in *to = (struct sockaddr_in *)&whereto;
412 register struct protoent *pe;
413 register int ttl, probe, i;
414 register int seq = 0;
415 register int tos = 0;
416 register int lsrr = 0;
417 register int optlen = 0;
418 int requestPort = -1;
423 * Do the setuid-required stuff first, then lose priveleges ASAP.
424 * Do error checking for these two calls where they appeared in
428 pe = getprotobyname(cp);
430 if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0)
432 else if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
440 int mib[4] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_DEFTTL };
441 size_t sz = sizeof(max_ttl);
443 if (sysctl(mib, 4, &max_ttl, &sz, NULL, 0) == -1)
444 err(1, "sysctl(net.inet.ip.ttl)");
450 if ((cp = strrchr(argv[0], '/')) != NULL)
456 while ((op = getopt(argc, argv, "Sdnrvg:M:m:P:p:q:s:t:w:")) != EOF)
467 if (lsrr >= NGATEWAYS) {
469 "%s: No more than %d gateways\n",
473 (void)getaddr(gwlist + lsrr, optarg);
478 min_ttl = atoi(optarg);
479 if (min_ttl < 1 || min_ttl > 0xff) {
480 Fprintf(stderr, "%s: invalid ttl value %s\n",
487 max_ttl = atoi(optarg);
488 if (max_ttl < 1 || max_ttl > 0xff) {
489 Fprintf(stderr, "%s: invalid ttl value %s\n",
500 for (i = 0; protos[i].name != NULL; i++) {
501 if (strcasecmp(protos[i].name, optarg) == 0) {
506 if (proto->name == NULL) { /* generic handler */
511 /* Determine the IP protocol number */
512 if ((pe = getprotobyname(optarg)) != NULL)
515 pnum = strtoul(optarg, &eptr, 10);
519 Fprintf(stderr, "%s: unknown "
530 requestPort = atoi(optarg);
531 if (requestPort <= 0) {
532 Fprintf(stderr, "%s: port must be > 0\n", prog);
538 nprobes = atoi(optarg);
540 Fprintf(stderr, "%s: nprobes must be > 0\n",
547 options |= SO_DONTROUTE;
552 * set the ip source address of the outbound
553 * probe (e.g., on a multi-homed host).
560 if (tos < 0 || tos > 255) {
561 Fprintf(stderr, "%s: tos must be 0 to 255\n",
572 waittime = atoi(optarg);
573 if (waittime <= 1 || waittime >= 24L * 60 * 60) {
575 "%s: wait must be > 1 sec and < 1 day\n",
585 /* Set requested port, if any, else default for this protocol */
586 port = (requestPort != -1) ? requestPort : proto->port;
588 /* Check min vs. max TTL */
589 if (min_ttl > max_ttl) {
590 Fprintf(stderr, "%s: min ttl must be <= max ttl\n", prog);
594 /* Process destination and optional packet size */
595 switch (argc - optind) {
598 packlen = atoi(argv[optind + 1]);
602 hostname = savestr(getsin(to, argv[optind]));
609 #ifdef HAVE_SETLINEBUF
612 setvbuf(stdout, NULL, _IOLBF, 0);
616 optlen = (lsrr + 1) * sizeof(gwlist[0]);
617 i = sizeof(*outip) + proto->hdrlen + sizeof(struct outdata) + optlen;
619 packlen = i; /* minimum sized packet */
620 else if (i > packlen || packlen > maxpacket) {
621 Fprintf(stderr, "%s: packet size must be %d <= s <= %d\n",
625 protlen = packlen - sizeof(*outip) - optlen;
627 outip = (struct ip *)malloc((unsigned)packlen);
629 Fprintf(stderr, "%s: malloc: %s\n", prog, strerror(errno));
632 memset((char *)outip, 0, packlen);
634 outip->ip_v = IPVERSION;
636 #ifdef BYTESWAP_IP_LEN
637 outip->ip_len = htons(packlen);
639 outip->ip_len = packlen;
641 outip->ip_p = proto->num;
642 outprot = (u_char *)(outip + 1);
643 #ifdef HAVE_RAW_OPTIONS
645 register u_char *optlist;
647 optlist = (u_char *)outprot;
648 (u_char *)outprot += optlen;
651 gwlist[lsrr] = to->sin_addr.s_addr;
653 outip->ip_dst.s_addr = gwlist[0];
655 /* force 4 byte alignment */
656 optlist[0] = IPOPT_NOP;
657 /* loose source route option */
658 optlist[1] = IPOPT_LSRR;
659 i = lsrr * sizeof(gwlist[0]);
661 /* Pointer to LSRR addresses */
662 optlist[3] = IPOPT_MINOFF;
663 memcpy(optlist + 4, gwlist + 1, i);
666 outip->ip_dst = to->sin_addr;
668 outip->ip_hl = ((u_char *)outprot - (u_char *)outip) >> 2;
670 ident = (getpid() & 0xffff) | 0x8000;
673 Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp);
678 Fprintf(stderr, "%s: icmp socket: %s\n", prog, strerror(errno));
681 if (options & SO_DEBUG)
682 (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on,
684 if (options & SO_DONTROUTE)
685 (void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
688 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
689 if (setpolicy(s, "in bypass") < 0)
690 errx(1, "%s", ipsec_strerror());
692 if (setpolicy(s, "out bypass") < 0)
693 errx(1, "%s", ipsec_strerror());
694 #endif /* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */
698 Fprintf(stderr, "%s: raw socket: %s\n", prog, strerror(errno));
702 #if defined(IP_OPTIONS) && !defined(HAVE_RAW_OPTIONS)
704 u_char optlist[MAX_IPOPTLEN];
707 if ((pe = getprotobyname(cp)) == NULL) {
708 Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp);
713 gwlist[lsrr] = to->sin_addr.s_addr;
716 /* force 4 byte alignment */
717 optlist[0] = IPOPT_NOP;
718 /* loose source route option */
719 optlist[1] = IPOPT_LSRR;
720 i = lsrr * sizeof(gwlist[0]);
722 /* Pointer to LSRR addresses */
723 optlist[3] = IPOPT_MINOFF;
724 memcpy(optlist + 4, gwlist, i);
726 if ((setsockopt(sndsock, pe->p_proto, IP_OPTIONS, optlist,
727 i + sizeof(gwlist[0]))) < 0) {
728 Fprintf(stderr, "%s: IP_OPTIONS: %s\n",
729 prog, strerror(errno));
736 if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&packlen,
737 sizeof(packlen)) < 0) {
738 Fprintf(stderr, "%s: SO_SNDBUF: %s\n", prog, strerror(errno));
743 if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on,
745 Fprintf(stderr, "%s: IP_HDRINCL: %s\n", prog, strerror(errno));
749 if (options & SO_DEBUG)
750 (void)setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on,
752 if (options & SO_DONTROUTE)
753 (void)setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
756 if (source != NULL) {
757 source = savestr(getsin(&from, source));
758 outip->ip_src = from.sin_addr;
760 if (bind(sndsock, (struct sockaddr *)&from, sizeof(from)) < 0) {
761 Fprintf(stderr, "%s: bind: %s\n",
762 prog, strerror(errno));
768 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
769 if (setpolicy(sndsock, "in bypass") < 0)
770 errx(1, "%s", ipsec_strerror());
772 if (setpolicy(sndsock, "out bypass") < 0)
773 errx(1, "%s", ipsec_strerror());
774 #endif /* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */
776 Fprintf(stderr, "%s to %s (%s)",
777 prog, hostname, inet_ntoa(to->sin_addr));
779 Fprintf(stderr, " from %s", source);
780 Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, packlen);
781 (void)fflush(stderr);
783 for (ttl = min_ttl; ttl <= max_ttl; ++ttl) {
784 u_int32_t lastaddr = 0;
790 for (probe = 0, loss = 0; probe < nprobes; ++probe) {
792 struct timeval t1, t2;
794 register struct ip *ip;
795 struct outdata outdata;
797 /* Prepare outgoing data */
800 outdata.optlen = optlen;
802 /* Avoid alignment problems by copying bytewise: */
803 (void)gettimeofday(&t1, &tz);
804 memcpy(&outdata.tv, &t1, sizeof(outdata.tv));
806 /* Finalize and send packet */
807 (*proto->prepare)(&outdata);
808 send_probe(seq, ttl);
810 /* Wait for a reply */
811 while ((cc = wait_for_reply(s, &from, &t1)) != 0) {
815 (void)gettimeofday(&t2, &tz);
816 i = packet_ok(packet, cc, &from, seq);
817 /* Skip short packet */
820 if (from.sin_addr.s_addr != lastaddr) {
821 print(packet, cc, &from);
822 lastaddr = from.sin_addr.s_addr;
824 T = deltaT(&t1, &t2);
825 #ifdef SANE_PRECISION
835 Printf(" %.*f ms", precis, T);
838 ip = (struct ip *)packet;
847 /* time exceeded in transit */
854 case ICMP_UNREACH_PORT:
856 ip = (struct ip *)packet;
863 case ICMP_UNREACH_NET:
868 case ICMP_UNREACH_HOST:
873 case ICMP_UNREACH_PROTOCOL:
878 case ICMP_UNREACH_NEEDFRAG:
883 case ICMP_UNREACH_SRCFAIL:
889 #ifndef ICMP_UNREACH_FILTER_PROHIB
890 #define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohibited filter */
892 case ICMP_UNREACH_FILTER_PROHIB:
899 Printf(" !<%d>", code);
908 (void)fflush(stdout);
911 Printf(" (%d%% loss)", (loss * 100) / nprobes);
915 (unreachable > 0 && unreachable >= nprobes - 1))
922 wait_for_reply(register int sock, register struct sockaddr_in *fromp,
923 register struct timeval *tp)
927 struct timeval now, wait;
931 int fromlen = sizeof(*fromp);
933 nfds = howmany(sock + 1, NFDBITS);
934 if ((fdsp = malloc(nfds * sizeof(fd_mask))) == NULL)
936 memset(fdsp, 0, nfds * sizeof(fd_mask));
939 wait.tv_sec = tp->tv_sec + waittime;
940 wait.tv_usec = tp->tv_usec;
941 (void)gettimeofday(&now, &tz);
943 if (wait.tv_sec < 0) {
948 error = select(sock + 1, fdsp, NULL, NULL, &wait);
949 if (error == -1 && errno == EINVAL) {
950 Fprintf(stderr, "%s: botched select() args\n", prog);
954 cc = recvfrom(s, (char *)packet, sizeof(packet), 0,
955 (struct sockaddr *)fromp, &fromlen);
961 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
963 setpolicy(so, policy)
969 buf = ipsec_set_policy(policy, strlen(policy));
971 warnx("%s", ipsec_strerror());
974 (void)setsockopt(so, IPPROTO_IP, IP_IPSEC_POLICY,
975 buf, ipsec_get_policylen(buf));
984 send_probe(int seq, int ttl)
989 outip->ip_id = htons(ident + seq);
991 i = sendto(sndsock, (char *)outip, packlen, 0, &whereto,
993 if (i < 0 || i != packlen) {
995 Fprintf(stderr, "%s: sendto: %s\n",
996 prog, strerror(errno));
997 Printf("%s: wrote %s %d chars, ret=%d\n",
998 prog, hostname, packlen, i);
999 (void)fflush(stdout);
1004 deltaT(struct timeval *t1p, struct timeval *t2p)
1008 dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
1009 (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
1014 * Convert an ICMP "type" field to a printable string.
1017 pr_type(register u_char t)
1019 static char *ttab[] = {
1020 "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable",
1021 "Source Quench", "Redirect", "ICMP 6", "ICMP 7",
1022 "Echo", "ICMP 9", "ICMP 10", "Time Exceeded",
1023 "Param Problem", "Timestamp", "Timestamp Reply", "Info Request",
1028 return("OUT-OF-RANGE");
1034 packet_ok(register u_char *buf, int cc, register struct sockaddr_in *from,
1037 register struct icmp *icp;
1038 register u_char type, code;
1041 register struct ip *ip;
1043 ip = (struct ip *) buf;
1044 hlen = ip->ip_hl << 2;
1045 if (cc < hlen + ICMP_MINLEN) {
1047 Printf("packet too short (%d bytes) from %s\n", cc,
1048 inet_ntoa(from->sin_addr));
1052 icp = (struct icmp *)(buf + hlen);
1054 icp = (struct icmp *)buf;
1056 type = icp->icmp_type;
1057 code = icp->icmp_code;
1058 if (type == ICMP_ECHOREPLY
1059 && proto->num == IPPROTO_ICMP
1060 && (*proto->check)((u_char *)icp,seq))
1062 if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
1063 type == ICMP_UNREACH) {
1067 hip = &icp->icmp_ip;
1068 hlen = hip->ip_hl << 2;
1069 inner = (u_char *)((u_char *)hip + hlen);
1071 && hip->ip_p == proto->num
1072 && (*proto->check)(inner, seq))
1073 return (type == ICMP_TIMXCEED ? -1 : code + 1);
1078 u_int32_t *lp = (u_int32_t *)&icp->icmp_ip;
1080 Printf("\n%d bytes from %s to ", cc, inet_ntoa(from->sin_addr));
1081 Printf("%s: icmp type %d (%s) code %d\n",
1082 inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code);
1083 for (i = 4; i < cc ; i += sizeof(*lp))
1084 Printf("%2d: x%8.8x\n", i, *lp++);
1091 icmp_prep(struct outdata *outdata)
1093 struct icmp *const icmpheader = (struct icmp *) outprot;
1095 icmpheader->icmp_type = ICMP_ECHO;
1096 icmpheader->icmp_id = htons(ident);
1097 icmpheader->icmp_seq = htons(outdata->seq);
1099 icmpheader->icmp_cksum = 0;
1100 icmpheader->icmp_cksum = in_cksum((u_short *)icmpheader,
1101 packlen - (sizeof(*outip) + outdata->optlen));
1102 if (icmpheader->icmp_cksum == 0)
1103 icmpheader->icmp_cksum = 0xffff;
1108 icmp_check(const u_char *data, int seq)
1110 struct icmp *const icmpheader = (struct icmp *) data;
1112 return (icmpheader->icmp_id == htons(ident)
1113 && icmpheader->icmp_seq == htons(seq));
1117 udp_prep(struct outdata *outdata)
1119 struct udphdr *const udp = (struct udphdr *) outprot;
1121 udp->uh_sport = htons(ident);
1122 udp->uh_dport = htons(port + outdata->seq);
1123 udp->uh_ulen = htons((u_short)protlen);
1127 udp_check(const u_char *data, int seq)
1129 struct udphdr *const udp = (struct udphdr *) data;
1131 return (ntohs(udp->uh_sport) == ident
1132 && ntohs(udp->uh_dport) == port + seq);
1136 tcp_prep(struct outdata *outdata)
1138 struct tcphdr *const tcp = (struct tcphdr *) outprot;
1140 tcp->th_sport = htons(ident);
1141 tcp->th_dport = htons(port + outdata->seq);
1142 tcp->th_seq = (tcp->th_sport << 16) | tcp->th_dport;
1145 tcp->th_flags = TH_SYN;
1149 tcp_check(const u_char *data, int seq)
1151 struct tcphdr *const tcp = (struct tcphdr *) data;
1153 return (ntohs(tcp->th_sport) == ident
1154 && ntohs(tcp->th_dport) == port + seq);
1158 gre_prep(struct outdata *outdata)
1160 struct grehdr *const gre = (struct grehdr *) outprot;
1162 gre->flags = htons(0x2001);
1163 gre->proto = htons(port);
1165 gre->callId = htons(ident + outdata->seq);
1169 gre_check(const u_char *data, int seq)
1171 struct grehdr *const gre = (struct grehdr *) data;
1173 return(ntohs(gre->proto) == port
1174 && ntohs(gre->callId) == ident + seq);
1178 gen_prep(struct outdata *outdata)
1180 u_int16_t *const ptr = (u_int16_t *) outprot;
1182 ptr[0] = htons(ident);
1183 ptr[1] = htons(port + outdata->seq);
1187 gen_check(const u_char *data, int seq)
1189 u_int16_t *const ptr = (u_int16_t *) data;
1191 return(ntohs(ptr[0]) == ident
1192 && ntohs(ptr[1]) == port + seq);
1196 print(register u_char *buf, register int cc, register struct sockaddr_in *from)
1198 register struct ip *ip;
1201 ip = (struct ip *) buf;
1202 hlen = ip->ip_hl << 2;
1206 Printf(" %s", inet_ntoa(from->sin_addr));
1208 Printf(" %s (%s)", inetname(from->sin_addr),
1209 inet_ntoa(from->sin_addr));
1212 Printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
1216 * Checksum routine for Internet Protocol family headers (C Version)
1219 in_cksum(register u_short *addr, register int len)
1221 register int nleft = len;
1222 register u_short *w = addr;
1223 register u_short answer;
1224 register int sum = 0;
1227 * Our algorithm is simple, using a 32 bit accumulator (sum),
1228 * we add sequential 16 bit words to it, and at the end, fold
1229 * back all the carry bits from the top 16 bits into the lower
1237 /* mop up an odd byte, if necessary */
1239 sum += *(u_char *)w;
1242 * add back carry outs from top 16 bits to low 16 bits
1244 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
1245 sum += (sum >> 16); /* add carry */
1246 answer = ~sum; /* truncate to 16 bits */
1251 * Subtract 2 timeval structs: out = out - in.
1252 * Out is assumed to be within about LONG_MAX seconds of in.
1255 tvsub(register struct timeval *out, register struct timeval *in)
1258 if ((out->tv_usec -= in->tv_usec) < 0) {
1260 out->tv_usec += 1000000;
1262 out->tv_sec -= in->tv_sec;
1266 * Construct an Internet address representation.
1267 * If the nflag has been supplied, give
1268 * numeric value, otherwise try for symbolic name.
1271 inetname(struct in_addr in)
1274 register struct hostent *hp;
1275 static int first = 1;
1276 static char domain[MAXHOSTNAMELEN + 1], line[MAXHOSTNAMELEN + 1];
1278 if (first && !nflag) {
1280 if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
1281 (cp = strchr(domain, '.')) != NULL) {
1282 (void)strncpy(domain, cp + 1, sizeof(domain) - 1);
1283 domain[sizeof(domain) - 1] = '\0';
1287 if (!nflag && in.s_addr != INADDR_ANY) {
1288 hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET);
1290 if ((cp = strchr(hp->h_name, '.')) != NULL &&
1291 strcmp(cp + 1, domain) == 0)
1293 (void)strncpy(line, hp->h_name, sizeof(line) - 1);
1294 line[sizeof(line) - 1] = '\0';
1298 return (inet_ntoa(in));
1302 getaddr(register u_int32_t *ap, register char *hostname)
1304 register struct hostent *hp;
1306 *ap = inet_addr(hostname);
1307 if ((int32_t)*ap != -1)
1310 hp = gethostbyname(hostname);
1312 Fprintf(stderr, "%s: unknown host %s\n", prog, hostname);
1315 if (hp->h_addrtype != AF_INET || hp->h_length != 4) {
1316 Fprintf(stderr, "%s: bad host %s\n", prog, hostname);
1319 memcpy((caddr_t)ap, hp->h_addr, hp->h_length);
1320 return (hp->h_name);
1324 getsin(register struct sockaddr_in *sin, register char *hostname)
1327 memset(sin, 0, sizeof(*sin));
1328 sin->sin_family = AF_INET;
1329 return (getaddr((u_int32_t *)&sin->sin_addr.s_addr, hostname));
1333 savestr(register const char *str)
1339 Fprintf(stderr, "%s: strdup: %s\n", prog, strerror(errno));
1348 extern char version[];
1350 Fprintf(stderr, "Version %s\n", version);
1351 Fprintf(stderr, "Usage: %s [-Sdnrv] [-w wait] [-m max_ttl] [-M min_ttl] \
1352 [-P proto]\n\t [-p port#] [-q nqueries] [-t tos] [-s src_addr] [-g gateway] \
1353 \n\t host [data_size]\n", prog);