Collin Funk <collin.fu...@gmail.com> writes:

> I've applied this patch using modern gnulib timespec functions instead
> of rolling our own versions (atleast for traceroute).

Likewise for ping & ping6.

Collin

>From b694830a330906e63a036513c7a6cdde997d19e4 Mon Sep 17 00:00:00 2001
From: Collin Funk <collin.fu...@gmail.com>
Date: Wed, 26 Jun 2024 20:43:41 -0700
Subject: [PATCH] ping, ping6: Modernize time functions.

* bootstrap.conf (gnulib_modules): Add timespec-add.
* ping/Makefile.am (LDADD): Add $(CLOCK_TIME_LIB),
$(PTHREAD_SIGMASK_LIB), and $(SELECT_LIB).
* ping/libping.c (ping_init): Use current_timespec instead of
gettimeofday.
* ping/ping_common.c (tvsub): Remove function.
(ping_timeout_p): Return a bool. Use timespec_sub and
current_timespec.
* ping/ping_common.h (PING_SET_INTERVAL): Expect a timespec instead of
a timeval.
(struct ping_data): Store the start time in a timespec instead of a
timeval.
(tvsub): Remove declaration.
(ping_timeout_p): Adjust prototype.
* ping/ping.c (send_echo): Use current_timespec.
(ping_init): Likewise.
(ping_run): Likewise. Use pselect.
* ping/ping6.c (send_echo): Use current_timespec.
(print_echo): Likewise.
(ping_init): Likewise.
(ping_run): Likewise. Use pselect.
* ping/ping_echo.c (print_echo): Use current_timespec.
---
 bootstrap.conf     |  1 +
 ping/Makefile.am   |  5 ++-
 ping/libping.c     |  4 ++-
 ping/ping.c        | 53 ++++++++++---------------------
 ping/ping6.c       | 79 ++++++++++++++++++----------------------------
 ping/ping_common.c | 34 ++++----------------
 ping/ping_common.h |  7 ++--
 ping/ping_echo.c   | 25 ++++++++-------
 8 files changed, 77 insertions(+), 131 deletions(-)

diff --git a/bootstrap.conf b/bootstrap.conf
index 7a572c96..9026eccc 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -104,6 +104,7 @@ sys_types
 sysexits
 termios
 timespec
+timespec-add
 timespec-sub
 unistd-safer
 update-copyright
diff --git a/ping/Makefile.am b/ping/Makefile.am
index 93d4fa17..085255bc 100644
--- a/ping/Makefile.am
+++ b/ping/Makefile.am
@@ -23,7 +23,10 @@ AM_CPPFLAGS = \
 
 LDADD = \
 	$(iu_LIBRARIES) \
-	$(LIBIDN)
+	$(LIBIDN) \
+	$(CLOCK_TIME_LIB) \
+	$(PTHREAD_SIGMASK_LIB) \
+	$(SELECT_LIB)
 
 bin_PROGRAMS = $(ping_BUILD) $(ping6_BUILD)
 
diff --git a/ping/libping.c b/ping/libping.c
index 1e22a58a..0991d3b2 100644
--- a/ping/libping.c
+++ b/ping/libping.c
@@ -38,6 +38,8 @@
 # include <idna.h>
 #endif
 
+#include <timespec.h>
+
 #include "ping.h"
 
 static int useless_ident = 0;	/* Relevant at least for Linux.  */
@@ -119,7 +121,7 @@ ping_init (int type, int ident)
   /* Make sure we use only 16 bits in this field, id for icmp is a unsigned short.  */
   p->ping_ident = ident & 0xFFFF;
   p->ping_cktab_size = PING_CKTABSIZE;
-  gettimeofday (&p->ping_start_time, NULL);
+  p->ping_start_time = current_timespec ();
   return p;
 }
 
diff --git a/ping/ping.c b/ping/ping.c
index 6c7dbd9a..1f2f6702 100644
--- a/ping/ping.c
+++ b/ping/ping.c
@@ -47,6 +47,7 @@
 
 #include <argp.h>
 #include <attribute.h>
+#include <timespec.h>
 #include <ping.h>
 #include "ping_impl.h"
 #include "libinetutils.h"
@@ -386,9 +387,9 @@ ping_run (PING *ping, int (*finish) (void))
 {
   fd_set fdset;
   int fdmax;
-  struct timeval resp_time;
-  struct timeval last, intvl, now;
-  struct timeval *t = NULL;
+  struct timespec resp_time;
+  struct timespec last, intvl, now;
+  struct timespec *t = NULL;
   int finishing = 0;
   size_t nresp = 0;
   size_t i;
@@ -397,26 +398,18 @@ ping_run (PING *ping, int (*finish) (void))
 
   fdmax = ping->ping_fd + 1;
 
-  /* Some systems use `struct timeval' of size 16.  As these are
-   * not initialising `timeval' properly by assignment alone, let
-   * us play safely here.  gettimeofday() is always sufficient.
-   */
-  memset (&resp_time, 0, sizeof (resp_time));
-  memset (&intvl, 0, sizeof (intvl));
-  memset (&now, 0, sizeof (now));
-
   for (i = 0; i < preload; i++)
     send_echo (ping);
 
   if (options & OPT_FLOOD)
     {
       intvl.tv_sec = 0;
-      intvl.tv_usec = 10000;
+      intvl.tv_nsec = 1e7;
     }
   else
     PING_SET_INTERVAL (intvl, ping->ping_interval);
 
-  gettimeofday (&last, NULL);
+  last = current_timespec ();
   send_echo (ping);
 
   while (!stop)
@@ -425,29 +418,14 @@ ping_run (PING *ping, int (*finish) (void))
 
       FD_ZERO (&fdset);
       FD_SET (ping->ping_fd, &fdset);
-      gettimeofday (&now, NULL);
-      resp_time.tv_sec = last.tv_sec + intvl.tv_sec - now.tv_sec;
-      resp_time.tv_usec = last.tv_usec + intvl.tv_usec - now.tv_usec;
-
-      while (resp_time.tv_usec < 0)
-	{
-	  resp_time.tv_usec += 1000000;
-	  resp_time.tv_sec--;
-	}
-      while (resp_time.tv_usec >= 1000000)
-	{
-	  resp_time.tv_usec -= 1000000;
-	  resp_time.tv_sec++;
-	}
-
-      if (resp_time.tv_sec < 0)
-	resp_time.tv_sec = resp_time.tv_usec = 0;
+      now = current_timespec ();
+      resp_time = timespec_sub (timespec_add (last, intvl), now);
 
-      n = select (fdmax, &fdset, NULL, NULL, &resp_time);
+      n = pselect (fdmax, &fdset, NULL, NULL, &resp_time, NULL);
       if (n < 0)
 	{
 	  if (errno != EINTR)
-	    error (EXIT_FAILURE, errno, "select failed");
+	    error (EXIT_FAILURE, errno, "pselect failed");
 	  continue;
 	}
       else if (n == 1)
@@ -456,7 +434,7 @@ ping_run (PING *ping, int (*finish) (void))
 	    nresp++;
 	  if (t == 0)
 	    {
-	      gettimeofday (&now, NULL);
+	      now = current_timespec ();
 	      t = &now;
 	    }
 
@@ -485,7 +463,7 @@ ping_run (PING *ping, int (*finish) (void))
 
 	      intvl.tv_sec = linger;
 	    }
-	  gettimeofday (&last, NULL);
+	  last = current_timespec ();
 	}
     }
 
@@ -504,8 +482,11 @@ send_echo (PING *ping)
 
   if (PING_TIMING (data_length))
     {
-      struct timeval tv;
-      gettimeofday (&tv, NULL);
+      struct timespec now = current_timespec ();
+      /* *INDENT-OFF* */
+      struct timeval tv = { .tv_sec = now.tv_sec,
+                            .tv_usec = now.tv_nsec / 1000 };
+      /* *INDENT-ON* */
       ping_set_data (ping, &tv, 0, sizeof (tv), USE_IPV6);
       off += sizeof (tv);
     }
diff --git a/ping/ping6.c b/ping/ping6.c
index 9cf03eb1..2ac47aa0 100644
--- a/ping/ping6.c
+++ b/ping/ping6.c
@@ -52,6 +52,7 @@
 
 #include <attribute.h>
 #include <xalloc.h>
+#include <timespec.h>
 #include "ping6.h"
 #include "libinetutils.h"
 
@@ -329,9 +330,9 @@ ping_run (PING *ping, int (*finish) (void))
 {
   fd_set fdset;
   int fdmax;
-  struct timeval resp_time;
-  struct timeval last, intvl, now;
-  struct timeval *t = NULL;
+  struct timespec resp_time;
+  struct timespec last, intvl, now;
+  struct timespec *t = NULL;
   int finishing = 0;
   size_t nresp = 0;
   unsigned long i;
@@ -340,26 +341,18 @@ ping_run (PING *ping, int (*finish) (void))
 
   fdmax = ping->ping_fd + 1;
 
-  /* Some systems use `struct timeval' of size 16.  As these are
-   * not initialising `timeval' properly by assignment alone, let
-   * us play safely here.  gettimeofday() is always sufficient.
-   */
-  memset (&resp_time, 0, sizeof (resp_time));
-  memset (&intvl, 0, sizeof (intvl));
-  memset (&now, 0, sizeof (now));
-
   for (i = 0; i < preload; i++)
     send_echo (ping);
 
   if (options & OPT_FLOOD)
     {
       intvl.tv_sec = 0;
-      intvl.tv_usec = 10000;
+      intvl.tv_nsec = 1e7;
     }
   else
     PING_SET_INTERVAL (intvl, ping->ping_interval);
 
-  gettimeofday (&last, NULL);
+  last = current_timespec ();
   send_echo (ping);
 
   while (!stop)
@@ -369,29 +362,14 @@ ping_run (PING *ping, int (*finish) (void))
       FD_ZERO (&fdset);
       FD_SET (ping->ping_fd, &fdset);
 
-      gettimeofday (&now, NULL);
-      resp_time.tv_sec = last.tv_sec + intvl.tv_sec - now.tv_sec;
-      resp_time.tv_usec = last.tv_usec + intvl.tv_usec - now.tv_usec;
-
-      while (resp_time.tv_usec < 0)
-	{
-	  resp_time.tv_usec += 1000000;
-	  resp_time.tv_sec--;
-	}
-      while (resp_time.tv_usec >= 1000000)
-	{
-	  resp_time.tv_usec -= 1000000;
-	  resp_time.tv_sec++;
-	}
-
-      if (resp_time.tv_sec < 0)
-	resp_time.tv_sec = resp_time.tv_usec = 0;
+      now = current_timespec ();
+      resp_time = timespec_sub (timespec_add (last, intvl), now);
 
-      n = select (fdmax, &fdset, NULL, NULL, &resp_time);
+      n = pselect (fdmax, &fdset, NULL, NULL, &resp_time, NULL);
       if (n < 0)
 	{
 	  if (errno != EINTR)
-	    error (EXIT_FAILURE, errno, "select failed");
+	    error (EXIT_FAILURE, errno, "pselect failed");
 	  continue;
 	}
       else if (n == 1)
@@ -400,7 +378,7 @@ ping_run (PING *ping, int (*finish) (void))
 	    nresp++;
 	  if (t == 0)
 	    {
-	      gettimeofday (&now, NULL);
+	      now = current_timespec ();
 	      t = &now;
 	    }
 
@@ -431,7 +409,7 @@ ping_run (PING *ping, int (*finish) (void))
 
 	      intvl.tv_sec = MAXWAIT;
 	    }
-	  gettimeofday (&last, NULL);
+	  last = current_timespec ();
 	}
     }
 
@@ -450,8 +428,11 @@ send_echo (PING *ping)
 
   if (PING_TIMING (data_length))
     {
-      struct timeval tv;
-      gettimeofday (&tv, NULL);
+      struct timespec now = current_timespec ();
+      /* *INDENT-OFF* */
+      struct timeval tv = { .tv_sec = now.tv_sec,
+                            .tv_usec = now.tv_nsec / 1000 };
+      /* *INDENT-ON* */
       ping_set_data (ping, &tv, 0, sizeof (tv), USE_IPV6);
       off += sizeof (tv);
     }
@@ -560,26 +541,26 @@ print_echo (int dupflag, int hops, struct ping_stat *ping_stat,
 {
   int err;
   char buf[256];
-  struct timeval tv;
-  int timing = 0;
+  bool timing = false;
   double triptime = 0.0;
 
-  gettimeofday (&tv, NULL);
-
   /* Do timing */
   if (PING_TIMING (datalen - sizeof (struct icmp6_hdr)))
     {
-      struct timeval tv1, *tp;
+      struct timeval tv;
+      struct timespec ts;
 
-      timing++;
-      tp = (struct timeval *) (icmp6 + 1);
+      timing = true;
 
-      /* Avoid unaligned data: */
-      memcpy (&tv1, tp, sizeof (tv1));
-      tvsub (&tv, &tv1);
+      /* Avoid unaligned data.  */
+      memcpy (&tv, icmp6 + 1, sizeof (tv));
+      /* *INDENT-OFF* */
+      ts = timespec_sub (current_timespec (),
+                         (struct timespec) { .tv_sec = tv.tv_sec,
+                                             .tv_nsec = tv.tv_usec * 1000 });
+      /* *INDENT-ON* */
 
-      triptime = ((double) tv.tv_sec) * 1000.0 +
-	((double) tv.tv_usec) / 1000.0;
+      triptime = timespectod (ts) * 1000.0;
       ping_stat->tsum += triptime;
       ping_stat->tsumsq += triptime * triptime;
       if (triptime < ping_stat->tmin)
@@ -890,7 +871,7 @@ ping_init (int type MAYBE_UNUSED, int ident)
   /* Make sure we use only 16 bits in this field, id for icmp is a unsigned short.  */
   p->ping_ident = ident & 0xFFFF;
   p->ping_cktab_size = PING_CKTABSIZE;
-  gettimeofday (&p->ping_start_time, NULL);
+  p->ping_start_time = current_timespec ();
   return p;
 }
 
diff --git a/ping/ping_common.c b/ping/ping_common.c
index c755e438..a4455d2b 100644
--- a/ping/ping_common.c
+++ b/ping/ping_common.c
@@ -30,6 +30,7 @@
 #include <netdb.h>
 #include <xalloc.h>
 #include <attribute.h>
+#include <timespec.h>
 
 #include "ping_common.h"
 
@@ -102,23 +103,6 @@ decode_pattern (const char *text, int *pattern_len,
   *pattern_len = i;
 }
 
-
-/*
- * tvsub --
- *	Subtract 2 timeval structs:  out = out - in.  Out is assumed to
- * be >= in.
- */
-void
-tvsub (struct timeval *out, struct timeval *in)
-{
-  if ((out->tv_usec -= in->tv_usec) < 0)
-    {
-      --out->tv_sec;
-      out->tv_usec += 1000000;
-    }
-  out->tv_sec -= in->tv_sec;
-}
-
 double
 nabs (double a)
 {
@@ -241,18 +225,12 @@ ping_unset_data (PING *p)
   _ping_freebuf (p);
 }
 
-int
-ping_timeout_p (struct timeval *start_time, int timeout)
+bool
+ping_timeout_p (struct timespec *start_time, int timeout)
 {
-  struct timeval now;
-  gettimeofday (&now, NULL);
-  if (timeout != -1)
-    {
-      tvsub (&now, start_time);
-      if (now.tv_sec >= timeout)
-	return 1;
-    }
-  return 0;
+  if (timeout == -1)
+    return false;
+  return timespec_sub (current_timespec (), *start_time).tv_sec >= timeout;
 }
 
 char *
diff --git a/ping/ping_common.h b/ping/ping_common.h
index 46f7b4b2..66e69d6d 100644
--- a/ping/ping_common.h
+++ b/ping/ping_common.h
@@ -70,7 +70,7 @@ struct ping_stat
 
 #define PING_SET_INTERVAL(t,i) do {\
   (t).tv_sec = (i)/PING_PRECISION;\
-  (t).tv_usec = ((i)%PING_PRECISION)*(1000000/PING_PRECISION) ;\
+  (t).tv_nsec = ((i)%PING_PRECISION)*(1e9/PING_PRECISION) ;\
 } while (0)
 
 
@@ -109,7 +109,7 @@ struct ping_data
   int ping_fd;			/* Raw socket descriptor */
   int ping_type;		/* Type of packets to send */
   size_t ping_count;		/* Number of packets to send */
-  struct timeval ping_start_time;	/* Start time */
+  struct timespec ping_start_time;	/* Start time */
   size_t ping_interval;		/* Number of seconds to wait between sending pkts */
   union ping_address ping_dest;	/* whom to ping */
   char *ping_hostname;		/* Printable hostname */
@@ -153,7 +153,6 @@ struct ping_data
   (_C_BIT (p, _C_IND (p,bit)) & _C_MASK  (_C_IND (p,bit)))
 
 
-void tvsub (struct timeval *out, struct timeval *in);
 double nabs (double a);
 double nsqrt (double a, double prec);
 
@@ -172,7 +171,7 @@ void ping_set_count (PING * ping, size_t count);
 void ping_set_sockopt (PING * ping, int opt, void *val, int valsize);
 void ping_set_interval (PING * ping, size_t interval);
 void ping_unset_data (PING * p);
-int ping_timeout_p (struct timeval *start_time, int timeout);
+bool ping_timeout_p (struct timespec *start_time, int timeout);
 
 char *ipaddr2str (struct sockaddr *from, socklen_t fromlen);
 char *sinaddr2str (struct in_addr ina);
diff --git a/ping/ping_echo.c b/ping/ping_echo.c
index 0f41b1bd..1aa69585 100644
--- a/ping/ping_echo.c
+++ b/ping/ping_echo.c
@@ -40,6 +40,7 @@
 #include <errno.h>
 #include <limits.h>
 #include <attribute.h>
+#include <timespec.h>
 
 #include <ping.h>
 #include "ping_impl.h"
@@ -177,12 +178,9 @@ print_echo (int dupflag, struct ping_stat *ping_stat,
 	    struct ip *ip, icmphdr_t *icmp, int datalen)
 {
   int hlen;
-  struct timeval tv;
-  int timing = 0;
+  bool timing = false;
   double triptime = 0.0;
 
-  gettimeofday (&tv, NULL);
-
   /* Length of IP header */
   hlen = ip->ip_hl << 2;
 
@@ -192,17 +190,20 @@ print_echo (int dupflag, struct ping_stat *ping_stat,
   /* Do timing */
   if (PING_TIMING (datalen - PING_HEADER_LEN))
     {
-      struct timeval tv1, *tp;
+      struct timeval tv;
+      struct timespec ts;
 
-      timing++;
-      tp = (struct timeval *) icmp->icmp_data;
+      timing = true;
 
-      /* Avoid unaligned data: */
-      memcpy (&tv1, tp, sizeof (tv1));
-      tvsub (&tv, &tv1);
+      /* Avoid unaligned data.  */
+      memcpy (&tv, icmp->icmp_data, sizeof (tv));
+      /* *INDENT-OFF* */
+      ts = timespec_sub (current_timespec (),
+                         (struct timespec) { .tv_sec = tv.tv_sec,
+                                             .tv_nsec = tv.tv_usec * 1000 });
+      /* *INDENT-ON* */
 
-      triptime = ((double) tv.tv_sec) * 1000.0 +
-	((double) tv.tv_usec) / 1000.0;
+      triptime = timespectod (ts) * 1000.0;
       ping_stat->tsum += triptime;
       ping_stat->tsumsq += triptime * triptime;
       if (triptime < ping_stat->tmin)
-- 
2.45.2

  • traceroute:... Collin Funk
    • Re: tr... Collin Funk
      • Re... Simon Josefsson via Bug reports for the GNU Internet utilities
        • ... Collin Funk
          • ... Simon Josefsson via Bug reports for the GNU Internet utilities

Reply via email to