#ifndef LLARP_HANDLERS_TUN_HPP #define LLARP_HANDLERS_TUN_HPP #include #include #include #include #include #include #include #include namespace llarp { namespace handlers { static const int DefaultTunNetmask = 16; static const char DefaultTunIfname[] = "lokinet0"; static const char DefaultTunDstAddr[] = "10.10.0.1"; static const char DefaultTunSrcAddr[] = "10.10.0.2"; struct TunEndpoint : public service::Endpoint, public dns::IQueryHandler, public std::enable_shared_from_this< TunEndpoint > { TunEndpoint(const std::string& nickname, AbstractRouter* r, llarp::service::Context* parent); ~TunEndpoint(); path::PathSet_ptr GetSelf() override { return shared_from_this(); } virtual bool SetOption(const std::string& k, const std::string& v) override; virtual void Tick(llarp_time_t now) override; util::StatusObject ExtractStatus() const; std::unordered_map< std::string, std::string > NotifyParams() const override; bool ShouldHookDNSMessage(const dns::Message& msg) const override; bool HandleHookedDNSMessage( dns::Message&& query, std::function< void(dns::Message) > sendreply) override; void TickTun(llarp_time_t now); bool MapAddress(const service::Address& remote, huint32_t ip, bool SNode); bool Start() override; bool Stop() override; bool IsSNode() const; /// set up tun interface, blocking bool SetupTun(); /// overrides Endpoint bool SetupNetworking() override; /// overrides Endpoint /// handle inbound traffic bool HandleWriteIPPacket(const llarp_buffer_t& buf, std::function< huint32_t(void) > getFromIP) override; /// queue outbound packet to the world bool QueueOutboundTraffic(llarp::net::IPv4Packet&& pkt); /// we have a resolvable ip address bool HasIfAddr() const override { return true; } /// get the local interface's address huint32_t GetIfAddr() const override; bool HasLocalIP(const huint32_t& ip) const; llarp_tun_io tunif; std::unique_ptr< llarp_fd_promise > Promise; /// called before writing to tun interface static void tunifBeforeWrite(llarp_tun_io* t); /// handle user to network send buffer flush /// called in router logic thread static void handleNetSend(void*); /// called every time we wish to read a packet from the tun interface static void tunifRecvPkt(llarp_tun_io* t, const llarp_buffer_t& buf); /// called in the endpoint logic thread static void handleTickTun(void* u); /// get a key for ip address template < typename Addr > Addr ObtainAddrForIP(huint32_t ip, bool isSNode) { auto itr = m_IPToAddr.find(ip); if(itr == m_IPToAddr.end() || m_SNodes[itr->second] != isSNode) { // not found Addr addr; addr.Zero(); return addr; } // found return Addr{itr->second}; } bool HasAddress(const AlignedBuffer< 32 >& addr) const override { return m_AddrToIP.find(addr) != m_AddrToIP.end(); } /// get ip address for key unconditionally huint32_t ObtainIPForAddr(const AlignedBuffer< 32 >& addr, bool serviceNode) override; /// flush network traffic void Flush(); protected: using PacketQueue_t = llarp::util::CoDelQueue< net::IPv4Packet, net::IPv4Packet::GetTime, net::IPv4Packet::PutTime, net::IPv4Packet::CompareOrder, net::IPv4Packet::GetNow >; /// queue for sending packets over the network from us PacketQueue_t m_UserToNetworkPktQueue; /// queue for sending packets to user from network PacketQueue_t m_NetworkToUserPktQueue; /// return true if we have a remote loki address for this ip address bool HasRemoteForIP(huint32_t ipv4) const; /// mark this address as active void MarkIPActive(huint32_t ip); /// mark this address as active forever void MarkIPActiveForever(huint32_t ip); /// flush ip packets virtual void FlushSend(); /// maps ip to key (host byte order) std::unordered_map< huint32_t, AlignedBuffer< 32 >, huint32_t::Hash > m_IPToAddr; /// maps key to ip (host byte order) std::unordered_map< AlignedBuffer< 32 >, huint32_t, AlignedBuffer< 32 >::Hash > m_AddrToIP; /// maps key to true if key is a service node, maps key to false if key is /// a hidden service std::unordered_map< AlignedBuffer< 32 >, bool, AlignedBuffer< 32 >::Hash > m_SNodes; private: bool QueueInboundPacketForExit(const llarp_buffer_t& buf) { ManagedBuffer copy{buf}; return m_NetworkToUserPktQueue.EmplaceIf( [&](llarp::net::IPv4Packet& pkt) -> bool { if(!pkt.Load(copy.underlying)) return false; pkt.UpdateIPv4PacketOnDst(pkt.src(), m_OurIP); return true; }); } template < typename Addr_t, typename Endpoint_t > void SendDNSReply(Addr_t addr, Endpoint_t ctx, dns::Message* query, std::function< void(dns::Message) > reply, bool snode, bool sendIPv6) { if(ctx) { huint32_t ip = ObtainIPForAddr(addr, snode); query->AddINReply(ip, sendIPv6); } else query->AddNXReply(); reply(*query); delete query; } #ifndef WIN32 /// handles fd injection force android std::promise< std::pair< int, int > > m_VPNPromise; #endif /// our dns resolver dns::Proxy m_Resolver; /// maps ip address to timestamp last active std::unordered_map< huint32_t, llarp_time_t, huint32_t::Hash > m_IPActivity; /// our ip address (host byte order) huint32_t m_OurIP; /// next ip address to allocate (host byte order) huint32_t m_NextIP; /// highest ip address to allocate (host byte order) huint32_t m_MaxIP; /// our ip range we are using llarp::IPRange m_OurRange; /// upstream dns resolver list std::vector< llarp::Addr > m_UpstreamResolvers; /// local dns llarp::Addr m_LocalResolverAddr; /// list of strict connect addresses for hooks std::vector< llarp::Addr > m_StrictConnectAddrs; }; } // namespace handlers } // namespace llarp #endif