From 83e61a06d5b904d362a413f2965575655bc65656 Mon Sep 17 00:00:00 2001 From: Erik Auerswald Date: Sun, 7 Jul 2024 14:09:07 +0200 Subject: [PATCH 1/4] align functions add_cidr() and add_range() * call freeaddrinfo() before checking the prefix length in add_cidr() * add a comment to the generator limit check in add_range() --- src/fping.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fping.c b/src/fping.c index e44f8d84..29901c93 100644 --- a/src/fping.c +++ b/src/fping.c @@ -1282,6 +1282,7 @@ void add_cidr(char *addr) exit(1); } net_addr = ntohl(((struct sockaddr_in *)addr_res->ai_addr)->sin_addr.s_addr); + freeaddrinfo(addr_res); /* check mask */ if (mask < 1 || mask > 32) { @@ -1310,8 +1311,6 @@ void add_cidr(char *addr) inet_ntop(AF_INET, &in_addr_tmp, buffer, sizeof(buffer)); add_name(buffer); } - - freeaddrinfo(addr_res); } void add_range(char *start, char *end) @@ -1355,6 +1354,7 @@ void add_range(char *start, char *end) end_long = ntohl(((struct sockaddr_in *)addr_res->ai_addr)->sin_addr.s_addr); freeaddrinfo(addr_res); + /* check if generator limit is exceeded */ if (end_long > start_long + MAX_GENERATE) { fprintf(stderr, "%s: -g parameter generates too many addresses\n", prog); exit(1); From 2303cccf0360276d7645135e0f88f12959824af0 Mon Sep 17 00:00:00 2001 From: Erik Auerswald Date: Sun, 7 Jul 2024 15:41:35 +0200 Subject: [PATCH 2/4] also apply generator limit to use with CIDR As described in GH issue #299, the MAX_GENERATE+1 limit is only applied when using an address range, not when using CIDR. This commit changes this to always honor the generator limit. * refactor target address generation to use the same new function for both range and CIDR notation * check the limit for addresses to generate in the new function * document the generator limit in "fping --help" output * document the generator limit in the fping man page * test that the address generation limit applies when using CIDR notation --- ci/test-06-options-f-h.pl | 10 +++++++++- doc/fping.pod | 3 +++ src/fping.c | 18 ++++++++++-------- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/ci/test-06-options-f-h.pl b/ci/test-06-options-f-h.pl index 1e226020..c9b520a0 100755 --- a/ci/test-06-options-f-h.pl +++ b/ci/test-06-options-f-h.pl @@ -1,6 +1,6 @@ #!/usr/bin/perl -w -use Test::Command tests => 72; +use Test::Command tests => 75; use Test::More; use File::Temp; @@ -170,6 +170,14 @@ $cmd->stderr_is_eq("fping: netmask must be between 1 and 32 (is: 0)\n"); } +# fping -g (cidr - too many addresses) +{ +my $cmd = Test::Command->new(cmd => "fping -g 127.0.0.0/8"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_is_eq("fping: -g parameter generates too many addresses\n"); +} + # fping -g (range - no IPv6 generator) SKIP: { if($ENV{SKIP_IPV6}) { diff --git a/doc/fping.pod b/doc/fping.pod index f7560b21..b9ca150a 100644 --- a/doc/fping.pod +++ b/doc/fping.pod @@ -294,6 +294,9 @@ line arguments, and 4 for a system call failure. =head1 RESTRICTIONS +The number of addresses that can be generated using the C<-g>, C<--generate> +option is limited to 100001. + If fping was configured with C<--enable-safe-limits>, the following values are not allowed for non-root users: diff --git a/src/fping.c b/src/fping.c index 29901c93..03b751bc 100644 --- a/src/fping.c +++ b/src/fping.c @@ -394,6 +394,7 @@ struct event *ev_dequeue(struct event_queue *queue); void ev_remove(struct event_queue *queue, struct event *event); void add_cidr(char *); void add_range(char *, char *); +void add_addr_range_ipv4(unsigned long, unsigned long); void print_warning(char *fmt, ...); int addr_cmp(struct sockaddr *a, struct sockaddr *b); void host_add_ping_event(HOST_ENTRY *h, int index, int64_t ev_time); @@ -1304,13 +1305,7 @@ void add_cidr(char *addr) } /* add all hosts in that network (net_addr and net_last inclusive) */ - for (; net_addr <= net_last; net_addr++) { - struct in_addr in_addr_tmp; - char buffer[20]; - in_addr_tmp.s_addr = htonl(net_addr); - inet_ntop(AF_INET, &in_addr_tmp, buffer, sizeof(buffer)); - add_name(buffer); - } + add_addr_range_ipv4(net_addr, net_last); } void add_range(char *start, char *end) @@ -1354,6 +1349,12 @@ void add_range(char *start, char *end) end_long = ntohl(((struct sockaddr_in *)addr_res->ai_addr)->sin_addr.s_addr); freeaddrinfo(addr_res); + /* add IPv4 addresses from closed interval [start_long,end_long] */ + add_addr_range_ipv4(start_long, end_long); +} + +void add_addr_range_ipv4(unsigned long start_long, unsigned long end_long) +{ /* check if generator limit is exceeded */ if (end_long > start_long + MAX_GENERATE) { fprintf(stderr, "%s: -g parameter generates too many addresses\n", prog); @@ -3013,7 +3014,8 @@ void usage(int is_error) fprintf(out, " -B, --backoff=N set exponential backoff factor to N (default: 1.5)\n"); fprintf(out, " -c, --count=N count mode: send N pings to each target and report stats\n"); fprintf(out, " -f, --file=FILE read list of targets from a file ( - means stdin)\n"); - fprintf(out, " -g, --generate generate target list (only if no -f specified)\n"); + fprintf(out, " -g, --generate generate target list (only if no -f specified),\n"); + fprintf(out, " limited to at most %d targets\n", MAX_GENERATE+1); fprintf(out, " (give start and end IP in the target list, or a CIDR address)\n"); fprintf(out, " (ex. %s -g 192.168.1.0 192.168.1.255 or %s -g 192.168.1.0/24)\n", prog, prog); fprintf(out, " -H, --ttl=N set the IP TTL value (Time To Live hops)\n"); From ce5d896a71e592751759cb01e57ba7fd82e393bc Mon Sep 17 00:00:00 2001 From: Erik Auerswald Date: Sun, 7 Jul 2024 16:30:23 +0200 Subject: [PATCH 3/4] fix off-by-one error in generator limit This commit does not add tests that verify the exact limit, because pinging 100000 localhost addresses takes over 15 minutes on my PC. I have tested this fix manually. --- doc/fping.pod | 2 +- src/fping.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/fping.pod b/doc/fping.pod index b9ca150a..7d20d391 100644 --- a/doc/fping.pod +++ b/doc/fping.pod @@ -295,7 +295,7 @@ line arguments, and 4 for a system call failure. =head1 RESTRICTIONS The number of addresses that can be generated using the C<-g>, C<--generate> -option is limited to 100001. +option is limited to 100000. If fping was configured with C<--enable-safe-limits>, the following values are not allowed for non-root users: diff --git a/src/fping.c b/src/fping.c index 03b751bc..ddffb287 100644 --- a/src/fping.c +++ b/src/fping.c @@ -1356,7 +1356,7 @@ void add_range(char *start, char *end) void add_addr_range_ipv4(unsigned long start_long, unsigned long end_long) { /* check if generator limit is exceeded */ - if (end_long > start_long + MAX_GENERATE) { + if (end_long >= start_long + MAX_GENERATE) { fprintf(stderr, "%s: -g parameter generates too many addresses\n", prog); exit(1); } @@ -3015,7 +3015,7 @@ void usage(int is_error) fprintf(out, " -c, --count=N count mode: send N pings to each target and report stats\n"); fprintf(out, " -f, --file=FILE read list of targets from a file ( - means stdin)\n"); fprintf(out, " -g, --generate generate target list (only if no -f specified),\n"); - fprintf(out, " limited to at most %d targets\n", MAX_GENERATE+1); + fprintf(out, " limited to at most %d targets\n", MAX_GENERATE); fprintf(out, " (give start and end IP in the target list, or a CIDR address)\n"); fprintf(out, " (ex. %s -g 192.168.1.0 192.168.1.255 or %s -g 192.168.1.0/24)\n", prog, prog); fprintf(out, " -H, --ttl=N set the IP TTL value (Time To Live hops)\n"); From e6a607705fa2ac1f1e2ed40d36c120d8418dfe44 Mon Sep 17 00:00:00 2001 From: Erik Auerswald Date: Sun, 7 Jul 2024 17:36:04 +0200 Subject: [PATCH 4/4] adjust generator limit to allow an IPv4 /15 --- doc/fping.pod | 3 ++- src/fping.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/fping.pod b/doc/fping.pod index 7d20d391..3fd73322 100644 --- a/doc/fping.pod +++ b/doc/fping.pod @@ -295,7 +295,8 @@ line arguments, and 4 for a system call failure. =head1 RESTRICTIONS The number of addresses that can be generated using the C<-g>, C<--generate> -option is limited to 100000. +option is limited to 131070 (the number of host addresses in one 15-bit IPv4 +prefix). If fping was configured with C<--enable-safe-limits>, the following values are not allowed for non-root users: diff --git a/src/fping.c b/src/fping.c index ddffb287..f7fe6a94 100644 --- a/src/fping.c +++ b/src/fping.c @@ -139,7 +139,7 @@ extern int h_errno; #define SIZE_ICMP_HDR 8 /* from ip_icmp.h */ #define MAX_PING_DATA (MAX_IP_PACKET - SIZE_IP_HDR - SIZE_ICMP_HDR) -#define MAX_GENERATE 100000 /* maximum number of hosts that -g can generate */ +#define MAX_GENERATE 131070 /* maximum number of hosts that -g can generate */ /* sized so as to be like traditional ping */ #define DEFAULT_PING_DATA_SIZE 56