Update from Vernon Schryver, fixing the kluge to flush the route cache.
This commit is contained in:
parent
079405ea2a
commit
01bf6a0596
@ -1,4 +1,4 @@
|
|||||||
.\" $NetBSD: ping.8,v 1.14 1997/04/10 06:16:06 mikel Exp $
|
.\" $NetBSD: ping.8,v 1.15 1997/06/01 19:34:46 christos Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 1985, 1991, 1993
|
.\" Copyright (c) 1985, 1991, 1993
|
||||||
.\" The Regents of the University of California. All rights reserved.
|
.\" The Regents of the University of California. All rights reserved.
|
||||||
@ -46,15 +46,14 @@ packets to network hosts
|
|||||||
.Op Fl dfnoqrvDPQRL
|
.Op Fl dfnoqrvDPQRL
|
||||||
.Op Fl c Ar count
|
.Op Fl c Ar count
|
||||||
.Op Fl g Ar gateway
|
.Op Fl g Ar gateway
|
||||||
.Op Fl i Ar wait
|
.Op Fl i Ar interval
|
||||||
|
.Op Fl I Ar ifaddr
|
||||||
.Op Fl l Ar preload
|
.Op Fl l Ar preload
|
||||||
.Op Fl p Ar pattern
|
.Op Fl p Ar pattern
|
||||||
.Op Fl s Ar packetsize
|
.Op Fl s Ar packetsize
|
||||||
.Op Fl t Ar ttl
|
.Op Fl t Ar tos
|
||||||
|
.Op Fl T Ar ttl
|
||||||
.Op Fl w Ar maxwait
|
.Op Fl w Ar maxwait
|
||||||
.Op Fl I Ar ifaddr
|
|
||||||
.Op Fl S Ar ifaddr
|
|
||||||
.Op Fl T Ar tos
|
|
||||||
.Ar host
|
.Ar host
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Nm Ping
|
.Nm Ping
|
||||||
@ -87,7 +86,8 @@ option on the socket being used.
|
|||||||
.It Fl D
|
.It Fl D
|
||||||
Set the
|
Set the
|
||||||
.Dv Don't Fragment
|
.Dv Don't Fragment
|
||||||
bit.
|
bit in the IP header.
|
||||||
|
This can be used to determine the path MTU.
|
||||||
.It Fl f
|
.It Fl f
|
||||||
Flood ping.
|
Flood ping.
|
||||||
Outputs packets as fast as they come back or one hundred times per second,
|
Outputs packets as fast as they come back or one hundred times per second,
|
||||||
@ -102,9 +102,13 @@ Only the super-user may use this option.
|
|||||||
.Bf -emphasis
|
.Bf -emphasis
|
||||||
This can be very hard on a network and should be used with caution.
|
This can be very hard on a network and should be used with caution.
|
||||||
.Ef
|
.Ef
|
||||||
.It Fl i Ar wait
|
.It Fl g Ar gateway
|
||||||
|
Use Lose Source Routing to send the ECHO_REQUEST packets via
|
||||||
|
.Ar gateway .
|
||||||
|
.TP
|
||||||
|
.It Fl i Ar internal
|
||||||
Wait
|
Wait
|
||||||
.Ar wait
|
.Ar internal
|
||||||
seconds
|
seconds
|
||||||
.Em between sending each packet .
|
.Em between sending each packet .
|
||||||
The default is to wait for one second between each packet,
|
The default is to wait for one second between each packet,
|
||||||
@ -112,6 +116,9 @@ except when the -f option is used the wait interval is 0.01 seconds.
|
|||||||
.It Fl I Ar ifaddr
|
.It Fl I Ar ifaddr
|
||||||
Send multicast datagrams on the network interface specified by the
|
Send multicast datagrams on the network interface specified by the
|
||||||
interface's hostname or IP address.
|
interface's hostname or IP address.
|
||||||
|
.It Fl h Ar host
|
||||||
|
is an alternate way of specifying the target host instead of as the
|
||||||
|
last argument.
|
||||||
.It Fl l Ar preload
|
.It Fl l Ar preload
|
||||||
If
|
If
|
||||||
.Ar preload
|
.Ar preload
|
||||||
@ -119,9 +126,12 @@ is specified,
|
|||||||
.Nm ping
|
.Nm ping
|
||||||
sends that many packets as fast as possible before falling into its normal
|
sends that many packets as fast as possible before falling into its normal
|
||||||
mode of behavior.
|
mode of behavior.
|
||||||
|
.It Fl L
|
||||||
|
Disable loopback when sending to multicast destinations,
|
||||||
|
so the transmitting host doesn't see the ICMP requests.
|
||||||
.It Fl n
|
.It Fl n
|
||||||
Numeric output only.
|
Numeric output only.
|
||||||
No attempt will be made to lookup symbolic names for host addresses.
|
No attempt will be made to look up symbolic names for host addresses.
|
||||||
.It Fl o
|
.It Fl o
|
||||||
Exit successfully after receiving one reply packet.
|
Exit successfully after receiving one reply packet.
|
||||||
.It Fl p Ar pattern
|
.It Fl p Ar pattern
|
||||||
@ -131,10 +141,17 @@ For example,
|
|||||||
.Dq Li \-p ff
|
.Dq Li \-p ff
|
||||||
will cause the sent packet to be filled with all
|
will cause the sent packet to be filled with all
|
||||||
ones.
|
ones.
|
||||||
|
.It Fl P
|
||||||
|
Use a psuedo-random sequence for the data instead of the default,
|
||||||
|
fixed sequence of incrementing 8-bit integers.
|
||||||
|
This is useful to foil compression on PPP and other links.
|
||||||
.It Fl q
|
.It Fl q
|
||||||
Quiet output.
|
Quiet output.
|
||||||
Nothing is displayed except the summary lines at startup time and
|
Nothing is displayed except the summary lines at startup time and
|
||||||
when finished.
|
when finished.
|
||||||
|
.It Fl Q
|
||||||
|
Do not display responses such as Network Unreachable ICMP messages
|
||||||
|
concerning the ECHO_REQUESTs sent.
|
||||||
.It Fl R
|
.It Fl R
|
||||||
Record route.
|
Record route.
|
||||||
Includes the
|
Includes the
|
||||||
@ -152,9 +169,14 @@ If the host is not on a directly-attached network, an error is returned.
|
|||||||
This option can be used to ping a local host through an interface
|
This option can be used to ping a local host through an interface
|
||||||
that has no route through it (e.g., after the interface was dropped by
|
that has no route through it (e.g., after the interface was dropped by
|
||||||
.Xr routed 8 ) .
|
.Xr routed 8 ) .
|
||||||
.It Fl S Ar ifaddr
|
.It Fl R
|
||||||
Specify the interface to transmit from on machines with multiple
|
Record Route. Includes the RECORD_ROUTE option in the ECHO_REQUEST
|
||||||
interfaces. For unicast pings.
|
packet and displays the route buffer on returned packets.
|
||||||
|
Note that the IP header is only large enough for eight such routes,
|
||||||
|
and only six when using the
|
||||||
|
.Fl g
|
||||||
|
option.
|
||||||
|
Many hosts ignore or discard this option.
|
||||||
.It Fl s Ar packetsize
|
.It Fl s Ar packetsize
|
||||||
Specifies the number of data bytes to be sent.
|
Specifies the number of data bytes to be sent.
|
||||||
The default is 56, which translates into 64
|
The default is 56, which translates into 64
|
||||||
@ -163,19 +185,10 @@ data bytes when combined
|
|||||||
with the 8 bytes of
|
with the 8 bytes of
|
||||||
.Tn ICMP
|
.Tn ICMP
|
||||||
header data. The maximum allowed value is 65468 bytes.
|
header data. The maximum allowed value is 65468 bytes.
|
||||||
header data. If the
|
.It Fl T Ar ttl
|
||||||
.Fl D
|
|
||||||
or
|
|
||||||
.Fl T
|
|
||||||
options are specified, or the
|
|
||||||
.Fl t
|
|
||||||
option to a unicast destination, a raw socket will be used and the 8 bytes of
|
|
||||||
header data are included in
|
|
||||||
.Ar packetsize .
|
|
||||||
.It Fl t Ar ttl
|
|
||||||
Use the specified time-to-live.
|
Use the specified time-to-live.
|
||||||
.It Fl T Ar tos
|
.It Fl t Ar tos
|
||||||
Use the specified type of service.
|
Use the specified hexadecimal type of service.
|
||||||
.It Fl v
|
.It Fl v
|
||||||
Verbose output.
|
Verbose output.
|
||||||
.Tn ICMP
|
.Tn ICMP
|
||||||
@ -187,18 +200,6 @@ Specifies the number of seconds to wait for a response to a packet
|
|||||||
before transmitting the next one. The default is 10.
|
before transmitting the next one. The default is 10.
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
In addition, the following options may be used for multicast pings:
|
|
||||||
.Bl -tag -width Ds
|
|
||||||
.It Fl L
|
|
||||||
Disable the loopback, so the transmitting host doesn't see the ICMP
|
|
||||||
requests.
|
|
||||||
.It Fl R
|
|
||||||
Record Route. Includes the RECORD_ROUTE option in the ECHO_REQUEST
|
|
||||||
packet and displays the route buffer on returned packets. Note that
|
|
||||||
the IP header is only large enough for six such routes. Many hosts
|
|
||||||
ignore or discard this option.
|
|
||||||
.El
|
|
||||||
.Pp
|
|
||||||
When using
|
When using
|
||||||
.Nm ping
|
.Nm ping
|
||||||
for fault isolation, it should first be run on the local host, to verify
|
for fault isolation, it should first be run on the local host, to verify
|
||||||
@ -275,8 +276,8 @@ header).
|
|||||||
.Pp
|
.Pp
|
||||||
If the data space is at least eight bytes large,
|
If the data space is at least eight bytes large,
|
||||||
.Nm ping
|
.Nm ping
|
||||||
uses the first eight bytes of this space to include a timestamp which
|
uses the first eight bytes of this space to include a timestamp to compute
|
||||||
it uses in the computation of round trip times.
|
round trip times.
|
||||||
If less than eight bytes of pad are specified, no round trip times are
|
If less than eight bytes of pad are specified, no round trip times are
|
||||||
given.
|
given.
|
||||||
.Sh DUPLICATE AND DAMAGED PACKETS
|
.Sh DUPLICATE AND DAMAGED PACKETS
|
||||||
@ -386,8 +387,8 @@ Others may use completely wild values.
|
|||||||
.El
|
.El
|
||||||
.Sh EXIT STATUS
|
.Sh EXIT STATUS
|
||||||
.Nm
|
.Nm
|
||||||
returns 0 on success (the host is alive), and non zero if the arguments are
|
returns 0 on success (the host is alive),
|
||||||
incorrect or the host is not responding.
|
and non-zero if the arguments are incorrect or the host is not responding.
|
||||||
.Sh BUGS
|
.Sh BUGS
|
||||||
Many Hosts and Gateways ignore the
|
Many Hosts and Gateways ignore the
|
||||||
.Tn RECORD_ROUTE
|
.Tn RECORD_ROUTE
|
||||||
|
493
sbin/ping/ping.c
493
sbin/ping/ping.c
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: ping.c,v 1.29 1997/04/02 09:22:01 augustss Exp $ */
|
/* $NetBSD: ping.c,v 1.30 1997/06/01 19:34:49 christos Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1989, 1993
|
* Copyright (c) 1989, 1993
|
||||||
@ -60,7 +60,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char rcsid[] = "$NetBSD: ping.c,v 1.29 1997/04/02 09:22:01 augustss Exp $";
|
static char rcsid[] = "$NetBSD: ping.c,v 1.30 1997/06/01 19:34:49 christos Exp $";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -75,7 +75,6 @@ static char rcsid[] = "$NetBSD: ping.c,v 1.29 1997/04/02 09:22:01 augustss Exp $
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <math.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#ifdef sgi
|
#ifdef sgi
|
||||||
@ -107,14 +106,11 @@ static char rcsid[] = "$NetBSD: ping.c,v 1.29 1997/04/02 09:22:01 augustss Exp $
|
|||||||
#define F_PING_RANDOM 0x0080 /* use random data */
|
#define F_PING_RANDOM 0x0080 /* use random data */
|
||||||
#define F_NUMERIC 0x0100 /* do not do gethostbyaddr() calls */
|
#define F_NUMERIC 0x0100 /* do not do gethostbyaddr() calls */
|
||||||
#define F_TIMING 0x0200 /* room for a timestamp */
|
#define F_TIMING 0x0200 /* room for a timestamp */
|
||||||
#define F_TTL 0x0400 /* Time to live */
|
#define F_DF 0x0400 /* set IP DF bit */
|
||||||
#define F_HDRINCL 0x0800 /* Include our ip headers */
|
#define F_SOURCE_ADDR 0x0800 /* set source IP address/interface */
|
||||||
#define F_SOURCE_ADDR 0x1000 /* Source address */
|
#define F_ONCE 0x1000 /* exit(0) after receiving 1 reply */
|
||||||
#define F_ONCE 0x2000 /* exit(0) after receiving 1 reply */
|
#define F_MCAST 0x2000 /* multicast target */
|
||||||
|
#define F_MCAST_NOLOOP 0x4000 /* no multicast loopback */
|
||||||
#define MULTICAST_NOLOOP 1 /* multicast options */
|
|
||||||
#define MULTICAST_TTL 2
|
|
||||||
#define MULTICAST_IF 4
|
|
||||||
|
|
||||||
/* MAX_DUP_CHK is the number of bits in received table, the
|
/* MAX_DUP_CHK is the number of bits in received table, the
|
||||||
* maximum number of received sequence numbers we can track to check
|
* maximum number of received sequence numbers we can track to check
|
||||||
@ -133,30 +129,40 @@ int nrepeats = 0;
|
|||||||
|
|
||||||
u_char *packet;
|
u_char *packet;
|
||||||
int packlen;
|
int packlen;
|
||||||
int pingflags = 0, options, moptions;
|
int pingflags = 0, options;
|
||||||
char *fill_pat;
|
char *fill_pat;
|
||||||
|
|
||||||
int s; /* Socket file descriptor */
|
int s; /* Socket file descriptor */
|
||||||
|
|
||||||
#define PHDR_LEN sizeof(struct timeval) /* size of timestamp header */
|
#define PHDR_LEN sizeof(struct timeval) /* size of timestamp header */
|
||||||
struct sockaddr_in whereto, send_addr; /* Who to ping */
|
struct sockaddr_in whereto, send_addr; /* Who to ping */
|
||||||
|
struct sockaddr_in src_addr; /* from where */
|
||||||
struct sockaddr_in loc_addr; /* 127.1 */
|
struct sockaddr_in loc_addr; /* 127.1 */
|
||||||
int datalen = 64-PHDR_LEN; /* How much data */
|
int datalen = 64-PHDR_LEN; /* How much data */
|
||||||
|
|
||||||
|
#ifdef sgi
|
||||||
|
static char *__progname;
|
||||||
|
#else
|
||||||
extern char *__progname;
|
extern char *__progname;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
char hostname[MAXHOSTNAMELEN];
|
char hostname[MAXHOSTNAMELEN];
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
struct ip o_ip;
|
struct ip o_ip;
|
||||||
|
char o_opt[MAX_IPOPTLEN];
|
||||||
union {
|
union {
|
||||||
u_char u_buf[MAXPACKET - sizeof(struct ip)];
|
u_char u_buf[MAXPACKET];
|
||||||
struct icmp u_icmp;
|
struct icmp u_icmp;
|
||||||
} o_u;
|
} o_u;
|
||||||
} out_pack;
|
} out_pack;
|
||||||
#define opack_icmp out_pack.o_u.u_icmp
|
#define opack_icmp out_pack.o_u.u_icmp
|
||||||
#define opack_ip out_pack.o_ip
|
struct ip *opack_ip;
|
||||||
|
|
||||||
|
char optspace[MAX_IPOPTLEN]; /* record route space */
|
||||||
|
int optlen;
|
||||||
|
|
||||||
|
|
||||||
int npackets; /* total packets to send */
|
int npackets; /* total packets to send */
|
||||||
int preload; /* number of packets to "preload" */
|
int preload; /* number of packets to "preload" */
|
||||||
@ -177,8 +183,6 @@ int reset_kerninfo;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
int bufspace = 60*1024;
|
int bufspace = 60*1024;
|
||||||
char optspace[MAX_IPOPTLEN]; /* record route space */
|
|
||||||
int optlen;
|
|
||||||
|
|
||||||
struct timeval now, clear_cache, last_tx, next_tx, first_tx;
|
struct timeval now, clear_cache, last_tx, next_tx, first_tx;
|
||||||
struct timeval last_rx, first_rx;
|
struct timeval last_rx, first_rx;
|
||||||
@ -207,32 +211,33 @@ static void pr_iph(struct icmp *, int);
|
|||||||
static void pr_retip(struct icmp *, int);
|
static void pr_retip(struct icmp *, int);
|
||||||
static int pr_icmph(struct icmp *, struct sockaddr_in *, int);
|
static int pr_icmph(struct icmp *, struct sockaddr_in *, int);
|
||||||
static void jiggle(int), jiggle_flush(int);
|
static void jiggle(int), jiggle_flush(int);
|
||||||
static void gethost(const char *, struct sockaddr_in *, char *);
|
static void gethost(const char *, const char *,
|
||||||
|
struct sockaddr_in *, char *, int);
|
||||||
static void usage(void);
|
static void usage(void);
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int c, i, on = 1;
|
int c, i, on = 1, hostind = 0;
|
||||||
struct sockaddr_in ifaddr;
|
long l;
|
||||||
|
u_char ttl = 0;
|
||||||
|
u_long tos = 0;
|
||||||
char *p;
|
char *p;
|
||||||
u_char ttl = MAXTTL, loop = 1, df = 0;
|
|
||||||
int tos = 0;
|
|
||||||
int mcast;
|
|
||||||
#ifdef SIGINFO
|
#ifdef SIGINFO
|
||||||
struct termios ts;
|
struct termios ts;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef SIGINFO
|
#if defined(SIGINFO) && defined(NOKERNINFO)
|
||||||
if (tcgetattr (0, &ts) != -1) {
|
if (tcgetattr (0, &ts) != -1) {
|
||||||
reset_kerninfo = !(ts.c_lflag & NOKERNINFO);
|
reset_kerninfo = !(ts.c_lflag & NOKERNINFO);
|
||||||
ts.c_lflag |= NOKERNINFO;
|
ts.c_lflag |= NOKERNINFO;
|
||||||
tcsetattr (0, TCSANOW, &ts);
|
tcsetattr (0, TCSANOW, &ts);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
while ((c = getopt(argc, argv, "c:dDfg:h:i:I:l:Lnop:PqRQrs:t:T:vw:")) != -1) {
|
while ((c = getopt(argc, argv,
|
||||||
|
"c:dDfg:h:i:I:l:Lnop:PqQrRs:t:T:vw:")) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'c':
|
case 'c':
|
||||||
npackets = strtol(optarg, &p, 0);
|
npackets = strtol(optarg, &p, 0);
|
||||||
@ -240,8 +245,7 @@ main(int argc, char *argv[])
|
|||||||
errx(1, "Bad/invalid number of packets");
|
errx(1, "Bad/invalid number of packets");
|
||||||
break;
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
options |= F_HDRINCL;
|
pingflags |= F_DF;
|
||||||
df = -1;
|
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
options |= SO_DEBUG;
|
options |= SO_DEBUG;
|
||||||
@ -249,15 +253,19 @@ main(int argc, char *argv[])
|
|||||||
case 'f':
|
case 'f':
|
||||||
pingflags |= F_FLOOD;
|
pingflags |= F_FLOOD;
|
||||||
break;
|
break;
|
||||||
|
case 'h':
|
||||||
|
hostind = optind-1;
|
||||||
|
break;
|
||||||
case 'i': /* wait between sending packets */
|
case 'i': /* wait between sending packets */
|
||||||
interval = strtod(optarg, &p);
|
interval = strtod(optarg, &p);
|
||||||
if (*p != '\0' || interval <= 0)
|
if (*p != '\0' || interval <= 0)
|
||||||
errx(1, "Bad/invalid interval");
|
errx(1, "Bad/invalid interval %s", optarg);
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
preload = strtol(optarg, &p, 0);
|
preload = strtol(optarg, &p, 0);
|
||||||
if (*p != '\0' || preload < 0)
|
if (*p != '\0' || preload < 0)
|
||||||
errx(1, "Bad/invalid preload value");
|
errx(1, "Bad/invalid preload value %s",
|
||||||
|
optarg);
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
pingflags |= F_NUMERIC;
|
pingflags |= F_NUMERIC;
|
||||||
@ -288,7 +296,7 @@ main(int argc, char *argv[])
|
|||||||
case 's': /* size of packet to send */
|
case 's': /* size of packet to send */
|
||||||
datalen = strtol(optarg, &p, 0);
|
datalen = strtol(optarg, &p, 0);
|
||||||
if (*p != '\0' || datalen <= 0)
|
if (*p != '\0' || datalen <= 0)
|
||||||
errx(1, "Bad/invalid packet size");
|
errx(1, "Bad/invalid packet size %s", optarg);
|
||||||
if (datalen > MAXPACKET)
|
if (datalen > MAXPACKET)
|
||||||
errx(1, "packet size is too large");
|
errx(1, "packet size is too large");
|
||||||
break;
|
break;
|
||||||
@ -299,34 +307,31 @@ main(int argc, char *argv[])
|
|||||||
pingflags |= F_RECORD_ROUTE;
|
pingflags |= F_RECORD_ROUTE;
|
||||||
break;
|
break;
|
||||||
case 'L':
|
case 'L':
|
||||||
moptions |= MULTICAST_NOLOOP;
|
pingflags |= F_MCAST_NOLOOP;
|
||||||
loop = 0;
|
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
options |= F_TTL;
|
tos = strtoul(optarg, &p, 0);
|
||||||
ttl = strtol(optarg, &p, 0);
|
if (*p != '\0' || tos > 0xFF)
|
||||||
if (*p != '\0' || ttl > 255 || ttl <= 0)
|
|
||||||
errx(1, "Bad/invalid ttl");
|
|
||||||
break;
|
|
||||||
case 'T':
|
|
||||||
options |= F_HDRINCL;
|
|
||||||
tos = strtoul(optarg, NULL, 0);
|
|
||||||
if (tos > 0xFF)
|
|
||||||
errx(1, "bad tos value: %s", optarg);
|
errx(1, "bad tos value: %s", optarg);
|
||||||
break;
|
break;
|
||||||
|
case 'T':
|
||||||
|
l = strtol(optarg, &p, 0);
|
||||||
|
if (*p != '\0' || l > 255 || l <= 0)
|
||||||
|
errx(1, "ttl out of range");
|
||||||
|
ttl = (u_char)l; /* cannot check >255 otherwise */
|
||||||
|
break;
|
||||||
case 'I':
|
case 'I':
|
||||||
options |= F_SOURCE_ADDR;
|
pingflags |= F_SOURCE_ADDR;
|
||||||
gethost(optarg, &ifaddr, NULL);
|
gethost("-I", optarg, &src_addr, 0, 0);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'g':
|
case 'g':
|
||||||
pingflags |= F_SOURCE_ROUTE;
|
pingflags |= F_SOURCE_ROUTE;
|
||||||
gethost(optarg, &send_addr, NULL);
|
gethost("-g", optarg, &send_addr, 0, 0);
|
||||||
break;
|
break;
|
||||||
case 'w':
|
case 'w':
|
||||||
maxwait = strtod(optarg, &p);
|
maxwait = strtod(optarg, &p);
|
||||||
if (*p != '\0' || maxwait <= 0)
|
if (*p != '\0' || maxwait <= 0)
|
||||||
errx(1, "Bad/invalid maxwait time");
|
errx(1, "Bad/invalid maxwait time %s", optarg);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
@ -348,33 +353,18 @@ main(int argc, char *argv[])
|
|||||||
npackets = INT_MAX;
|
npackets = INT_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (optind != argc-1)
|
if (hostind == 0) {
|
||||||
|
if (optind != argc-1)
|
||||||
|
usage();
|
||||||
|
else
|
||||||
|
hostind = optind;
|
||||||
|
}
|
||||||
|
else if (hostind >= argc - 1)
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
gethost(argv[optind], &whereto, hostname);
|
gethost("", argv[hostind], &whereto, hostname, sizeof(hostname));
|
||||||
|
if (IN_MULTICAST(ntohl(whereto.sin_addr.s_addr)))
|
||||||
mcast = IN_MULTICAST(ntohl(whereto.sin_addr.s_addr));
|
pingflags |= F_MCAST;
|
||||||
|
|
||||||
if (options & F_SOURCE_ADDR) {
|
|
||||||
if (mcast)
|
|
||||||
moptions |= MULTICAST_IF;
|
|
||||||
else {
|
|
||||||
if (bind(s, (struct sockaddr*) &ifaddr,
|
|
||||||
sizeof(ifaddr)) == -1)
|
|
||||||
err(1, "bind failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (options & F_TTL) {
|
|
||||||
if (mcast)
|
|
||||||
moptions |= MULTICAST_TTL;
|
|
||||||
else
|
|
||||||
options |= F_HDRINCL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options & F_RECORD_ROUTE && options & F_HDRINCL)
|
|
||||||
errx(1, "-R option and -D or -T, or -t to unicast destinations"
|
|
||||||
" are incompatible");
|
|
||||||
|
|
||||||
if (!(pingflags & F_SOURCE_ROUTE))
|
if (!(pingflags & F_SOURCE_ROUTE))
|
||||||
(void) memcpy(&send_addr, &whereto, sizeof(send_addr));
|
(void) memcpy(&send_addr, &whereto, sizeof(send_addr));
|
||||||
|
|
||||||
@ -398,80 +388,79 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
ident = getpid() & 0xFFFF;
|
ident = getpid() & 0xFFFF;
|
||||||
|
|
||||||
if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1)
|
if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
|
||||||
err(1, "Cannot create socket");
|
err(1, "Cannot create socket");
|
||||||
|
|
||||||
if (options & SO_DEBUG) {
|
if (options & SO_DEBUG) {
|
||||||
if (setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *) &on,
|
if (setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *) &on,
|
||||||
sizeof(on)) == -1)
|
sizeof(on)) == -1)
|
||||||
err(1, "Can't turn on socket debugging");
|
warn("Can't turn on socket debugging");
|
||||||
}
|
}
|
||||||
if (options & SO_DONTROUTE) {
|
if (options & SO_DONTROUTE) {
|
||||||
if (setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *) &on,
|
if (setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *) &on,
|
||||||
sizeof(on)) == -1)
|
sizeof(on)) == -1)
|
||||||
err(1, "Can't turn off socket routing");
|
warn("SO_DONTROUTE");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options & F_HDRINCL) {
|
if (pingflags & F_SOURCE_ROUTE) {
|
||||||
if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *) &on,
|
optspace[IPOPT_OPTVAL] = IPOPT_LSRR;
|
||||||
sizeof(on)) == -1)
|
optspace[IPOPT_OLEN] = optlen = 7;
|
||||||
err(1, "Can't set option to include ip headers");
|
optspace[IPOPT_OFFSET] = IPOPT_MINOFF;
|
||||||
|
(void) memcpy(&whereto.sin_addr, &optspace[IPOPT_MINOFF-1],
|
||||||
opack_ip.ip_v = IPVERSION;
|
sizeof(whereto.sin_addr));
|
||||||
opack_ip.ip_hl = sizeof(struct ip) >> 2;
|
optspace[optlen++] = IPOPT_NOP;
|
||||||
opack_ip.ip_tos = tos;
|
|
||||||
opack_ip.ip_id = 0;
|
|
||||||
opack_ip.ip_off = (df?IP_DF:0);
|
|
||||||
opack_ip.ip_ttl = ttl;
|
|
||||||
opack_ip.ip_p = IPPROTO_ICMP;
|
|
||||||
opack_ip.ip_src.s_addr = INADDR_ANY;
|
|
||||||
opack_ip.ip_dst = whereto.sin_addr;
|
|
||||||
}
|
}
|
||||||
|
if (pingflags & F_RECORD_ROUTE) {
|
||||||
|
optspace[optlen+IPOPT_OPTVAL] = IPOPT_RR;
|
||||||
|
optspace[optlen+IPOPT_OLEN] = (MAX_IPOPTLEN -1-optlen);
|
||||||
|
optspace[optlen+IPOPT_OFFSET] = IPOPT_MINOFF;
|
||||||
|
optlen = MAX_IPOPTLEN;
|
||||||
|
}
|
||||||
|
/* this leaves opack_ip 0(mod 4) aligned */
|
||||||
|
opack_ip = (struct ip *)((char *)&out_pack.o_ip
|
||||||
|
+ sizeof(out_pack.o_opt)
|
||||||
|
- optlen);
|
||||||
|
(void) memcpy(opack_ip + 1, optspace, optlen);
|
||||||
|
|
||||||
/*
|
if (setsockopt(s,IPPROTO_IP,IP_HDRINCL, (char *) &on, sizeof(on)) < 0)
|
||||||
* Loose Source Route and Record and Record Route options
|
err(1, "Can't set special IP header");
|
||||||
*/
|
|
||||||
if (0 != (pingflags & (F_RECORD_ROUTE | F_SOURCE_ROUTE))) {
|
opack_ip->ip_v = IPVERSION;
|
||||||
if (pingflags & F_SOURCE_ROUTE) {
|
opack_ip->ip_hl = (sizeof(struct ip)+optlen) >> 2;
|
||||||
optlen = 7+4;
|
opack_ip->ip_tos = tos;
|
||||||
optspace[IPOPT_OPTVAL] = IPOPT_LSRR;
|
opack_ip->ip_off = (pingflags & F_DF) ? IP_DF : 0;
|
||||||
optspace[IPOPT_OLEN] = optlen;
|
opack_ip->ip_ttl = ttl ? ttl : MAXTTL;
|
||||||
optspace[IPOPT_OFFSET] = IPOPT_MINOFF;
|
opack_ip->ip_p = IPPROTO_ICMP;
|
||||||
(void) memcpy(&optspace[IPOPT_MINOFF+4-1],
|
opack_ip->ip_src = src_addr.sin_addr;
|
||||||
&whereto.sin_addr, 4);
|
opack_ip->ip_dst = send_addr.sin_addr;
|
||||||
optspace[optlen++] = IPOPT_NOP;
|
|
||||||
|
if (pingflags & F_MCAST) {
|
||||||
|
if (pingflags & F_MCAST_NOLOOP) {
|
||||||
|
u_char loop = 0;
|
||||||
|
if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP,
|
||||||
|
(char *) &loop, 1) < 0)
|
||||||
|
err(1, "Can't disable multicast loopback");
|
||||||
}
|
}
|
||||||
if (pingflags & F_RECORD_ROUTE) {
|
|
||||||
optspace[optlen+IPOPT_OPTVAL] = IPOPT_RR;
|
|
||||||
optspace[optlen+IPOPT_OLEN] = (sizeof(optspace)
|
|
||||||
-1-optlen);
|
|
||||||
optspace[optlen+IPOPT_OFFSET] = IPOPT_MINOFF;
|
|
||||||
optlen = sizeof(optspace);
|
|
||||||
}
|
|
||||||
if (setsockopt(s, IPPROTO_IP, IP_OPTIONS, optspace,
|
|
||||||
optlen) == -1)
|
|
||||||
err(1, "Can't set source/record routing");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (moptions & MULTICAST_NOLOOP) {
|
if (ttl != 0
|
||||||
if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP,
|
&& setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL,
|
||||||
(char *) &loop, 1) == -1)
|
(char *) &ttl, 1) < 0)
|
||||||
err(1, "Can't disable multicast loopback");
|
|
||||||
}
|
|
||||||
if (moptions & MULTICAST_TTL) {
|
|
||||||
if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL,
|
|
||||||
(char *) &ttl, 1) == -1)
|
|
||||||
err(1, "Can't set multicast time-to-live");
|
err(1, "Can't set multicast time-to-live");
|
||||||
}
|
|
||||||
if (moptions & MULTICAST_IF) {
|
if ((pingflags & F_SOURCE_ADDR)
|
||||||
if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF,
|
&& setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF,
|
||||||
(char *) &ifaddr.sin_addr, sizeof(ifaddr.sin_addr)) == -1)
|
(char *) &src_addr.sin_addr,
|
||||||
|
sizeof(src_addr.sin_addr)) < 0)
|
||||||
err(1, "Can't set multicast source interface");
|
err(1, "Can't set multicast source interface");
|
||||||
|
|
||||||
|
} else if (pingflags & F_SOURCE_ADDR) {
|
||||||
|
if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF,
|
||||||
|
(char *) &src_addr.sin_addr,
|
||||||
|
sizeof(src_addr.sin_addr)) < 0)
|
||||||
|
err(1, "Can't set source interface/address");
|
||||||
}
|
}
|
||||||
|
|
||||||
(void)printf("PING %s (%s): %d data bytes\n", hostname,
|
(void)printf("PING %s (%s): %d data bytes\n", hostname,
|
||||||
inet_ntoa(whereto.sin_addr),
|
inet_ntoa(whereto.sin_addr), datalen);
|
||||||
datalen);
|
|
||||||
|
|
||||||
/* When pinging the broadcast address, you can get a lot
|
/* When pinging the broadcast address, you can get a lot
|
||||||
* of answers. Doing something so evil is useful if you
|
* of answers. Doing something so evil is useful if you
|
||||||
@ -484,10 +473,11 @@ main(int argc, char *argv[])
|
|||||||
err(1, "Cannot set the receive buffer size");
|
err(1, "Cannot set the receive buffer size");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make it possible to send giant probes */
|
/* make it possible to send giant probes, but do not worry now
|
||||||
if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char*)&bufspace,
|
* if it fails, since we probably won't send giant probes.
|
||||||
sizeof(bufspace)) == -1)
|
*/
|
||||||
err(1, "Cannot set the send buffer size");
|
(void)setsockopt(s, SOL_SOCKET, SO_SNDBUF,
|
||||||
|
(char*)&bufspace, sizeof(bufspace));
|
||||||
|
|
||||||
(void)signal(SIGINT, prefinish);
|
(void)signal(SIGINT, prefinish);
|
||||||
#ifdef SIGINFO
|
#ifdef SIGINFO
|
||||||
@ -499,7 +489,7 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
#ifdef sgi
|
#ifdef sgi
|
||||||
/* run with a non-degrading priority to improve the delay values. */
|
/* run with a non-degrading priority to improve the delay values. */
|
||||||
(void)schedctl(NDPRI, 0, NDPHIMAX);
|
(void) cap_schedctl(NDPRI, 0, NDPHIMAX);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* fire off them quickies */
|
/* fire off them quickies */
|
||||||
@ -519,50 +509,50 @@ doit(void)
|
|||||||
int cc;
|
int cc;
|
||||||
struct sockaddr_in from;
|
struct sockaddr_in from;
|
||||||
int fromlen;
|
int fromlen;
|
||||||
double sec;
|
double sec, last, d_last;
|
||||||
struct timeval timeout;
|
struct timeval timeout;
|
||||||
fd_set fdmask;
|
fd_set fdmask;
|
||||||
double last = 0;
|
|
||||||
|
|
||||||
|
|
||||||
(void)gettimeofday(&clear_cache, 0);
|
(void)gettimeofday(&clear_cache,0);
|
||||||
|
if (maxwait != 0) {
|
||||||
|
last = timeval_to_sec(&clear_cache) + maxwait;
|
||||||
|
d_last = 0;
|
||||||
|
} else {
|
||||||
|
last = 0;
|
||||||
|
d_last = 365*24*60*60;
|
||||||
|
}
|
||||||
|
|
||||||
FD_ZERO(&fdmask);
|
FD_ZERO(&fdmask);
|
||||||
for (;;) {
|
do {
|
||||||
(void)gettimeofday(&now, 0);
|
(void)gettimeofday(&now,0);
|
||||||
|
|
||||||
if (maxwait != 0) {
|
if (last != 0)
|
||||||
if (last == 0)
|
d_last = last - timeval_to_sec(&now);
|
||||||
last = timeval_to_sec(&now) + maxwait;
|
|
||||||
else if (last <= timeval_to_sec(&now))
|
|
||||||
finish(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ntransmitted < npackets) {
|
if (ntransmitted < npackets && d_last > 0) {
|
||||||
/* send if within 100 usec or late for next packet */
|
/* send if within 100 usec or late for next packet */
|
||||||
sec = diffsec(&next_tx, &now);
|
sec = diffsec(&next_tx,&now);
|
||||||
if (sec <= 0.0001
|
if (sec <= 0.0001
|
||||||
|| (lastrcvd && (pingflags & F_FLOOD))) {
|
|| (lastrcvd && (pingflags & F_FLOOD))) {
|
||||||
pinger();
|
pinger();
|
||||||
sec = diffsec(&next_tx, &now);
|
sec = diffsec(&next_tx,&now);
|
||||||
}
|
}
|
||||||
if (sec < 0.0)
|
if (sec < 0.0)
|
||||||
sec = 0.0;
|
sec = 0.0;
|
||||||
|
if (d_last < sec)
|
||||||
|
sec = d_last;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* For the last response, wait twice as long as the
|
/* For the last response, wait twice as long as the
|
||||||
* worst case seen, or 10 times as long as the
|
* worst case seen, or 10 times as long as the
|
||||||
* maximum interpacket interval, whichever is longer.
|
* maximum interpacket interval, whichever is longer.
|
||||||
*/
|
*/
|
||||||
if (2 * tmax > 10 * interval)
|
sec = MAX(2*tmax,10*interval) - diffsec(&now,&last_tx);
|
||||||
sec = 2 * tmax;
|
if (d_last < sec)
|
||||||
else
|
sec = d_last;
|
||||||
sec = 10 * interval;
|
|
||||||
|
|
||||||
sec -= diffsec(&now, &last_tx);
|
|
||||||
|
|
||||||
if (sec <= 0)
|
if (sec <= 0)
|
||||||
finish(0);
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -575,7 +565,7 @@ doit(void)
|
|||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
jiggle_flush(1);
|
jiggle_flush(1);
|
||||||
err(1, "select failed");
|
err(1, "select");
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -587,19 +577,18 @@ doit(void)
|
|||||||
if (cc < 0) {
|
if (cc < 0) {
|
||||||
if (errno != EINTR) {
|
if (errno != EINTR) {
|
||||||
jiggle_flush(1);
|
jiggle_flush(1);
|
||||||
warn("recvfrom failed");
|
warn("recvfrom");
|
||||||
(void)fflush(stderr);
|
(void)fflush(stderr);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
(void)gettimeofday(&now, 0);
|
(void)gettimeofday(&now, 0);
|
||||||
pr_pack(packet, cc, &from);
|
pr_pack(packet, cc, &from);
|
||||||
if (nreceived >= npackets)
|
|
||||||
finish(0);
|
} while (nreceived < npackets
|
||||||
if (nreceived > 0 && (pingflags & F_ONCE))
|
&& (nreceived == 0 || !(pingflags & F_ONCE)));
|
||||||
finish(0);
|
|
||||||
}
|
finish(0);
|
||||||
/*NOTREACHED*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -672,64 +661,57 @@ jiggle(int delta)
|
|||||||
static void
|
static void
|
||||||
pinger(void)
|
pinger(void)
|
||||||
{
|
{
|
||||||
int i, cc;
|
int i, cc, sw;
|
||||||
void *packet = &opack_icmp;
|
|
||||||
|
|
||||||
opack_icmp.icmp_code = 0;
|
opack_icmp.icmp_code = 0;
|
||||||
opack_icmp.icmp_seq = htons((u_short)(ntransmitted));
|
opack_icmp.icmp_seq = htons((u_short)(ntransmitted));
|
||||||
|
|
||||||
|
/* clear the cached route in the kernel after an ICMP
|
||||||
|
* response such as a Redirect is seen to stop causing
|
||||||
|
* more such packets. Also clear the cached route
|
||||||
|
* periodically in case of routing changes that make
|
||||||
|
* black holes come and go.
|
||||||
|
*/
|
||||||
if (clear_cache.tv_sec != now.tv_sec) {
|
if (clear_cache.tv_sec != now.tv_sec) {
|
||||||
/* clear the cached route in the kernel after an ICMP
|
|
||||||
* response such as a Redirect is seen to stop causing
|
|
||||||
* more such packets. Also clear the cached route
|
|
||||||
* periodically in case of routing changes that make
|
|
||||||
* black holes come and go.
|
|
||||||
*/
|
|
||||||
opack_icmp.icmp_type = ICMP_ECHOREPLY;
|
opack_icmp.icmp_type = ICMP_ECHOREPLY;
|
||||||
opack_icmp.icmp_id = ~ident;
|
opack_icmp.icmp_id = ~ident;
|
||||||
opack_icmp.icmp_cksum = 0;
|
opack_icmp.icmp_cksum = 0;
|
||||||
opack_icmp.icmp_cksum = in_cksum((u_short*)&opack_icmp,
|
opack_icmp.icmp_cksum = in_cksum((u_short*)&opack_icmp,
|
||||||
PHDR_LEN);
|
PHDR_LEN);
|
||||||
if (optlen != 0 &&
|
sw = 0;
|
||||||
setsockopt(s, IPPROTO_IP, IP_OPTIONS, optspace, 0) == -1)
|
if (setsockopt(s,IPPROTO_IP,IP_HDRINCL,
|
||||||
err(1, "Record/Source Route");
|
(char *)&sw,sizeof(sw)) < 0)
|
||||||
if (options & F_HDRINCL) {
|
err(1, "Can't turn off special IP header");
|
||||||
packet = &opack_ip;
|
if (sendto(s, (char *) &opack_icmp, PHDR_LEN, MSG_DONTROUTE,
|
||||||
cc = sizeof(struct ip) + PHDR_LEN;
|
(struct sockaddr *)&loc_addr,
|
||||||
opack_ip.ip_len = cc;
|
sizeof(struct sockaddr_in)) < 0)
|
||||||
opack_ip.ip_sum = in_cksum((u_short *)&opack_ip, cc);
|
err(1, "failed to clear cached route");
|
||||||
}
|
sw = 1;
|
||||||
else
|
if (setsockopt(s,IPPROTO_IP,IP_HDRINCL,
|
||||||
cc = PHDR_LEN;
|
(char *)&sw, sizeof(sw)) < 0)
|
||||||
(void) sendto(s, packet, cc, MSG_DONTROUTE,
|
err(1, "Can't set special IP header");
|
||||||
(struct sockaddr *)&loc_addr, sizeof(struct sockaddr_in));
|
|
||||||
if (optlen != 0 && setsockopt(s, IPPROTO_IP, IP_OPTIONS,
|
(void)gettimeofday(&clear_cache,0);
|
||||||
optspace, optlen) == -1)
|
|
||||||
err(1, "Record/Source Route");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
opack_icmp.icmp_type = ICMP_ECHO;
|
opack_icmp.icmp_type = ICMP_ECHO;
|
||||||
opack_icmp.icmp_id = ident;
|
opack_icmp.icmp_id = ident;
|
||||||
if (pingflags & F_TIMING)
|
if (pingflags & F_TIMING)
|
||||||
(void) memcpy(opack_icmp.icmp_data, &now, sizeof(now));
|
(void) memcpy(&opack_icmp.icmp_data[0], &now, sizeof(now));
|
||||||
cc = datalen+PHDR_LEN;
|
cc = datalen+PHDR_LEN;
|
||||||
opack_icmp.icmp_cksum = 0;
|
opack_icmp.icmp_cksum = 0;
|
||||||
opack_icmp.icmp_cksum = in_cksum((u_short*)&opack_icmp, cc);
|
opack_icmp.icmp_cksum = in_cksum((u_short*)&opack_icmp, cc);
|
||||||
|
|
||||||
if (options & F_HDRINCL) {
|
cc += opack_ip->ip_hl<<2;
|
||||||
packet = &opack_ip;
|
opack_ip->ip_len = cc;
|
||||||
cc += sizeof(struct ip);
|
i = sendto(s, (char *) opack_ip, cc, 0,
|
||||||
opack_ip.ip_len = cc;
|
(struct sockaddr *)&send_addr, sizeof(struct sockaddr_in));
|
||||||
opack_ip.ip_sum = in_cksum((u_short *)&opack_ip, cc);
|
|
||||||
}
|
|
||||||
i = sendto(s, packet, cc, 0, (struct sockaddr *)&send_addr,
|
|
||||||
sizeof(struct sockaddr_in));
|
|
||||||
if (i != cc) {
|
if (i != cc) {
|
||||||
jiggle_flush(1);
|
jiggle_flush(1);
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
warn("sendto failed");
|
warn("sendto");
|
||||||
else
|
else
|
||||||
(void) fprintf(stderr,
|
warnx("wrote %s %d chars, ret=%d", hostname, cc, i);
|
||||||
"%s: wrote %s %d chars, ret=%d\n", __progname,
|
|
||||||
hostname, cc, i);
|
|
||||||
(void)fflush(stderr);
|
(void)fflush(stderr);
|
||||||
}
|
}
|
||||||
lastrcvd = 0;
|
lastrcvd = 0;
|
||||||
@ -779,11 +761,11 @@ pr_pack_sub(int cc,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
(void)printf("%d bytes from %s: icmp_seq=%u", cc, addr, seqno);
|
(void)printf("%d bytes from %s: icmp_seq=%u", cc, addr, seqno);
|
||||||
|
if (dupflag)
|
||||||
|
(void)printf(" DUP!");
|
||||||
(void)printf(" ttl=%d", ttl);
|
(void)printf(" ttl=%d", ttl);
|
||||||
if (pingflags & F_TIMING)
|
if (pingflags & F_TIMING)
|
||||||
(void)printf(" time=%.3f ms", triptime*1000.0);
|
(void)printf(" time=%.3f ms", triptime*1000.0);
|
||||||
if (dupflag)
|
|
||||||
(void)printf(" (DUP!)");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -808,8 +790,8 @@ pr_pack(u_char *buf,
|
|||||||
double triptime = 0.0;
|
double triptime = 0.0;
|
||||||
#define PR_PACK_SUB() {if (!dumped) { \
|
#define PR_PACK_SUB() {if (!dumped) { \
|
||||||
dumped = 1; \
|
dumped = 1; \
|
||||||
pr_pack_sub(cc, inet_ntoa(from->sin_addr), \
|
pr_pack_sub(cc, inet_ntoa(from->sin_addr), \
|
||||||
ntohs((u_short)icp->icmp_seq), \
|
ntohs((u_short)icp->icmp_seq), \
|
||||||
dupflag, ip->ip_ttl, triptime);}}
|
dupflag, ip->ip_ttl, triptime);}}
|
||||||
|
|
||||||
/* Check the IP header */
|
/* Check the IP header */
|
||||||
@ -841,7 +823,6 @@ pr_pack(u_char *buf,
|
|||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
(void) memcpy(&tv, icp->icmp_data, sizeof(tv));
|
(void) memcpy(&tv, icp->icmp_data, sizeof(tv));
|
||||||
triptime = diffsec(&last_rx, &tv);
|
triptime = diffsec(&last_rx, &tv);
|
||||||
|
|
||||||
tsum += triptime;
|
tsum += triptime;
|
||||||
if (triptime < tmin)
|
if (triptime < tmin)
|
||||||
tmin = triptime;
|
tmin = triptime;
|
||||||
@ -852,8 +833,9 @@ pr_pack(u_char *buf,
|
|||||||
if (TST(ntohs((u_short)icp->icmp_seq))) {
|
if (TST(ntohs((u_short)icp->icmp_seq))) {
|
||||||
nrepeats++, nreceived--;
|
nrepeats++, nreceived--;
|
||||||
dupflag=1;
|
dupflag=1;
|
||||||
} else
|
} else {
|
||||||
SET(ntohs((u_short)icp->icmp_seq));
|
SET(ntohs((u_short)icp->icmp_seq));
|
||||||
|
}
|
||||||
|
|
||||||
if (pingflags & F_QUIET)
|
if (pingflags & F_QUIET)
|
||||||
return;
|
return;
|
||||||
@ -864,7 +846,7 @@ pr_pack(u_char *buf,
|
|||||||
/* check the data */
|
/* check the data */
|
||||||
if (datalen > PHDR_LEN
|
if (datalen > PHDR_LEN
|
||||||
&& !(pingflags & F_PING_RANDOM)
|
&& !(pingflags & F_PING_RANDOM)
|
||||||
&& bcmp(&icp->icmp_data[PHDR_LEN],
|
&& memcmp(&icp->icmp_data[PHDR_LEN],
|
||||||
&opack_icmp.icmp_data[PHDR_LEN],
|
&opack_icmp.icmp_data[PHDR_LEN],
|
||||||
datalen-PHDR_LEN)) {
|
datalen-PHDR_LEN)) {
|
||||||
for (i=PHDR_LEN; i<datalen; i++) {
|
for (i=PHDR_LEN; i<datalen; i++) {
|
||||||
@ -880,7 +862,7 @@ pr_pack(u_char *buf,
|
|||||||
for (i=PHDR_LEN; i<datalen; i++) {
|
for (i=PHDR_LEN; i<datalen; i++) {
|
||||||
if ((i%16) == PHDR_LEN)
|
if ((i%16) == PHDR_LEN)
|
||||||
(void)printf("\n\t");
|
(void)printf("\n\t");
|
||||||
(void)printf("%2x ", (u_char)icp->icmp_data[i]);
|
(void)printf("%2x ",(u_char)icp->icmp_data[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -933,7 +915,7 @@ pr_pack(u_char *buf,
|
|||||||
continue;
|
continue;
|
||||||
if (dumped <= 1) {
|
if (dumped <= 1) {
|
||||||
if (i == old_rrlen
|
if (i == old_rrlen
|
||||||
&& !bcmp(cp, old_rr, i)) {
|
&& !memcmp(cp, old_rr, i)) {
|
||||||
if (dumped)
|
if (dumped)
|
||||||
(void)printf("\t(same route)");
|
(void)printf("\t(same route)");
|
||||||
j = ((i+3)/4)*4;
|
j = ((i+3)/4)*4;
|
||||||
@ -942,7 +924,7 @@ pr_pack(u_char *buf,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
old_rrlen = i;
|
old_rrlen = i;
|
||||||
bcopy(cp, old_rr, i);
|
(void) memcpy(old_rr, cp, i);
|
||||||
}
|
}
|
||||||
if (!dumped) {
|
if (!dumped) {
|
||||||
jiggle_flush(1);
|
jiggle_flush(1);
|
||||||
@ -1059,7 +1041,7 @@ timevaladd(struct timeval *t1,
|
|||||||
static void
|
static void
|
||||||
sec_to_timeval(const double sec, struct timeval *tp)
|
sec_to_timeval(const double sec, struct timeval *tp)
|
||||||
{
|
{
|
||||||
tp->tv_sec = (long) sec;
|
tp->tv_sec = sec;
|
||||||
tp->tv_usec = (sec - tp->tv_sec) * 1000000.0;
|
tp->tv_usec = (sec - tp->tv_sec) * 1000000.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1157,7 +1139,7 @@ prefinish(int s)
|
|||||||
static void
|
static void
|
||||||
finish(int s)
|
finish(int s)
|
||||||
{
|
{
|
||||||
#ifdef SIGINFO
|
#if defined(SIGINFO) && defined(NOKERNINFO)
|
||||||
struct termios ts;
|
struct termios ts;
|
||||||
|
|
||||||
if (reset_kerninfo && tcgetattr (0, &ts) != -1) {
|
if (reset_kerninfo && tcgetattr (0, &ts) != -1) {
|
||||||
@ -1170,7 +1152,7 @@ finish(int s)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
summary(1);
|
summary(1);
|
||||||
exit(nreceived > 0 ? 0 : 1);
|
exit(nreceived > 0 ? 0 : 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1439,7 +1421,7 @@ pr_iph(struct icmp *icp,
|
|||||||
(void) memcpy(&ip, icp->icmp_data, sizeof(ip));
|
(void) memcpy(&ip, icp->icmp_data, sizeof(ip));
|
||||||
|
|
||||||
hlen = ip.ip_hl << 2;
|
hlen = ip.ip_hl << 2;
|
||||||
cp = &icp->icmp_data[20]; /* point to options */
|
cp = (u_char *) &icp->icmp_data[20]; /* point to options */
|
||||||
|
|
||||||
(void)printf("\n Vr HL TOS Len ID Flg off TTL Pro cks Src Dst\n");
|
(void)printf("\n Vr HL TOS Len ID Flg off TTL Pro cks Src Dst\n");
|
||||||
(void)printf(" %1x %1x %02x %04x %04x",
|
(void)printf(" %1x %1x %02x %04x %04x",
|
||||||
@ -1504,7 +1486,7 @@ pr_retip(struct icmp *icp,
|
|||||||
int cc)
|
int cc)
|
||||||
{
|
{
|
||||||
int hlen;
|
int hlen;
|
||||||
unsigned char *cp;
|
u_char *cp;
|
||||||
struct ip ip;
|
struct ip ip;
|
||||||
|
|
||||||
(void) memcpy(&ip, icp->icmp_data, sizeof(ip));
|
(void) memcpy(&ip, icp->icmp_data, sizeof(ip));
|
||||||
@ -1513,7 +1495,7 @@ pr_retip(struct icmp *icp,
|
|||||||
pr_iph(icp, cc);
|
pr_iph(icp, cc);
|
||||||
|
|
||||||
hlen = ip.ip_hl << 2;
|
hlen = ip.ip_hl << 2;
|
||||||
cp = &icp->icmp_data[hlen];
|
cp = (u_char *) &icp->icmp_data[hlen];
|
||||||
|
|
||||||
if (ip.ip_p == IPPROTO_TCP) {
|
if (ip.ip_p == IPPROTO_TCP) {
|
||||||
if (pingflags & F_VERBOSE)
|
if (pingflags & F_VERBOSE)
|
||||||
@ -1551,9 +1533,9 @@ fill(void)
|
|||||||
}
|
}
|
||||||
if (cp == fill_pat || *cp != '\0' || (cp-fill_pat) > 16*2) {
|
if (cp == fill_pat || *cp != '\0' || (cp-fill_pat) > 16*2) {
|
||||||
(void)fflush(stdout);
|
(void)fflush(stdout);
|
||||||
errx(1,
|
errx(1, "\"-p %s\": patterns must be specified with"
|
||||||
"\"-p %s\": patterns must be specified with 1-32 hex digits\n",
|
" 1-32 hex digits\n",
|
||||||
fill_pat);
|
fill_pat);
|
||||||
}
|
}
|
||||||
|
|
||||||
i = sscanf(fill_pat,
|
i = sscanf(fill_pat,
|
||||||
@ -1593,46 +1575,59 @@ rnd_fill(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gethost(const char *name, struct sockaddr_in *sa, char *realname)
|
gethost(const char *arg,
|
||||||
|
const char *name,
|
||||||
|
struct sockaddr_in *sa,
|
||||||
|
char *realname,
|
||||||
|
int realname_len)
|
||||||
{
|
{
|
||||||
struct hostent *hp;
|
struct hostent *hp;
|
||||||
|
|
||||||
(void) memset(sa, 0, sizeof(*sa));
|
bzero(sa, sizeof(*sa));
|
||||||
sa->sin_family = AF_INET;
|
sa->sin_family = AF_INET;
|
||||||
|
|
||||||
if (inet_aton(name, &sa->sin_addr) != 0) {
|
/* If it is an IP address, try to convert it to a name to
|
||||||
if (realname == NULL)
|
* have something nice to display.
|
||||||
|
*/
|
||||||
|
if (inet_aton(name, &sa->sin_addr) != 0) {
|
||||||
|
if (realname) {
|
||||||
|
if (pingflags & F_NUMERIC)
|
||||||
|
hp = 0;
|
||||||
|
else
|
||||||
|
hp = gethostbyaddr((char *)&sa->sin_addr,
|
||||||
|
sizeof(sa->sin_addr),
|
||||||
|
AF_INET);
|
||||||
|
(void)strncpy(realname, hp ? hp->h_name : name,
|
||||||
|
realname_len);
|
||||||
|
realname[realname_len-1] = '\0';
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
if ((pingflags & F_NUMERIC)
|
}
|
||||||
|| !(hp = gethostbyaddr((char *) &sa->sin_addr,
|
|
||||||
sizeof(sa->sin_addr), AF_INET)))
|
|
||||||
(void) strncpy(realname, name, MAXHOSTNAMELEN);
|
|
||||||
else
|
|
||||||
(void) strncpy(realname, hp->h_name, MAXHOSTNAMELEN);
|
|
||||||
realname[MAXHOSTNAMELEN-1] = '\0';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
hp = gethostbyname(name);
|
hp = gethostbyname(name);
|
||||||
if (hp) {
|
if (!hp)
|
||||||
if (hp->h_addrtype != AF_INET)
|
errx(1, "Cannot resolve \"%s\" (%s)",name,hstrerror(h_errno));
|
||||||
errx(1, "`%s' only supported with IP", name);
|
|
||||||
(void) memcpy(&sa->sin_addr, hp->h_addr, sizeof(sa->sin_addr));
|
if (hp->h_addrtype != AF_INET)
|
||||||
if (realname == NULL)
|
errx(1, "%s only supported with IP", arg);
|
||||||
return;
|
|
||||||
(void) strncpy(realname, hp->h_name, MAXHOSTNAMELEN);
|
bcopy(hp->h_addr, &sa->sin_addr, sizeof(sa->sin_addr));
|
||||||
realname[MAXHOSTNAMELEN-1] = '\0';
|
|
||||||
} else
|
if (realname) {
|
||||||
errx(1, "Cannot resolve host `%s' (%s)", name,
|
(void)strncpy(realname, hp->h_name, realname_len);
|
||||||
hstrerror(h_errno));
|
realname[realname_len-1] = '\0';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
(void) fprintf(stderr, "Usage: %s %s\n%s\n", __progname,
|
(void)fprintf(stderr, "Usage: \n"
|
||||||
"[-dfnoqrvRLP] [-c count] [-s size] [-l preload] [-p pattern]",
|
"%s [-dDfnqrvRLP] [-c count] [-s size] [-l preload]"
|
||||||
"[-i interval] [-T ttl] [-I addr] [-g gateway] [-w maxwait] host");
|
" [-p pattern]\n"
|
||||||
|
" [-i interval] [-i maxwait] [-t tos] [-T ttl]"
|
||||||
|
" [-I addr] [-g gateway] host\n",
|
||||||
|
__progname);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user