svn commit: r352357 - stable/12/sbin/ping

Alan Somers asomers at FreeBSD.org
Sun Sep 15 16:53:04 UTC 2019


Author: asomers
Date: Sun Sep 15 16:53:02 2019
New Revision: 352357
URL: https://svnweb.freebsd.org/changeset/base/352357

Log:
  MFC r350994, r350998, r351030, r351033, r351171, r351223, r351226, r351424
  
  r350994:
  ping: fix data type of a variable for a packet sequence number
  
  Submitted by:	Ján Sučan <sucanjan at gmail.com>
  Sponsored by:	Google, inc. (Google Summer of Code 2019)
  Differential Revision:	https://reviews.freebsd.org/D21244
  
  r350998:
  ping: use the monotonic clock to measure durations
  
  Submitted by:	Ján Sučan <sucanjan at gmail.com>
  Sponsored by:	Google, inc. (Google Summer of Code 2019)
  Differential Revision:	https://reviews.freebsd.org/D21245
  
  r351030:
  ping: fix triptime calculation after r350998
  
  That revision changed the internal clock to the monotonic, but neglected to
  change the datagram's timestamp source.
  
  Reported by:	Oliver Hartmann, Michael Butler
  Reviewed by:	Ján Sučan <sucanjan at gmail.com>, allanjude
  MFC-With:	r350998
  Differential Revision:	https://reviews.freebsd.org/D21258
  
  r351033:
  ping: Make in_cksum() operate on u_char buffer
  
  This fixes -Wcast-align errors for in_cksum() calls when compiled with
  WARNS=6.
  
  Submitted by:	Ján Sučan <sucanjan at gmail.com>
  Sponsored by:	Google, inc. (Google Summer of Code 2019)
  Differential Revision:	https://reviews.freebsd.org/D21261
  
  r351171:
  ping: Move in_cksum() to a separate source file
  
  This is a preparation step for adding ATF tests of in_cksum(), which has been
  modified to operate on unaligned data. ping.o cannot be linked to the test
  executable because both of them contain 'main' symbol.
  
  Submitted by:	Ján Sučan <sucanjan at gmail.com>
  Sponsored by:	Google, inc. (Google Summer of Code 2019)
  Differential Revision:	https://reviews.freebsd.org/D21288
  
  r351223:
  ping: fix -Wformat-truncating warning with GCC
  
  Increase buffer size for the string representation of n_time
  
  ICMP timestamp is a 32-bit number. In pr_ntime(), number of minutes
  and seconds is always 2 characters wide. Max. number of hours is 4
  characters wide. The buffer size should be at least:
  
  4 + 2 + 2 + 1 (':') + 1 (':') + 1 ('\0') = 11
  
  Submitted by:	Ján Sučan <sucanjan at gmail.com>
  Sponsored by:	Google, inc. (Google Summer of Code 2019)
  Differential Revision:	https://reviews.freebsd.org/D21325
  
  r351226:
  Fix uninitialized variable warnings when MK_CASPER=no
  
  Submitted by:	Ján Sučan <sucanjan at gmail.com>
  Sponsored by:	Google, inc. (Google Summer of Code 2019)
  Differential Revision:	https://reviews.freebsd.org/D21322
  
  r351424:
  ping: fix include guard symbol name to reflect the header file name
  
  Submitted by:	Ján Sučan <sucanjan at gmail.com>
  MFC-With:	351171
  Sponsored by:	Google LLC (Google Summer of Code 2019)
  Differential Revision:	https://reviews.freebsd.org/D21374

Added:
  stable/12/sbin/ping/utils.c
     - copied unchanged from r351171, head/sbin/ping/utils.c
  stable/12/sbin/ping/utils.h
     - copied, changed from r351171, head/sbin/ping/utils.h
Modified:
  stable/12/sbin/ping/Makefile
  stable/12/sbin/ping/ping.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sbin/ping/Makefile
==============================================================================
--- stable/12/sbin/ping/Makefile	Sun Sep 15 14:37:50 2019	(r352356)
+++ stable/12/sbin/ping/Makefile	Sun Sep 15 16:53:02 2019	(r352357)
@@ -5,6 +5,7 @@
 
 PACKAGE=runtime
 PROG=	ping
+SRCS=	ping.c utils.c
 MAN=	ping.8
 BINOWN=	root
 BINMODE=4555

Modified: stable/12/sbin/ping/ping.c
==============================================================================
--- stable/12/sbin/ping/ping.c	Sun Sep 15 14:37:50 2019	(r352356)
+++ stable/12/sbin/ping/ping.c	Sun Sep 15 16:53:02 2019	(r352357)
@@ -95,8 +95,11 @@ __FBSDID("$FreeBSD$");
 #include <stdlib.h>
 #include <string.h>
 #include <sysexits.h>
+#include <time.h>
 #include <unistd.h>
 
+#include "utils.h"
+
 #define	INADDR_LEN	((int)sizeof(in_addr_t))
 #define	TIMEVAL_LEN	((int)sizeof(struct tv32))
 #define	MASK_LEN	(ICMP_MASKLEN - ICMP_MINLEN)
@@ -118,7 +121,7 @@ __FBSDID("$FreeBSD$");
 
 struct tv32 {
 	int32_t tv32_sec;
-	int32_t tv32_usec;
+	int32_t tv32_nsec;
 };
 
 /* various options */
@@ -207,7 +210,6 @@ static volatile sig_atomic_t siginfo_p;
 static cap_channel_t *capdns;
 
 static void fill(char *, char *);
-static u_short in_cksum(u_short *, int);
 static cap_channel_t *capdns_setup(void);
 static void check_status(void);
 static void finish(void) __dead2;
@@ -216,11 +218,10 @@ static char *pr_addr(struct in_addr);
 static char *pr_ntime(n_time);
 static void pr_icmph(struct icmp *);
 static void pr_iph(struct ip *);
-static void pr_pack(char *, int, struct sockaddr_in *, struct timeval *);
+static void pr_pack(char *, int, struct sockaddr_in *, struct timespec *);
 static void pr_retip(struct ip *);
 static void status(int);
 static void stopit(int);
-static void tvsub(struct timeval *, const struct timeval *);
 static void usage(void) __dead2;
 
 int
@@ -228,7 +229,7 @@ main(int argc, char *const *argv)
 {
 	struct sockaddr_in from, sock_in;
 	struct in_addr ifaddr;
-	struct timeval last, intvl;
+	struct timespec last, intvl;
 	struct iovec iov;
 	struct ip *ip;
 	struct msghdr msg;
@@ -246,7 +247,7 @@ main(int argc, char *const *argv)
 	long ltmp;
 	int almost_done, ch, df, hold, i, icmp_len, mib[4], preload;
 	int ssend_errno, srecv_errno, tos, ttl;
-	char ctrl[CMSG_SPACE(sizeof(struct timeval))];
+	char ctrl[CMSG_SPACE(sizeof(struct timespec))];
 	char hnamebuf[MAXHOSTNAMELEN], snamebuf[MAXHOSTNAMELEN];
 #ifdef IP_OPTIONS
 	char rspace[MAX_IPOPTLEN];	/* record route space */
@@ -616,6 +617,7 @@ main(int argc, char *const *argv)
 	}
 
 	/* From now on we will use only reverse DNS lookups. */
+#ifdef WITH_CASPER
 	if (capdns != NULL) {
 		const char *types[1];
 
@@ -623,7 +625,7 @@ main(int argc, char *const *argv)
 		if (cap_dns_type_limit(capdns, types, 1) < 0)
 			err(1, "unable to limit access to system.dns service");
 	}
-
+#endif
 	if (connect(ssend, (struct sockaddr *)&whereto, sizeof(whereto)) != 0)
 		err(1, "connect");
 
@@ -774,9 +776,15 @@ main(int argc, char *const *argv)
 		}
 	}
 #ifdef SO_TIMESTAMP
-	{ int on = 1;
-	if (setsockopt(srecv, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)) < 0)
-		err(EX_OSERR, "setsockopt SO_TIMESTAMP");
+	{
+		int on = 1;
+		int ts_clock = SO_TS_MONOTONIC;
+		if (setsockopt(srecv, SOL_SOCKET, SO_TIMESTAMP, &on,
+		    sizeof(on)) < 0)
+			err(EX_OSERR, "setsockopt SO_TIMESTAMP");
+		if (setsockopt(srecv, SOL_SOCKET, SO_TS_CLOCK, &ts_clock,
+		    sizeof(ts_clock)) < 0)
+			err(EX_OSERR, "setsockopt SO_TS_CLOCK");
 	}
 #endif
 	if (sweepmax) {
@@ -885,19 +893,19 @@ main(int argc, char *const *argv)
 		while (preload--)	/* fire off them quickies */
 			pinger();
 	}
-	(void)gettimeofday(&last, NULL);
+	(void)clock_gettime(CLOCK_MONOTONIC, &last);
 
 	if (options & F_FLOOD) {
 		intvl.tv_sec = 0;
-		intvl.tv_usec = 10000;
+		intvl.tv_nsec = 10000000;
 	} else {
 		intvl.tv_sec = interval / 1000;
-		intvl.tv_usec = interval % 1000 * 1000;
+		intvl.tv_nsec = interval % 1000 * 1000000;
 	}
 
 	almost_done = 0;
 	while (!finish_up) {
-		struct timeval now, timeout;
+		struct timespec now, timeout;
 		fd_set rfds;
 		int cc, n;
 
@@ -906,24 +914,16 @@ main(int argc, char *const *argv)
 			errx(EX_OSERR, "descriptor too large");
 		FD_ZERO(&rfds);
 		FD_SET(srecv, &rfds);
-		(void)gettimeofday(&now, NULL);
-		timeout.tv_sec = last.tv_sec + intvl.tv_sec - now.tv_sec;
-		timeout.tv_usec = last.tv_usec + intvl.tv_usec - now.tv_usec;
-		while (timeout.tv_usec < 0) {
-			timeout.tv_usec += 1000000;
-			timeout.tv_sec--;
-		}
-		while (timeout.tv_usec >= 1000000) {
-			timeout.tv_usec -= 1000000;
-			timeout.tv_sec++;
-		}
+		(void)clock_gettime(CLOCK_MONOTONIC, &now);
+		timespecadd(&last, &intvl, &timeout);
+		timespecsub(&timeout, &now, &timeout);
 		if (timeout.tv_sec < 0)
-			timerclear(&timeout);
-		n = select(srecv + 1, &rfds, NULL, NULL, &timeout);
+			timespecclear(&timeout);
+		n = pselect(srecv + 1, &rfds, NULL, NULL, &timeout, NULL);
 		if (n < 0)
 			continue;	/* Must be EINTR. */
 		if (n == 1) {
-			struct timeval *tv = NULL;
+			struct timespec *tv = NULL;
 #ifdef SO_TIMESTAMP
 			struct cmsghdr *cmsg = (struct cmsghdr *)&ctrl;
 
@@ -946,7 +946,7 @@ main(int argc, char *const *argv)
 			}
 #endif
 			if (tv == NULL) {
-				(void)gettimeofday(&now, NULL);
+				(void)clock_gettime(CLOCK_MONOTONIC, &now);
 				tv = &now;
 			}
 			pr_pack((char *)packet, cc, &from, tv);
@@ -970,17 +970,17 @@ main(int argc, char *const *argv)
 				if (almost_done)
 					break;
 				almost_done = 1;
-				intvl.tv_usec = 0;
+				intvl.tv_nsec = 0;
 				if (nreceived) {
 					intvl.tv_sec = 2 * tmax / 1000;
 					if (!intvl.tv_sec)
 						intvl.tv_sec = 1;
 				} else {
 					intvl.tv_sec = waittime / 1000;
-					intvl.tv_usec = waittime % 1000 * 1000;
+					intvl.tv_nsec = waittime % 1000 * 1000000;
 				}
 			}
-			(void)gettimeofday(&last, NULL);
+			(void)clock_gettime(CLOCK_MONOTONIC, &last);
 			if (ntransmitted - nreceived - 1 > nmissedmax) {
 				nmissedmax = ntransmitted - nreceived - 1;
 				if (options & F_MISSED)
@@ -1017,13 +1017,13 @@ stopit(int sig __unused)
  *	Compose and transmit an ICMP ECHO REQUEST packet.  The IP packet
  * will be added on by the kernel.  The ID field is our UNIX process ID,
  * and the sequence number is an ascending integer.  The first TIMEVAL_LEN
- * bytes of the data portion are used to hold a UNIX "timeval" struct in
+ * bytes of the data portion are used to hold a UNIX "timespec" struct in
  * host byte-order, to compute the round-trip time.
  */
 static void
 pinger(void)
 {
-	struct timeval now;
+	struct timespec now;
 	struct tv32 tv32;
 	struct ip *ip;
 	struct icmp *icp;
@@ -1041,13 +1041,18 @@ pinger(void)
 	CLR(ntransmitted % mx_dup_ck);
 
 	if ((options & F_TIME) || timing) {
-		(void)gettimeofday(&now, NULL);
-
-		tv32.tv32_sec = htonl(now.tv_sec);
-		tv32.tv32_usec = htonl(now.tv_usec);
+		(void)clock_gettime(CLOCK_MONOTONIC, &now);
+		/*
+		 * Truncate seconds down to 32 bits in order
+		 * to fit the timestamp within 8 bytes of the
+		 * packet. We're only concerned with
+		 * durations, not absolute times.
+		 */
+		tv32.tv32_sec = (uint32_t)htonl(now.tv_sec);
+		tv32.tv32_nsec = (uint32_t)htonl(now.tv_nsec);
 		if (options & F_TIME)
 			icp->icmp_otime = htonl((now.tv_sec % (24*60*60))
-				* 1000 + now.tv_usec / 1000);
+				* 1000 + now.tv_nsec / 1000000);
 		if (timing)
 			bcopy((void *)&tv32,
 			    (void *)&outpack[ICMP_MINLEN + phdr_len],
@@ -1057,13 +1062,13 @@ pinger(void)
 	cc = ICMP_MINLEN + phdr_len + datalen;
 
 	/* compute ICMP checksum here */
-	icp->icmp_cksum = in_cksum((u_short *)icp, cc);
+	icp->icmp_cksum = in_cksum((u_char *)icp, cc);
 
 	if (options & F_HDRINCL) {
 		cc += sizeof(struct ip);
 		ip = (struct ip *)outpackhdr;
 		ip->ip_len = htons(cc);
-		ip->ip_sum = in_cksum((u_short *)outpackhdr, cc);
+		ip->ip_sum = in_cksum(outpackhdr, cc);
 		packet = outpackhdr;
 	}
 	i = send(ssend, (char *)packet, cc, 0);
@@ -1093,7 +1098,7 @@ pinger(void)
  * program to be run without having intermingled output (or statistics!).
  */
 static void
-pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timeval *tv)
+pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timespec *tv)
 {
 	struct in_addr ina;
 	u_char *cp, *dp;
@@ -1101,7 +1106,8 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from, s
 	struct ip *ip;
 	const void *tp;
 	double triptime;
-	int dupflag, hlen, i, j, recv_len, seq;
+	int dupflag, hlen, i, j, recv_len;
+	uint16_t seq;
 	static int old_rrlen;
 	static char old_rr[MAX_IPOPTLEN];
 
@@ -1125,7 +1131,7 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from, s
 		++nreceived;
 		triptime = 0.0;
 		if (timing) {
-			struct timeval tv1;
+			struct timespec tv1;
 			struct tv32 tv32;
 #ifndef icmp_data
 			tp = &icp->icmp_ip;
@@ -1139,10 +1145,10 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from, s
 				/* Copy to avoid alignment problems: */
 				memcpy(&tv32, tp, sizeof(tv32));
 				tv1.tv_sec = ntohl(tv32.tv32_sec);
-				tv1.tv_usec = ntohl(tv32.tv32_usec);
-				tvsub(tv, &tv1);
+				tv1.tv_nsec = ntohl(tv32.tv32_nsec);
+				timespecsub(tv, &tv1, tv);
  				triptime = ((double)tv->tv_sec) * 1000.0 +
- 				    ((double)tv->tv_usec) / 1000.0;
+				    ((double)tv->tv_nsec) / 1000000.0;
 				tsum += triptime;
 				tsumsq += triptime * triptime;
 				if (triptime < tmin)
@@ -1354,65 +1360,6 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from, s
 }
 
 /*
- * in_cksum --
- *	Checksum routine for Internet Protocol family headers (C Version)
- */
-u_short
-in_cksum(u_short *addr, int len)
-{
-	int nleft, sum;
-	u_short *w;
-	union {
-		u_short	us;
-		u_char	uc[2];
-	} last;
-	u_short answer;
-
-	nleft = len;
-	sum = 0;
-	w = addr;
-
-	/*
-	 * Our algorithm is simple, using a 32 bit accumulator (sum), we add
-	 * sequential 16 bit words to it, and at the end, fold back all the
-	 * carry bits from the top 16 bits into the lower 16 bits.
-	 */
-	while (nleft > 1)  {
-		sum += *w++;
-		nleft -= 2;
-	}
-
-	/* mop up an odd byte, if necessary */
-	if (nleft == 1) {
-		last.uc[0] = *(u_char *)w;
-		last.uc[1] = 0;
-		sum += last.us;
-	}
-
-	/* add back carry outs from top 16 bits to low 16 bits */
-	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
-	sum += (sum >> 16);			/* add carry */
-	answer = ~sum;				/* truncate to 16 bits */
-	return(answer);
-}
-
-/*
- * tvsub --
- *	Subtract 2 timeval structs:  out = out - in.  Out is assumed to
- * be >= in.
- */
-static void
-tvsub(struct timeval *out, const struct timeval *in)
-{
-
-	if ((out->tv_usec -= in->tv_usec) < 0) {
-		--out->tv_sec;
-		out->tv_usec += 1000000;
-	}
-	out->tv_sec -= in->tv_sec;
-}
-
-/*
  * status --
  *	Print out statistics when SIGINFO is received.
  */
@@ -1732,7 +1679,7 @@ pr_retip(struct ip *ip)
 static char *
 pr_ntime(n_time timestamp)
 {
-	static char buf[10];
+	static char buf[11];
 	int hour, min, sec;
 
 	sec = ntohl(timestamp) / 1000;
@@ -1780,9 +1727,10 @@ static cap_channel_t *
 capdns_setup(void)
 {
 	cap_channel_t *capcas, *capdnsloc;
+#ifdef WITH_CASPER
 	const char *types[2];
 	int families[1];
-
+#endif
 	capcas = cap_init();
 	if (capcas == NULL)
 		err(1, "unable to create casper process");
@@ -1791,6 +1739,7 @@ capdns_setup(void)
 	cap_close(capcas);
 	if (capdnsloc == NULL)
 		err(1, "unable to open system.dns service");
+#ifdef WITH_CASPER
 	types[0] = "NAME2ADDR";
 	types[1] = "ADDR2NAME";
 	if (cap_dns_type_limit(capdnsloc, types, 2) < 0)
@@ -1798,7 +1747,7 @@ capdns_setup(void)
 	families[0] = AF_INET;
 	if (cap_dns_family_limit(capdnsloc, families, 1) < 0)
 		err(1, "unable to limit access to system.dns service");
-
+#endif
 	return (capdnsloc);
 }
 

Copied: stable/12/sbin/ping/utils.c (from r351171, head/sbin/ping/utils.c)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/12/sbin/ping/utils.c	Sun Sep 15 16:53:02 2019	(r352357, copy of r351171, head/sbin/ping/utils.c)
@@ -0,0 +1,98 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Muuss.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * 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>
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+
+#include "utils.h"
+
+/*
+ * in_cksum --
+ *	Checksum routine for Internet Protocol family headers (C Version)
+ */
+u_short
+in_cksum(u_char *addr, int len)
+{
+	int nleft, sum;
+	u_char *w;
+	union {
+		u_short	us;
+		u_char	uc[2];
+	} last;
+	u_short answer;
+
+	nleft = len;
+	sum = 0;
+	w = addr;
+
+	/*
+	 * Our algorithm is simple, using a 32 bit accumulator (sum), we add
+	 * sequential 16 bit words to it, and at the end, fold back all the
+	 * carry bits from the top 16 bits into the lower 16 bits.
+	 */
+	while (nleft > 1)  {
+		u_short data;
+
+		memcpy(&data, w, sizeof(data));
+		sum += data;
+		w += sizeof(data);
+		nleft -= sizeof(data);
+	}
+
+	/* mop up an odd byte, if necessary */
+	if (nleft == 1) {
+		last.uc[0] = *w;
+		last.uc[1] = 0;
+		sum += last.us;
+	}
+
+	/* add back carry outs from top 16 bits to low 16 bits */
+	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
+	sum += (sum >> 16);			/* add carry */
+	answer = ~sum;				/* truncate to 16 bits */
+	return(answer);
+}

Copied and modified: stable/12/sbin/ping/utils.h (from r351171, head/sbin/ping/utils.h)
==============================================================================
--- head/sbin/ping/utils.h	Sat Aug 17 15:25:01 2019	(r351171, copy source)
+++ stable/12/sbin/ping/utils.h	Sun Sep 15 16:53:02 2019	(r352357)
@@ -28,8 +28,8 @@
  * $FreeBSD$
  */
 
-#ifndef PING_H
-#define PING_H 1
+#ifndef UTILS_H
+#define UTILS_H 1
 
 #include <sys/types.h>
 


More information about the svn-src-all mailing list