Stabilize the "IP" feature by caass · Pull Request #76098 · rust-lang/rust (original) (raw)

Latest Status Update: #76098 (comment)


Continuation of #66584, since it seems to be dead. This is my first time contributing and I did my best to read through the rustc-dev-guide, but I'll be honest I kind of skipped around a little bit. If there's anything I need to do that hasn't been done yet in terms of process, please let me know and I'll do it 😄

The old PR seemed to me (could be wrong) to be almost done, but there were two issues that were left unresolved. I left a comment on the PR, but I'll copy/paste it here for convenience:

If I understand correctly, the blockers currently are:

  1. There should be some checking for IPv4 addresses mapped it IPv6 space (comment)

From the RFC:

Two types of IPv6 addresses are defined that carry an IPv4 address in the low-order 32 bits of the address. These are the "IPv4-Compatible IPv6 address" and the "IPv4-mapped IPv6 address".

[...]

The "IPv4-Compatible IPv6 address" was defined to assist in the IPv6 transition. The format of the "IPv4-Compatible IPv6 address" is as follows:

80 bits 16 bits 32 bits
0000..............................0000 0000 IPv4 address

[...]

A second type of IPv6 address that holds an embedded IPv4 address is defined. This address type is used to represent the addresses of IPv4 nodes as IPv6 addresses. The format of the "IPv4-mapped IPv6 address" is as follows:

80 bits 16 bits 32 bits
0000..............................0000 FFFF IPv4 address

If we already have capability to check IPv4 addresses, I feel like it's almost trivial to implement these rules for IPv6 as well if we just need to pad it with some extra bytes? Famous last words, I know...

  1. There's some concern over the need for both is_unicast_link_local_strict and is_unicast_link_local (comment)

From the commit that introduced the change:

RFC 4291 is a little unclear about what is a unicast link local address.
According to section 2.4, the entire fe80::/10 range is reserved for
these addresses, but section 2.5.3 defines a stricter format for such
addresses.

After a discussion is has been decided to add a different method for
each definition, so this commit:

From section 2.4:

Address type Binary prefix IPv6 notation Section
Unspecified 00...0 (128 bits) ::/128 2.5.2
Loopback 00...1 (128 bits) ::1/128 2.5.3
Multicast 11111111 FF00::/8 2.7
Link-Local unicast 1111111010 FE80::/10 2.5.6
Global Unicast (everything else)

Section section 2.5.3 seems...unrelated? It has to do with the loopback address. Section 2.5.6 however, is where the problem lies:

Link-Local addresses are for use on a single link. Link-Local addresses have the following format:

10 bits 16 bits 64 bits
1111111010 0 interface ID

So the difference in the spec is this:

Spec CIDR Start End Available
2.4 FE80::/10 fe80:0:0:0:0:0:0:0 febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff 2^118
2.5.6 FE80::/64 fe80:0:0:0:0:0:0:0 fe80:0:0:0:ffff:ffff:ffff:ffff 2^64

This does seem like an issue, so I did some more digging to figure out what's going on. I found this draft, which appears to have died. It does however point us in the right direction:

The RFC "IPv6 Address Archi" illustrates the format of the link-local addresses. From the illustration it MAY be understood that the length of the link-local prefix is 10 bits of value 1111111010 and 54 0 bits.

IANA lists the "IPv6 prefix", and "Address Block", to be "fe80::/10" on its website. It is possible that in the future the IETF could decide to use the bits 11-53.

The RFC 2464 "IPv6-over-Ethernet" states that the prefix for link-local addresses is "fe80::/64".

RFC 6874, "Representing IPv6 Zone Identifiers in Address Literals and Uniform Resource Identifiers" specifies the link-local addresses to be under prefix "fe80::/10".

I'm not an expert in reading IETF material -- far from it -- but I am vaguely aware of the passage of time. Most documents linked here that specify /64 are more recent than those specifying /10, unless I've missed some -- which is totally possible. Additionally, there are countless secondhand sources (blogs, stackoverflow, etc) online all talking about how /64 is what's commonly used.

Again, not an expert. I posted all this info here so someone more versed than me can evaluate and decide what the best course of action is. Without further input, I'd personally go ahead with just the one is_unicast_link_local that validates against /64, since it's a more strict subset of /10, and if someone runs into trouble with running custom link-local addresses outside of /64 space I kind of feel like that is a problem outside the scope of the Rust programming language, and is something they should talk to their network administrator about.

Edit: Per further discussion here and here, I've decided to simply remove the strict check to bring Rust's functionality more in line with other similar features in other languages (e.g. Go, C, Python) as well as the Linux kernel.

At the moment, this PR is just fast-forwarding the existing work done by @little-dude to be up-to-date with rust-lang/rust. I wanted to get some confirmation that this hasn't been implemented yet in some other way / i'm not duplicating work / this feature is still needed before I get started on the code. Thanks in advance for your time! ❤️