Browse Source

net: Fix CIDR notation in ToString()

Only use CIDR notation if the netmask can be represented as such.
0.13
Wladimir J. van der Laan 10 years ago committed by Jonas Schnelli
parent
commit
e2b8028e4c
  1. 58
      src/netbase.cpp
  2. 6
      src/test/netbase_tests.cpp

58
src/netbase.cpp

@ -1311,20 +1311,58 @@ bool CSubNet::Match(const CNetAddr &addr) const
return true; 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 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; int cidr = 0;
for (int n = network.IsIPv4() ? 12 : 0 ; n < 16; ++n) bool valid_cidr = true;
{ int n = network.IsIPv4() ? 12 : 0;
uint8_t netmaskpart = netmask[n]; for (; n < 16 && netmask[n] == 0xff; ++n)
while (netmaskpart) cidr += 8;
{ if (n < 16) {
cidr += ( netmaskpart & 0x01 ); int bits = NetmaskBits(netmask[n]);
netmaskpart >>= 1; if (bits < 0)
} valid_cidr = false;
else
cidr += bits;
++n;
} }
return network.ToString() + strprintf("/%u", cidr); 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 bool CSubNet::IsValid() const

6
src/test/netbase_tests.cpp

@ -229,6 +229,12 @@ BOOST_AUTO_TEST_CASE(subnet_test)
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 = CSubNet("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");
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) BOOST_AUTO_TEST_CASE(netbase_getgroup)

Loading…
Cancel
Save