Skip to content

Commit 0c42410

Browse files
committed
merge bitcoin#27071: Handle CJDNS from LookupSubNet()
1 parent 821c11f commit 0c42410

File tree

14 files changed

+174
-145
lines changed

14 files changed

+174
-145
lines changed

src/httpserver.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,7 @@ CService HTTPRequest::GetPeer() const
653653
evhttp_connection_get_peer(con, (char**)&address, &port);
654654
#endif // HAVE_EVHTTP_CONNECTION_GET_PEER_CONST_CHAR
655655

656-
peer = LookupNumeric(address, port);
656+
peer = MaybeFlipIPv6toCJDNS(LookupNumeric(address, port));
657657
}
658658
return peer;
659659
}

src/init.cpp

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1694,38 +1694,32 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
16941694
}
16951695

16961696
if (args.IsArgSet("-onlynet")) {
1697-
std::set<enum Network> nets;
1697+
g_reachable_nets.RemoveAll();
16981698
for (const std::string& snet : args.GetArgs("-onlynet")) {
16991699
enum Network net = ParseNetwork(snet);
17001700
if (net == NET_UNROUTABLE)
17011701
return InitError(strprintf(_("Unknown network specified in -onlynet: '%s'"), snet));
1702-
nets.insert(net);
1703-
}
1704-
for (int n = 0; n < NET_MAX; n++) {
1705-
enum Network net = (enum Network)n;
1706-
assert(IsReachable(net));
1707-
if (!nets.count(net))
1708-
SetReachable(net, false);
1702+
g_reachable_nets.Add(net);
17091703
}
17101704
}
17111705

17121706
if (!args.IsArgSet("-cjdnsreachable")) {
1713-
if (args.IsArgSet("-onlynet") && IsReachable(NET_CJDNS)) {
1707+
if (args.IsArgSet("-onlynet") && g_reachable_nets.Contains(NET_CJDNS)) {
17141708
return InitError(
17151709
_("Outbound connections restricted to CJDNS (-onlynet=cjdns) but "
17161710
"-cjdnsreachable is not provided"));
17171711
}
1718-
SetReachable(NET_CJDNS, false);
1712+
g_reachable_nets.Remove(NET_CJDNS);
17191713
}
1720-
// Now IsReachable(NET_CJDNS) is true if:
1714+
// Now g_reachable_nets.Contains(NET_CJDNS) is true if:
17211715
// 1. -cjdnsreachable is given and
17221716
// 2.1. -onlynet is not given or
17231717
// 2.2. -onlynet=cjdns is given
17241718

17251719
// Requesting DNS seeds entails connecting to IPv4/IPv6, which -onlynet options may prohibit:
17261720
// If -dnsseed=1 is explicitly specified, abort. If it's left unspecified by the user, we skip
17271721
// the DNS seeds by adjusting -dnsseed in InitParameterInteraction.
1728-
if (args.GetBoolArg("-dnsseed", DEFAULT_DNSSEED) == true && !IsReachable(NET_IPV4) && !IsReachable(NET_IPV6)) {
1722+
if (args.GetBoolArg("-dnsseed", DEFAULT_DNSSEED) == true && !g_reachable_nets.Contains(NET_IPV4) && !g_reachable_nets.Contains(NET_IPV6)) {
17291723
return InitError(strprintf(_("Incompatible options: -dnsseed=1 was explicitly specified, but -onlynet forbids connections to IPv4/IPv6")));
17301724
};
17311725

@@ -1755,7 +1749,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
17551749
onion_proxy = addrProxy;
17561750
}
17571751

1758-
const bool onlynet_used_with_onion{args.IsArgSet("-onlynet") && IsReachable(NET_ONION)};
1752+
const bool onlynet_used_with_onion{args.IsArgSet("-onlynet") && g_reachable_nets.Contains(NET_ONION)};
17591753

17601754
// -onion can be used to set only a proxy for .onion, or override normal proxy for .onion addresses
17611755
// -noonion (or -onion=0) disables connecting to .onion entirely
@@ -1790,7 +1784,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
17901784
"reaching the Tor network is not provided: none of -proxy, -onion or "
17911785
"-listenonion is given"));
17921786
}
1793-
SetReachable(NET_ONION, false);
1787+
g_reachable_nets.Remove(NET_ONION);
17941788
}
17951789

17961790
for (const std::string& strAddr : args.GetArgs("-externalip")) {
@@ -2417,12 +2411,12 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
24172411
}
24182412
SetProxy(NET_I2P, Proxy{addr.value()});
24192413
} else {
2420-
if (args.IsArgSet("-onlynet") && IsReachable(NET_I2P)) {
2414+
if (args.IsArgSet("-onlynet") && g_reachable_nets.Contains(NET_I2P)) {
24212415
return InitError(
24222416
_("Outbound connections restricted to i2p (-onlynet=i2p) but "
24232417
"-i2psam is not provided"));
24242418
}
2425-
SetReachable(NET_I2P, false);
2419+
g_reachable_nets.Remove(NET_I2P);
24262420
}
24272421

24282422
connOptions.m_i2p_accept_incoming = args.GetBoolArg("-i2pacceptincoming", DEFAULT_I2P_ACCEPT_INCOMING);

src/masternode/node.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ bool CActiveMasternodeManager::IsValidNetAddr(const CService& addrIn)
264264
if (!addrIn.IsValid() || !addrIn.IsIPv4()) return false;
265265
// TODO: regtest is fine with any addresses for now,
266266
// should probably be a bit smarter if one day we start to implement tests for this
267-
return !Params().RequireRoutableExternalIP() || (IsReachable(addrIn) && addrIn.IsRoutable());
267+
return !Params().RequireRoutableExternalIP() || (g_reachable_nets.Contains(addrIn) && addrIn.IsRoutable());
268268
}
269269

270270
template <template <typename> class EncryptedObj, typename Obj>

src/net.cpp

Lines changed: 12 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,6 @@ bool fDiscover = true;
144144
bool fListen = true;
145145
Mutex g_maplocalhost_mutex;
146146
std::map<CNetAddr, LocalServiceInfo> mapLocalHost GUARDED_BY(g_maplocalhost_mutex);
147-
static bool vfLimited[NET_MAX] GUARDED_BY(g_maplocalhost_mutex) = {};
148147
std::string strSubVersion;
149148

150149
size_t CSerializedNetMsg::GetMemoryUsage() const noexcept
@@ -260,7 +259,7 @@ static int GetnScore(const CService& addr)
260259
{
261260
CService addrLocal = pnode->GetAddrLocal();
262261
return fDiscover && pnode->addr.IsRoutable() && addrLocal.IsRoutable() &&
263-
IsReachable(addrLocal.GetNetwork());
262+
g_reachable_nets.Contains(addrLocal);
264263
}
265264

266265
std::optional<CService> GetLocalAddrForPeer(CNode& node)
@@ -294,22 +293,6 @@ std::optional<CService> GetLocalAddrForPeer(CNode& node)
294293
return std::nullopt;
295294
}
296295

297-
/**
298-
* If an IPv6 address belongs to the address range used by the CJDNS network and
299-
* the CJDNS network is reachable (-cjdnsreachable config is set), then change
300-
* the type from NET_IPV6 to NET_CJDNS.
301-
* @param[in] service Address to potentially convert.
302-
* @return a copy of `service` either unmodified or changed to CJDNS.
303-
*/
304-
CService MaybeFlipIPv6toCJDNS(const CService& service)
305-
{
306-
CService ret{service};
307-
if (ret.IsIPv6() && ret.HasCJDNSPrefix() && IsReachable(NET_CJDNS)) {
308-
ret.m_net = NET_CJDNS;
309-
}
310-
return ret;
311-
}
312-
313296
// learn a new local address
314297
bool AddLocal(const CService& addr_, int nScore)
315298
{
@@ -321,7 +304,7 @@ bool AddLocal(const CService& addr_, int nScore)
321304
if (!fDiscover && nScore < LOCAL_MANUAL)
322305
return false;
323306

324-
if (!IsReachable(addr))
307+
if (!g_reachable_nets.Contains(addr))
325308
return false;
326309

327310
LogPrintf("AddLocal(%s,%i)\n", addr.ToStringAddrPort(), nScore);
@@ -351,25 +334,6 @@ void RemoveLocal(const CService& addr)
351334
mapLocalHost.erase(addr);
352335
}
353336

354-
void SetReachable(enum Network net, bool reachable)
355-
{
356-
if (net == NET_UNROUTABLE || net == NET_INTERNAL)
357-
return;
358-
LOCK(g_maplocalhost_mutex);
359-
vfLimited[net] = !reachable;
360-
}
361-
362-
bool IsReachable(enum Network net)
363-
{
364-
LOCK(g_maplocalhost_mutex);
365-
return !vfLimited[net];
366-
}
367-
368-
bool IsReachable(const CNetAddr &addr)
369-
{
370-
return IsReachable(addr.GetNetwork());
371-
}
372-
373337
/** vote for a local address */
374338
bool SeenLocal(const CService& addr)
375339
{
@@ -402,20 +366,6 @@ CNode* CConnman::FindNode(const CNetAddr& ip, bool fExcludeDisconnecting)
402366
return nullptr;
403367
}
404368

405-
CNode* CConnman::FindNode(const CSubNet& subNet, bool fExcludeDisconnecting)
406-
{
407-
LOCK(m_nodes_mutex);
408-
for (CNode* pnode : m_nodes) {
409-
if (fExcludeDisconnecting && pnode->fDisconnect) {
410-
continue;
411-
}
412-
if (subNet.Match(static_cast<CNetAddr>(pnode->addr))) {
413-
return pnode;
414-
}
415-
}
416-
return nullptr;
417-
}
418-
419369
CNode* CConnman::FindNode(const std::string& addrName, bool fExcludeDisconnecting)
420370
{
421371
LOCK(m_nodes_mutex);
@@ -3177,7 +3127,7 @@ std::unordered_set<Network> CConnman::GetReachableEmptyNetworks() const
31773127
for (int n = 0; n < NET_MAX; n++) {
31783128
enum Network net = (enum Network)n;
31793129
if (net == NET_UNROUTABLE || net == NET_INTERNAL) continue;
3180-
if (IsReachable(net) && addrman.Size(net, std::nullopt) == 0) {
3130+
if (g_reachable_nets.Contains(net) && addrman.Size(net, std::nullopt) == 0) {
31813131
networks.insert(net);
31823132
}
31833133
}
@@ -3197,7 +3147,7 @@ bool CConnman::MaybePickPreferredNetwork(std::optional<Network>& network)
31973147

31983148
LOCK(m_nodes_mutex);
31993149
for (const auto net : nets) {
3200-
if (IsReachable(net) && m_network_conn_counts[net] == 0 && addrman.Size(net) != 0) {
3150+
if (g_reachable_nets.Contains(net) && m_network_conn_counts[net] == 0 && addrman.Size(net) != 0) {
32013151
network = net;
32023152
return true;
32033153
}
@@ -3432,7 +3382,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect, CDe
34323382
// so low that less than MAX_OUTBOUND_FULL_RELAY_CONNECTIONS are made,
34333383
// to prevent interactions with otherwise protected outbound peers.
34343384
next_extra_network_peer = GetExponentialRand(now, EXTRA_NETWORK_PEER_INTERVAL);
3435-
} else if (nOutboundOnionRelay < m_max_outbound_onion && IsReachable(Network::NET_ONION)) {
3385+
} else if (nOutboundOnionRelay < m_max_outbound_onion && g_reachable_nets.Contains(Network::NET_ONION)) {
34363386
onion_only = true;
34373387
} else {
34383388
// skip to next iteration of while loop
@@ -3450,7 +3400,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect, CDe
34503400
if (anchor && !m_anchors.empty()) {
34513401
const CAddress addr = m_anchors.back();
34523402
m_anchors.pop_back();
3453-
if (!addr.IsValid() || IsLocal(addr) || !IsReachable(addr) ||
3403+
if (!addr.IsValid() || IsLocal(addr) || !g_reachable_nets.Contains(addr) ||
34543404
!HasAllDesirableServiceFlags(addr.nServices) ||
34553405
outbound_ipv46_peer_netgroups.count(m_netgroupman.GetGroup(addr))) continue;
34563406
addrConnect = addr;
@@ -3510,9 +3460,13 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect, CDe
35103460
break;
35113461
}
35123462

3513-
if (!IsReachable(addr))
3463+
if (!g_reachable_nets.Contains(addr)) {
35143464
continue;
3515-
if (onion_only && !addr.IsTor()) continue;
3465+
}
3466+
3467+
if (onion_only && !addr.IsTor()) {
3468+
continue;
3469+
}
35163470

35173471
// only consider very recently tried nodes after 30 failed attempts
35183472
if (current_time - addr_last_try < 10min && nTries < 30) {

src/net.h

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -191,24 +191,12 @@ enum
191191
/** Returns a local address that we should advertise to this peer. */
192192
std::optional<CService> GetLocalAddrForPeer(CNode& node);
193193

194-
/**
195-
* Mark a network as reachable or unreachable (no automatic connects to it)
196-
* @note Networks are reachable by default
197-
*/
198-
void SetReachable(enum Network net, bool reachable);
199-
/** @returns true if the network is reachable, false otherwise */
200-
bool IsReachable(enum Network net);
201-
/** @returns true if the address is in a reachable network, false otherwise */
202-
bool IsReachable(const CNetAddr& addr);
203-
204194
bool AddLocal(const CService& addr, int nScore = LOCAL_NONE);
205195
bool AddLocal(const CNetAddr& addr, int nScore = LOCAL_NONE);
206196
void RemoveLocal(const CService& addr);
207197
bool SeenLocal(const CService& addr);
208198
bool IsLocal(const CService& addr);
209199
CService GetLocalAddress(const CNode& peer);
210-
CService MaybeFlipIPv6toCJDNS(const CService& service);
211-
212200

213201
extern bool fDiscover;
214202
extern bool fListen;
@@ -1714,7 +1702,6 @@ friend class CNode;
17141702
uint64_t CalculateKeyedNetGroup(const CAddress& ad) const;
17151703

17161704
CNode* FindNode(const CNetAddr& ip, bool fExcludeDisconnecting = true);
1717-
CNode* FindNode(const CSubNet& subNet, bool fExcludeDisconnecting = true);
17181705
CNode* FindNode(const std::string& addrName, bool fExcludeDisconnecting = true);
17191706
CNode* FindNode(const CService& addr, bool fExcludeDisconnecting = true);
17201707

src/net_processing.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4027,14 +4027,15 @@ void PeerManagerImpl::ProcessMessage(
40274027
continue;
40284028
}
40294029
++num_proc;
4030-
bool fReachable = IsReachable(addr);
4030+
const bool reachable{g_reachable_nets.Contains(addr)};
40314031
if (addr.nTime > current_a_time - 10min && !peer->m_getaddr_sent && vAddr.size() <= 10 && addr.IsRoutable()) {
40324032
// Relay to a limited number of other nodes
4033-
RelayAddress(pfrom.GetId(), addr, fReachable);
4033+
RelayAddress(pfrom.GetId(), addr, reachable);
40344034
}
40354035
// Do not store addresses outside our network
4036-
if (fReachable)
4036+
if (reachable) {
40374037
vAddrOk.push_back(addr);
4038+
}
40384039
}
40394040
peer->m_addr_processed += num_proc;
40404041
peer->m_addr_rate_limited += num_rate_limit;

src/netaddress.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ static const std::array<uint8_t, 6> INTERNAL_IN_IPV6_PREFIX{
9191
0xFD, 0x6B, 0x88, 0xC0, 0x87, 0x24 // 0xFD + sha256("bitcoin")[0:5].
9292
};
9393

94+
/// All CJDNS addresses start with 0xFC. See
95+
/// https://github.com/cjdelisle/cjdns/blob/master/doc/Whitepaper.md#pulling-it-all-together
96+
static constexpr uint8_t CJDNS_PREFIX{0xFC};
97+
9498
/// Size of IPv4 address (in bytes).
9599
static constexpr size_t ADDR_IPV4_SIZE = 4;
96100

@@ -191,7 +195,7 @@ class CNetAddr
191195
[[nodiscard]] bool IsTor() const { return m_net == NET_ONION; }
192196
[[nodiscard]] bool IsI2P() const { return m_net == NET_I2P; }
193197
[[nodiscard]] bool IsCJDNS() const { return m_net == NET_CJDNS; }
194-
[[nodiscard]] bool HasCJDNSPrefix() const { return m_addr[0] == 0xfc; }
198+
[[nodiscard]] bool HasCJDNSPrefix() const { return m_addr[0] == CJDNS_PREFIX; }
195199
bool IsLocal() const;
196200
bool IsRoutable() const;
197201
bool IsInternal() const;

src/netbase.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ bool fNameLookup = DEFAULT_NAME_LOOKUP;
3939
int g_socks5_recv_timeout = 20 * 1000;
4040
static std::atomic<bool> interruptSocks5Recv(false);
4141

42+
ReachableNets g_reachable_nets;
43+
4244
std::vector<CNetAddr> WrappedGetAddrInfo(const std::string& name, bool allow_lookup)
4345
{
4446
addrinfo ai_hint{};
@@ -673,9 +675,10 @@ bool LookupSubNet(const std::string& subnet_str, CSubNet& subnet_out)
673675

674676
const size_t slash_pos{subnet_str.find_last_of('/')};
675677
const std::string str_addr{subnet_str.substr(0, slash_pos)};
676-
const std::optional<CNetAddr> addr{LookupHost(str_addr, /*fAllowLookup=*/false)};
678+
std::optional<CNetAddr> addr{LookupHost(str_addr, /*fAllowLookup=*/false)};
677679

678680
if (addr.has_value()) {
681+
addr = static_cast<CNetAddr>(MaybeFlipIPv6toCJDNS(CService{addr.value(), /*port=*/0}));
679682
if (slash_pos != subnet_str.npos) {
680683
const std::string netmask_str{subnet_str.substr(slash_pos + 1)};
681684
uint8_t netmask;
@@ -736,3 +739,12 @@ bool IsBadPort(uint16_t port)
736739
}
737740
return false;
738741
}
742+
743+
CService MaybeFlipIPv6toCJDNS(const CService& service)
744+
{
745+
CService ret{service};
746+
if (ret.IsIPv6() && ret.HasCJDNSPrefix() && g_reachable_nets.Contains(NET_CJDNS)) {
747+
ret.m_net = NET_CJDNS;
748+
}
749+
return ret;
750+
}

0 commit comments

Comments
 (0)