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 noahbpeterson1997@gmail.com --- 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); }