lokinet/llarp/handlers/tun.cpp

791 lines
23 KiB
C++
Raw Normal View History

2018-10-10 12:06:28 +00:00
#include <algorithm>
// harmless on other platforms
#define __USE_MINGW_ANSI_STDIO 1
2018-12-12 01:12:59 +00:00
#include <handlers/tun.hpp>
#include <sys/types.h>
2018-09-25 08:31:29 +00:00
#ifndef _WIN32
#include <sys/socket.h>
#include <netdb.h>
2018-09-25 08:31:29 +00:00
#endif
2018-08-15 15:36:34 +00:00
#include <dns/dns.hpp>
2019-01-11 01:19:36 +00:00
#include <ev/ev.hpp>
#include <router/abstractrouter.hpp>
#include <service/context.hpp>
2018-08-15 15:36:34 +00:00
namespace llarp
{
2018-08-16 14:34:15 +00:00
namespace handlers
2018-08-15 15:36:34 +00:00
{
static llarp_fd_promise *
get_tun_fd_promise(llarp_tun_io *tun)
{
return static_cast< TunEndpoint * >(tun->user)->Promise.get();
}
2018-12-15 16:56:35 +00:00
static void
tunifTick(llarp_tun_io *tun)
{
TunEndpoint *self = static_cast< TunEndpoint * >(tun->user);
self->Flush();
}
TunEndpoint::TunEndpoint(const std::string &nickname, AbstractRouter *r,
service::Context *parent)
: service::Endpoint(nickname, r, parent)
, m_UserToNetworkPktQueue(nickname + "_sendq", r->netloop(),
r->netloop())
, m_NetworkToUserPktQueue(nickname + "_recvq", r->netloop(),
r->netloop())
, m_Resolver(r->netloop(), this)
2018-08-15 15:36:34 +00:00
{
#ifdef ANDROID
tunif.get_fd_promise = &get_tun_fd_promise;
Promise.reset(new llarp_fd_promise(&m_VPNPromise));
#else
tunif.get_fd_promise = nullptr;
#endif
2018-08-16 14:34:15 +00:00
tunif.user = this;
tunif.netmask = DefaultTunNetmask;
2018-12-14 00:15:15 +00:00
2018-12-23 13:29:11 +00:00
// eh this shouldn't do anything on windows anyway
strncpy(tunif.ifaddr, DefaultTunSrcAddr, sizeof(tunif.ifaddr) - 1);
strncpy(tunif.ifname, DefaultTunIfname, sizeof(tunif.ifname) - 1);
2018-12-15 16:56:35 +00:00
tunif.tick = &tunifTick;
2018-12-03 22:22:59 +00:00
tunif.before_write = &tunifBeforeWrite;
tunif.recvpkt = &tunifRecvPkt;
2018-08-16 14:34:15 +00:00
}
2019-02-11 17:14:43 +00:00
util::StatusObject
TunEndpoint::ExtractStatus() const
2019-02-08 19:43:25 +00:00
{
2019-02-11 17:14:43 +00:00
auto obj = service::Endpoint::ExtractStatus();
obj.Put("ifaddr", m_OurRange.ToString());
2019-02-08 19:43:25 +00:00
std::vector< std::string > resolvers;
for(const auto &addr : m_UpstreamResolvers)
resolvers.emplace_back(addr.ToString());
2019-02-11 17:14:43 +00:00
obj.Put("ustreamResolvers", resolvers);
obj.Put("localResolver", m_LocalResolverAddr.ToString());
util::StatusObject ips{};
2019-02-08 19:43:25 +00:00
for(const auto &item : m_IPActivity)
{
2019-02-11 17:14:43 +00:00
util::StatusObject ipObj{{"lastActive", item.second}};
2019-02-08 19:43:25 +00:00
std::string remoteStr;
AlignedBuffer< 32 > addr = m_IPToAddr.at(item.first);
if(m_SNodes.at(addr))
remoteStr = RouterID(addr.as_array()).ToString();
else
remoteStr = service::Address(addr.as_array()).ToString();
2019-02-11 17:14:43 +00:00
ipObj.Put("remote", remoteStr);
2019-02-08 19:43:25 +00:00
std::string ipaddr = item.first.ToString();
2019-02-11 17:14:43 +00:00
ips.Put(ipaddr.c_str(), ipObj);
2019-02-08 19:43:25 +00:00
}
2019-02-11 17:14:43 +00:00
obj.Put("addrs", ips);
obj.Put("ourIP", m_OurIP.ToString());
obj.Put("nextIP", m_NextIP.ToString());
obj.Put("maxIP", m_MaxIP.ToString());
return obj;
2019-02-08 19:43:25 +00:00
}
2018-08-16 14:34:15 +00:00
bool
TunEndpoint::SetOption(const std::string &k, const std::string &v)
{
// Name won't be set because we need to read the config before we can read
// the keyfile
2018-11-14 19:34:17 +00:00
if(k == "exit-node")
{
llarp::RouterID exitRouter;
if(!(exitRouter.FromString(v)
|| HexDecode(v.c_str(), exitRouter.begin(), exitRouter.size())))
2018-11-14 19:34:17 +00:00
{
llarp::LogError(Name(), " bad exit router key: ", v);
return false;
}
2018-11-29 13:12:35 +00:00
m_Exit.reset(new llarp::exit::ExitSession(
2018-11-14 19:34:17 +00:00
exitRouter,
std::bind(&TunEndpoint::QueueInboundPacketForExit, this,
std::placeholders::_1),
router, m_NumPaths, numHops));
llarp::LogInfo(Name(), " using exit at ", exitRouter);
}
2018-11-11 13:14:19 +00:00
if(k == "local-dns")
{
std::string resolverAddr = v;
uint16_t dnsport = 53;
2018-11-11 13:14:19 +00:00
auto pos = v.find(":");
if(pos != std::string::npos)
{
resolverAddr = v.substr(0, pos);
dnsport = std::atoi(v.substr(pos + 1).c_str());
2018-11-11 13:14:19 +00:00
}
m_LocalResolverAddr = llarp::Addr(resolverAddr, dnsport);
llarp::LogInfo(Name(), " binding DNS server to ", m_LocalResolverAddr);
2018-11-11 13:14:19 +00:00
}
if(k == "upstream-dns")
{
std::string resolverAddr = v;
uint16_t dnsport = 53;
2018-11-11 13:14:19 +00:00
auto pos = v.find(":");
if(pos != std::string::npos)
{
resolverAddr = v.substr(0, pos);
dnsport = std::atoi(v.substr(pos + 1).c_str());
2018-11-11 13:14:19 +00:00
}
2018-12-03 22:22:59 +00:00
m_UpstreamResolvers.emplace_back(resolverAddr, dnsport);
llarp::LogInfo(Name(), " adding upstream DNS server ", resolverAddr,
2018-12-17 20:47:08 +00:00
":", dnsport);
2018-11-11 13:14:19 +00:00
}
2018-08-22 15:52:10 +00:00
if(k == "mapaddr")
{
auto pos = v.find(":");
if(pos == std::string::npos)
{
llarp::LogError("Cannot map address ", v,
2018-11-03 13:19:18 +00:00
" invalid format, missing colon (:), expects "
2018-08-22 15:52:10 +00:00
"address.loki:ip.address.goes.here");
return false;
}
service::Address addr;
auto addr_str = v.substr(0, pos);
if(!addr.FromString(addr_str))
{
2018-09-10 11:08:09 +00:00
llarp::LogError(Name() + " cannot map invalid address ", addr_str);
2018-08-22 15:52:10 +00:00
return false;
}
auto ip_str = v.substr(pos + 1);
2018-09-16 12:51:16 +00:00
in_addr ip;
2018-08-22 15:52:10 +00:00
if(inet_pton(AF_INET, ip_str.c_str(), &ip) != 1)
{
llarp::LogError("cannot map to invalid ip ", ip_str);
return false;
}
return MapAddress(addr, huint32_t{ntohl(ip.s_addr)}, false);
2018-08-22 15:52:10 +00:00
}
2018-08-16 14:34:15 +00:00
if(k == "ifname")
{
2018-12-28 15:10:05 +00:00
if(v.length() >= sizeof(tunif.ifname))
{
llarp::LogError(Name() + " ifname '", v, "' is too long");
return false;
}
2018-08-16 14:34:15 +00:00
strncpy(tunif.ifname, v.c_str(), sizeof(tunif.ifname) - 1);
2018-09-10 11:08:09 +00:00
llarp::LogInfo(Name() + " setting ifname to ", tunif.ifname);
2018-08-16 14:34:15 +00:00
return true;
}
if(k == "ifaddr")
{
std::string addr;
auto pos = v.find("/");
if(pos != std::string::npos)
{
2018-11-06 14:06:09 +00:00
int num;
std::string part = v.substr(pos + 1);
2018-11-08 12:31:50 +00:00
#if defined(ANDROID) || defined(RPI)
2018-11-06 14:06:09 +00:00
num = atoi(part.c_str());
#else
num = std::stoi(part);
#endif
2018-08-16 14:34:15 +00:00
if(num > 0)
{
tunif.netmask = num;
addr = v.substr(0, pos);
}
else
{
llarp::LogError("bad ifaddr value: ", v);
return false;
}
}
else
{
tunif.netmask = 32;
addr = v;
}
2018-09-10 11:08:09 +00:00
llarp::LogInfo(Name() + " set ifaddr to ", addr, " with netmask ",
tunif.netmask);
2018-08-16 14:34:15 +00:00
strncpy(tunif.ifaddr, addr.c_str(), sizeof(tunif.ifaddr) - 1);
return true;
}
return Endpoint::SetOption(k, v);
}
2018-11-14 12:23:08 +00:00
bool
TunEndpoint::HasLocalIP(const huint32_t &ip) const
{
return m_IPToAddr.find(ip) != m_IPToAddr.end();
}
bool
TunEndpoint::QueueOutboundTraffic(llarp::net::IPv4Packet &&pkt)
{
return m_NetworkToUserPktQueue.EmplaceIf(
[](llarp::net::IPv4Packet &) -> bool { return true; },
std::move(pkt));
}
2018-12-15 16:56:35 +00:00
void
TunEndpoint::Flush()
{
FlushSend();
}
2019-02-05 14:22:02 +00:00
static bool
is_random_snode(const dns::Message &msg)
{
return msg.questions[0].qname == "random.snode"
|| msg.questions[0].qname == "random.snode.";
}
static bool
is_localhost_loki(const dns::Message &msg)
{
return msg.questions[0].qname == "localhost.loki"
|| msg.questions[0].qname == "localhost.loki.";
}
2018-12-03 22:22:59 +00:00
bool
TunEndpoint::HandleHookedDNSMessage(
dns::Message &&msg, std::function< void(dns::Message) > reply)
2018-12-03 22:22:59 +00:00
{
2019-02-05 14:03:38 +00:00
// llarp::LogInfo("Tun.HandleHookedDNSMessage ", msg.questions[0].qname);
2018-12-03 22:22:59 +00:00
if(msg.questions.size() != 1)
{
llarp::LogWarn("bad number of dns questions: ", msg.questions.size());
return false;
}
std::string qname = msg.questions[0].qname;
if(msg.questions[0].qtype == dns::qTypeMX)
2018-12-07 21:52:19 +00:00
{
// mx record
2019-02-05 14:23:51 +00:00
service::Address addr;
2019-02-05 14:22:02 +00:00
if(addr.FromString(qname, ".loki") || addr.FromString(qname, ".snode")
|| is_random_snode(msg) || is_localhost_loki(msg))
2018-12-07 21:52:19 +00:00
msg.AddMXReply(qname, 1);
else
msg.AddNXReply();
2018-12-07 22:08:23 +00:00
reply(msg);
2018-12-07 21:52:19 +00:00
}
2019-01-10 15:49:08 +00:00
else if(msg.questions[0].qtype == dns::qTypeCNAME)
{
2019-02-05 14:22:02 +00:00
if(is_random_snode(msg))
2019-01-10 15:49:08 +00:00
{
RouterID random;
if(Router()->GetRandomGoodRouter(random))
msg.AddCNAMEReply(random.ToString(), 1);
else
msg.AddNXReply();
}
2019-02-05 14:22:02 +00:00
else if(is_localhost_loki(msg))
{
size_t counter = 0;
context->ForEachService(
[&](const std::string &,
const std::unique_ptr< service::Endpoint > &service) -> bool {
service::Address addr = service->GetIdentity().pub.Addr();
msg.AddCNAMEReply(addr.ToString(), 1);
++counter;
return true;
});
if(counter == 0)
msg.AddNXReply();
}
2019-01-10 15:49:08 +00:00
else
msg.AddNXReply();
2019-02-05 14:03:38 +00:00
reply(msg);
2019-01-10 15:49:08 +00:00
}
else if(msg.questions[0].qtype == dns::qTypeA)
2018-12-03 22:22:59 +00:00
{
llarp::service::Address addr;
2019-02-05 03:19:06 +00:00
// on MacOS this is a typeA query
2019-02-05 14:22:02 +00:00
if(is_random_snode(msg))
2019-02-05 03:19:06 +00:00
{
2019-02-05 21:04:30 +00:00
RouterID random;
if(Router()->GetRandomGoodRouter(random))
msg.AddCNAMEReply(random.ToString(), 1);
else
msg.AddNXReply();
2019-02-05 03:19:06 +00:00
}
2019-02-05 14:22:02 +00:00
else if(is_localhost_loki(msg))
2018-12-13 00:03:19 +00:00
{
size_t counter = 0;
context->ForEachService(
[&](const std::string &,
const std::unique_ptr< service::Endpoint > &service) -> bool {
huint32_t ip = service->GetIfAddr();
if(ip.h)
{
msg.AddINReply(ip);
++counter;
}
return true;
});
if(counter == 0)
2018-12-13 00:03:19 +00:00
msg.AddNXReply();
}
else if(addr.FromString(qname, ".loki"))
2018-12-03 22:22:59 +00:00
{
if(HasAddress(addr))
{
huint32_t ip = ObtainIPForAddr(addr, false);
msg.AddINReply(ip);
}
else
{
dns::Message *replyMsg = new dns::Message(std::move(msg));
return EnsurePathToService(
addr,
[=](const service::Address &remote, OutboundContext *ctx) {
SendDNSReply(remote, ctx, replyMsg, reply, false);
},
2000);
}
2018-12-03 22:22:59 +00:00
}
else if(addr.FromString(qname, ".snode"))
{
dns::Message *replyMsg = new dns::Message(std::move(msg));
EnsurePathToSNode(addr.as_array(),
[=](const RouterID &remote, exit::BaseSession *s) {
SendDNSReply(remote, s, replyMsg, reply, true);
});
return true;
2018-12-03 22:22:59 +00:00
}
else
2019-02-05 03:19:06 +00:00
// forward dns
2018-12-04 16:16:43 +00:00
msg.AddNXReply();
reply(msg);
2018-12-03 22:22:59 +00:00
}
2019-01-10 15:49:08 +00:00
else if(msg.questions[0].qtype == dns::qTypePTR)
2018-12-03 22:22:59 +00:00
{
2018-12-04 16:16:43 +00:00
// reverse dns
2018-12-03 22:22:59 +00:00
huint32_t ip = {0};
if(!dns::DecodePTR(msg.questions[0].qname, ip))
{
2018-12-04 16:16:43 +00:00
msg.AddNXReply();
reply(msg);
2018-12-03 22:22:59 +00:00
return true;
}
llarp::service::Address addr(
ObtainAddrForIP< llarp::service::Address >(ip, true));
2018-12-03 22:22:59 +00:00
if(!addr.IsZero())
{
2018-12-04 16:16:43 +00:00
msg.AddAReply(addr.ToString(".snode"));
reply(msg);
2018-12-03 22:22:59 +00:00
return true;
}
addr = ObtainAddrForIP< llarp::service::Address >(ip, false);
if(!addr.IsZero())
{
2018-12-04 16:16:43 +00:00
msg.AddAReply(addr.ToString(".loki"));
reply(msg);
2018-12-03 22:22:59 +00:00
return true;
}
2018-12-04 16:16:43 +00:00
msg.AddNXReply();
reply(msg);
2018-12-03 22:22:59 +00:00
return true;
}
else
2018-12-04 16:16:43 +00:00
{
msg.AddNXReply();
reply(msg);
}
2018-12-03 22:22:59 +00:00
return true;
}
bool
TunEndpoint::ShouldHookDNSMessage(const dns::Message &msg) const
{
llarp::service::Address addr;
if(msg.questions.size() == 1)
{
2018-12-07 23:36:53 +00:00
// always hook mx records
if(msg.questions[0].qtype == llarp::dns::qTypeMX)
2018-12-07 23:36:53 +00:00
return true;
// hook random.snode
2018-12-13 00:03:19 +00:00
if(msg.questions[0].qname == "random.snode"
|| msg.questions[0].qname == "random.snode.")
return true;
// hook localhost.loki
if(msg.questions[0].qname == "localhost.loki"
|| msg.questions[0].qname == "localhost.loki.")
return true;
2019-01-28 15:46:49 +00:00
// hook .loki A records
2018-12-03 22:22:59 +00:00
if(addr.FromString(msg.questions[0].qname, ".loki"))
return true;
2019-01-28 15:46:49 +00:00
// hook .snode A records
2018-12-03 22:22:59 +00:00
if(addr.FromString(msg.questions[0].qname, ".snode"))
return true;
2019-01-10 15:49:08 +00:00
// hook any ranges we own
if(msg.questions[0].qtype == llarp::dns::qTypePTR)
2018-12-03 22:22:59 +00:00
{
huint32_t ip = {0};
if(!dns::DecodePTR(msg.questions[0].qname, ip))
return false;
return m_OurRange.Contains(ip);
}
}
return false;
}
2018-08-22 15:52:10 +00:00
bool
TunEndpoint::MapAddress(const service::Address &addr, huint32_t ip,
bool SNode)
2018-08-22 15:52:10 +00:00
{
auto itr = m_IPToAddr.find(ip);
if(itr != m_IPToAddr.end())
{
2018-10-10 15:14:45 +00:00
// XXX is calling inet_ntoa safe in this context? it's MP-unsafe
2018-11-14 12:23:08 +00:00
llarp::LogWarn(ip, " already mapped to ",
service::Address(itr->second.as_array()).ToString());
2018-08-22 15:52:10 +00:00
return false;
}
2018-11-03 13:19:18 +00:00
llarp::LogInfo(Name() + " map ", addr.ToString(), " to ", ip);
2018-10-19 15:04:14 +00:00
m_IPToAddr[ip] = addr;
m_AddrToIP[addr] = ip;
m_SNodes[addr] = SNode;
2018-09-10 11:08:09 +00:00
MarkIPActiveForever(ip);
2018-08-22 15:52:10 +00:00
return true;
}
2018-08-16 14:34:15 +00:00
bool
TunEndpoint::Start()
{
if(!Endpoint::Start())
{
llarp::LogWarn("Couldn't start endpoint");
2018-08-16 14:34:15 +00:00
return false;
}
2018-08-21 18:39:18 +00:00
return SetupNetworking();
2018-08-16 14:34:15 +00:00
}
bool
TunEndpoint::IsSNode() const
{
// TODO : implement me
return false;
}
2018-08-16 14:34:15 +00:00
bool
TunEndpoint::SetupTun()
{
2018-08-20 19:12:12 +00:00
if(!llarp_ev_add_tun(EndpointNetLoop(), &tunif))
{
llarp::LogError(Name(),
" failed to set up tun interface: ", tunif.ifaddr,
" on ", tunif.ifname);
2018-08-20 19:12:12 +00:00
return false;
}
struct addrinfo hint, *res = NULL;
int ret;
memset(&hint, 0, sizeof hint);
hint.ai_family = PF_UNSPEC;
hint.ai_flags = AI_NUMERICHOST;
ret = getaddrinfo(tunif.ifaddr, NULL, &hint, &res);
if(ret)
{
llarp::LogError(Name(),
" failed to set up tun interface, cant determine "
"family from ",
tunif.ifaddr);
return false;
}
/*
// output is in network byte order
unsigned char buf[sizeof(struct in6_addr)];
int s = inet_pton(res->ai_family, tunif.ifaddr, buf);
if (s <= 0)
{
2018-12-03 22:22:59 +00:00
llarp::LogError(Name(), " failed to set up tun interface, cant parse
", tunif.ifaddr); return false;
}
*/
if(res->ai_family == AF_INET6)
{
llarp::LogError(Name(),
" failed to set up tun interface, we don't support "
"IPv6 format");
return false;
}
freeaddrinfo(res);
struct in_addr addr; // network byte order
if(inet_aton(tunif.ifaddr, &addr) == 0)
{
llarp::LogError(Name(), " failed to set up tun interface, cant parse ",
tunif.ifaddr);
return false;
}
llarp::Addr lAddr(tunif.ifaddr);
2018-12-03 22:22:59 +00:00
m_OurIP = lAddr.xtohl();
m_NextIP = m_OurIP;
m_OurRange.netmask_bits = netmask_ipv4_bits(tunif.netmask);
m_OurRange.addr = m_OurIP;
m_MaxIP = m_OurIP | (~m_OurRange.netmask_bits);
llarp::LogInfo(Name(), " set ", tunif.ifname, " to have address ", lAddr);
2018-12-03 22:22:59 +00:00
llarp::LogInfo(Name(), " allocated up to ", m_MaxIP, " on range ",
m_OurRange);
MapAddress(m_Identity.pub.Addr(), m_OurIP, IsSNode());
2018-08-20 19:12:12 +00:00
return true;
2018-08-16 14:34:15 +00:00
}
bool
TunEndpoint::SetupNetworking()
{
llarp::LogInfo("Set Up networking for ", Name());
2018-12-03 22:22:59 +00:00
if(!SetupTun())
2018-10-04 13:42:22 +00:00
{
2018-12-03 22:22:59 +00:00
llarp::LogError(Name(), " failed to set up network interface");
return false;
2018-10-04 13:42:22 +00:00
}
2018-12-03 22:22:59 +00:00
if(!m_Resolver.Start(m_LocalResolverAddr, m_UpstreamResolvers))
{
// downgrade DNS server failure to a warning
llarp::LogWarn(Name(), " failed to start dns server");
// return false;
}
2018-12-03 22:22:59 +00:00
return true;
2018-08-16 14:34:15 +00:00
}
void
TunEndpoint::Tick(llarp_time_t now)
{
// call tun code in endpoint logic in case of network isolation
2018-12-10 14:14:55 +00:00
// EndpointLogic()->queue_job({this, handleTickTun});
2018-12-10 15:39:22 +00:00
if(m_Exit)
EnsureRouterIsKnown(m_Exit->Endpoint());
2018-08-16 14:34:15 +00:00
Endpoint::Tick(now);
}
bool
TunEndpoint::Stop()
{
if(m_Exit)
m_Exit->Stop();
return llarp::service::Endpoint::Stop();
}
2018-08-22 15:52:10 +00:00
void
TunEndpoint::FlushSend()
{
2018-08-31 14:41:04 +00:00
m_UserToNetworkPktQueue.Process([&](net::IPv4Packet &pkt) {
2019-02-02 23:12:42 +00:00
std::function< bool(const llarp_buffer_t &) > sendFunc;
2018-08-31 14:41:04 +00:00
auto itr = m_IPToAddr.find(pkt.dst());
2018-08-22 15:52:10 +00:00
if(itr == m_IPToAddr.end())
{
2018-12-10 12:27:17 +00:00
if(m_Exit && !llarp::IsIPv4Bogon(pkt.dst()))
2018-11-14 19:34:17 +00:00
{
pkt.UpdateIPv4PacketOnDst({0}, pkt.dst());
m_Exit->QueueUpstreamTraffic(std::move(pkt),
llarp::routing::ExitPadSize);
2018-11-14 19:34:17 +00:00
}
else
llarp::LogWarn(Name(), " has no endpoint for ", pkt.dst());
2018-12-10 15:44:18 +00:00
return true;
2018-08-22 15:52:10 +00:00
}
2018-11-29 13:12:35 +00:00
if(m_SNodes.at(itr->second))
{
sendFunc = std::bind(&TunEndpoint::SendToSNodeOrQueue, this,
itr->second.as_array(), std::placeholders::_1);
2018-11-29 13:12:35 +00:00
}
else
2018-11-29 13:12:35 +00:00
{
sendFunc = std::bind(&TunEndpoint::SendToServiceOrQueue, this,
itr->second.as_array(), std::placeholders::_1,
service::eProtocolTraffic);
2018-11-29 13:12:35 +00:00
}
// prepare packet for insertion into network
// this includes clearing IP addresses, recalculating checksums, etc
pkt.UpdateIPv4PacketOnSrc();
2018-11-29 13:12:35 +00:00
if(sendFunc && sendFunc(pkt.Buffer()))
return true;
llarp::LogWarn(Name(), " did not flush packets");
2018-09-17 15:32:37 +00:00
return true;
2018-08-22 15:52:10 +00:00
});
}
bool
TunEndpoint::HandleWriteIPPacket(const llarp_buffer_t &b,
std::function< huint32_t(void) > getFromIP)
2018-08-18 14:01:21 +00:00
{
2018-11-03 13:19:18 +00:00
// llarp::LogInfo("got packet from ", msg->sender.Addr());
2018-11-29 13:12:35 +00:00
auto themIP = getFromIP();
2018-11-03 13:19:18 +00:00
// llarp::LogInfo("themIP ", themIP);
auto usIP = m_OurIP;
2019-02-03 00:48:10 +00:00
ManagedBuffer buf(b);
2018-11-29 13:12:35 +00:00
return m_NetworkToUserPktQueue.EmplaceIf(
[buf, themIP, usIP](net::IPv4Packet &pkt) -> bool {
// load
if(!pkt.Load(buf))
return false;
// filter out:
// - packets smaller than minimal IPv4 header
// - non-IPv4 packets
// - packets with weird src/dst addresses
// (0.0.0.0/8 but not 0.0.0.0)
// - packets with 0 src but non-0 dst and oposite
auto hdr = pkt.Header();
if(pkt.sz < sizeof(*hdr) || hdr->version != 4
|| (hdr->saddr != 0 && *(byte_t *)&(hdr->saddr) == 0)
|| (hdr->daddr != 0 && *(byte_t *)&(hdr->daddr) == 0)
|| ((hdr->saddr == 0) != (hdr->daddr == 0)))
{
return false;
}
2018-12-15 17:39:15 +00:00
// update packet to use proper addresses, recalc checksums
pkt.UpdateIPv4PacketOnDst(themIP, usIP);
return true;
});
2018-08-20 19:12:12 +00:00
}
2018-10-19 15:04:14 +00:00
2018-11-14 12:23:08 +00:00
huint32_t
TunEndpoint::GetIfAddr() const
{
2018-11-14 12:23:08 +00:00
return m_OurIP;
}
2018-08-20 19:12:12 +00:00
2018-10-10 15:14:45 +00:00
huint32_t
TunEndpoint::ObtainIPForAddr(const AlignedBuffer< 32 > &addr, bool snode)
2018-08-20 19:12:12 +00:00
{
2018-10-29 16:48:36 +00:00
llarp_time_t now = Now();
2018-10-10 15:14:45 +00:00
huint32_t nextIP = {0};
AlignedBuffer< 32 > ident(addr);
{
// previously allocated address
2018-11-14 20:56:54 +00:00
auto itr = m_AddrToIP.find(ident);
if(itr != m_AddrToIP.end())
2018-08-22 15:52:10 +00:00
{
// mark ip active
2018-09-16 12:25:17 +00:00
MarkIPActive(itr->second);
return itr->second;
2018-08-22 15:52:10 +00:00
}
}
// allocate new address
if(m_NextIP < m_MaxIP)
{
do
{
nextIP = ++m_NextIP;
} while(m_IPToAddr.find(nextIP) != m_IPToAddr.end()
&& m_NextIP < m_MaxIP);
if(nextIP < m_MaxIP)
{
2018-11-14 21:40:44 +00:00
m_AddrToIP[ident] = nextIP;
m_IPToAddr[nextIP] = ident;
m_SNodes[ident] = snode;
2018-11-14 20:56:54 +00:00
llarp::LogInfo(Name(), " mapped ", ident, " to ", nextIP);
MarkIPActive(nextIP);
return nextIP;
}
}
// we are full
// expire least active ip
// TODO: prevent DoS
2018-10-10 15:14:45 +00:00
std::pair< huint32_t, llarp_time_t > oldest = {huint32_t{0}, 0};
// find oldest entry
auto itr = m_IPActivity.begin();
while(itr != m_IPActivity.end())
{
if(itr->second <= now)
{
if((now - itr->second) > oldest.second)
{
oldest.first = itr->first;
oldest.second = itr->second;
}
}
++itr;
}
// remap address
2018-11-14 21:47:58 +00:00
m_IPToAddr[oldest.first] = ident;
m_AddrToIP[ident] = oldest.first;
m_SNodes[ident] = snode;
nextIP = oldest.first;
// mark ip active
m_IPActivity[nextIP] = std::max(m_IPActivity[nextIP], now);
2018-08-20 19:12:12 +00:00
return nextIP;
}
bool
2018-10-10 15:14:45 +00:00
TunEndpoint::HasRemoteForIP(huint32_t ip) const
2018-08-20 19:12:12 +00:00
{
return m_IPToAddr.find(ip) != m_IPToAddr.end();
2018-08-18 14:01:21 +00:00
}
void
2018-10-10 15:14:45 +00:00
TunEndpoint::MarkIPActive(huint32_t ip)
{
2018-10-29 16:48:36 +00:00
m_IPActivity[ip] = std::max(Now(), m_IPActivity[ip]);
}
2018-09-10 11:08:09 +00:00
void
2018-10-10 15:14:45 +00:00
TunEndpoint::MarkIPActiveForever(huint32_t ip)
2018-09-10 11:08:09 +00:00
{
m_IPActivity[ip] = std::numeric_limits< uint64_t >::max();
}
void
TunEndpoint::TickTun(__attribute__((unused)) llarp_time_t now)
{
// called in the isolated thread
}
void
TunEndpoint::tunifBeforeWrite(llarp_tun_io *tun)
{
// called in the isolated network thread
TunEndpoint *self = static_cast< TunEndpoint * >(tun->user);
// flush user to network
self->FlushSend();
// flush exit traffic queues if it's there
if(self->m_Exit)
self->m_Exit->Flush();
// flush snode traffic
self->FlushSNodeTraffic();
// flush network to user
self->m_NetworkToUserPktQueue.Process([tun](net::IPv4Packet &pkt) {
2018-11-23 14:37:26 +00:00
if(!llarp_ev_tun_async_write(tun, pkt.Buffer()))
2018-08-22 15:52:10 +00:00
llarp::LogWarn("packet dropped");
});
}
void
TunEndpoint::tunifRecvPkt(llarp_tun_io *tun, const llarp_buffer_t &b)
{
// called for every packet read from user in isolated network thread
TunEndpoint *self = static_cast< TunEndpoint * >(tun->user);
2019-02-03 00:48:10 +00:00
ManagedBuffer buf(b);
2018-08-20 19:12:12 +00:00
if(!self->m_UserToNetworkPktQueue.EmplaceIf(
2018-11-23 14:37:26 +00:00
[buf](net::IPv4Packet &pkt) -> bool {
return pkt.Load(buf) && pkt.Header()->version == 4;
2018-08-20 19:12:12 +00:00
}))
2018-09-28 23:47:18 +00:00
{
2019-01-21 04:20:21 +00:00
#if defined(DEBUG) || !defined(RELEASE_MOTTO)
2018-12-20 22:47:26 +00:00
llarp::LogInfo("invalid pkt");
llarp::DumpBuffer(buf.underlying);
#endif
2018-09-28 23:47:18 +00:00
}
}
2018-08-15 15:36:34 +00:00
TunEndpoint::~TunEndpoint()
{
}
2018-08-16 14:34:15 +00:00
} // namespace handlers
} // namespace llarp