Description
This issue is split out of the larger discussion around stabilization of the ip
feature (tracking issue: #27709). The focus of this issue on the question of how Rust should support IPv4-in-IPv6 adresses.
There are two ways of representing an IPv4 address in a IPv6 address:
- As an IPv4-compatible IPv6 address:
::1.2.3.4
- As an IPv4-mapped IPv6 address:
::ffff:1.2.3.4
IPv4-compatible IPv6 addresses have been officially deprecated, see IEFT RFC #4291 Section 2.5.5.1.
To convert between Ipv4Addr
and Ipv6Addr
there are the following methods:
impl Ipv4Addr {
fn to_ipv6_mapped(&self) -> Ipv6Addr;
fn to_ipv6_compatible(&self) -> Ipv6Addr;
}
impl Ipv6Addr {
fn to_ipv4(&self) -> Option<Ipv4Addr>; // supports converting both IPv4-compatible and Ipv4-mapped addresses
#[unstable]
fn to_ipv4_mapped(&self) -> Option<Ipv4Addr>; // only supports converting IPv4-mapped addresses
}
Open Problems
Converting IPv4-compatible addresses
As pointed out in (#75019 (comment)) IEFT RFC #4291 Section 2.5.5.1 states:
Note: The IPv4 address used in the "IPv4-Compatible IPv6 address" must be a globally-unique IPv4 unicast address.
Currently to_ipv6_compatible
performs no such check. Because of this, and the fact that IPv4-compatible addresses have been deprecated it was suggested (#75019 (comment)) that to_ipv6_compatible
should be deprecated. There was reservation against this (#75019 (comment)), and instead the docs were updated to reflect that users will almost always want to use to_ipv6_mapped
and not to_ipv6_compatible
(#75150).
In the other direction it was suggested to change the behaviour of to_ipv4
to that of to_ipv4_mapped
(#76098 (comment)), and thus only support IPv4-mapped addresses and no longer IPv4-compatible addresses. to_ipv4_mapped
could then be removed. Another suggestion (#76098 (comment)) was to avoid changing the behaviour and instead stabilizie to_ipv4_mapped
and deprecate to_ipv4
.
Unresolved: Should to_ipv6_compatible
be changed or deprecated? Should to_ipv4
be changed or deprecated?
Handling IPv4-in-IPv6 addresses
#69772 raises the concern that other languages consider the IPv4-mapped ::ffff:127.0.0.1
to be localhost and Rust does not. This raised the broader question about which (if any) methods of Ipv6Addr
should consider IPv4-mapped or IPv4-compatible addresses. A tool was created to check what multiple other languages were doing, however Rust offers much more helper methods than many other languages so there is often nothing to compare against. See the tool output (#76098 (comment)) and conclusion (#76098 (comment)). The results of this were:
- Probably nothing should take IPv4-compatible addresses into account (Stabilize the "IP" feature #76098 (comment))
is_unspecified
should not take IPv4-mapped addresses into account (Stabilize the "IP" feature #76098 (comment))is_loopback
should take IPv4-mapped addresses into account (std::net::IpAddr: is_loopback failing on ipv4-in-ipv6 addresses #69772, Stabilize the "IP" feature #76098 (comment)), see PR ChangeIpv6Addr::is_loopback
to include IPv4-mapped loopback addresses #85655- For methods like
is_documentation
from the naming it unclear if we want this to mean "any address for documentation", and thus include IPv4 mapped addresses, or "addresses specifically reserved for documentation as per IETF RFC 3849" - For
is_global
it is also not clear what semantics we want (Stabilize the "IP" feature #76098 (comment))
Unresolved: Nail down semantics of is_global
and other helper methods. See also #85612 IP Utility Methods.
RFCs
- IPv6 Addresses with Embedded IPv4 Addresses: IETF RFC #4291 Section 2.5.5
- IPv6 Address Prefix Reserved for Documentation: IETF RFC 3849
Previous Discussion
- stabilize the "ip" feature: PR #66584
- Stabilize the "IP" feature: PR #76098
- Stabilize the "IP" feature (continued from Stabilize the "IP" feature #76098): PR #85585