mirror of
https://github.com/wownero/wownero.git
synced 2026-10-17 07:31:35 +02:00
p2p, rpc: group public IPv6 connection limits by /64
This commit is contained in:
@@ -36,6 +36,7 @@
|
||||
#include "net_utils_base.h"
|
||||
#include "http_auth.h"
|
||||
#include "http_base.h"
|
||||
#include "syncobj.h"
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "net.http"
|
||||
@@ -65,6 +66,9 @@ namespace net_utils
|
||||
critical_section m_lock;
|
||||
};
|
||||
|
||||
// RPC limits groupable IPv6 clients by /64 to avoid per-address limit bypasses.
|
||||
std::string get_rpc_connection_limit_key(const net_utils::network_address& address);
|
||||
|
||||
/************************************************************************/
|
||||
/* */
|
||||
/************************************************************************/
|
||||
|
||||
@@ -225,7 +225,7 @@ namespace net_utils
|
||||
CRITICAL_REGION_LOCAL(m_config.m_lock);
|
||||
if (m_config.m_connection_count)
|
||||
--m_config.m_connection_count;
|
||||
auto elem = m_config.m_connections.find(m_conn_context.m_remote_address.host_str());
|
||||
auto elem = m_config.m_connections.find(get_rpc_connection_limit_key(m_conn_context.m_remote_address));
|
||||
if (elem != m_config.m_connections.end())
|
||||
{
|
||||
if (elem->second == 1 || elem->second == 0)
|
||||
@@ -243,7 +243,7 @@ namespace net_utils
|
||||
bool simple_http_connection_handler<t_connection_context>::after_init_connection()
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_config.m_lock);
|
||||
++m_config.m_connections[m_conn_context.m_remote_address.host_str()];
|
||||
++m_config.m_connections[get_rpc_connection_limit_key(m_conn_context.m_remote_address)];
|
||||
++m_config.m_connection_count;
|
||||
m_initialized = true;
|
||||
return true;
|
||||
|
||||
@@ -155,7 +155,7 @@ namespace epee
|
||||
return true;
|
||||
|
||||
const bool is_private = na.is_loopback() || na.is_local();
|
||||
const auto elem = config.m_connections.find(na.host_str());
|
||||
const auto elem = config.m_connections.find(net_utils::http::get_rpc_connection_limit_key(na));
|
||||
if (elem != config.m_connections.end())
|
||||
{
|
||||
if (is_private)
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/ip/address_v6.hpp>
|
||||
#include <boost/optional/optional.hpp>
|
||||
#include <cstddef>
|
||||
#include <stdexcept>
|
||||
#include <typeinfo>
|
||||
#include <type_traits>
|
||||
@@ -214,6 +215,9 @@ namespace net_utils
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
bool should_group_ipv6_by_prefix(const boost::asio::ip::address_v6& ip);
|
||||
boost::asio::ip::address_v6 get_ipv6_subnet_address(const boost::asio::ip::address_v6& ip, const std::size_t prefix_bits);
|
||||
|
||||
inline bool operator==(const ipv6_network_address& lhs, const ipv6_network_address& rhs) noexcept
|
||||
{ return lhs.equal(rhs); }
|
||||
inline bool operator!=(const ipv6_network_address& lhs, const ipv6_network_address& rhs) noexcept
|
||||
|
||||
@@ -31,7 +31,7 @@ set(EPEE_INCLUDE_DIR_BASE "${CMAKE_CURRENT_SOURCE_DIR}/../include")
|
||||
# Add headers to the file list, to be able to search for them and autosave in IDEs.
|
||||
monero_find_all_headers(EPEE_HEADERS_PUBLIC "${EPEE_INCLUDE_DIR_BASE}")
|
||||
|
||||
monero_add_library(epee byte_slice.cpp byte_stream.cpp hex.cpp abstract_http_client.cpp http_auth.cpp mlog.cpp net_helper.cpp net_utils_base.cpp string_tools.cpp parserse_base_utils.cpp
|
||||
monero_add_library(epee byte_slice.cpp byte_stream.cpp hex.cpp abstract_http_client.cpp http_auth.cpp http_protocol_handler.cpp mlog.cpp net_helper.cpp net_utils_base.cpp string_tools.cpp parserse_base_utils.cpp
|
||||
wipeable_string.cpp levin_base.cpp memwipe.c connection_basic.cpp network_throttle.cpp network_throttle-detail.cpp mlocker.cpp buffer.cpp net_ssl.cpp
|
||||
int-util.cpp portable_storage.cpp
|
||||
misc_language.cpp
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright (c) 2026, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "net/http_protocol_handler.h"
|
||||
|
||||
namespace epee { namespace net_utils { namespace http
|
||||
{
|
||||
std::string get_rpc_connection_limit_key(const net_utils::network_address& address)
|
||||
{
|
||||
if (address.get_type_id() == net_utils::ipv6_network_address::get_type_id())
|
||||
{
|
||||
const boost::asio::ip::address_v6 ip = address.as<const net_utils::ipv6_network_address>().ip();
|
||||
if (net_utils::should_group_ipv6_by_prefix(ip))
|
||||
return net_utils::get_ipv6_subnet_address(ip, 64).to_string() + "/64";
|
||||
}
|
||||
|
||||
return address.host_str();
|
||||
}
|
||||
}}}
|
||||
@@ -1,6 +1,8 @@
|
||||
|
||||
#include "net/net_utils_base.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/asio/ip/address_v4.hpp>
|
||||
#include <boost/uuid/uuid_io.hpp>
|
||||
|
||||
@@ -53,6 +55,34 @@ namespace epee { namespace net_utils
|
||||
return ipv4_network_address{SWAP32BE(ipv4.to_uint()), address.port()};
|
||||
}
|
||||
|
||||
static bool is_ipv6_unique_local(const boost::asio::ip::address_v6& ip)
|
||||
{
|
||||
const boost::asio::ip::address_v6::bytes_type bytes = ip.to_bytes();
|
||||
return (bytes[0] & 0xfe) == 0xfc;
|
||||
}
|
||||
|
||||
bool should_group_ipv6_by_prefix(const boost::asio::ip::address_v6& ip)
|
||||
{
|
||||
return !ip.is_unspecified() && !ip.is_loopback() && !ip.is_multicast() &&
|
||||
!ip.is_link_local() && !ip.is_site_local() && !is_ipv6_unique_local(ip) &&
|
||||
!ip.is_v4_mapped();
|
||||
}
|
||||
|
||||
boost::asio::ip::address_v6 get_ipv6_subnet_address(const boost::asio::ip::address_v6& ip, const std::size_t prefix_bits)
|
||||
{
|
||||
boost::asio::ip::address_v6::bytes_type bytes = ip.to_bytes();
|
||||
const std::size_t bits = std::min(prefix_bits, std::size_t{128});
|
||||
if (bits < 128)
|
||||
{
|
||||
const std::size_t full_bytes = bits / 8;
|
||||
const std::size_t remainder_bits = bits % 8;
|
||||
if (remainder_bits != 0)
|
||||
bytes[full_bytes] &= uint8_t(0xffu << (8 - remainder_bits));
|
||||
std::fill(bytes.begin() + full_bytes + (remainder_bits != 0), bytes.end(), 0);
|
||||
}
|
||||
return boost::asio::ip::address_v6(bytes);
|
||||
}
|
||||
|
||||
|
||||
bool ipv4_network_subnet::equal(const ipv4_network_subnet& other) const noexcept
|
||||
{ return is_same_host(other) && m_mask == other.m_mask; }
|
||||
|
||||
@@ -176,7 +176,7 @@ namespace nodetool
|
||||
const command_line::arg_descriptor<bool> arg_pad_transactions = {
|
||||
"pad-transactions", "Pad relayed transactions to help defend against traffic volume analysis", false
|
||||
};
|
||||
const command_line::arg_descriptor<uint32_t> arg_max_connections_per_ip = {"max-connections-per-ip", "Maximum number of p2p connections allowed from the same IP address", 1};
|
||||
const command_line::arg_descriptor<uint32_t> arg_max_connections_per_ip = {"max-connections-per-ip", "Maximum number of inbound p2p connections allowed from the same IPv4 address or shared across a public IPv6 /64 subnet", 1};
|
||||
|
||||
boost::optional<std::vector<proxy>> get_proxies(boost::program_options::variables_map const& vm)
|
||||
{
|
||||
|
||||
+17
-1
@@ -156,6 +156,22 @@ namespace nodetool
|
||||
return is_forbidden_ipv4_mapped_ipv6_address(address);
|
||||
}
|
||||
|
||||
inline bool is_same_p2p_connection_limit_host(const epee::net_utils::network_address& left, const epee::net_utils::network_address& right)
|
||||
{
|
||||
if (left.get_type_id() == epee::net_utils::ipv6_network_address::get_type_id() &&
|
||||
right.get_type_id() == epee::net_utils::ipv6_network_address::get_type_id())
|
||||
{
|
||||
const boost::asio::ip::address_v6 left_ip = left.as<const epee::net_utils::ipv6_network_address>().ip();
|
||||
const boost::asio::ip::address_v6 right_ip = right.as<const epee::net_utils::ipv6_network_address>().ip();
|
||||
if (epee::net_utils::should_group_ipv6_by_prefix(left_ip) &&
|
||||
epee::net_utils::should_group_ipv6_by_prefix(right_ip))
|
||||
return epee::net_utils::get_ipv6_subnet_address(left_ip, 64) ==
|
||||
epee::net_utils::get_ipv6_subnet_address(right_ip, 64);
|
||||
}
|
||||
|
||||
return left.is_same_host(right);
|
||||
}
|
||||
//-----------------------------------------------------------------------------------
|
||||
template<class t_payload_net_handler>
|
||||
node_server<t_payload_net_handler>::~node_server()
|
||||
{
|
||||
@@ -3077,7 +3093,7 @@ namespace nodetool
|
||||
|
||||
m_network_zones.at(epee::net_utils::zone::public_).m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
|
||||
{
|
||||
if (cntxt.m_is_income && cntxt.m_remote_address.is_same_host(address)) {
|
||||
if (cntxt.m_is_income && is_same_p2p_connection_limit_host(cntxt.m_remote_address, address)) {
|
||||
count++;
|
||||
|
||||
// the only call location happens BEFORE foreach_connection list is updated
|
||||
|
||||
@@ -3131,7 +3131,7 @@ namespace cryptonote
|
||||
|
||||
const command_line::arg_descriptor<std::size_t> core_rpc_server::arg_rpc_max_connections_per_public_ip = {
|
||||
"rpc-max-connections-per-public-ip"
|
||||
, "Max RPC connections per public IP permitted"
|
||||
, "Max RPC connections permitted per public IPv4 address or shared across a public IPv6 /64 subnet"
|
||||
, DEFAULT_RPC_MAX_CONNECTIONS_PER_PUBLIC_IP
|
||||
};
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@ namespace
|
||||
const command_line::arg_descriptor<std::string> arg_wallet_dir = {"wallet-dir", "Directory for newly created wallets"};
|
||||
const command_line::arg_descriptor<bool> arg_prompt_for_password = {"prompt-for-password", "Prompts for password when not provided", false};
|
||||
const command_line::arg_descriptor<bool> arg_no_initial_sync = {"no-initial-sync", "Skips the initial sync before listening for connections", false};
|
||||
const command_line::arg_descriptor<std::size_t> arg_rpc_max_connections_per_public_ip = {"rpc-max-connections-per-public-ip", "Max RPC connections per public IP permitted", DEFAULT_RPC_MAX_CONNECTIONS_PER_PUBLIC_IP};
|
||||
const command_line::arg_descriptor<std::size_t> arg_rpc_max_connections_per_public_ip = {"rpc-max-connections-per-public-ip", "Max RPC connections permitted per public IPv4 address or shared across a public IPv6 /64 subnet", DEFAULT_RPC_MAX_CONNECTIONS_PER_PUBLIC_IP};
|
||||
const command_line::arg_descriptor<std::size_t> arg_rpc_max_connections_per_private_ip = {"rpc-max-connections-per-private-ip", "Max RPC connections per private and localhost IP permitted", DEFAULT_RPC_MAX_CONNECTIONS_PER_PRIVATE_IP};
|
||||
const command_line::arg_descriptor<std::size_t> arg_rpc_max_connections = {"rpc-max-connections", "Max RPC connections permitted", DEFAULT_RPC_MAX_CONNECTIONS};
|
||||
const command_line::arg_descriptor<std::size_t> arg_rpc_response_soft_limit = {"rpc-response-soft-limit", "Max response bytes that can be queued, enforced at next response attempt", DEFAULT_RPC_SOFT_LIMIT_SIZE};
|
||||
|
||||
@@ -369,6 +369,83 @@ TEST(HTTP_Server_Auth, NotRequired)
|
||||
EXPECT_FALSE(auth.get_response(http::http_request_info{}));
|
||||
}
|
||||
|
||||
TEST(HTTP, RpcConnectionLimitKeyIPv6By64)
|
||||
{
|
||||
const epee::net_utils::network_address ipv6_a{
|
||||
epee::net_utils::ipv6_network_address{
|
||||
boost::asio::ip::make_address_v6("2001:db8:abcd:1234:1111:2222:3333:4444"), 18081
|
||||
}
|
||||
};
|
||||
const epee::net_utils::network_address ipv6_b{
|
||||
epee::net_utils::ipv6_network_address{
|
||||
boost::asio::ip::make_address_v6("2001:db8:abcd:1234:ffff:eeee:dddd:cccc"), 18081
|
||||
}
|
||||
};
|
||||
const epee::net_utils::network_address ipv6_c{
|
||||
epee::net_utils::ipv6_network_address{
|
||||
boost::asio::ip::make_address_v6("2001:db8:abcd:1235::1"), 18081
|
||||
}
|
||||
};
|
||||
|
||||
EXPECT_EQ("2001:db8:abcd:1234::/64", http::get_rpc_connection_limit_key(ipv6_a));
|
||||
EXPECT_EQ(http::get_rpc_connection_limit_key(ipv6_a), http::get_rpc_connection_limit_key(ipv6_b));
|
||||
EXPECT_NE(http::get_rpc_connection_limit_key(ipv6_a), http::get_rpc_connection_limit_key(ipv6_c));
|
||||
|
||||
const epee::net_utils::network_address loopback{
|
||||
epee::net_utils::ipv6_network_address{boost::asio::ip::address_v6::loopback(), 18081}
|
||||
};
|
||||
EXPECT_EQ(loopback.host_str(), http::get_rpc_connection_limit_key(loopback));
|
||||
|
||||
const epee::net_utils::network_address link_local{
|
||||
epee::net_utils::ipv6_network_address{boost::asio::ip::make_address_v6("fe80::1"), 18081}
|
||||
};
|
||||
EXPECT_EQ(link_local.host_str(), http::get_rpc_connection_limit_key(link_local));
|
||||
|
||||
const epee::net_utils::network_address unique_local_fc{
|
||||
epee::net_utils::ipv6_network_address{boost::asio::ip::make_address_v6("fc00::1"), 18081}
|
||||
};
|
||||
EXPECT_EQ(unique_local_fc.host_str(), http::get_rpc_connection_limit_key(unique_local_fc));
|
||||
|
||||
const epee::net_utils::network_address unique_local_fd{
|
||||
epee::net_utils::ipv6_network_address{boost::asio::ip::make_address_v6("fd00::1"), 18081}
|
||||
};
|
||||
EXPECT_EQ(unique_local_fd.host_str(), http::get_rpc_connection_limit_key(unique_local_fd));
|
||||
|
||||
const epee::net_utils::network_address unspecified{
|
||||
epee::net_utils::ipv6_network_address{boost::asio::ip::address_v6::any(), 18081}
|
||||
};
|
||||
EXPECT_EQ(unspecified.host_str(), http::get_rpc_connection_limit_key(unspecified));
|
||||
|
||||
const epee::net_utils::network_address multicast{
|
||||
epee::net_utils::ipv6_network_address{boost::asio::ip::make_address_v6("ff00::1"), 18081}
|
||||
};
|
||||
EXPECT_EQ(multicast.host_str(), http::get_rpc_connection_limit_key(multicast));
|
||||
|
||||
const epee::net_utils::network_address site_local{
|
||||
epee::net_utils::ipv6_network_address{boost::asio::ip::make_address_v6("fec0::1"), 18081}
|
||||
};
|
||||
EXPECT_EQ(site_local.host_str(), http::get_rpc_connection_limit_key(site_local));
|
||||
|
||||
uint32_t ip = 0;
|
||||
ASSERT_TRUE(epee::string_tools::get_ip_int32_from_string(ip, "203.0.113.1"));
|
||||
const epee::net_utils::network_address ipv4{
|
||||
epee::net_utils::ipv4_network_address{ip, 18081}
|
||||
};
|
||||
EXPECT_EQ(ipv4.host_str(), http::get_rpc_connection_limit_key(ipv4));
|
||||
|
||||
boost::asio::ip::address_v6::bytes_type bytes = {};
|
||||
bytes[10] = 0xff;
|
||||
bytes[11] = 0xff;
|
||||
bytes[12] = 203;
|
||||
bytes[13] = 0;
|
||||
bytes[14] = 113;
|
||||
bytes[15] = 1;
|
||||
const epee::net_utils::network_address mapped{
|
||||
epee::net_utils::ipv6_network_address{boost::asio::ip::address_v6{bytes}, 18081}
|
||||
};
|
||||
EXPECT_EQ(mapped.host_str(), http::get_rpc_connection_limit_key(mapped));
|
||||
}
|
||||
|
||||
TEST(HTTP_Server_Auth, MissingAuth)
|
||||
{
|
||||
http::http_server_auth auth{{"foo", "bar"}, rng};
|
||||
|
||||
@@ -198,6 +198,98 @@ TEST(node_server, ipv4_mapped_ipv6_address)
|
||||
EXPECT_FALSE(nodetool::should_skip_connect_address(ipv6, true));
|
||||
}
|
||||
|
||||
TEST(node_server, p2p_connection_limit_ipv6_by_64)
|
||||
{
|
||||
const epee::net_utils::network_address ipv6_a{
|
||||
epee::net_utils::ipv6_network_address{
|
||||
boost::asio::ip::make_address_v6("2001:db8:abcd:1234:1111:2222:3333:4444"), 18080
|
||||
}
|
||||
};
|
||||
const epee::net_utils::network_address ipv6_b{
|
||||
epee::net_utils::ipv6_network_address{
|
||||
boost::asio::ip::make_address_v6("2001:db8:abcd:1234:ffff:eeee:dddd:cccc"), 18080
|
||||
}
|
||||
};
|
||||
const epee::net_utils::network_address ipv6_c{
|
||||
epee::net_utils::ipv6_network_address{
|
||||
boost::asio::ip::make_address_v6("2001:db8:abcd:1235::1"), 18080
|
||||
}
|
||||
};
|
||||
|
||||
EXPECT_TRUE(nodetool::is_same_p2p_connection_limit_host(ipv6_a, ipv6_b));
|
||||
EXPECT_FALSE(nodetool::is_same_p2p_connection_limit_host(ipv6_a, ipv6_c));
|
||||
|
||||
const epee::net_utils::network_address loopback_a{
|
||||
epee::net_utils::ipv6_network_address{boost::asio::ip::address_v6::loopback(), 18080}
|
||||
};
|
||||
const epee::net_utils::network_address loopback_b{
|
||||
epee::net_utils::ipv6_network_address{boost::asio::ip::make_address_v6("::2"), 18080}
|
||||
};
|
||||
EXPECT_FALSE(nodetool::is_same_p2p_connection_limit_host(loopback_a, loopback_b));
|
||||
|
||||
const epee::net_utils::network_address link_local_a{
|
||||
epee::net_utils::ipv6_network_address{boost::asio::ip::make_address_v6("fe80::1"), 18080}
|
||||
};
|
||||
const epee::net_utils::network_address link_local_b{
|
||||
epee::net_utils::ipv6_network_address{boost::asio::ip::make_address_v6("fe80::2"), 18080}
|
||||
};
|
||||
EXPECT_FALSE(nodetool::is_same_p2p_connection_limit_host(link_local_a, link_local_b));
|
||||
|
||||
const epee::net_utils::network_address unique_local_a{
|
||||
epee::net_utils::ipv6_network_address{boost::asio::ip::make_address_v6("fc00::1"), 18080}
|
||||
};
|
||||
const epee::net_utils::network_address unique_local_b{
|
||||
epee::net_utils::ipv6_network_address{boost::asio::ip::make_address_v6("fc00::2"), 18080}
|
||||
};
|
||||
EXPECT_FALSE(nodetool::is_same_p2p_connection_limit_host(unique_local_a, unique_local_b));
|
||||
|
||||
const epee::net_utils::network_address unique_local_c{
|
||||
epee::net_utils::ipv6_network_address{boost::asio::ip::make_address_v6("fd00::1"), 18080}
|
||||
};
|
||||
const epee::net_utils::network_address unique_local_d{
|
||||
epee::net_utils::ipv6_network_address{boost::asio::ip::make_address_v6("fd00::2"), 18080}
|
||||
};
|
||||
EXPECT_FALSE(nodetool::is_same_p2p_connection_limit_host(unique_local_c, unique_local_d));
|
||||
|
||||
const epee::net_utils::network_address multicast_a{
|
||||
epee::net_utils::ipv6_network_address{boost::asio::ip::make_address_v6("ff00::1"), 18080}
|
||||
};
|
||||
const epee::net_utils::network_address multicast_b{
|
||||
epee::net_utils::ipv6_network_address{boost::asio::ip::make_address_v6("ff00::2"), 18080}
|
||||
};
|
||||
EXPECT_FALSE(nodetool::is_same_p2p_connection_limit_host(multicast_a, multicast_b));
|
||||
|
||||
const epee::net_utils::network_address site_local_a{
|
||||
epee::net_utils::ipv6_network_address{boost::asio::ip::make_address_v6("fec0::1"), 18080}
|
||||
};
|
||||
const epee::net_utils::network_address site_local_b{
|
||||
epee::net_utils::ipv6_network_address{boost::asio::ip::make_address_v6("fec0::2"), 18080}
|
||||
};
|
||||
EXPECT_FALSE(nodetool::is_same_p2p_connection_limit_host(site_local_a, site_local_b));
|
||||
|
||||
const epee::net_utils::network_address ipv4_a{MAKE_IPV4_ADDRESS_PORT(203, 0, 113, 1, 18080)};
|
||||
const epee::net_utils::network_address ipv4_b{MAKE_IPV4_ADDRESS_PORT(203, 0, 113, 2, 18080)};
|
||||
EXPECT_FALSE(nodetool::is_same_p2p_connection_limit_host(ipv4_a, ipv4_b));
|
||||
|
||||
boost::asio::ip::address_v6::bytes_type bytes_a = {};
|
||||
bytes_a[10] = 0xff;
|
||||
bytes_a[11] = 0xff;
|
||||
bytes_a[12] = 203;
|
||||
bytes_a[13] = 0;
|
||||
bytes_a[14] = 113;
|
||||
bytes_a[15] = 1;
|
||||
const epee::net_utils::network_address mapped_a{
|
||||
epee::net_utils::ipv6_network_address{boost::asio::ip::address_v6{bytes_a}, 18080}
|
||||
};
|
||||
|
||||
boost::asio::ip::address_v6::bytes_type bytes_b = bytes_a;
|
||||
bytes_b[15] = 2;
|
||||
const epee::net_utils::network_address mapped_b{
|
||||
epee::net_utils::ipv6_network_address{boost::asio::ip::address_v6{bytes_b}, 18080}
|
||||
};
|
||||
EXPECT_FALSE(nodetool::is_same_p2p_connection_limit_host(mapped_a, mapped_b));
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
using path_t = boost::filesystem::path;
|
||||
|
||||
Reference in New Issue
Block a user