2 * Copyright (c) 2004-2015 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
30 * Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000
31 * The Regents of the University of California. All rights reserved.
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that: (1) source code distributions
35 * retain the above copyright notice and this paragraph in its entirety, (2)
36 * distributions including binary code include the above copyright notice and
37 * this paragraph in its entirety in the documentation or other materials
38 * provided with the distribution, and (3) all advertising materials mentioning
39 * features or use of this software display the following acknowledgement:
40 * ``This product includes software developed by the University of California,
41 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
42 * the University nor the names of its contributors may be used to endorse
43 * or promote products derived from this software without specific prior
45 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
46 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
47 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
50 #include <sys/cdefs.h>
53 __unused
static const char copyright
[] =
54 "@(#) Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000\n\
55 The Regents of the University of California. All rights reserved.\n";
59 * traceroute host - trace the route ip packets follow going to "host".
61 * Attempt to trace the route an ip packet would follow to some
62 * internet host. We find out intermediate hops by launching probe
63 * packets with a small ttl (time to live) then listening for an
64 * icmp "time exceeded" reply from a gateway. We start our probes
65 * with a ttl of one and increase by one until we get an icmp "port
66 * unreachable" (which means we got to "host") or hit a max (which
67 * defaults to net.inet.ip.ttl hops & can be changed with the -m flag).
68 * Three probes (change with -q flag) are sent at each ttl setting and
69 * a line is printed showing the ttl, address of the gateway and
70 * round trip time of each probe. If the probe answers come from
71 * different gateways, the address of each responding system will
72 * be printed. If there is no response within a 5 sec. timeout
73 * interval (changed with the -w flag), a "*" is printed for that
76 * Probe packets are UDP format. We don't want the destination
77 * host to process them so the destination port is set to an
78 * unlikely value (if some clod on the destination is using that
79 * value, it can be changed with the -p flag).
81 * A sample use might be:
83 * [yak 71]% traceroute nis.nsf.net.
84 * traceroute to nis.nsf.net (35.1.1.48), 64 hops max, 56 byte packet
85 * 1 helios.ee.lbl.gov (128.3.112.1) 19 ms 19 ms 0 ms
86 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
87 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
88 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 39 ms
89 * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 39 ms 39 ms 39 ms
90 * 6 128.32.197.4 (128.32.197.4) 40 ms 59 ms 59 ms
91 * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 59 ms
92 * 8 129.140.70.13 (129.140.70.13) 99 ms 99 ms 80 ms
93 * 9 129.140.71.6 (129.140.71.6) 139 ms 239 ms 319 ms
94 * 10 129.140.81.7 (129.140.81.7) 220 ms 199 ms 199 ms
95 * 11 nic.merit.edu (35.1.1.48) 239 ms 239 ms 239 ms
97 * Note that lines 2 & 3 are the same. This is due to a buggy
98 * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
99 * packets with a zero ttl.
101 * A more interesting example is:
103 * [yak 72]% traceroute allspice.lcs.mit.edu.
104 * traceroute to allspice.lcs.mit.edu (18.26.0.115), 64 hops max
105 * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
106 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 19 ms 19 ms
107 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 19 ms
108 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 19 ms 39 ms 39 ms
109 * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 20 ms 39 ms 39 ms
110 * 6 128.32.197.4 (128.32.197.4) 59 ms 119 ms 39 ms
111 * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 39 ms
112 * 8 129.140.70.13 (129.140.70.13) 80 ms 79 ms 99 ms
113 * 9 129.140.71.6 (129.140.71.6) 139 ms 139 ms 159 ms
114 * 10 129.140.81.7 (129.140.81.7) 199 ms 180 ms 300 ms
115 * 11 129.140.72.17 (129.140.72.17) 300 ms 239 ms 239 ms
117 * 13 128.121.54.72 (128.121.54.72) 259 ms 499 ms 279 ms
122 * 18 ALLSPICE.LCS.MIT.EDU (18.26.0.115) 339 ms 279 ms 279 ms
124 * (I start to see why I'm having so much trouble with mail to
125 * MIT.) Note that the gateways 12, 14, 15, 16 & 17 hops away
126 * either don't send ICMP "time exceeded" messages or send them
127 * with a ttl too small to reach us. 14 - 17 are running the
128 * MIT C Gateway code that doesn't send "time exceeded"s. God
129 * only knows what's going on with 12.
131 * The silent gateway 12 in the above may be the result of a bug in
132 * the 4.[23]BSD network code (and its derivatives): 4.x (x <= 3)
133 * sends an unreachable message using whatever ttl remains in the
134 * original datagram. Since, for gateways, the remaining ttl is
135 * zero, the icmp "time exceeded" is guaranteed to not make it back
136 * to us. The behavior of this bug is slightly more interesting
137 * when it appears on the destination system:
139 * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
140 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 39 ms
141 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 39 ms 19 ms
142 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 19 ms
143 * 5 ccn-nerif35.Berkeley.EDU (128.32.168.35) 39 ms 39 ms 39 ms
144 * 6 csgw.Berkeley.EDU (128.32.133.254) 39 ms 59 ms 39 ms
151 * 13 rip.Berkeley.EDU (128.32.131.22) 59 ms ! 39 ms ! 39 ms !
153 * Notice that there are 12 "gateways" (13 is the final
154 * destination) and exactly the last half of them are "missing".
155 * What's really happening is that rip (a Sun-3 running Sun OS3.5)
156 * is using the ttl from our arriving datagram as the ttl in its
157 * icmp reply. So, the reply will time out on the return path
158 * (with no notice sent to anyone since icmp's aren't sent for
159 * icmp's) until we probe with a ttl that's at least twice the path
160 * length. I.e., rip is really only 7 hops away. A reply that
161 * returns with a ttl of 1 is a clue this problem exists.
162 * Traceroute prints a "!" after the time if the ttl is <= 1.
163 * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
164 * non-standard (HPUX) software, expect to see this problem
165 * frequently and/or take care picking the target host of your
168 * Other possible annotations after the time are !H, !N, !P (got a host,
169 * network or protocol unreachable, respectively), !S or !F (source
170 * route failed or fragmentation needed -- neither of these should
171 * ever occur and the associated gateway is busted if you see one). If
172 * almost all the probes result in some kind of unreachable, traceroute
173 * will give up and exit.
177 * This program must be run by root or be setuid. (I suggest that
178 * you *don't* make it setuid -- casual use could result in a lot
179 * of unnecessary traffic on our poor, congested nets.)
181 * This program requires a kernel mod that does not appear in any
182 * system available from Berkeley: A raw ip socket using proto
183 * IPPROTO_RAW must interpret the data sent as an ip datagram (as
184 * opposed to data to be wrapped in a ip datagram). See the README
185 * file that came with the source to this program for a description
186 * of the mods I made to /sys/netinet/raw_ip.c. Your mileage may
187 * vary. But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
188 * MODIFIED TO RUN THIS PROGRAM.
190 * The udp port usage may appear bizarre (well, ok, it is bizarre).
191 * The problem is that an icmp message only contains 8 bytes of
192 * data from the original datagram. 8 bytes is the size of a udp
193 * header so, if we want to associate replies with the original
194 * datagram, the necessary information must be encoded into the
195 * udp header (the ip id could be used but there's no way to
196 * interlock with the kernel's assignment of ip id's and, anyway,
197 * it would have taken a lot more kernel hacking to allow this
198 * code to set the ip id). So, to allow two or more users to
199 * use traceroute simultaneously, we use this task's pid as the
200 * source port (the high bit is set to move the port number out
201 * of the "likely" range). To keep track of which probe is being
202 * replied to (so times and/or hop counts don't get confused by a
203 * reply that was delayed in transit), we increment the destination
204 * port number before each probe.
206 * Don't use this as a coding example. I was trying to find a
207 * routing problem and this code sort-of popped out after 48 hours
208 * without sleep. I was amazed it ever compiled, much less ran.
210 * I stole the idea for this program from Steve Deering. Since
211 * the first release, I've learned that had I attended the right
212 * IETF working group meetings, I also could have stolen it from Guy
213 * Almes or Matt Mathis. I don't know (or care) who came up with
214 * the idea first. I envy the originators' perspicacity and I'm
215 * glad they didn't keep the idea a secret.
217 * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
218 * enhancements to the original distribution.
220 * I've hacked up a round-trip-route version of this that works by
221 * sending a loose-source-routed udp datagram through the destination
222 * back to yourself. Unfortunately, SO many gateways botch source
223 * routing, the thing is almost worthless. Maybe one day...
225 * -- Van Jacobson (van@ee.lbl.gov)
226 * Tue Dec 20 03:50:13 PST 1988
229 #include <sys/param.h>
230 #include <sys/file.h>
231 #include <sys/ioctl.h>
232 #ifdef HAVE_SYS_SELECT_H
233 #include <sys/select.h>
235 #include <sys/socket.h>
236 #ifdef HAVE_SYS_SYSCTL_H
237 #include <sys/sysctl.h>
239 #include <sys/time.h>
241 #include <netinet/in_systm.h>
242 #include <netinet/in.h>
243 #include <netinet/ip.h>
244 #include <netinet/ip_var.h>
245 #include <netinet/ip_icmp.h>
246 #include <netinet/udp.h>
247 #include <netinet/udp_var.h>
248 #include <netinet/tcp.h>
249 #include <netinet/tcpip.h>
251 #include <arpa/inet.h>
254 #include <net/route.h>
255 #include <netinet6/ipsec.h> /* XXX */
273 #ifdef HAVE_OS_PROTO_H
274 #include "os-proto.h"
278 #ifndef ICMP_UNREACH_FILTER_PROHIB
279 #define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohibited filter */
281 #ifndef ICMP_UNREACH_HOST_PRECEDENCE
282 #define ICMP_UNREACH_HOST_PRECEDENCE 14 /* host precedence violation */
284 #ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF
285 #define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* precedence cutoff */
288 #include "findsaddr.h"
289 #include "ifaddrlist.h"
291 #include "traceroute.h"
293 /* Maximum number of gateways (include room for one noop) */
294 #define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t)))
296 #ifndef MAXHOSTNAMELEN
297 #define MAXHOSTNAMELEN 64
300 #define Fprintf (void)fprintf
301 #define Printf (void)printf
303 /* What a GRE packet header looks like */
307 u_int16_t length
; /* PPTP version of these fields */
311 #define IPPROTO_GRE 47
314 /* For GRE, we prepare what looks like a PPTP packet */
315 #define GRE_PPTP_PROTO 0x880b
317 /* Host name and address list */
324 /* Data section of the probe packet */
326 u_char seq
; /* sequence number of this packet */
327 u_char ttl
; /* ttl packet left with */
328 struct timeval tv
; /* time packet left */
331 #ifndef HAVE_ICMP_NEXTMTU
332 /* Path MTU Discovery (RFC1191) */
339 u_char packet
[512]; /* last inbound (icmp) packet */
341 struct ip
*outip
; /* last output ip packet */
342 u_char
*outp
; /* last output inner protocol packet */
344 struct ip
*hip
= NULL
; /* Quoted IP header */
347 /* loose source route gateway list (including room for final destination) */
348 u_int32_t gwlist
[NGATEWAYS
+ 1];
350 int s
; /* receive (icmp) socket file descriptor */
351 int sndsock
; /* send (udp) socket file descriptor */
353 struct sockaddr whereto
; /* Who to try to reach */
354 struct sockaddr wherefrom
; /* Who we are */
355 int packlen
; /* total length of packet */
356 int protlen
; /* length of protocol part of packet */
357 int minpacket
; /* min ip packet size */
358 int maxpacket
= 32 * 1024; /* max ip packet size */
359 int pmtu
; /* Path MTU Discovery (RFC1191) */
366 static const char devnull
[] = "/dev/null";
372 u_short port
; /* protocol specific base "port" */
374 int options
; /* socket options */
376 int waittime
= 5; /* time to wait for response (in seconds) */
377 int nflag
; /* print addresses numerically */
378 int as_path
; /* print as numbers for each hop */
379 char *as_server
= NULL
;
381 #ifdef CANT_HACK_IPCKSUM
382 int doipcksum
= 0; /* don't calculate ip checksums by default */
384 int doipcksum
= 1; /* calculate ip checksums by default */
386 int optlen
; /* length of ip options */
387 int fixedPort
= 0; /* Use fixed destination port for TCP and UDP */
388 int printdiff
= 0; /* Print the difference between sent and quoted */
395 double deltaT(struct timeval
*, struct timeval
*);
396 void freehostinfo(struct hostinfo
*);
397 void getaddr(u_int32_t
*, char *);
398 struct hostinfo
*gethostinfo(char *);
399 u_short
in_cksum(u_short
*, int);
400 char *inetname(struct in_addr
);
401 int main(int, char **);
402 u_short
p_cksum(struct ip
*, u_short
*, int);
403 int packet_ok(u_char
*, int, struct sockaddr_in
*, int);
404 char *pr_type(u_char
);
405 void print(u_char
*, int, struct sockaddr_in
*);
407 int setpolicy
__P((int so
, char *policy
));
409 void send_probe(int, int);
410 struct outproto
*setproto(char *);
411 int str2val(const char *, const char *, int, int);
412 void tvsub(struct timeval
*, struct timeval
*);
414 int wait_for_reply(int, struct sockaddr_in
*, const struct timeval
*);
415 void pkt_compare(const u_char
*, int, const u_char
*, int);
420 void udp_prep(struct outdata
*);
421 int udp_check(const u_char
*, int);
422 void tcp_prep(struct outdata
*);
423 int tcp_check(const u_char
*, int);
424 void gre_prep(struct outdata
*);
425 int gre_check(const u_char
*, int);
426 void gen_prep(struct outdata
*);
427 int gen_check(const u_char
*, int);
428 void icmp_prep(struct outdata
*);
429 int icmp_check(const u_char
*, int);
431 /* Descriptor structure for each outgoing protocol we support */
433 char *name
; /* name of protocol */
434 const char *key
; /* An ascii key for the bytes of the header */
435 u_char num
; /* IP protocol number */
436 u_short hdrlen
; /* max size of protocol header */
437 u_short port
; /* default base protocol-specific "port" */
438 void (*prepare
)(struct outdata
*);
439 /* finish preparing an outgoing packet */
440 int (*check
)(const u_char
*, int);
441 /* check an incoming packet */
444 /* List of supported protocols. The first one is the default. The last
445 one is the handler for generic protocols not explicitly listed. */
446 struct outproto protos
[] = {
451 sizeof(struct udphdr
),
458 "spt dpt seq ack xxflwin sum urp",
460 sizeof(struct tcphdr
),
469 sizeof(struct grehdr
),
493 struct outproto
*proto
= &protos
[0];
495 const char *ip_hdr_key
= "vhtslen id off tlprsum srcip dstip opts";
498 main(int argc
, char **argv
)
500 register int op
, code
, n
;
502 register const char *err
;
503 register u_int32_t
*ap
;
504 register struct sockaddr_in
*from
= (struct sockaddr_in
*)&wherefrom
;
505 register struct sockaddr_in
*to
= (struct sockaddr_in
*)&whereto
;
506 register struct hostinfo
*hi
;
508 register struct protoent
*pe
;
509 register int ttl
, probe
, i
;
510 register int seq
= 0;
511 int tos
= 0, settos
= 0;
512 register int lsrr
= 0;
513 register u_short off
= 0;
514 struct ifaddrlist
*al
;
516 int requestPort
= -1;
522 else if ((cp
= strrchr(argv
[0], '/')) != NULL
)
527 /* Insure the socket fds won't be 0, 1 or 2 */
528 if (open(devnull
, O_RDONLY
) < 0 ||
529 open(devnull
, O_RDONLY
) < 0 ||
530 open(devnull
, O_RDONLY
) < 0) {
531 Fprintf(stderr
, "%s: open \"%s\": %s\n",
532 prog
, devnull
, strerror(errno
));
536 * Do the setuid-required stuff first, then lose priveleges ASAP.
537 * Do error checking for these two calls where they appeared in
541 pe
= getprotobyname(cp
);
543 if ((s
= socket(AF_INET
, SOCK_RAW
, pe
->p_proto
)) < 0)
545 else if ((sndsock
= socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
)) < 0)
553 int mib
[4] = { CTL_NET
, PF_INET
, IPPROTO_IP
, IPCTL_DEFTTL
};
554 size_t sz
= sizeof(max_ttl
);
556 if (sysctl(mib
, 4, &max_ttl
, &sz
, NULL
, 0) == -1) {
557 perror("sysctl(net.inet.ip.ttl)");
566 while ((op
= getopt(argc
, argv
, "aA:edDFInrSvxf:g:i:M:m:P:p:q:s:t:w:z:")) != EOF
)
590 case 'M': /* FreeBSD compat. */
591 first_ttl
= str2val(optarg
, "first ttl", 1, 255);
599 if (lsrr
>= NGATEWAYS
) {
601 "%s: No more than %d gateways\n",
605 getaddr(gwlist
+ lsrr
, optarg
);
614 proto
= setproto("icmp");
618 max_ttl
= str2val(optarg
, "max ttl", 1, 255);
626 proto
= setproto(optarg
);
630 requestPort
= (u_short
)str2val(optarg
, "port",
635 nprobes
= str2val(optarg
, "nprobes", 1, -1);
639 options
|= SO_DONTROUTE
;
644 * set the ip source address of the outbound
645 * probe (e.g., on a multi-homed host).
655 tos
= str2val(optarg
, "tos", 0, 255);
664 doipcksum
= (doipcksum
== 0);
668 waittime
= str2val(optarg
, "wait time",
673 pausemsecs
= str2val(optarg
, "pause msecs",
681 /* Set requested port, if any, else default for this protocol */
682 port
= (requestPort
!= -1) ? requestPort
: proto
->port
;
685 nprobes
= printdiff
? 1 : 3;
687 if (first_ttl
> max_ttl
) {
689 "%s: first ttl (%d) may not be greater than max ttl (%d)\n",
690 prog
, first_ttl
, max_ttl
);
695 Fprintf(stderr
, "%s: Warning: ip checksums disabled\n", prog
);
698 optlen
= (lsrr
+ 1) * sizeof(gwlist
[0]);
699 minpacket
= sizeof(*outip
) + proto
->hdrlen
+ sizeof(struct outdata
) + optlen
;
700 packlen
= minpacket
; /* minimum sized packet */
702 /* Process destination and optional packet size */
703 switch (argc
- optind
) {
706 packlen
= str2val(argv
[optind
+ 1],
707 "packet length", minpacket
, maxpacket
);
711 hostname
= argv
[optind
];
712 hi
= gethostinfo(hostname
);
713 setsin(to
, hi
->addrs
[0]);
716 "%s: Warning: %s has multiple addresses; using %s\n",
717 prog
, hostname
, inet_ntoa(to
->sin_addr
));
727 #ifdef HAVE_SETLINEBUF
730 setvbuf(stdout
, NULL
, _IOLBF
, 0);
733 protlen
= packlen
- sizeof(*outip
) - optlen
;
735 outip
= (struct ip
*)malloc((unsigned)packlen
);
737 Fprintf(stderr
, "%s: malloc: %s\n", prog
, strerror(errno
));
740 memset((char *)outip
, 0, packlen
);
742 outip
->ip_v
= IPVERSION
;
745 #ifdef BYTESWAP_IP_HDR
746 outip
->ip_len
= htons(packlen
);
747 outip
->ip_off
= htons(off
);
749 outip
->ip_len
= packlen
;
752 outip
->ip_p
= proto
->num
;
753 outp
= (u_char
*)(outip
+ 1);
754 #ifdef HAVE_RAW_OPTIONS
756 register u_char
*optlist
;
762 gwlist
[lsrr
] = to
->sin_addr
.s_addr
;
764 outip
->ip_dst
.s_addr
= gwlist
[0];
766 /* force 4 byte alignment */
767 optlist
[0] = IPOPT_NOP
;
768 /* loose source route option */
769 optlist
[1] = IPOPT_LSRR
;
770 i
= lsrr
* sizeof(gwlist
[0]);
772 /* Pointer to LSRR addresses */
773 optlist
[3] = IPOPT_MINOFF
;
774 memcpy(optlist
+ 4, gwlist
+ 1, i
);
777 outip
->ip_dst
= to
->sin_addr
;
779 outip
->ip_hl
= (outp
- (u_char
*)outip
) >> 2;
780 ident
= (getpid() & 0xffff) | 0x8000;
783 Fprintf(stderr
, "%s: unknown protocol %s\n", prog
, cp
);
788 Fprintf(stderr
, "%s: icmp socket: %s\n", prog
, strerror(errno
));
791 (void) setsockopt(s
, SOL_SOCKET
, SO_RECV_ANYIF
, (char *)&on
,
793 if (options
& SO_DEBUG
)
794 (void)setsockopt(s
, SOL_SOCKET
, SO_DEBUG
, (char *)&on
,
796 if (options
& SO_DONTROUTE
)
797 (void)setsockopt(s
, SOL_SOCKET
, SO_DONTROUTE
, (char *)&on
,
800 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
801 if (setpolicy(s
, "in bypass") < 0)
802 errx(1, "%s", ipsec_strerror());
804 if (setpolicy(s
, "out bypass") < 0)
805 errx(1, "%s", ipsec_strerror());
806 #endif /* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */
810 Fprintf(stderr
, "%s: raw socket: %s\n", prog
, strerror(errno
));
814 #if defined(IP_OPTIONS) && !defined(HAVE_RAW_OPTIONS)
816 u_char optlist
[MAX_IPOPTLEN
];
819 if ((pe
= getprotobyname(cp
)) == NULL
) {
820 Fprintf(stderr
, "%s: unknown protocol %s\n", prog
, cp
);
825 gwlist
[lsrr
] = to
->sin_addr
.s_addr
;
828 /* force 4 byte alignment */
829 optlist
[0] = IPOPT_NOP
;
830 /* loose source route option */
831 optlist
[1] = IPOPT_LSRR
;
832 i
= lsrr
* sizeof(gwlist
[0]);
834 /* Pointer to LSRR addresses */
835 optlist
[3] = IPOPT_MINOFF
;
836 memcpy(optlist
+ 4, gwlist
, i
);
838 if ((setsockopt(sndsock
, pe
->p_proto
, IP_OPTIONS
,
839 (char *)optlist
, i
+ sizeof(gwlist
[0]))) < 0) {
840 Fprintf(stderr
, "%s: IP_OPTIONS: %s\n",
841 prog
, strerror(errno
));
848 if (setsockopt(sndsock
, SOL_SOCKET
, SO_SNDBUF
, (char *)&packlen
,
849 sizeof(packlen
)) < 0) {
850 Fprintf(stderr
, "%s: SO_SNDBUF: %s\n", prog
, strerror(errno
));
855 if (setsockopt(sndsock
, IPPROTO_IP
, IP_HDRINCL
, (char *)&on
,
857 Fprintf(stderr
, "%s: IP_HDRINCL: %s\n", prog
, strerror(errno
));
862 if (settos
&& setsockopt(sndsock
, IPPROTO_IP
, IP_TOS
,
863 (char *)&tos
, sizeof(tos
)) < 0) {
864 Fprintf(stderr
, "%s: setsockopt tos %d: %s\n",
865 prog
, tos
, strerror(errno
));
870 if (options
& SO_DEBUG
)
871 (void)setsockopt(sndsock
, SOL_SOCKET
, SO_DEBUG
, (char *)&on
,
873 if (options
& SO_DONTROUTE
)
874 (void)setsockopt(sndsock
, SOL_SOCKET
, SO_DONTROUTE
, (char *)&on
,
877 /* Get the interface address list */
878 n
= ifaddrlist(&al
, errbuf
, sizeof(errbuf
));
880 Fprintf(stderr
, "%s: ifaddrlist: %s\n", prog
, errbuf
);
885 "%s: Can't find any network interfaces\n", prog
);
889 /* Look for a specific device */
890 if (device
!= NULL
) {
891 for (i
= n
; i
> 0; --i
, ++al
)
892 if (strcmp(device
, al
->device
) == 0)
895 Fprintf(stderr
, "%s: Can't find interface %.32s\n",
901 /* Determine our source address */
902 if (source
== NULL
) {
904 * If a device was specified, use the interface address.
905 * Otherwise, try to determine our source address.
908 setsin(from
, al
->addr
);
909 else if ((err
= findsaddr(to
, from
)) != NULL
) {
910 Fprintf(stderr
, "%s: findsaddr: %s\n",
915 hi
= gethostinfo(source
);
919 * If the device was specified make sure it
920 * corresponds to the source address specified.
921 * Otherwise, use the first address (and warn if
922 * there are more than one).
924 if (device
!= NULL
) {
925 for (i
= hi
->n
, ap
= hi
->addrs
; i
> 0; --i
, ++ap
)
930 "%s: %s is not on interface %.32s\n",
931 prog
, source
, device
);
936 setsin(from
, hi
->addrs
[0]);
939 "%s: Warning: %s has multiple addresses; using %s\n",
940 prog
, source
, inet_ntoa(from
->sin_addr
));
945 outip
->ip_src
= from
->sin_addr
;
947 /* Check the source address (-s), if any, is valid */
948 if (bind(sndsock
, (struct sockaddr
*)from
, sizeof(*from
)) < 0) {
949 Fprintf(stderr
, "%s: bind: %s\n",
950 prog
, strerror(errno
));
955 asn
= as_setup(as_server
);
957 Fprintf(stderr
, "%s: as_setup failed, AS# lookups"
958 " disabled\n", prog
);
959 (void)fflush(stderr
);
964 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
965 if (setpolicy(sndsock
, "in bypass") < 0)
966 errx(1, "%s", ipsec_strerror());
968 if (setpolicy(sndsock
, "out bypass") < 0)
969 errx(1, "%s", ipsec_strerror());
970 #endif /* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */
972 Fprintf(stderr
, "%s to %s (%s)",
973 prog
, hostname
, inet_ntoa(to
->sin_addr
));
975 Fprintf(stderr
, " from %s", source
);
976 Fprintf(stderr
, ", %d hops max, %d byte packets\n", max_ttl
, packlen
);
977 (void)fflush(stderr
);
979 for (ttl
= first_ttl
; ttl
<= max_ttl
; ++ttl
) {
980 u_int32_t lastaddr
= 0;
988 for (probe
= 0, loss
= 0; probe
< nprobes
; ++probe
) {
990 struct timeval t1
, t2
;
992 register struct ip
*ip
;
993 struct outdata outdata
;
995 if (sentfirst
&& pausemsecs
> 0)
996 usleep(pausemsecs
* 1000);
997 /* Prepare outgoing data */
1001 /* Avoid alignment problems by copying bytewise: */
1002 (void)gettimeofday(&t1
, &tz
);
1003 memcpy(&outdata
.tv
, &t1
, sizeof(outdata
.tv
));
1005 /* Finalize and send packet */
1006 (*proto
->prepare
)(&outdata
);
1007 send_probe(seq
, ttl
);
1010 /* Wait for a reply */
1011 while ((cc
= wait_for_reply(s
, from
, &t1
)) != 0) {
1015 (void)gettimeofday(&t2
, &tz
);
1016 i
= packet_ok(packet
, cc
, from
, seq
);
1017 /* Skip short packet */
1021 from
->sin_addr
.s_addr
!= lastaddr
) {
1022 if (gotlastaddr
) printf("\n ");
1023 print(packet
, cc
, from
);
1024 lastaddr
= from
->sin_addr
.s_addr
;
1027 T
= deltaT(&t1
, &t2
);
1028 #ifdef SANE_PRECISION
1031 else if (T
>= 100.0)
1038 Printf(" %.*f ms", precis
, T
);
1042 -(outip
->ip_hl
<< 3),
1046 pkt_compare((void *)outip
, packlen
,
1047 (void *)hip
, hiplen
);
1051 ip
= (struct ip
*)packet
;
1052 if (ip
->ip_ttl
<= 1)
1058 /* time exceeded in transit */
1064 case ICMP_UNREACH_PORT
:
1066 ip
= (struct ip
*)packet
;
1067 if (ip
->ip_ttl
<= 1)
1073 case ICMP_UNREACH_NET
:
1078 case ICMP_UNREACH_HOST
:
1083 case ICMP_UNREACH_PROTOCOL
:
1088 case ICMP_UNREACH_NEEDFRAG
:
1090 Printf(" !F-%d", pmtu
);
1093 case ICMP_UNREACH_SRCFAIL
:
1098 case ICMP_UNREACH_NET_UNKNOWN
:
1103 case ICMP_UNREACH_HOST_UNKNOWN
:
1108 case ICMP_UNREACH_ISOLATED
:
1113 case ICMP_UNREACH_NET_PROHIB
:
1118 case ICMP_UNREACH_HOST_PROHIB
:
1123 case ICMP_UNREACH_TOSNET
:
1128 case ICMP_UNREACH_TOSHOST
:
1133 case ICMP_UNREACH_FILTER_PROHIB
:
1138 case ICMP_UNREACH_HOST_PRECEDENCE
:
1143 case ICMP_UNREACH_PRECEDENCE_CUTOFF
:
1150 Printf(" !<%d>", code
);
1159 (void)fflush(stdout
);
1162 Printf(" (%d%% loss)", (loss
* 100) / nprobes
);
1166 (unreachable
> 0 && unreachable
>= nprobes
- 1))
1175 wait_for_reply(register int sock
, register struct sockaddr_in
*fromp
,
1176 register const struct timeval
*tp
)
1180 struct timeval now
, wait
;
1182 register int cc
= 0;
1184 socklen_t fromlen
= sizeof(*fromp
);
1186 nfds
= howmany(sock
+ 1, NFDBITS
);
1187 if ((fdsp
= malloc(nfds
* sizeof(fd_set
))) == NULL
)
1189 memset(fdsp
, 0, nfds
* sizeof(fd_set
));
1192 wait
.tv_sec
= tp
->tv_sec
+ waittime
;
1193 wait
.tv_usec
= tp
->tv_usec
;
1194 (void)gettimeofday(&now
, &tz
);
1196 if (wait
.tv_sec
< 0) {
1201 error
= select(sock
+ 1, fdsp
, NULL
, NULL
, &wait
);
1202 if (error
== -1 && errno
== EINVAL
) {
1203 Fprintf(stderr
, "%s: botched select() args\n", prog
);
1207 cc
= recvfrom(sock
, (char *)packet
, sizeof(packet
), 0,
1208 (struct sockaddr
*)fromp
, &fromlen
);
1215 send_probe(int seq
, int ttl
)
1219 outip
->ip_ttl
= ttl
;
1220 outip
->ip_id
= htons(ident
+ seq
);
1222 /* XXX undocumented debugging hack */
1224 register const u_short
*sp
;
1225 register int nshorts
, i
;
1227 sp
= (u_short
*)outip
;
1228 nshorts
= (u_int
)packlen
/ sizeof(u_short
);
1230 Printf("[ %d bytes", packlen
);
1231 while (--nshorts
>= 0) {
1234 Printf(" %04x", ntohs(*sp
++));
1239 Printf(" %02x", *(u_char
*)sp
);
1244 #if !defined(IP_HDRINCL) && defined(IP_TTL)
1245 if (setsockopt(sndsock
, IPPROTO_IP
, IP_TTL
,
1246 (char *)&ttl
, sizeof(ttl
)) < 0) {
1247 Fprintf(stderr
, "%s: setsockopt ttl %d: %s\n",
1248 prog
, ttl
, strerror(errno
));
1253 cc
= sendto(sndsock
, (char *)outip
,
1254 packlen
, 0, &whereto
, sizeof(whereto
));
1255 if (cc
< 0 || cc
!= packlen
) {
1257 Fprintf(stderr
, "%s: sendto: %s\n",
1258 prog
, strerror(errno
));
1259 Printf("%s: wrote %s %d chars, ret=%d\n",
1260 prog
, hostname
, packlen
, cc
);
1261 (void)fflush(stdout
);
1265 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
1267 setpolicy(so
, policy
)
1273 buf
= ipsec_set_policy(policy
, strlen(policy
));
1275 warnx("%s", ipsec_strerror());
1278 (void)setsockopt(so
, IPPROTO_IP
, IP_IPSEC_POLICY
,
1279 buf
, ipsec_get_policylen(buf
));
1288 deltaT(struct timeval
*t1p
, struct timeval
*t2p
)
1292 dt
= (double)(t2p
->tv_sec
- t1p
->tv_sec
) * 1000.0 +
1293 (double)(t2p
->tv_usec
- t1p
->tv_usec
) / 1000.0;
1298 * Convert an ICMP "type" field to a printable string.
1301 pr_type(register u_char t
)
1303 static char *ttab
[] = {
1304 "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable",
1305 "Source Quench", "Redirect", "ICMP 6", "ICMP 7",
1306 "Echo", "ICMP 9", "ICMP 10", "Time Exceeded",
1307 "Param Problem", "Timestamp", "Timestamp Reply", "Info Request",
1312 return("OUT-OF-RANGE");
1318 packet_ok(register u_char
*buf
, int cc
, register struct sockaddr_in
*from
,
1321 register struct icmp
*icp
;
1322 register u_char type
, code
;
1325 register struct ip
*ip
;
1327 ip
= (struct ip
*) buf
;
1328 hlen
= ip
->ip_hl
<< 2;
1329 if (cc
< hlen
+ ICMP_MINLEN
) {
1331 Printf("packet too short (%d bytes) from %s\n", cc
,
1332 inet_ntoa(from
->sin_addr
));
1336 icp
= (struct icmp
*)(buf
+ hlen
);
1338 icp
= (struct icmp
*)buf
;
1340 type
= icp
->icmp_type
;
1341 code
= icp
->icmp_code
;
1342 /* Path MTU Discovery (RFC1191) */
1343 if (code
!= ICMP_UNREACH_NEEDFRAG
)
1346 #ifdef HAVE_ICMP_NEXTMTU
1347 pmtu
= ntohs(icp
->icmp_nextmtu
);
1349 pmtu
= ntohs(((struct my_pmtu
*)&icp
->icmp_void
)->ipm_nextmtu
);
1352 if (type
== ICMP_ECHOREPLY
1353 && proto
->num
== IPPROTO_ICMP
1354 && (*proto
->check
)((u_char
*)icp
, (u_char
)seq
))
1356 if ((type
== ICMP_TIMXCEED
&& code
== ICMP_TIMXCEED_INTRANS
) ||
1357 type
== ICMP_UNREACH
) {
1360 hip
= &icp
->icmp_ip
;
1361 hiplen
= ((u_char
*)icp
+ cc
) - (u_char
*)hip
;
1362 hlen
= hip
->ip_hl
<< 2;
1363 inner
= (u_char
*)((u_char
*)hip
+ hlen
);
1365 && hip
->ip_p
== proto
->num
1366 && (*proto
->check
)(inner
, (u_char
)seq
))
1367 return (type
== ICMP_TIMXCEED
? -1 : code
+ 1);
1372 u_int32_t
*lp
= (u_int32_t
*)&icp
->icmp_ip
;
1374 Printf("\n%d bytes from %s to ", cc
, inet_ntoa(from
->sin_addr
));
1375 Printf("%s: icmp type %d (%s) code %d\n",
1376 inet_ntoa(ip
->ip_dst
), type
, pr_type(type
), icp
->icmp_code
);
1377 for (i
= 4; i
< cc
; i
+= sizeof(*lp
))
1378 Printf("%2d: x%8.8x\n", i
, *lp
++);
1385 icmp_prep(struct outdata
*outdata
)
1387 struct icmp
*const icmpheader
= (struct icmp
*) outp
;
1389 icmpheader
->icmp_type
= ICMP_ECHO
;
1390 icmpheader
->icmp_id
= htons(ident
);
1391 icmpheader
->icmp_seq
= htons(outdata
->seq
);
1392 icmpheader
->icmp_cksum
= 0;
1393 icmpheader
->icmp_cksum
= in_cksum((u_short
*)icmpheader
, protlen
);
1394 if (icmpheader
->icmp_cksum
== 0)
1395 icmpheader
->icmp_cksum
= 0xffff;
1399 icmp_check(const u_char
*data
, int seq
)
1401 struct icmp
*const icmpheader
= (struct icmp
*) data
;
1403 return (icmpheader
->icmp_id
== htons(ident
)
1404 && icmpheader
->icmp_seq
== htons(seq
));
1408 udp_prep(struct outdata
*outdata
)
1410 struct udphdr
*const outudp
= (struct udphdr
*) outp
;
1412 outudp
->uh_sport
= htons(ident
+ (fixedPort
? outdata
->seq
: 0));
1413 outudp
->uh_dport
= htons(port
+ (fixedPort
? 0 : outdata
->seq
));
1414 outudp
->uh_ulen
= htons((u_short
)protlen
);
1417 u_short sum
= p_cksum(outip
, (u_short
*)outudp
, protlen
);
1418 outudp
->uh_sum
= (sum
) ? sum
: 0xffff;
1425 udp_check(const u_char
*data
, int seq
)
1427 struct udphdr
*const udp
= (struct udphdr
*) data
;
1429 return (ntohs(udp
->uh_sport
) == ident
+ (fixedPort
? seq
: 0) &&
1430 ntohs(udp
->uh_dport
) == port
+ (fixedPort
? 0 : seq
));
1434 tcp_prep(struct outdata
*outdata
)
1436 struct tcphdr
*const tcp
= (struct tcphdr
*) outp
;
1438 tcp
->th_sport
= htons(ident
);
1439 tcp
->th_dport
= htons(port
+ (fixedPort
? 0 : outdata
->seq
));
1440 tcp
->th_seq
= (tcp
->th_sport
<< 16) | (tcp
->th_dport
+
1441 (fixedPort
? outdata
->seq
: 0));
1444 tcp
->th_flags
= TH_SYN
;
1448 u_short sum
= p_cksum(outip
, (u_short
*)tcp
, protlen
);
1449 tcp
->th_sum
= (sum
) ? sum
: 0xffff;
1454 tcp_check(const u_char
*data
, int seq
)
1456 struct tcphdr
*const tcp
= (struct tcphdr
*) data
;
1458 return (ntohs(tcp
->th_sport
) == ident
1459 && ntohs(tcp
->th_dport
) == port
+ (fixedPort
? 0 : seq
))
1460 && tcp
->th_seq
== ((ident
<< 16) | (port
+ seq
));
1464 gre_prep(struct outdata
*outdata
)
1466 struct grehdr
*const gre
= (struct grehdr
*) outp
;
1468 gre
->flags
= htons(0x2001);
1469 gre
->proto
= htons(port
);
1471 gre
->callId
= htons(ident
+ outdata
->seq
);
1475 gre_check(const u_char
*data
, int seq
)
1477 struct grehdr
*const gre
= (struct grehdr
*) data
;
1479 return(ntohs(gre
->proto
) == port
1480 && ntohs(gre
->callId
) == ident
+ seq
);
1484 gen_prep(struct outdata
*outdata
)
1486 u_int16_t
*const ptr
= (u_int16_t
*) outp
;
1488 ptr
[0] = htons(ident
);
1489 ptr
[1] = htons(port
+ outdata
->seq
);
1493 gen_check(const u_char
*data
, int seq
)
1495 u_int16_t
*const ptr
= (u_int16_t
*) data
;
1497 return(ntohs(ptr
[0]) == ident
1498 && ntohs(ptr
[1]) == port
+ seq
);
1502 print(register u_char
*buf
, register int cc
, register struct sockaddr_in
*from
)
1504 register struct ip
*ip
;
1507 ip
= (struct ip
*) buf
;
1508 hlen
= ip
->ip_hl
<< 2;
1512 Printf(" [AS%d]", as_lookup(asn
, &from
->sin_addr
));
1515 Printf(" %s", inet_ntoa(from
->sin_addr
));
1517 Printf(" %s (%s)", inetname(from
->sin_addr
),
1518 inet_ntoa(from
->sin_addr
));
1521 Printf(" %d bytes to %s", cc
, inet_ntoa (ip
->ip_dst
));
1525 * Checksum routine for UDP and TCP headers.
1528 p_cksum(struct ip
*ip
, u_short
*data
, int len
)
1530 static struct ipovly ipo
;
1534 ipo
.ih_pr
= ip
->ip_p
;
1535 ipo
.ih_len
= htons(len
);
1536 ipo
.ih_src
= ip
->ip_src
;
1537 ipo
.ih_dst
= ip
->ip_dst
;
1539 sumh
= in_cksum((u_short
*)&ipo
, sizeof(ipo
)); /* pseudo ip hdr cksum */
1540 sumd
= in_cksum((u_short
*)data
, len
); /* payload data cksum */
1541 sumt
= (sumh
<< 16) | (sumd
);
1543 return ~in_cksum((u_short
*)&sumt
, sizeof(sumt
));
1547 * Checksum routine for Internet Protocol family headers (C Version)
1550 in_cksum(register u_short
*addr
, register int len
)
1552 register int nleft
= len
;
1553 register u_short
*w
= addr
;
1554 register u_short answer
;
1555 register int sum
= 0;
1558 * Our algorithm is simple, using a 32 bit accumulator (sum),
1559 * we add sequential 16 bit words to it, and at the end, fold
1560 * back all the carry bits from the top 16 bits into the lower
1568 /* mop up an odd byte, if necessary */
1570 sum
+= *(u_char
*)w
;
1573 * add back carry outs from top 16 bits to low 16 bits
1575 sum
= (sum
>> 16) + (sum
& 0xffff); /* add hi 16 to low 16 */
1576 sum
+= (sum
>> 16); /* add carry */
1577 answer
= ~sum
; /* truncate to 16 bits */
1582 * Subtract 2 timeval structs: out = out - in.
1583 * Out is assumed to be within about LONG_MAX seconds of in.
1586 tvsub(register struct timeval
*out
, register struct timeval
*in
)
1589 if ((out
->tv_usec
-= in
->tv_usec
) < 0) {
1591 out
->tv_usec
+= 1000000;
1593 out
->tv_sec
-= in
->tv_sec
;
1597 * Construct an Internet address representation.
1598 * If the nflag has been supplied, give
1599 * numeric value, otherwise try for symbolic name.
1602 inetname(struct in_addr in
)
1605 register struct hostent
*hp
;
1606 static int first
= 1;
1607 static char domain
[MAXHOSTNAMELEN
+ 1], line
[MAXHOSTNAMELEN
+ 1];
1609 if (first
&& !nflag
) {
1611 if (gethostname(domain
, sizeof(domain
) - 1) < 0)
1614 cp
= strchr(domain
, '.');
1616 hp
= gethostbyname(domain
);
1618 cp
= strchr(hp
->h_name
, '.');
1624 (void)strncpy(domain
, cp
, sizeof(domain
) - 1);
1625 domain
[sizeof(domain
) - 1] = '\0';
1629 if (!nflag
&& in
.s_addr
!= INADDR_ANY
) {
1630 hp
= gethostbyaddr((char *)&in
, sizeof(in
), AF_INET
);
1632 if ((cp
= strchr(hp
->h_name
, '.')) != NULL
&&
1633 strcmp(cp
+ 1, domain
) == 0)
1635 (void)strncpy(line
, hp
->h_name
, sizeof(line
) - 1);
1636 line
[sizeof(line
) - 1] = '\0';
1640 return (inet_ntoa(in
));
1644 gethostinfo(register char *hostname
)
1647 register struct hostent
*hp
;
1648 register struct hostinfo
*hi
;
1650 register u_int32_t addr
, *ap
;
1652 if (strlen(hostname
) > 64) {
1653 Fprintf(stderr
, "%s: hostname \"%.32s...\" is too long\n",
1657 hi
= calloc(1, sizeof(*hi
));
1659 Fprintf(stderr
, "%s: calloc %s\n", prog
, strerror(errno
));
1662 addr
= inet_addr(hostname
);
1663 if ((int32_t)addr
!= -1) {
1664 hi
->name
= strdup(hostname
);
1666 hi
->addrs
= calloc(1, sizeof(hi
->addrs
[0]));
1667 if (hi
->addrs
== NULL
) {
1668 Fprintf(stderr
, "%s: calloc %s\n",
1669 prog
, strerror(errno
));
1672 hi
->addrs
[0] = addr
;
1676 hp
= gethostbyname(hostname
);
1678 Fprintf(stderr
, "%s: unknown host %s\n", prog
, hostname
);
1681 if (hp
->h_addrtype
!= AF_INET
|| hp
->h_length
!= 4) {
1682 Fprintf(stderr
, "%s: bad host %s\n", prog
, hostname
);
1685 hi
->name
= strdup(hp
->h_name
);
1686 for (n
= 0, p
= hp
->h_addr_list
; *p
!= NULL
; ++n
, ++p
)
1689 hi
->addrs
= calloc(n
, sizeof(hi
->addrs
[0]));
1690 if (hi
->addrs
== NULL
) {
1691 Fprintf(stderr
, "%s: calloc %s\n", prog
, strerror(errno
));
1694 for (ap
= hi
->addrs
, p
= hp
->h_addr_list
; *p
!= NULL
; ++ap
, ++p
)
1695 memcpy(ap
, *p
, sizeof(*ap
));
1700 freehostinfo(register struct hostinfo
*hi
)
1702 if (hi
->name
!= NULL
) {
1706 free((char *)hi
->addrs
);
1711 getaddr(register u_int32_t
*ap
, register char *hostname
)
1713 register struct hostinfo
*hi
;
1715 hi
= gethostinfo(hostname
);
1721 setsin(register struct sockaddr_in
*sin
, register u_int32_t addr
)
1724 memset(sin
, 0, sizeof(*sin
));
1725 #ifdef HAVE_SOCKADDR_SA_LEN
1726 sin
->sin_len
= sizeof(*sin
);
1728 sin
->sin_family
= AF_INET
;
1729 sin
->sin_addr
.s_addr
= addr
;
1732 /* String to value with optional min and max. Handles decimal and hex. */
1734 str2val(register const char *str
, register const char *what
,
1735 register int mi
, register int ma
)
1737 register const char *cp
;
1741 if (str
[0] == '0' && (str
[1] == 'x' || str
[1] == 'X')) {
1743 val
= (int)strtol(cp
, &ep
, 16);
1745 val
= (int)strtol(str
, &ep
, 10);
1747 Fprintf(stderr
, "%s: \"%s\" bad value for %s \n",
1751 if (val
< mi
&& mi
>= 0) {
1753 Fprintf(stderr
, "%s: %s must be >= %d\n",
1756 Fprintf(stderr
, "%s: %s must be > %d\n",
1757 prog
, what
, mi
- 1);
1760 if (val
> ma
&& ma
>= 0) {
1761 Fprintf(stderr
, "%s: %s must be <= %d\n", prog
, what
, ma
);
1768 setproto(char *pname
)
1770 struct outproto
*proto
;
1773 for (i
= 0; protos
[i
].name
!= NULL
; i
++) {
1774 if (strcasecmp(protos
[i
].name
, pname
) == 0) {
1779 if (proto
->name
== NULL
) { /* generic handler */
1780 struct protoent
*pe
;
1783 /* Determine the IP protocol number */
1784 if ((pe
= getprotobyname(pname
)) != NULL
)
1787 pnum
= str2val(optarg
, "proto number", 1, 255);
1794 pkt_compare(const u_char
*a
, int la
, const u_char
*b
, int lb
) {
1798 for (i
= 0; i
< la
; i
++)
1799 Printf("%02x", (unsigned int)a
[i
]);
1801 l
= (la
<= lb
) ? la
: lb
;
1802 for (i
= 0; i
< l
; i
++)
1806 Printf("%02x", (unsigned int)b
[i
]);
1808 Printf("%02x", (unsigned int)b
[i
]);
1816 extern char version
[];
1818 Fprintf(stderr
, "Version %s\n", version
);
1820 "Usage: %s [-adDeFInrSvx] [-A as_server] [-f first_ttl] [-g gateway] [-i iface]\n"
1821 "\t[-M first_ttl] [-m max_ttl] [-p port] [-P proto] [-q nqueries] [-s src_addr]\n"
1822 "\t[-t tos] [-w waittime] [-z pausemsecs] host [packetlen]\n", prog
);