Skip to content

Commit

Permalink
Add tests for ip address manipulation functions
Browse files Browse the repository at this point in the history
  • Loading branch information
pwojcikdev committed Mar 25, 2024
1 parent 31e3f12 commit 793bd07
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 8 deletions.
85 changes: 85 additions & 0 deletions nano/core_test/network_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,88 @@ TEST (network_functions, network_range_ipv4)
auto address2_subnet (nano::transport::map_address_to_subnetwork (address2));
ASSERT_EQ (subnet2.network (), address2_subnet);
}

TEST (network_functions, ipv4_address_or_ipv6_subnet)
{
// IPv4 mapped as IPv6 address should return the original IPv4 address
boost::asio::ip::address addr1 = boost::asio::ip::address::from_string ("192.168.1.1");
boost::asio::ip::address addr2 = boost::asio::ip::address::from_string ("::ffff:192.168.1.1");
ASSERT_EQ (nano::transport::ipv4_address_or_ipv6_subnet (addr1), addr2);

// IPv6 address within the same /48 subnet should return the network prefix
boost::asio::ip::address addr3 = boost::asio::ip::address::from_string ("2001:0db8:85a3:0000:0000:8a2e:0370:7334");
boost::asio::ip::address addr4 = boost::asio::ip::address::from_string ("2001:0db8:85a3::");
ASSERT_EQ (nano::transport::ipv4_address_or_ipv6_subnet (addr3), addr4);

// Different IPv6 address outside the /48 subnet should not match
boost::asio::ip::address addr5 = boost::asio::ip::address::from_string ("2001:0db8:85a4:0001:0000:8a2e:0370:7334");
ASSERT_NE (nano::transport::ipv4_address_or_ipv6_subnet (addr3), nano::transport::ipv4_address_or_ipv6_subnet (addr5));
}

TEST (network_functions, is_same_ip)
{
// Same IPv4 addresses
boost::asio::ip::address ipv4_addr1 = boost::asio::ip::address::from_string ("192.168.1.1");
ASSERT_TRUE (nano::transport::is_same_ip (ipv4_addr1, ipv4_addr1));

// IPv4 and its IPv6 mapped form
boost::asio::ip::address ipv6_mapped_ipv4 = boost::asio::ip::address::from_string ("::ffff:192.168.1.1");
ASSERT_TRUE (nano::transport::is_same_ip (ipv4_addr1, ipv6_mapped_ipv4));
}

TEST (network_functions, is_same_ipv4)
{
// Same IPv4 addresses
boost::asio::ip::address ipv4_addr1 = boost::asio::ip::address::from_string ("192.168.1.1");
ASSERT_TRUE (nano::transport::is_same_ip (ipv4_addr1, ipv4_addr1));

// IPv4 and its IPv6 mapped form
boost::asio::ip::address ipv6_mapped_ipv4 = boost::asio::ip::address::from_string ("::ffff:192.168.1.1");
ASSERT_TRUE (nano::transport::is_same_ip (ipv4_addr1, ipv6_mapped_ipv4));
}

TEST (network_functions, is_same_ipv6)
{
// Two different IPv6 addresses within the same /48 subnet
boost::asio::ip::address ipv6_addr1 = boost::asio::ip::address::from_string ("2001:db8::1");
boost::asio::ip::address ipv6_addr2 = boost::asio::ip::address::from_string ("2001:db8::2");
ASSERT_TRUE (nano::transport::is_same_ip (ipv6_addr1, ipv6_addr2));

// Two different IPv6 addresses in different /48 subnets
boost::asio::ip::address ipv6_addr3 = boost::asio::ip::address::from_string ("2001:db8:1::1");
ASSERT_FALSE (nano::transport::is_same_ip (ipv6_addr1, ipv6_addr3));
}

TEST (network_functions, is_different_ip_family)
{
boost::asio::ip::address addr1 = boost::asio::ip::address::from_string ("192.168.1.1");
boost::asio::ip::address addr2 = boost::asio::ip::address::from_string ("::1");
ASSERT_FALSE (nano::transport::is_same_ip (addr1, addr2));
}

TEST (network_functions, is_same_ip_v4_mapped)
{
boost::asio::ip::address addr1 = boost::asio::ip::address::from_string ("::ffff:192.168.1.1");
boost::asio::ip::address addr2 = boost::asio::ip::address::from_string ("192.168.1.1");
ASSERT_TRUE (nano::transport::is_same_ip (addr1, addr2));

boost::asio::ip::address addr3 = boost::asio::ip::address::from_string ("10.0.0.1");
ASSERT_FALSE (nano::transport::is_same_ip (addr1, addr3));
}

TEST (network_functions, map_ipv4_address_to_subnetwork)
{
boost::asio::ip::address addr = boost::asio::ip::address::from_string ("192.168.1.100");
auto subnetwork = nano::transport::map_address_to_subnetwork (addr);
// Assuming a /24 subnet mask for IPv4, all addresses in 192.168.1.x should map to the same network
// Automatically maps to IPv6
ASSERT_EQ (subnetwork.to_string (), "::ffff:192.168.1.0");
}

TEST (network_functions, map_ipv6_address_to_subnetwork)
{
boost::asio::ip::address addr = boost::asio::ip::address::from_string ("2001:db8:abcd:0012::0");
auto subnetwork = nano::transport::map_address_to_subnetwork (addr);
// Assuming a /32 subnet mask for IPv6
ASSERT_EQ (subnetwork.to_string (), "2001:db8::");
}
13 changes: 7 additions & 6 deletions nano/node/transport/transport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,18 @@ nano::tcp_endpoint nano::transport::map_endpoint_to_tcp (nano::endpoint const &
return { endpoint_a.address (), endpoint_a.port () };
}

boost::asio::ip::address nano::transport::map_address_to_subnetwork (boost::asio::ip::address const & address_a)
boost::asio::ip::address nano::transport::map_address_to_subnetwork (boost::asio::ip::address address_a)
{
debug_assert (address_a.is_v6 ());
static short const ipv6_subnet_prefix_length = 32; // Equivalent to network prefix /32.
static short const ipv4_subnet_prefix_length = (128 - 32) + 24; // Limits for /24 IPv4 subnetwork
address_a = mapped_from_v4_or_v6 (address_a);
static short const ipv6_subnet_prefix_length = 32; // Equivalent to network ipv6 prefix /32.
static short const ipv4_subnet_prefix_length = (128 - 32) + 24; // Limits for /24 IPv4 subnetwork (we're using mapped IPv4 to IPv6 addresses, hence (128 - 32))
return address_a.to_v6 ().is_v4_mapped () ? boost::asio::ip::make_network_v6 (address_a.to_v6 (), ipv4_subnet_prefix_length).network () : boost::asio::ip::make_network_v6 (address_a.to_v6 (), ipv6_subnet_prefix_length).network ();
}

boost::asio::ip::address nano::transport::ipv4_address_or_ipv6_subnet (boost::asio::ip::address const & address_a)
boost::asio::ip::address nano::transport::ipv4_address_or_ipv6_subnet (boost::asio::ip::address address_a)
{
debug_assert (address_a.is_v6 ());
address_a = mapped_from_v4_or_v6 (address_a);
// Assuming /48 subnet prefix for IPv6 as it's relatively easy to acquire such a /48 address range
static short const ipv6_address_prefix_length = 48; // /48 IPv6 subnetwork
return address_a.to_v6 ().is_v4_mapped () ? address_a : boost::asio::ip::make_network_v6 (address_a.to_v6 (), ipv6_address_prefix_length).network ();
}
Expand Down
4 changes: 2 additions & 2 deletions nano/node/transport/transport.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ namespace nano::transport
nano::endpoint map_endpoint_to_v6 (nano::endpoint const &);
nano::endpoint map_tcp_to_endpoint (nano::tcp_endpoint const &);
nano::tcp_endpoint map_endpoint_to_tcp (nano::endpoint const &);
boost::asio::ip::address map_address_to_subnetwork (boost::asio::ip::address const &);
boost::asio::ip::address ipv4_address_or_ipv6_subnet (boost::asio::ip::address const &);
boost::asio::ip::address map_address_to_subnetwork (boost::asio::ip::address);
boost::asio::ip::address ipv4_address_or_ipv6_subnet (boost::asio::ip::address);
boost::asio::ip::address_v6 mapped_from_v4_bytes (unsigned long);
boost::asio::ip::address_v6 mapped_from_v4_or_v6 (boost::asio::ip::address const &);
bool is_ipv4_or_v4_mapped_address (boost::asio::ip::address const &);
Expand Down

0 comments on commit 793bd07

Please sign in to comment.