traceroute.c revision 62786
1262566Sdes/*
276259Sgreen * Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996
376259Sgreen *	The Regents of the University of California.  All rights reserved.
476259Sgreen *
576259Sgreen * Redistribution and use in source and binary forms, with or without
676259Sgreen * modification, are permitted provided that: (1) source code distributions
776259Sgreen * retain the above copyright notice and this paragraph in its entirety, (2)
876259Sgreen * distributions including binary code include the above copyright notice and
976259Sgreen * this paragraph in its entirety in the documentation or other materials
1076259Sgreen * provided with the distribution, and (3) all advertising materials mentioning
1176259Sgreen * features or use of this software display the following acknowledgement:
1276259Sgreen * ``This product includes software developed by the University of California,
1376259Sgreen * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1476259Sgreen * the University nor the names of its contributors may be used to endorse
1592559Sdes * or promote products derived from this software without specific prior
1698941Sdes * written permission.
1798941Sdes * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1892559Sdes * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1998941Sdes * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2098941Sdes */
2198941Sdes
2276259Sgreen#ifndef lint
2398941Sdesstatic const char copyright[] =
2476259Sgreen    "@(#) Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996\n\
2576259SgreenThe Regents of the University of California.  All rights reserved.\n";
2676259Sgreen#if 0
2776259Sgreenstatic const char rcsid[] =
2876259Sgreen    "@(#)$Header: traceroute.c,v 1.43 96/09/27 20:08:10 leres Exp $ (LBL)";
2992559Sdes#endif
3092559Sdesstatic const char rcsid[] =
3192559Sdes    "$FreeBSD: head/contrib/traceroute/traceroute.c 62786 2000-07-07 19:44:36Z ghelmer $";
3276259Sgreen#endif
3376259Sgreen
3476259Sgreen/*
3576259Sgreen * traceroute host  - trace the route ip packets follow going to "host".
3676259Sgreen *
3792559Sdes * Attempt to trace the route an ip packet would follow to some
3892559Sdes * internet host.  We find out intermediate hops by launching probe
3992559Sdes * packets with a small ttl (time to live) then listening for an
4092559Sdes * icmp "time exceeded" reply from a gateway.  We start our probes
41221420Sdes * with a ttl of one and increase by one until we get an icmp "port
42262566Sdes * unreachable" (which means we got to "host") or hit a max (which
4392559Sdes * defaults to 30 hops & can be changed with the -m flag).  Three
4492559Sdes * probes (change with -q flag) are sent at each ttl setting and a
4592559Sdes * line is printed showing the ttl, address of the gateway and
4692559Sdes * round trip time of each probe.  If the probe answers come from
4776259Sgreen * different gateways, the address of each responding system will
4898941Sdes * be printed.  If there is no response within a 5 sec. timeout
4976259Sgreen * interval (changed with the -w flag), a "*" is printed for that
5098941Sdes * probe.
5176259Sgreen *
5276259Sgreen * Probe packets are UDP format.  We don't want the destination
5376259Sgreen * host to process them so the destination port is set to an
5476259Sgreen * unlikely value (if some clod on the destination is using that
5576259Sgreen * value, it can be changed with the -p flag).
5676259Sgreen *
5776259Sgreen * A sample use might be:
5876259Sgreen *
59192595Sdes *     [yak 71]% traceroute nis.nsf.net.
6076259Sgreen *     traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 56 byte packet
6176259Sgreen *      1  helios.ee.lbl.gov (128.3.112.1)  19 ms  19 ms  0 ms
6276259Sgreen *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
6376259Sgreen *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
6476259Sgreen *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  39 ms
6576259Sgreen *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  39 ms  39 ms  39 ms
6676259Sgreen *      6  128.32.197.4 (128.32.197.4)  40 ms  59 ms  59 ms
6776259Sgreen *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  59 ms
6876259Sgreen *      8  129.140.70.13 (129.140.70.13)  99 ms  99 ms  80 ms
69255767Sdes *      9  129.140.71.6 (129.140.71.6)  139 ms  239 ms  319 ms
7092559Sdes *     10  129.140.81.7 (129.140.81.7)  220 ms  199 ms  199 ms
71255767Sdes *     11  nic.merit.edu (35.1.1.48)  239 ms  239 ms  239 ms
7276259Sgreen *
7376259Sgreen * Note that lines 2 & 3 are the same.  This is due to a buggy
7476259Sgreen * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
7576259Sgreen * packets with a zero ttl.
7676259Sgreen *
77255767Sdes * A more interesting example is:
78255767Sdes *
79255767Sdes *     [yak 72]% traceroute allspice.lcs.mit.edu.
80255767Sdes *     traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max
81262566Sdes *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
8276259Sgreen *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  19 ms  19 ms
8376259Sgreen *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  19 ms
84192595Sdes *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  19 ms  39 ms  39 ms
8576259Sgreen *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  20 ms  39 ms  39 ms
86192595Sdes *      6  128.32.197.4 (128.32.197.4)  59 ms  119 ms  39 ms
8776259Sgreen *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  39 ms
8876259Sgreen *      8  129.140.70.13 (129.140.70.13)  80 ms  79 ms  99 ms
89255767Sdes *      9  129.140.71.6 (129.140.71.6)  139 ms  139 ms  159 ms
9076259Sgreen *     10  129.140.81.7 (129.140.81.7)  199 ms  180 ms  300 ms
9176259Sgreen *     11  129.140.72.17 (129.140.72.17)  300 ms  239 ms  239 ms
9276259Sgreen *     12  * * *
9376259Sgreen *     13  128.121.54.72 (128.121.54.72)  259 ms  499 ms  279 ms
94192595Sdes *     14  * * *
9576259Sgreen *     15  * * *
9676259Sgreen *     16  * * *
9776259Sgreen *     17  * * *
9876259Sgreen *     18  ALLSPICE.LCS.MIT.EDU (18.26.0.115)  339 ms  279 ms  279 ms
99255767Sdes *
10092559Sdes * (I start to see why I'm having so much trouble with mail to
10192559Sdes * MIT.)  Note that the gateways 12, 14, 15, 16 & 17 hops away
102255767Sdes * either don't send ICMP "time exceeded" messages or send them
10376259Sgreen * with a ttl too small to reach us.  14 - 17 are running the
10476259Sgreen * MIT C Gateway code that doesn't send "time exceeded"s.  God
10576259Sgreen * only knows what's going on with 12.
10676259Sgreen *
10776259Sgreen * The silent gateway 12 in the above may be the result of a bug in
10876259Sgreen * the 4.[23]BSD network code (and its derivatives):  4.x (x <= 3)
10976259Sgreen * sends an unreachable message using whatever ttl remains in the
110255767Sdes * original datagram.  Since, for gateways, the remaining ttl is
11192559Sdes * zero, the icmp "time exceeded" is guaranteed to not make it back
11276259Sgreen * to us.  The behavior of this bug is slightly more interesting
11376259Sgreen * when it appears on the destination system:
11476259Sgreen *
11576259Sgreen *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
11676259Sgreen *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  39 ms
11792559Sdes *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  39 ms  19 ms
11876259Sgreen *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  19 ms
11976259Sgreen *      5  ccn-nerif35.Berkeley.EDU (128.32.168.35)  39 ms  39 ms  39 ms
12076259Sgreen *      6  csgw.Berkeley.EDU (128.32.133.254)  39 ms  59 ms  39 ms
12176259Sgreen *      7  * * *
12276259Sgreen *      8  * * *
12398941Sdes *      9  * * *
124169966Sdes *     10  * * *
12598941Sdes *     11  * * *
12676259Sgreen *     12  * * *
12798684Sdes *     13  rip.Berkeley.EDU (128.32.131.22)  59 ms !  39 ms !  39 ms !
12898941Sdes *
129137019Sdes * Notice that there are 12 "gateways" (13 is the final
13098941Sdes * destination) and exactly the last half of them are "missing".
13198684Sdes * What's really happening is that rip (a Sun-3 running Sun OS3.5)
132204917Sdes * is using the ttl from our arriving datagram as the ttl in its
133204917Sdes * icmp reply.  So, the reply will time out on the return path
134204917Sdes * (with no notice sent to anyone since icmp's aren't sent for
135204917Sdes * icmp's) until we probe with a ttl that's at least twice the path
136204917Sdes * length.  I.e., rip is really only 7 hops away.  A reply that
13792559Sdes * returns with a ttl of 1 is a clue this problem exists.
13898941Sdes * Traceroute prints a "!" after the time if the ttl is <= 1.
139169966Sdes * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
14098941Sdes * non-standard (HPUX) software, expect to see this problem
14192559Sdes * frequently and/or take care picking the target host of your
14292559Sdes * probes.
14398941Sdes *
14492559Sdes * Other possible annotations after the time are !H, !N, !P (got a host,
14598941Sdes * network or protocol unreachable, respectively), !S or !F (source
14692559Sdes * route failed or fragmentation needed -- neither of these should
14798941Sdes * ever occur and the associated gateway is busted if you see one).  If
14898941Sdes * almost all the probes result in some kind of unreachable, traceroute
14998941Sdes * will give up and exit.
15098941Sdes *
15198941Sdes * Notes
15276259Sgreen * -----
15398941Sdes * This program must be run by root or be setuid.  (I suggest that
15476259Sgreen * you *don't* make it setuid -- casual use could result in a lot
15598941Sdes * of unnecessary traffic on our poor, congested nets.)
15698684Sdes *
15798684Sdes * This program requires a kernel mod that does not appear in any
15898941Sdes * system available from Berkeley:  A raw ip socket using proto
15998684Sdes * IPPROTO_RAW must interpret the data sent as an ip datagram (as
16098941Sdes * opposed to data to be wrapped in a ip datagram).  See the README
16198941Sdes * file that came with the source to this program for a description
162126277Sdes * of the mods I made to /sys/netinet/raw_ip.c.  Your mileage may
163126277Sdes * vary.  But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
164126277Sdes * MODIFIED TO RUN THIS PROGRAM.
165126277Sdes *
166126277Sdes * The udp port usage may appear bizarre (well, ok, it is bizarre).
16798941Sdes * The problem is that an icmp message only contains 8 bytes of
16898941Sdes * data from the original datagram.  8 bytes is the size of a udp
16998941Sdes * header so, if we want to associate replies with the original
17098941Sdes * datagram, the necessary information must be encoded into the
17198941Sdes * udp header (the ip id could be used but there's no way to
17298941Sdes * interlock with the kernel's assignment of ip id's and, anyway,
17398941Sdes * it would have taken a lot more kernel hacking to allow this
17498941Sdes * code to set the ip id).  So, to allow two or more users to
17598941Sdes * use traceroute simultaneously, we use this task's pid as the
17698941Sdes * source port (the high bit is set to move the port number out
17798941Sdes * of the "likely" range).  To keep track of which probe is being
17898941Sdes * replied to (so times and/or hop counts don't get confused by a
17998941Sdes * reply that was delayed in transit), we increment the destination
18098941Sdes * port number before each probe.
18198941Sdes *
18298941Sdes * Don't use this as a coding example.  I was trying to find a
18398941Sdes * 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#include <sys/time.h>
213
214#include <netinet/in_systm.h>
215#include <netinet/in.h>
216#include <netinet/ip.h>
217#include <netinet/ip_var.h>
218#include <netinet/ip_icmp.h>
219#include <netinet/udp.h>
220#include <netinet/tcp.h>
221
222#include <arpa/inet.h>
223
224#ifdef	IPSEC
225#include <net/route.h>
226#include <netinet6/ipsec.h>	/* XXX */
227#endif	/* IPSEC */
228
229#include <ctype.h>
230#include <errno.h>
231#ifdef HAVE_MALLOC_H
232#include <malloc.h>
233#endif
234#include <memory.h>
235#include <netdb.h>
236#include <stdio.h>
237#include <stdlib.h>
238#include <string.h>
239#include <unistd.h>
240
241#include "gnuc.h"
242#ifdef HAVE_OS_PROTO_H
243#include "os-proto.h"
244#endif
245
246/* Maximum number of gateways (include room for one noop) */
247#define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t)))
248
249#ifndef MAXHOSTNAMELEN
250#define MAXHOSTNAMELEN	64
251#endif
252
253#define Fprintf (void)fprintf
254#define Printf (void)printf
255
256/* What a GRE packet header looks like */
257struct grehdr {
258	u_int16_t   flags;
259	u_int16_t   proto;
260	u_int16_t   length;	/* PPTP version of these fields */
261	u_int16_t   callId;
262};
263#ifndef IPPROTO_GRE
264#define IPPROTO_GRE	47
265#endif
266
267/* For GRE, we prepare what looks like a PPTP packet */
268#define GRE_PPTP_PROTO	0x880b
269
270/* Data section of the probe packet */
271struct outdata {
272	u_char seq;		/* sequence number of this packet */
273	u_char ttl;		/* ttl packet left with */
274	struct timeval tv;	/* time packet left */
275};
276
277/* Descriptor structure for each outgoing protocol we support */
278struct outproto {
279	char	*name;		/* name of protocol */
280	u_char	num;		/* IP protocol number */
281	u_short	hdrlen;		/* max size of protocol header */
282	u_short	port;		/* default base protocol-specific "port" */
283	void	(*prepare)(struct outdata *);
284				/* finish preparing an outgoing packet */
285	int	(*check)(const u_char *, int);
286				/* check an incoming packet */
287};
288
289u_char	packet[512];		/* last inbound (icmp) packet */
290
291struct ip *outip;		/* last output ip packet */
292u_char *outprot;		/* last output inner protocol packet */
293
294/* loose source route gateway list (including room for final destination) */
295u_int32_t gwlist[NGATEWAYS + 1];
296
297int s;				/* receive (icmp) socket file descriptor */
298int sndsock;			/* send (udp) socket file descriptor */
299
300struct sockaddr whereto;	/* Who to try to reach */
301int packlen;			/* total length of packet */
302int protlen;			/* length of protocol part of packet */
303int maxpacket = 32 * 1024;	/* max ip packet size */
304
305char *prog;
306char *source;
307char *hostname;
308
309int nprobes = 3;
310int min_ttl = 1;
311int max_ttl = 30;
312u_short ident;
313u_short port;			/* protocol specific base "port" */
314
315int options;			/* socket options */
316int verbose;
317int waittime = 5;		/* time to wait for response (in seconds) */
318int nflag;			/* print addresses numerically */
319
320extern int optind;
321extern int opterr;
322extern char *optarg;
323
324/* Forwards */
325double	deltaT(struct timeval *, struct timeval *);
326char	*inetname(struct in_addr);
327int	main(int, char **);
328int	packet_ok(u_char *, int, struct sockaddr_in *, int);
329char	*pr_type(u_char);
330void	print(u_char *, int, struct sockaddr_in *);
331char	*getaddr(u_int32_t *, char *);
332char	*getsin(struct sockaddr_in *, char *);
333char	*savestr(const char *);
334#ifdef	IPSEC
335int	setpolicy __P((int so, char *policy));
336#endif
337void	send_probe(int, int);
338void	tvsub(struct timeval *, struct timeval *);
339__dead	void usage(void);
340int	wait_for_reply(int, struct sockaddr_in *, struct timeval *);
341
342void	udp_prep(struct outdata *);
343int	udp_check(const u_char *, int);
344void	tcp_prep(struct outdata *);
345int	tcp_check(const u_char *, int);
346void	gre_prep(struct outdata *);
347int	gre_check(const u_char *, int);
348void	gen_prep(struct outdata *);
349int	gen_check(const u_char *, int);
350
351/* List of supported protocols. The first one is the default. The last
352   one is the handler for generic protocols not explicitly listed. */
353struct	outproto protos[] = {
354	{
355		"udp",
356		IPPROTO_UDP,
357		sizeof(struct udphdr),
358		32768 + 666,
359		udp_prep,
360		udp_check
361	},
362	{
363		"tcp",
364		IPPROTO_TCP,
365		sizeof(struct tcphdr),
366		32768 + 666,
367		tcp_prep,
368		tcp_check
369	},
370	{
371		"gre",
372		IPPROTO_GRE,
373		sizeof(struct grehdr),
374		GRE_PPTP_PROTO,
375		gre_prep,
376		gre_check
377	},
378	{
379		NULL,
380		0,
381		2 * sizeof(u_short),
382		0,
383		gen_prep,
384		gen_check
385	},
386};
387struct	outproto *proto = &protos[0];
388
389int
390main(int argc, char **argv)
391{
392	register int op, code;
393	register char *cp;
394	struct sockaddr_in from;
395	register struct sockaddr_in *to = (struct sockaddr_in *)&whereto;
396	int on = 1;
397	register struct protoent *pe;
398	register int ttl, probe, i;
399	register int seq = 0;
400	register int tos = 0;
401	register int lsrr = 0;
402	register int optlen = 0;
403	int requestPort = -1;
404	int sump = 0;
405	int sockerrno;
406
407	/*
408	 * Do the setuid-required stuff first, then lose priveleges ASAP.
409	 * Do error checking for these two calls where they appeared in
410	 * the original code.
411	 */
412	cp = "icmp";
413	pe = getprotobyname(cp);
414	if (pe) {
415		if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0)
416			sockerrno = errno;
417		else if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
418			sockerrno = errno;
419	}
420
421	setuid(getuid());
422
423	if ((cp = strrchr(argv[0], '/')) != NULL)
424		prog = cp + 1;
425	else
426		prog = argv[0];
427
428	opterr = 0;
429	while ((op = getopt(argc, argv, "Sdnrvg:M:m:P:p:q:s:t:w:")) != EOF)
430		switch (op) {
431
432		case 'S':
433			sump = 1;
434			break;
435		case 'd':
436			options |= SO_DEBUG;
437			break;
438
439		case 'g':
440			if (lsrr >= NGATEWAYS) {
441				Fprintf(stderr,
442				    "%s: No more than %d gateways\n",
443				    prog, NGATEWAYS);
444				exit(1);
445			}
446			(void)getaddr(gwlist + lsrr, optarg);
447			++lsrr;
448			break;
449
450		case 'M':
451			min_ttl = atoi(optarg);
452			if (min_ttl < 1 || min_ttl > 0xff) {
453				Fprintf(stderr, "%s: invalid ttl value %s\n",
454				    prog, optarg);
455				exit(1);
456			}
457			break;
458
459		case 'm':
460			max_ttl = atoi(optarg);
461			if (max_ttl < 1 || max_ttl > 0xff) {
462				Fprintf(stderr, "%s: invalid ttl value %s\n",
463				    prog, optarg);
464				exit(1);
465			}
466			break;
467
468		case 'n':
469			++nflag;
470			break;
471
472		case 'P':
473			for (i = 0; protos[i].name != NULL; i++) {
474				if (strcasecmp(protos[i].name, optarg) == 0) {
475					proto = &protos[i];
476					break;
477				}
478			}
479			if (protos[i].name == NULL) {	/* generic handler */
480				struct protoent *pe;
481				u_long pnum;
482				char *eptr;
483
484				/* Determine the IP protocol number */
485				if ((pe = getprotobyname(optarg)) != NULL)
486					pnum = pe->p_proto;
487				else {
488					pnum = strtoul(optarg, &eptr, 10);
489					if (pnum > 0xff
490					    || *optarg == '\0'
491					    || *eptr != '\0') {
492						Fprintf(stderr, "%s: unknown "
493						    "protocol \"%s\"\n",
494						    prog, optarg);
495						exit(1);
496					}
497				}
498				proto->num = pnum;
499			}
500			break;
501
502		case 'p':
503			requestPort = atoi(optarg);
504			if (requestPort <= 0) {
505				Fprintf(stderr, "%s: port must be > 0\n", prog);
506				exit(1);
507			}
508			break;
509
510		case 'q':
511			nprobes = atoi(optarg);
512			if (nprobes <= 0) {
513				Fprintf(stderr, "%s: nprobes must be > 0\n",
514				    prog);
515				exit(1);
516			}
517			break;
518
519		case 'r':
520			options |= SO_DONTROUTE;
521			break;
522
523		case 's':
524			/*
525			 * set the ip source address of the outbound
526			 * probe (e.g., on a multi-homed host).
527			 */
528			source = optarg;
529			break;
530
531		case 't':
532			tos = atoi(optarg);
533			if (tos < 0 || tos > 255) {
534				Fprintf(stderr, "%s: tos must be 0 to 255\n",
535				    prog);
536				exit(1);
537			}
538			break;
539
540		case 'v':
541			++verbose;
542			break;
543
544		case 'w':
545			waittime = atoi(optarg);
546			if (waittime <= 1 || waittime >= 24L * 60 * 60) {
547				Fprintf(stderr,
548				    "%s: wait must be > 1 sec and < 1 day\n",
549				    prog);
550				exit(1);
551			}
552			break;
553
554		default:
555			usage();
556		}
557
558	/* Set requested port, if any, else default for this protocol */
559	port = (requestPort != -1) ? requestPort : proto->port;
560
561	/* Check min vs. max TTL */
562	if (min_ttl > max_ttl) {
563		Fprintf(stderr, "%s: min ttl must be <= max ttl\n", prog);
564		exit(1);
565	}
566
567	/* Process destination and optional packet size */
568	switch (argc - optind) {
569
570	case 2:
571		packlen = atoi(argv[optind + 1]);
572		/* Fall thorugh */
573
574	case 1:
575		hostname = savestr(getsin(to, argv[optind]));
576		break;
577
578	default:
579		usage();
580	}
581
582#ifdef HAVE_SETLINEBUF
583	setlinebuf (stdout);
584#else
585	setvbuf(stdout, NULL, _IOLBF, 0);
586#endif
587
588	if (lsrr > 0)
589		optlen = (lsrr + 1) * sizeof(gwlist[0]);
590	i = sizeof(*outip) + proto->hdrlen + sizeof(struct outdata) + optlen;
591	if (packlen == 0)
592		packlen = i;			/* minimum sized packet */
593	else if (i > packlen || packlen > maxpacket) {
594		Fprintf(stderr, "%s: packet size must be %d <= s <= %d\n",
595		    prog, i, maxpacket);
596		exit(1);
597	}
598	protlen = packlen - sizeof(*outip) - optlen;
599
600	outip = (struct ip *)malloc((unsigned)packlen);
601	if (outip == NULL) {
602		Fprintf(stderr, "%s: malloc: %s\n", prog, strerror(errno));
603		exit(1);
604	}
605	memset((char *)outip, 0, packlen);
606
607	outip->ip_v = IPVERSION;
608	outip->ip_tos = tos;
609#ifdef BYTESWAP_IP_LEN
610	outip->ip_len = htons(packlen);
611#else
612	outip->ip_len = packlen;
613#endif
614	outip->ip_p = proto->num;
615	outprot = (u_char *)(outip + 1);
616#ifdef HAVE_RAW_OPTIONS
617	if (lsrr > 0) {
618		register u_char *optlist;
619
620		optlist = (u_char *)outprot;
621		(u_char *)outprot += optlen;
622
623		/* final hop */
624		gwlist[lsrr] = to->sin_addr.s_addr;
625
626		outip->ip_dst.s_addr = gwlist[0];
627
628		/* force 4 byte alignment */
629		optlist[0] = IPOPT_NOP;
630		/* loose source route option */
631		optlist[1] = IPOPT_LSRR;
632		i = lsrr * sizeof(gwlist[0]);
633		optlist[2] = i + 3;
634		/* Pointer to LSRR addresses */
635		optlist[3] = IPOPT_MINOFF;
636		memcpy(optlist + 4, gwlist + 1, i);
637	} else
638#endif
639		outip->ip_dst = to->sin_addr;
640
641	outip->ip_hl = ((u_char *)outprot - (u_char *)outip) >> 2;
642
643	ident = (getpid() & 0xffff) | 0x8000;
644
645	if (pe == NULL) {
646		Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp);
647		exit(1);
648	}
649	if (s < 0) {
650		errno = sockerrno;
651		Fprintf(stderr, "%s: icmp socket: %s\n", prog, strerror(errno));
652		exit(1);
653	}
654	if (options & SO_DEBUG)
655		(void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on,
656		    sizeof(on));
657	if (options & SO_DONTROUTE)
658		(void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
659		    sizeof(on));
660
661#if	defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
662	if (setpolicy(s, "in bypass") < 0)
663		errx(1, ipsec_strerror());
664
665	if (setpolicy(s, "out bypass") < 0)
666		errx(1, ipsec_strerror());
667#endif	/* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */
668
669	if (sndsock < 0) {
670		errno = sockerrno;
671		Fprintf(stderr, "%s: raw socket: %s\n", prog, strerror(errno));
672		exit(1);
673	}
674
675#if defined(IP_OPTIONS) && !defined(HAVE_RAW_OPTIONS)
676	if (lsrr > 0) {
677		u_char optlist[MAX_IPOPTLEN];
678
679		cp = "ip";
680		if ((pe = getprotobyname(cp)) == NULL) {
681			Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp);
682			exit(1);
683		}
684
685		/* final hop */
686		gwlist[lsrr] = to->sin_addr.s_addr;
687		++lsrr;
688
689		/* force 4 byte alignment */
690		optlist[0] = IPOPT_NOP;
691		/* loose source route option */
692		optlist[1] = IPOPT_LSRR;
693		i = lsrr * sizeof(gwlist[0]);
694		optlist[2] = i + 3;
695		/* Pointer to LSRR addresses */
696		optlist[3] = IPOPT_MINOFF;
697		memcpy(optlist + 4, gwlist, i);
698
699		if ((setsockopt(sndsock, pe->p_proto, IP_OPTIONS, optlist,
700		    i + sizeof(gwlist[0]))) < 0) {
701			Fprintf(stderr, "%s: IP_OPTIONS: %s\n",
702			    prog, strerror(errno));
703			exit(1);
704		    }
705	}
706#endif
707
708#ifdef SO_SNDBUF
709	if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&packlen,
710	    sizeof(packlen)) < 0) {
711		Fprintf(stderr, "%s: SO_SNDBUF: %s\n", prog, strerror(errno));
712		exit(1);
713	}
714#endif
715#ifdef IP_HDRINCL
716	if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on,
717	    sizeof(on)) < 0) {
718		Fprintf(stderr, "%s: IP_HDRINCL: %s\n", prog, strerror(errno));
719		exit(1);
720	}
721#endif
722	if (options & SO_DEBUG)
723		(void)setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on,
724		    sizeof(on));
725	if (options & SO_DONTROUTE)
726		(void)setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
727		    sizeof(on));
728
729	if (source != NULL) {
730		source = savestr(getsin(&from, source));
731		outip->ip_src = from.sin_addr;
732#ifndef IP_HDRINCL
733		if (bind(sndsock, (struct sockaddr *)&from, sizeof(from)) < 0) {
734			Fprintf(stderr, "%s: bind: %s\n",
735			    prog, strerror(errno));
736			exit (1);
737		}
738#endif
739	}
740
741#if	defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
742	if (setpolicy(sndsock, "in bypass") < 0)
743		errx(1, ipsec_strerror());
744
745	if (setpolicy(sndsock, "out bypass") < 0)
746		errx(1, ipsec_strerror());
747#endif	/* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */
748
749	Fprintf(stderr, "%s to %s (%s)",
750	    prog, hostname, inet_ntoa(to->sin_addr));
751	if (source)
752		Fprintf(stderr, " from %s", source);
753	Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, packlen);
754	(void)fflush(stderr);
755
756	for (ttl = min_ttl; ttl <= max_ttl; ++ttl) {
757		u_int32_t lastaddr = 0;
758		int got_there = 0;
759		int unreachable = 0;
760		int loss;
761
762		Printf("%2d ", ttl);
763		for (probe = 0, loss = 0; probe < nprobes; ++probe) {
764			register int cc;
765			struct timeval t1, t2;
766			struct timezone tz;
767			register struct ip *ip;
768			struct outdata outdata;
769
770			/* Prepare outgoing data */
771			outdata.seq = ++seq;
772			outdata.ttl = ttl;
773
774			/* Avoid alignment problems by copying bytewise: */
775			(void)gettimeofday(&t1, &tz);
776			memcpy(&outdata.tv, &t1, sizeof(outdata.tv));
777
778			/* Finalize and send packet */
779			(*proto->prepare)(&outdata);
780			send_probe(seq, ttl);
781
782			/* Wait for a reply */
783			while ((cc = wait_for_reply(s, &from, &t1)) != 0) {
784				double T;
785				int precis;
786
787				(void)gettimeofday(&t2, &tz);
788				i = packet_ok(packet, cc, &from, seq);
789				/* Skip short packet */
790				if (i == 0)
791					continue;
792				if (from.sin_addr.s_addr != lastaddr) {
793					print(packet, cc, &from);
794					lastaddr = from.sin_addr.s_addr;
795				}
796				T = deltaT(&t1, &t2);
797#ifdef SANE_PRECISION
798				if (T >= 1000.0)
799					precis = 0;
800				else if (T >= 100.0)
801					precis = 1;
802				else if (T >= 10.0)
803					precis = 2;
804				else
805#endif
806					precis = 3;
807				Printf("  %.*f ms", precis, T);
808				/* time exceeded in transit */
809				if (i == -1)
810					break;
811				code = i - 1;
812				switch (code) {
813
814				case ICMP_UNREACH_PORT:
815#ifndef ARCHAIC
816					ip = (struct ip *)packet;
817					if (ip->ip_ttl <= 1)
818						Printf(" !");
819#endif
820					++got_there;
821					break;
822
823				case ICMP_UNREACH_NET:
824					++unreachable;
825					Printf(" !N");
826					break;
827
828				case ICMP_UNREACH_HOST:
829					++unreachable;
830					Printf(" !H");
831					break;
832
833				case ICMP_UNREACH_PROTOCOL:
834					++got_there;
835					Printf(" !P");
836					break;
837
838				case ICMP_UNREACH_NEEDFRAG:
839					++unreachable;
840					Printf(" !F");
841					break;
842
843				case ICMP_UNREACH_SRCFAIL:
844					++unreachable;
845					Printf(" !S");
846					break;
847
848/* rfc1716 */
849#ifndef ICMP_UNREACH_FILTER_PROHIB
850#define ICMP_UNREACH_FILTER_PROHIB	13	/* admin prohibited filter */
851#endif
852				case ICMP_UNREACH_FILTER_PROHIB:
853					++unreachable;
854					Printf(" !X");
855					break;
856
857				default:
858					++unreachable;
859					Printf(" !<%d>", code);
860					break;
861				}
862				break;
863			}
864			if (cc == 0) {
865				loss++;
866				Printf(" *");
867			}
868			(void)fflush(stdout);
869		}
870		if (sump) {
871			Printf(" (%d%% loss)", (loss * 100) / nprobes);
872		}
873		putchar('\n');
874		if (got_there ||
875		    (unreachable > 0 && unreachable >= nprobes - 1))
876			break;
877	}
878	exit(0);
879}
880
881int
882wait_for_reply(register int sock, register struct sockaddr_in *fromp,
883    register struct timeval *tp)
884{
885	fd_set fds;
886	struct timeval now, wait;
887	struct timezone tz;
888	register int cc = 0;
889	register int error;
890	int fromlen = sizeof(*fromp);
891
892	FD_ZERO(&fds);
893	FD_SET(sock, &fds);
894
895	wait.tv_sec = tp->tv_sec + waittime;
896	wait.tv_usec = tp->tv_usec;
897	(void)gettimeofday(&now, &tz);
898	tvsub(&wait, &now);
899	if (wait.tv_sec < 0) {
900		wait.tv_sec = 0;
901		wait.tv_usec = 1;
902	}
903
904	error = select(sock + 1, &fds, (fd_set *)0, (fd_set *)0, &wait);
905	if (error == -1 && errno == EINVAL) {
906		Fprintf(stderr, "%s: botched select() args\n", prog);
907		exit(1);
908	}
909	if (error > 0)
910		cc = recvfrom(s, (char *)packet, sizeof(packet), 0,
911			    (struct sockaddr *)fromp, &fromlen);
912
913	return(cc);
914}
915
916#if	defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
917int
918setpolicy(so, policy)
919	int so;
920	char *policy;
921{
922	char *buf;
923
924	buf = ipsec_set_policy(policy, strlen(policy));
925	if (buf == NULL) {
926		warnx(ipsec_strerror());
927		return -1;
928	}
929	(void)setsockopt(so, IPPROTO_IP, IP_IPSEC_POLICY,
930		buf, ipsec_get_policylen(buf));
931
932	free(buf);
933
934	return 0;
935}
936#endif
937
938void
939send_probe(int seq, int ttl)
940{
941	register int i;
942
943	outip->ip_ttl = ttl;
944	outip->ip_id = htons(ident + seq);
945
946	i = sendto(sndsock, (char *)outip, packlen, 0, &whereto,
947		   sizeof(whereto));
948	if (i < 0 || i != packlen)  {
949		if (i < 0)
950			Fprintf(stderr, "%s: sendto: %s\n",
951			    prog, strerror(errno));
952		Printf("%s: wrote %s %d chars, ret=%d\n",
953		    prog, hostname, packlen, i);
954		(void)fflush(stdout);
955	}
956}
957
958double
959deltaT(struct timeval *t1p, struct timeval *t2p)
960{
961	register double dt;
962
963	dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
964	     (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
965	return (dt);
966}
967
968/*
969 * Convert an ICMP "type" field to a printable string.
970 */
971char *
972pr_type(register u_char t)
973{
974	static char *ttab[] = {
975	"Echo Reply",	"ICMP 1",	"ICMP 2",	"Dest Unreachable",
976	"Source Quench", "Redirect",	"ICMP 6",	"ICMP 7",
977	"Echo",		"ICMP 9",	"ICMP 10",	"Time Exceeded",
978	"Param Problem", "Timestamp",	"Timestamp Reply", "Info Request",
979	"Info Reply"
980	};
981
982	if (t > 16)
983		return("OUT-OF-RANGE");
984
985	return(ttab[t]);
986}
987
988int
989packet_ok(register u_char *buf, int cc, register struct sockaddr_in *from,
990    register int seq)
991{
992	register struct icmp *icp;
993	register u_char type, code;
994	register int hlen;
995#ifndef ARCHAIC
996	register struct ip *ip;
997
998	ip = (struct ip *) buf;
999	hlen = ip->ip_hl << 2;
1000	if (cc < hlen + ICMP_MINLEN) {
1001		if (verbose)
1002			Printf("packet too short (%d bytes) from %s\n", cc,
1003				inet_ntoa(from->sin_addr));
1004		return (0);
1005	}
1006	cc -= hlen;
1007	icp = (struct icmp *)(buf + hlen);
1008#else
1009	icp = (struct icmp *)buf;
1010#endif
1011	type = icp->icmp_type;
1012	code = icp->icmp_code;
1013	if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
1014	    type == ICMP_UNREACH) {
1015		struct ip *hip;
1016		u_char *inner;
1017
1018		hip = &icp->icmp_ip;
1019		hlen = hip->ip_hl << 2;
1020		inner = (u_char *)((u_char *)hip + hlen);
1021		if (hlen + 12 <= cc
1022		    && hip->ip_p == proto->num
1023		    && (*proto->check)(inner, seq))
1024			return (type == ICMP_TIMXCEED ? -1 : code + 1);
1025	}
1026#ifndef ARCHAIC
1027	if (verbose) {
1028		register int i;
1029		u_int32_t *lp = (u_int32_t *)&icp->icmp_ip;
1030
1031		Printf("\n%d bytes from %s to ", cc, inet_ntoa(from->sin_addr));
1032		Printf("%s: icmp type %d (%s) code %d\n",
1033		    inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code);
1034		for (i = 4; i < cc ; i += sizeof(*lp))
1035			Printf("%2d: x%8.8x\n", i, *lp++);
1036	}
1037#endif
1038	return(0);
1039}
1040
1041void
1042udp_prep(struct outdata *outdata)
1043{
1044	struct udphdr *const udp = (struct udphdr *) outprot;
1045
1046	udp->uh_sport = htons(ident);
1047	udp->uh_dport = htons(port + outdata->seq);
1048	udp->uh_ulen = htons((u_short)protlen);
1049}
1050
1051int
1052udp_check(const u_char *data, int seq)
1053{
1054	struct udphdr *const udp = (struct udphdr *) data;
1055
1056	return (ntohs(udp->uh_sport) == ident
1057	    && ntohs(udp->uh_dport) == port + seq);
1058}
1059
1060void
1061tcp_prep(struct outdata *outdata)
1062{
1063	struct tcphdr *const tcp = (struct tcphdr *) outprot;
1064
1065	tcp->th_sport = htons(ident);
1066	tcp->th_dport = htons(port + outdata->seq);
1067	tcp->th_seq = (tcp->th_sport << 16) | tcp->th_dport;
1068	tcp->th_ack = 0;
1069	tcp->th_off = 5;
1070	tcp->th_flags = TH_SYN;
1071}
1072
1073int
1074tcp_check(const u_char *data, int seq)
1075{
1076	struct tcphdr *const tcp = (struct tcphdr *) data;
1077
1078	return (ntohs(tcp->th_sport) == ident
1079	    && ntohs(tcp->th_dport) == port + seq);
1080}
1081
1082void
1083gre_prep(struct outdata *outdata)
1084{
1085	struct grehdr *const gre = (struct grehdr *) outprot;
1086
1087	gre->flags = htons(0x2001);
1088	gre->proto = htons(port);
1089	gre->length = 0;
1090	gre->callId = htons(ident + outdata->seq);
1091}
1092
1093int
1094gre_check(const u_char *data, int seq)
1095{
1096	struct grehdr *const gre = (struct grehdr *) data;
1097
1098	return(ntohs(gre->proto) == port
1099	    && ntohs(gre->callId) == ident + seq);
1100}
1101
1102void
1103gen_prep(struct outdata *outdata)
1104{
1105	u_int16_t *const ptr;
1106
1107	ptr[0] = htons(ident);
1108	ptr[1] = htons(port + outdata->seq);
1109}
1110
1111int
1112gen_check(const u_char *data, int seq)
1113{
1114	u_int16_t *const ptr = (u_int16_t *) data;
1115
1116	return(ntohs(ptr[0]) == ident
1117	    && ntohs(ptr[1]) == port + seq);
1118}
1119
1120void
1121print(register u_char *buf, register int cc, register struct sockaddr_in *from)
1122{
1123	register struct ip *ip;
1124	register int hlen;
1125
1126	ip = (struct ip *) buf;
1127	hlen = ip->ip_hl << 2;
1128	cc -= hlen;
1129
1130	if (nflag)
1131		Printf(" %s", inet_ntoa(from->sin_addr));
1132	else
1133		Printf(" %s (%s)", inetname(from->sin_addr),
1134		    inet_ntoa(from->sin_addr));
1135
1136	if (verbose)
1137		Printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
1138}
1139
1140
1141#ifdef notyet
1142/*
1143 * Checksum routine for Internet Protocol family headers (C Version)
1144 */
1145in_cksum(register u_short *addr, register int len)
1146{
1147	register int nleft = len;
1148	register u_short *w = addr;
1149	register u_short answer;
1150	register int sum = 0;
1151
1152	/*
1153	 *  Our algorithm is simple, using a 32 bit accumulator (sum),
1154	 *  we add sequential 16 bit words to it, and at the end, fold
1155	 *  back all the carry bits from the top 16 bits into the lower
1156	 *  16 bits.
1157	 */
1158	while (nleft > 1)  {
1159		sum += *w++;
1160		nleft -= 2;
1161	}
1162
1163	/* mop up an odd byte, if necessary */
1164	if (nleft == 1)
1165		sum += *(u_char *)w;
1166
1167	/*
1168	 * add back carry outs from top 16 bits to low 16 bits
1169	 */
1170	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
1171	sum += (sum >> 16);			/* add carry */
1172	answer = ~sum;				/* truncate to 16 bits */
1173	return (answer);
1174}
1175#endif
1176
1177/*
1178 * Subtract 2 timeval structs:  out = out - in.
1179 * Out is assumed to be within about LONG_MAX seconds of in.
1180 */
1181void
1182tvsub(register struct timeval *out, register struct timeval *in)
1183{
1184
1185	if ((out->tv_usec -= in->tv_usec) < 0)   {
1186		--out->tv_sec;
1187		out->tv_usec += 1000000;
1188	}
1189	out->tv_sec -= in->tv_sec;
1190}
1191
1192/*
1193 * Construct an Internet address representation.
1194 * If the nflag has been supplied, give
1195 * numeric value, otherwise try for symbolic name.
1196 */
1197char *
1198inetname(struct in_addr in)
1199{
1200	register char *cp;
1201	register struct hostent *hp;
1202	static int first = 1;
1203	static char domain[MAXHOSTNAMELEN + 1], line[MAXHOSTNAMELEN + 1];
1204
1205	if (first && !nflag) {
1206		first = 0;
1207		if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
1208		    (cp = strchr(domain, '.')) != NULL) {
1209			(void)strncpy(domain, cp + 1, sizeof(domain) - 1);
1210			domain[sizeof(domain) - 1] = '\0';
1211		} else
1212			domain[0] = '\0';
1213	}
1214	if (!nflag && in.s_addr != INADDR_ANY) {
1215		hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET);
1216		if (hp != NULL) {
1217			if ((cp = strchr(hp->h_name, '.')) != NULL &&
1218			    strcmp(cp + 1, domain) == 0)
1219				*cp = '\0';
1220			(void)strncpy(line, hp->h_name, sizeof(line) - 1);
1221			line[sizeof(line) - 1] = '\0';
1222			return (line);
1223		}
1224	}
1225	return (inet_ntoa(in));
1226}
1227
1228char *
1229getaddr(register u_int32_t *ap, register char *hostname)
1230{
1231	register struct hostent *hp;
1232
1233	*ap = inet_addr(hostname);
1234	if ((int32_t)*ap != -1)
1235		return (hostname);
1236
1237	hp = gethostbyname(hostname);
1238	if (hp == NULL) {
1239		Fprintf(stderr, "%s: unknown host %s\n", prog, hostname);
1240		exit(1);
1241	}
1242	if (hp->h_addrtype != AF_INET || hp->h_length != 4) {
1243		Fprintf(stderr, "%s: bad host %s\n", prog, hostname);
1244		exit(1);
1245	}
1246	memcpy((caddr_t)ap, hp->h_addr, hp->h_length);
1247	return (hp->h_name);
1248}
1249
1250char *
1251getsin(register struct sockaddr_in *sin, register char *hostname)
1252{
1253
1254	memset(sin, 0, sizeof(*sin));
1255	sin->sin_family = AF_INET;
1256	return (getaddr((u_int32_t *)&sin->sin_addr.s_addr, hostname));
1257}
1258
1259char *
1260savestr(register const char *str)
1261{
1262	register char *cp;
1263
1264	cp = strdup(str);
1265	if (cp == NULL) {
1266		Fprintf(stderr, "%s: strdup: %s\n", prog, strerror(errno));
1267		exit(1);
1268	}
1269	return (cp);
1270}
1271
1272__dead void
1273usage(void)
1274{
1275	extern char version[];
1276
1277	Fprintf(stderr, "Version %s\n", version);
1278	Fprintf(stderr, "Usage: %s [-Sdnrv] [-w wait] [-m max_ttl] [-M min_ttl] \
1279[-P proto]\n\t [-p port#] [-q nqueries] [-t tos] [-s src_addr] [-g gateway] \
1280\n\t host [data_size]\n", prog);
1281	exit(1);
1282}
1283