Skip to content

Commit

Permalink
fix incorrect IP address range calculation when using /0 prefix (mfon…
Browse files Browse the repository at this point in the history
…tanini#484) (mfontanini#486)

According to the C/C++ Standard, for shift operations, the behavior is undefined if the right operand is equal to the width of the promoted left operand.
On a 64-bit Windows machine, this causes IP addresses 0.0.0.0 and 255.255.255.255 to have the same internal representation, leading to various issues when using a /0 prefix.
  • Loading branch information
mbcdev authored Aug 30, 2022
1 parent 18cbab4 commit eb997f5
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/ip_address.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ const AddressRange<IPv4Address> loopback_range = IPv4Address("127.0.0.0") / 8;
const AddressRange<IPv4Address> multicast_range = IPv4Address("224.0.0.0") / 4;

IPv4Address IPv4Address::from_prefix_length(uint32_t prefix_length) {
return IPv4Address(Endian::host_to_be(0xffffffff << (32 - prefix_length)));
return IPv4Address(prefix_length ? Endian::host_to_be(0xffffffff << (32 - prefix_length)) : 0u);
}

IPv4Address::IPv4Address(uint32_t ip)
Expand Down
23 changes: 23 additions & 0 deletions tests/src/address_range_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,19 @@ using namespace Tins;

class AddressRangeTest : public testing::Test {
public:
void contain_tests0(const IPv4Range& range);
void contain_tests0(const IPv6Range& range);
void contain_tests24(const IPv4Range& range);
void contain_tests24(const IPv6Range& range);
void contain_tests26(const IPv4Range& range);
};

void AddressRangeTest::contain_tests0(const IPv4Range& range) {
EXPECT_TRUE(range.contains("0.0.0.0"));
EXPECT_TRUE(range.contains("192.168.1.1"));
EXPECT_TRUE(range.contains("255.255.255.255"));
}

void AddressRangeTest::contain_tests24(const IPv4Range& range) {
EXPECT_TRUE(range.contains("192.168.0.0"));
EXPECT_TRUE(range.contains("192.168.0.1"));
Expand All @@ -33,6 +41,12 @@ void AddressRangeTest::contain_tests26(const IPv4Range& range) {
EXPECT_FALSE(range.contains("192.168.254.191"));
}

void AddressRangeTest::contain_tests0(const IPv6Range& range) {
EXPECT_TRUE(range.contains("::"));
EXPECT_TRUE(range.contains("dead::1:1"));
EXPECT_TRUE(range.contains("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
}

void AddressRangeTest::contain_tests24(const IPv6Range& range) {
EXPECT_TRUE(range.contains("dead::1"));
EXPECT_TRUE(range.contains("dead::1fee"));
Expand All @@ -42,13 +56,22 @@ void AddressRangeTest::contain_tests24(const IPv6Range& range) {
}

TEST_F(AddressRangeTest, Contains) {
contain_tests0(IPv4Range("0.0.0.0", "255.255.255.255"));
contain_tests0(IPv4Range::from_mask("0.0.0.0", "0.0.0.0"));
contain_tests0(IPv4Range::from_mask("0.0.0.0", IPv4Address::from_prefix_length(0)));
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_tests24(IPv4Range::from_mask("192.168.0.0", IPv4Address::from_prefix_length(24)));
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_tests26(IPv4Range::from_mask("192.168.254.192", IPv4Address::from_prefix_length(26)));

contain_tests0(IPv6Range("::0", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
contain_tests0(IPv6Range::from_mask("::", "::"));
contain_tests0(IPv6Range::from_mask("::", IPv6Address::from_prefix_length(0)));
contain_tests24(IPv6Range("dead::0", "dead::ffff"));
contain_tests24(IPv6Range::from_mask("dead::0", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:0"));
contain_tests24(IPv6Range::from_mask("dead::0", IPv6Address::from_prefix_length(112)));

{
AddressRange<HWAddress<6> > range("00:00:00:00:00:00", "00:00:00:00:00:ff");
Expand Down

0 comments on commit eb997f5

Please sign in to comment.