aboutsummaryrefslogtreecommitdiff
path: root/src/netaddress.cpp
diff options
context:
space:
mode:
authorCory Fields <cory-nospam-@coryfields.com>2017-05-23 20:04:38 -0400
committerCory Fields <cory-nospam-@coryfields.com>2017-06-14 18:05:00 -0400
commit7f31762cb6261806542cc6d1188ca07db98a6950 (patch)
tree6ed637d6ebbb0a3d572b1dfa02bbd152fbae6c32 /src/netaddress.cpp
parentfbf5d3ba15161f71cbb84a51c1703c22b651e8a9 (diff)
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).
Diffstat (limited to 'src/netaddress.cpp')
-rw-r--r--src/netaddress.cpp48
1 files changed, 41 insertions, 7 deletions
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();