mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 02:35:57 +01:00
Added IPv4Address, IPv6Address and HWAddress<> 'is_multicast' member function.
This commit is contained in:
@@ -294,6 +294,16 @@ private:
|
||||
address_type first, last;
|
||||
bool only_hosts;
|
||||
};
|
||||
|
||||
/**
|
||||
* An IPv4 address range.
|
||||
*/
|
||||
typedef AddressRange<IPv4Address> IPv4Range;
|
||||
|
||||
/**
|
||||
* An IPv6 address range.
|
||||
*/
|
||||
typedef AddressRange<IPv6Address> IPv6Range;
|
||||
} // namespace Tins
|
||||
|
||||
#endif // TINS_ADDRESS_RANGE
|
||||
@@ -234,6 +234,13 @@ public:
|
||||
return *std::min_element(begin(), end()) == 0xff;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Indicates whether this is a multicast address
|
||||
*/
|
||||
bool is_multicast() const {
|
||||
return (buffer[0] & 0x01);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert this address to a hex-notation std::string address.
|
||||
*
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <stdint.h>
|
||||
#include "constants.h"
|
||||
#include "pdu.h"
|
||||
#include "hw_address.h"
|
||||
|
||||
/**
|
||||
* \cond
|
||||
@@ -42,6 +43,7 @@
|
||||
namespace Tins {
|
||||
class IPv4Address;
|
||||
class IPv6Address;
|
||||
|
||||
namespace Internals {
|
||||
template<size_t n>
|
||||
class byte_array {
|
||||
@@ -114,10 +116,46 @@ PDU *pdu_from_flag(PDU::PDUType type, const uint8_t *buffer, uint32_t size);
|
||||
|
||||
Constants::Ethernet::e pdu_flag_to_ether_type(PDU::PDUType flag);
|
||||
|
||||
template<typename T>
|
||||
bool increment_buffer(T &addr) {
|
||||
typename T::iterator it = addr.end() - 1;
|
||||
while(it >= addr.begin() && *it == 0xff) {
|
||||
*it = 0;
|
||||
--it;
|
||||
}
|
||||
// reached end
|
||||
if(it < addr.begin())
|
||||
return true;
|
||||
(*it)++;
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool decrement_buffer(T &addr) {
|
||||
typename T::iterator it = addr.end() - 1;
|
||||
while(it >= addr.begin() && *it == 0) {
|
||||
*it = 0xff;
|
||||
--it;
|
||||
}
|
||||
// reached end
|
||||
if(it < addr.begin())
|
||||
return true;
|
||||
(*it)--;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool increment(IPv4Address &addr);
|
||||
bool increment(IPv6Address &addr);
|
||||
bool decrement(IPv4Address &addr);
|
||||
bool decrement(IPv6Address &addr);
|
||||
template<size_t n>
|
||||
bool increment(HWAddress<n> &addr) {
|
||||
return increment_buffer(addr);
|
||||
}
|
||||
template<size_t n>
|
||||
bool decrement(HWAddress<n> &addr) {
|
||||
return decrement_buffer(addr);
|
||||
}
|
||||
|
||||
inline bool is_dot3(const uint8_t *ptr, size_t sz) {
|
||||
return (sz >= 13 && ptr[12] < 8);
|
||||
|
||||
@@ -144,6 +144,14 @@ public:
|
||||
* 127.0.0.0/8, false otherwise.
|
||||
*/
|
||||
bool is_loopback() const;
|
||||
|
||||
/**
|
||||
* \brief Returns true if this is a multicast IPv4 address.
|
||||
*
|
||||
* This method returns true if this address is in the address range
|
||||
* 224.0.0.0/4, false otherwise.
|
||||
*/
|
||||
bool is_multicast() const;
|
||||
|
||||
/**
|
||||
* \brief Writes this address to a std::ostream.
|
||||
|
||||
@@ -191,6 +191,14 @@ public:
|
||||
* false otherwise.
|
||||
*/
|
||||
bool is_loopback() const;
|
||||
|
||||
/**
|
||||
* \brief Returns true if this is a multicast IPv6 address.
|
||||
*
|
||||
* This method returns true if this address is in the address range
|
||||
* ff00::/8, false otherwise.
|
||||
*/
|
||||
bool is_multicast() const;
|
||||
|
||||
/**
|
||||
* \brief Writes this address in hex-notation to a std::ostream.
|
||||
|
||||
@@ -174,16 +174,7 @@ bool increment(IPv4Address &addr) {
|
||||
}
|
||||
|
||||
bool increment(IPv6Address &addr) {
|
||||
IPv6Address::iterator it = addr.end() - 1;
|
||||
while(it >= addr.begin() && *it == 0xff) {
|
||||
*it = 0;
|
||||
--it;
|
||||
}
|
||||
// reached end
|
||||
if(it < addr.begin())
|
||||
return true;
|
||||
(*it)++;
|
||||
return false;
|
||||
return increment_buffer(addr);
|
||||
}
|
||||
|
||||
bool decrement(IPv4Address &addr) {
|
||||
@@ -194,16 +185,7 @@ bool decrement(IPv4Address &addr) {
|
||||
}
|
||||
|
||||
bool decrement(IPv6Address &addr) {
|
||||
IPv6Address::iterator it = addr.end() - 1;
|
||||
while(it >= addr.begin() && *it == 0) {
|
||||
*it = 0xff;
|
||||
--it;
|
||||
}
|
||||
// reached end
|
||||
if(it < addr.begin())
|
||||
return true;
|
||||
(*it)--;
|
||||
return false;
|
||||
return decrement_buffer(addr);
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace Tins
|
||||
|
||||
@@ -43,6 +43,7 @@ const AddressRange<IPv4Address> private_ranges[] = {
|
||||
};
|
||||
|
||||
const AddressRange<IPv4Address> loopback_range = IPv4Address("127.0.0.0") / 8;
|
||||
const AddressRange<IPv4Address> multicast_range = IPv4Address("224.0.0.0") / 4;
|
||||
|
||||
IPv4Address::IPv4Address(uint32_t ip)
|
||||
: ip_addr(Endian::be_to_host(ip)) {
|
||||
@@ -118,6 +119,10 @@ bool IPv4Address::is_loopback() const {
|
||||
return loopback_range.contains(*this);
|
||||
}
|
||||
|
||||
bool IPv4Address::is_multicast() const {
|
||||
return multicast_range.contains(*this);
|
||||
}
|
||||
|
||||
AddressRange<IPv4Address> operator/(const IPv4Address &addr, int mask) {
|
||||
if(mask > 32)
|
||||
throw std::logic_error("Prefix length cannot exceed 32");
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
|
||||
namespace Tins {
|
||||
const IPv6Address loopback_address = "::1";
|
||||
const AddressRange<IPv6Address> multicast_range = IPv6Address("ff00::") / 8;
|
||||
|
||||
IPv6Address::IPv6Address() {
|
||||
std::fill(address, address + address_size, 0);
|
||||
@@ -104,6 +105,10 @@ bool IPv6Address::is_loopback() const {
|
||||
return loopback_address == *this;
|
||||
}
|
||||
|
||||
bool IPv6Address::is_multicast() const {
|
||||
return multicast_range.contains(*this);
|
||||
}
|
||||
|
||||
AddressRange<IPv6Address> operator/(const IPv6Address &addr, int mask) {
|
||||
if(mask > 128)
|
||||
throw std::logic_error("Prefix length cannot exceed 128");
|
||||
|
||||
@@ -12,12 +12,12 @@ using namespace Tins;
|
||||
|
||||
class AddressRangeTest : public testing::Test {
|
||||
public:
|
||||
void contain_tests24(const AddressRange<IPv4Address> &range);
|
||||
void contain_tests24(const AddressRange<IPv6Address> &range);
|
||||
void contain_tests26(const AddressRange<IPv4Address> &range);
|
||||
void contain_tests24(const IPv4Range &range);
|
||||
void contain_tests24(const IPv6Range &range);
|
||||
void contain_tests26(const IPv4Range &range);
|
||||
};
|
||||
|
||||
void AddressRangeTest::contain_tests24(const AddressRange<IPv4Address> &range) {
|
||||
void AddressRangeTest::contain_tests24(const IPv4Range &range) {
|
||||
EXPECT_TRUE(range.contains("192.168.0.0"));
|
||||
EXPECT_TRUE(range.contains("192.168.0.1"));
|
||||
EXPECT_TRUE(range.contains("192.168.0.254"));
|
||||
@@ -26,14 +26,14 @@ void AddressRangeTest::contain_tests24(const AddressRange<IPv4Address> &range) {
|
||||
EXPECT_FALSE(range.contains("192.168.1.1"));
|
||||
}
|
||||
|
||||
void AddressRangeTest::contain_tests26(const AddressRange<IPv4Address> &range) {
|
||||
void AddressRangeTest::contain_tests26(const IPv4Range &range) {
|
||||
EXPECT_TRUE(range.contains("192.168.254.192"));
|
||||
EXPECT_TRUE(range.contains("192.168.254.255"));
|
||||
EXPECT_FALSE(range.contains("192.168.254.0"));
|
||||
EXPECT_FALSE(range.contains("192.168.254.191"));
|
||||
}
|
||||
|
||||
void AddressRangeTest::contain_tests24(const AddressRange<IPv6Address> &range) {
|
||||
void AddressRangeTest::contain_tests24(const IPv6Range &range) {
|
||||
EXPECT_TRUE(range.contains("dead::1"));
|
||||
EXPECT_TRUE(range.contains("dead::1fee"));
|
||||
EXPECT_TRUE(range.contains("dead::ffee"));
|
||||
@@ -42,19 +42,25 @@ void AddressRangeTest::contain_tests24(const AddressRange<IPv6Address> &range) {
|
||||
}
|
||||
|
||||
TEST_F(AddressRangeTest, Contains) {
|
||||
contain_tests24(AddressRange<IPv4Address>("192.168.0.0", "192.168.0.255"));
|
||||
contain_tests24(AddressRange<IPv4Address>::from_mask("192.168.0.0", "255.255.255.0"));
|
||||
contain_tests26(AddressRange<IPv4Address>("192.168.254.192", "192.168.254.255"));
|
||||
contain_tests26(AddressRange<IPv4Address>::from_mask("192.168.254.192", "255.255.255.192"));
|
||||
contain_tests24(IPv4Range("192.168.0.0", "192.168.0.255"));
|
||||
contain_tests24(IPv4Range::from_mask("192.168.0.0", "255.255.255.0"));
|
||||
contain_tests26(IPv4Range("192.168.254.192", "192.168.254.255"));
|
||||
contain_tests26(IPv4Range::from_mask("192.168.254.192", "255.255.255.192"));
|
||||
|
||||
contain_tests24(AddressRange<IPv6Address>("dead::0", "dead::ffff"));
|
||||
contain_tests24(AddressRange<IPv6Address>::from_mask("dead::0", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:0"));
|
||||
contain_tests24(IPv6Range("dead::0", "dead::ffff"));
|
||||
contain_tests24(IPv6Range::from_mask("dead::0", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:0"));
|
||||
|
||||
AddressRange<HWAddress<6> > range("00:00:00:00:00:00", "00:00:00:00:00:ff");
|
||||
EXPECT_TRUE(range.contains("00:00:00:00:00:00"));
|
||||
EXPECT_TRUE(range.contains("00:00:00:00:00:10"));
|
||||
EXPECT_TRUE(range.contains("00:00:00:00:00:ff"));
|
||||
EXPECT_FALSE(range.contains("00:00:00:00:01:00"));
|
||||
}
|
||||
|
||||
TEST_F(AddressRangeTest, Iterators) {
|
||||
// v4
|
||||
{
|
||||
AddressRange<IPv4Address> addr = AddressRange<IPv4Address>::from_mask("192.168.0.0", "255.255.255.252");
|
||||
IPv4Range addr = IPv4Range::from_mask("192.168.0.0", "255.255.255.252");
|
||||
std::vector<IPv4Address> addresses;
|
||||
addresses.push_back("192.168.0.1");
|
||||
addresses.push_back("192.168.0.2");
|
||||
@@ -62,7 +68,7 @@ TEST_F(AddressRangeTest, Iterators) {
|
||||
EXPECT_TRUE(addr.is_iterable());
|
||||
}
|
||||
{
|
||||
AddressRange<IPv4Address> addr = AddressRange<IPv4Address>::from_mask("255.255.255.252", "255.255.255.252");
|
||||
IPv4Range addr = IPv4Range::from_mask("255.255.255.252", "255.255.255.252");
|
||||
std::vector<IPv4Address> addresses;
|
||||
addresses.push_back("255.255.255.253");
|
||||
addresses.push_back("255.255.255.254");
|
||||
@@ -72,7 +78,7 @@ TEST_F(AddressRangeTest, Iterators) {
|
||||
|
||||
// v6
|
||||
{
|
||||
AddressRange<IPv6Address> addr = AddressRange<IPv6Address>::from_mask("dead::0", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc");
|
||||
IPv6Range addr = IPv6Range::from_mask("dead::0", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc");
|
||||
std::vector<IPv6Address> addresses;
|
||||
addresses.push_back("dead::1");
|
||||
addresses.push_back("dead::2");
|
||||
@@ -81,8 +87,8 @@ TEST_F(AddressRangeTest, Iterators) {
|
||||
}
|
||||
|
||||
{
|
||||
AddressRange<IPv6Address> addr =
|
||||
AddressRange<IPv6Address>::from_mask(
|
||||
IPv6Range addr =
|
||||
IPv6Range::from_mask(
|
||||
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc",
|
||||
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc"
|
||||
);
|
||||
@@ -97,16 +103,16 @@ TEST_F(AddressRangeTest, Iterators) {
|
||||
TEST_F(AddressRangeTest, Slash) {
|
||||
// v4
|
||||
{
|
||||
AddressRange<IPv4Address> range1 = AddressRange<IPv4Address>::from_mask("192.168.0.0", "255.255.255.252");
|
||||
AddressRange<IPv4Address> range2 = IPv4Address("192.168.0.0") / 30;
|
||||
IPv4Range range1 = IPv4Range::from_mask("192.168.0.0", "255.255.255.252");
|
||||
IPv4Range range2 = IPv4Address("192.168.0.0") / 30;
|
||||
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());
|
||||
}
|
||||
{
|
||||
AddressRange<IPv4Address> range1 = AddressRange<IPv4Address>::from_mask("255.255.255.252", "255.255.255.252");
|
||||
AddressRange<IPv4Address> range2 = IPv4Address("255.255.255.252") / 30;
|
||||
IPv4Range range1 = IPv4Range::from_mask("255.255.255.252", "255.255.255.252");
|
||||
IPv4Range range2 = IPv4Address("255.255.255.252") / 30;
|
||||
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());
|
||||
@@ -115,20 +121,20 @@ TEST_F(AddressRangeTest, Slash) {
|
||||
|
||||
// v6
|
||||
{
|
||||
AddressRange<IPv6Address> range1 = AddressRange<IPv6Address>::from_mask("dead::0", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc");
|
||||
AddressRange<IPv6Address> range2 = IPv6Address("dead::0") / 126;
|
||||
IPv6Range range1 = IPv6Range::from_mask("dead::0", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc");
|
||||
IPv6Range range2 = IPv6Address("dead::0") / 126;
|
||||
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());
|
||||
}
|
||||
{
|
||||
AddressRange<IPv6Address> range1 =
|
||||
AddressRange<IPv6Address>::from_mask(
|
||||
IPv6Range range1 =
|
||||
IPv6Range::from_mask(
|
||||
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc",
|
||||
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc"
|
||||
);
|
||||
AddressRange<IPv6Address> range2 = IPv6Address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc") / 126;
|
||||
IPv6Range range2 = IPv6Address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc") / 126;
|
||||
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());
|
||||
|
||||
@@ -66,6 +66,13 @@ TEST_F(HWAddressTest, IsBroadcast) {
|
||||
EXPECT_TRUE(HWAddress<6>("ff:ff:ff:ff:ff:ff").is_broadcast());
|
||||
}
|
||||
|
||||
TEST_F(HWAddressTest, IsMulticast) {
|
||||
EXPECT_TRUE(HWAddress<6>("01:02:03:04:05:06").is_multicast());
|
||||
EXPECT_TRUE(HWAddress<6>("09:02:03:04:05:06").is_multicast());
|
||||
EXPECT_TRUE(HWAddress<6>("03:02:03:04:05:06").is_multicast());
|
||||
EXPECT_FALSE(HWAddress<6>("00:02:03:04:05:06").is_multicast());
|
||||
EXPECT_FALSE(HWAddress<6>("02:02:03:04:05:06").is_multicast());
|
||||
}
|
||||
|
||||
TEST_F(HWAddressTest, CopyAssignmentOperator) {
|
||||
HWAddress<6> addr1(byte_address), addr2;
|
||||
|
||||
@@ -80,3 +80,11 @@ TEST(IPAddressTest, IsLoopback) {
|
||||
EXPECT_FALSE(IPv4Address("126.255.255.254").is_loopback());
|
||||
EXPECT_FALSE(IPv4Address("128.0.0.0").is_loopback());
|
||||
}
|
||||
|
||||
TEST(IPAddressTest, IsMulticast) {
|
||||
EXPECT_TRUE(IPv4Address("224.0.0.1").is_multicast());
|
||||
EXPECT_TRUE(IPv4Address("226.3.54.132").is_multicast());
|
||||
EXPECT_TRUE(IPv4Address("239.255.255.255").is_multicast());
|
||||
EXPECT_FALSE(IPv4Address("223.255.255.255").is_multicast());
|
||||
EXPECT_FALSE(IPv4Address("240.0.0.0").is_multicast());
|
||||
}
|
||||
|
||||
@@ -91,3 +91,12 @@ TEST(IPv6AddressTest, IsLoopback) {
|
||||
EXPECT_FALSE(IPv6Address("::2").is_loopback());
|
||||
EXPECT_FALSE(IPv6Address("ffff::2").is_loopback());
|
||||
}
|
||||
|
||||
TEST(IPv6AddressTest, IsMulticast) {
|
||||
EXPECT_TRUE(IPv6Address("ff00::1").is_multicast());
|
||||
EXPECT_TRUE(IPv6Address("ff02::1").is_multicast());
|
||||
EXPECT_TRUE(IPv6Address("ffff::ffff").is_multicast());
|
||||
EXPECT_FALSE(IPv6Address("f000::").is_multicast());
|
||||
EXPECT_FALSE(IPv6Address("feaa::dead").is_multicast());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user