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