From ce79f3251851f6177f38009341802e6065cb70af Mon Sep 17 00:00:00 2001 From: Marko Bencun Date: Thu, 1 Jun 2017 11:07:08 +0200 Subject: [PATCH 1/2] add WhitelistedRange to CConnman::Options Part of a series of changes to clean up the instantiation of connman by decoupling the command line arguments. --- src/init.cpp | 20 ++++++++++---------- src/net.cpp | 9 ++------- src/net.h | 4 +--- 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index ed7695344..aedad25bd 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1289,16 +1289,6 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) } } - if (gArgs.IsArgSet("-whitelist")) { - for (const std::string& net : gArgs.GetArgs("-whitelist")) { - CSubNet subnet; - LookupSubNet(net.c_str(), subnet); - if (!subnet.IsValid()) - return InitError(strprintf(_("Invalid netmask specified in -whitelist: '%s'"), net)); - connman.AddWhitelistedRange(subnet); - } - } - // Check for host lookup allowed before parsing any network related parameters fNameLookup = GetBoolArg("-dns", DEFAULT_NAME_LOOKUP); @@ -1661,6 +1651,16 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) connOptions.nMaxOutboundTimeframe = nMaxOutboundTimeframe; connOptions.nMaxOutboundLimit = nMaxOutboundLimit; + if (gArgs.IsArgSet("-whitelist")) { + for (const auto& net : gArgs.GetArgs("-whitelist")) { + CSubNet subnet; + LookupSubNet(net.c_str(), subnet); + if (!subnet.IsValid()) + return InitError(strprintf(_("Invalid netmask specified in -whitelist: '%s'"), net)); + connOptions.vWhitelistedRange.push_back(subnet); + } + } + if (gArgs.IsArgSet("-seednode")) { connOptions.vSeedNodes = gArgs.GetArgs("-seednode"); } diff --git a/src/net.cpp b/src/net.cpp index 73f020273..cc4341e29 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -601,7 +601,6 @@ void CConnman::SetBannedSetDirty(bool dirty) bool CConnman::IsWhitelistedRange(const CNetAddr &addr) { - LOCK(cs_vWhitelistedRange); for (const CSubNet& subnet : vWhitelistedRange) { if (subnet.Match(addr)) return true; @@ -609,12 +608,6 @@ bool CConnman::IsWhitelistedRange(const CNetAddr &addr) { return false; } -void CConnman::AddWhitelistedRange(const CSubNet &subnet) { - LOCK(cs_vWhitelistedRange); - vWhitelistedRange.push_back(subnet); -} - - std::string CNode::GetAddrName() const { LOCK(cs_addrName); return addrName; @@ -2248,6 +2241,8 @@ bool CConnman::Start(CScheduler& scheduler, std::string& strNodeError, Options c SetBestHeight(connOptions.nBestHeight); + vWhitelistedRange = connOptions.vWhitelistedRange; + for (const auto& strDest : connOptions.vSeedNodes) { AddOneShot(strDest); } diff --git a/src/net.h b/src/net.h index a6aea189f..b11baab33 100644 --- a/src/net.h +++ b/src/net.h @@ -144,6 +144,7 @@ public: uint64_t nMaxOutboundTimeframe = 0; uint64_t nMaxOutboundLimit = 0; std::vector vSeedNodes; + std::vector vWhitelistedRange; }; CConnman(uint64_t seed0, uint64_t seed1); ~CConnman(); @@ -244,8 +245,6 @@ public: unsigned int GetSendBufferSize() const; - void AddWhitelistedRange(const CSubNet &subnet); - ServiceFlags GetLocalServices() const; //!set the max outbound target in bytes @@ -346,7 +345,6 @@ private: // Whitelisted ranges. Any node connecting from these is automatically // whitelisted (as well as those connecting to whitelisted binds). std::vector vWhitelistedRange; - CCriticalSection cs_vWhitelistedRange; unsigned int nSendBufferMaxSize; unsigned int nReceiveFloodSize; From 07b2afef10bb6366a270e325fd41a8bc526c9ef3 Mon Sep 17 00:00:00 2001 From: Marko Bencun Date: Thu, 1 Jun 2017 12:34:02 +0200 Subject: [PATCH 2/2] add Binds, WhiteBinds to CConnman::Options Part of a series of changes to clean up the instantiation of connman by decoupling the command line arguments. We also now abort with an error when explicit binds are set with -listen=0. --- src/init.cpp | 89 ++++++++++++++++++++-------------------------------- src/net.cpp | 53 +++++++++++++++++++++++++++++-- src/net.h | 7 +++-- 3 files changed, 90 insertions(+), 59 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index aedad25bd..d1c196e35 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -88,14 +88,6 @@ static CZMQNotificationInterface* pzmqNotificationInterface = NULL; #define MIN_CORE_FILEDESCRIPTORS 150 #endif -/** Used to pass flags to the Bind() function */ -enum BindFlags { - BF_NONE = 0, - BF_EXPLICIT = (1U << 0), - BF_REPORT_ERROR = (1U << 1), - BF_WHITELIST = (1U << 2), -}; - static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat"; ////////////////////////////////////////////////////////////////////////////// @@ -296,17 +288,6 @@ static void registerSignalHandler(int signal, void(*handler)(int)) } #endif -bool static Bind(CConnman& connman, const CService &addr, unsigned int flags) { - if (!(flags & BF_EXPLICIT) && IsLimited(addr)) - return false; - std::string strError; - if (!connman.BindListenPort(addr, strError, (flags & BF_WHITELIST) != 0)) { - if (flags & BF_REPORT_ERROR) - return InitError(strError); - return false; - } - return true; -} void OnRPCStarted() { uiInterface.NotifyBlockTip.connect(&RPCNotifyBlockChange); @@ -900,10 +881,16 @@ bool AppInitParameterInteraction() return InitError(_("Prune mode is incompatible with -txindex.")); } + // -bind and -whitebind can't be set when not listening + size_t nUserBind = + (gArgs.IsArgSet("-bind") ? gArgs.GetArgs("-bind").size() : 0) + + (gArgs.IsArgSet("-whitebind") ? gArgs.GetArgs("-whitebind").size() : 0); + if (nUserBind != 0 && !gArgs.GetBoolArg("-listen", DEFAULT_LISTEN)) { + return InitError("Cannot set -bind or -whitebind together with -listen=0"); + } + // Make sure enough file descriptors are available - int nBind = std::max( - (gArgs.IsArgSet("-bind") ? gArgs.GetArgs("-bind").size() : 0) + - (gArgs.IsArgSet("-whitebind") ? gArgs.GetArgs("-whitebind").size() : 0), size_t(1)); + int nBind = std::max(nUserBind, size_t(1)); nUserMaxConnections = GetArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS); nMaxConnections = std::max(nUserMaxConnections, 0); @@ -1339,36 +1326,6 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) fDiscover = GetBoolArg("-discover", true); fRelayTxes = !GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY); - if (fListen) { - bool fBound = false; - if (gArgs.IsArgSet("-bind")) { - for (const std::string& strBind : gArgs.GetArgs("-bind")) { - CService addrBind; - if (!Lookup(strBind.c_str(), addrBind, GetListenPort(), false)) - return InitError(ResolveErrMsg("bind", strBind)); - fBound |= Bind(connman, addrBind, (BF_EXPLICIT | BF_REPORT_ERROR)); - } - } - if (gArgs.IsArgSet("-whitebind")) { - for (const std::string& strBind : gArgs.GetArgs("-whitebind")) { - CService addrBind; - if (!Lookup(strBind.c_str(), addrBind, 0, false)) - return InitError(ResolveErrMsg("whitebind", strBind)); - if (addrBind.GetPort() == 0) - return InitError(strprintf(_("Need to specify a port with -whitebind: '%s'"), strBind)); - fBound |= Bind(connman, addrBind, (BF_EXPLICIT | BF_REPORT_ERROR | BF_WHITELIST)); - } - } - if (!gArgs.IsArgSet("-bind") && !gArgs.IsArgSet("-whitebind")) { - struct in_addr inaddr_any; - inaddr_any.s_addr = INADDR_ANY; - fBound |= Bind(connman, CService(in6addr_any, GetListenPort()), BF_NONE); - fBound |= Bind(connman, CService(inaddr_any, GetListenPort()), !fBound ? BF_REPORT_ERROR : BF_NONE); - } - if (!fBound) - return InitError(_("Failed to listen on any port. Use -listen=0 if you want this.")); - } - if (gArgs.IsArgSet("-externalip")) { for (const std::string& strAddr : gArgs.GetArgs("-externalip")) { CService addrLocal; @@ -1635,7 +1592,6 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) // Map ports with UPnP MapPort(GetBoolArg("-upnp", DEFAULT_UPNP)); - std::string strNodeError; CConnman::Options connOptions; connOptions.nLocalServices = nLocalServices; connOptions.nRelevantServices = nRelevantServices; @@ -1651,6 +1607,28 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) connOptions.nMaxOutboundTimeframe = nMaxOutboundTimeframe; connOptions.nMaxOutboundLimit = nMaxOutboundLimit; + if (gArgs.IsArgSet("-bind")) { + for (const std::string& strBind : gArgs.GetArgs("-bind")) { + CService addrBind; + if (!Lookup(strBind.c_str(), addrBind, GetListenPort(), false)) { + return InitError(ResolveErrMsg("bind", strBind)); + } + connOptions.vBinds.push_back(addrBind); + } + } + if (gArgs.IsArgSet("-whitebind")) { + for (const std::string& strBind : gArgs.GetArgs("-whitebind")) { + CService addrBind; + if (!Lookup(strBind.c_str(), addrBind, 0, false)) { + return InitError(ResolveErrMsg("whitebind", strBind)); + } + if (addrBind.GetPort() == 0) { + return InitError(strprintf(_("Need to specify a port with -whitebind: '%s'"), strBind)); + } + connOptions.vWhiteBinds.push_back(addrBind); + } + } + if (gArgs.IsArgSet("-whitelist")) { for (const auto& net : gArgs.GetArgs("-whitelist")) { CSubNet subnet; @@ -1665,8 +1643,9 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) connOptions.vSeedNodes = gArgs.GetArgs("-seednode"); } - if (!connman.Start(scheduler, strNodeError, connOptions)) - return InitError(strNodeError); + if (!connman.Start(scheduler, connOptions)) { + return false; + } // ********************************************************* Step 12: finished diff --git a/src/net.cpp b/src/net.cpp index cc4341e29..9adad0327 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -64,6 +64,14 @@ #endif #endif +/** Used to pass flags to the Bind() function */ +enum BindFlags { + BF_NONE = 0, + BF_EXPLICIT = (1U << 0), + BF_REPORT_ERROR = (1U << 1), + BF_WHITELIST = (1U << 2), +}; + const static std::string NET_MESSAGE_COMMAND_OTHER = "*other*"; static const uint64_t RANDOMIZER_ID_NETGROUP = 0x6c0edd8036ef4036ULL; // SHA256("netgroup")[0:8] @@ -2219,7 +2227,38 @@ NodeId CConnman::GetNewNodeId() return nLastNodeId.fetch_add(1, std::memory_order_relaxed); } -bool CConnman::Start(CScheduler& scheduler, std::string& strNodeError, Options connOptions) + +bool CConnman::Bind(const CService &addr, unsigned int flags) { + if (!(flags & BF_EXPLICIT) && IsLimited(addr)) + return false; + std::string strError; + if (!BindListenPort(addr, strError, (flags & BF_WHITELIST) != 0)) { + if ((flags & BF_REPORT_ERROR) && clientInterface) { + clientInterface->ThreadSafeMessageBox(strError, "", CClientUIInterface::MSG_ERROR); + } + return false; + } + return true; +} + +bool CConnman::InitBinds(const std::vector& binds, const std::vector& whiteBinds) { + bool fBound = false; + for (const auto& addrBind : binds) { + fBound |= Bind(addrBind, (BF_EXPLICIT | BF_REPORT_ERROR)); + } + for (const auto& addrBind : whiteBinds) { + fBound |= Bind(addrBind, (BF_EXPLICIT | BF_REPORT_ERROR | BF_WHITELIST)); + } + if (binds.empty() && whiteBinds.empty()) { + struct in_addr inaddr_any; + inaddr_any.s_addr = INADDR_ANY; + fBound |= Bind(CService(in6addr_any, GetListenPort()), BF_NONE); + fBound |= Bind(CService(inaddr_any, GetListenPort()), !fBound ? BF_REPORT_ERROR : BF_NONE); + } + return fBound; +} + +bool CConnman::Start(CScheduler& scheduler, Options connOptions) { nTotalBytesRecv = 0; nTotalBytesSent = 0; @@ -2241,13 +2280,23 @@ bool CConnman::Start(CScheduler& scheduler, std::string& strNodeError, Options c SetBestHeight(connOptions.nBestHeight); + clientInterface = connOptions.uiInterface; + + if (fListen && !InitBinds(connOptions.vBinds, connOptions.vWhiteBinds)) { + if (clientInterface) { + clientInterface->ThreadSafeMessageBox( + _("Failed to listen on any port. Use -listen=0 if you want this."), + "", CClientUIInterface::MSG_ERROR); + } + return false; + } + vWhitelistedRange = connOptions.vWhitelistedRange; for (const auto& strDest : connOptions.vSeedNodes) { AddOneShot(strDest); } - clientInterface = connOptions.uiInterface; if (clientInterface) { clientInterface->InitMessage(_("Loading P2P addresses...")); } diff --git a/src/net.h b/src/net.h index b11baab33..dc25e7a5d 100644 --- a/src/net.h +++ b/src/net.h @@ -145,13 +145,13 @@ public: uint64_t nMaxOutboundLimit = 0; std::vector vSeedNodes; std::vector vWhitelistedRange; + std::vector vBinds, vWhiteBinds; }; CConnman(uint64_t seed0, uint64_t seed1); ~CConnman(); - bool Start(CScheduler& scheduler, std::string& strNodeError, Options options); + bool Start(CScheduler& scheduler, Options options); void Stop(); void Interrupt(); - bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); bool GetNetworkActive() const { return fNetworkActive; }; void SetNetworkActive(bool active); bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false, bool fAddnode = false); @@ -288,6 +288,9 @@ private: ListenSocket(SOCKET socket_, bool whitelisted_) : socket(socket_), whitelisted(whitelisted_) {} }; + bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); + bool Bind(const CService &addr, unsigned int flags); + bool InitBinds(const std::vector& binds, const std::vector& whiteBinds); void ThreadOpenAddedConnections(); void AddOneShot(const std::string& strDest); void ProcessOneShot();