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

Fix Ipv6Addr::is_unicast_global to check for unicast global scope #85696

Closed
wants to merge 3 commits into from

Conversation

CDirkx
Copy link
Contributor

@CDirkx CDirkx commented May 25, 2021

See #85604 for previous discussion.

The current behaviour of Ipv6Addr::is_unicast_global is

/// Returns [`true`] if the address is a globally routable unicast address.

This is inconsistent with methods like is_unicast_link_local and is_unicast_site_local, which check if an address has unicast link-local scope or site-local scope respectively. Similarly one would expect is_unicast_global to check if an address has unicast global scope (which is not the same thing as being globally routable, for that we already have Ipv6Addr::is_global which is reworked in #86634).

This PR changes the behaviour to

/// Returns `true` if the address is a unicast address with global scope, as defined in [RFC 4291].
///
/// Any unicast address has global scope if it is not:
///  - the [unspecified address] (`::`)
///  - the [loopback address] (`::1`)
///  - a [link-local address] (`fe80::/10`)

Basing itself on the following table from RFC 4291:

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)

The documentation is also updated to reflect that future RFCs may change the behaviour of this method: "Future specifications may redefine one or more sub-ranges of the Global Unicast space for other purposes".

The behaviour of is_global is kept the same, it used to delegate to is_unicast_global but now performs the checks for global reachability itself.

To avoid further confusion between is_unicast_global and is_global, and the concepts of "global scope" and "globally reachable", the folowing methods have been renamed:

@rust-highfive
Copy link
Collaborator

r? @joshtriplett

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label May 25, 2021
@the8472
Copy link
Member

the8472 commented May 25, 2021

What does that mean for unique local addresses now? Those clearly are not global and RFC 4291 doesn't even acknowledge their existence even though RFC 4193 predates it by a year.

Edit: Nevermind, I see is_global handles that now.

@CDirkx
Copy link
Contributor Author

CDirkx commented May 25, 2021

Yes that is where the difference between "global scope" and "globally reachable" comes into play. RFC 4193 has the following:

In practice, applications may treat these addresses like global scoped addresses.

Application and other higher level protocols can treat [Unique Local] IPv6 addresses in the same manner as other types of global unicast addresses. No special handling is required. This type of address may not be reachable, but that is no different from other types of IPv6 global unicast address.

So unique local addresses are indeed not globally reachable (which is implemented in is_global) but do have global scope.

@CDirkx
Copy link
Contributor Author

CDirkx commented May 25, 2021

Perhaps it would be less confusing to rename is_unicast_global (and the link-local and site-local versions) to has_unicast_global_scope etc. in order to distinguish it from is_global. Or alternatively rename is_global to is_globally_reachable.

I have already included in the documentation of is_unicast_global:

/// Note that an address that has global scope may still not be globally reachable.
/// If you want to check if an address appears to be globally reachable, use [`is_global`].

@CDirkx CDirkx changed the title Fix is_unicast_global to check for unicast global scope Fix Ipv6Addr::is_unicast_global to check for unicast global scope May 29, 2021
bors added a commit to rust-lang-ci/rust that referenced this pull request May 31, 2021
…r=joshtriplett

Remove `Ipv6Addr::is_unicast_link_local_strict`

Removes the unstable method `Ipv6Addr::is_unicast_link_local_strict` and keeps the behaviour of `Ipv6Addr::is_unicast_link_local`, see also rust-lang#85604 where I have tried to summarize related discussion so far.

My intent is for `is_unicast_link_local`, `is_unicast_site_local` and `is_unicast_global` to have the semantics of checking if an address has Link-Local, Site-Local or Global scope, see also rust-lang#85696 which changes the behaviour of `is_unicast_global` and renames these methods to `has_unicast_XXX_scope` to reflect this.

For checking Link-Local scope we currently have two methods: `is_unicast_link_local` and `is_unicast_link_local_strict`. This is because of what appears to be conflicting definitions in [IETF RFC 4291](https://datatracker.ietf.org/doc/html/rfc4291).

From [IETF RFC 4291 section 2.4](https://datatracker.ietf.org/doc/html/rfc4291#section-2.4): "Link-Local unicast" (`FE80::/10`)
```text
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)
```

From [IETF RFC 4291 section 2.5.6](https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.6): "Link-Local IPv6 Unicast Addresses" (`FE80::/64`)
```text
| 10 bits  |         54 bits         |          64 bits           |
+----------+-------------------------+----------------------------+
|1111111010|           0             |       interface ID         |
+----------+-------------------------+----------------------------+
```

With `is_unicast_link_local` checking `FE80::/10` and `is_unicast_link_local_strict` checking `FE80::/64`.

There is also [IETF RFC 5156 section 2.4](https://datatracker.ietf.org/doc/html/rfc5156#section-2.4) which defines "Link-Scoped Unicast" as `FE80::/10`.

It has been pointed out that implementations in other languages and the linux kernel all use `FE80::/10` (rust-lang#76098 (comment), rust-lang#76098 (comment)).

Given all of this I believe the correct interpretation to be the following: All addresses in `FE80::/10` are defined as having Link-Local scope, however currently only the block `FE80::/64` has been allocated for "Link-Local IPv6 Unicast Addresses". This might change in the future however; more addresses in `FE80::/10` could be allocated and those will have Link-Local scope. I therefore believe the current behaviour of `is_unicast_link_local` to be correct (if interpreting it to have the semantics of `has_unicast_link_local_scope`) and `is_unicast_link_local_strict` to be unnecessary, confusing and even a potential source of future bugs:

Currently there is no real difference in checking `FE80::/10` or `FE80::/64`, since any address in practice will be `FE80::/64`. However if an application uses `is_unicast_link_local_strict` to implement link-local (so non-global) behaviour, it will be incorrect in the future if addresses outside of `FE80::/64` are allocated.

r? `@joshtriplett` as reviewer of all the related PRs
@bors
Copy link
Contributor

bors commented May 31, 2021

☔ The latest upstream changes (presumably #85819) made this pull request unmergeable. Please resolve the merge conflicts.

@bors
Copy link
Contributor

bors commented Jun 9, 2021

☔ The latest upstream changes (presumably #86160) made this pull request unmergeable. Please resolve the merge conflicts.

@bors
Copy link
Contributor

bors commented Jun 16, 2021

☔ The latest upstream changes (presumably #85820) made this pull request unmergeable. Please resolve the merge conflicts.

@CDirkx
Copy link
Contributor Author

CDirkx commented Jun 16, 2021

I rebased and reordered the methods so now has_unicast_global_scope and has_unicast_link_local_scope are together (might look weird in the diff).

@CDirkx

This comment has been minimized.

@rustbot rustbot added A-io Area: `std::io`, `std::fs`, `std::net` and `std::path` T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels Jun 23, 2021
Comment on lines -1242 to +1245
None => self.is_unicast_global(),
None => {
self.has_unicast_global_scope()
&& !(self.is_unique_local() || self.is_documentation())
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implementation of is_global is changed completely in #86634

@crlf0710
Copy link
Member

Block on #86634

@crlf0710 crlf0710 added S-blocked Status: Blocked on something else such as an RFC or other implementation work. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 24, 2021
@bors
Copy link
Contributor

bors commented Oct 4, 2021

☔ The latest upstream changes (presumably #89512) made this pull request unmergeable. Please resolve the merge conflicts.

@chotchki
Copy link
Contributor

@CDirkx I'm trying to figure out where the "ip" feature left off and I think its on this rebase need. Am I correct?

@Mark-Simulacrum
Copy link
Member

Approved #99947, so going to go ahead and close this PR. #99947 contains the commits from here though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-io Area: `std::io`, `std::fs`, `std::net` and `std::path` S-blocked Status: Blocked on something else such as an RFC or other implementation work. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants