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