mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-21 14:34:49 +01:00
Merge bitcoin/bitcoin#27071: Handle CJDNS from LookupSubNet()
0e6f6ebc06
net: remove unused CConnman::FindNode(const CSubNet&) (Vasil Dimov)9482cb780f
netbase: possibly change the result of LookupSubNet() to CJDNS (Vasil Dimov)53afa68026
net: move MaybeFlipIPv6toCJDNS() from net to netbase (Vasil Dimov)6e308651c4
net: move IsReachable() code to netbase and encapsulate it (Vasil Dimov)c42ded3d9b
fuzz: ConsumeNetAddr(): avoid IPv6 addresses that look like CJDNS (Vasil Dimov)64d6f77907
net: put CJDNS prefix byte in a constant (Vasil Dimov) Pull request description: `LookupSubNet()` would treat addresses that start with `fc` as IPv6 even if `-cjdnsreachable` is set. This creates the following problems where it is called: * `NetWhitelistPermissions::TryParse()`: otherwise `-whitelist=` fails to white list CJDNS addresses: when a CJDNS peer connects to us, it will be matched against IPv6 `fc...` subnet and the match will never succeed. * `BanMapFromJson()`: CJDNS bans are stored as just IPv6 addresses in `banlist.json`. Upon reading from disk they have to be converted back to CJDNS, otherwise, after restart, a ban entry like (`fc00::1`, IPv6) would not match a peer (`fc00::1`, CJDNS). * `RPCConsole::unbanSelectedNode()`: in the GUI the ban entries go through `CSubNet::ToString()` and back via `LookupSubNet()`. Then it must match whatever is stored in `BanMan`, otherwise it is impossible to unban via the GUI. These were uncovered by https://github.com/bitcoin/bitcoin/pull/26859. Thus, flip the result of `LookupSubNet()` to CJDNS if the network base address starts with `fc` and `-cjdnsreachable` is set. Since subnetting/masking does not make sense for CJDNS (the address is "random" bytes, like Tor and I2P, there is no hierarchy) treat `fc.../mask` as an invalid `CSubNet`. To achieve that, `MaybeFlipIPv6toCJDNS()` has to be moved from `net` to `netbase` and thus also `IsReachable()`. In the process of moving `IsReachable()`, `SetReachable()` and `vfLimited[]` encapsulate those in a class. ACKs for top commit: jonatack: Code review ACK0e6f6ebc06
achow101: ACK0e6f6ebc06
mzumsande: re-ACK0e6f6ebc06
Tree-SHA512: 4767a60dc882916de4c8b110ce8de208ff3f58daaa0b560e6547d72e604d07c4157e72cf98b237228310fc05c0a3922f446674492e2ba02e990a272d288bd566
This commit is contained in:
commit
0655e9dd92
13 changed files with 162 additions and 133 deletions
|
@ -682,7 +682,7 @@ CService HTTPRequest::GetPeer() const
|
|||
evhttp_connection_get_peer(con, (char**)&address, &port);
|
||||
#endif // HAVE_EVHTTP_CONNECTION_GET_PEER_CONST_CHAR
|
||||
|
||||
peer = LookupNumeric(address, port);
|
||||
peer = MaybeFlipIPv6toCJDNS(LookupNumeric(address, port));
|
||||
}
|
||||
return peer;
|
||||
}
|
||||
|
|
26
src/init.cpp
26
src/init.cpp
|
@ -1314,30 +1314,24 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
|||
}
|
||||
|
||||
if (args.IsArgSet("-onlynet")) {
|
||||
std::set<enum Network> nets;
|
||||
g_reachable_nets.RemoveAll();
|
||||
for (const std::string& snet : args.GetArgs("-onlynet")) {
|
||||
enum Network net = ParseNetwork(snet);
|
||||
if (net == NET_UNROUTABLE)
|
||||
return InitError(strprintf(_("Unknown network specified in -onlynet: '%s'"), snet));
|
||||
nets.insert(net);
|
||||
}
|
||||
for (int n = 0; n < NET_MAX; n++) {
|
||||
enum Network net = (enum Network)n;
|
||||
assert(IsReachable(net));
|
||||
if (!nets.count(net))
|
||||
SetReachable(net, false);
|
||||
g_reachable_nets.Add(net);
|
||||
}
|
||||
}
|
||||
|
||||
if (!args.IsArgSet("-cjdnsreachable")) {
|
||||
if (args.IsArgSet("-onlynet") && IsReachable(NET_CJDNS)) {
|
||||
if (args.IsArgSet("-onlynet") && g_reachable_nets.Contains(NET_CJDNS)) {
|
||||
return InitError(
|
||||
_("Outbound connections restricted to CJDNS (-onlynet=cjdns) but "
|
||||
"-cjdnsreachable is not provided"));
|
||||
}
|
||||
SetReachable(NET_CJDNS, false);
|
||||
g_reachable_nets.Remove(NET_CJDNS);
|
||||
}
|
||||
// Now IsReachable(NET_CJDNS) is true if:
|
||||
// Now g_reachable_nets.Contains(NET_CJDNS) is true if:
|
||||
// 1. -cjdnsreachable is given and
|
||||
// 2.1. -onlynet is not given or
|
||||
// 2.2. -onlynet=cjdns is given
|
||||
|
@ -1345,7 +1339,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
|||
// Requesting DNS seeds entails connecting to IPv4/IPv6, which -onlynet options may prohibit:
|
||||
// If -dnsseed=1 is explicitly specified, abort. If it's left unspecified by the user, we skip
|
||||
// the DNS seeds by adjusting -dnsseed in InitParameterInteraction.
|
||||
if (args.GetBoolArg("-dnsseed") == true && !IsReachable(NET_IPV4) && !IsReachable(NET_IPV6)) {
|
||||
if (args.GetBoolArg("-dnsseed") == true && !g_reachable_nets.Contains(NET_IPV4) && !g_reachable_nets.Contains(NET_IPV6)) {
|
||||
return InitError(strprintf(_("Incompatible options: -dnsseed=1 was explicitly specified, but -onlynet forbids connections to IPv4/IPv6")));
|
||||
};
|
||||
|
||||
|
@ -1375,7 +1369,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
|||
onion_proxy = addrProxy;
|
||||
}
|
||||
|
||||
const bool onlynet_used_with_onion{args.IsArgSet("-onlynet") && IsReachable(NET_ONION)};
|
||||
const bool onlynet_used_with_onion{args.IsArgSet("-onlynet") && g_reachable_nets.Contains(NET_ONION)};
|
||||
|
||||
// -onion can be used to set only a proxy for .onion, or override normal proxy for .onion addresses
|
||||
// -noonion (or -onion=0) disables connecting to .onion entirely
|
||||
|
@ -1410,7 +1404,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
|||
"reaching the Tor network is not provided: none of -proxy, -onion or "
|
||||
"-listenonion is given"));
|
||||
}
|
||||
SetReachable(NET_ONION, false);
|
||||
g_reachable_nets.Remove(NET_ONION);
|
||||
}
|
||||
|
||||
for (const std::string& strAddr : args.GetArgs("-externalip")) {
|
||||
|
@ -1885,12 +1879,12 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
|||
}
|
||||
SetProxy(NET_I2P, Proxy{addr.value()});
|
||||
} else {
|
||||
if (args.IsArgSet("-onlynet") && IsReachable(NET_I2P)) {
|
||||
if (args.IsArgSet("-onlynet") && g_reachable_nets.Contains(NET_I2P)) {
|
||||
return InitError(
|
||||
_("Outbound connections restricted to i2p (-onlynet=i2p) but "
|
||||
"-i2psam is not provided"));
|
||||
}
|
||||
SetReachable(NET_I2P, false);
|
||||
g_reachable_nets.Remove(NET_I2P);
|
||||
}
|
||||
|
||||
connOptions.m_i2p_accept_incoming = args.GetBoolArg("-i2pacceptincoming", DEFAULT_I2P_ACCEPT_INCOMING);
|
||||
|
|
60
src/net.cpp
60
src/net.cpp
|
@ -115,7 +115,6 @@ bool fDiscover = true;
|
|||
bool fListen = true;
|
||||
GlobalMutex g_maplocalhost_mutex;
|
||||
std::map<CNetAddr, LocalServiceInfo> mapLocalHost GUARDED_BY(g_maplocalhost_mutex);
|
||||
static bool vfLimited[NET_MAX] GUARDED_BY(g_maplocalhost_mutex) = {};
|
||||
std::string strSubVersion;
|
||||
|
||||
size_t CSerializedNetMsg::GetMemoryUsage() const noexcept
|
||||
|
@ -232,7 +231,7 @@ static int GetnScore(const CService& addr)
|
|||
{
|
||||
CService addrLocal = pnode->GetAddrLocal();
|
||||
return fDiscover && pnode->addr.IsRoutable() && addrLocal.IsRoutable() &&
|
||||
IsReachable(addrLocal.GetNetwork());
|
||||
g_reachable_nets.Contains(addrLocal);
|
||||
}
|
||||
|
||||
std::optional<CService> GetLocalAddrForPeer(CNode& node)
|
||||
|
@ -270,22 +269,6 @@ std::optional<CService> GetLocalAddrForPeer(CNode& node)
|
|||
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.IsIPv6() && ret.HasCJDNSPrefix() && IsReachable(NET_CJDNS)) {
|
||||
ret.m_net = NET_CJDNS;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// learn a new local address
|
||||
bool AddLocal(const CService& addr_, int nScore)
|
||||
{
|
||||
|
@ -297,7 +280,7 @@ bool AddLocal(const CService& addr_, int nScore)
|
|||
if (!fDiscover && nScore < LOCAL_MANUAL)
|
||||
return false;
|
||||
|
||||
if (!IsReachable(addr))
|
||||
if (!g_reachable_nets.Contains(addr))
|
||||
return false;
|
||||
|
||||
LogPrintf("AddLocal(%s,%i)\n", addr.ToStringAddrPort(), nScore);
|
||||
|
@ -327,25 +310,6 @@ void RemoveLocal(const CService& addr)
|
|||
mapLocalHost.erase(addr);
|
||||
}
|
||||
|
||||
void SetReachable(enum Network net, bool reachable)
|
||||
{
|
||||
if (net == NET_UNROUTABLE || net == NET_INTERNAL)
|
||||
return;
|
||||
LOCK(g_maplocalhost_mutex);
|
||||
vfLimited[net] = !reachable;
|
||||
}
|
||||
|
||||
bool IsReachable(enum Network net)
|
||||
{
|
||||
LOCK(g_maplocalhost_mutex);
|
||||
return !vfLimited[net];
|
||||
}
|
||||
|
||||
bool IsReachable(const CNetAddr &addr)
|
||||
{
|
||||
return IsReachable(addr.GetNetwork());
|
||||
}
|
||||
|
||||
/** vote for a local address */
|
||||
bool SeenLocal(const CService& addr)
|
||||
{
|
||||
|
@ -375,17 +339,6 @@ CNode* CConnman::FindNode(const CNetAddr& ip)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
CNode* CConnman::FindNode(const CSubNet& subNet)
|
||||
{
|
||||
LOCK(m_nodes_mutex);
|
||||
for (CNode* pnode : m_nodes) {
|
||||
if (subNet.Match(static_cast<CNetAddr>(pnode->addr))) {
|
||||
return pnode;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CNode* CConnman::FindNode(const std::string& addrName)
|
||||
{
|
||||
LOCK(m_nodes_mutex);
|
||||
|
@ -2433,7 +2386,7 @@ std::unordered_set<Network> CConnman::GetReachableEmptyNetworks() const
|
|||
for (int n = 0; n < NET_MAX; n++) {
|
||||
enum Network net = (enum Network)n;
|
||||
if (net == NET_UNROUTABLE || net == NET_INTERNAL) continue;
|
||||
if (IsReachable(net) && addrman.Size(net, std::nullopt) == 0) {
|
||||
if (g_reachable_nets.Contains(net) && addrman.Size(net, std::nullopt) == 0) {
|
||||
networks.insert(net);
|
||||
}
|
||||
}
|
||||
|
@ -2453,7 +2406,7 @@ bool CConnman::MaybePickPreferredNetwork(std::optional<Network>& network)
|
|||
|
||||
LOCK(m_nodes_mutex);
|
||||
for (const auto net : nets) {
|
||||
if (IsReachable(net) && m_network_conn_counts[net] == 0 && addrman.Size(net) != 0) {
|
||||
if (g_reachable_nets.Contains(net) && m_network_conn_counts[net] == 0 && addrman.Size(net) != 0) {
|
||||
network = net;
|
||||
return true;
|
||||
}
|
||||
|
@ -2683,7 +2636,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
|
|||
if (anchor && !m_anchors.empty()) {
|
||||
const CAddress addr = m_anchors.back();
|
||||
m_anchors.pop_back();
|
||||
if (!addr.IsValid() || IsLocal(addr) || !IsReachable(addr) ||
|
||||
if (!addr.IsValid() || IsLocal(addr) || !g_reachable_nets.Contains(addr) ||
|
||||
!HasAllDesirableServiceFlags(addr.nServices) ||
|
||||
outbound_ipv46_peer_netgroups.count(m_netgroupman.GetGroup(addr))) continue;
|
||||
addrConnect = addr;
|
||||
|
@ -2738,8 +2691,9 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
|
|||
break;
|
||||
}
|
||||
|
||||
if (!IsReachable(addr))
|
||||
if (!g_reachable_nets.Contains(addr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// only consider very recently tried nodes after 30 failed attempts
|
||||
if (current_time - addr_last_try < 10min && nTries < 30) {
|
||||
|
|
13
src/net.h
13
src/net.h
|
@ -160,24 +160,12 @@ enum
|
|||
/** Returns a local address that we should advertise to this peer. */
|
||||
std::optional<CService> GetLocalAddrForPeer(CNode& node);
|
||||
|
||||
/**
|
||||
* Mark a network as reachable or unreachable (no automatic connects to it)
|
||||
* @note Networks are reachable by default
|
||||
*/
|
||||
void SetReachable(enum Network net, bool reachable);
|
||||
/** @returns true if the network is reachable, false otherwise */
|
||||
bool IsReachable(enum Network net);
|
||||
/** @returns true if the address is in a reachable network, false otherwise */
|
||||
bool IsReachable(const CNetAddr& addr);
|
||||
|
||||
bool AddLocal(const CService& addr, int nScore = LOCAL_NONE);
|
||||
bool AddLocal(const CNetAddr& addr, int nScore = LOCAL_NONE);
|
||||
void RemoveLocal(const CService& addr);
|
||||
bool SeenLocal(const CService& addr);
|
||||
bool IsLocal(const CService& addr);
|
||||
CService GetLocalAddress(const CNode& peer);
|
||||
CService MaybeFlipIPv6toCJDNS(const CService& service);
|
||||
|
||||
|
||||
extern bool fDiscover;
|
||||
extern bool fListen;
|
||||
|
@ -1341,7 +1329,6 @@ private:
|
|||
uint64_t CalculateKeyedNetGroup(const CAddress& ad) const;
|
||||
|
||||
CNode* FindNode(const CNetAddr& ip);
|
||||
CNode* FindNode(const CSubNet& subNet);
|
||||
CNode* FindNode(const std::string& addrName);
|
||||
CNode* FindNode(const CService& addr);
|
||||
|
||||
|
|
|
@ -3830,14 +3830,15 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||
continue;
|
||||
}
|
||||
++num_proc;
|
||||
bool fReachable = IsReachable(addr);
|
||||
const bool reachable{g_reachable_nets.Contains(addr)};
|
||||
if (addr.nTime > current_a_time - 10min && !peer->m_getaddr_sent && vAddr.size() <= 10 && addr.IsRoutable()) {
|
||||
// Relay to a limited number of other nodes
|
||||
RelayAddress(pfrom.GetId(), addr, fReachable);
|
||||
RelayAddress(pfrom.GetId(), addr, reachable);
|
||||
}
|
||||
// Do not store addresses outside our network
|
||||
if (fReachable)
|
||||
if (reachable) {
|
||||
vAddrOk.push_back(addr);
|
||||
}
|
||||
}
|
||||
peer->m_addr_processed += num_proc;
|
||||
peer->m_addr_rate_limited += num_rate_limit;
|
||||
|
|
|
@ -81,6 +81,10 @@ static const std::array<uint8_t, 6> INTERNAL_IN_IPV6_PREFIX{
|
|||
0xFD, 0x6B, 0x88, 0xC0, 0x87, 0x24 // 0xFD + sha256("bitcoin")[0:5].
|
||||
};
|
||||
|
||||
/// All CJDNS addresses start with 0xFC. See
|
||||
/// https://github.com/cjdelisle/cjdns/blob/master/doc/Whitepaper.md#pulling-it-all-together
|
||||
static constexpr uint8_t CJDNS_PREFIX{0xFC};
|
||||
|
||||
/// Size of IPv4 address (in bytes).
|
||||
static constexpr size_t ADDR_IPV4_SIZE = 4;
|
||||
|
||||
|
@ -174,7 +178,7 @@ public:
|
|||
[[nodiscard]] bool IsTor() const { return m_net == NET_ONION; }
|
||||
[[nodiscard]] bool IsI2P() const { return m_net == NET_I2P; }
|
||||
[[nodiscard]] bool IsCJDNS() const { return m_net == NET_CJDNS; }
|
||||
[[nodiscard]] bool HasCJDNSPrefix() const { return m_addr[0] == 0xfc; }
|
||||
[[nodiscard]] bool HasCJDNSPrefix() const { return m_addr[0] == CJDNS_PREFIX; }
|
||||
bool IsLocal() const;
|
||||
bool IsRoutable() const;
|
||||
bool IsInternal() const;
|
||||
|
|
|
@ -32,6 +32,8 @@ bool fNameLookup = DEFAULT_NAME_LOOKUP;
|
|||
std::chrono::milliseconds g_socks5_recv_timeout = 20s;
|
||||
static std::atomic<bool> interruptSocks5Recv(false);
|
||||
|
||||
ReachableNets g_reachable_nets;
|
||||
|
||||
std::vector<CNetAddr> WrappedGetAddrInfo(const std::string& name, bool allow_lookup)
|
||||
{
|
||||
addrinfo ai_hint{};
|
||||
|
@ -651,9 +653,10 @@ bool LookupSubNet(const std::string& subnet_str, CSubNet& subnet_out)
|
|||
|
||||
const size_t slash_pos{subnet_str.find_last_of('/')};
|
||||
const std::string str_addr{subnet_str.substr(0, slash_pos)};
|
||||
const std::optional<CNetAddr> addr{LookupHost(str_addr, /*fAllowLookup=*/false)};
|
||||
std::optional<CNetAddr> addr{LookupHost(str_addr, /*fAllowLookup=*/false)};
|
||||
|
||||
if (addr.has_value()) {
|
||||
addr = static_cast<CNetAddr>(MaybeFlipIPv6toCJDNS(CService{addr.value(), /*port=*/0}));
|
||||
if (slash_pos != subnet_str.npos) {
|
||||
const std::string netmask_str{subnet_str.substr(slash_pos + 1)};
|
||||
uint8_t netmask;
|
||||
|
@ -772,3 +775,12 @@ bool IsBadPort(uint16_t port)
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CService MaybeFlipIPv6toCJDNS(const CService& service)
|
||||
{
|
||||
CService ret{service};
|
||||
if (ret.IsIPv6() && ret.HasCJDNSPrefix() && g_reachable_nets.Contains(NET_CJDNS)) {
|
||||
ret.m_net = NET_CJDNS;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
extern int nConnectTimeout;
|
||||
|
@ -64,6 +65,61 @@ struct ProxyCredentials
|
|||
std::string password;
|
||||
};
|
||||
|
||||
/**
|
||||
* List of reachable networks. Everything is reachable by default.
|
||||
*/
|
||||
class ReachableNets {
|
||||
public:
|
||||
void Add(Network net) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
|
||||
{
|
||||
AssertLockNotHeld(m_mutex);
|
||||
LOCK(m_mutex);
|
||||
m_reachable.insert(net);
|
||||
}
|
||||
|
||||
void Remove(Network net) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
|
||||
{
|
||||
AssertLockNotHeld(m_mutex);
|
||||
LOCK(m_mutex);
|
||||
m_reachable.erase(net);
|
||||
}
|
||||
|
||||
void RemoveAll() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
|
||||
{
|
||||
AssertLockNotHeld(m_mutex);
|
||||
LOCK(m_mutex);
|
||||
m_reachable.clear();
|
||||
}
|
||||
|
||||
[[nodiscard]] bool Contains(Network net) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
|
||||
{
|
||||
AssertLockNotHeld(m_mutex);
|
||||
LOCK(m_mutex);
|
||||
return m_reachable.count(net) > 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool Contains(const CNetAddr& addr) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
|
||||
{
|
||||
AssertLockNotHeld(m_mutex);
|
||||
return Contains(addr.GetNetwork());
|
||||
}
|
||||
|
||||
private:
|
||||
mutable Mutex m_mutex;
|
||||
|
||||
std::unordered_set<Network> m_reachable GUARDED_BY(m_mutex){
|
||||
NET_UNROUTABLE,
|
||||
NET_IPV4,
|
||||
NET_IPV6,
|
||||
NET_ONION,
|
||||
NET_I2P,
|
||||
NET_CJDNS,
|
||||
NET_INTERNAL
|
||||
};
|
||||
};
|
||||
|
||||
extern ReachableNets g_reachable_nets;
|
||||
|
||||
/**
|
||||
* Wrapper for getaddrinfo(3). Do not use directly: call Lookup/LookupHost/LookupNumeric/LookupSubNet.
|
||||
*/
|
||||
|
@ -251,4 +307,13 @@ bool Socks5(const std::string& strDest, uint16_t port, const ProxyCredentials* a
|
|||
*/
|
||||
bool IsBadPort(uint16_t port);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
#endif // BITCOIN_NETBASE_H
|
||||
|
|
|
@ -52,8 +52,8 @@ std::vector<unsigned char> NetGroupManager::GetGroup(const CNetAddr& address) co
|
|||
} else if (address.IsCJDNS()) {
|
||||
// Treat in the same way as Tor and I2P because the address in all of
|
||||
// them is "random" bytes (derived from a public key). However in CJDNS
|
||||
// the first byte is a constant 0xfc, so the random bytes come after it.
|
||||
// Thus skip the constant 8 bits at the start.
|
||||
// the first byte is a constant (see CJDNS_PREFIX), so the random bytes
|
||||
// come after it. Thus skip the constant 8 bits at the start.
|
||||
nBits = 12;
|
||||
} else if (address.IsHeNet()) {
|
||||
// for he.net, use /36 groups
|
||||
|
|
|
@ -585,8 +585,8 @@ static UniValue GetNetworksInfo()
|
|||
UniValue obj(UniValue::VOBJ);
|
||||
GetProxy(network, proxy);
|
||||
obj.pushKV("name", GetNetworkName(network));
|
||||
obj.pushKV("limited", !IsReachable(network));
|
||||
obj.pushKV("reachable", IsReachable(network));
|
||||
obj.pushKV("limited", !g_reachable_nets.Contains(network));
|
||||
obj.pushKV("reachable", g_reachable_nets.Contains(network));
|
||||
obj.pushKV("proxy", proxy.IsValid() ? proxy.proxy.ToStringAddrPort() : std::string());
|
||||
obj.pushKV("proxy_randomize_credentials", proxy.randomize_credentials);
|
||||
networks.push_back(obj);
|
||||
|
@ -730,7 +730,7 @@ static RPCHelpMan setban()
|
|||
if (!isSubnet) {
|
||||
const std::optional<CNetAddr> addr{LookupHost(request.params[0].get_str(), false)};
|
||||
if (addr.has_value()) {
|
||||
netAddr = addr.value();
|
||||
netAddr = static_cast<CNetAddr>(MaybeFlipIPv6toCJDNS(CService{addr.value(), /*port=*/0}));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -36,7 +36,11 @@ CNetAddr ConsumeNetAddr(FuzzedDataProvider& fuzzed_data_provider) noexcept
|
|||
} else if (network == Network::NET_IPV6) {
|
||||
if (fuzzed_data_provider.remaining_bytes() >= 16) {
|
||||
in6_addr v6_addr = {};
|
||||
memcpy(v6_addr.s6_addr, fuzzed_data_provider.ConsumeBytes<uint8_t>(16).data(), 16);
|
||||
auto addr_bytes = fuzzed_data_provider.ConsumeBytes<uint8_t>(16);
|
||||
if (addr_bytes[0] == CJDNS_PREFIX) { // Avoid generating IPv6 addresses that look like CJDNS.
|
||||
addr_bytes[0] = 0x55; // Just an arbitrary number, anything != CJDNS_PREFIX would do.
|
||||
}
|
||||
memcpy(v6_addr.s6_addr, addr_bytes.data(), 16);
|
||||
net_addr = CNetAddr{v6_addr, fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
|
||||
}
|
||||
} else if (network == Network::NET_INTERNAL) {
|
||||
|
|
|
@ -718,47 +718,55 @@ BOOST_AUTO_TEST_CASE(get_local_addr_for_peer_port)
|
|||
|
||||
BOOST_AUTO_TEST_CASE(LimitedAndReachable_Network)
|
||||
{
|
||||
BOOST_CHECK(IsReachable(NET_IPV4));
|
||||
BOOST_CHECK(IsReachable(NET_IPV6));
|
||||
BOOST_CHECK(IsReachable(NET_ONION));
|
||||
BOOST_CHECK(IsReachable(NET_I2P));
|
||||
BOOST_CHECK(IsReachable(NET_CJDNS));
|
||||
BOOST_CHECK(g_reachable_nets.Contains(NET_IPV4));
|
||||
BOOST_CHECK(g_reachable_nets.Contains(NET_IPV6));
|
||||
BOOST_CHECK(g_reachable_nets.Contains(NET_ONION));
|
||||
BOOST_CHECK(g_reachable_nets.Contains(NET_I2P));
|
||||
BOOST_CHECK(g_reachable_nets.Contains(NET_CJDNS));
|
||||
|
||||
SetReachable(NET_IPV4, false);
|
||||
SetReachable(NET_IPV6, false);
|
||||
SetReachable(NET_ONION, false);
|
||||
SetReachable(NET_I2P, false);
|
||||
SetReachable(NET_CJDNS, false);
|
||||
g_reachable_nets.Remove(NET_IPV4);
|
||||
g_reachable_nets.Remove(NET_IPV6);
|
||||
g_reachable_nets.Remove(NET_ONION);
|
||||
g_reachable_nets.Remove(NET_I2P);
|
||||
g_reachable_nets.Remove(NET_CJDNS);
|
||||
|
||||
BOOST_CHECK(!IsReachable(NET_IPV4));
|
||||
BOOST_CHECK(!IsReachable(NET_IPV6));
|
||||
BOOST_CHECK(!IsReachable(NET_ONION));
|
||||
BOOST_CHECK(!IsReachable(NET_I2P));
|
||||
BOOST_CHECK(!IsReachable(NET_CJDNS));
|
||||
BOOST_CHECK(!g_reachable_nets.Contains(NET_IPV4));
|
||||
BOOST_CHECK(!g_reachable_nets.Contains(NET_IPV6));
|
||||
BOOST_CHECK(!g_reachable_nets.Contains(NET_ONION));
|
||||
BOOST_CHECK(!g_reachable_nets.Contains(NET_I2P));
|
||||
BOOST_CHECK(!g_reachable_nets.Contains(NET_CJDNS));
|
||||
|
||||
SetReachable(NET_IPV4, true);
|
||||
SetReachable(NET_IPV6, true);
|
||||
SetReachable(NET_ONION, true);
|
||||
SetReachable(NET_I2P, true);
|
||||
SetReachable(NET_CJDNS, true);
|
||||
g_reachable_nets.Add(NET_IPV4);
|
||||
g_reachable_nets.Add(NET_IPV6);
|
||||
g_reachable_nets.Add(NET_ONION);
|
||||
g_reachable_nets.Add(NET_I2P);
|
||||
g_reachable_nets.Add(NET_CJDNS);
|
||||
|
||||
BOOST_CHECK(IsReachable(NET_IPV4));
|
||||
BOOST_CHECK(IsReachable(NET_IPV6));
|
||||
BOOST_CHECK(IsReachable(NET_ONION));
|
||||
BOOST_CHECK(IsReachable(NET_I2P));
|
||||
BOOST_CHECK(IsReachable(NET_CJDNS));
|
||||
BOOST_CHECK(g_reachable_nets.Contains(NET_IPV4));
|
||||
BOOST_CHECK(g_reachable_nets.Contains(NET_IPV6));
|
||||
BOOST_CHECK(g_reachable_nets.Contains(NET_ONION));
|
||||
BOOST_CHECK(g_reachable_nets.Contains(NET_I2P));
|
||||
BOOST_CHECK(g_reachable_nets.Contains(NET_CJDNS));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(LimitedAndReachable_NetworkCaseUnroutableAndInternal)
|
||||
{
|
||||
BOOST_CHECK(IsReachable(NET_UNROUTABLE));
|
||||
BOOST_CHECK(IsReachable(NET_INTERNAL));
|
||||
// Should be reachable by default.
|
||||
BOOST_CHECK(g_reachable_nets.Contains(NET_UNROUTABLE));
|
||||
BOOST_CHECK(g_reachable_nets.Contains(NET_INTERNAL));
|
||||
|
||||
SetReachable(NET_UNROUTABLE, false);
|
||||
SetReachable(NET_INTERNAL, false);
|
||||
g_reachable_nets.RemoveAll();
|
||||
|
||||
BOOST_CHECK(IsReachable(NET_UNROUTABLE)); // Ignored for both networks
|
||||
BOOST_CHECK(IsReachable(NET_INTERNAL));
|
||||
BOOST_CHECK(!g_reachable_nets.Contains(NET_UNROUTABLE));
|
||||
BOOST_CHECK(!g_reachable_nets.Contains(NET_INTERNAL));
|
||||
|
||||
g_reachable_nets.Add(NET_IPV4);
|
||||
g_reachable_nets.Add(NET_IPV6);
|
||||
g_reachable_nets.Add(NET_ONION);
|
||||
g_reachable_nets.Add(NET_I2P);
|
||||
g_reachable_nets.Add(NET_CJDNS);
|
||||
g_reachable_nets.Add(NET_UNROUTABLE);
|
||||
g_reachable_nets.Add(NET_INTERNAL);
|
||||
}
|
||||
|
||||
CNetAddr UtilBuildAddress(unsigned char p1, unsigned char p2, unsigned char p3, unsigned char p4)
|
||||
|
@ -776,13 +784,13 @@ BOOST_AUTO_TEST_CASE(LimitedAndReachable_CNetAddr)
|
|||
{
|
||||
CNetAddr addr = UtilBuildAddress(0x001, 0x001, 0x001, 0x001); // 1.1.1.1
|
||||
|
||||
SetReachable(NET_IPV4, true);
|
||||
BOOST_CHECK(IsReachable(addr));
|
||||
g_reachable_nets.Add(NET_IPV4);
|
||||
BOOST_CHECK(g_reachable_nets.Contains(addr));
|
||||
|
||||
SetReachable(NET_IPV4, false);
|
||||
BOOST_CHECK(!IsReachable(addr));
|
||||
g_reachable_nets.Remove(NET_IPV4);
|
||||
BOOST_CHECK(!g_reachable_nets.Contains(addr));
|
||||
|
||||
SetReachable(NET_IPV4, true); // have to reset this, because this is stateful.
|
||||
g_reachable_nets.Add(NET_IPV4); // have to reset this, because this is stateful.
|
||||
}
|
||||
|
||||
|
||||
|
@ -790,7 +798,7 @@ BOOST_AUTO_TEST_CASE(LocalAddress_BasicLifecycle)
|
|||
{
|
||||
CService addr = CService(UtilBuildAddress(0x002, 0x001, 0x001, 0x001), 1000); // 2.1.1.1:1000
|
||||
|
||||
SetReachable(NET_IPV4, true);
|
||||
g_reachable_nets.Add(NET_IPV4);
|
||||
|
||||
BOOST_CHECK(!IsLocal(addr));
|
||||
BOOST_CHECK(AddLocal(addr, 1000));
|
||||
|
@ -915,7 +923,7 @@ BOOST_AUTO_TEST_CASE(advertise_local_address)
|
|||
ConnectionType::OUTBOUND_FULL_RELAY,
|
||||
/*inbound_onion=*/false);
|
||||
};
|
||||
SetReachable(NET_CJDNS, true);
|
||||
g_reachable_nets.Add(NET_CJDNS);
|
||||
|
||||
CAddress addr_ipv4{Lookup("1.2.3.4", 8333, false).value(), NODE_NONE};
|
||||
BOOST_REQUIRE(addr_ipv4.IsValid());
|
||||
|
|
|
@ -409,7 +409,7 @@ void TorController::get_socks_cb(TorControlConnection& _conn, const TorControlRe
|
|||
//
|
||||
// If NET_ONION is not reachable, then none of -proxy or -onion was given.
|
||||
// Since we are here, then -torcontrol and -torpassword were given.
|
||||
SetReachable(NET_ONION, true);
|
||||
g_reachable_nets.Add(NET_ONION);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue