Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / contrib / traceroute / traceroute.c
CommitLineData
984263bc
MD
1/*
2 * Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996
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.
1de703da
MD
20 *
21 * @(#) Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996 The Regents of the University of California. All rights reserved.
22 * @(#)$Header: traceroute.c,v 1.43 96/09/27 20:08:10 leres Exp $ (LBL)
23 * $FreeBSD: src/contrib/traceroute/traceroute.c,v 1.11.2.6 2002/08/05 23:37:16 fenner Exp $
24 * $DragonFly: src/contrib/traceroute/Attic/traceroute.c,v 1.2 2003/06/17 04:24:07 dillon Exp $
984263bc
MD
25 */
26
984263bc
MD
27/*
28 * traceroute host - trace the route ip packets follow going to "host".
29 *
30 * Attempt to trace the route an ip packet would follow to some
31 * internet host. We find out intermediate hops by launching probe
32 * packets with a small ttl (time to live) then listening for an
33 * icmp "time exceeded" reply from a gateway. We start our probes
34 * with a ttl of one and increase by one until we get an icmp "port
35 * unreachable" (which means we got to "host") or hit a max (which
36 * defaults to net.inet.ip.ttl hops & can be changed with the -m flag).
37 * Three probes (change with -q flag) are sent at each ttl setting and
38 * a line is printed showing the ttl, address of the gateway and
39 * round trip time of each probe. If the probe answers come from
40 * different gateways, the address of each responding system will
41 * be printed. If there is no response within a 5 sec. timeout
42 * interval (changed with the -w flag), a "*" is printed for that
43 * probe.
44 *
45 * Probe packets are UDP format. We don't want the destination
46 * host to process them so the destination port is set to an
47 * unlikely value (if some clod on the destination is using that
48 * value, it can be changed with the -p flag).
49 *
50 * A sample use might be:
51 *
52 * [yak 71]% traceroute nis.nsf.net.
53 * traceroute to nis.nsf.net (35.1.1.48), 64 hops max, 56 byte packet
54 * 1 helios.ee.lbl.gov (128.3.112.1) 19 ms 19 ms 0 ms
55 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
56 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
57 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 39 ms
58 * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 39 ms 39 ms 39 ms
59 * 6 128.32.197.4 (128.32.197.4) 40 ms 59 ms 59 ms
60 * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 59 ms
61 * 8 129.140.70.13 (129.140.70.13) 99 ms 99 ms 80 ms
62 * 9 129.140.71.6 (129.140.71.6) 139 ms 239 ms 319 ms
63 * 10 129.140.81.7 (129.140.81.7) 220 ms 199 ms 199 ms
64 * 11 nic.merit.edu (35.1.1.48) 239 ms 239 ms 239 ms
65 *
66 * Note that lines 2 & 3 are the same. This is due to a buggy
67 * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
68 * packets with a zero ttl.
69 *
70 * A more interesting example is:
71 *
72 * [yak 72]% traceroute allspice.lcs.mit.edu.
73 * traceroute to allspice.lcs.mit.edu (18.26.0.115), 64 hops max
74 * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
75 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 19 ms 19 ms
76 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 19 ms
77 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 19 ms 39 ms 39 ms
78 * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 20 ms 39 ms 39 ms
79 * 6 128.32.197.4 (128.32.197.4) 59 ms 119 ms 39 ms
80 * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 39 ms
81 * 8 129.140.70.13 (129.140.70.13) 80 ms 79 ms 99 ms
82 * 9 129.140.71.6 (129.140.71.6) 139 ms 139 ms 159 ms
83 * 10 129.140.81.7 (129.140.81.7) 199 ms 180 ms 300 ms
84 * 11 129.140.72.17 (129.140.72.17) 300 ms 239 ms 239 ms
85 * 12 * * *
86 * 13 128.121.54.72 (128.121.54.72) 259 ms 499 ms 279 ms
87 * 14 * * *
88 * 15 * * *
89 * 16 * * *
90 * 17 * * *
91 * 18 ALLSPICE.LCS.MIT.EDU (18.26.0.115) 339 ms 279 ms 279 ms
92 *
93 * (I start to see why I'm having so much trouble with mail to
94 * MIT.) Note that the gateways 12, 14, 15, 16 & 17 hops away
95 * either don't send ICMP "time exceeded" messages or send them
96 * with a ttl too small to reach us. 14 - 17 are running the
97 * MIT C Gateway code that doesn't send "time exceeded"s. God
98 * only knows what's going on with 12.
99 *
100 * The silent gateway 12 in the above may be the result of a bug in
101 * the 4.[23]BSD network code (and its derivatives): 4.x (x <= 3)
102 * sends an unreachable message using whatever ttl remains in the
103 * original datagram. Since, for gateways, the remaining ttl is
104 * zero, the icmp "time exceeded" is guaranteed to not make it back
105 * to us. The behavior of this bug is slightly more interesting
106 * when it appears on the destination system:
107 *
108 * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
109 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 39 ms
110 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 39 ms 19 ms
111 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 19 ms
112 * 5 ccn-nerif35.Berkeley.EDU (128.32.168.35) 39 ms 39 ms 39 ms
113 * 6 csgw.Berkeley.EDU (128.32.133.254) 39 ms 59 ms 39 ms
114 * 7 * * *
115 * 8 * * *
116 * 9 * * *
117 * 10 * * *
118 * 11 * * *
119 * 12 * * *
120 * 13 rip.Berkeley.EDU (128.32.131.22) 59 ms ! 39 ms ! 39 ms !
121 *
122 * Notice that there are 12 "gateways" (13 is the final
123 * destination) and exactly the last half of them are "missing".
124 * What's really happening is that rip (a Sun-3 running Sun OS3.5)
125 * is using the ttl from our arriving datagram as the ttl in its
126 * icmp reply. So, the reply will time out on the return path
127 * (with no notice sent to anyone since icmp's aren't sent for
128 * icmp's) until we probe with a ttl that's at least twice the path
129 * length. I.e., rip is really only 7 hops away. A reply that
130 * returns with a ttl of 1 is a clue this problem exists.
131 * Traceroute prints a "!" after the time if the ttl is <= 1.
132 * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
133 * non-standard (HPUX) software, expect to see this problem
134 * frequently and/or take care picking the target host of your
135 * probes.
136 *
137 * Other possible annotations after the time are !H, !N, !P (got a host,
138 * network or protocol unreachable, respectively), !S or !F (source
139 * route failed or fragmentation needed -- neither of these should
140 * ever occur and the associated gateway is busted if you see one). If
141 * almost all the probes result in some kind of unreachable, traceroute
142 * will give up and exit.
143 *
144 * Notes
145 * -----
146 * This program must be run by root or be setuid. (I suggest that
147 * you *don't* make it setuid -- casual use could result in a lot
148 * of unnecessary traffic on our poor, congested nets.)
149 *
150 * This program requires a kernel mod that does not appear in any
151 * system available from Berkeley: A raw ip socket using proto
152 * IPPROTO_RAW must interpret the data sent as an ip datagram (as
153 * opposed to data to be wrapped in a ip datagram). See the README
154 * file that came with the source to this program for a description
155 * of the mods I made to /sys/netinet/raw_ip.c. Your mileage may
156 * vary. But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
157 * MODIFIED TO RUN THIS PROGRAM.
158 *
159 * The udp port usage may appear bizarre (well, ok, it is bizarre).
160 * The problem is that an icmp message only contains 8 bytes of
161 * data from the original datagram. 8 bytes is the size of a udp
162 * header so, if we want to associate replies with the original
163 * datagram, the necessary information must be encoded into the
164 * udp header (the ip id could be used but there's no way to
165 * interlock with the kernel's assignment of ip id's and, anyway,
166 * it would have taken a lot more kernel hacking to allow this
167 * code to set the ip id). So, to allow two or more users to
168 * use traceroute simultaneously, we use this task's pid as the
169 * source port (the high bit is set to move the port number out
170 * of the "likely" range). To keep track of which probe is being
171 * replied to (so times and/or hop counts don't get confused by a
172 * reply that was delayed in transit), we increment the destination
173 * port number before each probe.
174 *
175 * Don't use this as a coding example. I was trying to find a
176 * routing problem and this code sort-of popped out after 48 hours
177 * without sleep. I was amazed it ever compiled, much less ran.
178 *
179 * I stole the idea for this program from Steve Deering. Since
180 * the first release, I've learned that had I attended the right
181 * IETF working group meetings, I also could have stolen it from Guy
182 * Almes or Matt Mathis. I don't know (or care) who came up with
183 * the idea first. I envy the originators' perspicacity and I'm
184 * glad they didn't keep the idea a secret.
185 *
186 * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
187 * enhancements to the original distribution.
188 *
189 * I've hacked up a round-trip-route version of this that works by
190 * sending a loose-source-routed udp datagram through the destination
191 * back to yourself. Unfortunately, SO many gateways botch source
192 * routing, the thing is almost worthless. Maybe one day...
193 *
194 * -- Van Jacobson (van@ee.lbl.gov)
195 * Tue Dec 20 03:50:13 PST 1988
196 */
197
198#include <sys/param.h>
199#include <sys/file.h>
200#include <sys/ioctl.h>
201#ifdef HAVE_SYS_SELECT_H
202#include <sys/select.h>
203#endif
204#include <sys/socket.h>
205#ifdef HAVE_SYS_SYSCTL_H
206#include <sys/sysctl.h>
207#endif
208#include <sys/time.h>
209
210#include <netinet/in_systm.h>
211#include <netinet/in.h>
212#include <netinet/ip.h>
213#include <netinet/ip_var.h>
214#include <netinet/ip_icmp.h>
215#include <netinet/udp.h>
216#include <netinet/tcp.h>
217
218#include <arpa/inet.h>
219
220#ifdef IPSEC
221#include <net/route.h>
222#include <netinet6/ipsec.h> /* XXX */
223#endif /* IPSEC */
224
225#include <ctype.h>
226#include <errno.h>
227#ifdef HAVE_MALLOC_H
228#include <malloc.h>
229#endif
230#include <memory.h>
231#include <netdb.h>
232#include <stdio.h>
233#include <stdlib.h>
234#include <string.h>
235#include <unistd.h>
236
237#include "gnuc.h"
238#ifdef HAVE_OS_PROTO_H
239#include "os-proto.h"
240#endif
241
242/* Maximum number of gateways (include room for one noop) */
243#define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t)))
244
245#ifndef MAXHOSTNAMELEN
246#define MAXHOSTNAMELEN 64
247#endif
248
249#define Fprintf (void)fprintf
250#define Printf (void)printf
251
252/* What a GRE packet header looks like */
253struct grehdr {
254 u_int16_t flags;
255 u_int16_t proto;
256 u_int16_t length; /* PPTP version of these fields */
257 u_int16_t callId;
258};
259#ifndef IPPROTO_GRE
260#define IPPROTO_GRE 47
261#endif
262
263/* For GRE, we prepare what looks like a PPTP packet */
264#define GRE_PPTP_PROTO 0x880b
265
266/* Data section of the probe packet */
267struct outdata {
268 u_char seq; /* sequence number of this packet */
269 u_char ttl; /* ttl packet left with */
270 struct timeval tv; /* time packet left */
271 int optlen; /* length of ip options */
272};
273
274/* Descriptor structure for each outgoing protocol we support */
275struct outproto {
276 char *name; /* name of protocol */
277 u_char num; /* IP protocol number */
278 u_short hdrlen; /* max size of protocol header */
279 u_short port; /* default base protocol-specific "port" */
280 void (*prepare)(struct outdata *);
281 /* finish preparing an outgoing packet */
282 int (*check)(const u_char *, int);
283 /* check an incoming packet */
284};
285
286u_char packet[512]; /* last inbound (icmp) packet */
287
288struct ip *outip; /* last output ip packet */
289u_char *outprot; /* last output inner protocol packet */
290
291/* loose source route gateway list (including room for final destination) */
292u_int32_t gwlist[NGATEWAYS + 1];
293
294int s; /* receive (icmp) socket file descriptor */
295int sndsock; /* send (udp) socket file descriptor */
296
297struct sockaddr whereto; /* Who to try to reach */
298int packlen; /* total length of packet */
299int protlen; /* length of protocol part of packet */
300int maxpacket = 32 * 1024; /* max ip packet size */
301
302char *prog;
303char *source;
304char *hostname;
305
306int nprobes = 3;
307int min_ttl = 1;
308int max_ttl;
309u_short ident;
310u_short port; /* protocol specific base "port" */
311
312int options; /* socket options */
313int verbose;
314int waittime = 5; /* time to wait for response (in seconds) */
315int nflag; /* print addresses numerically */
316
317extern int optind;
318extern int opterr;
319extern char *optarg;
320
321/* Forwards */
322double deltaT(struct timeval *, struct timeval *);
323u_short in_cksum(u_short *, int);
324char *inetname(struct in_addr);
325int main(int, char **);
326int packet_ok(u_char *, int, struct sockaddr_in *, int);
327char *pr_type(u_char);
328void print(u_char *, int, struct sockaddr_in *);
329char *getaddr(u_int32_t *, char *);
330char *getsin(struct sockaddr_in *, char *);
331char *savestr(const char *);
332#ifdef IPSEC
333int setpolicy __P((int so, char *policy));
334#endif
335void send_probe(int, int);
336void tvsub(struct timeval *, struct timeval *);
337__dead void usage(void);
338int wait_for_reply(int, struct sockaddr_in *, struct timeval *);
339
340void udp_prep(struct outdata *);
341int udp_check(const u_char *, int);
342void tcp_prep(struct outdata *);
343int tcp_check(const u_char *, int);
344void gre_prep(struct outdata *);
345int gre_check(const u_char *, int);
346void gen_prep(struct outdata *);
347int gen_check(const u_char *, int);
348void icmp_prep(struct outdata *);
349int icmp_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 "icmp",
380 IPPROTO_ICMP,
381 sizeof(struct icmp),
382 0,
383 icmp_prep,
384 icmp_check
385 },
386 {
387 NULL,
388 0,
389 2 * sizeof(u_short),
390 0,
391 gen_prep,
392 gen_check
393 },
394};
395struct outproto *proto = &protos[0];
396
397int
398main(int argc, char **argv)
399{
400 register int op, code;
401 register char *cp;
402 struct sockaddr_in from;
403 register struct sockaddr_in *to = (struct sockaddr_in *)&whereto;
404 int on = 1;
405 register struct protoent *pe;
406 register int ttl, probe, i;
407 register int seq = 0;
408 register int tos = 0;
409 register int lsrr = 0;
410 register int optlen = 0;
411 int requestPort = -1;
412 int sump = 0;
413 int sockerrno;
414
415 /*
416 * Do the setuid-required stuff first, then lose priveleges ASAP.
417 * Do error checking for these two calls where they appeared in
418 * the original code.
419 */
420 cp = "icmp";
421 pe = getprotobyname(cp);
422 if (pe) {
423 if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0)
424 sockerrno = errno;
425 else if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
426 sockerrno = errno;
427 }
428
429 setuid(getuid());
430
431#ifdef IPCTL_DEFTTL
432 {
433 int mib[4] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_DEFTTL };
434 size_t sz = sizeof(max_ttl);
435
436 if (sysctl(mib, 4, &max_ttl, &sz, NULL, 0) == -1)
437 err(1, "sysctl(net.inet.ip.ttl)");
438 }
439#else
440 max_ttl = 30;
441#endif
442
443 if ((cp = strrchr(argv[0], '/')) != NULL)
444 prog = cp + 1;
445 else
446 prog = argv[0];
447
448 opterr = 0;
449 while ((op = getopt(argc, argv, "Sdnrvg:M:m:P:p:q:s:t:w:")) != EOF)
450 switch (op) {
451
452 case 'S':
453 sump = 1;
454 break;
455 case 'd':
456 options |= SO_DEBUG;
457 break;
458
459 case 'g':
460 if (lsrr >= NGATEWAYS) {
461 Fprintf(stderr,
462 "%s: No more than %d gateways\n",
463 prog, NGATEWAYS);
464 exit(1);
465 }
466 (void)getaddr(gwlist + lsrr, optarg);
467 ++lsrr;
468 break;
469
470 case 'M':
471 min_ttl = atoi(optarg);
472 if (min_ttl < 1 || min_ttl > 0xff) {
473 Fprintf(stderr, "%s: invalid ttl value %s\n",
474 prog, optarg);
475 exit(1);
476 }
477 break;
478
479 case 'm':
480 max_ttl = atoi(optarg);
481 if (max_ttl < 1 || max_ttl > 0xff) {
482 Fprintf(stderr, "%s: invalid ttl value %s\n",
483 prog, optarg);
484 exit(1);
485 }
486 break;
487
488 case 'n':
489 ++nflag;
490 break;
491
492 case 'P':
493 for (i = 0; protos[i].name != NULL; i++) {
494 if (strcasecmp(protos[i].name, optarg) == 0) {
495 break;
496 }
497 }
498 proto = &protos[i];
499 if (proto->name == NULL) { /* generic handler */
500 struct protoent *pe;
501 u_long pnum;
502 char *eptr;
503
504 /* Determine the IP protocol number */
505 if ((pe = getprotobyname(optarg)) != NULL)
506 pnum = pe->p_proto;
507 else {
508 pnum = strtoul(optarg, &eptr, 10);
509 if (pnum > 0xff
510 || *optarg == '\0'
511 || *eptr != '\0') {
512 Fprintf(stderr, "%s: unknown "
513 "protocol \"%s\"\n",
514 prog, optarg);
515 exit(1);
516 }
517 }
518 proto->num = pnum;
519 }
520 break;
521
522 case 'p':
523 requestPort = atoi(optarg);
524 if (requestPort <= 0) {
525 Fprintf(stderr, "%s: port must be > 0\n", prog);
526 exit(1);
527 }
528 break;
529
530 case 'q':
531 nprobes = atoi(optarg);
532 if (nprobes <= 0) {
533 Fprintf(stderr, "%s: nprobes must be > 0\n",
534 prog);
535 exit(1);
536 }
537 break;
538
539 case 'r':
540 options |= SO_DONTROUTE;
541 break;
542
543 case 's':
544 /*
545 * set the ip source address of the outbound
546 * probe (e.g., on a multi-homed host).
547 */
548 source = optarg;
549 break;
550
551 case 't':
552 tos = atoi(optarg);
553 if (tos < 0 || tos > 255) {
554 Fprintf(stderr, "%s: tos must be 0 to 255\n",
555 prog);
556 exit(1);
557 }
558 break;
559
560 case 'v':
561 ++verbose;
562 break;
563
564 case 'w':
565 waittime = atoi(optarg);
566 if (waittime <= 1 || waittime >= 24L * 60 * 60) {
567 Fprintf(stderr,
568 "%s: wait must be > 1 sec and < 1 day\n",
569 prog);
570 exit(1);
571 }
572 break;
573
574 default:
575 usage();
576 }
577
578 /* Set requested port, if any, else default for this protocol */
579 port = (requestPort != -1) ? requestPort : proto->port;
580
581 /* Check min vs. max TTL */
582 if (min_ttl > max_ttl) {
583 Fprintf(stderr, "%s: min ttl must be <= max ttl\n", prog);
584 exit(1);
585 }
586
587 /* Process destination and optional packet size */
588 switch (argc - optind) {
589
590 case 2:
591 packlen = atoi(argv[optind + 1]);
592 /* Fall thorugh */
593
594 case 1:
595 hostname = savestr(getsin(to, argv[optind]));
596 break;
597
598 default:
599 usage();
600 }
601
602#ifdef HAVE_SETLINEBUF
603 setlinebuf (stdout);
604#else
605 setvbuf(stdout, NULL, _IOLBF, 0);
606#endif
607
608 if (lsrr > 0)
609 optlen = (lsrr + 1) * sizeof(gwlist[0]);
610 i = sizeof(*outip) + proto->hdrlen + sizeof(struct outdata) + optlen;
611 if (packlen == 0)
612 packlen = i; /* minimum sized packet */
613 else if (i > packlen || packlen > maxpacket) {
614 Fprintf(stderr, "%s: packet size must be %d <= s <= %d\n",
615 prog, i, maxpacket);
616 exit(1);
617 }
618 protlen = packlen - sizeof(*outip) - optlen;
619
620 outip = (struct ip *)malloc((unsigned)packlen);
621 if (outip == NULL) {
622 Fprintf(stderr, "%s: malloc: %s\n", prog, strerror(errno));
623 exit(1);
624 }
625 memset((char *)outip, 0, packlen);
626
627 outip->ip_v = IPVERSION;
628 outip->ip_tos = tos;
629#ifdef BYTESWAP_IP_LEN
630 outip->ip_len = htons(packlen);
631#else
632 outip->ip_len = packlen;
633#endif
634 outip->ip_p = proto->num;
635 outprot = (u_char *)(outip + 1);
636#ifdef HAVE_RAW_OPTIONS
637 if (lsrr > 0) {
638 register u_char *optlist;
639
640 optlist = (u_char *)outprot;
641 (u_char *)outprot += optlen;
642
643 /* final hop */
644 gwlist[lsrr] = to->sin_addr.s_addr;
645
646 outip->ip_dst.s_addr = gwlist[0];
647
648 /* force 4 byte alignment */
649 optlist[0] = IPOPT_NOP;
650 /* loose source route option */
651 optlist[1] = IPOPT_LSRR;
652 i = lsrr * sizeof(gwlist[0]);
653 optlist[2] = i + 3;
654 /* Pointer to LSRR addresses */
655 optlist[3] = IPOPT_MINOFF;
656 memcpy(optlist + 4, gwlist + 1, i);
657 } else
658#endif
659 outip->ip_dst = to->sin_addr;
660
661 outip->ip_hl = ((u_char *)outprot - (u_char *)outip) >> 2;
662
663 ident = (getpid() & 0xffff) | 0x8000;
664
665 if (pe == NULL) {
666 Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp);
667 exit(1);
668 }
669 if (s < 0) {
670 errno = sockerrno;
671 Fprintf(stderr, "%s: icmp socket: %s\n", prog, strerror(errno));
672 exit(1);
673 }
674 if (options & SO_DEBUG)
675 (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on,
676 sizeof(on));
677 if (options & SO_DONTROUTE)
678 (void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
679 sizeof(on));
680
681#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
682 if (setpolicy(s, "in bypass") < 0)
683 errx(1, "%s", ipsec_strerror());
684
685 if (setpolicy(s, "out bypass") < 0)
686 errx(1, "%s", ipsec_strerror());
687#endif /* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */
688
689 if (sndsock < 0) {
690 errno = sockerrno;
691 Fprintf(stderr, "%s: raw socket: %s\n", prog, strerror(errno));
692 exit(1);
693 }
694
695#if defined(IP_OPTIONS) && !defined(HAVE_RAW_OPTIONS)
696 if (lsrr > 0) {
697 u_char optlist[MAX_IPOPTLEN];
698
699 cp = "ip";
700 if ((pe = getprotobyname(cp)) == NULL) {
701 Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp);
702 exit(1);
703 }
704
705 /* final hop */
706 gwlist[lsrr] = to->sin_addr.s_addr;
707 ++lsrr;
708
709 /* force 4 byte alignment */
710 optlist[0] = IPOPT_NOP;
711 /* loose source route option */
712 optlist[1] = IPOPT_LSRR;
713 i = lsrr * sizeof(gwlist[0]);
714 optlist[2] = i + 3;
715 /* Pointer to LSRR addresses */
716 optlist[3] = IPOPT_MINOFF;
717 memcpy(optlist + 4, gwlist, i);
718
719 if ((setsockopt(sndsock, pe->p_proto, IP_OPTIONS, optlist,
720 i + sizeof(gwlist[0]))) < 0) {
721 Fprintf(stderr, "%s: IP_OPTIONS: %s\n",
722 prog, strerror(errno));
723 exit(1);
724 }
725 }
726#endif
727
728#ifdef SO_SNDBUF
729 if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&packlen,
730 sizeof(packlen)) < 0) {
731 Fprintf(stderr, "%s: SO_SNDBUF: %s\n", prog, strerror(errno));
732 exit(1);
733 }
734#endif
735#ifdef IP_HDRINCL
736 if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on,
737 sizeof(on)) < 0) {
738 Fprintf(stderr, "%s: IP_HDRINCL: %s\n", prog, strerror(errno));
739 exit(1);
740 }
741#endif
742 if (options & SO_DEBUG)
743 (void)setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on,
744 sizeof(on));
745 if (options & SO_DONTROUTE)
746 (void)setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
747 sizeof(on));
748
749 if (source != NULL) {
750 source = savestr(getsin(&from, source));
751 outip->ip_src = from.sin_addr;
752#ifndef IP_HDRINCL
753 if (bind(sndsock, (struct sockaddr *)&from, sizeof(from)) < 0) {
754 Fprintf(stderr, "%s: bind: %s\n",
755 prog, strerror(errno));
756 exit (1);
757 }
758#endif
759 }
760
761#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
762 if (setpolicy(sndsock, "in bypass") < 0)
763 errx(1, "%s", ipsec_strerror());
764
765 if (setpolicy(sndsock, "out bypass") < 0)
766 errx(1, "%s", ipsec_strerror());
767#endif /* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */
768
769 Fprintf(stderr, "%s to %s (%s)",
770 prog, hostname, inet_ntoa(to->sin_addr));
771 if (source)
772 Fprintf(stderr, " from %s", source);
773 Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, packlen);
774 (void)fflush(stderr);
775
776 for (ttl = min_ttl; ttl <= max_ttl; ++ttl) {
777 u_int32_t lastaddr = 0;
778 int got_there = 0;
779 int unreachable = 0;
780 int loss;
781
782 Printf("%2d ", ttl);
783 for (probe = 0, loss = 0; probe < nprobes; ++probe) {
784 register int cc;
785 struct timeval t1, t2;
786 struct timezone tz;
787 register struct ip *ip;
788 struct outdata outdata;
789
790 /* Prepare outgoing data */
791 outdata.seq = ++seq;
792 outdata.ttl = ttl;
793 outdata.optlen = optlen;
794
795 /* Avoid alignment problems by copying bytewise: */
796 (void)gettimeofday(&t1, &tz);
797 memcpy(&outdata.tv, &t1, sizeof(outdata.tv));
798
799 /* Finalize and send packet */
800 (*proto->prepare)(&outdata);
801 send_probe(seq, ttl);
802
803 /* Wait for a reply */
804 while ((cc = wait_for_reply(s, &from, &t1)) != 0) {
805 double T;
806 int precis;
807
808 (void)gettimeofday(&t2, &tz);
809 i = packet_ok(packet, cc, &from, seq);
810 /* Skip short packet */
811 if (i == 0)
812 continue;
813 if (from.sin_addr.s_addr != lastaddr) {
814 print(packet, cc, &from);
815 lastaddr = from.sin_addr.s_addr;
816 }
817 T = deltaT(&t1, &t2);
818#ifdef SANE_PRECISION
819 if (T >= 1000.0)
820 precis = 0;
821 else if (T >= 100.0)
822 precis = 1;
823 else if (T >= 10.0)
824 precis = 2;
825 else
826#endif
827 precis = 3;
828 Printf(" %.*f ms", precis, T);
829 if (i == -2) {
830#ifndef ARCHAIC
831 ip = (struct ip *)packet;
832 if (ip->ip_ttl <= 1)
833 Printf(" !");
834#endif
835
836 ++got_there;
837 break;
838 }
839
840 /* time exceeded in transit */
841 if (i == -1)
842 break;
843
844 code = i - 1;
845 switch (code) {
846
847 case ICMP_UNREACH_PORT:
848#ifndef ARCHAIC
849 ip = (struct ip *)packet;
850 if (ip->ip_ttl <= 1)
851 Printf(" !");
852#endif
853 ++got_there;
854 break;
855
856 case ICMP_UNREACH_NET:
857 ++unreachable;
858 Printf(" !N");
859 break;
860
861 case ICMP_UNREACH_HOST:
862 ++unreachable;
863 Printf(" !H");
864 break;
865
866 case ICMP_UNREACH_PROTOCOL:
867 ++got_there;
868 Printf(" !P");
869 break;
870
871 case ICMP_UNREACH_NEEDFRAG:
872 ++unreachable;
873 Printf(" !F");
874 break;
875
876 case ICMP_UNREACH_SRCFAIL:
877 ++unreachable;
878 Printf(" !S");
879 break;
880
881/* rfc1716 */
882#ifndef ICMP_UNREACH_FILTER_PROHIB
883#define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohibited filter */
884#endif
885 case ICMP_UNREACH_FILTER_PROHIB:
886 ++unreachable;
887 Printf(" !X");
888 break;
889
890 default:
891 ++unreachable;
892 Printf(" !<%d>", code);
893 break;
894 }
895 break;
896 }
897 if (cc == 0) {
898 loss++;
899 Printf(" *");
900 }
901 (void)fflush(stdout);
902 }
903 if (sump) {
904 Printf(" (%d%% loss)", (loss * 100) / nprobes);
905 }
906 putchar('\n');
907 if (got_there ||
908 (unreachable > 0 && unreachable >= nprobes - 1))
909 break;
910 }
911 exit(0);
912}
913
914int
915wait_for_reply(register int sock, register struct sockaddr_in *fromp,
916 register struct timeval *tp)
917{
918 fd_set *fdsp;
919 size_t nfds;
920 struct timeval now, wait;
921 struct timezone tz;
922 register int cc = 0;
923 register int error;
924 int fromlen = sizeof(*fromp);
925
926 nfds = howmany(sock + 1, NFDBITS);
927 if ((fdsp = malloc(nfds * sizeof(fd_mask))) == NULL)
928 err(1, "malloc");
929 memset(fdsp, 0, nfds * sizeof(fd_mask));
930 FD_SET(sock, fdsp);
931
932 wait.tv_sec = tp->tv_sec + waittime;
933 wait.tv_usec = tp->tv_usec;
934 (void)gettimeofday(&now, &tz);
935 tvsub(&wait, &now);
936 if (wait.tv_sec < 0) {
937 wait.tv_sec = 0;
938 wait.tv_usec = 1;
939 }
940
941 error = select(sock + 1, fdsp, NULL, NULL, &wait);
942 if (error == -1 && errno == EINVAL) {
943 Fprintf(stderr, "%s: botched select() args\n", prog);
944 exit(1);
945 }
946 if (error > 0)
947 cc = recvfrom(s, (char *)packet, sizeof(packet), 0,
948 (struct sockaddr *)fromp, &fromlen);
949
950 free(fdsp);
951 return(cc);
952}
953
954#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
955int
956setpolicy(so, policy)
957 int so;
958 char *policy;
959{
960 char *buf;
961
962 buf = ipsec_set_policy(policy, strlen(policy));
963 if (buf == NULL) {
964 warnx("%s", ipsec_strerror());
965 return -1;
966 }
967 (void)setsockopt(so, IPPROTO_IP, IP_IPSEC_POLICY,
968 buf, ipsec_get_policylen(buf));
969
970 free(buf);
971
972 return 0;
973}
974#endif
975
976void
977send_probe(int seq, int ttl)
978{
979 register int i;
980
981 outip->ip_ttl = ttl;
982 outip->ip_id = htons(ident + seq);
983
984 i = sendto(sndsock, (char *)outip, packlen, 0, &whereto,
985 sizeof(whereto));
986 if (i < 0 || i != packlen) {
987 if (i < 0)
988 Fprintf(stderr, "%s: sendto: %s\n",
989 prog, strerror(errno));
990 Printf("%s: wrote %s %d chars, ret=%d\n",
991 prog, hostname, packlen, i);
992 (void)fflush(stdout);
993 }
994}
995
996double
997deltaT(struct timeval *t1p, struct timeval *t2p)
998{
999 register double dt;
1000
1001 dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
1002 (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
1003 return (dt);
1004}
1005
1006/*
1007 * Convert an ICMP "type" field to a printable string.
1008 */
1009char *
1010pr_type(register u_char t)
1011{
1012 static char *ttab[] = {
1013 "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable",
1014 "Source Quench", "Redirect", "ICMP 6", "ICMP 7",
1015 "Echo", "ICMP 9", "ICMP 10", "Time Exceeded",
1016 "Param Problem", "Timestamp", "Timestamp Reply", "Info Request",
1017 "Info Reply"
1018 };
1019
1020 if (t > 16)
1021 return("OUT-OF-RANGE");
1022
1023 return(ttab[t]);
1024}
1025
1026int
1027packet_ok(register u_char *buf, int cc, register struct sockaddr_in *from,
1028 register int seq)
1029{
1030 register struct icmp *icp;
1031 register u_char type, code;
1032 register int hlen;
1033#ifndef ARCHAIC
1034 register struct ip *ip;
1035
1036 ip = (struct ip *) buf;
1037 hlen = ip->ip_hl << 2;
1038 if (cc < hlen + ICMP_MINLEN) {
1039 if (verbose)
1040 Printf("packet too short (%d bytes) from %s\n", cc,
1041 inet_ntoa(from->sin_addr));
1042 return (0);
1043 }
1044 cc -= hlen;
1045 icp = (struct icmp *)(buf + hlen);
1046#else
1047 icp = (struct icmp *)buf;
1048#endif
1049 type = icp->icmp_type;
1050 code = icp->icmp_code;
1051 if (type == ICMP_ECHOREPLY
1052 && proto->num == IPPROTO_ICMP
1053 && (*proto->check)((u_char *)icp,seq))
1054 return -2;
1055 if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
1056 type == ICMP_UNREACH) {
1057 struct ip *hip;
1058 u_char *inner;
1059
1060 hip = &icp->icmp_ip;
1061 hlen = hip->ip_hl << 2;
1062 inner = (u_char *)((u_char *)hip + hlen);
1063 if (hlen + 12 <= cc
1064 && hip->ip_p == proto->num
1065 && (*proto->check)(inner, seq))
1066 return (type == ICMP_TIMXCEED ? -1 : code + 1);
1067 }
1068#ifndef ARCHAIC
1069 if (verbose) {
1070 register int i;
1071 u_int32_t *lp = (u_int32_t *)&icp->icmp_ip;
1072
1073 Printf("\n%d bytes from %s to ", cc, inet_ntoa(from->sin_addr));
1074 Printf("%s: icmp type %d (%s) code %d\n",
1075 inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code);
1076 for (i = 4; i < cc ; i += sizeof(*lp))
1077 Printf("%2d: x%8.8x\n", i, *lp++);
1078 }
1079#endif
1080 return(0);
1081}
1082
1083void
1084icmp_prep(struct outdata *outdata)
1085{
1086 struct icmp *const icmpheader = (struct icmp *) outprot;
1087
1088 icmpheader->icmp_type = ICMP_ECHO;
1089 icmpheader->icmp_id = htons(ident);
1090 icmpheader->icmp_seq = htons(outdata->seq);
1091
1092 icmpheader->icmp_cksum = 0;
1093 icmpheader->icmp_cksum = in_cksum((u_short *)icmpheader,
1094 packlen - (sizeof(*outip) + outdata->optlen));
1095 if (icmpheader->icmp_cksum == 0)
1096 icmpheader->icmp_cksum = 0xffff;
1097
1098}
1099
1100int
1101icmp_check(const u_char *data, int seq)
1102{
1103 struct icmp *const icmpheader = (struct icmp *) data;
1104
1105 return (icmpheader->icmp_id == htons(ident)
1106 && icmpheader->icmp_seq == htons(seq));
1107}
1108
1109void
1110udp_prep(struct outdata *outdata)
1111{
1112 struct udphdr *const udp = (struct udphdr *) outprot;
1113
1114 udp->uh_sport = htons(ident);
1115 udp->uh_dport = htons(port + outdata->seq);
1116 udp->uh_ulen = htons((u_short)protlen);
1117}
1118
1119int
1120udp_check(const u_char *data, int seq)
1121{
1122 struct udphdr *const udp = (struct udphdr *) data;
1123
1124 return (ntohs(udp->uh_sport) == ident
1125 && ntohs(udp->uh_dport) == port + seq);
1126}
1127
1128void
1129tcp_prep(struct outdata *outdata)
1130{
1131 struct tcphdr *const tcp = (struct tcphdr *) outprot;
1132
1133 tcp->th_sport = htons(ident);
1134 tcp->th_dport = htons(port + outdata->seq);
1135 tcp->th_seq = (tcp->th_sport << 16) | tcp->th_dport;
1136 tcp->th_ack = 0;
1137 tcp->th_off = 5;
1138 tcp->th_flags = TH_SYN;
1139}
1140
1141int
1142tcp_check(const u_char *data, int seq)
1143{
1144 struct tcphdr *const tcp = (struct tcphdr *) data;
1145
1146 return (ntohs(tcp->th_sport) == ident
1147 && ntohs(tcp->th_dport) == port + seq);
1148}
1149
1150void
1151gre_prep(struct outdata *outdata)
1152{
1153 struct grehdr *const gre = (struct grehdr *) outprot;
1154
1155 gre->flags = htons(0x2001);
1156 gre->proto = htons(port);
1157 gre->length = 0;
1158 gre->callId = htons(ident + outdata->seq);
1159}
1160
1161int
1162gre_check(const u_char *data, int seq)
1163{
1164 struct grehdr *const gre = (struct grehdr *) data;
1165
1166 return(ntohs(gre->proto) == port
1167 && ntohs(gre->callId) == ident + seq);
1168}
1169
1170void
1171gen_prep(struct outdata *outdata)
1172{
1173 u_int16_t *const ptr = (u_int16_t *) outprot;
1174
1175 ptr[0] = htons(ident);
1176 ptr[1] = htons(port + outdata->seq);
1177}
1178
1179int
1180gen_check(const u_char *data, int seq)
1181{
1182 u_int16_t *const ptr = (u_int16_t *) data;
1183
1184 return(ntohs(ptr[0]) == ident
1185 && ntohs(ptr[1]) == port + seq);
1186}
1187
1188void
1189print(register u_char *buf, register int cc, register struct sockaddr_in *from)
1190{
1191 register struct ip *ip;
1192 register int hlen;
1193
1194 ip = (struct ip *) buf;
1195 hlen = ip->ip_hl << 2;
1196 cc -= hlen;
1197
1198 if (nflag)
1199 Printf(" %s", inet_ntoa(from->sin_addr));
1200 else
1201 Printf(" %s (%s)", inetname(from->sin_addr),
1202 inet_ntoa(from->sin_addr));
1203
1204 if (verbose)
1205 Printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
1206}
1207
1208/*
1209 * Checksum routine for Internet Protocol family headers (C Version)
1210 */
1211u_short
1212in_cksum(register u_short *addr, register int len)
1213{
1214 register int nleft = len;
1215 register u_short *w = addr;
1216 register u_short answer;
1217 register int sum = 0;
1218
1219 /*
1220 * Our algorithm is simple, using a 32 bit accumulator (sum),
1221 * we add sequential 16 bit words to it, and at the end, fold
1222 * back all the carry bits from the top 16 bits into the lower
1223 * 16 bits.
1224 */
1225 while (nleft > 1) {
1226 sum += *w++;
1227 nleft -= 2;
1228 }
1229
1230 /* mop up an odd byte, if necessary */
1231 if (nleft == 1)
1232 sum += *(u_char *)w;
1233
1234 /*
1235 * add back carry outs from top 16 bits to low 16 bits
1236 */
1237 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
1238 sum += (sum >> 16); /* add carry */
1239 answer = ~sum; /* truncate to 16 bits */
1240 return (answer);
1241}
1242
1243/*
1244 * Subtract 2 timeval structs: out = out - in.
1245 * Out is assumed to be within about LONG_MAX seconds of in.
1246 */
1247void
1248tvsub(register struct timeval *out, register struct timeval *in)
1249{
1250
1251 if ((out->tv_usec -= in->tv_usec) < 0) {
1252 --out->tv_sec;
1253 out->tv_usec += 1000000;
1254 }
1255 out->tv_sec -= in->tv_sec;
1256}
1257
1258/*
1259 * Construct an Internet address representation.
1260 * If the nflag has been supplied, give
1261 * numeric value, otherwise try for symbolic name.
1262 */
1263char *
1264inetname(struct in_addr in)
1265{
1266 register char *cp;
1267 register struct hostent *hp;
1268 static int first = 1;
1269 static char domain[MAXHOSTNAMELEN + 1], line[MAXHOSTNAMELEN + 1];
1270
1271 if (first && !nflag) {
1272 first = 0;
1273 if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
1274 (cp = strchr(domain, '.')) != NULL) {
1275 (void)strncpy(domain, cp + 1, sizeof(domain) - 1);
1276 domain[sizeof(domain) - 1] = '\0';
1277 } else
1278 domain[0] = '\0';
1279 }
1280 if (!nflag && in.s_addr != INADDR_ANY) {
1281 hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET);
1282 if (hp != NULL) {
1283 if ((cp = strchr(hp->h_name, '.')) != NULL &&
1284 strcmp(cp + 1, domain) == 0)
1285 *cp = '\0';
1286 (void)strncpy(line, hp->h_name, sizeof(line) - 1);
1287 line[sizeof(line) - 1] = '\0';
1288 return (line);
1289 }
1290 }
1291 return (inet_ntoa(in));
1292}
1293
1294char *
1295getaddr(register u_int32_t *ap, register char *hostname)
1296{
1297 register struct hostent *hp;
1298
1299 *ap = inet_addr(hostname);
1300 if ((int32_t)*ap != -1)
1301 return (hostname);
1302
1303 hp = gethostbyname(hostname);
1304 if (hp == NULL) {
1305 Fprintf(stderr, "%s: unknown host %s\n", prog, hostname);
1306 exit(1);
1307 }
1308 if (hp->h_addrtype != AF_INET || hp->h_length != 4) {
1309 Fprintf(stderr, "%s: bad host %s\n", prog, hostname);
1310 exit(1);
1311 }
1312 memcpy((caddr_t)ap, hp->h_addr, hp->h_length);
1313 return (hp->h_name);
1314}
1315
1316char *
1317getsin(register struct sockaddr_in *sin, register char *hostname)
1318{
1319
1320 memset(sin, 0, sizeof(*sin));
1321 sin->sin_family = AF_INET;
1322 return (getaddr((u_int32_t *)&sin->sin_addr.s_addr, hostname));
1323}
1324
1325char *
1326savestr(register const char *str)
1327{
1328 register char *cp;
1329
1330 cp = strdup(str);
1331 if (cp == NULL) {
1332 Fprintf(stderr, "%s: strdup: %s\n", prog, strerror(errno));
1333 exit(1);
1334 }
1335 return (cp);
1336}
1337
1338__dead void
1339usage(void)
1340{
1341 extern char version[];
1342
1343 Fprintf(stderr, "Version %s\n", version);
1344 Fprintf(stderr, "Usage: %s [-Sdnrv] [-w wait] [-m max_ttl] [-M min_ttl] \
1345[-P proto]\n\t [-p port#] [-q nqueries] [-t tos] [-s src_addr] [-g gateway] \
1346\n\t host [data_size]\n", prog);
1347 exit(1);
1348}