mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-29 20:47:31 -03:00
14ceddd290
3bd67ba5a4
Test addr response caching (Gleb Naumenko)cf1569e074
Add addr permission flag enabling non-cached addr sharing (Gleb Naumenko)acd6135b43
Cache responses to addr requests (Gleb Naumenko)7cc0e8101f
Remove useless 2500 limit on AddrMan queries (Gleb Naumenko)ded742bc5b
Move filtering banned addrs inside GetAddresses() (Gleb Naumenko) Pull request description: This is a very simple code change with a big p2p privacy benefit. It’s currently trivial to scrape any reachable node’s AddrMan (a database of all nodes known to them along with the timestamps). We do have a limit of one GETADDR per connection, but a spy can disconnect and reconnect even from the same IP, and send GETADDR again and again. Since we respond with 1,000 random records at most, depending on the AddrMan size it takes probably up to 100 requests for an spy to make sure they scraped (almost) everything. I even have a script for that. It is totally doable within couple minutes. Then, with some extra protocol knowledge a spy can infer the direct peers of the victim, and other topological stuff. I suggest to cache responses to GETADDR on a daily basis, so that an attacker gets at most 1,000 records per day, and can’t track the changes in real time. I will be following up with more improvements to addr relay privacy, but this one alone is a very effective. And simple! I doubt any of the real software does *reconnect to get new addrs from a given peer*, so we shouldn’t be cutting anyone. I also believe it doesn’t have any negative implications on the overall topology quality. And the records being “outdated” for at most a day doesn’t break any honest assumptions either. ACKs for top commit: jnewbery: reACK3bd67ba5a4
promag: Code review ACK3bd67ba5a4
. ariard: Code Review ACK3bd67ba
Tree-SHA512: dfa5d03205c2424e40a3f8a41af9306227e1ca18beead3b3dda44aa2a082175bb1c6d929dbc7ea8e48e01aed0d50f0d54491caa1147471a2b72a46c3ca06b66f
437 lines
23 KiB
C++
437 lines
23 KiB
C++
// Copyright (c) 2012-2020 The Bitcoin Core developers
|
|
// Distributed under the MIT software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#include <net_permissions.h>
|
|
#include <netbase.h>
|
|
#include <test/util/setup_common.h>
|
|
#include <util/strencodings.h>
|
|
#include <util/translation.h>
|
|
|
|
#include <string>
|
|
|
|
#include <boost/test/unit_test.hpp>
|
|
|
|
BOOST_FIXTURE_TEST_SUITE(netbase_tests, BasicTestingSetup)
|
|
|
|
static CNetAddr ResolveIP(const std::string& ip)
|
|
{
|
|
CNetAddr addr;
|
|
LookupHost(ip, addr, false);
|
|
return addr;
|
|
}
|
|
|
|
static CSubNet ResolveSubNet(const std::string& subnet)
|
|
{
|
|
CSubNet ret;
|
|
LookupSubNet(subnet, ret);
|
|
return ret;
|
|
}
|
|
|
|
static CNetAddr CreateInternal(const std::string& host)
|
|
{
|
|
CNetAddr addr;
|
|
addr.SetInternal(host);
|
|
return addr;
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(netbase_networks)
|
|
{
|
|
BOOST_CHECK(ResolveIP("127.0.0.1").GetNetwork() == NET_UNROUTABLE);
|
|
BOOST_CHECK(ResolveIP("::1").GetNetwork() == NET_UNROUTABLE);
|
|
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_ONION);
|
|
BOOST_CHECK(CreateInternal("foo.com").GetNetwork() == NET_INTERNAL);
|
|
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(netbase_properties)
|
|
{
|
|
|
|
BOOST_CHECK(ResolveIP("127.0.0.1").IsIPv4());
|
|
BOOST_CHECK(ResolveIP("::FFFF:192.168.1.1").IsIPv4());
|
|
BOOST_CHECK(ResolveIP("::1").IsIPv6());
|
|
BOOST_CHECK(ResolveIP("10.0.0.1").IsRFC1918());
|
|
BOOST_CHECK(ResolveIP("192.168.1.1").IsRFC1918());
|
|
BOOST_CHECK(ResolveIP("172.31.255.255").IsRFC1918());
|
|
BOOST_CHECK(ResolveIP("198.18.0.0").IsRFC2544());
|
|
BOOST_CHECK(ResolveIP("198.19.255.255").IsRFC2544());
|
|
BOOST_CHECK(ResolveIP("2001:0DB8::").IsRFC3849());
|
|
BOOST_CHECK(ResolveIP("169.254.1.1").IsRFC3927());
|
|
BOOST_CHECK(ResolveIP("2002::1").IsRFC3964());
|
|
BOOST_CHECK(ResolveIP("FC00::").IsRFC4193());
|
|
BOOST_CHECK(ResolveIP("2001::2").IsRFC4380());
|
|
BOOST_CHECK(ResolveIP("2001:10::").IsRFC4843());
|
|
BOOST_CHECK(ResolveIP("2001:20::").IsRFC7343());
|
|
BOOST_CHECK(ResolveIP("FE80::").IsRFC4862());
|
|
BOOST_CHECK(ResolveIP("64:FF9B::").IsRFC6052());
|
|
BOOST_CHECK(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").IsTor());
|
|
BOOST_CHECK(ResolveIP("127.0.0.1").IsLocal());
|
|
BOOST_CHECK(ResolveIP("::1").IsLocal());
|
|
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)
|
|
{
|
|
std::string hostOut;
|
|
int portOut = -1;
|
|
SplitHostPort(test, portOut, hostOut);
|
|
return hostOut == host && port == portOut;
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(netbase_splithost)
|
|
{
|
|
BOOST_CHECK(TestSplitHost("www.bitcoincore.org", "www.bitcoincore.org", -1));
|
|
BOOST_CHECK(TestSplitHost("[www.bitcoincore.org]", "www.bitcoincore.org", -1));
|
|
BOOST_CHECK(TestSplitHost("www.bitcoincore.org:80", "www.bitcoincore.org", 80));
|
|
BOOST_CHECK(TestSplitHost("[www.bitcoincore.org]:80", "www.bitcoincore.org", 80));
|
|
BOOST_CHECK(TestSplitHost("127.0.0.1", "127.0.0.1", -1));
|
|
BOOST_CHECK(TestSplitHost("127.0.0.1:8333", "127.0.0.1", 8333));
|
|
BOOST_CHECK(TestSplitHost("[127.0.0.1]", "127.0.0.1", -1));
|
|
BOOST_CHECK(TestSplitHost("[127.0.0.1]:8333", "127.0.0.1", 8333));
|
|
BOOST_CHECK(TestSplitHost("::ffff:127.0.0.1", "::ffff:127.0.0.1", -1));
|
|
BOOST_CHECK(TestSplitHost("[::ffff:127.0.0.1]:8333", "::ffff:127.0.0.1", 8333));
|
|
BOOST_CHECK(TestSplitHost("[::]:8333", "::", 8333));
|
|
BOOST_CHECK(TestSplitHost("::8333", "::8333", -1));
|
|
BOOST_CHECK(TestSplitHost(":8333", "", 8333));
|
|
BOOST_CHECK(TestSplitHost("[]:8333", "", 8333));
|
|
BOOST_CHECK(TestSplitHost("", "", -1));
|
|
}
|
|
|
|
bool static TestParse(std::string src, std::string canon)
|
|
{
|
|
CService addr(LookupNumeric(src, 65535));
|
|
return canon == addr.ToString();
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(netbase_lookupnumeric)
|
|
{
|
|
BOOST_CHECK(TestParse("127.0.0.1", "127.0.0.1:65535"));
|
|
BOOST_CHECK(TestParse("127.0.0.1:8333", "127.0.0.1:8333"));
|
|
BOOST_CHECK(TestParse("::ffff:127.0.0.1", "127.0.0.1:65535"));
|
|
BOOST_CHECK(TestParse("::", "[::]:65535"));
|
|
BOOST_CHECK(TestParse("[::]:8333", "[::]:8333"));
|
|
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)
|
|
{
|
|
// values from https://web.archive.org/web/20121122003543/http://www.cypherpunk.at/onioncat/wiki/OnionCat
|
|
CNetAddr addr1(ResolveIP("5wyqrzbvrdsumnok.onion"));
|
|
CNetAddr addr2(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca"));
|
|
BOOST_CHECK(addr1 == addr2);
|
|
BOOST_CHECK(addr1.IsTor());
|
|
BOOST_CHECK(addr1.ToStringIP() == "5wyqrzbvrdsumnok.onion");
|
|
BOOST_CHECK(addr1.IsRoutable());
|
|
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(embedded_test)
|
|
{
|
|
CNetAddr addr1(ResolveIP("1.2.3.4"));
|
|
CNetAddr addr2(ResolveIP("::FFFF:0102:0304"));
|
|
BOOST_CHECK(addr2.IsIPv4());
|
|
BOOST_CHECK_EQUAL(addr1.ToString(), addr2.ToString());
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(subnet_test)
|
|
{
|
|
|
|
BOOST_CHECK(ResolveSubNet("1.2.3.0/24") == ResolveSubNet("1.2.3.0/255.255.255.0"));
|
|
BOOST_CHECK(ResolveSubNet("1.2.3.0/24") != ResolveSubNet("1.2.4.0/255.255.255.0"));
|
|
BOOST_CHECK(ResolveSubNet("1.2.3.0/24").Match(ResolveIP("1.2.3.4")));
|
|
BOOST_CHECK(!ResolveSubNet("1.2.2.0/24").Match(ResolveIP("1.2.3.4")));
|
|
BOOST_CHECK(ResolveSubNet("1.2.3.4").Match(ResolveIP("1.2.3.4")));
|
|
BOOST_CHECK(ResolveSubNet("1.2.3.4/32").Match(ResolveIP("1.2.3.4")));
|
|
BOOST_CHECK(!ResolveSubNet("1.2.3.4").Match(ResolveIP("5.6.7.8")));
|
|
BOOST_CHECK(!ResolveSubNet("1.2.3.4/32").Match(ResolveIP("5.6.7.8")));
|
|
BOOST_CHECK(ResolveSubNet("::ffff:127.0.0.1").Match(ResolveIP("127.0.0.1")));
|
|
BOOST_CHECK(ResolveSubNet("1:2:3:4:5:6:7:8").Match(ResolveIP("1:2:3:4:5:6:7:8")));
|
|
BOOST_CHECK(!ResolveSubNet("1:2:3:4:5:6:7:8").Match(ResolveIP("1:2:3:4:5:6:7:9")));
|
|
BOOST_CHECK(ResolveSubNet("1:2:3:4:5:6:7:0/112").Match(ResolveIP("1:2:3:4:5:6:7:1234")));
|
|
BOOST_CHECK(ResolveSubNet("192.168.0.1/24").Match(ResolveIP("192.168.0.2")));
|
|
BOOST_CHECK(ResolveSubNet("192.168.0.20/29").Match(ResolveIP("192.168.0.18")));
|
|
BOOST_CHECK(ResolveSubNet("1.2.2.1/24").Match(ResolveIP("1.2.2.4")));
|
|
BOOST_CHECK(ResolveSubNet("1.2.2.110/31").Match(ResolveIP("1.2.2.111")));
|
|
BOOST_CHECK(ResolveSubNet("1.2.2.20/26").Match(ResolveIP("1.2.2.63")));
|
|
// All-Matching IPv6 Matches arbitrary IPv6
|
|
BOOST_CHECK(ResolveSubNet("::/0").Match(ResolveIP("1:2:3:4:5:6:7:1234")));
|
|
// But not `::` or `0.0.0.0` because they are considered invalid addresses
|
|
BOOST_CHECK(!ResolveSubNet("::/0").Match(ResolveIP("::")));
|
|
BOOST_CHECK(!ResolveSubNet("::/0").Match(ResolveIP("0.0.0.0")));
|
|
// Addresses from one network (IPv4) don't belong to subnets of another network (IPv6)
|
|
BOOST_CHECK(!ResolveSubNet("::/0").Match(ResolveIP("1.2.3.4")));
|
|
// All-Matching IPv4 does not Match IPv6
|
|
BOOST_CHECK(!ResolveSubNet("0.0.0.0/0").Match(ResolveIP("1:2:3:4:5:6:7:1234")));
|
|
// Invalid subnets Match nothing (not even invalid addresses)
|
|
BOOST_CHECK(!CSubNet().Match(ResolveIP("1.2.3.4")));
|
|
BOOST_CHECK(!ResolveSubNet("").Match(ResolveIP("4.5.6.7")));
|
|
BOOST_CHECK(!ResolveSubNet("bloop").Match(ResolveIP("0.0.0.0")));
|
|
BOOST_CHECK(!ResolveSubNet("bloop").Match(ResolveIP("hab")));
|
|
// Check valid/invalid
|
|
BOOST_CHECK(ResolveSubNet("1.2.3.0/0").IsValid());
|
|
BOOST_CHECK(!ResolveSubNet("1.2.3.0/-1").IsValid());
|
|
BOOST_CHECK(ResolveSubNet("1.2.3.0/32").IsValid());
|
|
BOOST_CHECK(!ResolveSubNet("1.2.3.0/33").IsValid());
|
|
BOOST_CHECK(ResolveSubNet("1:2:3:4:5:6:7:8/0").IsValid());
|
|
BOOST_CHECK(ResolveSubNet("1:2:3:4:5:6:7:8/33").IsValid());
|
|
BOOST_CHECK(!ResolveSubNet("1:2:3:4:5:6:7:8/-1").IsValid());
|
|
BOOST_CHECK(ResolveSubNet("1:2:3:4:5:6:7:8/128").IsValid());
|
|
BOOST_CHECK(!ResolveSubNet("1:2:3:4:5:6:7:8/129").IsValid());
|
|
BOOST_CHECK(!ResolveSubNet("fuzzy").IsValid());
|
|
|
|
//CNetAddr constructor test
|
|
BOOST_CHECK(CSubNet(ResolveIP("127.0.0.1")).IsValid());
|
|
BOOST_CHECK(CSubNet(ResolveIP("127.0.0.1")).Match(ResolveIP("127.0.0.1")));
|
|
BOOST_CHECK(!CSubNet(ResolveIP("127.0.0.1")).Match(ResolveIP("127.0.0.2")));
|
|
BOOST_CHECK(CSubNet(ResolveIP("127.0.0.1")).ToString() == "127.0.0.1/32");
|
|
|
|
CSubNet subnet = CSubNet(ResolveIP("1.2.3.4"), 32);
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/32");
|
|
subnet = CSubNet(ResolveIP("1.2.3.4"), 8);
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/8");
|
|
subnet = CSubNet(ResolveIP("1.2.3.4"), 0);
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/0");
|
|
|
|
subnet = CSubNet(ResolveIP("1.2.3.4"), ResolveIP("255.255.255.255"));
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/32");
|
|
subnet = CSubNet(ResolveIP("1.2.3.4"), ResolveIP("255.0.0.0"));
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/8");
|
|
subnet = CSubNet(ResolveIP("1.2.3.4"), ResolveIP("0.0.0.0"));
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/0");
|
|
|
|
BOOST_CHECK(CSubNet(ResolveIP("1:2:3:4:5:6:7:8")).IsValid());
|
|
BOOST_CHECK(CSubNet(ResolveIP("1:2:3:4:5:6:7:8")).Match(ResolveIP("1:2:3:4:5:6:7:8")));
|
|
BOOST_CHECK(!CSubNet(ResolveIP("1:2:3:4:5:6:7:8")).Match(ResolveIP("1:2:3:4:5:6:7:9")));
|
|
BOOST_CHECK(CSubNet(ResolveIP("1:2:3:4:5:6:7:8")).ToString() == "1:2:3:4:5:6:7:8/128");
|
|
|
|
subnet = ResolveSubNet("1.2.3.4/255.255.255.255");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/32");
|
|
subnet = ResolveSubNet("1.2.3.4/255.255.255.254");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/31");
|
|
subnet = ResolveSubNet("1.2.3.4/255.255.255.252");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/30");
|
|
subnet = ResolveSubNet("1.2.3.4/255.255.255.248");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/29");
|
|
subnet = ResolveSubNet("1.2.3.4/255.255.255.240");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/28");
|
|
subnet = ResolveSubNet("1.2.3.4/255.255.255.224");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/27");
|
|
subnet = ResolveSubNet("1.2.3.4/255.255.255.192");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/26");
|
|
subnet = ResolveSubNet("1.2.3.4/255.255.255.128");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/25");
|
|
subnet = ResolveSubNet("1.2.3.4/255.255.255.0");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/24");
|
|
subnet = ResolveSubNet("1.2.3.4/255.255.254.0");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.2.0/23");
|
|
subnet = ResolveSubNet("1.2.3.4/255.255.252.0");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/22");
|
|
subnet = ResolveSubNet("1.2.3.4/255.255.248.0");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/21");
|
|
subnet = ResolveSubNet("1.2.3.4/255.255.240.0");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/20");
|
|
subnet = ResolveSubNet("1.2.3.4/255.255.224.0");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/19");
|
|
subnet = ResolveSubNet("1.2.3.4/255.255.192.0");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/18");
|
|
subnet = ResolveSubNet("1.2.3.4/255.255.128.0");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/17");
|
|
subnet = ResolveSubNet("1.2.3.4/255.255.0.0");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/16");
|
|
subnet = ResolveSubNet("1.2.3.4/255.254.0.0");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/15");
|
|
subnet = ResolveSubNet("1.2.3.4/255.252.0.0");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/14");
|
|
subnet = ResolveSubNet("1.2.3.4/255.248.0.0");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/13");
|
|
subnet = ResolveSubNet("1.2.3.4/255.240.0.0");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/12");
|
|
subnet = ResolveSubNet("1.2.3.4/255.224.0.0");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/11");
|
|
subnet = ResolveSubNet("1.2.3.4/255.192.0.0");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/10");
|
|
subnet = ResolveSubNet("1.2.3.4/255.128.0.0");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/9");
|
|
subnet = ResolveSubNet("1.2.3.4/255.0.0.0");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/8");
|
|
subnet = ResolveSubNet("1.2.3.4/254.0.0.0");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/7");
|
|
subnet = ResolveSubNet("1.2.3.4/252.0.0.0");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/6");
|
|
subnet = ResolveSubNet("1.2.3.4/248.0.0.0");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/5");
|
|
subnet = ResolveSubNet("1.2.3.4/240.0.0.0");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/4");
|
|
subnet = ResolveSubNet("1.2.3.4/224.0.0.0");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/3");
|
|
subnet = ResolveSubNet("1.2.3.4/192.0.0.0");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/2");
|
|
subnet = ResolveSubNet("1.2.3.4/128.0.0.0");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/1");
|
|
subnet = ResolveSubNet("1.2.3.4/0.0.0.0");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/0");
|
|
|
|
subnet = ResolveSubNet("1:2:3:4:5:6:7:8/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1:2:3:4:5:6:7:8/128");
|
|
subnet = ResolveSubNet("1:2:3:4:5:6:7:8/ffff:0000:0000:0000:0000:0000:0000:0000");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1::/16");
|
|
subnet = ResolveSubNet("1:2:3:4:5:6:7:8/0000:0000:0000:0000:0000:0000:0000:0000");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "::/0");
|
|
subnet = ResolveSubNet("1.2.3.4/255.255.232.0");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/255.255.232.0");
|
|
subnet = ResolveSubNet("1:2:3:4:5:6:7:8/ffff:ffff:ffff:fffe:ffff:ffff:ffff:ff0f");
|
|
BOOST_CHECK_EQUAL(subnet.ToString(), "1:2:3:4:5:6:7:8/ffff:ffff:ffff:fffe:ffff:ffff:ffff:ff0f");
|
|
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(netbase_getgroup)
|
|
{
|
|
std::vector<bool> asmap; // use /16
|
|
BOOST_CHECK(ResolveIP("127.0.0.1").GetGroup(asmap) == std::vector<unsigned char>({0})); // Local -> !Routable()
|
|
BOOST_CHECK(ResolveIP("257.0.0.1").GetGroup(asmap) == std::vector<unsigned char>({0})); // !Valid -> !Routable()
|
|
BOOST_CHECK(ResolveIP("10.0.0.1").GetGroup(asmap) == std::vector<unsigned char>({0})); // RFC1918 -> !Routable()
|
|
BOOST_CHECK(ResolveIP("169.254.1.1").GetGroup(asmap) == std::vector<unsigned char>({0})); // RFC3927 -> !Routable()
|
|
BOOST_CHECK(ResolveIP("1.2.3.4").GetGroup(asmap) == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // IPv4
|
|
BOOST_CHECK(ResolveIP("::FFFF:0:102:304").GetGroup(asmap) == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // RFC6145
|
|
BOOST_CHECK(ResolveIP("64:FF9B::102:304").GetGroup(asmap) == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // RFC6052
|
|
BOOST_CHECK(ResolveIP("2002:102:304:9999:9999:9999:9999:9999").GetGroup(asmap) == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // RFC3964
|
|
BOOST_CHECK(ResolveIP("2001:0:9999:9999:9999:9999:FEFD:FCFB").GetGroup(asmap) == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // RFC4380
|
|
BOOST_CHECK(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetGroup(asmap) == std::vector<unsigned char>({(unsigned char)NET_ONION, 239})); // Tor
|
|
BOOST_CHECK(ResolveIP("2001:470:abcd:9999:9999:9999:9999:9999").GetGroup(asmap) == std::vector<unsigned char>({(unsigned char)NET_IPV6, 32, 1, 4, 112, 175})); //he.net
|
|
BOOST_CHECK(ResolveIP("2001:2001:9999:9999:9999:9999:9999:9999").GetGroup(asmap) == std::vector<unsigned char>({(unsigned char)NET_IPV6, 32, 1, 32, 1})); //IPv6
|
|
|
|
// baz.net sha256 hash: 12929400eb4607c4ac075f087167e75286b179c693eb059a01774b864e8fe505
|
|
std::vector<unsigned char> internal_group = {NET_INTERNAL, 0x12, 0x92, 0x94, 0x00, 0xeb, 0x46, 0x07, 0xc4, 0xac, 0x07};
|
|
BOOST_CHECK(CreateInternal("baz.net").GetGroup(asmap) == internal_group);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(netbase_parsenetwork)
|
|
{
|
|
BOOST_CHECK_EQUAL(ParseNetwork("ipv4"), NET_IPV4);
|
|
BOOST_CHECK_EQUAL(ParseNetwork("ipv6"), NET_IPV6);
|
|
BOOST_CHECK_EQUAL(ParseNetwork("onion"), NET_ONION);
|
|
BOOST_CHECK_EQUAL(ParseNetwork("tor"), NET_ONION);
|
|
|
|
BOOST_CHECK_EQUAL(ParseNetwork("IPv4"), NET_IPV4);
|
|
BOOST_CHECK_EQUAL(ParseNetwork("IPv6"), NET_IPV6);
|
|
BOOST_CHECK_EQUAL(ParseNetwork("ONION"), NET_ONION);
|
|
BOOST_CHECK_EQUAL(ParseNetwork("TOR"), NET_ONION);
|
|
|
|
BOOST_CHECK_EQUAL(ParseNetwork(":)"), NET_UNROUTABLE);
|
|
BOOST_CHECK_EQUAL(ParseNetwork("tÖr"), NET_UNROUTABLE);
|
|
BOOST_CHECK_EQUAL(ParseNetwork("\xfe\xff"), NET_UNROUTABLE);
|
|
BOOST_CHECK_EQUAL(ParseNetwork(""), NET_UNROUTABLE);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(netpermissions_test)
|
|
{
|
|
bilingual_str error;
|
|
NetWhitebindPermissions whitebindPermissions;
|
|
NetWhitelistPermissions whitelistPermissions;
|
|
|
|
// Detect invalid white bind
|
|
BOOST_CHECK(!NetWhitebindPermissions::TryParse("", whitebindPermissions, error));
|
|
BOOST_CHECK(error.original.find("Cannot resolve -whitebind address") != std::string::npos);
|
|
BOOST_CHECK(!NetWhitebindPermissions::TryParse("127.0.0.1", whitebindPermissions, error));
|
|
BOOST_CHECK(error.original.find("Need to specify a port with -whitebind") != std::string::npos);
|
|
BOOST_CHECK(!NetWhitebindPermissions::TryParse("", whitebindPermissions, error));
|
|
|
|
// If no permission flags, assume backward compatibility
|
|
BOOST_CHECK(NetWhitebindPermissions::TryParse("1.2.3.4:32", whitebindPermissions, error));
|
|
BOOST_CHECK(error.empty());
|
|
BOOST_CHECK_EQUAL(whitebindPermissions.m_flags, PF_ISIMPLICIT);
|
|
BOOST_CHECK(NetPermissions::HasFlag(whitebindPermissions.m_flags, PF_ISIMPLICIT));
|
|
NetPermissions::ClearFlag(whitebindPermissions.m_flags, PF_ISIMPLICIT);
|
|
BOOST_CHECK(!NetPermissions::HasFlag(whitebindPermissions.m_flags, PF_ISIMPLICIT));
|
|
BOOST_CHECK_EQUAL(whitebindPermissions.m_flags, PF_NONE);
|
|
NetPermissions::AddFlag(whitebindPermissions.m_flags, PF_ISIMPLICIT);
|
|
BOOST_CHECK(NetPermissions::HasFlag(whitebindPermissions.m_flags, PF_ISIMPLICIT));
|
|
|
|
// Can set one permission
|
|
BOOST_CHECK(NetWhitebindPermissions::TryParse("bloom@1.2.3.4:32", whitebindPermissions, error));
|
|
BOOST_CHECK_EQUAL(whitebindPermissions.m_flags, PF_BLOOMFILTER);
|
|
BOOST_CHECK(NetWhitebindPermissions::TryParse("@1.2.3.4:32", whitebindPermissions, error));
|
|
BOOST_CHECK_EQUAL(whitebindPermissions.m_flags, PF_NONE);
|
|
|
|
// Happy path, can parse flags
|
|
BOOST_CHECK(NetWhitebindPermissions::TryParse("bloom,forcerelay@1.2.3.4:32", whitebindPermissions, error));
|
|
// forcerelay should also activate the relay permission
|
|
BOOST_CHECK_EQUAL(whitebindPermissions.m_flags, PF_BLOOMFILTER | PF_FORCERELAY | PF_RELAY);
|
|
BOOST_CHECK(NetWhitebindPermissions::TryParse("bloom,relay,noban@1.2.3.4:32", whitebindPermissions, error));
|
|
BOOST_CHECK_EQUAL(whitebindPermissions.m_flags, PF_BLOOMFILTER | PF_RELAY | PF_NOBAN);
|
|
BOOST_CHECK(NetWhitebindPermissions::TryParse("bloom,forcerelay,noban@1.2.3.4:32", whitebindPermissions, error));
|
|
BOOST_CHECK(NetWhitebindPermissions::TryParse("all@1.2.3.4:32", whitebindPermissions, error));
|
|
BOOST_CHECK_EQUAL(whitebindPermissions.m_flags, PF_ALL);
|
|
|
|
// Allow dups
|
|
BOOST_CHECK(NetWhitebindPermissions::TryParse("bloom,relay,noban,noban@1.2.3.4:32", whitebindPermissions, error));
|
|
BOOST_CHECK_EQUAL(whitebindPermissions.m_flags, PF_BLOOMFILTER | PF_RELAY | PF_NOBAN);
|
|
|
|
// Allow empty
|
|
BOOST_CHECK(NetWhitebindPermissions::TryParse("bloom,relay,,noban@1.2.3.4:32", whitebindPermissions, error));
|
|
BOOST_CHECK_EQUAL(whitebindPermissions.m_flags, PF_BLOOMFILTER | PF_RELAY | PF_NOBAN);
|
|
BOOST_CHECK(NetWhitebindPermissions::TryParse(",@1.2.3.4:32", whitebindPermissions, error));
|
|
BOOST_CHECK_EQUAL(whitebindPermissions.m_flags, PF_NONE);
|
|
BOOST_CHECK(NetWhitebindPermissions::TryParse(",,@1.2.3.4:32", whitebindPermissions, error));
|
|
BOOST_CHECK_EQUAL(whitebindPermissions.m_flags, PF_NONE);
|
|
|
|
// Detect invalid flag
|
|
BOOST_CHECK(!NetWhitebindPermissions::TryParse("bloom,forcerelay,oopsie@1.2.3.4:32", whitebindPermissions, error));
|
|
BOOST_CHECK(error.original.find("Invalid P2P permission") != std::string::npos);
|
|
|
|
// Check netmask error
|
|
BOOST_CHECK(!NetWhitelistPermissions::TryParse("bloom,forcerelay,noban@1.2.3.4:32", whitelistPermissions, error));
|
|
BOOST_CHECK(error.original.find("Invalid netmask specified in -whitelist") != std::string::npos);
|
|
|
|
// Happy path for whitelist parsing
|
|
BOOST_CHECK(NetWhitelistPermissions::TryParse("noban@1.2.3.4", whitelistPermissions, error));
|
|
BOOST_CHECK_EQUAL(whitelistPermissions.m_flags, PF_NOBAN);
|
|
BOOST_CHECK(NetWhitelistPermissions::TryParse("bloom,forcerelay,noban,relay@1.2.3.4/32", whitelistPermissions, error));
|
|
BOOST_CHECK_EQUAL(whitelistPermissions.m_flags, PF_BLOOMFILTER | PF_FORCERELAY | PF_NOBAN | PF_RELAY);
|
|
BOOST_CHECK(error.empty());
|
|
BOOST_CHECK_EQUAL(whitelistPermissions.m_subnet.ToString(), "1.2.3.4/32");
|
|
BOOST_CHECK(NetWhitelistPermissions::TryParse("bloom,forcerelay,noban,relay,mempool@1.2.3.4/32", whitelistPermissions, error));
|
|
|
|
const auto strings = NetPermissions::ToStrings(PF_ALL);
|
|
BOOST_CHECK_EQUAL(strings.size(), 7U);
|
|
BOOST_CHECK(std::find(strings.begin(), strings.end(), "bloomfilter") != strings.end());
|
|
BOOST_CHECK(std::find(strings.begin(), strings.end(), "forcerelay") != strings.end());
|
|
BOOST_CHECK(std::find(strings.begin(), strings.end(), "relay") != strings.end());
|
|
BOOST_CHECK(std::find(strings.begin(), strings.end(), "noban") != strings.end());
|
|
BOOST_CHECK(std::find(strings.begin(), strings.end(), "mempool") != strings.end());
|
|
BOOST_CHECK(std::find(strings.begin(), strings.end(), "download") != strings.end());
|
|
BOOST_CHECK(std::find(strings.begin(), strings.end(), "addr") != strings.end());
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(netbase_dont_resolve_strings_with_embedded_nul_characters)
|
|
{
|
|
CNetAddr addr;
|
|
BOOST_CHECK(LookupHost(std::string("127.0.0.1", 9), addr, false));
|
|
BOOST_CHECK(!LookupHost(std::string("127.0.0.1\0", 10), addr, false));
|
|
BOOST_CHECK(!LookupHost(std::string("127.0.0.1\0example.com", 21), addr, false));
|
|
BOOST_CHECK(!LookupHost(std::string("127.0.0.1\0example.com\0", 22), addr, false));
|
|
CSubNet ret;
|
|
BOOST_CHECK(LookupSubNet(std::string("1.2.3.0/24", 10), ret));
|
|
BOOST_CHECK(!LookupSubNet(std::string("1.2.3.0/24\0", 11), ret));
|
|
BOOST_CHECK(!LookupSubNet(std::string("1.2.3.0/24\0example.com", 22), ret));
|
|
BOOST_CHECK(!LookupSubNet(std::string("1.2.3.0/24\0example.com\0", 23), ret));
|
|
BOOST_CHECK(LookupSubNet(std::string("5wyqrzbvrdsumnok.onion", 22), ret));
|
|
BOOST_CHECK(!LookupSubNet(std::string("5wyqrzbvrdsumnok.onion\0", 23), ret));
|
|
BOOST_CHECK(!LookupSubNet(std::string("5wyqrzbvrdsumnok.onion\0example.com", 34), ret));
|
|
BOOST_CHECK(!LookupSubNet(std::string("5wyqrzbvrdsumnok.onion\0example.com\0", 35), ret));
|
|
}
|
|
|
|
BOOST_AUTO_TEST_SUITE_END()
|