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<<bitsleft)-1));
+}
#include "config.h"
#endif
#include <boost/test/unit_test.hpp>
+#include <bitset>
#include "iputils.hh"
using namespace boost;
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);