traceroute.c revision 1.52 1 /* $NetBSD: traceroute.c,v 1.52 2002/08/09 02:57:09 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.52 2002/08/09 02:57:09 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 int op, code, n;
387 char *cp;
388 u_char *outp;
389 u_int32_t *ap;
390 struct sockaddr_in *from = &wherefrom;
391 struct sockaddr_in *to = (struct sockaddr_in *)&whereto;
392 struct hostinfo *hi;
393 int on = 1;
394 int ttl, probe, i;
395 int seq = 0;
396 int tos = 0, settos = 0, ttl_flag = 0;
397 int lsrr = 0;
398 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 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 int cc;
911 struct timeval t1, t2;
912 struct ip *ip;
913 (void)gettimeofday(&t1, NULL);
914 send_probe(++seq, ttl, &t1);
915 while ((cc = wait_for_reply(s, from, &t1)) != 0) {
916 (void)gettimeofday(&t2, NULL);
917 /*
918 * Since we'll be receiving all ICMP
919 * messages to this host above, we may
920 * never end up with cc=0, so we need
921 * an additional termination check.
922 */
923 if (t2.tv_sec - t1.tv_sec > waittime) {
924 cc = 0;
925 break;
926 }
927 i = packet_ok(packet, cc, from, seq);
928 /* Skip short packet */
929 if (i == 0)
930 continue;
931 if (from->sin_addr.s_addr != lastaddr) {
932 print(packet, cc, from);
933 lastaddr = from->sin_addr.s_addr;
934 }
935 ip = (struct ip *)packet;
936 Printf(" %.3f ms", deltaT(&t1, &t2));
937 if (ttl_flag)
938 Printf(" (ttl = %d)", ip->ip_ttl);
939 if (i == -2) {
940 #ifndef ARCHAIC
941 if (ip->ip_ttl <= 1)
942 Printf(" !");
943 #endif
944 ++got_there;
945 break;
946 }
947
948 /* time exceeded in transit */
949 if (i == -1)
950 break;
951 code = i - 1;
952 switch (code) {
953
954 case ICMP_UNREACH_PORT:
955 #ifndef ARCHAIC
956 if (ip->ip_ttl <= 1)
957 Printf(" !");
958 #endif
959 ++got_there;
960 break;
961
962 case ICMP_UNREACH_NET:
963 ++unreachable;
964 Printf(" !N");
965 break;
966
967 case ICMP_UNREACH_HOST:
968 ++unreachable;
969 Printf(" !H");
970 break;
971
972 case ICMP_UNREACH_PROTOCOL:
973 ++got_there;
974 Printf(" !P");
975 break;
976
977 case ICMP_UNREACH_NEEDFRAG:
978 if (mtudisc) {
979 frag_err();
980 goto again;
981 } else {
982 ++unreachable;
983 Printf(" !F");
984 }
985 break;
986
987 case ICMP_UNREACH_SRCFAIL:
988 ++unreachable;
989 Printf(" !S");
990 break;
991
992 /* rfc1716 */
993 #ifndef ICMP_UNREACH_FILTER_PROHIB
994 #define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohibited filter */
995 #endif
996 case ICMP_UNREACH_FILTER_PROHIB:
997 ++unreachable;
998 Printf(" !X");
999 break;
1000
1001 default:
1002 ++unreachable;
1003 Printf(" !<%d>", code);
1004 break;
1005 }
1006 break;
1007 }
1008 if (cc == 0)
1009 Printf(" *");
1010 (void)fflush(stdout);
1011 }
1012 putchar('\n');
1013 if (got_there ||
1014 (unreachable > 0 && unreachable >= ((nprobes + 1) / 2)))
1015 break;
1016 }
1017
1018 if (as_path)
1019 as_shutdown(asn);
1020
1021 exit(0);
1022 }
1023
1024 int
1025 wait_for_reply(int sock, struct sockaddr_in *fromp, struct timeval *tp)
1026 {
1027 fd_set *fdsp;
1028 size_t nfds;
1029 struct timeval now, wait;
1030 int cc = 0;
1031 int fromlen = sizeof(*fromp);
1032 int retval;
1033
1034 nfds = howmany(sock + 1, NFDBITS) * sizeof(fd_mask);
1035 if ((fdsp = malloc(nfds)) == NULL) {
1036 Fprintf(stderr, "%s: malloc: %s\n", prog, strerror(errno));
1037 exit(1);
1038 }
1039 memset(fdsp, 0, nfds);
1040 FD_SET(sock, fdsp);
1041
1042 wait.tv_sec = tp->tv_sec + waittime;
1043 wait.tv_usec = tp->tv_usec;
1044 (void)gettimeofday(&now, NULL);
1045 tvsub(&wait, &now);
1046
1047 if (wait.tv_sec < 0) {
1048 wait.tv_sec = 0;
1049 wait.tv_usec = 0;
1050 }
1051
1052 retval = select(sock + 1, fdsp, NULL, NULL, &wait);
1053 free(fdsp);
1054 if (retval < 0) {
1055 /* If we continue, we probably just flood the remote host. */
1056 Fprintf(stderr, "%s: select: %s\n", prog, strerror(errno));
1057 exit(1);
1058 }
1059 if (retval > 0) {
1060 cc = recvfrom(s, (char *)packet, sizeof(packet), 0,
1061 (struct sockaddr *)fromp, &fromlen);
1062 }
1063
1064 return(cc);
1065 }
1066
1067 void
1068 dump_packet()
1069 {
1070 u_char *p;
1071 int i;
1072
1073 Fprintf(stderr, "packet data:");
1074
1075 #ifdef __hpux
1076 for (p = useicmp ? (u_char *)outicmp : (u_char *)outudp, i = 0; i <
1077 i < packlen - (sizeof(*outip) + optlen); i++)
1078 #else
1079 for (p = (u_char *)outip, i = 0; i < packlen; i++)
1080 #endif
1081 {
1082 if ((i % 24) == 0)
1083 Fprintf(stderr, "\n ");
1084 Fprintf(stderr, " %02x", *p++);
1085 }
1086 Fprintf(stderr, "\n");
1087 }
1088
1089 void
1090 send_probe(int seq, int ttl, struct timeval *tp)
1091 {
1092 int cc;
1093 struct udpiphdr * ui;
1094 int oldmtu = packlen;
1095
1096 again:
1097 #ifdef BYTESWAP_IP_LEN
1098 outip->ip_len = htons(packlen);
1099 #else
1100 outip->ip_len = packlen;
1101 #endif
1102 outip->ip_ttl = ttl;
1103 #ifndef __hpux
1104 outip->ip_id = htons(ident + seq);
1105 #endif
1106
1107 /*
1108 * In most cases, the kernel will recalculate the ip checksum.
1109 * But we must do it anyway so that the udp checksum comes out
1110 * right.
1111 */
1112 if (docksum) {
1113 outip->ip_sum =
1114 in_cksum((u_int16_t *)outip, sizeof(*outip) + optlen);
1115 if (outip->ip_sum == 0)
1116 outip->ip_sum = 0xffff;
1117 }
1118
1119 /* Payload */
1120 outsetup.seq = seq;
1121 outsetup.ttl = ttl;
1122 outsetup.tv = *tp;
1123 memcpy(outmark,&outsetup,sizeof(outsetup));
1124
1125 if (useicmp)
1126 outicmp->icmp_seq = htons(seq);
1127 else
1128 outudp->uh_dport = htons(port + seq);
1129
1130 /* (We can only do the checksum if we know our ip address) */
1131 if (docksum) {
1132 if (useicmp) {
1133 outicmp->icmp_cksum = 0;
1134 outicmp->icmp_cksum = in_cksum((u_int16_t *)outicmp,
1135 packlen - (sizeof(*outip) + optlen));
1136 if (outicmp->icmp_cksum == 0)
1137 outicmp->icmp_cksum = 0xffff;
1138 } else {
1139 u_int16_t sum;
1140 struct {
1141 struct in_addr src;
1142 struct in_addr dst;
1143 u_int8_t zero;
1144 u_int8_t protocol;
1145 u_int16_t len;
1146 } __attribute__((__packed__)) phdr;
1147
1148 /* Checksum */
1149 ui = (struct udpiphdr *)outip;
1150 memset(&phdr, 0, sizeof(phdr));
1151 phdr.src = ui->ui_src;
1152 phdr.dst = ((struct sockaddr_in *)&whereto)->sin_addr;
1153 phdr.protocol = ui->ui_pr;
1154 phdr.len = outudp->uh_ulen;
1155 outudp->uh_sum = 0;
1156 sum = in_cksum2(0, (u_int16_t *)&phdr, sizeof(phdr));
1157 sum = in_cksum2(sum, (u_int16_t *)outudp, ntohs(outudp->uh_ulen));
1158 sum = ~sum; /** XXXSCW: Quell SuperH Compiler Bug */
1159 outudp->uh_sum = sum;
1160 if (outudp->uh_sum == 0)
1161 outudp->uh_sum = 0xffff;
1162 }
1163 }
1164
1165 /* XXX undocumented debugging hack */
1166 if (verbose > 1) {
1167 const u_int16_t *sp;
1168 int nshorts, i;
1169
1170 sp = (u_int16_t *)outip;
1171 nshorts = (u_int)packlen / sizeof(u_int16_t);
1172 i = 0;
1173 Printf("[ %d bytes", packlen);
1174 while (--nshorts >= 0) {
1175 if ((i++ % 8) == 0)
1176 Printf("\n\t");
1177 Printf(" %04x", ntohs(*sp++));
1178 }
1179 if (packlen & 1) {
1180 if ((i % 8) == 0)
1181 Printf("\n\t");
1182 Printf(" %02x", *(u_char *)sp);
1183 }
1184 Printf("]\n");
1185 }
1186
1187 #if !defined(IP_HDRINCL) && defined(IP_TTL)
1188 if (setsockopt(sndsock, IPPROTO_IP, IP_TTL,
1189 (char *)&ttl, sizeof(ttl)) < 0) {
1190 Fprintf(stderr, "%s: setsockopt ttl %d: %s\n",
1191 prog, ttl, strerror(errno));
1192 exit(1);
1193 }
1194 #endif
1195 if (dump)
1196 dump_packet();
1197
1198 #ifdef __hpux
1199 cc = sendto(sndsock, useicmp ? (char *)outicmp : (char *)outudp,
1200 packlen - (sizeof(*outip) + optlen), 0, &whereto, sizeof(whereto));
1201 if (cc > 0)
1202 cc += sizeof(*outip) + optlen;
1203 #else
1204 cc = sendto(sndsock, (char *)outip,
1205 packlen, 0, &whereto, sizeof(whereto));
1206 #endif
1207 if (cc < 0 || cc != packlen) {
1208 if (cc < 0) {
1209 /*
1210 * An errno of EMSGSIZE means we're writing too big a
1211 * datagram for the interface. We have to just
1212 * decrease the packet size until we find one that
1213 * works.
1214 *
1215 * XXX maybe we should try to read the outgoing if's
1216 * mtu?
1217 */
1218 if (errno == EMSGSIZE) {
1219 packlen = *mtuptr++;
1220 resize_packet();
1221 goto again;
1222 } else
1223 Fprintf(stderr, "%s: sendto: %s\n",
1224 prog, strerror(errno));
1225 }
1226
1227 Printf("%s: wrote %s %d chars, ret=%d\n",
1228 prog, hostname, packlen, cc);
1229 (void)fflush(stdout);
1230 }
1231 if (oldmtu != packlen) {
1232 Printf("message too big, "
1233 "trying new MTU = %d\n", packlen);
1234 printed_ttl = 0;
1235 }
1236 if (!printed_ttl) {
1237 Printf("%2d ", ttl);
1238 printed_ttl = 1;
1239 }
1240
1241 }
1242
1243 double
1244 deltaT(struct timeval *t1p, struct timeval *t2p)
1245 {
1246 double dt;
1247
1248 dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
1249 (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
1250 return (dt);
1251 }
1252
1253 /*
1254 * Convert an ICMP "type" field to a printable string.
1255 */
1256 char *
1257 pr_type(u_char t)
1258 {
1259 static char *ttab[] = {
1260 "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable",
1261 "Source Quench", "Redirect", "ICMP 6", "ICMP 7",
1262 "Echo", "ICMP 9", "ICMP 10", "Time Exceeded",
1263 "Param Problem", "Timestamp", "Timestamp Reply", "Info Request",
1264 "Info Reply"
1265 };
1266
1267 if (t > 16)
1268 return("OUT-OF-RANGE");
1269
1270 return(ttab[t]);
1271 }
1272
1273 int
1274 packet_ok(u_char *buf, int cc, struct sockaddr_in *from, int seq)
1275 {
1276 struct icmp *icp;
1277 u_char type, code;
1278 int hlen;
1279 #ifndef ARCHAIC
1280 struct ip *ip;
1281
1282 ip = (struct ip *) buf;
1283 hlen = ip->ip_hl << 2;
1284 if (cc < hlen + ICMP_MINLEN) {
1285 if (verbose)
1286 Printf("packet too short (%d bytes) from %s\n", cc,
1287 inet_ntoa(from->sin_addr));
1288 return (0);
1289 }
1290 cc -= hlen;
1291 icp = (struct icmp *)(buf + hlen);
1292 #else
1293 icp = (struct icmp *)buf;
1294 #endif
1295 type = icp->icmp_type;
1296 code = icp->icmp_code;
1297 if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
1298 type == ICMP_UNREACH || type == ICMP_ECHOREPLY) {
1299 struct ip *hip;
1300 struct udphdr *up;
1301 struct icmp *hicmp;
1302
1303 hip = &icp->icmp_ip;
1304 hlen = hip->ip_hl << 2;
1305
1306 nextmtu = ntohs(icp->icmp_nextmtu); /* for frag_err() */
1307
1308 if (useicmp) {
1309 /* XXX */
1310 if (type == ICMP_ECHOREPLY &&
1311 icp->icmp_id == htons(ident) &&
1312 icp->icmp_seq == htons(seq))
1313 return (-2);
1314
1315 hicmp = (struct icmp *)((u_char *)hip + hlen);
1316 /* XXX 8 is a magic number */
1317 if (hlen + 8 <= cc &&
1318 hip->ip_p == IPPROTO_ICMP &&
1319 hicmp->icmp_id == htons(ident) &&
1320 hicmp->icmp_seq == htons(seq))
1321 return (type == ICMP_TIMXCEED ? -1 : code + 1);
1322 } else {
1323 up = (struct udphdr *)((u_char *)hip + hlen);
1324 /* XXX 8 is a magic number */
1325 if (hlen + 12 <= cc &&
1326 hip->ip_p == IPPROTO_UDP &&
1327 up->uh_sport == htons(ident) &&
1328 up->uh_dport == htons(port + seq))
1329 return (type == ICMP_TIMXCEED ? -1 : code + 1);
1330 }
1331 }
1332 #ifndef ARCHAIC
1333 if (verbose) {
1334 int i;
1335 u_int32_t *lp = (u_int32_t *)&icp->icmp_ip;
1336
1337 Printf("\n%d bytes from %s to ", cc, inet_ntoa(from->sin_addr));
1338 Printf("%s: icmp type %d (%s) code %d\n",
1339 inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code);
1340 for (i = 4; i < cc ; i += sizeof(*lp))
1341 Printf("%2d: x%8.8x\n", i, *lp++);
1342 }
1343 #endif
1344 return(0);
1345 }
1346
1347 void resize_packet(void)
1348 {
1349 if (useicmp) {
1350 outicmp->icmp_cksum = 0;
1351 outicmp->icmp_cksum = in_cksum((u_int16_t *)outicmp,
1352 packlen - (sizeof(*outip) + optlen));
1353 if (outicmp->icmp_cksum == 0)
1354 outicmp->icmp_cksum = 0xffff;
1355 } else {
1356 outudp->uh_ulen =
1357 htons((u_int16_t)(packlen - (sizeof(*outip) + optlen)));
1358 }
1359 }
1360
1361 void
1362 print(u_char *buf, int cc, struct sockaddr_in *from)
1363 {
1364 struct ip *ip;
1365 int hlen;
1366
1367 ip = (struct ip *) buf;
1368 hlen = ip->ip_hl << 2;
1369 cc -= hlen;
1370
1371 if (as_path)
1372 Printf(" [AS%d]", as_lookup(asn, &from->sin_addr));
1373
1374 if (nflag)
1375 Printf(" %s", inet_ntoa(from->sin_addr));
1376 else
1377 Printf(" %s (%s)", inetname(from->sin_addr),
1378 inet_ntoa(from->sin_addr));
1379
1380 if (verbose)
1381 Printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
1382 }
1383
1384 u_int16_t
1385 in_cksum(u_int16_t *addr, int len)
1386 {
1387
1388 return ~in_cksum2(0, addr, len);
1389 }
1390
1391 /*
1392 * Checksum routine for Internet Protocol family headers (C Version)
1393 */
1394 u_int16_t
1395 in_cksum2(u_int16_t seed, u_int16_t *addr, int len)
1396 {
1397 int nleft = len;
1398 u_int16_t *w = addr;
1399 union {
1400 u_int16_t w;
1401 u_int8_t b[2];
1402 } answer;
1403 int32_t sum = seed;
1404
1405 /*
1406 * Our algorithm is simple, using a 32 bit accumulator (sum),
1407 * we add sequential 16 bit words to it, and at the end, fold
1408 * back all the carry bits from the top 16 bits into the lower
1409 * 16 bits.
1410 */
1411 while (nleft > 1) {
1412 sum += *w++;
1413 nleft -= 2;
1414 }
1415
1416 /* mop up an odd byte, if necessary */
1417 if (nleft == 1) {
1418 answer.b[0] = *(u_char *)w;
1419 answer.b[1] = 0;
1420 sum += answer.w;
1421 }
1422
1423 /*
1424 * add back carry outs from top 16 bits to low 16 bits
1425 */
1426 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
1427 sum += (sum >> 16); /* add carry */
1428 answer.w = sum; /* truncate to 16 bits */
1429 return (answer.w);
1430 }
1431
1432 /*
1433 * Subtract 2 timeval structs: out = out - in.
1434 * Out is assumed to be >= in.
1435 */
1436 void
1437 tvsub(struct timeval *out, struct timeval *in)
1438 {
1439
1440 if ((out->tv_usec -= in->tv_usec) < 0) {
1441 --out->tv_sec;
1442 out->tv_usec += 1000000;
1443 }
1444 out->tv_sec -= in->tv_sec;
1445 }
1446
1447 /*
1448 * Construct an Internet address representation.
1449 * If the nflag has been supplied, give
1450 * numeric value, otherwise try for symbolic name.
1451 */
1452 char *
1453 inetname(struct in_addr in)
1454 {
1455 char *cp;
1456 struct hostent *hp;
1457 static int first = 1;
1458 static char domain[MAXHOSTNAMELEN + 1], line[MAXHOSTNAMELEN + 1];
1459
1460 if (first && !nflag) {
1461 int rv;
1462
1463 first = 0;
1464 rv = gethostname(domain, sizeof domain);
1465 domain[sizeof(domain) - 1] = '\0';
1466 if (rv == 0 && (cp = strchr(domain, '.')) != NULL) {
1467 (void)strncpy(domain, cp + 1, sizeof(domain) - 1);
1468 } else
1469 domain[0] = '\0';
1470 }
1471 if (!nflag && in.s_addr != INADDR_ANY) {
1472 hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET);
1473 if (hp != NULL) {
1474 if ((cp = strchr(hp->h_name, '.')) != NULL &&
1475 strcmp(cp + 1, domain) == 0)
1476 *cp = '\0';
1477 (void)strncpy(line, hp->h_name, sizeof(line) - 1);
1478 line[sizeof(line) - 1] = '\0';
1479 return (line);
1480 }
1481 }
1482 return (inet_ntoa(in));
1483 }
1484
1485 struct hostinfo *
1486 gethostinfo(char *hostname)
1487 {
1488 int n;
1489 struct hostent *hp;
1490 struct hostinfo *hi;
1491 char **p;
1492 u_int32_t *ap;
1493 struct in_addr addr;
1494
1495 hi = calloc(1, sizeof(*hi));
1496 if (hi == NULL) {
1497 Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
1498 exit(1);
1499 }
1500 if (inet_aton(hostname, &addr) != 0) {
1501 hi->name = strdup(hostname);
1502 hi->n = 1;
1503 hi->addrs = calloc(1, sizeof(hi->addrs[0]));
1504 if (hi->addrs == NULL) {
1505 Fprintf(stderr, "%s: calloc %s\n",
1506 prog, strerror(errno));
1507 exit(1);
1508 }
1509 hi->addrs[0] = addr.s_addr;
1510 return (hi);
1511 }
1512
1513 hp = gethostbyname(hostname);
1514 if (hp == NULL) {
1515 Fprintf(stderr, "%s: unknown host %s\n", prog, hostname);
1516 exit(1);
1517 }
1518 if (hp->h_addrtype != AF_INET || hp->h_length != 4) {
1519 Fprintf(stderr, "%s: bad host %s\n", prog, hostname);
1520 exit(1);
1521 }
1522 hi->name = strdup(hp->h_name);
1523 for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p)
1524 continue;
1525 hi->n = n;
1526 hi->addrs = calloc(n, sizeof(hi->addrs[0]));
1527 if (hi->addrs == NULL) {
1528 Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
1529 exit(1);
1530 }
1531 for (ap = hi->addrs, p = hp->h_addr_list; *p != NULL; ++ap, ++p)
1532 memcpy(ap, *p, sizeof(*ap));
1533 return (hi);
1534 }
1535
1536 void
1537 freehostinfo(struct hostinfo *hi)
1538 {
1539 if (hi->name != NULL) {
1540 free(hi->name);
1541 hi->name = NULL;
1542 }
1543 free((char *)hi->addrs);
1544 free((char *)hi);
1545 }
1546
1547 void
1548 getaddr(u_int32_t *ap, char *hostname)
1549 {
1550 struct hostinfo *hi;
1551
1552 hi = gethostinfo(hostname);
1553 *ap = hi->addrs[0];
1554 freehostinfo(hi);
1555 }
1556
1557 void
1558 setsin(struct sockaddr_in *sin, u_int32_t addr)
1559 {
1560
1561 memset(sin, 0, sizeof(*sin));
1562 #ifdef HAVE_SOCKADDR_SA_LEN
1563 sin->sin_len = sizeof(*sin);
1564 #endif
1565 sin->sin_family = AF_INET;
1566 sin->sin_addr.s_addr = addr;
1567 }
1568
1569 /* String to value with optional min and max. Handles decimal and hex. */
1570 int
1571 str2val(const char *str, const char *what, int mi, int ma)
1572 {
1573 const char *cp;
1574 int val;
1575 char *ep;
1576
1577 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
1578 cp = str + 2;
1579 val = (int)strtol(cp, &ep, 16);
1580 } else
1581 val = (int)strtol(str, &ep, 10);
1582 if (*ep != '\0') {
1583 Fprintf(stderr, "%s: \"%s\" bad value for %s \n",
1584 prog, str, what);
1585 exit(1);
1586 }
1587 if (val < mi && mi >= 0) {
1588 if (mi == 0)
1589 Fprintf(stderr, "%s: %s must be >= %d\n",
1590 prog, what, mi);
1591 else
1592 Fprintf(stderr, "%s: %s must be > %d\n",
1593 prog, what, mi - 1);
1594 exit(1);
1595 }
1596 if (val > ma && ma >= 0) {
1597 Fprintf(stderr, "%s: %s must be <= %d\n", prog, what, ma);
1598 exit(1);
1599 }
1600 return (val);
1601 }
1602
1603 __dead void
1604 usage(void)
1605 {
1606 extern char version[];
1607
1608 Fprintf(stderr, "Version %s\n", version);
1609 Fprintf(stderr, "Usage: %s [-adDFPIlnrvx] [-g gateway] [-i iface] \
1610 [-f first_ttl]\n\t[-m max_ttl] [-p port] [-q nqueries] [-s src_addr] [-t tos]\n\t\
1611 [-w waittime] [-A as_server] host [packetlen]\n",
1612 prog);
1613 exit(1);
1614 }
1615
1616 /*
1617 * Received ICMP unreachable (fragmentation required and DF set).
1618 * If the ICMP error was from a "new" router, it'll contain the next-hop
1619 * MTU that we should use next. Otherwise we'll just keep going in the
1620 * mtus[] table, trying until we hit a valid MTU.
1621 */
1622
1623
1624 void
1625 frag_err()
1626 {
1627 int i;
1628
1629 if (nextmtu > 0 && nextmtu < packlen) {
1630 Printf("\nfragmentation required and DF set, "
1631 "next hop MTU = %d\n",
1632 nextmtu);
1633 packlen = nextmtu;
1634 for (i = 0; mtus[i] > 0; i++) {
1635 if (mtus[i] < nextmtu) {
1636 mtuptr = &mtus[i]; /* next one to try */
1637 break;
1638 }
1639 }
1640 } else {
1641 Printf("\nfragmentation required and DF set. ");
1642 if (nextmtu)
1643 Printf("\nBogus next hop MTU = %d > last MTU = %d. ",
1644 nextmtu, packlen);
1645 packlen = *mtuptr++;
1646 Printf("Trying new MTU = %d\n", packlen);
1647 }
1648 resize_packet();
1649 }
1650
1651 int
1652 find_local_ip(struct sockaddr_in *from, struct sockaddr_in *to)
1653 {
1654 int sock;
1655 struct sockaddr_in help;
1656 int help_len;
1657
1658 sock = socket(AF_INET, SOCK_DGRAM, 0);
1659 if (sock < 0) return (0);
1660
1661 help.sin_family = AF_INET;
1662 /*
1663 * At this point the port number doesn't matter
1664 * since it only has to be greater than zero.
1665 */
1666 help.sin_port = 42;
1667 help.sin_addr.s_addr = to->sin_addr.s_addr;
1668 if (connect(sock, (struct sockaddr *)&help, sizeof(help)) < 0) {
1669 (void)close(sock);
1670 return (0);
1671 }
1672
1673 help_len = sizeof(help);
1674 if (getsockname(sock, (struct sockaddr *)&help, &help_len) < 0 ||
1675 help_len != sizeof(help) ||
1676 help.sin_addr.s_addr == INADDR_ANY) {
1677 (void)close(sock);
1678 return (0);
1679 }
1680
1681 (void)close(sock);
1682 setsin(from, help.sin_addr.s_addr);
1683 return (1);
1684 }
1685
1686 #ifdef IPSEC
1687 #ifdef IPSEC_POLICY_IPSEC
1688 int
1689 setpolicy(so, policy)
1690 int so;
1691 char *policy;
1692 {
1693 char *buf;
1694
1695 buf = ipsec_set_policy(policy, strlen(policy));
1696 if (buf == NULL) {
1697 Fprintf(stderr, "%s: %s\n", prog, ipsec_strerror());
1698 return -1;
1699 }
1700 (void)setsockopt(so, IPPROTO_IP, IP_IPSEC_POLICY,
1701 buf, ipsec_get_policylen(buf));
1702
1703 free(buf);
1704
1705 return 0;
1706 }
1707 #endif
1708 #endif
1709
1710