In many network environments, IPv6 peers cannot be reached, which is currently not detected. As a result, IPv6 addresses take up spots in AddrMan, and we make futile attempts to connect to them (e.g. feelers or network-specific connections). The reverse (IPv6 is reachable, but IPv4 isn't) is much rarer, but also possible.
This PR introduces an automatic check for IPv4/IPv6 reachability. The idea is to connect() a UDP socket to several well-known global unicast addresses. Because it's UDP, this only performs a local route lookup and source address selection, so no packets are sent out. Depending on specific error codes (e.g. ENETUNREACH), or if the selected source address is unusable (link-local, loopback), we decide that a network has no route. This is done conservatively to avoid false positives: in case of inconclusive evidence, the network stays reachable.
If the check finds no route for either IPv4 or IPv6 (but not both, because then we most likely have no connectivity at all), the network is marked as unreachable. This means we won't make automatic outbound connections to it, won't add new addresses from it to AddrMan, and relay its addresses slightly less. The first check runs one minute after startup rather than immediately, so that short gaps at startup (e.g. addresses still being configured) don't cause us to drop anchors or fixed seeds. After that, the check is repeated every 10 minutes, so the node can adapt to changing network conditions.
The check is disabled by any -onlynet setting, for networks reached through a proxy, and if automatic outbound connections are disabled (-connect).
This is related to #35750, which addresses the same problem from the AddrMan side (not counting failures on networks we can't reach).
I'll keep this PR in draft for a while, until I have more confidence that the check works on various systems and has no false positives. I also haven't explored the possibility of unit/functional tests for it yet.
Test reports are very welcome, especially from more uncommon setups (e.g. IPv6-only, NAT64, containers, VPNs, Windows/BSD). Running with -debug=net shows the reason for each decision.