Address type migration + libquic bump

- llarp/router/router.hpp, route_poker, and platform code moved to libquic Address types
- implementing required methods in link_manager for connection establishment
- coming along nicely
pull/2204/head
dr7ana 9 months ago
parent bfa9629779
commit a3e6cec7e7

@ -1 +1 @@
Subproject commit 2c6b8774c53426b4c99ca6a84c71149789cd77e4
Subproject commit 009d61e251cf4cfaa70f224b13c4bb7e905d734b

@ -103,7 +103,6 @@ endif()
add_library(lokinet-nodedb
STATIC
bootstrap.cpp
net/address_info.cpp
net/exit_info.cpp
net/traffic_policy.cpp
nodedb.cpp
@ -201,10 +200,8 @@ add_library(lokinet-layer-link
STATIC
link/connection.cpp
link/link_manager.cpp
link/session.cpp
messages/dht_immediate.cpp
messages/link_intro.cpp
messages/link_message_parser.cpp
)
# lokinet-plainquic is for holding the tunneled plainquic code, not quic wire protocol code
@ -334,7 +331,6 @@ endif()
add_library(lokinet-layers INTERFACE)
add_library(lokinet-amalgum INTERFACE)
# helper function to link a library to lokinet-base, enable lto, add to lokinet-amalgum and then link to other libs
function(lokinet_link_lib libname)
message(DEBUG "created target: ${libname}")

@ -19,7 +19,7 @@ namespace llarp::apple
}
std::shared_ptr<llarp::handlers::TunEndpoint> tun;
router->hiddenServiceContext().ForEachService([&tun](const auto& /*name*/, const auto ep) {
router->hidden_service_context().ForEachService([&tun](const auto& /*name*/, const auto ep) {
tun = std::dynamic_pointer_cast<llarp::handlers::TunEndpoint>(ep);
return !tun;
});
@ -33,13 +33,13 @@ namespace llarp::apple
if (enable)
tun->ReconfigureDNS({SockAddr{127, 0, 0, 1, {dns_trampoline_port}}});
else
tun->ReconfigureDNS(router->GetConfig()->dns.m_upstreamDNS);
tun->ReconfigureDNS(router->config()->dns.m_upstreamDNS);
trampoline_active = enable;
}
void
RouteManager::AddDefaultRouteViaInterface(vpn::NetworkInterface&)
RouteManager::add_default_route_via_interface(vpn::NetworkInterface&)
{
check_trampoline(true);
if (callback_context and route_callbacks.add_default_route)
@ -47,7 +47,7 @@ namespace llarp::apple
}
void
RouteManager::DelDefaultRouteViaInterface(vpn::NetworkInterface&)
RouteManager::delete_default_route_via_interface(vpn::NetworkInterface&)
{
check_trampoline(false);
if (callback_context and route_callbacks.del_default_route)
@ -55,7 +55,7 @@ namespace llarp::apple
}
void
RouteManager::AddRouteViaInterface(vpn::NetworkInterface&, IPRange range)
RouteManager::add_route_via_interface(vpn::NetworkInterface&, IPRange range)
{
check_trampoline(true);
if (callback_context)
@ -78,7 +78,7 @@ namespace llarp::apple
}
void
RouteManager::DelRouteViaInterface(vpn::NetworkInterface&, IPRange range)
RouteManager::delete_route_via_interface(vpn::NetworkInterface&, IPRange range)
{
check_trampoline(false);
if (callback_context)

@ -6,7 +6,7 @@
namespace llarp::apple
{
class RouteManager final : public llarp::vpn::IRouteManager
class RouteManager final : public llarp::vpn::AbstractRouteManager
{
public:
RouteManager(llarp::Context& ctx, llarp_route_callbacks rcs, void* callback_context)
@ -16,33 +16,31 @@ namespace llarp::apple
/// These are called for poking route holes, but we don't have to do that at all on macos
/// because the appex isn't subject to its own rules.
void
AddRoute(net::ipaddr_t /*ip*/, net::ipaddr_t /*gateway*/) override
add_route(oxen::quic::Address /*ip*/, oxen::quic::Address /*gateway*/) override
{}
void
DelRoute(net::ipaddr_t /*ip*/, net::ipaddr_t /*gateway*/) override
delete_route(oxen::quic::Address /*ip*/, oxen::quic::Address /*gateway*/) override
{}
void
AddDefaultRouteViaInterface(vpn::NetworkInterface& vpn) override;
add_default_route_via_interface(vpn::NetworkInterface& vpn) override;
void
DelDefaultRouteViaInterface(vpn::NetworkInterface& vpn) override;
delete_default_route_via_interface(vpn::NetworkInterface& vpn) override;
void
AddRouteViaInterface(vpn::NetworkInterface& vpn, IPRange range) override;
add_route_via_interface(vpn::NetworkInterface& vpn, IPRange range) override;
void
DelRouteViaInterface(vpn::NetworkInterface& vpn, IPRange range) override;
delete_route_via_interface(vpn::NetworkInterface& vpn, IPRange range) override;
std::vector<net::ipaddr_t>
GetGatewaysNotOnInterface(vpn::NetworkInterface& /*vpn*/) override
std::vector<oxen::quic::Address>
get_non_interface_gateways(vpn::NetworkInterface& /*vpn*/) override
{
// We can't get this on mac from our sandbox, but we don't actually need it because we
// ignore the gateway for AddRoute/DelRoute anyway, so just return a zero IP.
std::vector<net::ipaddr_t> ret;
ret.emplace_back(net::ipv4addr_t{});
return ret;
return std::vector<oxen::quic::Address>{};
}
private:

@ -9,15 +9,15 @@ namespace llarp::apple
VPNInterface::on_readable_callback on_readable,
llarp_route_callbacks route_callbacks,
void* callback_context)
: m_Context{ctx}
, m_RouteManager{ctx, std::move(route_callbacks), callback_context}
, m_PacketWriter{std::move(packet_writer)}
, m_OnReadable{std::move(on_readable)}
: _context{ctx}
, _route_manager{ctx, std::move(route_callbacks), callback_context}
, _packet_writer{std::move(packet_writer)}
, _read_cb{std::move(on_readable)}
{}
std::shared_ptr<vpn::NetworkInterface>
VPNPlatform::ObtainInterface(vpn::InterfaceInfo, Router* router)
{
return std::make_shared<VPNInterface>(m_Context, m_PacketWriter, m_OnReadable, router);
return std::make_shared<VPNInterface>(_context, _packet_writer, _read_cb, router);
}
} // namespace llarp::apple

@ -19,17 +19,17 @@ namespace llarp::apple
std::shared_ptr<vpn::NetworkInterface>
ObtainInterface(vpn::InterfaceInfo, Router*) override;
vpn::IRouteManager&
vpn::AbstractRouteManager&
RouteManager() override
{
return m_RouteManager;
return _route_manager;
}
private:
Context& m_Context;
apple::RouteManager m_RouteManager;
VPNInterface::packet_write_callback m_PacketWriter;
VPNInterface::on_readable_callback m_OnReadable;
Context& _context;
apple::RouteManager _route_manager;
VPNInterface::packet_write_callback _packet_writer;
VPNInterface::on_readable_callback _read_cb;
};
} // namespace llarp::apple

@ -34,12 +34,20 @@ namespace llarp
}
bool
Endpoint::deregister_peer(RouterID remote)
Endpoint::deregister_peer(RouterID _rid)
{
if (auto itr = conns.find(remote); itr != conns.end())
if (auto itr = conns.find(_rid); itr != conns.end())
{
itr->second->conn->close_connection();
conns.erase(itr);
auto& c = itr->second;
auto& _scid = c->conn->scid();
link_manager.router.loop()->call([this, scid = _scid, rid = _rid]() {
endpoint->close_connection(scid);
conns.erase(rid);
connid_map.erase(scid);
});
return true;
}
@ -74,8 +82,42 @@ namespace llarp
log::warning(quic_cat, "Error: failed to fetch random connection");
return false;
}
void
Endpoint::for_each_connection(std::function<void(link::Connection&)> func)
{
for (const auto& [rid, conn] : conns)
func(*conn);
}
void
Endpoint::close_connection(RouterID _rid)
{
if (auto itr = conns.find(_rid); itr != conns.end())
{
auto& c = itr->second;
auto& _scid = c->conn->scid();
link_manager.router.loop()->call([this, scid = _scid, rid = _rid]() {
endpoint->close_connection(scid);
conns.erase(rid);
connid_map.erase(scid);
});
}
}
} // namespace link
void
LinkManager::for_each_connection(std::function<void(link::Connection&)> func)
{
if (is_stopping)
return;
return ep.for_each_connection(func);
}
// TODO: pass connection open callback to endpoint constructor!
LinkManager::LinkManager(Router& r)
: router{r}
@ -85,7 +127,10 @@ namespace llarp
{reinterpret_cast<const char*>(router.identity().toPublic().data()), size_t{32}})}
, ep{quic->endpoint(
router.public_ip(),
[this](oxen::quic::connection_interface& ci) { return on_conn_open(ci); }),
[this](oxen::quic::connection_interface& ci) { return on_conn_open(ci); },
[this](oxen::quic::connection_interface& ci, uint64_t ec) {
return on_conn_closed(ci, ec);
}),
*this}
{}
@ -93,7 +138,7 @@ namespace llarp
bool
LinkManager::send_to(const RouterID& remote, bstring data, uint16_t priority)
{
if (stopping)
if (is_stopping)
return false;
if (not have_connection_to(remote))
@ -127,10 +172,16 @@ namespace llarp
}
void
LinkManager::connect_to(RouterID router)
LinkManager::close_connection(RouterID rid)
{
return ep.close_connection(rid);
}
void
LinkManager::connect_to(RouterID rid)
{
rc_lookup->get_rc(
router,
rid,
[this](
[[maybe_unused]] const RouterID& rid,
const RouterContact* const rc,
@ -177,29 +228,55 @@ namespace llarp
log::warning(quic_cat, "Connection to {} successfully established!", remote_addr);
}
// TODO: should we add routes here now that Router::SessionOpen is gone?
void
LinkManager::on_conn_open(oxen::quic::connection_interface& ci)
{
router.loop()->call([]() {});
router.loop()->call([this, &conn_interface = ci]() {
const auto& scid = conn_interface.scid();
const auto& rid = ep.connid_map[scid];
const auto& scid = ci.scid();
const auto& rid = ep.connid_map[scid];
if (auto itr = pending_conn_msg_queue.find(rid); itr != pending_conn_msg_queue.end())
{
auto& que = itr->second;
if (auto itr = pending_conn_msg_queue.find(rid); itr != pending_conn_msg_queue.end())
{
auto& que = itr->second;
while (not que.empty())
{
auto& m = que.top();
(m.is_control) ? ep.conns[rid]->control_stream->send(std::move(m.buf))
: conn_interface.send_datagram(std::move(m.buf));
while (not que.empty())
que.pop();
}
}
});
};
void
LinkManager::on_conn_closed(oxen::quic::connection_interface& ci, uint64_t ec)
{
router.loop()->call([this, &conn_interface = ci, error_code = ec]() {
const auto& scid = conn_interface.scid();
log::debug(quic_cat, "Purging quic connection CID:{} (ec: {})", scid, error_code);
if (const auto& c_itr = ep.connid_map.find(scid); c_itr != ep.connid_map.end())
{
auto& m = que.top();
const auto& rid = c_itr->second;
(m.is_control) ? ep.conns[rid]->control_stream->send(std::move(m.buf))
: ci.send_datagram(std::move(m.buf));
if (auto p_itr = pending_conn_msg_queue.find(rid); p_itr != pending_conn_msg_queue.end())
pending_conn_msg_queue.erase(p_itr);
que.pop();
if (auto m_itr = ep.conns.find(rid); m_itr != ep.conns.end())
ep.conns.erase(m_itr);
ep.connid_map.erase(c_itr);
log::debug(quic_cat, "Quic connection CID:{} purged successfully", scid);
}
}
};
});
}
bool
LinkManager::have_connection_to(const RouterID& remote, bool client_only) const
@ -228,7 +305,7 @@ namespace llarp
void
LinkManager::stop()
{
if (stopping)
if (is_stopping)
{
return;
}
@ -236,7 +313,7 @@ namespace llarp
util::Lock l(m);
LogInfo("stopping links");
stopping = true;
is_stopping = true;
quic.reset();
}
@ -244,7 +321,7 @@ namespace llarp
void
LinkManager::set_conn_persist(const RouterID& remote, llarp_time_t until)
{
if (stopping)
if (is_stopping)
return;
util::Lock l(m);
@ -279,7 +356,7 @@ namespace llarp
void
LinkManager::check_persisting_conns(llarp_time_t)
{
if (stopping)
if (is_stopping)
return;
}
@ -298,7 +375,7 @@ namespace llarp
void
LinkManager::init(RCLookupHandler* rcLookup)
{
stopping = false;
is_stopping = false;
rc_lookup = rcLookup;
node_db = router.node_db();
}

@ -9,6 +9,7 @@
#include <llarp/util/compare_ptr.hpp>
#include <external/oxen-libquic/include/quic.hpp>
#include <quic.hpp>
#include <unordered_map>
#include <set>
@ -66,6 +67,12 @@ namespace llarp
bool
establish_connection(const oxen::quic::Address& remote, RouterContact& rc, Opt&&... opts);
void
for_each_connection(std::function<void(link::Connection&)> func);
void
close_connection(RouterID rid);
private:
};
} // namespace link
@ -114,7 +121,7 @@ namespace llarp
private:
friend struct link::Endpoint;
std::atomic<bool> stopping;
std::atomic<bool> is_stopping;
// DISCUSS: is this necessary? can we reduce the amount of locking and nuke this
mutable util::Mutex m; // protects persisting_conns
@ -148,9 +155,24 @@ namespace llarp
void
on_conn_open(oxen::quic::connection_interface& ci);
void
on_conn_closed(oxen::quic::connection_interface& ci, uint64_t ec);
public:
explicit LinkManager(Router& r);
const link::Endpoint&
endpoint()
{
return ep;
}
const oxen::quic::Address&
local()
{
return addr;
}
bool
send_to(const RouterID& remote, bstring data, uint16_t priority);
@ -169,6 +191,9 @@ namespace llarp
void
connect_to(RouterContact rc);
void
close_connection(RouterID rid);
void
stop();
@ -196,6 +221,9 @@ namespace llarp
void
init(RCLookupHandler* rcLookup);
void
for_each_connection(std::function<void(link::Connection&)> func);
// Attempts to connect to a number of random routers.
//
// This will try to connect to *up to* num_conns routers, but will not

@ -10,18 +10,21 @@
namespace llarp
{
struct AbstractLinkSession;
namespace link
{
struct Connection;
}
struct Router;
/// parsed link layer message
struct AbstractLinkMessage : private AbstractSerializable
{
/// who did this message come from or is going to
AbstractLinkSession* session = nullptr;
uint64_t version = llarp::constants::proto_version;
std::shared_ptr<link::Connection> conn;
PathID_t pathid;
uint64_t version = llarp::constants::proto_version;
AbstractLinkMessage() = default;
virtual ~AbstractLinkMessage() = default;

@ -1,139 +0,0 @@
#include "link_message_parser.hpp"
#include "dht_immediate.hpp"
#include "discard.hpp"
#include "link_intro.hpp"
#include "link_message.hpp"
#include "relay_commit.hpp"
#include "relay_status.hpp"
#include "relay.hpp"
#include <llarp/router_contact.hpp>
#include <llarp/util/buffer.hpp>
#include <llarp/util/logging.hpp>
#include <memory>
namespace llarp
{
struct LinkMessageParser::msg_holder_t
{
LinkIntroMessage i;
RelayDownstreamMessage d;
RelayUpstreamMessage u;
DHTImmediateMessage m;
LR_CommitMessage c;
LR_StatusMessage s;
LinkDiscardMessage x;
msg_holder_t() = default;
};
LinkMessageParser::LinkMessageParser(Router* _router)
: router(_router), from(nullptr), msg(nullptr), holder(std::make_unique<msg_holder_t>())
{}
LinkMessageParser::~LinkMessageParser() = default;
bool
LinkMessageParser::operator()(llarp_buffer_t* buffer, llarp_buffer_t* key)
{
// we are reading the first key
if (firstkey)
{
llarp_buffer_t strbuf;
// check for empty dict
if (!key)
return false;
// we are expecting the first key to be 'a'
if (!key->startswith("a"))
{
llarp::LogWarn("message has no message type");
return false;
}
if (!bencode_read_string(buffer, &strbuf))
{
llarp::LogWarn("could not read value of message type");
return false;
}
// bad key size
if (strbuf.sz != 1)
{
llarp::LogWarn("bad mesage type size: ", strbuf.sz);
return false;
}
// create the message to parse based off message type
llarp::LogDebug("inbound message ", *strbuf.cur);
switch (*strbuf.cur)
{
case 'i':
msg = &holder->i;
break;
case 'd':
msg = &holder->d;
break;
case 'u':
msg = &holder->u;
break;
case 'm':
msg = &holder->m;
break;
case 'c':
msg = &holder->c;
break;
case 's':
msg = &holder->s;
break;
case 'x':
msg = &holder->x;
break;
default:
return false;
}
msg->session = from;
firstkey = false;
return true;
}
// check for last element
if (!key)
return MessageDone();
return msg->decode_key(*key, buffer);
}
bool
LinkMessageParser::MessageDone()
{
bool result = false;
if (msg)
{
result = msg->handle_message(router);
}
Reset();
return result;
}
bool
LinkMessageParser::ProcessFrom(AbstractLinkSession* src, const llarp_buffer_t& buf)
{
if (!src)
{
llarp::LogWarn("no link session");
return false;
}
from = src;
firstkey = true;
ManagedBuffer copy(buf);
return bencode_read_dict(*this, &copy.underlying);
}
void
LinkMessageParser::Reset()
{
if (msg)
msg->clear();
msg = nullptr;
}
} // namespace llarp

@ -1,49 +0,0 @@
#pragma once
#include <llarp/router_id.hpp>
#include <llarp/util/bencode.h>
#include <memory>
namespace llarp
{
struct Router;
struct AbstractLinkMessage;
struct AbstractLinkSession;
struct LinkMessageParser
{
LinkMessageParser(Router* router);
~LinkMessageParser();
bool
operator()(llarp_buffer_t* buffer, llarp_buffer_t* key);
/// start processig message from a link session
bool
ProcessFrom(AbstractLinkSession* from, const llarp_buffer_t& buf);
/// called when the message is fully read
/// return true when the message was accepted otherwise returns false
bool
MessageDone();
/// resets internal state
void
Reset();
private:
RouterID
GetCurrentFrom();
private:
bool firstkey;
Router* router;
AbstractLinkSession* from;
AbstractLinkMessage* msg;
struct msg_holder_t;
std::unique_ptr<msg_holder_t> holder;
};
} // namespace llarp

@ -10,134 +10,133 @@ namespace llarp
static auto logcat = log::Cat("route-poker");
void
RoutePoker::AddRoute(net::ipv4addr_t ip)
RoutePoker::add_route(oxen::quic::Address ip)
{
if (not m_up)
if (not is_up)
return;
bool has_existing = m_PokedRoutes.count(ip);
bool has_existing = poked_routes.count(ip);
// set up route and apply as needed
auto& gw = m_PokedRoutes[ip];
if (m_CurrentGateway)
auto& gw = poked_routes[ip];
if (current_gateway)
{
// remove existing mapping as needed
if (has_existing)
DisableRoute(ip, gw);
disable_route(ip, gw);
// update and add new mapping
gw = *m_CurrentGateway;
log::info(logcat, "add route {} via {}", ip, gw);
EnableRoute(ip, gw);
gw = *current_gateway;
log::info(logcat, "Added route to {} via {}", ip, gw);
enable_route(ip, gw);
}
else
gw = net::ipv4addr_t{};
gw = oxen::quic::Address{};
}
void
RoutePoker::DisableRoute(net::ipv4addr_t ip, net::ipv4addr_t gateway)
RoutePoker::disable_route(oxen::quic::Address ip, oxen::quic::Address gateway)
{
if (ip.n and gateway.n and IsEnabled())
if (ip.is_set() and gateway.is_set() and is_enabled())
{
vpn::IRouteManager& route = m_Router->vpn_platform()->RouteManager();
route.DelRoute(ip, gateway);
vpn::AbstractRouteManager& route = router.vpn_platform()->RouteManager();
route.delete_route(ip, gateway);
}
}
void
RoutePoker::EnableRoute(net::ipv4addr_t ip, net::ipv4addr_t gateway)
RoutePoker::enable_route(oxen::quic::Address ip, oxen::quic::Address gateway)
{
if (ip.n and gateway.n and IsEnabled())
if (ip.is_set() and gateway.is_set() and is_enabled())
{
vpn::IRouteManager& route = m_Router->vpn_platform()->RouteManager();
route.AddRoute(ip, gateway);
vpn::AbstractRouteManager& route = router.vpn_platform()->RouteManager();
route.add_route(ip, gateway);
}
}
void
RoutePoker::DelRoute(net::ipv4addr_t ip)
RoutePoker::delete_route(oxen::quic::Address ip)
{
const auto itr = m_PokedRoutes.find(ip);
if (itr == m_PokedRoutes.end())
return;
log::info(logcat, "del route {} via {}", itr->first, itr->second);
DisableRoute(itr->first, itr->second);
m_PokedRoutes.erase(itr);
if (const auto itr = poked_routes.find(ip); itr != poked_routes.end())
{
log::info(logcat, "Deleting route to {} via {}", itr->first, itr->second);
disable_route(itr->first, itr->second);
poked_routes.erase(itr);
}
}
void
RoutePoker::Start(Router* router)
RoutePoker::start()
{
m_Router = router;
if (not IsEnabled())
if (not is_enabled())
return;
m_Router->loop()->call_every(100ms, weak_from_this(), [self = weak_from_this()]() {
router.loop()->call_every(100ms, weak_from_this(), [self = weak_from_this()]() {
if (auto ptr = self.lock())
ptr->Update();
ptr->update();
});
}
void
RoutePoker::DeleteAllRoutes()
RoutePoker::delete_all_routes()
{
// DelRoute will check enabled, so no need here
for (const auto& item : m_PokedRoutes)
DelRoute(item.first);
for (const auto& item : poked_routes)
delete_route(item.first);
}
void
RoutePoker::DisableAllRoutes()
RoutePoker::disable_all_routes()
{
for (const auto& [ip, gateway] : m_PokedRoutes)
for (const auto& [ip, gateway] : poked_routes)
{
DisableRoute(ip, gateway);
disable_route(ip, gateway);
}
}
void
RoutePoker::RefreshAllRoutes()
RoutePoker::refresh_all_routes()
{
for (const auto& item : m_PokedRoutes)
AddRoute(item.first);
for (const auto& item : poked_routes)
add_route(item.first);
}
RoutePoker::~RoutePoker()
{
if (not m_Router or not m_Router->vpn_platform())
if (not router.vpn_platform())
return;
auto& route = m_Router->vpn_platform()->RouteManager();
for (const auto& [ip, gateway] : m_PokedRoutes)
auto& route = router.vpn_platform()->RouteManager();
for (const auto& [ip, gateway] : poked_routes)
{
if (gateway.n and ip.n)
route.DelRoute(ip, gateway);
if (gateway.is_set() and ip.is_set())
route.delete_route(ip, gateway);
}
route.DelBlackhole();
route.delete_blackhole();
}
bool
RoutePoker::IsEnabled() const
RoutePoker::is_enabled() const
{
if (not m_Router)
throw std::runtime_error{"Attempting to use RoutePoker before calling Init"};
if (m_Router->IsServiceNode())
if (router.IsServiceNode())
return false;
if (const auto& conf = m_Router->config())
if (const auto& conf = router.config())
return conf->network.m_EnableRoutePoker;
throw std::runtime_error{"Attempting to use RoutePoker with router with no config set"};
}
void
RoutePoker::Update()
RoutePoker::update()
{
if (not m_Router)
throw std::runtime_error{"Attempting to use RoutePoker before calling Init"};
// ensure we have an endpoint
auto ep = m_Router->hiddenServiceContext().GetDefault();
auto ep = router.hidden_service_context().GetDefault();
if (ep == nullptr)
return;
// ensure we have a vpn platform
auto* platform = m_Router->vpn_platform();
auto* platform = router.vpn_platform();
if (platform == nullptr)
return;
// ensure we have a vpn interface
@ -148,47 +147,48 @@ namespace llarp
auto& route = platform->RouteManager();
// get current gateways, assume sorted by lowest metric first
auto gateways = route.GetGatewaysNotOnInterface(*vpn);
std::optional<net::ipv4addr_t> next_gw;
for (auto& gateway : gateways)
auto gateways = route.get_non_interface_gateways(*vpn);
std::optional<oxen::quic::Address> next_gw;
for (auto& g : gateways)
{
if (auto* gw_ptr = std::get_if<net::ipv4addr_t>(&gateway))
if (g.is_ipv4())
{
next_gw = *gw_ptr;
next_gw = g;
break;
}
}
// update current gateway and apply state changes as needed
if (m_CurrentGateway != next_gw)
if (!(current_gateway == next_gw))
{
if (next_gw and m_CurrentGateway)
if (next_gw and current_gateway)
{
log::info(logcat, "default gateway changed from {} to {}", *m_CurrentGateway, *next_gw);
m_CurrentGateway = next_gw;
m_Router->Thaw();
RefreshAllRoutes();
log::info(logcat, "default gateway changed from {} to {}", *current_gateway, *next_gw);
current_gateway = next_gw;
router.Thaw();
refresh_all_routes();
}
else if (m_CurrentGateway)
else if (current_gateway)
{
log::warning(logcat, "default gateway {} has gone away", *m_CurrentGateway);
m_CurrentGateway = next_gw;
m_Router->Freeze();
log::warning(logcat, "default gateway {} has gone away", *current_gateway);
current_gateway = next_gw;
router.Freeze();
}
else // next_gw and not m_CurrentGateway
{
log::info(logcat, "default gateway found at {}", *next_gw);
m_CurrentGateway = next_gw;
current_gateway = next_gw;
}
}
else if (m_Router->HasClientExit())
Up();
else if (router.HasClientExit())
put_up();
}
void
RoutePoker::SetDNSMode(bool exit_mode_on) const
RoutePoker::set_dns_mode(bool exit_mode_on) const
{
auto ep = m_Router->hiddenServiceContext().GetDefault();
auto ep = router.hidden_service_context().GetDefault();
if (not ep)
return;
if (auto dns_server = ep->DNS())
@ -196,17 +196,17 @@ namespace llarp
}
void
RoutePoker::Up()
RoutePoker::put_up()
{
bool was_up = m_up;
m_up = true;
bool was_up = is_up;
is_up = true;
if (not was_up)
{
if (not IsEnabled())
if (not is_enabled())
{
log::warning(logcat, "RoutePoker coming up, but route poking is disabled by config");
}
else if (not m_CurrentGateway)
else if (not current_gateway)
{
log::warning(logcat, "RokerPoker came up, but we don't know of a gateway!");
}
@ -214,50 +214,48 @@ namespace llarp
{
log::info(logcat, "RoutePoker coming up; poking routes");
vpn::IRouteManager& route = m_Router->vpn_platform()->RouteManager();
vpn::AbstractRouteManager& route = router.vpn_platform()->RouteManager();
// black hole all routes if enabled
if (m_Router->config()->network.m_BlackholeRoutes)
route.AddBlackhole();
if (router.config()->network.m_BlackholeRoutes)
route.add_blackhole();
// explicit route pokes for first hops
m_Router->ForEachPeer(
[this](auto session, auto) { AddRoute(session->GetRemoteEndpoint().getIPv4()); },
false);
router.for_each_connection(
[this](link::Connection conn) { add_route(conn.remote_rc.addr); });
add_route(router.link_manager().local());
// add default route
const auto ep = m_Router->hiddenServiceContext().GetDefault();
const auto ep = router.hidden_service_context().GetDefault();
if (auto* vpn = ep->GetVPNInterface())
route.AddDefaultRouteViaInterface(*vpn);
route.add_default_route_via_interface(*vpn);
log::info(logcat, "route poker up");
}
}
if (not was_up)
SetDNSMode(true);
set_dns_mode(true);
}
void
RoutePoker::Down()
RoutePoker::put_down()
{
// unpoke routes for first hops
m_Router->ForEachPeer(
[this](auto session, auto) { DelRoute(session->GetRemoteEndpoint().getIPv4()); }, false);
// remove default route
if (IsEnabled() and m_up)
router.for_each_connection(
[this](link::Connection conn) { delete_route(conn.remote_rc.addr); });
if (is_enabled() and is_up)
{
vpn::IRouteManager& route = m_Router->vpn_platform()->RouteManager();
const auto ep = m_Router->hiddenServiceContext().GetDefault();
vpn::AbstractRouteManager& route = router.vpn_platform()->RouteManager();
const auto ep = router.hidden_service_context().GetDefault();
if (auto* vpn = ep->GetVPNInterface())
route.DelDefaultRouteViaInterface(*vpn);
route.delete_default_route_via_interface(*vpn);
// delete route blackhole
route.DelBlackhole();
route.delete_blackhole();
log::info(logcat, "route poker down");
}
if (m_up)
SetDNSMode(false);
m_up = false;
if (is_up)
set_dns_mode(false);
is_up = false;
}
} // namespace llarp

@ -5,6 +5,7 @@
#include <memory>
#include <optional>
#include <llarp/net/net_int.hpp>
#include <external/oxen-libquic/include/quic.hpp>
namespace llarp
{
@ -12,57 +13,60 @@ namespace llarp
struct RoutePoker : public std::enable_shared_from_this<RoutePoker>
{
RoutePoker(Router& r) : router{r}
{}
void
AddRoute(net::ipv4addr_t ip);
add_route(oxen::quic::Address ip);
void
DelRoute(net::ipv4addr_t ip);
delete_route(oxen::quic::Address ip);
void
Start(Router* router);
start();
~RoutePoker();
/// explicitly put routes up
void
Up();
put_up();
/// explicitly put routes down
void
Down();
put_down();
/// set dns resolver
/// pass in if we are using exit node mode right now as a bool
void
SetDNSMode(bool using_exit_mode) const;
set_dns_mode(bool using_exit_mode) const;
private:
void
Update();
update();
bool
IsEnabled() const;
is_enabled() const;
void
DeleteAllRoutes();
delete_all_routes();
void
DisableAllRoutes();
disable_all_routes();
void
RefreshAllRoutes();
refresh_all_routes();
void
EnableRoute(net::ipv4addr_t ip, net::ipv4addr_t gateway);
enable_route(oxen::quic::Address ip, oxen::quic::Address gateway);
void
DisableRoute(net::ipv4addr_t ip, net::ipv4addr_t gateway);
disable_route(oxen::quic::Address ip, oxen::quic::Address gateway);
std::unordered_map<net::ipv4addr_t, net::ipv4addr_t> m_PokedRoutes;
std::unordered_map<oxen::quic::Address, oxen::quic::Address> poked_routes;
std::optional<net::ipv4addr_t> m_CurrentGateway;
std::optional<oxen::quic::Address> current_gateway;
Router* m_Router = nullptr;
bool m_up{false};
Router& router;
bool is_up{false};
};
} // namespace llarp

@ -46,7 +46,7 @@ namespace llarp
static auto logcat = log::Cat("router");
Router::Router(EventLoop_ptr loop, std::shared_ptr<vpn::Platform> vpnPlatform)
: _route_poker{std::make_shared<RoutePoker>()}
: _route_poker{std::make_shared<RoutePoker>(this)}
, _lmq{std::make_shared<oxenmq::OxenMQ>()}
, _loop{std::move(loop)}
, _vpn{std::move(vpnPlatform)}
@ -56,7 +56,6 @@ namespace llarp
, _disk_thread{_lmq->add_tagged_thread("disk")}
, m_RPCServer{nullptr}
, _randomStartDelay{platform::is_simulation ? std::chrono::milliseconds{(llarp::randint() % 1250) + 2000} : 0s}
, inbound_link_msg_parser{this}
, _hidden_service_context{this}
{
_key_manager = std::make_shared<KeyManager>();
@ -64,7 +63,7 @@ namespace llarp
_lmq->MAX_MSG_SIZE = -1;
is_stopping.store(false);
is_running.store(false);
_lastTick = llarp::time_now_ms();
_last_tick = llarp::time_now_ms();
_next_explore_at = std::chrono::steady_clock::now();
loop_wakeup = _loop->make_waker([this]() { PumpLL(); });
}
@ -206,16 +205,17 @@ namespace llarp
// TODO: libquic change
bool
Router::HandleRecvLinkMessageBuffer(AbstractLinkSession* session, const llarp_buffer_t& buf)
Router::recv_link_message_buffer(std::shared_ptr<link::Connection> conn, bstring_view buf)
{
if (is_stopping)
return true;
if (!session)
if (!conn)
{
LogWarn("no link session");
log::warning(quic_cat, "No connection to pass link message buffer to!");
return false;
}
return inbound_link_msg_parser.ProcessFrom(session, buf);
}
@ -224,15 +224,9 @@ namespace llarp
{
if (IsServiceNode())
return;
/*
*TODO: investigate changes needed for libquic integration
*
linkManager().ForEachPeer([](auto peer) {
if (peer)
peer->Close();
});
*
*/
for_each_connection(
[this](link::Connection& conn) { loop()->call([&]() { conn.conn->close_connection(); }); });
}
void
@ -240,30 +234,16 @@ namespace llarp
{
if (IsServiceNode())
return;
/*
*TODO: investigate changes needed for libquic integration
*
// get pubkeys we are connected to
std::unordered_set<RouterID> peerPubkeys;
linkManager().ForEachPeer([&peerPubkeys](auto peer) {
if (not peer)
return;
peerPubkeys.emplace(peer->GetPubKey());
});
// close our sessions to them on link layer
linkManager().ForEachOutboundLink([peerPubkeys](const auto& link) {
for (const auto& remote : peerPubkeys)
link->CloseSessionTo(remote);
});
// thaw endpoints
hiddenServiceContext().ForEachService([](const auto& name, const auto& ep) -> bool {
LogInfo(name, " thawing...");
ep->Thaw();
return true;
std::unordered_set<RouterID> peer_pubkeys;
for_each_connection(
[&peer_pubkeys](link::Connection& conn) { peer_pubkeys.emplace(conn.remote_rc.pubkey); });
loop()->call([this, &peer_pubkeys]() {
for (auto& pk : peer_pubkeys)
_link_manager.close_connection(pk);
});
LogInfo("We are ready to go bruh... probably");
*
*/
}
void
@ -316,20 +296,6 @@ namespace llarp
return _outboundMessageHandler.QueueMessage(remote, msg, handler);
}
// TODO: if still needed/useful, replace this in line with libquic impl
void
Router::ForEachPeer(std::function<void(const AbstractLinkSession*, bool)>, bool) const
{
//_linkManager.ForEachPeer(visit, randomize);
}
// TODO: if still needed/useful, replace this in line with libquic impl
void
Router::ForEachPeer(std::function<void(AbstractLinkSession*)>)
{
//_linkManager.ForEachPeer(visit);
}
void
Router::try_connect(fs::path rcfile)
{
@ -347,6 +313,11 @@ namespace llarp
else
LogError(rcfile, " contains invalid RC");
}
void
Router::for_each_connection(std::function<void(link::Connection&)> func)
{
return _link_manager.for_each_connection(func);
}
bool
Router::EnsureIdentity()
@ -528,8 +499,8 @@ namespace llarp
Router::Close()
{
log::info(logcat, "closing");
if (_onDown)
_onDown();
if (_router_close_cb)
_router_close_cb();
log::debug(logcat, "stopping mainloop");
_loop->stop();
is_running.store(false);
@ -834,7 +805,7 @@ namespace llarp
// API config
if (not IsServiceNode())
{
hiddenServiceContext().AddEndpoint(conf);
hidden_service_context().AddEndpoint(conf);
}
return true;
@ -915,7 +886,7 @@ namespace llarp
node_db()->NumLoaded(),
NumberOfConnectedRouters());
if (auto ep = hiddenServiceContext().GetDefault())
if (auto ep = hidden_service_context().GetDefault())
{
fmt::format_to(
out,
@ -940,7 +911,7 @@ namespace llarp
return;
// LogDebug("tick router");
const auto now = Now();
if (const auto delta = now - _lastTick; _lastTick != 0s and delta > TimeskipDetectedDuration)
if (const auto delta = now - _last_tick; _last_tick != 0s and delta > TimeskipDetectedDuration)
{
// we detected a time skip into the futre, thaw the network
LogWarn("Timeskip of ", ToString(delta), " detected. Resetting network state");
@ -962,27 +933,27 @@ namespace llarp
_rc_lookup_handler.periodic_update(now);
const bool gotWhitelist = _rc_lookup_handler.has_received_whitelist();
const bool isSvcNode = IsServiceNode();
const bool decom = appears_decommed();
bool shouldGossip = isSvcNode and follow_whitelist and gotWhitelist
const bool has_whitelist = _rc_lookup_handler.has_received_whitelist();
const bool is_snode = IsServiceNode();
const bool is_decommed = appears_decommed();
bool should_gossip = is_snode and follow_whitelist and has_whitelist
and _rc_lookup_handler.is_session_allowed(pubkey());
if (isSvcNode
if (is_snode
and (router_contact.ExpiresSoon(now, std::chrono::milliseconds(randint() % 10000)) or (now - router_contact.last_updated) > rc_regen_interval))
{
LogInfo("regenerating RC");
if (update_rc())
{
// our rc changed so we should gossip it
shouldGossip = true;
should_gossip = true;
// remove our replay entry so it goes out
_rcGossiper.Forget(pubkey());
}
else
LogError("failed to update our RC");
}
if (shouldGossip)
if (should_gossip)
{
// if we have the whitelist enabled, we have fetched the list and we are in either
// the white or grey list, we want to gossip our RC
@ -1012,7 +983,7 @@ namespace llarp
// clients have no notion of a whilelist
// we short circuit logic here so we dont remove
// routers that are not whitelisted for first hops
if (not isSvcNode)
if (not is_snode)
{
log::trace(logcat, "Not removing {}: we are a client and it looks fine", rc.pubkey);
return false;
@ -1020,7 +991,7 @@ namespace llarp
// if we have a whitelist enabled and we don't
// have the whitelist yet don't remove the entry
if (follow_whitelist and not gotWhitelist)
if (follow_whitelist and not has_whitelist)
{
log::debug(logcat, "Skipping check on {}: don't have whitelist yet", rc.pubkey);
return false;
@ -1029,7 +1000,7 @@ namespace llarp
// the whitelist enabled and we got the whitelist
// check against the whitelist and remove if it's not
// in the whitelist OR if there is no whitelist don't remove
if (gotWhitelist and not _rc_lookup_handler.is_session_allowed(rc.pubkey))
if (has_whitelist and not _rc_lookup_handler.is_session_allowed(rc.pubkey))
{
log::debug(logcat, "Removing {}: not a valid router", rc.pubkey);
return true;
@ -1038,37 +1009,29 @@ namespace llarp
});
// find all deregistered relays
std::unordered_set<PubKey> closePeers;
std::unordered_set<PubKey> close_peers;
/*
* TODO: change for libquic
*
_linkManager.ForEachPeer([&](auto session) {
if (whitelistRouters and not gotWhitelist)
for_each_connection([this, &has_whitelist, &close_peers](link::Connection& conn) {
if (follow_whitelist && has_whitelist)
return;
if (not session)
return;
const auto pk = session->GetPubKey();
if (session->IsRelay() and not _rcLookupHandler.SessionIsAllowed(pk))
{
closePeers.emplace(pk);
}
const auto pk = conn.remote_rc.pubkey;
if (conn.remote_is_relay and not _rc_lookup_handler.is_session_allowed(pk))
close_peers.emplace(pk);
});
*
*
*/
// mark peers as de-registered
for (auto& peer : closePeers)
for (auto& peer : close_peers)
_link_manager.deregister_peer(std::move(peer));
_link_manager.check_persisting_conns(now);
size_t connected = NumberOfConnectedRouters();
const int interval = isSvcNode ? 5 : 2;
const int interval = is_snode ? 5 : 2;
const auto timepoint_now = std::chrono::steady_clock::now();
if (timepoint_now >= _next_explore_at and not decom)
if (timepoint_now >= _next_explore_at and not is_decommed)
{
_rc_lookup_handler.explore_network();
_next_explore_at = timepoint_now + std::chrono::seconds(interval);
@ -1080,19 +1043,19 @@ namespace llarp
connectToNum = strictConnect;
}
if (isSvcNode and now >= _next_decomm_warning)
if (is_snode and now >= _next_decomm_warning)
{
constexpr auto DecommissionWarnInterval = 5min;
if (auto registered = appears_registered(), funded = appears_funded();
not(registered and funded and not decom))
not(registered and funded and not is_decommed))
{
// complain about being deregistered/decommed/unfunded
log::error(
logcat,
"We are running as a service node but we seem to be {}",
not registered ? "deregistered"
: decom ? "decommissioned"
: "not fully staked");
not registered ? "deregistered"
: is_decommed ? "decommissioned"
: "not fully staked");
_next_decomm_warning = now + DecommissionWarnInterval;
}
else if (insufficient_peers())
@ -1107,7 +1070,7 @@ namespace llarp
// if we need more sessions to routers and we are not a service node kicked from the network or
// we are a client we shall connect out to others
if (connected < connectToNum and (appears_funded() or not isSvcNode))
if (connected < connectToNum and (appears_funded() or not is_snode))
{
size_t dlt = connectToNum - connected;
LogDebug("connecting to ", dlt, " random routers to keep alive");
@ -1148,25 +1111,18 @@ namespace llarp
}
}
/*
*TODO: libquic change
*
// get connected peers
std::set<dht::Key_t> peersWeHave;
_linkManager.ForEachPeer([&peersWeHave](ILinkSession* s) {
if (!s->IsEstablished())
return;
peersWeHave.emplace(s->GetPubKey());
});
// remove any nodes we don't have connections to
_dht->impl->Nodes()->RemoveIf(
[&peersWeHave](const dht::Key_t& k) -> bool { return peersWeHave.count(k) == 0; });
// expire paths
std::set<dht::Key_t> peer_keys;
for_each_connection(
[&peer_keys](link::Connection& conn) { peer_keys.emplace(conn.remote_rc.pubkey); });
dht()->Nodes()->RemoveIf(
[&peer_keys](const dht::Key_t& k) -> bool { return peer_keys.count(k) == 0; });
paths.ExpirePaths(now);
*
*/
// update tick timestamp
_lastTick = llarp::time_now_ms();
_last_tick = llarp::time_now_ms();
}
bool
@ -1175,35 +1131,6 @@ namespace llarp
return CryptoManager::instance()->sign(sig, identity(), buf);
}
// TODO: replace this in line with libquic impl
void
Router::SessionClosed(RouterID remote)
{
dht::Key_t k(remote);
dht()->Nodes()->DelNode(k);
LogInfo("Session to ", remote, " fully closed");
if (IsServiceNode())
return;
if (const auto maybe = node_db()->Get(remote); maybe.has_value())
{
for (const auto& addr : maybe->addrs)
m_RoutePoker->DelRoute(addr.IPv4());
}
}
// TODO: replace this in line with libquic impl
void
Router::ConnectionTimedOut(AbstractLinkSession* session)
{
if (_peer_db)
{
RouterID id{session->GetPubKey()};
// TODO: make sure this is a public router (on whitelist)?
_peer_db->modifyPeerStats(id, [&](PeerStats& stats) { stats.numConnectionTimeouts++; });
}
}
void
Router::modify_rc(std::function<std::optional<RouterContact>(RouterContact)> modify)
{
@ -1215,20 +1142,6 @@ namespace llarp
}
}
// TODO: replace this in line with libquic impl
bool
Router::ConnectionEstablished(AbstractLinkSession* session, bool inbound)
{
RouterID id{session->GetPubKey()};
if (_peer_db)
{
// TODO: make sure this is a public router (on whitelist)?
_peer_db->modifyPeerStats(id, [&](PeerStats& stats) { stats.numConnectionSuccesses++; });
}
notify_router_event<tooling::LinkSessionEstablishedEvent>(pubkey(), id, inbound);
return true;
}
bool
Router::GetRandomConnectedRouter(RouterContact& result) const
{
@ -1352,7 +1265,7 @@ namespace llarp
}
LogInfo("starting hidden service context...");
if (!hiddenServiceContext().StartAll())
if (!hidden_service_context().StartAll())
{
LogError("Failed to start hidden service context");
return false;
@ -1375,7 +1288,7 @@ namespace llarp
LogInfo("have ", _node_db->NumLoaded(), " routers");
_loop->call_every(ROUTER_TICK_INTERVAL, weak_from_this(), [this] { Tick(); });
_route_poker->Start(this);
_route_poker->start();
is_running.store(true);
_started_at = Now();
if (follow_whitelist)
@ -1514,7 +1427,7 @@ namespace llarp
log::reset_level(log::Level::info);
LogWarn("stopping router hard");
llarp::sys::service_manager->stopping();
hiddenServiceContext().StopAll();
hidden_service_context().StopAll();
_exit_context.Stop();
StopLinks();
Close();
@ -1541,7 +1454,7 @@ namespace llarp
log::info(logcat, "stopping");
llarp::sys::service_manager->stopping();
log::debug(logcat, "stopping hidden service context");
hiddenServiceContext().StopAll();
hidden_service_context().StopAll();
llarp::sys::service_manager->stopping();
log::debug(logcat, "stopping exit context");
_exit_context.Stop();
@ -1628,7 +1541,7 @@ namespace llarp
{
if (IsServiceNode())
return false;
const auto ep = hiddenServiceContext().GetDefault();
const auto& ep = hidden_service_context().GetDefault();
return ep and ep->HasExit();
}
@ -1690,7 +1603,7 @@ namespace llarp
void
Router::InitOutboundLinks()
{
auto addrs = config->links.OutboundLinks;
auto addrs = config()->links.OutboundLinks;
if (addrs.empty())
addrs.emplace_back(net().Wildcard());
@ -1722,7 +1635,7 @@ namespace llarp
}
void
Router::handle_router_event(tooling::RouterEventPtr event) const
Router::handle_router_event(std::unique_ptr<tooling::RouterEvent> event) const
{
LogDebug(event->ToString());
}

@ -1,5 +1,9 @@
#pragma once
#include "rc_gossiper.hpp"
#include "rc_lookup_handler.hpp"
#include "route_poker.hpp"
#include <llarp/bootstrap.hpp>
#include <llarp/config/config.hpp>
#include <llarp/config/key_manager.hpp>
@ -10,7 +14,6 @@
#include <llarp/exit/context.hpp>
#include <llarp/handlers/tun.hpp>
#include <llarp/link/link_manager.hpp>
#include <llarp/messages/link_message_parser.hpp>
#include <llarp/nodedb.hpp>
#include <llarp/path/path_context.hpp>
#include <llarp/peerstats/peer_db.hpp>
@ -18,10 +21,6 @@
#include <llarp/router_contact.hpp>
#include <llarp/consensus/reachability_testing.hpp>
#include <llarp/tooling/router_event.hpp>
#include "outbound_message_handler.hpp"
#include "rc_gossiper.hpp"
#include "rc_lookup_handler.hpp"
#include "route_poker.hpp"
#include <llarp/routing/handler.hpp>
#include <llarp/routing/message_parser.hpp>
#include <llarp/rpc/lokid_rpc_client.hpp>
@ -46,7 +45,10 @@
#include <oxenmq/address.h>
namespace libquic = oxen::quic;
/*
TONUKE:
- hidden_service_context
*/
namespace llarp
{
@ -54,11 +56,11 @@ namespace llarp
class RouteManager final /* : public Router */
{
public:
std::shared_ptr<libquic::connection_interface>
std::shared_ptr<oxen::quic::connection_interface>
get_or_connect();
private:
std::shared_ptr<libquic::Endpoint> ep;
std::shared_ptr<oxen::quic::Endpoint> ep;
};
struct Router : std::enable_shared_from_this<Router>
@ -139,9 +141,6 @@ namespace llarp
// should we be sending padded messages every interval?
bool send_padding = false;
LinkMessageParser inbound_link_msg_parser;
routing::InboundMessageParser inbound_routing_msg_parser;
service::Context _hidden_service_context;
consensus::reachability_testing router_testing;
@ -166,7 +165,7 @@ namespace llarp
protected:
void
handle_router_event(tooling::RouterEventPtr event) const;
handle_router_event(std::unique_ptr<tooling::RouterEvent> event) const;
virtual bool
disableGossipingRC_TestingOnly()
@ -175,6 +174,9 @@ namespace llarp
};
public:
void
for_each_connection(std::function<void(link::Connection&)> func);
std::shared_ptr<Config>
config() const
{
@ -364,36 +366,36 @@ namespace llarp
Sign(Signature& sig, const llarp_buffer_t& buf) const;
service::Context&
hiddenServiceContext()
hidden_service_context()
{
return _hidden_service_context;
}
const service::Context&
hiddenServiceContext() const
hidden_service_context() const
{
return _hidden_service_context;
}
llarp_time_t _lastTick = 0s;
llarp_time_t _last_tick = 0s;
std::function<void(void)> _onDown;
std::function<void(void)> _router_close_cb;
void
SetDownHook(std::function<void(void)> hook)
set_router_close_cb(std::function<void(void)> hook)
{
_onDown = hook;
_router_close_cb = hook;
}
bool
LooksAlive() const
{
const llarp_time_t now = Now();
return now <= _lastTick || (now - _lastTick) <= llarp_time_t{30000};
return now <= _last_tick || (now - _last_tick) <= llarp_time_t{30000};
}
const std::shared_ptr<RoutePoker>&
routePoker() const
route_poker() const
{
return _route_poker;
}
@ -410,8 +412,9 @@ namespace llarp
void
GossipRCIfNeeded(const RouterContact rc);
// TODO: this is not used anywhere?
bool
HandleRecvLinkMessageBuffer(AbstractLinkSession* from, const llarp_buffer_t& msg);
recv_link_message_buffer(std::shared_ptr<link::Connection> conn, bstring_view msg);
void
InitInboundLinks();
@ -513,13 +516,6 @@ namespace llarp
SendToOrQueue(
const RouterID& remote, const AbstractLinkMessage& msg, SendStatusHandler handler);
void
ForEachPeer(
std::function<void(const AbstractLinkSession*, bool)> visit, bool randomize = false) const;
void
ForEachPeer(std::function<void(AbstractLinkSession*)> visit);
bool IsBootstrapNode(RouterID) const;
/// check if newRc matches oldRC and update local rc for this remote contact
@ -529,18 +525,6 @@ namespace llarp
bool
CheckRenegotiateValid(RouterContact newRc, RouterContact oldRC);
/// called by link when a remote session has no more sessions open
void
SessionClosed(RouterID remote);
/// called by link when an unestablished connection times out
void
ConnectionTimedOut(AbstractLinkSession* session);
/// called by link when session is fully established
bool
ConnectionEstablished(AbstractLinkSession* session, bool inbound);
/// call internal router ticker
void
Tick();

@ -84,7 +84,7 @@ namespace llarp::rpc
return r.exitContext().GetExitEndpoint(name);
}
return r.hiddenServiceContext().GetEndpointByName(name);
return r.hidden_service_context().GetEndpointByName(name);
}
template <typename RPC>
@ -360,7 +360,7 @@ namespace llarp::rpc
// steal replier from exit RPC endpoint
exit_request.replier.emplace(mapexit.move());
m_Router.hiddenServiceContext().GetDefault()->map_exit(
m_Router.hidden_service_context().GetDefault()->map_exit(
mapexit.request.address,
mapexit.request.token,
mapexit.request.ip_range,
@ -375,13 +375,13 @@ namespace llarp::rpc
void
RPCServer::invoke(ListExits& listexits)
{
if (not m_Router.hiddenServiceContext().hasEndpoints())
if (not m_Router.hidden_service_context().hasEndpoints())
{
SetJSONError("No mapped endpoints found", listexits.response);
return;
}
auto status = m_Router.hiddenServiceContext().GetDefault()->ExtractStatus()["exitMap"];
auto status = m_Router.hidden_service_context().GetDefault()->ExtractStatus()["exitMap"];
SetJSONResponse((status.empty()) ? "No exits" : status, listexits.response);
}
@ -413,7 +413,7 @@ namespace llarp::rpc
{
MapExit map_request;
UnmapExit unmap_request;
auto endpoint = m_Router.hiddenServiceContext().GetDefault();
auto endpoint = m_Router.hidden_service_context().GetDefault();
auto current_exits = endpoint->ExtractStatus()["exitMap"];
if (current_exits.empty())

@ -7,68 +7,70 @@
#include <unordered_map>
namespace llarp
/*
TODO:
- if we are only using one local endpoint, does this need to change to account for that?
*/
namespace llarp::service
{
namespace service
/// holds all the hidden service endpoints we own
/// this should be refactored (removed entirely...?) now that lokinet
/// only supports one endpoint per instance
struct Context
{
/// holds all the hidden service endpoints we own
/// this should be refactored (removed entirely...?) now that lokinet
/// only supports one endpoint per instance
struct Context
explicit Context(Router* r);
~Context();
void
Tick(llarp_time_t now);
/// stop all held services
bool
StopAll();
util::StatusObject
ExtractStatus() const;
bool
hasEndpoints();
/// function visitor returns false to prematurely break iteration
void
ForEachService(std::function<bool(const std::string&, const Endpoint_ptr&)> visit) const;
/// Pumps the hidden service endpoints, called during Router::PumpLL
void
Pump();
/// add endpoint via config
void
AddEndpoint(const Config& conf, bool autostart = false);
/// inject endpoint instance
void
InjectEndpoint(std::string name, std::shared_ptr<Endpoint> ep);
/// stop and remove an endpoint by name
/// return false if we don't have the hidden service with that name
bool
RemoveEndpoint(const std::string& name);
Endpoint_ptr
GetEndpointByName(const std::string& name) const;
Endpoint_ptr
GetDefault() const
{
explicit Context(Router* r);
~Context();
void
Tick(llarp_time_t now);
/// stop all held services
bool
StopAll();
util::StatusObject
ExtractStatus() const;
bool
hasEndpoints();
/// function visitor returns false to prematurely break iteration
void
ForEachService(std::function<bool(const std::string&, const Endpoint_ptr&)> visit) const;
/// Pumps the hidden service endpoints, called during Router::PumpLL
void
Pump();
/// add endpoint via config
void
AddEndpoint(const Config& conf, bool autostart = false);
/// inject endpoint instance
void
InjectEndpoint(std::string name, std::shared_ptr<Endpoint> ep);
/// stop and remove an endpoint by name
/// return false if we don't have the hidden service with that name
bool
RemoveEndpoint(const std::string& name);
Endpoint_ptr
GetEndpointByName(const std::string& name) const;
Endpoint_ptr
GetDefault() const
{
return GetEndpointByName("default");
}
bool
StartAll();
private:
Router* const m_Router;
std::unordered_map<std::string, std::shared_ptr<Endpoint>> m_Endpoints;
std::list<std::shared_ptr<Endpoint>> m_Stopped;
};
} // namespace service
} // namespace llarp
return GetEndpointByName("default");
}
bool
StartAll();
private:
Router* const m_Router;
std::unordered_map<std::string, std::shared_ptr<Endpoint>> m_Endpoints;
std::list<std::shared_ptr<Endpoint>> m_Stopped;
};
} // namespace llarp::service

@ -5,71 +5,68 @@
#include <utility>
#include <memory>
namespace llarp
namespace llarp::util
{
namespace util
// Wraps a member function and instance into a callable object that invokes
// the method (non-const overload).
template <
typename Return,
typename Class,
typename Derived,
typename... Arg,
typename = std::enable_if_t<std::is_base_of<Class, Derived>::value>>
auto
memFn(Return (Class::*f)(Arg...), Derived* self)
{
// Wraps a member function and instance into a callable object that invokes
// the method (non-const overload).
template <
typename Return,
typename Class,
typename Derived,
typename... Arg,
typename = std::enable_if_t<std::is_base_of<Class, Derived>::value>>
auto
memFn(Return (Class::*f)(Arg...), Derived* self)
{
return [f, self](Arg... args) -> Return { return (self->*f)(std::forward<Arg>(args)...); };
}
return [f, self](Arg... args) -> Return { return (self->*f)(std::forward<Arg>(args)...); };
}
// Wraps a member function and instance into a lambda that invokes the
// method (const overload).
template <
typename Return,
typename Class,
typename Derived,
typename... Arg,
typename = std::enable_if_t<std::is_base_of<Class, Derived>::value>>
auto
memFn(Return (Class::*f)(Arg...) const, const Derived* self)
{
return [f, self](Arg... args) -> Return { return (self->*f)(std::forward<Arg>(args)...); };
}
// Wraps a member function and instance into a lambda that invokes the
// method (const overload).
template <
typename Return,
typename Class,
typename Derived,
typename... Arg,
typename = std::enable_if_t<std::is_base_of<Class, Derived>::value>>
auto
memFn(Return (Class::*f)(Arg...) const, const Derived* self)
{
return [f, self](Arg... args) -> Return { return (self->*f)(std::forward<Arg>(args)...); };
}
// Wraps a member function and shared pointer to an instance into a lambda
// that invokes the method.
template <
typename Return,
typename Class,
typename Derived,
typename... Arg,
typename = std::enable_if_t<std::is_base_of<Class, Derived>::value>>
auto
memFn(Return (Class::*f)(Arg...), std::shared_ptr<Derived> self)
{
return [f, self = std::move(self)](Arg... args) -> Return {
return (self.get()->*f)(std::forward<Arg>(args)...);
};
}
// Wraps a member function and shared pointer to an instance into a lambda
// that invokes the method.
template <
typename Return,
typename Class,
typename Derived,
typename... Arg,
typename = std::enable_if_t<std::is_base_of<Class, Derived>::value>>
auto
memFn(Return (Class::*f)(Arg...), std::shared_ptr<Derived> self)
{
return [f, self = std::move(self)](Arg... args) -> Return {
return (self.get()->*f)(std::forward<Arg>(args)...);
};
}
// Wraps a member function and shared pointer to an instance into a lambda
// that invokes the method (const method overload).
template <
typename Return,
typename Class,
typename Derived,
typename... Arg,
typename = std::enable_if_t<std::is_base_of<Class, Derived>::value>>
auto
memFn(Return (Class::*f)(Arg...) const, std::shared_ptr<Derived> self)
{
return [f, self = std::move(self)](Arg... args) -> Return {
return (self.get()->*f)(std::forward<Arg>(args)...);
};
}
// Wraps a member function and shared pointer to an instance into a lambda
// that invokes the method (const method overload).
template <
typename Return,
typename Class,
typename Derived,
typename... Arg,
typename = std::enable_if_t<std::is_base_of<Class, Derived>::value>>
auto
memFn(Return (Class::*f)(Arg...) const, std::shared_ptr<Derived> self)
{
return [f, self = std::move(self)](Arg... args) -> Return {
return (self.get()->*f)(std::forward<Arg>(args)...);
};
}
} // namespace util
} // namespace llarp
} // namespace llarp::util
#endif

@ -53,35 +53,35 @@ namespace llarp::vpn
}
};
class AndroidRouteManager : public IRouteManager
class AndroidRouteManager : public AbstractRouteManager
{
void AddRoute(net::ipaddr_t, net::ipaddr_t) override{};
void add_route(oxen::quic::Address, oxen::quic::Address) override{};
void DelRoute(net::ipaddr_t, net::ipaddr_t) override{};
void delete_route(oxen::quic::Address, oxen::quic::Address) override{};
void
AddDefaultRouteViaInterface(NetworkInterface&) override{};
add_default_route_via_interface(NetworkInterface&) override{};
void
DelDefaultRouteViaInterface(NetworkInterface&) override{};
delete_default_route_via_interface(NetworkInterface&) override{};
void
AddRouteViaInterface(NetworkInterface&, IPRange) override{};
add_route_via_interface(NetworkInterface&, IPRange) override{};
void
DelRouteViaInterface(NetworkInterface&, IPRange) override{};
delete_route_via_interface(NetworkInterface&, IPRange) override{};
std::vector<net::ipaddr_t>
GetGatewaysNotOnInterface(NetworkInterface&) override
std::vector<oxen::quic::Address>
get_non_interface_gateways(NetworkInterface&) override
{
return std::vector<net::ipaddr_t>{};
return std::vector<oxen::quic::Address>{};
};
};
class AndroidPlatform : public Platform
{
const int fd;
AndroidRouteManager _routeManager{};
AndroidRouteManager _route_manager{};
public:
AndroidPlatform(llarp::Context* ctx) : fd{ctx->androidFD}
@ -92,10 +92,10 @@ namespace llarp::vpn
{
return std::make_shared<AndroidInterface>(std::move(info), fd);
}
IRouteManager&
AbstractRouteManager&
RouteManager() override
{
return _routeManager;
return _route_manager;
}
};

@ -132,7 +132,7 @@ namespace llarp::vpn
}
};
class LinuxRouteManager : public IRouteManager
class LinuxRouteManager : public AbstractRouteManager
{
const int fd;
@ -179,6 +179,15 @@ namespace llarp::vpn
unsigned char bitlen;
unsigned char data[sizeof(struct in6_addr)];
_inet_addr(oxen::quic::Address& addr)
{
const auto& v4 = addr.is_ipv4();
family = (v4) ? AF_INET : AF_INET6;
bitlen = (v4) ? 32 : 128;
std::memcpy(data, addr.host().data(), (v4) ? 4 : 16);
}
_inet_addr(net::ipv4addr_t addr, size_t bits = 32)
{
family = AF_INET;
@ -195,7 +204,7 @@ namespace llarp::vpn
};
void
Blackhole(int cmd, int flags, int af)
make_blackhole(int cmd, int flags, int af)
{
NLRequest nl_request{};
/* Initialize request structure */
@ -221,7 +230,7 @@ namespace llarp::vpn
}
void
Route(
make_route(
int cmd,
int flags,
const _inet_addr& dst,
@ -286,7 +295,7 @@ namespace llarp::vpn
}
void
DefaultRouteViaInterface(NetworkInterface& vpn, int cmd, int flags)
default_route_via_interface(NetworkInterface& vpn, int cmd, int flags)
{
const auto& info = vpn.Info();
@ -298,8 +307,8 @@ namespace llarp::vpn
const _inet_addr lower{ToNet(ipaddr_ipv4_bits(0, 0, 0, 0)), 1};
const _inet_addr upper{ToNet(ipaddr_ipv4_bits(128, 0, 0, 0)), 1};
Route(cmd, flags, lower, gateway, GatewayMode::eLowerDefault, info.index);
Route(cmd, flags, upper, gateway, GatewayMode::eUpperDefault, info.index);
make_route(cmd, flags, lower, gateway, GatewayMode::eLowerDefault, info.index);
make_route(cmd, flags, upper, gateway, GatewayMode::eUpperDefault, info.index);
if (const auto maybe6 = Net().GetInterfaceIPv6Address(info.ifname))
{
@ -307,13 +316,13 @@ namespace llarp::vpn
for (const std::string str : {"::", "4000::", "8000::", "c000::"})
{
const _inet_addr hole6{net::ipv6addr_t::from_string(str), 2};
Route(cmd, flags, hole6, gateway6, GatewayMode::eUpperDefault, info.index);
make_route(cmd, flags, hole6, gateway6, GatewayMode::eUpperDefault, info.index);
}
}
}
void
RouteViaInterface(int cmd, int flags, NetworkInterface& vpn, IPRange range)
route_via_interface(int cmd, int flags, NetworkInterface& vpn, IPRange range)
{
const auto& info = vpn.Info();
if (range.IsV4())
@ -328,7 +337,7 @@ namespace llarp::vpn
ToNet(net::TruncateV6(range.addr)),
bits::count_bits(net::TruncateV6(range.netmask_bits))};
Route(cmd, flags, addr, gateway, GatewayMode::eUpperDefault, info.index);
make_route(cmd, flags, addr, gateway, GatewayMode::eUpperDefault, info.index);
}
else
{
@ -337,17 +346,14 @@ namespace llarp::vpn
throw std::runtime_error{"we dont have our own network interface?"};
const _inet_addr gateway{ToNet(*maybe), 128};
const _inet_addr addr{ToNet(range.addr), bits::count_bits(range.netmask_bits)};
Route(cmd, flags, addr, gateway, GatewayMode::eUpperDefault, info.index);
make_route(cmd, flags, addr, gateway, GatewayMode::eUpperDefault, info.index);
}
}
void
Route(int cmd, int flags, net::ipaddr_t ip, net::ipaddr_t gateway)
make_route(int cmd, int flags, oxen::quic::Address ip, oxen::quic::Address gateway)
{
auto _ip = var::visit([](auto&& i) { return _inet_addr{i}; }, ip);
auto _gw = var::visit([](auto&& i) { return _inet_addr{i}; }, gateway);
Route(cmd, flags, _ip, _gw, GatewayMode::eFirstHop, 0);
make_route(cmd, flags, _inet_addr{ip}, _inet_addr{gateway}, GatewayMode::eFirstHop, 0);
}
public:
@ -363,46 +369,47 @@ namespace llarp::vpn
}
void
AddRoute(net::ipaddr_t ip, net::ipaddr_t gateway) override
add_route(oxen::quic::Address ip, oxen::quic::Address gateway) override
{
Route(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, ip, gateway);
make_route(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, ip, gateway);
}
void
DelRoute(net::ipaddr_t ip, net::ipaddr_t gateway) override
delete_route(oxen::quic::Address ip, oxen::quic::Address gateway) override
{
Route(RTM_DELROUTE, 0, ip, gateway);
make_route(RTM_DELROUTE, 0, ip, gateway);
}
void
AddDefaultRouteViaInterface(NetworkInterface& vpn) override
add_default_route_via_interface(NetworkInterface& vpn) override
{
DefaultRouteViaInterface(vpn, RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL);
default_route_via_interface(vpn, RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL);
}
void
DelDefaultRouteViaInterface(NetworkInterface& vpn) override
delete_default_route_via_interface(NetworkInterface& vpn) override
{
DefaultRouteViaInterface(vpn, RTM_DELROUTE, 0);
default_route_via_interface(vpn, RTM_DELROUTE, 0);
}
void
AddRouteViaInterface(NetworkInterface& vpn, IPRange range) override
add_route_via_interface(NetworkInterface& vpn, IPRange range) override
{
RouteViaInterface(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, vpn, range);
route_via_interface(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, vpn, range);
}
void
DelRouteViaInterface(NetworkInterface& vpn, IPRange range) override
delete_route_via_interface(NetworkInterface& vpn, IPRange range) override
{
RouteViaInterface(RTM_DELROUTE, 0, vpn, range);
route_via_interface(RTM_DELROUTE, 0, vpn, range);
}
std::vector<net::ipaddr_t>
GetGatewaysNotOnInterface(NetworkInterface& vpn) override
std::vector<oxen::quic::Address>
get_non_interface_gateways(NetworkInterface& vpn) override
{
const auto& ifname = vpn.Info().ifname;
std::vector<net::ipaddr_t> gateways{};
std::vector<oxen::quic::Address> gateways{};
std::ifstream inf{"/proc/net/route"};
for (std::string line; std::getline(inf, line);)
{
@ -412,9 +419,10 @@ namespace llarp::vpn
const auto& ip = parts[2];
if ((ip.size() == sizeof(uint32_t) * 2) and oxenc::is_hex(ip))
{
huint32_t x{};
oxenc::from_hex(ip.begin(), ip.end(), reinterpret_cast<char*>(&x.h));
gateways.emplace_back(net::ipv4addr_t::from_host(x.h));
std::string buf;
oxenc::from_hex(ip.begin(), ip.end(), buf.data());
oxen::quic::Address addr{buf, 0};
gateways.push_back(std::move(addr));
}
}
}
@ -422,17 +430,17 @@ namespace llarp::vpn
}
void
AddBlackhole() override
add_blackhole() override
{
Blackhole(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, AF_INET);
Blackhole(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, AF_INET6);
make_blackhole(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, AF_INET);
make_blackhole(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, AF_INET6);
}
void
DelBlackhole() override
delete_blackhole() override
{
Blackhole(RTM_DELROUTE, 0, AF_INET);
Blackhole(RTM_DELROUTE, 0, AF_INET6);
make_blackhole(RTM_DELROUTE, 0, AF_INET);
make_blackhole(RTM_DELROUTE, 0, AF_INET6);
}
};
@ -447,7 +455,7 @@ namespace llarp::vpn
return std::make_shared<LinuxInterface>(std::move(info));
};
IRouteManager&
AbstractRouteManager&
RouteManager() override
{
return _routeManager;

@ -17,7 +17,7 @@
namespace llarp::vpn
{
const llarp::net::Platform*
IRouteManager::Net_ptr() const
AbstractRouteManager::Net_ptr() const
{
return llarp::net::Platform::Default_ptr();
}

@ -3,6 +3,7 @@
#include <llarp/net/ip_range.hpp>
#include <llarp/net/ip_packet.hpp>
#include <oxenc/variant.h>
#include <external/oxen-libquic/include/quic.hpp>
#include "i_packet_io.hpp"
@ -70,13 +71,13 @@ namespace llarp::vpn
MaybeWakeUpperLayers() const {};
};
class IRouteManager
class AbstractRouteManager
{
public:
IRouteManager() = default;
IRouteManager(const IRouteManager&) = delete;
IRouteManager(IRouteManager&&) = delete;
virtual ~IRouteManager() = default;
AbstractRouteManager() = default;
AbstractRouteManager(const AbstractRouteManager&) = delete;
AbstractRouteManager(AbstractRouteManager&&) = delete;
virtual ~AbstractRouteManager() = default;
virtual const llarp::net::Platform*
Net_ptr() const;
@ -88,31 +89,31 @@ namespace llarp::vpn
}
virtual void
AddRoute(net::ipaddr_t ip, net::ipaddr_t gateway) = 0;
add_route(oxen::quic::Address ip, oxen::quic::Address gateway) = 0;
virtual void
DelRoute(net::ipaddr_t ip, net::ipaddr_t gateway) = 0;
delete_route(oxen::quic::Address ip, oxen::quic::Address gateway) = 0;
virtual void
AddDefaultRouteViaInterface(NetworkInterface& vpn) = 0;
add_default_route_via_interface(NetworkInterface& vpn) = 0;
virtual void
DelDefaultRouteViaInterface(NetworkInterface& vpn) = 0;
delete_default_route_via_interface(NetworkInterface& vpn) = 0;
virtual void
AddRouteViaInterface(NetworkInterface& vpn, IPRange range) = 0;
add_route_via_interface(NetworkInterface& vpn, IPRange range) = 0;
virtual void
DelRouteViaInterface(NetworkInterface& vpn, IPRange range) = 0;
delete_route_via_interface(NetworkInterface& vpn, IPRange range) = 0;
virtual std::vector<net::ipaddr_t>
GetGatewaysNotOnInterface(NetworkInterface& vpn) = 0;
virtual std::vector<oxen::quic::Address>
get_non_interface_gateways(NetworkInterface& vpn) = 0;
virtual void
AddBlackhole(){};
add_blackhole(){};
virtual void
DelBlackhole(){};
delete_blackhole(){};
};
/// a vpn platform
@ -144,7 +145,7 @@ namespace llarp::vpn
}
/// get owned ip route manager for managing routing table
virtual IRouteManager&
virtual AbstractRouteManager&
RouteManager() = 0;
/// create a packet io that will read (and optionally write) packets on a network interface the

@ -16,24 +16,24 @@ namespace llarp::win32
} // namespace
void
VPNPlatform::Route(std::string ip, std::string gw, std::string cmd)
VPNPlatform::make_route(std::string ip, std::string gw, std::string cmd)
{
llarp::win32::Exec(
"route.exe", fmt::format("{} {} MASK 255.255.255.255 {} METRIC {}", cmd, ip, gw, m_Metric));
}
void
VPNPlatform::DefaultRouteViaInterface(NetworkInterface& vpn, std::string cmd)
VPNPlatform::default_route_via_interface(NetworkInterface& vpn, std::string cmd)
{
// route hole for loopback bacause god is dead on windows
llarp::win32::Exec("route.exe", fmt::format("{} 127.0.0.0 MASK 255.0.0.0 0.0.0.0", cmd));
// set up ipv4 routes
RouteViaInterface(vpn, "0.0.0.0", "128.0.0.0", cmd);
RouteViaInterface(vpn, "128.0.0.0", "128.0.0.0", cmd);
route_via_interface(vpn, "0.0.0.0", "128.0.0.0", cmd);
route_via_interface(vpn, "128.0.0.0", "128.0.0.0", cmd);
}
void
VPNPlatform::RouteViaInterface(
VPNPlatform::route_via_interface(
NetworkInterface& vpn, std::string addr, std::string mask, std::string cmd)
{
const auto& info = vpn.Info();
@ -46,68 +46,73 @@ namespace llarp::win32
}
void
VPNPlatform::AddRoute(net::ipaddr_t ip, net::ipaddr_t gateway)
VPNPlatform::add_route(oxen::quic::Address ip, oxen::quic::Address gateway)
{
Route(ip_to_string(ip), ip_to_string(gateway), "ADD");
make_route(ip.to_string(), gateway.to_string(), "ADD");
}
void
VPNPlatform::DelRoute(net::ipaddr_t ip, net::ipaddr_t gateway)
VPNPlatform::delete_route(oxen::quic::Address ip, oxen::quic::Address gateway)
{
Route(ip_to_string(ip), ip_to_string(gateway), "DELETE");
make_route(ip.to_string(), gateway.to_string(), "DELETE");
}
void
VPNPlatform::AddRouteViaInterface(NetworkInterface& vpn, IPRange range)
VPNPlatform::add_route_via_interface(NetworkInterface& vpn, IPRange range)
{
RouteViaInterface(vpn, range.BaseAddressString(), range.NetmaskString(), "ADD");
route_via_interface(vpn, range.BaseAddressString(), range.NetmaskString(), "ADD");
}
void
VPNPlatform::DelRouteViaInterface(NetworkInterface& vpn, IPRange range)
VPNPlatform::delete_route_via_interface(NetworkInterface& vpn, IPRange range)
{
RouteViaInterface(vpn, range.BaseAddressString(), range.NetmaskString(), "DELETE");
route_via_interface(vpn, range.BaseAddressString(), range.NetmaskString(), "DELETE");
}
std::vector<net::ipaddr_t>
VPNPlatform::GetGatewaysNotOnInterface(NetworkInterface& vpn)
std::vector<oxen::quic::Address>
VPNPlatform::get_non_interface_gateways(NetworkInterface& vpn)
{
std::set<net::ipaddr_t> gateways;
std::set<oxen::quic::Address> gateways;
const auto ifaddr = vpn.Info()[0];
for (const auto& iface : Net().AllNetworkInterfaces())
{
if (not iface.gateway)
continue;
bool b = true;
for (const auto& range : iface.addrs)
{
if (not range.Contains(ifaddr))
gateways.emplace(*iface.gateway);
b = false;
}
if (b)
gateways.emplace(*iface.gateway);
}
return {gateways.begin(), gateways.end()};
}
void
VPNPlatform::AddDefaultRouteViaInterface(NetworkInterface& vpn)
VPNPlatform::add_default_route_via_interface(NetworkInterface& vpn)
{
// kill ipv6
llarp::win32::Exec(
"WindowsPowerShell\\v1.0\\powershell.exe",
"-Command (Disable-NetAdapterBinding -Name \"* \" -ComponentID ms_tcpip6)");
DefaultRouteViaInterface(vpn, "ADD");
default_route_via_interface(vpn, "ADD");
}
void
VPNPlatform::DelDefaultRouteViaInterface(NetworkInterface& vpn)
VPNPlatform::delete_default_route_via_interface(NetworkInterface& vpn)
{
// restore ipv6
llarp::win32::Exec(
"WindowsPowerShell\\v1.0\\powershell.exe",
"-Command (Enable-NetAdapterBinding -Name \"* \" -ComponentID ms_tcpip6)");
DefaultRouteViaInterface(vpn, "DELETE");
default_route_via_interface(vpn, "DELETE");
}
std::shared_ptr<NetworkInterface>

@ -1,18 +1,18 @@
#pragma once
#include <llarp/router/router.hpp>
#include <llarp.hpp>
#include <llarp/win32/exec.hpp>
#include <winsock2.h>
#include <windows.h>
#include <iphlpapi.h>
#include <llarp/router/router.hpp>
#include <llarp/win32/exec.hpp>
#include <llarp.hpp>
#include "platform.hpp"
namespace llarp::win32
{
using namespace llarp::vpn;
class VPNPlatform : public Platform, public IRouteManager
class VPNPlatform : public Platform, public AbstractRouteManager
{
llarp::Context* const _ctx;
const int m_Metric{2};
@ -20,17 +20,17 @@ namespace llarp::win32
const auto&
Net() const
{
return _ctx->router->Net();
return _ctx->router->net();
}
void
Route(std::string ip, std::string gw, std::string cmd);
make_route(std::string ip, std::string gw, std::string cmd);
void
DefaultRouteViaInterface(NetworkInterface& vpn, std::string cmd);
default_route_via_interface(NetworkInterface& vpn, std::string cmd);
void
RouteViaInterface(NetworkInterface& vpn, std::string addr, std::string mask, std::string cmd);
route_via_interface(NetworkInterface& vpn, std::string addr, std::string mask, std::string cmd);
public:
VPNPlatform(const VPNPlatform&) = delete;
@ -42,25 +42,25 @@ namespace llarp::win32
~VPNPlatform() override = default;
void
AddRoute(net::ipaddr_t ip, net::ipaddr_t gateway) override;
add_route(oxen::quic::Address ip, oxen::quic::Address gateway) override;
void
DelRoute(net::ipaddr_t ip, net::ipaddr_t gateway) override;
delete_route(oxen::quic::Address ip, oxen::quic::Address gateway) override;
void
AddRouteViaInterface(NetworkInterface& vpn, IPRange range) override;
add_route_via_interface(NetworkInterface& vpn, IPRange range) override;
void
DelRouteViaInterface(NetworkInterface& vpn, IPRange range) override;
delete_route_via_interface(NetworkInterface& vpn, IPRange range) override;
std::vector<net::ipaddr_t>
GetGatewaysNotOnInterface(NetworkInterface& vpn) override;
std::vector<oxen::quic::Address>
get_non_interface_gateways(NetworkInterface& vpn) override;
void
AddDefaultRouteViaInterface(NetworkInterface& vpn) override;
add_default_route_via_interface(NetworkInterface& vpn) override;
void
DelDefaultRouteViaInterface(NetworkInterface& vpn) override;
delete_default_route_via_interface(NetworkInterface& vpn) override;
std::shared_ptr<NetworkInterface>
ObtainInterface(InterfaceInfo info, Router* router) override;
@ -69,7 +69,7 @@ namespace llarp::win32
create_packet_io(
unsigned int ifindex, const std::optional<SockAddr>& dns_upstream_src) override;
IRouteManager&
AbstractRouteManager&
RouteManager() override
{
return *this;

Loading…
Cancel
Save