aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/netbase.cpp91
-rw-r--r--src/netbase.h7
-rw-r--r--src/test/base32_tests.cpp2
-rw-r--r--src/test/netbase_tests.cpp13
-rw-r--r--src/util.cpp2
5 files changed, 94 insertions, 21 deletions
diff --git a/src/netbase.cpp b/src/netbase.cpp
index ffd3ea68a5..21fca4737a 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -57,6 +57,15 @@ void SplitHostPort(std::string in, int &portOut, std::string &hostOut) {
bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
{
vIP.clear();
+
+ {
+ CNetAddr addr;
+ if (addr.SetSpecial(std::string(pszName))) {
+ vIP.push_back(addr);
+ return true;
+ }
+ }
+
struct addrinfo aiHint;
memset(&aiHint, 0, sizeof(struct addrinfo));
@@ -530,6 +539,32 @@ void CNetAddr::SetIP(const CNetAddr& ipIn)
memcpy(ip, ipIn.ip, sizeof(ip));
}
+static const unsigned char pchOnionCat[] = {0xFD,0x87,0xD8,0x7E,0xEB,0x43};
+static const unsigned char pchGarliCat[] = {0xFD,0x60,0xDB,0x4D,0xDD,0xB5};
+
+bool CNetAddr::SetSpecial(const std::string &strName)
+{
+ if (strName.size()>6 && strName.substr(strName.size() - 6, 6) == ".onion") {
+ std::vector<unsigned char> vchAddr = DecodeBase32(strName.substr(0, strName.size() - 6).c_str());
+ if (vchAddr.size() != 16-sizeof(pchOnionCat))
+ return false;
+ memcpy(ip, pchOnionCat, sizeof(pchOnionCat));
+ for (unsigned int i=0; i<16-sizeof(pchOnionCat); i++)
+ ip[i + sizeof(pchOnionCat)] = vchAddr[i];
+ return true;
+ }
+ if (strName.size()>11 && strName.substr(strName.size() - 11, 11) == ".oc.b32.i2p") {
+ std::vector<unsigned char> vchAddr = DecodeBase32(strName.substr(0, strName.size() - 11).c_str());
+ if (vchAddr.size() != 16-sizeof(pchGarliCat))
+ return false;
+ memcpy(ip, pchOnionCat, sizeof(pchGarliCat));
+ for (unsigned int i=0; i<16-sizeof(pchGarliCat); i++)
+ ip[i + sizeof(pchGarliCat)] = vchAddr[i];
+ return true;
+ }
+ return false;
+}
+
CNetAddr::CNetAddr()
{
Init();
@@ -576,7 +611,7 @@ bool CNetAddr::IsIPv4() const
bool CNetAddr::IsIPv6() const
{
- return (!IsIPv4());
+ return (!IsIPv4() && !IsTor() && !IsI2P());
}
bool CNetAddr::IsRFC1918() const
@@ -635,15 +670,13 @@ bool CNetAddr::IsRFC4843() const
return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x00 && (GetByte(12) & 0xF0) == 0x10);
}
-bool CNetAddr::IsOnionCat() const
+bool CNetAddr::IsTor() const
{
- static const unsigned char pchOnionCat[] = {0xFD,0x87,0xD8,0x7E,0xEB,0x43};
return (memcmp(ip, pchOnionCat, sizeof(pchOnionCat)) == 0);
}
-bool CNetAddr::IsGarliCat() const
+bool CNetAddr::IsI2P() const
{
- static const unsigned char pchGarliCat[] = {0xFD,0x60,0xDB,0x4D,0xDD,0xB5};
return (memcmp(ip, pchGarliCat, sizeof(pchGarliCat)) == 0);
}
@@ -705,7 +738,7 @@ bool CNetAddr::IsValid() const
bool CNetAddr::IsRoutable() const
{
- return IsValid() && !(IsRFC1918() || IsRFC3927() || IsRFC4862() || (IsRFC4193() && !IsOnionCat() && !IsGarliCat()) || IsRFC4843() || IsLocal());
+ return IsValid() && !(IsRFC1918() || IsRFC3927() || IsRFC4862() || (IsRFC4193() && !IsTor() && !IsI2P()) || IsRFC4843() || IsLocal());
}
enum Network CNetAddr::GetNetwork() const
@@ -716,10 +749,10 @@ enum Network CNetAddr::GetNetwork() const
if (IsIPv4())
return NET_IPV4;
- if (IsOnionCat())
+ if (IsTor())
return NET_TOR;
- if (IsGarliCat())
+ if (IsI2P())
return NET_I2P;
return NET_IPV6;
@@ -727,6 +760,10 @@ enum Network CNetAddr::GetNetwork() const
std::string CNetAddr::ToStringIP() const
{
+ if (IsTor())
+ return EncodeBase32(&ip[6], 10) + ".onion";
+ if (IsI2P())
+ return EncodeBase32(&ip[6], 10) + ".oc.b32.i2p";
CService serv(*this, 0);
#ifdef USE_IPV6
struct sockaddr_storage sockaddr;
@@ -739,7 +776,7 @@ std::string CNetAddr::ToStringIP() const
if (!getnameinfo((const struct sockaddr*)&sockaddr, socklen, name, sizeof(name), NULL, 0, NI_NUMERICHOST))
return std::string(name);
}
- if (IsIPv4())
+ if (IsIPv4())
return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0));
else
return strprintf("%x:%x:%x:%x:%x:%x:%x:%x",
@@ -828,6 +865,18 @@ std::vector<unsigned char> CNetAddr::GetGroup() const
vchRet.push_back(GetByte(2) ^ 0xFF);
return vchRet;
}
+ else if (IsTor())
+ {
+ nClass = NET_TOR;
+ nStartByte = 6;
+ nBits = 4;
+ }
+ else if (IsI2P())
+ {
+ nClass = NET_I2P;
+ nStartByte = 6;
+ nBits = 4;
+ }
// for he.net, use /36 groups
else if (GetByte(15) == 0x20 && GetByte(14) == 0x11 && GetByte(13) == 0x04 && GetByte(12) == 0x70)
nBits = 36;
@@ -861,11 +910,11 @@ void CNetAddr::print() const
printf("CNetAddr(%s)\n", ToString().c_str());
}
-// for IPv6 partners: for unknown/Teredo partners: for IPv4 partners:
-// 0 - unroutable // 0 - unroutable // 0 - unroutable
-// 1 - teredo // 1 - teredo // 1 - ipv4
-// 2 - tunneled ipv6 // 2 - tunneled ipv6
-// 3 - ipv4 // 3 - ipv6
+// for IPv6 partners: for unknown/Teredo partners: for IPv4 partners: for Tor partners: for I2P partners:
+// 0 - unroutable // 0 - unroutable // 0 - unroutable // 0 - unroutable // 0 - unroutable
+// 1 - teredo // 1 - teredo // 1 - ipv4 // 1 - the rest // 1 - the rest
+// 2 - tunneled ipv6 // 2 - tunneled ipv6 // 2 - ip4 // 2 - I2P
+// 3 - ipv4 // 3 - ipv6 // 3 - tor
// 4 - ipv6 // 4 - ipv4
int CNetAddr::GetReachabilityFrom(const CNetAddr *paddrPartner) const
{
@@ -873,6 +922,18 @@ int CNetAddr::GetReachabilityFrom(const CNetAddr *paddrPartner) const
return 0;
if (paddrPartner && paddrPartner->IsIPv4())
return IsIPv4() ? 1 : 0;
+ if (paddrPartner && paddrPartner->IsTor()) {
+ if (IsIPv4())
+ return 2;
+ if (IsTor())
+ return 3;
+ return 1;
+ }
+ if (paddrPartner && paddrPartner->IsI2P()) {
+ if (IsI2P())
+ return 2;
+ return 1;
+ }
if (IsRFC4380())
return 1;
if (IsRFC3964() || IsRFC6052())
@@ -1036,7 +1097,7 @@ std::string CService::ToStringPort() const
std::string CService::ToStringIPPort() const
{
- if (IsIPv4()) {
+ if (IsIPv4() || IsTor() || IsI2P()) {
return ToStringIP() + ":" + ToStringPort();
} else {
return "[" + ToStringIP() + "]:" + ToStringPort();
diff --git a/src/netbase.h b/src/netbase.h
index 7a797e2fd6..36f29b0b32 100644
--- a/src/netbase.h
+++ b/src/netbase.h
@@ -44,8 +44,9 @@ class CNetAddr
explicit CNetAddr(const std::string &strIp, bool fAllowLookup = false);
void Init();
void SetIP(const CNetAddr& ip);
+ bool SetSpecial(const std::string &strName); // for Tor and I2P addresses
bool IsIPv4() const; // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0)
- bool IsIPv6() const; // IPv6 address (not IPv4)
+ bool IsIPv6() const; // IPv6 address (not mapped IPv4, not Tor/I2P)
bool IsRFC1918() const; // IPv4 private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12)
bool IsRFC3849() const; // IPv6 documentation address (2001:0DB8::/32)
bool IsRFC3927() const; // IPv4 autoconfig (169.254.0.0/16)
@@ -56,8 +57,8 @@ class CNetAddr
bool IsRFC4862() const; // IPv6 autoconfig (FE80::/64)
bool IsRFC6052() const; // IPv6 well-known prefix (64:FF9B::/96)
bool IsRFC6145() const; // IPv6 IPv4-translated address (::FFFF:0:0:0/96)
- bool IsOnionCat() const;
- bool IsGarliCat() const;
+ bool IsTor() const;
+ bool IsI2P() const;
bool IsLocal() const;
bool IsRoutable() const;
bool IsValid() const;
diff --git a/src/test/base32_tests.cpp b/src/test/base32_tests.cpp
index 756c72b94d..fdf3285913 100644
--- a/src/test/base32_tests.cpp
+++ b/src/test/base32_tests.cpp
@@ -7,7 +7,7 @@ BOOST_AUTO_TEST_SUITE(base32_tests)
BOOST_AUTO_TEST_CASE(base32_testvectors)
{
static const std::string vstrIn[] = {"","f","fo","foo","foob","fooba","foobar"};
- static const std::string vstrOut[] = {"","MY======","MZXQ====","MZXW6===","MZXW6YQ=","MZXW6YTB","MZXW6YTBOI======"};
+ static const std::string vstrOut[] = {"","my======","mzxq====","mzxw6===","mzxw6yq=","mzxw6ytb","mzxw6ytboi======"};
for (unsigned int i=0; i<sizeof(vstrIn)/sizeof(vstrIn[0]); i++)
{
std::string strEnc = EncodeBase32(vstrIn[i]);
diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp
index f0828f39fc..e5a7562d97 100644
--- a/src/test/netbase_tests.cpp
+++ b/src/test/netbase_tests.cpp
@@ -34,7 +34,7 @@ BOOST_AUTO_TEST_CASE(netbase_properties)
BOOST_CHECK(CNetAddr("2001:10::").IsRFC4843());
BOOST_CHECK(CNetAddr("FE80::").IsRFC4862());
BOOST_CHECK(CNetAddr("64:FF9B::").IsRFC6052());
- BOOST_CHECK(CNetAddr("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").IsOnionCat());
+ BOOST_CHECK(CNetAddr("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").IsTor());
BOOST_CHECK(CNetAddr("127.0.0.1").IsLocal());
BOOST_CHECK(CNetAddr("::1").IsLocal());
BOOST_CHECK(CNetAddr("8.8.8.8").IsRoutable());
@@ -88,4 +88,15 @@ BOOST_AUTO_TEST_CASE(netbase_lookupnumeric)
BOOST_CHECK(TestParse(":::", ""));
}
+BOOST_AUTO_TEST_CASE(onioncat_test)
+{
+ // values from http://www.cypherpunk.at/onioncat/wiki/OnionCat
+ CNetAddr addr1("5wyqrzbvrdsumnok.onion");
+ CNetAddr addr2("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_SUITE_END()
diff --git a/src/util.cpp b/src/util.cpp
index 931d27ba00..5fff27160f 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -704,7 +704,7 @@ string DecodeBase64(const string& str)
string EncodeBase32(const unsigned char* pch, size_t len)
{
- static const char *pbase32 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
+ static const char *pbase32 = "abcdefghijklmnopqrstuvwxyz234567";
string strRet="";
strRet.reserve((len+4)/5*8);