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