From 4621357d144bf48087b99f1473d15321231f34b9 Mon Sep 17 00:00:00 2001 From: Jakub Stasiak Date: Sat, 16 Dec 2023 01:31:37 +0100 Subject: [PATCH] Make is_global/is_unicast_global special address handling complete IANA explicitly documents 192.0.0.9/32, 192.0.0.9/32 and 2001:30::/28 as globally reachable[1][2] and the is_global implementations declare following IANA so let's make this happen. In case of 2002::/16 IANA says N/A so I think it's safe to say we shouldn't return true there either. [1] https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml [2] https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml --- library/core/src/net/ip_addr.rs | 12 ++++++++++-- library/core/tests/net/ip_addr.rs | 14 ++++++++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs index 1ef876a3163..4b5862d98a3 100644 --- a/library/core/src/net/ip_addr.rs +++ b/library/core/src/net/ip_addr.rs @@ -771,7 +771,11 @@ pub const fn is_global(&self) -> bool { || self.is_loopback() || self.is_link_local() // addresses reserved for future protocols (`192.0.0.0/24`) - ||(self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0) + // .9 and .10 are documented as globally reachable so they're excluded + || ( + self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0 + && self.octets()[3] != 9 && self.octets()[3] != 10 + ) || self.is_documentation() || self.is_benchmarking() || self.is_reserved() @@ -1515,8 +1519,12 @@ pub const fn is_global(&self) -> bool { // AS112-v6 (`2001:4:112::/48`) || matches!(self.segments(), [0x2001, 4, 0x112, _, _, _, _, _]) // ORCHIDv2 (`2001:20::/28`) - || matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b >= 0x20 && b <= 0x2F) + // Drone Remote ID Protocol Entity Tags (DETs) Prefix (`2001:30::/28`)` + || matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b >= 0x20 && b <= 0x3F) )) + // 6to4 (`2002::/16`) – it's not explicitly documented as globally reachable, + // IANA says N/A. + || matches!(self.segments(), [0x2002, _, _, _, _, _, _, _]) || self.is_documentation() || self.is_unique_local() || self.is_unicast_link_local()) diff --git a/library/core/tests/net/ip_addr.rs b/library/core/tests/net/ip_addr.rs index 7530fc08487..7f7802c221a 100644 --- a/library/core/tests/net/ip_addr.rs +++ b/library/core/tests/net/ip_addr.rs @@ -461,6 +461,10 @@ macro_rules! check { check!("198.18.54.2", benchmarking); check!("198.19.255.255", benchmarking); check!("192.0.0.0"); + check!("192.0.0.8"); + check!("192.0.0.9", global); + check!("192.0.0.10", global); + check!("192.0.0.11"); check!("192.0.0.255"); check!("192.0.0.100"); check!("240.0.0.0", reserved); @@ -480,6 +484,10 @@ macro_rules! ip { } macro_rules! check { + ($s:expr, &[$($octet:expr),*]) => { + check!($s, &[$($octet),*], 0); + }; + ($s:expr, &[$($octet:expr),*], $mask:expr) => { assert_eq!($s, ip!($s).to_string()); let octets = &[$($octet),*]; @@ -656,8 +664,8 @@ macro_rules! check { &[0x20, 1, 0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], global | unicast_global ); - - check!("2001:30::", &[0x20, 1, 0, 0x30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global); + check!("2001:30::", &[0x20, 1, 0, 0x30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], global | unicast_global); + check!("2001:40::", &[0x20, 1, 0, 0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global); check!( "2001:200::", @@ -665,6 +673,8 @@ macro_rules! check { global | unicast_global ); + check!("2002::", &[0x20, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global); + check!("fc00::", &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unique_local); check!(