]>
git.saurik.com Git - apple/network_cmds.git/blob - traceroute.tproj/traceroute.c
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
25 * Copyright (c) 1990, 1993
26 * The Regents of the University of California. All rights reserved.
28 * This code is derived from software contributed to Berkeley by
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
34 * 1. Redistributions of source code must retain the above copyright
35 * notice, this list of conditions and the following disclaimer.
36 * 2. Redistributions in binary form must reproduce the above copyright
37 * notice, this list of conditions and the following disclaimer in the
38 * documentation and/or other materials provided with the distribution.
39 * 3. All advertising materials mentioning features or use of this software
40 * must display the following acknowledgement:
41 * This product includes software developed by the University of
42 * California, Berkeley and its contributors.
43 * 4. Neither the name of the University nor the names of its contributors
44 * may be used to endorse or promote products derived from this software
45 * without specific prior written permission.
47 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 static char copyright
[] =
62 "@(#) Copyright (c) 1990, 1993\n\
63 The Regents of the University of California. All rights reserved.\n";
67 static char sccsid
[] = "@(#)traceroute.c 8.1 (Berkeley) 6/6/93";
71 * traceroute host - trace the route ip packets follow going to "host".
73 * Attempt to trace the route an ip packet would follow to some
74 * internet host. We find out intermediate hops by launching probe
75 * packets with a small ttl (time to live) then listening for an
76 * icmp "time exceeded" reply from a gateway. We start our probes
77 * with a ttl of one and increase by one until we get an icmp "port
78 * unreachable" (which means we got to "host") or hit a max (which
79 * defaults to 30 hops & can be changed with the -m flag). Three
80 * probes (change with -q flag) are sent at each ttl setting and a
81 * line is printed showing the ttl, address of the gateway and
82 * round trip time of each probe. If the probe answers come from
83 * different gateways, the address of each responding system will
84 * be printed. If there is no response within a 5 sec. timeout
85 * interval (changed with the -w flag), a "*" is printed for that
88 * Probe packets are UDP format. We don't want the destination
89 * host to process them so the destination port is set to an
90 * unlikely value (if some clod on the destination is using that
91 * value, it can be changed with the -p flag).
93 * A sample use might be:
95 * [yak 71]% traceroute nis.nsf.net.
96 * traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 56 byte packet
97 * 1 helios.ee.lbl.gov (128.3.112.1) 19 ms 19 ms 0 ms
98 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
99 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
100 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 39 ms
101 * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 39 ms 39 ms 39 ms
102 * 6 128.32.197.4 (128.32.197.4) 40 ms 59 ms 59 ms
103 * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 59 ms
104 * 8 129.140.70.13 (129.140.70.13) 99 ms 99 ms 80 ms
105 * 9 129.140.71.6 (129.140.71.6) 139 ms 239 ms 319 ms
106 * 10 129.140.81.7 (129.140.81.7) 220 ms 199 ms 199 ms
107 * 11 nic.merit.edu (35.1.1.48) 239 ms 239 ms 239 ms
109 * Note that lines 2 & 3 are the same. This is due to a buggy
110 * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
111 * packets with a zero ttl.
113 * A more interesting example is:
115 * [yak 72]% traceroute allspice.lcs.mit.edu.
116 * traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max
117 * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
118 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 19 ms 19 ms
119 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 19 ms
120 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 19 ms 39 ms 39 ms
121 * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 20 ms 39 ms 39 ms
122 * 6 128.32.197.4 (128.32.197.4) 59 ms 119 ms 39 ms
123 * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 39 ms
124 * 8 129.140.70.13 (129.140.70.13) 80 ms 79 ms 99 ms
125 * 9 129.140.71.6 (129.140.71.6) 139 ms 139 ms 159 ms
126 * 10 129.140.81.7 (129.140.81.7) 199 ms 180 ms 300 ms
127 * 11 129.140.72.17 (129.140.72.17) 300 ms 239 ms 239 ms
129 * 13 128.121.54.72 (128.121.54.72) 259 ms 499 ms 279 ms
134 * 18 ALLSPICE.LCS.MIT.EDU (18.26.0.115) 339 ms 279 ms 279 ms
136 * (I start to see why I'm having so much trouble with mail to
137 * MIT.) Note that the gateways 12, 14, 15, 16 & 17 hops away
138 * either don't send ICMP "time exceeded" messages or send them
139 * with a ttl too small to reach us. 14 - 17 are running the
140 * MIT C Gateway code that doesn't send "time exceeded"s. God
141 * only knows what's going on with 12.
143 * The silent gateway 12 in the above may be the result of a bug in
144 * the 4.[23]BSD network code (and its derivatives): 4.x (x <= 3)
145 * sends an unreachable message using whatever ttl remains in the
146 * original datagram. Since, for gateways, the remaining ttl is
147 * zero, the icmp "time exceeded" is guaranteed to not make it back
148 * to us. The behavior of this bug is slightly more interesting
149 * when it appears on the destination system:
151 * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
152 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 39 ms
153 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 39 ms 19 ms
154 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 19 ms
155 * 5 ccn-nerif35.Berkeley.EDU (128.32.168.35) 39 ms 39 ms 39 ms
156 * 6 csgw.Berkeley.EDU (128.32.133.254) 39 ms 59 ms 39 ms
163 * 13 rip.Berkeley.EDU (128.32.131.22) 59 ms ! 39 ms ! 39 ms !
165 * Notice that there are 12 "gateways" (13 is the final
166 * destination) and exactly the last half of them are "missing".
167 * What's really happening is that rip (a Sun-3 running Sun OS3.5)
168 * is using the ttl from our arriving datagram as the ttl in its
169 * icmp reply. So, the reply will time out on the return path
170 * (with no notice sent to anyone since icmp's aren't sent for
171 * icmp's) until we probe with a ttl that's at least twice the path
172 * length. I.e., rip is really only 7 hops away. A reply that
173 * returns with a ttl of 1 is a clue this problem exists.
174 * Traceroute prints a "!" after the time if the ttl is <= 1.
175 * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
176 * non-standard (HPUX) software, expect to see this problem
177 * frequently and/or take care picking the target host of your
180 * Other possible annotations after the time are !H, !N, !P (got a host,
181 * network or protocol unreachable, respectively), !S or !F (source
182 * route failed or fragmentation needed -- neither of these should
183 * ever occur and the associated gateway is busted if you see one). If
184 * almost all the probes result in some kind of unreachable, traceroute
185 * will give up and exit.
189 * This program must be run by root or be setuid. (I suggest that
190 * you *don't* make it setuid -- casual use could result in a lot
191 * of unnecessary traffic on our poor, congested nets.)
193 * This program requires a kernel mod that does not appear in any
194 * system available from Berkeley: A raw ip socket using proto
195 * IPPROTO_RAW must interpret the data sent as an ip datagram (as
196 * opposed to data to be wrapped in a ip datagram). See the README
197 * file that came with the source to this program for a description
198 * of the mods I made to /sys/netinet/raw_ip.c. Your mileage may
199 * vary. But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
200 * MODIFIED TO RUN THIS PROGRAM.
202 * The udp port usage may appear bizarre (well, ok, it is bizarre).
203 * The problem is that an icmp message only contains 8 bytes of
204 * data from the original datagram. 8 bytes is the size of a udp
205 * header so, if we want to associate replies with the original
206 * datagram, the necessary information must be encoded into the
207 * udp header (the ip id could be used but there's no way to
208 * interlock with the kernel's assignment of ip id's and, anyway,
209 * it would have taken a lot more kernel hacking to allow this
210 * code to set the ip id). So, to allow two or more users to
211 * use traceroute simultaneously, we use this task's pid as the
212 * source port (the high bit is set to move the port number out
213 * of the "likely" range). To keep track of which probe is being
214 * replied to (so times and/or hop counts don't get confused by a
215 * reply that was delayed in transit), we increment the destination
216 * port number before each probe.
218 * Don't use this as a coding example. I was trying to find a
219 * routing problem and this code sort-of popped out after 48 hours
220 * without sleep. I was amazed it ever compiled, much less ran.
222 * I stole the idea for this program from Steve Deering. Since
223 * the first release, I've learned that had I attended the right
224 * IETF working group meetings, I also could have stolen it from Guy
225 * Almes or Matt Mathis. I don't know (or care) who came up with
226 * the idea first. I envy the originators' perspicacity and I'm
227 * glad they didn't keep the idea a secret.
229 * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
230 * enhancements to the original distribution.
232 * I've hacked up a round-trip-route version of this that works by
233 * sending a loose-source-routed udp datagram through the destination
234 * back to yourself. Unfortunately, SO many gateways botch source
235 * routing, the thing is almost worthless. Maybe one day...
237 * -- Van Jacobson (van@helios.ee.lbl.gov)
238 * Tue Dec 20 03:50:13 PST 1988
241 #include <sys/param.h>
242 #include <sys/time.h>
243 #include <sys/socket.h>
244 #include <sys/file.h>
245 #include <sys/ioctl.h>
247 #include <netinet/in_systm.h>
248 #include <netinet/in.h>
249 #include <netinet/ip.h>
250 #include <netinet/ip_icmp.h>
251 #include <netinet/udp.h>
253 #include <arpa/inet.h>
262 #define MAXPACKET 65535 /* max ip packet size */
263 #ifndef MAXHOSTNAMELEN
264 #define MAXHOSTNAMELEN 64
268 #define NFDBITS (8*sizeof(fd_set))
269 #define FD_SETSIZE NFDBITS
270 #define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
271 #define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
272 #define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
273 #define FD_ZERO(p) bzero((char *)(p), sizeof(*(p)))
276 #define Fprintf (void)fprintf
277 #define Sprintf (void)sprintf
278 #define Printf (void)printf
281 * format of a (udp) probe packet.
286 u_char seq
; /* sequence number of this packet */
287 u_char ttl
; /* ttl packet left with */
288 struct timeval tv
; /* time packet left */
291 u_char packet
[512]; /* last inbound (icmp) packet */
292 struct opacket
*outpacket
; /* last output (udp) packet */
294 int wait_for_reply
__P((int, struct sockaddr_in
*));
295 void send_probe
__P((int, int));
296 double deltaT
__P((struct timeval
*, struct timeval
*));
297 int packet_ok
__P((u_char
*, int, struct sockaddr_in
*, int));
298 void print
__P((u_char
*, int, struct sockaddr_in
*));
299 void tvsub
__P((struct timeval
*, struct timeval
*));
300 char *inetname
__P((struct in_addr
));
303 int s
; /* receive (icmp) socket file descriptor */
304 int sndsock
; /* send (udp) socket file descriptor */
305 struct timezone tz
; /* leftover */
307 struct sockaddr whereto
; /* Who to try to reach */
308 int datalen
; /* How much data */
316 u_short port
= 32768+666; /* start udp dest port # for probe packets */
317 int options
; /* socket options */
319 int waittime
= 5; /* time to wait for response (in seconds) */
320 int nflag
; /* print addresses numerically */
331 struct sockaddr_in from
, *to
;
332 int ch
, i
, on
, probe
, seq
, tos
, ttl
;
336 to
= (struct sockaddr_in
*)&whereto
;
337 while ((ch
= getopt(argc
, argv
, "dm:np:q:rs:t:w:v")) != EOF
)
343 max_ttl
= atoi(optarg
);
346 "traceroute: max ttl must be >1.\n");
357 "traceroute: port must be >0.\n");
362 nprobes
= atoi(optarg
);
365 "traceroute: nprobes must be >0.\n");
370 options
|= SO_DONTROUTE
;
374 * set the ip source address of the outbound
375 * probe (e.g., on a multi-homed host).
381 if (tos
< 0 || tos
> 255) {
383 "traceroute: tos must be 0 to 255.\n");
391 waittime
= atoi(optarg
);
394 "traceroute: wait must be >1 sec.\n");
409 (void) bzero((char *)&whereto
, sizeof(struct sockaddr
));
410 to
->sin_family
= AF_INET
;
411 to
->sin_addr
.s_addr
= inet_addr(*argv
);
412 if (to
->sin_addr
.s_addr
!= -1)
415 hp
= gethostbyname(*argv
);
417 to
->sin_family
= hp
->h_addrtype
;
418 bcopy(hp
->h_addr
, (caddr_t
)&to
->sin_addr
, hp
->h_length
);
419 hostname
= hp
->h_name
;
421 (void)fprintf(stderr
,
422 "traceroute: unknown host %s\n", *argv
);
427 datalen
= atoi(*argv
);
428 if (datalen
< 0 || datalen
>= MAXPACKET
- sizeof(struct opacket
)) {
430 "traceroute: packet size must be 0 <= s < %ld.\n",
431 MAXPACKET
- sizeof(struct opacket
));
434 datalen
+= sizeof(struct opacket
);
435 outpacket
= (struct opacket
*)malloc((unsigned)datalen
);
437 perror("traceroute: malloc");
440 (void) bzero((char *)outpacket
, datalen
);
441 outpacket
->ip
.ip_dst
= to
->sin_addr
;
442 outpacket
->ip
.ip_tos
= tos
;
443 outpacket
->ip
.ip_v
= IPVERSION
;
444 outpacket
->ip
.ip_id
= 0;
446 ident
= (getpid() & 0xffff) | 0x8000;
448 if ((pe
= getprotobyname("icmp")) == NULL
) {
449 Fprintf(stderr
, "icmp: unknown protocol\n");
452 if ((s
= socket(AF_INET
, SOCK_RAW
, pe
->p_proto
)) < 0) {
453 perror("traceroute: icmp socket");
456 if (options
& SO_DEBUG
)
457 (void) setsockopt(s
, SOL_SOCKET
, SO_DEBUG
,
458 (char *)&on
, sizeof(on
));
459 if (options
& SO_DONTROUTE
)
460 (void) setsockopt(s
, SOL_SOCKET
, SO_DONTROUTE
,
461 (char *)&on
, sizeof(on
));
463 if ((sndsock
= socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
)) < 0) {
464 perror("traceroute: raw socket");
468 if (setsockopt(sndsock
, SOL_SOCKET
, SO_SNDBUF
, (char *)&datalen
,
469 sizeof(datalen
)) < 0) {
470 perror("traceroute: SO_SNDBUF");
475 if (setsockopt(sndsock
, IPPROTO_IP
, IP_HDRINCL
, (char *)&on
,
477 perror("traceroute: IP_HDRINCL");
481 if (options
& SO_DEBUG
)
482 (void) setsockopt(sndsock
, SOL_SOCKET
, SO_DEBUG
,
483 (char *)&on
, sizeof(on
));
484 if (options
& SO_DONTROUTE
)
485 (void) setsockopt(sndsock
, SOL_SOCKET
, SO_DONTROUTE
,
486 (char *)&on
, sizeof(on
));
489 (void) bzero((char *)&from
, sizeof(struct sockaddr
));
490 from
.sin_family
= AF_INET
;
491 from
.sin_addr
.s_addr
= inet_addr(source
);
492 if (from
.sin_addr
.s_addr
== -1) {
493 Printf("traceroute: unknown host %s\n", source
);
496 outpacket
->ip
.ip_src
= from
.sin_addr
;
498 if (bind(sndsock
, (struct sockaddr
*)&from
, sizeof(from
)) < 0) {
499 perror ("traceroute: bind:");
505 Fprintf(stderr
, "traceroute to %s (%s)", hostname
,
506 inet_ntoa(to
->sin_addr
));
508 Fprintf(stderr
, " from %s", source
);
509 Fprintf(stderr
, ", %d hops max, %d byte packets\n", max_ttl
, datalen
);
510 (void) fflush(stderr
);
512 for (ttl
= 1; ttl
<= max_ttl
; ++ttl
) {
518 for (probe
= 0; probe
< nprobes
; ++probe
) {
520 struct timeval t1
, t2
;
524 (void) gettimeofday(&t1
, &tz
);
525 send_probe(++seq
, ttl
);
526 while (cc
= wait_for_reply(s
, &from
)) {
527 (void) gettimeofday(&t2
, &tz
);
528 if ((i
= packet_ok(packet
, cc
, &from
, seq
))) {
529 if (from
.sin_addr
.s_addr
!= lastaddr
) {
530 print(packet
, cc
, &from
);
531 lastaddr
= from
.sin_addr
.s_addr
;
533 Printf(" %g ms", deltaT(&t1
, &t2
));
535 case ICMP_UNREACH_PORT
:
537 ip
= (struct ip
*)packet
;
543 case ICMP_UNREACH_NET
:
547 case ICMP_UNREACH_HOST
:
551 case ICMP_UNREACH_PROTOCOL
:
555 case ICMP_UNREACH_NEEDFRAG
:
559 case ICMP_UNREACH_SRCFAIL
:
569 (void) fflush(stdout
);
572 if (got_there
|| unreachable
>= nprobes
-1)
578 wait_for_reply(sock
, from
)
580 struct sockaddr_in
*from
;
585 int fromlen
= sizeof (*from
);
589 wait
.tv_sec
= waittime
; wait
.tv_usec
= 0;
591 if (select(sock
+1, &fds
, (fd_set
*)0, (fd_set
*)0, &wait
) > 0)
592 cc
=recvfrom(s
, (char *)packet
, sizeof(packet
), 0,
593 (struct sockaddr
*)from
, &fromlen
);
603 struct opacket
*op
= outpacket
;
604 struct ip
*ip
= &op
->ip
;
605 struct udphdr
*up
= &op
->udp
;
609 ip
->ip_hl
= sizeof(*ip
) >> 2;
610 ip
->ip_p
= IPPROTO_UDP
;
611 ip
->ip_len
= datalen
;
613 ip
->ip_v
= IPVERSION
;
614 ip
->ip_id
= htons(ident
+seq
);
616 up
->uh_sport
= htons(ident
);
617 up
->uh_dport
= htons(port
+seq
);
618 up
->uh_ulen
= htons((u_short
)(datalen
- sizeof(struct ip
)));
623 (void) gettimeofday(&op
->tv
, &tz
);
625 i
= sendto(sndsock
, (char *)outpacket
, datalen
, 0, &whereto
,
626 sizeof(struct sockaddr
));
627 if (i
< 0 || i
!= datalen
) {
630 Printf("traceroute: wrote %s %d chars, ret=%d\n", hostname
,
632 (void) fflush(stdout
);
639 struct timeval
*t1p
, *t2p
;
643 dt
= (double)(t2p
->tv_sec
- t1p
->tv_sec
) * 1000.0 +
644 (double)(t2p
->tv_usec
- t1p
->tv_usec
) / 1000.0;
650 * Convert an ICMP "type" field to a printable string.
656 static char *ttab
[] = {
657 "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable",
658 "Source Quench", "Redirect", "ICMP 6", "ICMP 7",
659 "Echo", "ICMP 9", "ICMP 10", "Time Exceeded",
660 "Param Problem", "Timestamp", "Timestamp Reply", "Info Request",
665 return("OUT-OF-RANGE");
672 packet_ok(buf
, cc
, from
, seq
)
675 struct sockaddr_in
*from
;
678 register struct icmp
*icp
;
684 ip
= (struct ip
*) buf
;
685 hlen
= ip
->ip_hl
<< 2;
686 if (cc
< hlen
+ ICMP_MINLEN
) {
688 Printf("packet too short (%d bytes) from %s\n", cc
,
689 inet_ntoa(from
->sin_addr
));
693 icp
= (struct icmp
*)(buf
+ hlen
);
695 icp
= (struct icmp
*)buf
;
697 type
= icp
->icmp_type
; code
= icp
->icmp_code
;
698 if ((type
== ICMP_TIMXCEED
&& code
== ICMP_TIMXCEED_INTRANS
) ||
699 type
== ICMP_UNREACH
) {
704 hlen
= hip
->ip_hl
<< 2;
705 up
= (struct udphdr
*)((u_char
*)hip
+ hlen
);
706 if (hlen
+ 12 <= cc
&& hip
->ip_p
== IPPROTO_UDP
&&
707 up
->uh_sport
== htons(ident
) &&
708 up
->uh_dport
== htons(port
+seq
))
709 return (type
== ICMP_TIMXCEED
? -1 : code
+1);
714 u_long
*lp
= (u_long
*)&icp
->icmp_ip
;
716 Printf("\n%d bytes from %s to %s", cc
,
717 inet_ntoa(from
->sin_addr
), inet_ntoa(ip
->ip_dst
));
718 Printf(": icmp type %d (%s) code %d\n", type
, pr_type(type
),
720 for (i
= 4; i
< cc
; i
+= sizeof(long))
721 Printf("%2d: x%8.8lx\n", i
, *lp
++);
732 struct sockaddr_in
*from
;
737 ip
= (struct ip
*) buf
;
738 hlen
= ip
->ip_hl
<< 2;
742 Printf(" %s", inet_ntoa(from
->sin_addr
));
744 Printf(" %s (%s)", inetname(from
->sin_addr
),
745 inet_ntoa(from
->sin_addr
));
748 Printf (" %d bytes to %s", cc
, inet_ntoa (ip
->ip_dst
));
754 * Checksum routine for Internet Protocol family headers (C Version)
761 register int nleft
= len
;
762 register u_short
*w
= addr
;
763 register u_short answer
;
764 register int sum
= 0;
767 * Our algorithm is simple, using a 32 bit accumulator (sum),
768 * we add sequential 16 bit words to it, and at the end, fold
769 * back all the carry bits from the top 16 bits into the lower
777 /* mop up an odd byte, if necessary */
782 * add back carry outs from top 16 bits to low 16 bits
784 sum
= (sum
>> 16) + (sum
& 0xffff); /* add hi 16 to low 16 */
785 sum
+= (sum
>> 16); /* add carry */
786 answer
= ~sum
; /* truncate to 16 bits */
792 * Subtract 2 timeval structs: out = out - in.
793 * Out is assumed to be >= in.
797 register struct timeval
*out
, *in
;
799 if ((out
->tv_usec
-= in
->tv_usec
) < 0) {
801 out
->tv_usec
+= 1000000;
803 out
->tv_sec
-= in
->tv_sec
;
808 * Construct an Internet address representation.
809 * If the nflag has been supplied, give
810 * numeric value, otherwise try for symbolic name.
817 static char line
[50];
819 static char domain
[MAXHOSTNAMELEN
+ 1];
820 static int first
= 1;
822 if (first
&& !nflag
) {
824 if (gethostname(domain
, MAXHOSTNAMELEN
) == 0 &&
825 (cp
= index(domain
, '.')))
826 (void) strcpy(domain
, cp
+ 1);
831 if (!nflag
&& in
.s_addr
!= INADDR_ANY
) {
832 hp
= gethostbyaddr((char *)&in
, sizeof (in
), AF_INET
);
834 if ((cp
= index(hp
->h_name
, '.')) &&
835 !strcmp(cp
+ 1, domain
))
841 (void) strcpy(line
, cp
);
843 in
.s_addr
= ntohl(in
.s_addr
);
844 #define C(x) ((x) & 0xff)
845 Sprintf(line
, "%lu.%lu.%lu.%lu", C(in
.s_addr
>> 24),
846 C(in
.s_addr
>> 16), C(in
.s_addr
>> 8), C(in
.s_addr
));
854 (void)fprintf(stderr
,
855 "usage: traceroute [-dnrv] [-m max_ttl] [-p port#] [-q nqueries]\n\t\
856 [-s src_addr] [-t tos] [-w wait] host [data size]\n");