Skip to content

ACP: Alter Display for Ipv6Addr for IPv4-compatible addresses #239

Closed
@clarfonthey

Description

@clarfonthey

Proposal

(The main reason for filing an ACP here is because it does change the behaviour of Display slightly in an observable way, and not for indisputable reasons.)

Problem statement

In IPv6, devices are generally given access to a majority of the latter 64 bits of the address space and can freely select an address that does not conflict with others on the same network. When representing addresses, it's common to provide a "token" that sets the latter 64 bits while leaving the former 64 bits empty, so that the network prefix and the token can be ORed together to create a valid address. In these cases, if the "token" address only occupies the latter 32 bits of the address, the Display implementation for Ipv6Addr will show the address as a (deprecated) IPv4-compatible address in decimal notation rather than an IPv6 address in hexadecimal notation.

Note that ::1 is an exception to this rule and always displayed in hexadecimal notation.

Motivating examples or use cases

While the IPv4-mapped address scheme (::ffff:a.b.c.d) is still valid, the IPv4-compatible address scheme (::a.b.c.d) is deprecated. This makes it much more likely that a user will want to see the hexadecimal notation for the latter case instead of the decimal notation. The standard only suggests using the decimal notation when it's unambiguous, and this implies only the former is unambiguous: https://datatracker.ietf.org/doc/html/rfc5952#section-5

Certain networking configurations(*) accept an IPv6 token, and it's desirable to be able to treat this as a simple Ipv6Addr in Rust code. Additionally, applications may wish to represent addresses using tokens in their own code; see #235 for a potential API that could make this more desirable.

(*) Example from systemd-networkd (see Token option): https://www.man7.org/linux/man-pages/man5/systemd.network.5.html#[DHCPPREFIXDELEGATION]_SECTION_OPTIONS

Solution sketch

In the Display impl for Ipv6Addr, we have this branch:

// ...
} else if let Some(ipv4) = self.to_ipv4() {
    match segments[5] {
        // IPv4 Compatible address
        0 => write!(f, "::{}", ipv4),
        // IPv4 Mapped address
        0xffff => write!(f, "::ffff:{}", ipv4),
        _ => unreachable!(),
    }
} else {
// ...

The proposed solution would change this to:

} else if let Some(ipv4) = self.to_ipv4_mapped() {
    write!(f, "::ffff:{}", ipv4)
} else {

Additionally, the code could be extended so that the alternate (#) flag uses the existing formatting with IPv4-compatible addresses. This would be the first case where the # flag is used for a Display implementation in the standard library (to my knowledge), but it would still be valid. The Debug implementation just directly calls the Display implementation.

Alternatives

The main alternative is for users to write their own formatting, which is nontrivial due to the fact that IPv6 formatting is rather complicated. This seems undesired due to the relative ease of modifying the libstd implementation.

The other alternative is to invert the meaning of the # flag as suggested, keeping existing behaviour by default but allowing the use of # to use the proposed behaviour. This might even be desired due to the fact that pretty-printing a struct containing IPv6 values will automatically apply this flag regardless.

Links and related work

N/A

What happens now?

This issue is part of the libs-api team API change proposal process. Once this issue is filed the libs-api team will review open proposals as capability becomes available. Current response times do not have a clear estimate, but may be up to several months.

Possible responses

The libs team may respond in various different ways. First, the team will consider the problem (this doesn't require any concrete solution or alternatives to have been proposed):

  • We think this problem seems worth solving, and the standard library might be the right place to solve it.
  • We think that this probably doesn't belong in the standard library.

Second, if there's a concrete solution:

  • We think this specific solution looks roughly right, approved, you or someone else should implement this. (Further review will still happen on the subsequent implementation PR.)
  • We're not sure this is the right solution, and the alternatives or other materials don't give us enough information to be sure about that. Here are some questions we have that aren't answered, or rough ideas about alternatives we'd want to see discussed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    ACP-acceptedAPI Change Proposal is accepted (seconded with no objections)T-libs-apiapi-change-proposalA proposal to add or alter unstable APIs in the standard libraries

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions