2 * Copyright (c) 2004-2013 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.
51 static const char copyright
[] =
52 "@(#) Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000\n\
53 The Regents of the University of California. All rights reserved.\n";
55 static const char rcsid
[] =
56 "@(#)$Id: traceroute.c,v 1.4 2006/02/07 06:22:57 lindak Exp $ (LBL)";
58 static const char rcsid
[] =
59 "$FreeBSD: src/contrib/traceroute/traceroute.c,v 1.35 2008/02/20 23:29:52 rpaulo Exp $";
63 * traceroute host - trace the route ip packets follow going to "host".
65 * Attempt to trace the route an ip packet would follow to some
66 * internet host. We find out intermediate hops by launching probe
67 * packets with a small ttl (time to live) then listening for an
68 * icmp "time exceeded" reply from a gateway. We start our probes
69 * with a ttl of one and increase by one until we get an icmp "port
70 * unreachable" (which means we got to "host") or hit a max (which
71 * defaults to net.inet.ip.ttl hops & can be changed with the -m flag).
72 * Three probes (change with -q flag) are sent at each ttl setting and
73 * a line is printed showing the ttl, address of the gateway and
74 * round trip time of each probe. If the probe answers come from
75 * different gateways, the address of each responding system will
76 * be printed. If there is no response within a 5 sec. timeout
77 * interval (changed with the -w flag), a "*" is printed for that
80 * Probe packets are UDP format. We don't want the destination
81 * host to process them so the destination port is set to an
82 * unlikely value (if some clod on the destination is using that
83 * value, it can be changed with the -p flag).
85 * A sample use might be:
87 * [yak 71]% traceroute nis.nsf.net.
88 * traceroute to nis.nsf.net (35.1.1.48), 64 hops max, 56 byte packet
89 * 1 helios.ee.lbl.gov (128.3.112.1) 19 ms 19 ms 0 ms
90 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
91 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
92 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 39 ms
93 * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 39 ms 39 ms 39 ms
94 * 6 128.32.197.4 (128.32.197.4) 40 ms 59 ms 59 ms
95 * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 59 ms
96 * 8 129.140.70.13 (129.140.70.13) 99 ms 99 ms 80 ms
97 * 9 129.140.71.6 (129.140.71.6) 139 ms 239 ms 319 ms
98 * 10 129.140.81.7 (129.140.81.7) 220 ms 199 ms 199 ms
99 * 11 nic.merit.edu (35.1.1.48) 239 ms 239 ms 239 ms
101 * Note that lines 2 & 3 are the same. This is due to a buggy
102 * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
103 * packets with a zero ttl.
105 * A more interesting example is:
107 * [yak 72]% traceroute allspice.lcs.mit.edu.
108 * traceroute to allspice.lcs.mit.edu (18.26.0.115), 64 hops max
109 * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
110 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 19 ms 19 ms
111 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 19 ms
112 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 19 ms 39 ms 39 ms
113 * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 20 ms 39 ms 39 ms
114 * 6 128.32.197.4 (128.32.197.4) 59 ms 119 ms 39 ms
115 * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 39 ms
116 * 8 129.140.70.13 (129.140.70.13) 80 ms 79 ms 99 ms
117 * 9 129.140.71.6 (129.140.71.6) 139 ms 139 ms 159 ms
118 * 10 129.140.81.7 (129.140.81.7) 199 ms 180 ms 300 ms
119 * 11 129.140.72.17 (129.140.72.17) 300 ms 239 ms 239 ms
121 * 13 128.121.54.72 (128.121.54.72) 259 ms 499 ms 279 ms
126 * 18 ALLSPICE.LCS.MIT.EDU (18.26.0.115) 339 ms 279 ms 279 ms
128 * (I start to see why I'm having so much trouble with mail to
129 * MIT.) Note that the gateways 12, 14, 15, 16 & 17 hops away
130 * either don't send ICMP "time exceeded" messages or send them
131 * with a ttl too small to reach us. 14 - 17 are running the
132 * MIT C Gateway code that doesn't send "time exceeded"s. God
133 * only knows what's going on with 12.
135 * The silent gateway 12 in the above may be the result of a bug in
136 * the 4.[23]BSD network code (and its derivatives): 4.x (x <= 3)
137 * sends an unreachable message using whatever ttl remains in the
138 * original datagram. Since, for gateways, the remaining ttl is
139 * zero, the icmp "time exceeded" is guaranteed to not make it back
140 * to us. The behavior of this bug is slightly more interesting
141 * when it appears on the destination system:
143 * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
144 * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 39 ms
145 * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 39 ms 19 ms
146 * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 19 ms
147 * 5 ccn-nerif35.Berkeley.EDU (128.32.168.35) 39 ms 39 ms 39 ms
148 * 6 csgw.Berkeley.EDU (128.32.133.254) 39 ms 59 ms 39 ms
155 * 13 rip.Berkeley.EDU (128.32.131.22) 59 ms ! 39 ms ! 39 ms !
157 * Notice that there are 12 "gateways" (13 is the final
158 * destination) and exactly the last half of them are "missing".
159 * What's really happening is that rip (a Sun-3 running Sun OS3.5)
160 * is using the ttl from our arriving datagram as the ttl in its
161 * icmp reply. So, the reply will time out on the return path
162 * (with no notice sent to anyone since icmp's aren't sent for
163 * icmp's) until we probe with a ttl that's at least twice the path
164 * length. I.e., rip is really only 7 hops away. A reply that
165 * returns with a ttl of 1 is a clue this problem exists.
166 * Traceroute prints a "!" after the time if the ttl is <= 1.
167 * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
168 * non-standard (HPUX) software, expect to see this problem
169 * frequently and/or take care picking the target host of your
172 * Other possible annotations after the time are !H, !N, !P (got a host,
173 * network or protocol unreachable, respectively), !S or !F (source
174 * route failed or fragmentation needed -- neither of these should
175 * ever occur and the associated gateway is busted if you see one). If
176 * almost all the probes result in some kind of unreachable, traceroute
177 * will give up and exit.
181 * This program must be run by root or be setuid. (I suggest that
182 * you *don't* make it setuid -- casual use could result in a lot
183 * of unnecessary traffic on our poor, congested nets.)
185 * This program requires a kernel mod that does not appear in any
186 * system available from Berkeley: A raw ip socket using proto
187 * IPPROTO_RAW must interpret the data sent as an ip datagram (as
188 * opposed to data to be wrapped in a ip datagram). See the README
189 * file that came with the source to this program for a description
190 * of the mods I made to /sys/netinet/raw_ip.c. Your mileage may
191 * vary. But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
192 * MODIFIED TO RUN THIS PROGRAM.
194 * The udp port usage may appear bizarre (well, ok, it is bizarre).
195 * The problem is that an icmp message only contains 8 bytes of
196 * data from the original datagram. 8 bytes is the size of a udp
197 * header so, if we want to associate replies with the original
198 * datagram, the necessary information must be encoded into the
199 * udp header (the ip id could be used but there's no way to
200 * interlock with the kernel's assignment of ip id's and, anyway,
201 * it would have taken a lot more kernel hacking to allow this
202 * code to set the ip id). So, to allow two or more users to
203 * use traceroute simultaneously, we use this task's pid as the
204 * source port (the high bit is set to move the port number out
205 * of the "likely" range). To keep track of which probe is being
206 * replied to (so times and/or hop counts don't get confused by a
207 * reply that was delayed in transit), we increment the destination
208 * port number before each probe.
210 * Don't use this as a coding example. I was trying to find a
211 * routing problem and this code sort-of popped out after 48 hours
212 * without sleep. I was amazed it ever compiled, much less ran.
214 * I stole the idea for this program from Steve Deering. Since
215 * the first release, I've learned that had I attended the right
216 * IETF working group meetings, I also could have stolen it from Guy
217 * Almes or Matt Mathis. I don't know (or care) who came up with
218 * the idea first. I envy the originators' perspicacity and I'm
219 * glad they didn't keep the idea a secret.
221 * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
222 * enhancements to the original distribution.
224 * I've hacked up a round-trip-route version of this that works by
225 * sending a loose-source-routed udp datagram through the destination
226 * back to yourself. Unfortunately, SO many gateways botch source
227 * routing, the thing is almost worthless. Maybe one day...
229 * -- Van Jacobson (van@ee.lbl.gov)
230 * Tue Dec 20 03:50:13 PST 1988
233 #include <sys/param.h>
234 #include <sys/file.h>
235 #include <sys/ioctl.h>
236 #ifdef HAVE_SYS_SELECT_H
237 #include <sys/select.h>
239 #include <sys/socket.h>
240 #ifdef HAVE_SYS_SYSCTL_H
241 #include <sys/sysctl.h>
243 #include <sys/time.h>
245 #include <netinet/in_systm.h>
246 #include <netinet/in.h>
247 #include <netinet/ip.h>
248 #include <netinet/ip_var.h>
249 #include <netinet/ip_icmp.h>
250 #include <netinet/udp.h>
251 #include <netinet/udp_var.h>
252 #include <netinet/tcp.h>
253 #include <netinet/tcpip.h>
255 #include <arpa/inet.h>
258 #include <net/route.h>
259 #include <netinet6/ipsec.h> /* XXX */
277 #ifdef HAVE_OS_PROTO_H
278 #include "os-proto.h"
282 #ifndef ICMP_UNREACH_FILTER_PROHIB
283 #define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohibited filter */
285 #ifndef ICMP_UNREACH_HOST_PRECEDENCE
286 #define ICMP_UNREACH_HOST_PRECEDENCE 14 /* host precedence violation */
288 #ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF
289 #define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* precedence cutoff */
292 #include "findsaddr.h"
293 #include "ifaddrlist.h"
295 #include "traceroute.h"
297 /* Maximum number of gateways (include room for one noop) */
298 #define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t)))
300 #ifndef MAXHOSTNAMELEN
301 #define MAXHOSTNAMELEN 64
304 #define Fprintf (void)fprintf
305 #define Printf (void)printf
307 /* What a GRE packet header looks like */
311 u_int16_t length
; /* PPTP version of these fields */
315 #define IPPROTO_GRE 47
318 /* For GRE, we prepare what looks like a PPTP packet */
319 #define GRE_PPTP_PROTO 0x880b
321 /* Host name and address list */
328 /* Data section of the probe packet */
330 u_char seq
; /* sequence number of this packet */
331 u_char ttl
; /* ttl packet left with */
332 struct timeval tv
; /* time packet left */
335 #ifndef HAVE_ICMP_NEXTMTU
336 /* Path MTU Discovery (RFC1191) */
343 u_char packet
[512]; /* last inbound (icmp) packet */
345 struct ip
*outip
; /* last output ip packet */
346 u_char
*outp
; /* last output inner protocol packet */
348 struct ip
*hip
= NULL
; /* Quoted IP header */
351 /* loose source route gateway list (including room for final destination) */
352 u_int32_t gwlist
[NGATEWAYS
+ 1];
354 int s
; /* receive (icmp) socket file descriptor */
355 int sndsock
; /* send (udp) socket file descriptor */
357 struct sockaddr whereto
; /* Who to try to reach */
358 struct sockaddr wherefrom
; /* Who we are */
359 int packlen
; /* total length of packet */
360 int protlen
; /* length of protocol part of packet */
361 int minpacket
; /* min ip packet size */
362 int maxpacket
= 32 * 1024; /* max ip packet size */
363 int pmtu
; /* Path MTU Discovery (RFC1191) */
370 static const char devnull
[] = "/dev/null";
376 u_short port
; /* protocol specific base "port" */
378 int options
; /* socket options */
380 int waittime
= 5; /* time to wait for response (in seconds) */
381 int nflag
; /* print addresses numerically */
382 int as_path
; /* print as numbers for each hop */
383 char *as_server
= NULL
;
385 #ifdef CANT_HACK_IPCKSUM
386 int doipcksum
= 0; /* don't calculate ip checksums by default */
388 int doipcksum
= 1; /* calculate ip checksums by default */
390 int optlen
; /* length of ip options */
391 int fixedPort
= 0; /* Use fixed destination port for TCP and UDP */
392 int printdiff
= 0; /* Print the difference between sent and quoted */
399 double deltaT(struct timeval
*, struct timeval
*);
400 void freehostinfo(struct hostinfo
*);
401 void getaddr(u_int32_t
*, char *);
402 struct hostinfo
*gethostinfo(char *);
403 u_short
in_cksum(u_short
*, int);
404 char *inetname(struct in_addr
);
405 int main(int, char **);
406 u_short
p_cksum(struct ip
*, u_short
*, int);
407 int packet_ok(u_char
*, int, struct sockaddr_in
*, int);
408 char *pr_type(u_char
);
409 void print(u_char
*, int, struct sockaddr_in
*);
411 int setpolicy
__P((int so
, char *policy
));
413 void send_probe(int, int);
414 struct outproto
*setproto(char *);
415 int str2val(const char *, const char *, int, int);
416 void tvsub(struct timeval
*, struct timeval
*);
418 int wait_for_reply(int, struct sockaddr_in
*, const struct timeval
*);
419 void pkt_compare(const u_char
*, int, const u_char
*, int);
424 void udp_prep(struct outdata
*);
425 int udp_check(const u_char
*, int);
426 void tcp_prep(struct outdata
*);
427 int tcp_check(const u_char
*, int);
428 void gre_prep(struct outdata
*);
429 int gre_check(const u_char
*, int);
430 void gen_prep(struct outdata
*);
431 int gen_check(const u_char
*, int);
432 void icmp_prep(struct outdata
*);
433 int icmp_check(const u_char
*, int);
435 /* Descriptor structure for each outgoing protocol we support */
437 char *name
; /* name of protocol */
438 const char *key
; /* An ascii key for the bytes of the header */
439 u_char num
; /* IP protocol number */
440 u_short hdrlen
; /* max size of protocol header */
441 u_short port
; /* default base protocol-specific "port" */
442 void (*prepare
)(struct outdata
*);
443 /* finish preparing an outgoing packet */
444 int (*check
)(const u_char
*, int);
445 /* check an incoming packet */
448 /* List of supported protocols. The first one is the default. The last
449 one is the handler for generic protocols not explicitly listed. */
450 struct outproto protos
[] = {
455 sizeof(struct udphdr
),
462 "spt dpt seq ack xxflwin sum urp",
464 sizeof(struct tcphdr
),
473 sizeof(struct grehdr
),
497 struct outproto
*proto
= &protos
[0];
499 const char *ip_hdr_key
= "vhtslen id off tlprsum srcip dstip opts";
502 main(int argc
, char **argv
)
504 register int op
, code
, n
;
506 register const char *err
;
507 register u_int32_t
*ap
;
508 register struct sockaddr_in
*from
= (struct sockaddr_in
*)&wherefrom
;
509 register struct sockaddr_in
*to
= (struct sockaddr_in
*)&whereto
;
510 register struct hostinfo
*hi
;
512 register struct protoent
*pe
;
513 register int ttl
, probe
, i
;
514 register int seq
= 0;
515 int tos
= 0, settos
= 0;
516 register int lsrr
= 0;
517 register u_short off
= 0;
518 struct ifaddrlist
*al
;
520 int requestPort
= -1;
524 /* Insure the socket fds won't be 0, 1 or 2 */
525 if (open(devnull
, O_RDONLY
) < 0 ||
526 open(devnull
, O_RDONLY
) < 0 ||
527 open(devnull
, O_RDONLY
) < 0) {
528 Fprintf(stderr
, "%s: open \"%s\": %s\n",
529 prog
, devnull
, strerror(errno
));
533 * Do the setuid-required stuff first, then lose priveleges ASAP.
534 * Do error checking for these two calls where they appeared in
538 pe
= getprotobyname(cp
);
540 if ((s
= socket(AF_INET
, SOCK_RAW
, pe
->p_proto
)) < 0)
542 else if ((sndsock
= socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
)) < 0)
550 int mib
[4] = { CTL_NET
, PF_INET
, IPPROTO_IP
, IPCTL_DEFTTL
};
551 size_t sz
= sizeof(max_ttl
);
553 if (sysctl(mib
, 4, &max_ttl
, &sz
, NULL
, 0) == -1) {
554 perror("sysctl(net.inet.ip.ttl)");
564 else if ((cp
= strrchr(argv
[0], '/')) != NULL
)
570 while ((op
= getopt(argc
, argv
, "aA:edDFInrSvxf:g:i:M:m:P:p:q:s:t:w:z:")) != EOF
)
594 case 'M': /* FreeBSD compat. */
595 first_ttl
= str2val(optarg
, "first ttl", 1, 255);
603 if (lsrr
>= NGATEWAYS
) {
605 "%s: No more than %d gateways\n",
609 getaddr(gwlist
+ lsrr
, optarg
);
618 proto
= setproto("icmp");
622 max_ttl
= str2val(optarg
, "max ttl", 1, 255);
630 proto
= setproto(optarg
);
634 requestPort
= (u_short
)str2val(optarg
, "port",
639 nprobes
= str2val(optarg
, "nprobes", 1, -1);
643 options
|= SO_DONTROUTE
;
648 * set the ip source address of the outbound
649 * probe (e.g., on a multi-homed host).
659 tos
= str2val(optarg
, "tos", 0, 255);
668 doipcksum
= (doipcksum
== 0);
672 waittime
= str2val(optarg
, "wait time",
677 pausemsecs
= str2val(optarg
, "pause msecs",
685 /* Set requested port, if any, else default for this protocol */
686 port
= (requestPort
!= -1) ? requestPort
: proto
->port
;
689 nprobes
= printdiff
? 1 : 3;
691 if (first_ttl
> max_ttl
) {
693 "%s: first ttl (%d) may not be greater than max ttl (%d)\n",
694 prog
, first_ttl
, max_ttl
);
699 Fprintf(stderr
, "%s: Warning: ip checksums disabled\n", prog
);
702 optlen
= (lsrr
+ 1) * sizeof(gwlist
[0]);
703 minpacket
= sizeof(*outip
) + proto
->hdrlen
+ sizeof(struct outdata
) + optlen
;
704 packlen
= minpacket
; /* minimum sized packet */
706 /* Process destination and optional packet size */
707 switch (argc
- optind
) {
710 packlen
= str2val(argv
[optind
+ 1],
711 "packet length", minpacket
, maxpacket
);
715 hostname
= argv
[optind
];
716 hi
= gethostinfo(hostname
);
717 setsin(to
, hi
->addrs
[0]);
720 "%s: Warning: %s has multiple addresses; using %s\n",
721 prog
, hostname
, inet_ntoa(to
->sin_addr
));
731 #ifdef HAVE_SETLINEBUF
734 setvbuf(stdout
, NULL
, _IOLBF
, 0);
737 protlen
= packlen
- sizeof(*outip
) - optlen
;
739 outip
= (struct ip
*)malloc((unsigned)packlen
);
741 Fprintf(stderr
, "%s: malloc: %s\n", prog
, strerror(errno
));
744 memset((char *)outip
, 0, packlen
);
746 outip
->ip_v
= IPVERSION
;
749 #ifdef BYTESWAP_IP_HDR
750 outip
->ip_len
= htons(packlen
);
751 outip
->ip_off
= htons(off
);
753 outip
->ip_len
= packlen
;
756 outip
->ip_p
= proto
->num
;
757 outp
= (u_char
*)(outip
+ 1);
758 #ifdef HAVE_RAW_OPTIONS
760 register u_char
*optlist
;
766 gwlist
[lsrr
] = to
->sin_addr
.s_addr
;
768 outip
->ip_dst
.s_addr
= gwlist
[0];
770 /* force 4 byte alignment */
771 optlist
[0] = IPOPT_NOP
;
772 /* loose source route option */
773 optlist
[1] = IPOPT_LSRR
;
774 i
= lsrr
* sizeof(gwlist
[0]);
776 /* Pointer to LSRR addresses */
777 optlist
[3] = IPOPT_MINOFF
;
778 memcpy(optlist
+ 4, gwlist
+ 1, i
);
781 outip
->ip_dst
= to
->sin_addr
;
783 outip
->ip_hl
= (outp
- (u_char
*)outip
) >> 2;
784 ident
= (getpid() & 0xffff) | 0x8000;
787 Fprintf(stderr
, "%s: unknown protocol %s\n", prog
, cp
);
792 Fprintf(stderr
, "%s: icmp socket: %s\n", prog
, strerror(errno
));
795 (void) setsockopt(s
, SOL_SOCKET
, SO_RECV_ANYIF
, (char *)&on
,
797 if (options
& SO_DEBUG
)
798 (void)setsockopt(s
, SOL_SOCKET
, SO_DEBUG
, (char *)&on
,
800 if (options
& SO_DONTROUTE
)
801 (void)setsockopt(s
, SOL_SOCKET
, SO_DONTROUTE
, (char *)&on
,
804 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
805 if (setpolicy(s
, "in bypass") < 0)
806 errx(1, "%s", ipsec_strerror());
808 if (setpolicy(s
, "out bypass") < 0)
809 errx(1, "%s", ipsec_strerror());
810 #endif /* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */
814 Fprintf(stderr
, "%s: raw socket: %s\n", prog
, strerror(errno
));
818 #if defined(IP_OPTIONS) && !defined(HAVE_RAW_OPTIONS)
820 u_char optlist
[MAX_IPOPTLEN
];
823 if ((pe
= getprotobyname(cp
)) == NULL
) {
824 Fprintf(stderr
, "%s: unknown protocol %s\n", prog
, cp
);
829 gwlist
[lsrr
] = to
->sin_addr
.s_addr
;
832 /* force 4 byte alignment */
833 optlist
[0] = IPOPT_NOP
;
834 /* loose source route option */
835 optlist
[1] = IPOPT_LSRR
;
836 i
= lsrr
* sizeof(gwlist
[0]);
838 /* Pointer to LSRR addresses */
839 optlist
[3] = IPOPT_MINOFF
;
840 memcpy(optlist
+ 4, gwlist
, i
);
842 if ((setsockopt(sndsock
, pe
->p_proto
, IP_OPTIONS
,
843 (char *)optlist
, i
+ sizeof(gwlist
[0]))) < 0) {
844 Fprintf(stderr
, "%s: IP_OPTIONS: %s\n",
845 prog
, strerror(errno
));
852 if (setsockopt(sndsock
, SOL_SOCKET
, SO_SNDBUF
, (char *)&packlen
,
853 sizeof(packlen
)) < 0) {
854 Fprintf(stderr
, "%s: SO_SNDBUF: %s\n", prog
, strerror(errno
));
859 if (setsockopt(sndsock
, IPPROTO_IP
, IP_HDRINCL
, (char *)&on
,
861 Fprintf(stderr
, "%s: IP_HDRINCL: %s\n", prog
, strerror(errno
));
866 if (settos
&& setsockopt(sndsock
, IPPROTO_IP
, IP_TOS
,
867 (char *)&tos
, sizeof(tos
)) < 0) {
868 Fprintf(stderr
, "%s: setsockopt tos %d: %s\n",
869 prog
, tos
, strerror(errno
));
874 if (options
& SO_DEBUG
)
875 (void)setsockopt(sndsock
, SOL_SOCKET
, SO_DEBUG
, (char *)&on
,
877 if (options
& SO_DONTROUTE
)
878 (void)setsockopt(sndsock
, SOL_SOCKET
, SO_DONTROUTE
, (char *)&on
,
881 /* Get the interface address list */
882 n
= ifaddrlist(&al
, errbuf
, sizeof(errbuf
));
884 Fprintf(stderr
, "%s: ifaddrlist: %s\n", prog
, errbuf
);
889 "%s: Can't find any network interfaces\n", prog
);
893 /* Look for a specific device */
894 if (device
!= NULL
) {
895 for (i
= n
; i
> 0; --i
, ++al
)
896 if (strcmp(device
, al
->device
) == 0)
899 Fprintf(stderr
, "%s: Can't find interface %.32s\n",
905 /* Determine our source address */
906 if (source
== NULL
) {
908 * If a device was specified, use the interface address.
909 * Otherwise, try to determine our source address.
912 setsin(from
, al
->addr
);
913 else if ((err
= findsaddr(to
, from
)) != NULL
) {
914 Fprintf(stderr
, "%s: findsaddr: %s\n",
919 hi
= gethostinfo(source
);
923 * If the device was specified make sure it
924 * corresponds to the source address specified.
925 * Otherwise, use the first address (and warn if
926 * there are more than one).
928 if (device
!= NULL
) {
929 for (i
= hi
->n
, ap
= hi
->addrs
; i
> 0; --i
, ++ap
)
934 "%s: %s is not on interface %.32s\n",
935 prog
, source
, device
);
940 setsin(from
, hi
->addrs
[0]);
943 "%s: Warning: %s has multiple addresses; using %s\n",
944 prog
, source
, inet_ntoa(from
->sin_addr
));
949 outip
->ip_src
= from
->sin_addr
;
951 /* Check the source address (-s), if any, is valid */
952 if (bind(sndsock
, (struct sockaddr
*)from
, sizeof(*from
)) < 0) {
953 Fprintf(stderr
, "%s: bind: %s\n",
954 prog
, strerror(errno
));
959 asn
= as_setup(as_server
);
961 Fprintf(stderr
, "%s: as_setup failed, AS# lookups"
962 " disabled\n", prog
);
963 (void)fflush(stderr
);
968 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
969 if (setpolicy(sndsock
, "in bypass") < 0)
970 errx(1, "%s", ipsec_strerror());
972 if (setpolicy(sndsock
, "out bypass") < 0)
973 errx(1, "%s", ipsec_strerror());
974 #endif /* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */
976 Fprintf(stderr
, "%s to %s (%s)",
977 prog
, hostname
, inet_ntoa(to
->sin_addr
));
979 Fprintf(stderr
, " from %s", source
);
980 Fprintf(stderr
, ", %d hops max, %d byte packets\n", max_ttl
, packlen
);
981 (void)fflush(stderr
);
983 for (ttl
= first_ttl
; ttl
<= max_ttl
; ++ttl
) {
984 u_int32_t lastaddr
= 0;
992 for (probe
= 0, loss
= 0; probe
< nprobes
; ++probe
) {
994 struct timeval t1
, t2
;
996 register struct ip
*ip
;
997 struct outdata outdata
;
999 if (sentfirst
&& pausemsecs
> 0)
1000 usleep(pausemsecs
* 1000);
1001 /* Prepare outgoing data */
1002 outdata
.seq
= ++seq
;
1005 /* Avoid alignment problems by copying bytewise: */
1006 (void)gettimeofday(&t1
, &tz
);
1007 memcpy(&outdata
.tv
, &t1
, sizeof(outdata
.tv
));
1009 /* Finalize and send packet */
1010 (*proto
->prepare
)(&outdata
);
1011 send_probe(seq
, ttl
);
1014 /* Wait for a reply */
1015 while ((cc
= wait_for_reply(s
, from
, &t1
)) != 0) {
1019 (void)gettimeofday(&t2
, &tz
);
1020 i
= packet_ok(packet
, cc
, from
, seq
);
1021 /* Skip short packet */
1025 from
->sin_addr
.s_addr
!= lastaddr
) {
1026 if (gotlastaddr
) printf("\n ");
1027 print(packet
, cc
, from
);
1028 lastaddr
= from
->sin_addr
.s_addr
;
1031 T
= deltaT(&t1
, &t2
);
1032 #ifdef SANE_PRECISION
1035 else if (T
>= 100.0)
1042 Printf(" %.*f ms", precis
, T
);
1046 -(outip
->ip_hl
<< 3),
1050 pkt_compare((void *)outip
, packlen
,
1051 (void *)hip
, hiplen
);
1055 ip
= (struct ip
*)packet
;
1056 if (ip
->ip_ttl
<= 1)
1062 /* time exceeded in transit */
1068 case ICMP_UNREACH_PORT
:
1070 ip
= (struct ip
*)packet
;
1071 if (ip
->ip_ttl
<= 1)
1077 case ICMP_UNREACH_NET
:
1082 case ICMP_UNREACH_HOST
:
1087 case ICMP_UNREACH_PROTOCOL
:
1092 case ICMP_UNREACH_NEEDFRAG
:
1094 Printf(" !F-%d", pmtu
);
1097 case ICMP_UNREACH_SRCFAIL
:
1102 case ICMP_UNREACH_NET_UNKNOWN
:
1107 case ICMP_UNREACH_HOST_UNKNOWN
:
1112 case ICMP_UNREACH_ISOLATED
:
1117 case ICMP_UNREACH_NET_PROHIB
:
1122 case ICMP_UNREACH_HOST_PROHIB
:
1127 case ICMP_UNREACH_TOSNET
:
1132 case ICMP_UNREACH_TOSHOST
:
1137 case ICMP_UNREACH_FILTER_PROHIB
:
1142 case ICMP_UNREACH_HOST_PRECEDENCE
:
1147 case ICMP_UNREACH_PRECEDENCE_CUTOFF
:
1154 Printf(" !<%d>", code
);
1163 (void)fflush(stdout
);
1166 Printf(" (%d%% loss)", (loss
* 100) / nprobes
);
1170 (unreachable
> 0 && unreachable
>= nprobes
- 1))
1179 wait_for_reply(register int sock
, register struct sockaddr_in
*fromp
,
1180 register const struct timeval
*tp
)
1184 struct timeval now
, wait
;
1186 register int cc
= 0;
1188 socklen_t fromlen
= sizeof(*fromp
);
1190 nfds
= howmany(sock
+ 1, NFDBITS
);
1191 if ((fdsp
= malloc(nfds
* sizeof(fd_mask
))) == NULL
)
1193 memset(fdsp
, 0, nfds
* sizeof(fd_mask
));
1196 wait
.tv_sec
= tp
->tv_sec
+ waittime
;
1197 wait
.tv_usec
= tp
->tv_usec
;
1198 (void)gettimeofday(&now
, &tz
);
1200 if (wait
.tv_sec
< 0) {
1205 error
= select(sock
+ 1, fdsp
, NULL
, NULL
, &wait
);
1206 if (error
== -1 && errno
== EINVAL
) {
1207 Fprintf(stderr
, "%s: botched select() args\n", prog
);
1211 cc
= recvfrom(sock
, (char *)packet
, sizeof(packet
), 0,
1212 (struct sockaddr
*)fromp
, &fromlen
);
1219 send_probe(int seq
, int ttl
)
1223 outip
->ip_ttl
= ttl
;
1224 outip
->ip_id
= htons(ident
+ seq
);
1226 /* XXX undocumented debugging hack */
1228 register const u_short
*sp
;
1229 register int nshorts
, i
;
1231 sp
= (u_short
*)outip
;
1232 nshorts
= (u_int
)packlen
/ sizeof(u_short
);
1234 Printf("[ %d bytes", packlen
);
1235 while (--nshorts
>= 0) {
1238 Printf(" %04x", ntohs(*sp
++));
1243 Printf(" %02x", *(u_char
*)sp
);
1248 #if !defined(IP_HDRINCL) && defined(IP_TTL)
1249 if (setsockopt(sndsock
, IPPROTO_IP
, IP_TTL
,
1250 (char *)&ttl
, sizeof(ttl
)) < 0) {
1251 Fprintf(stderr
, "%s: setsockopt ttl %d: %s\n",
1252 prog
, ttl
, strerror(errno
));
1257 cc
= sendto(sndsock
, (char *)outip
,
1258 packlen
, 0, &whereto
, sizeof(whereto
));
1259 if (cc
< 0 || cc
!= packlen
) {
1261 Fprintf(stderr
, "%s: sendto: %s\n",
1262 prog
, strerror(errno
));
1263 Printf("%s: wrote %s %d chars, ret=%d\n",
1264 prog
, hostname
, packlen
, cc
);
1265 (void)fflush(stdout
);
1269 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
1271 setpolicy(so
, policy
)
1277 buf
= ipsec_set_policy(policy
, strlen(policy
));
1279 warnx("%s", ipsec_strerror());
1282 (void)setsockopt(so
, IPPROTO_IP
, IP_IPSEC_POLICY
,
1283 buf
, ipsec_get_policylen(buf
));
1292 deltaT(struct timeval
*t1p
, struct timeval
*t2p
)
1296 dt
= (double)(t2p
->tv_sec
- t1p
->tv_sec
) * 1000.0 +
1297 (double)(t2p
->tv_usec
- t1p
->tv_usec
) / 1000.0;
1302 * Convert an ICMP "type" field to a printable string.
1305 pr_type(register u_char t
)
1307 static char *ttab
[] = {
1308 "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable",
1309 "Source Quench", "Redirect", "ICMP 6", "ICMP 7",
1310 "Echo", "ICMP 9", "ICMP 10", "Time Exceeded",
1311 "Param Problem", "Timestamp", "Timestamp Reply", "Info Request",
1316 return("OUT-OF-RANGE");
1322 packet_ok(register u_char
*buf
, int cc
, register struct sockaddr_in
*from
,
1325 register struct icmp
*icp
;
1326 register u_char type
, code
;
1329 register struct ip
*ip
;
1331 ip
= (struct ip
*) buf
;
1332 hlen
= ip
->ip_hl
<< 2;
1333 if (cc
< hlen
+ ICMP_MINLEN
) {
1335 Printf("packet too short (%d bytes) from %s\n", cc
,
1336 inet_ntoa(from
->sin_addr
));
1340 icp
= (struct icmp
*)(buf
+ hlen
);
1342 icp
= (struct icmp
*)buf
;
1344 type
= icp
->icmp_type
;
1345 code
= icp
->icmp_code
;
1346 /* Path MTU Discovery (RFC1191) */
1347 if (code
!= ICMP_UNREACH_NEEDFRAG
)
1350 #ifdef HAVE_ICMP_NEXTMTU
1351 pmtu
= ntohs(icp
->icmp_nextmtu
);
1353 pmtu
= ntohs(((struct my_pmtu
*)&icp
->icmp_void
)->ipm_nextmtu
);
1356 if (type
== ICMP_ECHOREPLY
1357 && proto
->num
== IPPROTO_ICMP
1358 && (*proto
->check
)((u_char
*)icp
, (u_char
)seq
))
1360 if ((type
== ICMP_TIMXCEED
&& code
== ICMP_TIMXCEED_INTRANS
) ||
1361 type
== ICMP_UNREACH
) {
1364 hip
= &icp
->icmp_ip
;
1365 hiplen
= ((u_char
*)icp
+ cc
) - (u_char
*)hip
;
1366 hlen
= hip
->ip_hl
<< 2;
1367 inner
= (u_char
*)((u_char
*)hip
+ hlen
);
1369 && hip
->ip_p
== proto
->num
1370 && (*proto
->check
)(inner
, (u_char
)seq
))
1371 return (type
== ICMP_TIMXCEED
? -1 : code
+ 1);
1376 u_int32_t
*lp
= (u_int32_t
*)&icp
->icmp_ip
;
1378 Printf("\n%d bytes from %s to ", cc
, inet_ntoa(from
->sin_addr
));
1379 Printf("%s: icmp type %d (%s) code %d\n",
1380 inet_ntoa(ip
->ip_dst
), type
, pr_type(type
), icp
->icmp_code
);
1381 for (i
= 4; i
< cc
; i
+= sizeof(*lp
))
1382 Printf("%2d: x%8.8x\n", i
, *lp
++);
1389 icmp_prep(struct outdata
*outdata
)
1391 struct icmp
*const icmpheader
= (struct icmp
*) outp
;
1393 icmpheader
->icmp_type
= ICMP_ECHO
;
1394 icmpheader
->icmp_id
= htons(ident
);
1395 icmpheader
->icmp_seq
= htons(outdata
->seq
);
1396 icmpheader
->icmp_cksum
= 0;
1397 icmpheader
->icmp_cksum
= in_cksum((u_short
*)icmpheader
, protlen
);
1398 if (icmpheader
->icmp_cksum
== 0)
1399 icmpheader
->icmp_cksum
= 0xffff;
1403 icmp_check(const u_char
*data
, int seq
)
1405 struct icmp
*const icmpheader
= (struct icmp
*) data
;
1407 return (icmpheader
->icmp_id
== htons(ident
)
1408 && icmpheader
->icmp_seq
== htons(seq
));
1412 udp_prep(struct outdata
*outdata
)
1414 struct udphdr
*const outudp
= (struct udphdr
*) outp
;
1416 outudp
->uh_sport
= htons(ident
+ (fixedPort
? outdata
->seq
: 0));
1417 outudp
->uh_dport
= htons(port
+ (fixedPort
? 0 : outdata
->seq
));
1418 outudp
->uh_ulen
= htons((u_short
)protlen
);
1421 u_short sum
= p_cksum(outip
, (u_short
*)outudp
, protlen
);
1422 outudp
->uh_sum
= (sum
) ? sum
: 0xffff;
1429 udp_check(const u_char
*data
, int seq
)
1431 struct udphdr
*const udp
= (struct udphdr
*) data
;
1433 return (ntohs(udp
->uh_sport
) == ident
+ (fixedPort
? seq
: 0) &&
1434 ntohs(udp
->uh_dport
) == port
+ (fixedPort
? 0 : seq
));
1438 tcp_prep(struct outdata
*outdata
)
1440 struct tcphdr
*const tcp
= (struct tcphdr
*) outp
;
1442 tcp
->th_sport
= htons(ident
);
1443 tcp
->th_dport
= htons(port
+ (fixedPort
? 0 : outdata
->seq
));
1444 tcp
->th_seq
= (tcp
->th_sport
<< 16) | (tcp
->th_dport
+
1445 (fixedPort
? outdata
->seq
: 0));
1448 tcp
->th_flags
= TH_SYN
;
1452 u_short sum
= p_cksum(outip
, (u_short
*)tcp
, protlen
);
1453 tcp
->th_sum
= (sum
) ? sum
: 0xffff;
1458 tcp_check(const u_char
*data
, int seq
)
1460 struct tcphdr
*const tcp
= (struct tcphdr
*) data
;
1462 return (ntohs(tcp
->th_sport
) == ident
1463 && ntohs(tcp
->th_dport
) == port
+ (fixedPort
? 0 : seq
))
1464 && tcp
->th_seq
== ((ident
<< 16) | (port
+ seq
));
1468 gre_prep(struct outdata
*outdata
)
1470 struct grehdr
*const gre
= (struct grehdr
*) outp
;
1472 gre
->flags
= htons(0x2001);
1473 gre
->proto
= htons(port
);
1475 gre
->callId
= htons(ident
+ outdata
->seq
);
1479 gre_check(const u_char
*data
, int seq
)
1481 struct grehdr
*const gre
= (struct grehdr
*) data
;
1483 return(ntohs(gre
->proto
) == port
1484 && ntohs(gre
->callId
) == ident
+ seq
);
1488 gen_prep(struct outdata
*outdata
)
1490 u_int16_t
*const ptr
= (u_int16_t
*) outp
;
1492 ptr
[0] = htons(ident
);
1493 ptr
[1] = htons(port
+ outdata
->seq
);
1497 gen_check(const u_char
*data
, int seq
)
1499 u_int16_t
*const ptr
= (u_int16_t
*) data
;
1501 return(ntohs(ptr
[0]) == ident
1502 && ntohs(ptr
[1]) == port
+ seq
);
1506 print(register u_char
*buf
, register int cc
, register struct sockaddr_in
*from
)
1508 register struct ip
*ip
;
1511 ip
= (struct ip
*) buf
;
1512 hlen
= ip
->ip_hl
<< 2;
1516 Printf(" [AS%d]", as_lookup(asn
, &from
->sin_addr
));
1519 Printf(" %s", inet_ntoa(from
->sin_addr
));
1521 Printf(" %s (%s)", inetname(from
->sin_addr
),
1522 inet_ntoa(from
->sin_addr
));
1525 Printf(" %d bytes to %s", cc
, inet_ntoa (ip
->ip_dst
));
1529 * Checksum routine for UDP and TCP headers.
1532 p_cksum(struct ip
*ip
, u_short
*data
, int len
)
1534 static struct ipovly ipo
;
1538 ipo
.ih_pr
= ip
->ip_p
;
1539 ipo
.ih_len
= htons(len
);
1540 ipo
.ih_src
= ip
->ip_src
;
1541 ipo
.ih_dst
= ip
->ip_dst
;
1543 sumh
= in_cksum((u_short
*)&ipo
, sizeof(ipo
)); /* pseudo ip hdr cksum */
1544 sumd
= in_cksum((u_short
*)data
, len
); /* payload data cksum */
1545 sumt
= (sumh
<< 16) | (sumd
);
1547 return ~in_cksum((u_short
*)&sumt
, sizeof(sumt
));
1551 * Checksum routine for Internet Protocol family headers (C Version)
1554 in_cksum(register u_short
*addr
, register int len
)
1556 register int nleft
= len
;
1557 register u_short
*w
= addr
;
1558 register u_short answer
;
1559 register int sum
= 0;
1562 * Our algorithm is simple, using a 32 bit accumulator (sum),
1563 * we add sequential 16 bit words to it, and at the end, fold
1564 * back all the carry bits from the top 16 bits into the lower
1572 /* mop up an odd byte, if necessary */
1574 sum
+= *(u_char
*)w
;
1577 * add back carry outs from top 16 bits to low 16 bits
1579 sum
= (sum
>> 16) + (sum
& 0xffff); /* add hi 16 to low 16 */
1580 sum
+= (sum
>> 16); /* add carry */
1581 answer
= ~sum
; /* truncate to 16 bits */
1586 * Subtract 2 timeval structs: out = out - in.
1587 * Out is assumed to be within about LONG_MAX seconds of in.
1590 tvsub(register struct timeval
*out
, register struct timeval
*in
)
1593 if ((out
->tv_usec
-= in
->tv_usec
) < 0) {
1595 out
->tv_usec
+= 1000000;
1597 out
->tv_sec
-= in
->tv_sec
;
1601 * Construct an Internet address representation.
1602 * If the nflag has been supplied, give
1603 * numeric value, otherwise try for symbolic name.
1606 inetname(struct in_addr in
)
1609 register struct hostent
*hp
;
1610 static int first
= 1;
1611 static char domain
[MAXHOSTNAMELEN
+ 1], line
[MAXHOSTNAMELEN
+ 1];
1613 if (first
&& !nflag
) {
1615 if (gethostname(domain
, sizeof(domain
) - 1) < 0)
1618 cp
= strchr(domain
, '.');
1620 hp
= gethostbyname(domain
);
1622 cp
= strchr(hp
->h_name
, '.');
1628 (void)strncpy(domain
, cp
, sizeof(domain
) - 1);
1629 domain
[sizeof(domain
) - 1] = '\0';
1633 if (!nflag
&& in
.s_addr
!= INADDR_ANY
) {
1634 hp
= gethostbyaddr((char *)&in
, sizeof(in
), AF_INET
);
1636 if ((cp
= strchr(hp
->h_name
, '.')) != NULL
&&
1637 strcmp(cp
+ 1, domain
) == 0)
1639 (void)strncpy(line
, hp
->h_name
, sizeof(line
) - 1);
1640 line
[sizeof(line
) - 1] = '\0';
1644 return (inet_ntoa(in
));
1648 gethostinfo(register char *hostname
)
1651 register struct hostent
*hp
;
1652 register struct hostinfo
*hi
;
1654 register u_int32_t addr
, *ap
;
1656 if (strlen(hostname
) > 64) {
1657 Fprintf(stderr
, "%s: hostname \"%.32s...\" is too long\n",
1661 hi
= calloc(1, sizeof(*hi
));
1663 Fprintf(stderr
, "%s: calloc %s\n", prog
, strerror(errno
));
1666 addr
= inet_addr(hostname
);
1667 if ((int32_t)addr
!= -1) {
1668 hi
->name
= strdup(hostname
);
1670 hi
->addrs
= calloc(1, sizeof(hi
->addrs
[0]));
1671 if (hi
->addrs
== NULL
) {
1672 Fprintf(stderr
, "%s: calloc %s\n",
1673 prog
, strerror(errno
));
1676 hi
->addrs
[0] = addr
;
1680 hp
= gethostbyname(hostname
);
1682 Fprintf(stderr
, "%s: unknown host %s\n", prog
, hostname
);
1685 if (hp
->h_addrtype
!= AF_INET
|| hp
->h_length
!= 4) {
1686 Fprintf(stderr
, "%s: bad host %s\n", prog
, hostname
);
1689 hi
->name
= strdup(hp
->h_name
);
1690 for (n
= 0, p
= hp
->h_addr_list
; *p
!= NULL
; ++n
, ++p
)
1693 hi
->addrs
= calloc(n
, sizeof(hi
->addrs
[0]));
1694 if (hi
->addrs
== NULL
) {
1695 Fprintf(stderr
, "%s: calloc %s\n", prog
, strerror(errno
));
1698 for (ap
= hi
->addrs
, p
= hp
->h_addr_list
; *p
!= NULL
; ++ap
, ++p
)
1699 memcpy(ap
, *p
, sizeof(*ap
));
1704 freehostinfo(register struct hostinfo
*hi
)
1706 if (hi
->name
!= NULL
) {
1710 free((char *)hi
->addrs
);
1715 getaddr(register u_int32_t
*ap
, register char *hostname
)
1717 register struct hostinfo
*hi
;
1719 hi
= gethostinfo(hostname
);
1725 setsin(register struct sockaddr_in
*sin
, register u_int32_t addr
)
1728 memset(sin
, 0, sizeof(*sin
));
1729 #ifdef HAVE_SOCKADDR_SA_LEN
1730 sin
->sin_len
= sizeof(*sin
);
1732 sin
->sin_family
= AF_INET
;
1733 sin
->sin_addr
.s_addr
= addr
;
1736 /* String to value with optional min and max. Handles decimal and hex. */
1738 str2val(register const char *str
, register const char *what
,
1739 register int mi
, register int ma
)
1741 register const char *cp
;
1745 if (str
[0] == '0' && (str
[1] == 'x' || str
[1] == 'X')) {
1747 val
= (int)strtol(cp
, &ep
, 16);
1749 val
= (int)strtol(str
, &ep
, 10);
1751 Fprintf(stderr
, "%s: \"%s\" bad value for %s \n",
1755 if (val
< mi
&& mi
>= 0) {
1757 Fprintf(stderr
, "%s: %s must be >= %d\n",
1760 Fprintf(stderr
, "%s: %s must be > %d\n",
1761 prog
, what
, mi
- 1);
1764 if (val
> ma
&& ma
>= 0) {
1765 Fprintf(stderr
, "%s: %s must be <= %d\n", prog
, what
, ma
);
1772 setproto(char *pname
)
1774 struct outproto
*proto
;
1777 for (i
= 0; protos
[i
].name
!= NULL
; i
++) {
1778 if (strcasecmp(protos
[i
].name
, pname
) == 0) {
1783 if (proto
->name
== NULL
) { /* generic handler */
1784 struct protoent
*pe
;
1787 /* Determine the IP protocol number */
1788 if ((pe
= getprotobyname(pname
)) != NULL
)
1791 pnum
= str2val(optarg
, "proto number", 1, 255);
1798 pkt_compare(const u_char
*a
, int la
, const u_char
*b
, int lb
) {
1802 for (i
= 0; i
< la
; i
++)
1803 Printf("%02x", (unsigned int)a
[i
]);
1805 l
= (la
<= lb
) ? la
: lb
;
1806 for (i
= 0; i
< l
; i
++)
1810 Printf("%02x", (unsigned int)b
[i
]);
1812 Printf("%02x", (unsigned int)b
[i
]);
1820 extern char version
[];
1822 Fprintf(stderr
, "Version %s\n", version
);
1824 "Usage: %s [-adDeFInrSvx] [-A as_server] [-f first_ttl] [-g gateway] [-i iface]\n"
1825 "\t[-M first_ttl] [-m max_ttl] [-p port] [-P proto] [-q nqueries] [-s src_addr]\n"
1826 "\t[-t tos] [-w waittime] [-z pausemsecs] host [packetlen]\n", prog
);