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