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