mirror of
https://github.com/kvazar-network/kevacoin.git
synced 2025-01-17 10:30:04 +00:00
Merge #8128: Net: Turn net structures into dumb storage classes
9e9d644 net: fixup nits (Cory Fields) 8945384 net: Have LookupNumeric return a CService directly (Cory Fields) 21ba407 net: narrow include scope after moving to netaddress (Cory Fields) 21e5b96 net: move CNetAddr/CService/CSubNet out of netbase (Cory Fields) 1017b8a net: Add direct tests for new CSubNet constructors (Cory Fields) b6c3ff3 net: Split resolving out of CSubNet (Cory Fields) f96c7c4 net: Split resolving out of CService (Cory Fields) 31d6b1d net: Split resolving out of CNetAddr (Cory Fields)
This commit is contained in:
commit
1030fa718c
@ -105,6 +105,7 @@ BITCOIN_CORE_H = \
|
||||
merkleblock.h \
|
||||
miner.h \
|
||||
net.h \
|
||||
netaddress.h \
|
||||
netbase.h \
|
||||
noui.h \
|
||||
policy/fees.h \
|
||||
@ -289,6 +290,7 @@ libbitcoin_common_a_SOURCES = \
|
||||
core_write.cpp \
|
||||
key.cpp \
|
||||
keystore.cpp \
|
||||
netaddress.cpp \
|
||||
netbase.cpp \
|
||||
protocol.cpp \
|
||||
scheduler.cpp \
|
||||
|
@ -6,7 +6,7 @@
|
||||
#ifndef BITCOIN_ADDRMAN_H
|
||||
#define BITCOIN_ADDRMAN_H
|
||||
|
||||
#include "netbase.h"
|
||||
#include "netaddress.h"
|
||||
#include "protocol.h"
|
||||
#include "random.h"
|
||||
#include "sync.h"
|
||||
|
@ -197,12 +197,17 @@ static bool ClientAllowed(const CNetAddr& netaddr)
|
||||
static bool InitHTTPAllowList()
|
||||
{
|
||||
rpc_allow_subnets.clear();
|
||||
rpc_allow_subnets.push_back(CSubNet("127.0.0.0/8")); // always allow IPv4 local subnet
|
||||
rpc_allow_subnets.push_back(CSubNet("::1")); // always allow IPv6 localhost
|
||||
CNetAddr localv4;
|
||||
CNetAddr localv6;
|
||||
LookupHost("127.0.0.1", localv4, false);
|
||||
LookupHost("::1", localv6, false);
|
||||
rpc_allow_subnets.push_back(CSubNet(localv4, 8)); // always allow IPv4 local subnet
|
||||
rpc_allow_subnets.push_back(CSubNet(localv6)); // always allow IPv6 localhost
|
||||
if (mapMultiArgs.count("-rpcallowip")) {
|
||||
const std::vector<std::string>& vAllow = mapMultiArgs["-rpcallowip"];
|
||||
for (std::string strAllow : vAllow) {
|
||||
CSubNet subnet(strAllow);
|
||||
CSubNet subnet;
|
||||
LookupSubNet(strAllow.c_str(), subnet);
|
||||
if (!subnet.IsValid()) {
|
||||
uiInterface.ThreadSafeMessageBox(
|
||||
strprintf("Invalid -rpcallowip subnet specification: %s. Valid are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24).", strAllow),
|
||||
@ -614,7 +619,7 @@ CService HTTPRequest::GetPeer()
|
||||
const char* address = "";
|
||||
uint16_t port = 0;
|
||||
evhttp_connection_get_peer(con, (char**)&address, &port);
|
||||
peer = CService(address, port);
|
||||
peer = LookupNumeric(address, port);
|
||||
}
|
||||
return peer;
|
||||
}
|
||||
|
10
src/init.cpp
10
src/init.cpp
@ -21,6 +21,7 @@
|
||||
#include "key.h"
|
||||
#include "main.h"
|
||||
#include "miner.h"
|
||||
#include "netbase.h"
|
||||
#include "net.h"
|
||||
#include "policy/policy.h"
|
||||
#include "rpc/server.h"
|
||||
@ -1134,7 +1135,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||
|
||||
if (mapArgs.count("-whitelist")) {
|
||||
BOOST_FOREACH(const std::string& net, mapMultiArgs["-whitelist"]) {
|
||||
CSubNet subnet(net);
|
||||
CSubNet subnet;
|
||||
LookupSubNet(net.c_str(), subnet);
|
||||
if (!subnet.IsValid())
|
||||
return InitError(strprintf(_("Invalid netmask specified in -whitelist: '%s'"), net));
|
||||
CNode::AddWhitelistedRange(subnet);
|
||||
@ -1147,7 +1149,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||
std::string proxyArg = GetArg("-proxy", "");
|
||||
SetLimited(NET_TOR);
|
||||
if (proxyArg != "" && proxyArg != "0") {
|
||||
proxyType addrProxy = proxyType(CService(proxyArg, 9050), proxyRandomize);
|
||||
CService resolved(LookupNumeric(proxyArg.c_str(), 9050));
|
||||
proxyType addrProxy = proxyType(resolved, proxyRandomize);
|
||||
if (!addrProxy.IsValid())
|
||||
return InitError(strprintf(_("Invalid -proxy address: '%s'"), proxyArg));
|
||||
|
||||
@ -1166,7 +1169,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||
if (onionArg == "0") { // Handle -noonion/-onion=0
|
||||
SetLimited(NET_TOR); // set onions as unreachable
|
||||
} else {
|
||||
proxyType addrOnion = proxyType(CService(onionArg, 9050), proxyRandomize);
|
||||
CService resolved(LookupNumeric(onionArg.c_str(), 9050));
|
||||
proxyType addrOnion = proxyType(resolved, proxyRandomize);
|
||||
if (!addrOnion.IsValid())
|
||||
return InitError(strprintf(_("Invalid -onion address: '%s'"), onionArg));
|
||||
SetProxy(NET_TOR, addrOnion);
|
||||
|
27
src/net.cpp
27
src/net.cpp
@ -17,6 +17,7 @@
|
||||
#include "crypto/sha256.h"
|
||||
#include "hash.h"
|
||||
#include "primitives/transaction.h"
|
||||
#include "netbase.h"
|
||||
#include "scheduler.h"
|
||||
#include "ui_interface.h"
|
||||
#include "utilstrencodings.h"
|
||||
@ -175,7 +176,7 @@ static std::vector<CAddress> convertSeed6(const std::vector<SeedSpec6> &vSeedsIn
|
||||
// one by discovery.
|
||||
CAddress GetLocalAddress(const CNetAddr *paddrPeer)
|
||||
{
|
||||
CAddress ret(CService("0.0.0.0",GetListenPort()), NODE_NONE);
|
||||
CAddress ret(CService(CNetAddr(),GetListenPort()), NODE_NONE);
|
||||
CService addr;
|
||||
if (GetLocal(addr, paddrPeer))
|
||||
{
|
||||
@ -494,7 +495,7 @@ void CNode::PushVersion()
|
||||
int nBestHeight = GetNodeSignals().GetHeight().get_value_or(0);
|
||||
|
||||
int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime());
|
||||
CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0", 0), addr.nServices));
|
||||
CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService(), addr.nServices));
|
||||
CAddress addrMe = GetLocalAddress(&addr);
|
||||
GetRandBytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
|
||||
if (fLogIPs)
|
||||
@ -1396,8 +1397,11 @@ void ThreadMapPort()
|
||||
{
|
||||
if(externalIPAddress[0])
|
||||
{
|
||||
LogPrintf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
|
||||
AddLocal(CNetAddr(externalIPAddress), LOCAL_UPNP);
|
||||
CNetAddr resolved;
|
||||
if(LookupHost(externalIPAddress, resolved, false)) {
|
||||
LogPrintf("UPnP: ExternalIPAddress = %s\n", resolved.ToString().c_str());
|
||||
AddLocal(resolved, LOCAL_UPNP);
|
||||
}
|
||||
}
|
||||
else
|
||||
LogPrintf("UPnP: GetExternalIPAddress failed.\n");
|
||||
@ -1623,7 +1627,9 @@ void ThreadOpenConnections()
|
||||
static bool done = false;
|
||||
if (!done) {
|
||||
LogPrintf("Adding fixed seed nodes as DNS doesn't seem to be available.\n");
|
||||
addrman.Add(convertSeed6(Params().FixedSeeds()), CNetAddr("127.0.0.1"));
|
||||
CNetAddr local;
|
||||
LookupHost("127.0.0.1", local, false);
|
||||
addrman.Add(convertSeed6(Params().FixedSeeds()), local);
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
@ -1722,7 +1728,7 @@ std::vector<AddedNodeInfo> GetAddedNodeInfo()
|
||||
}
|
||||
|
||||
BOOST_FOREACH(const std::string& strAddNode, lAddresses) {
|
||||
CService service(strAddNode, Params().GetDefaultPort());
|
||||
CService service(LookupNumeric(strAddNode.c_str(), Params().GetDefaultPort()));
|
||||
if (service.IsValid()) {
|
||||
// strAddNode is an IP:port
|
||||
auto it = mapConnected.find(service);
|
||||
@ -1760,7 +1766,7 @@ void ThreadOpenAddedConnections()
|
||||
CSemaphoreGrant grant(*semOutbound);
|
||||
// If strAddedNode is an IP/port, decode it immediately, so
|
||||
// OpenNetworkConnection can detect existing connections to that IP/port.
|
||||
CService service(info.strAddedNode, Params().GetDefaultPort());
|
||||
CService service(LookupNumeric(info.strAddedNode.c_str(), Params().GetDefaultPort()));
|
||||
OpenNetworkConnection(CAddress(service, NODE_NONE), false, &grant, info.strAddedNode.c_str(), false);
|
||||
MilliSleep(500);
|
||||
}
|
||||
@ -2060,8 +2066,11 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||
semOutbound = new CSemaphore(nMaxOutbound);
|
||||
}
|
||||
|
||||
if (pnodeLocalHost == NULL)
|
||||
pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices));
|
||||
if (pnodeLocalHost == NULL) {
|
||||
CNetAddr local;
|
||||
LookupHost("127.0.0.1", local, false);
|
||||
pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService(local, 0), nLocalServices));
|
||||
}
|
||||
|
||||
Discover(threadGroup);
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include "bloom.h"
|
||||
#include "compat.h"
|
||||
#include "limitedmap.h"
|
||||
#include "netbase.h"
|
||||
#include "netaddress.h"
|
||||
#include "protocol.h"
|
||||
#include "random.h"
|
||||
#include "streams.h"
|
||||
|
716
src/netaddress.cpp
Normal file
716
src/netaddress.cpp
Normal file
@ -0,0 +1,716 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2015 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config/bitcoin-config.h"
|
||||
#endif
|
||||
|
||||
#include "netaddress.h"
|
||||
#include "hash.h"
|
||||
#include "utilstrencodings.h"
|
||||
#include "tinyformat.h"
|
||||
|
||||
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};
|
||||
|
||||
void CNetAddr::Init()
|
||||
{
|
||||
memset(ip, 0, sizeof(ip));
|
||||
scopeId = 0;
|
||||
}
|
||||
|
||||
void CNetAddr::SetIP(const CNetAddr& ipIn)
|
||||
{
|
||||
memcpy(ip, ipIn.ip, sizeof(ip));
|
||||
}
|
||||
|
||||
void CNetAddr::SetRaw(Network network, const uint8_t *ip_in)
|
||||
{
|
||||
switch(network)
|
||||
{
|
||||
case NET_IPV4:
|
||||
memcpy(ip, pchIPv4, 12);
|
||||
memcpy(ip+12, ip_in, 4);
|
||||
break;
|
||||
case NET_IPV6:
|
||||
memcpy(ip, ip_in, 16);
|
||||
break;
|
||||
default:
|
||||
assert(!"invalid network");
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CNetAddr::CNetAddr()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
CNetAddr::CNetAddr(const struct in_addr& ipv4Addr)
|
||||
{
|
||||
SetRaw(NET_IPV4, (const uint8_t*)&ipv4Addr);
|
||||
}
|
||||
|
||||
CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr, const uint32_t scope)
|
||||
{
|
||||
SetRaw(NET_IPV6, (const uint8_t*)&ipv6Addr);
|
||||
scopeId = scope;
|
||||
}
|
||||
|
||||
unsigned int CNetAddr::GetByte(int n) const
|
||||
{
|
||||
return ip[15-n];
|
||||
}
|
||||
|
||||
bool CNetAddr::IsIPv4() const
|
||||
{
|
||||
return (memcmp(ip, pchIPv4, sizeof(pchIPv4)) == 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsIPv6() const
|
||||
{
|
||||
return (!IsIPv4() && !IsTor());
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC1918() const
|
||||
{
|
||||
return IsIPv4() && (
|
||||
GetByte(3) == 10 ||
|
||||
(GetByte(3) == 192 && GetByte(2) == 168) ||
|
||||
(GetByte(3) == 172 && (GetByte(2) >= 16 && GetByte(2) <= 31)));
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC2544() const
|
||||
{
|
||||
return IsIPv4() && GetByte(3) == 198 && (GetByte(2) == 18 || GetByte(2) == 19);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC3927() const
|
||||
{
|
||||
return IsIPv4() && (GetByte(3) == 169 && GetByte(2) == 254);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC6598() const
|
||||
{
|
||||
return IsIPv4() && GetByte(3) == 100 && GetByte(2) >= 64 && GetByte(2) <= 127;
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC5737() const
|
||||
{
|
||||
return IsIPv4() && ((GetByte(3) == 192 && GetByte(2) == 0 && GetByte(1) == 2) ||
|
||||
(GetByte(3) == 198 && GetByte(2) == 51 && GetByte(1) == 100) ||
|
||||
(GetByte(3) == 203 && GetByte(2) == 0 && GetByte(1) == 113));
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC3849() const
|
||||
{
|
||||
return GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x0D && GetByte(12) == 0xB8;
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC3964() const
|
||||
{
|
||||
return (GetByte(15) == 0x20 && GetByte(14) == 0x02);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC6052() const
|
||||
{
|
||||
static const unsigned char pchRFC6052[] = {0,0x64,0xFF,0x9B,0,0,0,0,0,0,0,0};
|
||||
return (memcmp(ip, pchRFC6052, sizeof(pchRFC6052)) == 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC4380() const
|
||||
{
|
||||
return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0 && GetByte(12) == 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC4862() const
|
||||
{
|
||||
static const unsigned char pchRFC4862[] = {0xFE,0x80,0,0,0,0,0,0};
|
||||
return (memcmp(ip, pchRFC4862, sizeof(pchRFC4862)) == 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC4193() const
|
||||
{
|
||||
return ((GetByte(15) & 0xFE) == 0xFC);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC6145() const
|
||||
{
|
||||
static const unsigned char pchRFC6145[] = {0,0,0,0,0,0,0,0,0xFF,0xFF,0,0};
|
||||
return (memcmp(ip, pchRFC6145, sizeof(pchRFC6145)) == 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC4843() const
|
||||
{
|
||||
return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x00 && (GetByte(12) & 0xF0) == 0x10);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsTor() const
|
||||
{
|
||||
return (memcmp(ip, pchOnionCat, sizeof(pchOnionCat)) == 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsLocal() const
|
||||
{
|
||||
// IPv4 loopback
|
||||
if (IsIPv4() && (GetByte(3) == 127 || GetByte(3) == 0))
|
||||
return true;
|
||||
|
||||
// IPv6 loopback (::1/128)
|
||||
static const unsigned char pchLocal[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
|
||||
if (memcmp(ip, pchLocal, 16) == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CNetAddr::IsMulticast() const
|
||||
{
|
||||
return (IsIPv4() && (GetByte(3) & 0xF0) == 0xE0)
|
||||
|| (GetByte(15) == 0xFF);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsValid() const
|
||||
{
|
||||
// Cleanup 3-byte shifted addresses caused by garbage in size field
|
||||
// of addr messages from versions before 0.2.9 checksum.
|
||||
// Two consecutive addr messages look like this:
|
||||
// header20 vectorlen3 addr26 addr26 addr26 header20 vectorlen3 addr26 addr26 addr26...
|
||||
// so if the first length field is garbled, it reads the second batch
|
||||
// of addr misaligned by 3 bytes.
|
||||
if (memcmp(ip, pchIPv4+3, sizeof(pchIPv4)-3) == 0)
|
||||
return false;
|
||||
|
||||
// unspecified IPv6 address (::/128)
|
||||
unsigned char ipNone[16] = {};
|
||||
if (memcmp(ip, ipNone, 16) == 0)
|
||||
return false;
|
||||
|
||||
// documentation IPv6 address
|
||||
if (IsRFC3849())
|
||||
return false;
|
||||
|
||||
if (IsIPv4())
|
||||
{
|
||||
// INADDR_NONE
|
||||
uint32_t ipNone = INADDR_NONE;
|
||||
if (memcmp(ip+12, &ipNone, 4) == 0)
|
||||
return false;
|
||||
|
||||
// 0
|
||||
ipNone = 0;
|
||||
if (memcmp(ip+12, &ipNone, 4) == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRoutable() const
|
||||
{
|
||||
return IsValid() && !(IsRFC1918() || IsRFC2544() || IsRFC3927() || IsRFC4862() || IsRFC6598() || IsRFC5737() || (IsRFC4193() && !IsTor()) || IsRFC4843() || IsLocal());
|
||||
}
|
||||
|
||||
enum Network CNetAddr::GetNetwork() const
|
||||
{
|
||||
if (!IsRoutable())
|
||||
return NET_UNROUTABLE;
|
||||
|
||||
if (IsIPv4())
|
||||
return NET_IPV4;
|
||||
|
||||
if (IsTor())
|
||||
return NET_TOR;
|
||||
|
||||
return NET_IPV6;
|
||||
}
|
||||
|
||||
std::string CNetAddr::ToStringIP() const
|
||||
{
|
||||
if (IsTor())
|
||||
return EncodeBase32(&ip[6], 10) + ".onion";
|
||||
CService serv(*this, 0);
|
||||
struct sockaddr_storage sockaddr;
|
||||
socklen_t socklen = sizeof(sockaddr);
|
||||
if (serv.GetSockAddr((struct sockaddr*)&sockaddr, &socklen)) {
|
||||
char name[1025] = "";
|
||||
if (!getnameinfo((const struct sockaddr*)&sockaddr, socklen, name, sizeof(name), NULL, 0, NI_NUMERICHOST))
|
||||
return std::string(name);
|
||||
}
|
||||
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",
|
||||
GetByte(15) << 8 | GetByte(14), GetByte(13) << 8 | GetByte(12),
|
||||
GetByte(11) << 8 | GetByte(10), GetByte(9) << 8 | GetByte(8),
|
||||
GetByte(7) << 8 | GetByte(6), GetByte(5) << 8 | GetByte(4),
|
||||
GetByte(3) << 8 | GetByte(2), GetByte(1) << 8 | GetByte(0));
|
||||
}
|
||||
|
||||
std::string CNetAddr::ToString() const
|
||||
{
|
||||
return ToStringIP();
|
||||
}
|
||||
|
||||
bool operator==(const CNetAddr& a, const CNetAddr& b)
|
||||
{
|
||||
return (memcmp(a.ip, b.ip, 16) == 0);
|
||||
}
|
||||
|
||||
bool operator!=(const CNetAddr& a, const CNetAddr& b)
|
||||
{
|
||||
return (memcmp(a.ip, b.ip, 16) != 0);
|
||||
}
|
||||
|
||||
bool operator<(const CNetAddr& a, const CNetAddr& b)
|
||||
{
|
||||
return (memcmp(a.ip, b.ip, 16) < 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const
|
||||
{
|
||||
if (!IsIPv4())
|
||||
return false;
|
||||
memcpy(pipv4Addr, ip+12, 4);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const
|
||||
{
|
||||
memcpy(pipv6Addr, ip, 16);
|
||||
return true;
|
||||
}
|
||||
|
||||
// get canonical identifier of an address' group
|
||||
// no two connections will be attempted to addresses with the same group
|
||||
std::vector<unsigned char> CNetAddr::GetGroup() const
|
||||
{
|
||||
std::vector<unsigned char> vchRet;
|
||||
int nClass = NET_IPV6;
|
||||
int nStartByte = 0;
|
||||
int nBits = 16;
|
||||
|
||||
// all local addresses belong to the same group
|
||||
if (IsLocal())
|
||||
{
|
||||
nClass = 255;
|
||||
nBits = 0;
|
||||
}
|
||||
|
||||
// all unroutable addresses belong to the same group
|
||||
if (!IsRoutable())
|
||||
{
|
||||
nClass = NET_UNROUTABLE;
|
||||
nBits = 0;
|
||||
}
|
||||
// for IPv4 addresses, '1' + the 16 higher-order bits of the IP
|
||||
// includes mapped IPv4, SIIT translated IPv4, and the well-known prefix
|
||||
else if (IsIPv4() || IsRFC6145() || IsRFC6052())
|
||||
{
|
||||
nClass = NET_IPV4;
|
||||
nStartByte = 12;
|
||||
}
|
||||
// for 6to4 tunnelled addresses, use the encapsulated IPv4 address
|
||||
else if (IsRFC3964())
|
||||
{
|
||||
nClass = NET_IPV4;
|
||||
nStartByte = 2;
|
||||
}
|
||||
// for Teredo-tunnelled IPv6 addresses, use the encapsulated IPv4 address
|
||||
else if (IsRFC4380())
|
||||
{
|
||||
vchRet.push_back(NET_IPV4);
|
||||
vchRet.push_back(GetByte(3) ^ 0xFF);
|
||||
vchRet.push_back(GetByte(2) ^ 0xFF);
|
||||
return vchRet;
|
||||
}
|
||||
else if (IsTor())
|
||||
{
|
||||
nClass = NET_TOR;
|
||||
nStartByte = 6;
|
||||
nBits = 4;
|
||||
}
|
||||
// for he.net, use /36 groups
|
||||
else if (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x04 && GetByte(12) == 0x70)
|
||||
nBits = 36;
|
||||
// for the rest of the IPv6 network, use /32 groups
|
||||
else
|
||||
nBits = 32;
|
||||
|
||||
vchRet.push_back(nClass);
|
||||
while (nBits >= 8)
|
||||
{
|
||||
vchRet.push_back(GetByte(15 - nStartByte));
|
||||
nStartByte++;
|
||||
nBits -= 8;
|
||||
}
|
||||
if (nBits > 0)
|
||||
vchRet.push_back(GetByte(15 - nStartByte) | ((1 << (8 - nBits)) - 1));
|
||||
|
||||
return vchRet;
|
||||
}
|
||||
|
||||
uint64_t CNetAddr::GetHash() const
|
||||
{
|
||||
uint256 hash = Hash(&ip[0], &ip[16]);
|
||||
uint64_t nRet;
|
||||
memcpy(&nRet, &hash, sizeof(nRet));
|
||||
return nRet;
|
||||
}
|
||||
|
||||
// private extensions to enum Network, only returned by GetExtNetwork,
|
||||
// and only used in GetReachabilityFrom
|
||||
static const int NET_UNKNOWN = NET_MAX + 0;
|
||||
static const int NET_TEREDO = NET_MAX + 1;
|
||||
int static GetExtNetwork(const CNetAddr *addr)
|
||||
{
|
||||
if (addr == NULL)
|
||||
return NET_UNKNOWN;
|
||||
if (addr->IsRFC4380())
|
||||
return NET_TEREDO;
|
||||
return addr->GetNetwork();
|
||||
}
|
||||
|
||||
/** Calculates a metric for how reachable (*this) is from a given partner */
|
||||
int CNetAddr::GetReachabilityFrom(const CNetAddr *paddrPartner) const
|
||||
{
|
||||
enum Reachability {
|
||||
REACH_UNREACHABLE,
|
||||
REACH_DEFAULT,
|
||||
REACH_TEREDO,
|
||||
REACH_IPV6_WEAK,
|
||||
REACH_IPV4,
|
||||
REACH_IPV6_STRONG,
|
||||
REACH_PRIVATE
|
||||
};
|
||||
|
||||
if (!IsRoutable())
|
||||
return REACH_UNREACHABLE;
|
||||
|
||||
int ourNet = GetExtNetwork(this);
|
||||
int theirNet = GetExtNetwork(paddrPartner);
|
||||
bool fTunnel = IsRFC3964() || IsRFC6052() || IsRFC6145();
|
||||
|
||||
switch(theirNet) {
|
||||
case NET_IPV4:
|
||||
switch(ourNet) {
|
||||
default: return REACH_DEFAULT;
|
||||
case NET_IPV4: return REACH_IPV4;
|
||||
}
|
||||
case NET_IPV6:
|
||||
switch(ourNet) {
|
||||
default: return REACH_DEFAULT;
|
||||
case NET_TEREDO: return REACH_TEREDO;
|
||||
case NET_IPV4: return REACH_IPV4;
|
||||
case NET_IPV6: return fTunnel ? REACH_IPV6_WEAK : REACH_IPV6_STRONG; // only prefer giving our IPv6 address if it's not tunnelled
|
||||
}
|
||||
case NET_TOR:
|
||||
switch(ourNet) {
|
||||
default: return REACH_DEFAULT;
|
||||
case NET_IPV4: return REACH_IPV4; // Tor users can connect to IPv4 as well
|
||||
case NET_TOR: return REACH_PRIVATE;
|
||||
}
|
||||
case NET_TEREDO:
|
||||
switch(ourNet) {
|
||||
default: return REACH_DEFAULT;
|
||||
case NET_TEREDO: return REACH_TEREDO;
|
||||
case NET_IPV6: return REACH_IPV6_WEAK;
|
||||
case NET_IPV4: return REACH_IPV4;
|
||||
}
|
||||
case NET_UNKNOWN:
|
||||
case NET_UNROUTABLE:
|
||||
default:
|
||||
switch(ourNet) {
|
||||
default: return REACH_DEFAULT;
|
||||
case NET_TEREDO: return REACH_TEREDO;
|
||||
case NET_IPV6: return REACH_IPV6_WEAK;
|
||||
case NET_IPV4: return REACH_IPV4;
|
||||
case NET_TOR: return REACH_PRIVATE; // either from Tor, or don't care about our address
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CService::Init()
|
||||
{
|
||||
port = 0;
|
||||
}
|
||||
|
||||
CService::CService()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
CService::CService(const CNetAddr& cip, unsigned short portIn) : CNetAddr(cip), port(portIn)
|
||||
{
|
||||
}
|
||||
|
||||
CService::CService(const struct in_addr& ipv4Addr, unsigned short portIn) : CNetAddr(ipv4Addr), port(portIn)
|
||||
{
|
||||
}
|
||||
|
||||
CService::CService(const struct in6_addr& ipv6Addr, unsigned short portIn) : CNetAddr(ipv6Addr), port(portIn)
|
||||
{
|
||||
}
|
||||
|
||||
CService::CService(const struct sockaddr_in& addr) : CNetAddr(addr.sin_addr), port(ntohs(addr.sin_port))
|
||||
{
|
||||
assert(addr.sin_family == AF_INET);
|
||||
}
|
||||
|
||||
CService::CService(const struct sockaddr_in6 &addr) : CNetAddr(addr.sin6_addr, addr.sin6_scope_id), port(ntohs(addr.sin6_port))
|
||||
{
|
||||
assert(addr.sin6_family == AF_INET6);
|
||||
}
|
||||
|
||||
bool CService::SetSockAddr(const struct sockaddr *paddr)
|
||||
{
|
||||
switch (paddr->sa_family) {
|
||||
case AF_INET:
|
||||
*this = CService(*(const struct sockaddr_in*)paddr);
|
||||
return true;
|
||||
case AF_INET6:
|
||||
*this = CService(*(const struct sockaddr_in6*)paddr);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned short CService::GetPort() const
|
||||
{
|
||||
return port;
|
||||
}
|
||||
|
||||
bool operator==(const CService& a, const CService& b)
|
||||
{
|
||||
return (CNetAddr)a == (CNetAddr)b && a.port == b.port;
|
||||
}
|
||||
|
||||
bool operator!=(const CService& a, const CService& b)
|
||||
{
|
||||
return (CNetAddr)a != (CNetAddr)b || a.port != b.port;
|
||||
}
|
||||
|
||||
bool operator<(const CService& a, const CService& b)
|
||||
{
|
||||
return (CNetAddr)a < (CNetAddr)b || ((CNetAddr)a == (CNetAddr)b && a.port < b.port);
|
||||
}
|
||||
|
||||
bool CService::GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const
|
||||
{
|
||||
if (IsIPv4()) {
|
||||
if (*addrlen < (socklen_t)sizeof(struct sockaddr_in))
|
||||
return false;
|
||||
*addrlen = sizeof(struct sockaddr_in);
|
||||
struct sockaddr_in *paddrin = (struct sockaddr_in*)paddr;
|
||||
memset(paddrin, 0, *addrlen);
|
||||
if (!GetInAddr(&paddrin->sin_addr))
|
||||
return false;
|
||||
paddrin->sin_family = AF_INET;
|
||||
paddrin->sin_port = htons(port);
|
||||
return true;
|
||||
}
|
||||
if (IsIPv6()) {
|
||||
if (*addrlen < (socklen_t)sizeof(struct sockaddr_in6))
|
||||
return false;
|
||||
*addrlen = sizeof(struct sockaddr_in6);
|
||||
struct sockaddr_in6 *paddrin6 = (struct sockaddr_in6*)paddr;
|
||||
memset(paddrin6, 0, *addrlen);
|
||||
if (!GetIn6Addr(&paddrin6->sin6_addr))
|
||||
return false;
|
||||
paddrin6->sin6_scope_id = scopeId;
|
||||
paddrin6->sin6_family = AF_INET6;
|
||||
paddrin6->sin6_port = htons(port);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> CService::GetKey() const
|
||||
{
|
||||
std::vector<unsigned char> vKey;
|
||||
vKey.resize(18);
|
||||
memcpy(&vKey[0], ip, 16);
|
||||
vKey[16] = port / 0x100;
|
||||
vKey[17] = port & 0x0FF;
|
||||
return vKey;
|
||||
}
|
||||
|
||||
std::string CService::ToStringPort() const
|
||||
{
|
||||
return strprintf("%u", port);
|
||||
}
|
||||
|
||||
std::string CService::ToStringIPPort() const
|
||||
{
|
||||
if (IsIPv4() || IsTor()) {
|
||||
return ToStringIP() + ":" + ToStringPort();
|
||||
} else {
|
||||
return "[" + ToStringIP() + "]:" + ToStringPort();
|
||||
}
|
||||
}
|
||||
|
||||
std::string CService::ToString() const
|
||||
{
|
||||
return ToStringIPPort();
|
||||
}
|
||||
|
||||
void CService::SetPort(unsigned short portIn)
|
||||
{
|
||||
port = portIn;
|
||||
}
|
||||
|
||||
CSubNet::CSubNet():
|
||||
valid(false)
|
||||
{
|
||||
memset(netmask, 0, sizeof(netmask));
|
||||
}
|
||||
|
||||
CSubNet::CSubNet(const CNetAddr &addr, int32_t mask)
|
||||
{
|
||||
valid = true;
|
||||
network = addr;
|
||||
// Default to /32 (IPv4) or /128 (IPv6), i.e. match single address
|
||||
memset(netmask, 255, sizeof(netmask));
|
||||
|
||||
// IPv4 addresses start at offset 12, and first 12 bytes must match, so just offset n
|
||||
const int astartofs = network.IsIPv4() ? 12 : 0;
|
||||
|
||||
int32_t n = mask;
|
||||
if(n >= 0 && n <= (128 - astartofs*8)) // Only valid if in range of bits of address
|
||||
{
|
||||
n += astartofs*8;
|
||||
// Clear bits [n..127]
|
||||
for (; n < 128; ++n)
|
||||
netmask[n>>3] &= ~(1<<(7-(n&7)));
|
||||
} else
|
||||
valid = false;
|
||||
|
||||
// Normalize network according to netmask
|
||||
for(int x=0; x<16; ++x)
|
||||
network.ip[x] &= netmask[x];
|
||||
}
|
||||
|
||||
CSubNet::CSubNet(const CNetAddr &addr, const CNetAddr &mask)
|
||||
{
|
||||
valid = true;
|
||||
network = addr;
|
||||
// Default to /32 (IPv4) or /128 (IPv6), i.e. match single address
|
||||
memset(netmask, 255, sizeof(netmask));
|
||||
|
||||
// IPv4 addresses start at offset 12, and first 12 bytes must match, so just offset n
|
||||
const int astartofs = network.IsIPv4() ? 12 : 0;
|
||||
|
||||
for(int x=astartofs; x<16; ++x)
|
||||
netmask[x] = mask.ip[x];
|
||||
|
||||
// Normalize network according to netmask
|
||||
for(int x=0; x<16; ++x)
|
||||
network.ip[x] &= netmask[x];
|
||||
}
|
||||
|
||||
CSubNet::CSubNet(const CNetAddr &addr):
|
||||
valid(addr.IsValid())
|
||||
{
|
||||
memset(netmask, 255, sizeof(netmask));
|
||||
network = addr;
|
||||
}
|
||||
|
||||
bool CSubNet::Match(const CNetAddr &addr) const
|
||||
{
|
||||
if (!valid || !addr.IsValid())
|
||||
return false;
|
||||
for(int x=0; x<16; ++x)
|
||||
if ((addr.ip[x] & netmask[x]) != network.ip[x])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline int NetmaskBits(uint8_t x)
|
||||
{
|
||||
switch(x) {
|
||||
case 0x00: return 0; break;
|
||||
case 0x80: return 1; break;
|
||||
case 0xc0: return 2; break;
|
||||
case 0xe0: return 3; break;
|
||||
case 0xf0: return 4; break;
|
||||
case 0xf8: return 5; break;
|
||||
case 0xfc: return 6; break;
|
||||
case 0xfe: return 7; break;
|
||||
case 0xff: return 8; break;
|
||||
default: return -1; break;
|
||||
}
|
||||
}
|
||||
|
||||
std::string CSubNet::ToString() const
|
||||
{
|
||||
/* Parse binary 1{n}0{N-n} to see if mask can be represented as /n */
|
||||
int cidr = 0;
|
||||
bool valid_cidr = true;
|
||||
int n = network.IsIPv4() ? 12 : 0;
|
||||
for (; n < 16 && netmask[n] == 0xff; ++n)
|
||||
cidr += 8;
|
||||
if (n < 16) {
|
||||
int bits = NetmaskBits(netmask[n]);
|
||||
if (bits < 0)
|
||||
valid_cidr = false;
|
||||
else
|
||||
cidr += bits;
|
||||
++n;
|
||||
}
|
||||
for (; n < 16 && valid_cidr; ++n)
|
||||
if (netmask[n] != 0x00)
|
||||
valid_cidr = false;
|
||||
|
||||
/* Format output */
|
||||
std::string strNetmask;
|
||||
if (valid_cidr) {
|
||||
strNetmask = strprintf("%u", cidr);
|
||||
} else {
|
||||
if (network.IsIPv4())
|
||||
strNetmask = strprintf("%u.%u.%u.%u", netmask[12], netmask[13], netmask[14], netmask[15]);
|
||||
else
|
||||
strNetmask = strprintf("%x:%x:%x:%x:%x:%x:%x:%x",
|
||||
netmask[0] << 8 | netmask[1], netmask[2] << 8 | netmask[3],
|
||||
netmask[4] << 8 | netmask[5], netmask[6] << 8 | netmask[7],
|
||||
netmask[8] << 8 | netmask[9], netmask[10] << 8 | netmask[11],
|
||||
netmask[12] << 8 | netmask[13], netmask[14] << 8 | netmask[15]);
|
||||
}
|
||||
|
||||
return network.ToString() + "/" + strNetmask;
|
||||
}
|
||||
|
||||
bool CSubNet::IsValid() const
|
||||
{
|
||||
return valid;
|
||||
}
|
||||
|
||||
bool operator==(const CSubNet& a, const CSubNet& b)
|
||||
{
|
||||
return a.valid == b.valid && a.network == b.network && !memcmp(a.netmask, b.netmask, 16);
|
||||
}
|
||||
|
||||
bool operator!=(const CSubNet& a, const CSubNet& b)
|
||||
{
|
||||
return !(a==b);
|
||||
}
|
||||
|
||||
bool operator<(const CSubNet& a, const CSubNet& b)
|
||||
{
|
||||
return (a.network < b.network || (a.network == b.network && memcmp(a.netmask, b.netmask, 16) < 0));
|
||||
}
|
171
src/netaddress.h
Normal file
171
src/netaddress.h
Normal file
@ -0,0 +1,171 @@
|
||||
// Copyright (c) 2009-2015 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_NETADDRESS_H
|
||||
#define BITCOIN_NETADDRESS_H
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "config/bitcoin-config.h"
|
||||
#endif
|
||||
|
||||
#include "compat.h"
|
||||
#include "serialize.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
enum Network
|
||||
{
|
||||
NET_UNROUTABLE = 0,
|
||||
NET_IPV4,
|
||||
NET_IPV6,
|
||||
NET_TOR,
|
||||
|
||||
NET_MAX,
|
||||
};
|
||||
|
||||
/** IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96)) */
|
||||
class CNetAddr
|
||||
{
|
||||
protected:
|
||||
unsigned char ip[16]; // in network byte order
|
||||
uint32_t scopeId; // for scoped/link-local ipv6 addresses
|
||||
|
||||
public:
|
||||
CNetAddr();
|
||||
CNetAddr(const struct in_addr& ipv4Addr);
|
||||
void Init();
|
||||
void SetIP(const CNetAddr& ip);
|
||||
|
||||
/**
|
||||
* Set raw IPv4 or IPv6 address (in network byte order)
|
||||
* @note Only NET_IPV4 and NET_IPV6 are allowed for network.
|
||||
*/
|
||||
void SetRaw(Network network, const uint8_t *data);
|
||||
|
||||
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)
|
||||
bool IsRFC1918() const; // IPv4 private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12)
|
||||
bool IsRFC2544() const; // IPv4 inter-network communcations (192.18.0.0/15)
|
||||
bool IsRFC6598() const; // IPv4 ISP-level NAT (100.64.0.0/10)
|
||||
bool IsRFC5737() const; // IPv4 documentation addresses (192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24)
|
||||
bool IsRFC3849() const; // IPv6 documentation address (2001:0DB8::/32)
|
||||
bool IsRFC3927() const; // IPv4 autoconfig (169.254.0.0/16)
|
||||
bool IsRFC3964() const; // IPv6 6to4 tunnelling (2002::/16)
|
||||
bool IsRFC4193() const; // IPv6 unique local (FC00::/7)
|
||||
bool IsRFC4380() const; // IPv6 Teredo tunnelling (2001::/32)
|
||||
bool IsRFC4843() const; // IPv6 ORCHID (2001:10::/28)
|
||||
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 IsTor() const;
|
||||
bool IsLocal() const;
|
||||
bool IsRoutable() const;
|
||||
bool IsValid() const;
|
||||
bool IsMulticast() const;
|
||||
enum Network GetNetwork() const;
|
||||
std::string ToString() const;
|
||||
std::string ToStringIP() const;
|
||||
unsigned int GetByte(int n) const;
|
||||
uint64_t GetHash() const;
|
||||
bool GetInAddr(struct in_addr* pipv4Addr) const;
|
||||
std::vector<unsigned char> GetGroup() const;
|
||||
int GetReachabilityFrom(const CNetAddr *paddrPartner = NULL) const;
|
||||
|
||||
CNetAddr(const struct in6_addr& pipv6Addr, const uint32_t scope = 0);
|
||||
bool GetIn6Addr(struct in6_addr* pipv6Addr) const;
|
||||
|
||||
friend bool operator==(const CNetAddr& a, const CNetAddr& b);
|
||||
friend bool operator!=(const CNetAddr& a, const CNetAddr& b);
|
||||
friend bool operator<(const CNetAddr& a, const CNetAddr& b);
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
READWRITE(FLATDATA(ip));
|
||||
}
|
||||
|
||||
friend class CSubNet;
|
||||
};
|
||||
|
||||
class CSubNet
|
||||
{
|
||||
protected:
|
||||
/// Network (base) address
|
||||
CNetAddr network;
|
||||
/// Netmask, in network byte order
|
||||
uint8_t netmask[16];
|
||||
/// Is this value valid? (only used to signal parse errors)
|
||||
bool valid;
|
||||
|
||||
public:
|
||||
CSubNet();
|
||||
CSubNet(const CNetAddr &addr, int32_t mask);
|
||||
CSubNet(const CNetAddr &addr, const CNetAddr &mask);
|
||||
|
||||
//constructor for single ip subnet (<ipv4>/32 or <ipv6>/128)
|
||||
explicit CSubNet(const CNetAddr &addr);
|
||||
|
||||
bool Match(const CNetAddr &addr) const;
|
||||
|
||||
std::string ToString() const;
|
||||
bool IsValid() const;
|
||||
|
||||
friend bool operator==(const CSubNet& a, const CSubNet& b);
|
||||
friend bool operator!=(const CSubNet& a, const CSubNet& b);
|
||||
friend bool operator<(const CSubNet& a, const CSubNet& b);
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
READWRITE(network);
|
||||
READWRITE(FLATDATA(netmask));
|
||||
READWRITE(FLATDATA(valid));
|
||||
}
|
||||
};
|
||||
|
||||
/** A combination of a network address (CNetAddr) and a (TCP) port */
|
||||
class CService : public CNetAddr
|
||||
{
|
||||
protected:
|
||||
unsigned short port; // host order
|
||||
|
||||
public:
|
||||
CService();
|
||||
CService(const CNetAddr& ip, unsigned short port);
|
||||
CService(const struct in_addr& ipv4Addr, unsigned short port);
|
||||
CService(const struct sockaddr_in& addr);
|
||||
void Init();
|
||||
void SetPort(unsigned short portIn);
|
||||
unsigned short GetPort() const;
|
||||
bool GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const;
|
||||
bool SetSockAddr(const struct sockaddr* paddr);
|
||||
friend bool operator==(const CService& a, const CService& b);
|
||||
friend bool operator!=(const CService& a, const CService& b);
|
||||
friend bool operator<(const CService& a, const CService& b);
|
||||
std::vector<unsigned char> GetKey() const;
|
||||
std::string ToString() const;
|
||||
std::string ToStringPort() const;
|
||||
std::string ToStringIPPort() const;
|
||||
|
||||
CService(const struct in6_addr& ipv6Addr, unsigned short port);
|
||||
CService(const struct sockaddr_in6& addr);
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
READWRITE(FLATDATA(ip));
|
||||
unsigned short portN = htons(port);
|
||||
READWRITE(FLATDATA(portN));
|
||||
if (ser_action.ForRead())
|
||||
port = ntohs(portN);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // BITCOIN_NETADDRESS_H
|
782
src/netbase.cpp
782
src/netbase.cpp
@ -42,8 +42,6 @@ static CCriticalSection cs_proxyInfos;
|
||||
int nConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
|
||||
bool fNameLookup = DEFAULT_NAME_LOOKUP;
|
||||
|
||||
static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
|
||||
|
||||
// Need ample time for negotiation for very slow proxies such as Tor (milliseconds)
|
||||
static const int SOCKS5_RECV_TIMEOUT = 20 * 1000;
|
||||
|
||||
@ -195,6 +193,16 @@ bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nM
|
||||
return LookupIntern(strHost.c_str(), vIP, nMaxSolutions, fAllowLookup);
|
||||
}
|
||||
|
||||
bool LookupHost(const char *pszName, CNetAddr& addr, bool fAllowLookup)
|
||||
{
|
||||
std::vector<CNetAddr> vIP;
|
||||
LookupHost(pszName, vIP, 1, fAllowLookup);
|
||||
if(vIP.empty())
|
||||
return false;
|
||||
addr = vIP.front();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions)
|
||||
{
|
||||
if (pszName[0] == 0)
|
||||
@ -223,9 +231,14 @@ bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLoo
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LookupNumeric(const char *pszName, CService& addr, int portDefault)
|
||||
CService LookupNumeric(const char *pszName, int portDefault)
|
||||
{
|
||||
return Lookup(pszName, addr, portDefault, false);
|
||||
CService addr;
|
||||
// "1.2:345" will fail to resolve the ip, but will still set the port.
|
||||
// If the ip fails to resolve, re-init the result.
|
||||
if(!Lookup(pszName, addr, portDefault, false))
|
||||
addr = CService();
|
||||
return addr;
|
||||
}
|
||||
|
||||
struct timeval MillisToTimeval(int64_t nTimeout)
|
||||
@ -629,777 +642,48 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest
|
||||
}
|
||||
}
|
||||
|
||||
addr = CService("0.0.0.0:0");
|
||||
addr = CService();
|
||||
|
||||
if (!HaveNameProxy())
|
||||
return false;
|
||||
return ConnectThroughProxy(nameProxy, strDest, port, hSocketRet, nTimeout, outProxyConnectionFailed);
|
||||
}
|
||||
|
||||
void CNetAddr::Init()
|
||||
{
|
||||
memset(ip, 0, sizeof(ip));
|
||||
scopeId = 0;
|
||||
}
|
||||
|
||||
void CNetAddr::SetIP(const CNetAddr& ipIn)
|
||||
{
|
||||
memcpy(ip, ipIn.ip, sizeof(ip));
|
||||
}
|
||||
|
||||
void CNetAddr::SetRaw(Network network, const uint8_t *ip_in)
|
||||
{
|
||||
switch(network)
|
||||
{
|
||||
case NET_IPV4:
|
||||
memcpy(ip, pchIPv4, 12);
|
||||
memcpy(ip+12, ip_in, 4);
|
||||
break;
|
||||
case NET_IPV6:
|
||||
memcpy(ip, ip_in, 16);
|
||||
break;
|
||||
default:
|
||||
assert(!"invalid network");
|
||||
}
|
||||
}
|
||||
|
||||
static const unsigned char pchOnionCat[] = {0xFD,0x87,0xD8,0x7E,0xEB,0x43};
|
||||
|
||||
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;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CNetAddr::CNetAddr()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
CNetAddr::CNetAddr(const struct in_addr& ipv4Addr)
|
||||
{
|
||||
SetRaw(NET_IPV4, (const uint8_t*)&ipv4Addr);
|
||||
}
|
||||
|
||||
CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr, const uint32_t scope)
|
||||
{
|
||||
SetRaw(NET_IPV6, (const uint8_t*)&ipv6Addr);
|
||||
scopeId = scope;
|
||||
}
|
||||
|
||||
CNetAddr::CNetAddr(const char *pszIp)
|
||||
{
|
||||
Init();
|
||||
std::vector<CNetAddr> vIP;
|
||||
if (LookupHost(pszIp, vIP, 1, false))
|
||||
*this = vIP[0];
|
||||
}
|
||||
|
||||
CNetAddr::CNetAddr(const std::string &strIp)
|
||||
{
|
||||
Init();
|
||||
std::vector<CNetAddr> vIP;
|
||||
if (LookupHost(strIp.c_str(), vIP, 1, false))
|
||||
*this = vIP[0];
|
||||
}
|
||||
|
||||
unsigned int CNetAddr::GetByte(int n) const
|
||||
{
|
||||
return ip[15-n];
|
||||
}
|
||||
|
||||
bool CNetAddr::IsIPv4() const
|
||||
{
|
||||
return (memcmp(ip, pchIPv4, sizeof(pchIPv4)) == 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsIPv6() const
|
||||
{
|
||||
return (!IsIPv4() && !IsTor());
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC1918() const
|
||||
{
|
||||
return IsIPv4() && (
|
||||
GetByte(3) == 10 ||
|
||||
(GetByte(3) == 192 && GetByte(2) == 168) ||
|
||||
(GetByte(3) == 172 && (GetByte(2) >= 16 && GetByte(2) <= 31)));
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC2544() const
|
||||
{
|
||||
return IsIPv4() && GetByte(3) == 198 && (GetByte(2) == 18 || GetByte(2) == 19);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC3927() const
|
||||
{
|
||||
return IsIPv4() && (GetByte(3) == 169 && GetByte(2) == 254);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC6598() const
|
||||
{
|
||||
return IsIPv4() && GetByte(3) == 100 && GetByte(2) >= 64 && GetByte(2) <= 127;
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC5737() const
|
||||
{
|
||||
return IsIPv4() && ((GetByte(3) == 192 && GetByte(2) == 0 && GetByte(1) == 2) ||
|
||||
(GetByte(3) == 198 && GetByte(2) == 51 && GetByte(1) == 100) ||
|
||||
(GetByte(3) == 203 && GetByte(2) == 0 && GetByte(1) == 113));
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC3849() const
|
||||
{
|
||||
return GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x0D && GetByte(12) == 0xB8;
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC3964() const
|
||||
{
|
||||
return (GetByte(15) == 0x20 && GetByte(14) == 0x02);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC6052() const
|
||||
{
|
||||
static const unsigned char pchRFC6052[] = {0,0x64,0xFF,0x9B,0,0,0,0,0,0,0,0};
|
||||
return (memcmp(ip, pchRFC6052, sizeof(pchRFC6052)) == 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC4380() const
|
||||
{
|
||||
return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0 && GetByte(12) == 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC4862() const
|
||||
{
|
||||
static const unsigned char pchRFC4862[] = {0xFE,0x80,0,0,0,0,0,0};
|
||||
return (memcmp(ip, pchRFC4862, sizeof(pchRFC4862)) == 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC4193() const
|
||||
{
|
||||
return ((GetByte(15) & 0xFE) == 0xFC);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC6145() const
|
||||
{
|
||||
static const unsigned char pchRFC6145[] = {0,0,0,0,0,0,0,0,0xFF,0xFF,0,0};
|
||||
return (memcmp(ip, pchRFC6145, sizeof(pchRFC6145)) == 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC4843() const
|
||||
{
|
||||
return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x00 && (GetByte(12) & 0xF0) == 0x10);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsTor() const
|
||||
{
|
||||
return (memcmp(ip, pchOnionCat, sizeof(pchOnionCat)) == 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsLocal() const
|
||||
{
|
||||
// IPv4 loopback
|
||||
if (IsIPv4() && (GetByte(3) == 127 || GetByte(3) == 0))
|
||||
return true;
|
||||
|
||||
// IPv6 loopback (::1/128)
|
||||
static const unsigned char pchLocal[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
|
||||
if (memcmp(ip, pchLocal, 16) == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CNetAddr::IsMulticast() const
|
||||
{
|
||||
return (IsIPv4() && (GetByte(3) & 0xF0) == 0xE0)
|
||||
|| (GetByte(15) == 0xFF);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsValid() const
|
||||
{
|
||||
// Cleanup 3-byte shifted addresses caused by garbage in size field
|
||||
// of addr messages from versions before 0.2.9 checksum.
|
||||
// Two consecutive addr messages look like this:
|
||||
// header20 vectorlen3 addr26 addr26 addr26 header20 vectorlen3 addr26 addr26 addr26...
|
||||
// so if the first length field is garbled, it reads the second batch
|
||||
// of addr misaligned by 3 bytes.
|
||||
if (memcmp(ip, pchIPv4+3, sizeof(pchIPv4)-3) == 0)
|
||||
return false;
|
||||
|
||||
// unspecified IPv6 address (::/128)
|
||||
unsigned char ipNone[16] = {};
|
||||
if (memcmp(ip, ipNone, 16) == 0)
|
||||
return false;
|
||||
|
||||
// documentation IPv6 address
|
||||
if (IsRFC3849())
|
||||
return false;
|
||||
|
||||
if (IsIPv4())
|
||||
{
|
||||
// INADDR_NONE
|
||||
uint32_t ipNone = INADDR_NONE;
|
||||
if (memcmp(ip+12, &ipNone, 4) == 0)
|
||||
return false;
|
||||
|
||||
// 0
|
||||
ipNone = 0;
|
||||
if (memcmp(ip+12, &ipNone, 4) == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRoutable() const
|
||||
{
|
||||
return IsValid() && !(IsRFC1918() || IsRFC2544() || IsRFC3927() || IsRFC4862() || IsRFC6598() || IsRFC5737() || (IsRFC4193() && !IsTor()) || IsRFC4843() || IsLocal());
|
||||
}
|
||||
|
||||
enum Network CNetAddr::GetNetwork() const
|
||||
{
|
||||
if (!IsRoutable())
|
||||
return NET_UNROUTABLE;
|
||||
|
||||
if (IsIPv4())
|
||||
return NET_IPV4;
|
||||
|
||||
if (IsTor())
|
||||
return NET_TOR;
|
||||
|
||||
return NET_IPV6;
|
||||
}
|
||||
|
||||
std::string CNetAddr::ToStringIP() const
|
||||
{
|
||||
if (IsTor())
|
||||
return EncodeBase32(&ip[6], 10) + ".onion";
|
||||
CService serv(*this, 0);
|
||||
struct sockaddr_storage sockaddr;
|
||||
socklen_t socklen = sizeof(sockaddr);
|
||||
if (serv.GetSockAddr((struct sockaddr*)&sockaddr, &socklen)) {
|
||||
char name[1025] = "";
|
||||
if (!getnameinfo((const struct sockaddr*)&sockaddr, socklen, name, sizeof(name), NULL, 0, NI_NUMERICHOST))
|
||||
return std::string(name);
|
||||
}
|
||||
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",
|
||||
GetByte(15) << 8 | GetByte(14), GetByte(13) << 8 | GetByte(12),
|
||||
GetByte(11) << 8 | GetByte(10), GetByte(9) << 8 | GetByte(8),
|
||||
GetByte(7) << 8 | GetByte(6), GetByte(5) << 8 | GetByte(4),
|
||||
GetByte(3) << 8 | GetByte(2), GetByte(1) << 8 | GetByte(0));
|
||||
}
|
||||
|
||||
std::string CNetAddr::ToString() const
|
||||
{
|
||||
return ToStringIP();
|
||||
}
|
||||
|
||||
bool operator==(const CNetAddr& a, const CNetAddr& b)
|
||||
{
|
||||
return (memcmp(a.ip, b.ip, 16) == 0);
|
||||
}
|
||||
|
||||
bool operator!=(const CNetAddr& a, const CNetAddr& b)
|
||||
{
|
||||
return (memcmp(a.ip, b.ip, 16) != 0);
|
||||
}
|
||||
|
||||
bool operator<(const CNetAddr& a, const CNetAddr& b)
|
||||
{
|
||||
return (memcmp(a.ip, b.ip, 16) < 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const
|
||||
{
|
||||
if (!IsIPv4())
|
||||
return false;
|
||||
memcpy(pipv4Addr, ip+12, 4);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const
|
||||
{
|
||||
memcpy(pipv6Addr, ip, 16);
|
||||
return true;
|
||||
}
|
||||
|
||||
// get canonical identifier of an address' group
|
||||
// no two connections will be attempted to addresses with the same group
|
||||
std::vector<unsigned char> CNetAddr::GetGroup() const
|
||||
{
|
||||
std::vector<unsigned char> vchRet;
|
||||
int nClass = NET_IPV6;
|
||||
int nStartByte = 0;
|
||||
int nBits = 16;
|
||||
|
||||
// all local addresses belong to the same group
|
||||
if (IsLocal())
|
||||
{
|
||||
nClass = 255;
|
||||
nBits = 0;
|
||||
}
|
||||
|
||||
// all unroutable addresses belong to the same group
|
||||
if (!IsRoutable())
|
||||
{
|
||||
nClass = NET_UNROUTABLE;
|
||||
nBits = 0;
|
||||
}
|
||||
// for IPv4 addresses, '1' + the 16 higher-order bits of the IP
|
||||
// includes mapped IPv4, SIIT translated IPv4, and the well-known prefix
|
||||
else if (IsIPv4() || IsRFC6145() || IsRFC6052())
|
||||
{
|
||||
nClass = NET_IPV4;
|
||||
nStartByte = 12;
|
||||
}
|
||||
// for 6to4 tunnelled addresses, use the encapsulated IPv4 address
|
||||
else if (IsRFC3964())
|
||||
{
|
||||
nClass = NET_IPV4;
|
||||
nStartByte = 2;
|
||||
}
|
||||
// for Teredo-tunnelled IPv6 addresses, use the encapsulated IPv4 address
|
||||
else if (IsRFC4380())
|
||||
{
|
||||
vchRet.push_back(NET_IPV4);
|
||||
vchRet.push_back(GetByte(3) ^ 0xFF);
|
||||
vchRet.push_back(GetByte(2) ^ 0xFF);
|
||||
return vchRet;
|
||||
}
|
||||
else if (IsTor())
|
||||
{
|
||||
nClass = NET_TOR;
|
||||
nStartByte = 6;
|
||||
nBits = 4;
|
||||
}
|
||||
// for he.net, use /36 groups
|
||||
else if (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x04 && GetByte(12) == 0x70)
|
||||
nBits = 36;
|
||||
// for the rest of the IPv6 network, use /32 groups
|
||||
else
|
||||
nBits = 32;
|
||||
|
||||
vchRet.push_back(nClass);
|
||||
while (nBits >= 8)
|
||||
{
|
||||
vchRet.push_back(GetByte(15 - nStartByte));
|
||||
nStartByte++;
|
||||
nBits -= 8;
|
||||
}
|
||||
if (nBits > 0)
|
||||
vchRet.push_back(GetByte(15 - nStartByte) | ((1 << (8 - nBits)) - 1));
|
||||
|
||||
return vchRet;
|
||||
}
|
||||
|
||||
uint64_t CNetAddr::GetHash() const
|
||||
{
|
||||
uint256 hash = Hash(&ip[0], &ip[16]);
|
||||
uint64_t nRet;
|
||||
memcpy(&nRet, &hash, sizeof(nRet));
|
||||
return nRet;
|
||||
}
|
||||
|
||||
// private extensions to enum Network, only returned by GetExtNetwork,
|
||||
// and only used in GetReachabilityFrom
|
||||
static const int NET_UNKNOWN = NET_MAX + 0;
|
||||
static const int NET_TEREDO = NET_MAX + 1;
|
||||
int static GetExtNetwork(const CNetAddr *addr)
|
||||
{
|
||||
if (addr == NULL)
|
||||
return NET_UNKNOWN;
|
||||
if (addr->IsRFC4380())
|
||||
return NET_TEREDO;
|
||||
return addr->GetNetwork();
|
||||
}
|
||||
|
||||
/** Calculates a metric for how reachable (*this) is from a given partner */
|
||||
int CNetAddr::GetReachabilityFrom(const CNetAddr *paddrPartner) const
|
||||
{
|
||||
enum Reachability {
|
||||
REACH_UNREACHABLE,
|
||||
REACH_DEFAULT,
|
||||
REACH_TEREDO,
|
||||
REACH_IPV6_WEAK,
|
||||
REACH_IPV4,
|
||||
REACH_IPV6_STRONG,
|
||||
REACH_PRIVATE
|
||||
};
|
||||
|
||||
if (!IsRoutable())
|
||||
return REACH_UNREACHABLE;
|
||||
|
||||
int ourNet = GetExtNetwork(this);
|
||||
int theirNet = GetExtNetwork(paddrPartner);
|
||||
bool fTunnel = IsRFC3964() || IsRFC6052() || IsRFC6145();
|
||||
|
||||
switch(theirNet) {
|
||||
case NET_IPV4:
|
||||
switch(ourNet) {
|
||||
default: return REACH_DEFAULT;
|
||||
case NET_IPV4: return REACH_IPV4;
|
||||
}
|
||||
case NET_IPV6:
|
||||
switch(ourNet) {
|
||||
default: return REACH_DEFAULT;
|
||||
case NET_TEREDO: return REACH_TEREDO;
|
||||
case NET_IPV4: return REACH_IPV4;
|
||||
case NET_IPV6: return fTunnel ? REACH_IPV6_WEAK : REACH_IPV6_STRONG; // only prefer giving our IPv6 address if it's not tunnelled
|
||||
}
|
||||
case NET_TOR:
|
||||
switch(ourNet) {
|
||||
default: return REACH_DEFAULT;
|
||||
case NET_IPV4: return REACH_IPV4; // Tor users can connect to IPv4 as well
|
||||
case NET_TOR: return REACH_PRIVATE;
|
||||
}
|
||||
case NET_TEREDO:
|
||||
switch(ourNet) {
|
||||
default: return REACH_DEFAULT;
|
||||
case NET_TEREDO: return REACH_TEREDO;
|
||||
case NET_IPV6: return REACH_IPV6_WEAK;
|
||||
case NET_IPV4: return REACH_IPV4;
|
||||
}
|
||||
case NET_UNKNOWN:
|
||||
case NET_UNROUTABLE:
|
||||
default:
|
||||
switch(ourNet) {
|
||||
default: return REACH_DEFAULT;
|
||||
case NET_TEREDO: return REACH_TEREDO;
|
||||
case NET_IPV6: return REACH_IPV6_WEAK;
|
||||
case NET_IPV4: return REACH_IPV4;
|
||||
case NET_TOR: return REACH_PRIVATE; // either from Tor, or don't care about our address
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CService::Init()
|
||||
{
|
||||
port = 0;
|
||||
}
|
||||
|
||||
CService::CService()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
CService::CService(const CNetAddr& cip, unsigned short portIn) : CNetAddr(cip), port(portIn)
|
||||
{
|
||||
}
|
||||
|
||||
CService::CService(const struct in_addr& ipv4Addr, unsigned short portIn) : CNetAddr(ipv4Addr), port(portIn)
|
||||
{
|
||||
}
|
||||
|
||||
CService::CService(const struct in6_addr& ipv6Addr, unsigned short portIn) : CNetAddr(ipv6Addr), port(portIn)
|
||||
{
|
||||
}
|
||||
|
||||
CService::CService(const struct sockaddr_in& addr) : CNetAddr(addr.sin_addr), port(ntohs(addr.sin_port))
|
||||
{
|
||||
assert(addr.sin_family == AF_INET);
|
||||
}
|
||||
|
||||
CService::CService(const struct sockaddr_in6 &addr) : CNetAddr(addr.sin6_addr, addr.sin6_scope_id), port(ntohs(addr.sin6_port))
|
||||
{
|
||||
assert(addr.sin6_family == AF_INET6);
|
||||
}
|
||||
|
||||
bool CService::SetSockAddr(const struct sockaddr *paddr)
|
||||
{
|
||||
switch (paddr->sa_family) {
|
||||
case AF_INET:
|
||||
*this = CService(*(const struct sockaddr_in*)paddr);
|
||||
return true;
|
||||
case AF_INET6:
|
||||
*this = CService(*(const struct sockaddr_in6*)paddr);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
CService::CService(const char *pszIpPort)
|
||||
{
|
||||
Init();
|
||||
CService ip;
|
||||
if (Lookup(pszIpPort, ip, 0, false))
|
||||
*this = ip;
|
||||
}
|
||||
|
||||
CService::CService(const char *pszIpPort, int portDefault)
|
||||
{
|
||||
Init();
|
||||
CService ip;
|
||||
if (Lookup(pszIpPort, ip, portDefault, false))
|
||||
*this = ip;
|
||||
}
|
||||
|
||||
CService::CService(const std::string &strIpPort)
|
||||
{
|
||||
Init();
|
||||
CService ip;
|
||||
if (Lookup(strIpPort.c_str(), ip, 0, false))
|
||||
*this = ip;
|
||||
}
|
||||
|
||||
CService::CService(const std::string &strIpPort, int portDefault)
|
||||
{
|
||||
Init();
|
||||
CService ip;
|
||||
if (Lookup(strIpPort.c_str(), ip, portDefault, false))
|
||||
*this = ip;
|
||||
}
|
||||
|
||||
unsigned short CService::GetPort() const
|
||||
{
|
||||
return port;
|
||||
}
|
||||
|
||||
bool operator==(const CService& a, const CService& b)
|
||||
{
|
||||
return (CNetAddr)a == (CNetAddr)b && a.port == b.port;
|
||||
}
|
||||
|
||||
bool operator!=(const CService& a, const CService& b)
|
||||
{
|
||||
return (CNetAddr)a != (CNetAddr)b || a.port != b.port;
|
||||
}
|
||||
|
||||
bool operator<(const CService& a, const CService& b)
|
||||
{
|
||||
return (CNetAddr)a < (CNetAddr)b || ((CNetAddr)a == (CNetAddr)b && a.port < b.port);
|
||||
}
|
||||
|
||||
bool CService::GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const
|
||||
{
|
||||
if (IsIPv4()) {
|
||||
if (*addrlen < (socklen_t)sizeof(struct sockaddr_in))
|
||||
return false;
|
||||
*addrlen = sizeof(struct sockaddr_in);
|
||||
struct sockaddr_in *paddrin = (struct sockaddr_in*)paddr;
|
||||
memset(paddrin, 0, *addrlen);
|
||||
if (!GetInAddr(&paddrin->sin_addr))
|
||||
return false;
|
||||
paddrin->sin_family = AF_INET;
|
||||
paddrin->sin_port = htons(port);
|
||||
return true;
|
||||
}
|
||||
if (IsIPv6()) {
|
||||
if (*addrlen < (socklen_t)sizeof(struct sockaddr_in6))
|
||||
return false;
|
||||
*addrlen = sizeof(struct sockaddr_in6);
|
||||
struct sockaddr_in6 *paddrin6 = (struct sockaddr_in6*)paddr;
|
||||
memset(paddrin6, 0, *addrlen);
|
||||
if (!GetIn6Addr(&paddrin6->sin6_addr))
|
||||
return false;
|
||||
paddrin6->sin6_scope_id = scopeId;
|
||||
paddrin6->sin6_family = AF_INET6;
|
||||
paddrin6->sin6_port = htons(port);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> CService::GetKey() const
|
||||
{
|
||||
std::vector<unsigned char> vKey;
|
||||
vKey.resize(18);
|
||||
memcpy(&vKey[0], ip, 16);
|
||||
vKey[16] = port / 0x100;
|
||||
vKey[17] = port & 0x0FF;
|
||||
return vKey;
|
||||
}
|
||||
|
||||
std::string CService::ToStringPort() const
|
||||
{
|
||||
return strprintf("%u", port);
|
||||
}
|
||||
|
||||
std::string CService::ToStringIPPort() const
|
||||
{
|
||||
if (IsIPv4() || IsTor()) {
|
||||
return ToStringIP() + ":" + ToStringPort();
|
||||
} else {
|
||||
return "[" + ToStringIP() + "]:" + ToStringPort();
|
||||
}
|
||||
}
|
||||
|
||||
std::string CService::ToString() const
|
||||
{
|
||||
return ToStringIPPort();
|
||||
}
|
||||
|
||||
void CService::SetPort(unsigned short portIn)
|
||||
{
|
||||
port = portIn;
|
||||
}
|
||||
|
||||
CSubNet::CSubNet():
|
||||
valid(false)
|
||||
{
|
||||
memset(netmask, 0, sizeof(netmask));
|
||||
}
|
||||
|
||||
CSubNet::CSubNet(const std::string &strSubnet)
|
||||
bool LookupSubNet(const char* pszName, CSubNet& ret)
|
||||
{
|
||||
std::string strSubnet(pszName);
|
||||
size_t slash = strSubnet.find_last_of('/');
|
||||
std::vector<CNetAddr> vIP;
|
||||
|
||||
valid = true;
|
||||
// Default to /32 (IPv4) or /128 (IPv6), i.e. match single address
|
||||
memset(netmask, 255, sizeof(netmask));
|
||||
|
||||
std::string strAddress = strSubnet.substr(0, slash);
|
||||
if (LookupHost(strAddress.c_str(), vIP, 1, false))
|
||||
{
|
||||
network = vIP[0];
|
||||
CNetAddr network = vIP[0];
|
||||
if (slash != strSubnet.npos)
|
||||
{
|
||||
std::string strNetmask = strSubnet.substr(slash + 1);
|
||||
int32_t n;
|
||||
// IPv4 addresses start at offset 12, and first 12 bytes must match, so just offset n
|
||||
const int astartofs = network.IsIPv4() ? 12 : 0;
|
||||
if (ParseInt32(strNetmask, &n)) // If valid number, assume /24 symtex
|
||||
{
|
||||
if(n >= 0 && n <= (128 - astartofs*8)) // Only valid if in range of bits of address
|
||||
{
|
||||
n += astartofs*8;
|
||||
// Clear bits [n..127]
|
||||
for (; n < 128; ++n)
|
||||
netmask[n>>3] &= ~(1<<(7-(n&7)));
|
||||
}
|
||||
else
|
||||
{
|
||||
valid = false;
|
||||
}
|
||||
if (ParseInt32(strNetmask, &n)) { // If valid number, assume /24 syntax
|
||||
ret = CSubNet(network, n);
|
||||
return ret.IsValid();
|
||||
}
|
||||
else // If not a valid number, try full netmask syntax
|
||||
{
|
||||
if (LookupHost(strNetmask.c_str(), vIP, 1, false)) // Never allow lookup for netmask
|
||||
{
|
||||
// Copy only the *last* four bytes in case of IPv4, the rest of the mask should stay 1's as
|
||||
// we don't want pchIPv4 to be part of the mask.
|
||||
for(int x=astartofs; x<16; ++x)
|
||||
netmask[x] = vIP[0].ip[x];
|
||||
}
|
||||
else
|
||||
{
|
||||
valid = false;
|
||||
// Never allow lookup for netmask
|
||||
if (LookupHost(strNetmask.c_str(), vIP, 1, false)) {
|
||||
ret = CSubNet(network, vIP[0]);
|
||||
return ret.IsValid();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
valid = false;
|
||||
}
|
||||
|
||||
// Normalize network according to netmask
|
||||
for(int x=0; x<16; ++x)
|
||||
network.ip[x] &= netmask[x];
|
||||
}
|
||||
|
||||
CSubNet::CSubNet(const CNetAddr &addr):
|
||||
valid(addr.IsValid())
|
||||
{
|
||||
memset(netmask, 255, sizeof(netmask));
|
||||
network = addr;
|
||||
}
|
||||
|
||||
bool CSubNet::Match(const CNetAddr &addr) const
|
||||
{
|
||||
if (!valid || !addr.IsValid())
|
||||
return false;
|
||||
for(int x=0; x<16; ++x)
|
||||
if ((addr.ip[x] & netmask[x]) != network.ip[x])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline int NetmaskBits(uint8_t x)
|
||||
{
|
||||
switch(x) {
|
||||
case 0x00: return 0; break;
|
||||
case 0x80: return 1; break;
|
||||
case 0xc0: return 2; break;
|
||||
case 0xe0: return 3; break;
|
||||
case 0xf0: return 4; break;
|
||||
case 0xf8: return 5; break;
|
||||
case 0xfc: return 6; break;
|
||||
case 0xfe: return 7; break;
|
||||
case 0xff: return 8; break;
|
||||
default: return -1; break;
|
||||
}
|
||||
}
|
||||
|
||||
std::string CSubNet::ToString() const
|
||||
{
|
||||
/* Parse binary 1{n}0{N-n} to see if mask can be represented as /n */
|
||||
int cidr = 0;
|
||||
bool valid_cidr = true;
|
||||
int n = network.IsIPv4() ? 12 : 0;
|
||||
for (; n < 16 && netmask[n] == 0xff; ++n)
|
||||
cidr += 8;
|
||||
if (n < 16) {
|
||||
int bits = NetmaskBits(netmask[n]);
|
||||
if (bits < 0)
|
||||
valid_cidr = false;
|
||||
else
|
||||
cidr += bits;
|
||||
++n;
|
||||
{
|
||||
ret = CSubNet(network);
|
||||
return ret.IsValid();
|
||||
}
|
||||
}
|
||||
for (; n < 16 && valid_cidr; ++n)
|
||||
if (netmask[n] != 0x00)
|
||||
valid_cidr = false;
|
||||
|
||||
/* Format output */
|
||||
std::string strNetmask;
|
||||
if (valid_cidr) {
|
||||
strNetmask = strprintf("%u", cidr);
|
||||
} else {
|
||||
if (network.IsIPv4())
|
||||
strNetmask = strprintf("%u.%u.%u.%u", netmask[12], netmask[13], netmask[14], netmask[15]);
|
||||
else
|
||||
strNetmask = strprintf("%x:%x:%x:%x:%x:%x:%x:%x",
|
||||
netmask[0] << 8 | netmask[1], netmask[2] << 8 | netmask[3],
|
||||
netmask[4] << 8 | netmask[5], netmask[6] << 8 | netmask[7],
|
||||
netmask[8] << 8 | netmask[9], netmask[10] << 8 | netmask[11],
|
||||
netmask[12] << 8 | netmask[13], netmask[14] << 8 | netmask[15]);
|
||||
}
|
||||
|
||||
return network.ToString() + "/" + strNetmask;
|
||||
}
|
||||
|
||||
bool CSubNet::IsValid() const
|
||||
{
|
||||
return valid;
|
||||
}
|
||||
|
||||
bool operator==(const CSubNet& a, const CSubNet& b)
|
||||
{
|
||||
return a.valid == b.valid && a.network == b.network && !memcmp(a.netmask, b.netmask, 16);
|
||||
}
|
||||
|
||||
bool operator!=(const CSubNet& a, const CSubNet& b)
|
||||
{
|
||||
return !(a==b);
|
||||
}
|
||||
|
||||
bool operator<(const CSubNet& a, const CSubNet& b)
|
||||
{
|
||||
return (a.network < b.network || (a.network == b.network && memcmp(a.netmask, b.netmask, 16) < 0));
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
|
167
src/netbase.h
167
src/netbase.h
@ -10,6 +10,7 @@
|
||||
#endif
|
||||
|
||||
#include "compat.h"
|
||||
#include "netaddress.h"
|
||||
#include "serialize.h"
|
||||
|
||||
#include <stdint.h>
|
||||
@ -24,168 +25,6 @@ static const int DEFAULT_CONNECT_TIMEOUT = 5000;
|
||||
//! -dns default
|
||||
static const int DEFAULT_NAME_LOOKUP = true;
|
||||
|
||||
#ifdef WIN32
|
||||
// In MSVC, this is defined as a macro, undefine it to prevent a compile and link error
|
||||
#undef SetPort
|
||||
#endif
|
||||
|
||||
enum Network
|
||||
{
|
||||
NET_UNROUTABLE = 0,
|
||||
NET_IPV4,
|
||||
NET_IPV6,
|
||||
NET_TOR,
|
||||
|
||||
NET_MAX,
|
||||
};
|
||||
|
||||
/** IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96)) */
|
||||
class CNetAddr
|
||||
{
|
||||
protected:
|
||||
unsigned char ip[16]; // in network byte order
|
||||
uint32_t scopeId; // for scoped/link-local ipv6 addresses
|
||||
|
||||
public:
|
||||
CNetAddr();
|
||||
CNetAddr(const struct in_addr& ipv4Addr);
|
||||
explicit CNetAddr(const char *pszIp);
|
||||
explicit CNetAddr(const std::string &strIp);
|
||||
void Init();
|
||||
void SetIP(const CNetAddr& ip);
|
||||
|
||||
/**
|
||||
* Set raw IPv4 or IPv6 address (in network byte order)
|
||||
* @note Only NET_IPV4 and NET_IPV6 are allowed for network.
|
||||
*/
|
||||
void SetRaw(Network network, const uint8_t *data);
|
||||
|
||||
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)
|
||||
bool IsRFC1918() const; // IPv4 private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12)
|
||||
bool IsRFC2544() const; // IPv4 inter-network communcations (192.18.0.0/15)
|
||||
bool IsRFC6598() const; // IPv4 ISP-level NAT (100.64.0.0/10)
|
||||
bool IsRFC5737() const; // IPv4 documentation addresses (192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24)
|
||||
bool IsRFC3849() const; // IPv6 documentation address (2001:0DB8::/32)
|
||||
bool IsRFC3927() const; // IPv4 autoconfig (169.254.0.0/16)
|
||||
bool IsRFC3964() const; // IPv6 6to4 tunnelling (2002::/16)
|
||||
bool IsRFC4193() const; // IPv6 unique local (FC00::/7)
|
||||
bool IsRFC4380() const; // IPv6 Teredo tunnelling (2001::/32)
|
||||
bool IsRFC4843() const; // IPv6 ORCHID (2001:10::/28)
|
||||
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 IsTor() const;
|
||||
bool IsLocal() const;
|
||||
bool IsRoutable() const;
|
||||
bool IsValid() const;
|
||||
bool IsMulticast() const;
|
||||
enum Network GetNetwork() const;
|
||||
std::string ToString() const;
|
||||
std::string ToStringIP() const;
|
||||
unsigned int GetByte(int n) const;
|
||||
uint64_t GetHash() const;
|
||||
bool GetInAddr(struct in_addr* pipv4Addr) const;
|
||||
std::vector<unsigned char> GetGroup() const;
|
||||
int GetReachabilityFrom(const CNetAddr *paddrPartner = NULL) const;
|
||||
|
||||
CNetAddr(const struct in6_addr& pipv6Addr, const uint32_t scope = 0);
|
||||
bool GetIn6Addr(struct in6_addr* pipv6Addr) const;
|
||||
|
||||
friend bool operator==(const CNetAddr& a, const CNetAddr& b);
|
||||
friend bool operator!=(const CNetAddr& a, const CNetAddr& b);
|
||||
friend bool operator<(const CNetAddr& a, const CNetAddr& b);
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
READWRITE(FLATDATA(ip));
|
||||
}
|
||||
|
||||
friend class CSubNet;
|
||||
};
|
||||
|
||||
class CSubNet
|
||||
{
|
||||
protected:
|
||||
/// Network (base) address
|
||||
CNetAddr network;
|
||||
/// Netmask, in network byte order
|
||||
uint8_t netmask[16];
|
||||
/// Is this value valid? (only used to signal parse errors)
|
||||
bool valid;
|
||||
|
||||
public:
|
||||
CSubNet();
|
||||
explicit CSubNet(const std::string &strSubnet);
|
||||
|
||||
//constructor for single ip subnet (<ipv4>/32 or <ipv6>/128)
|
||||
explicit CSubNet(const CNetAddr &addr);
|
||||
|
||||
bool Match(const CNetAddr &addr) const;
|
||||
|
||||
std::string ToString() const;
|
||||
bool IsValid() const;
|
||||
|
||||
friend bool operator==(const CSubNet& a, const CSubNet& b);
|
||||
friend bool operator!=(const CSubNet& a, const CSubNet& b);
|
||||
friend bool operator<(const CSubNet& a, const CSubNet& b);
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
READWRITE(network);
|
||||
READWRITE(FLATDATA(netmask));
|
||||
READWRITE(FLATDATA(valid));
|
||||
}
|
||||
};
|
||||
|
||||
/** A combination of a network address (CNetAddr) and a (TCP) port */
|
||||
class CService : public CNetAddr
|
||||
{
|
||||
protected:
|
||||
unsigned short port; // host order
|
||||
|
||||
public:
|
||||
CService();
|
||||
CService(const CNetAddr& ip, unsigned short port);
|
||||
CService(const struct in_addr& ipv4Addr, unsigned short port);
|
||||
CService(const struct sockaddr_in& addr);
|
||||
explicit CService(const char *pszIpPort, int portDefault);
|
||||
explicit CService(const char *pszIpPort);
|
||||
explicit CService(const std::string& strIpPort, int portDefault);
|
||||
explicit CService(const std::string& strIpPort);
|
||||
void Init();
|
||||
void SetPort(unsigned short portIn);
|
||||
unsigned short GetPort() const;
|
||||
bool GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const;
|
||||
bool SetSockAddr(const struct sockaddr* paddr);
|
||||
friend bool operator==(const CService& a, const CService& b);
|
||||
friend bool operator!=(const CService& a, const CService& b);
|
||||
friend bool operator<(const CService& a, const CService& b);
|
||||
std::vector<unsigned char> GetKey() const;
|
||||
std::string ToString() const;
|
||||
std::string ToStringPort() const;
|
||||
std::string ToStringIPPort() const;
|
||||
|
||||
CService(const struct in6_addr& ipv6Addr, unsigned short port);
|
||||
CService(const struct sockaddr_in6& addr);
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
READWRITE(FLATDATA(ip));
|
||||
unsigned short portN = htons(port);
|
||||
READWRITE(FLATDATA(portN));
|
||||
if (ser_action.ForRead())
|
||||
port = ntohs(portN);
|
||||
}
|
||||
};
|
||||
|
||||
class proxyType
|
||||
{
|
||||
public:
|
||||
@ -207,9 +46,11 @@ bool IsProxy(const CNetAddr &addr);
|
||||
bool SetNameProxy(const proxyType &addrProxy);
|
||||
bool HaveNameProxy();
|
||||
bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup);
|
||||
bool LookupHost(const char *pszName, CNetAddr& addr, bool fAllowLookup);
|
||||
bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLookup);
|
||||
bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions);
|
||||
bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0);
|
||||
CService LookupNumeric(const char *pszName, int portDefault = 0);
|
||||
bool LookupSubNet(const char *pszName, CSubNet& subnet);
|
||||
bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed = 0);
|
||||
bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout, bool *outProxyConnectionFailed = 0);
|
||||
/** Return readable error string for a network error code */
|
||||
|
@ -10,7 +10,7 @@
|
||||
#ifndef BITCOIN_PROTOCOL_H
|
||||
#define BITCOIN_PROTOCOL_H
|
||||
|
||||
#include "netbase.h"
|
||||
#include "netaddress.h"
|
||||
#include "serialize.h"
|
||||
#include "uint256.h"
|
||||
#include "version.h"
|
||||
|
@ -327,7 +327,8 @@ QValidator::State ProxyAddressValidator::validate(QString &input, int &pos) cons
|
||||
{
|
||||
Q_UNUSED(pos);
|
||||
// Validate the proxy
|
||||
proxyType addrProxy = proxyType(CService(input.toStdString(), 9050), true);
|
||||
CService serv(LookupNumeric(input.toStdString().c_str(), 9050));
|
||||
proxyType addrProxy = proxyType(serv, true);
|
||||
if (addrProxy.IsValid())
|
||||
return QValidator::Acceptable;
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "init.h"
|
||||
#include "main.h" // For DEFAULT_SCRIPTCHECK_THREADS
|
||||
#include "net.h"
|
||||
#include "netbase.h"
|
||||
#include "txdb.h" // for -dbcache defaults
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "bantablemodel.h"
|
||||
|
||||
#include "chainparams.h"
|
||||
#include "netbase.h"
|
||||
#include "rpc/server.h"
|
||||
#include "rpc/client.h"
|
||||
#include "util.h"
|
||||
@ -898,7 +899,10 @@ void RPCConsole::banSelectedNode(int bantime)
|
||||
int port = 0;
|
||||
SplitHostPort(nStr, port, addr);
|
||||
|
||||
CNode::Ban(CNetAddr(addr), BanReasonManuallyAdded, bantime);
|
||||
CNetAddr resolved;
|
||||
if(!LookupHost(addr.c_str(), resolved, false))
|
||||
return;
|
||||
CNode::Ban(resolved, BanReasonManuallyAdded, bantime);
|
||||
|
||||
clearSelectedNode();
|
||||
clientModel->getBanTableModel()->refresh();
|
||||
@ -912,8 +916,9 @@ void RPCConsole::unbanSelectedNode()
|
||||
|
||||
// Get currently selected ban address
|
||||
QString strNode = GUIUtil::getEntryData(ui->banlistWidget, 0, BanTableModel::Address);
|
||||
CSubNet possibleSubnet(strNode.toStdString());
|
||||
CSubNet possibleSubnet;
|
||||
|
||||
LookupSubNet(strNode.toStdString().c_str(), possibleSubnet);
|
||||
if (possibleSubnet.IsValid())
|
||||
{
|
||||
CNode::Unban(possibleSubnet);
|
||||
|
@ -494,10 +494,13 @@ UniValue setban(const UniValue& params, bool fHelp)
|
||||
if (params[0].get_str().find("/") != string::npos)
|
||||
isSubnet = true;
|
||||
|
||||
if (!isSubnet)
|
||||
netAddr = CNetAddr(params[0].get_str());
|
||||
if (!isSubnet) {
|
||||
CNetAddr resolved;
|
||||
LookupHost(params[0].get_str().c_str(), resolved, false);
|
||||
netAddr = resolved;
|
||||
}
|
||||
else
|
||||
subNet = CSubNet(params[0].get_str());
|
||||
LookupSubNet(params[0].get_str().c_str(), subNet);
|
||||
|
||||
if (! (isSubnet ? subNet.IsValid() : netAddr.IsValid()) )
|
||||
throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Invalid IP/Subnet");
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include "hash.h"
|
||||
#include "netbase.h"
|
||||
#include "random.h"
|
||||
|
||||
using namespace std;
|
||||
@ -50,6 +51,30 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
static CNetAddr ResolveIP(const char* ip)
|
||||
{
|
||||
CNetAddr addr;
|
||||
BOOST_CHECK_MESSAGE(LookupHost(ip, addr, false), strprintf("failed to resolve: %s", ip));
|
||||
return addr;
|
||||
}
|
||||
|
||||
static CNetAddr ResolveIP(std::string ip)
|
||||
{
|
||||
return ResolveIP(ip.c_str());
|
||||
}
|
||||
|
||||
static CService ResolveService(const char* ip, int port = 0)
|
||||
{
|
||||
CService serv;
|
||||
BOOST_CHECK_MESSAGE(Lookup(ip, serv, port, false), strprintf("failed to resolve: %s:%i", ip, port));
|
||||
return serv;
|
||||
}
|
||||
|
||||
static CService ResolveService(std::string ip, int port = 0)
|
||||
{
|
||||
return ResolveService(ip.c_str(), port);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(addrman_tests, BasicTestingSetup)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(addrman_simple)
|
||||
@ -59,7 +84,7 @@ BOOST_AUTO_TEST_CASE(addrman_simple)
|
||||
// Set addrman addr placement to be deterministic.
|
||||
addrman.MakeDeterministic();
|
||||
|
||||
CNetAddr source = CNetAddr("252.2.2.2");
|
||||
CNetAddr source = ResolveIP("252.2.2.2");
|
||||
|
||||
// Test 1: Does Addrman respond correctly when empty.
|
||||
BOOST_CHECK(addrman.size() == 0);
|
||||
@ -67,7 +92,7 @@ BOOST_AUTO_TEST_CASE(addrman_simple)
|
||||
BOOST_CHECK(addr_null.ToString() == "[::]:0");
|
||||
|
||||
// Test 2: Does Addrman::Add work as expected.
|
||||
CService addr1 = CService("250.1.1.1", 8333);
|
||||
CService addr1 = ResolveService("250.1.1.1", 8333);
|
||||
addrman.Add(CAddress(addr1, NODE_NONE), source);
|
||||
BOOST_CHECK(addrman.size() == 1);
|
||||
CAddrInfo addr_ret1 = addrman.Select();
|
||||
@ -75,14 +100,14 @@ BOOST_AUTO_TEST_CASE(addrman_simple)
|
||||
|
||||
// Test 3: Does IP address deduplication work correctly.
|
||||
// Expected dup IP should not be added.
|
||||
CService addr1_dup = CService("250.1.1.1", 8333);
|
||||
CService addr1_dup = ResolveService("250.1.1.1", 8333);
|
||||
addrman.Add(CAddress(addr1_dup, NODE_NONE), source);
|
||||
BOOST_CHECK(addrman.size() == 1);
|
||||
|
||||
|
||||
// Test 5: New table has one addr and we add a diff addr we should
|
||||
// have two addrs.
|
||||
CService addr2 = CService("250.1.1.2", 8333);
|
||||
CService addr2 = ResolveService("250.1.1.2", 8333);
|
||||
addrman.Add(CAddress(addr2, NODE_NONE), source);
|
||||
BOOST_CHECK(addrman.size() == 2);
|
||||
|
||||
@ -100,16 +125,16 @@ BOOST_AUTO_TEST_CASE(addrman_ports)
|
||||
// Set addrman addr placement to be deterministic.
|
||||
addrman.MakeDeterministic();
|
||||
|
||||
CNetAddr source = CNetAddr("252.2.2.2");
|
||||
CNetAddr source = ResolveIP("252.2.2.2");
|
||||
|
||||
BOOST_CHECK(addrman.size() == 0);
|
||||
|
||||
// Test 7; Addr with same IP but diff port does not replace existing addr.
|
||||
CService addr1 = CService("250.1.1.1", 8333);
|
||||
CService addr1 = ResolveService("250.1.1.1", 8333);
|
||||
addrman.Add(CAddress(addr1, NODE_NONE), source);
|
||||
BOOST_CHECK(addrman.size() == 1);
|
||||
|
||||
CService addr1_port = CService("250.1.1.1", 8334);
|
||||
CService addr1_port = ResolveService("250.1.1.1", 8334);
|
||||
addrman.Add(CAddress(addr1_port, NODE_NONE), source);
|
||||
BOOST_CHECK(addrman.size() == 1);
|
||||
CAddrInfo addr_ret2 = addrman.Select();
|
||||
@ -132,10 +157,10 @@ BOOST_AUTO_TEST_CASE(addrman_select)
|
||||
// Set addrman addr placement to be deterministic.
|
||||
addrman.MakeDeterministic();
|
||||
|
||||
CNetAddr source = CNetAddr("252.2.2.2");
|
||||
CNetAddr source = ResolveIP("252.2.2.2");
|
||||
|
||||
// Test 9: Select from new with 1 addr in new.
|
||||
CService addr1 = CService("250.1.1.1", 8333);
|
||||
CService addr1 = ResolveService("250.1.1.1", 8333);
|
||||
addrman.Add(CAddress(addr1, NODE_NONE), source);
|
||||
BOOST_CHECK(addrman.size() == 1);
|
||||
|
||||
@ -156,24 +181,24 @@ BOOST_AUTO_TEST_CASE(addrman_select)
|
||||
|
||||
|
||||
// Add three addresses to new table.
|
||||
CService addr2 = CService("250.3.1.1", 8333);
|
||||
CService addr3 = CService("250.3.2.2", 9999);
|
||||
CService addr4 = CService("250.3.3.3", 9999);
|
||||
CService addr2 = ResolveService("250.3.1.1", 8333);
|
||||
CService addr3 = ResolveService("250.3.2.2", 9999);
|
||||
CService addr4 = ResolveService("250.3.3.3", 9999);
|
||||
|
||||
addrman.Add(CAddress(addr2, NODE_NONE), CService("250.3.1.1", 8333));
|
||||
addrman.Add(CAddress(addr3, NODE_NONE), CService("250.3.1.1", 8333));
|
||||
addrman.Add(CAddress(addr4, NODE_NONE), CService("250.4.1.1", 8333));
|
||||
addrman.Add(CAddress(addr2, NODE_NONE), ResolveService("250.3.1.1", 8333));
|
||||
addrman.Add(CAddress(addr3, NODE_NONE), ResolveService("250.3.1.1", 8333));
|
||||
addrman.Add(CAddress(addr4, NODE_NONE), ResolveService("250.4.1.1", 8333));
|
||||
|
||||
// Add three addresses to tried table.
|
||||
CService addr5 = CService("250.4.4.4", 8333);
|
||||
CService addr6 = CService("250.4.5.5", 7777);
|
||||
CService addr7 = CService("250.4.6.6", 8333);
|
||||
CService addr5 = ResolveService("250.4.4.4", 8333);
|
||||
CService addr6 = ResolveService("250.4.5.5", 7777);
|
||||
CService addr7 = ResolveService("250.4.6.6", 8333);
|
||||
|
||||
addrman.Add(CAddress(addr5, NODE_NONE), CService("250.3.1.1", 8333));
|
||||
addrman.Add(CAddress(addr5, NODE_NONE), ResolveService("250.3.1.1", 8333));
|
||||
addrman.Good(CAddress(addr5, NODE_NONE));
|
||||
addrman.Add(CAddress(addr6, NODE_NONE), CService("250.3.1.1", 8333));
|
||||
addrman.Add(CAddress(addr6, NODE_NONE), ResolveService("250.3.1.1", 8333));
|
||||
addrman.Good(CAddress(addr6, NODE_NONE));
|
||||
addrman.Add(CAddress(addr7, NODE_NONE), CService("250.1.1.3", 8333));
|
||||
addrman.Add(CAddress(addr7, NODE_NONE), ResolveService("250.1.1.3", 8333));
|
||||
addrman.Good(CAddress(addr7, NODE_NONE));
|
||||
|
||||
// Test 11: 6 addrs + 1 addr from last test = 7.
|
||||
@ -193,12 +218,12 @@ BOOST_AUTO_TEST_CASE(addrman_new_collisions)
|
||||
// Set addrman addr placement to be deterministic.
|
||||
addrman.MakeDeterministic();
|
||||
|
||||
CNetAddr source = CNetAddr("252.2.2.2");
|
||||
CNetAddr source = ResolveIP("252.2.2.2");
|
||||
|
||||
BOOST_CHECK(addrman.size() == 0);
|
||||
|
||||
for (unsigned int i = 1; i < 18; i++) {
|
||||
CService addr = CService("250.1.1." + boost::to_string(i));
|
||||
CService addr = ResolveService("250.1.1." + boost::to_string(i));
|
||||
addrman.Add(CAddress(addr, NODE_NONE), source);
|
||||
|
||||
//Test 13: No collision in new table yet.
|
||||
@ -206,11 +231,11 @@ BOOST_AUTO_TEST_CASE(addrman_new_collisions)
|
||||
}
|
||||
|
||||
//Test 14: new table collision!
|
||||
CService addr1 = CService("250.1.1.18");
|
||||
CService addr1 = ResolveService("250.1.1.18");
|
||||
addrman.Add(CAddress(addr1, NODE_NONE), source);
|
||||
BOOST_CHECK(addrman.size() == 17);
|
||||
|
||||
CService addr2 = CService("250.1.1.19");
|
||||
CService addr2 = ResolveService("250.1.1.19");
|
||||
addrman.Add(CAddress(addr2, NODE_NONE), source);
|
||||
BOOST_CHECK(addrman.size() == 18);
|
||||
}
|
||||
@ -222,12 +247,12 @@ BOOST_AUTO_TEST_CASE(addrman_tried_collisions)
|
||||
// Set addrman addr placement to be deterministic.
|
||||
addrman.MakeDeterministic();
|
||||
|
||||
CNetAddr source = CNetAddr("252.2.2.2");
|
||||
CNetAddr source = ResolveIP("252.2.2.2");
|
||||
|
||||
BOOST_CHECK(addrman.size() == 0);
|
||||
|
||||
for (unsigned int i = 1; i < 80; i++) {
|
||||
CService addr = CService("250.1.1." + boost::to_string(i));
|
||||
CService addr = ResolveService("250.1.1." + boost::to_string(i));
|
||||
addrman.Add(CAddress(addr, NODE_NONE), source);
|
||||
addrman.Good(CAddress(addr, NODE_NONE));
|
||||
|
||||
@ -237,11 +262,11 @@ BOOST_AUTO_TEST_CASE(addrman_tried_collisions)
|
||||
}
|
||||
|
||||
//Test 16: tried table collision!
|
||||
CService addr1 = CService("250.1.1.80");
|
||||
CService addr1 = ResolveService("250.1.1.80");
|
||||
addrman.Add(CAddress(addr1, NODE_NONE), source);
|
||||
BOOST_CHECK(addrman.size() == 79);
|
||||
|
||||
CService addr2 = CService("250.1.1.81");
|
||||
CService addr2 = ResolveService("250.1.1.81");
|
||||
addrman.Add(CAddress(addr2, NODE_NONE), source);
|
||||
BOOST_CHECK(addrman.size() == 80);
|
||||
}
|
||||
@ -255,12 +280,12 @@ BOOST_AUTO_TEST_CASE(addrman_find)
|
||||
|
||||
BOOST_CHECK(addrman.size() == 0);
|
||||
|
||||
CAddress addr1 = CAddress(CService("250.1.2.1", 8333), NODE_NONE);
|
||||
CAddress addr2 = CAddress(CService("250.1.2.1", 9999), NODE_NONE);
|
||||
CAddress addr3 = CAddress(CService("251.255.2.1", 8333), NODE_NONE);
|
||||
CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
|
||||
CAddress addr2 = CAddress(ResolveService("250.1.2.1", 9999), NODE_NONE);
|
||||
CAddress addr3 = CAddress(ResolveService("251.255.2.1", 8333), NODE_NONE);
|
||||
|
||||
CNetAddr source1 = CNetAddr("250.1.2.1");
|
||||
CNetAddr source2 = CNetAddr("250.1.2.2");
|
||||
CNetAddr source1 = ResolveIP("250.1.2.1");
|
||||
CNetAddr source2 = ResolveIP("250.1.2.2");
|
||||
|
||||
addrman.Add(addr1, source1);
|
||||
addrman.Add(addr2, source2);
|
||||
@ -294,8 +319,8 @@ BOOST_AUTO_TEST_CASE(addrman_create)
|
||||
|
||||
BOOST_CHECK(addrman.size() == 0);
|
||||
|
||||
CAddress addr1 = CAddress(CService("250.1.2.1", 8333), NODE_NONE);
|
||||
CNetAddr source1 = CNetAddr("250.1.2.1");
|
||||
CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
|
||||
CNetAddr source1 = ResolveIP("250.1.2.1");
|
||||
|
||||
int nId;
|
||||
CAddrInfo* pinfo = addrman.Create(addr1, source1, &nId);
|
||||
@ -317,8 +342,8 @@ BOOST_AUTO_TEST_CASE(addrman_delete)
|
||||
|
||||
BOOST_CHECK(addrman.size() == 0);
|
||||
|
||||
CAddress addr1 = CAddress(CService("250.1.2.1", 8333), NODE_NONE);
|
||||
CNetAddr source1 = CNetAddr("250.1.2.1");
|
||||
CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
|
||||
CNetAddr source1 = ResolveIP("250.1.2.1");
|
||||
|
||||
int nId;
|
||||
addrman.Create(addr1, source1, &nId);
|
||||
@ -344,18 +369,18 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr)
|
||||
vector<CAddress> vAddr1 = addrman.GetAddr();
|
||||
BOOST_CHECK(vAddr1.size() == 0);
|
||||
|
||||
CAddress addr1 = CAddress(CService("250.250.2.1", 8333), NODE_NONE);
|
||||
CAddress addr1 = CAddress(ResolveService("250.250.2.1", 8333), NODE_NONE);
|
||||
addr1.nTime = GetAdjustedTime(); // Set time so isTerrible = false
|
||||
CAddress addr2 = CAddress(CService("250.251.2.2", 9999), NODE_NONE);
|
||||
CAddress addr2 = CAddress(ResolveService("250.251.2.2", 9999), NODE_NONE);
|
||||
addr2.nTime = GetAdjustedTime();
|
||||
CAddress addr3 = CAddress(CService("251.252.2.3", 8333), NODE_NONE);
|
||||
CAddress addr3 = CAddress(ResolveService("251.252.2.3", 8333), NODE_NONE);
|
||||
addr3.nTime = GetAdjustedTime();
|
||||
CAddress addr4 = CAddress(CService("252.253.3.4", 8333), NODE_NONE);
|
||||
CAddress addr4 = CAddress(ResolveService("252.253.3.4", 8333), NODE_NONE);
|
||||
addr4.nTime = GetAdjustedTime();
|
||||
CAddress addr5 = CAddress(CService("252.254.4.5", 8333), NODE_NONE);
|
||||
CAddress addr5 = CAddress(ResolveService("252.254.4.5", 8333), NODE_NONE);
|
||||
addr5.nTime = GetAdjustedTime();
|
||||
CNetAddr source1 = CNetAddr("250.1.2.1");
|
||||
CNetAddr source2 = CNetAddr("250.2.3.3");
|
||||
CNetAddr source1 = ResolveIP("250.1.2.1");
|
||||
CNetAddr source2 = ResolveIP("250.2.3.3");
|
||||
|
||||
// Test 23: Ensure GetAddr works with new addresses.
|
||||
addrman.Add(addr1, source1);
|
||||
@ -378,11 +403,11 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr)
|
||||
int octet2 = (i / 256) % 256;
|
||||
int octet3 = (i / (256 * 2)) % 256;
|
||||
string strAddr = boost::to_string(octet1) + "." + boost::to_string(octet2) + "." + boost::to_string(octet3) + ".23";
|
||||
CAddress addr = CAddress(CService(strAddr), NODE_NONE);
|
||||
CAddress addr = CAddress(ResolveService(strAddr), NODE_NONE);
|
||||
|
||||
// Ensure that for all addrs in addrman, isTerrible == false.
|
||||
addr.nTime = GetAdjustedTime();
|
||||
addrman.Add(addr, CNetAddr(strAddr));
|
||||
addrman.Add(addr, ResolveIP(strAddr));
|
||||
if (i % 8 == 0)
|
||||
addrman.Good(addr);
|
||||
}
|
||||
@ -403,10 +428,10 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket)
|
||||
// Set addrman addr placement to be deterministic.
|
||||
addrman.MakeDeterministic();
|
||||
|
||||
CAddress addr1 = CAddress(CService("250.1.1.1", 8333), NODE_NONE);
|
||||
CAddress addr2 = CAddress(CService("250.1.1.1", 9999), NODE_NONE);
|
||||
CAddress addr1 = CAddress(ResolveService("250.1.1.1", 8333), NODE_NONE);
|
||||
CAddress addr2 = CAddress(ResolveService("250.1.1.1", 9999), NODE_NONE);
|
||||
|
||||
CNetAddr source1 = CNetAddr("250.1.1.1");
|
||||
CNetAddr source1 = ResolveIP("250.1.1.1");
|
||||
|
||||
|
||||
CAddrInfo info1 = CAddrInfo(addr1, source1);
|
||||
@ -431,8 +456,8 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket)
|
||||
set<int> buckets;
|
||||
for (int i = 0; i < 255; i++) {
|
||||
CAddrInfo infoi = CAddrInfo(
|
||||
CAddress(CService("250.1.1." + boost::to_string(i)), NODE_NONE),
|
||||
CNetAddr("250.1.1." + boost::to_string(i)));
|
||||
CAddress(ResolveService("250.1.1." + boost::to_string(i)), NODE_NONE),
|
||||
ResolveIP("250.1.1." + boost::to_string(i)));
|
||||
int bucket = infoi.GetTriedBucket(nKey1);
|
||||
buckets.insert(bucket);
|
||||
}
|
||||
@ -443,8 +468,8 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket)
|
||||
buckets.clear();
|
||||
for (int j = 0; j < 255; j++) {
|
||||
CAddrInfo infoj = CAddrInfo(
|
||||
CAddress(CService("250." + boost::to_string(j) + ".1.1"), NODE_NONE),
|
||||
CNetAddr("250." + boost::to_string(j) + ".1.1"));
|
||||
CAddress(ResolveService("250." + boost::to_string(j) + ".1.1"), NODE_NONE),
|
||||
ResolveIP("250." + boost::to_string(j) + ".1.1"));
|
||||
int bucket = infoj.GetTriedBucket(nKey1);
|
||||
buckets.insert(bucket);
|
||||
}
|
||||
@ -460,10 +485,10 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket)
|
||||
// Set addrman addr placement to be deterministic.
|
||||
addrman.MakeDeterministic();
|
||||
|
||||
CAddress addr1 = CAddress(CService("250.1.2.1", 8333), NODE_NONE);
|
||||
CAddress addr2 = CAddress(CService("250.1.2.1", 9999), NODE_NONE);
|
||||
CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
|
||||
CAddress addr2 = CAddress(ResolveService("250.1.2.1", 9999), NODE_NONE);
|
||||
|
||||
CNetAddr source1 = CNetAddr("250.1.2.1");
|
||||
CNetAddr source1 = ResolveIP("250.1.2.1");
|
||||
|
||||
CAddrInfo info1 = CAddrInfo(addr1, source1);
|
||||
|
||||
@ -484,8 +509,8 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket)
|
||||
set<int> buckets;
|
||||
for (int i = 0; i < 255; i++) {
|
||||
CAddrInfo infoi = CAddrInfo(
|
||||
CAddress(CService("250.1.1." + boost::to_string(i)), NODE_NONE),
|
||||
CNetAddr("250.1.1." + boost::to_string(i)));
|
||||
CAddress(ResolveService("250.1.1." + boost::to_string(i)), NODE_NONE),
|
||||
ResolveIP("250.1.1." + boost::to_string(i)));
|
||||
int bucket = infoi.GetNewBucket(nKey1);
|
||||
buckets.insert(bucket);
|
||||
}
|
||||
@ -496,9 +521,9 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket)
|
||||
buckets.clear();
|
||||
for (int j = 0; j < 4 * 255; j++) {
|
||||
CAddrInfo infoj = CAddrInfo(CAddress(
|
||||
CService(
|
||||
ResolveService(
|
||||
boost::to_string(250 + (j / 255)) + "." + boost::to_string(j % 256) + ".1.1"), NODE_NONE),
|
||||
CNetAddr("251.4.1.1"));
|
||||
ResolveIP("251.4.1.1"));
|
||||
int bucket = infoj.GetNewBucket(nKey1);
|
||||
buckets.insert(bucket);
|
||||
}
|
||||
@ -509,8 +534,8 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket)
|
||||
buckets.clear();
|
||||
for (int p = 0; p < 255; p++) {
|
||||
CAddrInfo infoj = CAddrInfo(
|
||||
CAddress(CService("250.1.1.1"), NODE_NONE),
|
||||
CNetAddr("250." + boost::to_string(p) + ".1.1"));
|
||||
CAddress(ResolveService("250.1.1.1"), NODE_NONE),
|
||||
ResolveIP("250." + boost::to_string(p) + ".1.1"));
|
||||
int bucket = infoj.GetNewBucket(nKey1);
|
||||
buckets.insert(bucket);
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "serialize.h"
|
||||
#include "streams.h"
|
||||
#include "net.h"
|
||||
#include "netbase.h"
|
||||
#include "chainparams.h"
|
||||
|
||||
using namespace std;
|
||||
@ -51,8 +52,12 @@ public:
|
||||
int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30);
|
||||
s << nUBuckets;
|
||||
|
||||
CAddress addr = CAddress(CService("252.1.1.1", 7777), NODE_NONE);
|
||||
CAddrInfo info = CAddrInfo(addr, CNetAddr("252.2.2.2"));
|
||||
CService serv;
|
||||
Lookup("252.1.1.1", serv, 7777, false);
|
||||
CAddress addr = CAddress(serv, NODE_NONE);
|
||||
CNetAddr resolved;
|
||||
LookupHost("252.2.2.2", resolved, false);
|
||||
CAddrInfo info = CAddrInfo(addr, resolved);
|
||||
s << info;
|
||||
}
|
||||
};
|
||||
@ -74,14 +79,17 @@ BOOST_AUTO_TEST_CASE(caddrdb_read)
|
||||
CAddrManUncorrupted addrmanUncorrupted;
|
||||
addrmanUncorrupted.MakeDeterministic();
|
||||
|
||||
CService addr1 = CService("250.7.1.1", 8333);
|
||||
CService addr2 = CService("250.7.2.2", 9999);
|
||||
CService addr3 = CService("250.7.3.3", 9999);
|
||||
CService addr1, addr2, addr3;
|
||||
Lookup("250.7.1.1", addr1, 8333, false);
|
||||
Lookup("250.7.2.2", addr2, 9999, false);
|
||||
Lookup("250.7.3.3", addr3, 9999, false);
|
||||
|
||||
// Add three addresses to new table.
|
||||
addrmanUncorrupted.Add(CAddress(addr1, NODE_NONE), CService("252.5.1.1", 8333));
|
||||
addrmanUncorrupted.Add(CAddress(addr2, NODE_NONE), CService("252.5.1.1", 8333));
|
||||
addrmanUncorrupted.Add(CAddress(addr3, NODE_NONE), CService("252.5.1.1", 8333));
|
||||
CService source;
|
||||
Lookup("252.5.1.1", source, 8333, false);
|
||||
addrmanUncorrupted.Add(CAddress(addr1, NODE_NONE), source);
|
||||
addrmanUncorrupted.Add(CAddress(addr2, NODE_NONE), source);
|
||||
addrmanUncorrupted.Add(CAddress(addr3, NODE_NONE), source);
|
||||
|
||||
// Test that the de-serialization does not throw an exception.
|
||||
CDataStream ssPeers1 = AddrmanToStream(addrmanUncorrupted);
|
||||
|
@ -14,37 +14,54 @@ using namespace std;
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(netbase_tests, BasicTestingSetup)
|
||||
|
||||
static CNetAddr ResolveIP(const char* ip)
|
||||
{
|
||||
CNetAddr addr;
|
||||
LookupHost(ip, addr, false);
|
||||
return addr;
|
||||
}
|
||||
|
||||
static CSubNet ResolveSubNet(const char* subnet)
|
||||
{
|
||||
CSubNet ret;
|
||||
LookupSubNet(subnet, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(netbase_networks)
|
||||
{
|
||||
BOOST_CHECK(CNetAddr("127.0.0.1").GetNetwork() == NET_UNROUTABLE);
|
||||
BOOST_CHECK(CNetAddr("::1").GetNetwork() == NET_UNROUTABLE);
|
||||
BOOST_CHECK(CNetAddr("8.8.8.8").GetNetwork() == NET_IPV4);
|
||||
BOOST_CHECK(CNetAddr("2001::8888").GetNetwork() == NET_IPV6);
|
||||
BOOST_CHECK(CNetAddr("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetNetwork() == NET_TOR);
|
||||
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_TOR);
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(netbase_properties)
|
||||
{
|
||||
BOOST_CHECK(CNetAddr("127.0.0.1").IsIPv4());
|
||||
BOOST_CHECK(CNetAddr("::FFFF:192.168.1.1").IsIPv4());
|
||||
BOOST_CHECK(CNetAddr("::1").IsIPv6());
|
||||
BOOST_CHECK(CNetAddr("10.0.0.1").IsRFC1918());
|
||||
BOOST_CHECK(CNetAddr("192.168.1.1").IsRFC1918());
|
||||
BOOST_CHECK(CNetAddr("172.31.255.255").IsRFC1918());
|
||||
BOOST_CHECK(CNetAddr("2001:0DB8::").IsRFC3849());
|
||||
BOOST_CHECK(CNetAddr("169.254.1.1").IsRFC3927());
|
||||
BOOST_CHECK(CNetAddr("2002::1").IsRFC3964());
|
||||
BOOST_CHECK(CNetAddr("FC00::").IsRFC4193());
|
||||
BOOST_CHECK(CNetAddr("2001::2").IsRFC4380());
|
||||
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").IsTor());
|
||||
BOOST_CHECK(CNetAddr("127.0.0.1").IsLocal());
|
||||
BOOST_CHECK(CNetAddr("::1").IsLocal());
|
||||
BOOST_CHECK(CNetAddr("8.8.8.8").IsRoutable());
|
||||
BOOST_CHECK(CNetAddr("2001::1").IsRoutable());
|
||||
BOOST_CHECK(CNetAddr("127.0.0.1").IsValid());
|
||||
|
||||
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("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("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());
|
||||
|
||||
}
|
||||
|
||||
bool static TestSplitHost(string test, string host, int port)
|
||||
@ -76,9 +93,7 @@ BOOST_AUTO_TEST_CASE(netbase_splithost)
|
||||
|
||||
bool static TestParse(string src, string canon)
|
||||
{
|
||||
CService addr;
|
||||
if (!LookupNumeric(src.c_str(), addr, 65535))
|
||||
return canon == "";
|
||||
CService addr(LookupNumeric(src.c_str(), 65535));
|
||||
return canon == addr.ToString();
|
||||
}
|
||||
|
||||
@ -90,165 +105,185 @@ BOOST_AUTO_TEST_CASE(netbase_lookupnumeric)
|
||||
BOOST_CHECK(TestParse("::", "[::]:65535"));
|
||||
BOOST_CHECK(TestParse("[::]:8333", "[::]:8333"));
|
||||
BOOST_CHECK(TestParse("[127.0.0.1]", "127.0.0.1:65535"));
|
||||
BOOST_CHECK(TestParse(":::", ""));
|
||||
BOOST_CHECK(TestParse(":::", "[::]:0"));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(onioncat_test)
|
||||
{
|
||||
|
||||
// values from https://web.archive.org/web/20121122003543/http://www.cypherpunk.at/onioncat/wiki/OnionCat
|
||||
CNetAddr addr1("5wyqrzbvrdsumnok.onion");
|
||||
CNetAddr addr2("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca");
|
||||
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(subnet_test)
|
||||
{
|
||||
BOOST_CHECK(CSubNet("1.2.3.0/24") == CSubNet("1.2.3.0/255.255.255.0"));
|
||||
BOOST_CHECK(CSubNet("1.2.3.0/24") != CSubNet("1.2.4.0/255.255.255.0"));
|
||||
BOOST_CHECK(CSubNet("1.2.3.0/24").Match(CNetAddr("1.2.3.4")));
|
||||
BOOST_CHECK(!CSubNet("1.2.2.0/24").Match(CNetAddr("1.2.3.4")));
|
||||
BOOST_CHECK(CSubNet("1.2.3.4").Match(CNetAddr("1.2.3.4")));
|
||||
BOOST_CHECK(CSubNet("1.2.3.4/32").Match(CNetAddr("1.2.3.4")));
|
||||
BOOST_CHECK(!CSubNet("1.2.3.4").Match(CNetAddr("5.6.7.8")));
|
||||
BOOST_CHECK(!CSubNet("1.2.3.4/32").Match(CNetAddr("5.6.7.8")));
|
||||
BOOST_CHECK(CSubNet("::ffff:127.0.0.1").Match(CNetAddr("127.0.0.1")));
|
||||
BOOST_CHECK(CSubNet("1:2:3:4:5:6:7:8").Match(CNetAddr("1:2:3:4:5:6:7:8")));
|
||||
BOOST_CHECK(!CSubNet("1:2:3:4:5:6:7:8").Match(CNetAddr("1:2:3:4:5:6:7:9")));
|
||||
BOOST_CHECK(CSubNet("1:2:3:4:5:6:7:0/112").Match(CNetAddr("1:2:3:4:5:6:7:1234")));
|
||||
BOOST_CHECK(CSubNet("192.168.0.1/24").Match(CNetAddr("192.168.0.2")));
|
||||
BOOST_CHECK(CSubNet("192.168.0.20/29").Match(CNetAddr("192.168.0.18")));
|
||||
BOOST_CHECK(CSubNet("1.2.2.1/24").Match(CNetAddr("1.2.2.4")));
|
||||
BOOST_CHECK(CSubNet("1.2.2.110/31").Match(CNetAddr("1.2.2.111")));
|
||||
BOOST_CHECK(CSubNet("1.2.2.20/26").Match(CNetAddr("1.2.2.63")));
|
||||
|
||||
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 IPv4 and IPv6
|
||||
BOOST_CHECK(CSubNet("::/0").Match(CNetAddr("1:2:3:4:5:6:7:1234")));
|
||||
BOOST_CHECK(CSubNet("::/0").Match(CNetAddr("1.2.3.4")));
|
||||
BOOST_CHECK(ResolveSubNet("::/0").Match(ResolveIP("1:2:3:4:5:6:7:1234")));
|
||||
BOOST_CHECK(ResolveSubNet("::/0").Match(ResolveIP("1.2.3.4")));
|
||||
// All-Matching IPv4 does not Match IPv6
|
||||
BOOST_CHECK(!CSubNet("0.0.0.0/0").Match(CNetAddr("1:2:3:4:5:6:7:1234")));
|
||||
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(CNetAddr("1.2.3.4")));
|
||||
BOOST_CHECK(!CSubNet("").Match(CNetAddr("4.5.6.7")));
|
||||
BOOST_CHECK(!CSubNet("bloop").Match(CNetAddr("0.0.0.0")));
|
||||
BOOST_CHECK(!CSubNet("bloop").Match(CNetAddr("hab")));
|
||||
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(CSubNet("1.2.3.0/0").IsValid());
|
||||
BOOST_CHECK(!CSubNet("1.2.3.0/-1").IsValid());
|
||||
BOOST_CHECK(CSubNet("1.2.3.0/32").IsValid());
|
||||
BOOST_CHECK(!CSubNet("1.2.3.0/33").IsValid());
|
||||
BOOST_CHECK(CSubNet("1:2:3:4:5:6:7:8/0").IsValid());
|
||||
BOOST_CHECK(CSubNet("1:2:3:4:5:6:7:8/33").IsValid());
|
||||
BOOST_CHECK(!CSubNet("1:2:3:4:5:6:7:8/-1").IsValid());
|
||||
BOOST_CHECK(CSubNet("1:2:3:4:5:6:7:8/128").IsValid());
|
||||
BOOST_CHECK(!CSubNet("1:2:3:4:5:6:7:8/129").IsValid());
|
||||
BOOST_CHECK(!CSubNet("fuzzy").IsValid());
|
||||
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(CNetAddr("127.0.0.1")).IsValid());
|
||||
BOOST_CHECK(CSubNet(CNetAddr("127.0.0.1")).Match(CNetAddr("127.0.0.1")));
|
||||
BOOST_CHECK(!CSubNet(CNetAddr("127.0.0.1")).Match(CNetAddr("127.0.0.2")));
|
||||
BOOST_CHECK(CSubNet(CNetAddr("127.0.0.1")).ToString() == "127.0.0.1/32");
|
||||
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");
|
||||
|
||||
BOOST_CHECK(CSubNet(CNetAddr("1:2:3:4:5:6:7:8")).IsValid());
|
||||
BOOST_CHECK(CSubNet(CNetAddr("1:2:3:4:5:6:7:8")).Match(CNetAddr("1:2:3:4:5:6:7:8")));
|
||||
BOOST_CHECK(!CSubNet(CNetAddr("1:2:3:4:5:6:7:8")).Match(CNetAddr("1:2:3:4:5:6:7:9")));
|
||||
BOOST_CHECK(CSubNet(CNetAddr("1:2:3:4:5:6:7:8")).ToString() == "1:2:3:4:5:6:7:8/128");
|
||||
|
||||
CSubNet subnet = CSubNet("1.2.3.4/255.255.255.255");
|
||||
CSubNet subnet = CSubNet(ResolveIP("1.2.3.4"), 32);
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/32");
|
||||
subnet = CSubNet("1.2.3.4/255.255.255.254");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/31");
|
||||
subnet = CSubNet("1.2.3.4/255.255.255.252");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/30");
|
||||
subnet = CSubNet("1.2.3.4/255.255.255.248");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/29");
|
||||
subnet = CSubNet("1.2.3.4/255.255.255.240");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/28");
|
||||
subnet = CSubNet("1.2.3.4/255.255.255.224");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/27");
|
||||
subnet = CSubNet("1.2.3.4/255.255.255.192");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/26");
|
||||
subnet = CSubNet("1.2.3.4/255.255.255.128");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/25");
|
||||
subnet = CSubNet("1.2.3.4/255.255.255.0");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/24");
|
||||
subnet = CSubNet("1.2.3.4/255.255.254.0");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.2.0/23");
|
||||
subnet = CSubNet("1.2.3.4/255.255.252.0");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/22");
|
||||
subnet = CSubNet("1.2.3.4/255.255.248.0");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/21");
|
||||
subnet = CSubNet("1.2.3.4/255.255.240.0");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/20");
|
||||
subnet = CSubNet("1.2.3.4/255.255.224.0");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/19");
|
||||
subnet = CSubNet("1.2.3.4/255.255.192.0");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/18");
|
||||
subnet = CSubNet("1.2.3.4/255.255.128.0");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/17");
|
||||
subnet = CSubNet("1.2.3.4/255.255.0.0");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/16");
|
||||
subnet = CSubNet("1.2.3.4/255.254.0.0");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/15");
|
||||
subnet = CSubNet("1.2.3.4/255.252.0.0");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/14");
|
||||
subnet = CSubNet("1.2.3.4/255.248.0.0");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/13");
|
||||
subnet = CSubNet("1.2.3.4/255.240.0.0");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/12");
|
||||
subnet = CSubNet("1.2.3.4/255.224.0.0");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/11");
|
||||
subnet = CSubNet("1.2.3.4/255.192.0.0");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/10");
|
||||
subnet = CSubNet("1.2.3.4/255.128.0.0");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/9");
|
||||
subnet = CSubNet("1.2.3.4/255.0.0.0");
|
||||
subnet = CSubNet(ResolveIP("1.2.3.4"), 8);
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/8");
|
||||
subnet = CSubNet("1.2.3.4/254.0.0.0");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/7");
|
||||
subnet = CSubNet("1.2.3.4/252.0.0.0");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/6");
|
||||
subnet = CSubNet("1.2.3.4/248.0.0.0");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/5");
|
||||
subnet = CSubNet("1.2.3.4/240.0.0.0");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/4");
|
||||
subnet = CSubNet("1.2.3.4/224.0.0.0");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/3");
|
||||
subnet = CSubNet("1.2.3.4/192.0.0.0");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/2");
|
||||
subnet = CSubNet("1.2.3.4/128.0.0.0");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/1");
|
||||
subnet = CSubNet("1.2.3.4/0.0.0.0");
|
||||
subnet = CSubNet(ResolveIP("1.2.3.4"), 0);
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/0");
|
||||
|
||||
subnet = CSubNet("1:2:3:4:5:6:7:8/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
|
||||
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 = CSubNet("1:2:3:4:5:6:7:8/ffff:0000:0000:0000:0000:0000:0000:0000");
|
||||
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 = CSubNet("1:2:3:4:5:6:7:8/0000:0000:0000:0000:0000:0000:0000:0000");
|
||||
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 = CSubNet("1.2.3.4/255.255.232.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 = CSubNet("1:2:3:4:5:6:7:8/ffff:ffff:ffff:fffe:ffff:ffff:ffff:ff0f");
|
||||
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)
|
||||
{
|
||||
BOOST_CHECK(CNetAddr("127.0.0.1").GetGroup() == boost::assign::list_of(0)); // Local -> !Routable()
|
||||
BOOST_CHECK(CNetAddr("257.0.0.1").GetGroup() == boost::assign::list_of(0)); // !Valid -> !Routable()
|
||||
BOOST_CHECK(CNetAddr("10.0.0.1").GetGroup() == boost::assign::list_of(0)); // RFC1918 -> !Routable()
|
||||
BOOST_CHECK(CNetAddr("169.254.1.1").GetGroup() == boost::assign::list_of(0)); // RFC3927 -> !Routable()
|
||||
BOOST_CHECK(CNetAddr("1.2.3.4").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // IPv4
|
||||
BOOST_CHECK(CNetAddr("::FFFF:0:102:304").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC6145
|
||||
BOOST_CHECK(CNetAddr("64:FF9B::102:304").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC6052
|
||||
BOOST_CHECK(CNetAddr("2002:102:304:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC3964
|
||||
BOOST_CHECK(CNetAddr("2001:0:9999:9999:9999:9999:FEFD:FCFB").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC4380
|
||||
BOOST_CHECK(CNetAddr("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetGroup() == boost::assign::list_of((unsigned char)NET_TOR)(239)); // Tor
|
||||
BOOST_CHECK(CNetAddr("2001:470:abcd:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV6)(32)(1)(4)(112)(175)); //he.net
|
||||
BOOST_CHECK(CNetAddr("2001:2001:9999:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV6)(32)(1)(32)(1)); //IPv6
|
||||
|
||||
BOOST_CHECK(ResolveIP("127.0.0.1").GetGroup() == boost::assign::list_of(0)); // Local -> !Routable()
|
||||
BOOST_CHECK(ResolveIP("257.0.0.1").GetGroup() == boost::assign::list_of(0)); // !Valid -> !Routable()
|
||||
BOOST_CHECK(ResolveIP("10.0.0.1").GetGroup() == boost::assign::list_of(0)); // RFC1918 -> !Routable()
|
||||
BOOST_CHECK(ResolveIP("169.254.1.1").GetGroup() == boost::assign::list_of(0)); // RFC3927 -> !Routable()
|
||||
BOOST_CHECK(ResolveIP("1.2.3.4").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // IPv4
|
||||
BOOST_CHECK(ResolveIP("::FFFF:0:102:304").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC6145
|
||||
BOOST_CHECK(ResolveIP("64:FF9B::102:304").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC6052
|
||||
BOOST_CHECK(ResolveIP("2002:102:304:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC3964
|
||||
BOOST_CHECK(ResolveIP("2001:0:9999:9999:9999:9999:FEFD:FCFB").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC4380
|
||||
BOOST_CHECK(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetGroup() == boost::assign::list_of((unsigned char)NET_TOR)(239)); // Tor
|
||||
BOOST_CHECK(ResolveIP("2001:470:abcd:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV6)(32)(1)(4)(112)(175)); //he.net
|
||||
BOOST_CHECK(ResolveIP("2001:2001:9999:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV6)(32)(1)(32)(1)); //IPv6
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
#include "timedata.h"
|
||||
|
||||
#include "netbase.h"
|
||||
#include "netaddress.h"
|
||||
#include "sync.h"
|
||||
#include "ui_interface.h"
|
||||
#include "util.h"
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "torcontrol.h"
|
||||
#include "utilstrencodings.h"
|
||||
#include "netbase.h"
|
||||
#include "net.h"
|
||||
#include "util.h"
|
||||
#include "crypto/hmac_sha256.h"
|
||||
@ -437,8 +438,7 @@ void TorController::add_onion_cb(TorControlConnection& conn, const TorControlRep
|
||||
if ((i = m.find("PrivateKey")) != m.end())
|
||||
private_key = i->second;
|
||||
}
|
||||
|
||||
service = CService(service_id+".onion", GetListenPort());
|
||||
service = LookupNumeric(std::string(service_id+".onion").c_str(), GetListenPort());
|
||||
LogPrintf("tor: Got service ID %s, advertising service %s\n", service_id, service.ToString());
|
||||
if (WriteBinaryFile(GetPrivateKeyFile(), private_key)) {
|
||||
LogPrint("tor", "tor: Cached service private key to %s\n", GetPrivateKeyFile());
|
||||
@ -462,7 +462,8 @@ void TorController::auth_cb(TorControlConnection& conn, const TorControlReply& r
|
||||
// Now that we know Tor is running setup the proxy for onion addresses
|
||||
// if -onion isn't set to something else.
|
||||
if (GetArg("-onion", "") == "") {
|
||||
proxyType addrOnion = proxyType(CService("127.0.0.1", 9050), true);
|
||||
CService resolved(LookupNumeric("127.0.0.1", 9050));
|
||||
proxyType addrOnion = proxyType(resolved, true);
|
||||
SetProxy(NET_TOR, addrOnion);
|
||||
SetLimited(NET_TOR, false);
|
||||
}
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "init.h"
|
||||
#include "main.h"
|
||||
#include "net.h"
|
||||
#include "netbase.h"
|
||||
#include "policy/rbf.h"
|
||||
#include "rpc/server.h"
|
||||
#include "timedata.h"
|
||||
|
Loading…
x
Reference in New Issue
Block a user