net: Split resolving out of CSubNet

This commit is contained in:
Cory Fields 2016-05-31 15:50:24 -04:00
parent f96c7c4d91
commit b6c3ff3dae
7 changed files with 153 additions and 115 deletions

View File

@ -197,12 +197,17 @@ static bool ClientAllowed(const CNetAddr& netaddr)
static bool InitHTTPAllowList() static bool InitHTTPAllowList()
{ {
rpc_allow_subnets.clear(); rpc_allow_subnets.clear();
rpc_allow_subnets.push_back(CSubNet("127.0.0.0/8")); // always allow IPv4 local subnet CNetAddr localv4;
rpc_allow_subnets.push_back(CSubNet("::1")); // always allow IPv6 localhost 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")) { if (mapMultiArgs.count("-rpcallowip")) {
const std::vector<std::string>& vAllow = mapMultiArgs["-rpcallowip"]; const std::vector<std::string>& vAllow = mapMultiArgs["-rpcallowip"];
for (std::string strAllow : vAllow) { for (std::string strAllow : vAllow) {
CSubNet subnet(strAllow); CSubNet subnet;
LookupSubNet(strAllow.c_str(), subnet);
if (!subnet.IsValid()) { if (!subnet.IsValid()) {
uiInterface.ThreadSafeMessageBox( 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), 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),

View File

@ -1083,7 +1083,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
if (mapArgs.count("-whitelist")) { if (mapArgs.count("-whitelist")) {
BOOST_FOREACH(const std::string& net, mapMultiArgs["-whitelist"]) { BOOST_FOREACH(const std::string& net, mapMultiArgs["-whitelist"]) {
CSubNet subnet(net); CSubNet subnet;
LookupSubNet(net.c_str(), subnet);
if (!subnet.IsValid()) if (!subnet.IsValid())
return InitError(strprintf(_("Invalid netmask specified in -whitelist: '%s'"), net)); return InitError(strprintf(_("Invalid netmask specified in -whitelist: '%s'"), net));
CNode::AddWhitelistedRange(subnet); CNode::AddWhitelistedRange(subnet);

View File

@ -1214,63 +1214,85 @@ CSubNet::CSubNet():
memset(netmask, 0, sizeof(netmask)); memset(netmask, 0, sizeof(netmask));
} }
CSubNet::CSubNet(const std::string &strSubnet) CSubNet::CSubNet(const CNetAddr &addr, int32_t mask)
{ {
size_t slash = strSubnet.find_last_of('/');
std::vector<CNetAddr> vIP;
valid = true; valid = true;
network = addr;
// Default to /32 (IPv4) or /128 (IPv6), i.e. match single address // Default to /32 (IPv4) or /128 (IPv6), i.e. match single address
memset(netmask, 255, sizeof(netmask)); 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];
}
bool LookupSubNet(const char* pszName, CSubNet& ret)
{
std::string strSubnet(pszName);
size_t slash = strSubnet.find_last_of('/');
std::vector<CNetAddr> vIP;
std::string strAddress = strSubnet.substr(0, slash); std::string strAddress = strSubnet.substr(0, slash);
if (LookupHost(strAddress.c_str(), vIP, 1, false)) if (LookupHost(strAddress.c_str(), vIP, 1, false))
{ {
network = vIP[0]; CNetAddr network = vIP[0];
if (slash != strSubnet.npos) if (slash != strSubnet.npos)
{ {
std::string strNetmask = strSubnet.substr(slash + 1); std::string strNetmask = strSubnet.substr(slash + 1);
int32_t n; int32_t n;
// IPv4 addresses start at offset 12, and first 12 bytes must match, so just offset 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 syntax
if (ParseInt32(strNetmask, &n)) // If valid number, assume /24 symtex ret = CSubNet(network, n);
{ return ret.IsValid();
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;
}
} }
else // If not a valid number, try full netmask syntax else // If not a valid number, try full netmask syntax
{ {
if (LookupHost(strNetmask.c_str(), vIP, 1, false)) // Never allow lookup for netmask // Never allow lookup for netmask
{ if (LookupHost(strNetmask.c_str(), vIP, 1, false)) {
// Copy only the *last* four bytes in case of IPv4, the rest of the mask should stay 1's as ret = CSubNet(network, vIP[0]);
// we don't want pchIPv4 to be part of the mask. return ret.IsValid();
for(int x=astartofs; x<16; ++x)
netmask[x] = vIP[0].ip[x];
}
else
{
valid = false;
} }
} }
} }
else
{
ret = CSubNet(network);
return ret.IsValid();
}
} }
else return false;
{
valid = false;
}
// Normalize network according to netmask
for(int x=0; x<16; ++x)
network.ip[x] &= netmask[x];
} }
CSubNet::CSubNet(const CNetAddr &addr): CSubNet::CSubNet(const CNetAddr &addr):

View File

@ -117,7 +117,8 @@ class CSubNet
public: public:
CSubNet(); CSubNet();
explicit CSubNet(const std::string &strSubnet); CSubNet(const CNetAddr &addr, int32_t mask);
CSubNet(const CNetAddr &addr, const CNetAddr &mask);
//constructor for single ip subnet (<ipv4>/32 or <ipv6>/128) //constructor for single ip subnet (<ipv4>/32 or <ipv6>/128)
explicit CSubNet(const CNetAddr &addr); explicit CSubNet(const CNetAddr &addr);
@ -205,6 +206,7 @@ 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, CService& addr, int portDefault, bool fAllowLookup);
bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions); 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); bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0);
bool LookupSubNet(const char *pszName, CSubNet& subnet);
bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed = 0); 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); 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 */ /** Return readable error string for a network error code */

View File

@ -915,8 +915,9 @@ void RPCConsole::unbanSelectedNode()
// Get currently selected ban address // Get currently selected ban address
QString strNode = GUIUtil::getEntryData(ui->banlistWidget, 0, BanTableModel::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()) if (possibleSubnet.IsValid())
{ {
CNode::Unban(possibleSubnet); CNode::Unban(possibleSubnet);

View File

@ -500,7 +500,7 @@ UniValue setban(const UniValue& params, bool fHelp)
netAddr = resolved; netAddr = resolved;
} }
else else
subNet = CSubNet(params[0].get_str()); LookupSubNet(params[0].get_str().c_str(), subNet);
if (! (isSubnet ? subNet.IsValid() : netAddr.IsValid()) ) if (! (isSubnet ? subNet.IsValid() : netAddr.IsValid()) )
throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Invalid IP/Subnet"); throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Invalid IP/Subnet");

View File

@ -21,6 +21,13 @@ static CNetAddr ResolveIP(const char* ip)
return addr; return addr;
} }
static CSubNet ResolveSubNet(const char* subnet)
{
CSubNet ret;
LookupSubNet(subnet, ret);
return ret;
}
BOOST_AUTO_TEST_CASE(netbase_networks) BOOST_AUTO_TEST_CASE(netbase_networks)
{ {
BOOST_CHECK(ResolveIP("127.0.0.1").GetNetwork() == NET_UNROUTABLE); BOOST_CHECK(ResolveIP("127.0.0.1").GetNetwork() == NET_UNROUTABLE);
@ -119,44 +126,44 @@ BOOST_AUTO_TEST_CASE(onioncat_test)
BOOST_AUTO_TEST_CASE(subnet_test) 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(ResolveSubNet("1.2.3.0/24") == ResolveSubNet("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(ResolveSubNet("1.2.3.0/24") != ResolveSubNet("1.2.4.0/255.255.255.0"));
BOOST_CHECK(CSubNet("1.2.3.0/24").Match(ResolveIP("1.2.3.4"))); BOOST_CHECK(ResolveSubNet("1.2.3.0/24").Match(ResolveIP("1.2.3.4")));
BOOST_CHECK(!CSubNet("1.2.2.0/24").Match(ResolveIP("1.2.3.4"))); BOOST_CHECK(!ResolveSubNet("1.2.2.0/24").Match(ResolveIP("1.2.3.4")));
BOOST_CHECK(CSubNet("1.2.3.4").Match(ResolveIP("1.2.3.4"))); BOOST_CHECK(ResolveSubNet("1.2.3.4").Match(ResolveIP("1.2.3.4")));
BOOST_CHECK(CSubNet("1.2.3.4/32").Match(ResolveIP("1.2.3.4"))); BOOST_CHECK(ResolveSubNet("1.2.3.4/32").Match(ResolveIP("1.2.3.4")));
BOOST_CHECK(!CSubNet("1.2.3.4").Match(ResolveIP("5.6.7.8"))); BOOST_CHECK(!ResolveSubNet("1.2.3.4").Match(ResolveIP("5.6.7.8")));
BOOST_CHECK(!CSubNet("1.2.3.4/32").Match(ResolveIP("5.6.7.8"))); BOOST_CHECK(!ResolveSubNet("1.2.3.4/32").Match(ResolveIP("5.6.7.8")));
BOOST_CHECK(CSubNet("::ffff:127.0.0.1").Match(ResolveIP("127.0.0.1"))); BOOST_CHECK(ResolveSubNet("::ffff:127.0.0.1").Match(ResolveIP("127.0.0.1")));
BOOST_CHECK(CSubNet("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:8")));
BOOST_CHECK(!CSubNet("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:8").Match(ResolveIP("1:2:3:4:5:6:7:9")));
BOOST_CHECK(CSubNet("1:2:3:4:5:6:7:0/112").Match(ResolveIP("1:2:3:4:5:6:7:1234"))); BOOST_CHECK(ResolveSubNet("1:2:3:4:5:6:7:0/112").Match(ResolveIP("1:2:3:4:5:6:7:1234")));
BOOST_CHECK(CSubNet("192.168.0.1/24").Match(ResolveIP("192.168.0.2"))); BOOST_CHECK(ResolveSubNet("192.168.0.1/24").Match(ResolveIP("192.168.0.2")));
BOOST_CHECK(CSubNet("192.168.0.20/29").Match(ResolveIP("192.168.0.18"))); BOOST_CHECK(ResolveSubNet("192.168.0.20/29").Match(ResolveIP("192.168.0.18")));
BOOST_CHECK(CSubNet("1.2.2.1/24").Match(ResolveIP("1.2.2.4"))); BOOST_CHECK(ResolveSubNet("1.2.2.1/24").Match(ResolveIP("1.2.2.4")));
BOOST_CHECK(CSubNet("1.2.2.110/31").Match(ResolveIP("1.2.2.111"))); BOOST_CHECK(ResolveSubNet("1.2.2.110/31").Match(ResolveIP("1.2.2.111")));
BOOST_CHECK(CSubNet("1.2.2.20/26").Match(ResolveIP("1.2.2.63"))); BOOST_CHECK(ResolveSubNet("1.2.2.20/26").Match(ResolveIP("1.2.2.63")));
// All-Matching IPv6 Matches arbitrary IPv4 and IPv6 // All-Matching IPv6 Matches arbitrary IPv4 and IPv6
BOOST_CHECK(CSubNet("::/0").Match(ResolveIP("1:2:3:4:5:6:7:1234"))); BOOST_CHECK(ResolveSubNet("::/0").Match(ResolveIP("1:2:3:4:5:6:7:1234")));
BOOST_CHECK(CSubNet("::/0").Match(ResolveIP("1.2.3.4"))); BOOST_CHECK(ResolveSubNet("::/0").Match(ResolveIP("1.2.3.4")));
// All-Matching IPv4 does not Match IPv6 // All-Matching IPv4 does not Match IPv6
BOOST_CHECK(!CSubNet("0.0.0.0/0").Match(ResolveIP("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) // Invalid subnets Match nothing (not even invalid addresses)
BOOST_CHECK(!CSubNet().Match(ResolveIP("1.2.3.4"))); BOOST_CHECK(!CSubNet().Match(ResolveIP("1.2.3.4")));
BOOST_CHECK(!CSubNet("").Match(ResolveIP("4.5.6.7"))); BOOST_CHECK(!ResolveSubNet("").Match(ResolveIP("4.5.6.7")));
BOOST_CHECK(!CSubNet("bloop").Match(ResolveIP("0.0.0.0"))); BOOST_CHECK(!ResolveSubNet("bloop").Match(ResolveIP("0.0.0.0")));
BOOST_CHECK(!CSubNet("bloop").Match(ResolveIP("hab"))); BOOST_CHECK(!ResolveSubNet("bloop").Match(ResolveIP("hab")));
// Check valid/invalid // Check valid/invalid
BOOST_CHECK(CSubNet("1.2.3.0/0").IsValid()); BOOST_CHECK(ResolveSubNet("1.2.3.0/0").IsValid());
BOOST_CHECK(!CSubNet("1.2.3.0/-1").IsValid()); BOOST_CHECK(!ResolveSubNet("1.2.3.0/-1").IsValid());
BOOST_CHECK(CSubNet("1.2.3.0/32").IsValid()); BOOST_CHECK(ResolveSubNet("1.2.3.0/32").IsValid());
BOOST_CHECK(!CSubNet("1.2.3.0/33").IsValid()); BOOST_CHECK(!ResolveSubNet("1.2.3.0/33").IsValid());
BOOST_CHECK(CSubNet("1:2:3:4:5:6:7:8/0").IsValid()); BOOST_CHECK(ResolveSubNet("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(ResolveSubNet("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(!ResolveSubNet("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(ResolveSubNet("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(!ResolveSubNet("1:2:3:4:5:6:7:8/129").IsValid());
BOOST_CHECK(!CSubNet("fuzzy").IsValid()); BOOST_CHECK(!ResolveSubNet("fuzzy").IsValid());
//CNetAddr constructor test //CNetAddr constructor test
BOOST_CHECK(CSubNet(ResolveIP("127.0.0.1")).IsValid()); BOOST_CHECK(CSubNet(ResolveIP("127.0.0.1")).IsValid());
@ -169,82 +176,82 @@ BOOST_AUTO_TEST_CASE(subnet_test)
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")).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"); BOOST_CHECK(CSubNet(ResolveIP("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 = ResolveSubNet("1.2.3.4/255.255.255.255");
BOOST_CHECK_EQUAL(subnet.ToString(), "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"); subnet = ResolveSubNet("1.2.3.4/255.255.255.254");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/31"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/31");
subnet = CSubNet("1.2.3.4/255.255.255.252"); subnet = ResolveSubNet("1.2.3.4/255.255.255.252");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/30"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/30");
subnet = CSubNet("1.2.3.4/255.255.255.248"); subnet = ResolveSubNet("1.2.3.4/255.255.255.248");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/29"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/29");
subnet = CSubNet("1.2.3.4/255.255.255.240"); subnet = ResolveSubNet("1.2.3.4/255.255.255.240");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/28"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/28");
subnet = CSubNet("1.2.3.4/255.255.255.224"); subnet = ResolveSubNet("1.2.3.4/255.255.255.224");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/27"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/27");
subnet = CSubNet("1.2.3.4/255.255.255.192"); subnet = ResolveSubNet("1.2.3.4/255.255.255.192");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/26"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/26");
subnet = CSubNet("1.2.3.4/255.255.255.128"); subnet = ResolveSubNet("1.2.3.4/255.255.255.128");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/25"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/25");
subnet = CSubNet("1.2.3.4/255.255.255.0"); subnet = ResolveSubNet("1.2.3.4/255.255.255.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/24"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/24");
subnet = CSubNet("1.2.3.4/255.255.254.0"); subnet = ResolveSubNet("1.2.3.4/255.255.254.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.2.0/23"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.2.0/23");
subnet = CSubNet("1.2.3.4/255.255.252.0"); subnet = ResolveSubNet("1.2.3.4/255.255.252.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/22"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/22");
subnet = CSubNet("1.2.3.4/255.255.248.0"); subnet = ResolveSubNet("1.2.3.4/255.255.248.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/21"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/21");
subnet = CSubNet("1.2.3.4/255.255.240.0"); subnet = ResolveSubNet("1.2.3.4/255.255.240.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/20"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/20");
subnet = CSubNet("1.2.3.4/255.255.224.0"); subnet = ResolveSubNet("1.2.3.4/255.255.224.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/19"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/19");
subnet = CSubNet("1.2.3.4/255.255.192.0"); subnet = ResolveSubNet("1.2.3.4/255.255.192.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/18"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/18");
subnet = CSubNet("1.2.3.4/255.255.128.0"); subnet = ResolveSubNet("1.2.3.4/255.255.128.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/17"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/17");
subnet = CSubNet("1.2.3.4/255.255.0.0"); subnet = ResolveSubNet("1.2.3.4/255.255.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/16"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/16");
subnet = CSubNet("1.2.3.4/255.254.0.0"); subnet = ResolveSubNet("1.2.3.4/255.254.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/15"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/15");
subnet = CSubNet("1.2.3.4/255.252.0.0"); subnet = ResolveSubNet("1.2.3.4/255.252.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/14"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/14");
subnet = CSubNet("1.2.3.4/255.248.0.0"); subnet = ResolveSubNet("1.2.3.4/255.248.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/13"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/13");
subnet = CSubNet("1.2.3.4/255.240.0.0"); subnet = ResolveSubNet("1.2.3.4/255.240.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/12"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/12");
subnet = CSubNet("1.2.3.4/255.224.0.0"); subnet = ResolveSubNet("1.2.3.4/255.224.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/11"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/11");
subnet = CSubNet("1.2.3.4/255.192.0.0"); subnet = ResolveSubNet("1.2.3.4/255.192.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/10"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/10");
subnet = CSubNet("1.2.3.4/255.128.0.0"); subnet = ResolveSubNet("1.2.3.4/255.128.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/9"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/9");
subnet = CSubNet("1.2.3.4/255.0.0.0"); subnet = ResolveSubNet("1.2.3.4/255.0.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/8"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/8");
subnet = CSubNet("1.2.3.4/254.0.0.0"); subnet = ResolveSubNet("1.2.3.4/254.0.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/7"); BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/7");
subnet = CSubNet("1.2.3.4/252.0.0.0"); subnet = ResolveSubNet("1.2.3.4/252.0.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/6"); BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/6");
subnet = CSubNet("1.2.3.4/248.0.0.0"); subnet = ResolveSubNet("1.2.3.4/248.0.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/5"); BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/5");
subnet = CSubNet("1.2.3.4/240.0.0.0"); subnet = ResolveSubNet("1.2.3.4/240.0.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/4"); BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/4");
subnet = CSubNet("1.2.3.4/224.0.0.0"); subnet = ResolveSubNet("1.2.3.4/224.0.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/3"); BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/3");
subnet = CSubNet("1.2.3.4/192.0.0.0"); subnet = ResolveSubNet("1.2.3.4/192.0.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/2"); BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/2");
subnet = CSubNet("1.2.3.4/128.0.0.0"); subnet = ResolveSubNet("1.2.3.4/128.0.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/1"); BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/1");
subnet = CSubNet("1.2.3.4/0.0.0.0"); subnet = ResolveSubNet("1.2.3.4/0.0.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/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 = 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"); 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"); 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"); 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"); 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_CHECK_EQUAL(subnet.ToString(), "1:2:3:4:5:6:7:8/ffff:ffff:ffff:fffe:ffff:ffff:ffff:ff0f");
} }