net: Fix CIDR notation in ToString()
Only use CIDR notation if the netmask can be represented as such.
This commit is contained in:
parent
9e521c1735
commit
e2b8028e4c
2 changed files with 54 additions and 10 deletions
|
@ -1311,20 +1311,58 @@ bool CSubNet::Match(const CNetAddr &addr) const
|
|||
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
|
||||
{
|
||||
std::string strNetmask;
|
||||
/* Parse binary 1{n}0{N-n} to see if mask can be represented as /n */
|
||||
int cidr = 0;
|
||||
for (int n = network.IsIPv4() ? 12 : 0 ; n < 16; ++n)
|
||||
{
|
||||
uint8_t netmaskpart = netmask[n];
|
||||
while (netmaskpart)
|
||||
{
|
||||
cidr += ( netmaskpart & 0x01 );
|
||||
netmaskpart >>= 1;
|
||||
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() + strprintf("/%u", cidr);
|
||||
|
||||
return network.ToString() + "/" + strNetmask;
|
||||
}
|
||||
|
||||
bool CSubNet::IsValid() const
|
||||
|
|
|
@ -229,6 +229,12 @@ BOOST_AUTO_TEST_CASE(subnet_test)
|
|||
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");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "::/0");
|
||||
subnet = CSubNet("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");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "1:2:3:4:5:6:7:8/ffff:ffff:ffff:fffe:ffff:ffff:ffff:ff0f");
|
||||
subnet = CSubNet("1:2:3:4:5:6:7:8/fff:ffff:ffff:ffff:ffff:ffff:ffff:fff0");
|
||||
BOOST_CHECK_EQUAL(subnet.ToString(), "1:2:3:4:5:6:7:0/fff:ffff:ffff:ffff:ffff:ffff:ffff:fff0");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(netbase_getgroup)
|
||||
|
|
Loading…
Reference in a new issue