Implement a new feature for ping(8) - sweeping pings. In a sweeping

ping ICMP payload of packets being sent is increased with given step.
Sweeping pings are useful for testing problematic channels, MTU
issues or traffic policing functions in networks.

PR:		bin/82625
Submitted by:	Chris Hellberg <chellberg juniper.net> (with some cleanups)
This commit is contained in:
Gleb Smirnoff 2005-08-15 14:15:37 +00:00
parent a0f08bdf0c
commit 9ff95228e8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=149086
2 changed files with 117 additions and 7 deletions

View File

@ -28,7 +28,7 @@
.\" @(#)ping.8 8.2 (Berkeley) 12/11/93
.\" $FreeBSD$
.\"
.Dd October 2, 2002
.Dd August 15, 2005
.Dt PING 8
.Os
.Sh NAME
@ -40,6 +40,9 @@ packets to network hosts
.Nm
.Op Fl AaDdfnoQqRrv
.Op Fl c Ar count
.Op Fl G Ar sweepmaxsize
.Op Fl g Ar sweepminsize
.Op Fl h Ar sweepincrsize
.Op Fl i Ar wait
.Op Fl l Ar preload
.Op Fl M Cm mask | time
@ -116,6 +119,10 @@ packets.
If this option is not specified,
.Nm
will operate until interrupted.
If this option is specified in conjunction with ping sweeps,
each sweep will consist of
.Ar count
packets.
.It Fl D
Set the Don't Fragment bit.
.It Fl d
@ -138,6 +145,21 @@ Only the super-user may use this option.
.Bf -emphasis
This can be very hard on a network and should be used with caution.
.Ef
.It Fl G Ar sweepmaxsize
Specify the maximum size of
.Tn ICMP
payload when sending sweeping pings.
This option is required for ping sweeps.
.It Fl g Ar sweepminsize
Specify the size of
.Tn ICMP
payload to start with when sending sweeping pings.
The default value is 0.
.It Fl h Ar sweepincrsize
Specify the number of bytes to increment the size of
.Tn ICMP
payload after
each sweep when sending sweeping pings. The default value is 1.
.It Fl I Ar iface
Source multicast packets with the given interface address.
This flag only applies if the ping destination is a multicast address.
@ -270,6 +292,7 @@ with the 8 bytes of
.Tn ICMP
header data.
Only the super-user may specify values more than default.
This option cannot be used with ping sweeps.
.It Fl T Ar ttl
Set the IP Time To Live for multicasted packets.
This flag only applies if the ping destination is a multicast address.

View File

@ -142,6 +142,7 @@ int options;
#define F_HDRINCL 0x40000
#define F_MASK 0x80000
#define F_TIME 0x100000
#define F_SWEEP 0x200000
/*
* MAX_DUP_CHK is the number of bits in received table, i.e. the maximum
@ -175,6 +176,12 @@ long npackets; /* max packets to transmit */
long nreceived; /* # of packets we got back */
long nrepeats; /* number of duplicates */
long ntransmitted; /* sequence # for outbound packets = #sent */
long snpackets; /* max packets to transmit in one sweep */
long snreceived; /* # of packets we got back in this sweep */
long sntransmitted; /* # of packets we sent in this sweep */
int sweepmax; /* max value of payload in sweep */
int sweepmin = 0; /* start value of payload in sweep */
int sweepincr = 1; /* payload increment in sweep */
int interval = 1000; /* interval between packets, ms */
/* timing */
@ -254,7 +261,7 @@ main(argc, argv)
outpack = outpackhdr + sizeof(struct ip);
while ((ch = getopt(argc, argv,
"Aac:DdfI:i:Ll:M:m:nop:QqRrS:s:T:t:vz:"
"Aac:DdfG:g:h:I:i:Ll:M:m:nop:QqRrS:s:T:t:vz:"
#ifdef IPSEC
#ifdef IPSEC_POLICY_IPSEC
"P:"
@ -292,6 +299,48 @@ main(argc, argv)
options |= F_FLOOD;
setbuf(stdout, (char *)NULL);
break;
case 'G': /* Maximum packet size for ping sweep */
ultmp = strtoul(optarg, &ep, 0);
if (*ep || ep == optarg)
errx(EX_USAGE, "invalid packet size: `%s'",
optarg);
if (uid != 0 && ultmp > DEFDATALEN) {
errno = EPERM;
err(EX_NOPERM,
"packet size too large: %lu > %u",
ultmp, DEFDATALEN);
}
options |= F_SWEEP;
sweepmax = ultmp;
break;
case 'g': /* Minimum packet size for ping sweep */
ultmp = strtoul(optarg, &ep, 0);
if (*ep || ep == optarg)
errx(EX_USAGE, "invalid packet size: `%s'",
optarg);
if (uid != 0 && ultmp > DEFDATALEN) {
errno = EPERM;
err(EX_NOPERM,
"packet size too large: %lu > %u",
ultmp, DEFDATALEN);
}
options |= F_SWEEP;
sweepmin = ultmp;
break;
case 'h': /* Packet size increment for ping sweep */
ultmp = strtoul(optarg, &ep, 0);
if (*ep || ep == optarg || ultmp < 1)
errx(EX_USAGE, "invalid increment size: `%s'",
optarg);
if (uid != 0 && ultmp > DEFDATALEN) {
errno = EPERM;
err(EX_NOPERM,
"packet size too large: %lu > %u",
ultmp, DEFDATALEN);
}
options |= F_SWEEP;
sweepincr = ultmp;
break;
case 'I': /* multicast interface */
if (inet_aton(optarg, &ifaddr) == 0)
errx(EX_USAGE,
@ -643,6 +692,23 @@ main(argc, argv)
err(EX_OSERR, "setsockopt SO_TIMESTAMP");
}
#endif
if (sweepmax) {
if (sweepmin >= sweepmax)
errx(EX_USAGE, "Maximum packet size must be greater than the minimum packet size");
if (datalen != DEFDATALEN)
errx(EX_USAGE, "Packet size and ping sweep are mutually exclusive");
if (npackets > 0) {
snpackets = npackets;
npackets = 0;
} else
snpackets = 1;
datalen = sweepmin;
send_len = icmp_len + sweepmin;
}
if (options & F_SWEEP && !sweepmax)
errx(EX_USAGE, "Maximum sweep size must be specified");
/*
* When pinging the broadcast address, you can get a lot of answers.
@ -668,9 +734,19 @@ main(argc, argv)
inet_ntoa(to->sin_addr));
if (source)
(void)printf(" from %s", shostname);
(void)printf(": %d data bytes\n", datalen);
} else
(void)printf("PING %s: %d data bytes\n", hostname, datalen);
if (sweepmax)
(void)printf(": (%d ... %d) data bytes\n",
sweepmin, sweepmax);
else
(void)printf(": %d data bytes\n", datalen);
} else {
if (sweepmax)
(void)printf("PING %s: (%d ... %d) data bytes\n",
hostname, sweepmin, sweepmax);
else
(void)printf("PING %s: %d data bytes\n", hostname, datalen);
}
/*
* Use sigaction() instead of signal() to get unambiguous semantics,
@ -784,6 +860,15 @@ main(argc, argv)
break;
}
if (n == 0 || options & F_FLOOD) {
if (sweepmax && sntransmitted == snpackets) {
for (i = 0; i < sweepincr ; ++i)
*datap++ = i;
datalen += sweepincr;
if (datalen > sweepmax)
break;
send_len = icmp_len + datalen;
sntransmitted = 0;
}
if (!npackets || ntransmitted < npackets)
pinger();
else {
@ -901,6 +986,7 @@ pinger(void)
}
}
ntransmitted++;
sntransmitted++;
if (!(options & F_QUIET) && options & F_FLOOD)
(void)write(STDOUT_FILENO, &DOT, 1);
}
@ -1600,10 +1686,11 @@ static void
usage()
{
(void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n",
(void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
"usage: ping [-AaDdfnoQqRrv] [-c count] [-i wait] [-l preload] [-M mask | time]",
" [-m ttl]" SECOPT " [-p pattern] [-S src_addr] [-s packetsize]",
" [-t timeout] [-z tos] host",
" [-t timeout] [-z tos] [-G sweepmaxsize ] [-g sweepminsize ]",
" [-h sweepincrsize ] host",
" ping [-AaDdfLnoQqRrv] [-c count] [-I iface] [-i wait] [-l preload]",
" [-M mask | time] [-m ttl]" SECOPT " [-p pattern] [-S src_addr]",
" [-s packetsize] [-T ttl] [-t timeout] [-z tos] mcast-group");