mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 02:35:57 +01:00
Allow masking IPv4/6 and HW addresses
This commit is contained in:
@@ -211,7 +211,7 @@ public:
|
||||
*/
|
||||
static AddressRange from_mask(const address_type& first, const address_type& mask) {
|
||||
return AddressRange<address_type>(
|
||||
Internals::first_address_from_mask(first, mask),
|
||||
first & mask,
|
||||
Internals::last_address_from_mask(first, mask),
|
||||
true
|
||||
);
|
||||
|
||||
@@ -249,6 +249,20 @@ public:
|
||||
bool operator<(const HWAddress& rhs) const {
|
||||
return std::lexicographical_compare(begin(), end(), rhs.begin(), rhs.end());
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Apply a mask to this address
|
||||
*
|
||||
* \param mask The mask to be applied
|
||||
* \return The result of applying the mask to this address
|
||||
*/
|
||||
HWAddress operator&(const HWAddress& mask) const {
|
||||
HWAddress<n> output = *this;
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
output[i] = output[i] & mask[i];
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Retrieves the size of this address.
|
||||
@@ -299,6 +313,15 @@ public:
|
||||
storage_type operator[](size_t i) const {
|
||||
return begin()[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Retrieves the i-th storage_type in this address.
|
||||
*
|
||||
* \param i The element to retrieve.
|
||||
*/
|
||||
storage_type& operator[](size_t i) {
|
||||
return begin()[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Writes this HWAddress in hex-notation to a std::ostream.
|
||||
|
||||
@@ -183,18 +183,6 @@ bool decrement(HWAddress<n>& addr) {
|
||||
// Compares sequence numbers as defined by RFC 1982.
|
||||
int seq_compare(uint32_t seq1, uint32_t seq2);
|
||||
|
||||
|
||||
IPv4Address first_address_from_mask(IPv4Address addr, IPv4Address mask);
|
||||
IPv6Address first_address_from_mask(IPv6Address addr, const IPv6Address& mask);
|
||||
template<size_t n>
|
||||
HWAddress<n> first_address_from_mask(HWAddress<n> addr, const HWAddress<n>& mask) {
|
||||
typename HWAddress<n>::iterator addr_iter = addr.begin();
|
||||
for (typename HWAddress<n>::const_iterator it = mask.begin(); it != mask.end(); ++it, ++addr_iter) {
|
||||
*addr_iter = *addr_iter & *it;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
IPv4Address last_address_from_mask(IPv4Address addr, IPv4Address mask);
|
||||
IPv6Address last_address_from_mask(IPv6Address addr, const IPv6Address& mask);
|
||||
template<size_t n>
|
||||
|
||||
@@ -123,9 +123,17 @@ public:
|
||||
* \param rhs The address to be compared.
|
||||
* \return bool indicating whether this address is less-than rhs.
|
||||
*/
|
||||
bool operator< (const IPv4Address& rhs) const {
|
||||
bool operator<(const IPv4Address& rhs) const {
|
||||
return ip_addr_ < rhs.ip_addr_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Apply a mask to this address
|
||||
*
|
||||
* \param mask The mask to be applied
|
||||
* \return The result of applying the mask to this address
|
||||
*/
|
||||
IPv4Address operator&(const IPv4Address& mask) const;
|
||||
|
||||
/**
|
||||
* \brief Returns true if this is a private IPv4 address.
|
||||
|
||||
@@ -206,6 +206,13 @@ public:
|
||||
friend std::ostream& operator<<(std::ostream& os, const IPv6Address& addr) {
|
||||
return os << addr.to_string();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Applies a mask to an address
|
||||
*/
|
||||
TINS_API friend IPv6Address operator&(const IPv6Address& lhs, const IPv6Address& rhs);
|
||||
|
||||
private:
|
||||
void init(const char* addr);
|
||||
|
||||
|
||||
@@ -443,19 +443,5 @@ IPv6Address last_address_from_mask(IPv6Address addr, const IPv6Address& mask) {
|
||||
return addr;
|
||||
}
|
||||
|
||||
IPv4Address first_address_from_mask(IPv4Address addr, IPv4Address mask) {
|
||||
uint32_t addr_int = Endian::be_to_host<uint32_t>(addr),
|
||||
mask_int = Endian::be_to_host<uint32_t>(mask);
|
||||
return IPv4Address(Endian::host_to_be(addr_int & mask_int));
|
||||
}
|
||||
|
||||
IPv6Address first_address_from_mask(IPv6Address addr, const IPv6Address& mask) {
|
||||
IPv6Address::iterator addr_iter = addr.begin();
|
||||
for (IPv6Address::const_iterator it = mask.begin(); it != mask.end(); ++it, ++addr_iter) {
|
||||
*addr_iter = *addr_iter & *it;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
} // namespace Internals
|
||||
} // namespace Tins
|
||||
|
||||
@@ -139,4 +139,8 @@ bool IPv4Address::is_broadcast() const {
|
||||
return* this == broadcast;
|
||||
}
|
||||
|
||||
IPv4Address IPv4Address::operator&(const IPv4Address& mask) const {
|
||||
return IPv4Address(Endian::be_to_host(ip_addr_ & mask.ip_addr_));
|
||||
}
|
||||
|
||||
} // Tins
|
||||
|
||||
@@ -132,4 +132,13 @@ bool IPv6Address::is_multicast() const {
|
||||
return multicast_range.contains(*this);
|
||||
}
|
||||
|
||||
IPv6Address operator&(const IPv6Address& lhs, const IPv6Address& rhs) {
|
||||
IPv6Address output = lhs;
|
||||
IPv6Address::iterator addr_iter = output.begin();
|
||||
for (IPv6Address::const_iterator it = rhs.begin(); it != rhs.end(); ++it, ++addr_iter) {
|
||||
*addr_iter = *addr_iter & *it;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
} // Tins
|
||||
|
||||
@@ -63,7 +63,7 @@ ADD_CUSTOM_TARGET(
|
||||
ICMPv6Test
|
||||
IPTest
|
||||
IPReassemblerTest
|
||||
IPAddressTest
|
||||
IPv4AddressTest
|
||||
IPSecTest
|
||||
IPv6Test
|
||||
IPv6AddressTest
|
||||
@@ -102,16 +102,16 @@ ADD_EXECUTABLE(DHCPv6Test EXCLUDE_FROM_ALL dhcpv6.cpp)
|
||||
ADD_EXECUTABLE(DNSTest EXCLUDE_FROM_ALL dns.cpp)
|
||||
ADD_EXECUTABLE(Dot1QTest EXCLUDE_FROM_ALL dot1q.cpp)
|
||||
ADD_EXECUTABLE(EthernetTest EXCLUDE_FROM_ALL ethernetII.cpp)
|
||||
ADD_EXECUTABLE(HWAddressTest EXCLUDE_FROM_ALL hwaddress.cpp)
|
||||
ADD_EXECUTABLE(HWAddressTest EXCLUDE_FROM_ALL hw_address.cpp)
|
||||
ADD_EXECUTABLE(ICMPExtensionTest EXCLUDE_FROM_ALL icmp_extension.cpp)
|
||||
ADD_EXECUTABLE(ICMPTest EXCLUDE_FROM_ALL icmp.cpp)
|
||||
ADD_EXECUTABLE(ICMPv6Test EXCLUDE_FROM_ALL icmpv6.cpp)
|
||||
ADD_EXECUTABLE(IPTest EXCLUDE_FROM_ALL ip.cpp)
|
||||
ADD_EXECUTABLE(IPReassemblerTest EXCLUDE_FROM_ALL ip_reassembler.cpp)
|
||||
ADD_EXECUTABLE(IPAddressTest EXCLUDE_FROM_ALL ipaddress.cpp)
|
||||
ADD_EXECUTABLE(IPv4AddressTest EXCLUDE_FROM_ALL ip_address.cpp)
|
||||
ADD_EXECUTABLE(IPSecTest EXCLUDE_FROM_ALL ipsec.cpp)
|
||||
ADD_EXECUTABLE(IPv6Test EXCLUDE_FROM_ALL ipv6.cpp)
|
||||
ADD_EXECUTABLE(IPv6AddressTest EXCLUDE_FROM_ALL ipv6address.cpp)
|
||||
ADD_EXECUTABLE(IPv6AddressTest EXCLUDE_FROM_ALL ipv6_address.cpp)
|
||||
ADD_EXECUTABLE(LLCTest EXCLUDE_FROM_ALL llc.cpp)
|
||||
ADD_EXECUTABLE(LoopbackTest EXCLUDE_FROM_ALL loopback.cpp)
|
||||
ADD_EXECUTABLE(MPLSTest EXCLUDE_FROM_ALL mpls.cpp)
|
||||
@@ -190,7 +190,7 @@ ADD_TEST(ICMP ICMPTest)
|
||||
ADD_TEST(ICMPv6 ICMPv6Test)
|
||||
ADD_TEST(IP IPTest)
|
||||
ADD_TEST(IPReassembler IPReassemblerTest)
|
||||
ADD_TEST(IPAddress IPAddressTest)
|
||||
ADD_TEST(IPv4Address IPv4AddressTest)
|
||||
ADD_TEST(IPSec IPSecTest)
|
||||
ADD_TEST(IPv6 IPv6Test)
|
||||
ADD_TEST(IPv6Address IPv6AddressTest)
|
||||
|
||||
@@ -159,3 +159,35 @@ TEST_F(AddressRangeTest, Slash) {
|
||||
EXPECT_TRUE(range2.is_iterable());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(AddressRangeTest, SlashUsingAddressGreaterThanMask) {
|
||||
// v4
|
||||
{
|
||||
IPv4Range range1 = IPv4Range::from_mask("192.168.0.128", "255.255.255.0");
|
||||
IPv4Range range2 = IPv4Address("192.168.0.0") / 24;
|
||||
EXPECT_TRUE(std::equal(range1.begin(), range1.end(), range2.begin()));
|
||||
EXPECT_TRUE(std::equal(range2.begin(), range2.end(), range1.begin()));
|
||||
EXPECT_TRUE(range1.is_iterable());
|
||||
EXPECT_TRUE(range2.is_iterable());
|
||||
}
|
||||
// v6
|
||||
{
|
||||
IPv6Range range1 = IPv6Range::from_mask("dead:beef::1200",
|
||||
"ffff:ffff:ffff:ffff:ffff:ffff:ffff::");
|
||||
IPv6Range range2 = IPv6Address("dead:beef::") / 112;
|
||||
EXPECT_TRUE(std::equal(range1.begin(), range1.end(), range2.begin()));
|
||||
EXPECT_TRUE(std::equal(range2.begin(), range2.end(), range1.begin()));
|
||||
EXPECT_TRUE(range1.is_iterable());
|
||||
EXPECT_TRUE(range2.is_iterable());
|
||||
}
|
||||
{
|
||||
typedef AddressRange<HWAddress<6> > HWAddressRange;
|
||||
HWAddressRange range1 = HWAddressRange::from_mask("de:ad:be:ef:fe:00",
|
||||
"ff:ff:ff:ef:00:00");
|
||||
HWAddressRange range2 = HWAddress<6>("de:ad:be:ef:00:00") / 32;
|
||||
EXPECT_TRUE(std::equal(range1.begin(), range1.end(), range2.begin()));
|
||||
EXPECT_TRUE(std::equal(range2.begin(), range2.end(), range1.begin()));
|
||||
EXPECT_TRUE(range1.is_iterable());
|
||||
EXPECT_TRUE(range2.is_iterable());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,3 +107,11 @@ TEST_F(HWAddressTest, OutputOperator) {
|
||||
oss << addr;
|
||||
EXPECT_EQ(oss.str(), address);
|
||||
}
|
||||
|
||||
TEST_F(HWAddressTest, Mask) {
|
||||
typedef HWAddress<6> address_type;
|
||||
EXPECT_EQ(
|
||||
address_type("de:ad:be:e0:00:00"),
|
||||
address_type("de:ad:be:ef:00:00") & address_type("ff:ff:ff:f0:00:00")
|
||||
);
|
||||
}
|
||||
@@ -101,3 +101,14 @@ TEST(IPAddressTest, IsUnicast) {
|
||||
EXPECT_TRUE(IPv4Address("240.0.0.0").is_unicast());
|
||||
EXPECT_TRUE(IPv4Address("127.0.0.1").is_unicast());
|
||||
}
|
||||
|
||||
TEST(IPAddressTest, Mask) {
|
||||
EXPECT_EQ(
|
||||
IPv4Address("192.168.100.0"),
|
||||
IPv4Address("192.168.100.1") & IPv4Address("255.255.255.0")
|
||||
);
|
||||
EXPECT_EQ(
|
||||
IPv4Address("192.128.0.0"),
|
||||
IPv4Address("192.255.1.2") & IPv4Address("255.128.0.0")
|
||||
);
|
||||
}
|
||||
@@ -106,3 +106,21 @@ TEST(IPv6AddressTest, FromPrefixLength) {
|
||||
EXPECT_EQ(IPv6Address("ffff:ffff::"), IPv6Address::from_prefix_length(32));
|
||||
}
|
||||
|
||||
TEST(IPv6AddressTest, MaskAddress) {
|
||||
EXPECT_EQ(
|
||||
IPv6Address("deaf:beef::"),
|
||||
IPv6Address("deaf:beef:adad:beef::") & IPv6Address("ffff:ffff::")
|
||||
);
|
||||
EXPECT_EQ(
|
||||
IPv6Address("deaf:be00::"),
|
||||
IPv6Address("deaf:beef:adad:beef::") & IPv6Address("ffff:ff00::")
|
||||
);
|
||||
EXPECT_EQ(
|
||||
IPv6Address("deaf:b000::"),
|
||||
IPv6Address("deaf:beef:adad:beef::") & IPv6Address("ffff:f000::")
|
||||
);
|
||||
EXPECT_EQ(
|
||||
IPv6Address("deaf:a000::"),
|
||||
IPv6Address("deaf:beef:adad:beef::") & IPv6Address("ffff:e000::")
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user