xref: /netbsd-src/usr.sbin/traceroute/traceroute.c (revision 23c8222edbfb0f0932d88a8351d3a0cf817dfb9e)
1 /*	$NetBSD: traceroute.c,v 1.61 2004/04/22 01:41:22 itojun 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.61 2004/04/22 01:41:22 itojun 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 #include <sys/socket.h>
211 #include <sys/time.h>
212 #include <sys/sysctl.h>
213 
214 #include <netinet/in_systm.h>
215 #include <netinet/in.h>
216 #include <netinet/ip.h>
217 #include <netinet/ip_var.h>
218 #include <netinet/ip_icmp.h>
219 #include <netinet/udp.h>
220 #include <netinet/udp_var.h>
221 
222 #include <arpa/inet.h>
223 
224 #include <ctype.h>
225 #include <errno.h>
226 #ifdef HAVE_MALLOC_H
227 #include <malloc.h>
228 #endif
229 #include <memory.h>
230 #include <netdb.h>
231 #include <stdio.h>
232 #include <stdlib.h>
233 #include <string.h>
234 #include <unistd.h>
235 #include <poll.h>
236 #ifdef IPSEC
237 #include <net/route.h>
238 #include <netinet6/ipsec.h>
239 #endif
240 
241 #include "gnuc.h"
242 #ifdef HAVE_OS_PROTO_H
243 #include "os-proto.h"
244 #endif
245 
246 #include "ifaddrlist.h"
247 #include "as.h"
248 
249 /* Maximum number of gateways (include room for one noop) */
250 #define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t)))
251 
252 #ifndef MAXHOSTNAMELEN
253 #define MAXHOSTNAMELEN	64
254 #endif
255 
256 #define Fprintf (void)fprintf
257 #define Printf (void)printf
258 
259 /* Host name and address list */
260 struct hostinfo {
261 	char *name;
262 	int n;
263 	u_int32_t *addrs;
264 };
265 
266 /* Data section of the probe packet */
267 struct outdata {
268 	u_char seq;		/* sequence number of this packet */
269 	u_char ttl;		/* ttl packet left with */
270 	struct timeval tv;	/* time packet left */
271 };
272 
273 u_char	packet[512];		/* last inbound (icmp) packet */
274 
275 struct ip *outip;		/* last output (udp) packet */
276 struct udphdr *outudp;		/* last output (udp) packet */
277 void *outmark;			/* packed location of struct outdata */
278 struct outdata outsetup;	/* setup and copy for alignment */
279 
280 struct icmp *outicmp;		/* last output (icmp) packet */
281 
282 /* loose source route gateway list (including room for final destination) */
283 u_int32_t gwlist[NGATEWAYS + 1];
284 
285 int s;				/* receive (icmp) socket file descriptor */
286 int sndsock;			/* send (udp/icmp) socket file descriptor */
287 
288 struct sockaddr whereto;	/* Who to try to reach */
289 struct sockaddr_in wherefrom;	/* Who we are */
290 int packlen;			/* total length of packet */
291 int minpacket;			/* min ip packet size */
292 int maxpacket = 32 * 1024;	/* max ip packet size */
293 int printed_ttl = 0;
294 
295 char *prog;
296 char *source;
297 char *hostname;
298 char *device;
299 
300 int nprobes = 3;
301 int max_ttl = 30;
302 int first_ttl = 1;
303 u_int16_t ident;
304 in_port_t port = 32768 + 666;	/* start udp dest port # for probe packets */
305 
306 int options;			/* socket options */
307 int verbose;
308 int waittime = 5;		/* time to wait for response (in seconds) */
309 int nflag;			/* print addresses numerically */
310 int dump;
311 int as_path;			/* print as numbers for each hop */
312 char *as_server = NULL;
313 void *asn;
314 int useicmp;			/* use icmp echo instead of udp packets */
315 #ifdef CANT_HACK_CKSUM
316 int docksum = 0;		/* don't calculate checksums */
317 #else
318 int docksum = 1;		/* calculate checksums */
319 #endif
320 int optlen;			/* length of ip options */
321 
322 int mtus[] = {
323         17914,
324          8166,
325          4464,
326          4352,
327          2048,
328          2002,
329          1536,
330          1500,
331          1492,
332 	 1480,
333 	 1280,
334          1006,
335           576,
336           552,
337           544,
338           512,
339           508,
340           296,
341            68,
342             0
343 };
344 int *mtuptr = &mtus[0];
345 int mtudisc = 0;
346 int nextmtu;   /* from ICMP error, set by packet_ok(), might be 0 */
347 
348 extern int optind;
349 extern int opterr;
350 extern char *optarg;
351 
352 /* Forwards */
353 double	deltaT(struct timeval *, struct timeval *);
354 void	freehostinfo(struct hostinfo *);
355 void	getaddr(u_int32_t *, char *);
356 struct	hostinfo *gethostinfo(char *);
357 u_int16_t in_cksum(u_int16_t *, int);
358 u_int16_t in_cksum2(u_int16_t, u_int16_t *, int);
359 char	*inetname(struct in_addr);
360 int	main(int, char **);
361 int	packet_ok(u_char *, int, struct sockaddr_in *, int);
362 char	*pr_type(u_char);
363 void	print(u_char *, int, struct sockaddr_in *);
364 void	resize_packet(void);
365 void	dump_packet(void);
366 void	send_probe(int, int, struct timeval *);
367 void	setsin(struct sockaddr_in *, u_int32_t);
368 int	str2val(const char *, const char *, int, int);
369 void	tvsub(struct timeval *, struct timeval *);
370 __dead	void usage(void);
371 int	wait_for_reply(int, struct sockaddr_in *, struct timeval *);
372 void	frag_err(void);
373 int	find_local_ip(struct sockaddr_in *, struct sockaddr_in *);
374 #ifdef IPSEC
375 #ifdef IPSEC_POLICY_IPSEC
376 int	setpolicy(int so, char *policy);
377 #endif
378 #endif
379 
380 int
381 main(int argc, char **argv)
382 {
383 	int op, code, n;
384 	char *cp;
385 	u_char *outp;
386 	u_int32_t *ap;
387 	struct sockaddr_in *from = &wherefrom;
388 	struct sockaddr_in *to = (struct sockaddr_in *)&whereto;
389 	struct hostinfo *hi;
390 	int on = 1;
391 	int ttl, probe, i;
392 	int seq = 0;
393 	int tos = 0, settos = 0, ttl_flag = 0;
394 	int lsrr = 0;
395 	u_int16_t off = 0;
396 	struct ifaddrlist *al, *al2;
397 	char errbuf[132];
398 	int mib[4] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_DEFTTL };
399 	size_t size = sizeof(max_ttl);
400 
401 	(void) sysctl(mib, sizeof(mib)/sizeof(mib[0]), &max_ttl, &size,
402 	    NULL, 0);
403 
404 	if ((cp = strrchr(argv[0], '/')) != NULL)
405 		prog = cp + 1;
406 	else
407 		prog = argv[0];
408 
409 	opterr = 0;
410 	while ((op = getopt(argc, argv, "aA:dDFPInlrvxf:g:i:m:p:q:s:t:w:")) != -1)
411 		switch (op) {
412 
413 		case 'a':
414 			as_path = 1;
415 			break;
416 
417 		case 'A':
418 			as_path = 1;
419 			as_server = optarg;
420 			break;
421 
422 		case 'd':
423 			options |= SO_DEBUG;
424 			break;
425 
426 		case 'D':
427 			dump = 1;
428 			break;
429 
430 		case 'f':
431 			first_ttl = str2val(optarg, "first ttl", 1, 255);
432 			break;
433 
434 		case 'F':
435 			off = IP_DF;
436 			break;
437 
438 		case 'g':
439 			if (lsrr >= NGATEWAYS) {
440 				Fprintf(stderr,
441 				    "%s: No more than %d gateways\n",
442 				    prog, NGATEWAYS);
443 				exit(1);
444 			}
445 			getaddr(gwlist + lsrr, optarg);
446 			++lsrr;
447 			break;
448 
449 		case 'i':
450 			device = optarg;
451 			break;
452 
453 		case 'I':
454 			++useicmp;
455 			break;
456 
457 		case 'l':
458 			++ttl_flag;
459 			break;
460 
461 		case 'm':
462 			max_ttl = str2val(optarg, "max ttl", 1, 255);
463 			break;
464 
465 		case 'n':
466 			++nflag;
467 			break;
468 
469 		case 'p':
470 			port = str2val(optarg, "port", 1, -1);
471 			break;
472 
473 		case 'q':
474 			nprobes = str2val(optarg, "nprobes", 1, -1);
475 			break;
476 
477 		case 'r':
478 			options |= SO_DONTROUTE;
479 			break;
480 
481 		case 's':
482 			/*
483 			 * set the ip source address of the outbound
484 			 * probe (e.g., on a multi-homed host).
485 			 */
486 			source = optarg;
487 			break;
488 
489 		case 't':
490 			tos = str2val(optarg, "tos", 0, 255);
491 			++settos;
492 			break;
493 
494 		case 'v':
495 			++verbose;
496 			break;
497 
498 		case 'x':
499 			docksum = (docksum == 0);
500 			break;
501 
502 		case 'w':
503 			waittime = str2val(optarg, "wait time", 2, 24 * 3600);
504 			break;
505 
506 		case 'P':
507 			off = IP_DF;
508 			mtudisc = 1;
509 			break;
510 
511 		default:
512 			usage();
513 		}
514 
515 	if (first_ttl > max_ttl) {
516 		Fprintf(stderr,
517 		    "%s: first ttl (%d) may not be greater than max ttl (%d)\n",
518 		    prog, first_ttl, max_ttl);
519 		exit(1);
520 	}
521 
522 	if (!docksum)
523 		Fprintf(stderr, "%s: Warning: ckecksums disabled\n", prog);
524 
525 	if (lsrr > 0)
526 		optlen = (lsrr + 1) * sizeof(gwlist[0]);
527 	minpacket = sizeof(*outip) + sizeof(struct outdata) + optlen;
528 	if (useicmp)
529 		minpacket += 8;			/* XXX magic number */
530 	else
531 		minpacket += sizeof(*outudp);
532 	if (packlen == 0)
533 		packlen = minpacket;		/* minimum sized packet */
534 	else if (minpacket > packlen || packlen > maxpacket) {
535 		Fprintf(stderr, "%s: packet size must be %d <= s <= %d\n",
536 		    prog, minpacket, maxpacket);
537 		exit(1);
538 	}
539 
540 	if (mtudisc)
541 		packlen = *mtuptr++;
542 
543 	/* Process destination and optional packet size */
544 	switch (argc - optind) {
545 
546 	case 2:
547 		packlen = str2val(argv[optind + 1],
548 		    "packet length", minpacket, -1);
549 		/* Fall through */
550 
551 	case 1:
552 		hostname = argv[optind];
553 		hi = gethostinfo(hostname);
554 		setsin(to, hi->addrs[0]);
555 		if (hi->n > 1)
556 			Fprintf(stderr,
557 		    "%s: Warning: %s has multiple addresses; using %s\n",
558 				prog, hostname, inet_ntoa(to->sin_addr));
559 		hostname = hi->name;
560 		hi->name = NULL;
561 		freehostinfo(hi);
562 		break;
563 
564 	default:
565 		usage();
566 	}
567 
568 #ifdef HAVE_SETLINEBUF
569 	setlinebuf (stdout);
570 #else
571 	setvbuf(stdout, NULL, _IOLBF, 0);
572 #endif
573 
574 	outip = (struct ip *)malloc((unsigned)packlen);
575 	if (outip == NULL) {
576 		Fprintf(stderr, "%s: malloc: %s\n", prog, strerror(errno));
577 		exit(1);
578 	}
579 	memset((char *)outip, 0, packlen);
580 
581 	outip->ip_v = IPVERSION;
582 	if (settos)
583 		outip->ip_tos = tos;
584 #ifdef BYTESWAP_IP_LEN
585 	outip->ip_len = htons(packlen);
586 #else
587 	outip->ip_len = packlen;
588 #endif
589 	outip->ip_off = off;
590 	outp = (u_char *)(outip + 1);
591 #ifdef HAVE_RAW_OPTIONS
592 	if (lsrr > 0) {
593 		u_char *optlist;
594 
595 		optlist = outp;
596 		outp += optlen;
597 
598 		/* final hop */
599 		gwlist[lsrr] = to->sin_addr.s_addr;
600 
601 		outip->ip_dst.s_addr = gwlist[0];
602 
603 		/* force 4 byte alignment */
604 		optlist[0] = IPOPT_NOP;
605 		/* loose source route option */
606 		optlist[1] = IPOPT_LSRR;
607 		i = lsrr * sizeof(gwlist[0]);
608 		optlist[2] = i + 3;
609 		/* Pointer to LSRR addresses */
610 		optlist[3] = IPOPT_MINOFF;
611 		memcpy(optlist + 4, gwlist + 1, i);
612 	} else
613 #endif
614 		outip->ip_dst = to->sin_addr;
615 
616 	outip->ip_hl = (outp - (u_char *)outip) >> 2;
617 	ident = htons(arc4random() & 0xffff) | 0x8000;
618 	if (useicmp) {
619 		outip->ip_p = IPPROTO_ICMP;
620 
621 		outicmp = (struct icmp *)outp;
622 		outicmp->icmp_type = ICMP_ECHO;
623 		outicmp->icmp_id = htons(ident);
624 
625 		outmark = outp + 8;	/* XXX magic number */
626 	} else {
627 		outip->ip_p = IPPROTO_UDP;
628 
629 		outudp = (struct udphdr *)outp;
630 		outudp->uh_sport = htons(ident);
631 		outudp->uh_ulen =
632 		    htons((u_int16_t)(packlen - (sizeof(*outip) + optlen)));
633 		outmark = outudp + 1;
634 	}
635 
636 	if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
637 		Fprintf(stderr, "%s: icmp socket: %s\n", prog, strerror(errno));
638 		exit(1);
639 	}
640 	if (options & SO_DEBUG)
641 		(void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on,
642 		    sizeof(on));
643 #ifdef IPSEC
644 #ifdef IPSEC_POLICY_IPSEC
645 	/*
646 	 * do not raise error even if setsockopt fails, kernel may have ipsec
647 	 * turned off.
648 	 */
649 	if (setpolicy(s, "in bypass") < 0)
650 		exit(1);
651 	if (setpolicy(s, "out bypass") < 0)
652 		exit(1);
653 #else
654     {
655 	int level = IPSEC_LEVEL_AVAIL;
656 
657 	(void)setsockopt(s, IPPROTO_IP, IP_ESP_TRANS_LEVEL, &level,
658 		sizeof(level));
659 	(void)setsockopt(s, IPPROTO_IP, IP_ESP_NETWORK_LEVEL, &level,
660 		sizeof(level));
661 #ifdef IP_AUTH_TRANS_LEVEL
662 	(void)setsockopt(s, IPPROTO_IP, IP_AUTH_TRANS_LEVEL, &level,
663 		sizeof(level));
664 #else
665 	(void)setsockopt(s, IPPROTO_IP, IP_AUTH_LEVEL, &level,
666 		sizeof(level));
667 #endif
668 #ifdef IP_AUTH_NETWORK_LEVEL
669 	(void)setsockopt(s, IPPROTO_IP, IP_AUTH_NETWORK_LEVEL, &level,
670 		sizeof(level));
671 #endif
672     }
673 #endif /*IPSEC_POLICY_IPSEC*/
674 #endif /*IPSEC*/
675 
676 #ifndef __hpux
677 	sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
678 #else
679 	sndsock = socket(AF_INET, SOCK_RAW,
680 	    useicmp ? IPPROTO_ICMP : IPPROTO_UDP);
681 #endif
682 	if (sndsock < 0) {
683 		Fprintf(stderr, "%s: raw socket: %s\n", prog, strerror(errno));
684 		exit(1);
685 	}
686 
687 #ifdef IPSEC
688 #ifdef IPSEC_POLICY_IPSEC
689 	/*
690 	 * do not raise error even if setsockopt fails, kernel may have ipsec
691 	 * turned off.
692 	 */
693 	if (setpolicy(sndsock, "in bypass") < 0)
694 		exit(1);
695 	if (setpolicy(sndsock, "out bypass") < 0)
696 		exit(1);
697 #else
698     {
699 	int level = IPSEC_LEVEL_BYPASS;
700 
701 	(void)setsockopt(sndsock, IPPROTO_IP, IP_ESP_TRANS_LEVEL, &level,
702 		sizeof(level));
703 	(void)setsockopt(sndsock, IPPROTO_IP, IP_ESP_NETWORK_LEVEL, &level,
704 		sizeof(level));
705 #ifdef IP_AUTH_TRANS_LEVEL
706 	(void)setsockopt(sndsock, IPPROTO_IP, IP_AUTH_TRANS_LEVEL, &level,
707 		sizeof(level));
708 #else
709 	(void)setsockopt(sndsock, IPPROTO_IP, IP_AUTH_LEVEL, &level,
710 		sizeof(level));
711 #endif
712 #ifdef IP_AUTH_NETWORK_LEVEL
713 	(void)setsockopt(sndsock, IPPROTO_IP, IP_AUTH_NETWORK_LEVEL, &level,
714 		sizeof(level));
715 #endif
716     }
717 #endif /*IPSEC_POLICY_IPSEC*/
718 #endif /*IPSEC*/
719 
720 	/* Revert to non-privileged user after opening sockets */
721 	setuid(getuid());
722 
723 #if defined(IP_OPTIONS) && !defined(HAVE_RAW_OPTIONS)
724 	if (lsrr > 0) {
725 		u_char optlist[MAX_IPOPTLEN];
726 
727 		/* final hop */
728 		gwlist[lsrr] = to->sin_addr.s_addr;
729 		++lsrr;
730 
731 		/* force 4 byte alignment */
732 		optlist[0] = IPOPT_NOP;
733 		/* loose source route option */
734 		optlist[1] = IPOPT_LSRR;
735 		i = lsrr * sizeof(gwlist[0]);
736 		optlist[2] = i + 3;
737 		/* Pointer to LSRR addresses */
738 		optlist[3] = IPOPT_MINOFF;
739 		memcpy(optlist + 4, gwlist, i);
740 
741 		if ((setsockopt(sndsock, IPPROTO_IP, IP_OPTIONS, optlist,
742 		    i + sizeof(gwlist[0]))) < 0) {
743 			Fprintf(stderr, "%s: IP_OPTIONS: %s\n",
744 			    prog, strerror(errno));
745 			exit(1);
746 		    }
747 	}
748 #endif
749 
750 #ifdef SO_SNDBUF
751 	if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&packlen,
752 	    sizeof(packlen)) < 0) {
753 		Fprintf(stderr, "%s: SO_SNDBUF: %s\n", prog, strerror(errno));
754 		exit(1);
755 	}
756 #endif
757 #ifdef IP_HDRINCL
758 	if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on,
759 	    sizeof(on)) < 0) {
760 		Fprintf(stderr, "%s: IP_HDRINCL: %s\n", prog, strerror(errno));
761 		exit(1);
762 	}
763 #else
764 #ifdef IP_TOS
765 	if (settos && setsockopt(sndsock, IPPROTO_IP, IP_TOS,
766 	    (char *)&tos, sizeof(tos)) < 0) {
767 		Fprintf(stderr, "%s: setsockopt tos %d: %s\n",
768 		    prog, tos, strerror(errno));
769 		exit(1);
770 	}
771 #endif
772 #endif
773 	if (options & SO_DEBUG)
774 		(void)setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on,
775 		    sizeof(on));
776 	if (options & SO_DONTROUTE)
777 		(void)setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
778 		    sizeof(on));
779 
780 	/* Get the interface address list */
781 	n = ifaddrlist(&al, errbuf, sizeof errbuf);
782 	al2 = al;
783 	if (n < 0) {
784 		Fprintf(stderr, "%s: ifaddrlist: %s\n", prog, errbuf);
785 		exit(1);
786 	}
787 	if (n == 0) {
788 		Fprintf(stderr,
789 		    "%s: Can't find any network interfaces\n", prog);
790 		exit(1);
791 	}
792 
793 	/* Look for a specific device */
794 	if (device != NULL) {
795 		for (i = n; i > 0; --i, ++al2)
796 			if (strcmp(device, al2->device) == 0)
797 				break;
798 		if (i <= 0) {
799 			Fprintf(stderr, "%s: Can't find interface %s\n",
800 			    prog, device);
801 			exit(1);
802 		}
803 	}
804 
805 	/* Determine our source address */
806 	if (source == NULL) {
807 		/*
808 		 * If a device was specified, use the interface address.
809 		 * Otherwise, use the first interface found.
810 		 * Warn if there are more than one.
811 		 */
812 		setsin(from, al2->addr);
813 		if (n > 1 && device == NULL && !find_local_ip(from, to)) {
814 			Fprintf(stderr,
815 		    "%s: Warning: Multiple interfaces found; using %s @ %s\n",
816 			    prog, inet_ntoa(from->sin_addr), al2->device);
817 		}
818 	} else {
819 		hi = gethostinfo(source);
820 		source = hi->name;
821 		hi->name = NULL;
822 		if (device == NULL) {
823 			/*
824 			 * Use the first interface found.
825 			 * Warn if there are more than one.
826 			 */
827 			setsin(from, hi->addrs[0]);
828 			if (hi->n > 1)
829 				Fprintf(stderr,
830 			"%s: Warning: %s has multiple addresses; using %s\n",
831 				    prog, source, inet_ntoa(from->sin_addr));
832 		} else {
833 			/*
834 			 * Make sure the source specified matches the
835 			 * interface address.
836 			 */
837 			for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap)
838 				if (*ap == al2->addr)
839 					break;
840 			if (i <= 0) {
841 				Fprintf(stderr,
842 				    "%s: %s is not on interface %s\n",
843 				    prog, source, device);
844 				exit(1);
845 			}
846 			setsin(from, *ap);
847 		}
848 		freehostinfo(hi);
849 	}
850 
851 	/*
852 	 * If not root, make sure source address matches a local interface.
853 	 * (The list of addresses produced by ifaddrlist() automatically
854 	 * excludes interfaces that are marked down and/or loopback.)
855 	 */
856 	if (getuid())  {
857 		al2 = al;
858 		for (i = n; i > 0; --i, ++al2)
859 			if (from->sin_addr.s_addr == al2->addr)
860 			    break;
861 		if (i <= 0) {
862 			Fprintf(stderr, "%s: %s is not a valid local address "
863 			    "and you are not superuser.\n", prog,
864 			    inet_ntoa(from->sin_addr));
865 			exit(1);
866 		}
867 	}
868 
869 	outip->ip_src = from->sin_addr;
870 #ifndef IP_HDRINCL
871 	if (bind(sndsock, (struct sockaddr *)from, sizeof(*from)) < 0) {
872 		Fprintf(stderr, "%s: bind: %s\n",
873 		    prog, strerror(errno));
874 		exit (1);
875 	}
876 #endif
877 
878 	if (as_path) {
879 		asn = as_setup(as_server);
880 		if (asn == NULL) {
881 			Fprintf(stderr, "%s: as_setup failed, AS# lookups disabled\n",
882 				prog);
883 			(void)fflush(stderr);
884 			as_path = 0;
885 		}
886 	}
887 
888 	setuid(getuid());
889 	Fprintf(stderr, "%s to %s (%s)",
890 	    prog, hostname, inet_ntoa(to->sin_addr));
891 	if (source)
892 		Fprintf(stderr, " from %s", source);
893 	Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, packlen);
894 	(void)fflush(stderr);
895 
896 	for (ttl = first_ttl; ttl <= max_ttl; ++ttl) {
897 		u_int32_t lastaddr = 0;
898 		int got_there = 0;
899 		int unreachable = 0;
900 
901 again:
902 		printed_ttl = 0;
903 		for (probe = 0; probe < nprobes; ++probe) {
904 			int cc;
905 			struct timeval t1, t2;
906 			struct ip *ip;
907 			(void)gettimeofday(&t1, NULL);
908 			send_probe(++seq, ttl, &t1);
909 			while ((cc = wait_for_reply(s, from, &t1)) != 0) {
910 				(void)gettimeofday(&t2, NULL);
911 				/*
912 				 * Since we'll be receiving all ICMP
913 				 * messages to this host above, we may
914 				 * never end up with cc=0, so we need
915 				 * an additional termination check.
916 				 */
917 				if (t2.tv_sec - t1.tv_sec > waittime) {
918 					cc = 0;
919 					break;
920 				}
921 				i = packet_ok(packet, cc, from, seq);
922 				/* Skip short packet */
923 				if (i == 0)
924 					continue;
925 				if (from->sin_addr.s_addr != lastaddr) {
926 					print(packet, cc, from);
927 					lastaddr = from->sin_addr.s_addr;
928 				}
929 				ip = (struct ip *)packet;
930 				Printf("  %.3f ms", deltaT(&t1, &t2));
931 				if (ttl_flag)
932 					Printf(" (ttl = %d)", ip->ip_ttl);
933 				if (i == -2) {
934 #ifndef ARCHAIC
935 					if (ip->ip_ttl <= 1)
936 						Printf(" !");
937 #endif
938 					++got_there;
939 					break;
940 				}
941 
942 				/* time exceeded in transit */
943 				if (i == -1)
944 					break;
945 				code = i - 1;
946 				switch (code) {
947 
948 				case ICMP_UNREACH_PORT:
949 #ifndef ARCHAIC
950 					if (ip->ip_ttl <= 1)
951 						Printf(" !");
952 #endif
953 					++got_there;
954 					break;
955 
956 				case ICMP_UNREACH_NET:
957 					++unreachable;
958 					Printf(" !N");
959 					break;
960 
961 				case ICMP_UNREACH_HOST:
962 					++unreachable;
963 					Printf(" !H");
964 					break;
965 
966 				case ICMP_UNREACH_PROTOCOL:
967 					++got_there;
968 					Printf(" !P");
969 					break;
970 
971 				case ICMP_UNREACH_NEEDFRAG:
972 					if (mtudisc) {
973 						frag_err();
974 						goto again;
975 					} else {
976 						++unreachable;
977 						Printf(" !F");
978 					}
979 					break;
980 
981 				case ICMP_UNREACH_SRCFAIL:
982 					++unreachable;
983 					Printf(" !S");
984 					break;
985 
986 /* rfc1716 */
987 #ifndef ICMP_UNREACH_FILTER_PROHIB
988 #define ICMP_UNREACH_FILTER_PROHIB	13	/* admin prohibited filter */
989 #endif
990 				case ICMP_UNREACH_FILTER_PROHIB:
991 					++unreachable;
992 					Printf(" !X");
993 					break;
994 
995 				default:
996 					++unreachable;
997 					Printf(" !<%d>", code);
998 					break;
999 				}
1000 				break;
1001 			}
1002 			if (cc == 0)
1003 				Printf(" *");
1004 			(void)fflush(stdout);
1005 		}
1006 		putchar('\n');
1007 		if (got_there ||
1008 		    (unreachable > 0 && unreachable >= ((nprobes + 1) / 2)))
1009 			break;
1010 	}
1011 
1012 	if (as_path)
1013 		as_shutdown(asn);
1014 
1015 	exit(0);
1016 }
1017 
1018 int
1019 wait_for_reply(int sock, struct sockaddr_in *fromp, struct timeval *tp)
1020 {
1021 	struct pollfd set[1];
1022 	struct timeval now, wait;
1023 	int cc = 0;
1024 	int fromlen = sizeof(*fromp);
1025 	int retval;
1026 
1027 	set[0].fd = sock;
1028 	set[0].events = POLLIN;
1029 
1030 	wait.tv_sec = tp->tv_sec + waittime;
1031 	wait.tv_usec = tp->tv_usec;
1032 	(void)gettimeofday(&now, NULL);
1033 	tvsub(&wait, &now);
1034 
1035 	if (wait.tv_sec < 0) {
1036 		wait.tv_sec = 0;
1037 		wait.tv_usec = 0;
1038 	}
1039 
1040 	retval = poll(set, 1, wait.tv_sec * 1000 + wait.tv_usec / 1000);
1041 	if (retval < 0)  {
1042 		/* If we continue, we probably just flood the remote host. */
1043 		Fprintf(stderr, "%s: select: %s\n", prog, strerror(errno));
1044 		exit(1);
1045 	}
1046 	if (retval > 0)  {
1047 		cc = recvfrom(s, (char *)packet, sizeof(packet), 0,
1048 			    (struct sockaddr *)fromp, &fromlen);
1049 	}
1050 
1051 	return(cc);
1052 }
1053 
1054 void
1055 dump_packet()
1056 {
1057 	u_char *p;
1058 	int i;
1059 
1060 	Fprintf(stderr, "packet data:");
1061 
1062 #ifdef __hpux
1063 	for (p = useicmp ? (u_char *)outicmp : (u_char *)outudp, i = 0; i <
1064 	    i < packlen - (sizeof(*outip) + optlen); i++)
1065 #else
1066 	for (p = (u_char *)outip, i = 0; i < packlen; i++)
1067 #endif
1068 	{
1069 		if ((i % 24) == 0)
1070 			Fprintf(stderr, "\n ");
1071 		Fprintf(stderr, " %02x", *p++);
1072 	}
1073 	Fprintf(stderr, "\n");
1074 }
1075 
1076 void
1077 send_probe(int seq, int ttl, struct timeval *tp)
1078 {
1079 	int cc;
1080 	struct udpiphdr * ui;
1081 	int oldmtu = packlen;
1082 
1083 again:
1084 #ifdef BYTESWAP_IP_LEN
1085 	outip->ip_len = htons(packlen);
1086 #else
1087 	outip->ip_len = packlen;
1088 #endif
1089 	outip->ip_ttl = ttl;
1090 #ifndef __hpux
1091 	outip->ip_id = htons(ident + seq);
1092 #endif
1093 
1094 	/*
1095 	 * In most cases, the kernel will recalculate the ip checksum.
1096 	 * But we must do it anyway so that the udp checksum comes out
1097 	 * right.
1098 	 */
1099 	if (docksum) {
1100 		outip->ip_sum =
1101 		    in_cksum((u_int16_t *)outip, sizeof(*outip) + optlen);
1102 		if (outip->ip_sum == 0)
1103 			outip->ip_sum = 0xffff;
1104 	}
1105 
1106 	/* Payload */
1107 	outsetup.seq = seq;
1108 	outsetup.ttl = ttl;
1109 	outsetup.tv  = *tp;
1110 	memcpy(outmark,&outsetup,sizeof(outsetup));
1111 
1112 	if (useicmp)
1113 		outicmp->icmp_seq = htons(seq);
1114 	else
1115 		outudp->uh_dport = htons(port + seq);
1116 
1117 	/* (We can only do the checksum if we know our ip address) */
1118 	if (docksum) {
1119 		if (useicmp) {
1120 			outicmp->icmp_cksum = 0;
1121 			outicmp->icmp_cksum = in_cksum((u_int16_t *)outicmp,
1122 			    packlen - (sizeof(*outip) + optlen));
1123 			if (outicmp->icmp_cksum == 0)
1124 				outicmp->icmp_cksum = 0xffff;
1125 		} else {
1126 			u_int16_t sum;
1127 			struct {
1128 				struct in_addr src;
1129 				struct in_addr dst;
1130 				u_int8_t zero;
1131 				u_int8_t protocol;
1132 				u_int16_t len;
1133 			} __attribute__((__packed__)) phdr;
1134 
1135 			/* Checksum */
1136 			ui = (struct udpiphdr *)outip;
1137 			memset(&phdr, 0, sizeof(phdr));
1138 			phdr.src = ui->ui_src;
1139 			phdr.dst = ((struct sockaddr_in *)&whereto)->sin_addr;
1140 			phdr.protocol = ui->ui_pr;
1141 			phdr.len = outudp->uh_ulen;
1142 			outudp->uh_sum = 0;
1143 			sum = in_cksum2(0, (u_int16_t *)&phdr, sizeof(phdr));
1144 			sum = in_cksum2(sum, (u_int16_t *)outudp, ntohs(outudp->uh_ulen));
1145 			sum = ~sum;	/** XXXSCW: Quell SuperH Compiler Bug */
1146 			outudp->uh_sum = sum;
1147 			if (outudp->uh_sum == 0)
1148 				outudp->uh_sum = 0xffff;
1149 		}
1150 	}
1151 
1152 	/* XXX undocumented debugging hack */
1153 	if (verbose > 1) {
1154 		const u_int16_t *sp;
1155 		int nshorts, i;
1156 
1157 		sp = (u_int16_t *)outip;
1158 		nshorts = (u_int)packlen / sizeof(u_int16_t);
1159 		i = 0;
1160 		Printf("[ %d bytes", packlen);
1161 		while (--nshorts >= 0) {
1162 			if ((i++ % 8) == 0)
1163 				Printf("\n\t");
1164 			Printf(" %04x", ntohs(*sp++));
1165 		}
1166 		if (packlen & 1) {
1167 			if ((i % 8) == 0)
1168 				Printf("\n\t");
1169 			Printf(" %02x", *(u_char *)sp);
1170 		}
1171 		Printf("]\n");
1172 	}
1173 
1174 #if !defined(IP_HDRINCL) && defined(IP_TTL)
1175 	if (setsockopt(sndsock, IPPROTO_IP, IP_TTL,
1176 	    (char *)&ttl, sizeof(ttl)) < 0) {
1177 		Fprintf(stderr, "%s: setsockopt ttl %d: %s\n",
1178 		    prog, ttl, strerror(errno));
1179 		exit(1);
1180 	}
1181 #endif
1182 	if (dump)
1183 		dump_packet();
1184 
1185 #ifdef __hpux
1186 	cc = sendto(sndsock, useicmp ? (char *)outicmp : (char *)outudp,
1187 	    packlen - (sizeof(*outip) + optlen), 0, &whereto, sizeof(whereto));
1188 	if (cc > 0)
1189 		cc += sizeof(*outip) + optlen;
1190 #else
1191 	cc = sendto(sndsock, (char *)outip,
1192 	    packlen, 0, &whereto, sizeof(whereto));
1193 #endif
1194 	if (cc < 0 || cc != packlen)  {
1195 		if (cc < 0) {
1196 			/*
1197 			 * An errno of EMSGSIZE means we're writing too big a
1198 			 * datagram for the interface.  We have to just
1199 			 * decrease the packet size until we find one that
1200 			 * works.
1201 			 *
1202 			 * XXX maybe we should try to read the outgoing if's
1203 			 * mtu?
1204 			 */
1205 			if (errno == EMSGSIZE) {
1206 				packlen = *mtuptr++;
1207 				resize_packet();
1208 				goto again;
1209 			} else
1210 				Fprintf(stderr, "%s: sendto: %s\n",
1211 				    prog, strerror(errno));
1212 		}
1213 
1214 		Printf("%s: wrote %s %d chars, ret=%d\n",
1215 		    prog, hostname, packlen, cc);
1216 		(void)fflush(stdout);
1217 	}
1218 	if (oldmtu != packlen) {
1219 		Printf("message too big, "
1220 		    "trying new MTU = %d\n", packlen);
1221 		printed_ttl = 0;
1222 	}
1223 	if (!printed_ttl) {
1224 		Printf("%2d ", ttl);
1225 		printed_ttl = 1;
1226 	}
1227 
1228 }
1229 
1230 double
1231 deltaT(struct timeval *t1p, struct timeval *t2p)
1232 {
1233 	double dt;
1234 
1235 	dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
1236 	     (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
1237 	return (dt);
1238 }
1239 
1240 /*
1241  * Convert an ICMP "type" field to a printable string.
1242  */
1243 char *
1244 pr_type(u_char t)
1245 {
1246 	static char *ttab[] = {
1247 	"Echo Reply",	"ICMP 1",	"ICMP 2",	"Dest Unreachable",
1248 	"Source Quench", "Redirect",	"ICMP 6",	"ICMP 7",
1249 	"Echo",		"ICMP 9",	"ICMP 10",	"Time Exceeded",
1250 	"Param Problem", "Timestamp",	"Timestamp Reply", "Info Request",
1251 	"Info Reply"
1252 	};
1253 
1254 	if (t > 16)
1255 		return("OUT-OF-RANGE");
1256 
1257 	return(ttab[t]);
1258 }
1259 
1260 int
1261 packet_ok(u_char *buf, int cc, struct sockaddr_in *from, int seq)
1262 {
1263 	struct icmp *icp;
1264 	u_char type, code;
1265 	int hlen;
1266 #ifndef ARCHAIC
1267 	struct ip *ip;
1268 
1269 	ip = (struct ip *) buf;
1270 	hlen = ip->ip_hl << 2;
1271 	if (cc < hlen + ICMP_MINLEN) {
1272 		if (verbose)
1273 			Printf("packet too short (%d bytes) from %s\n", cc,
1274 				inet_ntoa(from->sin_addr));
1275 		return (0);
1276 	}
1277 	cc -= hlen;
1278 	icp = (struct icmp *)(buf + hlen);
1279 #else
1280 	icp = (struct icmp *)buf;
1281 #endif
1282 	type = icp->icmp_type;
1283 	code = icp->icmp_code;
1284 	if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
1285 	    type == ICMP_UNREACH || type == ICMP_ECHOREPLY) {
1286 		struct ip *hip;
1287 		struct udphdr *up;
1288 		struct icmp *hicmp;
1289 
1290 		hip = &icp->icmp_ip;
1291 		hlen = hip->ip_hl << 2;
1292 
1293 		nextmtu = ntohs(icp->icmp_nextmtu);	/* for frag_err() */
1294 
1295 		if (useicmp) {
1296 			/* XXX */
1297 			if (type == ICMP_ECHOREPLY &&
1298 			    icp->icmp_id == htons(ident) &&
1299 			    icp->icmp_seq == htons(seq))
1300 				return (-2);
1301 
1302 			hicmp = (struct icmp *)((u_char *)hip + hlen);
1303 			/* XXX 8 is a magic number */
1304 			if (hlen + 8 <= cc &&
1305 			    hip->ip_p == IPPROTO_ICMP &&
1306 			    hicmp->icmp_id == htons(ident) &&
1307 			    hicmp->icmp_seq == htons(seq))
1308 				return (type == ICMP_TIMXCEED ? -1 : code + 1);
1309 		} else {
1310 			up = (struct udphdr *)((u_char *)hip + hlen);
1311 			/* XXX 8 is a magic number */
1312 			if (hlen + 12 <= cc &&
1313 			    hip->ip_p == IPPROTO_UDP &&
1314 			    up->uh_sport == htons(ident) &&
1315 			    up->uh_dport == htons(port + seq))
1316 				return (type == ICMP_TIMXCEED ? -1 : code + 1);
1317 		}
1318 	}
1319 #ifndef ARCHAIC
1320 	if (verbose) {
1321 		int i;
1322 		u_int32_t *lp = (u_int32_t *)&icp->icmp_ip;
1323 
1324 		Printf("\n%d bytes from %s to ", cc, inet_ntoa(from->sin_addr));
1325 		Printf("%s: icmp type %d (%s) code %d\n",
1326 		    inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code);
1327 		for (i = 4; i < cc ; i += sizeof(*lp))
1328 			Printf("%2d: x%8.8x\n", i, *lp++);
1329 	}
1330 #endif
1331 	return(0);
1332 }
1333 
1334 void resize_packet(void)
1335 {
1336 	if (useicmp) {
1337 		outicmp->icmp_cksum = 0;
1338 		outicmp->icmp_cksum = in_cksum((u_int16_t *)outicmp,
1339 		    packlen - (sizeof(*outip) + optlen));
1340 		if (outicmp->icmp_cksum == 0)
1341 			outicmp->icmp_cksum = 0xffff;
1342 	} else {
1343 		outudp->uh_ulen =
1344 		    htons((u_int16_t)(packlen - (sizeof(*outip) + optlen)));
1345 	}
1346 }
1347 
1348 void
1349 print(u_char *buf, int cc, struct sockaddr_in *from)
1350 {
1351 	struct ip *ip;
1352 	int hlen;
1353 
1354 	ip = (struct ip *) buf;
1355 	hlen = ip->ip_hl << 2;
1356 	cc -= hlen;
1357 
1358 	if (as_path)
1359 		Printf(" [AS%d]", as_lookup(asn, &from->sin_addr));
1360 
1361 	if (nflag)
1362 		Printf(" %s", inet_ntoa(from->sin_addr));
1363 	else
1364 		Printf(" %s (%s)", inetname(from->sin_addr),
1365 		    inet_ntoa(from->sin_addr));
1366 
1367 	if (verbose)
1368 		Printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
1369 }
1370 
1371 u_int16_t
1372 in_cksum(u_int16_t *addr, int len)
1373 {
1374 
1375 	return ~in_cksum2(0, addr, len);
1376 }
1377 
1378 /*
1379  * Checksum routine for Internet Protocol family headers (C Version)
1380  */
1381 u_int16_t
1382 in_cksum2(u_int16_t seed, u_int16_t *addr, int len)
1383 {
1384 	int nleft = len;
1385 	u_int16_t *w = addr;
1386 	union {
1387 		u_int16_t w;
1388 		u_int8_t b[2];
1389 	} answer;
1390 	int32_t sum = seed;
1391 
1392 	/*
1393 	 *  Our algorithm is simple, using a 32 bit accumulator (sum),
1394 	 *  we add sequential 16 bit words to it, and at the end, fold
1395 	 *  back all the carry bits from the top 16 bits into the lower
1396 	 *  16 bits.
1397 	 */
1398 	while (nleft > 1)  {
1399 		sum += *w++;
1400 		nleft -= 2;
1401 	}
1402 
1403 	/* mop up an odd byte, if necessary */
1404 	if (nleft == 1) {
1405 		answer.b[0] = *(u_char *)w;
1406 		answer.b[1] = 0;
1407 		sum += answer.w;
1408 	}
1409 
1410 	/*
1411 	 * add back carry outs from top 16 bits to low 16 bits
1412 	 */
1413 	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
1414 	sum += (sum >> 16);			/* add carry */
1415 	answer.w = sum;				/* truncate to 16 bits */
1416 	return (answer.w);
1417 }
1418 
1419 /*
1420  * Subtract 2 timeval structs:  out = out - in.
1421  * Out is assumed to be >= in.
1422  */
1423 void
1424 tvsub(struct timeval *out, struct timeval *in)
1425 {
1426 
1427 	if ((out->tv_usec -= in->tv_usec) < 0)   {
1428 		--out->tv_sec;
1429 		out->tv_usec += 1000000;
1430 	}
1431 	out->tv_sec -= in->tv_sec;
1432 }
1433 
1434 /*
1435  * Construct an Internet address representation.
1436  * If the nflag has been supplied, give
1437  * numeric value, otherwise try for symbolic name.
1438  */
1439 char *
1440 inetname(struct in_addr in)
1441 {
1442 	char *cp;
1443 	struct hostent *hp;
1444 	static int first = 1;
1445 	static char domain[MAXHOSTNAMELEN + 1], line[MAXHOSTNAMELEN + 1];
1446 
1447 	if (first && !nflag) {
1448 		int rv;
1449 
1450 		first = 0;
1451 		rv = gethostname(domain, sizeof domain);
1452 		if (rv == 0 && (cp = strchr(domain, '.')) != NULL) {
1453 			(void)strlcpy(domain, cp + 1, sizeof(domain));
1454 		} else
1455 			domain[0] = '\0';
1456 	}
1457 	if (!nflag && in.s_addr != INADDR_ANY) {
1458 		hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET);
1459 		if (hp != NULL) {
1460 			if ((cp = strchr(hp->h_name, '.')) != NULL &&
1461 			    strcmp(cp + 1, domain) == 0)
1462 				*cp = '\0';
1463 			(void)strlcpy(line, hp->h_name, sizeof(line));
1464 			return (line);
1465 		}
1466 	}
1467 	return (inet_ntoa(in));
1468 }
1469 
1470 struct hostinfo *
1471 gethostinfo(char *hostname)
1472 {
1473 	int n;
1474 	struct hostent *hp;
1475 	struct hostinfo *hi;
1476 	char **p;
1477 	u_int32_t *ap;
1478 	struct in_addr addr;
1479 
1480 	hi = calloc(1, sizeof(*hi));
1481 	if (hi == NULL) {
1482 		Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
1483 		exit(1);
1484 	}
1485 	if (inet_aton(hostname, &addr) != 0) {
1486 		hi->name = strdup(hostname);
1487 		if (!hi->name) {
1488 			Fprintf(stderr, "%s: strdup %s\n", prog,
1489 			    strerror(errno));
1490 			exit(1);
1491 		}
1492 		hi->n = 1;
1493 		hi->addrs = calloc(1, sizeof(hi->addrs[0]));
1494 		if (hi->addrs == NULL) {
1495 			Fprintf(stderr, "%s: calloc %s\n",
1496 			    prog, strerror(errno));
1497 			exit(1);
1498 		}
1499 		hi->addrs[0] = addr.s_addr;
1500 		return (hi);
1501 	}
1502 
1503 	hp = gethostbyname(hostname);
1504 	if (hp == NULL) {
1505 		Fprintf(stderr, "%s: unknown host %s\n", prog, hostname);
1506 		exit(1);
1507 	}
1508 	if (hp->h_addrtype != AF_INET || hp->h_length != 4) {
1509 		Fprintf(stderr, "%s: bad host %s\n", prog, hostname);
1510 		exit(1);
1511 	}
1512 	hi->name = strdup(hp->h_name);
1513 	if (!hi->name) {
1514 		Fprintf(stderr, "%s: strdup %s\n", prog, strerror(errno));
1515 		exit(1);
1516 	}
1517 	for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p)
1518 		continue;
1519 	hi->n = n;
1520 	hi->addrs = calloc(n, sizeof(hi->addrs[0]));
1521 	if (hi->addrs == NULL) {
1522 		Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
1523 		exit(1);
1524 	}
1525 	for (ap = hi->addrs, p = hp->h_addr_list; *p != NULL; ++ap, ++p)
1526 		memcpy(ap, *p, sizeof(*ap));
1527 	return (hi);
1528 }
1529 
1530 void
1531 freehostinfo(struct hostinfo *hi)
1532 {
1533 	if (hi->name != NULL) {
1534 		free(hi->name);
1535 		hi->name = NULL;
1536 	}
1537 	free((char *)hi->addrs);
1538 	free((char *)hi);
1539 }
1540 
1541 void
1542 getaddr(u_int32_t *ap, char *hostname)
1543 {
1544 	struct hostinfo *hi;
1545 
1546 	hi = gethostinfo(hostname);
1547 	*ap = hi->addrs[0];
1548 	freehostinfo(hi);
1549 }
1550 
1551 void
1552 setsin(struct sockaddr_in *sin, u_int32_t addr)
1553 {
1554 
1555 	memset(sin, 0, sizeof(*sin));
1556 #ifdef HAVE_SOCKADDR_SA_LEN
1557 	sin->sin_len = sizeof(*sin);
1558 #endif
1559 	sin->sin_family = AF_INET;
1560 	sin->sin_addr.s_addr = addr;
1561 }
1562 
1563 /* String to value with optional min and max. Handles decimal and hex. */
1564 int
1565 str2val(const char *str, const char *what, int mi, int ma)
1566 {
1567 	const char *cp;
1568 	long val;
1569 	char *ep;
1570 
1571 	errno = 0;
1572 	ep = NULL;
1573 	if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
1574 		cp = str + 2;
1575 		val = strtol(cp, &ep, 16);
1576 	} else
1577 		val = strtol(str, &ep, 10);
1578 	if (errno || str[0] == '\0' || *ep != '\0') {
1579 		Fprintf(stderr, "%s: \"%s\" bad value for %s \n",
1580 		    prog, str, what);
1581 		exit(1);
1582 	}
1583 	if (val < mi && mi >= 0) {
1584 		if (mi == 0)
1585 			Fprintf(stderr, "%s: %s must be >= %d\n",
1586 			    prog, what, mi);
1587 		else
1588 			Fprintf(stderr, "%s: %s must be > %d\n",
1589 			    prog, what, mi - 1);
1590 		exit(1);
1591 	}
1592 	if (val > ma && ma >= 0) {
1593 		Fprintf(stderr, "%s: %s must be <= %d\n", prog, what, ma);
1594 		exit(1);
1595 	}
1596 	return ((int)val);
1597 }
1598 
1599 __dead void
1600 usage(void)
1601 {
1602 	extern char version[];
1603 
1604 	Fprintf(stderr, "Version %s\n", version);
1605 	Fprintf(stderr, "usage: %s [-adDFPIlnrvx] [-g gateway] [-i iface] \
1606 [-f first_ttl]\n\t[-m max_ttl] [-p port] [-q nqueries] [-s src_addr] [-t tos]\n\t\
1607 [-w waittime] [-A as_server] host [packetlen]\n",
1608 	    prog);
1609 	exit(1);
1610 }
1611 
1612 /*
1613  * Received ICMP unreachable (fragmentation required and DF set).
1614  * If the ICMP error was from a "new" router, it'll contain the next-hop
1615  * MTU that we should use next.  Otherwise we'll just keep going in the
1616  * mtus[] table, trying until we hit a valid MTU.
1617  */
1618 
1619 
1620 void
1621 frag_err()
1622 {
1623         int i;
1624 
1625         if (nextmtu > 0 && nextmtu < packlen) {
1626                 Printf("\nfragmentation required and DF set, "
1627 		     "next hop MTU = %d\n",
1628                         nextmtu);
1629                 packlen = nextmtu;
1630                 for (i = 0; mtus[i] > 0; i++) {
1631                         if (mtus[i] < nextmtu) {
1632                                 mtuptr = &mtus[i];    /* next one to try */
1633                                 break;
1634                         }
1635                 }
1636         } else {
1637                 Printf("\nfragmentation required and DF set. ");
1638 		if (nextmtu)
1639 			Printf("\nBogus next hop MTU = %d > last MTU = %d. ",
1640 			    nextmtu, packlen);
1641                 packlen = *mtuptr++;
1642 		Printf("Trying new MTU = %d\n", packlen);
1643         }
1644 	resize_packet();
1645 }
1646 
1647 int
1648 find_local_ip(struct sockaddr_in *from, struct sockaddr_in *to)
1649 {
1650 	int sock;
1651 	struct sockaddr_in help;
1652 	int help_len;
1653 
1654 	sock = socket(AF_INET, SOCK_DGRAM, 0);
1655 	if (sock < 0) return (0);
1656 
1657 	help.sin_family = AF_INET;
1658 	/*
1659 	 * At this point the port number doesn't matter
1660 	 * since it only has to be greater than zero.
1661 	 */
1662 	help.sin_port = 42;
1663 	help.sin_addr.s_addr = to->sin_addr.s_addr;
1664 	if (connect(sock, (struct sockaddr *)&help, sizeof(help)) < 0) {
1665 		(void)close(sock);
1666 		return (0);
1667 	}
1668 
1669 	help_len = sizeof(help);
1670 	if (getsockname(sock, (struct sockaddr *)&help, &help_len) < 0 ||
1671 	    help_len != sizeof(help) ||
1672 	    help.sin_addr.s_addr == INADDR_ANY) {
1673 		(void)close(sock);
1674 		return (0);
1675 	}
1676 
1677 	(void)close(sock);
1678 	setsin(from, help.sin_addr.s_addr);
1679 	return (1);
1680 }
1681 
1682 #ifdef IPSEC
1683 #ifdef IPSEC_POLICY_IPSEC
1684 int
1685 setpolicy(so, policy)
1686 	int so;
1687 	char *policy;
1688 {
1689 	char *buf;
1690 
1691 	buf = ipsec_set_policy(policy, strlen(policy));
1692 	if (buf == NULL) {
1693 		Fprintf(stderr, "%s: %s\n", prog, ipsec_strerror());
1694 		return -1;
1695 	}
1696 	(void)setsockopt(so, IPPROTO_IP, IP_IPSEC_POLICY,
1697 		buf, ipsec_get_policylen(buf));
1698 
1699 	free(buf);
1700 
1701 	return 0;
1702 }
1703 #endif
1704 #endif
1705 
1706