llarp/handlers/tun.hpp

Namespaces

Name
llarp
[crypto.hpp]
llarp::handlers

Classes

Name
struct llarp::handlers::TunEndpoint

Source code

#pragma once

#include <llarp/dns/server.hpp>
#include <llarp/ev/ev.hpp>
#include <llarp/net/ip.hpp>
#include <llarp/net/ip_packet.hpp>
#include <llarp/net/net.hpp>
#include <llarp/service/endpoint.hpp>
#include <llarp/service/protocol_type.hpp>
#include <llarp/util/priority_queue.hpp>
#include <llarp/util/thread/threading.hpp>
#include <llarp/vpn/packet_router.hpp>
#include <llarp/vpn/platform.hpp>

#include <future>
#include <type_traits>
#include <variant>

namespace llarp
{
  namespace handlers
  {
    struct TunEndpoint : public service::Endpoint,
                         public dns::Resolver_Base,
                         public std::enable_shared_from_this<TunEndpoint>
    {
      TunEndpoint(AbstractRouter* r, llarp::service::Context* parent);
      ~TunEndpoint() override;

      vpn::NetworkInterface*
      GetVPNInterface() override
      {
        return m_NetIf.get();
      }

      int
      Rank() const override
      {
        return 0;
      }

      std::string_view
      ResolverName() const override
      {
        return "lokinet";
      }

      bool
      MaybeHookDNS(
          std::shared_ptr<dns::PacketSource_Base> source,
          const dns::Message& query,
          const SockAddr& to,
          const SockAddr& from) override;

      path::PathSet_ptr
      GetSelf() override
      {
        return shared_from_this();
      }

      std::weak_ptr<path::PathSet>
      GetWeak() override
      {
        return weak_from_this();
      }

      void
      Thaw() override;

      // Reconfigures DNS servers and restarts libunbound with the new servers.
      void
      ReconfigureDNS(std::vector<SockAddr> servers);

      bool
      Configure(const NetworkConfig& conf, const DnsConfig& dnsConf) override;

      void
      SendPacketToRemote(const llarp_buffer_t&, service::ProtocolType) override{};

      std::string
      GetIfName() const override;

      void
      Tick(llarp_time_t now) override;

      std::unordered_map<std::string, std::string>
      NotifyParams() const override;

      bool
      SupportsV6() const override;

      bool
      ShouldHookDNSMessage(const dns::Message& msg) const;

      bool
      HandleHookedDNSMessage(dns::Message query, std::function<void(dns::Message)> sendreply);

      void
      TickTun(llarp_time_t now);

      bool
      MapAddress(const service::Address& remote, net::ipv6addr_t ip, bool SNode);

      bool
      Start() override;

      bool
      Stop() override;

      bool
      IsSNode() const;

      bool
      SetupTun();

      void
      SetupDNS();

      std::shared_ptr<dns::Server>
      DNS() const override
      {
        return m_DNS;
      };

      bool
      SetupNetworking() override;

      bool
      HandleInboundPacket(
          const service::ConvoTag tag,
          const llarp_buffer_t& pkt,
          service::ProtocolType t,
          uint64_t seqno) override;

      bool
      HandleWriteIPPacket(
          const llarp_buffer_t& buf, net::ipv6addr_t src, net::ipv6addr_t dst, uint64_t seqno);

      void
      HandleGotUserPacket(llarp::net::IPPacket pkt);

      net::ipv6addr_t
      GetIfAddr() const override;

      bool
      HasIfAddr() const override
      {
        return true;
      }

      bool
      HasLocalIP(const net::ipv6addr_t& ip) const;

      std::optional<net::TrafficPolicy>
      GetExitPolicy() const override
      {
        return m_TrafficPolicy;
      }

      std::set<IPRange>
      GetOwnedRanges() const override
      {
        return m_OwnedRanges;
      }

      llarp_time_t
      PathAlignmentTimeout() const override
      {
        return m_PathAlignmentTimeout;
      }

      bool
      ShouldAllowTraffic(const net::IPPacket& pkt) const;

      std::optional<std::variant<service::Address, RouterID>>
      ObtainAddrForIP(net::ipv6addr_t ip) const override;

      bool
      HasAddress(const AlignedBuffer<32>& addr) const
      {
        return m_AddrToIP.find(addr) != m_AddrToIP.end();
      }

      net::ipv6addr_t
      ObtainIPForAddr(std::variant<service::Address, RouterID> addr) override;

      void
      ResetInternalState() override;

     protected:
      struct WritePacket
      {
        uint64_t seqno;
        net::IPPacket pkt;

        bool
        operator<(const WritePacket& other) const
        {
          return seqno < other.seqno;
        }
      };

      std::priority_queue<WritePacket> m_NetworkToUserPktQueue;

      void
      Pump(llarp_time_t now) override;

      bool
      HasRemoteForIP(net::ipv6addr_t ipv4) const;

      void
      MarkIPActive(net::ipv6addr_t ip);

      void
      MarkIPActiveForever(net::ipv6addr_t ip);

      void
      FlushWrite();

      std::unordered_map<net::ipv6addr_t, AlignedBuffer<32>> m_IPToAddr;
      std::unordered_map<AlignedBuffer<32>, net::ipv6addr_t> m_AddrToIP;

      std::unordered_map<AlignedBuffer<32>, bool> m_SNodes;

      std::unordered_map<net::ipv6addr_t, service::Address> m_ExitIPToExitAddress;

     private:
      std::optional<service::Address>
      ObtainExitAddressFor(
          net::ipv6addr_t ip,
          std::function<service::Address(std::unordered_set<service::Address>)> exitSelectionStrat =
              nullptr);

      template <typename Addr_t, typename Endpoint_t>
      void
      SendDNSReply(
          Addr_t addr,
          Endpoint_t ctx,
          std::shared_ptr<dns::Message> query,
          std::function<void(dns::Message)> reply,
          bool sendIPv6)
      {
        if (ctx)
        {
          auto ip = ObtainIPForAddr(addr);
          query->answers.clear();
          query->AddINReply(ToHost(ip), sendIPv6);
        }
        else
          query->AddNXReply();
        reply(*query);
      }

      std::shared_ptr<dns::Server> m_DNS;

      DnsConfig m_DnsConfig;

      std::unordered_map<net::ipv6addr_t, llarp_time_t> m_IPActivity;
      net::ipv6addr_t m_OurIP;
      net::ipv6addr_t m_OurIPv6;

      huint128_t m_NextIP;
      net::ipv6addr_t m_MaxIP;
      llarp::IPRange m_OurRange;
      std::vector<SockAddr> m_StrictConnectAddrs;
      bool m_UseV6;
      std::string m_IfName;

      std::optional<net::ipv6addr_t> m_BaseV6Address;

      std::shared_ptr<vpn::NetworkInterface> m_NetIf;

      std::shared_ptr<vpn::PacketRouter> m_PacketRouter;

      std::optional<net::TrafficPolicy> m_TrafficPolicy;
      std::set<IPRange> m_OwnedRanges;
      llarp_time_t m_PathAlignmentTimeout;

      std::optional<fs::path> m_PersistAddrMapFile;

      std::shared_ptr<vpn::I_Packet_IO> m_RawDNS;
    };

  }  // namespace handlers
}  // namespace llarp

Updated on 2026-01-10 at 22:49:45 +0000