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