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