From 227791961e138b066dc7a71859697ce5bcf95fba Mon Sep 17 00:00:00 2001 From: bert hubert Date: Fri, 4 Sep 2015 11:45:20 +0200 Subject: [PATCH] implement ComboAddress::truncate() - 24 leaves the first 3 octets for IPv4. 0 leaves nothing. --- pdns/iputils.cc | 33 +++++++++++++++ pdns/iputils.hh | 2 + pdns/test-iputils_hh.cc | 90 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+) diff --git a/pdns/iputils.cc b/pdns/iputils.cc index ec8fa0605..6e6020909 100644 --- a/pdns/iputils.cc +++ b/pdns/iputils.cc @@ -160,3 +160,36 @@ void fillMSGHdr(struct msghdr* msgh, struct iovec* iov, char* cbuf, size_t cbufs msgh->msg_iovlen = 1; msgh->msg_flags = 0; } + +void ComboAddress::truncate(unsigned int bits) +{ + uint8_t* start; + int len=4; + if(sin4.sin_family==AF_INET) { + if(bits > 32) + return; + start = (uint8_t*)&sin4.sin_addr.s_addr; + len=4; + } + else { + if(bits > 128) + return; + start = (uint8_t*)&sin6.sin6_addr.s6_addr; + len=16; + } + + + auto tozero= len*8 - bits; // if set to 22, this will clear 1 byte, as it should + + memset(start + len - tozero/8, 0, tozero/8); // blot out the whole bytes on the right + + auto bitsleft=tozero % 8; // 2 bits left to clear + + // a b c d, to truncate to 22 bits, we just zeroed 'd' and need to zero 2 bits from c + // so and by '11111100', which is ~((1<<2)-1) = ~3 + uint8_t* place = start + len - 1 - tozero/8; + + + + *place &= (~((1<(ntohs(sin4.sin_port)); } + + void truncate(unsigned int bits); }; /** This exception is thrown by the Netmask class and by extension by the NetmaskGroup class */ diff --git a/pdns/test-iputils_hh.cc b/pdns/test-iputils_hh.cc index ea6523a03..89076bd48 100644 --- a/pdns/test-iputils_hh.cc +++ b/pdns/test-iputils_hh.cc @@ -4,6 +4,7 @@ #include "config.h" #endif #include +#include #include "iputils.hh" using namespace boost; @@ -34,6 +35,95 @@ BOOST_AUTO_TEST_CASE(test_ComboAddress) { BOOST_CHECK_EQUAL(withport.sin4.sin_port, htons(5300)); } +BOOST_AUTO_TEST_CASE(test_ComboAddressTruncate) { + ComboAddress ca4("130.161.252.29"); + ca4.truncate(24); + BOOST_CHECK_EQUAL(ca4.toString(), "130.161.252.0"); + ca4.truncate(16); + BOOST_CHECK_EQUAL(ca4.toString(), "130.161.0.0"); + + + + ca4 = ComboAddress("130.161.252.29"); + ComboAddress orig(ca4); + for(int n=32; n; --n) { + ca4.truncate(n); + + uint32_t p; + memcpy(&p, (char*)&ca4.sin4.sin_addr.s_addr, 4); + std::bitset<32> result(htonl(p)); + + memcpy(&p, (char*)&orig.sin4.sin_addr.s_addr, 4); + std::bitset<32> manual(htonl(p)); + + auto tokill=32-n; + for(int i =0; i< tokill; ++i) + manual.set(i, 0); + + BOOST_CHECK_EQUAL(result, manual); + } + + ca4 = ComboAddress("130.161.252.29"); + ca4.truncate(31); + BOOST_CHECK_EQUAL(ca4.toString(), "130.161.252.28"); + + ca4.truncate(30); + BOOST_CHECK_EQUAL(ca4.toString(), "130.161.252.28"); + + ca4.truncate(29); + BOOST_CHECK_EQUAL(ca4.toString(), "130.161.252.24"); + + ca4.truncate(23); + BOOST_CHECK_EQUAL(ca4.toString(), "130.161.252.0"); + + ca4.truncate(22); + BOOST_CHECK_EQUAL(ca4.toString(), "130.161.252.0"); + + ca4.truncate(21); + BOOST_CHECK_EQUAL(ca4.toString(), "130.161.248.0"); + + ComboAddress ca6("2001:888:2000:1d::2"); + ca6.truncate(120); + BOOST_CHECK_EQUAL(ca6.toString(), "2001:888:2000:1d::"); + ca6.truncate(64); + BOOST_CHECK_EQUAL(ca6.toString(), "2001:888:2000:1d::"); + ca6.truncate(72); // 0102 304 0506 78 + BOOST_CHECK_EQUAL(ca6.toString(), "2001:888:2000:1d::"); + ca6.truncate(56); + BOOST_CHECK_EQUAL(ca6.toString(), "2001:888:2000::"); + ca6.truncate(48); + BOOST_CHECK_EQUAL(ca6.toString(), "2001:888:2000::"); + ca6.truncate(32); + BOOST_CHECK_EQUAL(ca6.toString(), "2001:888::"); + ca6.truncate(16); + BOOST_CHECK_EQUAL(ca6.toString(), "2001::"); + ca6.truncate(8); + BOOST_CHECK_EQUAL(ca6.toString(), "2000::"); + + + orig=ca6=ComboAddress("2001:888:2000:1d::2"); + for(int n=128; n; --n) { + ca6.truncate(n); + + std::bitset<128> result, manual; + for(int i=0; i < 16; ++i) { + result<<=8; + result|= std::bitset<128>(*((unsigned char*)&ca6.sin6.sin6_addr.s6_addr + i)); + + manual<<=8; + manual|= std::bitset<128>(*((unsigned char*)&orig.sin6.sin6_addr.s6_addr + i)); + } + + auto tokill=128-n; + for(int i =0; i< tokill; ++i) + manual.set(i, 0); + + BOOST_CHECK_EQUAL(result, manual); + } + + +} + BOOST_AUTO_TEST_CASE(test_Netmask) { ComboAddress local("127.0.0.1", 53); ComboAddress remote("130.161.252.29", 53); -- 2.40.0