Skip to content
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

IPv4-in-IPv6 Address Support #85609

Open
CDirkx opened this issue May 23, 2021 · 1 comment
Open

IPv4-in-IPv6 Address Support #85609

CDirkx opened this issue May 23, 2021 · 1 comment
Labels
C-enhancement Category: An issue proposing an enhancement or a PR with one. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Comments

@CDirkx
Copy link
Contributor

CDirkx commented May 23, 2021

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:

Unresolved: Nail down semantics of is_global and other helper methods. See also #85612 IP Utility Methods.

RFCs

Previous Discussion

@CDirkx CDirkx changed the title IPv4-in-IPv6 Adress Support IPv4-in-IPv6 Address Support May 23, 2021
bors added a commit to rust-lang-ci/rust that referenced this issue Aug 3, 2021
Commit to not supporting IPv4-in-IPv6 addresses

Stabilization of the `ip` feature has for a long time been blocked on the question of whether Rust should support handling "IPv4-in-IPv6" addresses: should the various `Ipv6Address` property methods take IPv4-mapped or IPv4-compatible addresses into account. See also the IPv4-in-IPv6 Address Support issue rust-lang#85609 and rust-lang#69772 which originally asked the question.

# Overview

In the recent PR rust-lang#85655 I proposed changing `is_loopback` to take IPv4-mapped addresses into account, so `::ffff:127.0.0.1` would be recognized as a looback address. However, due to the points that came up in that PR, I alternatively propose the following: Keeping the current behaviour and commit to not assigning any special meaning for IPv4-in-IPv6 addresses, other than what the standards prescribe. This would apply to the stable method `is_loopback`, but also to currently unstable methods like `is_global` and `is_documentation` and any future methods. This is implemented in this PR as a change in documentation, specifically the following section:

> Both types of addresses are not assigned any special meaning by this implementation, other than what the relevant standards prescribe. This means that an address like `::ffff:127.0.0.1`, while representing an IPv4 loopback address, is not itself an IPv6 loopback address; only `::1` is. To handle these so called "IPv4-in-IPv6" addresses, they have to first be converted to their canonical IPv4 address.

# Discussion

In the discussion for or against supporting IPv4-in-IPv6 addresses the question what would be least surprising for users of other languages has come up several times. At first it seemed most big other languages supported IPv4-in-IPv6 addresses (or at least considered `::ffff:127.0.0.1` a loopback address). However after further investigation it appears that supporting IPv4-in-IPv6 addresses comes down to how a language represents addresses. .Net and Go do not have a separate type for IPv4 or IPv6 addresses, and do consider `::ffff:127.0.0.1` a loopback address. Java and Python, which do have separate types, do not consider `::ffff:127.0.0.1` a loopback address. Seeing as Rust has the separate `Ipv6Addr` type, it would make sense to also not support IPv4-in-IPv6 addresses. Note that this focuses on IPv4-mapped addresses, no other language handles IPv4-compatible addresses.

Another issue that was raised is how useful supporting these IPv4-in-IPv6 addresses would be in practice. Again with the example of `::ffff:127.0.0.1`, considering it a loopback address isn't too useful as to use it with most of the socket APIs it has to be converted to an IPv4 address anyway. From that perspective it would be better to instead provide better ways for doing this conversion like stabilizing `to_ipv4_mapped` or introducing a `to_canonical` method.

A point in favour of not supporting IPv4-in-IPv6 addresses is that that is the behaviour Rust has always had, and that supporting it would require changing already stable functions like `is_loopback`. This also keeps the documentation of these functions simpler, as we only have to refer to the relevant definitions in the IPv6 specification.

# Decision

To make progress on the `ip` feature, a decision needs to be made on whether or not to support IPv4-in-IPv6 addresses.
There are several options:

- Keep the current implementation and commit to never supporting IPv4-in-IPv6 addresses (accept this PR).
- Support IPv4-in-IPv6 addresses in some/all `IPv6Addr` methods (accept PR rust-lang#85655).
- Keep the current implementation and but not commit to anything yet (reject both this PR and PR rust-lang#85655), this entire issue will however come up again in the stabilization of several methods under the `ip` feature.

There are more options, like supporting IPv4-in-IPv6 addresses in `IpAddr` methods instead, but to my knowledge those haven't been seriously argued for by anyone.

There is currently an FCP ongoing on PR rust-lang#85655. I would ask the libs team for an alternative FCP on this PR as well, which if completed means the rejection of PR rust-lang#85655, and the decision to commit to not supporting IPv4-in-IPv6 addresses.

If anyone feels there is not enough evidence yet to make the decision for or against supporting IPv4-in-IPv6 addresses, let me know and I'll do whatever I can to resolve it.
@Dylan-DPC Dylan-DPC added C-enhancement Category: An issue proposing an enhancement or a PR with one. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Feb 12, 2023
@tgross35
Copy link
Contributor

I think #69772 is related

@CDirkx this might be able to be closed since the referenced methods have all been stabilized. I am not sure if this issue is meant to be a discussion point for the semantics, but it seems like that is discussed elsewhere.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-enhancement Category: An issue proposing an enhancement or a PR with one. T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

3 participants