As per RFC requirements, upon removing a router from the default
router list, remove any entries pointing to it from the destination
cache. While here, synchronize timing out entries in the default
router list with the rest of the timer code.
When removing a netif, clear the destination cache altogether
in order to prevent more general inconsistency. When this happens,
the entries for other netifs will have to be rebuilt, but removing
netifs should be sufficiently rare that this is not worth optimizing.
The current ND implementation does not yet implement the most basic
required ('MUST') checks for message validation and generation.
- implement some of the required checks for message validation;
- document the remaining missing message validation checks;
- hardcode the hop limit of Neighbor Discovery messages rather than
having it depend on lwIP configuration which, if changed, would
cause all of ND to cease working.
The introduction of address lifetimes also means that lwIP correctly
supports transitions between PREFERRED and DEPRECATED address states,
and that means that the source address selection must be changed to
take this into account. Adding this feature to the previous algorithm
would have resulted in a mess, so this patch rewrites the algorithm to
stay close to the rules described in RFC 6724 (formerly 3484) Sec. 5.
This yields the following changes:
- Rule 2 ("prefer appropriate scope") is now fully implemented, most
importantly allowing larger-scope addresses to be picked if no
smaller-scope addresses are available (e.g., a global address may
now be used to connect to a unique-local address);
- Rule 3 ("avoid deprecated addresses") is now also fully implemented;
- unknown-scope addresses are also supported, with lowest priority;
- the link between the prescribed rules and the actual algorithm is
made much more explicit, hopefully allowing future improvements to
be made more easily.
For reasons explained in comments, one previous deviation from the RFC
on Rule 2 is retained for now.
As laid out in RFC 5942, the assumption that a dynamically assigned
(SLAAC/DHCPv6) address implies an on-link subnet, is wrong. lwIP does
currently make that assumption, routing packets according to local
address subnets rather than the on-link prefix list. The result is
that packets may not make it to their destination due to incorrect
routing decisions.
This patch changes the routing algorithms to be (more) compliant with
RFC 5942, by implementing the following new routing policies:
- all routing decisions check the on-link prefix list first, and
select a default router for off-link routing only if there is no
matching entry in the on-link prefix list;
- dynamically assigned addresses (from address autoconfiguration) are
considered /128 assignments, and thus, no routing decisions are taken
based on matches against their (/64) subnet anymore;
- more generally, all addresses that have a lifetime are considered
dynamically assigned and thus of size /128, which is the required
behavior for externally implemented SLAAC clients and DHCPv6;
- statically assigned (i.e., manually configured) addresses are still
considered /64 assignments, and thus, their associated subnet is
considered for routing decisions, in order to behave as generally
expected by end users and to retain backward compatibility;
- the link-local address in IPv6 address slot #0 is considered static
and thus has no lifetime and an implied /64 subnet, although link-
local routing is currently always handled separately anyway.
IPv6 source address selection is kept as is, as the subnet tests in
the algorithm serve as poor man's longest-common-prefix equivalent
there (RFC 6724 Sec. 5, Rule 8).
Previously, IPv6 routing could select a next-hop router on a netif
that was down or disconnected, potentially resulting in packets being
dropped unnecessarily. This patch changes router selection to take
into account the state of the router's associated netif, eliminating
such unnecessary packet loss.
Also, this patch fixes the test for router validity, which was
erroneously based on the router's invalidation timer rather than its
neighbor cache entry state. Given that an expired router has no
associated neighbor cache entry, no invalid routers would previously
ever be returned.
Finally, this patch also adds round-robin selection of routers that
are not known to be reachable or probably reachable, as per RFC 4861
Sec. 6.3.6 point (2). Support for this feature was partially present
but not actually functional.
For applications that use NETIF_STATUS_CALLBACK to help keep track of
extra per-address shadow state of IPv6 addresses, even in the light of
autogenerated addresses (which may "spontaneously" appear/disappear),
state transitions between tentative, duplicated, and invalid are
important as well. Therefore, invoke the status callback for all such
state transitions. Continue to filter out state changes between
various levels of progress of the tentative state, though.
Previously, Duplicate Address Detection (DAD) would work only for the
link-local address. For DAD-spawned Neighbor Solicitation requests for
any other address, the request would use the link-local address as the
source, meaning the other side would send a targeted reply (RFC 4861
Sec. 7.2.4). However, the nd6 implementation currently does not
consider targeted replies for DAD--even though technically an RFC 4862
Sec. 5.4.4 violation--supposedly because no real-world scenario could
trigger that case. The combination of these factors resulted in DAD
being entirely ineffective for non-link-local addresses.
This patch forces all DAD-spawned Neighbor Solicitation packets to use
the unspecified ('any') address as source, as per RFC 4862 Sec. 5.4.2.
As a result, other nodes would reply with multicast replies, for which
there is appropriate DAD checking code.
The patch also makes a slight rearrangement of statements such that
MLD join messages are sent before the NS packets, rather than after.
In the cases that nd6 checks whether the interface is up before
sending a packet, also check whether the link is up. Without this
additional check, temporary link downtime could easily result in
unnecessary false negatives for Duplicate Address Detection.
In addition, use the netif abstraction macros to perform the checks.
In summary, this patch aims to resolve bugs #47923 and #48162, by
decoupling address autoconfiguration from the on-link prefix list,
since those are not related. Important necessary changes are needed
to meet this goal, ultimately bringing the lwIP ND6 implementation
closer to compliance with RFC 4862. The main changes are:
1. support for address lifetimes, and,
2. addition of a new DUPLICATED address state.
The decoupling implies that the prefix list can no longer be used to
maintain state for address autoconfiguration. Most importantly, the
lifetime of each address, which was previously derived from the
prefix slot's lifetime, must now be associated with the address
itself. This patch implements address lifetime tracking, maintaining
both a valid and a preferred lifetime for each address, along with
the corresponding address state changes (e.g., between PREFERRED and
DEPRECATED), all as required by RFC 4862.
The support for address lifetimes can be enabled with a new
LWIP_IPV6_ADDRESS_LIFETIMES setting in lwipopts.h. It is required for
autoconfiguration and enabled by default if autoconfiguration is
enabled as well, but it may also be enabled separately, so as to allow
application-controlled lifetime management (e.g., if autoconfiguration
is implemented in a separate application). A special valid-lifetime of
zero is used to denote a static address--that is, an address that was
configured manually, that does not have lifetimes, and that should be
left alone by the autoconfiguration functionality. Addresses assigned
without setting a lifetime are deemed static, thus preserving
compatibility with existing lwIP-based applications in this respect.
Similarly, the decoupling implies that the prefix list can no longer
be used to remember cases of address duplication. Previously, the
detection of a duplicated address would simply result in removal of
the address altogether. Instead, this patch introduces a new state
"DUPLICATED", indicating that the address, while technically still
present, has been found to conflict with other node addresses, and no
attempt should be made to produce an autoconfiguration address for
that prefix.
Manually added addresses, including the link-local address, once set
to DUPLICATED, will remain in that state until manual intervention.
Autoconfigured DUPLICATED addresses will expire according to their
valid-lifetime, essentially preserving the current behavior but
without the use of the prefix list. As a first attempt to approach
compliance with RFC 4862 Sec. 5.4.5, if the link-local address is
detected to be duplicated, all derived addresses are marked duplicated
as well, and no new addresses will be autoconfigured. More work is to
be done for full compliance with that section, however.
Together, those two main changes indeed do fully decouple address
autoconfiguration from the on-link prefix list. Changes to the latter
thus no longer affect the former, resolving bug #47923. Moreover, as a
result, autoconfiguration can, and does, now also take place on
advertised prefixes that do not have the on-link flag set, resolving
bug #48162. The routing changes mentioned in the discussion of that
bug are left to a separate patch, though.
This patch adds a new RAW_FLAGS_HDRINCL flag to the raw core
implementation. When this flag is set on a RAW PCB, the raw send
routines expect the caller to supply an IP header for the given
packet, and will use that IP header instead of prepending one to
the packet themselves.
This feature allows the IP_HDRINCL socket option to be implemented
in higher layers with no further effort. Even thoguh that option is
traditionally supported for IPv4 sockets only (e.g., see RFC 3542
Sec. 3), the RAW_FLAGS_HDRINCL flag supports both IPv4 and IPv6, as
much of the lower-level infrastructure was already in place anyway.
Similar to the core UDP API, the new function may be used to implement
IPV6_PKTINFO (RFC 3542 Sec. 4), for example. This patch makes no
further functional changes; it merely moves code around a bit.
The support for connecting raw sockets is extended to match the
support for UDP sockets, while keeping the current API unchanged:
- for connected sockets, filter incoming packets on source address;
- use a flag to indicate whether a socket is connected, at no extra
memory cost; the application may check this flag if needed;
- added raw_disconnect(), which so far existed in documentation only.
The boolean condition of setting the WILL flag differs from that of appending the will message
Found by Axel Lin
(I fixed it the same way as Axel suggested, but I wanted a different commit message)
The caller of tcp_listen_with_backlog_and_err() usually check if the return
pcb is NULL before checking the err reason. I think the commit adding
tcp_listen_with_backlog_and_err() accidently change the behavior, Fix it.
Fixes: 98fc82fa71 ("added function tcp_listen_with_backlog_and_err() to get the error reason when listening fails")
Signed-off-by: Axel Lin <axel.lin@ingics.com>