Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/httpserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
26 changes: 10 additions & 16 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1305,38 +1305,32 @@ 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

// 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")));
};

Expand Down Expand Up @@ -1366,7 +1360,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
Expand Down Expand Up @@ -1401,7 +1395,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")) {
Expand Down Expand Up @@ -1876,12 +1870,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);
Expand Down
60 changes: 7 additions & 53 deletions src/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
{
Expand All @@ -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);
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
}
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down
13 changes: 0 additions & 13 deletions src/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -1341,7 +1329,6 @@ class CConnman
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);

Expand Down
7 changes: 4 additions & 3 deletions src/net_processing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3823,14 +3823,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;
Expand Down
6 changes: 5 additions & 1 deletion src/netaddress.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -174,7 +178,7 @@ class CNetAddr
[[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;
Expand Down
14 changes: 13 additions & 1 deletion src/netbase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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{};
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Loading