1 /* $OpenBSD: traceroute.c,v 1.61 2004/01/26 18:23:51 deraadt Exp $ */
2 /* $NetBSD: traceroute.c,v 1.10 1995/05/21 15:50:45 mycroft Exp $ */
5 * Copyright (c) 1990, 1993
6 * The Regents of the University of California. All rights reserved.
8 * This code is derived from software contributed to Berkeley by
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * @(#)traceroute.c 8.1 (Berkeley) 6/6/93
39 * traceroute host - trace the route ip packets follow going to "host".
41 * Attempt to trace the route an ip packet would follow to some
42 * internet host. We find out intermediate hops by launching probe
43 * packets with a small ttl (time to live) then listening for an
44 * icmp "time exceeded" reply from a gateway. We start our probes
45 * with a ttl of one and increase by one until we get an icmp "port
46 * unreachable" (which means we got to "host") or hit a max (which
47 * defaults to 64 hops & can be changed with the -m flag). Three
48 * probes (change with -q flag) are sent at each ttl setting and a
49 * line is printed showing the ttl, address of the gateway and
50 * round trip time of each probe. If the probe answers come from
51 * different gateways, the address of each responding system will
52 * be printed. If there is no response within a 5 sec. timeout
53 * interval (changed with the -w flag), a "*" is printed for that
56 * Probe packets are UDP format. We don't want the destination
57 * host to process them so the destination port is set to an
58 * unlikely value (if some clod on the destination is using that
59 * value, it can be changed with the -p flag).
61 * A sample use might be:
63 * [yak 71]% traceroute nis.nsf.net.
64 * traceroute to nis.nsf.net (35.1.1.48), 64 hops max, 56 byte packet
65 * 1 helios.ee.lbl.gov (128.3.112.1) 19 ms 19 ms 0 ms
66 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
67 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
68 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 39 ms
69 * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 39 ms 39 ms 39 ms
70 * 6 128.32.197.4 (128.32.197.4) 40 ms 59 ms 59 ms
71 * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 59 ms
72 * 8 129.140.70.13 (129.140.70.13) 99 ms 99 ms 80 ms
73 * 9 129.140.71.6 (129.140.71.6) 139 ms 239 ms 319 ms
74 * 10 129.140.81.7 (129.140.81.7) 220 ms 199 ms 199 ms
75 * 11 nic.merit.edu (35.1.1.48) 239 ms 239 ms 239 ms
77 * Note that lines 2 & 3 are the same. This is due to a buggy
78 * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
79 * packets with a zero ttl.
81 * A more interesting example is:
83 * [yak 72]% traceroute allspice.lcs.mit.edu.
84 * traceroute to allspice.lcs.mit.edu (18.26.0.115), 64 hops max
85 * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
86 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 19 ms 19 ms
87 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 19 ms
88 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 19 ms 39 ms 39 ms
89 * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 20 ms 39 ms 39 ms
90 * 6 128.32.197.4 (128.32.197.4) 59 ms 119 ms 39 ms
91 * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 39 ms
92 * 8 129.140.70.13 (129.140.70.13) 80 ms 79 ms 99 ms
93 * 9 129.140.71.6 (129.140.71.6) 139 ms 139 ms 159 ms
94 * 10 129.140.81.7 (129.140.81.7) 199 ms 180 ms 300 ms
95 * 11 129.140.72.17 (129.140.72.17) 300 ms 239 ms 239 ms
97 * 13 128.121.54.72 (128.121.54.72) 259 ms 499 ms 279 ms
102 * 18 ALLSPICE.LCS.MIT.EDU (18.26.0.115) 339 ms 279 ms 279 ms
104 * (I start to see why I'm having so much trouble with mail to
105 * MIT.) Note that the gateways 12, 14, 15, 16 & 17 hops away
106 * either don't send ICMP "time exceeded" messages or send them
107 * with a ttl too small to reach us. 14 - 17 are running the
108 * MIT C Gateway code that doesn't send "time exceeded"s. God
109 * only knows what's going on with 12.
111 * The silent gateway 12 in the above may be the result of a bug in
112 * the 4.[23]BSD network code (and its derivatives): 4.x (x <= 3)
113 * sends an unreachable message using whatever ttl remains in the
114 * original datagram. Since, for gateways, the remaining ttl is
115 * zero, the icmp "time exceeded" is guaranteed to not make it back
116 * to us. The behavior of this bug is slightly more interesting
117 * when it appears on the destination system:
119 * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
120 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 39 ms
121 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 39 ms 19 ms
122 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 19 ms
123 * 5 ccn-nerif35.Berkeley.EDU (128.32.168.35) 39 ms 39 ms 39 ms
124 * 6 csgw.Berkeley.EDU (128.32.133.254) 39 ms 59 ms 39 ms
131 * 13 rip.Berkeley.EDU (128.32.131.22) 59 ms ! 39 ms ! 39 ms !
133 * Notice that there are 12 "gateways" (13 is the final
134 * destination) and exactly the last half of them are "missing".
135 * What's really happening is that rip (a Sun-3 running Sun OS3.5)
136 * is using the ttl from our arriving datagram as the ttl in its
137 * icmp reply. So, the reply will time out on the return path
138 * (with no notice sent to anyone since icmp's aren't sent for
139 * icmp's) until we probe with a ttl that's at least twice the path
140 * length. I.e., rip is really only 7 hops away. A reply that
141 * returns with a ttl of 1 is a clue this problem exists.
142 * Traceroute prints a "!" after the time if the ttl is <= 1.
143 * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
144 * non-standard (HPUX) software, expect to see this problem
145 * frequently and/or take care picking the target host of your
148 * Other possible annotations after the time are !H, !N, !P (got a host,
149 * network or protocol unreachable, respectively), !S or !F (source
150 * route failed or fragmentation needed -- neither of these should
151 * ever occur and the associated gateway is busted if you see one). If
152 * almost all the probes result in some kind of unreachable, traceroute
153 * will give up and exit.
157 * This program must be run by root or be setuid. (I suggest that
158 * you *don't* make it setuid -- casual use could result in a lot
159 * of unnecessary traffic on our poor, congested nets.)
161 * This program requires a kernel mod that does not appear in any
162 * system available from Berkeley: A raw ip socket using proto
163 * IPPROTO_RAW must interpret the data sent as an ip datagram (as
164 * opposed to data to be wrapped in a ip datagram). See the README
165 * file that came with the source to this program for a description
166 * of the mods I made to /sys/netinet/raw_ip.c. Your mileage may
167 * vary. But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
168 * MODIFIED TO RUN THIS PROGRAM.
170 * The udp port usage may appear bizarre (well, ok, it is bizarre).
171 * The problem is that an icmp message only contains 8 bytes of
172 * data from the original datagram. 8 bytes is the size of a udp
173 * header so, if we want to associate replies with the original
174 * datagram, the necessary information must be encoded into the
175 * udp header (the ip id could be used but there's no way to
176 * interlock with the kernel's assignment of ip id's and, anyway,
177 * it would have taken a lot more kernel hacking to allow this
178 * code to set the ip id). So, to allow two or more users to
179 * use traceroute simultaneously, we use this task's pid as the
180 * source port (the high bit is set to move the port number out
181 * of the "likely" range). To keep track of which probe is being
182 * replied to (so times and/or hop counts don't get confused by a
183 * reply that was delayed in transit), we increment the destination
184 * port number before each probe.
186 * Don't use this as a coding example. I was trying to find a
187 * routing problem and this code sort-of popped out after 48 hours
188 * without sleep. I was amazed it ever compiled, much less ran.
190 * I stole the idea for this program from Steve Deering. Since
191 * the first release, I've learned that had I attended the right
192 * IETF working group meetings, I also could have stolen it from Guy
193 * Almes or Matt Mathis. I don't know (or care) who came up with
194 * the idea first. I envy the originators' perspicacity and I'm
195 * glad they didn't keep the idea a secret.
197 * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
198 * enhancements to the original distribution.
200 * I've hacked up a round-trip-route version of this that works by
201 * sending a loose-source-routed udp datagram through the destination
202 * back to yourself. Unfortunately, SO many gateways botch source
203 * routing, the thing is almost worthless. Maybe one day...
205 * -- Van Jacobson (van@helios.ee.lbl.gov)
206 * Tue Dec 20 03:50:13 PST 1988
209 #include <sys/param.h>
210 #include <sys/time.h>
211 #include <sys/socket.h>
212 #include <sys/file.h>
213 #include <sys/ioctl.h>
214 #include <sys/sysctl.h>
216 #include <netinet/in_systm.h>
217 #include <netinet/in.h>
218 #include <netinet/ip.h>
219 #include <netinet/ip_icmp.h>
220 #include <netinet/ip_var.h>
221 #include <netinet/udp.h>
223 #include <arpa/inet.h>
234 #define MAX_LSRR ((MAX_IPOPTLEN - 4) / 4)
237 * Format of the data in a (udp) probe packet.
240 u_char seq
; /* sequence number of this packet */
241 u_int8_t ttl
; /* ttl packet left with */
242 u_int32_t sec
; /* time packet left */
247 * Support for ICMP extensions - RFC4950.
249 #define ICMP_EXT_OFFSET 8 + 128 /* ICMP type, code, checksum (unused)
250 * + original datagram */
251 #define ICMP_EXT_VERSION 2
253 /* ICMP Extension Header according to RFC4884. */
254 #define EXT_VERSION(x) (((x) & 0xf0000000) >> 28)
255 #define EXT_CHECKSUM(x) ((x) & 0x0000ffff)
258 * ICMP extensions, object header
260 struct icmp_ext_obj_hdr
{
263 #define MPLS_STACK_ENTRY_CLASS 1
265 #define MPLS_STACK_ENTRY_C_TYPE 1
268 /* MPLS Label Stack Object. */
269 #define MPLS_LABEL(x) (((x) & 0xfffff000) >> 12)
270 #define MPLS_EXP(x) (((x) & 0x00000e00) >> 9)
271 #define MPLS_STACK(x) (((x) & 0x00000100) >> 8)
272 #define MPLS_TTL(x) ((x) & 0x000000ff)
274 struct in_addr gateway
[MAX_LSRR
+ 1];
277 int32_t usec_perturb
;
279 u_char packet
[512], *outpacket
; /* last inbound (icmp) packet */
281 void decode_extensions(unsigned char *, int);
282 void dump_packet(void);
283 int wait_for_reply(int, struct sockaddr_in
*, struct timeval
*);
284 void send_probe(int, u_int8_t
, int, struct sockaddr_in
*);
285 int packet_ok(u_char
*, int, struct sockaddr_in
*, int, int);
286 const char *pr_type(u_int8_t
);
287 void print(u_char
*, int, struct sockaddr_in
*);
288 char *inetname(struct in_addr
);
289 u_short
in_cksum(u_short
*, int);
292 int s
; /* receive (icmp) socket file descriptor */
293 int sndsock
; /* send (udp) socket file descriptor */
295 int datalen
; /* How much data */
296 int headerlen
; /* How long packet's header is */
302 u_int8_t max_ttl
= IPDEFTTL
;
303 u_int8_t first_ttl
= 1;
305 u_short port
= 32768+666; /* start udp dest port # for probe packets */
306 u_char proto
= IPPROTO_UDP
;
307 u_int8_t icmp_type
= ICMP_ECHO
; /* default ICMP code/type */
308 u_char icmp_code
= 0;
309 int options
; /* socket options */
311 int waittime
= 5; /* time to wait for response (in seconds) */
312 int nflag
; /* print addresses numerically */
314 int Mflag
; /* show MPLS labels if any */
317 main(int argc
, char *argv
[])
319 int mib
[4] = { CTL_NET
, PF_INET
, IPPROTO_IP
, IPCTL_DEFTTL
};
320 int ttl_flag
= 0, incflag
= 1, protoset
= 0, sump
= 0;
321 int ch
, i
, lsrr
= 0, on
= 1, probe
, seq
= 0, tos
= 0;
322 size_t size
= sizeof(max_ttl
);
323 struct sockaddr_in from
, to
;
331 if ((s
= socket(AF_INET
, SOCK_RAW
, IPPROTO_ICMP
)) < 0)
332 err(5, "icmp socket");
333 if ((sndsock
= socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
)) < 0)
334 err(5, "raw socket");
340 sysctl(mib
, sizeof(mib
)/sizeof(mib
[0]), &max_ttl
, &size
, NULL
, 0);
342 while ((ch
= getopt(argc
, argv
, "SDIdg:f:m:np:q:rs:t:w:vlP:cM")) != -1)
350 l
= strtol(optarg
, &ep
, 10);
351 if (errno
|| !*optarg
|| *ep
|| l
< 1 || l
> max_ttl
)
352 errx(1, "min ttl must be 1 to %u.", max_ttl
);
353 first_ttl
= (u_int8_t
)l
;
365 if (lsrr
>= MAX_LSRR
)
366 errx(1, "too many gateways; max %d", MAX_LSRR
);
367 if (inet_aton(optarg
, &gateway
[lsrr
]) == 0) {
368 hp
= gethostbyname(optarg
);
370 errx(1, "unknown host %s", optarg
);
371 memcpy(&gateway
[lsrr
], hp
->h_addr
, hp
->h_length
);
379 errx(1, "protocol already set with -P");
381 proto
= IPPROTO_ICMP
;
389 l
= strtol(optarg
, &ep
, 10);
390 if (errno
|| !*optarg
|| *ep
|| l
< first_ttl
||
392 errx(1, "max ttl must be %u to %u.", first_ttl
,
394 max_ttl
= (u_int8_t
)l
;
405 l
= strtol(optarg
, &ep
, 10);
406 if (errno
|| !*optarg
|| *ep
|| l
<= 0 || l
>= 65536)
407 errx(1, "port must be >0, <65536.");
412 errx(1, "protocol already set with -I");
416 l
= strtol(optarg
, &ep
, 10);
417 if (errno
|| !*optarg
|| *ep
|| l
< 1 ||
419 struct protoent
*pent
;
421 pent
= getprotobyname(optarg
);
423 proto
= pent
->p_proto
;
425 errx(1, "proto must be >=1, or a name.");
432 l
= strtol(optarg
, &ep
, 10);
433 if (errno
|| !*optarg
|| *ep
|| l
< 1 || l
> INT_MAX
)
434 errx(1, "nprobes must be >0.");
438 options
|= SO_DONTROUTE
;
442 * set the ip source address of the outbound
443 * probe (e.g., on a multi-homed host).
450 l
= strtol(optarg
, &ep
, 10);
451 if (errno
|| !*optarg
|| *ep
|| l
< 0 || l
> 255)
452 errx(1, "tos must be 0 to 255.");
461 l
= strtol(optarg
, &ep
, 10);
462 if (errno
|| !*optarg
|| *ep
|| l
<= 1 || l
> INT_MAX
)
463 errx(1, "wait must be >1 sec.");
477 memset(&to
, 0, sizeof(struct sockaddr
));
478 to
.sin_family
= AF_INET
;
479 if (inet_aton(*argv
, &to
.sin_addr
) != 0)
482 hp
= gethostbyname(*argv
);
484 errx(1, "unknown host %s", *argv
);
485 to
.sin_family
= hp
->h_addrtype
;
486 memcpy(&to
.sin_addr
, hp
->h_addr
, hp
->h_length
);
487 if ((hostname
= strdup(hp
->h_name
)) == NULL
)
489 if (hp
->h_addr_list
[1] != NULL
)
490 warnx("Warning: %s has multiple addresses; using %s",
491 hostname
, inet_ntoa(to
.sin_addr
));
496 l
= strtol(*argv
, &ep
, 10);
497 if (errno
|| !*argv
|| *ep
|| l
< 0 || l
> INT_MAX
)
498 errx(1, "datalen out of range");
504 headerlen
= (sizeof(struct ip
) + lsrrlen
+
505 sizeof(struct udphdr
) + sizeof(struct packetdata
));
508 headerlen
= (sizeof(struct ip
) + lsrrlen
+
509 sizeof(struct icmp
) + sizeof(struct packetdata
));
512 headerlen
= (sizeof(struct ip
) + lsrrlen
+
513 sizeof(struct packetdata
));
516 if (datalen
< 0 || datalen
> IP_MAXPACKET
- headerlen
)
517 errx(1, "packet size must be 0 to %d.",
518 IP_MAXPACKET
- headerlen
);
520 datalen
+= headerlen
;
522 outpacket
= (u_char
*)malloc(datalen
);
523 if (outpacket
== NULL
)
525 memset(outpacket
, 0, datalen
);
527 ip
= (struct ip
*)outpacket
;
529 u_char
*p
= (u_char
*)(ip
+ 1);
535 gateway
[lsrr
] = to
.sin_addr
;
536 for (i
= 1; i
<= lsrr
; i
++) {
537 memcpy(p
, &gateway
[i
], sizeof(struct in_addr
));
538 p
+= sizeof(struct in_addr
);
540 ip
->ip_dst
= gateway
[0];
542 ip
->ip_dst
= to
.sin_addr
;
543 ip
->ip_off
= htons(0);
544 ip
->ip_hl
= (sizeof(struct ip
) + lsrrlen
) >> 2;
546 ip
->ip_v
= IPVERSION
;
549 ident
= (getpid() & 0xffff) | 0x8000;
550 tmprnd
= arc4random();
551 sec_perturb
= (tmprnd
& 0x80000000) ? -(tmprnd
& 0x7ff) :
553 usec_perturb
= arc4random();
555 if (options
& SO_DEBUG
)
556 setsockopt(s
, SOL_SOCKET
, SO_DEBUG
, (char *)&on
, sizeof(on
));
558 if (setsockopt(sndsock
, SOL_SOCKET
, SO_SNDBUF
, (char *)&datalen
,
559 sizeof(datalen
)) < 0)
561 #endif /* SO_SNDBUF */
563 if (setsockopt(sndsock
, IPPROTO_IP
, IP_HDRINCL
, (char *)&on
,
565 err(6, "IP_HDRINCL");
566 #endif /* IP_HDRINCL */
567 if (options
& SO_DEBUG
)
568 setsockopt(sndsock
, SOL_SOCKET
, SO_DEBUG
,
569 (char *)&on
, sizeof(on
));
570 if (options
& SO_DONTROUTE
)
571 setsockopt(sndsock
, SOL_SOCKET
, SO_DONTROUTE
,
572 (char *)&on
, sizeof(on
));
575 memset(&from
, 0, sizeof(struct sockaddr
));
576 from
.sin_family
= AF_INET
;
577 if (inet_aton(source
, &from
.sin_addr
) == 0)
578 errx(1, "unknown host %s", source
);
579 ip
->ip_src
= from
.sin_addr
;
581 (ntohl(from
.sin_addr
.s_addr
) & 0xff000000U
) == 0x7f000000U
&&
582 (ntohl(to
.sin_addr
.s_addr
) & 0xff000000U
) != 0x7f000000U
)
583 errx(1, "source is on 127/8, destination is not");
586 bind(sndsock
, (struct sockaddr
*)&from
, sizeof(from
)) < 0)
590 fprintf(stderr
, "traceroute to %s (%s)", hostname
,
591 inet_ntoa(to
.sin_addr
));
593 fprintf(stderr
, " from %s", source
);
594 fprintf(stderr
, ", %u hops max, %d byte packets\n", max_ttl
, datalen
);
598 printf("Skipping %u intermediate hops\n", first_ttl
- 1);
600 for (ttl
= first_ttl
; ttl
<= max_ttl
; ++ttl
) {
601 int got_there
= 0, unreachable
= 0, timeout
= 0, loss
;
603 in_addr_t lastaddr
= 0;
607 for (probe
= 0, loss
= 0; probe
< nprobes
; ++probe
) {
609 struct timeval t1
, t2
;
612 gettimeofday(&t1
, NULL
);
613 send_probe(++seq
, ttl
, incflag
, &to
);
614 while ((cc
= wait_for_reply(s
, &from
, &t1
))) {
615 gettimeofday(&t2
, NULL
);
616 if (t2
.tv_sec
- t1
.tv_sec
> waittime
) {
620 i
= packet_ok(packet
, cc
, &from
, seq
, incflag
);
621 /* Skip short packet */
625 from
.sin_addr
.s_addr
!= lastaddr
) {
628 print(packet
, cc
, &from
);
629 lastaddr
= from
.sin_addr
.s_addr
;
632 dt
= (quad_t
)(t2
.tv_sec
- t1
.tv_sec
) * 1000000 +
633 (quad_t
)(t2
.tv_usec
- t1
.tv_usec
);
634 printf(" %u", (u_int
)(dt
/ 1000));
636 printf(".%u", (u_int
)(dt
% 1000));
638 ip
= (struct ip
*)packet
;
640 printf(" (%u)", ip
->ip_ttl
);
643 ip
= (struct ip
*)packet
;
650 /* time exceeded in transit */
655 case ICMP_UNREACH_PORT
:
657 ip
= (struct ip
*)packet
;
663 case ICMP_UNREACH_NET
:
667 case ICMP_UNREACH_HOST
:
671 case ICMP_UNREACH_PROTOCOL
:
675 case ICMP_UNREACH_NEEDFRAG
:
679 case ICMP_UNREACH_SRCFAIL
:
683 case ICMP_UNREACH_FILTER_PROHIB
:
687 case ICMP_UNREACH_NET_PROHIB
: /*misuse*/
691 case ICMP_UNREACH_HOST_PROHIB
:
695 case ICMP_UNREACH_NET_UNKNOWN
:
696 case ICMP_UNREACH_HOST_UNKNOWN
:
700 case ICMP_UNREACH_ISOLATED
:
704 case ICMP_UNREACH_TOSNET
:
705 case ICMP_UNREACH_TOSHOST
:
711 printf(" !<%d>", i
- 1);
721 else if (cc
&& probe
== nprobes
- 1 && Mflag
)
722 decode_extensions(packet
, cc
);
726 printf(" (%d%% loss)", (loss
* 100) / nprobes
);
728 if (got_there
|| (unreachable
&& (unreachable
+ timeout
) >= nprobes
))
735 wait_for_reply(int sock
, struct sockaddr_in
*from
, struct timeval
*sent
)
737 socklen_t fromlen
= sizeof (*from
);
738 struct timeval now
, wait
;
742 fdsn
= howmany(sock
+1, NFDBITS
) * sizeof(fd_mask
);
743 if ((fdsp
= (fd_set
*)malloc(fdsn
)) == NULL
)
745 memset(fdsp
, 0, fdsn
);
747 gettimeofday(&now
, NULL
);
748 wait
.tv_sec
= (sent
->tv_sec
+ waittime
) - now
.tv_sec
;
749 wait
.tv_usec
= sent
->tv_usec
- now
.tv_usec
;
750 if (wait
.tv_usec
< 0) {
751 wait
.tv_usec
+= 1000000;
755 wait
.tv_sec
= wait
.tv_usec
= 0;
757 if (select(sock
+1, fdsp
, NULL
, NULL
, &wait
) > 0)
758 cc
= recvfrom(s
, (char *)packet
, sizeof(packet
), 0,
759 (struct sockaddr
*)from
, &fromlen
);
766 decode_extensions(unsigned char *buf
, int ip_len
)
769 struct icmp_ext_obj_hdr
*obj_hdr
;
771 int data_len
, obj_len
;
774 ip
= (struct ip
*)buf
;
776 if (ip_len
<= (int)(sizeof(struct ip
) + ICMP_EXT_OFFSET
)) {
778 * No support for ICMP extensions on this host
784 * Move forward to the start of the ICMP extensions, if present
786 buf
+= (ip
->ip_hl
<< 2) + ICMP_EXT_OFFSET
;
787 cmn_hdr
= (uint32_t *)buf
;
789 if (EXT_VERSION(ntohl(*cmn_hdr
)) != ICMP_EXT_VERSION
) {
796 data_len
= ip_len
- ((u_char
*)cmn_hdr
- (u_char
*)ip
);
799 * Check the checksum, cmn_hdr->checksum == 0 means no checksum'ing
802 * If the checksum is ok, we'll get 0, as the checksum is calculated
803 * with the checksum field being 0'd.
805 if (EXT_CHECKSUM(ntohl(*cmn_hdr
)) &&
806 in_cksum((u_short
*)cmn_hdr
, data_len
)) {
810 buf
+= sizeof(*cmn_hdr
);
811 data_len
-= sizeof(*cmn_hdr
);
813 while (data_len
>= (int)sizeof(struct icmp_ext_obj_hdr
)) {
814 unsigned char *nextbuf
;
816 obj_hdr
= (struct icmp_ext_obj_hdr
*)buf
;
817 obj_len
= ntohs(obj_hdr
->length
);
820 * Sanity check the length field
822 if (obj_len
< (int)sizeof(*obj_hdr
) || obj_len
> data_len
)
825 /* Object has to be 4-byte aligned. */
829 nextbuf
= buf
+ obj_len
;
833 * Move past the object header
835 buf
+= sizeof(struct icmp_ext_obj_hdr
);
836 obj_len
-= sizeof(struct icmp_ext_obj_hdr
);
838 switch (obj_hdr
->class_num
) {
839 case MPLS_STACK_ENTRY_CLASS
:
840 switch (obj_hdr
->c_type
) {
841 case MPLS_STACK_ENTRY_C_TYPE
:
842 while (obj_len
>= (int)sizeof(uint32_t)) {
843 mpls_hdr
= ntohl(*(uint32_t *)buf
);
845 buf
+= sizeof(uint32_t);
846 obj_len
-= sizeof(uint32_t);
847 printf(" [MPLS: Label %d Exp %d]",
848 MPLS_LABEL(mpls_hdr
),
853 * Something went wrong, and we're at
854 * a unknown offset into the packet,
855 * ditch the rest of it.
862 * Unknown object, skip past it
871 * Unknown object, skip past it
885 fprintf(stderr
, "packet data:");
886 for (p
= outpacket
, i
= 0; i
< datalen
; i
++) {
888 fprintf(stderr
, "\n ");
889 fprintf(stderr
, " %02x", *p
++);
891 fprintf(stderr
, "\n");
895 send_probe(int seq
, u_int8_t ttl
, int iflag
, struct sockaddr_in
*to
)
897 struct ip
*ip
= (struct ip
*)outpacket
;
898 u_char
*p
= (u_char
*)(ip
+ 1);
899 struct udphdr
*up
= (struct udphdr
*)(p
+ lsrrlen
);
900 struct icmp
*icmpp
= (struct icmp
*)(p
+ lsrrlen
);
901 struct packetdata
*op
;
905 ip
->ip_len
= datalen
;
907 ip
->ip_id
= htons(ident
+seq
);
911 icmpp
->icmp_type
= icmp_type
;
912 icmpp
->icmp_code
= icmp_code
;
913 icmpp
->icmp_seq
= htons(seq
);
914 icmpp
->icmp_id
= htons(ident
);
915 op
= (struct packetdata
*)(icmpp
+ 1);
918 up
->uh_sport
= htons(ident
);
920 up
->uh_dport
= htons(port
+seq
);
922 up
->uh_dport
= htons(port
);
923 up
->uh_ulen
= htons((u_short
)(datalen
- sizeof(struct ip
) -
926 op
= (struct packetdata
*)(up
+ 1);
929 op
= (struct packetdata
*)(ip
+ 1);
936 * We don't want hostiles snooping the net to get any useful
937 * information about us. Send the timestamp in network byte order,
938 * and perturb the timestamp enough that they won't know our
939 * real clock ticker. We don't want to perturb the time by too
940 * much: being off by a suspiciously large amount might indicate
943 * The timestamps in the packet are currently unused. If future
944 * work wants to use them they will have to subtract out the
945 * perturbation first.
947 gettimeofday(&tv
, NULL
);
948 op
->sec
= htonl(tv
.tv_sec
+ sec_perturb
);
949 op
->usec
= htonl((tv
.tv_usec
+ usec_perturb
) % 1000000);
951 if (proto
== IPPROTO_ICMP
&& icmp_type
== ICMP_ECHO
) {
952 icmpp
->icmp_cksum
= 0;
953 icmpp
->icmp_cksum
= in_cksum((u_short
*)icmpp
,
954 datalen
- sizeof(struct ip
) - lsrrlen
);
955 if (icmpp
->icmp_cksum
== 0)
956 icmpp
->icmp_cksum
= 0xffff;
962 i
= sendto(sndsock
, outpacket
, datalen
, 0, (struct sockaddr
*)to
,
963 sizeof(struct sockaddr_in
));
964 if (i
< 0 || i
!= datalen
) {
967 printf("traceroute: wrote %s %d chars, ret=%d\n", hostname
,
973 static const char *ttab
[] = {
996 * Convert an ICMP "type" field to a printable string.
1002 return ("OUT-OF-RANGE");
1007 packet_ok(u_char
*buf
, int cc
, struct sockaddr_in
*from
, int seq
, int iflag
)
1016 ip
= (struct ip
*) buf
;
1017 hlen
= ip
->ip_hl
<< 2;
1018 if (cc
< hlen
+ ICMP_MINLEN
) {
1020 printf("packet too short (%d bytes) from %s\n", cc
,
1021 inet_ntoa(from
->sin_addr
));
1025 icp
= (struct icmp
*)(buf
+ hlen
);
1027 icp
= (struct icmp
*)buf
;
1028 #endif /* ARCHAIC */
1029 type
= icp
->icmp_type
;
1030 code
= icp
->icmp_code
;
1031 if ((type
== ICMP_TIMXCEED
&& code
== ICMP_TIMXCEED_INTRANS
) ||
1032 type
== ICMP_UNREACH
|| type
== ICMP_ECHOREPLY
) {
1037 hip
= &icp
->icmp_ip
;
1038 hlen
= hip
->ip_hl
<< 2;
1042 if (icmp_type
== ICMP_ECHO
&&
1043 type
== ICMP_ECHOREPLY
&&
1044 icp
->icmp_id
== htons(ident
) &&
1045 icp
->icmp_seq
== htons(seq
))
1046 return (-2); /* we got there */
1048 icmpp
= (struct icmp
*)((u_char
*)hip
+ hlen
);
1049 if (hlen
+ 8 <= cc
&& hip
->ip_p
== IPPROTO_ICMP
&&
1050 icmpp
->icmp_id
== htons(ident
) &&
1051 icmpp
->icmp_seq
== htons(seq
))
1052 return (type
== ICMP_TIMXCEED
? -1 : code
+ 1);
1056 up
= (struct udphdr
*)((u_char
*)hip
+ hlen
);
1057 if (hlen
+ 12 <= cc
&& hip
->ip_p
== proto
&&
1058 up
->uh_sport
== htons(ident
) &&
1059 ((iflag
&& up
->uh_dport
== htons(port
+ seq
)) ||
1060 (!iflag
&& up
->uh_dport
== htons(port
))))
1061 return (type
== ICMP_TIMXCEED
? -1 : code
+ 1);
1064 /* this is some odd, user specified proto,
1065 * how do we check it?
1067 if (hip
->ip_p
== proto
)
1068 return (type
== ICMP_TIMXCEED
? -1 : code
+ 1);
1074 in_addr_t
*lp
= (in_addr_t
*)&icp
->icmp_ip
;
1076 printf("\n%d bytes from %s", cc
, inet_ntoa(from
->sin_addr
));
1077 printf(" to %s", inet_ntoa(ip
->ip_dst
));
1078 printf(": icmp type %u (%s) code %d\n", type
, pr_type(type
),
1080 for (i
= 4; i
< cc
; i
+= sizeof(in_addr_t
))
1081 printf("%2d: x%8.8lx\n", i
, (unsigned long)*lp
++);
1083 #endif /* ARCHAIC */
1088 print(u_char
*buf
, int cc
, struct sockaddr_in
*from
)
1093 ip
= (struct ip
*) buf
;
1094 hlen
= ip
->ip_hl
<< 2;
1098 printf(" %s", inet_ntoa(from
->sin_addr
));
1100 printf(" %s (%s)", inetname(from
->sin_addr
),
1101 inet_ntoa(from
->sin_addr
));
1104 printf(" %d bytes to %s", cc
, inet_ntoa (ip
->ip_dst
));
1109 * Checksum routine for Internet Protocol family headers (C Version)
1112 in_cksum(u_short
*addr
, int len
)
1114 u_short
*w
= addr
, answer
;
1115 int nleft
= len
, sum
= 0;
1118 * Our algorithm is simple, using a 32 bit accumulator (sum),
1119 * we add sequential 16 bit words to it, and at the end, fold
1120 * back all the carry bits from the top 16 bits into the lower
1128 /* mop up an odd byte, if necessary */
1130 sum
+= *(u_char
*)w
;
1133 * add back carry outs from top 16 bits to low 16 bits
1135 sum
= (sum
>> 16) + (sum
& 0xffff); /* add hi 16 to low 16 */
1136 sum
+= (sum
>> 16); /* add carry */
1137 answer
= ~sum
; /* truncate to 16 bits */
1142 * Construct an Internet address representation.
1143 * If the nflag has been supplied, give
1144 * numeric value, otherwise try for symbolic name.
1147 inetname(struct in_addr in
)
1149 static char domain
[MAXHOSTNAMELEN
], line
[MAXHOSTNAMELEN
];
1150 static int first
= 1;
1154 if (first
&& !nflag
) {
1156 if (gethostname(domain
, sizeof domain
) == 0 &&
1157 (cp
= strchr(domain
, '.')) != NULL
) {
1158 strlcpy(domain
, cp
+ 1, sizeof(domain
));
1161 if (!nflag
&& in
.s_addr
!= INADDR_ANY
) {
1162 hp
= gethostbyaddr(&in
, sizeof(in
), AF_INET
);
1164 if ((cp
= strchr(hp
->h_name
, '.')) != NULL
&&
1165 strcmp(cp
+ 1, domain
) == 0)
1167 strlcpy(line
, hp
->h_name
, sizeof(line
));
1171 return (inet_ntoa(in
));
1178 "usage: %s [-cdDIlMnrSv] [-f first_ttl] [-g gateway_addr] [-m max_ttl]\n"
1179 "\t[-p port] [-P proto] [-q nqueries] [-s src_addr] [-t tos]\n"
1180 "\t[-w waittime] host [packetsize]\n", getprogname());