1 /* $NetBSD: traceroute.c,v 1.81 2012/08/16 00:40:28 zafer Exp $ */
4 * Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that: (1) source code distributions
9 * retain the above copyright notice and this paragraph in its entirety, (2)
10 * distributions including binary code include the above copyright notice and
11 * this paragraph in its entirety in the documentation or other materials
12 * provided with the distribution, and (3) all advertising materials mentioning
13 * features or use of this software display the following acknowledgement:
14 * ``This product includes software developed by the University of California,
15 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16 * the University nor the names of its contributors may be used to endorse
17 * or promote products derived from this software without specific prior
19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
24 #include <sys/cdefs.h>
27 static const char rcsid
[] =
28 "@(#)Id: traceroute.c,v 1.68 2000/12/14 08:04:33 leres Exp (LBL)";
30 __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997,\
32 The Regents of the University of California. All rights reserved.");
33 __RCSID("$NetBSD: traceroute.c,v 1.81 2012/08/16 00:40:28 zafer Exp $");
38 * traceroute host - trace the route ip packets follow going to "host".
40 * Attempt to trace the route an ip packet would follow to some
41 * internet host. We find out intermediate hops by launching probe
42 * packets with a small ttl (time to live) then listening for an
43 * icmp "time exceeded" reply from a gateway. We start our probes
44 * with a ttl of one and increase by one until we get an icmp "port
45 * unreachable" (which means we got to "host") or hit a max (which
46 * defaults to 30 hops & can be changed with the -m flag). Three
47 * probes (change with -q flag) are sent at each ttl setting and a
48 * line is printed showing the ttl, address of the gateway and
49 * round trip time of each probe. If the probe answers come from
50 * different gateways, the address of each responding system will
51 * be printed. If there is no response within a 5 sec. timeout
52 * interval (changed with the -w flag), a "*" is printed for that
55 * Probe packets are UDP format. We don't want the destination
56 * host to process them so the destination port is set to an
57 * unlikely value (if some clod on the destination is using that
58 * value, it can be changed with the -p flag).
60 * A sample use might be:
62 * [yak 71]% traceroute nis.nsf.net.
63 * traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 56 byte packet
64 * 1 helios.ee.lbl.gov (128.3.112.1) 19 ms 19 ms 0 ms
65 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
66 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
67 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 39 ms
68 * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 39 ms 39 ms 39 ms
69 * 6 128.32.197.4 (128.32.197.4) 40 ms 59 ms 59 ms
70 * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 59 ms
71 * 8 129.140.70.13 (129.140.70.13) 99 ms 99 ms 80 ms
72 * 9 129.140.71.6 (129.140.71.6) 139 ms 239 ms 319 ms
73 * 10 129.140.81.7 (129.140.81.7) 220 ms 199 ms 199 ms
74 * 11 nic.merit.edu (35.1.1.48) 239 ms 239 ms 239 ms
76 * Note that lines 2 & 3 are the same. This is due to a buggy
77 * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
78 * packets with a zero ttl.
80 * A more interesting example is:
82 * [yak 72]% traceroute allspice.lcs.mit.edu.
83 * traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max
84 * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
85 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 19 ms 19 ms
86 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 19 ms
87 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 19 ms 39 ms 39 ms
88 * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 20 ms 39 ms 39 ms
89 * 6 128.32.197.4 (128.32.197.4) 59 ms 119 ms 39 ms
90 * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 39 ms
91 * 8 129.140.70.13 (129.140.70.13) 80 ms 79 ms 99 ms
92 * 9 129.140.71.6 (129.140.71.6) 139 ms 139 ms 159 ms
93 * 10 129.140.81.7 (129.140.81.7) 199 ms 180 ms 300 ms
94 * 11 129.140.72.17 (129.140.72.17) 300 ms 239 ms 239 ms
96 * 13 128.121.54.72 (128.121.54.72) 259 ms 499 ms 279 ms
101 * 18 ALLSPICE.LCS.MIT.EDU (18.26.0.115) 339 ms 279 ms 279 ms
103 * (I start to see why I'm having so much trouble with mail to
104 * MIT.) Note that the gateways 12, 14, 15, 16 & 17 hops away
105 * either don't send ICMP "time exceeded" messages or send them
106 * with a ttl too small to reach us. 14 - 17 are running the
107 * MIT C Gateway code that doesn't send "time exceeded"s. God
108 * only knows what's going on with 12.
110 * The silent gateway 12 in the above may be the result of a bug in
111 * the 4.[23]BSD network code (and its derivatives): 4.x (x <= 3)
112 * sends an unreachable message using whatever ttl remains in the
113 * original datagram. Since, for gateways, the remaining ttl is
114 * zero, the icmp "time exceeded" is guaranteed to not make it back
115 * to us. The behavior of this bug is slightly more interesting
116 * when it appears on the destination system:
118 * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
119 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 39 ms
120 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 39 ms 19 ms
121 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 19 ms
122 * 5 ccn-nerif35.Berkeley.EDU (128.32.168.35) 39 ms 39 ms 39 ms
123 * 6 csgw.Berkeley.EDU (128.32.133.254) 39 ms 59 ms 39 ms
130 * 13 rip.Berkeley.EDU (128.32.131.22) 59 ms ! 39 ms ! 39 ms !
132 * Notice that there are 12 "gateways" (13 is the final
133 * destination) and exactly the last half of them are "missing".
134 * What's really happening is that rip (a Sun-3 running Sun OS3.5)
135 * is using the ttl from our arriving datagram as the ttl in its
136 * icmp reply. So, the reply will time out on the return path
137 * (with no notice sent to anyone since icmp's aren't sent for
138 * icmp's) until we probe with a ttl that's at least twice the path
139 * length. I.e., rip is really only 7 hops away. A reply that
140 * returns with a ttl of 1 is a clue this problem exists.
141 * Traceroute prints a "!" after the time if the ttl is <= 1.
142 * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
143 * non-standard (HPUX) software, expect to see this problem
144 * frequently and/or take care picking the target host of your
147 * Other possible annotations after the time are !H, !N, !P (got a host,
148 * network or protocol unreachable, respectively), !S or !F (source
149 * route failed or fragmentation needed -- neither of these should
150 * ever occur and the associated gateway is busted if you see one). If
151 * almost all the probes result in some kind of unreachable, traceroute
152 * will give up and exit.
156 * This program must be run by root or be setuid. (I suggest that
157 * you *don't* make it setuid -- casual use could result in a lot
158 * of unnecessary traffic on our poor, congested nets.)
160 * This program requires a kernel mod that does not appear in any
161 * system available from Berkeley: A raw ip socket using proto
162 * IPPROTO_RAW must interpret the data sent as an ip datagram (as
163 * opposed to data to be wrapped in a ip datagram). See the README
164 * file that came with the source to this program for a description
165 * of the mods I made to /sys/netinet/raw_ip.c. Your mileage may
166 * vary. But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
167 * MODIFIED TO RUN THIS PROGRAM.
169 * The udp port usage may appear bizarre (well, ok, it is bizarre).
170 * The problem is that an icmp message only contains 8 bytes of
171 * data from the original datagram. 8 bytes is the size of a udp
172 * header so, if we want to associate replies with the original
173 * datagram, the necessary information must be encoded into the
174 * udp header (the ip id could be used but there's no way to
175 * interlock with the kernel's assignment of ip id's and, anyway,
176 * it would have taken a lot more kernel hacking to allow this
177 * code to set the ip id). So, to allow two or more users to
178 * use traceroute simultaneously, we use this task's pid as the
179 * source port (the high bit is set to move the port number out
180 * of the "likely" range). To keep track of which probe is being
181 * replied to (so times and/or hop counts don't get confused by a
182 * reply that was delayed in transit), we increment the destination
183 * port number before each probe.
185 * Don't use this as a coding example. I was trying to find a
186 * routing problem and this code sort-of popped out after 48 hours
187 * without sleep. I was amazed it ever compiled, much less ran.
189 * I stole the idea for this program from Steve Deering. Since
190 * the first release, I've learned that had I attended the right
191 * IETF working group meetings, I also could have stolen it from Guy
192 * Almes or Matt Mathis. I don't know (or care) who came up with
193 * the idea first. I envy the originators' perspicacity and I'm
194 * glad they didn't keep the idea a secret.
196 * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
197 * enhancements to the original distribution.
199 * I've hacked up a round-trip-route version of this that works by
200 * sending a loose-source-routed udp datagram through the destination
201 * back to yourself. Unfortunately, SO many gateways botch source
202 * routing, the thing is almost worthless. Maybe one day...
204 * -- Van Jacobson (van@ee.lbl.gov)
205 * Tue Dec 20 03:50:13 PST 1988
208 #include <sys/param.h>
209 #include <sys/file.h>
210 #include <sys/ioctl.h>
211 #include <sys/socket.h>
212 #include <sys/time.h>
213 #include <sys/sysctl.h>
215 #include <netinet/in_systm.h>
216 #include <netinet/in.h>
217 #include <netinet/ip.h>
218 #include <netinet/ip_var.h>
219 #include <netinet/ip_icmp.h>
220 #include <netinet/udp.h>
221 #include <netinet/udp_var.h>
223 #include <arpa/inet.h>
239 #include <net/route.h>
240 #include <netipsec/ipsec.h>
244 #ifdef HAVE_OS_PROTO_H
245 #include "os-proto.h"
249 #ifndef ICMP_UNREACH_FILTER_PROHIB
250 #define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohibited filter */
252 #ifndef ICMP_UNREACH_HOST_PRECEDENCE
253 #define ICMP_UNREACH_HOST_PRECEDENCE 14 /* host precedence violation */
255 #ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF
256 #define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* precedence cutoff */
259 #include "ifaddrlist.h"
261 #include "prog_ops.h"
263 /* Maximum number of gateways (include room for one noop) */
264 #define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t)))
266 #ifndef MAXHOSTNAMELEN
267 #define MAXHOSTNAMELEN 64
270 #define Fprintf (void)fprintf
271 #define Printf (void)printf
273 /* Host name and address list */
280 /* Data section of the probe packet */
282 u_char seq
; /* sequence number of this packet */
283 u_char ttl
; /* ttl packet left with */
287 } tv
; /* time packet left */
291 * Support for ICMP extensions
293 * http://www.ietf.org/proceedings/01aug/I-D/draft-ietf-mpls-icmp-02.txt
295 #define ICMP_EXT_OFFSET 8 /* ICMP type, code, checksum, unused */ + \
296 128 /* original datagram */
297 #define ICMP_EXT_VERSION 2
299 * ICMP extensions, common header
301 struct icmp_ext_cmn_hdr
{
302 #if BYTE_ORDER == BIG_ENDIAN
303 unsigned char version
:4;
304 unsigned char reserved1
:4;
306 unsigned char reserved1
:4;
307 unsigned char version
:4;
309 unsigned char reserved2
;
310 unsigned short checksum
;
314 * ICMP extensions, object header
316 struct icmp_ext_obj_hdr
{
319 #define MPLS_STACK_ENTRY_CLASS 1
321 #define MPLS_STACK_ENTRY_C_TYPE 1
325 #if BYTE_ORDER == BIG_ENDIAN
338 #ifndef HAVE_ICMP_NEXTMTU
339 /* Path MTU Discovery (RFC1191) */
346 static u_char packet
[512]; /* last inbound (icmp) packet */
348 static struct ip
*outip
; /* last output (udp) packet */
349 static struct udphdr
*outudp
; /* last output (udp) packet */
350 static void *outmark
; /* packed location of struct outdata */
351 static struct outdata outsetup
; /* setup and copy for alignment */
353 static struct icmp
*outicmp
; /* last output (icmp) packet */
355 /* loose source route gateway list (including room for final destination) */
356 static u_int32_t gwlist
[NGATEWAYS
+ 1];
358 static int s
; /* receive (icmp) socket file descriptor */
359 static int sndsock
; /* send (udp/icmp) socket file descriptor */
361 static struct sockaddr whereto
; /* Who to try to reach */
362 static struct sockaddr wherefrom
; /* Who we are */
363 static int packlen
; /* total length of packet */
364 static int minpacket
; /* min ip packet size */
365 static int maxpacket
= 32 * 1024; /* max ip packet size */
366 static int printed_ttl
= 0;
367 static int pmtu
; /* Path MTU Discovery (RFC1191) */
368 static u_int pausemsecs
;
370 static const char *prog
;
372 static char *hostname
;
375 static const char devnull
[] = "/dev/null";
378 static int nprobes
= 3;
379 static int max_ttl
= 30;
380 static int first_ttl
= 1;
381 static u_int16_t ident
;
382 static in_port_t port
= 32768 + 666; /* start udp dest port # for probe packets */
384 static int options
; /* socket options */
386 static int waittime
= 5; /* time to wait for response (in seconds) */
387 static int nflag
; /* print addresses numerically */
389 static int Mflag
; /* show MPLS labels if any */
390 static int as_path
; /* print as numbers for each hop */
391 static char *as_server
= NULL
;
393 static int useicmp
= 0; /* use icmp echo instead of udp packets */
394 #ifdef CANT_HACK_CKSUM
395 static int doipcksum
= 0; /* don't calculate checksums */
397 static int doipcksum
= 1; /* calculate checksums */
399 static int optlen
; /* length of ip options */
401 static int mtus
[] = {
423 static int *mtuptr
= &mtus
[0];
424 static int mtudisc
= 0;
425 static int nextmtu
; /* from ICMP error, set by packet_ok(), might be 0 */
428 static double deltaT(struct timeval
*, struct timeval
*);
429 static void freehostinfo(struct hostinfo
*);
430 static void getaddr(u_int32_t
*, char *);
431 static struct hostinfo
*gethostinfo(char *);
432 static u_int16_t
in_cksum(u_int16_t
*, int);
433 static u_int16_t
in_cksum2(u_int16_t
, u_int16_t
*, int);
434 static char *inetname(struct in_addr
);
435 static int packet_ok(u_char
*, ssize_t
, struct sockaddr_in
*, int);
436 static const char *pr_type(u_char
);
437 static void print(u_char
*, int, struct sockaddr_in
*);
438 static void resize_packet(void);
439 static void dump_packet(void);
440 static void send_probe(int, int, struct timeval
*);
441 static void setsin(struct sockaddr_in
*, u_int32_t
);
442 static int str2val(const char *, const char *, int, int);
443 static void tvsub(struct timeval
*, struct timeval
*);
444 static void usage(void) __attribute__((__noreturn__
));
445 static ssize_t
wait_for_reply(int, struct sockaddr_in
*, const struct timeval
*);
446 static void decode_extensions(unsigned char *buf
, int ip_len
);
447 static void frag_err(void);
448 static int find_local_ip(struct sockaddr_in
*, struct sockaddr_in
*);
450 #ifdef IPSEC_POLICY_IPSEC
451 static int setpolicy(int, const char *);
456 main(int argc
, char **argv
)
461 struct sockaddr_in
*from
= (struct sockaddr_in
*)&wherefrom
;
462 struct sockaddr_in
*to
= (struct sockaddr_in
*)&whereto
;
467 int tos
= 0, settos
= 0, ttl_flag
= 0;
470 struct ifaddrlist
*al
, *al2
;
472 int mib
[4] = { CTL_NET
, PF_INET
, IPPROTO_IP
, IPCTL_DEFTTL
};
473 size_t size
= sizeof(max_ttl
);
475 setprogname(argv
[0]);
476 prog
= getprogname();
478 if (prog_init
&& prog_init() == -1)
479 err(1, "init failed");
482 /* Kernel takes care of it */
483 /* Insure the socket fds won't be 0, 1 or 2 */
484 if (open(devnull
, O_RDONLY
) < 0 ||
485 open(devnull
, O_RDONLY
) < 0 ||
486 open(devnull
, O_RDONLY
) < 0)
487 err(1, "Cannot open `%s'", devnull
);
489 if ((s
= prog_socket(AF_INET
, SOCK_RAW
, IPPROTO_ICMP
)) < 0)
490 err(1, "icmp socket");
493 * XXX 'useicmp' will always be zero here. I think the HP-UX users
494 * running our traceroute code will forgive us.
497 sndsock
= prog_socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
);
499 sndsock
= socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
500 useicmp
? IPPROTO_ICMP
: IPPROTO_UDP
);
503 err(1, "raw socket");
505 (void) prog_sysctl(mib
, sizeof(mib
)/sizeof(mib
[0]), &max_ttl
, &size
,
509 while ((op
= getopt(argc
, argv
, "aA:dDFPIMnlrvxf:g:i:m:p:q:s:t:w:z:")) != -1)
530 first_ttl
= str2val(optarg
, "first ttl", 1, 255);
538 if (lsrr
>= NGATEWAYS
)
539 errx(1, "more than %d gateways", NGATEWAYS
);
540 getaddr(gwlist
+ lsrr
, optarg
);
557 max_ttl
= str2val(optarg
, "max ttl", 1, 255);
569 port
= (u_short
)str2val(optarg
, "port",
574 nprobes
= str2val(optarg
, "nprobes", 1, -1);
578 options
|= SO_DONTROUTE
;
583 * set the ip source address of the outbound
584 * probe (e.g., on a multi-homed host).
590 tos
= str2val(optarg
, "tos", 0, 255);
599 doipcksum
= (doipcksum
== 0);
603 waittime
= str2val(optarg
, "wait time",
608 pausemsecs
= str2val(optarg
, "pause msecs",
620 if (first_ttl
> max_ttl
)
621 errx(1, "first ttl (%d) may not be greater than max ttl (%d)",
625 warnx("ip checksums disabled");
628 optlen
= (lsrr
+ 1) * sizeof(gwlist
[0]);
629 minpacket
= sizeof(*outip
) + sizeof(struct outdata
) + optlen
;
631 minpacket
+= 8; /* XXX magic number */
633 minpacket
+= sizeof(*outudp
);
634 packlen
= minpacket
; /* minimum sized packet */
639 /* Process destination and optional packet size */
640 switch (argc
- optind
) {
643 packlen
= str2val(argv
[optind
+ 1],
644 "packet length", minpacket
, maxpacket
);
648 hostname
= argv
[optind
];
649 hi
= gethostinfo(hostname
);
650 setsin(to
, hi
->addrs
[0]);
652 warnx("%s has multiple addresses; using %s",
653 hostname
, inet_ntoa(to
->sin_addr
));
663 #ifdef HAVE_SETLINEBUF
666 setvbuf(stdout
, NULL
, _IOLBF
, 0);
669 outip
= malloc((unsigned)packlen
);
672 memset(outip
, 0, packlen
);
674 outip
->ip_v
= IPVERSION
;
677 #ifdef BYTESWAP_IP_HDR
678 outip
->ip_len
= htons(packlen
);
679 outip
->ip_off
= htons(off
);
681 outip
->ip_len
= packlen
;
684 outp
= (u_char
*)(outip
+ 1);
685 #ifdef HAVE_RAW_OPTIONS
693 gwlist
[lsrr
] = to
->sin_addr
.s_addr
;
695 outip
->ip_dst
.s_addr
= gwlist
[0];
697 /* force 4 byte alignment */
698 optlist
[0] = IPOPT_NOP
;
699 /* loose source route option */
700 optlist
[1] = IPOPT_LSRR
;
701 i
= lsrr
* sizeof(gwlist
[0]);
703 /* Pointer to LSRR addresses */
704 optlist
[3] = IPOPT_MINOFF
;
705 memcpy(optlist
+ 4, gwlist
+ 1, i
);
708 outip
->ip_dst
= to
->sin_addr
;
710 outip
->ip_hl
= (outp
- (u_char
*)outip
) >> 2;
711 ident
= htons(arc4random() & 0xffff) | 0x8000;
713 outip
->ip_p
= IPPROTO_ICMP
;
715 outicmp
= (struct icmp
*)outp
;
716 outicmp
->icmp_type
= ICMP_ECHO
;
717 outicmp
->icmp_id
= htons(ident
);
719 outmark
= outp
+ 8; /* XXX magic number */
721 outip
->ip_p
= IPPROTO_UDP
;
723 outudp
= (struct udphdr
*)outp
;
724 outudp
->uh_sport
= htons(ident
);
726 htons((u_int16_t
)(packlen
- (sizeof(*outip
) + optlen
)));
727 outmark
= outudp
+ 1;
730 if (options
& SO_DEBUG
)
731 (void)prog_setsockopt(s
, SOL_SOCKET
, SO_DEBUG
, (char *)&on
,
734 #ifdef IPSEC_POLICY_IPSEC
736 * do not raise error even if setsockopt fails, kernel may have ipsec
739 if (setpolicy(s
, "in bypass") < 0)
741 if (setpolicy(s
, "out bypass") < 0)
745 int level
= IPSEC_LEVEL_AVAIL
;
747 (void)prog_setsockopt(s
, IPPROTO_IP
, IP_ESP_TRANS_LEVEL
, &level
,
749 (void)prog_setsockopt(s
, IPPROTO_IP
, IP_ESP_NETWORK_LEVEL
, &level
,
751 #ifdef IP_AUTH_TRANS_LEVEL
752 (void)prog_setsockopt(s
, IPPROTO_IP
, IP_AUTH_TRANS_LEVEL
, &level
,
755 (void)prog_setsockopt(s
, IPPROTO_IP
, IP_AUTH_LEVEL
, &level
,
758 #ifdef IP_AUTH_NETWORK_LEVEL
759 (void)prog_setsockopt(s
, IPPROTO_IP
, IP_AUTH_NETWORK_LEVEL
, &level
,
763 #endif /*IPSEC_POLICY_IPSEC*/
767 #ifdef IPSEC_POLICY_IPSEC
769 * do not raise error even if setsockopt fails, kernel may have ipsec
772 if (setpolicy(sndsock
, "in bypass") < 0)
774 if (setpolicy(sndsock
, "out bypass") < 0)
778 int level
= IPSEC_LEVEL_BYPASS
;
780 (void)prog_setsockopt(sndsock
, IPPROTO_IP
, IP_ESP_TRANS_LEVEL
, &level
,
782 (void)prog_setsockopt(sndsock
, IPPROTO_IP
, IP_ESP_NETWORK_LEVEL
, &level
,
784 #ifdef IP_AUTH_TRANS_LEVEL
785 (void)prog_setsockopt(sndsock
, IPPROTO_IP
, IP_AUTH_TRANS_LEVEL
, &level
,
788 (void)prog_setsockopt(sndsock
, IPPROTO_IP
, IP_AUTH_LEVEL
, &level
,
791 #ifdef IP_AUTH_NETWORK_LEVEL
792 (void)prog_setsockopt(sndsock
, IPPROTO_IP
, IP_AUTH_NETWORK_LEVEL
, &level
,
796 #endif /*IPSEC_POLICY_IPSEC*/
799 #if defined(IP_OPTIONS) && !defined(HAVE_RAW_OPTIONS)
801 u_char optlist
[MAX_IPOPTLEN
];
804 gwlist
[lsrr
] = to
->sin_addr
.s_addr
;
807 /* force 4 byte alignment */
808 optlist
[0] = IPOPT_NOP
;
809 /* loose source route option */
810 optlist
[1] = IPOPT_LSRR
;
811 i
= lsrr
* sizeof(gwlist
[0]);
813 /* Pointer to LSRR addresses */
814 optlist
[3] = IPOPT_MINOFF
;
815 memcpy(optlist
+ 4, gwlist
, i
);
817 if ((prog_setsockopt(sndsock
, IPPROTO_IP
, IP_OPTIONS
, optlist
,
818 i
+ sizeof(gwlist
[0]))) < 0)
819 err(1, "IP_OPTIONS");
824 if (prog_setsockopt(sndsock
, SOL_SOCKET
, SO_SNDBUF
, (char *)&packlen
,
825 sizeof(packlen
)) < 0)
829 if (prog_setsockopt(sndsock
, IPPROTO_IP
, IP_HDRINCL
, (char *)&on
,
831 err(1, "IP_HDRINCL");
834 if (settos
&& prog_setsockopt(sndsock
, IPPROTO_IP
, IP_TOS
,
835 &tos
, sizeof(tos
)) < 0)
836 err(1, "setsockopt tos %d", tos
);
839 if (options
& SO_DEBUG
)
840 if (prog_setsockopt(sndsock
, SOL_SOCKET
, SO_DEBUG
, &on
,
842 err(1, "setsockopt debug %d", tos
);
843 if (options
& SO_DONTROUTE
)
844 if (prog_setsockopt(sndsock
, SOL_SOCKET
, SO_DONTROUTE
, &on
,
846 err(1, "setsockopt dontroute %d", tos
);
848 /* Get the interface address list */
849 n
= ifaddrlist(&al
, errbuf
, sizeof errbuf
);
852 errx(1, "ifaddrlist (%s)", errbuf
);
854 errx(1, "Can't find any network interfaces");
856 /* Look for a specific device */
857 if (device
!= NULL
) {
858 for (i
= n
; i
> 0; --i
, ++al2
)
859 if (strcmp(device
, al2
->device
) == 0)
862 errx(1, "Can't find interface %.32s", device
);
865 /* Determine our source address */
866 if (source
== NULL
) {
868 * If a device was specified, use the interface address.
869 * Otherwise, try to determine our source address.
870 * Warn if there are more than one.
872 setsin(from
, al2
->addr
);
873 if (n
> 1 && device
== NULL
&& !find_local_ip(from
, to
)) {
874 warnx("Multiple interfaces found; using %s @ %s",
875 inet_ntoa(from
->sin_addr
), al2
->device
);
878 hi
= gethostinfo(source
);
881 if (device
== NULL
) {
883 * Use the first interface found.
884 * Warn if there are more than one.
886 setsin(from
, hi
->addrs
[0]);
888 warnx("%s has multiple addresses; using %s",
889 source
, inet_ntoa(from
->sin_addr
));
892 * Make sure the source specified matches the
895 for (i
= hi
->n
, ap
= hi
->addrs
; i
> 0; --i
, ++ap
)
896 if (*ap
== al2
->addr
)
899 errx(1, "%s is not on interface %s",
906 /* Revert to non-privileged user after opening sockets */
911 * If not root, make sure source address matches a local interface.
912 * (The list of addresses produced by ifaddrlist() automatically
913 * excludes interfaces that are marked down and/or loopback.)
917 for (i
= n
; i
> 0; --i
, ++al2
)
918 if (from
->sin_addr
.s_addr
== al2
->addr
)
921 errx(1, "%s is not a valid local address "
922 "and you are not superuser.",
923 inet_ntoa(from
->sin_addr
));
926 outip
->ip_src
= from
->sin_addr
;
928 if (bind(sndsock
, (struct sockaddr
*)from
, sizeof(*from
)) < 0)
933 asn
= as_setup(as_server
);
935 warnx("as_setup failed, AS# lookups disabled");
936 (void)fflush(stderr
);
942 Fprintf(stderr
, "%s to %s (%s)",
943 prog
, hostname
, inet_ntoa(to
->sin_addr
));
945 Fprintf(stderr
, " from %s", source
);
946 Fprintf(stderr
, ", %d hops max, %d byte packets\n", max_ttl
, packlen
);
947 (void)fflush(stderr
);
949 for (ttl
= first_ttl
; ttl
<= max_ttl
; ++ttl
) {
950 u_int32_t lastaddr
= 0;
958 for (probe
= 0; probe
< nprobes
; ++probe
) {
960 struct timeval t1
, t2
;
962 if (sentfirst
&& pausemsecs
> 0)
963 usleep(pausemsecs
* 1000);
964 (void)gettimeofday(&t1
, NULL
);
965 if (!useicmp
&& htons(port
+ seq
+ 1) == 0)
967 send_probe(++seq
, ttl
, &t1
);
969 while ((cc
= wait_for_reply(s
, from
, &t1
)) != 0) {
970 (void)gettimeofday(&t2
, NULL
);
972 * Since we'll be receiving all ICMP
973 * messages to this host above, we may
974 * never end up with cc=0, so we need
975 * an additional termination check.
977 if (t2
.tv_sec
- t1
.tv_sec
> waittime
) {
981 i
= packet_ok(packet
, cc
, from
, seq
);
982 /* Skip short packet */
986 from
->sin_addr
.s_addr
!= lastaddr
) {
987 if (gotlastaddr
) printf("\n ");
988 print(packet
, cc
, from
);
989 lastaddr
= from
->sin_addr
.s_addr
;
992 ip
= (struct ip
*)packet
;
993 Printf(" %.3f ms", deltaT(&t1
, &t2
));
995 Printf(" (ttl = %d)", ip
->ip_ttl
);
1005 /* time exceeded in transit */
1011 case ICMP_UNREACH_PORT
:
1013 if (ip
->ip_ttl
<= 1)
1019 case ICMP_UNREACH_NET
:
1024 case ICMP_UNREACH_HOST
:
1029 case ICMP_UNREACH_PROTOCOL
:
1034 case ICMP_UNREACH_NEEDFRAG
:
1040 Printf(" !F-%d", pmtu
);
1044 case ICMP_UNREACH_SRCFAIL
:
1049 case ICMP_UNREACH_FILTER_PROHIB
:
1054 case ICMP_UNREACH_HOST_PRECEDENCE
:
1059 case ICMP_UNREACH_PRECEDENCE_CUTOFF
:
1066 Printf(" !<%d>", code
);
1073 else if (cc
&& probe
== nprobes
- 1 && Mflag
)
1074 decode_extensions(packet
, cc
);
1075 (void)fflush(stdout
);
1079 (unreachable
> 0 && unreachable
>= ((nprobes
+ 1) / 2)))
1090 wait_for_reply(int sock
, struct sockaddr_in
*fromp
, const struct timeval
*tp
)
1092 struct pollfd set
[1];
1093 struct timeval now
, wait
;
1095 socklen_t fromlen
= sizeof(*fromp
);
1099 set
[0].events
= POLLIN
;
1101 wait
.tv_sec
= tp
->tv_sec
+ waittime
;
1102 wait
.tv_usec
= tp
->tv_usec
;
1103 (void)gettimeofday(&now
, NULL
);
1106 if (wait
.tv_sec
< 0) {
1111 retval
= prog_poll(set
, 1, wait
.tv_sec
* 1000 + wait
.tv_usec
/ 1000);
1113 /* If we continue, we probably just flood the remote host. */
1116 cc
= prog_recvfrom(sock
, (char *)packet
, sizeof(packet
), 0,
1117 (struct sockaddr
*)fromp
, &fromlen
);
1124 decode_extensions(unsigned char *buf
, int ip_len
)
1126 struct icmp_ext_cmn_hdr
*cmn_hdr
;
1127 struct icmp_ext_obj_hdr
*obj_hdr
;
1129 struct mpls_header mpls
;
1132 size_t datalen
, obj_len
;
1135 ip
= (struct ip
*)buf
;
1137 if (ip_len
< (int)((ip
->ip_hl
<< 2) + ICMP_EXT_OFFSET
+
1138 sizeof(struct icmp_ext_cmn_hdr
))) {
1140 * No support for ICMP extensions on this host
1146 * Move forward to the start of the ICMP extensions, if present
1148 buf
+= (ip
->ip_hl
<< 2) + ICMP_EXT_OFFSET
;
1149 cmn_hdr
= (struct icmp_ext_cmn_hdr
*)buf
;
1151 if (cmn_hdr
->version
!= ICMP_EXT_VERSION
) {
1158 datalen
= ip_len
- ((u_char
*)cmn_hdr
- (u_char
*)ip
);
1161 * Check the checksum, cmn_hdr->checksum == 0 means no checksum'ing
1164 * If the checksum is ok, we'll get 0, as the checksum is calculated
1165 * with the checksum field being 0'd.
1167 if (ntohs(cmn_hdr
->checksum
) &&
1168 in_cksum((u_short
*)cmn_hdr
, datalen
)) {
1173 buf
+= sizeof(*cmn_hdr
);
1174 datalen
-= sizeof(*cmn_hdr
);
1176 while (datalen
>= sizeof(struct icmp_ext_obj_hdr
)) {
1177 obj_hdr
= (struct icmp_ext_obj_hdr
*)buf
;
1178 obj_len
= ntohs(obj_hdr
->length
);
1181 * Sanity check the length field
1183 if (obj_len
> datalen
)
1189 * Move past the object header
1191 buf
+= sizeof(struct icmp_ext_obj_hdr
);
1192 obj_len
-= sizeof(struct icmp_ext_obj_hdr
);
1194 switch (obj_hdr
->class_num
) {
1195 case MPLS_STACK_ENTRY_CLASS
:
1196 switch (obj_hdr
->c_type
) {
1197 case MPLS_STACK_ENTRY_C_TYPE
:
1198 while (obj_len
>= sizeof(uint32_t)) {
1199 mpls
.mpls_h
= ntohl(*(uint32_t *)buf
);
1201 buf
+= sizeof(uint32_t);
1202 obj_len
-= sizeof(uint32_t);
1204 printf(" [MPLS: Label %d Exp %d]",
1205 mpls
.mpls
.label
, mpls
.mpls
.exp
);
1209 * Something went wrong, and we're at
1210 * a unknown offset into the packet,
1211 * ditch the rest of it.
1218 * Unknown object, skip past it
1220 buf
+= ntohs(obj_hdr
->length
) -
1221 sizeof(struct icmp_ext_obj_hdr
);
1228 * Unknown object, skip past it
1230 buf
+= ntohs(obj_hdr
->length
) -
1231 sizeof(struct icmp_ext_obj_hdr
);
1243 Fprintf(stderr
, "packet data:");
1246 for (p
= useicmp
? (u_char
*)outicmp
: (u_char
*)outudp
, i
= 0; i
<
1247 i
< packlen
- (sizeof(*outip
) + optlen
); i
++)
1249 for (p
= (u_char
*)outip
, i
= 0; i
< packlen
; i
++)
1253 Fprintf(stderr
, "\n ");
1254 Fprintf(stderr
, " %02x", *p
++);
1256 Fprintf(stderr
, "\n");
1260 send_probe(int seq
, int ttl
, struct timeval
*tp
)
1263 struct udpiphdr
* ui
, *oui
;
1264 int oldmtu
= packlen
;
1268 #ifdef BYTESWAP_IP_LEN
1269 outip
->ip_len
= htons(packlen
);
1271 outip
->ip_len
= packlen
;
1273 outip
->ip_ttl
= ttl
;
1275 outip
->ip_id
= htons(ident
+ seq
);
1279 * In most cases, the kernel will recalculate the ip checksum.
1280 * But we must do it anyway so that the udp checksum comes out
1285 in_cksum((u_int16_t
*)outip
, sizeof(*outip
) + optlen
);
1286 if (outip
->ip_sum
== 0)
1287 outip
->ip_sum
= 0xffff;
1293 outsetup
.tv
.tv32_sec
= htonl(tp
->tv_sec
);
1294 outsetup
.tv
.tv32_usec
= htonl(tp
->tv_usec
);
1295 memcpy(outmark
,&outsetup
,sizeof(outsetup
));
1298 outicmp
->icmp_seq
= htons(seq
);
1300 outudp
->uh_dport
= htons(port
+ seq
);
1303 /* Always calculate checksum for icmp packets */
1304 outicmp
->icmp_cksum
= 0;
1305 outicmp
->icmp_cksum
= in_cksum((u_short
*)outicmp
,
1306 packlen
- (sizeof(*outip
) + optlen
));
1307 if (outicmp
->icmp_cksum
== 0)
1308 outicmp
->icmp_cksum
= 0xffff;
1309 } else if (doipcksum
) {
1310 /* Checksum (we must save and restore ip header) */
1312 ui
= (struct udpiphdr
*)outip
;
1313 oui
= (struct udpiphdr
*)&tip
;
1314 /* Easier to zero and put back things that are ok */
1315 memset(ui
, 0, sizeof(ui
->ui_i
));
1316 ui
->ui_src
= oui
->ui_src
;
1317 ui
->ui_dst
= oui
->ui_dst
;
1318 ui
->ui_pr
= oui
->ui_pr
;
1319 ui
->ui_len
= outudp
->uh_ulen
;
1321 outudp
->uh_sum
= in_cksum((u_short
*)ui
, packlen
);
1322 if (outudp
->uh_sum
== 0)
1323 outudp
->uh_sum
= 0xffff;
1327 /* XXX undocumented debugging hack */
1329 const u_int16_t
*sp
;
1332 sp
= (u_int16_t
*)outip
;
1333 nshorts
= (u_int
)packlen
/ sizeof(u_int16_t
);
1335 Printf("[ %d bytes", packlen
);
1336 while (--nshorts
>= 0) {
1339 Printf(" %04x", ntohs(*sp
++));
1344 Printf(" %02x", *(const u_char
*)sp
);
1349 #if !defined(IP_HDRINCL) && defined(IP_TTL)
1350 if (prog_setsockopt(sndsock
, IPPROTO_IP
, IP_TTL
,
1351 (char *)&ttl
, sizeof(ttl
)) < 0)
1352 err(1, "setsockopt ttl %d", ttl
);
1358 cc
= sendto(sndsock
, useicmp
? (char *)outicmp
: (char *)outudp
,
1359 packlen
- (sizeof(*outip
) + optlen
), 0, &whereto
, sizeof(whereto
));
1361 cc
+= sizeof(*outip
) + optlen
;
1363 cc
= prog_sendto(sndsock
, (char *)outip
,
1364 packlen
, 0, &whereto
, sizeof(whereto
));
1366 if (cc
< 0 || cc
!= packlen
) {
1369 * An errno of EMSGSIZE means we're writing too big a
1370 * datagram for the interface. We have to just
1371 * decrease the packet size until we find one that
1374 * XXX maybe we should try to read the outgoing if's
1377 if (errno
== EMSGSIZE
) {
1378 packlen
= *mtuptr
++;
1385 Printf("%s: wrote %s %d chars, ret=%d\n",
1386 prog
, hostname
, packlen
, cc
);
1387 (void)fflush(stdout
);
1389 if (oldmtu
!= packlen
) {
1390 Printf("message too big, "
1391 "trying new MTU = %d\n", packlen
);
1395 Printf("%2d ", ttl
);
1402 deltaT(struct timeval
*t1p
, struct timeval
*t2p
)
1406 dt
= (double)(t2p
->tv_sec
- t1p
->tv_sec
) * 1000.0 +
1407 (double)(t2p
->tv_usec
- t1p
->tv_usec
) / 1000.0;
1412 * Convert an ICMP "type" field to a printable string.
1417 static const char *ttab
[] = {
1418 "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable",
1419 "Source Quench", "Redirect", "ICMP 6", "ICMP 7",
1420 "Echo", "ICMP 9", "ICMP 10", "Time Exceeded",
1421 "Param Problem", "Timestamp", "Timestamp Reply", "Info Request",
1426 return "OUT-OF-RANGE";
1432 packet_ok(u_char
*buf
, ssize_t cc
, struct sockaddr_in
*from
, int seq
)
1440 ip
= (struct ip
*) buf
;
1441 hlen
= ip
->ip_hl
<< 2;
1442 if (cc
< hlen
+ ICMP_MINLEN
) {
1444 Printf("packet too short (%zd bytes) from %s\n", cc
,
1445 inet_ntoa(from
->sin_addr
));
1449 icp
= (struct icmp
*)(buf
+ hlen
);
1451 icp
= (struct icmp
*)buf
;
1453 type
= icp
->icmp_type
;
1454 code
= icp
->icmp_code
;
1455 /* Path MTU Discovery (RFC1191) */
1456 if (code
!= ICMP_UNREACH_NEEDFRAG
)
1459 #ifdef HAVE_ICMP_NEXTMTU
1460 pmtu
= ntohs(icp
->icmp_nextmtu
);
1462 pmtu
= ntohs(((struct my_pmtu
*)&icp
->icmp_void
)->ipm_nextmtu
);
1465 if ((type
== ICMP_TIMXCEED
&& code
== ICMP_TIMXCEED_INTRANS
) ||
1466 type
== ICMP_UNREACH
|| type
== ICMP_ECHOREPLY
) {
1471 hip
= &icp
->icmp_ip
;
1472 hlen
= hip
->ip_hl
<< 2;
1474 nextmtu
= ntohs(icp
->icmp_nextmtu
); /* for frag_err() */
1478 if (type
== ICMP_ECHOREPLY
&&
1479 icp
->icmp_id
== htons(ident
) &&
1480 icp
->icmp_seq
== htons(seq
))
1483 hicmp
= (struct icmp
*)((u_char
*)hip
+ hlen
);
1484 /* XXX 8 is a magic number */
1485 if (hlen
+ 8 <= cc
&&
1486 hip
->ip_p
== IPPROTO_ICMP
&&
1487 hicmp
->icmp_id
== htons(ident
) &&
1488 hicmp
->icmp_seq
== htons(seq
))
1489 return type
== ICMP_TIMXCEED
? -1 : code
+ 1;
1491 up
= (struct udphdr
*)((u_char
*)hip
+ hlen
);
1492 /* XXX 8 is a magic number */
1493 if (hlen
+ 12 <= cc
&&
1494 hip
->ip_p
== IPPROTO_UDP
&&
1495 up
->uh_sport
== htons(ident
) &&
1496 up
->uh_dport
== htons(port
+ seq
))
1497 return type
== ICMP_TIMXCEED
? -1 : code
+ 1;
1503 u_int32_t
*lp
= (u_int32_t
*)&icp
->icmp_ip
;
1505 Printf("\n%zd bytes from %s to ", cc
, inet_ntoa(from
->sin_addr
));
1506 Printf("%s: icmp type %d (%s) code %d\n",
1507 inet_ntoa(ip
->ip_dst
), type
, pr_type(type
), icp
->icmp_code
);
1508 for (i
= 4; i
< cc
; i
+= sizeof(*lp
))
1509 Printf("%2d: x%8.8x\n", i
, *lp
++);
1519 outicmp
->icmp_cksum
= 0;
1520 outicmp
->icmp_cksum
= in_cksum((u_int16_t
*)outicmp
,
1521 packlen
- (sizeof(*outip
) + optlen
));
1522 if (outicmp
->icmp_cksum
== 0)
1523 outicmp
->icmp_cksum
= 0xffff;
1526 htons((u_int16_t
)(packlen
- (sizeof(*outip
) + optlen
)));
1531 print(u_char
*buf
, int cc
, struct sockaddr_in
*from
)
1535 char addr
[INET_ADDRSTRLEN
];
1537 ip
= (struct ip
*) buf
;
1538 hlen
= ip
->ip_hl
<< 2;
1541 strlcpy(addr
, inet_ntoa(from
->sin_addr
), sizeof(addr
));
1544 Printf(" [AS%u]", as_lookup(asn
, addr
, AF_INET
));
1547 Printf(" %s", addr
);
1549 Printf(" %s (%s)", inetname(from
->sin_addr
), addr
);
1552 Printf(" %d bytes to %s", cc
, inet_ntoa (ip
->ip_dst
));
1556 in_cksum(u_int16_t
*addr
, int len
)
1559 return ~in_cksum2(0, addr
, len
);
1563 * Checksum routine for Internet Protocol family headers (C Version)
1566 in_cksum2(u_int16_t seed
, u_int16_t
*addr
, int len
)
1569 u_int16_t
*w
= addr
;
1577 * Our algorithm is simple, using a 32 bit accumulator (sum),
1578 * we add sequential 16 bit words to it, and at the end, fold
1579 * back all the carry bits from the top 16 bits into the lower
1587 /* mop up an odd byte, if necessary */
1589 answer
.b
[0] = *(u_char
*)w
;
1595 * add back carry outs from top 16 bits to low 16 bits
1597 sum
= (sum
>> 16) + (sum
& 0xffff); /* add hi 16 to low 16 */
1598 sum
+= (sum
>> 16); /* add carry */
1599 answer
.w
= sum
; /* truncate to 16 bits */
1604 * Subtract 2 timeval structs: out = out - in.
1605 * Out is assumed to be >= in.
1608 tvsub(struct timeval
*out
, struct timeval
*in
)
1611 if ((out
->tv_usec
-= in
->tv_usec
) < 0) {
1613 out
->tv_usec
+= 1000000;
1615 out
->tv_sec
-= in
->tv_sec
;
1619 * Construct an Internet address representation.
1620 * If the nflag has been supplied, give
1621 * numeric value, otherwise try for symbolic name.
1624 inetname(struct in_addr in
)
1628 static int first
= 1;
1629 static char domain
[MAXHOSTNAMELEN
+ 1], line
[MAXHOSTNAMELEN
+ 1];
1631 if (first
&& !nflag
) {
1634 if (gethostname(domain
, sizeof(domain
) - 1) < 0)
1637 cp
= strchr(domain
, '.');
1639 hp
= gethostbyname(domain
);
1641 cp
= strchr(hp
->h_name
, '.');
1647 (void)strlcpy(domain
, cp
, sizeof(domain
));
1651 if (!nflag
&& in
.s_addr
!= INADDR_ANY
) {
1652 hp
= gethostbyaddr((char *)&in
, sizeof(in
), AF_INET
);
1654 if ((cp
= strchr(hp
->h_name
, '.')) != NULL
&&
1655 strcmp(cp
+ 1, domain
) == 0)
1657 (void)strlcpy(line
, hp
->h_name
, sizeof(line
));
1661 return inet_ntoa(in
);
1664 static struct hostinfo
*
1665 gethostinfo(char *hname
)
1669 struct hostinfo
*hi
;
1672 struct in_addr addr
;
1674 hi
= calloc(1, sizeof(*hi
));
1677 if (inet_aton(hname
, &addr
) != 0) {
1678 hi
->name
= strdup(hname
);
1682 hi
->addrs
= calloc(1, sizeof(hi
->addrs
[0]));
1683 if (hi
->addrs
== NULL
)
1685 hi
->addrs
[0] = addr
.s_addr
;
1689 hp
= gethostbyname(hname
);
1691 errx(1, "unknown host %s", hname
);
1692 if (hp
->h_addrtype
!= AF_INET
|| hp
->h_length
!= 4)
1693 errx(1, "bad host %s", hname
);
1694 hi
->name
= strdup(hp
->h_name
);
1697 for (n
= 0, p
= hp
->h_addr_list
; *p
!= NULL
; ++n
, ++p
)
1700 hi
->addrs
= calloc(n
, sizeof(hi
->addrs
[0]));
1701 if (hi
->addrs
== NULL
)
1703 for (ap
= hi
->addrs
, p
= hp
->h_addr_list
; *p
!= NULL
; ++ap
, ++p
)
1704 memcpy(ap
, *p
, sizeof(*ap
));
1709 freehostinfo(struct hostinfo
*hi
)
1711 if (hi
->name
!= NULL
) {
1720 getaddr(u_int32_t
*ap
, char *hname
)
1722 struct hostinfo
*hi
;
1724 hi
= gethostinfo(hname
);
1730 setsin(struct sockaddr_in
*sin
, u_int32_t addr
)
1733 memset(sin
, 0, sizeof(*sin
));
1734 #ifdef HAVE_SOCKADDR_SA_LEN
1735 sin
->sin_len
= sizeof(*sin
);
1737 sin
->sin_family
= AF_INET
;
1738 sin
->sin_addr
.s_addr
= addr
;
1741 /* String to value with optional min and max. Handles decimal and hex. */
1743 str2val(const char *str
, const char *what
, int mi
, int ma
)
1751 if (str
[0] == '0' && (str
[1] == 'x' || str
[1] == 'X')) {
1753 val
= strtol(cp
, &ep
, 16);
1755 val
= strtol(str
, &ep
, 10);
1756 if (errno
|| str
[0] == '\0' || *ep
!= '\0')
1757 errx(1, "\"%s\" bad value for %s", str
, what
);
1758 if (val
< mi
&& mi
>= 0) {
1760 errx(1, "%s must be >= %d", what
, mi
);
1762 errx(1, "%s must be > %d", what
, mi
- 1);
1764 if (val
> ma
&& ma
>= 0)
1765 errx(1, "%s must be <= %d", what
, ma
);
1772 extern char version
[];
1774 Fprintf(stderr
, "Version %s\n", version
);
1775 Fprintf(stderr
, "Usage: %s [-adDFPIlMnrvx] [-g gateway] [-i iface] \
1776 [-f first_ttl]\n\t[-m max_ttl] [-p port] [-q nqueries] [-s src_addr] [-t tos]\n\t\
1777 [-w waittime] [-z pausemsecs] [-A as_server] host [packetlen]\n",
1783 * Received ICMP unreachable (fragmentation required and DF set).
1784 * If the ICMP error was from a "new" router, it'll contain the next-hop
1785 * MTU that we should use next. Otherwise we'll just keep going in the
1786 * mtus[] table, trying until we hit a valid MTU.
1795 if (nextmtu
> 0 && nextmtu
< packlen
) {
1796 Printf("\nfragmentation required and DF set, "
1797 "next hop MTU = %d\n",
1800 for (i
= 0; mtus
[i
] > 0; i
++) {
1801 if (mtus
[i
] < nextmtu
) {
1802 mtuptr
= &mtus
[i
]; /* next one to try */
1807 Printf("\nfragmentation required and DF set. ");
1809 Printf("\nBogus next hop MTU = %d > last MTU = %d. ",
1811 packlen
= *mtuptr
++;
1812 Printf("Trying new MTU = %d\n", packlen
);
1818 find_local_ip(struct sockaddr_in
*from
, struct sockaddr_in
*to
)
1821 struct sockaddr_in help
;
1824 sock
= prog_socket(AF_INET
, SOCK_DGRAM
, 0);
1825 if (sock
< 0) return 0;
1827 help
.sin_family
= AF_INET
;
1829 * At this point the port number doesn't matter
1830 * since it only has to be greater than zero.
1833 help
.sin_addr
.s_addr
= to
->sin_addr
.s_addr
;
1834 if (prog_connect(sock
, (struct sockaddr
*)&help
, sizeof(help
)) < 0) {
1835 (void)prog_close(sock
);
1839 help_len
= sizeof(help
);
1840 if (prog_getsockname(sock
, (struct sockaddr
*)&help
, &help_len
) < 0 ||
1841 help_len
!= sizeof(help
) ||
1842 help
.sin_addr
.s_addr
== INADDR_ANY
) {
1843 (void)prog_close(sock
);
1847 (void)prog_close(sock
);
1848 setsin(from
, help
.sin_addr
.s_addr
);
1853 #ifdef IPSEC_POLICY_IPSEC
1855 setpolicy(int so
, const char *policy
)
1859 buf
= ipsec_set_policy(policy
, strlen(policy
));
1861 warnx("%s", ipsec_strerror());
1864 (void)prog_setsockopt(so
, IPPROTO_IP
, IP_IPSEC_POLICY
,
1865 buf
, ipsec_get_policylen(buf
));