1/*
2 * Copyright (c) 2004-2013 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29/*
30 * Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000
31 *	The Regents of the University of California.  All rights reserved.
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that: (1) source code distributions
35 * retain the above copyright notice and this paragraph in its entirety, (2)
36 * distributions including binary code include the above copyright notice and
37 * this paragraph in its entirety in the documentation or other materials
38 * provided with the distribution, and (3) all advertising materials mentioning
39 * features or use of this software display the following acknowledgement:
40 * ``This product includes software developed by the University of California,
41 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
42 * the University nor the names of its contributors may be used to endorse
43 * or promote products derived from this software without specific prior
44 * written permission.
45 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
46 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
47 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
48 */
49
50#include <sys/cdefs.h>
51
52#ifndef lint
53__unused static const char copyright[] =
54    "@(#) Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000\n\
55The Regents of the University of California.  All rights reserved.\n";
56#endif
57
58/*
59 * traceroute host  - trace the route ip packets follow going to "host".
60 *
61 * Attempt to trace the route an ip packet would follow to some
62 * internet host.  We find out intermediate hops by launching probe
63 * packets with a small ttl (time to live) then listening for an
64 * icmp "time exceeded" reply from a gateway.  We start our probes
65 * with a ttl of one and increase by one until we get an icmp "port
66 * unreachable" (which means we got to "host") or hit a max (which
67 * defaults to net.inet.ip.ttl hops & can be changed with the -m flag).
68 * Three probes (change with -q flag) are sent at each ttl setting and
69 * a line is printed showing the ttl, address of the gateway and
70 * round trip time of each probe.  If the probe answers come from
71 * different gateways, the address of each responding system will
72 * be printed.  If there is no response within a 5 sec. timeout
73 * interval (changed with the -w flag), a "*" is printed for that
74 * probe.
75 *
76 * Probe packets are UDP format.  We don't want the destination
77 * host to process them so the destination port is set to an
78 * unlikely value (if some clod on the destination is using that
79 * value, it can be changed with the -p flag).
80 *
81 * A sample use might be:
82 *
83 *     [yak 71]% traceroute nis.nsf.net.
84 *     traceroute to nis.nsf.net (35.1.1.48), 64 hops max, 56 byte packet
85 *      1  helios.ee.lbl.gov (128.3.112.1)  19 ms  19 ms  0 ms
86 *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
87 *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
88 *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  39 ms
89 *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  39 ms  39 ms  39 ms
90 *      6  128.32.197.4 (128.32.197.4)  40 ms  59 ms  59 ms
91 *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  59 ms
92 *      8  129.140.70.13 (129.140.70.13)  99 ms  99 ms  80 ms
93 *      9  129.140.71.6 (129.140.71.6)  139 ms  239 ms  319 ms
94 *     10  129.140.81.7 (129.140.81.7)  220 ms  199 ms  199 ms
95 *     11  nic.merit.edu (35.1.1.48)  239 ms  239 ms  239 ms
96 *
97 * Note that lines 2 & 3 are the same.  This is due to a buggy
98 * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
99 * packets with a zero ttl.
100 *
101 * A more interesting example is:
102 *
103 *     [yak 72]% traceroute allspice.lcs.mit.edu.
104 *     traceroute to allspice.lcs.mit.edu (18.26.0.115), 64 hops max
105 *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
106 *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  19 ms  19 ms
107 *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  19 ms
108 *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  19 ms  39 ms  39 ms
109 *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  20 ms  39 ms  39 ms
110 *      6  128.32.197.4 (128.32.197.4)  59 ms  119 ms  39 ms
111 *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  39 ms
112 *      8  129.140.70.13 (129.140.70.13)  80 ms  79 ms  99 ms
113 *      9  129.140.71.6 (129.140.71.6)  139 ms  139 ms  159 ms
114 *     10  129.140.81.7 (129.140.81.7)  199 ms  180 ms  300 ms
115 *     11  129.140.72.17 (129.140.72.17)  300 ms  239 ms  239 ms
116 *     12  * * *
117 *     13  128.121.54.72 (128.121.54.72)  259 ms  499 ms  279 ms
118 *     14  * * *
119 *     15  * * *
120 *     16  * * *
121 *     17  * * *
122 *     18  ALLSPICE.LCS.MIT.EDU (18.26.0.115)  339 ms  279 ms  279 ms
123 *
124 * (I start to see why I'm having so much trouble with mail to
125 * MIT.)  Note that the gateways 12, 14, 15, 16 & 17 hops away
126 * either don't send ICMP "time exceeded" messages or send them
127 * with a ttl too small to reach us.  14 - 17 are running the
128 * MIT C Gateway code that doesn't send "time exceeded"s.  God
129 * only knows what's going on with 12.
130 *
131 * The silent gateway 12 in the above may be the result of a bug in
132 * the 4.[23]BSD network code (and its derivatives):  4.x (x <= 3)
133 * sends an unreachable message using whatever ttl remains in the
134 * original datagram.  Since, for gateways, the remaining ttl is
135 * zero, the icmp "time exceeded" is guaranteed to not make it back
136 * to us.  The behavior of this bug is slightly more interesting
137 * when it appears on the destination system:
138 *
139 *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
140 *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  39 ms
141 *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  39 ms  19 ms
142 *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  19 ms
143 *      5  ccn-nerif35.Berkeley.EDU (128.32.168.35)  39 ms  39 ms  39 ms
144 *      6  csgw.Berkeley.EDU (128.32.133.254)  39 ms  59 ms  39 ms
145 *      7  * * *
146 *      8  * * *
147 *      9  * * *
148 *     10  * * *
149 *     11  * * *
150 *     12  * * *
151 *     13  rip.Berkeley.EDU (128.32.131.22)  59 ms !  39 ms !  39 ms !
152 *
153 * Notice that there are 12 "gateways" (13 is the final
154 * destination) and exactly the last half of them are "missing".
155 * What's really happening is that rip (a Sun-3 running Sun OS3.5)
156 * is using the ttl from our arriving datagram as the ttl in its
157 * icmp reply.  So, the reply will time out on the return path
158 * (with no notice sent to anyone since icmp's aren't sent for
159 * icmp's) until we probe with a ttl that's at least twice the path
160 * length.  I.e., rip is really only 7 hops away.  A reply that
161 * returns with a ttl of 1 is a clue this problem exists.
162 * Traceroute prints a "!" after the time if the ttl is <= 1.
163 * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
164 * non-standard (HPUX) software, expect to see this problem
165 * frequently and/or take care picking the target host of your
166 * probes.
167 *
168 * Other possible annotations after the time are !H, !N, !P (got a host,
169 * network or protocol unreachable, respectively), !S or !F (source
170 * route failed or fragmentation needed -- neither of these should
171 * ever occur and the associated gateway is busted if you see one).  If
172 * almost all the probes result in some kind of unreachable, traceroute
173 * will give up and exit.
174 *
175 * Notes
176 * -----
177 * This program must be run by root or be setuid.  (I suggest that
178 * you *don't* make it setuid -- casual use could result in a lot
179 * of unnecessary traffic on our poor, congested nets.)
180 *
181 * This program requires a kernel mod that does not appear in any
182 * system available from Berkeley:  A raw ip socket using proto
183 * IPPROTO_RAW must interpret the data sent as an ip datagram (as
184 * opposed to data to be wrapped in a ip datagram).  See the README
185 * file that came with the source to this program for a description
186 * of the mods I made to /sys/netinet/raw_ip.c.  Your mileage may
187 * vary.  But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
188 * MODIFIED TO RUN THIS PROGRAM.
189 *
190 * The udp port usage may appear bizarre (well, ok, it is bizarre).
191 * The problem is that an icmp message only contains 8 bytes of
192 * data from the original datagram.  8 bytes is the size of a udp
193 * header so, if we want to associate replies with the original
194 * datagram, the necessary information must be encoded into the
195 * udp header (the ip id could be used but there's no way to
196 * interlock with the kernel's assignment of ip id's and, anyway,
197 * it would have taken a lot more kernel hacking to allow this
198 * code to set the ip id).  So, to allow two or more users to
199 * use traceroute simultaneously, we use this task's pid as the
200 * source port (the high bit is set to move the port number out
201 * of the "likely" range).  To keep track of which probe is being
202 * replied to (so times and/or hop counts don't get confused by a
203 * reply that was delayed in transit), we increment the destination
204 * port number before each probe.
205 *
206 * Don't use this as a coding example.  I was trying to find a
207 * routing problem and this code sort-of popped out after 48 hours
208 * without sleep.  I was amazed it ever compiled, much less ran.
209 *
210 * I stole the idea for this program from Steve Deering.  Since
211 * the first release, I've learned that had I attended the right
212 * IETF working group meetings, I also could have stolen it from Guy
213 * Almes or Matt Mathis.  I don't know (or care) who came up with
214 * the idea first.  I envy the originators' perspicacity and I'm
215 * glad they didn't keep the idea a secret.
216 *
217 * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
218 * enhancements to the original distribution.
219 *
220 * I've hacked up a round-trip-route version of this that works by
221 * sending a loose-source-routed udp datagram through the destination
222 * back to yourself.  Unfortunately, SO many gateways botch source
223 * routing, the thing is almost worthless.  Maybe one day...
224 *
225 *  -- Van Jacobson (van@ee.lbl.gov)
226 *     Tue Dec 20 03:50:13 PST 1988
227 */
228
229#include <sys/param.h>
230#include <sys/file.h>
231#include <sys/ioctl.h>
232#ifdef HAVE_SYS_SELECT_H
233#include <sys/select.h>
234#endif
235#include <sys/socket.h>
236#ifdef HAVE_SYS_SYSCTL_H
237#include <sys/sysctl.h>
238#endif
239#include <sys/time.h>
240
241#include <netinet/in_systm.h>
242#include <netinet/in.h>
243#include <netinet/ip.h>
244#include <netinet/ip_var.h>
245#include <netinet/ip_icmp.h>
246#include <netinet/udp.h>
247#include <netinet/udp_var.h>
248#include <netinet/tcp.h>
249#include <netinet/tcpip.h>
250
251#include <arpa/inet.h>
252
253#ifdef	IPSEC
254#include <net/route.h>
255#include <netinet6/ipsec.h>	/* XXX */
256#endif	/* IPSEC */
257
258#include <ctype.h>
259#include <err.h>
260#include <errno.h>
261#include <fcntl.h>
262#ifdef HAVE_MALLOC_H
263#include <malloc.h>
264#endif
265#include <memory.h>
266#include <netdb.h>
267#include <stdio.h>
268#include <stdlib.h>
269#include <string.h>
270#include <unistd.h>
271
272#include "gnuc.h"
273#ifdef HAVE_OS_PROTO_H
274#include "os-proto.h"
275#endif
276
277/* rfc1716 */
278#ifndef ICMP_UNREACH_FILTER_PROHIB
279#define ICMP_UNREACH_FILTER_PROHIB	13	/* admin prohibited filter */
280#endif
281#ifndef ICMP_UNREACH_HOST_PRECEDENCE
282#define ICMP_UNREACH_HOST_PRECEDENCE	14	/* host precedence violation */
283#endif
284#ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF
285#define ICMP_UNREACH_PRECEDENCE_CUTOFF	15	/* precedence cutoff */
286#endif
287
288#include "findsaddr.h"
289#include "ifaddrlist.h"
290#include "as.h"
291#include "traceroute.h"
292
293/* Maximum number of gateways (include room for one noop) */
294#define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t)))
295
296#ifndef MAXHOSTNAMELEN
297#define MAXHOSTNAMELEN	64
298#endif
299
300#define Fprintf (void)fprintf
301#define Printf (void)printf
302
303/* What a GRE packet header looks like */
304struct grehdr {
305	u_int16_t   flags;
306	u_int16_t   proto;
307	u_int16_t   length;	/* PPTP version of these fields */
308	u_int16_t   callId;
309};
310#ifndef IPPROTO_GRE
311#define IPPROTO_GRE	47
312#endif
313
314/* For GRE, we prepare what looks like a PPTP packet */
315#define GRE_PPTP_PROTO	0x880b
316
317/* Host name and address list */
318struct hostinfo {
319	char *name;
320	int n;
321	u_int32_t *addrs;
322};
323
324/* Data section of the probe packet */
325struct outdata {
326	u_char seq;		/* sequence number of this packet */
327	u_char ttl;		/* ttl packet left with */
328	struct timeval tv;	/* time packet left */
329};
330
331#ifndef HAVE_ICMP_NEXTMTU
332/* Path MTU Discovery (RFC1191) */
333struct my_pmtu {
334	u_short ipm_void;
335	u_short ipm_nextmtu;
336};
337#endif
338
339u_char	packet[512];		/* last inbound (icmp) packet */
340
341struct ip *outip;		/* last output ip packet */
342u_char *outp;		/* last output inner protocol packet */
343
344struct ip *hip = NULL;		/* Quoted IP header */
345int hiplen = 0;
346
347/* loose source route gateway list (including room for final destination) */
348u_int32_t gwlist[NGATEWAYS + 1];
349
350int s;				/* receive (icmp) socket file descriptor */
351int sndsock;			/* send (udp) socket file descriptor */
352
353struct sockaddr whereto;	/* Who to try to reach */
354struct sockaddr wherefrom;	/* Who we are */
355int packlen;			/* total length of packet */
356int protlen;			/* length of protocol part of packet */
357int minpacket;			/* min ip packet size */
358int maxpacket = 32 * 1024;	/* max ip packet size */
359int pmtu;			/* Path MTU Discovery (RFC1191) */
360u_int pausemsecs;
361
362char *prog;
363char *source;
364char *hostname;
365char *device;
366static const char devnull[] = "/dev/null";
367
368int nprobes = -1;
369int max_ttl;
370int first_ttl = 1;
371u_short ident;
372u_short port;			/* protocol specific base "port" */
373
374int options;			/* socket options */
375int verbose;
376int waittime = 5;		/* time to wait for response (in seconds) */
377int nflag;			/* print addresses numerically */
378int as_path;			/* print as numbers for each hop */
379char *as_server = NULL;
380void *asn;
381#ifdef CANT_HACK_IPCKSUM
382int doipcksum = 0;		/* don't calculate ip checksums by default */
383#else
384int doipcksum = 1;		/* calculate ip checksums by default */
385#endif
386int optlen;			/* length of ip options */
387int fixedPort = 0;		/* Use fixed destination port for TCP and UDP */
388int printdiff = 0;		/* Print the difference between sent and quoted */
389
390extern int optind;
391extern int opterr;
392extern char *optarg;
393
394/* Forwards */
395double	deltaT(struct timeval *, struct timeval *);
396void	freehostinfo(struct hostinfo *);
397void	getaddr(u_int32_t *, char *);
398struct	hostinfo *gethostinfo(char *);
399u_short	in_cksum(u_short *, int);
400char	*inetname(struct in_addr);
401int	main(int, char **);
402u_short p_cksum(struct ip *, u_short *, int);
403int	packet_ok(u_char *, int, struct sockaddr_in *, int);
404char	*pr_type(u_char);
405void	print(u_char *, int, struct sockaddr_in *);
406#ifdef	IPSEC
407int	setpolicy __P((int so, char *policy));
408#endif
409void	send_probe(int, int);
410struct outproto *setproto(char *);
411int	str2val(const char *, const char *, int, int);
412void	tvsub(struct timeval *, struct timeval *);
413void usage(void);
414int	wait_for_reply(int, struct sockaddr_in *, const struct timeval *);
415void pkt_compare(const u_char *, int, const u_char *, int);
416#ifndef HAVE_USLEEP
417int	usleep(u_int);
418#endif
419
420void	udp_prep(struct outdata *);
421int	udp_check(const u_char *, int);
422void	tcp_prep(struct outdata *);
423int	tcp_check(const u_char *, int);
424void	gre_prep(struct outdata *);
425int	gre_check(const u_char *, int);
426void	gen_prep(struct outdata *);
427int	gen_check(const u_char *, int);
428void	icmp_prep(struct outdata *);
429int	icmp_check(const u_char *, int);
430
431/* Descriptor structure for each outgoing protocol we support */
432struct outproto {
433	char	*name;		/* name of protocol */
434	const char *key;	/* An ascii key for the bytes of the header */
435	u_char	num;		/* IP protocol number */
436	u_short	hdrlen;		/* max size of protocol header */
437	u_short	port;		/* default base protocol-specific "port" */
438	void	(*prepare)(struct outdata *);
439				/* finish preparing an outgoing packet */
440	int	(*check)(const u_char *, int);
441				/* check an incoming packet */
442};
443
444/* List of supported protocols. The first one is the default. The last
445   one is the handler for generic protocols not explicitly listed. */
446struct	outproto protos[] = {
447	{
448		"udp",
449		"spt dpt len sum",
450		IPPROTO_UDP,
451		sizeof(struct udphdr),
452		32768 + 666,
453		udp_prep,
454		udp_check
455	},
456	{
457		"tcp",
458		"spt dpt seq     ack     xxflwin sum urp",
459		IPPROTO_TCP,
460		sizeof(struct tcphdr),
461		32768 + 666,
462		tcp_prep,
463		tcp_check
464	},
465	{
466		"gre",
467		"flg pro len clid",
468		IPPROTO_GRE,
469		sizeof(struct grehdr),
470		GRE_PPTP_PROTO,
471		gre_prep,
472		gre_check
473	},
474	{
475		"icmp",
476		"typ cod sum ",
477		IPPROTO_ICMP,
478		sizeof(struct icmp),
479		0,
480		icmp_prep,
481		icmp_check
482	},
483	{
484		NULL,
485		NULL,
486		0,
487		2 * sizeof(u_short),
488		0,
489		gen_prep,
490		gen_check
491	},
492};
493struct	outproto *proto = &protos[0];
494
495const char *ip_hdr_key = "vhtslen id  off tlprsum srcip   dstip   opts";
496
497int
498main(int argc, char **argv)
499{
500	register int op, code, n;
501	register char *cp;
502	register const char *err;
503	register u_int32_t *ap;
504	register struct sockaddr_in *from = (struct sockaddr_in *)&wherefrom;
505	register struct sockaddr_in *to = (struct sockaddr_in *)&whereto;
506	register struct hostinfo *hi;
507	int on = 1;
508	register struct protoent *pe;
509	register int ttl, probe, i;
510	register int seq = 0;
511	int tos = 0, settos = 0;
512	register int lsrr = 0;
513	register u_short off = 0;
514	struct ifaddrlist *al;
515	char errbuf[132];
516	int requestPort = -1;
517	int sump = 0;
518	int sockerrno = 0;
519
520	/* Insure the socket fds won't be 0, 1 or 2 */
521	if (open(devnull, O_RDONLY) < 0 ||
522	    open(devnull, O_RDONLY) < 0 ||
523	    open(devnull, O_RDONLY) < 0) {
524		Fprintf(stderr, "%s: open \"%s\": %s\n",
525		    prog, devnull, strerror(errno));
526		exit(1);
527	}
528	/*
529	 * Do the setuid-required stuff first, then lose priveleges ASAP.
530	 * Do error checking for these two calls where they appeared in
531	 * the original code.
532	 */
533	cp = "icmp";
534	pe = getprotobyname(cp);
535	if (pe) {
536		if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0)
537			sockerrno = errno;
538		else if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
539			sockerrno = errno;
540	}
541
542	setuid(getuid());
543
544#ifdef IPCTL_DEFTTL
545	{
546		int mib[4] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_DEFTTL };
547		size_t sz = sizeof(max_ttl);
548
549		if (sysctl(mib, 4, &max_ttl, &sz, NULL, 0) == -1) {
550			perror("sysctl(net.inet.ip.ttl)");
551			exit(1);
552		}
553	}
554#else
555	max_ttl = 30;
556#endif
557
558	if (argv[0] == NULL)
559		prog = "traceroute";
560	else if ((cp = strrchr(argv[0], '/')) != NULL)
561		prog = cp + 1;
562	else
563		prog = argv[0];
564
565	opterr = 0;
566	while ((op = getopt(argc, argv, "aA:edDFInrSvxf:g:i:M:m:P:p:q:s:t:w:z:")) != EOF)
567		switch (op) {
568		case 'a':
569			as_path = 1;
570			break;
571
572		case 'A':
573			as_path = 1;
574			as_server = optarg;
575			break;
576
577		case 'd':
578			options |= SO_DEBUG;
579			break;
580
581		case 'D':
582			printdiff = 1;
583			break;
584
585		case 'e':
586			fixedPort = 1;
587			break;
588
589		case 'f':
590		case 'M':	/* FreeBSD compat. */
591			first_ttl = str2val(optarg, "first ttl", 1, 255);
592			break;
593
594		case 'F':
595			off = IP_DF;
596			break;
597
598		case 'g':
599			if (lsrr >= NGATEWAYS) {
600				Fprintf(stderr,
601				    "%s: No more than %d gateways\n",
602				    prog, NGATEWAYS);
603				exit(1);
604			}
605			getaddr(gwlist + lsrr, optarg);
606			++lsrr;
607			break;
608
609		case 'i':
610			device = optarg;
611			break;
612
613		case 'I':
614			proto = setproto("icmp");
615			break;
616
617		case 'm':
618			max_ttl = str2val(optarg, "max ttl", 1, 255);
619			break;
620
621		case 'n':
622			++nflag;
623			break;
624
625		case 'P':
626			proto = setproto(optarg);
627			break;
628
629		case 'p':
630			requestPort = (u_short)str2val(optarg, "port",
631			    1, (1 << 16) - 1);
632			break;
633
634		case 'q':
635			nprobes = str2val(optarg, "nprobes", 1, -1);
636			break;
637
638		case 'r':
639			options |= SO_DONTROUTE;
640			break;
641
642		case 's':
643			/*
644			 * set the ip source address of the outbound
645			 * probe (e.g., on a multi-homed host).
646			 */
647			source = optarg;
648			break;
649
650		case 'S':
651			sump = 1;
652			break;
653
654		case 't':
655			tos = str2val(optarg, "tos", 0, 255);
656			++settos;
657			break;
658
659		case 'v':
660			++verbose;
661			break;
662
663		case 'x':
664			doipcksum = (doipcksum == 0);
665			break;
666
667		case 'w':
668			waittime = str2val(optarg, "wait time",
669			    1, 24 * 60 * 60);
670			break;
671
672		case 'z':
673			pausemsecs = str2val(optarg, "pause msecs",
674			    0, 60 * 60 * 1000);
675			break;
676
677		default:
678			usage();
679		}
680
681	/* Set requested port, if any, else default for this protocol */
682	port = (requestPort != -1) ? requestPort : proto->port;
683
684	if (nprobes == -1)
685		nprobes = printdiff ? 1 : 3;
686
687	if (first_ttl > max_ttl) {
688		Fprintf(stderr,
689		    "%s: first ttl (%d) may not be greater than max ttl (%d)\n",
690		    prog, first_ttl, max_ttl);
691		exit(1);
692	}
693
694	if (!doipcksum)
695		Fprintf(stderr, "%s: Warning: ip checksums disabled\n", prog);
696
697	if (lsrr > 0)
698		optlen = (lsrr + 1) * sizeof(gwlist[0]);
699	minpacket = sizeof(*outip) + proto->hdrlen + sizeof(struct outdata) + optlen;
700	packlen = minpacket;			/* minimum sized packet */
701
702	/* Process destination and optional packet size */
703	switch (argc - optind) {
704
705	case 2:
706		packlen = str2val(argv[optind + 1],
707		    "packet length", minpacket, maxpacket);
708		/* Fall through */
709
710	case 1:
711		hostname = argv[optind];
712		hi = gethostinfo(hostname);
713		setsin(to, hi->addrs[0]);
714		if (hi->n > 1)
715			Fprintf(stderr,
716		    "%s: Warning: %s has multiple addresses; using %s\n",
717				prog, hostname, inet_ntoa(to->sin_addr));
718		hostname = hi->name;
719		hi->name = NULL;
720		freehostinfo(hi);
721		break;
722
723	default:
724		usage();
725	}
726
727#ifdef HAVE_SETLINEBUF
728	setlinebuf (stdout);
729#else
730	setvbuf(stdout, NULL, _IOLBF, 0);
731#endif
732
733	protlen = packlen - sizeof(*outip) - optlen;
734
735	outip = (struct ip *)malloc((unsigned)packlen);
736	if (outip == NULL) {
737		Fprintf(stderr, "%s: malloc: %s\n", prog, strerror(errno));
738		exit(1);
739	}
740	memset((char *)outip, 0, packlen);
741
742	outip->ip_v = IPVERSION;
743	if (settos)
744		outip->ip_tos = tos;
745#ifdef BYTESWAP_IP_HDR
746	outip->ip_len = htons(packlen);
747	outip->ip_off = htons(off);
748#else
749	outip->ip_len = packlen;
750	outip->ip_off = off;
751#endif
752	outip->ip_p = proto->num;
753	outp = (u_char *)(outip + 1);
754#ifdef HAVE_RAW_OPTIONS
755	if (lsrr > 0) {
756		register u_char *optlist;
757
758		optlist = outp;
759		outp += optlen;
760
761		/* final hop */
762		gwlist[lsrr] = to->sin_addr.s_addr;
763
764		outip->ip_dst.s_addr = gwlist[0];
765
766		/* force 4 byte alignment */
767		optlist[0] = IPOPT_NOP;
768		/* loose source route option */
769		optlist[1] = IPOPT_LSRR;
770		i = lsrr * sizeof(gwlist[0]);
771		optlist[2] = i + 3;
772		/* Pointer to LSRR addresses */
773		optlist[3] = IPOPT_MINOFF;
774		memcpy(optlist + 4, gwlist + 1, i);
775	} else
776#endif
777		outip->ip_dst = to->sin_addr;
778
779	outip->ip_hl = (outp - (u_char *)outip) >> 2;
780	ident = (getpid() & 0xffff) | 0x8000;
781
782	if (pe == NULL) {
783		Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp);
784		exit(1);
785	}
786	if (s < 0) {
787		errno = sockerrno;
788		Fprintf(stderr, "%s: icmp socket: %s\n", prog, strerror(errno));
789		exit(1);
790	}
791	(void) setsockopt(s, SOL_SOCKET, SO_RECV_ANYIF, (char *)&on,
792	    sizeof(on));
793	if (options & SO_DEBUG)
794		(void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on,
795		    sizeof(on));
796	if (options & SO_DONTROUTE)
797		(void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
798		    sizeof(on));
799
800#if	defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
801	if (setpolicy(s, "in bypass") < 0)
802		errx(1, "%s", ipsec_strerror());
803
804	if (setpolicy(s, "out bypass") < 0)
805		errx(1, "%s", ipsec_strerror());
806#endif	/* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */
807
808	if (sndsock < 0) {
809		errno = sockerrno;
810		Fprintf(stderr, "%s: raw socket: %s\n", prog, strerror(errno));
811		exit(1);
812	}
813
814#if defined(IP_OPTIONS) && !defined(HAVE_RAW_OPTIONS)
815	if (lsrr > 0) {
816		u_char optlist[MAX_IPOPTLEN];
817
818		cp = "ip";
819		if ((pe = getprotobyname(cp)) == NULL) {
820			Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp);
821			exit(1);
822		}
823
824		/* final hop */
825		gwlist[lsrr] = to->sin_addr.s_addr;
826		++lsrr;
827
828		/* force 4 byte alignment */
829		optlist[0] = IPOPT_NOP;
830		/* loose source route option */
831		optlist[1] = IPOPT_LSRR;
832		i = lsrr * sizeof(gwlist[0]);
833		optlist[2] = i + 3;
834		/* Pointer to LSRR addresses */
835		optlist[3] = IPOPT_MINOFF;
836		memcpy(optlist + 4, gwlist, i);
837
838		if ((setsockopt(sndsock, pe->p_proto, IP_OPTIONS,
839		    (char *)optlist, i + sizeof(gwlist[0]))) < 0) {
840			Fprintf(stderr, "%s: IP_OPTIONS: %s\n",
841			    prog, strerror(errno));
842			exit(1);
843		    }
844	}
845#endif
846
847#ifdef SO_SNDBUF
848	if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&packlen,
849	    sizeof(packlen)) < 0) {
850		Fprintf(stderr, "%s: SO_SNDBUF: %s\n", prog, strerror(errno));
851		exit(1);
852	}
853#endif
854#ifdef IP_HDRINCL
855	if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on,
856	    sizeof(on)) < 0) {
857		Fprintf(stderr, "%s: IP_HDRINCL: %s\n", prog, strerror(errno));
858		exit(1);
859	}
860#else
861#ifdef IP_TOS
862	if (settos && setsockopt(sndsock, IPPROTO_IP, IP_TOS,
863	    (char *)&tos, sizeof(tos)) < 0) {
864		Fprintf(stderr, "%s: setsockopt tos %d: %s\n",
865		    prog, tos, strerror(errno));
866		exit(1);
867	}
868#endif
869#endif
870	if (options & SO_DEBUG)
871		(void)setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on,
872		    sizeof(on));
873	if (options & SO_DONTROUTE)
874		(void)setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
875		    sizeof(on));
876
877	/* Get the interface address list */
878	n = ifaddrlist(&al, errbuf, sizeof(errbuf));
879	if (n < 0) {
880		Fprintf(stderr, "%s: ifaddrlist: %s\n", prog, errbuf);
881		exit(1);
882	}
883	if (n == 0) {
884		Fprintf(stderr,
885		    "%s: Can't find any network interfaces\n", prog);
886		exit(1);
887	}
888
889	/* Look for a specific device */
890	if (device != NULL) {
891		for (i = n; i > 0; --i, ++al)
892			if (strcmp(device, al->device) == 0)
893				break;
894		if (i <= 0) {
895			Fprintf(stderr, "%s: Can't find interface %.32s\n",
896			    prog, device);
897			exit(1);
898		}
899	}
900
901	/* Determine our source address */
902	if (source == NULL) {
903		/*
904		 * If a device was specified, use the interface address.
905		 * Otherwise, try to determine our source address.
906		 */
907		if (device != NULL)
908			setsin(from, al->addr);
909		else if ((err = findsaddr(to, from)) != NULL) {
910			Fprintf(stderr, "%s: findsaddr: %s\n",
911			    prog, err);
912			exit(1);
913		}
914	} else {
915		hi = gethostinfo(source);
916		source = hi->name;
917		hi->name = NULL;
918		/*
919		 * If the device was specified make sure it
920		 * corresponds to the source address specified.
921		 * Otherwise, use the first address (and warn if
922		 * there are more than one).
923		 */
924		if (device != NULL) {
925			for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap)
926				if (*ap == al->addr)
927					break;
928			if (i <= 0) {
929				Fprintf(stderr,
930				    "%s: %s is not on interface %.32s\n",
931				    prog, source, device);
932				exit(1);
933			}
934			setsin(from, *ap);
935		} else {
936			setsin(from, hi->addrs[0]);
937			if (hi->n > 1)
938				Fprintf(stderr,
939			"%s: Warning: %s has multiple addresses; using %s\n",
940				    prog, source, inet_ntoa(from->sin_addr));
941		}
942		freehostinfo(hi);
943	}
944
945	outip->ip_src = from->sin_addr;
946
947	/* Check the source address (-s), if any, is valid */
948	if (bind(sndsock, (struct sockaddr *)from, sizeof(*from)) < 0) {
949		Fprintf(stderr, "%s: bind: %s\n",
950		    prog, strerror(errno));
951		exit (1);
952	}
953
954	if (as_path) {
955		asn = as_setup(as_server);
956		if (asn == NULL) {
957			Fprintf(stderr, "%s: as_setup failed, AS# lookups"
958			    " disabled\n", prog);
959			(void)fflush(stderr);
960			as_path = 0;
961		}
962	}
963
964#if	defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
965	if (setpolicy(sndsock, "in bypass") < 0)
966		errx(1, "%s", ipsec_strerror());
967
968	if (setpolicy(sndsock, "out bypass") < 0)
969		errx(1, "%s", ipsec_strerror());
970#endif	/* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */
971
972	Fprintf(stderr, "%s to %s (%s)",
973	    prog, hostname, inet_ntoa(to->sin_addr));
974	if (source)
975		Fprintf(stderr, " from %s", source);
976	Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, packlen);
977	(void)fflush(stderr);
978
979	for (ttl = first_ttl; ttl <= max_ttl; ++ttl) {
980		u_int32_t lastaddr = 0;
981		int gotlastaddr = 0;
982		int got_there = 0;
983		int unreachable = 0;
984		int sentfirst = 0;
985		int loss;
986
987		Printf("%2d ", ttl);
988		for (probe = 0, loss = 0; probe < nprobes; ++probe) {
989			register int cc;
990			struct timeval t1, t2;
991			struct timezone tz;
992			register struct ip *ip;
993			struct outdata outdata;
994
995			if (sentfirst && pausemsecs > 0)
996				usleep(pausemsecs * 1000);
997			/* Prepare outgoing data */
998			outdata.seq = ++seq;
999			outdata.ttl = ttl;
1000
1001			/* Avoid alignment problems by copying bytewise: */
1002			(void)gettimeofday(&t1, &tz);
1003			memcpy(&outdata.tv, &t1, sizeof(outdata.tv));
1004
1005			/* Finalize and send packet */
1006			(*proto->prepare)(&outdata);
1007			send_probe(seq, ttl);
1008			++sentfirst;
1009
1010			/* Wait for a reply */
1011			while ((cc = wait_for_reply(s, from, &t1)) != 0) {
1012				double T;
1013				int precis;
1014
1015				(void)gettimeofday(&t2, &tz);
1016				i = packet_ok(packet, cc, from, seq);
1017				/* Skip short packet */
1018				if (i == 0)
1019					continue;
1020				if (!gotlastaddr ||
1021				    from->sin_addr.s_addr != lastaddr) {
1022					if (gotlastaddr) printf("\n   ");
1023					print(packet, cc, from);
1024					lastaddr = from->sin_addr.s_addr;
1025					++gotlastaddr;
1026				}
1027				T = deltaT(&t1, &t2);
1028#ifdef SANE_PRECISION
1029				if (T >= 1000.0)
1030					precis = 0;
1031				else if (T >= 100.0)
1032					precis = 1;
1033				else if (T >= 10.0)
1034					precis = 2;
1035				else
1036#endif
1037					precis = 3;
1038				Printf("  %.*f ms", precis, T);
1039				if (printdiff) {
1040					Printf("\n");
1041					Printf("%*.*s%s\n",
1042					    -(outip->ip_hl << 3),
1043					    outip->ip_hl << 3,
1044					    ip_hdr_key,
1045					    proto->key);
1046					pkt_compare((void *)outip, packlen,
1047					    (void *)hip, hiplen);
1048				}
1049				if (i == -2) {
1050#ifndef ARCHAIC
1051					ip = (struct ip *)packet;
1052					if (ip->ip_ttl <= 1)
1053						Printf(" !");
1054#endif
1055					++got_there;
1056					break;
1057				}
1058				/* time exceeded in transit */
1059				if (i == -1)
1060					break;
1061				code = i - 1;
1062				switch (code) {
1063
1064				case ICMP_UNREACH_PORT:
1065#ifndef ARCHAIC
1066					ip = (struct ip *)packet;
1067					if (ip->ip_ttl <= 1)
1068						Printf(" !");
1069#endif
1070					++got_there;
1071					break;
1072
1073				case ICMP_UNREACH_NET:
1074					++unreachable;
1075					Printf(" !N");
1076					break;
1077
1078				case ICMP_UNREACH_HOST:
1079					++unreachable;
1080					Printf(" !H");
1081					break;
1082
1083				case ICMP_UNREACH_PROTOCOL:
1084					++got_there;
1085					Printf(" !P");
1086					break;
1087
1088				case ICMP_UNREACH_NEEDFRAG:
1089					++unreachable;
1090					Printf(" !F-%d", pmtu);
1091					break;
1092
1093				case ICMP_UNREACH_SRCFAIL:
1094					++unreachable;
1095					Printf(" !S");
1096					break;
1097
1098				case ICMP_UNREACH_NET_UNKNOWN:
1099					++unreachable;
1100					Printf(" !U");
1101					break;
1102
1103				case ICMP_UNREACH_HOST_UNKNOWN:
1104					++unreachable;
1105					Printf(" !W");
1106					break;
1107
1108				case ICMP_UNREACH_ISOLATED:
1109					++unreachable;
1110					Printf(" !I");
1111					break;
1112
1113				case ICMP_UNREACH_NET_PROHIB:
1114					++unreachable;
1115					Printf(" !A");
1116					break;
1117
1118				case ICMP_UNREACH_HOST_PROHIB:
1119					++unreachable;
1120					Printf(" !Z");
1121					break;
1122
1123				case ICMP_UNREACH_TOSNET:
1124					++unreachable;
1125					Printf(" !Q");
1126					break;
1127
1128				case ICMP_UNREACH_TOSHOST:
1129					++unreachable;
1130					Printf(" !T");
1131					break;
1132
1133				case ICMP_UNREACH_FILTER_PROHIB:
1134					++unreachable;
1135					Printf(" !X");
1136					break;
1137
1138				case ICMP_UNREACH_HOST_PRECEDENCE:
1139					++unreachable;
1140					Printf(" !V");
1141					break;
1142
1143				case ICMP_UNREACH_PRECEDENCE_CUTOFF:
1144					++unreachable;
1145					Printf(" !C");
1146					break;
1147
1148				default:
1149					++unreachable;
1150					Printf(" !<%d>", code);
1151					break;
1152				}
1153				break;
1154			}
1155			if (cc == 0) {
1156				loss++;
1157				Printf(" *");
1158			}
1159			(void)fflush(stdout);
1160		}
1161		if (sump) {
1162			Printf(" (%d%% loss)", (loss * 100) / nprobes);
1163		}
1164		putchar('\n');
1165		if (got_there ||
1166		    (unreachable > 0 && unreachable >= nprobes - 1))
1167			break;
1168	}
1169	if (as_path)
1170		as_shutdown(asn);
1171	exit(0);
1172}
1173
1174int
1175wait_for_reply(register int sock, register struct sockaddr_in *fromp,
1176    register const struct timeval *tp)
1177{
1178	fd_set *fdsp;
1179	size_t nfds;
1180	struct timeval now, wait;
1181	struct timezone tz;
1182	register int cc = 0;
1183	register int error;
1184	socklen_t fromlen = sizeof(*fromp);
1185
1186	nfds = howmany(sock + 1, NFDBITS);
1187	if ((fdsp = malloc(nfds * sizeof(fd_mask))) == NULL)
1188		err(1, "malloc");
1189	memset(fdsp, 0, nfds * sizeof(fd_mask));
1190	FD_SET(sock, fdsp);
1191
1192	wait.tv_sec = tp->tv_sec + waittime;
1193	wait.tv_usec = tp->tv_usec;
1194	(void)gettimeofday(&now, &tz);
1195	tvsub(&wait, &now);
1196	if (wait.tv_sec < 0) {
1197		wait.tv_sec = 0;
1198		wait.tv_usec = 1;
1199	}
1200
1201	error = select(sock + 1, fdsp, NULL, NULL, &wait);
1202	if (error == -1 && errno == EINVAL) {
1203		Fprintf(stderr, "%s: botched select() args\n", prog);
1204		exit(1);
1205	}
1206	if (error > 0)
1207		cc = recvfrom(sock, (char *)packet, sizeof(packet), 0,
1208			    (struct sockaddr *)fromp, &fromlen);
1209
1210	free(fdsp);
1211	return(cc);
1212}
1213
1214void
1215send_probe(int seq, int ttl)
1216{
1217	register int cc;
1218
1219	outip->ip_ttl = ttl;
1220	outip->ip_id = htons(ident + seq);
1221
1222	/* XXX undocumented debugging hack */
1223	if (verbose > 1) {
1224		register const u_short *sp;
1225		register int nshorts, i;
1226
1227		sp = (u_short *)outip;
1228		nshorts = (u_int)packlen / sizeof(u_short);
1229		i = 0;
1230		Printf("[ %d bytes", packlen);
1231		while (--nshorts >= 0) {
1232			if ((i++ % 8) == 0)
1233				Printf("\n\t");
1234			Printf(" %04x", ntohs(*sp++));
1235		}
1236		if (packlen & 1) {
1237			if ((i % 8) == 0)
1238				Printf("\n\t");
1239			Printf(" %02x", *(u_char *)sp);
1240		}
1241		Printf("]\n");
1242	}
1243
1244#if !defined(IP_HDRINCL) && defined(IP_TTL)
1245	if (setsockopt(sndsock, IPPROTO_IP, IP_TTL,
1246	    (char *)&ttl, sizeof(ttl)) < 0) {
1247		Fprintf(stderr, "%s: setsockopt ttl %d: %s\n",
1248		    prog, ttl, strerror(errno));
1249		exit(1);
1250	}
1251#endif
1252
1253	cc = sendto(sndsock, (char *)outip,
1254	    packlen, 0, &whereto, sizeof(whereto));
1255	if (cc < 0 || cc != packlen)  {
1256		if (cc < 0)
1257			Fprintf(stderr, "%s: sendto: %s\n",
1258			    prog, strerror(errno));
1259		Printf("%s: wrote %s %d chars, ret=%d\n",
1260		    prog, hostname, packlen, cc);
1261		(void)fflush(stdout);
1262	}
1263}
1264
1265#if	defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
1266int
1267setpolicy(so, policy)
1268	int so;
1269	char *policy;
1270{
1271	char *buf;
1272
1273	buf = ipsec_set_policy(policy, strlen(policy));
1274	if (buf == NULL) {
1275		warnx("%s", ipsec_strerror());
1276		return -1;
1277	}
1278	(void)setsockopt(so, IPPROTO_IP, IP_IPSEC_POLICY,
1279		buf, ipsec_get_policylen(buf));
1280
1281	free(buf);
1282
1283	return 0;
1284}
1285#endif
1286
1287double
1288deltaT(struct timeval *t1p, struct timeval *t2p)
1289{
1290	register double dt;
1291
1292	dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
1293	     (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
1294	return (dt);
1295}
1296
1297/*
1298 * Convert an ICMP "type" field to a printable string.
1299 */
1300char *
1301pr_type(register u_char t)
1302{
1303	static char *ttab[] = {
1304	"Echo Reply",	"ICMP 1",	"ICMP 2",	"Dest Unreachable",
1305	"Source Quench", "Redirect",	"ICMP 6",	"ICMP 7",
1306	"Echo",		"ICMP 9",	"ICMP 10",	"Time Exceeded",
1307	"Param Problem", "Timestamp",	"Timestamp Reply", "Info Request",
1308	"Info Reply"
1309	};
1310
1311	if (t > 16)
1312		return("OUT-OF-RANGE");
1313
1314	return(ttab[t]);
1315}
1316
1317int
1318packet_ok(register u_char *buf, int cc, register struct sockaddr_in *from,
1319    register int seq)
1320{
1321	register struct icmp *icp;
1322	register u_char type, code;
1323	register int hlen;
1324#ifndef ARCHAIC
1325	register struct ip *ip;
1326
1327	ip = (struct ip *) buf;
1328	hlen = ip->ip_hl << 2;
1329	if (cc < hlen + ICMP_MINLEN) {
1330		if (verbose)
1331			Printf("packet too short (%d bytes) from %s\n", cc,
1332				inet_ntoa(from->sin_addr));
1333		return (0);
1334	}
1335	cc -= hlen;
1336	icp = (struct icmp *)(buf + hlen);
1337#else
1338	icp = (struct icmp *)buf;
1339#endif
1340	type = icp->icmp_type;
1341	code = icp->icmp_code;
1342	/* Path MTU Discovery (RFC1191) */
1343	if (code != ICMP_UNREACH_NEEDFRAG)
1344		pmtu = 0;
1345	else {
1346#ifdef HAVE_ICMP_NEXTMTU
1347		pmtu = ntohs(icp->icmp_nextmtu);
1348#else
1349		pmtu = ntohs(((struct my_pmtu *)&icp->icmp_void)->ipm_nextmtu);
1350#endif
1351	}
1352	if (type == ICMP_ECHOREPLY
1353	    && proto->num == IPPROTO_ICMP
1354	    && (*proto->check)((u_char *)icp, (u_char)seq))
1355		return -2;
1356	if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
1357	    type == ICMP_UNREACH) {
1358		u_char *inner;
1359
1360		hip = &icp->icmp_ip;
1361		hiplen = ((u_char *)icp + cc) - (u_char *)hip;
1362		hlen = hip->ip_hl << 2;
1363		inner = (u_char *)((u_char *)hip + hlen);
1364		if (hlen + 12 <= cc
1365		    && hip->ip_p == proto->num
1366		    && (*proto->check)(inner, (u_char)seq))
1367			return (type == ICMP_TIMXCEED ? -1 : code + 1);
1368	}
1369#ifndef ARCHAIC
1370	if (verbose) {
1371		register int i;
1372		u_int32_t *lp = (u_int32_t *)&icp->icmp_ip;
1373
1374		Printf("\n%d bytes from %s to ", cc, inet_ntoa(from->sin_addr));
1375		Printf("%s: icmp type %d (%s) code %d\n",
1376		    inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code);
1377		for (i = 4; i < cc ; i += sizeof(*lp))
1378			Printf("%2d: x%8.8x\n", i, *lp++);
1379	}
1380#endif
1381	return(0);
1382}
1383
1384void
1385icmp_prep(struct outdata *outdata)
1386{
1387	struct icmp *const icmpheader = (struct icmp *) outp;
1388
1389	icmpheader->icmp_type = ICMP_ECHO;
1390	icmpheader->icmp_id = htons(ident);
1391	icmpheader->icmp_seq = htons(outdata->seq);
1392	icmpheader->icmp_cksum = 0;
1393	icmpheader->icmp_cksum = in_cksum((u_short *)icmpheader, protlen);
1394	if (icmpheader->icmp_cksum == 0)
1395		icmpheader->icmp_cksum = 0xffff;
1396}
1397
1398int
1399icmp_check(const u_char *data, int seq)
1400{
1401	struct icmp *const icmpheader = (struct icmp *) data;
1402
1403	return (icmpheader->icmp_id == htons(ident)
1404	    && icmpheader->icmp_seq == htons(seq));
1405}
1406
1407void
1408udp_prep(struct outdata *outdata)
1409{
1410	struct udphdr *const outudp = (struct udphdr *) outp;
1411
1412	outudp->uh_sport = htons(ident + (fixedPort ? outdata->seq : 0));
1413	outudp->uh_dport = htons(port + (fixedPort ? 0 : outdata->seq));
1414	outudp->uh_ulen = htons((u_short)protlen);
1415	outudp->uh_sum = 0;
1416	if (doipcksum) {
1417	    u_short sum = p_cksum(outip, (u_short*)outudp, protlen);
1418	    outudp->uh_sum = (sum) ? sum : 0xffff;
1419	}
1420
1421	return;
1422}
1423
1424int
1425udp_check(const u_char *data, int seq)
1426{
1427	struct udphdr *const udp = (struct udphdr *) data;
1428
1429	return (ntohs(udp->uh_sport) == ident + (fixedPort ? seq : 0) &&
1430	    ntohs(udp->uh_dport) == port + (fixedPort ? 0 : seq));
1431}
1432
1433void
1434tcp_prep(struct outdata *outdata)
1435{
1436	struct tcphdr *const tcp = (struct tcphdr *) outp;
1437
1438	tcp->th_sport = htons(ident);
1439	tcp->th_dport = htons(port + (fixedPort ? 0 : outdata->seq));
1440	tcp->th_seq = (tcp->th_sport << 16) | (tcp->th_dport +
1441	    (fixedPort ? outdata->seq : 0));
1442	tcp->th_ack = 0;
1443	tcp->th_off = 5;
1444	tcp->th_flags = TH_SYN;
1445	tcp->th_sum = 0;
1446
1447	if (doipcksum) {
1448	    u_short sum = p_cksum(outip, (u_short*)tcp, protlen);
1449	    tcp->th_sum = (sum) ? sum : 0xffff;
1450	}
1451}
1452
1453int
1454tcp_check(const u_char *data, int seq)
1455{
1456	struct tcphdr *const tcp = (struct tcphdr *) data;
1457
1458	return (ntohs(tcp->th_sport) == ident
1459	    && ntohs(tcp->th_dport) == port + (fixedPort ? 0 : seq))
1460	    && tcp->th_seq == ((ident << 16) | (port + seq));
1461}
1462
1463void
1464gre_prep(struct outdata *outdata)
1465{
1466	struct grehdr *const gre = (struct grehdr *) outp;
1467
1468	gre->flags = htons(0x2001);
1469	gre->proto = htons(port);
1470	gre->length = 0;
1471	gre->callId = htons(ident + outdata->seq);
1472}
1473
1474int
1475gre_check(const u_char *data, int seq)
1476{
1477	struct grehdr *const gre = (struct grehdr *) data;
1478
1479	return(ntohs(gre->proto) == port
1480	    && ntohs(gre->callId) == ident + seq);
1481}
1482
1483void
1484gen_prep(struct outdata *outdata)
1485{
1486	u_int16_t *const ptr = (u_int16_t *) outp;
1487
1488	ptr[0] = htons(ident);
1489	ptr[1] = htons(port + outdata->seq);
1490}
1491
1492int
1493gen_check(const u_char *data, int seq)
1494{
1495	u_int16_t *const ptr = (u_int16_t *) data;
1496
1497	return(ntohs(ptr[0]) == ident
1498	    && ntohs(ptr[1]) == port + seq);
1499}
1500
1501void
1502print(register u_char *buf, register int cc, register struct sockaddr_in *from)
1503{
1504	register struct ip *ip;
1505	register int hlen;
1506
1507	ip = (struct ip *) buf;
1508	hlen = ip->ip_hl << 2;
1509	cc -= hlen;
1510
1511	if (as_path)
1512		Printf(" [AS%d]", as_lookup(asn, &from->sin_addr));
1513
1514	if (nflag)
1515		Printf(" %s", inet_ntoa(from->sin_addr));
1516	else
1517		Printf(" %s (%s)", inetname(from->sin_addr),
1518		    inet_ntoa(from->sin_addr));
1519
1520	if (verbose)
1521		Printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
1522}
1523
1524/*
1525 * Checksum routine for UDP and TCP headers.
1526 */
1527u_short
1528p_cksum(struct ip *ip, u_short *data, int len)
1529{
1530	static struct ipovly ipo;
1531	u_short sumh, sumd;
1532	u_int32_t sumt;
1533
1534	ipo.ih_pr = ip->ip_p;
1535	ipo.ih_len = htons(len);
1536	ipo.ih_src = ip->ip_src;
1537	ipo.ih_dst = ip->ip_dst;
1538
1539	sumh = in_cksum((u_short*)&ipo, sizeof(ipo)); /* pseudo ip hdr cksum */
1540	sumd = in_cksum((u_short*)data, len);	      /* payload data cksum */
1541	sumt = (sumh << 16) | (sumd);
1542
1543	return ~in_cksum((u_short*)&sumt, sizeof(sumt));
1544}
1545
1546/*
1547 * Checksum routine for Internet Protocol family headers (C Version)
1548 */
1549u_short
1550in_cksum(register u_short *addr, register int len)
1551{
1552	register int nleft = len;
1553	register u_short *w = addr;
1554	register u_short answer;
1555	register int sum = 0;
1556
1557	/*
1558	 *  Our algorithm is simple, using a 32 bit accumulator (sum),
1559	 *  we add sequential 16 bit words to it, and at the end, fold
1560	 *  back all the carry bits from the top 16 bits into the lower
1561	 *  16 bits.
1562	 */
1563	while (nleft > 1)  {
1564		sum += *w++;
1565		nleft -= 2;
1566	}
1567
1568	/* mop up an odd byte, if necessary */
1569	if (nleft == 1)
1570		sum += *(u_char *)w;
1571
1572	/*
1573	 * add back carry outs from top 16 bits to low 16 bits
1574	 */
1575	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
1576	sum += (sum >> 16);			/* add carry */
1577	answer = ~sum;				/* truncate to 16 bits */
1578	return (answer);
1579}
1580
1581/*
1582 * Subtract 2 timeval structs:  out = out - in.
1583 * Out is assumed to be within about LONG_MAX seconds of in.
1584 */
1585void
1586tvsub(register struct timeval *out, register struct timeval *in)
1587{
1588
1589	if ((out->tv_usec -= in->tv_usec) < 0)   {
1590		--out->tv_sec;
1591		out->tv_usec += 1000000;
1592	}
1593	out->tv_sec -= in->tv_sec;
1594}
1595
1596/*
1597 * Construct an Internet address representation.
1598 * If the nflag has been supplied, give
1599 * numeric value, otherwise try for symbolic name.
1600 */
1601char *
1602inetname(struct in_addr in)
1603{
1604	register char *cp;
1605	register struct hostent *hp;
1606	static int first = 1;
1607	static char domain[MAXHOSTNAMELEN + 1], line[MAXHOSTNAMELEN + 1];
1608
1609	if (first && !nflag) {
1610		first = 0;
1611		if (gethostname(domain, sizeof(domain) - 1) < 0)
1612			domain[0] = '\0';
1613		else {
1614			cp = strchr(domain, '.');
1615			if (cp == NULL) {
1616				hp = gethostbyname(domain);
1617				if (hp != NULL)
1618					cp = strchr(hp->h_name, '.');
1619			}
1620			if (cp == NULL)
1621				domain[0] = '\0';
1622			else {
1623				++cp;
1624				(void)strncpy(domain, cp, sizeof(domain) - 1);
1625				domain[sizeof(domain) - 1] = '\0';
1626			}
1627		}
1628	}
1629	if (!nflag && in.s_addr != INADDR_ANY) {
1630		hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET);
1631		if (hp != NULL) {
1632			if ((cp = strchr(hp->h_name, '.')) != NULL &&
1633			    strcmp(cp + 1, domain) == 0)
1634				*cp = '\0';
1635			(void)strncpy(line, hp->h_name, sizeof(line) - 1);
1636			line[sizeof(line) - 1] = '\0';
1637			return (line);
1638		}
1639	}
1640	return (inet_ntoa(in));
1641}
1642
1643struct hostinfo *
1644gethostinfo(register char *hostname)
1645{
1646	register int n;
1647	register struct hostent *hp;
1648	register struct hostinfo *hi;
1649	register char **p;
1650	register u_int32_t addr, *ap;
1651
1652	if (strlen(hostname) > 64) {
1653		Fprintf(stderr, "%s: hostname \"%.32s...\" is too long\n",
1654		    prog, hostname);
1655		exit(1);
1656	}
1657	hi = calloc(1, sizeof(*hi));
1658	if (hi == NULL) {
1659		Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
1660		exit(1);
1661	}
1662	addr = inet_addr(hostname);
1663	if ((int32_t)addr != -1) {
1664		hi->name = strdup(hostname);
1665		hi->n = 1;
1666		hi->addrs = calloc(1, sizeof(hi->addrs[0]));
1667		if (hi->addrs == NULL) {
1668			Fprintf(stderr, "%s: calloc %s\n",
1669			    prog, strerror(errno));
1670			exit(1);
1671		}
1672		hi->addrs[0] = addr;
1673		return (hi);
1674	}
1675
1676	hp = gethostbyname(hostname);
1677	if (hp == NULL) {
1678		Fprintf(stderr, "%s: unknown host %s\n", prog, hostname);
1679		exit(1);
1680	}
1681	if (hp->h_addrtype != AF_INET || hp->h_length != 4) {
1682		Fprintf(stderr, "%s: bad host %s\n", prog, hostname);
1683		exit(1);
1684	}
1685	hi->name = strdup(hp->h_name);
1686	for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p)
1687		continue;
1688	hi->n = n;
1689	hi->addrs = calloc(n, sizeof(hi->addrs[0]));
1690	if (hi->addrs == NULL) {
1691		Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
1692		exit(1);
1693	}
1694	for (ap = hi->addrs, p = hp->h_addr_list; *p != NULL; ++ap, ++p)
1695		memcpy(ap, *p, sizeof(*ap));
1696	return (hi);
1697}
1698
1699void
1700freehostinfo(register struct hostinfo *hi)
1701{
1702	if (hi->name != NULL) {
1703		free(hi->name);
1704		hi->name = NULL;
1705	}
1706	free((char *)hi->addrs);
1707	free((char *)hi);
1708}
1709
1710void
1711getaddr(register u_int32_t *ap, register char *hostname)
1712{
1713	register struct hostinfo *hi;
1714
1715	hi = gethostinfo(hostname);
1716	*ap = hi->addrs[0];
1717	freehostinfo(hi);
1718}
1719
1720void
1721setsin(register struct sockaddr_in *sin, register u_int32_t addr)
1722{
1723
1724	memset(sin, 0, sizeof(*sin));
1725#ifdef HAVE_SOCKADDR_SA_LEN
1726	sin->sin_len = sizeof(*sin);
1727#endif
1728	sin->sin_family = AF_INET;
1729	sin->sin_addr.s_addr = addr;
1730}
1731
1732/* String to value with optional min and max. Handles decimal and hex. */
1733int
1734str2val(register const char *str, register const char *what,
1735    register int mi, register int ma)
1736{
1737	register const char *cp;
1738	register int val;
1739	char *ep;
1740
1741	if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
1742		cp = str + 2;
1743		val = (int)strtol(cp, &ep, 16);
1744	} else
1745		val = (int)strtol(str, &ep, 10);
1746	if (*ep != '\0') {
1747		Fprintf(stderr, "%s: \"%s\" bad value for %s \n",
1748		    prog, str, what);
1749		exit(1);
1750	}
1751	if (val < mi && mi >= 0) {
1752		if (mi == 0)
1753			Fprintf(stderr, "%s: %s must be >= %d\n",
1754			    prog, what, mi);
1755		else
1756			Fprintf(stderr, "%s: %s must be > %d\n",
1757			    prog, what, mi - 1);
1758		exit(1);
1759	}
1760	if (val > ma && ma >= 0) {
1761		Fprintf(stderr, "%s: %s must be <= %d\n", prog, what, ma);
1762		exit(1);
1763	}
1764	return (val);
1765}
1766
1767struct outproto *
1768setproto(char *pname)
1769{
1770	struct outproto *proto;
1771	int i;
1772
1773	for (i = 0; protos[i].name != NULL; i++) {
1774		if (strcasecmp(protos[i].name, pname) == 0) {
1775			break;
1776		}
1777	}
1778	proto = &protos[i];
1779	if (proto->name == NULL) {	/* generic handler */
1780		struct protoent *pe;
1781		u_int32_t pnum;
1782
1783		/* Determine the IP protocol number */
1784		if ((pe = getprotobyname(pname)) != NULL)
1785			pnum = pe->p_proto;
1786		else
1787			pnum = str2val(optarg, "proto number", 1, 255);
1788		proto->num = pnum;
1789	}
1790	return proto;
1791}
1792
1793void
1794pkt_compare(const u_char *a, int la, const u_char *b, int lb) {
1795	int l;
1796	int i;
1797
1798	for (i = 0; i < la; i++)
1799		Printf("%02x", (unsigned int)a[i]);
1800	Printf("\n");
1801	l = (la <= lb) ? la : lb;
1802	for (i = 0; i < l; i++)
1803		if (a[i] == b[i])
1804			Printf("__");
1805		else
1806			Printf("%02x", (unsigned int)b[i]);
1807	for (; i < lb; i++)
1808		Printf("%02x", (unsigned int)b[i]);
1809	Printf("\n");
1810}
1811
1812
1813void
1814usage(void)
1815{
1816	extern char version[];
1817
1818	Fprintf(stderr, "Version %s\n", version);
1819	Fprintf(stderr,
1820	    "Usage: %s [-adDeFInrSvx] [-A as_server] [-f first_ttl] [-g gateway] [-i iface]\n"
1821	    "\t[-M first_ttl] [-m max_ttl] [-p port] [-P proto] [-q nqueries] [-s src_addr]\n"
1822	    "\t[-t tos] [-w waittime] [-z pausemsecs] host [packetlen]\n", prog);
1823	exit(1);
1824}
1825