net: recognize CJDNS addresses as such

In some cases addresses come from an external source as a string or as a
`struct sockaddr_in6`, without a tag to tell whether it is a private
IPv6 or a CJDNS address. In those cases interpret the address as a CJDNS
address instead of an IPv6 address if `-cjdnsreachable` is set and the
seemingly-IPv6-address belongs to `fc00::/8`. Those external sources are:

* `-externalip=`
* `-bind=`
* UPnP
* `getifaddrs(3)` (called through `-discover`)
* `addnode`
* `connect`
* incoming connections (returned by `accept(2)`)
This commit is contained in:
Vasil Dimov 2021-09-13 13:02:05 +02:00
parent e6890fcb44
commit 6387f397b3
No known key found for this signature in database
GPG Key ID: 54DF06F64B55CBBF
2 changed files with 30 additions and 5 deletions

View File

@ -230,9 +230,27 @@ std::optional<CAddress> GetLocalAddrForPeer(CNode *pnode)
return std::nullopt;
}
// learn a new local address
bool AddLocal(const CService& addr, int nScore)
/**
* If an IPv6 address belongs to the address range used by the CJDNS network and
* the CJDNS network is reachable (-cjdnsreachable config is set), then change
* the type from NET_IPV6 to NET_CJDNS.
* @param[in] service Address to potentially convert.
* @return a copy of `service` either unmodified or changed to CJDNS.
*/
CService MaybeFlipIPv6toCJDNS(const CService& service)
{
CService ret{service};
if (ret.m_net == NET_IPV6 && ret.m_addr[0] == 0xfc && IsReachable(NET_CJDNS)) {
ret.m_net = NET_CJDNS;
}
return ret;
}
// learn a new local address
bool AddLocal(const CService& addr_, int nScore)
{
CService addr{MaybeFlipIPv6toCJDNS(addr_)};
if (!addr.IsRoutable())
return false;
@ -409,7 +427,8 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
if (pszDest) {
std::vector<CService> resolved;
if (Lookup(pszDest, resolved, default_port, fNameLookup && !HaveNameProxy(), 256) && !resolved.empty()) {
addrConnect = CAddress(resolved[GetRand(resolved.size())], NODE_NONE);
const CService rnd{resolved[GetRand(resolved.size())]};
addrConnect = CAddress{MaybeFlipIPv6toCJDNS(rnd), NODE_NONE};
if (!addrConnect.IsValid()) {
LogPrint(BCLog::NET, "Resolver returned invalid address %s for %s\n", addrConnect.ToString(), pszDest);
return nullptr;
@ -1092,9 +1111,11 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr)) {
LogPrintf("Warning: Unknown socket family\n");
} else {
addr = CAddress{MaybeFlipIPv6toCJDNS(addr), NODE_NONE};
}
const CAddress addr_bind = GetBindAddress(hSocket);
const CAddress addr_bind{MaybeFlipIPv6toCJDNS(GetBindAddress(hSocket)), NODE_NONE};
NetPermissionFlags permissionFlags = NetPermissionFlags::None;
hListenSocket.AddSocketPermissionFlags(permissionFlags);
@ -2460,7 +2481,10 @@ NodeId CConnman::GetNewNodeId()
}
bool CConnman::Bind(const CService &addr, unsigned int flags, NetPermissionFlags permissions) {
bool CConnman::Bind(const CService& addr_, unsigned int flags, NetPermissionFlags permissions)
{
const CService addr{MaybeFlipIPv6toCJDNS(addr_)};
if (!(flags & BF_EXPLICIT) && !IsReachable(addr)) {
return false;
}

View File

@ -550,6 +550,7 @@ public:
}
friend class CServiceHash;
friend CService MaybeFlipIPv6toCJDNS(const CService& service);
};
class CServiceHash