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