Modify the batctl ping utility to accept both integer and floating-point
values for the interval between sending pings. This enhancement allows
specifying intervals with millisecond precision.

For example:
`sudo batctl ping aa:bb:cc:dd:ee:ff -i 0.5`

Also, improve error handling for invalid interval arguments.

Signed-off-by: Noah Peterson <[email protected]>
---
 ping.c | 35 +++++++++++++++++++++++++++--------
 1 file changed, 27 insertions(+), 8 deletions(-)

diff --git a/ping.c b/ping.c
index 3681e7e..104b17c 100644
--- a/ping.c
+++ b/ping.c
@@ -16,6 +16,7 @@
 #include <signal.h>
 #include <fcntl.h>
 #include <string.h>
+#include <limits.h>
 #include <math.h>
 #include <stddef.h>
 #include <stdint.h>
@@ -65,14 +66,15 @@ static int ping(struct state *state, int argc, char **argv)
        struct bat_host *bat_host, *rr_host;
        ssize_t read_len;
        int ret = EXIT_FAILURE, res, optchar, found_args = 1;
-       int loop_count = -1, loop_interval = 0, timeout = 1, rr = 0, i;
+       int loop_count = -1, timeout = 1, rr = 0, i;
        unsigned int seq_counter = 0, packets_out = 0, packets_in = 0, 
packets_loss;
-       char *dst_string, *mac_string, *rr_string;
-       double time_delta;
+       char *dst_string, *mac_string, *rr_string, *end, *loop_interval = NULL;
+       double time_delta, ping_interval = 0.0;
        float min = 0.0, max = 0.0, avg = 0.0, mdev = 0.0;
        uint8_t last_rr_cur = 0, last_rr[BATADV_RR_LEN][ETH_ALEN];
        size_t packet_len;
        int disable_translate_mac = 0;
+       struct timespec req;
 
        while ((optchar = getopt(argc, argv, "hc:i:t:RT")) != -1) {
                switch (optchar) {
@@ -86,9 +88,7 @@ static int ping(struct state *state, int argc, char **argv)
                        ping_usage();
                        return EXIT_SUCCESS;
                case 'i':
-                       loop_interval = strtol(optarg, NULL , 10);
-                       if (loop_interval < 1)
-                               loop_interval = 1;
+                       loop_interval = strdup(optarg);
                        found_args += ((*((char*)(optarg - 1)) == optchar ) ? 1 
: 2);
                        break;
                case 't':
@@ -135,6 +135,25 @@ static int ping(struct state *state, int argc, char **argv)
                }
        }
 
+       if (loop_interval) {
+               errno = 0;
+               ping_interval = strtod(loop_interval, &end);
+               free(loop_interval);
+
+               if (errno || end != (loop_interval + strlen(loop_interval))) {
+                       fprintf(stderr, "Error - invalid ping interval '%s'\n", 
(ULONG_MAX / 1000000 - 1.0));
+                       goto out;
+               } else if (ping_interval >= (ULONG_MAX / 1000000 - 1.0)) {
+                       fprintf(stderr, "Error - ping interval too large\n");
+                       goto out;
+               } else {
+                       ping_interval = fmax(ping_interval, 0.001);
+               }
+
+               req.tv_sec = (long) (ping_interval);
+               req.tv_nsec = fmod(ping_interval, 1.0) * 1000000000l;
+       }
+
        if (!disable_translate_mac)
                dst_mac = translate_mac(state, dst_mac);
 
@@ -286,8 +305,8 @@ static int ping(struct state *state, int argc, char **argv)
                if (loop_count == 0)
                        continue;
 
-               if (loop_interval > 0)
-                       sleep(loop_interval);
+               if (ping_interval > 0.0)
+                       nanosleep(&req, NULL);
                else if ((tv.tv_sec != 0) || (tv.tv_usec != 0))
                        select(0, NULL, NULL, NULL, &tv);
        }
-- 
2.39.5 (Apple Git-154)

Reply via email to