diff options
Diffstat (limited to 'sbin/ping')
-rw-r--r-- | sbin/ping/Makefile | 5 | ||||
-rw-r--r-- | sbin/ping/main.c | 215 | ||||
-rw-r--r-- | sbin/ping/main.h | 25 | ||||
-rw-r--r-- | sbin/ping/ping.8 | 7 | ||||
-rw-r--r-- | sbin/ping/ping.c | 236 | ||||
-rw-r--r-- | sbin/ping/ping6.c | 147 | ||||
-rw-r--r-- | sbin/ping/tests/Makefile | 1 | ||||
-rw-r--r-- | sbin/ping/tests/Makefile.depend | 15 | ||||
-rw-r--r-- | sbin/ping/tests/in_cksum_test.c | 1 | ||||
-rw-r--r-- | sbin/ping/tests/ping_6_c1_s8_t1.out | 6 | ||||
-rw-r--r-- | sbin/ping/tests/ping_c1_s8_t1_S1.out | 6 | ||||
-rw-r--r-- | sbin/ping/tests/ping_test.sh | 67 | ||||
-rw-r--r-- | sbin/ping/tests/test_ping.py | 267 | ||||
-rw-r--r-- | sbin/ping/utils.c | 12 |
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" |