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