The RA's Retransmission Timer field was being ignored. This resolves the IPv6
Core Conformance test, v6LC.2.1.5 [1].
Retransmission Timer is a 32-bit unsigned integer. The time, in milliseconds,
between retransmitted Neighbor Solicitation messages. Used by the Address
Resolution and Neighbor Unreachability Detection (NUD) algorithm.
Support setting a default value for the neighbour retransmission timer value with:
[Network]
IPv6RetransmissionTimeSec=<int>
By default, upon receiving a Router Advertisement with the Retransmission Timer
field set to a non-zero value, it will update the kernel's retransmit timer value.
To disable this behaviour, configure the UseIPv6RetransmissionTime= under the
[IPv6AcceptRA] section.
[IPv6AcceptRA]
UseIPv6RetransmissionTime=<bool>
RFC4861: Neighbor Discovery in IPv6
* Section 4.2 RA Message Format.
* Section 6.3.4 Processing Received Router Advertisements
A Router Advertisement field (e.g., Cur Hop Limit, Reachable Time,
and Retrans Timer) may contain a value denoting that it is
unspecified. In such cases, the parameter should be ignored and the
host should continue using whatever value it is already using. In
particular, a host MUST NOT interpret the unspecified value as
meaning change back to the default value that was in use before the
first Router Advertisement was received.
The RetransTimer variable SHOULD be copied from the Retrans Timer
field, if the received value is non-zero.
References
[1] IPv6 Core Conformance Spec (PDF)
Previously,
1. use the passed Route object as is when a route is requested,
2. when the route becomes ready to configure, convert the Route object
if necessary, to resolve outgoing interface name, and split multipath
routes, and save them to the associated interfaces,
3. configure the route with the passed Route object.
However, there are several inconsistencies with what kernel does:
- The kernel does not merge nor split IPv4 multipath routes. However, we
unconditionally split multipath routes to manage.
- The kernel does not set gateway or so to a route if it has nexthop ID.
Fortunately, I do not find any issues caused by the inconsistencies. But
for safety, let's manage routes in a consistent way with the kernel.
This makes,
1. when a route is requested, split IPv6 multipath routes, but keep IPv4
multipath routes as is, and queue (possibly multiple) requests for
the route.
2. when the route becomes ready to configure, resolve nexthop and interface
name, and requeue request if necessary.
3. configure the (possibly split) route.
By using the logic,
- Now we manage routes in a mostly consistent way with the kernel.
- We can drop ConvertedRoutes object.
- Hopefully the code becomes much simpler.
This also introduce an extra argument for route_dup(), but it is
currently unused, will be used later.
No functional change, just preparation for later commits.
Except for RTAX_CC_ALGO, all RTAX_XYZ attributes take uint32_t and
the kernel's default value is zero. So, let's unify handling of the
attributes.
This should not change any effective behavior. Just refactoring.
Then, split out route metric handling from networkd-route.c to
networkd-route-metric.c.
No functional change, just refactoring and preparation for later
commits.
Then, replace address_remove_and_drop() with it.
If an address is requested, and the request is already called,
we may not received its reply and notification from the kernel, and
the corresponding address object may not be remmbered. Even in such
case, we need to remove the address, otherwise the address will come
later after the function called.
This reverts commit 0ba8374bb8.
- link->network->ipv6_hop_limit must not be updated, as it may be used
by multiple interfaces,
- We may receive multiple RA from multiple routers with different hop
limit, and we should not make the default hop limit flicking,
- First of all, there is no reason that we need to update the default hop
limit,
- The original issue should be caused by the hash and compare functions
for Route object.
This reverts commit 4ccd48cb26.
From RFC 4861 section 4.2.
> The Router Lifetime applies only to the router's usefulness as a default
> router; it does not apply to information contained in other message fields
> or options. Options that need time limits for their information include
> their own lifetime fields.
Hence, based on the lifetime field of the message header, we should not
drop any other information.
Note that, in ndisc_router_process_default(), we have already dropp the
default gateway when the lifetime is zero. Hence, we can safely drop the
change.
A Lifetime of 0 indicates that the router is not a default router anymore
and associated default route should be discarded from host's routing table.
https://datatracker.ietf.org/doc/html/rfc4861
```
Router Lifetime
16-bit unsigned integer. The lifetime associated
with the default router in units of seconds. The
field can contain values up to 65535 and receivers
should handle any value, while the sending rules in
Section 6 limit the lifetime to 9000 seconds. A
Lifetime of 0 indicates that the router is not a
default router and SHOULD NOT appear on the default
router list. The Router Lifetime applies only to
the router's usefulness as a default router; it
does not apply to information contained in other
message fields or options. Options that need time
limits for their information include their own
lifetime fields.
```
received
RFC4191 – Section 2.3 Route Information Option's Prf field:
If the Reserved (10) value is received, the Route Information Option MUST be ignored.
RFC4861 Neighbor Discovery – Sections 4.2 and 6.3.4
From section 4.2. Router Advertisement Message Format:
Cur Hop Limit 8-bit unsigned integer. The default value that
should be placed in the Hop Count field of the IP
header for outgoing IP packets. A value of zero
means unspecified (by this router).
Before this patch, if a network has multiple routers and one of them
provides a captive portal, then the portal was overwritten or cleared
when another RA from another router is received.
This makes captive portals managed in the similar way as DNS servers or
DNS domains. So now captive portal can safely handled even if a network
has multiple routers.
This allows the correct, gracious, error handling to follow up in the
ndisc handler. Otherwise, an internal error is assumed and the interface
disabled.
Fixes: 9747955d2d ("ndisc: parse RFC8910 captive portal ipv6ra option")
This fixes an issue introduced by af2aea8bb6.
When an outdated address or route is passed to link_request_address()/route(),
then they return 0 and the address or route will not be assigned. Such
situation can happen when we receive RA with zero lifetime. In that
case, we should not unset Link.ndisc_configured flag, otherwise even
no new address nor route will assigned, the interface will enter to the
configuring state, and unnecessary DBus property change is emit and the state
file will be updated. That makes resolved or timesyncd triggered to
reconfigure the interface.
Fixes#25456.
Even if different preference is specified, the kernel merges multiple
routes with the same preference. This is problematic when a network has
multiple routers.
Fixes#25138.