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