diff options
author | Vasil Dimov <vd@FreeBSD.org> | 2021-09-13 13:02:05 +0200 |
---|---|---|
committer | Vasil Dimov <vd@FreeBSD.org> | 2021-11-03 14:58:50 +0100 |
commit | 6387f397b323b0fb4ca303fe418550f5465147c6 (patch) | |
tree | 28a81daab7dda4beb6920516290dd365b41c8ab4 | |
parent | e6890fcb440245c9a24ded0b7af46267453433f1 (diff) |
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)`)
-rw-r--r-- | src/net.cpp | 32 | ||||
-rw-r--r-- | src/netaddress.h | 1 |
2 files changed, 29 insertions, 4 deletions
diff --git a/src/net.cpp b/src/net.cpp index 8cf59f0b0d..82e55d4189 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -230,9 +230,27 @@ std::optional<CAddress> GetLocalAddrForPeer(CNode *pnode) return std::nullopt; } +/** + * 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) +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; } diff --git a/src/netaddress.h b/src/netaddress.h index 57eb8bc72f..f074c1d3ec 100644 --- a/src/netaddress.h +++ b/src/netaddress.h @@ -550,6 +550,7 @@ public: } friend class CServiceHash; + friend CService MaybeFlipIPv6toCJDNS(const CService& service); }; class CServiceHash |