xref: /openbsd/usr.sbin/traceroute/traceroute.c (revision d485f761)
1 /*	$OpenBSD: traceroute.c,v 1.40 2001/08/12 12:03:03 heko Exp $	*/
2 /*	$NetBSD: traceroute.c,v 1.10 1995/05/21 15:50:45 mycroft Exp $	*/
3 
4 /*-
5  * Copyright (c) 1990, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * Van Jacobson.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
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. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *	This product includes software developed by the University of
22  *	California, Berkeley and its contributors.
23  * 4. Neither the name of the University nor the names of its contributors
24  *    may be used to endorse or promote products derived from this software
25  *    without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37  * SUCH DAMAGE.
38  */
39 
40 #ifndef lint
41 static char copyright[] =
42 "@(#) Copyright (c) 1990, 1993\n\
43 	The Regents of the University of California.  All rights reserved.\n";
44 #endif /* not lint */
45 
46 #ifndef lint
47 #if 0
48 static char sccsid[] = "@(#)traceroute.c	8.1 (Berkeley) 6/6/93";*/
49 #else
50 static char rcsid[] = "$OpenBSD: traceroute.c,v 1.40 2001/08/12 12:03:03 heko Exp $";
51 #endif
52 #endif /* not lint */
53 
54 /*
55  * traceroute host  - trace the route ip packets follow going to "host".
56  *
57  * Attempt to trace the route an ip packet would follow to some
58  * internet host.  We find out intermediate hops by launching probe
59  * packets with a small ttl (time to live) then listening for an
60  * icmp "time exceeded" reply from a gateway.  We start our probes
61  * with a ttl of one and increase by one until we get an icmp "port
62  * unreachable" (which means we got to "host") or hit a max (which
63  * defaults to 64 hops & can be changed with the -m flag).  Three
64  * probes (change with -q flag) are sent at each ttl setting and a
65  * line is printed showing the ttl, address of the gateway and
66  * round trip time of each probe.  If the probe answers come from
67  * different gateways, the address of each responding system will
68  * be printed.  If there is no response within a 5 sec. timeout
69  * interval (changed with the -w flag), a "*" is printed for that
70  * probe.
71  *
72  * Probe packets are UDP format.  We don't want the destination
73  * host to process them so the destination port is set to an
74  * unlikely value (if some clod on the destination is using that
75  * value, it can be changed with the -p flag).
76  *
77  * A sample use might be:
78  *
79  *     [yak 71]% traceroute nis.nsf.net.
80  *     traceroute to nis.nsf.net (35.1.1.48), 64 hops max, 56 byte packet
81  *      1  helios.ee.lbl.gov (128.3.112.1)  19 ms  19 ms  0 ms
82  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
83  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
84  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  39 ms
85  *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  39 ms  39 ms  39 ms
86  *      6  128.32.197.4 (128.32.197.4)  40 ms  59 ms  59 ms
87  *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  59 ms
88  *      8  129.140.70.13 (129.140.70.13)  99 ms  99 ms  80 ms
89  *      9  129.140.71.6 (129.140.71.6)  139 ms  239 ms  319 ms
90  *     10  129.140.81.7 (129.140.81.7)  220 ms  199 ms  199 ms
91  *     11  nic.merit.edu (35.1.1.48)  239 ms  239 ms  239 ms
92  *
93  * Note that lines 2 & 3 are the same.  This is due to a buggy
94  * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
95  * packets with a zero ttl.
96  *
97  * A more interesting example is:
98  *
99  *     [yak 72]% traceroute allspice.lcs.mit.edu.
100  *     traceroute to allspice.lcs.mit.edu (18.26.0.115), 64 hops max
101  *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
102  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  19 ms  19 ms
103  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  19 ms
104  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  19 ms  39 ms  39 ms
105  *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  20 ms  39 ms  39 ms
106  *      6  128.32.197.4 (128.32.197.4)  59 ms  119 ms  39 ms
107  *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  39 ms
108  *      8  129.140.70.13 (129.140.70.13)  80 ms  79 ms  99 ms
109  *      9  129.140.71.6 (129.140.71.6)  139 ms  139 ms  159 ms
110  *     10  129.140.81.7 (129.140.81.7)  199 ms  180 ms  300 ms
111  *     11  129.140.72.17 (129.140.72.17)  300 ms  239 ms  239 ms
112  *     12  * * *
113  *     13  128.121.54.72 (128.121.54.72)  259 ms  499 ms  279 ms
114  *     14  * * *
115  *     15  * * *
116  *     16  * * *
117  *     17  * * *
118  *     18  ALLSPICE.LCS.MIT.EDU (18.26.0.115)  339 ms  279 ms  279 ms
119  *
120  * (I start to see why I'm having so much trouble with mail to
121  * MIT.)  Note that the gateways 12, 14, 15, 16 & 17 hops away
122  * either don't send ICMP "time exceeded" messages or send them
123  * with a ttl too small to reach us.  14 - 17 are running the
124  * MIT C Gateway code that doesn't send "time exceeded"s.  God
125  * only knows what's going on with 12.
126  *
127  * The silent gateway 12 in the above may be the result of a bug in
128  * the 4.[23]BSD network code (and its derivatives):  4.x (x <= 3)
129  * sends an unreachable message using whatever ttl remains in the
130  * original datagram.  Since, for gateways, the remaining ttl is
131  * zero, the icmp "time exceeded" is guaranteed to not make it back
132  * to us.  The behavior of this bug is slightly more interesting
133  * when it appears on the destination system:
134  *
135  *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
136  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  39 ms
137  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  39 ms  19 ms
138  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  19 ms
139  *      5  ccn-nerif35.Berkeley.EDU (128.32.168.35)  39 ms  39 ms  39 ms
140  *      6  csgw.Berkeley.EDU (128.32.133.254)  39 ms  59 ms  39 ms
141  *      7  * * *
142  *      8  * * *
143  *      9  * * *
144  *     10  * * *
145  *     11  * * *
146  *     12  * * *
147  *     13  rip.Berkeley.EDU (128.32.131.22)  59 ms !  39 ms !  39 ms !
148  *
149  * Notice that there are 12 "gateways" (13 is the final
150  * destination) and exactly the last half of them are "missing".
151  * What's really happening is that rip (a Sun-3 running Sun OS3.5)
152  * is using the ttl from our arriving datagram as the ttl in its
153  * icmp reply.  So, the reply will time out on the return path
154  * (with no notice sent to anyone since icmp's aren't sent for
155  * icmp's) until we probe with a ttl that's at least twice the path
156  * length.  I.e., rip is really only 7 hops away.  A reply that
157  * returns with a ttl of 1 is a clue this problem exists.
158  * Traceroute prints a "!" after the time if the ttl is <= 1.
159  * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
160  * non-standard (HPUX) software, expect to see this problem
161  * frequently and/or take care picking the target host of your
162  * probes.
163  *
164  * Other possible annotations after the time are !H, !N, !P (got a host,
165  * network or protocol unreachable, respectively), !S or !F (source
166  * route failed or fragmentation needed -- neither of these should
167  * ever occur and the associated gateway is busted if you see one).  If
168  * almost all the probes result in some kind of unreachable, traceroute
169  * will give up and exit.
170  *
171  * Notes
172  * -----
173  * This program must be run by root or be setuid.  (I suggest that
174  * you *don't* make it setuid -- casual use could result in a lot
175  * of unnecessary traffic on our poor, congested nets.)
176  *
177  * This program requires a kernel mod that does not appear in any
178  * system available from Berkeley:  A raw ip socket using proto
179  * IPPROTO_RAW must interpret the data sent as an ip datagram (as
180  * opposed to data to be wrapped in a ip datagram).  See the README
181  * file that came with the source to this program for a description
182  * of the mods I made to /sys/netinet/raw_ip.c.  Your mileage may
183  * vary.  But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
184  * MODIFIED TO RUN THIS PROGRAM.
185  *
186  * The udp port usage may appear bizarre (well, ok, it is bizarre).
187  * The problem is that an icmp message only contains 8 bytes of
188  * data from the original datagram.  8 bytes is the size of a udp
189  * header so, if we want to associate replies with the original
190  * datagram, the necessary information must be encoded into the
191  * udp header (the ip id could be used but there's no way to
192  * interlock with the kernel's assignment of ip id's and, anyway,
193  * it would have taken a lot more kernel hacking to allow this
194  * code to set the ip id).  So, to allow two or more users to
195  * use traceroute simultaneously, we use this task's pid as the
196  * source port (the high bit is set to move the port number out
197  * of the "likely" range).  To keep track of which probe is being
198  * replied to (so times and/or hop counts don't get confused by a
199  * reply that was delayed in transit), we increment the destination
200  * port number before each probe.
201  *
202  * Don't use this as a coding example.  I was trying to find a
203  * routing problem and this code sort-of popped out after 48 hours
204  * without sleep.  I was amazed it ever compiled, much less ran.
205  *
206  * I stole the idea for this program from Steve Deering.  Since
207  * the first release, I've learned that had I attended the right
208  * IETF working group meetings, I also could have stolen it from Guy
209  * Almes or Matt Mathis.  I don't know (or care) who came up with
210  * the idea first.  I envy the originators' perspicacity and I'm
211  * glad they didn't keep the idea a secret.
212  *
213  * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
214  * enhancements to the original distribution.
215  *
216  * I've hacked up a round-trip-route version of this that works by
217  * sending a loose-source-routed udp datagram through the destination
218  * back to yourself.  Unfortunately, SO many gateways botch source
219  * routing, the thing is almost worthless.  Maybe one day...
220  *
221  *  -- Van Jacobson (van@helios.ee.lbl.gov)
222  *     Tue Dec 20 03:50:13 PST 1988
223  */
224 
225 #include <sys/param.h>
226 #include <sys/time.h>
227 #include <sys/socket.h>
228 #include <sys/file.h>
229 #include <sys/ioctl.h>
230 
231 #include <netinet/in_systm.h>
232 #include <netinet/in.h>
233 #include <netinet/ip.h>
234 #include <netinet/ip_icmp.h>
235 #include <netinet/ip_var.h>
236 #include <netinet/udp.h>
237 
238 #include <arpa/inet.h>
239 
240 #include <ctype.h>
241 #include <err.h>
242 #include <errno.h>
243 #include <netdb.h>
244 #include <stdio.h>
245 #include <stdlib.h>
246 #include <string.h>
247 #include <unistd.h>
248 
249 #define Fprintf (void)fprintf
250 #define Printf (void)printf
251 
252 #define	MAX_LSRR	((MAX_IPOPTLEN - 4) / 4)
253 
254 /*
255  * Format of the data in a (udp) probe packet.
256  */
257 struct packetdata {
258 	u_char seq;		/* sequence number of this packet */
259 	u_char ttl;		/* ttl packet left with */
260 	u_int32_t sec;		/* time packet left */
261 	u_int32_t usec;
262 };
263 
264 struct in_addr gateway[MAX_LSRR + 1];
265 int lsrrlen = 0;
266 int32_t sec_perturb;
267 int32_t usec_perturb;
268 
269 u_char packet[512], *outpacket;	/* last inbound (icmp) packet */
270 
271 int wait_for_reply __P((int, struct sockaddr_in *, struct timeval *));
272 void send_probe __P((int, int, int, struct sockaddr_in *));
273 int packet_ok __P((u_char *, int, struct sockaddr_in *, int, int));
274 void print __P((u_char *, int, struct sockaddr_in *));
275 char *inetname __P((struct in_addr));
276 u_short in_cksum __P((u_short *, int));
277 void usage __P((void));
278 
279 int s;				/* receive (icmp) socket file descriptor */
280 int sndsock;			/* send (udp) socket file descriptor */
281 struct timezone tz;		/* leftover */
282 
283 int datalen;			/* How much data */
284 int headerlen;			/* How long packet's header is */
285 
286 char *source = 0;
287 char *hostname;
288 
289 int nprobes = 3;
290 int max_ttl = IPDEFTTL;
291 int first_ttl = 1;
292 u_short ident;
293 u_short port = 32768+666;	/* start udp dest port # for probe packets */
294 u_char	proto = IPPROTO_UDP;
295 u_char  icmp_type = ICMP_ECHO; /* default ICMP code/type */
296 u_char  icmp_code = 0;
297 int options;			/* socket options */
298 int verbose;
299 int waittime = 5;		/* time to wait for response (in seconds) */
300 int nflag;			/* print addresses numerically */
301 int dump;
302 
303 int
304 main(argc, argv)
305 	int argc;
306 	char *argv[];
307 {
308 	struct hostent *hp;
309 	struct protoent *pe;
310 	struct sockaddr_in from, to;
311 	int ch, i, lsrr, on, probe, seq, tos, ttl, ttl_flag, incflag = 1;
312 	struct ip *ip;
313 	u_int32_t tmprnd;
314 	int sump = 0;
315 
316 	if ((pe = getprotobyname("icmp")) == NULL) {
317 		Fprintf(stderr, "icmp: unknown protocol\n");
318 		exit(10);
319 	}
320 	if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0)
321 		err(5, "icmp socket");
322 	if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
323 		err(5, "raw socket");
324 
325 	/* revoke privs */
326 	seteuid(getuid());
327 	setuid(getuid());
328 
329 	ttl_flag = 0;
330 	lsrr = 0;
331 	on = 1;
332 	seq = tos = 0;
333 	while ((ch = getopt(argc, argv, "SDIdg:f:m:np:q:rs:t:w:vlP:c")) != -1)
334 		switch (ch) {
335 		case 'S':
336 			sump = 1;
337 			break;
338 		case 'f':
339 			first_ttl = atoi(optarg);
340 			if (first_ttl < 1 || first_ttl > max_ttl)
341 				errx(1, "min ttl must be 1 to %d.", max_ttl);
342 			break;
343 		case 'c':
344 			incflag = 0;
345 			break;
346 		case 'd':
347 			options |= SO_DEBUG;
348 			break;
349 		case 'D':
350 			dump = 1;
351 			break;
352 		case 'g':
353 			if (lsrr >= MAX_LSRR)
354 				errx(1, "too many gateways; max %d", MAX_LSRR);
355 			if (inet_aton(optarg, &gateway[lsrr]) == 0) {
356 				hp = gethostbyname(optarg);
357 				if (hp == 0)
358 					errx(1, "unknown host %s", optarg);
359 				memcpy(&gateway[lsrr], hp->h_addr, hp->h_length);
360 			}
361 			if (++lsrr == 1)
362 				lsrrlen = 4;
363 			lsrrlen += 4;
364 			break;
365 		case 'I':
366 			proto = IPPROTO_ICMP;
367 			break;
368 		case 'l':
369 			ttl_flag++;
370 			break;
371 		case 'm':
372 			max_ttl = atoi(optarg);
373 			if (max_ttl < first_ttl || max_ttl > MAXTTL)
374 				errx(1, "max ttl must be %d to %d.", first_ttl,
375 				    MAXTTL);
376 			break;
377 		case 'n':
378 			nflag++;
379 			break;
380 		case 'p':
381 			port = atoi(optarg);
382 			if (port < 1)
383 				errx(1, "port must be >0.");
384 			break;
385 		case 'P':
386 			proto = atoi(optarg);
387 			if (proto < 1) {
388 				struct protoent *pent;
389 				pent = getprotobyname(optarg);
390 				if (pent)
391 					proto = pent->p_proto;
392 				else
393 					errx(1, "proto must be >=1, or a name.");
394 			}
395 			break;
396 		case 'q':
397 			nprobes = atoi(optarg);
398 			if (nprobes < 1)
399 				errx(1, "nprobes must be >0.");
400 			break;
401 		case 'r':
402 			options |= SO_DONTROUTE;
403 			break;
404 		case 's':
405 			/*
406 			 * set the ip source address of the outbound
407 			 * probe (e.g., on a multi-homed host).
408 			 */
409 			source = optarg;
410 			break;
411 		case 't':
412 			tos = atoi(optarg);
413 			if (tos < 0 || tos > 255)
414 				errx(1, "tos must be 0 to 255.");
415 			break;
416 		case 'v':
417 			verbose++;
418 			break;
419 		case 'w':
420 			waittime = atoi(optarg);
421 			if (waittime <= 1)
422 				errx(1, "wait must be >1 sec.");
423 			break;
424 		default:
425 			usage();
426 		}
427 	argc -= optind;
428 	argv += optind;
429 
430 	if (argc < 1)
431 		usage();
432 
433 	setlinebuf (stdout);
434 
435 	(void) memset(&to, 0, sizeof(struct sockaddr));
436 	to.sin_family = AF_INET;
437 	if (inet_aton(*argv, &to.sin_addr) != 0)
438 		hostname = *argv;
439 	else {
440 		hp = gethostbyname(*argv);
441 		if (hp == 0)
442 			errx(1, "unknown host %s", *argv);
443 		to.sin_family = hp->h_addrtype;
444 		memcpy(&to.sin_addr, hp->h_addr, hp->h_length);
445 		if ((hostname = strdup(hp->h_name)) == NULL)
446 			err(1, "malloc");
447 	}
448 	if (*++argv)
449 		datalen = atoi(*argv);
450 
451 	switch (proto) {
452 	case IPPROTO_UDP:
453 		headerlen = (sizeof(struct ip) + lsrrlen +
454 		    sizeof(struct udphdr) + sizeof(struct packetdata));
455 		break;
456 	case IPPROTO_ICMP:
457 		headerlen = (sizeof(struct ip) + lsrrlen +
458 		    sizeof(struct icmp) + sizeof(struct packetdata));
459 		break;
460 	default:
461 		headerlen = (sizeof(struct ip) + lsrrlen +
462 		    sizeof(struct packetdata));
463 	}
464 
465 	if (datalen < 0 || datalen > IP_MAXPACKET - headerlen)
466 		errx(1, "packet size must be 0 to %d.",
467 		    IP_MAXPACKET - headerlen);
468 
469 	datalen += headerlen;
470 
471 	outpacket = (u_char *)malloc(datalen);
472 	if (outpacket == 0)
473 		err(1, "malloc");
474 	(void) memset(outpacket, 0, datalen);
475 
476 	ip = (struct ip *)outpacket;
477 	if (lsrr != 0) {
478 		u_char *p;
479 		p = (u_char *)(ip + 1);
480 		*p++ = IPOPT_NOP;
481 		*p++ = IPOPT_LSRR;
482 		*p++ = lsrrlen - 1;
483 		*p++ = IPOPT_MINOFF;
484 		gateway[lsrr] = to.sin_addr;
485 		for (i = 1; i <= lsrr; i++)
486 			*((struct in_addr *)p)++ = gateway[i];
487 		ip->ip_dst = gateway[0];
488 	} else
489 		ip->ip_dst = to.sin_addr;
490 	ip->ip_off = htons(0);
491 	ip->ip_hl = (sizeof(struct ip) + lsrrlen) >> 2;
492 	ip->ip_p = proto;
493 	ip->ip_v = IPVERSION;
494 	ip->ip_tos = tos;
495 
496 	ident = (getpid() & 0xffff) | 0x8000;
497 	tmprnd = arc4random();
498 	sec_perturb = (tmprnd & 0x80000000) ? -(tmprnd & 0x7ff) :
499 						(tmprnd & 0x7ff);
500 	usec_perturb = arc4random();
501 
502 	if (options & SO_DEBUG)
503 		(void) setsockopt(s, SOL_SOCKET, SO_DEBUG,
504 				  (char *)&on, sizeof(on));
505 	if (options & SO_DONTROUTE)
506 		(void) setsockopt(s, SOL_SOCKET, SO_DONTROUTE,
507 				  (char *)&on, sizeof(on));
508 #ifdef SO_SNDBUF
509 	if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&datalen,
510 	    sizeof(datalen)) < 0)
511 		err(6, "SO_SNDBUF");
512 #endif /* SO_SNDBUF */
513 #ifdef IP_HDRINCL
514 	if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on,
515 	    sizeof(on)) < 0)
516 		err(6, "IP_HDRINCL");
517 #endif /* IP_HDRINCL */
518 	if (options & SO_DEBUG)
519 		(void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG,
520 				  (char *)&on, sizeof(on));
521 	if (options & SO_DONTROUTE)
522 		(void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE,
523 				  (char *)&on, sizeof(on));
524 
525 	if (source) {
526 		(void) memset(&from, 0, sizeof(struct sockaddr));
527 		from.sin_family = AF_INET;
528 		if (inet_aton(source, &from.sin_addr) == 0)
529 			errx(1, "unknown host %s", source);
530 		ip->ip_src = from.sin_addr;
531 		if (getuid() != 0 &&
532 		    (ntohl(from.sin_addr.s_addr) & 0xff000000U) == 0x7f000000U &&
533 		    (ntohl(to.sin_addr.s_addr) & 0xff000000U) != 0x7f000000U)
534 			errx(1, "source is on 127/8, destination is not");
535 
536 		if (getuid() &&
537 		    bind(sndsock, (struct sockaddr *)&from, sizeof(from)) < 0)
538 			err(1, "bind");
539 	}
540 
541 	Fprintf(stderr, "traceroute to %s (%s)", hostname,
542 		inet_ntoa(to.sin_addr));
543 	if (source)
544 		Fprintf(stderr, " from %s", source);
545 	Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, datalen);
546 	(void) fflush(stderr);
547 
548 	if (first_ttl > 1)
549 		Printf("Skipping %d intermediate hops\n", first_ttl - 1);
550 
551 	for (ttl = first_ttl; ttl <= max_ttl; ++ttl) {
552 		in_addr_t lastaddr = 0;
553 		int got_there = 0;
554 		int unreachable = 0;
555 		int timeout = 0;
556 		quad_t dt;
557 		int loss;
558 
559 		Printf("%2d ", ttl);
560 		for (probe = 0, loss = 0; probe < nprobes; ++probe) {
561 			int cc;
562 			struct timeval t1, t2;
563 			struct timezone tz;
564 			int code;
565 
566 			(void) gettimeofday(&t1, &tz);
567 			send_probe(++seq, ttl, incflag, &to);
568 			while ((cc = wait_for_reply(s, &from, &t1))) {
569 				(void) gettimeofday(&t2, &tz);
570 				if (t2.tv_sec - t1.tv_sec > waittime) {
571 					cc = 0;
572 					break;
573 				}
574 				i = packet_ok(packet, cc, &from, seq, incflag);
575 				/* Skip short packet */
576 				if (i == 0)
577 					continue;
578 				if (from.sin_addr.s_addr != lastaddr) {
579 					print(packet, cc, &from);
580 					lastaddr = from.sin_addr.s_addr;
581 				}
582 				dt = (quad_t)(t2.tv_sec - t1.tv_sec) * 1000000
583 					+ (quad_t)(t2.tv_usec - t1.tv_usec);
584 				Printf("  %u", (u_int)(dt / 1000));
585 				if (dt % 1000)
586 					Printf(".%u", (u_int)(dt % 1000));
587 				Printf(" ms");
588 				ip = (struct ip *)packet;
589 				if (ttl_flag)
590 					Printf(" (%d)", ip->ip_ttl);
591 				if (i == -2) {
592 #ifndef ARCHAIC
593 					ip = (struct ip *)packet;
594 					if (ip->ip_ttl <= 1)
595 						Printf(" !");
596 #endif
597 					++got_there;
598 					break;
599 				}
600 				/* time exceeded in transit */
601 				if (i == -1)
602 					break;
603 				code = i - 1;
604 				switch (code) {
605 				case ICMP_UNREACH_PORT:
606 #ifndef ARCHAIC
607 					ip = (struct ip *)packet;
608 					if (ip->ip_ttl <= 1)
609 						Printf(" !");
610 #endif /* ARCHAIC */
611 					++got_there;
612 					break;
613 				case ICMP_UNREACH_NET:
614 					++unreachable;
615 					Printf(" !N");
616 					break;
617 				case ICMP_UNREACH_HOST:
618 					++unreachable;
619 					Printf(" !H");
620 					break;
621 				case ICMP_UNREACH_PROTOCOL:
622 					++got_there;
623 					Printf(" !P");
624 					break;
625 				case ICMP_UNREACH_NEEDFRAG:
626 					++unreachable;
627 					Printf(" !F");
628 					break;
629 				case ICMP_UNREACH_SRCFAIL:
630 					++unreachable;
631 					Printf(" !S");
632 					break;
633 				case ICMP_UNREACH_FILTER_PROHIB:
634 				case ICMP_UNREACH_NET_PROHIB: /*misuse*/
635 					++unreachable;
636 					Printf(" !A");
637 					break;
638 				case ICMP_UNREACH_HOST_PROHIB:
639 					++unreachable;
640 					Printf(" !C");
641 					break;
642 				case ICMP_UNREACH_NET_UNKNOWN:
643 				case ICMP_UNREACH_HOST_UNKNOWN:
644 					++unreachable;
645 					Printf(" !U");
646 					break;
647 				case ICMP_UNREACH_ISOLATED:
648 					++unreachable;
649 					Printf(" !I");
650 					break;
651 				case ICMP_UNREACH_TOSNET:
652 				case ICMP_UNREACH_TOSHOST:
653 					++unreachable;
654 					Printf(" !T");
655 					break;
656 				default:
657 					++unreachable;
658 					Printf(" !<%d>", i - 1);
659 					break;
660 				}
661 				break;
662 			}
663 			if (cc == 0) {
664 				Printf(" *");
665 				timeout++;
666 				loss++;
667 			}
668 			(void) fflush(stdout);
669 		}
670 		if (sump)
671 			Printf(" (%d%% loss)", (loss * 100) / nprobes);
672 		putchar('\n');
673 		if (got_there || (unreachable && (unreachable + timeout) >= nprobes))
674 			break;
675 	}
676 	exit(0);
677 }
678 
679 int
680 wait_for_reply(sock, from, sent)
681 	int sock;
682 	struct sockaddr_in *from;
683 	struct timeval *sent;
684 {
685 	struct timeval now, wait;
686 	int cc = 0, fdsn;
687 	int fromlen = sizeof (*from);
688 	fd_set *fdsp;
689 
690 	fdsn = howmany(sock+1, NFDBITS) * sizeof(fd_mask);
691 	if ((fdsp = (fd_set *)malloc(fdsn)) == NULL)
692 		err(1, "malloc");
693 	memset(fdsp, 0, fdsn);
694 	FD_SET(sock, fdsp);
695 	gettimeofday(&now, NULL);
696 	wait.tv_sec = (sent->tv_sec + waittime) - now.tv_sec;
697 	wait.tv_usec =  sent->tv_usec - now.tv_usec;
698 	if (wait.tv_usec < 0) {
699 		wait.tv_usec += 1000000;
700 		wait.tv_sec--;
701 	}
702 	if (wait.tv_sec < 0)
703 		wait.tv_sec = wait.tv_usec = 0;
704 
705 	if (select(sock+1, fdsp, (fd_set *)0, (fd_set *)0, &wait) > 0)
706 		cc=recvfrom(s, (char *)packet, sizeof(packet), 0,
707 			    (struct sockaddr *)from, &fromlen);
708 
709 	free(fdsp);
710 	return (cc);
711 }
712 
713 void
714 dump_packet()
715 {
716 	u_char *p;
717 	int i;
718 
719 	Fprintf(stderr, "packet data:");
720 	for (p = outpacket, i = 0; i < datalen; i++) {
721 		if ((i % 24) == 0)
722 			Fprintf(stderr, "\n ");
723 		Fprintf(stderr, " %02x", *p++);
724 	}
725 	Fprintf(stderr, "\n");
726 }
727 
728 void
729 send_probe(seq, ttl, iflag, to)
730 	int seq, ttl, iflag;
731 	struct sockaddr_in *to;
732 {
733 	struct ip *ip = (struct ip *)outpacket;
734 	u_char *p = (u_char *)(ip + 1);
735 	struct udphdr *up = (struct udphdr *)(p + lsrrlen);
736 	struct icmp *icmpp = (struct icmp *)(p + lsrrlen);
737 	struct packetdata *op;
738 	int i;
739 	struct timeval tv;
740 
741 	ip->ip_len = htons(datalen);
742 	ip->ip_ttl = ttl;
743 	ip->ip_id = htons(ident+seq);
744 
745 	switch(proto) {
746 	   case IPPROTO_ICMP:
747 		icmpp->icmp_type = icmp_type;
748 		icmpp->icmp_code = icmp_code;
749 		icmpp->icmp_seq = htons(seq);
750 		icmpp->icmp_id = htons(ident);
751 		op = (struct packetdata *)(icmpp + 1);
752 		break;
753 	   case IPPROTO_UDP:
754 		up->uh_sport = htons(ident);
755 		if (iflag)
756 			up->uh_dport = htons(port+seq);
757 		else
758 			up->uh_dport = htons(port);
759 		up->uh_ulen = htons((u_short)(datalen - sizeof(struct ip) -
760 		    lsrrlen));
761 		up->uh_sum = 0;
762 		op = (struct packetdata *)(up + 1);
763 		break;
764 	default:
765 		op = (struct packetdata *)(ip + 1);
766 		break;
767 	}
768 	op->seq = seq;
769 	op->ttl = ttl;
770 	(void) gettimeofday(&tv, &tz);
771 
772 	/*
773 	 * We don't want hostiles snooping the net to get any useful
774 	 * information about us. Send the timestamp in network byte order,
775 	 * and perturb the timestamp enough that they won't know our
776 	 * real clock ticker. We don't want to perturb the time by too
777 	 * much: being off by a suspiciously large amount might indicate
778 	 * OpenBSD.
779 	 *
780 	 * The timestamps in the packet are currently unused. If future
781 	 * work wants to use them they will have to subtract out the
782 	 * perturbation first.
783 	 */
784 	(void) gettimeofday(&tv, &tz);
785 	op->sec = htonl(tv.tv_sec + sec_perturb);
786 	op->usec = htonl((tv.tv_usec + usec_perturb) % 1000000);
787 
788 	if (proto == IPPROTO_ICMP && icmp_type == ICMP_ECHO) {
789 		icmpp->icmp_cksum = 0;
790 		icmpp->icmp_cksum = in_cksum((u_short *)icmpp,
791 					datalen - sizeof(struct ip) - lsrrlen);
792 		if (icmpp->icmp_cksum == 0) icmpp->icmp_cksum = 0xffff;
793 	}
794 
795 	if (dump)
796 		dump_packet();
797 
798 	i = sendto(sndsock, outpacket, datalen, 0, (struct sockaddr *)to,
799 		   sizeof(struct sockaddr_in));
800 	if (i < 0 || i != datalen)  {
801 		if (i<0)
802 			perror("sendto");
803 		Printf("traceroute: wrote %s %d chars, ret=%d\n", hostname,
804 			datalen, i);
805 		(void) fflush(stdout);
806 	}
807 }
808 
809 /*
810  * Convert an ICMP "type" field to a printable string.
811  */
812 char *
813 pr_type(t)
814 	u_char t;
815 {
816 	static char *ttab[] = {
817 	"Echo Reply",	"ICMP 1",	"ICMP 2",	"Dest Unreachable",
818 	"Source Quench", "Redirect",	"ICMP 6",	"ICMP 7",
819 	"Echo",		"Router Advert",	"Router Solicit",	"Time Exceeded",
820 	"Param Problem", "Timestamp",	"Timestamp Reply", "Info Request",
821 	"Info Reply", "Mask Request", "Mask Reply"
822 	};
823 
824 	if (t > 18)
825 		return ("OUT-OF-RANGE");
826 
827 	return (ttab[t]);
828 }
829 
830 
831 int
832 packet_ok(buf, cc, from, seq, iflag)
833 	u_char *buf;
834 	int cc;
835 	struct sockaddr_in *from;
836 	int seq;
837 	int iflag;
838 {
839 	register struct icmp *icp;
840 	u_char type, code;
841 	int hlen;
842 #ifndef ARCHAIC
843 	struct ip *ip;
844 
845 	ip = (struct ip *) buf;
846 	hlen = ip->ip_hl << 2;
847 	if (cc < hlen + ICMP_MINLEN) {
848 		if (verbose)
849 			Printf("packet too short (%d bytes) from %s\n", cc,
850 				inet_ntoa(from->sin_addr));
851 		return (0);
852 	}
853 	cc -= hlen;
854 	icp = (struct icmp *)(buf + hlen);
855 #else
856 	icp = (struct icmp *)buf;
857 #endif /* ARCHAIC */
858 	type = icp->icmp_type; code = icp->icmp_code;
859 	if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
860 	    type == ICMP_UNREACH || type == ICMP_ECHOREPLY ) {
861 		struct ip *hip;
862 		struct udphdr *up;
863 		struct icmp *icmpp;
864 
865 		hip = &icp->icmp_ip;
866 		hlen = hip->ip_hl << 2;
867 
868 		switch(proto) {
869 		  case IPPROTO_ICMP:
870 
871 			if (icmp_type == ICMP_ECHO &&
872 			    type == ICMP_ECHOREPLY &&
873 			    icp->icmp_id == htons(ident) &&
874 			    icp->icmp_seq == htons(seq))
875 				return (-2); /* we got there */
876 
877 			icmpp = (struct icmp *)((u_char *)hip + hlen);
878 			if (hlen + 8 <= cc && hip->ip_p == IPPROTO_ICMP &&
879 			    icmpp->icmp_id == htons(ident) &&
880 			    icmpp->icmp_seq == htons(seq))
881 				return (type == ICMP_TIMXCEED? -1 : code + 1);
882 			break;
883 
884 		  case IPPROTO_UDP:
885 			up = (struct udphdr *)((u_char *)hip + hlen);
886 			if (hlen + 12 <= cc && hip->ip_p == proto &&
887 			    up->uh_sport == htons(ident) &&
888 			    ((iflag && up->uh_dport == htons(port + seq)) ||
889 			    (!iflag && up->uh_dport == htons(port))))
890 				return (type == ICMP_TIMXCEED? -1 : code + 1);
891 			break;
892 		default:
893 			/* this is some odd, user specified proto,
894 			 * how do we check it?
895 			 */
896 			if (hip->ip_p == proto)
897 				return (type == ICMP_TIMXCEED? -1 : code + 1);
898 		}
899 	}
900 #ifndef ARCHAIC
901 	if (verbose) {
902 		int i;
903 		in_addr_t *lp = (in_addr_t *)&icp->icmp_ip;
904 
905 		Printf("\n%d bytes from %s", cc, inet_ntoa(from->sin_addr));
906 		Printf(" to %s", inet_ntoa(ip->ip_dst));
907 		Printf(": icmp type %d (%s) code %d\n", type, pr_type(type),
908 		    icp->icmp_code);
909 		for (i = 4; i < cc ; i += sizeof(in_addr_t))
910 			Printf("%2d: x%8.8lx\n", i, (unsigned long)*lp++);
911 	}
912 #endif /* ARCHAIC */
913 	return (0);
914 }
915 
916 
917 void
918 print(buf, cc, from)
919 	u_char *buf;
920 	int cc;
921 	struct sockaddr_in *from;
922 {
923 	struct ip *ip;
924 	int hlen;
925 
926 	ip = (struct ip *) buf;
927 	hlen = ip->ip_hl << 2;
928 	cc -= hlen;
929 
930 	if (nflag)
931 		Printf(" %s", inet_ntoa(from->sin_addr));
932 	else
933 		Printf(" %s (%s)", inetname(from->sin_addr),
934 		    inet_ntoa(from->sin_addr));
935 
936 	if (verbose)
937 		Printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
938 }
939 
940 
941 /*
942  * Checksum routine for Internet Protocol family headers (C Version)
943  */
944 u_short
945 in_cksum(addr, len)
946 	u_short *addr;
947 	int len;
948 {
949 	register int nleft = len;
950 	register u_short *w = addr;
951 	register u_short answer;
952 	register int sum = 0;
953 
954 	/*
955 	 *  Our algorithm is simple, using a 32 bit accumulator (sum),
956 	 *  we add sequential 16 bit words to it, and at the end, fold
957 	 *  back all the carry bits from the top 16 bits into the lower
958 	 *  16 bits.
959 	 */
960 	while (nleft > 1)  {
961 		sum += *w++;
962 		nleft -= 2;
963 	}
964 
965 	/* mop up an odd byte, if necessary */
966 	if (nleft == 1)
967 		sum += *(u_char *)w;
968 
969 	/*
970 	 * add back carry outs from top 16 bits to low 16 bits
971 	 */
972 	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
973 	sum += (sum >> 16);			/* add carry */
974 	answer = ~sum;				/* truncate to 16 bits */
975 	return (answer);
976 }
977 
978 /*
979  * Construct an Internet address representation.
980  * If the nflag has been supplied, give
981  * numeric value, otherwise try for symbolic name.
982  */
983 char *
984 inetname(in)
985 	struct in_addr in;
986 {
987 	register char *cp;
988 	register struct hostent *hp;
989 	static int first = 1;
990 	static char domain[MAXHOSTNAMELEN], line[MAXHOSTNAMELEN];
991 
992 	if (first && !nflag) {
993 		first = 0;
994 		if (gethostname(domain, sizeof domain) == 0 &&
995 		    (cp = strchr(domain, '.')) != NULL) {
996 			strlcpy(domain, cp + 1, sizeof(domain));
997 		}
998 	}
999 	if (!nflag && in.s_addr != INADDR_ANY) {
1000 		hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET);
1001 		if (hp != NULL) {
1002 			if ((cp = strchr(hp->h_name, '.')) != NULL &&
1003 			    strcmp(cp + 1, domain) == 0)
1004 				*cp = '\0';
1005 			strlcpy(line, hp->h_name, sizeof(line));
1006 			return (line);
1007 		}
1008 	}
1009 	return (inet_ntoa(in));
1010 }
1011 
1012 void
1013 usage()
1014 {
1015 	extern char *__progname;
1016 	fprintf(stderr,
1017 "usage: %s [-SDIdnrvc] [-g gateway_addr] ... [-m max_ttl] [-p port#]\n\t\
1018 [-P proto] [-q nqueries] [-s src_addr] [-t tos]\n\t\
1019 [-w wait] [-f first_ttl] host [data size]\n", __progname);
1020 	exit(1);
1021 }
1022