ReconfigureDNS fixes, fixes macos exit mode

- ReconfigureDNS wasn't returning the old servers; made it void instead
  (the Apple code can just store a copy of the original upstream
  servers instead).
- Reconfiguring DNS reset the unbound context but didn't replace it, so
  a Down()/Up() would crash.
- Simplify Resolver() destructor to just call Down(), and make it final
  just so that no one tries to inherit from us (so that calling a
  virtual function from the destructor is safe).
- Rename CancelPendingQueries() to Down(); the former cancelled but also
  shut down the object, so the name seemed a bit misleading.
- Rename SetInternalState in Resolver_Base to ResetResolver, so that we
  aren't conflicting with ResetInternalState from Endpoint (which was a
  problem because TunEndpoint inherited from both; it could be resolved
  through the different argument type if we removed the default, but
  that seems gross).
- Make Resolver use a bare unbound context pointer rather than a
  shared_ptr; since Resolver (now) entirely manages it already we don't
  need an extra management layer, and it saves a bunch of `.get()`s.
pull/1969/head
Jason Rhinelander 2 years ago
parent 2ccc518849
commit ec91a6db05
No known key found for this signature in database
GPG Key ID: C4992CE7A88D4262

@ -31,10 +31,10 @@ namespace llarp::apple
} }
if (enable) if (enable)
saved_upstream_dns = tun->ReconfigureDNS({SockAddr{127, 0, 0, 1, {dns_trampoline_port}}});
tun->ReconfigureDNS({SockAddr{127, 0, 0, 1, huint16_t{dns_trampoline_port}}});
else else
tun->ReconfigureDNS(std::move(saved_upstream_dns)); tun->ReconfigureDNS(router->GetConfig()->dns.m_upstreamDNS);
trampoline_active = enable; trampoline_active = enable;
} }

@ -48,7 +48,6 @@ namespace llarp::apple
private: private:
llarp::Context& context; llarp::Context& context;
bool trampoline_active = false; bool trampoline_active = false;
std::vector<llarp::SockAddr> saved_upstream_dns;
void void
check_trampoline(bool enable); check_trampoline(bool enable);

@ -113,9 +113,9 @@ namespace llarp::dns
}; };
/// Resolver_Base that uses libunbound /// Resolver_Base that uses libunbound
class Resolver : public Resolver_Base, public std::enable_shared_from_this<Resolver> class Resolver final : public Resolver_Base, public std::enable_shared_from_this<Resolver>
{ {
std::shared_ptr<ub_ctx> m_ctx; ub_ctx* m_ctx = nullptr;
std::weak_ptr<EventLoop> m_Loop; std::weak_ptr<EventLoop> m_Loop;
#ifdef _WIN32 #ifdef _WIN32
// windows is dumb so we do ub mainloop in a thread // windows is dumb so we do ub mainloop in a thread
@ -179,7 +179,7 @@ namespace llarp::dns
if (const auto port = dns.getPort(); port != 53) if (const auto port = dns.getPort(); port != 53)
fmt::format_to(std::back_inserter(str), "@{}", port); fmt::format_to(std::back_inserter(str), "@{}", port);
if (auto err = ub_ctx_set_fwd(m_ctx.get(), str.c_str())) if (auto err = ub_ctx_set_fwd(m_ctx, str.c_str()))
{ {
throw std::runtime_error{ throw std::runtime_error{
fmt::format("cannot use {} as upstream dns: {}", str, ub_strerror(err))}; fmt::format("cannot use {} as upstream dns: {}", str, ub_strerror(err))};
@ -300,7 +300,7 @@ namespace llarp::dns
void void
SetOpt(const std::string& key, const std::string& val) SetOpt(const std::string& key, const std::string& val)
{ {
ub_ctx_set_option(m_ctx.get(), key.c_str(), val.c_str()); ub_ctx_set_option(m_ctx, key.c_str(), val.c_str());
} }
// Wrapper around the above that takes 3+ arguments: the 2nd arg gets formatted with the // Wrapper around the above that takes 3+ arguments: the 2nd arg gets formatted with the
@ -312,24 +312,21 @@ namespace llarp::dns
SetOpt(key, fmt::format(format, std::forward<FmtArgs>(args)...)); SetOpt(key, fmt::format(format, std::forward<FmtArgs>(args)...));
} }
// Copy of the DNS config (a copy because on some platforms, like Apple, we change the applied
// upstream DNS settings when turning on/off exit mode).
llarp::DnsConfig m_conf; llarp::DnsConfig m_conf;
public: public:
explicit Resolver(const EventLoop_ptr& loop, llarp::DnsConfig conf) explicit Resolver(const EventLoop_ptr& loop, llarp::DnsConfig conf)
: m_ctx{::ub_ctx_create(), ::ub_ctx_delete}, m_Loop{loop}, m_conf{std::move(conf)} : m_Loop{loop}, m_conf{std::move(conf)}
{ {
Up(m_conf); Up(m_conf);
} }
#ifdef _WIN32 ~Resolver() override
virtual ~Resolver()
{ {
running = false; Down();
runner.join();
} }
#else
virtual ~Resolver() = default;
#endif
std::string_view std::string_view
ResolverName() const override ResolverName() const override
@ -346,6 +343,10 @@ namespace llarp::dns
void void
Up(const llarp::DnsConfig& conf) Up(const llarp::DnsConfig& conf)
{ {
if (m_ctx)
throw std::logic_error{"Internal error: attempt to Up() dns server multiple times"};
m_ctx = ::ub_ctx_create();
// set libunbound settings // set libunbound settings
SetOpt("do-tcp:", "no"); SetOpt("do-tcp:", "no");
@ -357,7 +358,7 @@ namespace llarp::dns
for (const auto& file : conf.m_hostfiles) for (const auto& file : conf.m_hostfiles)
{ {
const auto str = file.u8string(); const auto str = file.u8string();
if (auto ret = ub_ctx_hosts(m_ctx.get(), str.c_str())) if (auto ret = ub_ctx_hosts(m_ctx, str.c_str()))
{ {
throw std::runtime_error{ throw std::runtime_error{
fmt::format("Failed to add host file {}: {}", file, ub_strerror(ret))}; fmt::format("Failed to add host file {}: {}", file, ub_strerror(ret))};
@ -367,15 +368,14 @@ namespace llarp::dns
ConfigureUpstream(conf); ConfigureUpstream(conf);
// set async // set async
ub_ctx_async(m_ctx.get(), 1); ub_ctx_async(m_ctx, 1);
// setup mainloop // setup mainloop
#ifdef _WIN32 #ifdef _WIN32
running = true; running = true;
runner = std::thread{[this, ctx = std::weak_ptr{m_ctx}]() { runner = std::thread{[this]() {
while (running) while (running)
{ {
if (auto c = ctx.lock()) ub_wait(ctx);
ub_wait(c.get());
std::this_thread::sleep_for(10ms); std::this_thread::sleep_for(10ms);
} }
if (auto c = ctx.lock()) if (auto c = ctx.lock())
@ -386,10 +386,9 @@ namespace llarp::dns
{ {
if (auto loop_ptr = loop->MaybeGetUVWLoop()) if (auto loop_ptr = loop->MaybeGetUVWLoop())
{ {
m_Poller = loop_ptr->resource<uvw::PollHandle>(ub_fd(m_ctx.get())); m_Poller = loop_ptr->resource<uvw::PollHandle>(ub_fd(m_ctx));
m_Poller->on<uvw::PollEvent>([ptr = std::weak_ptr{m_ctx}](auto&, auto&) { m_Poller->on<uvw::PollEvent>([this](auto&, auto&) {
if (auto ctx = ptr.lock()) ub_process(m_ctx);
ub_process(ctx.get());
}); });
m_Poller->start(uvw::PollHandle::Event::READABLE); m_Poller->start(uvw::PollHandle::Event::READABLE);
return; return;
@ -400,15 +399,19 @@ namespace llarp::dns
} }
void void
Down() Down() override
{ {
#ifdef _WIN32 #ifdef _WIN32
running = false; if (running.exchange(false))
runner.join(); runner.join();
#else #else
m_Poller->close(); if (m_Poller)
m_Poller->close();
#endif #endif
m_ctx.reset(); if (m_ctx) {
::ub_ctx_delete(m_ctx);
m_ctx = nullptr;
}
} }
int int
@ -418,20 +421,14 @@ namespace llarp::dns
} }
void void
ResetInternalState(std::optional<std::vector<SockAddr>> replace_upstream) override ResetResolver(std::optional<std::vector<SockAddr>> replace_upstream) override
{ {
Down(); Down();
if (replace_upstream) if (replace_upstream)
m_conf.m_upstreamDNS = *replace_upstream; m_conf.m_upstreamDNS = std::move(*replace_upstream);
Up(m_conf); Up(m_conf);
} }
void
CancelPendingQueries() override
{
Down();
}
bool bool
WouldLoop(const SockAddr& to, const SockAddr& from) const override WouldLoop(const SockAddr& to, const SockAddr& from) const override
{ {
@ -485,7 +482,7 @@ namespace llarp::dns
} }
const auto& q = query.questions[0]; const auto& q = query.questions[0];
if (auto err = ub_resolve_async( if (auto err = ub_resolve_async(
m_ctx.get(), m_ctx,
q.Name().c_str(), q.Name().c_str(),
q.qtype, q.qtype,
q.qclass, q.qclass,
@ -642,7 +639,7 @@ namespace llarp::dns
for (const auto& resolver : m_Resolvers) for (const auto& resolver : m_Resolvers)
{ {
if (auto ptr = resolver.lock()) if (auto ptr = resolver.lock())
ptr->CancelPendingQueries(); ptr->Down();
} }
} }
@ -652,7 +649,7 @@ namespace llarp::dns
for (const auto& resolver : m_Resolvers) for (const auto& resolver : m_Resolvers)
{ {
if (auto ptr = resolver.lock()) if (auto ptr = resolver.lock())
ptr->ResetInternalState(); ptr->ResetResolver();
} }
} }

@ -174,16 +174,17 @@ namespace llarp::dns
virtual std::string_view virtual std::string_view
ResolverName() const = 0; ResolverName() const = 0;
/// reset state, replace upstream info with new info if desired /// reset the resolver state, optionally replace upstream info with new info. The default base
/// implementation does nothing.
virtual void virtual void
ResetInternalState(std::optional<std::vector<SockAddr>> replace_upstream = std::nullopt) ResetResolver([[maybe_unused]] std::optional<std::vector<SockAddr>> replace_upstream = std::nullopt)
{ {
(void)replace_upstream; }
};
/// cancel all pending requests and ceace further operation /// cancel all pending requests and cease further operation. Default operation is a no-op.
virtual void virtual void
CancelPendingQueries(){}; Down(){}
/// attempt to handle a dns message /// attempt to handle a dns message
/// returns true if we consumed this query and it should not be processed again /// returns true if we consumed this query and it should not be processed again
virtual bool virtual bool
@ -201,7 +202,7 @@ namespace llarp::dns
(void)to; (void)to;
(void)from; (void)from;
return false; return false;
}; }
}; };
// Base class for DNS proxy // Base class for DNS proxy

@ -24,9 +24,6 @@ namespace llarp
return "snode"; return "snode";
} }
void
CancelPendingQueries() override{};
bool bool
MaybeHookDNS( MaybeHookDNS(
std::shared_ptr<dns::PacketSource_Base> source, std::shared_ptr<dns::PacketSource_Base> source,

@ -260,7 +260,7 @@ namespace llarp
m_DNS->Reset(); m_DNS->Reset();
} }
std::vector<SockAddr> void
TunEndpoint::ReconfigureDNS(std::vector<SockAddr> servers) TunEndpoint::ReconfigureDNS(std::vector<SockAddr> servers)
{ {
if (m_DNS) if (m_DNS)
@ -268,10 +268,9 @@ namespace llarp
for (auto weak : m_DNS->GetAllResolvers()) for (auto weak : m_DNS->GetAllResolvers())
{ {
if (auto ptr = weak.lock()) if (auto ptr = weak.lock())
ptr->ResetInternalState(servers); ptr->ResetResolver(servers);
} }
} }
return servers;
} }
bool bool
@ -903,7 +902,7 @@ namespace llarp
return true; return true;
} }
void TunEndpoint::ResetInternalState(std::optional<std::vector<SockAddr>>) void TunEndpoint::ResetInternalState()
{ {
service::Endpoint::ResetInternalState(); service::Endpoint::ResetInternalState();
} }

@ -67,9 +67,8 @@ namespace llarp
void void
Thaw() override; Thaw() override;
// Reconfigures DNS servers and restarts libunbound with the new servers. Returns the old set // Reconfigures DNS servers and restarts libunbound with the new servers.
// of configured dns servers. void
std::vector<SockAddr>
ReconfigureDNS(std::vector<SockAddr> servers); ReconfigureDNS(std::vector<SockAddr> servers);
bool bool
@ -202,8 +201,7 @@ namespace llarp
ObtainIPForAddr(std::variant<service::Address, RouterID> addr) override; ObtainIPForAddr(std::variant<service::Address, RouterID> addr) override;
void void
ResetInternalState( ResetInternalState() override;
std::optional<std::vector<SockAddr>> replace_upstream = std::nullopt) override;
protected: protected:
struct WritePacket struct WritePacket

Loading…
Cancel
Save