From b41d9eac22f3e19f2765efc61fad44cb5dfdf087 Mon Sep 17 00:00:00 2001
From: Oleg Girko
Date: Sat, 2 Sep 2017 21:07:11 +0100
Subject: [PATCH] Backport Bitcoin PR#7868: net: Split DNS resolving
functionality out of net structures (#1601)
* net: require lookup functions to specify all arguments
To make it clear where DNS resolves are happening
* net: manually resolve dns seed sources
Note: Some seeds aren't actually returning an IP for their name entries, so
they're being added to addrman with a source of [::].
This commit shouldn't change that behavior, for better or worse.
* net: resolve outside of storage structures
Rather than allowing CNetAddr/CService/CSubNet to launch DNS queries, require
that addresses are already resolved.
This greatly simplifies async resolve logic, and makes it harder to
accidentally leak DNS queries.
* net: disable resolving from storage structures
CNetAddr/CService/CSubnet can no longer resolve DNS.
---
src/init.cpp | 7 ++++---
src/net.cpp | 14 +++++++++++---
src/netbase.cpp | 28 ++++++++++++++--------------
src/netbase.h | 20 ++++++++++----------
src/torcontrol.cpp | 2 +-
5 files changed, 40 insertions(+), 31 deletions(-)
diff --git a/src/init.cpp b/src/init.cpp
index c9fdd1a43..55bda1f51 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -1444,10 +1444,11 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
if (mapArgs.count("-externalip")) {
BOOST_FOREACH(const std::string& strAddr, mapMultiArgs["-externalip"]) {
- CService addrLocal(strAddr, GetListenPort(), fNameLookup);
- if (!addrLocal.IsValid())
+ CService addrLocal;
+ if (Lookup(strAddr.c_str(), addrLocal, GetListenPort(), fNameLookup) && addrLocal.IsValid())
+ AddLocal(addrLocal, LOCAL_MANUAL);
+ else
return InitError(strprintf(_("Cannot resolve -externalip address: '%s'"), strAddr));
- AddLocal(CService(strAddr, GetListenPort(), fNameLookup), LOCAL_MANUAL);
}
}
diff --git a/src/net.cpp b/src/net.cpp
index 1d54005f5..b6da8f55f 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -1523,7 +1523,7 @@ void CConnman::ThreadDNSAddressSeed()
} else {
std::vector vIPs;
std::vector vAdd;
- if (LookupHost(seed.host.c_str(), vIPs))
+ if (LookupHost(seed.host.c_str(), vIPs, 0, true))
{
BOOST_FOREACH(const CNetAddr& ip, vIPs)
{
@@ -1534,7 +1534,15 @@ void CConnman::ThreadDNSAddressSeed()
found++;
}
}
- addrman.Add(vAdd, CNetAddr(seed.name, true));
+ // TODO: The seed name resolve may fail, yielding an IP of [::], which results in
+ // addrman assigning the same source to results from different seeds.
+ // This should switch to a hard-coded stable dummy IP for each seed name, so that the
+ // resolve is not required at all.
+ if (!vIPs.empty()) {
+ CService seedSource;
+ Lookup(seed.name.c_str(), seedSource, 0, true);
+ addrman.Add(vAdd, seedSource);
+ }
}
}
@@ -2039,7 +2047,7 @@ void Discover(boost::thread_group& threadGroup)
if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
{
std::vector vaddr;
- if (LookupHost(pszHostName, vaddr))
+ if (LookupHost(pszHostName, vaddr, 0, true))
{
BOOST_FOREACH (const CNetAddr &addr, vaddr)
{
diff --git a/src/netbase.cpp b/src/netbase.cpp
index eff8062d3..433b96844 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -681,19 +681,19 @@ CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr)
SetRaw(NET_IPV6, (const uint8_t*)&ipv6Addr);
}
-CNetAddr::CNetAddr(const char *pszIp, bool fAllowLookup)
+CNetAddr::CNetAddr(const char *pszIp)
{
Init();
std::vector vIP;
- if (LookupHost(pszIp, vIP, 1, fAllowLookup))
+ if (LookupHost(pszIp, vIP, 1, false))
*this = vIP[0];
}
-CNetAddr::CNetAddr(const std::string &strIp, bool fAllowLookup)
+CNetAddr::CNetAddr(const std::string &strIp)
{
Init();
std::vector vIP;
- if (LookupHost(strIp.c_str(), vIP, 1, fAllowLookup))
+ if (LookupHost(strIp.c_str(), vIP, 1, false))
*this = vIP[0];
}
@@ -1119,35 +1119,35 @@ bool CService::SetSockAddr(const struct sockaddr *paddr)
}
}
-CService::CService(const char *pszIpPort, bool fAllowLookup)
+CService::CService(const char *pszIpPort)
{
Init();
CService ip;
- if (Lookup(pszIpPort, ip, 0, fAllowLookup))
+ if (Lookup(pszIpPort, ip, 0, false))
*this = ip;
}
-CService::CService(const char *pszIpPort, int portDefault, bool fAllowLookup)
+CService::CService(const char *pszIpPort, int portDefault)
{
Init();
CService ip;
- if (Lookup(pszIpPort, ip, portDefault, fAllowLookup))
+ if (Lookup(pszIpPort, ip, portDefault, false))
*this = ip;
}
-CService::CService(const std::string &strIpPort, bool fAllowLookup)
+CService::CService(const std::string &strIpPort)
{
Init();
CService ip;
- if (Lookup(strIpPort.c_str(), ip, 0, fAllowLookup))
+ if (Lookup(strIpPort.c_str(), ip, 0, false))
*this = ip;
}
-CService::CService(const std::string &strIpPort, int portDefault, bool fAllowLookup)
+CService::CService(const std::string &strIpPort, int portDefault)
{
Init();
CService ip;
- if (Lookup(strIpPort.c_str(), ip, portDefault, fAllowLookup))
+ if (Lookup(strIpPort.c_str(), ip, portDefault, false))
*this = ip;
}
@@ -1240,7 +1240,7 @@ CSubNet::CSubNet():
memset(netmask, 0, sizeof(netmask));
}
-CSubNet::CSubNet(const std::string &strSubnet, bool fAllowLookup)
+CSubNet::CSubNet(const std::string &strSubnet)
{
size_t slash = strSubnet.find_last_of('/');
std::vector vIP;
@@ -1250,7 +1250,7 @@ CSubNet::CSubNet(const std::string &strSubnet, bool fAllowLookup)
memset(netmask, 255, sizeof(netmask));
std::string strAddress = strSubnet.substr(0, slash);
- if (LookupHost(strAddress.c_str(), vIP, 1, fAllowLookup))
+ if (LookupHost(strAddress.c_str(), vIP, 1, false))
{
network = vIP[0];
if (slash != strSubnet.npos)
diff --git a/src/netbase.h b/src/netbase.h
index 2eea8d5d8..8cf3f09fd 100644
--- a/src/netbase.h
+++ b/src/netbase.h
@@ -48,8 +48,8 @@ class CNetAddr
public:
CNetAddr();
CNetAddr(const struct in_addr& ipv4Addr);
- explicit CNetAddr(const char *pszIp, bool fAllowLookup = false);
- explicit CNetAddr(const std::string &strIp, bool fAllowLookup = false);
+ explicit CNetAddr(const char *pszIp);
+ explicit CNetAddr(const std::string &strIp);
void Init();
void SetIP(const CNetAddr& ip);
@@ -118,7 +118,7 @@ class CSubNet
public:
CSubNet();
- explicit CSubNet(const std::string &strSubnet, bool fAllowLookup = false);
+ explicit CSubNet(const std::string &strSubnet);
//constructor for single ip subnet (/32 or /128)
explicit CSubNet(const CNetAddr &addr);
@@ -153,10 +153,10 @@ class CService : public CNetAddr
CService(const CNetAddr& ip, unsigned short port);
CService(const struct in_addr& ipv4Addr, unsigned short port);
CService(const struct sockaddr_in& addr);
- explicit CService(const char *pszIpPort, int portDefault, bool fAllowLookup = false);
- explicit CService(const char *pszIpPort, bool fAllowLookup = false);
- explicit CService(const std::string& strIpPort, int portDefault, bool fAllowLookup = false);
- explicit CService(const std::string& strIpPort, bool fAllowLookup = false);
+ explicit CService(const char *pszIpPort, int portDefault);
+ explicit CService(const char *pszIpPort);
+ explicit CService(const std::string& strIpPort, int portDefault);
+ explicit CService(const std::string& strIpPort);
void Init();
void SetPort(unsigned short portIn);
unsigned short GetPort() const;
@@ -205,9 +205,9 @@ bool GetProxy(enum Network net, proxyType &proxyInfoOut);
bool IsProxy(const CNetAddr &addr);
bool SetNameProxy(const proxyType &addrProxy);
bool HaveNameProxy();
-bool LookupHost(const char *pszName, std::vector& vIP, unsigned int nMaxSolutions = 0, bool fAllowLookup = true);
-bool Lookup(const char *pszName, CService& addr, int portDefault = 0, bool fAllowLookup = true);
-bool Lookup(const char *pszName, std::vector& vAddr, int portDefault = 0, bool fAllowLookup = true, unsigned int nMaxSolutions = 0);
+bool LookupHost(const char *pszName, std::vector& vIP, unsigned int nMaxSolutions, bool fAllowLookup);
+bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLookup);
+bool Lookup(const char *pszName, std::vector& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions);
bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0);
bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed = 0);
bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout, bool *outProxyConnectionFailed = 0);
diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp
index f77a60eb5..6ee1ee2e5 100644
--- a/src/torcontrol.cpp
+++ b/src/torcontrol.cpp
@@ -434,7 +434,7 @@ void TorController::add_onion_cb(TorControlConnection& conn, const TorControlRep
private_key = i->second;
}
- service = CService(service_id+".onion", GetListenPort(), false);
+ service = CService(service_id+".onion", GetListenPort());
LogPrintf("tor: Got service ID %s, advertising service %s\n", service_id, service.ToString());
if (WriteBinaryFile(GetPrivateKeyFile(), private_key)) {
LogPrint("tor", "tor: Cached service private key to %s\n", GetPrivateKeyFile());