aboutsummaryrefslogtreecommitdiff
path: root/sbin/ping
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/ping')
-rw-r--r--sbin/ping/Makefile5
-rw-r--r--sbin/ping/main.c215
-rw-r--r--sbin/ping/main.h25
-rw-r--r--sbin/ping/ping.87
-rw-r--r--sbin/ping/ping.c236
-rw-r--r--sbin/ping/ping6.c147
-rw-r--r--sbin/ping/tests/Makefile1
-rw-r--r--sbin/ping/tests/Makefile.depend15
-rw-r--r--sbin/ping/tests/in_cksum_test.c1
-rw-r--r--sbin/ping/tests/ping_6_c1_s8_t1.out6
-rw-r--r--sbin/ping/tests/ping_c1_s8_t1_S1.out6
-rw-r--r--sbin/ping/tests/ping_test.sh67
-rw-r--r--sbin/ping/tests/test_ping.py267
-rw-r--r--sbin/ping/utils.c12
14 files changed, 544 insertions, 466 deletions
diff --git a/sbin/ping/Makefile b/sbin/ping/Makefile
index 4713b01cac90..30c68cbaba52 100644
--- a/sbin/ping/Makefile
+++ b/sbin/ping/Makefile
@@ -1,5 +1,3 @@
-# @(#)Makefile 8.1 (Berkeley) 6/5/93
-
.include <src.opts.mk>
PACKAGE=runtime
@@ -20,6 +18,7 @@ CFLAGS+= -DINET6 -DKAME_SCOPEID
SRCS+= ping6.c
LIBADD+= md
LINKS= ${BINDIR}/ping ${BINDIR}/ping6
+MLINKS= ping.8 ping6.8
.endif
.if ${MK_DYNAMICROOT} == "no"
@@ -33,8 +32,6 @@ CFLAGS+=-DWITH_CASPER
CFLAGS+=-DIPSEC
LIBADD+= ipsec
-CFLAGS+= -Wno-error=unused-but-set-variable
-
HAS_TESTS=
SUBDIR.${MK_TESTS}+= tests
diff --git a/sbin/ping/main.c b/sbin/ping/main.c
index 47d20f569008..8a572cb3c914 100644
--- a/sbin/ping/main.c
+++ b/sbin/ping/main.c
@@ -26,7 +26,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
#include <sys/types.h>
#include <sys/socket.h>
@@ -35,10 +34,13 @@
#include <netinet/in.h>
#include <err.h>
+#include <math.h>
+#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sysexits.h>
#include <unistd.h>
#include "main.h"
@@ -59,115 +61,186 @@
#error At least one of INET and INET6 is required
#endif
+/* various options */
+u_int options;
+
+char *hostname;
+
+/* counters */
+long nreceived; /* # of packets we got back */
+long nrepeats; /* number of duplicates */
+long ntransmitted; /* sequence # for outbound packets = #sent */
+long nrcvtimeout = 0; /* # of packets we got back after waittime */
+
+/* nonzero if we've been told to finish up */
+volatile sig_atomic_t seenint;
+volatile sig_atomic_t seeninfo;
+
+/* timing */
+int timing; /* flag to do timing */
+double tmin = 999999999.0; /* minimum round trip time */
+double tmax = 0.0; /* maximum round trip time */
+double tsum = 0.0; /* sum of all times, for doing average */
+double tsumsq = 0.0; /* sum of all times squared, for std. dev. */
+
int
main(int argc, char *argv[])
{
-#if defined(INET) && defined(INET6)
+#if defined(INET)
struct in_addr a;
- struct in6_addr a6;
#endif
-#if defined(INET) || defined(INET6)
- struct addrinfo hints;
+#if defined(INET6)
+ struct in6_addr a6;
#endif
- int ch;
-#ifdef INET
- bool ipv4 = false;
+#if defined(INET) && defined(INET6)
+ struct addrinfo hints, *res, *ai;
+ const char *target;
+ int error;
#endif
-#ifdef INET6
- bool ipv6 = false;
+ int opt;
+#ifdef INET6
if (strcmp(getprogname(), "ping6") == 0)
- ipv6 = true;
+ return ping6(argc, argv);
#endif
- while ((ch = getopt(argc, argv, ":" OPTSTR)) != -1) {
- switch(ch) {
+ while ((opt = getopt(argc, argv, ":" OPTSTR)) != -1) {
+ switch (opt) {
#ifdef INET
case '4':
- ipv4 = true;
- break;
+ goto ping4;
#endif
#ifdef INET6
case '6':
- ipv6 = true;
- break;
+ goto ping6;
#endif
-#if defined(INET) && defined(INET6)
case 'S':
/*
* If -S is given with a numeric parameter,
* force use of the corresponding version.
*/
+#ifdef INET
if (inet_pton(AF_INET, optarg, &a) == 1)
- ipv4 = true;
- else if (inet_pton(AF_INET6, optarg, &a6) == 1)
- ipv6 = true;
- break;
+ goto ping4;
#endif
+#ifdef INET6
+ if (inet_pton(AF_INET6, optarg, &a6) == 1)
+ goto ping6;
+#endif
+ break;
default:
break;
}
}
+ /*
+ * For IPv4, only one positional argument, the target, is allowed.
+ * For IPv6, multiple positional argument are allowed; the last
+ * one is the target, and preceding ones are intermediate hops.
+ * This nuance is lost here, but the only case where it matters is
+ * an error.
+ */
if (optind >= argc)
usage();
- optreset = 1;
- optind = 1;
-#if defined(INET) && defined(INET6)
- if (ipv4 && ipv6)
- errx(1, "-4 and -6 cannot be used simultaneously");
-#endif
-
#if defined(INET) && defined(INET6)
- if (inet_pton(AF_INET, argv[argc - 1], &a) == 1) {
- if (ipv6)
- errx(1, "IPv6 requested but IPv4 target address "
- "provided");
+ target = argv[argc - 1];
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_socktype = SOCK_RAW;
+ if (feature_present("inet") && !feature_present("inet6"))
hints.ai_family = AF_INET;
- }
- else if (inet_pton(AF_INET6, argv[argc - 1], &a6) == 1) {
- if (ipv4)
- errx(1, "IPv4 requested but IPv6 target address "
- "provided");
+ else if (feature_present("inet6") && !feature_present("inet"))
hints.ai_family = AF_INET6;
- } else if (ipv6)
- hints.ai_family = AF_INET6;
- else if (ipv4)
- hints.ai_family = AF_INET;
- else {
- if (!feature_present("inet6"))
- hints.ai_family = AF_INET;
- else if (!feature_present("inet"))
- hints.ai_family = AF_INET6;
- else {
- struct addrinfo *res;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_socktype = SOCK_RAW;
- hints.ai_family = AF_UNSPEC;
- getaddrinfo(argv[argc - 1], NULL, &hints, &res);
- if (res != NULL) {
- hints.ai_family = res[0].ai_family;
- freeaddrinfo(res);
- }
+ else
+ hints.ai_family = AF_UNSPEC;
+ error = getaddrinfo(target, NULL, &hints, &res);
+ if (res == NULL)
+ errx(EX_NOHOST, "cannot resolve %s: %s",
+ target, gai_strerror(error));
+ for (ai = res; ai != NULL; ai = ai->ai_next) {
+ if (ai->ai_family == AF_INET) {
+ freeaddrinfo(res);
+ goto ping4;
+ }
+ if (ai->ai_family == AF_INET6) {
+ freeaddrinfo(res);
+ goto ping6;
}
}
-#elif defined(INET)
- hints.ai_family = AF_INET;
-#elif defined(INET6)
- hints.ai_family = AF_INET6;
+ freeaddrinfo(res);
+ errx(EX_NOHOST, "cannot resolve %s", target);
#endif
-
#ifdef INET
- if (hints.ai_family == AF_INET)
- return ping(argc, argv);
-#endif /* INET */
+ping4:
+ optreset = 1;
+ optind = 1;
+ return ping(argc, argv);
+#endif
#ifdef INET6
- if (hints.ai_family == AF_INET6)
- return ping6(argc, argv);
-#endif /* INET6 */
- errx(1, "Unknown host");
+ping6:
+ optreset = 1;
+ optind = 1;
+ return ping6(argc, argv);
+#endif
+}
+
+/*
+ * onsignal --
+ * Set the global bit that causes the main loop to quit.
+ */
+void
+onsignal(int sig)
+{
+ switch (sig) {
+ case SIGALRM:
+ case SIGINT:
+ /*
+ * When doing reverse DNS lookups, the seenint flag might not
+ * be noticed for a while. Just exit if we get a second SIGINT.
+ */
+ if (!(options & F_HOSTNAME) && seenint != 0)
+ _exit(nreceived ? 0 : 2);
+ seenint++;
+ break;
+ case SIGINFO:
+ seeninfo++;
+ break;
+ }
+}
+
+/*
+ * pr_summary --
+ * Print out summary statistics to the given output stream.
+ */
+void
+pr_summary(FILE * restrict stream)
+{
+ fprintf(stream, "\n--- %s ping statistics ---\n", hostname);
+ fprintf(stream, "%ld packets transmitted, ", ntransmitted);
+ fprintf(stream, "%ld packets received, ", nreceived);
+ if (nrepeats)
+ fprintf(stream, "+%ld duplicates, ", nrepeats);
+ if (ntransmitted) {
+ if (nreceived > ntransmitted)
+ fprintf(stream, "-- somebody's duplicating packets!");
+ else
+ fprintf(stream, "%.1f%% packet loss",
+ ((((double)ntransmitted - nreceived) * 100.0) /
+ ntransmitted));
+ }
+ if (nrcvtimeout)
+ fprintf(stream, ", %ld packets out of wait time", nrcvtimeout);
+ fputc('\n', stream);
+ if (nreceived && timing) {
+ /* Only display average to microseconds */
+ double num = nreceived + nrepeats;
+ double avg = tsum / num;
+ double stddev = sqrt(fmax(0, tsumsq / num - avg * avg));
+ fprintf(stream,
+ "round-trip min/avg/max/stddev = %.3f/%.3f/%.3f/%.3f ms\n",
+ tmin, avg, tmax, stddev);
+ }
+ fflush(stream);
}
void
@@ -211,7 +284,7 @@ usage(void)
"Z"
#endif
"] "
- "[-b bufsiz] [-c count] [-e gateway]\n"
+ "[-b bufsiz] [-C pcp] [-c count] [-e gateway]\n"
"\t [-I interface] [-i wait] [-k addrtype] [-l preload] "
"[-m hoplimit]\n"
"\t [-p pattern]"
diff --git a/sbin/ping/main.h b/sbin/ping/main.h
index 7084585e6bb0..9a883b61a350 100644
--- a/sbin/ping/main.h
+++ b/sbin/ping/main.h
@@ -49,6 +49,31 @@
#endif
#define PING6OPTS ".::6Aab:C:c:Dde:fHI:i:k:l:m:nNoOp:qS:s:t:uvyYW:z:" PING6ADDOPTS
+/* various options */
+extern u_int options;
+#define F_HOSTNAME 0x0004
+
+extern char *hostname;
+
+/* counters */
+extern long nreceived; /* # of packets we got back */
+extern long nrepeats; /* number of duplicates */
+extern long ntransmitted; /* sequence # for outbound packets = #sent */
+extern long nrcvtimeout; /* # of packets we got back after waittime */
+
+/* nonzero if we've been told to finish up */
+extern volatile sig_atomic_t seenint;
+extern volatile sig_atomic_t seeninfo;
+
+/* timing */
+extern int timing; /* flag to do timing */
+extern double tmin; /* minimum round trip time */
+extern double tmax; /* maximum round trip time */
+extern double tsum; /* sum of all times, for doing average */
+extern double tsumsq; /* sum of all times squared, for std. dev. */
+
+void onsignal(int);
+void pr_summary(FILE * __restrict);
void usage(void) __dead2;
#endif
diff --git a/sbin/ping/ping.8 b/sbin/ping/ping.8
index 7419aef51dfa..43dca1148e16 100644
--- a/sbin/ping/ping.8
+++ b/sbin/ping/ping.8
@@ -25,9 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)ping.8 8.2 (Berkeley) 12/11/93
-.\"
-.Dd November 20, 2022
+.Dd September 15, 2023
.Dt PING 8
.Os
.Sh NAME
@@ -81,6 +79,7 @@ packets to network hosts
.Op Fl 6AaDdEfHNnOoquvYyZ
.Op Fl .\& Ns Ar chars
.Op Fl b Ar bufsiz
+.Op Fl C Ar pcp
.Op Fl c Ar count
.Op Fl e Ar gateway
.Op Fl I Ar interface
@@ -231,7 +230,7 @@ option.
.It Fl I Ar iface
For an IPv4 target,
.Ar iface
-is an IP address indentifying an interface from which the packets will be sent.
+is an IP address identifying an interface from which the packets will be sent.
This flag applies only if the ping target is a multicast address.
.Pp
For an IPv6 target,
diff --git a/sbin/ping/ping.c b/sbin/ping/ping.c
index 072d4607f745..d10e3c85c9bd 100644
--- a/sbin/ping/ping.c
+++ b/sbin/ping/ping.c
@@ -32,18 +32,6 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1989, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static char sccsid[] = "@(#)ping.c 8.1 (Berkeley) 6/5/93";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
/*
* P I N G . C
*
@@ -87,7 +75,6 @@ static char sccsid[] = "@(#)ping.c 8.1 (Berkeley) 6/5/93";
#include <ctype.h>
#include <err.h>
#include <errno.h>
-#include <math.h>
#include <netdb.h>
#include <stddef.h>
#include <signal.h>
@@ -127,10 +114,8 @@ struct tv32 {
};
/* various options */
-static int options;
#define F_FLOOD 0x0001
#define F_INTERVAL 0x0002
-#define F_NUMERIC 0x0004
#define F_PINGFILLED 0x0008
#define F_QUIET 0x0010
#define F_RROUTE 0x0020
@@ -178,7 +163,6 @@ static char BSPACE = '\b'; /* characters written for flood */
static const char *DOT = ".";
static size_t DOTlen = 1;
static size_t DOTidx = 0;
-static char *hostname;
static char *shostname;
static int ident; /* process id to identify our packets */
static int uid; /* cached uid for micro-optimization */
@@ -190,43 +174,24 @@ static int send_len;
/* counters */
static long nmissedmax; /* max value of ntransmitted - nreceived - 1 */
static long npackets; /* max packets to transmit */
-static long nreceived; /* # of packets we got back */
-static long nrepeats; /* number of duplicates */
-static long ntransmitted; /* sequence # for outbound packets = #sent */
-static long snpackets; /* max packets to transmit in one sweep */
+static long snpackets; /* max packets to transmit in one sweep */
static long sntransmitted; /* # of packets we sent in this sweep */
static int sweepmax; /* max value of payload in sweep */
static int sweepmin = 0; /* start value of payload in sweep */
static int sweepincr = 1; /* payload increment in sweep */
static int interval = 1000; /* interval between packets, ms */
static int waittime = MAXWAIT; /* timeout for each packet */
-static long nrcvtimeout = 0; /* # of packets we got back after waittime */
-
-/* timing */
-static int timing; /* flag to do timing */
-static double tmin = 999999999.0; /* minimum round trip time */
-static double tmax = 0.0; /* maximum round trip time */
-static double tsum = 0.0; /* sum of all times, for doing average */
-static double tsumsq = 0.0; /* sum of all times squared, for std. dev. */
-
-/* nonzero if we've been told to finish up */
-static volatile sig_atomic_t finish_up;
-static volatile sig_atomic_t siginfo_p;
static cap_channel_t *capdns;
static void fill(char *, char *);
static cap_channel_t *capdns_setup(void);
-static void check_status(void);
-static void finish(void) __dead2;
static void pinger(void);
static char *pr_addr(struct in_addr);
static char *pr_ntime(n_time);
static void pr_icmph(struct icmp *, struct ip *, const u_char *const);
static void pr_iph(struct ip *, const u_char *);
static void pr_pack(char *, ssize_t, struct sockaddr_in *, struct timespec *);
-static void status(int);
-static void stopit(int);
int
ping(int argc, char *const *argv)
@@ -264,8 +229,6 @@ ping(int argc, char *const *argv)
#endif
cap_rights_t rights;
- options |= F_NUMERIC;
-
/*
* Do the stuff that we need root priv's for *first*, and
* then drop our setuid bit. Save error reporting for
@@ -350,47 +313,47 @@ ping(int argc, char *const *argv)
options |= F_DOT;
setbuf(stdout, (char *)NULL);
break;
- case 'G': /* Maximum packet size for ping sweep */
+ case 'G': /* Maximum payload size for ping sweep */
ltmp = strtonum(optarg, 1, INT_MAX, &errstr);
if (errstr != NULL) {
- errx(EX_USAGE, "invalid packet size: `%s'",
+ errx(EX_USAGE, "invalid payload size: `%s'",
optarg);
}
sweepmax = (int)ltmp;
if (uid != 0 && sweepmax > DEFDATALEN) {
errc(EX_NOPERM, EPERM,
- "packet size too large: %d > %u",
+ "payload size too large: %d > %u",
sweepmax, DEFDATALEN);
}
options |= F_SWEEP;
break;
- case 'g': /* Minimum packet size for ping sweep */
- ltmp = strtonum(optarg, 1, INT_MAX, &errstr);
+ case 'g': /* Minimum payload size for ping sweep */
+ ltmp = strtonum(optarg, 0, INT_MAX, &errstr);
if (errstr != NULL) {
- errx(EX_USAGE, "invalid packet size: `%s'",
+ errx(EX_USAGE, "invalid payload size: `%s'",
optarg);
}
sweepmin = (int)ltmp;
if (uid != 0 && sweepmin > DEFDATALEN) {
errc(EX_NOPERM, EPERM,
- "packet size too large: %d > %u",
+ "payload size too large: %d > %u",
sweepmin, DEFDATALEN);
}
options |= F_SWEEP;
break;
case 'H':
- options &= ~F_NUMERIC;
+ options |= F_HOSTNAME;
break;
- case 'h': /* Packet size increment for ping sweep */
+ case 'h': /* Payload size increment for ping sweep */
ltmp = strtonum(optarg, 1, INT_MAX, &errstr);
if (errstr != NULL) {
- errx(EX_USAGE, "invalid packet size: `%s'",
+ errx(EX_USAGE, "invalid payload size: `%s'",
optarg);
}
sweepincr = (int)ltmp;
if (uid != 0 && sweepincr > DEFDATALEN) {
errc(EX_NOPERM, EPERM,
- "packet size too large: %d > %u",
+ "payload size too large: %d > %u",
sweepincr, DEFDATALEN);
}
options |= F_SWEEP;
@@ -452,7 +415,7 @@ ping(int argc, char *const *argv)
options |= F_TTL;
break;
case 'n':
- options |= F_NUMERIC;
+ options &= ~F_HOSTNAME;
break;
case 'o':
options |= F_ONCE;
@@ -882,22 +845,17 @@ ping(int argc, char *const *argv)
sigemptyset(&si_sa.sa_mask);
si_sa.sa_flags = 0;
-
- si_sa.sa_handler = stopit;
- if (sigaction(SIGINT, &si_sa, 0) == -1) {
+ si_sa.sa_handler = onsignal;
+ if (sigaction(SIGINT, &si_sa, 0) == -1)
err(EX_OSERR, "sigaction SIGINT");
- }
-
- si_sa.sa_handler = status;
- if (sigaction(SIGINFO, &si_sa, 0) == -1) {
- err(EX_OSERR, "sigaction");
- }
-
- if (alarmtimeout > 0) {
- si_sa.sa_handler = stopit;
+ seenint = 0;
+ if (sigaction(SIGINFO, &si_sa, 0) == -1)
+ err(EX_OSERR, "sigaction SIGINFO");
+ seeninfo = 0;
+ if (alarmtimeout > 0) {
if (sigaction(SIGALRM, &si_sa, 0) == -1)
err(EX_OSERR, "sigaction SIGALRM");
- }
+ }
bzero(&msg, sizeof(msg));
msg.msg_name = (caddr_t)&from;
@@ -929,13 +887,18 @@ ping(int argc, char *const *argv)
}
almost_done = 0;
- while (!finish_up) {
+ while (seenint == 0) {
struct timespec now, timeout;
fd_set rfds;
int n;
ssize_t cc;
- check_status();
+ /* signal handling */
+ if (seeninfo) {
+ pr_summary(stderr);
+ seeninfo = 0;
+ continue;
+ }
if ((unsigned)srecv >= FD_SETSIZE)
errx(EX_OSERR, "descriptor too large");
FD_ZERO(&rfds);
@@ -945,9 +908,10 @@ ping(int argc, char *const *argv)
timespecsub(&timeout, &now, &timeout);
if (timeout.tv_sec < 0)
timespecclear(&timeout);
+
n = pselect(srecv + 1, &rfds, NULL, NULL, &timeout, NULL);
if (n < 0)
- continue; /* Must be EINTR. */
+ continue; /* EINTR */
if (n == 1) {
struct timespec *tv = NULL;
#ifdef SO_TIMESTAMP
@@ -982,7 +946,7 @@ ping(int argc, char *const *argv)
(npackets && nreceived >= npackets))
break;
}
- if (n == 0 || options & F_FLOOD) {
+ if (n == 0 || (options & F_FLOOD)) {
if (sweepmax && sntransmitted == snpackets) {
if (datalen + sweepincr > sweepmax)
break;
@@ -998,14 +962,21 @@ ping(int argc, char *const *argv)
if (almost_done)
break;
almost_done = 1;
+ /*
+ * If we're not transmitting any more packets,
+ * change the timer to wait two round-trip times
+ * if we've received any packets or (waittime)
+ * milliseconds if we haven't.
+ */
intvl.tv_nsec = 0;
if (nreceived) {
intvl.tv_sec = 2 * tmax / 1000;
- if (!intvl.tv_sec)
+ if (intvl.tv_sec == 0)
intvl.tv_sec = 1;
} else {
intvl.tv_sec = waittime / 1000;
- intvl.tv_nsec = waittime % 1000 * 1000000;
+ intvl.tv_nsec =
+ waittime % 1000 * 1000000;
}
}
(void)clock_gettime(CLOCK_MONOTONIC, &last);
@@ -1016,28 +987,9 @@ ping(int argc, char *const *argv)
}
}
}
- finish();
- /* NOTREACHED */
- exit(0); /* Make the compiler happy */
-}
+ pr_summary(stdout);
-/*
- * stopit --
- * Set the global bit that causes the main loop to quit.
- * Do NOT call finish() from here, since finish() does far too much
- * to be called from a signal handler.
- */
-void
-stopit(int sig __unused)
-{
-
- /*
- * When doing reverse DNS lookups, the finish_up flag might not
- * be noticed for a while. Just exit if we get a second SIGINT.
- */
- if (!(options & F_NUMERIC) && finish_up)
- _exit(nreceived ? 0 : 2);
- finish_up = 1;
+ exit(nreceived ? 0 : 2);
}
/*
@@ -1297,14 +1249,14 @@ pr_pack(char *buf, ssize_t cc, struct sockaddr_in *from, struct timespec *tv)
for (i = 0; i < datalen; ++i, ++cp) {
if ((i % 16) == 8)
(void)printf("\n\t");
- (void)printf("%2x ", *cp);
+ (void)printf(" %2x", *cp);
}
(void)printf("\ndp:");
cp = &outpack[ICMP_MINLEN];
for (i = 0; i < datalen; ++i, ++cp) {
if ((i % 16) == 8)
(void)printf("\n\t");
- (void)printf("%2x ", *cp);
+ (void)printf(" %2x", *cp);
}
break;
}
@@ -1406,7 +1358,7 @@ pr_pack(char *buf, ssize_t cc, struct sockaddr_in *from, struct timespec *tv)
(void)putchar('\n');
}
} else
- (void)printf("\t(truncated route)\n");
+ (void)printf("\t(truncated route)");
break;
case IPOPT_RR:
j = cp[IPOPT_OLEN]; /* get length */
@@ -1464,77 +1416,6 @@ pr_pack(char *buf, ssize_t cc, struct sockaddr_in *from, struct timespec *tv)
}
/*
- * status --
- * Print out statistics when SIGINFO is received.
- */
-
-static void
-status(int sig __unused)
-{
-
- siginfo_p = 1;
-}
-
-static void
-check_status(void)
-{
-
- if (siginfo_p) {
- siginfo_p = 0;
- (void)fprintf(stderr, "\r%ld/%ld packets received (%.1f%%)",
- nreceived, ntransmitted,
- ntransmitted ? nreceived * 100.0 / ntransmitted : 0.0);
- if (nreceived && timing)
- (void)fprintf(stderr, " %.3f min / %.3f avg / %.3f max",
- tmin, tsum / (nreceived + nrepeats), tmax);
- (void)fprintf(stderr, "\n");
- }
-}
-
-/*
- * finish --
- * Print out statistics, and give up.
- */
-static void
-finish(void)
-{
-
- (void)signal(SIGINT, SIG_IGN);
- (void)signal(SIGALRM, SIG_IGN);
- (void)putchar('\n');
- (void)fflush(stdout);
- (void)printf("--- %s ping statistics ---\n", hostname);
- (void)printf("%ld packets transmitted, ", ntransmitted);
- (void)printf("%ld packets received, ", nreceived);
- if (nrepeats)
- (void)printf("+%ld duplicates, ", nrepeats);
- if (ntransmitted) {
- if (nreceived > ntransmitted)
- (void)printf("-- somebody's printing up packets!");
- else
- (void)printf("%.1f%% packet loss",
- ((ntransmitted - nreceived) * 100.0) /
- ntransmitted);
- }
- if (nrcvtimeout)
- (void)printf(", %ld packets out of wait time", nrcvtimeout);
- (void)putchar('\n');
- if (nreceived && timing) {
- double n = nreceived + nrepeats;
- double avg = tsum / n;
- double vari = tsumsq / n - avg * avg;
- (void)printf(
- "round-trip min/avg/max/stddev = %.3f/%.3f/%.3f/%.3f ms\n",
- tmin, avg, tmax, sqrt(vari));
- }
-
- if (nreceived)
- exit(0);
- else
- exit(2);
-}
-
-/*
* pr_icmph --
* Print a descriptive string about an ICMP header.
*/
@@ -1668,13 +1549,21 @@ pr_icmph(struct icmp *icp, struct ip *oip, const u_char *const oicmp_raw)
static void
pr_iph(struct ip *ip, const u_char *cp)
{
- struct in_addr ina;
+ struct in_addr dst_ina, src_ina;
int hlen;
hlen = ip->ip_hl << 2;
cp = cp + sizeof(struct ip); /* point to options */
- (void)printf("Vr HL TOS Len ID Flg off TTL Pro cks Src Dst\n");
+ memcpy(&src_ina, &ip->ip_src.s_addr, sizeof(src_ina));
+ memcpy(&dst_ina, &ip->ip_dst.s_addr, sizeof(dst_ina));
+
+ (void)printf("Vr HL TOS Len ID Flg off TTL Pro cks %*s %*s",
+ (int)strlen(inet_ntoa(src_ina)), "Src",
+ (int)strlen(inet_ntoa(dst_ina)), "Dst");
+ if (hlen > (int)sizeof(struct ip))
+ (void)printf(" Opts");
+ (void)putchar('\n');
(void)printf(" %1x %1x %02x %04x %04x",
ip->ip_v, ip->ip_hl, ip->ip_tos, ntohs(ip->ip_len),
ntohs(ip->ip_id));
@@ -1683,13 +1572,14 @@ pr_iph(struct ip *ip, const u_char *cp)
ntohs(ip->ip_off) & 0x1fff);
(void)printf(" %02x %02x %04x", ip->ip_ttl, ip->ip_p,
ntohs(ip->ip_sum));
- memcpy(&ina, &ip->ip_src.s_addr, sizeof ina);
- (void)printf(" %s ", inet_ntoa(ina));
- memcpy(&ina, &ip->ip_dst.s_addr, sizeof ina);
- (void)printf(" %s ", inet_ntoa(ina));
+ (void)printf(" %s", inet_ntoa(src_ina));
+ (void)printf(" %s", inet_ntoa(dst_ina));
/* dump any option bytes */
- while (hlen-- > (int)sizeof(struct ip)) {
- (void)printf("%02x", *cp++);
+ if (hlen > (int)sizeof(struct ip)) {
+ (void)printf(" ");
+ while (hlen-- > (int)sizeof(struct ip)) {
+ (void)printf("%02x", *cp++);
+ }
}
(void)putchar('\n');
}
@@ -1705,7 +1595,7 @@ pr_addr(struct in_addr ina)
struct hostent *hp;
static char buf[16 + 3 + MAXHOSTNAMELEN];
- if (options & F_NUMERIC)
+ if (!(options & F_HOSTNAME))
return inet_ntoa(ina);
hp = cap_gethostbyaddr(capdns, (char *)&ina, sizeof(ina), AF_INET);
diff --git a/sbin/ping/ping6.c b/sbin/ping/ping6.c
index bd1658f9500a..356f0f72a6f8 100644
--- a/sbin/ping/ping6.c
+++ b/sbin/ping/ping6.c
@@ -65,19 +65,6 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1989, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static char sccsid[] = "@(#)ping.c 8.1 (Berkeley) 6/5/93";
-#endif /* not lint */
-#endif
-
-#include <sys/cdefs.h>
/*
* Using the InterNet Control Message Protocol (ICMP) "ECHO" facility,
* measure round-trip-delays and packet loss across network paths.
@@ -124,7 +111,6 @@ static char sccsid[] = "@(#)ping.c 8.1 (Berkeley) 6/5/93";
#include <err.h>
#include <errno.h>
#include <fcntl.h>
-#include <math.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -188,7 +174,6 @@ struct tv32 {
#define F_FQDN 0x1000
#define F_INTERFACE 0x2000
#define F_SRCADDR 0x4000
-#define F_HOSTNAME 0x10000
#define F_FQDNOLD 0x20000
#define F_NIGROUP 0x40000
#define F_SUPTYPES 0x80000
@@ -200,7 +185,6 @@ struct tv32 {
#define F_NOUSERDATA (F_NODEADDR | F_FQDN | F_FQDNOLD | F_SUPTYPES)
#define F_WAITTIME 0x2000000
#define F_DOT 0x4000000
-static u_int options;
#define IN6LEN sizeof(struct in6_addr)
#define SA6LEN sizeof(struct sockaddr_in6)
@@ -229,7 +213,6 @@ static char BBELL = '\a'; /* characters written for AUDIBLE */
static const char *DOT = ".";
static size_t DOTlen = 1;
static size_t DOTidx = 0;
-static char *hostname;
static int ident; /* process id to identify our packets */
static u_int8_t nonce[8]; /* nonce field for node information */
static int hoplimit = -1; /* hoplimit */
@@ -241,20 +224,9 @@ static cap_channel_t *capdns;
/* counters */
static long nmissedmax; /* max value of ntransmitted - nreceived - 1 */
static long npackets; /* max packets to transmit */
-static long nreceived; /* # of packets we got back */
-static long nrepeats; /* number of duplicates */
-static long ntransmitted; /* sequence # for outbound packets = #sent */
static long ntransmitfailures; /* number of transmit failures */
static int interval = 1000; /* interval between packets in ms */
static int waittime = MAXWAIT; /* timeout for each packet */
-static long nrcvtimeout = 0; /* # of packets we got back after waittime */
-
-/* timing */
-static int timing; /* flag to do timing */
-static double tmin = 999999999.0; /* minimum round trip time */
-static double tmax = 0.0; /* maximum round trip time */
-static double tsum = 0.0; /* sum of all times, for doing average */
-static double tsumsq = 0.0; /* sum of all times squared, for std. dev. */
/* for node addresses */
static u_short naflags;
@@ -264,18 +236,11 @@ static struct msghdr smsghdr;
static struct iovec smsgiov;
static char *scmsg = 0;
-static volatile sig_atomic_t seenint;
-#ifdef SIGINFO
-static volatile sig_atomic_t seeninfo;
-#endif
-
static cap_channel_t *capdns_setup(void);
static void fill(char *, char *);
static int get_hoplim(struct msghdr *);
static int get_pathmtu(struct msghdr *);
static struct in6_pktinfo *get_rcvpktinfo(struct msghdr *);
-static void onsignal(int);
-static void onint(int);
static size_t pingerlen(void);
static int pinger(void);
static const char *pr_addr(struct sockaddr *, int);
@@ -293,7 +258,6 @@ static void pr_ip6opt(void *, size_t);
static void pr_rthdr(void *, size_t);
static int pr_bitrange(u_int32_t, int, int);
static void pr_retip(struct ip6_hdr *, u_char *);
-static void summary(void);
#ifdef IPSEC
#ifdef IPSEC_POLICY_IPSEC
static int setpolicy(int, char *);
@@ -677,14 +641,15 @@ ping6(int argc, char *argv[])
error = cap_getaddrinfo(capdns, target, NULL, &hints, &res);
if (error)
- errx(1, "%s", gai_strerror(error));
+ errx(EX_NOHOST, "cannot resolve %s: %s",
+ target, gai_strerror(error));
if (res->ai_canonname)
hostname = strdup(res->ai_canonname);
else
hostname = target;
if (!res->ai_addr)
- errx(1, "cap_getaddrinfo failed");
+ errx(EX_NOHOST, "cannot resolve %s", target);
(void)memcpy(&dst, res->ai_addr, res->ai_addrlen);
@@ -735,7 +700,7 @@ ping6(int argc, char *argv[])
}
/*
- * let the kerel pass extension headers of incoming packets,
+ * let the kernel pass extension headers of incoming packets,
* for privileged socket options
*/
if ((options & F_VERBOSE) != 0) {
@@ -895,7 +860,7 @@ ping6(int argc, char *argv[])
}
#endif /*ICMP6_FILTER*/
- /* let the kerel pass extension headers of incoming packets */
+ /* let the kernel pass extension headers of incoming packets */
if ((options & F_VERBOSE) != 0) {
int opton = 1;
@@ -1142,7 +1107,7 @@ ping6(int argc, char *argv[])
if (caph_rights_limit(ssend, &rights_ssend) < 0)
err(1, "caph_rights_limit ssend setsockopt");
- printf("PING6(%lu=40+8+%lu bytes) ", (unsigned long)(40 + pingerlen()),
+ printf("PING(%lu=40+8+%lu bytes) ", (unsigned long)(40 + pingerlen()),
(unsigned long)(pingerlen() - 8));
printf("%s --> ", pr_addr((struct sockaddr *)&src, sizeof(src)));
printf("%s\n", pr_addr((struct sockaddr *)&dst, sizeof(dst)));
@@ -1163,11 +1128,9 @@ ping6(int argc, char *argv[])
if (sigaction(SIGINT, &si_sa, 0) == -1)
err(EX_OSERR, "sigaction SIGINT");
seenint = 0;
-#ifdef SIGINFO
if (sigaction(SIGINFO, &si_sa, 0) == -1)
err(EX_OSERR, "sigaction SIGINFO");
seeninfo = 0;
-#endif
if (alarmtimeout > 0) {
if (sigaction(SIGALRM, &si_sa, 0) == -1)
err(EX_OSERR, "sigaction SIGALRM");
@@ -1186,15 +1149,11 @@ ping6(int argc, char *argv[])
int n;
/* signal handling */
- if (seenint)
- onint(SIGINT);
-#ifdef SIGINFO
if (seeninfo) {
- summary();
+ pr_summary(stderr);
seeninfo = 0;
continue;
}
-#endif
FD_ZERO(&rfds);
FD_SET(srecv, &rfds);
clock_gettime(CLOCK_MONOTONIC, &now);
@@ -1258,12 +1217,12 @@ ping6(int argc, char *argv[])
if (almost_done)
break;
almost_done = 1;
- /*
- * If we're not transmitting any more packets,
- * change the timer to wait two round-trip times
- * if we've received any packets or (waittime)
- * milliseconds if we haven't.
- */
+ /*
+ * If we're not transmitting any more packets,
+ * change the timer to wait two round-trip times
+ * if we've received any packets or (waittime)
+ * milliseconds if we haven't.
+ */
intvl.tv_nsec = 0;
if (nreceived) {
intvl.tv_sec = 2 * tmax / 1000;
@@ -1272,7 +1231,7 @@ ping6(int argc, char *argv[])
} else {
intvl.tv_sec = waittime / 1000;
intvl.tv_nsec =
- waittime % 1000 * 1000000;
+ waittime % 1000 * 1000000;
}
}
clock_gettime(CLOCK_MONOTONIC, &last);
@@ -1288,7 +1247,7 @@ ping6(int argc, char *argv[])
si_sa.sa_handler = SIG_IGN;
sigaction(SIGINT, &si_sa, 0);
sigaction(SIGALRM, &si_sa, 0);
- summary();
+ pr_summary(stdout);
if(packet != NULL)
free(packet);
@@ -1301,23 +1260,6 @@ ping6(int argc, char *argv[])
exit(EX_OSERR);
}
-static void
-onsignal(int sig)
-{
-
- switch (sig) {
- case SIGINT:
- case SIGALRM:
- seenint++;
- break;
-#ifdef SIGINFO
- case SIGINFO:
- seeninfo++;
- break;
-#endif
- }
-}
-
/*
* pinger --
* Compose and transmit an ICMP ECHO REQUEST packet. The IP packet
@@ -1469,7 +1411,7 @@ pinger(void)
ntransmitfailures++;
warn("sendmsg");
}
- (void)printf("ping6: wrote %s %d chars, ret=%d\n",
+ (void)printf("ping: wrote %s %d chars, ret=%d\n",
hostname, cc, i);
}
if (!(options & F_QUIET) && options & F_DOT)
@@ -2165,7 +2107,7 @@ pr_nodeaddr(struct icmp6_nodeinfo *ni, int nilen)
/*
* In icmp-name-lookups 05 and later, TTL of each returned address
- * is contained in the resposne. We try to detect the version
+ * is contained in the response. We try to detect the version
* by the length of the data, but note that the detection algorithm
* is incomplete. We assume the latest draft by default.
*/
@@ -2305,59 +2247,6 @@ get_pathmtu(struct msghdr *mhdr)
return(0);
}
-/*
- * onint --
- * SIGINT handler.
- */
-/* ARGSUSED */
-static void
-onint(int notused __unused)
-{
- /*
- * When doing reverse DNS lookups, the seenint flag might not
- * be noticed for a while. Just exit if we get a second SIGINT.
- */
- if ((options & F_HOSTNAME) && seenint != 0)
- _exit(nreceived ? 0 : 2);
-}
-
-/*
- * summary --
- * Print out statistics.
- */
-static void
-summary(void)
-{
-
- (void)printf("\n--- %s ping6 statistics ---\n", hostname);
- (void)printf("%ld packets transmitted, ", ntransmitted);
- (void)printf("%ld packets received, ", nreceived);
- if (nrepeats)
- (void)printf("+%ld duplicates, ", nrepeats);
- if (ntransmitted) {
- if (nreceived > ntransmitted)
- (void)printf("-- somebody's duplicating packets!");
- else
- (void)printf("%.1f%% packet loss",
- ((((double)ntransmitted - nreceived) * 100.0) /
- ntransmitted));
- }
- if (nrcvtimeout)
- printf(", %ld packets out of wait time", nrcvtimeout);
- (void)putchar('\n');
- if (nreceived && timing) {
- /* Only display average to microseconds */
- double num = nreceived + nrepeats;
- double avg = tsum / num;
- double dev = sqrt(tsumsq / num - avg * avg);
- (void)printf(
- "round-trip min/avg/max/std-dev = %.3f/%.3f/%.3f/%.3f ms\n",
- tmin, avg, tmax, dev);
- (void)fflush(stdout);
- }
- (void)fflush(stdout);
-}
-
/*subject type*/
static const char *niqcode[] = {
"IPv6 address",
@@ -2640,7 +2529,7 @@ pr_addr(struct sockaddr *addr, int addrlen)
static char buf[NI_MAXHOST];
int flag = 0;
- if ((options & F_HOSTNAME) == 0)
+ if (!(options & F_HOSTNAME))
flag |= NI_NUMERICHOST;
if (cap_getnameinfo(capdns, addr, addrlen, buf, sizeof(buf), NULL, 0,
diff --git a/sbin/ping/tests/Makefile b/sbin/ping/tests/Makefile
index 3bdf53c15a7c..0520b1d634cf 100644
--- a/sbin/ping/tests/Makefile
+++ b/sbin/ping/tests/Makefile
@@ -1,4 +1,3 @@
-
ATF_TESTS_C+= in_cksum_test
SRCS.in_cksum_test= in_cksum_test.c ../utils.c
diff --git a/sbin/ping/tests/Makefile.depend b/sbin/ping/tests/Makefile.depend
new file mode 100644
index 000000000000..b372e6d58e9f
--- /dev/null
+++ b/sbin/ping/tests/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ lib/${CSU_DIR} \
+ lib/atf/libatf-c \
+ lib/libc \
+ lib/libcompiler_rt \
+ sbin/ping \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/sbin/ping/tests/in_cksum_test.c b/sbin/ping/tests/in_cksum_test.c
index fd51a83b1f4a..ffdf8b4c63c5 100644
--- a/sbin/ping/tests/in_cksum_test.c
+++ b/sbin/ping/tests/in_cksum_test.c
@@ -26,7 +26,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
#include <sys/param.h>
#include <atf-c.h>
diff --git a/sbin/ping/tests/ping_6_c1_s8_t1.out b/sbin/ping/tests/ping_6_c1_s8_t1.out
index 81c56e6cf586..0d207e74bc3e 100644
--- a/sbin/ping/tests/ping_6_c1_s8_t1.out
+++ b/sbin/ping/tests/ping_6_c1_s8_t1.out
@@ -1,6 +1,6 @@
-PING6(56=40+8+8 bytes) ::1 --> ::1
+PING(56=40+8+8 bytes) ::1 --> ::1
16 bytes from ::1, icmp_seq=0 hlim= time= ms
---- localhost ping6 statistics ---
+--- localhost ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
-round-trip min/avg/max/std-dev = /// ms
+round-trip min/avg/max/stddev = /// ms
diff --git a/sbin/ping/tests/ping_c1_s8_t1_S1.out b/sbin/ping/tests/ping_c1_s8_t1_S1.out
index 81c56e6cf586..0d207e74bc3e 100644
--- a/sbin/ping/tests/ping_c1_s8_t1_S1.out
+++ b/sbin/ping/tests/ping_c1_s8_t1_S1.out
@@ -1,6 +1,6 @@
-PING6(56=40+8+8 bytes) ::1 --> ::1
+PING(56=40+8+8 bytes) ::1 --> ::1
16 bytes from ::1, icmp_seq=0 hlim= time= ms
---- localhost ping6 statistics ---
+--- localhost ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
-round-trip min/avg/max/std-dev = /// ms
+round-trip min/avg/max/stddev = /// ms
diff --git a/sbin/ping/tests/ping_test.sh b/sbin/ping/tests/ping_test.sh
index 4a2dda0ebcce..5a12ace104d7 100644
--- a/sbin/ping/tests/ping_test.sh
+++ b/sbin/ping/tests/ping_test.sh
@@ -106,6 +106,7 @@ ping6_c1_s8_t1_body()
check_ping_statistics std.out $(atf_get_srcdir)/ping_6_c1_s8_t1.out
}
+atf_test_case ping_c1t6
ping_c1t6_head()
{
atf_set "descr" "-t6 is not interpreted as -t -6 by ping"
@@ -116,6 +117,7 @@ ping_c1t6_body()
atf_check -s exit:0 -o ignore -e empty ping -c1 -t6 127.0.0.1
}
+atf_test_case ping_c1t4
ping6_c1t4_head()
{
atf_set "descr" "-t4 is not interpreted as -t -4 by ping6"
@@ -126,6 +128,7 @@ ping6_c1t4_body()
atf_check -s exit:0 -o ignore -e empty ping6 -c1 -t4 ::1
}
+atf_test_case ping_46
ping_46_head()
{
atf_set "descr" "-4 and -6 cannot be used simultaneously"
@@ -135,21 +138,69 @@ ping_46_body()
require_ipv4
require_ipv6
atf_check -s exit:1 \
- -e match:"-4 and -6 cannot be used simultaneously" \
+ -e match:"illegal option -- 6" \
ping -4 -6 localhost
}
-ping6_46_head()
+atf_test_case ping_64
+ping_64_head()
{
atf_set "descr" "-4 and -6 cannot be used simultaneously"
}
-ping6_46_body()
+ping_64_body()
{
require_ipv4
require_ipv6
atf_check -s exit:1 \
- -e match:"-4 and -6 cannot be used simultaneously" \
- ping6 -4 -6 localhost
+ -e match:"illegal option -- 4" \
+ ping -6 -4 localhost
+}
+
+atf_test_case ping6_4
+ping6_4_head()
+{
+ atf_set "descr" "ping6 does not accept -4"
+}
+ping6_4_body()
+{
+ require_ipv4
+ require_ipv6
+ atf_check -s exit:1 \
+ -e match:"illegal option -- 4" \
+ ping6 -4 localhost
+}
+
+atf_test_case ping_nohost
+ping_nohost_head()
+{
+ atf_set "descr" "ping a nonexistent host"
+}
+ping_nohost_body()
+{
+ atf_check -s exit:68 -e match:"cannot resolve" \
+ ping nonexistent.in-addr.arpa.
+}
+
+atf_test_case ping4_nohost
+ping4_nohost_head()
+{
+ atf_set "descr" "ping -4 a nonexistent host"
+}
+ping4_nohost_body()
+{
+ atf_check -s exit:68 -e match:"cannot resolve" \
+ ping -4 nonexistent.in-addr.arpa.
+}
+
+atf_test_case ping6_nohost
+ping6_nohost_head()
+{
+ atf_set "descr" "ping -6 a nonexistent host"
+}
+ping6_nohost_body()
+{
+ atf_check -s exit:68 -e match:"cannot resolve" \
+ ping -6 nonexistent.in-addr.arpa.
}
atf_test_case "inject_opts" "cleanup"
@@ -212,7 +263,11 @@ atf_init_test_cases()
atf_add_test_case ping_c1t6
atf_add_test_case ping6_c1t4
atf_add_test_case ping_46
- atf_add_test_case ping6_46
+ atf_add_test_case ping_64
+ atf_add_test_case ping6_4
+ atf_add_test_case ping_nohost
+ atf_add_test_case ping4_nohost
+ atf_add_test_case ping6_nohost
atf_add_test_case inject_opts
atf_add_test_case inject_pip
atf_add_test_case inject_reply
diff --git a/sbin/ping/tests/test_ping.py b/sbin/ping/tests/test_ping.py
index 26a69b62f8fb..3f9a3aecf924 100644
--- a/sbin/ping/tests/test_ping.py
+++ b/sbin/ping/tests/test_ping.py
@@ -51,7 +51,7 @@ def build_response_packet(echo, ip, icmp, oip_ihl, special):
# Build a package with a timestamp of INT_MAX
# (time-warped package)
payload_no_timestamp = sc.bytes_hex(load)[16:]
- load = (b"\xff" * 8) + sc.hex_bytes(payload_no_timestamp)
+ load = b"\x7f" + (b"\xff" * 7) + sc.hex_bytes(payload_no_timestamp)
if special == "wrong":
# Build a package with a wrong last byte
payload_no_last_byte = sc.bytes_hex(load)[:-2]
@@ -63,14 +63,14 @@ def build_response_packet(echo, ip, icmp, oip_ihl, special):
if icmp.type in icmp_id_seq_types:
pkt = ip / icmp / load
else:
- ip.options = ""
+ del ip.options
pkt = ip / icmp / oip / oicmp / load
return pkt
def generate_ip_options(opts):
if not opts:
- return ""
+ return []
routers = [
"192.0.2.10",
@@ -85,11 +85,11 @@ def generate_ip_options(opts):
]
routers_zero = [0, 0, 0, 0, 0, 0, 0, 0, 0]
if opts == "EOL":
- options = sc.IPOption(b"\x00")
+ options = sc.IPOption_EOL()
elif opts == "NOP":
- options = sc.IPOption(b"\x01")
+ options = sc.IPOption_NOP()
elif opts == "NOP-40":
- options = sc.IPOption(b"\x01" * 40)
+ options = sc.IPOption_NOP() * 40
elif opts == "RR":
ToolsHelper.set_sysctl("net.inet.ip.process_options", 0)
options = sc.IPOption_RR(pointer=40, routers=routers)
@@ -113,12 +113,12 @@ def generate_ip_options(opts):
options = sc.IPOption_SSRR(length=3, routers=routers_zero)
elif opts == "unk":
ToolsHelper.set_sysctl("net.inet.ip.process_options", 0)
- options = sc.IPOption(b"\x9f")
+ options = b"\x9f"
elif opts == "unk-40":
ToolsHelper.set_sysctl("net.inet.ip.process_options", 0)
- options = sc.IPOption(b"\x9f" * 40)
+ options = b"\x9f" * 40
else:
- options = ""
+ options = []
return options
@@ -134,7 +134,7 @@ def pinger(
icmp_code: sc.scapy.fields.MultiEnumField,
# IP arguments
ihl: Optional[sc.scapy.fields.BitField] = None,
- flags: Optional[sc.scapy.fields.FlagsField] = None,
+ flags: Optional[sc.scapy.fields.FlagsField] = 0,
opts: Optional[str] = None,
oip_ihl: Optional[sc.scapy.fields.BitField] = None,
special: Optional[str] = None,
@@ -169,7 +169,7 @@ def pinger(
:keyword ihl: Internet Header Length, defaults to None
:type ihl: class:`scapy.fields.BitField`, optional
- :keyword flags: IP flags - one of `DF`, `MF` or `evil`, defaults to None
+ :keyword flags: IP flags - one of `DF`, `MF` or `evil`, defaults to 0
:type flags: class:`scapy.fields.FlagsField`, optional
:keyword opts: Include IP options - one of `EOL`, `NOP`, `NOP-40`, `unk`,
`unk-40`, `RR`, `RR-same`, `RR-trunc`, `LSRR`, `LSRR-trunc`, `SSRR` or
@@ -270,13 +270,15 @@ def pinger(
def redact(output):
"""Redact some elements of ping's output"""
pattern_replacements = [
- ("localhost \([0-9]{1,3}(\.[0-9]{1,3}){3}\)", "localhost"),
- ("from [0-9]{1,3}(\.[0-9]{1,3}){3}", "from"),
+ (r"localhost \([0-9]{1,3}(\.[0-9]{1,3}){3}\)", "localhost"),
+ (r"from [0-9]{1,3}(\.[0-9]{1,3}){3}", "from"),
("hlim=[0-9]*", "hlim="),
("ttl=[0-9]*", "ttl="),
("time=[0-9.-]*", "time="),
- ("\(-[0-9\.]+[0-9]+ ms\)", "(- ms)"),
- ("[0-9\.]+/[0-9.]+", "/"),
+ ("cp: .*", "cp: xx xx xx xx xx xx xx xx"),
+ ("dp: .*", "dp: xx xx xx xx xx xx xx xx"),
+ (r"\(-[0-9\.]+[0-9]+ ms\)", "(- ms)"),
+ (r"[0-9\.]+/[0-9.]+", "/"),
]
for pattern, repl in pattern_replacements:
output = re.sub(pattern, repl, output)
@@ -311,12 +313,12 @@ round-trip min/avg/max/stddev = /// ms
"args": "ping -6 -c1 -s8 -t1 localhost",
"returncode": 0,
"stdout": """\
-PING6(56=40+8+8 bytes) ::1 --> ::1
+PING(56=40+8+8 bytes) ::1 --> ::1
16 bytes from ::1, icmp_seq=0 hlim= time= ms
---- localhost ping6 statistics ---
+--- localhost ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
-round-trip min/avg/max/std-dev = /// ms
+round-trip min/avg/max/stddev = /// ms
""",
"stderr": "",
},
@@ -357,12 +359,12 @@ PING 192.0.2.2 (192.0.2.2): 56 data bytes
"args": "ping -A -c1 2001:db8::1",
"returncode": 0,
"stdout": """\
-PING6(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::1
+PING(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::1
16 bytes from 2001:db8::1, icmp_seq=0 hlim= time= ms
---- 2001:db8::1 ping6 statistics ---
+--- 2001:db8::1 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
-round-trip min/avg/max/std-dev = /// ms
+round-trip min/avg/max/stddev = /// ms
""",
"stderr": "",
},
@@ -373,9 +375,9 @@ round-trip min/avg/max/std-dev = /// ms
"args": "ping -A -c1 2001:db8::2",
"returncode": 2,
"stdout": """\
-PING6(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::2
+PING(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::2
---- 2001:db8::2 ping6 statistics ---
+--- 2001:db8::2 ping statistics ---
1 packets transmitted, 0 packets received, 100.0% packet loss
""",
"stderr": "",
@@ -419,14 +421,14 @@ round-trip min/avg/max/stddev = /// ms
"args": "ping -A -c3 2001:db8::1",
"returncode": 0,
"stdout": """\
-PING6(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::1
+PING(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::1
16 bytes from 2001:db8::1, icmp_seq=0 hlim= time= ms
16 bytes from 2001:db8::1, icmp_seq=1 hlim= time= ms
16 bytes from 2001:db8::1, icmp_seq=2 hlim= time= ms
---- 2001:db8::1 ping6 statistics ---
+--- 2001:db8::1 ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
-round-trip min/avg/max/std-dev = /// ms
+round-trip min/avg/max/stddev = /// ms
""",
"stderr": "",
},
@@ -437,9 +439,9 @@ round-trip min/avg/max/std-dev = /// ms
"args": "ping -A -c3 2001:db8::2",
"returncode": 2,
"stdout": """\
-\x07\x07PING6(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::2
+\x07\x07PING(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::2
---- 2001:db8::2 ping6 statistics ---
+--- 2001:db8::2 ping statistics ---
3 packets transmitted, 0 packets received, 100.0% packet loss
""",
"stderr": "",
@@ -481,12 +483,12 @@ PING 192.0.2.2 (192.0.2.2): 56 data bytes
"args": "ping -c1 2001:db8::1",
"returncode": 0,
"stdout": """\
-PING6(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::1
+PING(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::1
16 bytes from 2001:db8::1, icmp_seq=0 hlim= time= ms
---- 2001:db8::1 ping6 statistics ---
+--- 2001:db8::1 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
-round-trip min/avg/max/std-dev = /// ms
+round-trip min/avg/max/stddev = /// ms
""",
"stderr": "",
},
@@ -497,9 +499,9 @@ round-trip min/avg/max/std-dev = /// ms
"args": "ping -c1 2001:db8::2",
"returncode": 2,
"stdout": """\
-PING6(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::2
+PING(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::2
---- 2001:db8::2 ping6 statistics ---
+--- 2001:db8::2 ping statistics ---
1 packets transmitted, 0 packets received, 100.0% packet loss
""",
"stderr": "",
@@ -527,12 +529,12 @@ round-trip min/avg/max/stddev = /// ms
"args": "ping -c1 -S::1 -s8 -t1 localhost",
"returncode": 0,
"stdout": """\
-PING6(56=40+8+8 bytes) ::1 --> ::1
+PING(56=40+8+8 bytes) ::1 --> ::1
16 bytes from ::1, icmp_seq=0 hlim= time= ms
---- localhost ping6 statistics ---
+--- localhost ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
-round-trip min/avg/max/std-dev = /// ms
+round-trip min/avg/max/stddev = /// ms
""",
"stderr": "",
},
@@ -575,14 +577,14 @@ PING 192.0.2.2 (192.0.2.2): 56 data bytes
"args": "ping -c3 2001:db8::1",
"returncode": 0,
"stdout": """\
-PING6(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::1
+PING(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::1
16 bytes from 2001:db8::1, icmp_seq=0 hlim= time= ms
16 bytes from 2001:db8::1, icmp_seq=1 hlim= time= ms
16 bytes from 2001:db8::1, icmp_seq=2 hlim= time= ms
---- 2001:db8::1 ping6 statistics ---
+--- 2001:db8::1 ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
-round-trip min/avg/max/std-dev = /// ms
+round-trip min/avg/max/stddev = /// ms
""",
"stderr": "",
},
@@ -593,9 +595,9 @@ round-trip min/avg/max/std-dev = /// ms
"args": "ping -c3 2001:db8::2",
"returncode": 2,
"stdout": """\
-PING6(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::2
+PING(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::2
---- 2001:db8::2 ping6 statistics ---
+--- 2001:db8::2 ping statistics ---
3 packets transmitted, 0 packets received, 100.0% packet loss
""",
"stderr": "",
@@ -636,11 +638,11 @@ PING 192.0.2.2 (192.0.2.2): 56 data bytes
"args": "ping -q -c1 2001:db8::1",
"returncode": 0,
"stdout": """\
-PING6(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::1
+PING(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::1
---- 2001:db8::1 ping6 statistics ---
+--- 2001:db8::1 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
-round-trip min/avg/max/std-dev = /// ms
+round-trip min/avg/max/stddev = /// ms
""",
"stderr": "",
},
@@ -651,9 +653,9 @@ round-trip min/avg/max/std-dev = /// ms
"args": "ping -q -c1 2001:db8::2",
"returncode": 2,
"stdout": """\
-PING6(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::2
+PING(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::2
---- 2001:db8::2 ping6 statistics ---
+--- 2001:db8::2 ping statistics ---
1 packets transmitted, 0 packets received, 100.0% packet loss
""",
"stderr": "",
@@ -694,11 +696,11 @@ PING 192.0.2.2 (192.0.2.2): 56 data bytes
"args": "ping -q -c3 2001:db8::1",
"returncode": 0,
"stdout": """\
-PING6(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::1
+PING(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::1
---- 2001:db8::1 ping6 statistics ---
+--- 2001:db8::1 ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
-round-trip min/avg/max/std-dev = /// ms
+round-trip min/avg/max/stddev = /// ms
""",
"stderr": "",
},
@@ -709,9 +711,9 @@ round-trip min/avg/max/std-dev = /// ms
"args": "ping -q -c3 2001:db8::2",
"returncode": 2,
"stdout": """\
-PING6(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::2
+PING(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::2
---- 2001:db8::2 ping6 statistics ---
+--- 2001:db8::2 ping statistics ---
3 packets transmitted, 0 packets received, 100.0% packet loss
""",
"stderr": "",
@@ -721,6 +723,8 @@ PING6(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::2
]
@pytest.mark.parametrize("expected", testdata)
+ @pytest.mark.require_user("root")
+ @pytest.mark.require_user("unprivileged")
def test_ping(self, expected):
"""Test ping"""
ping = subprocess.run(
@@ -749,6 +753,8 @@ PING6(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::2
]
@pytest.mark.parametrize("expected", ping46_testdata)
+ @pytest.mark.require_user("root")
+ @pytest.mark.require_user("unprivileged")
def test_ping_46(self, expected):
"""Test ping -4/ping -6"""
for version in [4, 6]:
@@ -859,7 +865,6 @@ PING 192.0.2.2 (192.0.2.2): 56 data bytes
64 bytes from: icmp_seq=0 ttl= time= ms
LSRR: (truncated route)
-
--- 192.0.2.2 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = /// ms
@@ -916,7 +921,6 @@ PING 192.0.2.2 (192.0.2.2): 56 data bytes
64 bytes from: icmp_seq=0 ttl= time= ms
SSRR: (truncated route)
-
--- 192.0.2.2 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = /// ms
@@ -1034,6 +1038,118 @@ round-trip min/avg/max/stddev = /// ms
{
"src": "192.0.2.1",
"dst": "192.0.2.2",
+ "icmp_type": 3,
+ "icmp_code": 1,
+ "ihl": 0x4,
+ },
+ {
+ "returncode": 2,
+ "stdout": """\
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 0 packets received, 100.0% packet loss
+""",
+ "stderr": "", # "IHL too short" message not shown
+ "redacted": False,
+ },
+ id="_IHL_too_short",
+ ),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 3,
+ "icmp_code": 1,
+ "special": "no-payload",
+ },
+ {
+ "returncode": 2,
+ "stdout": """\
+PATTERN: 0x01
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 0 packets received, 100.0% packet loss
+""",
+ "stderr": """\
+ping: quoted data too short (28 bytes) from 192.0.2.2
+""",
+ "redacted": False,
+ },
+ id="_quoted_data_too_short",
+ ),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 3,
+ "icmp_code": 1,
+ "oip_ihl": 0x4,
+ },
+ {
+ "returncode": 2,
+ "stdout": """\
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 0 packets received, 100.0% packet loss
+""",
+ "stderr": "", # "inner IHL too short" message not shown
+ "redacted": False,
+ },
+ id="_inner_IHL_too_short",
+ ),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 3,
+ "icmp_code": 1,
+ "oip_ihl": 0xF,
+ },
+ {
+ "returncode": 2,
+ "stdout": """\
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 0 packets received, 100.0% packet loss
+""",
+ "stderr": """\
+ping: inner packet too short (84 bytes) from 192.0.2.2
+""",
+ "redacted": False,
+ },
+ id="_inner_packet_too_short",
+ ),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 3,
+ "icmp_code": 1,
+ "oip_ihl": 0xF,
+ "special": "no-payload",
+ },
+ {
+ "returncode": 2,
+ "stdout": """\
+PATTERN: 0x01
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 0 packets received, 100.0% packet loss
+""",
+ "stderr": "",
+ "redacted": False,
+ },
+ id="_max_inner_packet_ihl_without_payload",
+ ),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
"icmp_type": 0,
"icmp_code": 0,
"opts": "NOP-40",
@@ -1132,8 +1248,8 @@ round-trip min/avg/max/stddev = /// ms
"stdout": """\
PING 192.0.2.2 (192.0.2.2): 56 data bytes
132 bytes from 192.0.2.2: Destination Host Unreachable
-Vr HL TOS Len ID Flg off TTL Pro cks Src Dst
- 4 f 00 007c 0001 0 0000 40 01 d868 192.0.2.1 192.0.2.2 01010101010101010101010101010101010101010101010101010101010101010101010101010101
+Vr HL TOS Len ID Flg off TTL Pro cks Src Dst Opts
+ 4 f 00 007c 0001 0 0000 40 01 d868 192.0.2.1 192.0.2.2 01010101010101010101010101010101010101010101010101010101010101010101010101010101
--- 192.0.2.2 ping statistics ---
@@ -1157,8 +1273,8 @@ Vr HL TOS Len ID Flg off TTL Pro cks Src Dst
"stdout": """\
PING 192.0.2.2 (192.0.2.2): 56 data bytes
92 bytes from 192.0.2.2: Destination Host Unreachable
-Vr HL TOS Len ID Flg off TTL Pro cks Src Dst
- 4 5 00 0054 0001 2 0000 40 01 b6a4 192.0.2.1 192.0.2.2
+Vr HL TOS Len ID Flg off TTL Pro cks Src Dst
+ 4 5 00 0054 0001 2 0000 40 01 b6a4 192.0.2.1 192.0.2.2
--- 192.0.2.2 ping statistics ---
@@ -1230,8 +1346,8 @@ ping: quoted data too short (28 bytes) from 192.0.2.2
"stdout": """\
PING 192.0.2.2 (192.0.2.2): 56 data bytes
92 bytes from 192.0.2.2: Destination Host Unreachable
-Vr HL TOS Len ID Flg off TTL Pro cks Src Dst
- 4 5 00 0054 0001 0 0000 40 01 f6a4 192.0.2.1 192.0.2.2
+Vr HL TOS Len ID Flg off TTL Pro cks Src Dst
+ 4 5 00 0054 0001 0 0000 40 01 f6a4 192.0.2.1 192.0.2.2
--- 192.0.2.2 ping statistics ---
@@ -1291,6 +1407,39 @@ ping: time of day goes back (- ms), clamping time to 0
},
id="_0_0_special_warp",
),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 0,
+ "icmp_code": 0,
+ "special": "wrong",
+ },
+ {
+ "returncode": 0,
+ "stdout": """\
+PATTERN: 0x01
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+64 bytes from: icmp_seq=0 ttl= time= ms
+wrong data byte #55 should be 0x1 but was 0x0
+cp: xx xx xx xx xx xx xx xx
+ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0
+dp: xx xx xx xx xx xx xx xx
+ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 1 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ "redacted": True,
+ },
+ id="_0_0_special_wrong",
+ ),
]
@pytest.mark.parametrize("pinger_kargs, expected", pinger_testdata)
diff --git a/sbin/ping/utils.c b/sbin/ping/utils.c
index 920102a68961..e723f690be2b 100644
--- a/sbin/ping/utils.c
+++ b/sbin/ping/utils.c
@@ -32,18 +32,6 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1989, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static char sccsid[] = "@(#)ping.c 8.1 (Berkeley) 6/5/93";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
#include <string.h>
#include "utils.h"