@@ -1311,20 +1311,58 @@ bool CSubNet::Match(const CNetAddr &addr) const
13111311 return true ;
13121312}
13131313
1314+ static inline int NetmaskBits (uint8_t x)
1315+ {
1316+ switch (x) {
1317+ case 0x00 : return 0 ; break ;
1318+ case 0x80 : return 1 ; break ;
1319+ case 0xc0 : return 2 ; break ;
1320+ case 0xe0 : return 3 ; break ;
1321+ case 0xf0 : return 4 ; break ;
1322+ case 0xf8 : return 5 ; break ;
1323+ case 0xfc : return 6 ; break ;
1324+ case 0xfe : return 7 ; break ;
1325+ case 0xff : return 8 ; break ;
1326+ default : return -1 ; break ;
1327+ }
1328+ }
1329+
13141330std::string CSubNet::ToString () const
13151331{
1316- std::string strNetmask;
1332+ /* Parse binary 1{n}0{N-n} to see if mask can be represented as /n */
13171333 int cidr = 0 ;
1318- for (int n = network.IsIPv4 () ? 12 : 0 ; n < 16 ; ++n)
1319- {
1320- uint8_t netmaskpart = netmask[n];
1321- while (netmaskpart)
1322- {
1323- cidr += ( netmaskpart & 0x01 );
1324- netmaskpart >>= 1 ;
1325- }
1334+ bool valid_cidr = true ;
1335+ int n = network.IsIPv4 () ? 12 : 0 ;
1336+ for (; n < 16 && netmask[n] == 0xff ; ++n)
1337+ cidr += 8 ;
1338+ if (n < 16 ) {
1339+ int bits = NetmaskBits (netmask[n]);
1340+ if (bits < 0 )
1341+ valid_cidr = false ;
1342+ else
1343+ cidr += bits;
1344+ ++n;
13261345 }
1327- return network.ToString () + strprintf (" /%u" , cidr);
1346+ for (; n < 16 && valid_cidr; ++n)
1347+ if (netmask[n] != 0x00 )
1348+ valid_cidr = false ;
1349+
1350+ /* Format output */
1351+ std::string strNetmask;
1352+ if (valid_cidr) {
1353+ strNetmask = strprintf (" %u" , cidr);
1354+ } else {
1355+ if (network.IsIPv4 ())
1356+ strNetmask = strprintf (" %u.%u.%u.%u" , netmask[12 ], netmask[13 ], netmask[14 ], netmask[15 ]);
1357+ else
1358+ strNetmask = strprintf (" %x:%x:%x:%x:%x:%x:%x:%x" ,
1359+ netmask[0 ] << 8 | netmask[1 ], netmask[2 ] << 8 | netmask[3 ],
1360+ netmask[4 ] << 8 | netmask[5 ], netmask[6 ] << 8 | netmask[7 ],
1361+ netmask[8 ] << 8 | netmask[9 ], netmask[10 ] << 8 | netmask[11 ],
1362+ netmask[12 ] << 8 | netmask[13 ], netmask[14 ] << 8 | netmask[15 ]);
1363+ }
1364+
1365+ return network.ToString () + " /" + strNetmask;
13281366}
13291367
13301368bool CSubNet::IsValid () const
0 commit comments