aboutsummaryrefslogtreecommitdiff
path: root/src/p2p/net_node.inl
diff options
context:
space:
mode:
Diffstat (limited to 'src/p2p/net_node.inl')
-rw-r--r--src/p2p/net_node.inl104
1 files changed, 96 insertions, 8 deletions
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
index 37a3f393d..f8011ec0e 100644
--- a/src/p2p/net_node.inl
+++ b/src/p2p/net_node.inl
@@ -155,19 +155,55 @@ namespace nodetool
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
- bool node_server<t_payload_net_handler>::is_remote_host_allowed(const epee::net_utils::network_address &address)
+ bool node_server<t_payload_net_handler>::is_remote_host_allowed(const epee::net_utils::network_address &address, time_t *t)
{
CRITICAL_REGION_LOCAL(m_blocked_hosts_lock);
+
+ const time_t now = time(nullptr);
+
+ // look in the hosts list
auto it = m_blocked_hosts.find(address);
- if(it == m_blocked_hosts.end())
- return true;
- if(time(nullptr) >= it->second)
+ if (it != m_blocked_hosts.end())
{
- m_blocked_hosts.erase(it);
- MCLOG_CYAN(el::Level::Info, "global", "Host " << address.host_str() << " unblocked.");
- return true;
+ if (now >= it->second)
+ {
+ m_blocked_hosts.erase(it);
+ MCLOG_CYAN(el::Level::Info, "global", "Host " << address.host_str() << " unblocked.");
+ it = m_blocked_hosts.end();
+ }
+ else
+ {
+ if (t)
+ *t = it->second - now;
+ return false;
+ }
}
- return false;
+
+ // manually loop in subnets
+ if (address.get_type_id() == epee::net_utils::address_type::ipv4)
+ {
+ auto ipv4_address = address.template as<epee::net_utils::ipv4_network_address>();
+ std::map<epee::net_utils::ipv4_network_subnet, time_t>::iterator it;
+ for (it = m_blocked_subnets.begin(); it != m_blocked_subnets.end(); )
+ {
+ if (now >= it->second)
+ {
+ it = m_blocked_subnets.erase(it);
+ MCLOG_CYAN(el::Level::Info, "global", "Subnet " << it->first.host_str() << " unblocked.");
+ continue;
+ }
+ if (it->first.matches(ipv4_address))
+ {
+ if (t)
+ *t = it->second - now;
+ return false;
+ }
+ ++it;
+ }
+ }
+
+ // not found in hosts or subnets, allowed
+ return true;
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
@@ -223,6 +259,58 @@ namespace nodetool
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
+ bool node_server<t_payload_net_handler>::block_subnet(const epee::net_utils::ipv4_network_subnet &subnet, time_t seconds)
+ {
+ const time_t now = time(nullptr);
+
+ CRITICAL_REGION_LOCAL(m_blocked_hosts_lock);
+ time_t limit;
+ if (now > std::numeric_limits<time_t>::max() - seconds)
+ limit = std::numeric_limits<time_t>::max();
+ else
+ limit = now + seconds;
+ m_blocked_subnets[subnet] = limit;
+
+ // drop any connection to that subnet. This should only have to look into
+ // the zone related to the connection, but really make sure everything is
+ // swept ...
+ std::vector<boost::uuids::uuid> conns;
+ for(auto& zone : m_network_zones)
+ {
+ zone.second.m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
+ {
+ if (cntxt.m_remote_address.get_type_id() != epee::net_utils::ipv4_network_address::get_type_id())
+ return true;
+ auto ipv4_address = cntxt.m_remote_address.template as<epee::net_utils::ipv4_network_address>();
+ if (subnet.matches(ipv4_address))
+ {
+ conns.push_back(cntxt.m_connection_id);
+ }
+ return true;
+ });
+ for (const auto &c: conns)
+ zone.second.m_net_server.get_config_object().close(c);
+
+ conns.clear();
+ }
+
+ MCLOG_CYAN(el::Level::Info, "global", "Subnet " << subnet.host_str() << " blocked.");
+ return true;
+ }
+ //-----------------------------------------------------------------------------------
+ template<class t_payload_net_handler>
+ bool node_server<t_payload_net_handler>::unblock_subnet(const epee::net_utils::ipv4_network_subnet &subnet)
+ {
+ CRITICAL_REGION_LOCAL(m_blocked_hosts_lock);
+ auto i = m_blocked_subnets.find(subnet);
+ if (i == m_blocked_subnets.end())
+ return false;
+ m_blocked_subnets.erase(i);
+ MCLOG_CYAN(el::Level::Info, "global", "Subnet " << subnet.host_str() << " unblocked.");
+ return true;
+ }
+ //-----------------------------------------------------------------------------------
+ template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::add_host_fail(const epee::net_utils::network_address &address)
{
if(!address.is_blockable())