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