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