2018-10-10 12:06:28 +00:00
|
|
|
#include <algorithm>
|
2018-08-22 07:35:49 +00:00
|
|
|
// harmless on other platforms
|
|
|
|
#define __USE_MINGW_ANSI_STDIO 1
|
2018-08-16 14:34:15 +00:00
|
|
|
#include <llarp/handlers/tun.hpp>
|
|
|
|
#include "router.hpp"
|
2018-09-23 16:48:43 +00:00
|
|
|
#include <sys/types.h>
|
2018-09-25 08:31:29 +00:00
|
|
|
#ifndef _WIN32
|
2018-09-23 16:48:43 +00:00
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <netdb.h>
|
2018-09-25 08:31:29 +00:00
|
|
|
#endif
|
2018-11-26 22:46:22 +00:00
|
|
|
#include "ev.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
|
|
|
{
|
2018-11-26 22:46:22 +00:00
|
|
|
|
|
|
|
static llarp_fd_promise * get_tun_fd_promise(llarp_tun_io * tun)
|
|
|
|
{
|
|
|
|
return static_cast<TunEndpoint *>(tun->user)->Promise.get();
|
|
|
|
}
|
|
|
|
|
2018-08-16 14:34:15 +00:00
|
|
|
TunEndpoint::TunEndpoint(const std::string &nickname, llarp_router *r)
|
|
|
|
: service::Endpoint(nickname, r)
|
2018-11-15 13:13:19 +00:00
|
|
|
, m_UserToNetworkPktQueue(nickname + "_sendq", r->netloop, r->netloop)
|
|
|
|
, m_NetworkToUserPktQueue(nickname + "_recvq", r->netloop, r->netloop)
|
2018-08-15 15:36:34 +00:00
|
|
|
{
|
2018-11-26 22:46:22 +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;
|
2018-08-17 19:49:58 +00:00
|
|
|
tunif.netmask = DefaultTunNetmask;
|
|
|
|
strncpy(tunif.ifaddr, DefaultTunSrcAddr, sizeof(tunif.ifaddr) - 1);
|
|
|
|
strncpy(tunif.ifname, DefaultTunIfname, sizeof(tunif.ifname) - 1);
|
2018-09-22 10:25:16 +00:00
|
|
|
tunif.tick = nullptr;
|
|
|
|
tunif.before_write = &tunifBeforeWrite;
|
|
|
|
tunif.recvpkt = &tunifRecvPkt;
|
|
|
|
this->dll.ip_tracker = nullptr;
|
2018-10-03 10:48:31 +00:00
|
|
|
this->dll.user = &r->hiddenServiceContext;
|
2018-09-22 10:25:16 +00:00
|
|
|
// this->dll.callback = std::bind(&TunEndpoint::MapAddress, this);
|
2018-08-16 14:34:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
TunEndpoint::SetOption(const std::string &k, const std::string &v)
|
|
|
|
{
|
2018-11-14 19:34:17 +00:00
|
|
|
if(k == "exit-node")
|
|
|
|
{
|
|
|
|
llarp::RouterID exitRouter;
|
|
|
|
if(!HexDecode(v.c_str(), exitRouter, exitRouter.size()))
|
|
|
|
{
|
|
|
|
llarp::LogError(Name(), " bad exit router key: ", v);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
m_Exit.reset(new llarp::exit::BaseSession(
|
|
|
|
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;
|
2018-11-18 17:41:09 +00:00
|
|
|
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);
|
2018-11-11 13:30:54 +00:00
|
|
|
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(), " local dns set to ", m_LocalResolverAddr);
|
|
|
|
}
|
|
|
|
if(k == "upstream-dns")
|
|
|
|
{
|
|
|
|
std::string resolverAddr = v;
|
2018-11-18 17:41:09 +00:00
|
|
|
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);
|
2018-11-11 13:30:54 +00:00
|
|
|
dnsport = std::atoi(v.substr(pos + 1).c_str());
|
2018-11-11 13:14:19 +00:00
|
|
|
}
|
|
|
|
m_UpstreamDNSAddr = llarp::Addr(resolverAddr, dnsport);
|
|
|
|
llarp::LogInfo(Name(), " upstream dns set to ", m_UpstreamDNSAddr);
|
|
|
|
}
|
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;
|
|
|
|
}
|
2018-10-10 15:14:45 +00:00
|
|
|
return MapAddress(addr, huint32_t{ntohl(ip.s_addr)});
|
2018-08-22 15:52:10 +00:00
|
|
|
}
|
2018-08-16 14:34:15 +00:00
|
|
|
if(k == "ifname")
|
|
|
|
{
|
|
|
|
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);
|
2018-09-22 10:25:16 +00:00
|
|
|
|
|
|
|
// set up address in dotLokiLookup
|
2018-11-03 13:22:07 +00:00
|
|
|
// llarp::Addr tunIp(tunif.ifaddr);
|
2018-11-03 13:19:18 +00:00
|
|
|
llarp::huint32_t tunIpV4;
|
|
|
|
tunIpV4.h = inet_addr(tunif.ifaddr);
|
2018-09-23 16:48:43 +00:00
|
|
|
// related to dns_iptracker_setup_dotLokiLookup(&this->dll, tunIp);
|
2018-11-03 13:19:18 +00:00
|
|
|
dns_iptracker_setup(
|
|
|
|
this->dll.ip_tracker,
|
|
|
|
tunIpV4); // claim GW IP to make sure it's not inuse
|
2018-08-16 14:34:15 +00:00
|
|
|
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-08-22 15:52:10 +00:00
|
|
|
bool
|
2018-10-10 15:14:45 +00:00
|
|
|
TunEndpoint::MapAddress(const service::Address &addr, huint32_t ip)
|
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).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
|
|
|
|
2018-11-14 12:23:08 +00:00
|
|
|
m_IPToAddr.insert(std::make_pair(ip, addr.data()));
|
|
|
|
m_AddrToIP.insert(std::make_pair(addr.data(), ip));
|
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()
|
|
|
|
{
|
|
|
|
// do network isolation first
|
|
|
|
if(!Endpoint::Start())
|
|
|
|
return false;
|
2018-10-19 16:47:06 +00:00
|
|
|
#ifdef WIN32
|
2018-08-21 18:39:18 +00:00
|
|
|
return SetupNetworking();
|
|
|
|
#else
|
2018-08-16 14:34:15 +00:00
|
|
|
if(!NetworkIsIsolated())
|
|
|
|
{
|
2018-10-03 10:48:31 +00:00
|
|
|
llarp::LogInfo("Setting up global DNS IP tracker");
|
2018-11-03 13:19:18 +00:00
|
|
|
llarp::huint32_t tunIpV4;
|
|
|
|
tunIpV4.h = inet_addr(tunif.ifaddr);
|
2018-10-03 10:48:31 +00:00
|
|
|
dns_iptracker_setup_dotLokiLookup(
|
2018-11-03 13:19:18 +00:00
|
|
|
&this->dll, tunIpV4); // just set ups dll to use global iptracker
|
|
|
|
dns_iptracker_setup(
|
|
|
|
this->dll.ip_tracker,
|
|
|
|
tunIpV4); // claim GW IP to make sure it's not inuse
|
2018-10-03 10:48:31 +00:00
|
|
|
|
2018-08-16 14:34:15 +00:00
|
|
|
// set up networking in currrent thread if we are not isolated
|
|
|
|
if(!SetupNetworking())
|
|
|
|
return false;
|
2018-09-22 10:25:16 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
llarp::LogInfo("Setting up per netns DNS IP tracker");
|
2018-11-03 13:19:18 +00:00
|
|
|
llarp::huint32_t tunIpV4;
|
|
|
|
tunIpV4.h = inet_addr(tunif.ifaddr);
|
2018-10-04 14:10:42 +00:00
|
|
|
llarp::Addr tunIp(tunif.ifaddr);
|
2018-09-22 10:25:16 +00:00
|
|
|
this->dll.ip_tracker = new dns_iptracker;
|
2018-10-04 14:10:42 +00:00
|
|
|
dns_iptracker_setup_dotLokiLookup(
|
2018-11-03 13:19:18 +00:00
|
|
|
&this->dll, tunIpV4); // just set ups dll to use global iptracker
|
|
|
|
dns_iptracker_setup(
|
|
|
|
this->dll.ip_tracker,
|
|
|
|
tunIpV4); // claim GW IP to make sure it's not inuse
|
2018-08-16 14:34:15 +00:00
|
|
|
}
|
|
|
|
// wait for result for network setup
|
|
|
|
llarp::LogInfo("waiting for tun interface...");
|
|
|
|
return m_TunSetupResult.get_future().get();
|
2018-08-21 18:39:18 +00:00
|
|
|
#endif
|
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");
|
|
|
|
return false;
|
|
|
|
}
|
2018-09-23 16:48:43 +00:00
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
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-10-10 15:14:45 +00:00
|
|
|
m_OurIP = lAddr.xtohl();
|
|
|
|
m_NextIP = m_OurIP;
|
|
|
|
auto xmask = netmask_ipv4_bits(tunif.netmask);
|
2018-11-15 13:13:19 +00:00
|
|
|
m_MaxIP = m_OurIP ^ (~xmask);
|
2018-09-23 16:48:43 +00:00
|
|
|
llarp::LogInfo(Name(), " set ", tunif.ifname, " to have address ", lAddr);
|
2018-08-21 18:17:16 +00:00
|
|
|
|
2018-11-03 13:19:18 +00:00
|
|
|
llarp::LogInfo(Name(), " allocated up to ", m_MaxIP);
|
2018-08-20 19:12:12 +00:00
|
|
|
return true;
|
2018-08-16 14:34:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
TunEndpoint::SetupNetworking()
|
|
|
|
{
|
2018-08-17 19:49:58 +00:00
|
|
|
llarp::LogInfo("Set Up networking for ", Name());
|
2018-08-16 14:34:15 +00:00
|
|
|
bool result = SetupTun();
|
2018-10-19 16:54:08 +00:00
|
|
|
#ifndef WIN32
|
2018-10-05 07:57:48 +00:00
|
|
|
m_TunSetupResult.set_value(
|
|
|
|
result); // now that NT has tun, we don't need the CPP guard
|
2018-10-19 16:54:08 +00:00
|
|
|
#endif
|
2018-10-04 13:42:22 +00:00
|
|
|
if(!NetworkIsIsolated())
|
|
|
|
{
|
|
|
|
// need to check to see if we have more than one hidden service
|
|
|
|
// well we'll only use the primary
|
|
|
|
// FIXME: detect number of hidden services
|
|
|
|
llarp::LogWarn(
|
|
|
|
"Only utilizing first hidden service for .loki look ups");
|
|
|
|
// because we can't find to the tun interface because we don't want it
|
|
|
|
// accessible on lokinet we can only bind one to loopback, and we can't
|
|
|
|
// really utilize anything other than port 53 we can't bind to our
|
|
|
|
// public interface, don't want it exploitable maybe we could detect if
|
|
|
|
// you have a private interface
|
|
|
|
}
|
2018-11-11 13:14:19 +00:00
|
|
|
|
|
|
|
llarp::LogInfo("TunDNS set up ", m_LocalResolverAddr, " to ",
|
|
|
|
m_UpstreamDNSAddr);
|
2018-09-22 10:25:16 +00:00
|
|
|
if(!llarp_dnsd_init(&this->dnsd, EndpointLogic(), EndpointNetLoop(),
|
2018-11-11 13:14:19 +00:00
|
|
|
m_LocalResolverAddr, m_UpstreamDNSAddr))
|
2018-09-22 10:25:16 +00:00
|
|
|
{
|
|
|
|
llarp::LogError("Couldnt init dns daemon");
|
|
|
|
}
|
2018-09-23 16:48:43 +00:00
|
|
|
// configure hook for .loki lookup
|
2018-09-22 10:25:16 +00:00
|
|
|
dnsd.intercept = &llarp_dotlokilookup_handler;
|
2018-09-23 16:48:43 +00:00
|
|
|
// set dotLokiLookup (this->dll) configuration
|
2018-09-22 10:25:16 +00:00
|
|
|
dnsd.user = &this->dll;
|
2018-08-16 14:34:15 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
TunEndpoint::Tick(llarp_time_t now)
|
|
|
|
{
|
|
|
|
// call tun code in endpoint logic in case of network isolation
|
2018-11-26 13:30:03 +00:00
|
|
|
// llarp_logic_queue_job(EndpointLogic(), {this, handleTickTun});
|
2018-08-22 15:52:10 +00:00
|
|
|
FlushSend();
|
2018-08-16 14:34:15 +00:00
|
|
|
Endpoint::Tick(now);
|
|
|
|
}
|
|
|
|
|
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) {
|
|
|
|
auto itr = m_IPToAddr.find(pkt.dst());
|
2018-08-22 15:52:10 +00:00
|
|
|
if(itr == m_IPToAddr.end())
|
|
|
|
{
|
2018-11-14 19:34:17 +00:00
|
|
|
if(m_Exit)
|
|
|
|
{
|
|
|
|
pkt.UpdateIPv4PacketOnDst({0}, pkt.dst());
|
|
|
|
m_Exit->SendUpstreamTraffic(std::move(pkt));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
llarp::LogWarn(Name(), " has no endpoint for ", pkt.dst());
|
2018-08-22 15:52:10 +00:00
|
|
|
return true;
|
|
|
|
}
|
2018-10-10 00:28:53 +00:00
|
|
|
|
|
|
|
// prepare packet for insertion into network
|
2018-10-10 21:29:49 +00:00
|
|
|
// this includes clearing IP addresses, recalculating checksums, etc
|
2018-11-01 17:15:01 +00:00
|
|
|
pkt.UpdateIPv4PacketOnSrc();
|
2018-10-10 00:28:53 +00:00
|
|
|
|
2018-11-14 12:23:08 +00:00
|
|
|
if(!SendToOrQueue(itr->second.data(), pkt.Buffer(),
|
|
|
|
service::eProtocolTraffic))
|
2018-09-17 15:32:37 +00:00
|
|
|
{
|
|
|
|
llarp::LogWarn(Name(), " did not flush packets");
|
|
|
|
}
|
|
|
|
return true;
|
2018-08-22 15:52:10 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-09-18 11:08:47 +00:00
|
|
|
bool
|
2018-09-18 17:48:26 +00:00
|
|
|
TunEndpoint::ProcessDataMessage(service::ProtocolMessage *msg)
|
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-14 12:23:08 +00:00
|
|
|
auto themIP = ObtainIPForAddr(msg->sender.Addr().data());
|
2018-11-03 13:19:18 +00:00
|
|
|
// llarp::LogInfo("themIP ", themIP);
|
|
|
|
auto usIP = m_OurIP;
|
|
|
|
auto buf = llarp::Buffer(msg->payload);
|
2018-09-16 12:25:17 +00:00
|
|
|
if(m_NetworkToUserPktQueue.EmplaceIf(
|
2018-08-31 14:41:04 +00:00
|
|
|
[buf, themIP, usIP](net::IPv4Packet &pkt) -> bool {
|
2018-10-13 18:57:31 +00:00
|
|
|
// 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)
|
2018-10-14 21:56:14 +00:00
|
|
|
// - packets with 0 src but non-0 dst and oposite
|
2018-10-13 18:57:31 +00:00
|
|
|
auto hdr = pkt.Header();
|
|
|
|
if(pkt.sz < sizeof(*hdr) || hdr->version != 4
|
2018-10-14 21:56:14 +00:00
|
|
|
|| (hdr->saddr != 0 && *(byte_t *)&(hdr->saddr) == 0)
|
|
|
|
|| (hdr->daddr != 0 && *(byte_t *)&(hdr->daddr) == 0)
|
|
|
|
|| ((hdr->saddr == 0) != (hdr->daddr == 0)))
|
2018-10-13 18:57:31 +00:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2018-10-10 21:29:49 +00:00
|
|
|
// update packet to use proper addresses, recalc checksums
|
2018-11-01 17:15:01 +00:00
|
|
|
pkt.UpdateIPv4PacketOnDst(themIP, usIP);
|
2018-08-20 19:12:12 +00:00
|
|
|
return true;
|
|
|
|
}))
|
2018-09-16 12:25:17 +00:00
|
|
|
|
2018-09-19 13:37:46 +00:00
|
|
|
llarp::LogDebug(Name(), " handle data message ", msg->payload.size(),
|
2018-11-03 13:19:18 +00:00
|
|
|
" bytes from ", themIP);
|
2018-09-18 11:08:47 +00:00
|
|
|
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-10-19 14:53:06 +00:00
|
|
|
{
|
2018-11-14 12:23:08 +00:00
|
|
|
return m_OurIP;
|
2018-10-19 14:53:06 +00:00
|
|
|
}
|
2018-08-20 19:12:12 +00:00
|
|
|
|
2018-10-10 15:14:45 +00:00
|
|
|
huint32_t
|
2018-11-14 21:47:58 +00:00
|
|
|
TunEndpoint::ObtainIPForAddr(const byte_t *a)
|
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};
|
2018-11-14 21:47:58 +00:00
|
|
|
AlignedBuffer< 32 > ident(a);
|
2018-08-21 18:17:16 +00:00
|
|
|
{
|
|
|
|
// previously allocated address
|
2018-11-14 20:56:54 +00:00
|
|
|
auto itr = m_AddrToIP.find(ident);
|
2018-08-21 18:17:16 +00:00
|
|
|
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);
|
2018-08-21 18:17:16 +00:00
|
|
|
return itr->second;
|
2018-08-22 15:52:10 +00:00
|
|
|
}
|
2018-08-21 18:17:16 +00:00
|
|
|
}
|
2018-09-13 16:41:53 +00:00
|
|
|
// allocate new address
|
2018-08-21 18:17:16 +00:00
|
|
|
if(m_NextIP < m_MaxIP)
|
|
|
|
{
|
2018-09-19 14:49:42 +00:00
|
|
|
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;
|
2018-11-14 20:56:54 +00:00
|
|
|
llarp::LogInfo(Name(), " mapped ", ident, " to ", nextIP);
|
2018-09-19 14:49:42 +00:00
|
|
|
MarkIPActive(nextIP);
|
|
|
|
return nextIP;
|
|
|
|
}
|
2018-08-21 18:17:16 +00:00
|
|
|
}
|
|
|
|
|
2018-09-19 14:49:42 +00:00
|
|
|
// 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};
|
2018-09-19 14:49:42 +00:00
|
|
|
|
|
|
|
// find oldest entry
|
|
|
|
auto itr = m_IPActivity.begin();
|
|
|
|
while(itr != m_IPActivity.end())
|
|
|
|
{
|
|
|
|
if(itr->second <= now)
|
2018-08-21 18:17:16 +00:00
|
|
|
{
|
2018-09-19 14:49:42 +00:00
|
|
|
if((now - itr->second) > oldest.second)
|
2018-08-21 18:17:16 +00:00
|
|
|
{
|
2018-09-19 14:49:42 +00:00
|
|
|
oldest.first = itr->first;
|
|
|
|
oldest.second = itr->second;
|
2018-08-21 18:17:16 +00:00
|
|
|
}
|
|
|
|
}
|
2018-09-19 14:49:42 +00:00
|
|
|
++itr;
|
2018-08-21 18:17:16 +00:00
|
|
|
}
|
2018-09-19 14:49:42 +00:00
|
|
|
// remap address
|
2018-11-14 21:47:58 +00:00
|
|
|
m_IPToAddr[oldest.first] = ident;
|
|
|
|
m_AddrToIP[ident] = oldest.first;
|
2018-09-19 14:49:42 +00:00
|
|
|
nextIP = oldest.first;
|
2018-08-21 18:17:16 +00:00
|
|
|
|
|
|
|
// mark ip active
|
2018-09-10 16:36:36 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2018-08-21 18:17:16 +00:00
|
|
|
void
|
2018-10-10 15:14:45 +00:00
|
|
|
TunEndpoint::MarkIPActive(huint32_t ip)
|
2018-08-21 18:17:16 +00:00
|
|
|
{
|
2018-10-29 16:48:36 +00:00
|
|
|
m_IPActivity[ip] = std::max(Now(), m_IPActivity[ip]);
|
2018-08-21 18:17:16 +00:00
|
|
|
}
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2018-08-16 14:34:15 +00:00
|
|
|
void
|
|
|
|
TunEndpoint::handleTickTun(void *u)
|
|
|
|
{
|
|
|
|
TunEndpoint *self = static_cast< TunEndpoint * >(u);
|
2018-10-29 16:48:36 +00:00
|
|
|
self->TickTun(self->Now());
|
2018-08-15 15:36:34 +00:00
|
|
|
}
|
|
|
|
|
2018-08-17 19:49:58 +00:00
|
|
|
void
|
2018-11-07 15:30:22 +00:00
|
|
|
TunEndpoint::TickTun(__attribute__((unused)) llarp_time_t now)
|
2018-08-17 19:49:58 +00:00
|
|
|
{
|
|
|
|
// called in the isolated thread
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
TunEndpoint::tunifBeforeWrite(llarp_tun_io *tun)
|
|
|
|
{
|
2018-08-21 18:17:16 +00:00
|
|
|
// called in the isolated network thread
|
2018-08-17 19:49:58 +00:00
|
|
|
TunEndpoint *self = static_cast< TunEndpoint * >(tun->user);
|
2018-11-06 22:48:17 +00:00
|
|
|
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");
|
|
|
|
});
|
|
|
|
if(self->m_UserToNetworkPktQueue.Size())
|
|
|
|
llarp_logic_queue_job(self->RouterLogic(), {self, &handleNetSend});
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
TunEndpoint::handleNetSend(void *user)
|
|
|
|
{
|
|
|
|
TunEndpoint *self = static_cast< TunEndpoint * >(user);
|
|
|
|
self->FlushSend();
|
2018-08-17 19:49:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-11-23 14:37:26 +00:00
|
|
|
TunEndpoint::tunifRecvPkt(llarp_tun_io *tun, llarp_buffer_t buf)
|
2018-08-17 19:49:58 +00:00
|
|
|
{
|
|
|
|
// called for every packet read from user in isolated network thread
|
|
|
|
TunEndpoint *self = static_cast< TunEndpoint * >(tun->user);
|
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 {
|
2018-11-26 13:30:03 +00:00
|
|
|
return pkt.Load(buf) && pkt.Header()->version == 4;
|
2018-08-20 19:12:12 +00:00
|
|
|
}))
|
2018-09-28 23:47:18 +00:00
|
|
|
{
|
|
|
|
llarp::LogInfo("Failed to parse ipv4 packet");
|
2018-11-23 14:37:26 +00:00
|
|
|
llarp::DumpBuffer(buf);
|
2018-09-28 23:47:18 +00:00
|
|
|
}
|
2018-08-17 19:49:58 +00:00
|
|
|
}
|
|
|
|
|
2018-08-15 15:36:34 +00:00
|
|
|
TunEndpoint::~TunEndpoint()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-08-16 14:34:15 +00:00
|
|
|
} // namespace handlers
|
|
|
|
} // namespace llarp
|