Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ Next

## New features

- New option --print-srcaddr to show used IP source address in output (#461, thanks @gsnw-sebast)

## Bugfixes and other changes

- ci: Removed travis-ci (#446, thanks @gsnw-sebast)
Expand Down
8 changes: 7 additions & 1 deletion ci/test-11-unpriv.pl
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,20 @@ sub get_ping_gid_range {
}

sub test_unprivileged_works {
plan tests => 18;
plan tests => 21;

{
my $cmd = Test::Command->new(cmd => "$fping_copy 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_is_eq("127.0.0.1 is alive\n");
$cmd->stderr_is_eq("");
}
{
my $cmd = Test::Command->new(cmd => "$fping_copy --print-srcaddr 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{127\.0\.0\.1 is alive \(SRC (?:\d+\.\d+\.\d+\.\d+|unknown)\)\n});
$cmd->stderr_is_eq("");
}
{
my $cmd = Test::Command->new(cmd => "$fping_copy --print-tos 127.0.0.1");
$cmd->exit_is_num(0);
Expand Down
9 changes: 8 additions & 1 deletion ci/test-16-json-output.pl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/perl -w

use Test::Command tests => 63;
use Test::Command tests => 66;
use Test::More;

# fping -J -c 2 127.0.0.1
Expand Down Expand Up @@ -98,6 +98,13 @@
$cmd->stderr_is_eq("");
}

# fping -J -c 1 --print-srcaddr 127.0.0.1
my $cmd = Test::Command->new(cmd => "fping -J -c 1 --print-srcaddr 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr/^\{"resp":\s\{"host":\s"127\.0\.0\.1",\s"seq":\s0,\s"size":\s\d+,\s"rtt":\s\d+\.\d+,\s"src":\s"\d+\.\d+\.\d+\.\d+"\}\}
\{"summary":\s\{"host":\s"127\.0\.0\.1",\s"xmt":\s\d+,\s"rcv":\s\d+,\s"loss":\s\d+,\s"rttMin":\s\d+\.\d+,\s"rttAvg":\s\d+\.\d+,\s"rttMax":\s\d+\.\d+\}\}\n?$/);
Comment on lines +104 to +105
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The regular expression for testing --print-srcaddr with JSON output doesn't account for the case where the source address is unknown. As you noted in the pull request description, this can happen in some environments (like unprivileged mode on Linux). To make the test more robust, it should be updated to handle this case, similar to the test in ci/test-11-unpriv.pl.

$cmd->stdout_like(qr/^\{"resp":\s\{"host":\s"127\.0\.0\.1",\s"seq":\s0,\s"size":\s\d+,\s"rtt":\s\d+\.\d+,\s"src":\s"(?:\d+\.\d+\.\d+\.\d+|unknown)"\}\}
\{"summary":\s\{"host":\s"127\.0\.0\.1",\s"xmt":\s\d+,\s"rcv":\s\d+,\s"loss":\s\d+,\s"rttMin":\s\d+\.\d+,\s"rttAvg":\s\d+\.\d+,\s"rttMax":\s\d+\.\d+\}\}\n?$/);

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Under Ubuntu 22.04, the test ./fping --print-srcaddr 127.0.0.1 always returns unknown.
I tested this with ubuntu-latest on Azure DevOps, and the behavior does not occur there.

$cmd->stderr_is_eq("");

# fping -J -c 1 -q 127.0.0.1
{
my $cmd = Test::Command->new(cmd => "fping -J -c 1 -q 127.0.0.1");
Expand Down
6 changes: 6 additions & 0 deletions doc/fping.pod
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,12 @@ Print cumulative statistics upon exit.

Set source address.

=item B<--print-srcaddr>

Displays the used IP source address in the output. If B<fping> cannot read the source address,
"(SRC unknown)" is returned.
IPv6 is currently not supported.

=item B<--seqmap-timeout>=I<MSEC>

Timeout for sequence number mappings in milliseconds. Sequence numbers can
Expand Down
1 change: 1 addition & 0 deletions src/flags.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ int opt_print_netdata_on = 0;
int opt_print_json_on = 0;
int opt_print_tos_on = 0;
int opt_print_ttl_on = 0;
int opt_print_srcaddr_on = 0;
int opt_per_recv_on = 0;
int opt_report_all_rtts_on = 0;
int opt_name_on = 0;
Expand Down
1 change: 1 addition & 0 deletions src/flags.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ extern int opt_print_netdata_on;
extern int opt_print_json_on;
extern int opt_print_tos_on;
extern int opt_print_ttl_on;
extern int opt_print_srcaddr_on;
extern int opt_per_recv_on;
extern int opt_report_all_rtts_on;
extern int opt_name_on;
Expand Down
34 changes: 30 additions & 4 deletions src/fping.c
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,14 @@ char *icmp6_param_prob_str[ICMP6_PARAM_PROB_MAXCODE + 1] = {
#endif

IP_HEADER_RESULT default_ip_header_result() {
return (IP_HEADER_RESULT){-1, -1, 0x80000000U, 0x80000000U, 0x80000000U};
IP_HEADER_RESULT res;
res.tos = -1;
res.ttl = -1;
res.otime_ms = 0x80000000U;
res.rtime_ms = 0x80000000U;
res.ttime_ms = 0x80000000U;
res.src_addr[0] = '\0';
return res;
}

int event_storage_count;
Expand Down Expand Up @@ -533,6 +540,7 @@ int main(int argc, char **argv)
{ "check-source", 0, OPTPARSE_NONE },
{ "print-tos", 0, OPTPARSE_NONE },
{ "print-ttl", 0, OPTPARSE_NONE },
{ "print-srcaddr", 0, OPTPARSE_NONE },
{ "seqmap-timeout", 0, OPTPARSE_REQUIRED },
#if defined(DEBUG) || defined(_DEBUG)
{ NULL, 'z', OPTPARSE_REQUIRED },
Expand Down Expand Up @@ -596,6 +604,8 @@ int main(int argc, char **argv)
}
}
#endif
} else if (strstr(optparse_state.optlongname, "print-srcaddr") != NULL) {
opt_print_srcaddr_on = 1;
} else if (strstr(optparse_state.optlongname, "seqmap-timeout") != NULL) {
opt_seqmap_timeout = strtod_strict(optparse_state.optarg) * 1000000;
} else {
Expand Down Expand Up @@ -2216,9 +2226,10 @@ int decode_icmp_ipv4(
{
struct icmp *icp;
int hlen = 0;
struct ip *ip = NULL;

if (!using_sock_dgram4) {
struct ip *ip = (struct ip *)reply_buf;
ip = (struct ip *)reply_buf;
ip_header_res->tos = ip->ip_tos;
ip_header_res->ttl = ip->ip_ttl;

Expand Down Expand Up @@ -2331,6 +2342,13 @@ int decode_icmp_ipv4(
ip_header_res->ttime_ms = ntohl(icp->icmp_dun.id_ts.its_ttime);
}

if (opt_print_srcaddr_on) {
if (ip == NULL || inet_ntop(AF_INET, &ip->ip_dst, ip_header_res->src_addr, sizeof(ip_header_res->src_addr)) == NULL) {
strncpy(ip_header_res->src_addr, "unknown", sizeof(ip_header_res->src_addr) - 1);
ip_header_res->src_addr[sizeof(ip_header_res->src_addr) - 1] = '\0';
}
}

return hlen;
}

Expand All @@ -2341,7 +2359,8 @@ int decode_icmp_ipv6(
char *reply_buf,
size_t reply_buf_len,
unsigned short *id,
unsigned short *seq)
unsigned short *seq,
IP_HEADER_RESULT *ip_header_res)
{
struct icmp6_hdr *icp;

Expand Down Expand Up @@ -2450,6 +2469,11 @@ int decode_icmp_ipv6(
*id = icp->icmp6_id;
*seq = ntohs(icp->icmp6_seq);

if (opt_print_srcaddr_on) {
strncpy(ip_header_res->src_addr, "not supported", sizeof(ip_header_res->src_addr) - 1);
ip_header_res->src_addr[sizeof(ip_header_res->src_addr) - 1] = '\0';
}

return 1;
}
#endif
Expand Down Expand Up @@ -2518,7 +2542,8 @@ int wait_for_reply(int64_t wait_time)
buffer,
sizeof(buffer),
&id,
&seq)) {
&seq,
&ip_header_res)) {
return 1;
}
if (id != ident6) {
Expand Down Expand Up @@ -3113,5 +3138,6 @@ void usage(int is_error)
fprintf(out, " -X, --fast-reachable=N exits true immediately when N hosts are found\n");
fprintf(out, " --print-tos show received TOS value\n");
fprintf(out, " --print-ttl show IP TTL value\n");
fprintf(out, " --print-srcaddr show used IP source address (IPv6 is currently not supported).\n");
exit(is_error);
}
1 change: 1 addition & 0 deletions src/fping.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ typedef struct ip_header_result {
uint32_t otime_ms;
uint32_t rtime_ms;
uint32_t ttime_ms;
char src_addr[INET6_ADDRSTRLEN];
} IP_HEADER_RESULT;

typedef struct host_entry {
Expand Down
8 changes: 8 additions & 0 deletions src/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,10 @@ void print_recv_ext(IP_HEADER_RESULT *ip_header_res, int64_t recv_time, int64_t
ms_since_midnight_utc(recv_time));
}

if (ip_header_res->src_addr[0]) {
printf(" (SRC %s)", ip_header_res->src_addr);
}

if(opt_print_tos_on) {
if(ip_header_res->tos != -1) {
printf(" (TOS %d)", ip_header_res->tos);
Expand Down Expand Up @@ -278,6 +282,10 @@ void print_recv_ext_json(IP_HEADER_RESULT *ip_header_res, int64_t recv_time, int
printf("\"localreceive\": %u}", ms_since_midnight_utc(recv_time));
}

if (ip_header_res->src_addr[0]) {
printf(", \"src\": \"%s\"", ip_header_res->src_addr);
}

if(opt_print_tos_on) {
if(ip_header_res->tos != -1) {
printf(", \"tos\": %d", ip_header_res->tos);
Expand Down