macos route poking (#1333)

* fix up macos route poker logic

* fix typo

* use string_view

* add forgotten header

* full paths

* add debugging

* catch exception on adding route

* workarround for macos

* typofix

* typofix

* fix for macos

* fix command for macos

* because we autopoke remove explicit route poking in rpc

* probably final fix of macos route poking

* split routes instead of deleting them

* dynamic route poking

* move log statement for introset lookup and dont consider bad sessions as able to send

* send convotag reset frame when we have no session

* add exit map to rpc

* use split_any
pull/1336/head
Jeff 4 years ago committed by GitHub
parent 60f4d96ba5
commit 3ab7db7723
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -694,6 +694,9 @@ namespace libuv
llarp::LogError("failed to start up ", m_Tun->ifname);
return false;
}
// copy back
memcpy(m_Tun->ifname, m_Device->if_name, sizeof(m_Tun->ifname));
if (tuntap_set_ip(m_Device, m_Tun->ifaddr, m_Tun->ifaddr, m_Tun->netmask) == -1)
{
llarp::LogError("failed to set address on ", m_Tun->ifname);

@ -592,6 +592,8 @@ namespace llarp
std::string
TunEndpoint::GetIfName() const
{
if (tunif)
return tunif->ifname;
return m_IfName;
}

@ -2,6 +2,7 @@
#define LLARP_NET_IP_RANGE_MAP_HPP
#include <net/ip_range.hpp>
#include <util/status.hpp>
#include <list>
namespace llarp
@ -114,6 +115,17 @@ namespace llarp
}
}
util::StatusObject
ExtractStatus() const
{
util::StatusObject obj;
for (const auto& [range, value] : m_Entries)
{
obj[range.ToString()] = value.ToString();
}
return obj;
}
private:
Container_t m_Entries;
};

@ -14,6 +14,7 @@
#endif
#ifdef __APPLE__
#include <net/net.hpp>
#include <util/str.hpp>
#endif
#ifdef _WIN32
#include <windows.h>
@ -34,7 +35,6 @@ namespace llarp::net
void
Execute(std::string cmd)
{
std::cout << cmd << std::endl;
#ifdef _WIN32
system(cmd.c_str());
#else
@ -65,10 +65,6 @@ namespace llarp::net
{
std::cout << "failed: " << result << std::endl;
}
else
{
std::cout << "ok" << std::endl;
}
exit(result);
}
else
@ -225,6 +221,7 @@ namespace llarp::net
void
AddRoute(std::string ip, std::string gateway)
{
LogInfo("Add route: ", ip, " via ", gateway);
#ifdef __linux__
NLSocket sock;
int default_gw = 0;
@ -235,14 +232,13 @@ namespace llarp::net
int nl_flags = NLM_F_CREATE | NLM_F_EXCL;
read_addr(gateway.c_str(), &gw_addr);
read_addr(ip.c_str(), &to_addr);
LogInfo("add route: ", ip, " via ", gateway);
do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, default_gw, if_idx);
#else
std::stringstream ss;
#if _WIN32
ss << "route ADD " << ip << " MASK 255.255.255.255 " << gateway << " METRIC 2";
#elif __APPLE__
ss << "route -n add -host " << ip << " " << gateway;
ss << "/sbin/route -n add -host " << ip << " " << gateway;
#else
#error unsupported platform
#endif
@ -253,6 +249,7 @@ namespace llarp::net
void
DelRoute(std::string ip, std::string gateway)
{
LogInfo("Delete route: ", ip, " via ", gateway);
#ifdef __linux__
NLSocket sock;
int default_gw = 0;
@ -269,7 +266,7 @@ namespace llarp::net
#if _WIN32
ss << "route DELETE " << ip << " MASK 255.255.255.255 " << gateway << " METRIC 2";
#elif __APPLE__
ss << "route -n delete -host " << ip << " " << gateway;
ss << "/sbin/route -n delete -host " << ip << " " << gateway;
#else
#error unsupported platform
#endif
@ -280,6 +277,7 @@ namespace llarp::net
void
AddDefaultRouteViaInterface(std::string ifname)
{
LogInfo("Add default route via ", ifname);
#ifdef __linux__
NLSocket sock;
int default_gw = 1;
@ -293,14 +291,14 @@ namespace llarp::net
int nl_cmd = RTM_NEWROUTE;
int nl_flags = NLM_F_CREATE | NLM_F_EXCL;
read_addr(maybe->toHost().c_str(), &gw_addr);
LogInfo("default route via ", ifname, " (", if_idx, ")");
do_route(sock.fd, nl_cmd, nl_flags, &to_addr, &gw_addr, default_gw, if_idx);
#elif _WIN32
ifname.back()++;
Execute("route ADD 0.0.0.0 MASK 128.0.0.0 " + ifname);
Execute("route ADD 128.0.0.0 MASK 128.0.0.0 " + ifname);
#elif __APPLE__
Execute("route -cloning add -net 0.0.0.0 -netmask 0.0.0.0 -interface " + ifname);
Execute("/sbin/route -n add -cloning -net 0.0.0.0 -netmask 128.0.0.0 -interface " + ifname);
Execute("/sbin/route -n add -cloning -net 128.0.0.0 -netmask 128.0.0.0 -interface " + ifname);
#else
#error unsupported platform
#endif
@ -309,8 +307,8 @@ namespace llarp::net
void
DelDefaultRouteViaInterface(std::string ifname)
{
LogInfo("Remove default route via ", ifname);
#ifdef __linux__
NLSocket sock;
int default_gw = 1;
int if_idx = if_nametoindex(ifname.c_str());
@ -329,7 +327,9 @@ namespace llarp::net
Execute("route DELETE 0.0.0.0 MASK 128.0.0.0 " + ifname);
Execute("route DELETE 128.0.0.0 MASK 128.0.0.0 " + ifname);
#elif __APPLE__
Execute("route -cloning delete -net 0.0.0.0 -netmask 0.0.0.0 -interface " + ifname);
Execute("/sbin/route -n delete -cloning -net 0.0.0.0 -netmask 128.0.0.0 -interface " + ifname);
Execute(
"/sbin/route -n delete -cloning -net 128.0.0.0 -netmask 128.0.0.0 -interface " + ifname);
#else
#error unsupported platform
#endif
@ -399,34 +399,27 @@ namespace llarp::net
#undef FREE
return gateways;
#elif __APPLE__
LogDebug("get gateways not on ", ifname);
const auto maybe = GetIFAddr(ifname);
if (not maybe.has_value())
return gateways;
const auto interface = maybe->toString();
// mac os is so godawful man
FILE* p = popen("netstat -rn -f inet", "r");
FILE* p = popen("/usr/sbin/netstat -rn -f inet", "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::string line_str(line, len);
if (line_str.find("default") == 0)
const std::string line_str(line, len);
const auto parts = llarp::split_any(line_str, " "sv, true);
if (parts[0] == "default" and parts[3] != ifname)
{
line_str = line_str.substr(7);
while (line_str[0] == ' ')
{
line_str = line_str.substr(1);
}
const auto pos = line_str.find(" ");
if (pos != std::string::npos)
{
auto gateway = line_str.substr(0, pos);
if (gateway != interface)
gateways.emplace_back(std::move(gateway));
}
gateways.emplace_back(parts[1]);
}
}
pclose(p);

@ -770,6 +770,47 @@ namespace llarp
_linkManager.CheckPersistingSessions(now);
if (not IsServiceNode())
{
const auto gateway = GetDefaultGateway();
if (m_CurrentGateway != gateway)
{
// changed gateways
if (m_CurrentGateway.empty())
{
LogInfo("found default gateway: ", gateway);
}
else if (not gateway.empty())
{
LogInfo("default gateway changed from ", m_CurrentGateway, " to ", gateway);
}
else
{
LogError("Network is down");
}
// unpoke current routes
std::unordered_set<std::string> holes;
for (const auto& [ip, gw] : m_PokedRoutes)
{
// save hole
holes.emplace(ip);
// unpoke route
net::DelRoute(ip, gw);
}
m_PokedRoutes.clear();
if (not gateway.empty())
{
m_CurrentGateway = gateway;
for (const auto& ip : holes)
{
AddRoute(ip);
}
}
}
}
size_t connected = NumberOfConnectedRouters();
if (not isSvcNode)
{
@ -1234,16 +1275,15 @@ namespace llarp
const auto ep = hiddenServiceContext().GetDefault();
const auto gateways = net::GetGatewaysNotOnInterface(ep->GetIfName());
if (gateways.empty())
throw std::runtime_error("no gateways?");
return "";
return gateways[0];
}
void
Router::AddRoute(std::string ip)
{
const auto gateway = GetDefaultGateway();
m_PokedRoutes.emplace(ip, gateway);
net::AddRoute(ip, gateway);
m_PokedRoutes.emplace(ip, m_CurrentGateway);
net::AddRoute(ip, m_CurrentGateway);
}
void

@ -270,6 +270,7 @@ namespace llarp
DelRoute(std::string ip);
std::unordered_map<std::string, std::string> m_PokedRoutes;
std::string m_CurrentGateway;
void
PumpLL() override;

@ -176,12 +176,6 @@ namespace llarp::rpc
}
if (map and exit.has_value())
{
const auto gateways = net::GetGatewaysNotOnInterface(ep->GetIfName());
if (gateways.empty())
{
reply(CreateJSONError("no gateway found"));
return;
}
ep->MapExitRange(range, *exit);
if (token.has_value())
{
@ -189,29 +183,13 @@ namespace llarp::rpc
}
ep->EnsurePathToService(
*exit,
[r, gateway = gateways[0], reply, ep](auto, service::OutboundContext* ctx) {
[reply, ep](auto, service::OutboundContext* ctx) {
if (ctx == nullptr)
{
reply(CreateJSONError("could not find exit"));
return;
}
std::vector<std::string> firsthops;
r->ForEachPeer(
[&firsthops](const auto* link, bool) {
firsthops.emplace_back(link->GetRemoteEndpoint().toHost());
},
false);
for (const auto& hop : firsthops)
{
net::AddRoute(hop, gateway);
}
net::AddDefaultRouteViaInterface(ep->GetIfName());
r->SetDownHook([firsthops, gateway]() {
for (const auto& hop : firsthops)
{
net::DelRoute(hop, gateway);
}
});
reply(CreateJSONResponse("OK"));
},
5s);
@ -224,19 +202,7 @@ namespace llarp::rpc
}
else if (not map)
{
const auto gateways = net::GetGatewaysNotOnInterface(ep->GetIfName());
if (gateways.empty())
{
reply(CreateJSONError("no gateway found"));
return;
}
net::DelDefaultRouteViaInterface(ep->GetIfName());
r->ForEachPeer(
[gateway = gateways[0]](const auto* link, bool) {
net::DelRoute(link->GetRemoteEndpoint().toHost(), gateway);
},
false);
ep->UnmapExitRange(range);
}
reply(CreateJSONResponse("OK"));

@ -182,6 +182,7 @@ namespace llarp
Endpoint::ExtractStatus() const
{
auto obj = path::Builder::ExtractStatus();
obj["exitMap"] = m_ExitMap.ExtractStatus();
obj["identity"] = m_Identity.pub.Addr().ToString();
return m_state->ExtractStatus(obj);
}
@ -914,7 +915,24 @@ namespace llarp
RemoveConvoTag(frame.T);
return true;
}
return frame.AsyncDecryptAndVerify(EndpointLogic(), p, m_Identity, this);
if (not frame.AsyncDecryptAndVerify(EndpointLogic(), p, m_Identity, this))
{
// send reset convo tag message
ProtocolFrame f;
f.R = 1;
f.T = frame.T;
f.F = p->intro.pathID;
f.Sign(m_Identity);
{
LogWarn("invalidating convotag T=", frame.T);
RemoveConvoTag(frame.T);
util::Lock lock(m_state->m_SendQueueMutex);
m_state->m_SendQueue.emplace_back(
std::make_shared<const routing::PathTransferMessage>(f, frame.F), p);
}
}
return true;
}
void Endpoint::HandlePathDied(path::Path_ptr)

@ -59,7 +59,6 @@ namespace llarp
obj["lastPublished"] = to_json(m_LastPublish);
obj["lastPublishAttempt"] = to_json(m_LastPublishAttempt);
obj["introset"] = m_IntroSet.ExtractStatus();
static auto getSecond = [](const auto& item) -> auto
{
return item.second->ExtractStatus();

@ -28,7 +28,6 @@ namespace llarp
{
std::optional<IntroSet> found;
const Address remote(rootkey);
LogInfo("found ", results.size(), " for ", remote.ToString());
if (results.size() > 0)
{
EncryptedIntroSet selected;
@ -39,7 +38,10 @@ namespace llarp
}
const auto maybe = selected.MaybeDecrypt(rootkey);
if (maybe)
{
LogInfo("found result for ", remote.ToString());
found = *maybe;
}
}
return handle(remote, found, endpoint);
}

@ -123,6 +123,8 @@ namespace llarp
bool
OutboundContext::ReadyToSend() const
{
if (markedBad)
return false;
return (!remoteIntro.router.IsZero()) && GetPathByRouter(remoteIntro.router) != nullptr;
}

@ -433,7 +433,7 @@ namespace llarp
if (!handler->GetCachedSessionKeyFor(T, v->shared))
{
LogError("No cached session for T=", T);
return true;
return false;
}
if (!handler->GetSenderFor(T, v->si))

Loading…
Cancel
Save