xref: /netbsd-src/usr.sbin/traceroute/traceroute.c (revision 93f9db1b75d415b78f73ed629beeb86235153473)
1 /*	$NetBSD: traceroute.c,v 1.25 1998/08/27 20:31:02 ross Exp $	*/
2 
3 /*
4  * Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that: (1) source code distributions
9  * retain the above copyright notice and this paragraph in its entirety, (2)
10  * distributions including binary code include the above copyright notice and
11  * this paragraph in its entirety in the documentation or other materials
12  * provided with the distribution, and (3) all advertising materials mentioning
13  * features or use of this software display the following acknowledgement:
14  * ``This product includes software developed by the University of California,
15  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16  * the University nor the names of its contributors may be used to endorse
17  * or promote products derived from this software without specific prior
18  * written permission.
19  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22  */
23 
24 #include <sys/cdefs.h>
25 #ifndef lint
26 #if 0
27 static const char rcsid[] =
28     "@(#)Header: traceroute.c,v 1.49 97/06/13 02:30:23 leres Exp  (LBL)";
29 #else
30 __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997\n\
31 The Regents of the University of California.  All rights reserved.\n");
32 __RCSID("$NetBSD: traceroute.c,v 1.25 1998/08/27 20:31:02 ross Exp $");
33 #endif
34 #endif
35 
36 /*
37  * traceroute host  - trace the route ip packets follow going to "host".
38  *
39  * Attempt to trace the route an ip packet would follow to some
40  * internet host.  We find out intermediate hops by launching probe
41  * packets with a small ttl (time to live) then listening for an
42  * icmp "time exceeded" reply from a gateway.  We start our probes
43  * with a ttl of one and increase by one until we get an icmp "port
44  * unreachable" (which means we got to "host") or hit a max (which
45  * defaults to 30 hops & can be changed with the -m flag).  Three
46  * probes (change with -q flag) are sent at each ttl setting and a
47  * line is printed showing the ttl, address of the gateway and
48  * round trip time of each probe.  If the probe answers come from
49  * different gateways, the address of each responding system will
50  * be printed.  If there is no response within a 5 sec. timeout
51  * interval (changed with the -w flag), a "*" is printed for that
52  * probe.
53  *
54  * Probe packets are UDP format.  We don't want the destination
55  * host to process them so the destination port is set to an
56  * unlikely value (if some clod on the destination is using that
57  * value, it can be changed with the -p flag).
58  *
59  * A sample use might be:
60  *
61  *     [yak 71]% traceroute nis.nsf.net.
62  *     traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 56 byte packet
63  *      1  helios.ee.lbl.gov (128.3.112.1)  19 ms  19 ms  0 ms
64  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
65  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
66  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  39 ms
67  *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  39 ms  39 ms  39 ms
68  *      6  128.32.197.4 (128.32.197.4)  40 ms  59 ms  59 ms
69  *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  59 ms
70  *      8  129.140.70.13 (129.140.70.13)  99 ms  99 ms  80 ms
71  *      9  129.140.71.6 (129.140.71.6)  139 ms  239 ms  319 ms
72  *     10  129.140.81.7 (129.140.81.7)  220 ms  199 ms  199 ms
73  *     11  nic.merit.edu (35.1.1.48)  239 ms  239 ms  239 ms
74  *
75  * Note that lines 2 & 3 are the same.  This is due to a buggy
76  * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
77  * packets with a zero ttl.
78  *
79  * A more interesting example is:
80  *
81  *     [yak 72]% traceroute allspice.lcs.mit.edu.
82  *     traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max
83  *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
84  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  19 ms  19 ms
85  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  19 ms
86  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  19 ms  39 ms  39 ms
87  *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  20 ms  39 ms  39 ms
88  *      6  128.32.197.4 (128.32.197.4)  59 ms  119 ms  39 ms
89  *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  39 ms
90  *      8  129.140.70.13 (129.140.70.13)  80 ms  79 ms  99 ms
91  *      9  129.140.71.6 (129.140.71.6)  139 ms  139 ms  159 ms
92  *     10  129.140.81.7 (129.140.81.7)  199 ms  180 ms  300 ms
93  *     11  129.140.72.17 (129.140.72.17)  300 ms  239 ms  239 ms
94  *     12  * * *
95  *     13  128.121.54.72 (128.121.54.72)  259 ms  499 ms  279 ms
96  *     14  * * *
97  *     15  * * *
98  *     16  * * *
99  *     17  * * *
100  *     18  ALLSPICE.LCS.MIT.EDU (18.26.0.115)  339 ms  279 ms  279 ms
101  *
102  * (I start to see why I'm having so much trouble with mail to
103  * MIT.)  Note that the gateways 12, 14, 15, 16 & 17 hops away
104  * either don't send ICMP "time exceeded" messages or send them
105  * with a ttl too small to reach us.  14 - 17 are running the
106  * MIT C Gateway code that doesn't send "time exceeded"s.  God
107  * only knows what's going on with 12.
108  *
109  * The silent gateway 12 in the above may be the result of a bug in
110  * the 4.[23]BSD network code (and its derivatives):  4.x (x <= 3)
111  * sends an unreachable message using whatever ttl remains in the
112  * original datagram.  Since, for gateways, the remaining ttl is
113  * zero, the icmp "time exceeded" is guaranteed to not make it back
114  * to us.  The behavior of this bug is slightly more interesting
115  * when it appears on the destination system:
116  *
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)  39 ms  19 ms  39 ms
119  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  39 ms  19 ms
120  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  19 ms
121  *      5  ccn-nerif35.Berkeley.EDU (128.32.168.35)  39 ms  39 ms  39 ms
122  *      6  csgw.Berkeley.EDU (128.32.133.254)  39 ms  59 ms  39 ms
123  *      7  * * *
124  *      8  * * *
125  *      9  * * *
126  *     10  * * *
127  *     11  * * *
128  *     12  * * *
129  *     13  rip.Berkeley.EDU (128.32.131.22)  59 ms !  39 ms !  39 ms !
130  *
131  * Notice that there are 12 "gateways" (13 is the final
132  * destination) and exactly the last half of them are "missing".
133  * What's really happening is that rip (a Sun-3 running Sun OS3.5)
134  * is using the ttl from our arriving datagram as the ttl in its
135  * icmp reply.  So, the reply will time out on the return path
136  * (with no notice sent to anyone since icmp's aren't sent for
137  * icmp's) until we probe with a ttl that's at least twice the path
138  * length.  I.e., rip is really only 7 hops away.  A reply that
139  * returns with a ttl of 1 is a clue this problem exists.
140  * Traceroute prints a "!" after the time if the ttl is <= 1.
141  * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
142  * non-standard (HPUX) software, expect to see this problem
143  * frequently and/or take care picking the target host of your
144  * probes.
145  *
146  * Other possible annotations after the time are !H, !N, !P (got a host,
147  * network or protocol unreachable, respectively), !S or !F (source
148  * route failed or fragmentation needed -- neither of these should
149  * ever occur and the associated gateway is busted if you see one).  If
150  * almost all the probes result in some kind of unreachable, traceroute
151  * will give up and exit.
152  *
153  * Notes
154  * -----
155  * This program must be run by root or be setuid.  (I suggest that
156  * you *don't* make it setuid -- casual use could result in a lot
157  * of unnecessary traffic on our poor, congested nets.)
158  *
159  * This program requires a kernel mod that does not appear in any
160  * system available from Berkeley:  A raw ip socket using proto
161  * IPPROTO_RAW must interpret the data sent as an ip datagram (as
162  * opposed to data to be wrapped in a ip datagram).  See the README
163  * file that came with the source to this program for a description
164  * of the mods I made to /sys/netinet/raw_ip.c.  Your mileage may
165  * vary.  But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
166  * MODIFIED TO RUN THIS PROGRAM.
167  *
168  * The udp port usage may appear bizarre (well, ok, it is bizarre).
169  * The problem is that an icmp message only contains 8 bytes of
170  * data from the original datagram.  8 bytes is the size of a udp
171  * header so, if we want to associate replies with the original
172  * datagram, the necessary information must be encoded into the
173  * udp header (the ip id could be used but there's no way to
174  * interlock with the kernel's assignment of ip id's and, anyway,
175  * it would have taken a lot more kernel hacking to allow this
176  * code to set the ip id).  So, to allow two or more users to
177  * use traceroute simultaneously, we use this task's pid as the
178  * source port (the high bit is set to move the port number out
179  * of the "likely" range).  To keep track of which probe is being
180  * replied to (so times and/or hop counts don't get confused by a
181  * reply that was delayed in transit), we increment the destination
182  * port number before each probe.
183  *
184  * Don't use this as a coding example.  I was trying to find a
185  * routing problem and this code sort-of popped out after 48 hours
186  * without sleep.  I was amazed it ever compiled, much less ran.
187  *
188  * I stole the idea for this program from Steve Deering.  Since
189  * the first release, I've learned that had I attended the right
190  * IETF working group meetings, I also could have stolen it from Guy
191  * Almes or Matt Mathis.  I don't know (or care) who came up with
192  * the idea first.  I envy the originators' perspicacity and I'm
193  * glad they didn't keep the idea a secret.
194  *
195  * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
196  * enhancements to the original distribution.
197  *
198  * I've hacked up a round-trip-route version of this that works by
199  * sending a loose-source-routed udp datagram through the destination
200  * back to yourself.  Unfortunately, SO many gateways botch source
201  * routing, the thing is almost worthless.  Maybe one day...
202  *
203  *  -- Van Jacobson (van@ee.lbl.gov)
204  *     Tue Dec 20 03:50:13 PST 1988
205  */
206 
207 #include <sys/param.h>
208 #include <sys/file.h>
209 #include <sys/ioctl.h>
210 #ifdef HAVE_SYS_SELECT_H
211 #include <sys/select.h>
212 #endif
213 #include <sys/socket.h>
214 #include <sys/time.h>
215 
216 #include <netinet/in_systm.h>
217 #include <netinet/in.h>
218 #include <netinet/ip.h>
219 #include <netinet/ip_var.h>
220 #include <netinet/ip_icmp.h>
221 #include <netinet/udp.h>
222 #include <netinet/udp_var.h>
223 
224 #include <arpa/inet.h>
225 
226 #include <ctype.h>
227 #include <errno.h>
228 #ifdef HAVE_MALLOC_H
229 #include <malloc.h>
230 #endif
231 #include <memory.h>
232 #include <netdb.h>
233 #include <stdio.h>
234 #include <stdlib.h>
235 #include <string.h>
236 #include <unistd.h>
237 
238 #include "gnuc.h"
239 #ifdef HAVE_OS_PROTO_H
240 #include "os-proto.h"
241 #endif
242 
243 #include "ifaddrlist.h"
244 #include "savestr.h"
245 
246 /* Maximum number of gateways (include room for one noop) */
247 #define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t)))
248 
249 #ifndef MAXHOSTNAMELEN
250 #define MAXHOSTNAMELEN	64
251 #endif
252 
253 #define Fprintf (void)fprintf
254 #define Printf (void)printf
255 
256 /* Host name and address list */
257 struct hostinfo {
258 	char *name;
259 	int n;
260 	u_int32_t *addrs;
261 };
262 
263 /* Data section of the probe packet */
264 struct outdata {
265 	u_char seq;		/* sequence number of this packet */
266 	u_char ttl;		/* ttl packet left with */
267 	struct timeval tv;	/* time packet left */
268 };
269 
270 u_char	packet[512];		/* last inbound (icmp) packet */
271 
272 struct ip *outip;		/* last output (udp) packet */
273 struct udphdr *outudp;		/* last output (udp) packet */
274 void *outmark;			/* packed location of struct outdata */
275 struct outdata outsetup;	/* setup and copy for alignment */
276 
277 struct icmp *outicmp;		/* last output (icmp) packet */
278 
279 /* loose source route gateway list (including room for final destination) */
280 u_int32_t gwlist[NGATEWAYS + 1];
281 
282 int s;				/* receive (icmp) socket file descriptor */
283 int sndsock;			/* send (udp/icmp) socket file descriptor */
284 
285 struct sockaddr whereto;	/* Who to try to reach */
286 struct sockaddr_in wherefrom;	/* Who we are */
287 int packlen;			/* total length of packet */
288 int minpacket;			/* min ip packet size */
289 int maxpacket = 32 * 1024;	/* max ip packet size */
290 
291 char *prog;
292 char *source;
293 char *hostname;
294 char *device;
295 
296 int nprobes = 3;
297 int max_ttl = 30;
298 int first_ttl = 1;
299 u_short ident;
300 u_short port = 32768 + 666;	/* start udp dest port # for probe packets */
301 
302 int options;			/* socket options */
303 int verbose;
304 int waittime = 5;		/* time to wait for response (in seconds) */
305 int nflag;			/* print addresses numerically */
306 int dump;
307 int useicmp;			/* use icmp echo instead of udp packets */
308 #ifdef CANT_HACK_CKSUM
309 int docksum = 0;		/* don't calculate checksums */
310 #else
311 int docksum = 1;		/* calculate checksums */
312 #endif
313 int optlen;			/* length of ip options */
314 
315 int mtus[] = {
316         17914,
317          8166,
318          4464,
319          4352,
320          2048,
321          2002,
322          1536,
323          1500,
324          1492,
325          1006,
326           576,
327           552,
328           544,
329           512,
330           508,
331           296,
332            68,
333             0
334 };
335 int *mtuptr = &mtus[0];
336 int mtudisc = 0;
337 int nextmtu;   /* from ICMP error, set by packet_ok(), might be 0 */
338 
339 extern int optind;
340 extern int opterr;
341 extern char *optarg;
342 
343 /* Forwards */
344 double	deltaT(struct timeval *, struct timeval *);
345 void	freehostinfo(struct hostinfo *);
346 void	getaddr(u_int32_t *, char *);
347 struct	hostinfo *gethostinfo(char *);
348 u_short	in_cksum(u_short *, int);
349 char	*inetname(struct in_addr);
350 int	main(int, char **);
351 int	packet_ok(u_char *, int, struct sockaddr_in *, int);
352 char	*pr_type(u_char);
353 void	print(u_char *, int, struct sockaddr_in *);
354 void	dump_packet(void);
355 void	send_probe(int, int, struct timeval *);
356 void	setsin(struct sockaddr_in *, u_int32_t);
357 int	str2val(const char *, const char *, int, int);
358 void	tvsub(struct timeval *, struct timeval *);
359 __dead	void usage(void);
360 int	wait_for_reply(int, struct sockaddr_in *, struct timeval *);
361 void	frag_err(void);
362 
363 
364 int
365 main(int argc, char **argv)
366 {
367 	register int op, code, n;
368 	register char *cp;
369 	register u_char *outp;
370 	register u_int32_t *ap;
371 	register struct sockaddr_in *from = &wherefrom;
372 	register struct sockaddr_in *to = (struct sockaddr_in *)&whereto;
373 	register struct hostinfo *hi;
374 	int on = 1;
375 	register struct protoent *pe;
376 	register int ttl, probe, i;
377 	register int seq = 0;
378 	int tos = 0, settos = 0, ttl_flag = 0;
379 	register int lsrr = 0;
380 	register u_short off = 0;
381 	struct ifaddrlist *al;
382 	char errbuf[132];
383 
384 	if ((cp = strrchr(argv[0], '/')) != NULL)
385 		prog = cp + 1;
386 	else
387 		prog = argv[0];
388 
389 	opterr = 0;
390 	while ((op = getopt(argc, argv, "dDFPInlrvxf:g:i:m:p:q:s:t:w:")) != -1)
391 		switch (op) {
392 
393 		case 'd':
394 			options |= SO_DEBUG;
395 			break;
396 
397 		case 'D':
398 			dump = 1;
399 			break;
400 
401 		case 'f':
402 			first_ttl = str2val(optarg, "first ttl", 1, 255);
403 			break;
404 
405 		case 'F':
406 			off = IP_DF;
407 			break;
408 
409 		case 'g':
410 			if (lsrr >= NGATEWAYS) {
411 				Fprintf(stderr,
412 				    "%s: No more than %d gateways\n",
413 				    prog, NGATEWAYS);
414 				exit(1);
415 			}
416 			getaddr(gwlist + lsrr, optarg);
417 			++lsrr;
418 			break;
419 
420 		case 'i':
421 			device = optarg;
422 			break;
423 
424 		case 'I':
425 			++useicmp;
426 			break;
427 
428 		case 'l':
429 			++ttl_flag;
430 			break;
431 
432 		case 'm':
433 			max_ttl = str2val(optarg, "max ttl", 1, 255);
434 			break;
435 
436 		case 'n':
437 			++nflag;
438 			break;
439 
440 		case 'p':
441 			port = str2val(optarg, "port", 1, -1);
442 			break;
443 
444 		case 'q':
445 			nprobes = str2val(optarg, "nprobes", 1, -1);
446 			break;
447 
448 		case 'r':
449 			options |= SO_DONTROUTE;
450 			break;
451 
452 		case 's':
453 			/*
454 			 * set the ip source address of the outbound
455 			 * probe (e.g., on a multi-homed host).
456 			 */
457 			source = optarg;
458 			break;
459 
460 		case 't':
461 			tos = str2val(optarg, "tos", 0, 255);
462 			++settos;
463 			break;
464 
465 		case 'v':
466 			++verbose;
467 			break;
468 
469 		case 'x':
470 			docksum = (docksum == 0);
471 			break;
472 
473 		case 'w':
474 			waittime = str2val(optarg, "wait time", 2, -1);
475 			break;
476 
477 		case 'P':
478 			off = IP_DF;
479 			mtudisc = 1;
480 			break;
481 
482 		default:
483 			usage();
484 		}
485 
486 	if (first_ttl > max_ttl) {
487 		Fprintf(stderr,
488 		    "%s: first ttl (%d) may not be greater than max ttl (%d)\n",
489 		    prog, first_ttl, max_ttl);
490 		exit(1);
491 	}
492 
493 	if (!docksum)
494 		Fprintf(stderr, "%s: Warning: ckecksums disabled\n", prog);
495 
496 	if (lsrr > 0)
497 		optlen = (lsrr + 1) * sizeof(gwlist[0]);
498 	minpacket = sizeof(*outip) + sizeof(struct outdata) + optlen;
499 	if (useicmp)
500 		minpacket += 8;			/* XXX magic number */
501 	else
502 		minpacket += sizeof(*outudp);
503 	if (packlen == 0)
504 		packlen = minpacket;		/* minimum sized packet */
505 	else if (minpacket > packlen || packlen > maxpacket) {
506 		Fprintf(stderr, "%s: packet size must be %d <= s <= %d\n",
507 		    prog, minpacket, maxpacket);
508 		exit(1);
509 	}
510 
511 	if (mtudisc)
512 		packlen = *mtuptr++;
513 
514 	/* Process destination and optional packet size */
515 	switch (argc - optind) {
516 
517 	case 2:
518 		packlen = str2val(argv[optind + 1],
519 		    "packet length", minpacket, -1);
520 		/* Fall through */
521 
522 	case 1:
523 		hostname = argv[optind];
524 		hi = gethostinfo(hostname);
525 		setsin(to, hi->addrs[0]);
526 		if (hi->n > 1)
527 			Fprintf(stderr,
528 		    "%s: Warning: %s has multiple addresses; using %s\n",
529 				prog, hostname, inet_ntoa(to->sin_addr));
530 		hostname = hi->name;
531 		hi->name = NULL;
532 		freehostinfo(hi);
533 		break;
534 
535 	default:
536 		usage();
537 	}
538 
539 #ifdef HAVE_SETLINEBUF
540 	setlinebuf (stdout);
541 #else
542 	setvbuf(stdout, NULL, _IOLBF, 0);
543 #endif
544 
545 	outip = (struct ip *)malloc((unsigned)packlen);
546 	if (outip == NULL) {
547 		Fprintf(stderr, "%s: malloc: %s\n", prog, strerror(errno));
548 		exit(1);
549 	}
550 	memset((char *)outip, 0, packlen);
551 
552 	outip->ip_v = IPVERSION;
553 	if (settos)
554 		outip->ip_tos = tos;
555 #ifdef BYTESWAP_IP_LEN
556 	outip->ip_len = htons(packlen);
557 #else
558 	outip->ip_len = packlen;
559 #endif
560 	outip->ip_off = off;
561 	outp = (u_char *)(outip + 1);
562 #ifdef HAVE_RAW_OPTIONS
563 	if (lsrr > 0) {
564 		register u_char *optlist;
565 
566 		optlist = outp;
567 		outp += optlen;
568 
569 		/* final hop */
570 		gwlist[lsrr] = to->sin_addr.s_addr;
571 
572 		outip->ip_dst.s_addr = gwlist[0];
573 
574 		/* force 4 byte alignment */
575 		optlist[0] = IPOPT_NOP;
576 		/* loose source route option */
577 		optlist[1] = IPOPT_LSRR;
578 		i = lsrr * sizeof(gwlist[0]);
579 		optlist[2] = i + 3;
580 		/* Pointer to LSRR addresses */
581 		optlist[3] = IPOPT_MINOFF;
582 		memcpy(optlist + 4, gwlist + 1, i);
583 	} else
584 #endif
585 		outip->ip_dst = to->sin_addr;
586 
587 	outip->ip_hl = (outp - (u_char *)outip) >> 2;
588 	ident = (getpid() & 0xffff) | 0x8000;
589 	if (useicmp) {
590 		outip->ip_p = IPPROTO_ICMP;
591 
592 		outicmp = (struct icmp *)outp;
593 		outicmp->icmp_type = ICMP_ECHO;
594 		outicmp->icmp_id = htons(ident);
595 
596 		outmark = outp + 8;	/* XXX magic number */
597 	} else {
598 		outip->ip_p = IPPROTO_UDP;
599 
600 		outudp = (struct udphdr *)outp;
601 		outudp->uh_sport = htons(ident);
602 		outudp->uh_ulen =
603 		    htons((u_short)(packlen - (sizeof(*outip) + optlen)));
604 		outmark = outudp + 1;
605 	}
606 
607 	cp = "icmp";
608 	if ((pe = getprotobyname(cp)) == NULL) {
609 		Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp);
610 		exit(1);
611 	}
612 	if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0) {
613 		Fprintf(stderr, "%s: icmp socket: %s\n", prog, strerror(errno));
614 		exit(1);
615 	}
616 	if (options & SO_DEBUG)
617 		(void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on,
618 		    sizeof(on));
619 	if (options & SO_DONTROUTE)
620 		(void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
621 		    sizeof(on));
622 
623 #ifndef __hpux
624 	sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
625 #else
626 	sndsock = socket(AF_INET, SOCK_RAW,
627 	    useicmp ? IPPROTO_ICMP : IPPROTO_UDP);
628 #endif
629 	if (sndsock < 0) {
630 		Fprintf(stderr, "%s: raw socket: %s\n", prog, strerror(errno));
631 		exit(1);
632 	}
633 
634 	/* Revert to non-privileged user after opening sockets */
635 	setuid(getuid());
636 
637 #if defined(IP_OPTIONS) && !defined(HAVE_RAW_OPTIONS)
638 	if (lsrr > 0) {
639 		u_char optlist[MAX_IPOPTLEN];
640 
641 		cp = "ip";
642 		if ((pe = getprotobyname(cp)) == NULL) {
643 			Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp);
644 			exit(1);
645 		}
646 
647 		/* final hop */
648 		gwlist[lsrr] = to->sin_addr.s_addr;
649 		++lsrr;
650 
651 		/* force 4 byte alignment */
652 		optlist[0] = IPOPT_NOP;
653 		/* loose source route option */
654 		optlist[1] = IPOPT_LSRR;
655 		i = lsrr * sizeof(gwlist[0]);
656 		optlist[2] = i + 3;
657 		/* Pointer to LSRR addresses */
658 		optlist[3] = IPOPT_MINOFF;
659 		memcpy(optlist + 4, gwlist, i);
660 
661 		if ((setsockopt(sndsock, pe->p_proto, IP_OPTIONS, optlist,
662 		    i + sizeof(gwlist[0]))) < 0) {
663 			Fprintf(stderr, "%s: IP_OPTIONS: %s\n",
664 			    prog, strerror(errno));
665 			exit(1);
666 		    }
667 	}
668 #endif
669 
670 #ifdef SO_SNDBUF
671 	if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&packlen,
672 	    sizeof(packlen)) < 0) {
673 		Fprintf(stderr, "%s: SO_SNDBUF: %s\n", prog, strerror(errno));
674 		exit(1);
675 	}
676 #endif
677 #ifdef IP_HDRINCL
678 	if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on,
679 	    sizeof(on)) < 0) {
680 		Fprintf(stderr, "%s: IP_HDRINCL: %s\n", prog, strerror(errno));
681 		exit(1);
682 	}
683 #else
684 #ifdef IP_TOS
685 	if (settos && setsockopt(sndsock, IPPROTO_IP, IP_TOS,
686 	    (char *)&tos, sizeof(tos)) < 0) {
687 		Fprintf(stderr, "%s: setsockopt tos %d: %s\n",
688 		    prog, tos, strerror(errno));
689 		exit(1);
690 	}
691 #endif
692 #endif
693 	if (options & SO_DEBUG)
694 		(void)setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on,
695 		    sizeof(on));
696 	if (options & SO_DONTROUTE)
697 		(void)setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
698 		    sizeof(on));
699 
700 	/* Get the interface address list */
701 	n = ifaddrlist(&al, errbuf, sizeof errbuf);
702 	if (n < 0) {
703 		Fprintf(stderr, "%s: ifaddrlist: %s\n", prog, errbuf);
704 		exit(1);
705 	}
706 	if (n == 0) {
707 		Fprintf(stderr,
708 		    "%s: Can't find any network interfaces\n", prog);
709 		exit(1);
710 	}
711 
712 	/* Look for a specific device */
713 	if (device != NULL) {
714 		for (i = n; i > 0; --i, ++al)
715 			if (strcmp(device, al->device) == 0)
716 				break;
717 		if (i <= 0) {
718 			Fprintf(stderr, "%s: Can't find interface %s\n",
719 			    prog, device);
720 			exit(1);
721 		}
722 	}
723 
724 	/* Determine our source address */
725 	if (source == NULL) {
726 		/*
727 		 * If a device was specified, use the interface address.
728 		 * Otherwise, use the first interface found.
729 		 * Warn if there are more than one.
730 		 */
731 		setsin(from, al->addr);
732 		if (n > 1 && device == NULL) {
733 			Fprintf(stderr,
734 		    "%s: Warning: Multiple interfaces found; using %s @ %s\n",
735 			    prog, inet_ntoa(from->sin_addr), al->device);
736 		}
737 	} else {
738 		hi = gethostinfo(source);
739 		source = hi->name;
740 		hi->name = NULL;
741 		if (device == NULL) {
742 			/*
743 			 * Use the first interface found.
744 			 * Warn if there are more than one.
745 			 */
746 			setsin(from, hi->addrs[0]);
747 			if (hi->n > 1)
748 				Fprintf(stderr,
749 			"%s: Warning: %s has multiple addresses; using %s\n",
750 				    prog, source, inet_ntoa(from->sin_addr));
751 		} else {
752 			/*
753 			 * Make sure the source specified matches the
754 			 * interface address.
755 			 */
756 			for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap)
757 				if (*ap == al->addr)
758 					break;
759 			if (i <= 0) {
760 				Fprintf(stderr,
761 				    "%s: %s is not on interface %s\n",
762 				    prog, source, device);
763 				exit(1);
764 			}
765 			setsin(from, *ap);
766 		}
767 		freehostinfo(hi);
768 	}
769 	outip->ip_src = from->sin_addr;
770 #ifndef IP_HDRINCL
771 	if (bind(sndsock, (struct sockaddr *)from, sizeof(*from)) < 0) {
772 		Fprintf(stderr, "%s: bind: %s\n",
773 		    prog, strerror(errno));
774 		exit (1);
775 	}
776 #endif
777 
778 	setuid(getuid());
779 	Fprintf(stderr, "%s to %s (%s)",
780 	    prog, hostname, inet_ntoa(to->sin_addr));
781 	if (source)
782 		Fprintf(stderr, " from %s", source);
783 	Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, packlen);
784 	(void)fflush(stderr);
785 
786 	for (ttl = first_ttl; ttl <= max_ttl; ++ttl) {
787 		u_int32_t lastaddr = 0;
788 		int got_there = 0;
789 		int unreachable = 0;
790 
791 again:
792 		Printf("%2d ", ttl);
793 		for (probe = 0; probe < nprobes; ++probe) {
794 			register int cc;
795 			struct timeval t1, t2;
796 			struct timezone tz;
797 			register struct ip *ip;
798 			(void)gettimeofday(&t1, &tz);
799 			send_probe(++seq, ttl, &t1);
800 			while ((cc = wait_for_reply(s, from, &t1)) != 0) {
801 				(void)gettimeofday(&t2, &tz);
802 				/*
803 				 * Since we'll be receiving all ICMP
804 				 * messages to this host above, we may
805 				 * never end up with cc=0, so we need
806 				 * an additional termination check.
807 				 */
808 				if (t2.tv_sec - t1.tv_sec > waittime) {
809 					cc = 0;
810 					break;
811 				}
812 				i = packet_ok(packet, cc, from, seq);
813 				/* Skip short packet */
814 				if (i == 0)
815 					continue;
816 				if (from->sin_addr.s_addr != lastaddr) {
817 					print(packet, cc, from);
818 					lastaddr = from->sin_addr.s_addr;
819 				}
820 				ip = (struct ip *)packet;
821 				Printf("  %.3f ms", deltaT(&t1, &t2));
822 				if (ttl_flag)
823 					Printf(" (ttl = %d)", ip->ip_ttl);
824 				if (i == -2) {
825 #ifndef ARCHAIC
826 					if (ip->ip_ttl <= 1)
827 						Printf(" !");
828 #endif
829 					++got_there;
830 					break;
831 				}
832 
833 				/* time exceeded in transit */
834 				if (i == -1)
835 					break;
836 				code = i - 1;
837 				switch (code) {
838 
839 				case ICMP_UNREACH_PORT:
840 #ifndef ARCHAIC
841 					if (ip->ip_ttl <= 1)
842 						Printf(" !");
843 #endif
844 					++got_there;
845 					break;
846 
847 				case ICMP_UNREACH_NET:
848 					++unreachable;
849 					Printf(" !N");
850 					break;
851 
852 				case ICMP_UNREACH_HOST:
853 					++unreachable;
854 					Printf(" !H");
855 					break;
856 
857 				case ICMP_UNREACH_PROTOCOL:
858 					++got_there;
859 					Printf(" !P");
860 					break;
861 
862 				case ICMP_UNREACH_NEEDFRAG:
863 					if (mtudisc) {
864 						frag_err();
865 						goto again;
866 					} else {
867 						++unreachable;
868 						Printf(" !F");
869 					}
870 					break;
871 
872 				case ICMP_UNREACH_SRCFAIL:
873 					++unreachable;
874 					Printf(" !S");
875 					break;
876 
877 /* rfc1716 */
878 #ifndef ICMP_UNREACH_FILTER_PROHIB
879 #define ICMP_UNREACH_FILTER_PROHIB	13	/* admin prohibited filter */
880 #endif
881 				case ICMP_UNREACH_FILTER_PROHIB:
882 					++unreachable;
883 					Printf(" !X");
884 					break;
885 
886 				default:
887 					++unreachable;
888 					Printf(" !<%d>", code);
889 					break;
890 				}
891 				break;
892 			}
893 			if (cc == 0)
894 				Printf(" *");
895 			(void)fflush(stdout);
896 		}
897 		putchar('\n');
898 		if (got_there ||
899 		    (unreachable > 0 && unreachable >= nprobes))
900 			break;
901 	}
902 	exit(0);
903 }
904 
905 int
906 wait_for_reply(register int sock, register struct sockaddr_in *fromp,
907     register struct timeval *tp)
908 {
909 	fd_set fds;
910 	struct timeval now, wait;
911 	struct timezone tz;
912 	register int cc = 0;
913 	int fromlen = sizeof(*fromp);
914 
915 	FD_ZERO(&fds);
916 	FD_SET(sock, &fds);
917 
918 	wait.tv_sec = tp->tv_sec + waittime;
919 	wait.tv_usec = tp->tv_usec;
920 	(void)gettimeofday(&now, &tz);
921 	tvsub(&wait, &now);
922 
923 	if (select(sock + 1, &fds, NULL, NULL, &wait) > 0)
924 		cc = recvfrom(s, (char *)packet, sizeof(packet), 0,
925 			    (struct sockaddr *)fromp, &fromlen);
926 
927 	return(cc);
928 }
929 
930 void
931 dump_packet()
932 {
933 	u_char *p;
934 	int i;
935 
936 	Fprintf(stderr, "packet data:");
937 
938 #ifdef __hpux
939 	for (p = useicmp ? (u_char *)outicmp : (u_char *)outudp, i = 0; i <
940 	    i < packlen - (sizeof(*outip) + optlen); i++)
941 #else
942 	for (p = (u_char *)outip, i = 0; i < packlen; i++)
943 #endif
944 	{
945 		if ((i % 24) == 0)
946 			Fprintf(stderr, "\n ");
947 		Fprintf(stderr, " %02x", *p++);
948 	}
949 	Fprintf(stderr, "\n");
950 }
951 
952 void
953 send_probe(register int seq, int ttl, register struct timeval *tp)
954 {
955 	register int cc;
956 	register struct udpiphdr * ui;
957 	struct ip tip;
958 
959 again:
960 #ifdef BYTESWAP_IP_LEN
961 	outip->ip_len = htons(packlen);
962 #else
963 	outip->ip_len = packlen;
964 #endif
965 	outip->ip_ttl = ttl;
966 #ifndef __hpux
967 	outip->ip_id = htons(ident + seq);
968 #endif
969 
970 	/*
971 	 * In most cases, the kernel will recalculate the ip checksum.
972 	 * But we must do it anyway so that the udp checksum comes out
973 	 * right.
974 	 */
975 	if (docksum) {
976 		outip->ip_sum =
977 		    in_cksum((u_short *)outip, sizeof(*outip) + optlen);
978 		if (outip->ip_sum == 0)
979 			outip->ip_sum = 0xffff;
980 	}
981 
982 	/* Payload */
983 	outsetup.seq = seq;
984 	outsetup.ttl = ttl;
985 	outsetup.tv  = *tp;
986 	memcpy(outmark,&outsetup,sizeof(outsetup));
987 
988 	if (useicmp)
989 		outicmp->icmp_seq = htons(seq);
990 	else
991 		outudp->uh_dport = htons(port + seq);
992 
993 	/* (We can only do the checksum if we know our ip address) */
994 	if (docksum) {
995 		if (useicmp) {
996 			outicmp->icmp_cksum = 0;
997 			outicmp->icmp_cksum = in_cksum((u_short *)outicmp,
998 			    packlen - (sizeof(*outip) + optlen));
999 			if (outicmp->icmp_cksum == 0)
1000 				outicmp->icmp_cksum = 0xffff;
1001 		} else {
1002 			/* Checksum (must save and restore ip header) */
1003 			tip = *outip;
1004 			ui = (struct udpiphdr *)outip;
1005 #ifndef __NetBSD__
1006 			ui->ui_next = 0;
1007 			ui->ui_prev = 0;
1008 			ui->ui_x1 = 0;
1009 #else
1010 			memset(ui->ui_x1, 0, sizeof(ui->ui_x1));
1011 #endif
1012 			ui->ui_len = outudp->uh_ulen;
1013 			outudp->uh_sum = 0;
1014 			outudp->uh_sum = in_cksum((u_short *)ui, packlen);
1015 			if (outudp->uh_sum == 0)
1016 				outudp->uh_sum = 0xffff;
1017 			*outip = tip;
1018 		}
1019 	}
1020 
1021 	/* XXX undocumented debugging hack */
1022 	if (verbose > 1) {
1023 		register const u_short *sp;
1024 		register int nshorts, i;
1025 
1026 		sp = (u_short *)outip;
1027 		nshorts = (u_int)packlen / sizeof(u_short);
1028 		i = 0;
1029 		Printf("[ %d bytes", packlen);
1030 		while (--nshorts >= 0) {
1031 			if ((i++ % 8) == 0)
1032 				Printf("\n\t");
1033 			Printf(" %04x", ntohs(*sp++));
1034 		}
1035 		if (packlen & 1) {
1036 			if ((i % 8) == 0)
1037 				Printf("\n\t");
1038 			Printf(" %02x", *(u_char *)sp);
1039 		}
1040 		Printf("]\n");
1041 	}
1042 
1043 #if !defined(IP_HDRINCL) && defined(IP_TTL)
1044 	if (setsockopt(sndsock, IPPROTO_IP, IP_TTL,
1045 	    (char *)&ttl, sizeof(ttl)) < 0) {
1046 		Fprintf(stderr, "%s: setsockopt ttl %d: %s\n",
1047 		    prog, ttl, strerror(errno));
1048 		exit(1);
1049 	}
1050 #endif
1051 	if (dump)
1052 		dump_packet();
1053 
1054 #ifdef __hpux
1055 	cc = sendto(sndsock, useicmp ? (char *)outicmp : (char *)outudp,
1056 	    packlen - (sizeof(*outip) + optlen), 0, &whereto, sizeof(whereto));
1057 	if (cc > 0)
1058 		cc += sizeof(*outip) + optlen;
1059 #else
1060 	cc = sendto(sndsock, (char *)outip,
1061 	    packlen, 0, &whereto, sizeof(whereto));
1062 #endif
1063 	if (cc < 0 || cc != packlen)  {
1064 		if (cc < 0) {
1065 			/*
1066 			 * An errno of EMSGSIZE means we're writing too big a
1067 			 * datagram for the interface.  We have to just decrease
1068 			 * the packet size until we find one that works.
1069 			 *
1070 			 * XXX maybe we should try to read the outgoing if's
1071 			 * mtu?
1072 			 */
1073 
1074 			if (errno == EMSGSIZE) {
1075 				packlen = *mtuptr++;
1076 #ifdef _NoLongerLooksUgly_
1077                 		Printf("\nmessage too big, "
1078 				    "trying new MTU = %d ", packlen);
1079 #endif
1080 				goto again;
1081 			} else
1082 				Fprintf(stderr, "%s: sendto: %s\n",
1083 				    prog, strerror(errno));
1084 		}
1085 
1086 		Printf("%s: wrote %s %d chars, ret=%d\n",
1087 		    prog, hostname, packlen, cc);
1088 		(void)fflush(stdout);
1089 	}
1090 }
1091 
1092 double
1093 deltaT(struct timeval *t1p, struct timeval *t2p)
1094 {
1095 	register double dt;
1096 
1097 	dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
1098 	     (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
1099 	return (dt);
1100 }
1101 
1102 /*
1103  * Convert an ICMP "type" field to a printable string.
1104  */
1105 char *
1106 pr_type(register u_char t)
1107 {
1108 	static char *ttab[] = {
1109 	"Echo Reply",	"ICMP 1",	"ICMP 2",	"Dest Unreachable",
1110 	"Source Quench", "Redirect",	"ICMP 6",	"ICMP 7",
1111 	"Echo",		"ICMP 9",	"ICMP 10",	"Time Exceeded",
1112 	"Param Problem", "Timestamp",	"Timestamp Reply", "Info Request",
1113 	"Info Reply"
1114 	};
1115 
1116 	if (t > 16)
1117 		return("OUT-OF-RANGE");
1118 
1119 	return(ttab[t]);
1120 }
1121 
1122 int
1123 packet_ok(register u_char *buf, int cc, register struct sockaddr_in *from,
1124     register int seq)
1125 {
1126 	register struct icmp *icp;
1127 	register u_char type, code;
1128 	register int hlen;
1129 #ifndef ARCHAIC
1130 	register struct ip *ip;
1131 
1132 	ip = (struct ip *) buf;
1133 	hlen = ip->ip_hl << 2;
1134 	if (cc < hlen + ICMP_MINLEN) {
1135 		if (verbose)
1136 			Printf("packet too short (%d bytes) from %s\n", cc,
1137 				inet_ntoa(from->sin_addr));
1138 		return (0);
1139 	}
1140 	cc -= hlen;
1141 	icp = (struct icmp *)(buf + hlen);
1142 #else
1143 	icp = (struct icmp *)buf;
1144 #endif
1145 	type = icp->icmp_type;
1146 	code = icp->icmp_code;
1147 	if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
1148 	    type == ICMP_UNREACH || type == ICMP_ECHOREPLY) {
1149 		register struct ip *hip;
1150 		register struct udphdr *up;
1151 		register struct icmp *hicmp;
1152 
1153 		hip = &icp->icmp_ip;
1154 		hlen = hip->ip_hl << 2;
1155 
1156 		nextmtu = icp->icmp_nextmtu;	/* for frag_err() */
1157 
1158 		if (useicmp) {
1159 			/* XXX */
1160 			if (type == ICMP_ECHOREPLY &&
1161 			    icp->icmp_id == htons(ident) &&
1162 			    icp->icmp_seq == htons(seq))
1163 				return (-2);
1164 
1165 			hicmp = (struct icmp *)((u_char *)hip + hlen);
1166 			/* XXX 8 is a magic number */
1167 			if (hlen + 8 <= cc &&
1168 			    hip->ip_p == IPPROTO_ICMP &&
1169 			    hicmp->icmp_id == htons(ident) &&
1170 			    hicmp->icmp_seq == htons(seq))
1171 				return (type == ICMP_TIMXCEED ? -1 : code + 1);
1172 		} else {
1173 			up = (struct udphdr *)((u_char *)hip + hlen);
1174 			/* XXX 8 is a magic number */
1175 			if (hlen + 12 <= cc &&
1176 			    hip->ip_p == IPPROTO_UDP &&
1177 			    up->uh_sport == htons(ident) &&
1178 			    up->uh_dport == htons(port + seq))
1179 				return (type == ICMP_TIMXCEED ? -1 : code + 1);
1180 		}
1181 	}
1182 #ifndef ARCHAIC
1183 	if (verbose) {
1184 		register int i;
1185 		u_int32_t *lp = (u_int32_t *)&icp->icmp_ip;
1186 
1187 		Printf("\n%d bytes from %s to ", cc, inet_ntoa(from->sin_addr));
1188 		Printf("%s: icmp type %d (%s) code %d\n",
1189 		    inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code);
1190 		for (i = 4; i < cc ; i += sizeof(*lp))
1191 			Printf("%2d: x%8.8x\n", i, *lp++);
1192 	}
1193 #endif
1194 	return(0);
1195 }
1196 
1197 
1198 void
1199 print(register u_char *buf, register int cc, register struct sockaddr_in *from)
1200 {
1201 	register struct ip *ip;
1202 	register int hlen;
1203 
1204 	ip = (struct ip *) buf;
1205 	hlen = ip->ip_hl << 2;
1206 	cc -= hlen;
1207 
1208 	if (nflag)
1209 		Printf(" %s", inet_ntoa(from->sin_addr));
1210 	else
1211 		Printf(" %s (%s)", inetname(from->sin_addr),
1212 		    inet_ntoa(from->sin_addr));
1213 
1214 	if (verbose)
1215 		Printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
1216 }
1217 
1218 /*
1219  * Checksum routine for Internet Protocol family headers (C Version)
1220  */
1221 u_short
1222 in_cksum(register u_short *addr, register int len)
1223 {
1224 	register int nleft = len;
1225 	register u_short *w = addr;
1226 	register u_short answer;
1227 	register int sum = 0;
1228 
1229 	/*
1230 	 *  Our algorithm is simple, using a 32 bit accumulator (sum),
1231 	 *  we add sequential 16 bit words to it, and at the end, fold
1232 	 *  back all the carry bits from the top 16 bits into the lower
1233 	 *  16 bits.
1234 	 */
1235 	while (nleft > 1)  {
1236 		sum += *w++;
1237 		nleft -= 2;
1238 	}
1239 
1240 	/* mop up an odd byte, if necessary */
1241 	if (nleft == 1)
1242 		sum += *(u_char *)w;
1243 
1244 	/*
1245 	 * add back carry outs from top 16 bits to low 16 bits
1246 	 */
1247 	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
1248 	sum += (sum >> 16);			/* add carry */
1249 	answer = ~sum;				/* truncate to 16 bits */
1250 	return (answer);
1251 }
1252 
1253 /*
1254  * Subtract 2 timeval structs:  out = out - in.
1255  * Out is assumed to be >= in.
1256  */
1257 void
1258 tvsub(register struct timeval *out, register struct timeval *in)
1259 {
1260 
1261 	if ((out->tv_usec -= in->tv_usec) < 0)   {
1262 		--out->tv_sec;
1263 		out->tv_usec += 1000000;
1264 	}
1265 	out->tv_sec -= in->tv_sec;
1266 }
1267 
1268 /*
1269  * Construct an Internet address representation.
1270  * If the nflag has been supplied, give
1271  * numeric value, otherwise try for symbolic name.
1272  */
1273 char *
1274 inetname(struct in_addr in)
1275 {
1276 	register char *cp;
1277 	register struct hostent *hp;
1278 	static int first = 1;
1279 	static char domain[MAXHOSTNAMELEN + 1], line[MAXHOSTNAMELEN + 1];
1280 
1281 	if (first && !nflag) {
1282 		int rv;
1283 
1284 		first = 0;
1285 		rv = gethostname(domain, sizeof domain);
1286 		domain[sizeof(domain) - 1] = '\0';
1287 		if (rv == 0 && (cp = strchr(domain, '.')) != NULL) {
1288 			(void)strncpy(domain, cp + 1, sizeof(domain) - 1);
1289 		} else
1290 			domain[0] = '\0';
1291 	}
1292 	if (!nflag && in.s_addr != INADDR_ANY) {
1293 		hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET);
1294 		if (hp != NULL) {
1295 			if ((cp = strchr(hp->h_name, '.')) != NULL &&
1296 			    strcmp(cp + 1, domain) == 0)
1297 				*cp = '\0';
1298 			(void)strncpy(line, hp->h_name, sizeof(line) - 1);
1299 			line[sizeof(line) - 1] = '\0';
1300 			return (line);
1301 		}
1302 	}
1303 	return (inet_ntoa(in));
1304 }
1305 
1306 struct hostinfo *
1307 gethostinfo(register char *hostname)
1308 {
1309 	register int n;
1310 	register struct hostent *hp;
1311 	register struct hostinfo *hi;
1312 	register char **p;
1313 	register u_int32_t *ap;
1314 	struct in_addr addr;
1315 
1316 	hi = calloc(1, sizeof(*hi));
1317 	if (hi == NULL) {
1318 		Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
1319 		exit(1);
1320 	}
1321 	if (inet_aton(hostname, &addr) != 0) {
1322 		hi->name = savestr(hostname);
1323 		hi->n = 1;
1324 		hi->addrs = calloc(1, sizeof(hi->addrs[0]));
1325 		if (hi->addrs == NULL) {
1326 			Fprintf(stderr, "%s: calloc %s\n",
1327 			    prog, strerror(errno));
1328 			exit(1);
1329 		}
1330 		hi->addrs[0] = addr.s_addr;
1331 		return (hi);
1332 	}
1333 
1334 	hp = gethostbyname(hostname);
1335 	if (hp == NULL) {
1336 		Fprintf(stderr, "%s: unknown host %s\n", prog, hostname);
1337 		exit(1);
1338 	}
1339 	if (hp->h_addrtype != AF_INET || hp->h_length != 4) {
1340 		Fprintf(stderr, "%s: bad host %s\n", prog, hostname);
1341 		exit(1);
1342 	}
1343 	hi->name = savestr(hp->h_name);
1344 	for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p)
1345 		continue;
1346 	hi->n = n;
1347 	hi->addrs = calloc(n, sizeof(hi->addrs[0]));
1348 	if (hi->addrs == NULL) {
1349 		Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
1350 		exit(1);
1351 	}
1352 	for (ap = hi->addrs, p = hp->h_addr_list; *p != NULL; ++ap, ++p)
1353 		memcpy(ap, *p, sizeof(*ap));
1354 	return (hi);
1355 }
1356 
1357 void
1358 freehostinfo(register struct hostinfo *hi)
1359 {
1360 	if (hi->name != NULL) {
1361 		free(hi->name);
1362 		hi->name = NULL;
1363 	}
1364 	free((char *)hi->addrs);
1365 	free((char *)hi);
1366 }
1367 
1368 void
1369 getaddr(register u_int32_t *ap, register char *hostname)
1370 {
1371 	register struct hostinfo *hi;
1372 
1373 	hi = gethostinfo(hostname);
1374 	*ap = hi->addrs[0];
1375 	freehostinfo(hi);
1376 }
1377 
1378 void
1379 setsin(register struct sockaddr_in *sin, register u_int32_t addr)
1380 {
1381 
1382 	memset(sin, 0, sizeof(*sin));
1383 #ifdef HAVE_SOCKADDR_SA_LEN
1384 	sin->sin_len = sizeof(*sin);
1385 #endif
1386 	sin->sin_family = AF_INET;
1387 	sin->sin_addr.s_addr = addr;
1388 }
1389 
1390 /* String to value with optional min and max. Handles decimal and hex. */
1391 int
1392 str2val(register const char *str, register const char *what,
1393     register int mi, register int ma)
1394 {
1395 	register const char *cp;
1396 	register int val;
1397 	char *ep;
1398 
1399 	if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
1400 		cp = str + 2;
1401 		val = (int)strtol(cp, &ep, 16);
1402 	} else
1403 		val = (int)strtol(str, &ep, 10);
1404 	if (*ep != '\0') {
1405 		Fprintf(stderr, "%s: \"%s\" bad value for %s \n",
1406 		    prog, str, what);
1407 		exit(1);
1408 	}
1409 	if (val < mi && mi >= 0) {
1410 		if (mi == 0)
1411 			Fprintf(stderr, "%s: %s must be >= %d\n",
1412 			    prog, what, mi);
1413 		else
1414 			Fprintf(stderr, "%s: %s must be > %d\n",
1415 			    prog, what, mi - 1);
1416 		exit(1);
1417 	}
1418 	if (val > ma && ma >= 0) {
1419 		Fprintf(stderr, "%s: %s must be <= %d\n", prog, what, ma);
1420 		exit(1);
1421 	}
1422 	return (val);
1423 }
1424 
1425 __dead void
1426 usage(void)
1427 {
1428 	extern char version[];
1429 
1430 	Fprintf(stderr, "Version %s\n", version);
1431 	Fprintf(stderr, "Usage: %s [-dDFPIlnrvx] [-g gateway] [-i iface] \
1432 [-f first_ttl] [-m max_ttl]\n\t[ -p port] [-q nqueries] [-s src_addr] [-t tos] \
1433 [-w waittime]\n\thost [packetlen]\n",
1434 	    prog);
1435 	exit(1);
1436 }
1437 
1438 /*
1439  * Received ICMP unreachable (fragmentation required and DF set).
1440  * If the ICMP error was from a "new" router, it'll contain the next-hop
1441  * MTU that we should use next.  Otherwise we'll just keep going in the
1442  * mtus[] table, trying until we hit a valid MTU.
1443  */
1444 
1445 
1446 void
1447 frag_err()
1448 {
1449         int i;
1450 
1451         if (nextmtu > 0) {
1452                 Printf("\nfragmentation required and DF set, next hop MTU = %d\n
1453 ",
1454                         nextmtu);
1455                 packlen = nextmtu;
1456                 for (i = 0; mtus[i] > 0; i++) {
1457                         if (mtus[i] < nextmtu) {
1458                                 mtuptr = &mtus[i];    /* next one to try */
1459                                 return;
1460                         }
1461                 }
1462         } else {
1463                 packlen = *mtuptr++;
1464                 Printf("fragmentation required and DF set, "
1465 		    "trying new MTU = %d ", packlen);
1466         }
1467 }
1468 
1469