aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/net.cpp2
-rw-r--r--src/netaddress.cpp48
-rw-r--r--src/netaddress.h8
-rw-r--r--src/rpc/net.cpp2
-rw-r--r--src/test/netbase_tests.cpp13
5 files changed, 64 insertions, 9 deletions
diff --git a/src/net.cpp b/src/net.cpp
index 75d1719e86..e10016d983 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -240,7 +240,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 34a7029862..89f257c642 100644
--- a/src/netaddress.cpp
+++ b/src/netaddress.cpp
@@ -15,6 +15,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
@@ -199,6 +214,9 @@ bool CNetAddr::IsValid() const
if (IsRFC3849())
return false;
+ if (IsInternal())
+ return false;
+
if (IsIPv4())
{
// INADDR_NONE
@@ -217,11 +235,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;
@@ -238,6 +264,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);
@@ -305,9 +333,15 @@ std::vector<unsigned char> 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;
@@ -393,7 +427,7 @@ int CNetAddr::GetReachabilityFrom(const CNetAddr *paddrPartner) const
REACH_PRIVATE
};
- if (!IsRoutable())
+ if (!IsRoutable() || IsInternal())
return REACH_UNREACHABLE;
int ourNet = GetExtNetwork(this);
@@ -552,7 +586,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 fbc4d1a65f..80716600d1 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;
enum Network GetNetwork() const;
std::string ToString() const;
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index 10bf99eb38..ab4ecbcf17 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -397,7 +397,7 @@ static UniValue GetNetworksInfo()
for(int n=0; n<NET_MAX; ++n)
{
enum Network network = static_cast<enum Network>(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 e4b4b85720..94a3dac4ba 100644
--- a/src/test/netbase_tests.cpp
+++ b/src/test/netbase_tests.cpp
@@ -25,6 +25,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);
@@ -32,6 +39,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);
}
@@ -58,6 +66,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());
}
@@ -281,6 +291,9 @@ BOOST_AUTO_TEST_CASE(netbase_getgroup)
BOOST_CHECK(ResolveIP("2001:470:abcd:9999:9999:9999:9999:9999").GetGroup() == 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() == 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() == internal_group);
}
BOOST_AUTO_TEST_SUITE_END()