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