From 60f4d96ba514400279b48e1dfb6efc8b70d6d14f Mon Sep 17 00:00:00 2001 From: Jeff Date: Tue, 1 Sep 2020 17:22:22 -0400 Subject: [PATCH] proper route poking (#1330) * route poking: * remove popen() call, replace with reading /proc/net/route for getting default route * dynamically poke and unpoke routes on runtime * swap intros and fix rpc endpoint for version to return what the ui expects * use std::string::find_first_not_of instead of using a lambda --- llarp/iwp/iwp.cpp | 6 ++-- llarp/iwp/iwp.hpp | 2 ++ llarp/iwp/linklayer.cpp | 4 ++- llarp/iwp/linklayer.hpp | 1 + llarp/link/server.cpp | 6 ++++ llarp/link/server.hpp | 5 ++++ llarp/net/route.cpp | 32 ++++++++++----------- llarp/router/router.cpp | 45 ++++++++++++++++++++++++++++++ llarp/router/router.hpp | 11 ++++++++ llarp/rpc/rpc_server.cpp | 6 +++- llarp/service/context.cpp | 2 +- llarp/service/context.hpp | 4 +-- llarp/service/outbound_context.cpp | 2 +- test/iwp/test_iwp_session.cpp | 2 ++ 14 files changed, 102 insertions(+), 26 deletions(-) diff --git a/llarp/iwp/iwp.cpp b/llarp/iwp/iwp.cpp index 408001505..038c03e28 100644 --- a/llarp/iwp/iwp.cpp +++ b/llarp/iwp/iwp.cpp @@ -13,6 +13,7 @@ namespace llarp GetRCFunc getrc, LinkMessageHandler h, SignBufferFunc sign, + BeforeConnectFunc_t before, SessionEstablishedHandler est, SessionRenegotiateHandler reneg, TimeoutHandler timeout, @@ -21,7 +22,7 @@ namespace llarp WorkerFunc_t work) { return std::make_shared( - keyManager, getrc, h, sign, est, reneg, timeout, closed, pumpDone, work, true); + keyManager, getrc, h, sign, before, est, reneg, timeout, closed, pumpDone, work, true); } LinkLayer_ptr @@ -30,6 +31,7 @@ namespace llarp GetRCFunc getrc, LinkMessageHandler h, SignBufferFunc sign, + BeforeConnectFunc_t before, SessionEstablishedHandler est, SessionRenegotiateHandler reneg, TimeoutHandler timeout, @@ -38,7 +40,7 @@ namespace llarp WorkerFunc_t work) { return std::make_shared( - keyManager, getrc, h, sign, est, reneg, timeout, closed, pumpDone, work, false); + keyManager, getrc, h, sign, before, est, reneg, timeout, closed, pumpDone, work, false); } } // namespace iwp } // namespace llarp diff --git a/llarp/iwp/iwp.hpp b/llarp/iwp/iwp.hpp index 34e080fb3..1b9f71596 100644 --- a/llarp/iwp/iwp.hpp +++ b/llarp/iwp/iwp.hpp @@ -14,6 +14,7 @@ namespace llarp::iwp GetRCFunc getrc, LinkMessageHandler h, SignBufferFunc sign, + BeforeConnectFunc_t before, SessionEstablishedHandler est, SessionRenegotiateHandler reneg, TimeoutHandler timeout, @@ -27,6 +28,7 @@ namespace llarp::iwp GetRCFunc getrc, LinkMessageHandler h, SignBufferFunc sign, + BeforeConnectFunc_t before, SessionEstablishedHandler est, SessionRenegotiateHandler reneg, TimeoutHandler timeout, diff --git a/llarp/iwp/linklayer.cpp b/llarp/iwp/linklayer.cpp index 15f758cbe..c4f616413 100644 --- a/llarp/iwp/linklayer.cpp +++ b/llarp/iwp/linklayer.cpp @@ -13,6 +13,7 @@ namespace llarp GetRCFunc getrc, LinkMessageHandler h, SignBufferFunc sign, + BeforeConnectFunc_t before, SessionEstablishedHandler est, SessionRenegotiateHandler reneg, TimeoutHandler timeout, @@ -20,7 +21,8 @@ namespace llarp PumpDoneHandler pumpDone, WorkerFunc_t worker, bool allowInbound) - : ILinkLayer(keyManager, getrc, h, sign, est, reneg, timeout, closed, pumpDone, worker) + : ILinkLayer( + keyManager, getrc, h, sign, before, est, reneg, timeout, closed, pumpDone, worker) , permitInbound{allowInbound} { } diff --git a/llarp/iwp/linklayer.hpp b/llarp/iwp/linklayer.hpp index 7e56f96ff..1af850486 100644 --- a/llarp/iwp/linklayer.hpp +++ b/llarp/iwp/linklayer.hpp @@ -21,6 +21,7 @@ namespace llarp GetRCFunc getrc, LinkMessageHandler h, SignBufferFunc sign, + BeforeConnectFunc_t before, SessionEstablishedHandler est, SessionRenegotiateHandler reneg, TimeoutHandler timeout, diff --git a/llarp/link/server.cpp b/llarp/link/server.cpp index 3463e0480..40d1174e5 100644 --- a/llarp/link/server.cpp +++ b/llarp/link/server.cpp @@ -18,6 +18,7 @@ namespace llarp GetRCFunc getrc, LinkMessageHandler handler, SignBufferFunc signbuf, + BeforeConnectFunc_t before, SessionEstablishedHandler establishedSession, SessionRenegotiateHandler reneg, TimeoutHandler timeout, @@ -28,6 +29,7 @@ namespace llarp , HandleTimeout(std::move(timeout)) , Sign(std::move(signbuf)) , GetOurRC(std::move(getrc)) + , BeforeConnect(std::move(before)) , SessionEstablished(std::move(establishedSession)) , SessionClosed(std::move(closed)) , SessionRenegotiate(std::move(reneg)) @@ -311,6 +313,10 @@ namespace llarp } } std::shared_ptr s = NewOutboundSession(rc, to); + if (BeforeConnect) + { + BeforeConnect(std::move(rc)); + } if (PutSession(s)) { s->Start(); diff --git a/llarp/link/server.hpp b/llarp/link/server.hpp index 55df4fa6f..3d30dc21b 100644 --- a/llarp/link/server.hpp +++ b/llarp/link/server.hpp @@ -70,6 +70,9 @@ namespace llarp /// queue work to worker thread using WorkerFunc_t = std::function; + /// before connection hook, called before we try connecting via outbound link + using BeforeConnectFunc_t = std::function; + struct ILinkLayer { ILinkLayer( @@ -77,6 +80,7 @@ namespace llarp GetRCFunc getrc, LinkMessageHandler handler, SignBufferFunc signFunc, + BeforeConnectFunc_t before, SessionEstablishedHandler sessionEstablish, SessionRenegotiateHandler renegotiate, TimeoutHandler timeout, @@ -195,6 +199,7 @@ namespace llarp TimeoutHandler HandleTimeout; SignBufferFunc Sign; GetRCFunc GetOurRC; + BeforeConnectFunc_t BeforeConnect; SessionEstablishedHandler SessionEstablished; SessionClosedHandler SessionClosed; SessionRenegotiateHandler SessionRenegotiate; diff --git a/llarp/net/route.cpp b/llarp/net/route.cpp index 8edf8e35d..2dd66a4f4 100644 --- a/llarp/net/route.cpp +++ b/llarp/net/route.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #endif #ifdef __APPLE__ #include @@ -25,6 +26,7 @@ #include #include +#include namespace llarp::net { @@ -338,28 +340,22 @@ namespace llarp::net { std::vector gateways; #ifdef __linux__ - - FILE* p = popen("ip route", "r"); - if (p == nullptr) - return gateways; - char* line = nullptr; - size_t len = 0; - ssize_t read = 0; - while ((read = getline(&line, &len, p)) != -1) + std::ifstream inf("/proc/net/route"); + for (std::string line; std::getline(inf, line);) { - std::string line_str(line, len); - std::vector words; - std::istringstream instr(line_str); - for (std::string word; std::getline(instr, word, ' ');) - { - words.emplace_back(std::move(word)); - } - if (words[0] == "default" and words[1] == "via" and words[3] == "dev" and words[4] != ifname) + const auto parts = split(line, '\t'); + if (parts[1].find_first_not_of('0') == std::string::npos and parts[0] != ifname) { - gateways.emplace_back(std::move(words[2])); + const auto& ip = parts[2]; + if ((ip.size() == sizeof(uint32_t) * 2) and lokimq::is_hex(ip)) + { + huint32_t x{}; + lokimq::from_hex(ip.begin(), ip.end(), reinterpret_cast(&x.h)); + gateways.emplace_back(x.ToString()); + } } } - pclose(p); + return gateways; #elif _WIN32 #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 0a5aed92f..0f9a1e016 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -332,6 +333,10 @@ namespace llarp void Router::Close() { + for (const auto& [ip, gateway] : m_PokedRoutes) + { + net::DelRoute(ip, gateway); + } if (_onDown) _onDown(); LogInfo("closing router"); @@ -574,6 +579,7 @@ namespace llarp util::memFn(&AbstractRouter::rc, this), util::memFn(&AbstractRouter::HandleRecvLinkMessageBuffer, this), util::memFn(&AbstractRouter::Sign, this), + nullptr, util::memFn(&Router::ConnectionEstablished, this), util::memFn(&AbstractRouter::CheckRenegotiateValid, this), util::memFn(&Router::ConnectionTimedOut, this), @@ -853,6 +859,12 @@ namespace llarp dht()->impl->Nodes()->DelNode(k); LogInfo("Session to ", remote, " fully closed"); + if (IsServiceNode()) + return; + RouterContact rc; + if (not nodedb()->Get(remote, rc)) + return; + DelRoute(rc.addrs[0].toIpAddress().toHost()); } void @@ -1216,6 +1228,34 @@ namespace llarp return true; } + std::string + Router::GetDefaultGateway() const + { + const auto ep = hiddenServiceContext().GetDefault(); + const auto gateways = net::GetGatewaysNotOnInterface(ep->GetIfName()); + if (gateways.empty()) + throw std::runtime_error("no gateways?"); + return gateways[0]; + } + + void + Router::AddRoute(std::string ip) + { + const auto gateway = GetDefaultGateway(); + m_PokedRoutes.emplace(ip, gateway); + net::AddRoute(ip, gateway); + } + + void + Router::DelRoute(std::string ip) + { + const auto itr = m_PokedRoutes.find(ip); + if (itr == m_PokedRoutes.end()) + return; + net::DelRoute(itr->first, itr->second); + m_PokedRoutes.erase(itr); + } + bool Router::InitOutboundLinks() { @@ -1224,6 +1264,11 @@ namespace llarp util::memFn(&AbstractRouter::rc, this), util::memFn(&AbstractRouter::HandleRecvLinkMessageBuffer, this), util::memFn(&AbstractRouter::Sign, this), + [&](llarp::RouterContact rc) { + if (IsServiceNode()) + return; + AddRoute(rc.addrs[0].toIpAddress().toHost()); + }, util::memFn(&Router::ConnectionEstablished, this), util::memFn(&AbstractRouter::CheckRenegotiateValid, this), util::memFn(&Router::ConnectionTimedOut, this), diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index f83e919e0..78c5c6027 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -260,6 +260,17 @@ namespace llarp */ } + std::string + GetDefaultGateway() const; + + void + AddRoute(std::string ip); + + void + DelRoute(std::string ip); + + std::unordered_map m_PokedRoutes; + void PumpLL() override; diff --git a/llarp/rpc/rpc_server.cpp b/llarp/rpc/rpc_server.cpp index 7ab1644a0..05f51be9f 100644 --- a/llarp/rpc/rpc_server.cpp +++ b/llarp/rpc/rpc_server.cpp @@ -98,7 +98,11 @@ namespace llarp::rpc }) .add_request_command( "version", - [](lokimq::Message& msg) { msg.send_reply(CreateJSONResponse(llarp::VERSION_FULL)); }) + [r = m_Router](lokimq::Message& msg) { + util::StatusObject result{{"version", llarp::VERSION_FULL}, + {"uptime", to_json(r->Uptime())}}; + msg.send_reply(CreateJSONResponse(result)); + }) .add_request_command( "status", [&](lokimq::Message& msg) { diff --git a/llarp/service/context.cpp b/llarp/service/context.cpp index bfb4a5dae..b1bb94577 100644 --- a/llarp/service/context.cpp +++ b/llarp/service/context.cpp @@ -153,7 +153,7 @@ namespace llarp } Endpoint_ptr - Context::GetEndpointByName(const std::string& name) + Context::GetEndpointByName(const std::string& name) const { auto itr = m_Endpoints.find(name); if (itr != m_Endpoints.end()) diff --git a/llarp/service/context.hpp b/llarp/service/context.hpp index 147a66e73..f5f17ac60 100644 --- a/llarp/service/context.hpp +++ b/llarp/service/context.hpp @@ -51,10 +51,10 @@ namespace llarp RemoveEndpoint(const std::string& name); Endpoint_ptr - GetEndpointByName(const std::string& name); + GetEndpointByName(const std::string& name) const; Endpoint_ptr - GetDefault() + GetDefault() const { return GetEndpointByName("default"); } diff --git a/llarp/service/outbound_context.cpp b/llarp/service/outbound_context.cpp index d7142fafa..0c03725e7 100644 --- a/llarp/service/outbound_context.cpp +++ b/llarp/service/outbound_context.cpp @@ -110,7 +110,7 @@ namespace llarp return true; } currentIntroSet = *foundIntro; - ShiftIntroduction(false); + SwapIntros(); } else { diff --git a/test/iwp/test_iwp_session.cpp b/test/iwp/test_iwp_session.cpp index 3d2f26394..6da9c6947 100644 --- a/test/iwp/test_iwp_session.cpp +++ b/test/iwp/test_iwp_session.cpp @@ -85,6 +85,8 @@ struct IWPLinkContext REQUIRE(llarp::CryptoManager::instance()->sign(sig, keyManager->identityKey, buf)); return true; }, + // before connect + nullptr, // established handler [established](llarp::ILinkSession* s, bool linkIsInbound) { REQUIRE(s != nullptr);