From 3d36540ee4658a5ba3b6f97a7b9cf790bdb0d06a Mon Sep 17 00:00:00 2001 From: Kaz Wesley Date: Thu, 15 Nov 2018 12:34:46 -0800 Subject: [PATCH 01/23] add test demonstrating addrLocal UB --- src/test/net_tests.cpp | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index c33fdb6a7e80..a2af0fbec908 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -9,6 +9,7 @@ #include "netbase.h" #include "serialize.h" #include "streams.h" +#include "util/memory.h" #include "test/test_pivx.h" @@ -176,4 +177,42 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test) BOOST_CHECK(pnode2->fFeeler == false); } +// prior to PR #14728, this test triggers an undefined behavior +BOOST_AUTO_TEST_CASE(ipv4_peer_with_ipv6_addrMe_test) +{ + // set up local addresses; all that's necessary to reproduce the bug is + // that a normal IPv4 address is among the entries, but if this address is + // !IsRoutable the undefined behavior is easier to trigger deterministically + { + LOCK(cs_mapLocalHost); + in_addr ipv4AddrLocal; + ipv4AddrLocal.s_addr = 0x0100007f; + CNetAddr addr = CNetAddr(ipv4AddrLocal); + LocalServiceInfo lsi; + lsi.nScore = 23; + lsi.nPort = 42; + mapLocalHost[addr] = lsi; + } + + // create a peer with an IPv4 address + in_addr ipv4AddrPeer; + ipv4AddrPeer.s_addr = 0xa0b0c001; + CAddress addr = CAddress(CService(ipv4AddrPeer, 7777), NODE_NETWORK); + std::unique_ptr pnode = MakeUnique(0, NODE_NETWORK, 0, INVALID_SOCKET, addr, 0, 0, std::string{}, false); + pnode->fSuccessfullyConnected.store(true); + + // the peer claims to be reaching us via IPv6 + in6_addr ipv6AddrLocal; + memset(ipv6AddrLocal.s6_addr, 0, 16); + ipv6AddrLocal.s6_addr[0] = 0xcc; + CAddress addrLocal = CAddress(CService(ipv6AddrLocal, 7777), NODE_NETWORK); + pnode->SetAddrLocal(addrLocal); + + // before patch, this causes undefined behavior detectable with clang's -fsanitize=memory + AdvertiseLocal(&*pnode); + + // suppress no-checks-run warning; if this test fails, it's by triggering a sanitizer + BOOST_CHECK(1); +} + BOOST_AUTO_TEST_SUITE_END() From c60b8752dc08e07a0ca00306fd223d27f51408ed Mon Sep 17 00:00:00 2001 From: Kaz Wesley Date: Wed, 14 Nov 2018 11:53:27 -0800 Subject: [PATCH 02/23] fix uninitialized read when stringifying an addrLocal Reachable from either place where SetIP is used when our best-guess addrLocal for a peer is IPv4, but the peer tells us it's reaching us at an IPv6 address. In that case, SetIP turns an IPv4 address into an IPv6 address without setting the scopeId, which is subsequently read in GetSockAddr during CNetAddr::ToStringIP and passed to getnameinfo. Fix by ensuring every constructor initializes the scopeId field with something. --- src/netaddress.cpp | 1 - src/netaddress.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/netaddress.cpp b/src/netaddress.cpp index 87ce9e53a011..42b8f939bebf 100644 --- a/src/netaddress.cpp +++ b/src/netaddress.cpp @@ -19,7 +19,6 @@ static const unsigned char pchOnionCat[] = {0xFD,0x87,0xD8,0x7E,0xEB,0x43}; void CNetAddr::Init() { memset(ip, 0, sizeof(ip)); - scopeId = 0; } void CNetAddr::SetIP(const CNetAddr& ipIn) diff --git a/src/netaddress.h b/src/netaddress.h index 7894e2aff5c2..f23e9c237171 100644 --- a/src/netaddress.h +++ b/src/netaddress.h @@ -31,7 +31,7 @@ class CNetAddr { protected: unsigned char ip[16]; // in network byte order - uint32_t scopeId{0}; // for scoped/link-local ipv6 addresses + uint32_t scopeId{0}; // for scoped/link-local ipv6 addresses public: CNetAddr(); From 8ba3a40fe6a43d24b480448af8c95e1c4b131a43 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 23 May 2017 20:04:38 -0400 Subject: [PATCH 03/23] net: add an internal subnet for representing unresolved hostnames We currently do two resolves for dns seeds: one for the results, and one to serve in addrman as the source for those addresses. There's no requirement that the source hostname resolves to the stored identifier, only that the mapping is unique. So rather than incurring the second lookup, combine a private subnet with a hash of the hostname. The resulting v6 ip is guaranteed not to be publicy routable, and has only a negligible chance of colliding with a user's internal network (which would be of no consequence anyway). --- src/net.cpp | 2 +- src/netaddress.cpp | 48 ++++++++++++++++++++++++++++++++------ src/netaddress.h | 8 +++++++ src/rpc/net.cpp | 2 +- src/test/netbase_tests.cpp | 14 +++++++++++ 5 files changed, 65 insertions(+), 9 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 0bf9b374297e..f6f160fc0d55 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -235,7 +235,7 @@ bool RemoveLocal(const CService& addr) /** Make a particular network entirely off-limits (no automatic connects to it) */ void SetLimited(enum Network net, bool fLimited) { - if (net == NET_UNROUTABLE) + if (net == NET_UNROUTABLE || net == NET_INTERNAL) return; LOCK(cs_mapLocalHost); vfLimited[net] = fLimited; diff --git a/src/netaddress.cpp b/src/netaddress.cpp index 42b8f939bebf..b735c92ce314 100644 --- a/src/netaddress.cpp +++ b/src/netaddress.cpp @@ -16,6 +16,9 @@ static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff }; static const unsigned char pchOnionCat[] = {0xFD,0x87,0xD8,0x7E,0xEB,0x43}; +// 0xFD + sha256("bitcoin")[0:5] +static const unsigned char g_internal_prefix[] = { 0xFD, 0x6B, 0x88, 0xC0, 0x87, 0x24 }; + void CNetAddr::Init() { memset(ip, 0, sizeof(ip)); @@ -42,6 +45,18 @@ void CNetAddr::SetRaw(Network network, const uint8_t* ip_in) } } +bool CNetAddr::SetInternal(const std::string &name) +{ + if (name.empty()) { + return false; + } + unsigned char hash[32] = {}; + CSHA256().Write((const unsigned char*)name.data(), name.size()).Finalize(hash); + memcpy(ip, g_internal_prefix, sizeof(g_internal_prefix)); + memcpy(ip + sizeof(g_internal_prefix), hash, sizeof(ip) - sizeof(g_internal_prefix)); + return true; +} + bool CNetAddr::SetSpecial(const std::string& strName) { if (strName.size()>6 && strName.substr(strName.size() - 6, 6) == ".onion") { @@ -84,7 +99,7 @@ bool CNetAddr::IsIPv4() const bool CNetAddr::IsIPv6() const { - return (!IsIPv4() && !IsTor()); + return (!IsIPv4() && !IsTor() && !IsInternal()); } bool CNetAddr::IsRFC1918() const @@ -205,6 +220,9 @@ bool CNetAddr::IsValid() const if (IsRFC3849()) return false; + if (IsInternal()) + return false; + if (IsIPv4()) { // INADDR_NONE @@ -223,11 +241,19 @@ bool CNetAddr::IsValid() const bool CNetAddr::IsRoutable() const { - return IsValid() && !(IsRFC1918() || IsRFC2544() || IsRFC3927() || IsRFC4862() || IsRFC6598() || IsRFC5737() || (IsRFC4193() && !IsTor()) || IsRFC4843() || IsLocal()); + return IsValid() && !(IsRFC1918() || IsRFC2544() || IsRFC3927() || IsRFC4862() || IsRFC6598() || IsRFC5737() || (IsRFC4193() && !IsTor()) || IsRFC4843() || IsLocal() || IsInternal()); +} + +bool CNetAddr::IsInternal() const +{ + return memcmp(ip, g_internal_prefix, sizeof(g_internal_prefix)) == 0; } enum Network CNetAddr::GetNetwork() const { + if (IsInternal()) + return NET_INTERNAL; + if (!IsRoutable()) return NET_UNROUTABLE; @@ -244,6 +270,8 @@ std::string CNetAddr::ToStringIP() const { if (IsTor()) return EncodeBase32(&ip[6], 10) + ".onion"; + if (IsInternal()) + return EncodeBase32(ip + sizeof(g_internal_prefix), sizeof(ip) - sizeof(g_internal_prefix)) + ".internal"; CService serv(*this, 0); struct sockaddr_storage sockaddr; socklen_t socklen = sizeof(sockaddr); @@ -311,9 +339,15 @@ std::vector CNetAddr::GetGroup() const nClass = 255; nBits = 0; } - - // all unroutable addresses belong to the same group - if (!IsRoutable()) + // all internal-usage addresses get their own group + if (IsInternal()) + { + nClass = NET_INTERNAL; + nStartByte = sizeof(g_internal_prefix); + nBits = (sizeof(ip) - sizeof(g_internal_prefix)) * 8; + } + // all other unroutable addresses belong to the same group + else if (!IsRoutable()) { nClass = NET_UNROUTABLE; nBits = 0; @@ -399,7 +433,7 @@ int CNetAddr::GetReachabilityFrom(const CNetAddr *paddrPartner) const REACH_PRIVATE }; - if (!IsRoutable()) + if (!IsRoutable() || IsInternal()) return REACH_UNREACHABLE; int ourNet = GetExtNetwork(this); @@ -558,7 +592,7 @@ std::string CService::ToStringPort() const std::string CService::ToStringIPPort() const { - if (IsIPv4() || IsTor()) { + if (IsIPv4() || IsTor() || IsInternal()) { return ToStringIP() + ":" + ToStringPort(); } else { return "[" + ToStringIP() + "]:" + ToStringPort(); diff --git a/src/netaddress.h b/src/netaddress.h index f23e9c237171..ba4a9b72d2d4 100644 --- a/src/netaddress.h +++ b/src/netaddress.h @@ -22,6 +22,7 @@ enum Network { NET_IPV4, NET_IPV6, NET_TOR, + NET_INTERNAL, NET_MAX, }; @@ -45,6 +46,12 @@ class CNetAddr */ void SetRaw(Network network, const uint8_t* data); + /** + * Transform an arbitrary string into a non-routable ipv6 address. + * Useful for mapping resolved addresses back to their source. + */ + bool SetInternal(const std::string& name); + bool SetSpecial(const std::string& strName); // for Tor addresses bool IsIPv4() const; // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0) bool IsIPv6() const; // IPv6 address (not mapped IPv4, not Tor) @@ -64,6 +71,7 @@ class CNetAddr bool IsTor() const; bool IsLocal() const; bool IsRoutable() const; + bool IsInternal() const; bool IsValid() const; bool IsMulticast() const; enum Network GetNetwork() const; diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 110fae714870..3b96c0b280f1 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -343,7 +343,7 @@ static UniValue GetNetworksInfo() UniValue networks(UniValue::VARR); for (int n = 0; n < NET_MAX; ++n) { enum Network network = static_cast(n); - if (network == NET_UNROUTABLE) + if (network == NET_UNROUTABLE || network == NET_INTERNAL) continue; proxyType proxy; UniValue obj(UniValue::VOBJ); diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index 7b03a7bc0632..ee70538792d6 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -29,6 +29,13 @@ static CSubNet ResolveSubNet(const char* subnet) return ret; } +static CNetAddr CreateInternal(const char* host) +{ + CNetAddr addr; + addr.SetInternal(host); + return addr; +} + BOOST_AUTO_TEST_CASE(netbase_networks) { BOOST_CHECK(ResolveIP("127.0.0.1").GetNetwork() == NET_UNROUTABLE); @@ -36,6 +43,7 @@ BOOST_AUTO_TEST_CASE(netbase_networks) BOOST_CHECK(ResolveIP("8.8.8.8").GetNetwork() == NET_IPV4); BOOST_CHECK(ResolveIP("2001::8888").GetNetwork() == NET_IPV6); BOOST_CHECK(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetNetwork() == NET_TOR); + BOOST_CHECK(CreateInternal("foo.com").GetNetwork() == NET_INTERNAL); } BOOST_AUTO_TEST_CASE(netbase_properties) @@ -60,6 +68,8 @@ BOOST_AUTO_TEST_CASE(netbase_properties) BOOST_CHECK(ResolveIP("8.8.8.8").IsRoutable()); BOOST_CHECK(ResolveIP("2001::1").IsRoutable()); BOOST_CHECK(ResolveIP("127.0.0.1").IsValid()); + BOOST_CHECK(CreateInternal("FD6B:88C0:8724:edb1:8e4:3588:e546:35ca").IsInternal()); + BOOST_CHECK(CreateInternal("bar.com").IsInternal()); } bool static TestSplitHost(std::string test, std::string host, int port) @@ -302,6 +312,10 @@ BOOST_AUTO_TEST_CASE(netbase_getgroup) BOOST_CHECK(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetGroup() == std::vector({(unsigned char)NET_TOR, 239})); // Tor BOOST_CHECK(ResolveIP("2001:470:abcd:9999:9999:9999:9999:9999").GetGroup() == std::vector({(unsigned char)NET_IPV6, 32, 1, 4, 112, 175})); //he.net BOOST_CHECK(ResolveIP("2001:2001:9999:9999:9999:9999:9999:9999").GetGroup() == std::vector({(unsigned char)NET_IPV6, 32, 1, 32, 1})); //IPv6 + + // baz.net sha256 hash: 12929400eb4607c4ac075f087167e75286b179c693eb059a01774b864e8fe505 + std::vector internal_group = {NET_INTERNAL, 0x12, 0x92, 0x94, 0x00, 0xeb, 0x46, 0x07, 0xc4, 0xac, 0x07}; + BOOST_CHECK(CreateInternal("baz.net").GetGroup() == internal_group); } BOOST_AUTO_TEST_CASE(netbase_parsenetwork) From 8f312950eb01a333dc9cfd873a0e7f2548a3ca9e Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 13 Jun 2017 17:26:50 -0400 Subject: [PATCH 04/23] net: do not allow resolving to an internal address In order to prevent mixups, our internal range is never allowed as a resolve result. This means that no user-provided string will ever be confused with an internal address. --- src/netbase.cpp | 10 ++++++++-- src/test/netbase_tests.cpp | 5 +++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/netbase.cpp b/src/netbase.cpp index 442260e58a81..468a6d013d57 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -112,14 +112,20 @@ bool static LookupIntern(const char* pszName, std::vector& vIP, unsign struct addrinfo* aiTrav = aiRes; while (aiTrav != NULL && (nMaxSolutions == 0 || vIP.size() < nMaxSolutions)) { + CNetAddr resolved; if (aiTrav->ai_family == AF_INET) { assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in)); - vIP.emplace_back(((struct sockaddr_in*)(aiTrav->ai_addr))->sin_addr); + resolved = CNetAddr(((struct sockaddr_in*)(aiTrav->ai_addr))->sin_addr); } if (aiTrav->ai_family == AF_INET6) { assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in6)); - vIP.emplace_back(((struct sockaddr_in6*)(aiTrav->ai_addr))->sin6_addr); + struct sockaddr_in6* s6 = (struct sockaddr_in6*) aiTrav->ai_addr; + resolved = CNetAddr(s6->sin6_addr, s6->sin6_scope_id); + } + /* Never allow resolving to an internal address. Consider any such result invalid */ + if (!resolved.IsInternal()) { + vIP.push_back(resolved); } aiTrav = aiTrav->ai_next; diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index ee70538792d6..6c0ff70d95b3 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -114,6 +114,11 @@ BOOST_AUTO_TEST_CASE(netbase_lookupnumeric) BOOST_CHECK(TestParse("[::]:51472", "[::]:51472")); BOOST_CHECK(TestParse("[127.0.0.1]", "127.0.0.1:65535")); BOOST_CHECK(TestParse(":::", "[::]:0")); + + // verify that an internal address fails to resolve + BOOST_CHECK(TestParse("[fd6b:88c0:8724:1:2:3:4:5]", "[::]:0")); + // and that a one-off resolves correctly + BOOST_CHECK(TestParse("[fd6c:88c0:8724:1:2:3:4:5]", "[fd6c:88c0:8724:1:2:3:4:5]:65535")); } BOOST_AUTO_TEST_CASE(onioncat_test) From 36368c58f4912c183e510e8ce6b0406d88ad0872 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 23 May 2017 20:48:08 -0400 Subject: [PATCH 05/23] net: switch to dummy internal ip for dns seed source This addresss the TODO to avoid resolving twice. --- src/chainparams.cpp | 8 ++++---- src/chainparams.h | 4 ++-- src/net.cpp | 22 ++++++++-------------- 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 95a414b64019..ded25027cafc 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -227,8 +227,8 @@ class CMainParams : public CChainParams nDefaultPort = 51472; // Note that of those with the service bits flag, most only support a subset of possible options - vSeeds.emplace_back("fuzzbawls.pw", "pivx.seed.fuzzbawls.pw", true); // Primary DNS Seeder from Fuzzbawls - vSeeds.emplace_back("fuzzbawls.pw", "pivx.seed2.fuzzbawls.pw", true); // Secondary DNS Seeder from Fuzzbawls + vSeeds.emplace_back("pivx.seed.fuzzbawls.pw", true); // Primary DNS Seeder from Fuzzbawls + vSeeds.emplace_back("pivx.seed2.fuzzbawls.pw", true); // Secondary DNS Seeder from Fuzzbawls base58Prefixes[PUBKEY_ADDRESS] = std::vector(1, 30); base58Prefixes[SCRIPT_ADDRESS] = std::vector(1, 13); @@ -351,8 +351,8 @@ class CTestNetParams : public CChainParams nDefaultPort = 51474; // nodes with support for servicebits filtering should be at the top - vSeeds.emplace_back("fuzzbawls.pw", "pivx-testnet.seed.fuzzbawls.pw", true); - vSeeds.emplace_back("fuzzbawls.pw", "pivx-testnet.seed2.fuzzbawls.pw", true); + vSeeds.emplace_back("pivx-testnet.seed.fuzzbawls.pw", true); + vSeeds.emplace_back("pivx-testnet.seed2.fuzzbawls.pw", true); base58Prefixes[PUBKEY_ADDRESS] = std::vector(1, 139); // Testnet pivx addresses start with 'x' or 'y' base58Prefixes[SCRIPT_ADDRESS] = std::vector(1, 19); // Testnet pivx script addresses start with '8' or '9' diff --git a/src/chainparams.h b/src/chainparams.h index 88c052f2edd9..adfc063a47da 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -19,9 +19,9 @@ #include struct CDNSSeedData { - std::string name, host; + std::string host; bool supportsServiceBitsFiltering; - CDNSSeedData(const std::string& strName, const std::string& strHost, bool supportsServiceBitsFilteringIn = false) : name(strName), host(strHost), supportsServiceBitsFiltering(supportsServiceBitsFilteringIn) {} + CDNSSeedData(const std::string& strHost, bool supportsServiceBitsFilteringIn = false) : host(strHost), supportsServiceBitsFiltering(supportsServiceBitsFilteringIn) {} }; struct SeedSpec6 { diff --git a/src/net.cpp b/src/net.cpp index f6f160fc0d55..b35b88c15c53 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1519,26 +1519,20 @@ void CConnman::ThreadDNSAddressSeed() std::vector vIPs; std::vector vAdd; ServiceFlags requiredServiceBits = nRelevantServices; - if (LookupHost(GetDNSHost(seed, &requiredServiceBits).c_str(), vIPs, 0, true)) { + std::string host = GetDNSHost(seed, &requiredServiceBits); + CNetAddr resolveSource; + if (!resolveSource.SetInternal(host)) { + continue; + } + if (LookupHost(host.c_str(), vIPs, 0, true)) { for (CNetAddr& ip : vIPs) { - int nOneDay = 24 * 3600; + int nOneDay = 24*3600; CAddress addr = CAddress(CService(ip, Params().GetDefaultPort()), requiredServiceBits); addr.nTime = GetTime() - 3 * nOneDay - GetRand(4 * nOneDay); // use a random age between 3 and 7 days old vAdd.push_back(addr); found++; } - } - if (interruptNet) { - return; - } - // 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); + addrman.Add(vAdd, resolveSource); } } } From af4cba3349e6f4ed86798f8fa19f07fb33358785 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 21 Jun 2017 15:45:20 -0400 Subject: [PATCH 06/23] net: use an internal address for fixed seeds --- src/net.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net.cpp b/src/net.cpp index b35b88c15c53..74ad83657de8 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1626,7 +1626,7 @@ void CConnman::ThreadOpenConnections() if (!done) { LogPrintf("Adding fixed seed nodes as DNS doesn't seem to be available.\n"); CNetAddr local; - LookupHost("127.0.0.1", local, false); + local.SetInternal("fixedseeds"); addrman.Add(convertSeed6(Params().FixedSeeds()), local); done = true; } From 48a622d181efc07cdd3c56cc423848314eea6ab0 Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Sun, 19 Feb 2017 13:18:04 -0500 Subject: [PATCH 07/23] Fix subscript[0] bug in net.cpp if GetGroup returns a 0-sized vector --- src/net.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net.cpp b/src/net.cpp index 74ad83657de8..041b6bbfed3f 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2604,6 +2604,6 @@ uint64_t CConnman::CalculateKeyedNetGroup(const CAddress& ad) { std::vector vchNetGroup(ad.GetGroup()); - return GetDeterministicRandomizer(RANDOMIZER_ID_NETGROUP).Write(&vchNetGroup[0], vchNetGroup.size()).Finalize(); + return GetDeterministicRandomizer(RANDOMIZER_ID_NETGROUP).Write(vchNetGroup.data(), vchNetGroup.size()).Finalize(); } From 5e14f548d5399544340263751f0abfa37736058e Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Sun, 19 Feb 2017 12:39:51 -0500 Subject: [PATCH 08/23] Fix subscript[0] in compressor.cpp --- src/compressor.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/compressor.cpp b/src/compressor.cpp index 994d4932519f..a54f7ab6757f 100644 --- a/src/compressor.cpp +++ b/src/compressor.cpp @@ -89,7 +89,7 @@ bool CScriptCompressor::Decompress(unsigned int nSize, const std::vector Date: Sun, 19 Feb 2017 13:11:44 -0500 Subject: [PATCH 09/23] Cleanup (safe, it was checked) subscript[0] in MurmurHash3 (and cleanup MurmurHash3 to be more clear). --- src/hash.cpp | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/src/hash.cpp b/src/hash.cpp index f5c5b3155a0c..cac5c5a4df30 100644 --- a/src/hash.cpp +++ b/src/hash.cpp @@ -17,35 +17,34 @@ unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector 0) { - const uint32_t c1 = 0xcc9e2d51; - const uint32_t c2 = 0x1b873593; + const uint32_t c1 = 0xcc9e2d51; + const uint32_t c2 = 0x1b873593; - const int nblocks = vDataToHash.size() / 4; + const int nblocks = vDataToHash.size() / 4; - //---------- - // body - const uint8_t* blocks = &vDataToHash[0] + nblocks * 4; + //---------- + // body + const uint8_t* blocks = vDataToHash.data(); - for (int i = -nblocks; i; i++) { - uint32_t k1 = ReadLE32(blocks + i*4); + for (int i = 0; i < nblocks; ++i) { + uint32_t k1 = ReadLE32(blocks + i*4); - k1 *= c1; - k1 = ROTL32(k1, 15); - k1 *= c2; + k1 *= c1; + k1 = ROTL32(k1, 15); + k1 *= c2; - h1 ^= k1; - h1 = ROTL32(h1, 13); - h1 = h1 * 5 + 0xe6546b64; - } + h1 ^= k1; + h1 = ROTL32(h1, 13); + h1 = h1 * 5 + 0xe6546b64; + } - //---------- - // tail - const uint8_t* tail = (const uint8_t*)(&vDataToHash[0] + nblocks * 4); + //---------- + // tail + const uint8_t* tail = vDataToHash.data() + nblocks * 4; - uint32_t k1 = 0; + uint32_t k1 = 0; - switch (vDataToHash.size() & 3) { + switch (vDataToHash.size() & 3) { case 3: k1 ^= tail[2] << 16; case 2: @@ -56,7 +55,6 @@ unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector Date: Sun, 19 Feb 2017 13:41:13 -0500 Subject: [PATCH 10/23] Fix subscript[0] in base58.cpp --- src/base58.cpp | 8 ++++---- src/base58.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/base58.cpp b/src/base58.cpp index 69092bdd5b11..40e3b1cb336c 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -127,7 +127,7 @@ std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend) std::string EncodeBase58(const std::vector& vch) { - return EncodeBase58(&vch[0], &vch[0] + vch.size()); + return EncodeBase58(vch.data(), vch.data() + vch.size()); } bool DecodeBase58(const std::string& str, std::vector& vchRet) @@ -177,7 +177,7 @@ void CBase58Data::SetData(const std::vector& vchVersionIn, const vchVersion = vchVersionIn; vchData.resize(nSize); if (!vchData.empty()) - memcpy(&vchData[0], pdata, nSize); + memcpy(vchData.data(), pdata, nSize); } void CBase58Data::SetData(const std::vector& vchVersionIn, const unsigned char* pbegin, const unsigned char* pend) @@ -197,8 +197,8 @@ bool CBase58Data::SetString(const char* psz, unsigned int nVersionBytes) vchVersion.assign(vchTemp.begin(), vchTemp.begin() + nVersionBytes); vchData.resize(vchTemp.size() - nVersionBytes); if (!vchData.empty()) - memcpy(&vchData[0], &vchTemp[nVersionBytes], vchData.size()); - memory_cleanse(&vchTemp[0], vchTemp.size()); + memcpy(vchData.data(), vchTemp.data() + nVersionBytes, vchData.size()); + memory_cleanse(vchTemp.data(), vchTemp.size()); return true; } diff --git a/src/base58.h b/src/base58.h index b825533f6604..63fa97b8620b 100644 --- a/src/base58.h +++ b/src/base58.h @@ -118,8 +118,8 @@ class CBitcoinExtKeyBase : public CBase58Data { K ret; if (vchData.size() == Size) { - //if base58 encouded data not holds a ext key, return a !IsValid() key - ret.Decode(&vchData[0]); + // If base58 encoded data does not hold an ext key, return a !IsValid() key + ret.Decode(vchData.data()); } return ret; } From 3b883eb9d4ca7f1d7f7e49012b483cc35e00fdd0 Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Sun, 19 Feb 2017 13:43:46 -0500 Subject: [PATCH 11/23] Fix subscript[0] in netaddress.cpp --- src/netaddress.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/netaddress.cpp b/src/netaddress.cpp index b735c92ce314..32d1e200dab4 100644 --- a/src/netaddress.cpp +++ b/src/netaddress.cpp @@ -579,7 +579,7 @@ std::vector CService::GetKey() const { std::vector vKey; vKey.resize(18); - memcpy(&vKey[0], ip, 16); + memcpy(vKey.data(), ip, 16); vKey[16] = port / 0x100; vKey[17] = port & 0x0FF; return vKey; From 2f7b73be93769a704a3a2e60334a1b5f28266f29 Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Sun, 19 Feb 2017 13:44:01 -0500 Subject: [PATCH 12/23] Fix subscript[0] in torcontrol --- src/torcontrol.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index c0439091852c..53d97548b858 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -663,7 +663,7 @@ void TorController::protocolinfo_cb(TorControlConnection& _conn, const TorContro // _conn.Command("AUTHENTICATE " + HexStr(status_cookie.second), std::bind(&TorController::auth_cb, this, std::placeholders::_1, std::placeholders::_2)); cookie = std::vector(status_cookie.second.begin(), status_cookie.second.end()); clientNonce = std::vector(TOR_NONCE_SIZE, 0); - GetRandBytes(&clientNonce[0], TOR_NONCE_SIZE); + GetRandBytes(clientNonce.data(), TOR_NONCE_SIZE); _conn.Command("AUTHCHALLENGE SAFECOOKIE " + HexStr(clientNonce), std::bind(&TorController::authchallenge_cb, this, std::placeholders::_1, std::placeholders::_2)); } else { if (status_cookie.first) { From b7e64a5a11dfb7b6b42838c418b622489d729084 Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Tue, 28 Mar 2017 11:37:06 -0400 Subject: [PATCH 13/23] Fix subscript[0] in validation.cpp --- src/serialize.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/serialize.h b/src/serialize.h index aa3e60b7cea9..dde4883be959 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -535,7 +535,7 @@ class LimitedString } string.resize(size); if (size != 0) - s.read((char*)&string[0], size); + s.read((char*)string.data(), size); } template @@ -543,7 +543,7 @@ class LimitedString { WriteCompactSize(s, string.size()); if (!string.empty()) - s.write((char*)&string[0], string.size()); + s.write((char*)string.data(), string.size()); } }; @@ -740,7 +740,7 @@ void Serialize(Stream& os, const std::basic_string& str) { WriteCompactSize(os, str.size()); if (!str.empty()) - os.write((char*)&str[0], str.size() * sizeof(str[0])); + os.write((char*)str.data(), str.size() * sizeof(C)); } template @@ -749,7 +749,7 @@ void Unserialize(Stream& is, std::basic_string& str) unsigned int nSize = ReadCompactSize(is); str.resize(nSize); if (nSize != 0) - is.read((char*)&str[0], nSize * sizeof(str[0])); + is.read((char*)str.data(), nSize * sizeof(C)); } /** @@ -798,7 +798,7 @@ void Serialize_impl(Stream& os, const prevector& v, const unsigned char&) { WriteCompactSize(os, v.size()); if (!v.empty()) - os.write((char*)&v[0], v.size() * sizeof(T)); + os.write((char*)v.data(), v.size() * sizeof(T)); } template @@ -866,7 +866,7 @@ void Serialize_impl(Stream& os, const std::vector& v, const unsigned char& { WriteCompactSize(os, v.size()); if (!v.empty()) - os.write((char*)&v[0], v.size() * sizeof(T)); + os.write((char*)v.data(), v.size() * sizeof(T)); } template From df0584e886ff1bef81f9cbc2026e5c2fb3b2135c Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Tue, 28 Mar 2017 11:35:51 -0400 Subject: [PATCH 14/23] Fix subscript[0] in streams.h --- src/streams.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/streams.h b/src/streams.h index 10df39862f24..9a2198aa030b 100644 --- a/src/streams.h +++ b/src/streams.h @@ -267,7 +267,7 @@ class CBaseDataStream { // Special case: stream << stream concatenates like stream += stream if (!vch.empty()) - s.write((char*)&vch[0], vch.size() * sizeof(vch[0])); + s.write((char*)vch.data(), vch.size() * sizeof(value_type)); } template From 25a16b31ab21c1bbf4669a26b87a826e3f5686ee Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Sun, 19 Feb 2017 13:46:19 -0500 Subject: [PATCH 15/23] Fix subscript[0] in utilstrencodings.cpp --- src/utilstrencodings.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp index 4a8f6adb5d4b..df51f66e7692 100644 --- a/src/utilstrencodings.cpp +++ b/src/utilstrencodings.cpp @@ -190,7 +190,7 @@ std::vector DecodeBase64(const char* p, bool* pfInvalid) std::string DecodeBase64(const std::string& str) { std::vector vchRet = DecodeBase64(str.c_str()); - return (vchRet.size() == 0) ? std::string() : std::string((const char*)&vchRet[0], vchRet.size()); + return (vchRet.size() == 0) ? std::string() : std::string((const char*)vchRet.data(), vchRet.size()); } // Base64 encoding with secure memory allocation @@ -286,7 +286,7 @@ std::vector DecodeBase32(const char* p, bool* pfInvalid) std::string DecodeBase32(const std::string& str) { std::vector vchRet = DecodeBase32(str.c_str()); - return (vchRet.size() == 0) ? std::string() : std::string((const char*)&vchRet[0], vchRet.size()); + return (vchRet.size() == 0) ? std::string() : std::string((const char*) vchRet.data(), vchRet.size()); } static bool ParsePrechecks(const std::string& str) From 8e2e79ec900a689c61ceeedaf2dbec9e3e5e923b Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Tue, 28 Mar 2017 11:17:07 -0400 Subject: [PATCH 16/23] Remove unnecessary branches in utilstrencodings string constructors. --- src/utilstrencodings.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp index df51f66e7692..96d5d60465a9 100644 --- a/src/utilstrencodings.cpp +++ b/src/utilstrencodings.cpp @@ -190,7 +190,7 @@ std::vector DecodeBase64(const char* p, bool* pfInvalid) std::string DecodeBase64(const std::string& str) { std::vector vchRet = DecodeBase64(str.c_str()); - return (vchRet.size() == 0) ? std::string() : std::string((const char*)vchRet.data(), vchRet.size()); + return std::string((const char*)vchRet.data(), vchRet.size()); } // Base64 encoding with secure memory allocation @@ -286,7 +286,7 @@ std::vector DecodeBase32(const char* p, bool* pfInvalid) std::string DecodeBase32(const std::string& str) { std::vector vchRet = DecodeBase32(str.c_str()); - return (vchRet.size() == 0) ? std::string() : std::string((const char*) vchRet.data(), vchRet.size()); + return std::string((const char*)vchRet.data(), vchRet.size()); } static bool ParsePrechecks(const std::string& str) From c814967a088f8ed7cf92ebfa649e30029b711283 Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Sun, 19 Feb 2017 13:35:49 -0500 Subject: [PATCH 17/23] Fix subscript[0] potential bugs in key.cpp --- src/key.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/key.cpp b/src/key.cpp index fce2d4a52d2e..7ca369007fe8 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -189,7 +189,7 @@ CPrivKey CKey::GetPrivKey() const size_t privkeylen; privkey.resize(PRIVATE_KEY_SIZE); privkeylen = PRIVATE_KEY_SIZE; - int ret = ec_privkey_export_der(secp256k1_context_sign, (unsigned char*)&privkey[0], &privkeylen, begin(), fCompressed ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED); + int ret = ec_privkey_export_der(secp256k1_context_sign, (unsigned char*)privkey.data(), &privkeylen, begin(), fCompressed ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED); assert(ret); privkey.resize(privkeylen); return privkey; @@ -306,7 +306,6 @@ void CExtKey::SetSeed(const unsigned char* seed, unsigned int nSeedLen) CHMAC_SHA512(hashkey, sizeof(hashkey)).Write(seed, nSeedLen).Finalize(vout.data()); key.Set(vout.data(), vout.data() + 32, true); memcpy(chaincode.begin(), vout.data() + 32, 32); - nDepth = 0; nChild = 0; memset(vchFingerprint, 0, sizeof(vchFingerprint)); From 3b3bf631eab692d5780d9079541aa675dd844046 Mon Sep 17 00:00:00 2001 From: kazcw Date: Wed, 16 Jul 2014 14:31:41 -0700 Subject: [PATCH 18/23] prevent peer flooding request queue for an inv mapAlreadyAskedFor does not keep track of which peer has a request queued for a particular tx. As a result, a peer can blind a node to a tx indefinitely by sending many invs for the same tx, and then never replying to getdatas for it. Each inv received will be placed 2 minutes farther back in mapAlreadyAskedFor, so a short message containing 10 invs would render that tx unavailable for 20 minutes. This is fixed by disallowing a peer from having more than one entry for a particular inv in mapAlreadyAskedFor at a time. --- src/net.cpp | 4 ++++ src/net.h | 1 + src/net_processing.cpp | 1 + 3 files changed, 6 insertions(+) diff --git a/src/net.cpp b/src/net.cpp index 041b6bbfed3f..27be7c993b5b 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2489,6 +2489,10 @@ void CNode::AskFor(const CInv& inv) { if (mapAskFor.size() > MAPASKFOR_MAX_SZ) return; + // a peer may not occupy multiple positions in an inv's request queue + if (!setAskFor.insert(inv.hash).second) + return; + // We're using mapAskFor as a priority queue, // the key is the earliest time the request can be sent int64_t nRequestTime; diff --git a/src/net.h b/src/net.h index 6f0eab8ac9b2..7478c27eb53c 100644 --- a/src/net.h +++ b/src/net.h @@ -624,6 +624,7 @@ class CNode std::vector vInventoryTierTwoToSend; RecursiveMutex cs_inventory; std::multimap mapAskFor; + std::set setAskFor; std::vector vBlockRequested; int64_t nNextInvSend; // Used for BIP35 mempool sending, also protected by cs_inventory diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 96dde1668ea2..5879194edad2 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -2371,6 +2371,7 @@ bool SendMessages(CNode* pto, CConnman& connman, std::atomic& interruptMsg vGetData.clear(); } } + pto->setAskFor.erase(inv.hash); pto->mapAskFor.erase(pto->mapAskFor.begin()); } if (!vGetData.empty()) From 74d0482c2297afa652f58d31895a3905368368f7 Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Mon, 23 Nov 2015 01:54:23 +0000 Subject: [PATCH 19/23] Limit setAskFor and retire requested entries only when a getdata returns. The setAskFor duplicate elimination was too eager and removed entries when we still had no getdata response, allowing the peer to keep INVing and not responding. --- src/net.cpp | 4 ++-- src/net.h | 2 ++ src/net_processing.cpp | 5 ++++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 27be7c993b5b..5fb70252abde 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2487,9 +2487,9 @@ CNode::~CNode() void CNode::AskFor(const CInv& inv) { - if (mapAskFor.size() > MAPASKFOR_MAX_SZ) + if (mapAskFor.size() > MAPASKFOR_MAX_SZ || setAskFor.size() > SETASKFOR_MAX_SZ) return; - // a peer may not occupy multiple positions in an inv's request queue + // a peer may not have multiple non-responded queue positions for a single inv item if (!setAskFor.insert(inv.hash).second) return; diff --git a/src/net.h b/src/net.h index 7478c27eb53c..ab959fc5ab18 100644 --- a/src/net.h +++ b/src/net.h @@ -69,6 +69,8 @@ static const bool DEFAULT_UPNP = false; #endif /** The maximum number of entries in mapAskFor */ static const size_t MAPASKFOR_MAX_SZ = MAX_INV_SZ; +/** The maximum number of entries in setAskFor (larger due to getdata latency)*/ +static const size_t SETASKFOR_MAX_SZ = 2 * MAX_INV_SZ; /** The maximum number of peer connections to maintain. */ static const unsigned int DEFAULT_MAX_PEER_CONNECTIONS = 125; /** Disconnected peers are added to setOffsetDisconnectedPeers only if node has less than ENOUGH_CONNECTIONS */ diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 5879194edad2..ccbd57ee58db 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -1508,6 +1508,7 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR bool fMissingInputs = false; CValidationState state; + pfrom->setAskFor.erase(inv.hash); mapAlreadyAskedFor.erase(inv); if (ptx->ContainsZerocoins()) { @@ -2370,8 +2371,10 @@ bool SendMessages(CNode* pto, CConnman& connman, std::atomic& interruptMsg connman.PushMessage(pto, msgMaker.Make(NetMsgType::GETDATA, vGetData)); vGetData.clear(); } + } else { + //If we're not going to ask, don't expect a response. + pto->setAskFor.erase(inv.hash); } - pto->setAskFor.erase(inv.hash); pto->mapAskFor.erase(pto->mapAskFor.begin()); } if (!vGetData.empty()) From 539086274b562ab9bd198ef462a1aaa9acebf99c Mon Sep 17 00:00:00 2001 From: furszy Date: Sat, 8 May 2021 12:59:30 -0300 Subject: [PATCH 20/23] net: remove unimplemented functions. --- src/net.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/net.h b/src/net.h index ab959fc5ab18..fa5f538fed70 100644 --- a/src/net.h +++ b/src/net.h @@ -224,7 +224,6 @@ class CConnman void AddNewAddress(const CAddress& addr, const CAddress& addrFrom, int64_t nTimePenalty = 0); void AddNewAddresses(const std::vector& vAddr, const CAddress& addrFrom, int64_t nTimePenalty = 0); std::vector GetAddresses(); - void AddressCurrentlyConnected(const CService& addr); // Denial-of-service detection/prevention // The idea is to detect peers that are behaving @@ -794,9 +793,6 @@ class CNode vecRequestsFulfilled.push_back(strRequest); } - bool IsSubscribed(unsigned int nChannel); - void Subscribe(unsigned int nChannel, unsigned int nHops = 0); - void CancelSubscribe(unsigned int nChannel); void CloseSocketDisconnect(); bool DisconnectOldProtocol(int nVersionIn, int nVersionRequired, std::string strLastCommand = ""); From 7772138e3b200a60c2f12162dabc4acfa95641e5 Mon Sep 17 00:00:00 2001 From: practicalswift Date: Wed, 28 Jun 2017 23:14:48 +0200 Subject: [PATCH 21/23] Remove redundant nullptr checks before deallocation Rationale: * delete ptr is a no-op if ptr is nullptr --- src/net.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 5fb70252abde..33ae3508b761 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2481,8 +2481,7 @@ CNode::~CNode() { CloseSocket(hSocket); - if (pfilter) - delete pfilter; + delete pfilter; } void CNode::AskFor(const CInv& inv) From a0a079fc778fe7e8e0de30c77b5a794e963a1dad Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Fri, 9 Jun 2017 02:05:53 +0000 Subject: [PATCH 22/23] Return early in IsBanned. I am not aware of any reason that we'd try to stop a ban-list timing side-channel and the prior code wouldn't be enough if we were. --- src/net.cpp | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 33ae3508b761..7a9f6cc9f2aa 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -453,34 +453,30 @@ void CConnman::ClearBanned() bool CConnman::IsBanned(CNetAddr ip) { - bool fResult = false; + LOCK(cs_setBanned); + for (banmap_t::iterator it = setBanned.begin(); it != setBanned.end(); it++) { - LOCK(cs_setBanned); - for (banmap_t::iterator it = setBanned.begin(); it != setBanned.end(); it++) - { - CSubNet subNet = (*it).first; - CBanEntry banEntry = (*it).second; + CSubNet subNet = (*it).first; + CBanEntry banEntry = (*it).second; - if(subNet.Match(ip) && GetTime() < banEntry.nBanUntil) - fResult = true; + if (subNet.Match(ip) && GetTime() < banEntry.nBanUntil) { + return true; } } - return fResult; + return false; } bool CConnman::IsBanned(CSubNet subnet) { - bool fResult = false; - { - LOCK(cs_setBanned); - banmap_t::iterator i = setBanned.find(subnet); - if (i != setBanned.end()) { - CBanEntry banEntry = (*i).second; - if (GetTime() < banEntry.nBanUntil) - fResult = true; + LOCK(cs_setBanned); + banmap_t::iterator i = setBanned.find(subnet); + if (i != setBanned.end()) { + CBanEntry banEntry = (*i).second; + if (GetTime() < banEntry.nBanUntil) { + return true; } } - return fResult; + return false; } void CConnman::Ban(const CNetAddr& addr, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch) From fcdf87a55ad8c90a28b479d41e3591253da921e2 Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Thu, 18 May 2017 16:57:53 -0400 Subject: [PATCH 23/23] Populate services in GetLocalAddress Previously if we didn't have any local addresses, GetLocalAddress would return 0.0.0.0 and then we'd swap in a peer's notion of our address in AdvertiseLocal, but then nServices would never get set. --- src/net.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net.cpp b/src/net.cpp index 7a9f6cc9f2aa..3ec16a5b3f4f 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -147,7 +147,7 @@ static std::vector convertSeed6(const std::vector& vSeedsIn // one by discovery. CAddress GetLocalAddress(const CNetAddr* paddrPeer, ServiceFlags nLocalServices) { - CAddress ret(CService(CNetAddr(), GetListenPort()), NODE_NONE); + CAddress ret(CService(CNetAddr(), GetListenPort()), nLocalServices); CService addr; if (GetLocal(addr, paddrPeer)) { ret = CAddress(addr, nLocalServices);