2021-03-09 22:24:35 +00:00
|
|
|
#include "route_poker.hpp"
|
|
|
|
#include "abstractrouter.hpp"
|
|
|
|
#include <llarp/net/route.hpp>
|
|
|
|
#include <llarp/service/context.hpp>
|
2020-09-24 00:28:38 +00:00
|
|
|
#include <unordered_set>
|
|
|
|
|
|
|
|
namespace llarp
|
|
|
|
{
|
|
|
|
void
|
|
|
|
RoutePoker::AddRoute(huint32_t ip)
|
|
|
|
{
|
2021-02-18 23:51:43 +00:00
|
|
|
m_PokedRoutes[ip] = m_CurrentGateway;
|
2020-10-20 09:15:39 +00:00
|
|
|
if (m_CurrentGateway.h == 0)
|
|
|
|
{
|
2021-01-11 23:13:22 +00:00
|
|
|
llarp::LogDebug("RoutePoker::AddRoute no current gateway, cannot enable route.");
|
2020-10-20 09:15:39 +00:00
|
|
|
}
|
|
|
|
else if (m_Enabled or m_Enabling)
|
|
|
|
{
|
2021-01-11 23:13:22 +00:00
|
|
|
llarp::LogInfo(
|
|
|
|
"RoutePoker::AddRoute enabled, enabling route to ", ip, " via ", m_CurrentGateway);
|
2020-10-20 09:15:39 +00:00
|
|
|
EnableRoute(ip, m_CurrentGateway);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-01-11 23:13:22 +00:00
|
|
|
llarp::LogDebug("RoutePoker::AddRoute disabled, not enabling route.");
|
2020-10-20 09:15:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
RoutePoker::DisableRoute(huint32_t ip, huint32_t gateway)
|
|
|
|
{
|
|
|
|
net::DelRoute(ip.ToString(), gateway.ToString());
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
RoutePoker::EnableRoute(huint32_t ip, huint32_t gateway)
|
|
|
|
{
|
|
|
|
net::AddRoute(ip.ToString(), gateway.ToString());
|
2020-09-24 00:28:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
RoutePoker::DelRoute(huint32_t ip)
|
|
|
|
{
|
|
|
|
const auto itr = m_PokedRoutes.find(ip);
|
|
|
|
if (itr == m_PokedRoutes.end())
|
|
|
|
return;
|
2020-10-20 09:15:39 +00:00
|
|
|
|
|
|
|
if (m_Enabled)
|
|
|
|
DisableRoute(itr->first, itr->second);
|
2021-02-18 23:51:43 +00:00
|
|
|
m_PokedRoutes.erase(itr);
|
2020-09-24 00:28:38 +00:00
|
|
|
}
|
|
|
|
|
2020-10-20 09:15:39 +00:00
|
|
|
void
|
|
|
|
RoutePoker::Init(AbstractRouter* router, bool enable)
|
|
|
|
{
|
|
|
|
m_Router = router;
|
|
|
|
m_Enabled = enable;
|
|
|
|
m_CurrentGateway = {0};
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
RoutePoker::DeleteAllRoutes()
|
2020-09-24 00:28:38 +00:00
|
|
|
{
|
2020-10-20 09:15:39 +00:00
|
|
|
// DelRoute will check enabled, so no need here
|
2020-09-24 00:28:38 +00:00
|
|
|
for (const auto& [ip, gateway] : m_PokedRoutes)
|
2020-10-20 09:15:39 +00:00
|
|
|
DelRoute(ip);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
RoutePoker::DisableAllRoutes()
|
|
|
|
{
|
|
|
|
for (const auto& [ip, gateway] : m_PokedRoutes)
|
|
|
|
DisableRoute(ip, gateway);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
RoutePoker::EnableAllRoutes()
|
|
|
|
{
|
|
|
|
for (auto& [ip, gateway] : m_PokedRoutes)
|
|
|
|
{
|
|
|
|
gateway = m_CurrentGateway;
|
|
|
|
EnableRoute(ip, m_CurrentGateway);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RoutePoker::~RoutePoker()
|
|
|
|
{
|
2020-10-29 14:19:45 +00:00
|
|
|
for (const auto& [ip, gateway] : m_PokedRoutes)
|
2021-01-11 23:13:22 +00:00
|
|
|
{
|
|
|
|
if (gateway.h)
|
|
|
|
net::DelRoute(ip.ToString(), gateway.ToString());
|
|
|
|
}
|
2020-09-24 00:28:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<huint32_t>
|
2020-10-20 09:15:39 +00:00
|
|
|
RoutePoker::GetDefaultGateway() const
|
2020-09-24 00:28:38 +00:00
|
|
|
{
|
2020-10-20 09:15:39 +00:00
|
|
|
if (not m_Router)
|
|
|
|
throw std::runtime_error("Attempting to use RoutePoker before calling Init");
|
|
|
|
|
|
|
|
const auto ep = m_Router->hiddenServiceContext().GetDefault();
|
2020-09-24 00:28:38 +00:00
|
|
|
const auto gateways = net::GetGatewaysNotOnInterface(ep->GetIfName());
|
2021-01-11 23:13:22 +00:00
|
|
|
if (gateways.empty())
|
|
|
|
{
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
2020-09-24 00:28:38 +00:00
|
|
|
huint32_t addr{};
|
2021-01-11 23:13:22 +00:00
|
|
|
addr.FromString(gateways[0]);
|
2020-09-24 00:28:38 +00:00
|
|
|
return addr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-10-20 09:15:39 +00:00
|
|
|
RoutePoker::Update()
|
2020-09-24 00:28:38 +00:00
|
|
|
{
|
2020-10-20 09:15:39 +00:00
|
|
|
if (not m_Router)
|
|
|
|
throw std::runtime_error("Attempting to use RoutePoker before calling Init");
|
|
|
|
|
2021-02-08 12:44:01 +00:00
|
|
|
// check for network
|
2020-10-20 09:15:39 +00:00
|
|
|
const auto maybe = GetDefaultGateway();
|
2020-09-24 00:28:38 +00:00
|
|
|
if (not maybe.has_value())
|
|
|
|
{
|
|
|
|
LogError("Network is down");
|
2021-02-08 12:44:01 +00:00
|
|
|
// mark network lost
|
|
|
|
m_HasNetwork = false;
|
2020-09-24 00:28:38 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
const huint32_t gateway = *maybe;
|
2021-02-08 12:44:01 +00:00
|
|
|
|
|
|
|
const bool gatewayChanged = m_CurrentGateway.h != 0 and m_CurrentGateway != gateway;
|
|
|
|
|
|
|
|
if (m_CurrentGateway != gateway)
|
2020-09-24 00:28:38 +00:00
|
|
|
{
|
|
|
|
LogInfo("found default gateway: ", gateway);
|
|
|
|
m_CurrentGateway = gateway;
|
2021-02-08 12:44:01 +00:00
|
|
|
if (m_Enabling)
|
|
|
|
{
|
|
|
|
EnableAllRoutes();
|
2021-02-17 18:36:57 +00:00
|
|
|
Up();
|
2021-02-08 12:44:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// revive network connectitivity on gateway change or network wakeup
|
|
|
|
if (gatewayChanged or not m_HasNetwork)
|
|
|
|
{
|
|
|
|
LogInfo("our network changed, thawing router state");
|
|
|
|
m_Router->Thaw();
|
|
|
|
m_HasNetwork = true;
|
2020-09-24 00:28:38 +00:00
|
|
|
}
|
|
|
|
}
|
2020-10-20 09:15:39 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
RoutePoker::Enable()
|
|
|
|
{
|
|
|
|
if (m_Enabled)
|
|
|
|
return;
|
|
|
|
|
|
|
|
m_Enabling = true;
|
|
|
|
Update();
|
|
|
|
m_Enabling = false;
|
|
|
|
m_Enabled = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
RoutePoker::Disable()
|
|
|
|
{
|
|
|
|
if (not m_Enabled)
|
|
|
|
return;
|
|
|
|
|
|
|
|
DisableAllRoutes();
|
2021-02-18 23:24:50 +00:00
|
|
|
m_Enabled = false;
|
2020-10-20 09:15:39 +00:00
|
|
|
}
|
2021-02-16 15:59:18 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
RoutePoker::Up()
|
|
|
|
{
|
|
|
|
// explicit route pokes for first hops
|
|
|
|
m_Router->ForEachPeer(
|
2021-02-22 15:01:05 +00:00
|
|
|
[&](auto session, auto) mutable { AddRoute(session->GetRemoteEndpoint().asIPv4()); },
|
|
|
|
false);
|
2021-02-16 15:59:18 +00:00
|
|
|
// add default route
|
|
|
|
const auto ep = m_Router->hiddenServiceContext().GetDefault();
|
|
|
|
net::AddDefaultRouteViaInterface(ep->GetIfName());
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
RoutePoker::Down()
|
|
|
|
{
|
|
|
|
// unpoke routes for first hops
|
|
|
|
m_Router->ForEachPeer(
|
2021-02-22 15:01:05 +00:00
|
|
|
[&](auto session, auto) mutable { DelRoute(session->GetRemoteEndpoint().asIPv4()); },
|
|
|
|
false);
|
2021-02-16 15:59:18 +00:00
|
|
|
// remove default route
|
|
|
|
const auto ep = m_Router->hiddenServiceContext().GetDefault();
|
|
|
|
net::DelDefaultRouteViaInterface(ep->GetIfName());
|
|
|
|
}
|
|
|
|
|
2020-09-24 00:28:38 +00:00
|
|
|
} // namespace llarp
|