rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
94.72k stars 12.21k forks source link

IP Utility Methods #85612

Open CDirkx opened 3 years ago

CDirkx commented 3 years ago

This issue is split out of the larger discussion around stabilization of the ip feature (tracking issue: #27709). The focus of this issue is on the question of what utility methods Rust should provide for handling IPv4 and IPv6 addresses.

For discussion about the conversion methods (to_ipv6_mapped, to_ipv6_compatible, to_ipv4, to_ipv4_mapped) see #85609 IPv4-in-IPv6 Address Support.

For discussion about the IPv6 unicast methods (is_unicast_link_local, is_unicast_link_local_strict, is_unicast_site_local, is_unicast_global) see #85604 IPv6 Unicast Interface.

Specifically this issue concerns itself with the various special address utility methods:

impl Ipv4Addr {
    #[unstable]
    fn is_benchmarking(&self) -> bool;
    fn is_documentation(&self) -> bool;
    #[unstable]
    fn is_ietf_protocol_assignment(&self) -> bool;
    #[unstable]
    fn is_global(&self) -> bool;
    fn is_private(&self) -> bool;
    #[unstable]
    fn is_reserved(&self) -> bool;
    #[unstable]
    fn is_shared(&self) -> bool;
}

impl Ipv6Addr {
    #[unstable]
    fn is_documentation(&self) -> bool;
    #[unstable]
    fn is_global(&self) -> bool;
}

All of these excluding is_global currently correspond to various special addresses in the IANA IPv4 Special-Purpose Address Registry and IANA IPv6 Special-Purpose Address Registry.

Note that of these only Ipv4Addr::is_documentation and is_private are currently stable.

Open Problems

Semantics of utility methods

What should the exact semantics of is_global be? The current documentation of Ipv4Addr::is_global mentions the IANA IPv4 Special-Purpose Address Registry and follows it exactly, Ipv6Addr::is_global does not (https://github.com/rust-lang/rust/pull/76098#discussion_r558690082). For IPv6 specifically, should IPv4-mapped addresses be considered global? Python does not (https://github.com/rust-lang/rust/pull/76098#issuecomment-760651861). Is there an official definition for which addresses are globally reachable? What would be the least surprising to users.

There is a similar question for all the other methods: should we strictly adhere to standards and the address registry, or for IPv6 addresses also consider IPv4-mapped addresses. Is it a problem if the IPv4 version and IPv6 version of a method have different definitions?

Unresolved: Settle on the exact semantics of is_global and other methods. See also #85609 IPv4-in-IPv6 Address Support.

Which utility methods are useful

Which utility methods do we want to offer? Maybe offer the equivalent of is_reserved, is_benchmarking etc. for Ipv6Addr as well? Maybe not expose is_ietf_protocol_assignment (what would be a real-world use case for this other than computing is_global?) A lot of these methods are not offered by other languages, but .NET does have IsIPv6Teredo. is_ipv4_mapped and maybe is_ipv4_compatible could also be useful.

Unresolved: Which utility methods should be stabilized. How do we determine if a method is useful enough to be added.

Methods on both Ipv4Addr and Ipv6Addr

If methods like is_documentation and is_benchmarking are added to both Ipv4Addr and Ipv6Addr they can also be implemented for IpAddr. Does this make sense semantically? Is the definition of Ipv4Addr::is_documentation equivalent to Ipv6Addr::documentation? Does a user ever needs to check in practice if they have an IPv4 documentation address or an IPv6 documentation address? It has been suggested that for these common methods on IpAddr, Ipv4Addr and Ipv6Addr there could be a trait.

Unresolved: Which utility methods should be implemented for IpAddr.

Previous Discussion

the8472 commented 3 years ago

Is there an official definition for which addresses are globally reachable?

Yes and no. The spec defines global unicast as the complement of all the other special-purpose ranges. With a strong emphasis on "subject to change". And of course that covers pretty much everything, including ranges that won't be allocated for a very long time. So this is fundamentally different from the way IPv4 categories are defined.

https://datatracker.ietf.org/doc/html/rfc4291#section-2.4

CDirkx commented 3 years ago

I propose removing (or making private) the utility function Ipv4Addr::is_ietf_protocol_assignment and not adding a (public) equivalent Ipv6Addr::is_ietf_protocol_assignment. The method was introduced in #60145 along with other methods to be used in making is_global more accurate, however it can still be used for this purpose as a private function.

To me it is not clear what practical use of is_ietf_protocol_assignment is; I can't think of anything that a user might want to do with the knowledge that a certain address is reserved for IETF protocol assignment, outside of computing more useful properties like is_global or is is_special_use. It has been more than 2 years ago that this function was added, but I couldn't find any real usage in the wild: 1.

To me all of this suggest that is_ietf_protocol_assignment is not a good candidate for stabilization.

Edit: PR #86439 submitted

CDirkx commented 3 years ago

Regarding is_global: In the current implementation there is a conflation between the concepts of globally reachable, and having global scope. To address this I submitted #85696 to rework is_unicast_global and #86634 to rework is_global.

clubby789 commented 1 year ago

@rustbot label +T-libs