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