Merge bitcoin/bitcoin#36199: net: treat RFC 9637 new IPv6 documentation range as invalid

b48a27691d fuzz: assert invalid addresses are not routable (Fabian Jahr)
e6c775c6d6 net: treat RFC 9637 new IPv6 documentation range as invalid (Fabian Jahr)

Pull request description:

  [RFC 9637](https://www.rfc-editor.org/rfc/rfc9637.html) was newly introduced in 2024 but we don't handle this yet. This pull handles it in the same way as RFC 3849 of which 9637 is an extension.

  This came up in #36196 because the new `GetMappedAS()` benchmark from https://github.com/bitcoin/bitcoin/pull/35285 asserts on these addresses being unmapped. New maps using `--fill` couldn't be embedded because the filling assigns these addresses. Making this range invalid in the code fixes the benchmarks.

ACKs for top commit:
  0xB10C:
    ACK b48a27691d
  willcl-ark:
    ACK b48a27691d
  hodlinator:
    re-ACK b48a27691d
  sedited:
    ACK b48a27691d

Tree-SHA512: d28552c0620f2b4c7de311d9ddf90bffb0f2dfdac4d76e305fc6b8138c8f3f070958a8a50679b45e1875cb5b24f6a7a10297ad327200b3ed5cd5ab5338187bcc
This commit is contained in:
merge-script
2026-09-09 16:24:22 +02:00
4 changed files with 19 additions and 4 deletions

View File

@@ -343,6 +343,12 @@ bool CNetAddr::IsRFC3849() const
return IsIPv6() && HasPrefix(m_addr, std::array<uint8_t, 4>{0x20, 0x01, 0x0D, 0xB8});
}
bool CNetAddr::IsRFC9637() const
{
return IsIPv6() && HasPrefix(m_addr, std::array<uint8_t, 2>{0x3F, 0xFF}) &&
(m_addr[2] & 0xF0) == 0x00;
}
bool CNetAddr::IsRFC3964() const
{
return IsIPv6() && HasPrefix(m_addr, std::array<uint8_t, 2>{0x20, 0x02});
@@ -434,7 +440,7 @@ bool CNetAddr::IsValid() const
}
// documentation IPv6 address
if (IsRFC3849())
if (IsRFC3849() || IsRFC9637())
return false;
if (IsInternal())

View File

@@ -162,6 +162,7 @@ public:
bool IsRFC6598() const; // IPv4 ISP-level NAT (100.64.0.0/10)
bool IsRFC5737() const; // IPv4 documentation addresses (192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24)
bool IsRFC3849() const; // IPv6 documentation address (2001:0DB8::/32)
bool IsRFC9637() const; // IPv6 documentation address (3FFF::/20)
bool IsRFC3927() const; // IPv4 autoconfig (169.254.0.0/16)
bool IsRFC3964() const; // IPv6 6to4 tunnelling (2002::/16)
bool IsRFC4193() const; // IPv6 unique local (FC00::/7)

View File

@@ -55,7 +55,7 @@ FUZZ_TARGET(netaddress)
assert(net_addr.IsIPv4());
}
(void)net_addr.IsRFC2544();
if (net_addr.IsRFC3849() || net_addr.IsRFC3964() || net_addr.IsRFC4380() || net_addr.IsRFC4843() || net_addr.IsRFC7343() || net_addr.IsRFC4862() || net_addr.IsRFC6052() || net_addr.IsRFC6145()) {
if (net_addr.IsRFC3849() || net_addr.IsRFC3964() || net_addr.IsRFC4380() || net_addr.IsRFC4843() || net_addr.IsRFC7343() || net_addr.IsRFC4862() || net_addr.IsRFC6052() || net_addr.IsRFC6145() || net_addr.IsRFC9637()) {
assert(net_addr.IsIPv6());
}
(void)net_addr.IsRFC3927();
@@ -71,7 +71,9 @@ FUZZ_TARGET(netaddress)
(void)net_addr.IsRFC6145();
(void)net_addr.IsRFC6598();
(void)net_addr.IsRFC7343();
if (!net_addr.IsRoutable()) {
(void)net_addr.IsRFC9637();
const bool routable{net_addr.IsRoutable()};
if (!routable) {
assert(net_addr.GetNetwork() == Network::NET_UNROUTABLE || net_addr.GetNetwork() == Network::NET_INTERNAL);
}
if (net_addr.IsTor()) {
@@ -83,7 +85,9 @@ FUZZ_TARGET(netaddress)
if (net_addr.IsCJDNS()) {
assert(net_addr.GetNetwork() == Network::NET_CJDNS);
}
(void)net_addr.IsValid();
if (!net_addr.IsValid()) {
assert(!routable);
}
(void)net_addr.ToStringAddr();
const CSubNet sub_net{net_addr, fuzzed_data_provider.ConsumeIntegral<uint8_t>()};

View File

@@ -59,6 +59,9 @@ BOOST_AUTO_TEST_CASE(netbase_properties)
BOOST_CHECK(ResolveIP("198.18.0.0").IsRFC2544());
BOOST_CHECK(ResolveIP("198.19.255.255").IsRFC2544());
BOOST_CHECK(ResolveIP("2001:0DB8::").IsRFC3849());
BOOST_CHECK(ResolveIP("3FFF::").IsRFC9637());
BOOST_CHECK(ResolveIP("3FFF:0FFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF").IsRFC9637());
BOOST_CHECK(!ResolveIP("3FFF:1000::").IsRFC9637());
BOOST_CHECK(ResolveIP("169.254.1.1").IsRFC3927());
BOOST_CHECK(ResolveIP("2002::1").IsRFC3964());
BOOST_CHECK(ResolveIP("FC00::").IsRFC4193());
@@ -73,6 +76,7 @@ BOOST_AUTO_TEST_CASE(netbase_properties)
BOOST_CHECK(ResolveIP("8.8.8.8").IsRoutable());
BOOST_CHECK(ResolveIP("2001::1").IsRoutable());
BOOST_CHECK(ResolveIP("127.0.0.1").IsValid());
BOOST_CHECK(!ResolveIP("3FFF::").IsValid());
BOOST_CHECK(CreateInternal("FD6B:88C0:8724:edb1:8e4:3588:e546:35ca").IsInternal());
BOOST_CHECK(CreateInternal("bar.com").IsInternal());