-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rework Ipv6Addr::is_global
to check for global reachability rather than global scope
#86634
Conversation
r? @kennytm (rust-highfive has picked a reviewer for you, use r? to override) |
/// Returns [`true`] if the address appears to be globally routable. | ||
/// See [iana-ipv4-special-registry][ipv4-sr]. | ||
/// | ||
/// The following return [`false`]: | ||
/// | ||
/// - private addresses (see [`Ipv4Addr::is_private()`]) | ||
/// - the loopback address (see [`Ipv4Addr::is_loopback()`]) | ||
/// - the link-local address (see [`Ipv4Addr::is_link_local()`]) | ||
/// - the broadcast address (see [`Ipv4Addr::is_broadcast()`]) | ||
/// - addresses used for documentation (see [`Ipv4Addr::is_documentation()`]) | ||
/// - the unspecified address (see [`Ipv4Addr::is_unspecified()`]), and the whole | ||
/// `0.0.0.0/8` block | ||
/// - addresses reserved for future protocols (see | ||
/// [`Ipv4Addr::is_ietf_protocol_assignment()`], except | ||
/// `192.0.0.9/32` and `192.0.0.10/32` which are globally routable | ||
/// - addresses reserved for future use (see [`Ipv4Addr::is_reserved()`] | ||
/// - addresses reserved for networking devices benchmarking (see | ||
/// [`Ipv4Addr::is_benchmarking()`]) | ||
/// | ||
/// [ipv4-sr]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml | ||
/// Returns [`true`] if the address appears to be globally reachable | ||
/// as specified by the [IANA IPv4 Special-Purpose Address Registry]. | ||
/// Whether or not an address is practically reachable will depend on your network configuration. | ||
/// | ||
/// Most IPv4 addresses are globally reachable; | ||
/// unless they are specifically defined as *not* globally reachable. | ||
/// | ||
/// Non-exhaustive list of notable addresses that are not globally reachable: | ||
/// | ||
/// - The [unspecified address] ([`is_unspecified`](Ipv4Addr::is_unspecified)) | ||
/// - Addresses reserved for private use ([`is_private`](Ipv4Addr::is_private)) | ||
/// - Addresses in the shared address space ([`is_shared`](Ipv4Addr::is_shared)) | ||
/// - Loopback addresses ([`is_loopback`](Ipv4Addr::is_loopback)) | ||
/// - Link-local addresses ([`is_link_local`](Ipv4Addr::is_link_local)) | ||
/// - Addresses reserved for documentation ([`is_documentation`](Ipv4Addr::is_documentation)) | ||
/// - Addresses reserved for benchmarking ([`is_benchmarking`](Ipv4Addr::is_benchmarking)) | ||
/// - Reserved addresses ([`is_reserved`](Ipv4Addr::is_reserved)) | ||
/// - The [broadcast address] ([`is_broadcast`](Ipv4Addr::is_broadcast)) | ||
/// | ||
/// For the complete overview of which addresses are globally reachable, see the table at the [IANA IPv4 Special-Purpose Address Registry]. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reworded to a (in my opinion) less cluttered non-exhaustive list. Instead of trying to list every type of address and exceptions, we list the most notable ones (mostly the ones Rust has methods for) and refer to the Special Address Registry for the complete overview. A similar thing is done in the description of Ipv6Addr::is_global
.
// check if this address is 192.0.0.9 or 192.0.0.10. These addresses are the only two | ||
// globally routable addresses in the 192.0.0.0/24 range. | ||
if u32::from_be_bytes(self.octets()) == 0xc0000009 | ||
|| u32::from_be_bytes(self.octets()) == 0xc000000a | ||
{ | ||
return true; | ||
} | ||
!self.is_private() | ||
&& !self.is_loopback() | ||
&& !self.is_link_local() | ||
&& !self.is_broadcast() | ||
&& !self.is_documentation() | ||
&& !self.is_shared() | ||
&& !self.is_ietf_protocol_assignment() | ||
&& !self.is_reserved() | ||
&& !self.is_benchmarking() | ||
// Make sure the address is not in 0.0.0.0/8 | ||
&& self.octets()[0] != 0 | ||
!(self.octets()[0] == 0 // "This network" | ||
|| self.is_private() | ||
|| self.is_shared() | ||
|| self.is_loopback() | ||
|| self.is_link_local() | ||
|| (self.is_ietf_protocol_assignment() | ||
&& !( | ||
// Port Control Protocol Anycast (`192.0.0.9`) | ||
u32::from_be_bytes(self.octets()) == 0xc0000009 | ||
// Traversal Using Relays around NAT Anycast (`192.0.0.10`) | ||
|| u32::from_be_bytes(self.octets()) == 0xc000000a | ||
)) | ||
|| self.is_documentation() | ||
|| self.is_benchmarking() | ||
|| self.is_reserved() | ||
|| self.is_broadcast()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reordered the checks to match the order in the Special Address Registry.
@@ -1214,13 +1214,33 @@ impl Ipv6Addr { | |||
u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets()) | |||
} | |||
|
|||
/// Returns [`true`] if the address appears to be globally routable. | |||
/// Returns [`true`] if the address appears to be globally reachable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"globally reachable" instead of "globally routable", as that is the terminology used in the Special Address Registry.
/// Returns [`true`] if the address appears to be globally routable. | ||
/// Returns [`true`] if the address appears to be globally reachable | ||
/// as specified by the [IANA IPv6 Special-Purpose Address Registry]. | ||
/// Whether or not an address is practically reachable will depend on your network configuration. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you're not connected to the internet, you still can't reach a "globally reachable" address. I hope this also makes it clear that this method doesn't actually do any network traffic.
/// Note that an address having global scope is not the same as being globally reachable, | ||
/// and there is no direct relation between the two concepts: There exist addresses with global scope | ||
/// that are not globally reachable (for example unique local addresses), | ||
/// and addresses that are globally reachable without having global scope | ||
/// (multicast addresses with non-global scope). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trying to avoid the confusion between "globally reachable" and "global scope", the rename in #85696 from is_unicast_global
to has_unicast_global_scope
should hopefully help with this. Another possibility would be to rename is_global
to is_globally_reachable
.
check!("ff01::", multicast); | ||
check!("ff02::", multicast); | ||
check!("ff03::", multicast); | ||
check!("ff04::", multicast); | ||
check!("ff05::", multicast); | ||
check!("ff08::", multicast); | ||
check!("ff01::", global | multicast); | ||
check!("ff02::", global | multicast); | ||
check!("ff03::", global | multicast); | ||
check!("ff04::", global | multicast); | ||
check!("ff05::", global | multicast); | ||
check!("ff08::", global | multicast); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentioned in the PR description, multicast addresses with non-global scope are actually still globally reachable.
dabff95
to
2be1e92
Compare
2be1e92
to
9ddd5a5
Compare
Addressed an incorrect check pointed out in #86969 (comment) |
☔ The latest upstream changes (presumably #87535) made this pull request unmergeable. Please resolve the merge conflicts. |
…plett Add `Ipv6Addr::is_benchmarking` This PR adds the unstable method `Ipv6Addr::is_benchmarking`. This method is added for parity with `Ipv4Addr::is_benchmarking`, and I intend to use it in a future rework of `Ipv6Addr::is_global` (edit: rust-lang#86634) to more accurately follow the [IANA Special Address Registry](https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml) (like is done in `Ipv4Addr::is_global`). With `Ipv6Addr::is_benchmarking` and `Ipv4Addr::is_benchmarking` now both existing, `IpAddr::is_benchmarking` is also added.
…plett Add `Ipv6Addr::is_benchmarking` This PR adds the unstable method `Ipv6Addr::is_benchmarking`. This method is added for parity with `Ipv4Addr::is_benchmarking`, and I intend to use it in a future rework of `Ipv6Addr::is_global` (edit: rust-lang#86634) to more accurately follow the [IANA Special Address Registry](https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml) (like is done in `Ipv4Addr::is_global`). With `Ipv6Addr::is_benchmarking` and `Ipv4Addr::is_benchmarking` now both existing, `IpAddr::is_benchmarking` is also added.
Ping from triage: |
…se, r=Mark-Simulacrum Rework Ipv6Addr::is_global to check for global reachability rather than global scope - rebase Rebasing of pull request rust-lang#86634 off of master to try and get the feature "ip" stabilized. I also found a test failure in the rebase that is_global was considering the benchmark space to be globally reachable. This is related to my other rebasing pull request rust-lang#99947
This PR changes the unstable method
Ipv6Addr::is_global
to make it consistent withIpv4Addr::is_global
, checking for reachability rather than global scope (see also #85696 fixing this conflation inIpv6Addr::is_unicast_global
).To summarize, there are two concepts; an address can be globally reachable, and an address can have global scope. These concepts have been conflated in the past, but are not the same thing. There exist addresses with global scope that are not globally reachable (for example unique local addresses), and addresses that are globally reachable without having global scope (multicast addresses with non-global scope).
is_unicast_global
should be used to check for global scope, andis_global
for global reachability according to the IANA IPv6 Special-Purpose Address Registry, like is done inIpv4Addr::is_global
and other language implementations. (To prevent this confusion in the future, #85696 renamesis_unicast_global
tohas_unicast_global_scope
)The documentation of
Ipv4Addr::is_global
is also updated to make the two methods have similar descriptions and examples.