From e11efe9bc5413d9ec4202579926fa54044843c96 Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Wed, 1 Sep 2021 15:31:45 -0300 Subject: [PATCH] Reformat --- llarp/apple/DNSTrampoline.h | 19 +++-- llarp/apple/context.hpp | 3 +- llarp/apple/context_wrapper.cpp | 32 ++++--- llarp/apple/context_wrapper.h | 144 ++++++++++++++++---------------- llarp/apple/route_manager.cpp | 142 +++++++++++++++++-------------- llarp/apple/route_manager.hpp | 41 +++++---- llarp/apple/vpn_platform.hpp | 6 +- llarp/dns/server.cpp | 4 +- llarp/dns/server.hpp | 3 +- llarp/dns/unbound_resolver.cpp | 21 ++--- llarp/handlers/tun.cpp | 17 ++-- 11 files changed, 230 insertions(+), 202 deletions(-) diff --git a/llarp/apple/DNSTrampoline.h b/llarp/apple/DNSTrampoline.h index 9e3446d76..4935d43c8 100644 --- a/llarp/apple/DNSTrampoline.h +++ b/llarp/apple/DNSTrampoline.h @@ -25,19 +25,23 @@ extern NSString* error_domain; uv_udp_t request_socket; // The reply address. This is a bit hacky: we configure libunbound to just use single address // (rather than a range) so that we don't have to worry about tracking different reply addresses. - @public struct sockaddr reply_addr; + @public + struct sockaddr reply_addr; // UDP "session" aimed at the upstream DNS - @public NWUDPSession* upstream; + @public + NWUDPSession* upstream; // Apple docs say writes could take time *and* the crappy Apple datagram write methods aren't // callable again until the previous write finishes. Deal with this garbage API by queuing // everything than using a uv_async to process the queue. - @public int write_ready; - @public NSMutableArray* pending_writes; + @public + int write_ready; + @public + NSMutableArray* pending_writes; uv_async_t write_trigger; } -- (void)startWithUpstreamDns:(NWUDPSession*) dns - listenPort:(uint16_t) listenPort - uvLoop:(uv_loop_t*) loop +- (void)startWithUpstreamDns:(NWUDPSession*)dns + listenPort:(uint16_t)listenPort + uvLoop:(uv_loop_t*)loop completionHandler:(void (^)(NSError* error))completionHandler; - (void)flushWrites; @@ -45,4 +49,3 @@ extern NSString* error_domain; - (void)dealloc; @end - diff --git a/llarp/apple/context.hpp b/llarp/apple/context.hpp index a3b92ad75..4fc808874 100644 --- a/llarp/apple/context.hpp +++ b/llarp/apple/context.hpp @@ -11,7 +11,8 @@ namespace llarp::apple std::shared_ptr makeVPNPlatform() override { - return std::make_shared(*this, m_PacketWriter, m_OnReadable, route_callbacks, callback_context); + return std::make_shared( + *this, m_PacketWriter, m_OnReadable, route_callbacks, callback_context); } // Callbacks that must be set for packet handling *before* calling Setup/Configure/Run; the main diff --git a/llarp/apple/context_wrapper.cpp b/llarp/apple/context_wrapper.cpp index 6d6cbd0c8..ce9354540 100644 --- a/llarp/apple/context_wrapper.cpp +++ b/llarp/apple/context_wrapper.cpp @@ -34,7 +34,8 @@ const uint16_t dns_trampoline_port = 1053; void* llarp_apple_init(llarp_apple_config* appleconf) { - llarp::LogContext::Instance().logStream = std::make_unique(appleconf->ns_logger); + llarp::LogContext::Instance().logStream = + std::make_unique(appleconf->ns_logger); try { @@ -42,7 +43,7 @@ llarp_apple_init(llarp_apple_config* appleconf) auto config = std::make_shared(config_dir); fs::path config_path = config_dir / "lokinet.ini"; if (!fs::exists(config_path)) - llarp::ensureConfig(config_dir, config_path, /*overwrite=*/ false, /*router=*/ false); + llarp::ensureConfig(config_dir, config_path, /*overwrite=*/false, /*router=*/false); config->Load(config_path); // If no range is specified then go look for a free one, set that in the config, and then return @@ -63,8 +64,10 @@ llarp_apple_init(llarp_apple_config* appleconf) std::strcpy(appleconf->tunnel_ipv4_netmask, mask.c_str()); appleconf->upstream_dns[0] = '\0'; - for (auto& upstream : config->dns.m_upstreamDNS) { - if (upstream.isIPv4()) { + for (auto& upstream : config->dns.m_upstreamDNS) + { + if (upstream.isIPv4()) + { std::strcpy(appleconf->upstream_dns, upstream.hostString().c_str()); appleconf->upstream_dns_port = upstream.getPort(); break; @@ -87,7 +90,6 @@ llarp_apple_init(llarp_apple_config* appleconf) inst->packet_writer = appleconf->packet_writer; inst->start_reading = appleconf->start_reading; - return inst.release(); } catch (const std::exception& e) @@ -98,25 +100,21 @@ llarp_apple_init(llarp_apple_config* appleconf) } int -llarp_apple_start( - void* lokinet, - void* callback_context) +llarp_apple_start(void* lokinet, void* callback_context) { auto* inst = static_cast(lokinet); inst->context.callback_context = callback_context; - inst->context.m_PacketWriter = [inst, callback_context]( - int af_family, void* data, size_t size) { - inst->packet_writer(af_family, data, size, callback_context); - return true; + inst->context.m_PacketWriter = [inst, callback_context](int af_family, void* data, size_t size) { + inst->packet_writer(af_family, data, size, callback_context); + return true; }; - inst->context.m_OnReadable = - [inst, callback_context](llarp::apple::VPNInterface& iface) { - inst->iface = iface.weak_from_this(); - inst->start_reading(callback_context); - }; + inst->context.m_OnReadable = [inst, callback_context](llarp::apple::VPNInterface& iface) { + inst->iface = iface.weak_from_this(); + inst->start_reading(callback_context); + }; std::promise result; inst->runner = std::thread{[inst, &result] { diff --git a/llarp/apple/context_wrapper.h b/llarp/apple/context_wrapper.h index 74ac38eed..914446741 100644 --- a/llarp/apple/context_wrapper.h +++ b/llarp/apple/context_wrapper.h @@ -17,91 +17,91 @@ extern "C" extern const uint16_t dns_trampoline_port; /// C callback function for us to invoke when we need to write a packet - typedef void(*packet_writer_callback)(int af, const void* data, size_t size, void* ctx); + typedef void (*packet_writer_callback)(int af, const void* data, size_t size, void* ctx); /// C callback function to invoke once we are ready to start receiving packets - typedef void(*start_reading_callback)(void* ctx); + typedef void (*start_reading_callback)(void* ctx); /// C callback that bridges things into NSLog - typedef void(*ns_logger_callback)(const char* msg); + typedef void (*ns_logger_callback)(const char* msg); /// C callbacks to add/remove specific and default routes to the tunnel - typedef void(*llarp_route_ipv4_callback)(const char* addr, const char* netmask, void* ctx); - typedef void(*llarp_route_ipv6_callback)(const char* addr, int prefix, void* ctx); - typedef void(*llarp_default_route_callback)(void* ctx); - typedef struct llarp_route_callbacks { - /// Callback invoked to set up an IPv4 range that should be routed through the tunnel - /// interface. Called with the address and netmask. - llarp_route_ipv4_callback add_ipv4_route; - - /// Callback invoked to set the tunnel as the default IPv4 route. - llarp_default_route_callback add_ipv4_default_route; - - /// Callback invoked to remove a specific range from the tunnel IPv4 routes. Called with the - /// address and netmask. - llarp_route_ipv4_callback del_ipv4_route; - - /// Callback invoked to set up an IPv6 range that should be routed through the tunnel - /// interface. Called with the address and netmask. - llarp_route_ipv6_callback add_ipv6_route; - - /// Callback invoked to remove a specific range from the tunnel IPv6 routes. Called with the - /// address and netmask. - llarp_route_ipv6_callback del_ipv6_route; - - /// Callback invoked to set the tunnel as the default IPv4/IPv6 route. - llarp_default_route_callback add_default_route; - - /// Callback invoked to remove the tunnel as the default IPv4/IPv6 route. - llarp_default_route_callback del_default_route; + typedef void (*llarp_route_ipv4_callback)(const char* addr, const char* netmask, void* ctx); + typedef void (*llarp_route_ipv6_callback)(const char* addr, int prefix, void* ctx); + typedef void (*llarp_default_route_callback)(void* ctx); + typedef struct llarp_route_callbacks + { + /// Callback invoked to set up an IPv4 range that should be routed through the tunnel + /// interface. Called with the address and netmask. + llarp_route_ipv4_callback add_ipv4_route; + + /// Callback invoked to set the tunnel as the default IPv4 route. + llarp_default_route_callback add_ipv4_default_route; + + /// Callback invoked to remove a specific range from the tunnel IPv4 routes. Called with the + /// address and netmask. + llarp_route_ipv4_callback del_ipv4_route; + + /// Callback invoked to set up an IPv6 range that should be routed through the tunnel + /// interface. Called with the address and netmask. + llarp_route_ipv6_callback add_ipv6_route; + + /// Callback invoked to remove a specific range from the tunnel IPv6 routes. Called with the + /// address and netmask. + llarp_route_ipv6_callback del_ipv6_route; + + /// Callback invoked to set the tunnel as the default IPv4/IPv6 route. + llarp_default_route_callback add_default_route; + + /// Callback invoked to remove the tunnel as the default IPv4/IPv6 route. + llarp_default_route_callback del_default_route; } llarp_route_callbacks; /// Pack of crap to be passed into llarp_apple_init to initialize typedef struct llarp_apple_config { - /// lokinet configuration directory, expected to be the application-specific "home" directory, - /// which is where state files are stored and the lokinet.ini will be loaded (or created if it - /// doesn't exist). - const char* config_dir; - /// path to the default bootstrap.signed file included in installation, which will be used by - /// default when no specific bootstrap is in the config file. - const char* default_bootstrap; - /// llarp_apple_init writes the IP address for the primary tunnel IP address here, - /// null-terminated. - char tunnel_ipv4_ip[16]; - /// llarp_apple_init writes the netmask of the tunnel address here, null-terminated. - char tunnel_ipv4_netmask[16]; - /// The first upstream DNS server's IPv4 address the OS should use when in exit mode. - /// (Currently on mac in exit mode we only support querying the first such configured server). - char upstream_dns[16]; - uint16_t upstream_dns_port; - - /// \defgroup callbacks Callbacks - /// Callbacks we invoke for various operations that require glue into the Apple network - /// extension APIs. All of these except for ns_logger are passed the pointer provided to - /// llarp_apple_start when invoked. - /// @{ - - /// simple wrapper around NSLog for lokinet message logging - ns_logger_callback ns_logger; - - /// C function callback that will be called when we need to write a packet to the packet - /// tunnel. Will be passed AF_INET or AF_INET6, a void pointer to the data, and the size of - /// the data in bytes. - packet_writer_callback packet_writer; - - /// C function callback that will be called when lokinet is setup and ready to start receiving - /// packets from the packet tunnel. This should set up the read handler to deliver packets - /// via llarp_apple_incoming. - start_reading_callback start_reading; - - /// Callbacks invoked to add/remove routes to the tunnel. - llarp_route_callbacks route_callbacks; - - /// @} + /// lokinet configuration directory, expected to be the application-specific "home" directory, + /// which is where state files are stored and the lokinet.ini will be loaded (or created if it + /// doesn't exist). + const char* config_dir; + /// path to the default bootstrap.signed file included in installation, which will be used by + /// default when no specific bootstrap is in the config file. + const char* default_bootstrap; + /// llarp_apple_init writes the IP address for the primary tunnel IP address here, + /// null-terminated. + char tunnel_ipv4_ip[16]; + /// llarp_apple_init writes the netmask of the tunnel address here, null-terminated. + char tunnel_ipv4_netmask[16]; + /// The first upstream DNS server's IPv4 address the OS should use when in exit mode. + /// (Currently on mac in exit mode we only support querying the first such configured server). + char upstream_dns[16]; + uint16_t upstream_dns_port; + + /// \defgroup callbacks Callbacks + /// Callbacks we invoke for various operations that require glue into the Apple network + /// extension APIs. All of these except for ns_logger are passed the pointer provided to + /// llarp_apple_start when invoked. + /// @{ + + /// simple wrapper around NSLog for lokinet message logging + ns_logger_callback ns_logger; + + /// C function callback that will be called when we need to write a packet to the packet + /// tunnel. Will be passed AF_INET or AF_INET6, a void pointer to the data, and the size of + /// the data in bytes. + packet_writer_callback packet_writer; + + /// C function callback that will be called when lokinet is setup and ready to start receiving + /// packets from the packet tunnel. This should set up the read handler to deliver packets + /// via llarp_apple_incoming. + start_reading_callback start_reading; + + /// Callbacks invoked to add/remove routes to the tunnel. + llarp_route_callbacks route_callbacks; + + /// @} } llarp_apple_config; - /// Initializes a lokinet instance by initializing various objects and loading the configuration /// (if /lokinet.ini exists). Does not actually start lokinet (call llarp_apple_start /// for that). diff --git a/llarp/apple/route_manager.cpp b/llarp/apple/route_manager.cpp index 87376f576..0bf170577 100644 --- a/llarp/apple/route_manager.cpp +++ b/llarp/apple/route_manager.cpp @@ -4,86 +4,98 @@ #include #include -namespace llarp::apple { - -void RouteManager::check_trampoline(bool enable) { - if (trampoline_active == enable) - return; - auto router = context.router; - if (!router) { - LogError("Cannot reconfigure to use DNS trampoline: no router"); - return; - } +namespace llarp::apple +{ + void + RouteManager::check_trampoline(bool enable) + { + if (trampoline_active == enable) + return; + auto router = context.router; + if (!router) + { + LogError("Cannot reconfigure to use DNS trampoline: no router"); + return; + } - std::shared_ptr tun; - router->hiddenServiceContext().ForEachService([&tun] (const auto& name, const auto ep) { + std::shared_ptr tun; + router->hiddenServiceContext().ForEachService([&tun](const auto& name, const auto ep) { tun = std::dynamic_pointer_cast(ep); return !tun; - }); + }); - if (!tun) { - LogError("Cannot reconfigure to use DNS trampoline: no tun endpoint found (!?)"); - return; - } - - if (enable) - saved_upstream_dns = tun->ReconfigureDNS({SockAddr{127, 0, 0, 1, huint16_t{dns_trampoline_port}}}); - else - tun->ReconfigureDNS(std::move(saved_upstream_dns)); - trampoline_active = enable; -} + if (!tun) + { + LogError("Cannot reconfigure to use DNS trampoline: no tun endpoint found (!?)"); + return; + } + if (enable) + saved_upstream_dns = + tun->ReconfigureDNS({SockAddr{127, 0, 0, 1, huint16_t{dns_trampoline_port}}}); + else + tun->ReconfigureDNS(std::move(saved_upstream_dns)); + trampoline_active = enable; + } -void RouteManager::AddDefaultRouteViaInterface(std::string) -{ - check_trampoline(true); + void RouteManager::AddDefaultRouteViaInterface(std::string) + { + check_trampoline(true); if (callback_context and route_callbacks.add_default_route) - route_callbacks.add_default_route(callback_context); -} + route_callbacks.add_default_route(callback_context); + } -void RouteManager::DelDefaultRouteViaInterface(std::string) -{ - check_trampoline(false); + void RouteManager::DelDefaultRouteViaInterface(std::string) + { + check_trampoline(false); if (callback_context and route_callbacks.del_default_route) - route_callbacks.del_default_route(callback_context); -} + route_callbacks.del_default_route(callback_context); + } -void -RouteManager::AddRouteViaInterface(vpn::NetworkInterface&, IPRange range) -{ - check_trampoline(true); + void + RouteManager::AddRouteViaInterface(vpn::NetworkInterface&, IPRange range) + { + check_trampoline(true); if (callback_context) { - if (range.IsV4()) { - if (route_callbacks.add_ipv4_route) - route_callbacks.add_ipv4_route( - range.BaseAddressString().c_str(), - net::TruncateV6(range.netmask_bits).ToString().c_str(), - callback_context); - } else { - if (route_callbacks.add_ipv6_route) - route_callbacks.add_ipv6_route(range.BaseAddressString().c_str(), range.HostmaskBits(), callback_context); - } + if (range.IsV4()) + { + if (route_callbacks.add_ipv4_route) + route_callbacks.add_ipv4_route( + range.BaseAddressString().c_str(), + net::TruncateV6(range.netmask_bits).ToString().c_str(), + callback_context); + } + else + { + if (route_callbacks.add_ipv6_route) + route_callbacks.add_ipv6_route( + range.BaseAddressString().c_str(), range.HostmaskBits(), callback_context); + } } -} + } -void -RouteManager::DelRouteViaInterface(vpn::NetworkInterface&, IPRange range) -{ - check_trampoline(false); + void + RouteManager::DelRouteViaInterface(vpn::NetworkInterface&, IPRange range) + { + check_trampoline(false); if (callback_context) { - if (range.IsV4()) { - if (route_callbacks.del_ipv4_route) - route_callbacks.del_ipv4_route( - range.BaseAddressString().c_str(), - net::TruncateV6(range.netmask_bits).ToString().c_str(), - callback_context); - } else { - if (route_callbacks.del_ipv6_route) - route_callbacks.del_ipv6_route(range.BaseAddressString().c_str(), range.HostmaskBits(), callback_context); - } + if (range.IsV4()) + { + if (route_callbacks.del_ipv4_route) + route_callbacks.del_ipv4_route( + range.BaseAddressString().c_str(), + net::TruncateV6(range.netmask_bits).ToString().c_str(), + callback_context); + } + else + { + if (route_callbacks.del_ipv6_route) + route_callbacks.del_ipv6_route( + range.BaseAddressString().c_str(), range.HostmaskBits(), callback_context); + } } -} + } -} +} // namespace llarp::apple diff --git a/llarp/apple/route_manager.hpp b/llarp/apple/route_manager.hpp index e012c3dc0..cb8bb3f1b 100644 --- a/llarp/apple/route_manager.hpp +++ b/llarp/apple/route_manager.hpp @@ -4,20 +4,24 @@ #include #include "context_wrapper.h" -namespace llarp::apple { - -class RouteManager final : public llarp::vpn::IRouteManager { -public: +namespace llarp::apple +{ + class RouteManager final : public llarp::vpn::IRouteManager + { + public: RouteManager(llarp::Context& ctx, llarp_route_callbacks rcs, void* callback_context) - : context{ctx}, route_callbacks{std::move(rcs)}, callback_context{callback_context} {} + : context{ctx}, route_callbacks{std::move(rcs)}, callback_context{callback_context} + {} /// These are called for poking route holes, but we don't have to do that at all on macos /// because the appex isn't subject to its own rules. void - AddRoute(IPVariant_t ip, IPVariant_t gateway) override {} + AddRoute(IPVariant_t ip, IPVariant_t gateway) override + {} void - DelRoute(IPVariant_t ip, IPVariant_t gateway) override {} + DelRoute(IPVariant_t ip, IPVariant_t gateway) override + {} void AddDefaultRouteViaInterface(std::string ifname) override; @@ -32,23 +36,24 @@ public: DelRouteViaInterface(vpn::NetworkInterface& vpn, IPRange range) override; virtual std::vector - GetGatewaysNotOnInterface(std::string ifname) override { - // We can't get this on mac from our sandbox, but we don't actually need it because we - // ignore the gateway for AddRoute/DelRoute anyway, so just return a zero IP. - std::vector ret; - ret.push_back(huint32_t{0}); - return ret; + GetGatewaysNotOnInterface(std::string ifname) override + { + // We can't get this on mac from our sandbox, but we don't actually need it because we + // ignore the gateway for AddRoute/DelRoute anyway, so just return a zero IP. + std::vector ret; + ret.push_back(huint32_t{0}); + return ret; } -private: - + private: llarp::Context& context; bool trampoline_active = false; std::vector saved_upstream_dns; - void check_trampoline(bool enable); + void + check_trampoline(bool enable); void* callback_context = nullptr; llarp_route_callbacks route_callbacks; -}; + }; -} +} // namespace llarp::apple diff --git a/llarp/apple/vpn_platform.hpp b/llarp/apple/vpn_platform.hpp index 974a79305..04ce75646 100644 --- a/llarp/apple/vpn_platform.hpp +++ b/llarp/apple/vpn_platform.hpp @@ -18,7 +18,11 @@ namespace llarp::apple std::shared_ptr ObtainInterface(vpn::InterfaceInfo) override; - vpn::IRouteManager& RouteManager() override { return m_RouteManager; } + vpn::IRouteManager& + RouteManager() override + { + return m_RouteManager; + } private: Context& m_Context; diff --git a/llarp/dns/server.cpp b/llarp/dns/server.cpp index e22a51db2..d2cac921b 100644 --- a/llarp/dns/server.cpp +++ b/llarp/dns/server.cpp @@ -103,7 +103,9 @@ namespace llarp::dns llarp::LogError("dns reply failed"); } - bool PacketHandler::IsUpstreamResolver(const SockAddr& to, const SockAddr& from) const { + bool + PacketHandler::IsUpstreamResolver(const SockAddr& to, const SockAddr& from) const + { return m_Resolvers.count(to); } diff --git a/llarp/dns/server.hpp b/llarp/dns/server.hpp index 2242ba450..025ec8ef6 100644 --- a/llarp/dns/server.hpp +++ b/llarp/dns/server.hpp @@ -58,7 +58,8 @@ namespace llarp // Returns true if this packet is something that looks like it's going to an upstream // resolver, i.e. matches a configured resolver. - virtual bool IsUpstreamResolver(const SockAddr& to, const SockAddr& from) const; + virtual bool + IsUpstreamResolver(const SockAddr& to, const SockAddr& from) const; private: void diff --git a/llarp/dns/unbound_resolver.cpp b/llarp/dns/unbound_resolver.cpp index 9df195095..d115c3f52 100644 --- a/llarp/dns/unbound_resolver.cpp +++ b/llarp/dns/unbound_resolver.cpp @@ -157,16 +157,17 @@ namespace llarp::dns // On Apple, we configure a localhost resolver to trampoline requests through the tunnel to the // actual upstream (because the network extension itself cannot route through the tunnel using // normal sockets but instead we "get" to use Apple's interfaces, hurray). - if (hoststr == "127.0.0.1") { - // 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:", hoststr.c_str()); - - // 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:", "1253"); + if (hoststr == "127.0.0.1") + { + // 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:", hoststr.c_str()); + + // 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:", "1253"); } #endif diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index f0a754cf4..61553acff 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -71,8 +71,9 @@ namespace llarp bool IsUpstreamResolver(const SockAddr& to, const SockAddr& from) const override { - LogError("IsUpstreamResolver? ", to.asIPv6(), " != ", m_Endpoint->GetIfAddr(), ", from=", from); - return to.asIPv6() != m_Endpoint->GetIfAddr(); + LogError( + "IsUpstreamResolver? ", to.asIPv6(), " != ", m_Endpoint->GetIfAddr(), ", from=", from); + return to.asIPv6() != m_Endpoint->GetIfAddr(); } #endif }; @@ -153,12 +154,12 @@ namespace llarp std::vector TunEndpoint::ReconfigureDNS(std::vector servers) { - std::swap(m_UpstreamResolvers, servers); - m_Resolver->Stop(); - if (!m_Resolver->Start( - m_LocalResolverAddr.createSockAddr(), m_UpstreamResolvers, m_hostfiles)) - llarp::LogError(Name(), " failed to reconfigure DNS server"); - return servers; + std::swap(m_UpstreamResolvers, servers); + m_Resolver->Stop(); + if (!m_Resolver->Start( + m_LocalResolverAddr.createSockAddr(), m_UpstreamResolvers, m_hostfiles)) + llarp::LogError(Name(), " failed to reconfigure DNS server"); + return servers; } bool