Module Name:    src
Committed By:   christos
Date:           Sat Sep 10 20:04:28 UTC 2011

Modified Files:
        src/sbin/ping: ping.8 ping.c

Log Message:
PR/45257: Instead of passing a 32bit sec and 32 bit usec timestamp in little
endian format by default, pass a struct timespec in native host format. Add
-C flag to produce a compatible timestamp like before.


To generate a diff of this commit:
cvs rdiff -u -r1.47 -r1.48 src/sbin/ping/ping.8
cvs rdiff -u -r1.98 -r1.99 src/sbin/ping/ping.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sbin/ping/ping.8
diff -u src/sbin/ping/ping.8:1.47 src/sbin/ping/ping.8:1.48
--- src/sbin/ping/ping.8:1.47	Tue Mar 21 17:54:46 2006
+++ src/sbin/ping/ping.8	Sat Sep 10 16:04:28 2011
@@ -1,4 +1,4 @@
-.\"	$NetBSD: ping.8,v 1.47 2006/03/21 22:54:46 pavel Exp $
+.\"	$NetBSD: ping.8,v 1.48 2011/09/10 20:04:28 christos Exp $
 .\"
 .\" Copyright (c) 1985, 1991, 1993
 .\"	The Regents of the University of California.  All rights reserved.
@@ -29,7 +29,7 @@
 .\"
 .\"     @(#)ping.8	8.2 (Berkeley) 12/11/93
 .\"
-.Dd March 21, 2006
+.Dd September 10, 2011
 .Dt PING 8
 .Os
 .Sh NAME
@@ -40,7 +40,7 @@
 .Sh SYNOPSIS
 .Nm
 .Bk -words
-.Op Fl adDfLnoPqQrRv
+.Op Fl aCdDfLnoPqQrRv
 .Ek
 .Bk -words
 .Op Fl c Ar count
@@ -93,7 +93,7 @@
 .Tn ICMP
 header,
 followed by a
-.Dq struct timeval
+.Dq struct timespec
 and then an arbitrary number of ``pad'' bytes used to fill out the
 packet.
 The options are as follows:
@@ -108,6 +108,10 @@
 .Ar count
 .Tn ECHO_RESPONSE
 packets.
+.It Fl C
+Send timestamps in compat format; two 32 bit words in little endian format,
+the first one representing seconds, and the second one representing
+microseconds.
 .It Fl d
 Set the
 .Dv SO_DEBUG
@@ -322,12 +326,20 @@
 .Tn ICMP
 header).
 .Pp
-If the data space is at least eight bytes large,
+If the data space is at least 
+.Dv sizeof(struct timespec)
+(16) large,
+.Nm
+uses the first
+.Dv sizeof(struct timespec)
+byres to include a timestamp to compute round trip times.
+Otherwise if the data space is at least eight bytes large (or the
+.Fl C
+flag is specified),
 .Nm
 uses the first eight bytes of this space to include a timestamp to compute
 round trip times.
-If less than eight bytes of pad are specified,
-no round trip times are given.
+If there are not enough bytes of pad no round trip times are given.
 .Sh DUPLICATE AND DAMAGED PACKETS
 .Nm
 will report duplicate and damaged packets.

Index: src/sbin/ping/ping.c
diff -u src/sbin/ping/ping.c:1.98 src/sbin/ping/ping.c:1.99
--- src/sbin/ping/ping.c:1.98	Sat Aug 27 14:40:18 2011
+++ src/sbin/ping/ping.c	Sat Sep 10 16:04:28 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: ping.c,v 1.98 2011/08/27 18:40:18 joerg Exp $	*/
+/*	$NetBSD: ping.c,v 1.99 2011/09/10 20:04:28 christos Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993
@@ -58,7 +58,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: ping.c,v 1.98 2011/08/27 18:40:18 joerg Exp $");
+__RCSID("$NetBSD: ping.c,v 1.99 2011/09/10 20:04:28 christos Exp $");
 #endif
 
 #include <stdio.h>
@@ -113,6 +113,7 @@
 #define F_MCAST		0x2000		/* multicast target */
 #define F_MCAST_NOLOOP	0x4000		/* no multicast loopback */
 #define F_AUDIBLE	0x8000		/* audible output */
+#define F_TIMING64	0x10000		/* 64 bit time, nanoseconds */
 #ifdef IPSEC
 #ifdef IPSEC_POLICY_IPSEC
 #define F_POLICY	0x10000
@@ -151,11 +152,13 @@
 static int s;					/* Socket file descriptor */
 static int sloop;				/* Socket file descriptor/loopback */
 
-#define PHDR_LEN sizeof(struct tv32)	/* size of timestamp header */
+#define PHDR_LEN sizeof(struct tv32)		/* size of timestamp header */
+#define PHDR64_LEN sizeof(struct timespec)	/* size of timestamp header */
 static struct sockaddr_in whereto, send_addr;	/* Who to ping */
 static struct sockaddr_in src_addr;		/* from where */
 static struct sockaddr_in loc_addr;		/* 127.1 */
-static int datalen = 64 - PHDR_LEN;		/* How much data */
+static int datalen;				/* How much data */
+static int phdrlen;
 
 #ifndef __NetBSD__
 static char *progname;
@@ -187,7 +190,7 @@
 static int nreceived;				/* # of packets we got back */
 
 static double interval;			/* interval between packets */
-static struct timeval interval_tv;
+static struct timespec interval_tv;
 static double tmin = 999999999.0;
 static double tmax = 0.0;
 static double tsum = 0.0;			/* sum of all times */
@@ -196,11 +199,11 @@
 
 static int bufspace = IP_MAXPACKET;
 
-static struct timeval now, clear_cache, last_tx, next_tx, first_tx;
-static struct timeval last_rx, first_rx;
+static struct timespec now, clear_cache, last_tx, next_tx, first_tx;
+static struct timespec last_rx, first_rx;
 static int lastrcvd = 1;			/* last ping sent has been received */
 
-static struct timeval jiggle_time;
+static struct timespec jiggle_time;
 static int jiggle_cnt, total_jiggled, jiggle_direction = -1;
 
 __dead static void doit(void);
@@ -211,10 +214,12 @@
 static void pinger(void);
 static void fill(void);
 static void rnd_fill(void);
-static double diffsec(struct timeval *, struct timeval *);
-static void timevaladd(struct timeval *, struct timeval *);
-static void sec_to_timeval(const double, struct timeval *);
-static double timeval_to_sec(const struct timeval *);
+static double diffsec(struct timespec *, struct timespec *);
+#if 0
+static void timespecadd(struct timespec *, struct timespec *);
+#endif
+static void sec_to_timespec(const double, struct timespec *);
+static double timespec_to_sec(const struct timespec *);
 static void pr_pack(u_char *, int, struct sockaddr_in *);
 static u_int16_t in_cksum(u_int16_t *, u_int);
 static void pr_saddr(u_char *);
@@ -232,6 +237,7 @@
 {
 	int c, i, on = 1, hostind = 0;
 	long l;
+	int len = -1, compat = 0;
 	u_char ttl = 0;
 	u_long tos = 0;
 	char *p;
@@ -275,12 +281,15 @@
 #endif /*IPSEC_POLICY_IPSEC*/
 #endif
 	while ((c = getopt(argc, argv,
-			   "ac:dDfg:h:i:I:l:Lnop:PqQrRs:t:T:vw:" IPSECOPT)) != -1) {
+			   "ac:CdDfg:h:i:I:l:Lnop:PqQrRs:t:T:vw:" IPSECOPT)) != -1) {
 #undef IPSECOPT
 		switch (c) {
 		case 'a':
 			pingflags |= F_AUDIBLE;
 			break;
+		case 'C':
+			compat = 1;
+			break;
 		case 'c':
 			npackets = strtol(optarg, &p, 0);
 			if (*p != '\0' || npackets <= 0)
@@ -341,7 +350,7 @@
 				errx(1, "Bad/invalid packet size %s", optarg);
 			if (l > MAXPACKET)
 				errx(1, "packet size is too large");
-			datalen = (int)l;
+			len = (int)l;
 			break;
 		case 'v':
 			pingflags |= F_VERBOSE;
@@ -416,7 +425,7 @@
 	if (preload > 0 && prog_getuid())
 		errx(1, "Must be superuser to use -l");
 #endif
-	sec_to_timeval(interval, &interval_tv);
+	sec_to_timespec(interval, &interval_tv);
 
 	if ((pingflags & (F_AUDIBLE|F_FLOOD)) == (F_AUDIBLE|F_FLOOD))
 		warnx("Sorry, no audible output for flood pings");
@@ -446,8 +455,20 @@
 	loc_addr.sin_len = sizeof(struct sockaddr_in);
 	loc_addr.sin_addr.s_addr = htonl((127 << 24) + 1);
 
-	if (datalen >= (int)PHDR_LEN)	/* can we time them? */
+	if (len != -1)
+		datalen = len;
+	else
+		datalen = 64;
+	if (!compat && datalen >= (int)PHDR64_LEN) { /* can we time them? */
+		pingflags |= F_TIMING64;
+		phdrlen = PHDR64_LEN;
+	} else if (datalen >= (int)PHDR_LEN) {	/* can we time them? */
 		pingflags |= F_TIMING;
+		phdrlen = PHDR_LEN;
+	} else
+		phdrlen = 0;
+	datalen -= phdrlen;
+
 	packlen = datalen + 60 + 76;	/* MAXIP + MAXICMP */
 	if ((packet = malloc(packlen)) == NULL)
 		err(1, "Out of memory");
@@ -457,7 +478,7 @@
 	} else if (pingflags & F_PING_RANDOM) {
 		rnd_fill();
 	} else {
-		for (i = PHDR_LEN; i < datalen; i++)
+		for (i = phdrlen; i < datalen; i++)
 			opack_icmp.icmp_data[i] = i;
 	}
 
@@ -649,7 +670,7 @@
 
 	/* fire off them quickies */
 	for (i = 0; i < preload; i++) {
-		(void)gettimeofday(&now, 0);
+		clock_gettime(CLOCK_MONOTONIC, &now);
 		pinger();
 	}
 
@@ -667,9 +688,9 @@
 	double sec, last, d_last;
 	struct pollfd fdmaskp[1];
 
-	(void)gettimeofday(&clear_cache,0);
+	(void)clock_gettime(CLOCK_MONOTONIC, &clear_cache);
 	if (maxwait != 0) {
-		last = timeval_to_sec(&clear_cache) + maxwait;
+		last = timespec_to_sec(&clear_cache) + maxwait;
 		d_last = 0;
 	} else {
 		last = 0;
@@ -677,10 +698,10 @@
 	}
 
 	do {
-		(void)gettimeofday(&now,0);
+		clock_gettime(CLOCK_MONOTONIC, &now);
 
 		if (last != 0)
-			d_last = last - timeval_to_sec(&now);
+			d_last = last - timespec_to_sec(&now);
 
 		if (ntransmitted < npackets && d_last > 0) {
 			/* send if within 100 usec or late for next packet */
@@ -708,7 +729,6 @@
 				break;
 		}
 
-
 		fdmaskp[0].fd = s;
 		fdmaskp[0].events = POLLIN;
 		cc = prog_poll(fdmaskp, 1, (int)(sec * 1000));
@@ -734,7 +754,7 @@
 			}
 			continue;
 		}
-		(void)gettimeofday(&now, 0);
+		clock_gettime(CLOCK_MONOTONIC, &now);
 		pr_pack(packet, cc, &from);
 
 	} while (nreceived < npackets
@@ -806,9 +826,10 @@
 /*
  * 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 PHDR_LEN bytes
+ * and the sequence number is an ascending integer.  The first phdrlen bytes
  * of the data portion are used to hold a UNIX "timeval" struct in VAX
- * byte-order, to compute the round-trip time.
+ * byte-order, to compute the round-trip time, or a UNIX "timespec" in native
+ * format.
  */
 static void
 pinger(void)
@@ -830,13 +851,13 @@
 		opack_icmp.icmp_id = ~ident;
 		opack_icmp.icmp_cksum = 0;
 		opack_icmp.icmp_cksum = in_cksum((u_int16_t *)&opack_icmp,
-		    PHDR_LEN);
+		    phdrlen);
 		sw = 0;
 		if (prog_setsockopt(sloop,IPPROTO_IP,IP_HDRINCL,
 			       (char *)&sw,sizeof(sw)) < 0)
 			err(1, "Can't turn off special IP header");
 		if (prog_sendto(sloop, (char *) &opack_icmp,
-			   PHDR_LEN, MSG_DONTROUTE,
+			   phdrlen, MSG_DONTROUTE,
 			   (struct sockaddr *)&loc_addr,
 			   sizeof(struct sockaddr_in)) < 0) {
 			/*
@@ -853,16 +874,20 @@
 			       (char *)&sw, sizeof(sw)) < 0)
 			err(1, "Can't set special IP header");
 		
-		(void)gettimeofday(&clear_cache,0);
+		(void)clock_gettime(CLOCK_MONOTONIC, &clear_cache);
 	}
 
 	opack_icmp.icmp_type = ICMP_ECHO;
 	opack_icmp.icmp_id = ident;
-	tv32.tv32_sec = (uint32_t)htonl(now.tv_sec);
-	tv32.tv32_usec = htonl(now.tv_usec);
-	if (pingflags & F_TIMING)
+
+	if (pingflags & F_TIMING) {
+		tv32.tv32_sec = (uint32_t)htonl(now.tv_sec);
+		tv32.tv32_usec = htonl(now.tv_nsec / 1000);
 		(void) memcpy(&opack_icmp.icmp_data[0], &tv32, sizeof(tv32));
-	cc = datalen + PHDR_LEN;
+	} else if (pingflags & F_TIMING64)
+		(void) memcpy(&opack_icmp.icmp_data[0], &now, sizeof(now));
+
+	cc = datalen + phdrlen;
 	opack_icmp.icmp_cksum = 0;
 	opack_icmp.icmp_cksum = in_cksum((u_int16_t *)&opack_icmp, cc);
 
@@ -896,7 +921,7 @@
 	 */
 	if (diffsec(&next_tx, &now) <= interval) {
 		do {
-			timevaladd(&next_tx, &interval_tv);
+			timespecadd(&next_tx, &interval_tv, &next_tx);
 		} while (diffsec(&next_tx, &now) < -0.1);
 	}
 
@@ -928,7 +953,7 @@
 	if (dupflag)
 		(void)printf(" DUP!");
 	(void)printf(" ttl=%d", ttl);
-	if (pingflags & F_TIMING)
+	if (pingflags & (F_TIMING|F_TIMING64))
 		(void)printf(" time=%.3f ms", triptime*1000.0);
 
 	/*
@@ -983,6 +1008,8 @@
 	icp = (struct icmp *)(buf + hlen);
 	if (icp->icmp_type == ICMP_ECHOREPLY
 	    && icp->icmp_id == ident) {
+		struct timespec tv;
+
 		if (icp->icmp_seq == htons((u_int16_t)(ntransmitted-1)))
 			lastrcvd = 1;
 		last_rx = now;
@@ -990,12 +1017,15 @@
 			first_rx = last_rx;
 		nreceived++;
 		if (pingflags & F_TIMING) {
-			struct timeval tv;
 			struct tv32 tv32;
 
 			(void) memcpy(&tv32, icp->icmp_data, sizeof(tv32));
 			tv.tv_sec = (uint32_t)ntohl(tv32.tv32_sec);
-			tv.tv_usec = ntohl(tv32.tv32_usec);
+			tv.tv_nsec = ntohl(tv32.tv32_usec) * 1000;
+		} else if (pingflags & F_TIMING64) 
+			(void) memcpy(&tv, icp->icmp_data, sizeof(tv));
+
+		if (pingflags & (F_TIMING|F_TIMING64)) {
 			triptime = diffsec(&last_rx, &tv);
 			tsum += triptime;
 			tsumsq += triptime * triptime;
@@ -1066,12 +1096,12 @@
 			PR_PACK_SUB();
 
 		/* check the data */
-		if (datalen > (int)PHDR_LEN
+		if (datalen > phdrlen
 		    && !(pingflags & F_PING_RANDOM)
-		    && memcmp(icp->icmp_data + PHDR_LEN,
-			    opack_icmp.icmp_data + PHDR_LEN,
-			    datalen-PHDR_LEN)) {
-			for (i=PHDR_LEN; i<datalen; i++) {
+		    && memcmp(icp->icmp_data + phdrlen,
+			    opack_icmp.icmp_data + phdrlen,
+			    datalen - phdrlen)) {
+			for (i = phdrlen; i < datalen; i++) {
 				if (icp->icmp_data[i] !=
 				    opack_icmp.icmp_data[i])
 					break;
@@ -1081,8 +1111,8 @@
 				     " %#x but was %#x", i,
 				     (u_char)opack_icmp.icmp_data[i],
 				     (u_char)icp->icmp_data[i]);
-			for (i=PHDR_LEN; i<datalen; i++) {
-				if ((i%16) == PHDR_LEN)
+			for (i = phdrlen; i < datalen; i++) {
+				if ((i % 16) == phdrlen)
 					(void)printf("\n\t");
 				(void)printf("%2x ",(u_char)icp->icmp_data[i]);
 			}
@@ -1235,44 +1265,46 @@
 
 
 /*
- * compute the difference of two timevals in seconds
+ * compute the difference of two timespecs in seconds
  */
 static double
-diffsec(struct timeval *timenow,
-	struct timeval *then)
+diffsec(struct timespec *timenow,
+	struct timespec *then)
 {
 	if (timenow->tv_sec == 0)
 		return -1;
-	return ((int32_t)((uint32_t)timenow->tv_sec - (uint32_t)then->tv_sec)
-	    * 1.0 + (timenow->tv_usec - then->tv_usec)/1000000.0);
+	return (timenow->tv_sec - then->tv_sec)
+	    * 1.0 + (timenow->tv_nsec - then->tv_nsec) / 1000000000.0;
 }
 
 
+#if 0
 static void
-timevaladd(struct timeval *t1,
-	   struct timeval *t2)
+timespecadd(struct timespec *t1,
+	   struct timespec *t2)
 {
 
 	t1->tv_sec += t2->tv_sec;
-	if ((t1->tv_usec += t2->tv_usec) >= 1000000) {
+	if ((t1->tv_nsec += t2->tv_nsec) >= 1000000000) {
 		t1->tv_sec++;
-		t1->tv_usec -= 1000000;
+		t1->tv_nsec -= 1000000000;
 	}
 }
+#endif
 
 
 static void
-sec_to_timeval(const double sec, struct timeval *tp)
+sec_to_timespec(const double sec, struct timespec *tp)
 {
 	tp->tv_sec = sec;
-	tp->tv_usec = (sec - tp->tv_sec) * 1000000.0;
+	tp->tv_nsec = (sec - tp->tv_sec) * 1000000000.0;
 }
 
 
 static double
-timeval_to_sec(const struct timeval *tp)
+timespec_to_sec(const struct timespec *tp)
 {
-	return tp->tv_sec + tp->tv_usec / 1000000.0;
+	return tp->tv_sec + tp->tv_nsec / 1000000000.0;
 }
 
 
@@ -1768,7 +1800,7 @@
 		    &pat[8], &pat[9], &pat[10], &pat[11],
 		    &pat[12], &pat[13], &pat[14], &pat[15]);
 
-	for (k=PHDR_LEN, j = 0; k <= datalen; k++) {
+	for (k = phdrlen, j = 0; k <= datalen; k++) {
 		opack_icmp.icmp_data[k] = pat[j];
 		if (++j >= i)
 			j = 0;
@@ -1778,7 +1810,7 @@
 		(void)printf("PATTERN: 0x");
 		for (j=0; j<i; j++)
 			(void)printf("%02x",
-				     (u_char)opack_icmp.icmp_data[PHDR_LEN+j]);
+				     (u_char)opack_icmp.icmp_data[phdrlen + j]);
 		(void)printf("\n");
 	}
 
@@ -1791,7 +1823,7 @@
 	static u_int32_t rnd;
 	int i;
 
-	for (i = PHDR_LEN; i < datalen; i++) {
+	for (i = phdrlen; i < datalen; i++) {
 		rnd = (3141592621U * rnd + 663896637U);
 		opack_icmp.icmp_data[i] = rnd>>24;
 	}
@@ -1856,7 +1888,7 @@
 #endif /*IPSEC*/
 
 	(void)fprintf(stderr, "usage: \n"
-	    "%s [-adDfLnoPqQrRv] [-c count] [-g gateway] [-h host]"
+	    "%s [-aCdDfLnoPqQrRv] [-c count] [-g gateway] [-h host]"
 	    " [-i interval] [-I addr]\n"
 	    "     [-l preload] [-p pattern] [-s size] [-t tos] [-T ttl]"
 	    " [-w maxwait] " IPSECOPT "host\n",

Reply via email to