diff --git a/llarp/dns/unbound_resolver.cpp b/llarp/dns/unbound_resolver.cpp deleted file mode 100644 index e29c39389..000000000 --- a/llarp/dns/unbound_resolver.cpp +++ /dev/null @@ -1,240 +0,0 @@ -#include "unbound_resolver.hpp" - -#include "server.hpp" -#include -#include -#include -#include -#include - -#include - -namespace llarp::dns -{ - static auto logcat = log::Cat("dns"); - - struct PendingUnboundLookup - { - std::weak_ptr resolver; - Message msg; - SockAddr resolverAddr; - SockAddr askerAddr; - }; - - void - UnboundResolver::Stop() - { - Reset(); - } - - void - UnboundResolver::Reset() - { - started = false; -#ifdef _WIN32 - if (runner.joinable()) - { - runner.join(); - } -#else - if (udp) - { - udp->close(); - } - udp.reset(); -#endif - if (unboundContext) - { - ub_ctx_delete(unboundContext); - } - unboundContext = nullptr; - } - - UnboundResolver::UnboundResolver(EventLoop_ptr _loop, ReplyFunction reply, FailFunction fail) - : unboundContext{nullptr} - , started{false} - , replyFunc{_loop->make_caller(std::move(reply))} - , failFunc{_loop->make_caller(std::move(fail))} - { -#ifndef _WIN32 - loop = _loop->MaybeGetUVWLoop(); -#endif - } - - // static callback - void - UnboundResolver::Callback(void* data, int err, ub_result* result) - { - std::unique_ptr lookup{static_cast(data)}; - - auto this_ptr = lookup->resolver.lock(); - if (not this_ptr) - return; // resolver is gone, so we don't reply. - - if (err != 0) - { - Message& msg = lookup->msg; - msg.AddServFail(); - this_ptr->failFunc(lookup->askerAddr, lookup->resolverAddr, msg); - ub_resolve_free(result); - return; - } - OwnedBuffer pkt{(size_t)result->answer_len}; - std::memcpy(pkt.buf.get(), result->answer_packet, pkt.sz); - llarp_buffer_t buf(pkt); - - MessageHeader hdr; - hdr.Decode(&buf); - hdr.id = lookup->msg.hdr_id; - - buf.cur = buf.base; - hdr.Encode(&buf); - - this_ptr->replyFunc(lookup->askerAddr, lookup->resolverAddr, std::move(pkt)); - - ub_resolve_free(result); - } - - bool - UnboundResolver::Init() - { - if (started) - { - Reset(); - } - - unboundContext = ub_ctx_create(); - - if (not unboundContext) - { - return false; - } - - // disable ip6 for upstream dns - ub_ctx_set_option(unboundContext, "prefer-ip6", "0"); - // enable async - ub_ctx_async(unboundContext, 1); -#ifdef _WIN32 - runner = std::thread{[&]() { - while (started) - { - if (unboundContext) - ub_wait(unboundContext); - std::this_thread::sleep_for(25ms); - } - if (unboundContext) - ub_process(unboundContext); - }}; -#else - if (auto loop_ptr = loop.lock()) - { - udp = loop_ptr->resource(ub_fd(unboundContext)); - udp->on([ptr = weak_from_this()](auto&, auto&) { - if (auto self = ptr.lock()) - { - if (self->unboundContext) - { - ub_process(self->unboundContext); - } - } - }); - udp->start(uvw::PollHandle::Event::READABLE); - } -#endif - started = true; - return true; - } - - bool - UnboundResolver::AddUpstreamResolver(const SockAddr& upstreamResolver) - { - const auto hoststr = upstreamResolver.hostString(); - std::string upstream = hoststr; - - const auto port = upstreamResolver.getPort(); - if (port != 53) - { - upstream += '@'; - upstream += std::to_string(port); - } - - log::info("Adding upstream resolver ", upstream); - if (ub_ctx_set_fwd(unboundContext, upstream.c_str()) != 0) - { - Reset(); - return false; - } - - if constexpr (platform::is_apple) - { - // On Apple, when we turn on exit mode, we can't directly connect to upstream from here - // because, from within the network extension, macOS ignores setting the tunnel as the default - // route and would leak all DNS; instead we have to bounce things through the objective C - // trampoline code so that it can call into Apple's special snowflake API to set up a socket - // that has the magic Apple snowflake sauce added on top so that it actually routes through - // the tunnel instead of around it. - // - // This behaviour is all carefully and explicitly documented by Apple with plenty of examples - // and other exposition, of course, just like all of their wonderful new APIs to reinvent - // standard unix interfaces. - if (hoststr == "127.0.0.1" && port == apple::dns_trampoline_port) - { - // Not at all clear why this is needed but without it we get "send failed: Can't assign - // requested address" when unbound tries to connect to the localhost address using a source - // address of 0.0.0.0. Yay apple. - ub_ctx_set_option(unboundContext, "outgoing-interface:", "127.0.0.1"); - - // The trampoline expects just a single source port (and sends everything back to it) - ub_ctx_set_option(unboundContext, "outgoing-range:", "1"); - ub_ctx_set_option(unboundContext, "outgoing-port-avoid:", "0-65535"); - ub_ctx_set_option( - unboundContext, - "outgoing-port-permit:", - std::to_string(apple::dns_trampoline_source_port).c_str()); - } - } - - return true; - } - - void - UnboundResolver::AddHostsFile(const fs::path& file) - { - log::debug(logcat, "adding hosts file {}", file); - const auto str = file.u8string(); - if (auto ret = ub_ctx_hosts(unboundContext, str.c_str())) - throw std::runtime_error{ - fmt::format("Failed to add host file {}: {}", file, ub_strerror(ret))}; - log::info(logcat, "added hosts file {}", file); - } - - void - UnboundResolver::Lookup(SockAddr to, SockAddr from, Message msg) - { - if (not unboundContext) - { - msg.AddServFail(); - failFunc(from, to, std::move(msg)); - return; - } - - const auto& q = msg.questions[0]; - auto* lookup = new PendingUnboundLookup{weak_from_this(), msg, to, from}; - int err = ub_resolve_async( - unboundContext, - q.Name().c_str(), - q.qtype, - q.qclass, - (void*)lookup, - &UnboundResolver::Callback, - nullptr); - - if (err != 0) - { - msg.AddServFail(); - failFunc(from, to, std::move(msg)); - return; - } - } - -} // namespace llarp::dns diff --git a/llarp/dns/unbound_resolver.hpp b/llarp/dns/unbound_resolver.hpp deleted file mode 100644 index 4d79569ce..000000000 --- a/llarp/dns/unbound_resolver.hpp +++ /dev/null @@ -1,75 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#include -#include - -#include "message.hpp" - -#ifdef _WIN32 -#include -#else -#include -#endif - -extern "C" -{ - struct ub_ctx; - struct ub_result; -} - -namespace llarp::dns -{ - using ReplyFunction = - std::function; - using FailFunction = - std::function; - - class UnboundResolver : public std::enable_shared_from_this - { - private: - ub_ctx* unboundContext; - - std::atomic started; - -#ifdef _WIN32 - std::thread runner; -#else - std::weak_ptr loop; - std::shared_ptr udp; -#endif - - ReplyFunction replyFunc; - FailFunction failFunc; - void - Reset(); - - public: - UnboundResolver(EventLoop_ptr loop, ReplyFunction replyFunc, FailFunction failFunc); - - static void - Callback(void* data, int err, ub_result* result); - - // stop resolver thread - void - Stop(); - - // upstream resolver IP can be IPv4 or IPv6 - bool - Init(); - - bool - AddUpstreamResolver(const SockAddr& upstreamResolverIP); - - void - AddHostsFile(const fs::path& file); - - void - Lookup(SockAddr to, SockAddr from, Message msg); - }; - -} // namespace llarp::dns