From: Remi Gacogne Date: Tue, 11 Feb 2020 13:28:07 +0000 (+0100) Subject: Keep a masked network in the Netmask class X-Git-Tag: rec-4.4.0-alpha0~14^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7c408ab42f3424dc09aa0b854c72a73eb241b5bf;p=thirdparty%2Fpdns.git Keep a masked network in the Netmask class --- diff --git a/pdns/iputils.hh b/pdns/iputils.hh index 754b104b2b..45c0badc4a 100644 --- a/pdns/iputils.hh +++ b/pdns/iputils.hh @@ -414,43 +414,63 @@ class Netmask public: Netmask() { - d_network.sin4.sin_family=0; // disable this doing anything useful + d_network.sin4.sin_family = 0; // disable this doing anything useful d_network.sin4.sin_port = 0; // this guarantees d_network compares identical - d_mask=0; - d_bits=0; + d_mask = 0; + d_bits = 0; } Netmask(const ComboAddress& network, uint8_t bits=0xff): d_network(network) { - d_network.sin4.sin_port=0; - d_bits = (network.isIPv4() ? std::min(bits, (uint8_t)32) : std::min(bits, (uint8_t)128)); + d_network.sin4.sin_port = 0; + setBits(network.isIPv4() ? std::min(bits, static_cast(32)) : std::min(bits, static_cast(128))); + } - if(d_bits<32) - d_mask=~(0xFFFFFFFF>>d_bits); - else - d_mask=0xFFFFFFFF; // not actually used for IPv6 + void setBits(uint8_t value) + { + d_bits = value; + + if (d_bits < 32) { + d_mask = ~(0xFFFFFFFF >> d_bits); + } + else { + // note that d_mask is unused for IPv6 + d_mask = 0xFFFFFFFF; + } + + if (isIPv4()) { + d_network.sin4.sin_addr.s_addr = htonl(ntohl(d_network.sin4.sin_addr.s_addr) & d_mask); + } + else if (isIPv6()) { + uint8_t bytes = d_bits/8; + uint8_t *us = (uint8_t*) &d_network.sin6.sin6_addr.s6_addr; + uint8_t bits = d_bits % 8; + uint8_t mask = (uint8_t) ~(0xFF>>bits); + + if (bytes < sizeof(d_network.sin6.sin6_addr.s6_addr)) { + us[bytes] &= mask; + } + + for(size_t idx = bytes + 1; idx < sizeof(d_network.sin6.sin6_addr.s6_addr); ++idx) { + us[idx] = 0; + } + } } //! Constructor supplies the mask, which cannot be changed Netmask(const string &mask) { - pair split=splitField(mask,'/'); - d_network=makeComboAddress(split.first); + pair split = splitField(mask,'/'); + d_network = makeComboAddress(split.first); - if(!split.second.empty()) { - d_bits = (uint8_t)pdns_stou(split.second); - if(d_bits<32) - d_mask=~(0xFFFFFFFF>>d_bits); - else - d_mask=0xFFFFFFFF; + if (!split.second.empty()) { + setBits(static_cast(pdns_stou(split.second))); } - else if(d_network.sin4.sin_family==AF_INET) { - d_bits = 32; - d_mask = 0xFFFFFFFF; + else if (d_network.sin4.sin_family == AF_INET) { + setBits(32); } else { - d_bits=128; - d_mask=0; // silence silly warning - d_mask is unused for IPv6 + setBits(128); } } @@ -482,7 +502,7 @@ public: uint8_t bits= d_bits % 8; uint8_t mask= (uint8_t) ~(0xFF>>bits); - return((us[n] & mask) == (them[n] & mask)); + return((us[n]) == (them[n] & mask)); } return false; } @@ -497,7 +517,7 @@ public: //! If this IP address in native format matches bool match4(uint32_t ip) const { - return (ip & d_mask) == (ntohl(d_network.sin4.sin_addr.s_addr) & d_mask); + return (ip & d_mask) == (ntohl(d_network.sin4.sin_addr.s_addr)); } string toString() const @@ -509,41 +529,27 @@ public: { return d_network.toString(); } + const ComboAddress& getNetwork() const { return d_network; } - const ComboAddress getMaskedNetwork() const - { - ComboAddress result(d_network); - if(isIPv4()) { - result.sin4.sin_addr.s_addr = htonl(ntohl(result.sin4.sin_addr.s_addr) & d_mask); - } - else if(isIPv6()) { - size_t idx; - uint8_t bytes=d_bits/8; - uint8_t *us=(uint8_t*) &result.sin6.sin6_addr.s6_addr; - uint8_t bits= d_bits % 8; - uint8_t mask= (uint8_t) ~(0xFF>>bits); - - if (bytes < sizeof(result.sin6.sin6_addr.s6_addr)) { - us[bytes] &= mask; - } - for(idx = bytes + 1; idx < sizeof(result.sin6.sin6_addr.s6_addr); ++idx) { - us[idx] = 0; - } - } - return result; + const ComboAddress& getMaskedNetwork() const + { + return getNetwork(); } + uint8_t getBits() const { return d_bits; } + bool isIPv6() const { return d_network.sin6.sin6_family == AF_INET6; } + bool isIPv4() const { return d_network.sin4.sin_family == AF_INET; @@ -562,7 +568,7 @@ public: if (d_bits < rhs.d_bits) return false; - return getMaskedNetwork() < rhs.getMaskedNetwork(); + return d_network < rhs.d_network; } bool operator>(const Netmask& rhs) const @@ -1093,7 +1099,7 @@ public: node = d_root->left.get(); else if (value.isIPv6()) node = d_root->right.get(); - else + else throw NetmaskException("invalid address family"); if (node == nullptr) return nullptr; @@ -1145,7 +1151,7 @@ public: node = d_root->left.get(); else if (key.isIPv6()) node = d_root->right.get(); - else + else throw NetmaskException("invalid address family"); // no tree, no value if (node == nullptr) return; diff --git a/pdns/recursordist/test-rpzloader_cc.cc b/pdns/recursordist/test-rpzloader_cc.cc index 2b46e9efab..8769c6eb17 100644 --- a/pdns/recursordist/test-rpzloader_cc.cc +++ b/pdns/recursordist/test-rpzloader_cc.cc @@ -23,10 +23,10 @@ BOOST_AUTO_TEST_CASE(test_rpz_loader) string tests[][2] = { {"32.3.2.168.192", "192.168.2.3/32"}, - {"27.73.2.168.192", "192.168.2.73/27"}, + {"27.73.2.168.192", "192.168.2.64/27"}, {"24.0.2.168.192", "192.168.2.0/24"}, {"128.57.zz.1.0.db8.2001", "2001:db8:0:1::57/128"}, - {"48.zz.1.0.db8.2001", "2001:db8:0:1::/48"}, + {"48.zz.1.0.db8.2001", "2001:db8::/48"}, {"128.5.C0A8.FFFF.0.1.0.db8.2001", "2001:db8:0:1:0:ffff:c0a8:5/128"}, {"21.0.248.44.5", "5.44.248.0/21"}, diff --git a/pdns/test-iputils_hh.cc b/pdns/test-iputils_hh.cc index 1b6d2943c6..472e144a69 100644 --- a/pdns/test-iputils_hh.cc +++ b/pdns/test-iputils_hh.cc @@ -210,7 +210,7 @@ BOOST_AUTO_TEST_CASE(test_Netmask) { Netmask nm25("192.0.2.255/25"); BOOST_CHECK(nm25.getBits() == 25); - BOOST_CHECK(nm25.getNetwork() == ComboAddress("192.0.2.255")); + BOOST_CHECK(nm25.getNetwork() == ComboAddress("192.0.2.128")); BOOST_CHECK(nm25.getMaskedNetwork() == ComboAddress("192.0.2.128")); /* Make sure that more specific Netmasks are lesser than less specific ones,