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