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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Next

- New option --print-reply-dst to show the destination address of the received reply packet (#461, thanks @gsnw-sebast)
- New option --oiface for outgoing interface (#463, thanks @gsnw-sebast)
- Add IPv6 support to --print-reply-dst (#462, thanks @gsnw-sebast)

## Bugfixes and other changes

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,7 +40,7 @@ sub get_ping_gid_range {
}

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

{
my $cmd = Test::Command->new(cmd => "$fping_copy 127.0.0.1");
Expand All @@ -54,6 +54,12 @@ sub test_unprivileged_works {
$cmd->stdout_like(qr{127\.0\.0\.1 is alive \(Reply-DST unknown\)\n});
$cmd->stderr_is_eq("");
}
{
my $cmd = Test::Command->new(cmd => "$fping_copy --print-reply-dst ::1");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{::1 is alive \(Reply-DST ::1\)\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
15 changes: 13 additions & 2 deletions 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 => 66;
use Test::Command tests => 69;
use Test::More;

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

# fping -J -c 1 --print-srcaddr 127.0.0.1
# fping -J -c 1 --print-reply-dst 127.0.0.1
{
my $cmd = Test::Command->new(cmd => "fping -J -c 1 --print-reply-dst 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"replyDst":\s"127\.0\.0\.1"\}\}
\{"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?$/);
$cmd->stderr_is_eq("");
}

# fping -J -c 1 --print-reply-dst ::1
{
my $cmd = Test::Command->new(cmd => "fping -J -c 1 --print-reply-dst ::1");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr/^\{"resp":\s\{"host":\s"::1",\s"seq":\s0,\s"size":\s\d+,\s"rtt":\s\d+\.\d+,\s"replyDst":\s"::1"\}\}
\{"summary":\s\{"host":\s"::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?$/);
$cmd->stderr_is_eq("");
}

# fping -J -c 1 -q 127.0.0.1
{
Expand Down
2 changes: 1 addition & 1 deletion doc/fping.pod
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ Set source address.

=item B<--print-reply-dst>

Displays the destination address of the received reply packet. (IPv6 is currently not supported).
Displays the destination address of the received reply packet.
Note this reflects the address as seen on the reply packet, not necessarily the
address the request was sent from. It is only printed for hosts that reply (not for timeouts),
and NAT between fping and the target can make it differ from the request's source or the reply's real origin.
Expand Down
46 changes: 39 additions & 7 deletions src/fping.c
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,13 @@ int main(int argc, char **argv)
#endif
} else if (strstr(optparse_state.optlongname, "print-reply-dst") != NULL) {
opt_print_reply_dst_on = 1;
#if defined(IPV6) && defined(IPV6_RECVPKTINFO)
if (socket6 >= 0) {
if (setsockopt(socket6, IPPROTO_IPV6, IPV6_RECVPKTINFO, &sock_opt_on, sizeof(sock_opt_on))) {
perror("setsockopt IPV6_RECVPKTINFO");
}
}
#endif
} else if (strstr(optparse_state.optlongname, "seqmap-timeout") != NULL) {
opt_seqmap_timeout = strtod_strict(optparse_state.optarg) * 1000000;
} else if (strstr(optparse_state.optlongname, "oiface") != NULL) {
Expand Down Expand Up @@ -2077,7 +2084,13 @@ int receive_packet(int64_t wait_time,
char *reply_buf,
size_t reply_buf_len,
int *ip_header_tos,
int *ip_header_ttl)
int *ip_header_ttl,
#ifdef IPV6
struct in6_addr *recv_dst_addr_ipv6
#else
void *recv_dst_addr_ipv6
#endif
)
{
struct timeval to;
int s = 0;
Expand Down Expand Up @@ -2161,6 +2174,11 @@ int receive_packet(int64_t wait_time,
if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_HOPLIMIT) {
memcpy(ip_header_ttl, CMSG_DATA(cmsg), sizeof(*ip_header_ttl));
}
if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
struct in6_pktinfo *pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
if (recv_dst_addr_ipv6)
memcpy(recv_dst_addr_ipv6, &pktinfo->ipi6_addr, sizeof(*recv_dst_addr_ipv6));
}
#endif
}
}
Expand Down Expand Up @@ -2384,7 +2402,8 @@ int decode_icmp_ipv6(
size_t reply_buf_len,
unsigned short *id,
unsigned short *seq,
IP_HEADER_RESULT *ip_header_res)
IP_HEADER_RESULT *ip_header_res,
struct in6_addr *local_addr)
{
struct icmp6_hdr *icp;

Expand Down Expand Up @@ -2494,8 +2513,10 @@ int decode_icmp_ipv6(
*seq = ntohs(icp->icmp6_seq);

if (opt_print_reply_dst_on) {
strncpy(ip_header_res->reply_dst_addr, "not supported", sizeof(ip_header_res->reply_dst_addr) - 1);
ip_header_res->reply_dst_addr[sizeof(ip_header_res->reply_dst_addr) - 1] = '\0';
if (local_addr == NULL || IN6_IS_ADDR_UNSPECIFIED(local_addr) || inet_ntop(AF_INET6, local_addr, ip_header_res->reply_dst_addr, sizeof(ip_header_res->reply_dst_addr)) == NULL) {
strncpy(ip_header_res->reply_dst_addr, "unknown", sizeof(ip_header_res->reply_dst_addr) - 1);
ip_header_res->reply_dst_addr[sizeof(ip_header_res->reply_dst_addr) - 1] = '\0';
}
}

return 1;
Expand All @@ -2517,6 +2538,11 @@ int wait_for_reply(int64_t wait_time)
unsigned short seq;
IP_HEADER_RESULT ip_header_res = default_ip_header_result();

#ifdef IPV6
struct in6_addr recv_dst_addr_ipv6;
memset(&recv_dst_addr_ipv6, 0, sizeof(recv_dst_addr_ipv6));
#endif

/* Receive packet */
result = receive_packet(wait_time, /* max. wait time, in ns */
&recv_time, /* reply_timestamp */
Expand All @@ -2525,7 +2551,12 @@ int wait_for_reply(int64_t wait_time)
buffer, /* reply_buf */
sizeof(buffer), /* reply_buf_len */
&ip_header_res.tos, /* TOS resp. TC byte */
&ip_header_res.ttl /* TTL resp. hop limit */
&ip_header_res.ttl, /* TTL resp. hop limit */
#ifdef IPV6
&recv_dst_addr_ipv6
#else
NULL
#endif
);

if (result <= 0) {
Expand Down Expand Up @@ -2567,7 +2598,8 @@ int wait_for_reply(int64_t wait_time)
sizeof(buffer),
&id,
&seq,
&ip_header_res)) {
&ip_header_res,
&recv_dst_addr_ipv6)) {
return 1;
}
if (id != ident6) {
Expand Down Expand Up @@ -3165,6 +3197,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-reply-dst show the destination address of the received reply packet (IPv6 is currently not supported).\n");
fprintf(out, " --print-reply-dst show the destination address of the received reply packet\n");
exit(is_error);
}
Loading