Skip to content

Commit 29c1ed4

Browse files
committed
Add IPv6 support to --print-srcaddr
1 parent 9949f35 commit 29c1ed4

5 files changed

Lines changed: 59 additions & 10 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Next
44
## New features
55

66
- New option --print-srcaddr to show used IP source address in output (#461, thanks @gsnw-sebast)
7+
- Add IPv6 support to --print-srcaddr (#462, thanks @gsnw-sebast)
78
- New option --oiface for outgoing interface (#463, thanks @gsnw-sebast)
89

910
## Bugfixes and other changes

‎ci/test-11-unpriv.pl‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ sub get_ping_gid_range {
4040
}
4141

4242
sub test_unprivileged_works {
43-
plan tests => 21;
43+
plan tests => 24;
4444

4545
{
4646
my $cmd = Test::Command->new(cmd => "$fping_copy 127.0.0.1");
@@ -54,6 +54,12 @@ sub test_unprivileged_works {
5454
$cmd->stdout_like(qr{127\.0\.0\.1 is alive \(SRC (?:\d+\.\d+\.\d+\.\d+|unknown)\)\n});
5555
$cmd->stderr_is_eq("");
5656
}
57+
{
58+
my $cmd = Test::Command->new(cmd => "$fping_copy --print-srcaddr ::1");
59+
$cmd->exit_is_num(0);
60+
$cmd->stdout_like(qr{::1 is alive \(SRC (?:::1|unknown)\)\n});
61+
$cmd->stderr_is_eq("");
62+
}
5763
{
5864
my $cmd = Test::Command->new(cmd => "$fping_copy --print-tos 127.0.0.1");
5965
$cmd->exit_is_num(0);

‎ci/test-16-json-output.pl‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/perl -w
22

3-
use Test::Command tests => 66;
3+
use Test::Command tests => 69;
44
use Test::More;
55

66
# fping -J -c 2 127.0.0.1
@@ -99,11 +99,22 @@
9999
}
100100

101101
# fping -J -c 1 --print-srcaddr 127.0.0.1
102+
{
102103
my $cmd = Test::Command->new(cmd => "fping -J -c 1 --print-srcaddr 127.0.0.1");
103104
$cmd->exit_is_num(0);
104105
$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+"\}\}
105106
\{"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?$/);
106107
$cmd->stderr_is_eq("");
108+
}
109+
110+
# fping -J -c 1 --print-srcaddr ::1
111+
{
112+
my $cmd = Test::Command->new(cmd => "fping -J -c 1 --print-srcaddr ::1");
113+
$cmd->exit_is_num(0);
114+
$cmd->stdout_like(qr/^\{"resp":\s\{"host":\s"::1",\s"seq":\s0,\s"size":\s\d+,\s"rtt":\s\d+\.\d+,\s"src":\s"::1"\}\}
115+
\{"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?$/);
116+
$cmd->stderr_is_eq("");
117+
}
107118

108119
# fping -J -c 1 -q 127.0.0.1
109120
{

‎doc/fping.pod‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,6 @@ Set source address.
263263

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

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

‎src/fping.c‎

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,13 @@ int main(int argc, char **argv)
607607
#endif
608608
} else if (strstr(optparse_state.optlongname, "print-srcaddr") != NULL) {
609609
opt_print_srcaddr_on = 1;
610+
#if defined(IPV6) && defined(IPV6_RECVPKTINFO)
611+
if (socket6 >= 0) {
612+
if (setsockopt(socket6, IPPROTO_IPV6, IPV6_RECVPKTINFO, &sock_opt_on, sizeof(sock_opt_on))) {
613+
perror("setsockopt IPV6_RECVPKTINFO");
614+
}
615+
}
616+
#endif
610617
} else if (strstr(optparse_state.optlongname, "seqmap-timeout") != NULL) {
611618
opt_seqmap_timeout = strtod_strict(optparse_state.optarg) * 1000000;
612619
} else if (strstr(optparse_state.optlongname, "oiface") != NULL) {
@@ -2077,7 +2084,13 @@ int receive_packet(int64_t wait_time,
20772084
char *reply_buf,
20782085
size_t reply_buf_len,
20792086
int *ip_header_tos,
2080-
int *ip_header_ttl)
2087+
int *ip_header_ttl,
2088+
#ifdef IPV6
2089+
struct in6_addr *recv_dst_addr_ipv6
2090+
#else
2091+
void *recv_dst_addr_ipv6
2092+
#endif
2093+
)
20812094
{
20822095
struct timeval to;
20832096
int s = 0;
@@ -2161,6 +2174,11 @@ int receive_packet(int64_t wait_time,
21612174
if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_HOPLIMIT) {
21622175
memcpy(ip_header_ttl, CMSG_DATA(cmsg), sizeof(*ip_header_ttl));
21632176
}
2177+
if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
2178+
struct in6_pktinfo *pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
2179+
if (recv_dst_addr_ipv6)
2180+
memcpy(recv_dst_addr_ipv6, &pktinfo->ipi6_addr, sizeof(*recv_dst_addr_ipv6));
2181+
}
21642182
#endif
21652183
}
21662184
}
@@ -2384,7 +2402,8 @@ int decode_icmp_ipv6(
23842402
size_t reply_buf_len,
23852403
unsigned short *id,
23862404
unsigned short *seq,
2387-
IP_HEADER_RESULT *ip_header_res)
2405+
IP_HEADER_RESULT *ip_header_res,
2406+
struct in6_addr *local_addr)
23882407
{
23892408
struct icmp6_hdr *icp;
23902409

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

24962515
if (opt_print_srcaddr_on) {
2497-
strncpy(ip_header_res->src_addr, "not supported", sizeof(ip_header_res->src_addr) - 1);
2498-
ip_header_res->src_addr[sizeof(ip_header_res->src_addr) - 1] = '\0';
2516+
if (local_addr == NULL || IN6_IS_ADDR_UNSPECIFIED(local_addr) || inet_ntop(AF_INET6, local_addr, ip_header_res->src_addr, sizeof(ip_header_res->src_addr)) == NULL) {
2517+
strncpy(ip_header_res->src_addr, "unknown", sizeof(ip_header_res->src_addr) - 1);
2518+
ip_header_res->src_addr[sizeof(ip_header_res->src_addr) - 1] = '\0';
2519+
}
24992520
}
25002521

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

2541+
#ifdef IPV6
2542+
struct in6_addr recv_dst_addr_ipv6;
2543+
memset(&recv_dst_addr_ipv6, 0, sizeof(recv_dst_addr_ipv6));
2544+
#endif
2545+
25202546
/* Receive packet */
25212547
result = receive_packet(wait_time, /* max. wait time, in ns */
25222548
&recv_time, /* reply_timestamp */
@@ -2525,7 +2551,12 @@ int wait_for_reply(int64_t wait_time)
25252551
buffer, /* reply_buf */
25262552
sizeof(buffer), /* reply_buf_len */
25272553
&ip_header_res.tos, /* TOS resp. TC byte */
2528-
&ip_header_res.ttl /* TTL resp. hop limit */
2554+
&ip_header_res.ttl, /* TTL resp. hop limit */
2555+
#ifdef IPV6
2556+
&recv_dst_addr_ipv6
2557+
#else
2558+
NULL
2559+
#endif
25292560
);
25302561

25312562
if (result <= 0) {
@@ -2567,7 +2598,8 @@ int wait_for_reply(int64_t wait_time)
25672598
sizeof(buffer),
25682599
&id,
25692600
&seq,
2570-
&ip_header_res)) {
2601+
&ip_header_res,
2602+
&recv_dst_addr_ipv6)) {
25712603
return 1;
25722604
}
25732605
if (id != ident6) {
@@ -3165,6 +3197,6 @@ void usage(int is_error)
31653197
fprintf(out, " -X, --fast-reachable=N exits true immediately when N hosts are found\n");
31663198
fprintf(out, " --print-tos show received TOS value\n");
31673199
fprintf(out, " --print-ttl show IP TTL value\n");
3168-
fprintf(out, " --print-srcaddr show used IP source address (IPv6 is currently not supported).\n");
3200+
fprintf(out, " --print-srcaddr show used IP source address\n");
31693201
exit(is_error);
31703202
}

0 commit comments

Comments
 (0)