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