From edb704a069b74618fe686664115dc4e84f084b09 Mon Sep 17 00:00:00 2001 From: Erik Auerswald Date: Sat, 30 Nov 2024 19:38:05 +0100 Subject: [PATCH] use correct data size when sending ICMP Timestamp ICMP Timestamp messages have a fixed size. The data portion following the ICMP header comprises 12 octets to hold three timestamps of 4 octets each. Giving the --icmp-timestamp option now automatically sets the data size to 12 octets. Error out when -b N is used together with --icmp-timestamp. Adjust man page to mention incompatibility of -b N, --size=N with --icmp-timestamp. Also mention in man page that cap_net_raw can be used instead of root privileges for ICMP Timestamp. --- ci/test-04-options-a-b.pl | 20 ++++++++++++++++++-- doc/fping.pod | 4 ++-- src/fping.c | 16 ++++++++++++---- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/ci/test-04-options-a-b.pl b/ci/test-04-options-a-b.pl index 90afa9b..36e3acb 100755 --- a/ci/test-04-options-a-b.pl +++ b/ci/test-04-options-a-b.pl @@ -1,6 +1,6 @@ #!/usr/bin/perl -w -use Test::Command tests => 47; +use Test::Command tests => 53; use Test::More; use Time::HiRes qw(gettimeofday tv_interval); @@ -127,7 +127,23 @@ $cmd->stderr_is_eq(""); my $cmd = Test::Command->new(cmd => "fping --icmp-timestamp -b 1000 127.0.0.1"); $cmd->exit_is_num(1); $cmd->stdout_is_eq(""); -$cmd->stderr_like(qr{Usage:}); +$cmd->stderr_like(qr{cannot change ICMP Timestamp size}); +} + +# fping -b --icmp-timestamp +{ +my $cmd = Test::Command->new(cmd => "fping -b 1000 --icmp-timestamp 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{cannot change ICMP Timestamp size}); +} + +# fping --icmp-timestamp -b 12 (ICMP Timestamp data size) +{ +my $cmd = Test::Command->new(cmd => "fping --icmp-timestamp -b 12 127.0.0.1"); +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(""); +$cmd->stderr_like(qr{cannot change ICMP Timestamp size}); } # fping -B diff --git a/doc/fping.pod b/doc/fping.pod index bc3a44d..e155a96 100644 --- a/doc/fping.pod +++ b/doc/fping.pod @@ -51,7 +51,7 @@ timestamp). The reported received data size includes the IP header (normally 20 bytes) and ICMP header (8 bytes), so the minimum total size is 40 bytes. Default is 56, as in B. Maximum is the theoretical maximum IP datagram size (64K), though most systems limit this to a smaller, system-dependent -number. +number. Cannot be used together with B<--icmp-timestamp>. =item B<-B>, B<--backoff>=I @@ -159,7 +159,7 @@ Set the interface (requires SO_BINDTODEVICE support). Send ICMP timestamp requests (ICMP type 13) instead of ICMP Echo requests. Cannot be used together with B<-b> because ICMP timestamp messages have a fixed size. -IPv4 only, requires root privileges. +IPv4 only, requires root privileges or cap_net_raw. =item B<-k>, B<--fwmark>=I diff --git a/src/fping.c b/src/fping.c index 1f57aa1..38fa0a3 100644 --- a/src/fping.c +++ b/src/fping.c @@ -144,6 +144,9 @@ extern int h_errno; /* sized so as to be like traditional ping */ #define DEFAULT_PING_DATA_SIZE 56 +/* ICMP Timestamp has a fixed payload size of 12 bytes */ +#define ICMP_TIMESTAMP_DATA_SIZE 12 + /* maxima and minima */ #ifdef FPING_SAFE_LIMITS #define MIN_INTERVAL 1 /* in millisec */ @@ -364,6 +367,7 @@ int check_source_flag = 0; int icmp_request_typ = 0; int print_tos_flag = 0; int print_ttl_flag = 0; +int size_flag = 0; #if defined(DEBUG) || defined(_DEBUG) int randomly_lose_flag, trace_flag, print_per_system_flag; int lose_factor; @@ -588,6 +592,7 @@ int main(int argc, char **argv) check_source_flag = 1; } else if (strstr(optparse_state.optlongname, "icmp-timestamp") != NULL) { icmp_request_typ = 13; + ping_data_size = ICMP_TIMESTAMP_DATA_SIZE; } else if (strstr(optparse_state.optlongname, "print-tos") != NULL) { print_tos_flag = 1; } else if (strstr(optparse_state.optlongname, "print-ttl") != NULL) { @@ -691,9 +696,7 @@ int main(int argc, char **argv) case 'b': if (sscanf(optparse_state.optarg, "%u", &ping_data_size) != 1) usage(1); - if (icmp_request_typ > 0) - usage(1); - + size_flag = 1; break; case 'h': @@ -973,6 +976,11 @@ int main(int argc, char **argv) exit(1); } + if (icmp_request_typ == 13 && size_flag != 0) { + fprintf(stderr, "%s: cannot change ICMP Timestamp size\n", prog); + exit(1); + } + if (count_flag) { if (verbose_flag) per_recv_flag = 1; @@ -2290,7 +2298,7 @@ int decode_icmp_ipv4( if(icp->icmp_type == ICMP_TSTAMPREPLY) { /* Check that reply_buf_len is sufficiently big to contain the timestamps */ - if (reply_buf_len < hlen + ICMP_MINLEN + 3 * sizeof(uint32_t)) { + if (reply_buf_len < hlen + ICMP_MINLEN + ICMP_TIMESTAMP_DATA_SIZE) { if (verbose_flag) { char buf[INET6_ADDRSTRLEN]; getnameinfo(response_addr, response_addr_len, buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST); -- 2.43.0