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