From 55e1bc80f75a1dacc6f02da24a33543402bb3f93 Mon Sep 17 00:00:00 2001 From: Claudius Zingerli Date: Sun, 18 Feb 2018 20:49:41 +0100 Subject: ping: zorbid zero timeout Setting a timeout of zero (in fact: anything below one) makes ping wait infinitely. This commit exits on such values Reviewed-by: Sami Kerola --- ping.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ping.c b/ping.c index 74d74b9..48dc031 100644 --- a/ping.c +++ b/ping.c @@ -412,7 +412,7 @@ main(int argc, char **argv) break; case 'W': lingertime = atoi(optarg); - if (lingertime < 0 || lingertime > INT_MAX/1000000) + if (lingertime <= 0 || lingertime > INT_MAX / 1000000) { error(2, 0, "bad linger time: %s", optarg); lingertime *= 1000; break; -- cgit v1.2.1 From 918e824dc13a39e4d68fcd82fd2d248c9fba6bbd Mon Sep 17 00:00:00 2001 From: Claudius Zingerli Date: Sun, 18 Feb 2018 21:01:04 +0100 Subject: ping: add support for sub-second timeouts Timeouts (-W) were previously silently rounded down to the next lower integral number. Subsecond values were rounded to zero which resulted in infinite timeouts, therefore ping never exited if there were no responses and timeouts below 1s. This commit fixes this issue. [Sami: I changed ping_strtod() to return double. Claudius did updated needed value by pointer reference, and had multiplication by 1000 in wrapper function. I think that made understanding the code unnecessarily difficult, so implementation was slightly changed.] Reviewed-by: Sami Kerola Reference: https://github.com/iputils/iputils/pull/122 --- ping.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 48 insertions(+), 20 deletions(-) diff --git a/ping.c b/ping.c index 48dc031..2d3adc0 100644 --- a/ping.c +++ b/ping.c @@ -55,6 +55,7 @@ #include #include #include +#include #ifndef ICMP_FILTER #define ICMP_FILTER 1 @@ -182,6 +183,40 @@ static void set_socket_option(socket_st *sock, int level, int optname, const voi error(2, errno, "setsockopt"); } +/* Much like stdtod(3, but will fails if str is not valid number. */ +static double ping_strtod(const char *str, const char *err_msg) +{ + double num; + char *end = NULL; + + if (str == NULL || *str == '\0') + goto err; + errno = 0; +#ifdef USE_IDN + setlocale(LC_ALL, "C"); +#endif + num = strtod(str, &end); +#ifdef USE_IDN + setlocale(LC_ALL, ""); +#endif + if (errno || str == end || (end && *end)) + goto err; + switch (fpclassify(num)) { + case FP_NORMAL: + case FP_ZERO: + break; + default: + errno = ERANGE; + goto err; + } + return num; + err: + if (errno == ERANGE) + error(2, errno, "%s: %s", err_msg, str); + error(2, 0, "%s: %s", err_msg, str); + return num; +} + int main(int argc, char **argv) { @@ -275,27 +310,15 @@ main(int argc, char **argv) break; case 'i': { - double dbl; - char *ep; + double optval; - errno = 0; -#ifdef USE_IDN - setlocale(LC_ALL, "C"); -#endif - dbl = strtod(optarg, &ep); -#ifdef USE_IDN - setlocale(LC_ALL, ""); -#endif - - if (errno || *ep != '\0' || - !finite(dbl) || dbl < 0.0 || dbl >= (double)INT_MAX / 1000 - 1.0) + optval = ping_strtod(optarg, "bad timing interval"); + if (isgreater(optval, (double)(INT_MAX / 1000))) error(2, 0, "bad timing interval: %s", optarg); - - interval = (int)(dbl * 1000); - + interval = (int)(optval * 1000); options |= F_INTERVAL; - break; } + break; case 'I': /* IPv6 */ if (strchr(optarg, ':')) { @@ -411,10 +434,15 @@ main(int argc, char **argv) error(2, 0, "bad wait time: %s", optarg); break; case 'W': - lingertime = atoi(optarg); - if (lingertime <= 0 || lingertime > INT_MAX / 1000000) { + { + double optval; + + optval = ping_strtod(optarg, "bad linger time"); + if (isless(optval, 0.001) || isgreater(optval, (double)(INT_MAX / 1000))) error(2, 0, "bad linger time: %s", optarg); - lingertime *= 1000; + /* lingertime will be converted to usec later */ + lingertime = (int)(optval * 1000); + } break; default: usage(); -- cgit v1.2.1