From 9427b5a6d52a25d75333a34ec91c906c194f53dd Mon Sep 17 00:00:00 2001 From: moneromooo Date: Wed, 2 Dec 2020 19:36:08 +0000 Subject: [PATCH] keep only the last seen node on a given host in the white list --- contrib/epee/src/net_utils_base.cpp | 33 +++++++++++++++++++++++++++++ src/p2p/net_peerlist.cpp | 13 ++++++++++++ src/p2p/net_peerlist.h | 2 ++ 3 files changed, 48 insertions(+) diff --git a/contrib/epee/src/net_utils_base.cpp b/contrib/epee/src/net_utils_base.cpp index 5cc49cc71..6b2d27938 100644 --- a/contrib/epee/src/net_utils_base.cpp +++ b/contrib/epee/src/net_utils_base.cpp @@ -6,6 +6,17 @@ #include "string_tools.h" #include "net/local_ip.h" +static inline uint32_t make_address_v4_from_v6(const boost::asio::ip::address_v6& a) +{ + const auto &bytes = a.to_bytes(); + uint32_t v4 = 0; + v4 = (v4 << 8) | bytes[12]; + v4 = (v4 << 8) | bytes[13]; + v4 = (v4 << 8) | bytes[14]; + v4 = (v4 << 8) | bytes[15]; + return htonl(v4); +} + namespace epee { namespace net_utils { bool ipv4_network_address::equal(const ipv4_network_address& other) const noexcept @@ -83,6 +94,28 @@ namespace epee { namespace net_utils network_address::interface const* const other_self = other.self.get(); if (self_ == other_self) return true; if (!self_ || !other_self) return false; + const bool this_is_4 = get_type_id() == epee::net_utils::ipv4_network_address::get_type_id(); + const bool this_is_6 = get_type_id() == epee::net_utils::ipv6_network_address::get_type_id(); + const bool other_is_4 = other.get_type_id() == epee::net_utils::ipv4_network_address::get_type_id(); + const bool other_is_6 = other.get_type_id() == epee::net_utils::ipv6_network_address::get_type_id(); + if (this_is_4 && other_is_6) + { + const boost::asio::ip::address_v6 &actual_ip = other.as().ip(); + if (actual_ip.is_v4_mapped()) + { + const uint32_t v4ip = make_address_v4_from_v6(actual_ip); + return is_same_host(ipv4_network_address(v4ip, 0)); + } + } + else if (this_is_6 && other_is_4) + { + const boost::asio::ip::address_v6 &actual_ip = this->as().ip(); + if (actual_ip.is_v4_mapped()) + { + const uint32_t v4ip = make_address_v4_from_v6(actual_ip); + return other.is_same_host(ipv4_network_address(v4ip, 0)); + } + } if (typeid(*self_) != typeid(*other_self)) return false; return self_->is_same_host(*other_self); } diff --git a/src/p2p/net_peerlist.cpp b/src/p2p/net_peerlist.cpp index ce5c67fe5..42ab9727d 100644 --- a/src/p2p/net_peerlist.cpp +++ b/src/p2p/net_peerlist.cpp @@ -288,6 +288,19 @@ namespace nodetool copy_peers(peers.gray, m_peers_gray.get()); copy_peers(peers.anchor, m_peers_anchor.get()); } + + void peerlist_manager::evict_host_from_white_peerlist(const peerlist_entry& pr) + { + peers_indexed::index::type& sorted_index=m_peers_white.get(); + auto i = sorted_index.begin(); + while (i != sorted_index.end()) + { + if (i->adr.is_same_host(pr.adr)) + i = sorted_index.erase(i); + else + ++i; + } + } } BOOST_CLASS_VERSION(nodetool::peerlist_types, nodetool::CURRENT_PEERLIST_STORAGE_ARCHIVE_VER); diff --git a/src/p2p/net_peerlist.h b/src/p2p/net_peerlist.h index 992462d0b..c794b0f3b 100644 --- a/src/p2p/net_peerlist.h +++ b/src/p2p/net_peerlist.h @@ -109,6 +109,7 @@ namespace nodetool bool get_white_peer_by_index(peerlist_entry& p, size_t i); bool get_gray_peer_by_index(peerlist_entry& p, size_t i); template bool foreach(bool white, const F &f); + void evict_host_from_white_peerlist(const peerlist_entry& pr); bool append_with_peer_white(const peerlist_entry& pr); bool append_with_peer_gray(const peerlist_entry& pr); bool append_with_peer_anchor(const anchor_peerlist_entry& ple); @@ -345,6 +346,7 @@ namespace nodetool if(by_addr_it_wt == m_peers_white.get().end()) { //put new record into white list + evict_host_from_white_peerlist(ple); m_peers_white.insert(ple); trim_white_peerlist(); }else