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