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
23 static const char copyright[] =
24     "@(#) Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000\n\
25 The Regents of the University of California.  All rights reserved.\n";
26 #if 0
27 static const char rcsid[] =
28     "@(#)$Id: traceroute.c,v 1.68 2000/12/14 08:04:33 leres Exp $ (LBL)";
29 #endif
30 static const char rcsid[] =
31     "$FreeBSD: stable/9/contrib/traceroute/traceroute.c 234948 2012-05-03 09:47:22Z tuexen $";
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/tcp.h>
224 #include <netinet/tcpip.h>
225 
226 #include <arpa/inet.h>
227 
228 #ifdef	IPSEC
229 #include <net/route.h>
230 #include <netipsec/ipsec.h>	/* XXX */
231 #endif	/* IPSEC */
232 
233 #include <ctype.h>
234 #include <err.h>
235 #include <errno.h>
236 #include <fcntl.h>
237 #ifdef HAVE_MALLOC_H
238 #include <malloc.h>
239 #endif
240 #include <memory.h>
241 #include <netdb.h>
242 #include <stdio.h>
243 #include <stdlib.h>
244 #include <string.h>
245 #include <unistd.h>
246 
247 /* rfc1716 */
248 #ifndef ICMP_UNREACH_FILTER_PROHIB
249 #define ICMP_UNREACH_FILTER_PROHIB	13	/* admin prohibited filter */
250 #endif
251 #ifndef ICMP_UNREACH_HOST_PRECEDENCE
252 #define ICMP_UNREACH_HOST_PRECEDENCE	14	/* host precedence violation */
253 #endif
254 #ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF
255 #define ICMP_UNREACH_PRECEDENCE_CUTOFF	15	/* precedence cutoff */
256 #endif
257 
258 #include "findsaddr.h"
259 #include "ifaddrlist.h"
260 #include "as.h"
261 #include "traceroute.h"
262 
263 /* Maximum number of gateways (include room for one noop) */
264 #define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t)))
265 
266 #ifndef MAXHOSTNAMELEN
267 #define MAXHOSTNAMELEN	64
268 #endif
269 
270 #define Fprintf (void)fprintf
271 #define Printf (void)printf
272 
273 /* What a GRE packet header looks like */
274 struct grehdr {
275 	u_int16_t   flags;
276 	u_int16_t   proto;
277 	u_int16_t   length;	/* PPTP version of these fields */
278 	u_int16_t   callId;
279 };
280 #ifndef IPPROTO_GRE
281 #define IPPROTO_GRE	47
282 #endif
283 
284 /* For GRE, we prepare what looks like a PPTP packet */
285 #define GRE_PPTP_PROTO	0x880b
286 
287 /* Host name and address list */
288 struct hostinfo {
289 	char *name;
290 	int n;
291 	u_int32_t *addrs;
292 };
293 
294 /* Data section of the probe packet */
295 struct outdata {
296 	u_char seq;		/* sequence number of this packet */
297 	u_char ttl;		/* ttl packet left with */
298 	struct timeval tv;	/* time packet left */
299 };
300 
301 #ifndef HAVE_ICMP_NEXTMTU
302 /* Path MTU Discovery (RFC1191) */
303 struct my_pmtu {
304 	u_short ipm_void;
305 	u_short ipm_nextmtu;
306 };
307 #endif
308 
309 u_char	packet[512];		/* last inbound (icmp) packet */
310 
311 struct ip *outip;		/* last output ip packet */
312 u_char *outp;		/* last output inner protocol packet */
313 
314 struct ip *hip = NULL;		/* Quoted IP header */
315 int hiplen = 0;
316 
317 /* loose source route gateway list (including room for final destination) */
318 u_int32_t gwlist[NGATEWAYS + 1];
319 
320 int s;				/* receive (icmp) socket file descriptor */
321 int sndsock;			/* send (udp) socket file descriptor */
322 
323 struct sockaddr whereto;	/* Who to try to reach */
324 struct sockaddr wherefrom;	/* Who we are */
325 int packlen;			/* total length of packet */
326 int protlen;			/* length of protocol part of packet */
327 int minpacket;			/* min ip packet size */
328 int maxpacket = 32 * 1024;	/* max ip packet size */
329 int pmtu;			/* Path MTU Discovery (RFC1191) */
330 u_int pausemsecs;
331 
332 char *prog;
333 char *source;
334 char *hostname;
335 char *device;
336 static const char devnull[] = "/dev/null";
337 
338 int nprobes = -1;
339 int max_ttl;
340 int first_ttl = 1;
341 u_short ident;
342 u_short port;			/* protocol specific base "port" */
343 
344 int options;			/* socket options */
345 int verbose;
346 int waittime = 5;		/* time to wait for response (in seconds) */
347 int nflag;			/* print addresses numerically */
348 int as_path;			/* print as numbers for each hop */
349 char *as_server = NULL;
350 void *asn;
351 #ifdef CANT_HACK_IPCKSUM
352 int doipcksum = 0;		/* don't calculate ip checksums by default */
353 #else
354 int doipcksum = 1;		/* calculate ip checksums by default */
355 #endif
356 int optlen;			/* length of ip options */
357 int fixedPort = 0;		/* Use fixed destination port for TCP and UDP */
358 int printdiff = 0;		/* Print the difference between sent and quoted */
359 
360 extern int optind;
361 extern int opterr;
362 extern char *optarg;
363 
364 /* Forwards */
365 double	deltaT(struct timeval *, struct timeval *);
366 void	freehostinfo(struct hostinfo *);
367 void	getaddr(u_int32_t *, char *);
368 struct	hostinfo *gethostinfo(char *);
369 u_short	in_cksum(u_short *, int);
370 char	*inetname(struct in_addr);
371 int	main(int, char **);
372 u_short p_cksum(struct ip *, u_short *, int);
373 int	packet_ok(u_char *, int, struct sockaddr_in *, int);
374 char	*pr_type(u_char);
375 void	print(u_char *, int, struct sockaddr_in *);
376 #ifdef	IPSEC
377 int	setpolicy __P((int so, char *policy));
378 #endif
379 void	send_probe(int, int);
380 struct outproto *setproto(char *);
381 int	str2val(const char *, const char *, int, int);
382 void	tvsub(struct timeval *, struct timeval *);
383 void usage(void);
384 int	wait_for_reply(int, struct sockaddr_in *, const struct timeval *);
385 void pkt_compare(const u_char *, int, const u_char *, int);
386 #ifndef HAVE_USLEEP
387 int	usleep(u_int);
388 #endif
389 
390 void	udp_prep(struct outdata *);
391 int	udp_check(const u_char *, int);
392 void	tcp_prep(struct outdata *);
393 int	tcp_check(const u_char *, int);
394 void	gre_prep(struct outdata *);
395 int	gre_check(const u_char *, int);
396 void	gen_prep(struct outdata *);
397 int	gen_check(const u_char *, int);
398 void	icmp_prep(struct outdata *);
399 int	icmp_check(const u_char *, int);
400 
401 /* Descriptor structure for each outgoing protocol we support */
402 struct outproto {
403 	char	*name;		/* name of protocol */
404 	const char *key;	/* An ascii key for the bytes of the header */
405 	u_char	num;		/* IP protocol number */
406 	u_short	hdrlen;		/* max size of protocol header */
407 	u_short	port;		/* default base protocol-specific "port" */
408 	void	(*prepare)(struct outdata *);
409 				/* finish preparing an outgoing packet */
410 	int	(*check)(const u_char *, int);
411 				/* check an incoming packet */
412 };
413 
414 /* List of supported protocols. The first one is the default. The last
415    one is the handler for generic protocols not explicitly listed. */
416 struct	outproto protos[] = {
417 	{
418 		"udp",
419 		"spt dpt len sum",
420 		IPPROTO_UDP,
421 		sizeof(struct udphdr),
422 		32768 + 666,
423 		udp_prep,
424 		udp_check
425 	},
426 	{
427 		"tcp",
428 		"spt dpt seq     ack     xxflwin sum urp",
429 		IPPROTO_TCP,
430 		sizeof(struct tcphdr),
431 		32768 + 666,
432 		tcp_prep,
433 		tcp_check
434 	},
435 	{
436 		"gre",
437 		"flg pro len clid",
438 		IPPROTO_GRE,
439 		sizeof(struct grehdr),
440 		GRE_PPTP_PROTO,
441 		gre_prep,
442 		gre_check
443 	},
444 	{
445 		"icmp",
446 		"typ cod sum ",
447 		IPPROTO_ICMP,
448 		sizeof(struct icmp),
449 		0,
450 		icmp_prep,
451 		icmp_check
452 	},
453 	{
454 		NULL,
455 		NULL,
456 		0,
457 		2 * sizeof(u_short),
458 		0,
459 		gen_prep,
460 		gen_check
461 	},
462 };
463 struct	outproto *proto = &protos[0];
464 
465 const char *ip_hdr_key = "vhtslen id  off tlprsum srcip   dstip   opts";
466 
467 int
main(int argc,char ** argv)468 main(int argc, char **argv)
469 {
470 	register int op, code, n;
471 	register char *cp;
472 	register const char *err;
473 	register u_int32_t *ap;
474 	register struct sockaddr_in *from = (struct sockaddr_in *)&wherefrom;
475 	register struct sockaddr_in *to = (struct sockaddr_in *)&whereto;
476 	register struct hostinfo *hi;
477 	int on = 1;
478 	register struct protoent *pe;
479 	register int ttl, probe, i;
480 	register int seq = 0;
481 	int tos = 0, settos = 0;
482 	register int lsrr = 0;
483 	register u_short off = 0;
484 	struct ifaddrlist *al;
485 	char errbuf[132];
486 	int requestPort = -1;
487 	int sump = 0;
488 	int sockerrno;
489 
490 	/* Insure the socket fds won't be 0, 1 or 2 */
491 	if (open(devnull, O_RDONLY) < 0 ||
492 	    open(devnull, O_RDONLY) < 0 ||
493 	    open(devnull, O_RDONLY) < 0) {
494 		Fprintf(stderr, "%s: open \"%s\": %s\n",
495 		    prog, devnull, strerror(errno));
496 		exit(1);
497 	}
498 	/*
499 	 * Do the setuid-required stuff first, then lose priveleges ASAP.
500 	 * Do error checking for these two calls where they appeared in
501 	 * the original code.
502 	 */
503 	cp = "icmp";
504 	pe = getprotobyname(cp);
505 	if (pe) {
506 		if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0)
507 			sockerrno = errno;
508 		else if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
509 			sockerrno = errno;
510 	}
511 
512 	if (setuid(getuid()) != 0) {
513 		perror("setuid()");
514 		exit(1);
515 	}
516 
517 #ifdef IPCTL_DEFTTL
518 	{
519 		int mib[4] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_DEFTTL };
520 		size_t sz = sizeof(max_ttl);
521 
522 		if (sysctl(mib, 4, &max_ttl, &sz, NULL, 0) == -1) {
523 			perror("sysctl(net.inet.ip.ttl)");
524 			exit(1);
525 		}
526 	}
527 #else
528 	max_ttl = 30;
529 #endif
530 
531 	if (argv[0] == NULL)
532 		prog = "traceroute";
533 	else if ((cp = strrchr(argv[0], '/')) != NULL)
534 		prog = cp + 1;
535 	else
536 		prog = argv[0];
537 
538 	opterr = 0;
539 	while ((op = getopt(argc, argv, "aA:edDFInrSvxf:g:i:M:m:P:p:q:s:t:w:z:")) != EOF)
540 		switch (op) {
541 		case 'a':
542 			as_path = 1;
543 			break;
544 
545 		case 'A':
546 			as_path = 1;
547 			as_server = optarg;
548 			break;
549 
550 		case 'd':
551 			options |= SO_DEBUG;
552 			break;
553 
554 		case 'D':
555 			printdiff = 1;
556 			break;
557 
558 		case 'e':
559 			fixedPort = 1;
560 			break;
561 
562 		case 'f':
563 		case 'M':	/* FreeBSD compat. */
564 			first_ttl = str2val(optarg, "first ttl", 1, 255);
565 			break;
566 
567 		case 'F':
568 			off = IP_DF;
569 			break;
570 
571 		case 'g':
572 			if (lsrr >= NGATEWAYS) {
573 				Fprintf(stderr,
574 				    "%s: No more than %d gateways\n",
575 				    prog, NGATEWAYS);
576 				exit(1);
577 			}
578 			getaddr(gwlist + lsrr, optarg);
579 			++lsrr;
580 			break;
581 
582 		case 'i':
583 			device = optarg;
584 			break;
585 
586 		case 'I':
587 			proto = setproto("icmp");
588 			break;
589 
590 		case 'm':
591 			max_ttl = str2val(optarg, "max ttl", 1, 255);
592 			break;
593 
594 		case 'n':
595 			++nflag;
596 			break;
597 
598 		case 'P':
599 			proto = setproto(optarg);
600 			break;
601 
602 		case 'p':
603 			requestPort = (u_short)str2val(optarg, "port",
604 			    1, (1 << 16) - 1);
605 			break;
606 
607 		case 'q':
608 			nprobes = str2val(optarg, "nprobes", 1, -1);
609 			break;
610 
611 		case 'r':
612 			options |= SO_DONTROUTE;
613 			break;
614 
615 		case 's':
616 			/*
617 			 * set the ip source address of the outbound
618 			 * probe (e.g., on a multi-homed host).
619 			 */
620 			source = optarg;
621 			break;
622 
623 		case 'S':
624 			sump = 1;
625 			break;
626 
627 		case 't':
628 			tos = str2val(optarg, "tos", 0, 255);
629 			++settos;
630 			break;
631 
632 		case 'v':
633 			++verbose;
634 			break;
635 
636 		case 'x':
637 			doipcksum = (doipcksum == 0);
638 			break;
639 
640 		case 'w':
641 			waittime = str2val(optarg, "wait time",
642 			    1, 24 * 60 * 60);
643 			break;
644 
645 		case 'z':
646 			pausemsecs = str2val(optarg, "pause msecs",
647 			    0, 60 * 60 * 1000);
648 			break;
649 
650 		default:
651 			usage();
652 		}
653 
654 	/* Set requested port, if any, else default for this protocol */
655 	port = (requestPort != -1) ? requestPort : proto->port;
656 
657 	if (nprobes == -1)
658 		nprobes = printdiff ? 1 : 3;
659 
660 	if (first_ttl > max_ttl) {
661 		Fprintf(stderr,
662 		    "%s: first ttl (%d) may not be greater than max ttl (%d)\n",
663 		    prog, first_ttl, max_ttl);
664 		exit(1);
665 	}
666 
667 	if (!doipcksum)
668 		Fprintf(stderr, "%s: Warning: ip checksums disabled\n", prog);
669 
670 	if (lsrr > 0)
671 		optlen = (lsrr + 1) * sizeof(gwlist[0]);
672 	minpacket = sizeof(*outip) + proto->hdrlen + sizeof(struct outdata) + optlen;
673 	packlen = minpacket;			/* minimum sized packet */
674 
675 	/* Process destination and optional packet size */
676 	switch (argc - optind) {
677 
678 	case 2:
679 		packlen = str2val(argv[optind + 1],
680 		    "packet length", minpacket, maxpacket);
681 		/* Fall through */
682 
683 	case 1:
684 		hostname = argv[optind];
685 		hi = gethostinfo(hostname);
686 		setsin(to, hi->addrs[0]);
687 		if (hi->n > 1)
688 			Fprintf(stderr,
689 		    "%s: Warning: %s has multiple addresses; using %s\n",
690 				prog, hostname, inet_ntoa(to->sin_addr));
691 		hostname = hi->name;
692 		hi->name = NULL;
693 		freehostinfo(hi);
694 		break;
695 
696 	default:
697 		usage();
698 	}
699 
700 #ifdef HAVE_SETLINEBUF
701 	setlinebuf (stdout);
702 #else
703 	setvbuf(stdout, NULL, _IOLBF, 0);
704 #endif
705 
706 	protlen = packlen - sizeof(*outip) - optlen;
707 
708 	outip = (struct ip *)malloc((unsigned)packlen);
709 	if (outip == NULL) {
710 		Fprintf(stderr, "%s: malloc: %s\n", prog, strerror(errno));
711 		exit(1);
712 	}
713 	memset((char *)outip, 0, packlen);
714 
715 	outip->ip_v = IPVERSION;
716 	if (settos)
717 		outip->ip_tos = tos;
718 #ifdef BYTESWAP_IP_HDR
719 	outip->ip_len = htons(packlen);
720 	outip->ip_off = htons(off);
721 #else
722 	outip->ip_len = packlen;
723 	outip->ip_off = off;
724 #endif
725 	outip->ip_p = proto->num;
726 	outp = (u_char *)(outip + 1);
727 #ifdef HAVE_RAW_OPTIONS
728 	if (lsrr > 0) {
729 		register u_char *optlist;
730 
731 		optlist = outp;
732 		outp += optlen;
733 
734 		/* final hop */
735 		gwlist[lsrr] = to->sin_addr.s_addr;
736 
737 		outip->ip_dst.s_addr = gwlist[0];
738 
739 		/* force 4 byte alignment */
740 		optlist[0] = IPOPT_NOP;
741 		/* loose source route option */
742 		optlist[1] = IPOPT_LSRR;
743 		i = lsrr * sizeof(gwlist[0]);
744 		optlist[2] = i + 3;
745 		/* Pointer to LSRR addresses */
746 		optlist[3] = IPOPT_MINOFF;
747 		memcpy(optlist + 4, gwlist + 1, i);
748 	} else
749 #endif
750 		outip->ip_dst = to->sin_addr;
751 
752 	outip->ip_hl = (outp - (u_char *)outip) >> 2;
753 	ident = (getpid() & 0xffff) | 0x8000;
754 
755 	if (pe == NULL) {
756 		Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp);
757 		exit(1);
758 	}
759 	if (s < 0) {
760 		errno = sockerrno;
761 		Fprintf(stderr, "%s: icmp socket: %s\n", prog, strerror(errno));
762 		exit(1);
763 	}
764 	if (options & SO_DEBUG)
765 		(void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on,
766 		    sizeof(on));
767 	if (options & SO_DONTROUTE)
768 		(void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
769 		    sizeof(on));
770 
771 #if	defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
772 	if (setpolicy(s, "in bypass") < 0)
773 		errx(1, "%s", ipsec_strerror());
774 
775 	if (setpolicy(s, "out bypass") < 0)
776 		errx(1, "%s", ipsec_strerror());
777 #endif	/* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */
778 
779 	if (sndsock < 0) {
780 		errno = sockerrno;
781 		Fprintf(stderr, "%s: raw socket: %s\n", prog, strerror(errno));
782 		exit(1);
783 	}
784 
785 #if defined(IP_OPTIONS) && !defined(HAVE_RAW_OPTIONS)
786 	if (lsrr > 0) {
787 		u_char optlist[MAX_IPOPTLEN];
788 
789 		cp = "ip";
790 		if ((pe = getprotobyname(cp)) == NULL) {
791 			Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp);
792 			exit(1);
793 		}
794 
795 		/* final hop */
796 		gwlist[lsrr] = to->sin_addr.s_addr;
797 		++lsrr;
798 
799 		/* force 4 byte alignment */
800 		optlist[0] = IPOPT_NOP;
801 		/* loose source route option */
802 		optlist[1] = IPOPT_LSRR;
803 		i = lsrr * sizeof(gwlist[0]);
804 		optlist[2] = i + 3;
805 		/* Pointer to LSRR addresses */
806 		optlist[3] = IPOPT_MINOFF;
807 		memcpy(optlist + 4, gwlist, i);
808 
809 		if ((setsockopt(sndsock, pe->p_proto, IP_OPTIONS,
810 		    (char *)optlist, i + sizeof(gwlist[0]))) < 0) {
811 			Fprintf(stderr, "%s: IP_OPTIONS: %s\n",
812 			    prog, strerror(errno));
813 			exit(1);
814 		    }
815 	}
816 #endif
817 
818 #ifdef SO_SNDBUF
819 	if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&packlen,
820 	    sizeof(packlen)) < 0) {
821 		Fprintf(stderr, "%s: SO_SNDBUF: %s\n", prog, strerror(errno));
822 		exit(1);
823 	}
824 #endif
825 #ifdef IP_HDRINCL
826 	if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on,
827 	    sizeof(on)) < 0) {
828 		Fprintf(stderr, "%s: IP_HDRINCL: %s\n", prog, strerror(errno));
829 		exit(1);
830 	}
831 #else
832 #ifdef IP_TOS
833 	if (settos && setsockopt(sndsock, IPPROTO_IP, IP_TOS,
834 	    (char *)&tos, sizeof(tos)) < 0) {
835 		Fprintf(stderr, "%s: setsockopt tos %d: %s\n",
836 		    prog, tos, strerror(errno));
837 		exit(1);
838 	}
839 #endif
840 #endif
841 	if (options & SO_DEBUG)
842 		(void)setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on,
843 		    sizeof(on));
844 	if (options & SO_DONTROUTE)
845 		(void)setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
846 		    sizeof(on));
847 
848 	/* Get the interface address list */
849 	n = ifaddrlist(&al, errbuf);
850 	if (n < 0) {
851 		Fprintf(stderr, "%s: ifaddrlist: %s\n", prog, errbuf);
852 		exit(1);
853 	}
854 	if (n == 0) {
855 		Fprintf(stderr,
856 		    "%s: Can't find any network interfaces\n", prog);
857 		exit(1);
858 	}
859 
860 	/* Look for a specific device */
861 	if (device != NULL) {
862 		for (i = n; i > 0; --i, ++al)
863 			if (strcmp(device, al->device) == 0)
864 				break;
865 		if (i <= 0) {
866 			Fprintf(stderr, "%s: Can't find interface %.32s\n",
867 			    prog, device);
868 			exit(1);
869 		}
870 	}
871 
872 	/* Determine our source address */
873 	if (source == NULL) {
874 		/*
875 		 * If a device was specified, use the interface address.
876 		 * Otherwise, try to determine our source address.
877 		 */
878 		if (device != NULL)
879 			setsin(from, al->addr);
880 		else if ((err = findsaddr(to, from)) != NULL) {
881 			Fprintf(stderr, "%s: findsaddr: %s\n",
882 			    prog, err);
883 			exit(1);
884 		}
885 	} else {
886 		hi = gethostinfo(source);
887 		source = hi->name;
888 		hi->name = NULL;
889 		/*
890 		 * If the device was specified make sure it
891 		 * corresponds to the source address specified.
892 		 * Otherwise, use the first address (and warn if
893 		 * there are more than one).
894 		 */
895 		if (device != NULL) {
896 			for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap)
897 				if (*ap == al->addr)
898 					break;
899 			if (i <= 0) {
900 				Fprintf(stderr,
901 				    "%s: %s is not on interface %.32s\n",
902 				    prog, source, device);
903 				exit(1);
904 			}
905 			setsin(from, *ap);
906 		} else {
907 			setsin(from, hi->addrs[0]);
908 			if (hi->n > 1)
909 				Fprintf(stderr,
910 			"%s: Warning: %s has multiple addresses; using %s\n",
911 				    prog, source, inet_ntoa(from->sin_addr));
912 		}
913 		freehostinfo(hi);
914 	}
915 
916 	outip->ip_src = from->sin_addr;
917 
918 	/* Check the source address (-s), if any, is valid */
919 	if (bind(sndsock, (struct sockaddr *)from, sizeof(*from)) < 0) {
920 		Fprintf(stderr, "%s: bind: %s\n",
921 		    prog, strerror(errno));
922 		exit (1);
923 	}
924 
925 	if (as_path) {
926 		asn = as_setup(as_server);
927 		if (asn == NULL) {
928 			Fprintf(stderr, "%s: as_setup failed, AS# lookups"
929 			    " disabled\n", prog);
930 			(void)fflush(stderr);
931 			as_path = 0;
932 		}
933 	}
934 
935 #if	defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
936 	if (setpolicy(sndsock, "in bypass") < 0)
937 		errx(1, "%s", ipsec_strerror());
938 
939 	if (setpolicy(sndsock, "out bypass") < 0)
940 		errx(1, "%s", ipsec_strerror());
941 #endif	/* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */
942 
943 	Fprintf(stderr, "%s to %s (%s)",
944 	    prog, hostname, inet_ntoa(to->sin_addr));
945 	if (source)
946 		Fprintf(stderr, " from %s", source);
947 	Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, packlen);
948 	(void)fflush(stderr);
949 
950 	for (ttl = first_ttl; ttl <= max_ttl; ++ttl) {
951 		u_int32_t lastaddr = 0;
952 		int gotlastaddr = 0;
953 		int got_there = 0;
954 		int unreachable = 0;
955 		int sentfirst = 0;
956 		int loss;
957 
958 		Printf("%2d ", ttl);
959 		for (probe = 0, loss = 0; probe < nprobes; ++probe) {
960 			register int cc;
961 			struct timeval t1, t2;
962 			register struct ip *ip;
963 			struct outdata outdata;
964 
965 			if (sentfirst && pausemsecs > 0)
966 				usleep(pausemsecs * 1000);
967 			/* Prepare outgoing data */
968 			outdata.seq = ++seq;
969 			outdata.ttl = ttl;
970 
971 			/* Avoid alignment problems by copying bytewise: */
972 			(void)gettimeofday(&t1, NULL);
973 			memcpy(&outdata.tv, &t1, sizeof(outdata.tv));
974 
975 			/* Finalize and send packet */
976 			(*proto->prepare)(&outdata);
977 			send_probe(seq, ttl);
978 			++sentfirst;
979 
980 			/* Wait for a reply */
981 			while ((cc = wait_for_reply(s, from, &t1)) != 0) {
982 				double T;
983 				int precis;
984 
985 				(void)gettimeofday(&t2, NULL);
986 				i = packet_ok(packet, cc, from, seq);
987 				/* Skip short packet */
988 				if (i == 0)
989 					continue;
990 				if (!gotlastaddr ||
991 				    from->sin_addr.s_addr != lastaddr) {
992 					if (gotlastaddr) printf("\n   ");
993 					print(packet, cc, from);
994 					lastaddr = from->sin_addr.s_addr;
995 					++gotlastaddr;
996 				}
997 				T = deltaT(&t1, &t2);
998 #ifdef SANE_PRECISION
999 				if (T >= 1000.0)
1000 					precis = 0;
1001 				else if (T >= 100.0)
1002 					precis = 1;
1003 				else if (T >= 10.0)
1004 					precis = 2;
1005 				else
1006 #endif
1007 					precis = 3;
1008 				Printf("  %.*f ms", precis, T);
1009 				if (printdiff) {
1010 					Printf("\n");
1011 					Printf("%*.*s%s\n",
1012 					    -(outip->ip_hl << 3),
1013 					    outip->ip_hl << 3,
1014 					    ip_hdr_key,
1015 					    proto->key);
1016 					pkt_compare((void *)outip, packlen,
1017 					    (void *)hip, hiplen);
1018 				}
1019 				if (i == -2) {
1020 #ifndef ARCHAIC
1021 					ip = (struct ip *)packet;
1022 					if (ip->ip_ttl <= 1)
1023 						Printf(" !");
1024 #endif
1025 					++got_there;
1026 					break;
1027 				}
1028 				/* time exceeded in transit */
1029 				if (i == -1)
1030 					break;
1031 				code = i - 1;
1032 				switch (code) {
1033 
1034 				case ICMP_UNREACH_PORT:
1035 #ifndef ARCHAIC
1036 					ip = (struct ip *)packet;
1037 					if (ip->ip_ttl <= 1)
1038 						Printf(" !");
1039 #endif
1040 					++got_there;
1041 					break;
1042 
1043 				case ICMP_UNREACH_NET:
1044 					++unreachable;
1045 					Printf(" !N");
1046 					break;
1047 
1048 				case ICMP_UNREACH_HOST:
1049 					++unreachable;
1050 					Printf(" !H");
1051 					break;
1052 
1053 				case ICMP_UNREACH_PROTOCOL:
1054 					++got_there;
1055 					Printf(" !P");
1056 					break;
1057 
1058 				case ICMP_UNREACH_NEEDFRAG:
1059 					++unreachable;
1060 					Printf(" !F-%d", pmtu);
1061 					break;
1062 
1063 				case ICMP_UNREACH_SRCFAIL:
1064 					++unreachable;
1065 					Printf(" !S");
1066 					break;
1067 
1068 				case ICMP_UNREACH_NET_UNKNOWN:
1069 					++unreachable;
1070 					Printf(" !U");
1071 					break;
1072 
1073 				case ICMP_UNREACH_HOST_UNKNOWN:
1074 					++unreachable;
1075 					Printf(" !W");
1076 					break;
1077 
1078 				case ICMP_UNREACH_ISOLATED:
1079 					++unreachable;
1080 					Printf(" !I");
1081 					break;
1082 
1083 				case ICMP_UNREACH_NET_PROHIB:
1084 					++unreachable;
1085 					Printf(" !A");
1086 					break;
1087 
1088 				case ICMP_UNREACH_HOST_PROHIB:
1089 					++unreachable;
1090 					Printf(" !Z");
1091 					break;
1092 
1093 				case ICMP_UNREACH_TOSNET:
1094 					++unreachable;
1095 					Printf(" !Q");
1096 					break;
1097 
1098 				case ICMP_UNREACH_TOSHOST:
1099 					++unreachable;
1100 					Printf(" !T");
1101 					break;
1102 
1103 				case ICMP_UNREACH_FILTER_PROHIB:
1104 					++unreachable;
1105 					Printf(" !X");
1106 					break;
1107 
1108 				case ICMP_UNREACH_HOST_PRECEDENCE:
1109 					++unreachable;
1110 					Printf(" !V");
1111 					break;
1112 
1113 				case ICMP_UNREACH_PRECEDENCE_CUTOFF:
1114 					++unreachable;
1115 					Printf(" !C");
1116 					break;
1117 
1118 				default:
1119 					++unreachable;
1120 					Printf(" !<%d>", code);
1121 					break;
1122 				}
1123 				break;
1124 			}
1125 			if (cc == 0) {
1126 				loss++;
1127 				Printf(" *");
1128 			}
1129 			(void)fflush(stdout);
1130 		}
1131 		if (sump) {
1132 			Printf(" (%d%% loss)", (loss * 100) / nprobes);
1133 		}
1134 		putchar('\n');
1135 		if (got_there ||
1136 		    (unreachable > 0 && unreachable >= nprobes - 1))
1137 			break;
1138 	}
1139 	if (as_path)
1140 		as_shutdown(asn);
1141 	exit(0);
1142 }
1143 
1144 int
wait_for_reply(register int sock,register struct sockaddr_in * fromp,register const struct timeval * tp)1145 wait_for_reply(register int sock, register struct sockaddr_in *fromp,
1146     register const struct timeval *tp)
1147 {
1148 	fd_set *fdsp;
1149 	size_t nfds;
1150 	struct timeval now, wait;
1151 	register int cc = 0;
1152 	register int error;
1153 	int fromlen = sizeof(*fromp);
1154 
1155 	nfds = howmany(sock + 1, NFDBITS);
1156 	if ((fdsp = malloc(nfds * sizeof(fd_mask))) == NULL)
1157 		err(1, "malloc");
1158 	memset(fdsp, 0, nfds * sizeof(fd_mask));
1159 	FD_SET(sock, fdsp);
1160 
1161 	wait.tv_sec = tp->tv_sec + waittime;
1162 	wait.tv_usec = tp->tv_usec;
1163 	(void)gettimeofday(&now, NULL);
1164 	tvsub(&wait, &now);
1165 	if (wait.tv_sec < 0) {
1166 		wait.tv_sec = 0;
1167 		wait.tv_usec = 1;
1168 	}
1169 
1170 	error = select(sock + 1, fdsp, NULL, NULL, &wait);
1171 	if (error == -1 && errno == EINVAL) {
1172 		Fprintf(stderr, "%s: botched select() args\n", prog);
1173 		exit(1);
1174 	}
1175 	if (error > 0)
1176 		cc = recvfrom(sock, (char *)packet, sizeof(packet), 0,
1177 			    (struct sockaddr *)fromp, &fromlen);
1178 
1179 	free(fdsp);
1180 	return(cc);
1181 }
1182 
1183 void
send_probe(int seq,int ttl)1184 send_probe(int seq, int ttl)
1185 {
1186 	register int cc;
1187 
1188 	outip->ip_ttl = ttl;
1189 	outip->ip_id = htons(ident + seq);
1190 
1191 	/* XXX undocumented debugging hack */
1192 	if (verbose > 1) {
1193 		register const u_short *sp;
1194 		register int nshorts, i;
1195 
1196 		sp = (u_short *)outip;
1197 		nshorts = (u_int)packlen / sizeof(u_short);
1198 		i = 0;
1199 		Printf("[ %d bytes", packlen);
1200 		while (--nshorts >= 0) {
1201 			if ((i++ % 8) == 0)
1202 				Printf("\n\t");
1203 			Printf(" %04x", ntohs(*sp++));
1204 		}
1205 		if (packlen & 1) {
1206 			if ((i % 8) == 0)
1207 				Printf("\n\t");
1208 			Printf(" %02x", *(u_char *)sp);
1209 		}
1210 		Printf("]\n");
1211 	}
1212 
1213 #if !defined(IP_HDRINCL) && defined(IP_TTL)
1214 	if (setsockopt(sndsock, IPPROTO_IP, IP_TTL,
1215 	    (char *)&ttl, sizeof(ttl)) < 0) {
1216 		Fprintf(stderr, "%s: setsockopt ttl %d: %s\n",
1217 		    prog, ttl, strerror(errno));
1218 		exit(1);
1219 	}
1220 #endif
1221 
1222 	cc = sendto(sndsock, (char *)outip,
1223 	    packlen, 0, &whereto, sizeof(whereto));
1224 	if (cc < 0 || cc != packlen)  {
1225 		if (cc < 0)
1226 			Fprintf(stderr, "%s: sendto: %s\n",
1227 			    prog, strerror(errno));
1228 		Printf("%s: wrote %s %d chars, ret=%d\n",
1229 		    prog, hostname, packlen, cc);
1230 		(void)fflush(stdout);
1231 	}
1232 }
1233 
1234 #if	defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
1235 int
setpolicy(so,policy)1236 setpolicy(so, policy)
1237 	int so;
1238 	char *policy;
1239 {
1240 	char *buf;
1241 
1242 	buf = ipsec_set_policy(policy, strlen(policy));
1243 	if (buf == NULL) {
1244 		warnx("%s", ipsec_strerror());
1245 		return -1;
1246 	}
1247 	(void)setsockopt(so, IPPROTO_IP, IP_IPSEC_POLICY,
1248 		buf, ipsec_get_policylen(buf));
1249 
1250 	free(buf);
1251 
1252 	return 0;
1253 }
1254 #endif
1255 
1256 double
deltaT(struct timeval * t1p,struct timeval * t2p)1257 deltaT(struct timeval *t1p, struct timeval *t2p)
1258 {
1259 	register double dt;
1260 
1261 	dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
1262 	     (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
1263 	return (dt);
1264 }
1265 
1266 /*
1267  * Convert an ICMP "type" field to a printable string.
1268  */
1269 char *
pr_type(register u_char t)1270 pr_type(register u_char t)
1271 {
1272 	static char *ttab[] = {
1273 	"Echo Reply",	"ICMP 1",	"ICMP 2",	"Dest Unreachable",
1274 	"Source Quench", "Redirect",	"ICMP 6",	"ICMP 7",
1275 	"Echo",		"ICMP 9",	"ICMP 10",	"Time Exceeded",
1276 	"Param Problem", "Timestamp",	"Timestamp Reply", "Info Request",
1277 	"Info Reply"
1278 	};
1279 
1280 	if (t > 16)
1281 		return("OUT-OF-RANGE");
1282 
1283 	return(ttab[t]);
1284 }
1285 
1286 int
packet_ok(register u_char * buf,int cc,register struct sockaddr_in * from,register int seq)1287 packet_ok(register u_char *buf, int cc, register struct sockaddr_in *from,
1288     register int seq)
1289 {
1290 	register struct icmp *icp;
1291 	register u_char type, code;
1292 	register int hlen;
1293 #ifndef ARCHAIC
1294 	register struct ip *ip;
1295 
1296 	ip = (struct ip *) buf;
1297 	hlen = ip->ip_hl << 2;
1298 	if (cc < hlen + ICMP_MINLEN) {
1299 		if (verbose)
1300 			Printf("packet too short (%d bytes) from %s\n", cc,
1301 				inet_ntoa(from->sin_addr));
1302 		return (0);
1303 	}
1304 	cc -= hlen;
1305 	icp = (struct icmp *)(buf + hlen);
1306 #else
1307 	icp = (struct icmp *)buf;
1308 #endif
1309 	type = icp->icmp_type;
1310 	code = icp->icmp_code;
1311 	/* Path MTU Discovery (RFC1191) */
1312 	if (code != ICMP_UNREACH_NEEDFRAG)
1313 		pmtu = 0;
1314 	else {
1315 #ifdef HAVE_ICMP_NEXTMTU
1316 		pmtu = ntohs(icp->icmp_nextmtu);
1317 #else
1318 		pmtu = ntohs(((struct my_pmtu *)&icp->icmp_void)->ipm_nextmtu);
1319 #endif
1320 	}
1321 	if (type == ICMP_ECHOREPLY
1322 	    && proto->num == IPPROTO_ICMP
1323 	    && (*proto->check)((u_char *)icp, (u_char)seq))
1324 		return -2;
1325 	if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
1326 	    type == ICMP_UNREACH) {
1327 		u_char *inner;
1328 
1329 		hip = &icp->icmp_ip;
1330 		hiplen = ((u_char *)icp + cc) - (u_char *)hip;
1331 		hlen = hip->ip_hl << 2;
1332 		inner = (u_char *)((u_char *)hip + hlen);
1333 		if (hlen + 12 <= cc
1334 		    && hip->ip_p == proto->num
1335 		    && (*proto->check)(inner, (u_char)seq))
1336 			return (type == ICMP_TIMXCEED ? -1 : code + 1);
1337 	}
1338 #ifndef ARCHAIC
1339 	if (verbose) {
1340 		register int i;
1341 		u_int32_t *lp = (u_int32_t *)&icp->icmp_ip;
1342 
1343 		Printf("\n%d bytes from %s to ", cc, inet_ntoa(from->sin_addr));
1344 		Printf("%s: icmp type %d (%s) code %d\n",
1345 		    inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code);
1346 		for (i = 4; i < cc ; i += sizeof(*lp))
1347 			Printf("%2d: x%8.8x\n", i, *lp++);
1348 	}
1349 #endif
1350 	return(0);
1351 }
1352 
1353 void
icmp_prep(struct outdata * outdata)1354 icmp_prep(struct outdata *outdata)
1355 {
1356 	struct icmp *const icmpheader = (struct icmp *) outp;
1357 
1358 	icmpheader->icmp_type = ICMP_ECHO;
1359 	icmpheader->icmp_id = htons(ident);
1360 	icmpheader->icmp_seq = htons(outdata->seq);
1361 	icmpheader->icmp_cksum = 0;
1362 	icmpheader->icmp_cksum = in_cksum((u_short *)icmpheader, protlen);
1363 	if (icmpheader->icmp_cksum == 0)
1364 		icmpheader->icmp_cksum = 0xffff;
1365 }
1366 
1367 int
icmp_check(const u_char * data,int seq)1368 icmp_check(const u_char *data, int seq)
1369 {
1370 	struct icmp *const icmpheader = (struct icmp *) data;
1371 
1372 	return (icmpheader->icmp_id == htons(ident)
1373 	    && icmpheader->icmp_seq == htons(seq));
1374 }
1375 
1376 void
udp_prep(struct outdata * outdata)1377 udp_prep(struct outdata *outdata)
1378 {
1379 	struct udphdr *const outudp = (struct udphdr *) outp;
1380 
1381 	outudp->uh_sport = htons(ident + (fixedPort ? outdata->seq : 0));
1382 	outudp->uh_dport = htons(port + (fixedPort ? 0 : outdata->seq));
1383 	outudp->uh_ulen = htons((u_short)protlen);
1384 	outudp->uh_sum = 0;
1385 	if (doipcksum) {
1386 	    u_short sum = p_cksum(outip, (u_short*)outudp, protlen);
1387 	    outudp->uh_sum = (sum) ? sum : 0xffff;
1388 	}
1389 
1390 	return;
1391 }
1392 
1393 int
udp_check(const u_char * data,int seq)1394 udp_check(const u_char *data, int seq)
1395 {
1396 	struct udphdr *const udp = (struct udphdr *) data;
1397 
1398 	return (ntohs(udp->uh_sport) == ident + (fixedPort ? seq : 0) &&
1399 	    ntohs(udp->uh_dport) == port + (fixedPort ? 0 : seq));
1400 }
1401 
1402 void
tcp_prep(struct outdata * outdata)1403 tcp_prep(struct outdata *outdata)
1404 {
1405 	struct tcphdr *const tcp = (struct tcphdr *) outp;
1406 
1407 	tcp->th_sport = htons(ident);
1408 	tcp->th_dport = htons(port + (fixedPort ? 0 : outdata->seq));
1409 	tcp->th_seq = (tcp->th_sport << 16) | tcp->th_dport;
1410 	tcp->th_ack = 0;
1411 	tcp->th_off = 5;
1412 	tcp->th_flags = TH_SYN;
1413 	tcp->th_sum = 0;
1414 
1415 	if (doipcksum) {
1416 	    u_short sum = p_cksum(outip, (u_short*)tcp, protlen);
1417 	    tcp->th_sum = (sum) ? sum : 0xffff;
1418 	}
1419 }
1420 
1421 int
tcp_check(const u_char * data,int seq)1422 tcp_check(const u_char *data, int seq)
1423 {
1424 	struct tcphdr *const tcp = (struct tcphdr *) data;
1425 
1426 	return (ntohs(tcp->th_sport) == ident
1427 	    && ntohs(tcp->th_dport) == port + (fixedPort ? 0 : seq)
1428 	    && tcp->th_seq == (tcp_seq)((tcp->th_sport << 16) | tcp->th_dport));
1429 }
1430 
1431 void
gre_prep(struct outdata * outdata)1432 gre_prep(struct outdata *outdata)
1433 {
1434 	struct grehdr *const gre = (struct grehdr *) outp;
1435 
1436 	gre->flags = htons(0x2001);
1437 	gre->proto = htons(port);
1438 	gre->length = 0;
1439 	gre->callId = htons(ident + outdata->seq);
1440 }
1441 
1442 int
gre_check(const u_char * data,int seq)1443 gre_check(const u_char *data, int seq)
1444 {
1445 	struct grehdr *const gre = (struct grehdr *) data;
1446 
1447 	return(ntohs(gre->proto) == port
1448 	    && ntohs(gre->callId) == ident + seq);
1449 }
1450 
1451 void
gen_prep(struct outdata * outdata)1452 gen_prep(struct outdata *outdata)
1453 {
1454 	u_int16_t *const ptr = (u_int16_t *) outp;
1455 
1456 	ptr[0] = htons(ident);
1457 	ptr[1] = htons(port + outdata->seq);
1458 }
1459 
1460 int
gen_check(const u_char * data,int seq)1461 gen_check(const u_char *data, int seq)
1462 {
1463 	u_int16_t *const ptr = (u_int16_t *) data;
1464 
1465 	return(ntohs(ptr[0]) == ident
1466 	    && ntohs(ptr[1]) == port + seq);
1467 }
1468 
1469 void
print(register u_char * buf,register int cc,register struct sockaddr_in * from)1470 print(register u_char *buf, register int cc, register struct sockaddr_in *from)
1471 {
1472 	register struct ip *ip;
1473 	register int hlen;
1474 	char addr[INET_ADDRSTRLEN];
1475 
1476 	ip = (struct ip *) buf;
1477 	hlen = ip->ip_hl << 2;
1478 	cc -= hlen;
1479 
1480 	strlcpy(addr, inet_ntoa(from->sin_addr), sizeof(addr));
1481 
1482 	if (as_path)
1483 		Printf(" [AS%u]", as_lookup(asn, addr, AF_INET));
1484 
1485 	if (nflag)
1486 		Printf(" %s", addr);
1487 	else
1488 		Printf(" %s (%s)", inetname(from->sin_addr), addr);
1489 
1490 	if (verbose)
1491 		Printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
1492 }
1493 
1494 /*
1495  * Checksum routine for UDP and TCP headers.
1496  */
1497 u_short
p_cksum(struct ip * ip,u_short * data,int len)1498 p_cksum(struct ip *ip, u_short *data, int len)
1499 {
1500 	static struct ipovly ipo;
1501 	u_short sum[2];
1502 
1503 	ipo.ih_pr = ip->ip_p;
1504 	ipo.ih_len = htons(len);
1505 	ipo.ih_src = ip->ip_src;
1506 	ipo.ih_dst = ip->ip_dst;
1507 
1508 	sum[1] = in_cksum((u_short*)&ipo, sizeof(ipo)); /* pseudo ip hdr cksum */
1509 	sum[0] = in_cksum(data, len);                   /* payload data cksum */
1510 
1511 	return ~in_cksum(sum, sizeof(sum));
1512 }
1513 
1514 /*
1515  * Checksum routine for Internet Protocol family headers (C Version)
1516  */
1517 u_short
in_cksum(register u_short * addr,register int len)1518 in_cksum(register u_short *addr, register int len)
1519 {
1520 	register int nleft = len;
1521 	register u_short *w = addr;
1522 	register u_short answer;
1523 	register int sum = 0;
1524 
1525 	/*
1526 	 *  Our algorithm is simple, using a 32 bit accumulator (sum),
1527 	 *  we add sequential 16 bit words to it, and at the end, fold
1528 	 *  back all the carry bits from the top 16 bits into the lower
1529 	 *  16 bits.
1530 	 */
1531 	while (nleft > 1)  {
1532 		sum += *w++;
1533 		nleft -= 2;
1534 	}
1535 
1536 	/* mop up an odd byte, if necessary */
1537 	if (nleft == 1)
1538 		sum += *(u_char *)w;
1539 
1540 	/*
1541 	 * add back carry outs from top 16 bits to low 16 bits
1542 	 */
1543 	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
1544 	sum += (sum >> 16);			/* add carry */
1545 	answer = ~sum;				/* truncate to 16 bits */
1546 	return (answer);
1547 }
1548 
1549 /*
1550  * Subtract 2 timeval structs:  out = out - in.
1551  * Out is assumed to be within about LONG_MAX seconds of in.
1552  */
1553 void
tvsub(register struct timeval * out,register struct timeval * in)1554 tvsub(register struct timeval *out, register struct timeval *in)
1555 {
1556 
1557 	if ((out->tv_usec -= in->tv_usec) < 0)   {
1558 		--out->tv_sec;
1559 		out->tv_usec += 1000000;
1560 	}
1561 	out->tv_sec -= in->tv_sec;
1562 }
1563 
1564 /*
1565  * Construct an Internet address representation.
1566  * If the nflag has been supplied, give
1567  * numeric value, otherwise try for symbolic name.
1568  */
1569 char *
inetname(struct in_addr in)1570 inetname(struct in_addr in)
1571 {
1572 	register char *cp;
1573 	register struct hostent *hp;
1574 	static int first = 1;
1575 	static char domain[MAXHOSTNAMELEN + 1], line[MAXHOSTNAMELEN + 1];
1576 
1577 	if (first && !nflag) {
1578 		first = 0;
1579 		if (gethostname(domain, sizeof(domain) - 1) < 0)
1580 			domain[0] = '\0';
1581 		else {
1582 			cp = strchr(domain, '.');
1583 			if (cp == NULL) {
1584 				hp = gethostbyname(domain);
1585 				if (hp != NULL)
1586 					cp = strchr(hp->h_name, '.');
1587 			}
1588 			if (cp == NULL)
1589 				domain[0] = '\0';
1590 			else {
1591 				++cp;
1592 				(void)strncpy(domain, cp, sizeof(domain) - 1);
1593 				domain[sizeof(domain) - 1] = '\0';
1594 			}
1595 		}
1596 	}
1597 	if (!nflag && in.s_addr != INADDR_ANY) {
1598 		hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET);
1599 		if (hp != NULL) {
1600 			if ((cp = strchr(hp->h_name, '.')) != NULL &&
1601 			    strcmp(cp + 1, domain) == 0)
1602 				*cp = '\0';
1603 			(void)strncpy(line, hp->h_name, sizeof(line) - 1);
1604 			line[sizeof(line) - 1] = '\0';
1605 			return (line);
1606 		}
1607 	}
1608 	return (inet_ntoa(in));
1609 }
1610 
1611 struct hostinfo *
gethostinfo(register char * hostname)1612 gethostinfo(register char *hostname)
1613 {
1614 	register int n;
1615 	register struct hostent *hp;
1616 	register struct hostinfo *hi;
1617 	register char **p;
1618 	register u_int32_t addr, *ap;
1619 
1620 	if (strlen(hostname) >= MAXHOSTNAMELEN) {
1621 		Fprintf(stderr, "%s: hostname \"%.32s...\" is too long\n",
1622 		    prog, hostname);
1623 		exit(1);
1624 	}
1625 	hi = calloc(1, sizeof(*hi));
1626 	if (hi == NULL) {
1627 		Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
1628 		exit(1);
1629 	}
1630 	addr = inet_addr(hostname);
1631 	if ((int32_t)addr != -1) {
1632 		hi->name = strdup(hostname);
1633 		hi->n = 1;
1634 		hi->addrs = calloc(1, sizeof(hi->addrs[0]));
1635 		if (hi->addrs == NULL) {
1636 			Fprintf(stderr, "%s: calloc %s\n",
1637 			    prog, strerror(errno));
1638 			exit(1);
1639 		}
1640 		hi->addrs[0] = addr;
1641 		return (hi);
1642 	}
1643 
1644 	hp = gethostbyname(hostname);
1645 	if (hp == NULL) {
1646 		Fprintf(stderr, "%s: unknown host %s\n", prog, hostname);
1647 		exit(1);
1648 	}
1649 	if (hp->h_addrtype != AF_INET || hp->h_length != 4) {
1650 		Fprintf(stderr, "%s: bad host %s\n", prog, hostname);
1651 		exit(1);
1652 	}
1653 	hi->name = strdup(hp->h_name);
1654 	for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p)
1655 		continue;
1656 	hi->n = n;
1657 	hi->addrs = calloc(n, sizeof(hi->addrs[0]));
1658 	if (hi->addrs == NULL) {
1659 		Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
1660 		exit(1);
1661 	}
1662 	for (ap = hi->addrs, p = hp->h_addr_list; *p != NULL; ++ap, ++p)
1663 		memcpy(ap, *p, sizeof(*ap));
1664 	return (hi);
1665 }
1666 
1667 void
freehostinfo(register struct hostinfo * hi)1668 freehostinfo(register struct hostinfo *hi)
1669 {
1670 	if (hi->name != NULL) {
1671 		free(hi->name);
1672 		hi->name = NULL;
1673 	}
1674 	free((char *)hi->addrs);
1675 	free((char *)hi);
1676 }
1677 
1678 void
getaddr(register u_int32_t * ap,register char * hostname)1679 getaddr(register u_int32_t *ap, register char *hostname)
1680 {
1681 	register struct hostinfo *hi;
1682 
1683 	hi = gethostinfo(hostname);
1684 	*ap = hi->addrs[0];
1685 	freehostinfo(hi);
1686 }
1687 
1688 void
setsin(register struct sockaddr_in * sin,register u_int32_t addr)1689 setsin(register struct sockaddr_in *sin, register u_int32_t addr)
1690 {
1691 
1692 	memset(sin, 0, sizeof(*sin));
1693 #ifdef HAVE_SOCKADDR_SA_LEN
1694 	sin->sin_len = sizeof(*sin);
1695 #endif
1696 	sin->sin_family = AF_INET;
1697 	sin->sin_addr.s_addr = addr;
1698 }
1699 
1700 /* String to value with optional min and max. Handles decimal and hex. */
1701 int
str2val(register const char * str,register const char * what,register int mi,register int ma)1702 str2val(register const char *str, register const char *what,
1703     register int mi, register int ma)
1704 {
1705 	register const char *cp;
1706 	register int val;
1707 	char *ep;
1708 
1709 	if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
1710 		cp = str + 2;
1711 		val = (int)strtol(cp, &ep, 16);
1712 	} else
1713 		val = (int)strtol(str, &ep, 10);
1714 	if (*ep != '\0') {
1715 		Fprintf(stderr, "%s: \"%s\" bad value for %s \n",
1716 		    prog, str, what);
1717 		exit(1);
1718 	}
1719 	if (val < mi && mi >= 0) {
1720 		if (mi == 0)
1721 			Fprintf(stderr, "%s: %s must be >= %d\n",
1722 			    prog, what, mi);
1723 		else
1724 			Fprintf(stderr, "%s: %s must be > %d\n",
1725 			    prog, what, mi - 1);
1726 		exit(1);
1727 	}
1728 	if (val > ma && ma >= 0) {
1729 		Fprintf(stderr, "%s: %s must be <= %d\n", prog, what, ma);
1730 		exit(1);
1731 	}
1732 	return (val);
1733 }
1734 
1735 struct outproto *
setproto(char * pname)1736 setproto(char *pname)
1737 {
1738 	struct outproto *proto;
1739 	int i;
1740 
1741 	for (i = 0; protos[i].name != NULL; i++) {
1742 		if (strcasecmp(protos[i].name, pname) == 0) {
1743 			break;
1744 		}
1745 	}
1746 	proto = &protos[i];
1747 	if (proto->name == NULL) {	/* generic handler */
1748 		struct protoent *pe;
1749 		u_long pnum;
1750 
1751 		/* Determine the IP protocol number */
1752 		if ((pe = getprotobyname(pname)) != NULL)
1753 			pnum = pe->p_proto;
1754 		else
1755 			pnum = str2val(optarg, "proto number", 1, 255);
1756 		proto->num = pnum;
1757 	}
1758 	return proto;
1759 }
1760 
1761 void
pkt_compare(const u_char * a,int la,const u_char * b,int lb)1762 pkt_compare(const u_char *a, int la, const u_char *b, int lb) {
1763 	int l;
1764 	int i;
1765 
1766 	for (i = 0; i < la; i++)
1767 		Printf("%02x", (unsigned int)a[i]);
1768 	Printf("\n");
1769 	l = (la <= lb) ? la : lb;
1770 	for (i = 0; i < l; i++)
1771 		if (a[i] == b[i])
1772 			Printf("__");
1773 		else
1774 			Printf("%02x", (unsigned int)b[i]);
1775 	for (; i < lb; i++)
1776 		Printf("%02x", (unsigned int)b[i]);
1777 	Printf("\n");
1778 }
1779 
1780 
1781 void
usage(void)1782 usage(void)
1783 {
1784 	extern char version[];
1785 
1786 	Fprintf(stderr, "Version %s\n", version);
1787 	Fprintf(stderr,
1788 	    "Usage: %s [-adDeFInrSvx] [-f first_ttl] [-g gateway] [-i iface]\n"
1789 	    "\t[-m max_ttl] [-p port] [-P proto] [-q nqueries] [-s src_addr]\n"
1790 	    "\t[-t tos] [-w waittime] [-A as_server] [-z pausemsecs] host [packetlen]\n", prog);
1791 	exit(1);
1792 }
1793