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