traceroute.c revision 1.43 1 /* $NetBSD: traceroute.c,v 1.43 2001/10/09 12:43:37 yamt 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.43 2001/10/09 12:43:37 yamt 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 u_short in_cksum2(u_short, u_short *, int);
357 char *inetname(struct in_addr);
358 int main(int, char **);
359 int packet_ok(u_char *, int, struct sockaddr_in *, int);
360 char *pr_type(u_char);
361 void print(u_char *, int, struct sockaddr_in *);
362 void resize_packet(void);
363 void dump_packet(void);
364 void send_probe(int, int, struct timeval *);
365 void setsin(struct sockaddr_in *, u_int32_t);
366 int str2val(const char *, const char *, int, int);
367 void tvsub(struct timeval *, struct timeval *);
368 __dead void usage(void);
369 int wait_for_reply(int, struct sockaddr_in *, struct timeval *);
370 void frag_err(void);
371 int find_local_ip(struct sockaddr_in *, struct sockaddr_in *);
372 #ifdef IPSEC
373 #ifdef IPSEC_POLICY_IPSEC
374 int setpolicy(int so, char *policy);
375 #endif
376 #endif
377
378 int
379 main(int argc, char **argv)
380 {
381 register int op, code, n;
382 register char *cp;
383 register u_char *outp;
384 register u_int32_t *ap;
385 register struct sockaddr_in *from = &wherefrom;
386 register struct sockaddr_in *to = (struct sockaddr_in *)&whereto;
387 register struct hostinfo *hi;
388 int on = 1;
389 register struct protoent *pe;
390 register int ttl, probe, i;
391 register int seq = 0;
392 int tos = 0, settos = 0, ttl_flag = 0;
393 register int lsrr = 0;
394 register u_short off = 0;
395 struct ifaddrlist *al, *al2;
396 char errbuf[132];
397
398 if ((cp = strrchr(argv[0], '/')) != NULL)
399 prog = cp + 1;
400 else
401 prog = argv[0];
402
403 opterr = 0;
404 while ((op = getopt(argc, argv, "dDFPInlrvxf:g:i:m:p:q:s:t:w:")) != -1)
405 switch (op) {
406
407 case 'd':
408 options |= SO_DEBUG;
409 break;
410
411 case 'D':
412 dump = 1;
413 break;
414
415 case 'f':
416 first_ttl = str2val(optarg, "first ttl", 1, 255);
417 break;
418
419 case 'F':
420 off = IP_DF;
421 break;
422
423 case 'g':
424 if (lsrr >= NGATEWAYS) {
425 Fprintf(stderr,
426 "%s: No more than %d gateways\n",
427 prog, NGATEWAYS);
428 exit(1);
429 }
430 getaddr(gwlist + lsrr, optarg);
431 ++lsrr;
432 break;
433
434 case 'i':
435 device = optarg;
436 break;
437
438 case 'I':
439 ++useicmp;
440 break;
441
442 case 'l':
443 ++ttl_flag;
444 break;
445
446 case 'm':
447 max_ttl = str2val(optarg, "max ttl", 1, 255);
448 break;
449
450 case 'n':
451 ++nflag;
452 break;
453
454 case 'p':
455 port = str2val(optarg, "port", 1, -1);
456 break;
457
458 case 'q':
459 nprobes = str2val(optarg, "nprobes", 1, -1);
460 break;
461
462 case 'r':
463 options |= SO_DONTROUTE;
464 break;
465
466 case 's':
467 /*
468 * set the ip source address of the outbound
469 * probe (e.g., on a multi-homed host).
470 */
471 source = optarg;
472 break;
473
474 case 't':
475 tos = str2val(optarg, "tos", 0, 255);
476 ++settos;
477 break;
478
479 case 'v':
480 ++verbose;
481 break;
482
483 case 'x':
484 docksum = (docksum == 0);
485 break;
486
487 case 'w':
488 waittime = str2val(optarg, "wait time", 2, 24 * 3600);
489 break;
490
491 case 'P':
492 off = IP_DF;
493 mtudisc = 1;
494 break;
495
496 default:
497 usage();
498 }
499
500 if (first_ttl > max_ttl) {
501 Fprintf(stderr,
502 "%s: first ttl (%d) may not be greater than max ttl (%d)\n",
503 prog, first_ttl, max_ttl);
504 exit(1);
505 }
506
507 if (!docksum)
508 Fprintf(stderr, "%s: Warning: ckecksums disabled\n", prog);
509
510 if (lsrr > 0)
511 optlen = (lsrr + 1) * sizeof(gwlist[0]);
512 minpacket = sizeof(*outip) + sizeof(struct outdata) + optlen;
513 if (useicmp)
514 minpacket += 8; /* XXX magic number */
515 else
516 minpacket += sizeof(*outudp);
517 if (packlen == 0)
518 packlen = minpacket; /* minimum sized packet */
519 else if (minpacket > packlen || packlen > maxpacket) {
520 Fprintf(stderr, "%s: packet size must be %d <= s <= %d\n",
521 prog, minpacket, maxpacket);
522 exit(1);
523 }
524
525 if (mtudisc)
526 packlen = *mtuptr++;
527
528 /* Process destination and optional packet size */
529 switch (argc - optind) {
530
531 case 2:
532 packlen = str2val(argv[optind + 1],
533 "packet length", minpacket, -1);
534 /* Fall through */
535
536 case 1:
537 hostname = argv[optind];
538 hi = gethostinfo(hostname);
539 setsin(to, hi->addrs[0]);
540 if (hi->n > 1)
541 Fprintf(stderr,
542 "%s: Warning: %s has multiple addresses; using %s\n",
543 prog, hostname, inet_ntoa(to->sin_addr));
544 hostname = hi->name;
545 hi->name = NULL;
546 freehostinfo(hi);
547 break;
548
549 default:
550 usage();
551 }
552
553 #ifdef HAVE_SETLINEBUF
554 setlinebuf (stdout);
555 #else
556 setvbuf(stdout, NULL, _IOLBF, 0);
557 #endif
558
559 outip = (struct ip *)malloc((unsigned)packlen);
560 if (outip == NULL) {
561 Fprintf(stderr, "%s: malloc: %s\n", prog, strerror(errno));
562 exit(1);
563 }
564 memset((char *)outip, 0, packlen);
565
566 outip->ip_v = IPVERSION;
567 if (settos)
568 outip->ip_tos = tos;
569 #ifdef BYTESWAP_IP_LEN
570 outip->ip_len = htons(packlen);
571 #else
572 outip->ip_len = packlen;
573 #endif
574 outip->ip_off = off;
575 outp = (u_char *)(outip + 1);
576 #ifdef HAVE_RAW_OPTIONS
577 if (lsrr > 0) {
578 register u_char *optlist;
579
580 optlist = outp;
581 outp += optlen;
582
583 /* final hop */
584 gwlist[lsrr] = to->sin_addr.s_addr;
585
586 outip->ip_dst.s_addr = gwlist[0];
587
588 /* force 4 byte alignment */
589 optlist[0] = IPOPT_NOP;
590 /* loose source route option */
591 optlist[1] = IPOPT_LSRR;
592 i = lsrr * sizeof(gwlist[0]);
593 optlist[2] = i + 3;
594 /* Pointer to LSRR addresses */
595 optlist[3] = IPOPT_MINOFF;
596 memcpy(optlist + 4, gwlist + 1, i);
597 } else
598 #endif
599 outip->ip_dst = to->sin_addr;
600
601 outip->ip_hl = (outp - (u_char *)outip) >> 2;
602 ident = (getpid() & 0xffff) | 0x8000;
603 if (useicmp) {
604 outip->ip_p = IPPROTO_ICMP;
605
606 outicmp = (struct icmp *)outp;
607 outicmp->icmp_type = ICMP_ECHO;
608 outicmp->icmp_id = htons(ident);
609
610 outmark = outp + 8; /* XXX magic number */
611 } else {
612 outip->ip_p = IPPROTO_UDP;
613
614 outudp = (struct udphdr *)outp;
615 outudp->uh_sport = htons(ident);
616 outudp->uh_ulen =
617 htons((u_short)(packlen - (sizeof(*outip) + optlen)));
618 outmark = outudp + 1;
619 }
620
621 cp = "icmp";
622 if ((pe = getprotobyname(cp)) == NULL) {
623 Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp);
624 exit(1);
625 }
626 if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0) {
627 Fprintf(stderr, "%s: icmp socket: %s\n", prog, strerror(errno));
628 exit(1);
629 }
630 if (options & SO_DEBUG)
631 (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on,
632 sizeof(on));
633 if (options & SO_DONTROUTE)
634 (void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
635 sizeof(on));
636 #ifdef IPSEC
637 #ifdef IPSEC_POLICY_IPSEC
638 /*
639 * do not raise error even if setsockopt fails, kernel may have ipsec
640 * turned off.
641 */
642 if (setpolicy(s, "in bypass") < 0)
643 exit(1);
644 if (setpolicy(s, "out bypass") < 0)
645 exit(1);
646 #else
647 {
648 int level = IPSEC_LEVEL_AVAIL;
649
650 (void)setsockopt(s, IPPROTO_IP, IP_ESP_TRANS_LEVEL, &level,
651 sizeof(level));
652 (void)setsockopt(s, IPPROTO_IP, IP_ESP_NETWORK_LEVEL, &level,
653 sizeof(level));
654 #ifdef IP_AUTH_TRANS_LEVEL
655 (void)setsockopt(s, IPPROTO_IP, IP_AUTH_TRANS_LEVEL, &level,
656 sizeof(level));
657 #else
658 (void)setsockopt(s, IPPROTO_IP, IP_AUTH_LEVEL, &level,
659 sizeof(level));
660 #endif
661 #ifdef IP_AUTH_NETWORK_LEVEL
662 (void)setsockopt(s, IPPROTO_IP, IP_AUTH_NETWORK_LEVEL, &level,
663 sizeof(level));
664 #endif
665 }
666 #endif /*IPSEC_POLICY_IPSEC*/
667 #endif /*IPSEC*/
668
669 #ifndef __hpux
670 sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
671 #else
672 sndsock = socket(AF_INET, SOCK_RAW,
673 useicmp ? IPPROTO_ICMP : IPPROTO_UDP);
674 #endif
675 if (sndsock < 0) {
676 Fprintf(stderr, "%s: raw socket: %s\n", prog, strerror(errno));
677 exit(1);
678 }
679
680 #ifdef IPSEC
681 #ifdef IPSEC_POLICY_IPSEC
682 /*
683 * do not raise error even if setsockopt fails, kernel may have ipsec
684 * turned off.
685 */
686 if (setpolicy(sndsock, "in bypass") < 0)
687 exit(1);
688 if (setpolicy(sndsock, "out bypass") < 0)
689 exit(1);
690 #else
691 {
692 int level = IPSEC_LEVEL_BYPASS;
693
694 (void)setsockopt(sndsock, IPPROTO_IP, IP_ESP_TRANS_LEVEL, &level,
695 sizeof(level));
696 (void)setsockopt(sndsock, IPPROTO_IP, IP_ESP_NETWORK_LEVEL, &level,
697 sizeof(level));
698 #ifdef IP_AUTH_TRANS_LEVEL
699 (void)setsockopt(sndsock, IPPROTO_IP, IP_AUTH_TRANS_LEVEL, &level,
700 sizeof(level));
701 #else
702 (void)setsockopt(sndsock, IPPROTO_IP, IP_AUTH_LEVEL, &level,
703 sizeof(level));
704 #endif
705 #ifdef IP_AUTH_NETWORK_LEVEL
706 (void)setsockopt(sndsock, IPPROTO_IP, IP_AUTH_NETWORK_LEVEL, &level,
707 sizeof(level));
708 #endif
709 }
710 #endif /*IPSEC_POLICY_IPSEC*/
711 #endif /*IPSEC*/
712
713 /* Revert to non-privileged user after opening sockets */
714 setuid(getuid());
715
716 #if defined(IP_OPTIONS) && !defined(HAVE_RAW_OPTIONS)
717 if (lsrr > 0) {
718 u_char optlist[MAX_IPOPTLEN];
719
720 cp = "ip";
721 if ((pe = getprotobyname(cp)) == NULL) {
722 Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp);
723 exit(1);
724 }
725
726 /* final hop */
727 gwlist[lsrr] = to->sin_addr.s_addr;
728 ++lsrr;
729
730 /* force 4 byte alignment */
731 optlist[0] = IPOPT_NOP;
732 /* loose source route option */
733 optlist[1] = IPOPT_LSRR;
734 i = lsrr * sizeof(gwlist[0]);
735 optlist[2] = i + 3;
736 /* Pointer to LSRR addresses */
737 optlist[3] = IPOPT_MINOFF;
738 memcpy(optlist + 4, gwlist, i);
739
740 if ((setsockopt(sndsock, pe->p_proto, IP_OPTIONS, optlist,
741 i + sizeof(gwlist[0]))) < 0) {
742 Fprintf(stderr, "%s: IP_OPTIONS: %s\n",
743 prog, strerror(errno));
744 exit(1);
745 }
746 }
747 #endif
748
749 #ifdef SO_SNDBUF
750 if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&packlen,
751 sizeof(packlen)) < 0) {
752 Fprintf(stderr, "%s: SO_SNDBUF: %s\n", prog, strerror(errno));
753 exit(1);
754 }
755 #endif
756 #ifdef IP_HDRINCL
757 if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on,
758 sizeof(on)) < 0) {
759 Fprintf(stderr, "%s: IP_HDRINCL: %s\n", prog, strerror(errno));
760 exit(1);
761 }
762 #else
763 #ifdef IP_TOS
764 if (settos && setsockopt(sndsock, IPPROTO_IP, IP_TOS,
765 (char *)&tos, sizeof(tos)) < 0) {
766 Fprintf(stderr, "%s: setsockopt tos %d: %s\n",
767 prog, tos, strerror(errno));
768 exit(1);
769 }
770 #endif
771 #endif
772 if (options & SO_DEBUG)
773 (void)setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on,
774 sizeof(on));
775 if (options & SO_DONTROUTE)
776 (void)setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
777 sizeof(on));
778
779 /* Get the interface address list */
780 n = ifaddrlist(&al, errbuf, sizeof errbuf);
781 al2 = al;
782 if (n < 0) {
783 Fprintf(stderr, "%s: ifaddrlist: %s\n", prog, errbuf);
784 exit(1);
785 }
786 if (n == 0) {
787 Fprintf(stderr,
788 "%s: Can't find any network interfaces\n", prog);
789 exit(1);
790 }
791
792 /* Look for a specific device */
793 if (device != NULL) {
794 for (i = n; i > 0; --i, ++al2)
795 if (strcmp(device, al2->device) == 0)
796 break;
797 if (i <= 0) {
798 Fprintf(stderr, "%s: Can't find interface %s\n",
799 prog, device);
800 exit(1);
801 }
802 }
803
804 /* Determine our source address */
805 if (source == NULL) {
806 /*
807 * If a device was specified, use the interface address.
808 * Otherwise, use the first interface found.
809 * Warn if there are more than one.
810 */
811 setsin(from, al2->addr);
812 if (n > 1 && device == NULL && !find_local_ip(from, to)) {
813 Fprintf(stderr,
814 "%s: Warning: Multiple interfaces found; using %s @ %s\n",
815 prog, inet_ntoa(from->sin_addr), al2->device);
816 }
817 } else {
818 hi = gethostinfo(source);
819 source = hi->name;
820 hi->name = NULL;
821 if (device == NULL) {
822 /*
823 * Use the first interface found.
824 * Warn if there are more than one.
825 */
826 setsin(from, hi->addrs[0]);
827 if (hi->n > 1)
828 Fprintf(stderr,
829 "%s: Warning: %s has multiple addresses; using %s\n",
830 prog, source, inet_ntoa(from->sin_addr));
831 } else {
832 /*
833 * Make sure the source specified matches the
834 * interface address.
835 */
836 for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap)
837 if (*ap == al2->addr)
838 break;
839 if (i <= 0) {
840 Fprintf(stderr,
841 "%s: %s is not on interface %s\n",
842 prog, source, device);
843 exit(1);
844 }
845 setsin(from, *ap);
846 }
847 freehostinfo(hi);
848 }
849
850 /*
851 * If not root, make sure source address matches a local interface.
852 * (The list of addresses produced by ifaddrlist() automatically
853 * excludes interfaces that are marked down and/or loopback.)
854 */
855 if (getuid()) {
856 al2 = al;
857 for (i = n; i > 0; --i, ++al2)
858 if (from->sin_addr.s_addr == al2->addr)
859 break;
860 if (i <= 0) {
861 Fprintf(stderr, "%s: %s is not a valid local address "
862 "and you are not superuser.\n", prog,
863 inet_ntoa(from->sin_addr));
864 exit(1);
865 }
866 }
867
868 outip->ip_src = from->sin_addr;
869 #ifndef IP_HDRINCL
870 if (bind(sndsock, (struct sockaddr *)from, sizeof(*from)) < 0) {
871 Fprintf(stderr, "%s: bind: %s\n",
872 prog, strerror(errno));
873 exit (1);
874 }
875 #endif
876
877 setuid(getuid());
878 Fprintf(stderr, "%s to %s (%s)",
879 prog, hostname, inet_ntoa(to->sin_addr));
880 if (source)
881 Fprintf(stderr, " from %s", source);
882 Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, packlen);
883 (void)fflush(stderr);
884
885 for (ttl = first_ttl; ttl <= max_ttl; ++ttl) {
886 u_int32_t lastaddr = 0;
887 int got_there = 0;
888 int unreachable = 0;
889
890 again:
891 printed_ttl = 0;
892 for (probe = 0; probe < nprobes; ++probe) {
893 register int cc;
894 struct timeval t1, t2;
895 struct timezone tz;
896 register struct ip *ip;
897 (void)gettimeofday(&t1, &tz);
898 send_probe(++seq, ttl, &t1);
899 while ((cc = wait_for_reply(s, from, &t1)) != 0) {
900 (void)gettimeofday(&t2, &tz);
901 /*
902 * Since we'll be receiving all ICMP
903 * messages to this host above, we may
904 * never end up with cc=0, so we need
905 * an additional termination check.
906 */
907 if (t2.tv_sec - t1.tv_sec > waittime) {
908 cc = 0;
909 break;
910 }
911 i = packet_ok(packet, cc, from, seq);
912 /* Skip short packet */
913 if (i == 0)
914 continue;
915 if (from->sin_addr.s_addr != lastaddr) {
916 print(packet, cc, from);
917 lastaddr = from->sin_addr.s_addr;
918 }
919 ip = (struct ip *)packet;
920 Printf(" %.3f ms", deltaT(&t1, &t2));
921 if (ttl_flag)
922 Printf(" (ttl = %d)", ip->ip_ttl);
923 if (i == -2) {
924 #ifndef ARCHAIC
925 if (ip->ip_ttl <= 1)
926 Printf(" !");
927 #endif
928 ++got_there;
929 break;
930 }
931
932 /* time exceeded in transit */
933 if (i == -1)
934 break;
935 code = i - 1;
936 switch (code) {
937
938 case ICMP_UNREACH_PORT:
939 #ifndef ARCHAIC
940 if (ip->ip_ttl <= 1)
941 Printf(" !");
942 #endif
943 ++got_there;
944 break;
945
946 case ICMP_UNREACH_NET:
947 ++unreachable;
948 Printf(" !N");
949 break;
950
951 case ICMP_UNREACH_HOST:
952 ++unreachable;
953 Printf(" !H");
954 break;
955
956 case ICMP_UNREACH_PROTOCOL:
957 ++got_there;
958 Printf(" !P");
959 break;
960
961 case ICMP_UNREACH_NEEDFRAG:
962 if (mtudisc) {
963 frag_err();
964 goto again;
965 } else {
966 ++unreachable;
967 Printf(" !F");
968 }
969 break;
970
971 case ICMP_UNREACH_SRCFAIL:
972 ++unreachable;
973 Printf(" !S");
974 break;
975
976 /* rfc1716 */
977 #ifndef ICMP_UNREACH_FILTER_PROHIB
978 #define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohibited filter */
979 #endif
980 case ICMP_UNREACH_FILTER_PROHIB:
981 ++unreachable;
982 Printf(" !X");
983 break;
984
985 default:
986 ++unreachable;
987 Printf(" !<%d>", code);
988 break;
989 }
990 break;
991 }
992 if (cc == 0)
993 Printf(" *");
994 (void)fflush(stdout);
995 }
996 putchar('\n');
997 if (got_there ||
998 (unreachable > 0 && unreachable >= ((nprobes + 1) / 2)))
999 break;
1000 }
1001 exit(0);
1002 }
1003
1004 int
1005 wait_for_reply(register int sock, register struct sockaddr_in *fromp,
1006 register struct timeval *tp)
1007 {
1008 fd_set *fdsp;
1009 size_t nfds;
1010 struct timeval now, wait;
1011 struct timezone tz;
1012 register int cc = 0;
1013 int fromlen = sizeof(*fromp);
1014 int retval;
1015
1016 nfds = howmany(sock + 1, NFDBITS) * sizeof(fd_mask);
1017 if ((fdsp = malloc(nfds)) == NULL) {
1018 Fprintf(stderr, "%s: malloc: %s\n", prog, strerror(errno));
1019 exit(1);
1020 }
1021 memset(fdsp, 0, nfds);
1022 FD_SET(sock, fdsp);
1023
1024 wait.tv_sec = tp->tv_sec + waittime;
1025 wait.tv_usec = tp->tv_usec;
1026 (void)gettimeofday(&now, &tz);
1027 tvsub(&wait, &now);
1028
1029 retval = select(sock + 1, fdsp, NULL, NULL, &wait);
1030 free(fdsp);
1031 if (retval < 0) {
1032 /* If we continue, we probably just flood the remote host. */
1033 Fprintf(stderr, "%s: select: %s\n", prog, strerror(errno));
1034 exit(1);
1035 }
1036 if (retval > 0) {
1037 cc = recvfrom(s, (char *)packet, sizeof(packet), 0,
1038 (struct sockaddr *)fromp, &fromlen);
1039 }
1040
1041 return(cc);
1042 }
1043
1044 void
1045 dump_packet()
1046 {
1047 u_char *p;
1048 int i;
1049
1050 Fprintf(stderr, "packet data:");
1051
1052 #ifdef __hpux
1053 for (p = useicmp ? (u_char *)outicmp : (u_char *)outudp, i = 0; i <
1054 i < packlen - (sizeof(*outip) + optlen); i++)
1055 #else
1056 for (p = (u_char *)outip, i = 0; i < packlen; i++)
1057 #endif
1058 {
1059 if ((i % 24) == 0)
1060 Fprintf(stderr, "\n ");
1061 Fprintf(stderr, " %02x", *p++);
1062 }
1063 Fprintf(stderr, "\n");
1064 }
1065
1066 void
1067 send_probe(register int seq, int ttl, register struct timeval *tp)
1068 {
1069 register int cc;
1070 register struct udpiphdr * ui;
1071 int oldmtu = packlen;
1072
1073 again:
1074 #ifdef BYTESWAP_IP_LEN
1075 outip->ip_len = htons(packlen);
1076 #else
1077 outip->ip_len = packlen;
1078 #endif
1079 outip->ip_ttl = ttl;
1080 #ifndef __hpux
1081 outip->ip_id = htons(ident + seq);
1082 #endif
1083
1084 /*
1085 * In most cases, the kernel will recalculate the ip checksum.
1086 * But we must do it anyway so that the udp checksum comes out
1087 * right.
1088 */
1089 if (docksum) {
1090 outip->ip_sum =
1091 in_cksum((u_short *)outip, sizeof(*outip) + optlen);
1092 if (outip->ip_sum == 0)
1093 outip->ip_sum = 0xffff;
1094 }
1095
1096 /* Payload */
1097 outsetup.seq = seq;
1098 outsetup.ttl = ttl;
1099 outsetup.tv = *tp;
1100 memcpy(outmark,&outsetup,sizeof(outsetup));
1101
1102 if (useicmp)
1103 outicmp->icmp_seq = htons(seq);
1104 else
1105 outudp->uh_dport = htons(port + seq);
1106
1107 /* (We can only do the checksum if we know our ip address) */
1108 if (docksum) {
1109 if (useicmp) {
1110 outicmp->icmp_cksum = 0;
1111 outicmp->icmp_cksum = in_cksum((u_short *)outicmp,
1112 packlen - (sizeof(*outip) + optlen));
1113 if (outicmp->icmp_cksum == 0)
1114 outicmp->icmp_cksum = 0xffff;
1115 } else {
1116 u_short sum;
1117 struct {
1118 struct in_addr src;
1119 struct in_addr dst;
1120 u_int8_t zero;
1121 u_int8_t protocol;
1122 u_int16_t len;
1123 } __attribute__((__packed__)) phdr;
1124
1125 /* Checksum */
1126 ui = (struct udpiphdr *)outip;
1127 memset(&phdr, 0, sizeof(phdr));
1128 phdr.src = ui->ui_src;
1129 phdr.dst = ((struct sockaddr_in *)&whereto)->sin_addr;
1130 phdr.protocol = ui->ui_pr;
1131 phdr.len = outudp->uh_ulen;
1132 outudp->uh_sum = 0;
1133 sum = in_cksum2(0, (u_short *)&phdr, sizeof(phdr));
1134 sum = in_cksum2(sum, (u_short *)outudp, ntohs(outudp->uh_ulen));
1135 outudp->uh_sum = ~sum;
1136 if (outudp->uh_sum == 0)
1137 outudp->uh_sum = 0xffff;
1138 }
1139 }
1140
1141 /* XXX undocumented debugging hack */
1142 if (verbose > 1) {
1143 register const u_short *sp;
1144 register int nshorts, i;
1145
1146 sp = (u_short *)outip;
1147 nshorts = (u_int)packlen / sizeof(u_short);
1148 i = 0;
1149 Printf("[ %d bytes", packlen);
1150 while (--nshorts >= 0) {
1151 if ((i++ % 8) == 0)
1152 Printf("\n\t");
1153 Printf(" %04x", ntohs(*sp++));
1154 }
1155 if (packlen & 1) {
1156 if ((i % 8) == 0)
1157 Printf("\n\t");
1158 Printf(" %02x", *(u_char *)sp);
1159 }
1160 Printf("]\n");
1161 }
1162
1163 #if !defined(IP_HDRINCL) && defined(IP_TTL)
1164 if (setsockopt(sndsock, IPPROTO_IP, IP_TTL,
1165 (char *)&ttl, sizeof(ttl)) < 0) {
1166 Fprintf(stderr, "%s: setsockopt ttl %d: %s\n",
1167 prog, ttl, strerror(errno));
1168 exit(1);
1169 }
1170 #endif
1171 if (dump)
1172 dump_packet();
1173
1174 #ifdef __hpux
1175 cc = sendto(sndsock, useicmp ? (char *)outicmp : (char *)outudp,
1176 packlen - (sizeof(*outip) + optlen), 0, &whereto, sizeof(whereto));
1177 if (cc > 0)
1178 cc += sizeof(*outip) + optlen;
1179 #else
1180 cc = sendto(sndsock, (char *)outip,
1181 packlen, 0, &whereto, sizeof(whereto));
1182 #endif
1183 if (cc < 0 || cc != packlen) {
1184 if (cc < 0) {
1185 /*
1186 * An errno of EMSGSIZE means we're writing too big a
1187 * datagram for the interface. We have to just
1188 * decrease the packet size until we find one that
1189 * works.
1190 *
1191 * XXX maybe we should try to read the outgoing if's
1192 * mtu?
1193 */
1194 if (errno == EMSGSIZE) {
1195 packlen = *mtuptr++;
1196 resize_packet();
1197 goto again;
1198 } else
1199 Fprintf(stderr, "%s: sendto: %s\n",
1200 prog, strerror(errno));
1201 }
1202
1203 Printf("%s: wrote %s %d chars, ret=%d\n",
1204 prog, hostname, packlen, cc);
1205 (void)fflush(stdout);
1206 }
1207 if (oldmtu != packlen) {
1208 Printf("message too big, "
1209 "trying new MTU = %d\n", packlen);
1210 printed_ttl = 0;
1211 }
1212 if (!printed_ttl) {
1213 Printf("%2d ", ttl);
1214 printed_ttl = 1;
1215 }
1216
1217 }
1218
1219 double
1220 deltaT(struct timeval *t1p, struct timeval *t2p)
1221 {
1222 register double dt;
1223
1224 dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
1225 (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
1226 return (dt);
1227 }
1228
1229 /*
1230 * Convert an ICMP "type" field to a printable string.
1231 */
1232 char *
1233 pr_type(register u_char t)
1234 {
1235 static char *ttab[] = {
1236 "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable",
1237 "Source Quench", "Redirect", "ICMP 6", "ICMP 7",
1238 "Echo", "ICMP 9", "ICMP 10", "Time Exceeded",
1239 "Param Problem", "Timestamp", "Timestamp Reply", "Info Request",
1240 "Info Reply"
1241 };
1242
1243 if (t > 16)
1244 return("OUT-OF-RANGE");
1245
1246 return(ttab[t]);
1247 }
1248
1249 int
1250 packet_ok(register u_char *buf, int cc, register struct sockaddr_in *from,
1251 register int seq)
1252 {
1253 register struct icmp *icp;
1254 register u_char type, code;
1255 register int hlen;
1256 #ifndef ARCHAIC
1257 register struct ip *ip;
1258
1259 ip = (struct ip *) buf;
1260 hlen = ip->ip_hl << 2;
1261 if (cc < hlen + ICMP_MINLEN) {
1262 if (verbose)
1263 Printf("packet too short (%d bytes) from %s\n", cc,
1264 inet_ntoa(from->sin_addr));
1265 return (0);
1266 }
1267 cc -= hlen;
1268 icp = (struct icmp *)(buf + hlen);
1269 #else
1270 icp = (struct icmp *)buf;
1271 #endif
1272 type = icp->icmp_type;
1273 code = icp->icmp_code;
1274 if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
1275 type == ICMP_UNREACH || type == ICMP_ECHOREPLY) {
1276 register struct ip *hip;
1277 register struct udphdr *up;
1278 register struct icmp *hicmp;
1279
1280 hip = &icp->icmp_ip;
1281 hlen = hip->ip_hl << 2;
1282
1283 nextmtu = ntohs(icp->icmp_nextmtu); /* for frag_err() */
1284
1285 if (useicmp) {
1286 /* XXX */
1287 if (type == ICMP_ECHOREPLY &&
1288 icp->icmp_id == htons(ident) &&
1289 icp->icmp_seq == htons(seq))
1290 return (-2);
1291
1292 hicmp = (struct icmp *)((u_char *)hip + hlen);
1293 /* XXX 8 is a magic number */
1294 if (hlen + 8 <= cc &&
1295 hip->ip_p == IPPROTO_ICMP &&
1296 hicmp->icmp_id == htons(ident) &&
1297 hicmp->icmp_seq == htons(seq))
1298 return (type == ICMP_TIMXCEED ? -1 : code + 1);
1299 } else {
1300 up = (struct udphdr *)((u_char *)hip + hlen);
1301 /* XXX 8 is a magic number */
1302 if (hlen + 12 <= cc &&
1303 hip->ip_p == IPPROTO_UDP &&
1304 up->uh_sport == htons(ident) &&
1305 up->uh_dport == htons(port + seq))
1306 return (type == ICMP_TIMXCEED ? -1 : code + 1);
1307 }
1308 }
1309 #ifndef ARCHAIC
1310 if (verbose) {
1311 register int i;
1312 u_int32_t *lp = (u_int32_t *)&icp->icmp_ip;
1313
1314 Printf("\n%d bytes from %s to ", cc, inet_ntoa(from->sin_addr));
1315 Printf("%s: icmp type %d (%s) code %d\n",
1316 inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code);
1317 for (i = 4; i < cc ; i += sizeof(*lp))
1318 Printf("%2d: x%8.8x\n", i, *lp++);
1319 }
1320 #endif
1321 return(0);
1322 }
1323
1324 void resize_packet(void)
1325 {
1326 if (useicmp) {
1327 outicmp->icmp_cksum = 0;
1328 outicmp->icmp_cksum = in_cksum((u_short *)outicmp,
1329 packlen - (sizeof(*outip) + optlen));
1330 if (outicmp->icmp_cksum == 0)
1331 outicmp->icmp_cksum = 0xffff;
1332 } else {
1333 outudp->uh_ulen =
1334 htons((u_short)(packlen - (sizeof(*outip) + optlen)));
1335 }
1336 }
1337
1338 void
1339 print(register u_char *buf, register int cc, register struct sockaddr_in *from)
1340 {
1341 register struct ip *ip;
1342 register int hlen;
1343
1344 ip = (struct ip *) buf;
1345 hlen = ip->ip_hl << 2;
1346 cc -= hlen;
1347
1348 if (nflag)
1349 Printf(" %s", inet_ntoa(from->sin_addr));
1350 else
1351 Printf(" %s (%s)", inetname(from->sin_addr),
1352 inet_ntoa(from->sin_addr));
1353
1354 if (verbose)
1355 Printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
1356 }
1357
1358 u_short
1359 in_cksum(u_short *addr, int len)
1360 {
1361
1362 return ~in_cksum2(0, addr, len);
1363 }
1364
1365 /*
1366 * Checksum routine for Internet Protocol family headers (C Version)
1367 */
1368 u_short
1369 in_cksum2(u_short seed, register u_short *addr, register int len)
1370 {
1371 register int nleft = len;
1372 register u_short *w = addr;
1373 register u_short answer;
1374 register int sum = seed;
1375
1376 /*
1377 * Our algorithm is simple, using a 32 bit accumulator (sum),
1378 * we add sequential 16 bit words to it, and at the end, fold
1379 * back all the carry bits from the top 16 bits into the lower
1380 * 16 bits.
1381 */
1382 while (nleft > 1) {
1383 sum += *w++;
1384 nleft -= 2;
1385 }
1386
1387 /* mop up an odd byte, if necessary */
1388 if (nleft == 1)
1389 sum += *(u_char *)w;
1390
1391 /*
1392 * add back carry outs from top 16 bits to low 16 bits
1393 */
1394 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
1395 sum += (sum >> 16); /* add carry */
1396 answer = sum; /* truncate to 16 bits */
1397 return (answer);
1398 }
1399
1400 /*
1401 * Subtract 2 timeval structs: out = out - in.
1402 * Out is assumed to be >= in.
1403 */
1404 void
1405 tvsub(register struct timeval *out, register struct timeval *in)
1406 {
1407
1408 if ((out->tv_usec -= in->tv_usec) < 0) {
1409 --out->tv_sec;
1410 out->tv_usec += 1000000;
1411 }
1412 out->tv_sec -= in->tv_sec;
1413 }
1414
1415 /*
1416 * Construct an Internet address representation.
1417 * If the nflag has been supplied, give
1418 * numeric value, otherwise try for symbolic name.
1419 */
1420 char *
1421 inetname(struct in_addr in)
1422 {
1423 register char *cp;
1424 register struct hostent *hp;
1425 static int first = 1;
1426 static char domain[MAXHOSTNAMELEN + 1], line[MAXHOSTNAMELEN + 1];
1427
1428 if (first && !nflag) {
1429 int rv;
1430
1431 first = 0;
1432 rv = gethostname(domain, sizeof domain);
1433 domain[sizeof(domain) - 1] = '\0';
1434 if (rv == 0 && (cp = strchr(domain, '.')) != NULL) {
1435 (void)strncpy(domain, cp + 1, sizeof(domain) - 1);
1436 } else
1437 domain[0] = '\0';
1438 }
1439 if (!nflag && in.s_addr != INADDR_ANY) {
1440 hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET);
1441 if (hp != NULL) {
1442 if ((cp = strchr(hp->h_name, '.')) != NULL &&
1443 strcmp(cp + 1, domain) == 0)
1444 *cp = '\0';
1445 (void)strncpy(line, hp->h_name, sizeof(line) - 1);
1446 line[sizeof(line) - 1] = '\0';
1447 return (line);
1448 }
1449 }
1450 return (inet_ntoa(in));
1451 }
1452
1453 struct hostinfo *
1454 gethostinfo(register char *hostname)
1455 {
1456 register int n;
1457 register struct hostent *hp;
1458 register struct hostinfo *hi;
1459 register char **p;
1460 register u_int32_t *ap;
1461 struct in_addr addr;
1462
1463 hi = calloc(1, sizeof(*hi));
1464 if (hi == NULL) {
1465 Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
1466 exit(1);
1467 }
1468 if (inet_aton(hostname, &addr) != 0) {
1469 hi->name = strdup(hostname);
1470 hi->n = 1;
1471 hi->addrs = calloc(1, sizeof(hi->addrs[0]));
1472 if (hi->addrs == NULL) {
1473 Fprintf(stderr, "%s: calloc %s\n",
1474 prog, strerror(errno));
1475 exit(1);
1476 }
1477 hi->addrs[0] = addr.s_addr;
1478 return (hi);
1479 }
1480
1481 hp = gethostbyname(hostname);
1482 if (hp == NULL) {
1483 Fprintf(stderr, "%s: unknown host %s\n", prog, hostname);
1484 exit(1);
1485 }
1486 if (hp->h_addrtype != AF_INET || hp->h_length != 4) {
1487 Fprintf(stderr, "%s: bad host %s\n", prog, hostname);
1488 exit(1);
1489 }
1490 hi->name = strdup(hp->h_name);
1491 for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p)
1492 continue;
1493 hi->n = n;
1494 hi->addrs = calloc(n, sizeof(hi->addrs[0]));
1495 if (hi->addrs == NULL) {
1496 Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
1497 exit(1);
1498 }
1499 for (ap = hi->addrs, p = hp->h_addr_list; *p != NULL; ++ap, ++p)
1500 memcpy(ap, *p, sizeof(*ap));
1501 return (hi);
1502 }
1503
1504 void
1505 freehostinfo(register struct hostinfo *hi)
1506 {
1507 if (hi->name != NULL) {
1508 free(hi->name);
1509 hi->name = NULL;
1510 }
1511 free((char *)hi->addrs);
1512 free((char *)hi);
1513 }
1514
1515 void
1516 getaddr(register u_int32_t *ap, register char *hostname)
1517 {
1518 register struct hostinfo *hi;
1519
1520 hi = gethostinfo(hostname);
1521 *ap = hi->addrs[0];
1522 freehostinfo(hi);
1523 }
1524
1525 void
1526 setsin(register struct sockaddr_in *sin, register u_int32_t addr)
1527 {
1528
1529 memset(sin, 0, sizeof(*sin));
1530 #ifdef HAVE_SOCKADDR_SA_LEN
1531 sin->sin_len = sizeof(*sin);
1532 #endif
1533 sin->sin_family = AF_INET;
1534 sin->sin_addr.s_addr = addr;
1535 }
1536
1537 /* String to value with optional min and max. Handles decimal and hex. */
1538 int
1539 str2val(register const char *str, register const char *what,
1540 register int mi, register int ma)
1541 {
1542 register const char *cp;
1543 register int val;
1544 char *ep;
1545
1546 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
1547 cp = str + 2;
1548 val = (int)strtol(cp, &ep, 16);
1549 } else
1550 val = (int)strtol(str, &ep, 10);
1551 if (*ep != '\0') {
1552 Fprintf(stderr, "%s: \"%s\" bad value for %s \n",
1553 prog, str, what);
1554 exit(1);
1555 }
1556 if (val < mi && mi >= 0) {
1557 if (mi == 0)
1558 Fprintf(stderr, "%s: %s must be >= %d\n",
1559 prog, what, mi);
1560 else
1561 Fprintf(stderr, "%s: %s must be > %d\n",
1562 prog, what, mi - 1);
1563 exit(1);
1564 }
1565 if (val > ma && ma >= 0) {
1566 Fprintf(stderr, "%s: %s must be <= %d\n", prog, what, ma);
1567 exit(1);
1568 }
1569 return (val);
1570 }
1571
1572 __dead void
1573 usage(void)
1574 {
1575 extern char version[];
1576
1577 Fprintf(stderr, "Version %s\n", version);
1578 Fprintf(stderr, "Usage: %s [-dDFPIlnrvx] [-g gateway] [-i iface] \
1579 [-f first_ttl] [-m max_ttl]\n\t[ -p port] [-q nqueries] [-s src_addr] [-t tos] \
1580 [-w waittime]\n\thost [packetlen]\n",
1581 prog);
1582 exit(1);
1583 }
1584
1585 /*
1586 * Received ICMP unreachable (fragmentation required and DF set).
1587 * If the ICMP error was from a "new" router, it'll contain the next-hop
1588 * MTU that we should use next. Otherwise we'll just keep going in the
1589 * mtus[] table, trying until we hit a valid MTU.
1590 */
1591
1592
1593 void
1594 frag_err()
1595 {
1596 int i;
1597
1598 if (nextmtu > 0 && nextmtu < packlen) {
1599 Printf("\nfragmentation required and DF set, "
1600 "next hop MTU = %d\n",
1601 nextmtu);
1602 packlen = nextmtu;
1603 for (i = 0; mtus[i] > 0; i++) {
1604 if (mtus[i] < nextmtu) {
1605 mtuptr = &mtus[i]; /* next one to try */
1606 break;
1607 }
1608 }
1609 } else {
1610 Printf("\nfragmentation required and DF set. ");
1611 if (nextmtu)
1612 Printf("\nBogus next hop MTU = %d > last MTU = %d. ",
1613 nextmtu, packlen);
1614 packlen = *mtuptr++;
1615 Printf("Trying new MTU = %d\n", packlen);
1616 }
1617 resize_packet();
1618 }
1619
1620 int
1621 find_local_ip(struct sockaddr_in *from, struct sockaddr_in *to)
1622 {
1623 int sock;
1624 struct sockaddr_in help;
1625 int help_len;
1626
1627 sock = socket(AF_INET, SOCK_DGRAM, 0);
1628 if (sock < 0) return (0);
1629
1630 help.sin_family = AF_INET;
1631 /*
1632 * At this point the port number doesn't matter
1633 * since it only has to be greater than zero.
1634 */
1635 help.sin_port = 42;
1636 help.sin_addr.s_addr = to->sin_addr.s_addr;
1637 if (connect(sock, (struct sockaddr *)&help, sizeof(help)) < 0) {
1638 (void)close(sock);
1639 return (0);
1640 }
1641
1642 help_len = sizeof(help);
1643 if (getsockname(sock, (struct sockaddr *)&help, &help_len) < 0 ||
1644 help_len != sizeof(help) ||
1645 help.sin_addr.s_addr == INADDR_ANY) {
1646 (void)close(sock);
1647 return (0);
1648 }
1649
1650 (void)close(sock);
1651 setsin(from, help.sin_addr.s_addr);
1652 return (1);
1653 }
1654
1655 #ifdef IPSEC
1656 #ifdef IPSEC_POLICY_IPSEC
1657 int
1658 setpolicy(so, policy)
1659 int so;
1660 char *policy;
1661 {
1662 char *buf;
1663
1664 buf = ipsec_set_policy(policy, strlen(policy));
1665 if (buf == NULL) {
1666 Fprintf(stderr, "%s: %s\n", prog, ipsec_strerror());
1667 return -1;
1668 }
1669 (void)setsockopt(so, IPPROTO_IP, IP_IPSEC_POLICY,
1670 buf, ipsec_get_policylen(buf));
1671
1672 free(buf);
1673
1674 return 0;
1675 }
1676 #endif
1677 #endif
1678
1679