134 lines
5.0 KiB
Diff
134 lines
5.0 KiB
Diff
|
From aa75473cac4a37cd673da3a66904878efcfdbd6f Mon Sep 17 00:00:00 2001
|
||
|
From: Petr Vorel <pvorel@suse.cz>
|
||
|
Date: Mon, 18 Oct 2021 15:13:44 +0200
|
||
|
Subject: [PATCH 2/3] ping: Print reply from Subnet-Router anycast address
|
||
|
|
||
|
by detecting Subnet-Router address for 64 bit prefix and suppress
|
||
|
address comparison check.
|
||
|
|
||
|
5e052ad ("ping: discard packets with wrong source address") correctly
|
||
|
hid replies with wrong source address to comply RFC 1122 (Section
|
||
|
3.2.1.3: "The IP source address in an ICMP Echo Reply MUST be the same
|
||
|
as the specific-destination address").
|
||
|
|
||
|
While change in 5e052ad works for broadcast and multicast addresses and
|
||
|
some of anycast addresses, it does not work for (at least) Subnet-Router
|
||
|
anycast address):
|
||
|
|
||
|
# VETH1_IPV6=fd00:dead:beef:1234::1
|
||
|
# VPEER1_IPV6=fd00:dead:beef:1234::2
|
||
|
# ip netns add ns-ipv6
|
||
|
# ip li add name veth1 type veth peer name vpeer1
|
||
|
# ip -6 addr add $VETH1_IPV6/64 dev veth1
|
||
|
# ip li set dev veth1 up
|
||
|
# ip li set dev vpeer1 netns ns-ipv6
|
||
|
# ip netns exec ns-ipv6 ip li set dev lo up
|
||
|
# ip netns exec ns-ipv6 ip -6 addr add $VPEER1_IPV6/64 dev vpeer1
|
||
|
# ip netns exec ns-ipv6 ip li set vpeer1 up
|
||
|
# ip netns exec ns-ipv6 ip -6 route add default dev vpeer1 via $VETH1_IPV6
|
||
|
# sysctl -w net.ipv6.conf.all.forwarding=1
|
||
|
|
||
|
$ ping -c1 ff02::1 # anycast - all nodes
|
||
|
PING ff02::1(ff02::1) 56 data bytes
|
||
|
64 bytes from fe80::9c9c:ffff:fe14:e9d2%vpeer1: icmp_seq=1 ttl=64 time=0.064 ms
|
||
|
|
||
|
$ ping -c1 ff02::2 # anycast - all routers
|
||
|
PING ff02::2(ff02::2) 56 data bytes
|
||
|
64 bytes from fe80::5496:9ff:fef5:8f01%vpeer1: icmp_seq=1 ttl=64 time=0.088 ms
|
||
|
|
||
|
$ ping -c1 -W5 fd00:dead:beef:1234:: # Subnet-Router anycast
|
||
|
PING fd00:dead:beef:1234::(fd00:dead:beef:1234::) 56 data bytes
|
||
|
|
||
|
Subnet-Router anycast address works for both busybox ping (without
|
||
|
printing the real source address) and fping:
|
||
|
|
||
|
$ busybox ping -c1 fd00:dead:beef:1234::
|
||
|
PING fd00:dead:beef:1234:: (fd00:dead:beef:1234::): 56 data bytes
|
||
|
64 bytes from fd00:dead:beef:1234::1: seq=0 ttl=64 time=0.122 ms
|
||
|
|
||
|
$ fping -c1 fd00:dead:beef:1234::
|
||
|
[<- fd00:dead:beef:1234::1]fd00:dead:beef:1234:: : [0], 64 bytes, 0.096 ms (0.096 avg, 0% loss)
|
||
|
|
||
|
RFC 4291 specifies Subnet-Router anycast address as [1]:
|
||
|
|
||
|
The Subnet-Router anycast address is predefined. Its format is as
|
||
|
follows:
|
||
|
| n bits | 128-n bits |
|
||
|
+------------------------------------------------+----------------+
|
||
|
| subnet prefix | 00000000000000 |
|
||
|
+------------------------------------------------+----------------+
|
||
|
|
||
|
The "subnet prefix" in an anycast address is the prefix that
|
||
|
identifies a specific link. This anycast address is syntactically
|
||
|
the same as a unicast address for an interface on the link with the
|
||
|
interface identifier set to zero.
|
||
|
|
||
|
=> to detect Subnet-Router anycast address we need to know prefix, which
|
||
|
we don't know, thus detect it for prefix 64 (the default IPv6 prefix).
|
||
|
|
||
|
[1] https://datatracker.ietf.org/doc/html/rfc4291#section-2.6.1
|
||
|
|
||
|
Fixes: 5e052ad ("ping: discard packets with wrong source address")
|
||
|
Closes: https://github.com/iputils/iputils/issues/371
|
||
|
|
||
|
Reported-by: Tim Sandquist
|
||
|
Signed-off-by: Petr Vorel <pvorel@suse.cz>
|
||
|
(cherry picked from commit 15a5e5c7aace5a7a782ff802988e04ed4c1148a5)
|
||
|
---
|
||
|
ping/ping.h | 1 +
|
||
|
ping/ping6_common.c | 12 +++++++++++-
|
||
|
2 files changed, 12 insertions(+), 1 deletion(-)
|
||
|
|
||
|
diff --git a/ping/ping.h b/ping/ping.h
|
||
|
index 86652bf..f26fdac 100644
|
||
|
--- a/ping/ping.h
|
||
|
+++ b/ping/ping.h
|
||
|
@@ -212,6 +212,7 @@ struct ping_rts {
|
||
|
#endif
|
||
|
|
||
|
/* Used only in ping6_common.c */
|
||
|
+ int subnet_router_anycast; /* Subnet-Router anycast (RFC 4291) */
|
||
|
struct sockaddr_in6 firsthop;
|
||
|
unsigned char cmsgbuf[4096];
|
||
|
size_t cmsglen;
|
||
|
diff --git a/ping/ping6_common.c b/ping/ping6_common.c
|
||
|
index fcb48be..d0d2d84 100644
|
||
|
--- a/ping/ping6_common.c
|
||
|
+++ b/ping/ping6_common.c
|
||
|
@@ -101,6 +101,7 @@ int ping6_run(struct ping_rts *rts, int argc, char **argv, struct addrinfo *ai,
|
||
|
struct socket_st *sock)
|
||
|
{
|
||
|
int hold, packlen;
|
||
|
+ size_t i;
|
||
|
unsigned char *packet;
|
||
|
char *target;
|
||
|
struct icmp6_filter filter;
|
||
|
@@ -247,6 +248,15 @@ int ping6_run(struct ping_rts *rts, int argc, char **argv, struct addrinfo *ai,
|
||
|
rts->pmtudisc = IPV6_PMTUDISC_DO;
|
||
|
}
|
||
|
|
||
|
+ /* detect Subnet-Router anycast at least for the default prefix 64 */
|
||
|
+ rts->subnet_router_anycast = 1;
|
||
|
+ for (i = 8; i < sizeof(struct in6_addr); i++) {
|
||
|
+ if (rts->whereto6.sin6_addr.s6_addr[i]) {
|
||
|
+ rts->subnet_router_anycast = 0;
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
if (rts->pmtudisc >= 0) {
|
||
|
if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &rts->pmtudisc,
|
||
|
sizeof rts->pmtudisc) == -1)
|
||
|
@@ -818,7 +828,7 @@ int ping6_parse_reply(struct ping_rts *rts, socket_st *sock,
|
||
|
}
|
||
|
|
||
|
if (icmph->icmp6_type == ICMP6_ECHO_REPLY) {
|
||
|
- if (!rts->multicast &&
|
||
|
+ if (!rts->multicast && !rts->subnet_router_anycast &&
|
||
|
memcmp(&from->sin6_addr.s6_addr, &rts->whereto6.sin6_addr.s6_addr, 16))
|
||
|
return 1;
|
||
|
if (!is_ours(rts, sock, icmph->icmp6_id))
|
||
|
--
|
||
|
2.46.0
|
||
|
|