2 * Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000
3 * The Regents of the University of California. All rights reserved.
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
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.
23 static const char copyright
[] =
24 "@(#) Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000\n\
25 The Regents of the University of California. All rights reserved.\n";
27 static const char rcsid
[] =
28 "@(#)$Id: traceroute.c,v 1.4 2006/02/07 06:22:57 lindak Exp $ (LBL)";
30 static const char rcsid
[] =
31 "$FreeBSD: src/contrib/traceroute/traceroute.c,v 1.35 2008/02/20 23:29:52 rpaulo Exp $";
35 * traceroute host - trace the route ip packets follow going to "host".
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
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).
57 * A sample use might be:
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
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.
77 * A more interesting example is:
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
93 * 13 128.121.54.72 (128.121.54.72) 259 ms 499 ms 279 ms
98 * 18 ALLSPICE.LCS.MIT.EDU (18.26.0.115) 339 ms 279 ms 279 ms
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.
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:
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
127 * 13 rip.Berkeley.EDU (128.32.131.22) 59 ms ! 39 ms ! 39 ms !
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
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.
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.)
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.
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.
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.
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.
193 * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
194 * enhancements to the original distribution.
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...
201 * -- Van Jacobson (van@ee.lbl.gov)
202 * Tue Dec 20 03:50:13 PST 1988
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>
211 #include <sys/socket.h>
212 #ifdef HAVE_SYS_SYSCTL_H
213 #include <sys/sysctl.h>
215 #include <sys/time.h>
217 #include <netinet/in_systm.h>
218 #include <netinet/in.h>
219 #include <netinet/ip.h>
220 #include <netinet/ip_var.h>
221 #include <netinet/ip_icmp.h>
222 #include <netinet/udp.h>
223 #include <netinet/udp_var.h>
224 #include <netinet/tcp.h>
225 #include <netinet/tcpip.h>
227 #include <arpa/inet.h>
230 #include <net/route.h>
231 #include <netinet6/ipsec.h> /* XXX */
249 #ifdef HAVE_OS_PROTO_H
250 #include "os-proto.h"
254 #ifndef ICMP_UNREACH_FILTER_PROHIB
255 #define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohibited filter */
257 #ifndef ICMP_UNREACH_HOST_PRECEDENCE
258 #define ICMP_UNREACH_HOST_PRECEDENCE 14 /* host precedence violation */
260 #ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF
261 #define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* precedence cutoff */
264 #include "findsaddr.h"
265 #include "ifaddrlist.h"
267 #include "traceroute.h"
269 /* Maximum number of gateways (include room for one noop) */
270 #define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t)))
272 #ifndef MAXHOSTNAMELEN
273 #define MAXHOSTNAMELEN 64
276 #define Fprintf (void)fprintf
277 #define Printf (void)printf
279 /* What a GRE packet header looks like */
283 u_int16_t length
; /* PPTP version of these fields */
287 #define IPPROTO_GRE 47
290 /* For GRE, we prepare what looks like a PPTP packet */
291 #define GRE_PPTP_PROTO 0x880b
293 /* Host name and address list */
300 /* Data section of the probe packet */
302 u_char seq
; /* sequence number of this packet */
303 u_char ttl
; /* ttl packet left with */
304 struct timeval tv
; /* time packet left */
307 #ifndef HAVE_ICMP_NEXTMTU
308 /* Path MTU Discovery (RFC1191) */
315 u_char packet
[512]; /* last inbound (icmp) packet */
317 struct ip
*outip
; /* last output ip packet */
318 u_char
*outp
; /* last output inner protocol packet */
320 struct ip
*hip
= NULL
; /* Quoted IP header */
323 /* loose source route gateway list (including room for final destination) */
324 u_int32_t gwlist
[NGATEWAYS
+ 1];
326 int s
; /* receive (icmp) socket file descriptor */
327 int sndsock
; /* send (udp) socket file descriptor */
329 struct sockaddr whereto
; /* Who to try to reach */
330 struct sockaddr wherefrom
; /* Who we are */
331 int packlen
; /* total length of packet */
332 int protlen
; /* length of protocol part of packet */
333 int minpacket
; /* min ip packet size */
334 int maxpacket
= 32 * 1024; /* max ip packet size */
335 int pmtu
; /* Path MTU Discovery (RFC1191) */
342 static const char devnull
[] = "/dev/null";
348 u_short port
; /* protocol specific base "port" */
350 int options
; /* socket options */
352 int waittime
= 5; /* time to wait for response (in seconds) */
353 int nflag
; /* print addresses numerically */
354 int as_path
; /* print as numbers for each hop */
355 char *as_server
= NULL
;
357 #ifdef CANT_HACK_IPCKSUM
358 int doipcksum
= 0; /* don't calculate ip checksums by default */
360 int doipcksum
= 1; /* calculate ip checksums by default */
362 int optlen
; /* length of ip options */
363 int fixedPort
= 0; /* Use fixed destination port for TCP and UDP */
364 int printdiff
= 0; /* Print the difference between sent and quoted */
371 double deltaT(struct timeval
*, struct timeval
*);
372 void freehostinfo(struct hostinfo
*);
373 void getaddr(u_int32_t
*, char *);
374 struct hostinfo
*gethostinfo(char *);
375 u_short
in_cksum(u_short
*, int);
376 char *inetname(struct in_addr
);
377 int main(int, char **);
378 u_short
p_cksum(struct ip
*, u_short
*, int);
379 int packet_ok(u_char
*, int, struct sockaddr_in
*, int);
380 char *pr_type(u_char
);
381 void print(u_char
*, int, struct sockaddr_in
*);
383 int setpolicy
__P((int so
, char *policy
));
385 void send_probe(int, int);
386 struct outproto
*setproto(char *);
387 int str2val(const char *, const char *, int, int);
388 void tvsub(struct timeval
*, struct timeval
*);
390 int wait_for_reply(int, struct sockaddr_in
*, const struct timeval
*);
391 void pkt_compare(const u_char
*, int, const u_char
*, int);
396 void udp_prep(struct outdata
*);
397 int udp_check(const u_char
*, int);
398 void tcp_prep(struct outdata
*);
399 int tcp_check(const u_char
*, int);
400 void gre_prep(struct outdata
*);
401 int gre_check(const u_char
*, int);
402 void gen_prep(struct outdata
*);
403 int gen_check(const u_char
*, int);
404 void icmp_prep(struct outdata
*);
405 int icmp_check(const u_char
*, int);
407 /* Descriptor structure for each outgoing protocol we support */
409 char *name
; /* name of protocol */
410 const char *key
; /* An ascii key for the bytes of the header */
411 u_char num
; /* IP protocol number */
412 u_short hdrlen
; /* max size of protocol header */
413 u_short port
; /* default base protocol-specific "port" */
414 void (*prepare
)(struct outdata
*);
415 /* finish preparing an outgoing packet */
416 int (*check
)(const u_char
*, int);
417 /* check an incoming packet */
420 /* List of supported protocols. The first one is the default. The last
421 one is the handler for generic protocols not explicitly listed. */
422 struct outproto protos
[] = {
427 sizeof(struct udphdr
),
434 "spt dpt seq ack xxflwin sum urp",
436 sizeof(struct tcphdr
),
445 sizeof(struct grehdr
),
469 struct outproto
*proto
= &protos
[0];
471 const char *ip_hdr_key
= "vhtslen id off tlprsum srcip dstip opts";
474 main(int argc
, char **argv
)
476 register int op
, code
, n
;
478 register const char *err
;
479 register u_int32_t
*ap
;
480 register struct sockaddr_in
*from
= (struct sockaddr_in
*)&wherefrom
;
481 register struct sockaddr_in
*to
= (struct sockaddr_in
*)&whereto
;
482 register struct hostinfo
*hi
;
484 register struct protoent
*pe
;
485 register int ttl
, probe
, i
;
486 register int seq
= 0;
487 int tos
= 0, settos
= 0;
488 register int lsrr
= 0;
489 register u_short off
= 0;
490 struct ifaddrlist
*al
;
492 int requestPort
= -1;
496 /* Insure the socket fds won't be 0, 1 or 2 */
497 if (open(devnull
, O_RDONLY
) < 0 ||
498 open(devnull
, O_RDONLY
) < 0 ||
499 open(devnull
, O_RDONLY
) < 0) {
500 Fprintf(stderr
, "%s: open \"%s\": %s\n",
501 prog
, devnull
, strerror(errno
));
505 * Do the setuid-required stuff first, then lose priveleges ASAP.
506 * Do error checking for these two calls where they appeared in
510 pe
= getprotobyname(cp
);
512 if ((s
= socket(AF_INET
, SOCK_RAW
, pe
->p_proto
)) < 0)
514 else if ((sndsock
= socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
)) < 0)
522 int mib
[4] = { CTL_NET
, PF_INET
, IPPROTO_IP
, IPCTL_DEFTTL
};
523 size_t sz
= sizeof(max_ttl
);
525 if (sysctl(mib
, 4, &max_ttl
, &sz
, NULL
, 0) == -1) {
526 perror("sysctl(net.inet.ip.ttl)");
536 else if ((cp
= strrchr(argv
[0], '/')) != NULL
)
542 while ((op
= getopt(argc
, argv
, "aA:edDFInrSvxf:g:i:M:m:P:p:q:s:t:w:z:")) != EOF
)
566 case 'M': /* FreeBSD compat. */
567 first_ttl
= str2val(optarg
, "first ttl", 1, 255);
575 if (lsrr
>= NGATEWAYS
) {
577 "%s: No more than %d gateways\n",
581 getaddr(gwlist
+ lsrr
, optarg
);
590 proto
= setproto("icmp");
594 max_ttl
= str2val(optarg
, "max ttl", 1, 255);
602 proto
= setproto(optarg
);
606 requestPort
= (u_short
)str2val(optarg
, "port",
611 nprobes
= str2val(optarg
, "nprobes", 1, -1);
615 options
|= SO_DONTROUTE
;
620 * set the ip source address of the outbound
621 * probe (e.g., on a multi-homed host).
631 tos
= str2val(optarg
, "tos", 0, 255);
640 doipcksum
= (doipcksum
== 0);
644 waittime
= str2val(optarg
, "wait time",
649 pausemsecs
= str2val(optarg
, "pause msecs",
657 /* Set requested port, if any, else default for this protocol */
658 port
= (requestPort
!= -1) ? requestPort
: proto
->port
;
661 nprobes
= printdiff
? 1 : 3;
663 if (first_ttl
> max_ttl
) {
665 "%s: first ttl (%d) may not be greater than max ttl (%d)\n",
666 prog
, first_ttl
, max_ttl
);
671 Fprintf(stderr
, "%s: Warning: ip checksums disabled\n", prog
);
674 optlen
= (lsrr
+ 1) * sizeof(gwlist
[0]);
675 minpacket
= sizeof(*outip
) + proto
->hdrlen
+ sizeof(struct outdata
) + optlen
;
676 packlen
= minpacket
; /* minimum sized packet */
678 /* Process destination and optional packet size */
679 switch (argc
- optind
) {
682 packlen
= str2val(argv
[optind
+ 1],
683 "packet length", minpacket
, maxpacket
);
687 hostname
= argv
[optind
];
688 hi
= gethostinfo(hostname
);
689 setsin(to
, hi
->addrs
[0]);
692 "%s: Warning: %s has multiple addresses; using %s\n",
693 prog
, hostname
, inet_ntoa(to
->sin_addr
));
703 #ifdef HAVE_SETLINEBUF
706 setvbuf(stdout
, NULL
, _IOLBF
, 0);
709 protlen
= packlen
- sizeof(*outip
) - optlen
;
711 outip
= (struct ip
*)malloc((unsigned)packlen
);
713 Fprintf(stderr
, "%s: malloc: %s\n", prog
, strerror(errno
));
716 memset((char *)outip
, 0, packlen
);
718 outip
->ip_v
= IPVERSION
;
721 #ifdef BYTESWAP_IP_HDR
722 outip
->ip_len
= htons(packlen
);
723 outip
->ip_off
= htons(off
);
725 outip
->ip_len
= packlen
;
728 outip
->ip_p
= proto
->num
;
729 outp
= (u_char
*)(outip
+ 1);
730 #ifdef HAVE_RAW_OPTIONS
732 register u_char
*optlist
;
738 gwlist
[lsrr
] = to
->sin_addr
.s_addr
;
740 outip
->ip_dst
.s_addr
= gwlist
[0];
742 /* force 4 byte alignment */
743 optlist
[0] = IPOPT_NOP
;
744 /* loose source route option */
745 optlist
[1] = IPOPT_LSRR
;
746 i
= lsrr
* sizeof(gwlist
[0]);
748 /* Pointer to LSRR addresses */
749 optlist
[3] = IPOPT_MINOFF
;
750 memcpy(optlist
+ 4, gwlist
+ 1, i
);
753 outip
->ip_dst
= to
->sin_addr
;
755 outip
->ip_hl
= (outp
- (u_char
*)outip
) >> 2;
756 ident
= (getpid() & 0xffff) | 0x8000;
759 Fprintf(stderr
, "%s: unknown protocol %s\n", prog
, cp
);
764 Fprintf(stderr
, "%s: icmp socket: %s\n", prog
, strerror(errno
));
767 if (options
& SO_DEBUG
)
768 (void)setsockopt(s
, SOL_SOCKET
, SO_DEBUG
, (char *)&on
,
770 if (options
& SO_DONTROUTE
)
771 (void)setsockopt(s
, SOL_SOCKET
, SO_DONTROUTE
, (char *)&on
,
774 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
775 if (setpolicy(s
, "in bypass") < 0)
776 errx(1, "%s", ipsec_strerror());
778 if (setpolicy(s
, "out bypass") < 0)
779 errx(1, "%s", ipsec_strerror());
780 #endif /* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */
784 Fprintf(stderr
, "%s: raw socket: %s\n", prog
, strerror(errno
));
788 #if defined(IP_OPTIONS) && !defined(HAVE_RAW_OPTIONS)
790 u_char optlist
[MAX_IPOPTLEN
];
793 if ((pe
= getprotobyname(cp
)) == NULL
) {
794 Fprintf(stderr
, "%s: unknown protocol %s\n", prog
, cp
);
799 gwlist
[lsrr
] = to
->sin_addr
.s_addr
;
802 /* force 4 byte alignment */
803 optlist
[0] = IPOPT_NOP
;
804 /* loose source route option */
805 optlist
[1] = IPOPT_LSRR
;
806 i
= lsrr
* sizeof(gwlist
[0]);
808 /* Pointer to LSRR addresses */
809 optlist
[3] = IPOPT_MINOFF
;
810 memcpy(optlist
+ 4, gwlist
, i
);
812 if ((setsockopt(sndsock
, pe
->p_proto
, IP_OPTIONS
,
813 (char *)optlist
, i
+ sizeof(gwlist
[0]))) < 0) {
814 Fprintf(stderr
, "%s: IP_OPTIONS: %s\n",
815 prog
, strerror(errno
));
822 if (setsockopt(sndsock
, SOL_SOCKET
, SO_SNDBUF
, (char *)&packlen
,
823 sizeof(packlen
)) < 0) {
824 Fprintf(stderr
, "%s: SO_SNDBUF: %s\n", prog
, strerror(errno
));
829 if (setsockopt(sndsock
, IPPROTO_IP
, IP_HDRINCL
, (char *)&on
,
831 Fprintf(stderr
, "%s: IP_HDRINCL: %s\n", prog
, strerror(errno
));
836 if (settos
&& setsockopt(sndsock
, IPPROTO_IP
, IP_TOS
,
837 (char *)&tos
, sizeof(tos
)) < 0) {
838 Fprintf(stderr
, "%s: setsockopt tos %d: %s\n",
839 prog
, tos
, strerror(errno
));
844 if (options
& SO_DEBUG
)
845 (void)setsockopt(sndsock
, SOL_SOCKET
, SO_DEBUG
, (char *)&on
,
847 if (options
& SO_DONTROUTE
)
848 (void)setsockopt(sndsock
, SOL_SOCKET
, SO_DONTROUTE
, (char *)&on
,
851 /* Get the interface address list */
852 n
= ifaddrlist(&al
, errbuf
);
854 Fprintf(stderr
, "%s: ifaddrlist: %s\n", prog
, errbuf
);
859 "%s: Can't find any network interfaces\n", prog
);
863 /* Look for a specific device */
864 if (device
!= NULL
) {
865 for (i
= n
; i
> 0; --i
, ++al
)
866 if (strcmp(device
, al
->device
) == 0)
869 Fprintf(stderr
, "%s: Can't find interface %.32s\n",
875 /* Determine our source address */
876 if (source
== NULL
) {
878 * If a device was specified, use the interface address.
879 * Otherwise, try to determine our source address.
882 setsin(from
, al
->addr
);
883 else if ((err
= findsaddr(to
, from
)) != NULL
) {
884 Fprintf(stderr
, "%s: findsaddr: %s\n",
889 hi
= gethostinfo(source
);
893 * If the device was specified make sure it
894 * corresponds to the source address specified.
895 * Otherwise, use the first address (and warn if
896 * there are more than one).
898 if (device
!= NULL
) {
899 for (i
= hi
->n
, ap
= hi
->addrs
; i
> 0; --i
, ++ap
)
904 "%s: %s is not on interface %.32s\n",
905 prog
, source
, device
);
910 setsin(from
, hi
->addrs
[0]);
913 "%s: Warning: %s has multiple addresses; using %s\n",
914 prog
, source
, inet_ntoa(from
->sin_addr
));
919 outip
->ip_src
= from
->sin_addr
;
921 /* Check the source address (-s), if any, is valid */
922 if (bind(sndsock
, (struct sockaddr
*)from
, sizeof(*from
)) < 0) {
923 Fprintf(stderr
, "%s: bind: %s\n",
924 prog
, strerror(errno
));
929 asn
= as_setup(as_server
);
931 Fprintf(stderr
, "%s: as_setup failed, AS# lookups"
932 " disabled\n", prog
);
933 (void)fflush(stderr
);
938 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
939 if (setpolicy(sndsock
, "in bypass") < 0)
940 errx(1, "%s", ipsec_strerror());
942 if (setpolicy(sndsock
, "out bypass") < 0)
943 errx(1, "%s", ipsec_strerror());
944 #endif /* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */
946 Fprintf(stderr
, "%s to %s (%s)",
947 prog
, hostname
, inet_ntoa(to
->sin_addr
));
949 Fprintf(stderr
, " from %s", source
);
950 Fprintf(stderr
, ", %d hops max, %d byte packets\n", max_ttl
, packlen
);
951 (void)fflush(stderr
);
953 for (ttl
= first_ttl
; ttl
<= max_ttl
; ++ttl
) {
954 u_int32_t lastaddr
= 0;
962 for (probe
= 0, loss
= 0; probe
< nprobes
; ++probe
) {
964 struct timeval t1
, t2
;
966 register struct ip
*ip
;
967 struct outdata outdata
;
969 if (sentfirst
&& pausemsecs
> 0)
970 usleep(pausemsecs
* 1000);
971 /* Prepare outgoing data */
975 /* Avoid alignment problems by copying bytewise: */
976 (void)gettimeofday(&t1
, &tz
);
977 memcpy(&outdata
.tv
, &t1
, sizeof(outdata
.tv
));
979 /* Finalize and send packet */
980 (*proto
->prepare
)(&outdata
);
981 send_probe(seq
, ttl
);
984 /* Wait for a reply */
985 while ((cc
= wait_for_reply(s
, from
, &t1
)) != 0) {
989 (void)gettimeofday(&t2
, &tz
);
990 i
= packet_ok(packet
, cc
, from
, seq
);
991 /* Skip short packet */
995 from
->sin_addr
.s_addr
!= lastaddr
) {
996 if (gotlastaddr
) printf("\n ");
997 print(packet
, cc
, from
);
998 lastaddr
= from
->sin_addr
.s_addr
;
1001 T
= deltaT(&t1
, &t2
);
1002 #ifdef SANE_PRECISION
1005 else if (T
>= 100.0)
1012 Printf(" %.*f ms", precis
, T
);
1016 -(outip
->ip_hl
<< 3),
1020 pkt_compare((void *)outip
, packlen
,
1021 (void *)hip
, hiplen
);
1025 ip
= (struct ip
*)packet
;
1026 if (ip
->ip_ttl
<= 1)
1032 /* time exceeded in transit */
1038 case ICMP_UNREACH_PORT
:
1040 ip
= (struct ip
*)packet
;
1041 if (ip
->ip_ttl
<= 1)
1047 case ICMP_UNREACH_NET
:
1052 case ICMP_UNREACH_HOST
:
1057 case ICMP_UNREACH_PROTOCOL
:
1062 case ICMP_UNREACH_NEEDFRAG
:
1064 Printf(" !F-%d", pmtu
);
1067 case ICMP_UNREACH_SRCFAIL
:
1072 case ICMP_UNREACH_NET_UNKNOWN
:
1077 case ICMP_UNREACH_HOST_UNKNOWN
:
1082 case ICMP_UNREACH_ISOLATED
:
1087 case ICMP_UNREACH_NET_PROHIB
:
1092 case ICMP_UNREACH_HOST_PROHIB
:
1097 case ICMP_UNREACH_TOSNET
:
1102 case ICMP_UNREACH_TOSHOST
:
1107 case ICMP_UNREACH_FILTER_PROHIB
:
1112 case ICMP_UNREACH_HOST_PRECEDENCE
:
1117 case ICMP_UNREACH_PRECEDENCE_CUTOFF
:
1124 Printf(" !<%d>", code
);
1133 (void)fflush(stdout
);
1136 Printf(" (%d%% loss)", (loss
* 100) / nprobes
);
1140 (unreachable
> 0 && unreachable
>= nprobes
- 1))
1149 wait_for_reply(register int sock
, register struct sockaddr_in
*fromp
,
1150 register const struct timeval
*tp
)
1154 struct timeval now
, wait
;
1156 register int cc
= 0;
1158 socklen_t fromlen
= sizeof(*fromp
);
1160 nfds
= howmany(sock
+ 1, NFDBITS
);
1161 if ((fdsp
= malloc(nfds
* sizeof(fd_mask
))) == NULL
)
1163 memset(fdsp
, 0, nfds
* sizeof(fd_mask
));
1166 wait
.tv_sec
= tp
->tv_sec
+ waittime
;
1167 wait
.tv_usec
= tp
->tv_usec
;
1168 (void)gettimeofday(&now
, &tz
);
1170 if (wait
.tv_sec
< 0) {
1175 error
= select(sock
+ 1, fdsp
, NULL
, NULL
, &wait
);
1176 if (error
== -1 && errno
== EINVAL
) {
1177 Fprintf(stderr
, "%s: botched select() args\n", prog
);
1181 cc
= recvfrom(sock
, (char *)packet
, sizeof(packet
), 0,
1182 (struct sockaddr
*)fromp
, &fromlen
);
1189 send_probe(int seq
, int ttl
)
1193 outip
->ip_ttl
= ttl
;
1194 outip
->ip_id
= htons(ident
+ seq
);
1196 /* XXX undocumented debugging hack */
1198 register const u_short
*sp
;
1199 register int nshorts
, i
;
1201 sp
= (u_short
*)outip
;
1202 nshorts
= (u_int
)packlen
/ sizeof(u_short
);
1204 Printf("[ %d bytes", packlen
);
1205 while (--nshorts
>= 0) {
1208 Printf(" %04x", ntohs(*sp
++));
1213 Printf(" %02x", *(u_char
*)sp
);
1218 #if !defined(IP_HDRINCL) && defined(IP_TTL)
1219 if (setsockopt(sndsock
, IPPROTO_IP
, IP_TTL
,
1220 (char *)&ttl
, sizeof(ttl
)) < 0) {
1221 Fprintf(stderr
, "%s: setsockopt ttl %d: %s\n",
1222 prog
, ttl
, strerror(errno
));
1227 cc
= sendto(sndsock
, (char *)outip
,
1228 packlen
, 0, &whereto
, sizeof(whereto
));
1229 if (cc
< 0 || cc
!= packlen
) {
1231 Fprintf(stderr
, "%s: sendto: %s\n",
1232 prog
, strerror(errno
));
1233 Printf("%s: wrote %s %d chars, ret=%d\n",
1234 prog
, hostname
, packlen
, cc
);
1235 (void)fflush(stdout
);
1239 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
1241 setpolicy(so
, policy
)
1247 buf
= ipsec_set_policy(policy
, strlen(policy
));
1249 warnx("%s", ipsec_strerror());
1252 (void)setsockopt(so
, IPPROTO_IP
, IP_IPSEC_POLICY
,
1253 buf
, ipsec_get_policylen(buf
));
1262 deltaT(struct timeval
*t1p
, struct timeval
*t2p
)
1266 dt
= (double)(t2p
->tv_sec
- t1p
->tv_sec
) * 1000.0 +
1267 (double)(t2p
->tv_usec
- t1p
->tv_usec
) / 1000.0;
1272 * Convert an ICMP "type" field to a printable string.
1275 pr_type(register u_char t
)
1277 static char *ttab
[] = {
1278 "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable",
1279 "Source Quench", "Redirect", "ICMP 6", "ICMP 7",
1280 "Echo", "ICMP 9", "ICMP 10", "Time Exceeded",
1281 "Param Problem", "Timestamp", "Timestamp Reply", "Info Request",
1286 return("OUT-OF-RANGE");
1292 packet_ok(register u_char
*buf
, int cc
, register struct sockaddr_in
*from
,
1295 register struct icmp
*icp
;
1296 register u_char type
, code
;
1299 register struct ip
*ip
;
1301 ip
= (struct ip
*) buf
;
1302 hlen
= ip
->ip_hl
<< 2;
1303 if (cc
< hlen
+ ICMP_MINLEN
) {
1305 Printf("packet too short (%d bytes) from %s\n", cc
,
1306 inet_ntoa(from
->sin_addr
));
1310 icp
= (struct icmp
*)(buf
+ hlen
);
1312 icp
= (struct icmp
*)buf
;
1314 type
= icp
->icmp_type
;
1315 code
= icp
->icmp_code
;
1316 /* Path MTU Discovery (RFC1191) */
1317 if (code
!= ICMP_UNREACH_NEEDFRAG
)
1320 #ifdef HAVE_ICMP_NEXTMTU
1321 pmtu
= ntohs(icp
->icmp_nextmtu
);
1323 pmtu
= ntohs(((struct my_pmtu
*)&icp
->icmp_void
)->ipm_nextmtu
);
1326 if (type
== ICMP_ECHOREPLY
1327 && proto
->num
== IPPROTO_ICMP
1328 && (*proto
->check
)((u_char
*)icp
, (u_char
)seq
))
1330 if ((type
== ICMP_TIMXCEED
&& code
== ICMP_TIMXCEED_INTRANS
) ||
1331 type
== ICMP_UNREACH
) {
1334 hip
= &icp
->icmp_ip
;
1335 hiplen
= ((u_char
*)icp
+ cc
) - (u_char
*)hip
;
1336 hlen
= hip
->ip_hl
<< 2;
1337 inner
= (u_char
*)((u_char
*)hip
+ hlen
);
1339 && hip
->ip_p
== proto
->num
1340 && (*proto
->check
)(inner
, (u_char
)seq
))
1341 return (type
== ICMP_TIMXCEED
? -1 : code
+ 1);
1346 u_int32_t
*lp
= (u_int32_t
*)&icp
->icmp_ip
;
1348 Printf("\n%d bytes from %s to ", cc
, inet_ntoa(from
->sin_addr
));
1349 Printf("%s: icmp type %d (%s) code %d\n",
1350 inet_ntoa(ip
->ip_dst
), type
, pr_type(type
), icp
->icmp_code
);
1351 for (i
= 4; i
< cc
; i
+= sizeof(*lp
))
1352 Printf("%2d: x%8.8x\n", i
, *lp
++);
1359 icmp_prep(struct outdata
*outdata
)
1361 struct icmp
*const icmpheader
= (struct icmp
*) outp
;
1363 icmpheader
->icmp_type
= ICMP_ECHO
;
1364 icmpheader
->icmp_id
= htons(ident
);
1365 icmpheader
->icmp_seq
= htons(outdata
->seq
);
1366 icmpheader
->icmp_cksum
= 0;
1367 icmpheader
->icmp_cksum
= in_cksum((u_short
*)icmpheader
, protlen
);
1368 if (icmpheader
->icmp_cksum
== 0)
1369 icmpheader
->icmp_cksum
= 0xffff;
1373 icmp_check(const u_char
*data
, int seq
)
1375 struct icmp
*const icmpheader
= (struct icmp
*) data
;
1377 return (icmpheader
->icmp_id
== htons(ident
)
1378 && icmpheader
->icmp_seq
== htons(seq
));
1382 udp_prep(struct outdata
*outdata
)
1384 struct udphdr
*const outudp
= (struct udphdr
*) outp
;
1386 outudp
->uh_sport
= htons(ident
+ (fixedPort
? outdata
->seq
: 0));
1387 outudp
->uh_dport
= htons(port
+ (fixedPort
? 0 : outdata
->seq
));
1388 outudp
->uh_ulen
= htons((u_short
)protlen
);
1391 u_short sum
= p_cksum(outip
, (u_short
*)outudp
, protlen
);
1392 outudp
->uh_sum
= (sum
) ? sum
: 0xffff;
1399 udp_check(const u_char
*data
, int seq
)
1401 struct udphdr
*const udp
= (struct udphdr
*) data
;
1403 return (ntohs(udp
->uh_sport
) == ident
+ (fixedPort
? seq
: 0) &&
1404 ntohs(udp
->uh_dport
) == port
+ (fixedPort
? 0 : seq
));
1408 tcp_prep(struct outdata
*outdata
)
1410 struct tcphdr
*const tcp
= (struct tcphdr
*) outp
;
1412 tcp
->th_sport
= htons(ident
);
1413 tcp
->th_dport
= htons(port
+ (fixedPort
? 0 : outdata
->seq
));
1414 tcp
->th_seq
= (tcp
->th_sport
<< 16) | (tcp
->th_dport
+
1415 (fixedPort
? outdata
->seq
: 0));
1418 tcp
->th_flags
= TH_SYN
;
1422 u_short sum
= p_cksum(outip
, (u_short
*)tcp
, protlen
);
1423 tcp
->th_sum
= (sum
) ? sum
: 0xffff;
1428 tcp_check(const u_char
*data
, int seq
)
1430 struct tcphdr
*const tcp
= (struct tcphdr
*) data
;
1432 return (ntohs(tcp
->th_sport
) == ident
1433 && ntohs(tcp
->th_dport
) == port
+ (fixedPort
? 0 : seq
))
1434 && tcp
->th_seq
== ((ident
<< 16) | (port
+ seq
));
1438 gre_prep(struct outdata
*outdata
)
1440 struct grehdr
*const gre
= (struct grehdr
*) outp
;
1442 gre
->flags
= htons(0x2001);
1443 gre
->proto
= htons(port
);
1445 gre
->callId
= htons(ident
+ outdata
->seq
);
1449 gre_check(const u_char
*data
, int seq
)
1451 struct grehdr
*const gre
= (struct grehdr
*) data
;
1453 return(ntohs(gre
->proto
) == port
1454 && ntohs(gre
->callId
) == ident
+ seq
);
1458 gen_prep(struct outdata
*outdata
)
1460 u_int16_t
*const ptr
= (u_int16_t
*) outp
;
1462 ptr
[0] = htons(ident
);
1463 ptr
[1] = htons(port
+ outdata
->seq
);
1467 gen_check(const u_char
*data
, int seq
)
1469 u_int16_t
*const ptr
= (u_int16_t
*) data
;
1471 return(ntohs(ptr
[0]) == ident
1472 && ntohs(ptr
[1]) == port
+ seq
);
1476 print(register u_char
*buf
, register int cc
, register struct sockaddr_in
*from
)
1478 register struct ip
*ip
;
1481 ip
= (struct ip
*) buf
;
1482 hlen
= ip
->ip_hl
<< 2;
1486 Printf(" [AS%d]", as_lookup(asn
, &from
->sin_addr
));
1489 Printf(" %s", inet_ntoa(from
->sin_addr
));
1491 Printf(" %s (%s)", inetname(from
->sin_addr
),
1492 inet_ntoa(from
->sin_addr
));
1495 Printf(" %d bytes to %s", cc
, inet_ntoa (ip
->ip_dst
));
1499 * Checksum routine for UDP and TCP headers.
1502 p_cksum(struct ip
*ip
, u_short
*data
, int len
)
1504 static struct ipovly ipo
;
1508 ipo
.ih_pr
= ip
->ip_p
;
1509 ipo
.ih_len
= htons(len
);
1510 ipo
.ih_src
= ip
->ip_src
;
1511 ipo
.ih_dst
= ip
->ip_dst
;
1513 sumh
= in_cksum((u_short
*)&ipo
, sizeof(ipo
)); /* pseudo ip hdr cksum */
1514 sumd
= in_cksum((u_short
*)data
, len
); /* payload data cksum */
1515 sumt
= (sumh
<< 16) | (sumd
);
1517 return ~in_cksum((u_short
*)&sumt
, sizeof(sumt
));
1521 * Checksum routine for Internet Protocol family headers (C Version)
1524 in_cksum(register u_short
*addr
, register int len
)
1526 register int nleft
= len
;
1527 register u_short
*w
= addr
;
1528 register u_short answer
;
1529 register int sum
= 0;
1532 * Our algorithm is simple, using a 32 bit accumulator (sum),
1533 * we add sequential 16 bit words to it, and at the end, fold
1534 * back all the carry bits from the top 16 bits into the lower
1542 /* mop up an odd byte, if necessary */
1544 sum
+= *(u_char
*)w
;
1547 * add back carry outs from top 16 bits to low 16 bits
1549 sum
= (sum
>> 16) + (sum
& 0xffff); /* add hi 16 to low 16 */
1550 sum
+= (sum
>> 16); /* add carry */
1551 answer
= ~sum
; /* truncate to 16 bits */
1556 * Subtract 2 timeval structs: out = out - in.
1557 * Out is assumed to be within about LONG_MAX seconds of in.
1560 tvsub(register struct timeval
*out
, register struct timeval
*in
)
1563 if ((out
->tv_usec
-= in
->tv_usec
) < 0) {
1565 out
->tv_usec
+= 1000000;
1567 out
->tv_sec
-= in
->tv_sec
;
1571 * Construct an Internet address representation.
1572 * If the nflag has been supplied, give
1573 * numeric value, otherwise try for symbolic name.
1576 inetname(struct in_addr in
)
1579 register struct hostent
*hp
;
1580 static int first
= 1;
1581 static char domain
[MAXHOSTNAMELEN
+ 1], line
[MAXHOSTNAMELEN
+ 1];
1583 if (first
&& !nflag
) {
1585 if (gethostname(domain
, sizeof(domain
) - 1) < 0)
1588 cp
= strchr(domain
, '.');
1590 hp
= gethostbyname(domain
);
1592 cp
= strchr(hp
->h_name
, '.');
1598 (void)strncpy(domain
, cp
, sizeof(domain
) - 1);
1599 domain
[sizeof(domain
) - 1] = '\0';
1603 if (!nflag
&& in
.s_addr
!= INADDR_ANY
) {
1604 hp
= gethostbyaddr((char *)&in
, sizeof(in
), AF_INET
);
1606 if ((cp
= strchr(hp
->h_name
, '.')) != NULL
&&
1607 strcmp(cp
+ 1, domain
) == 0)
1609 (void)strncpy(line
, hp
->h_name
, sizeof(line
) - 1);
1610 line
[sizeof(line
) - 1] = '\0';
1614 return (inet_ntoa(in
));
1618 gethostinfo(register char *hostname
)
1621 register struct hostent
*hp
;
1622 register struct hostinfo
*hi
;
1624 register u_int32_t addr
, *ap
;
1626 if (strlen(hostname
) > 64) {
1627 Fprintf(stderr
, "%s: hostname \"%.32s...\" is too long\n",
1631 hi
= calloc(1, sizeof(*hi
));
1633 Fprintf(stderr
, "%s: calloc %s\n", prog
, strerror(errno
));
1636 addr
= inet_addr(hostname
);
1637 if ((int32_t)addr
!= -1) {
1638 hi
->name
= strdup(hostname
);
1640 hi
->addrs
= calloc(1, sizeof(hi
->addrs
[0]));
1641 if (hi
->addrs
== NULL
) {
1642 Fprintf(stderr
, "%s: calloc %s\n",
1643 prog
, strerror(errno
));
1646 hi
->addrs
[0] = addr
;
1650 hp
= gethostbyname(hostname
);
1652 Fprintf(stderr
, "%s: unknown host %s\n", prog
, hostname
);
1655 if (hp
->h_addrtype
!= AF_INET
|| hp
->h_length
!= 4) {
1656 Fprintf(stderr
, "%s: bad host %s\n", prog
, hostname
);
1659 hi
->name
= strdup(hp
->h_name
);
1660 for (n
= 0, p
= hp
->h_addr_list
; *p
!= NULL
; ++n
, ++p
)
1663 hi
->addrs
= calloc(n
, sizeof(hi
->addrs
[0]));
1664 if (hi
->addrs
== NULL
) {
1665 Fprintf(stderr
, "%s: calloc %s\n", prog
, strerror(errno
));
1668 for (ap
= hi
->addrs
, p
= hp
->h_addr_list
; *p
!= NULL
; ++ap
, ++p
)
1669 memcpy(ap
, *p
, sizeof(*ap
));
1674 freehostinfo(register struct hostinfo
*hi
)
1676 if (hi
->name
!= NULL
) {
1680 free((char *)hi
->addrs
);
1685 getaddr(register u_int32_t
*ap
, register char *hostname
)
1687 register struct hostinfo
*hi
;
1689 hi
= gethostinfo(hostname
);
1695 setsin(register struct sockaddr_in
*sin
, register u_int32_t addr
)
1698 memset(sin
, 0, sizeof(*sin
));
1699 #ifdef HAVE_SOCKADDR_SA_LEN
1700 sin
->sin_len
= sizeof(*sin
);
1702 sin
->sin_family
= AF_INET
;
1703 sin
->sin_addr
.s_addr
= addr
;
1706 /* String to value with optional min and max. Handles decimal and hex. */
1708 str2val(register const char *str
, register const char *what
,
1709 register int mi
, register int ma
)
1711 register const char *cp
;
1715 if (str
[0] == '0' && (str
[1] == 'x' || str
[1] == 'X')) {
1717 val
= (int)strtol(cp
, &ep
, 16);
1719 val
= (int)strtol(str
, &ep
, 10);
1721 Fprintf(stderr
, "%s: \"%s\" bad value for %s \n",
1725 if (val
< mi
&& mi
>= 0) {
1727 Fprintf(stderr
, "%s: %s must be >= %d\n",
1730 Fprintf(stderr
, "%s: %s must be > %d\n",
1731 prog
, what
, mi
- 1);
1734 if (val
> ma
&& ma
>= 0) {
1735 Fprintf(stderr
, "%s: %s must be <= %d\n", prog
, what
, ma
);
1742 setproto(char *pname
)
1744 struct outproto
*proto
;
1747 for (i
= 0; protos
[i
].name
!= NULL
; i
++) {
1748 if (strcasecmp(protos
[i
].name
, pname
) == 0) {
1753 if (proto
->name
== NULL
) { /* generic handler */
1754 struct protoent
*pe
;
1757 /* Determine the IP protocol number */
1758 if ((pe
= getprotobyname(pname
)) != NULL
)
1761 pnum
= str2val(optarg
, "proto number", 1, 255);
1768 pkt_compare(const u_char
*a
, int la
, const u_char
*b
, int lb
) {
1772 for (i
= 0; i
< la
; i
++)
1773 Printf("%02x", (unsigned int)a
[i
]);
1775 l
= (la
<= lb
) ? la
: lb
;
1776 for (i
= 0; i
< l
; i
++)
1780 Printf("%02x", (unsigned int)b
[i
]);
1782 Printf("%02x", (unsigned int)b
[i
]);
1790 extern char version
[];
1792 Fprintf(stderr
, "Version %s\n", version
);
1794 "Usage: %s [-adDeFInrSvx] [-A as_server] [-f first_ttl] [-g gateway] [-i iface]\n"
1795 "\t[-M first_ttl] [-m max_ttl] [-p port] [-P proto] [-q nqueries] [-s src_addr]\n"
1796 "\t[-t tos] [-w waittime] [-z pausemsecs] host [packetlen]\n", prog
);