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!(