diff --git a/llarp/dns/server.cpp b/llarp/dns/server.cpp index 4a0d22da4..ef1c01c03 100644 --- a/llarp/dns/server.cpp +++ b/llarp/dns/server.cpp @@ -146,6 +146,7 @@ namespace llarp::dns static void Callback(void* data, int err, ub_result* _result) { + log::debug(logcat, "got dns response from libunbound"); // take ownership of ub_result std::unique_ptr result{_result}; // borrow query @@ -158,6 +159,8 @@ namespace llarp::dns return; } + log::trace(logcat, "queueing dns response from libunbound to userland"); + // rewrite response OwnedBuffer pkt{(const byte_t*)result->answer_packet, (size_t)result->answer_len}; llarp_buffer_t buf{pkt}; @@ -452,20 +455,6 @@ namespace llarp::dns Up(m_conf); } - bool - WouldLoop(const SockAddr& to, const SockAddr& from) const override - { -#if defined(ANDROID) - (void)to; - (void)from; - return false; -#else - const auto& vec = m_conf.m_upstreamDNS; - return std::find(vec.begin(), vec.end(), to) != std::end(vec) - or std::find(vec.begin(), vec.end(), from) != std::end(vec); -#endif - } - template void call(Callable&& f) @@ -483,13 +472,15 @@ namespace llarp::dns const SockAddr& to, const SockAddr& from) override { - if (WouldLoop(to, from)) - return false; - auto tmp = std::make_shared(weak_from_this(), query, source, to, from); // no questions, send fail if (query.questions.empty()) { + log::info( + logcat, + "dns from {} to {} has empty query questions, sending failure reply", + from, + to); tmp->Cancel(); return true; } @@ -499,6 +490,12 @@ namespace llarp::dns // dont process .loki or .snode if (q.HasTLD(".loki") or q.HasTLD(".snode")) { + log::warning( + logcat, + "dns from {} to {} is for .loki or .snode but got to the unbound resolver, sending " + "failure reply", + from, + to); tmp->Cancel(); return true; } @@ -506,6 +503,12 @@ namespace llarp::dns if (not m_ctx) { // we are down + log::debug( + logcat, + "dns from {} to {} got to the unbound resolver, but the resolver isn't set up, " + "sending failure reply", + from, + to); tmp->Cancel(); return true; } @@ -514,6 +517,12 @@ namespace llarp::dns if (not running) { // we are stopping the win32 thread + log::debug( + logcat, + "dns from {} to {} got to the unbound resolver, but the resolver isn't running, " + "sending failure reply", + from, + to); tmp->Cancel(); return true; } @@ -533,7 +542,10 @@ namespace llarp::dns tmp->Cancel(); } else + { + log::trace(logcat, "dns from {} to {} processing via libunbound", from, to); m_Pending.insert(std::move(tmp)); + } return true; } @@ -549,6 +561,12 @@ namespace llarp::dns { parent_ptr->call( [self = shared_from_this(), parent_ptr = std::move(parent_ptr), buf = replyBuf.copy()] { + log::trace( + logcat, + "forwarding dns response from libunbound to userland (resolverAddr: {}, " + "askerAddr: {})", + self->resolverAddr, + self->askerAddr); self->src->SendTo(self->askerAddr, self->resolverAddr, OwnedBuffer::copy_from(buf)); // remove query parent_ptr->RemovePending(self); @@ -742,10 +760,14 @@ namespace llarp::dns { if (auto res_ptr = resolver.lock()) { - log::debug( + log::trace( logcat, "check resolver {} for dns from {} to {}", res_ptr->ResolverName(), from, to); if (res_ptr->MaybeHookDNS(ptr, msg, to, from)) + { + log::trace( + logcat, "resolver {} handling dns from {} to {}", res_ptr->ResolverName(), from, to); return true; + } } } return false; diff --git a/llarp/dns/server.hpp b/llarp/dns/server.hpp index 7f22df48e..6b1ba54b3 100644 --- a/llarp/dns/server.hpp +++ b/llarp/dns/server.hpp @@ -197,16 +197,6 @@ namespace llarp::dns const Message& query, const SockAddr& to, const SockAddr& from) = 0; - - /// Returns true if a packet with to and from addresses is something that would cause a - /// resolution loop and thus should not be used on this resolver - virtual bool - WouldLoop(const SockAddr& to, const SockAddr& from) const - { - (void)to; - (void)from; - return false; - } }; // Base class for DNS proxy diff --git a/llarp/win32/windivert.cpp b/llarp/win32/windivert.cpp index 344718db1..48f5c27b5 100644 --- a/llarp/win32/windivert.cpp +++ b/llarp/win32/windivert.cpp @@ -12,6 +12,94 @@ extern "C" #include } +namespace +{ + using namespace oxen::log::literals; + + std::string + windivert_addr_to_string(const WINDIVERT_ADDRESS& addr) + { + std::string layer_str{}; + std::string ifidx_str{}; + switch (addr.Layer) + { + case WINDIVERT_LAYER_NETWORK: + layer_str = "WINDIVERT_LAYER_NETWORK"; + ifidx_str = + "Network: [IfIdx: {}, SubIfIdx: {}]"_format(addr.Network.IfIdx, addr.Network.SubIfIdx); + break; + case WINDIVERT_LAYER_NETWORK_FORWARD: + layer_str = "WINDIVERT_LAYER_NETWORK_FORWARD"; + break; + case WINDIVERT_LAYER_FLOW: + layer_str = "WINDIVERT_LAYER_FLOW"; + break; + case WINDIVERT_LAYER_SOCKET: + layer_str = "WINDIVERT_LAYER_SOCKET"; + break; + case WINDIVERT_LAYER_REFLECT: + layer_str = "WINDIVERT_LAYER_REFLECT"; + break; + default: + layer_str = "unknown"; + } + + std::string event_str{}; + switch (addr.Event) + { + case WINDIVERT_EVENT_NETWORK_PACKET: + event_str = "WINDIVERT_EVENT_NETWORK_PACKET"; + break; + case WINDIVERT_EVENT_FLOW_ESTABLISHED: + event_str = "WINDIVERT_EVENT_FLOW_ESTABLISHED"; + break; + case WINDIVERT_EVENT_FLOW_DELETED: + event_str = "WINDIVERT_EVENT_FLOW_DELETED"; + break; + case WINDIVERT_EVENT_SOCKET_BIND: + event_str = "WINDIVERT_EVENT_SOCKET_BIND"; + break; + case WINDIVERT_EVENT_SOCKET_CONNECT: + event_str = "WINDIVERT_EVENT_SOCKET_CONNECT"; + break; + case WINDIVERT_EVENT_SOCKET_LISTEN: + event_str = "WINDIVERT_EVENT_SOCKET_LISTEN"; + break; + case WINDIVERT_EVENT_SOCKET_ACCEPT: + event_str = "WINDIVERT_EVENT_SOCKET_ACCEPT"; + break; + case WINDIVERT_EVENT_SOCKET_CLOSE: + event_str = "WINDIVERT_EVENT_SOCKET_CLOSE"; + break; + case WINDIVERT_EVENT_REFLECT_OPEN: + event_str = "WINDIVERT_EVENT_REFLECT_OPEN"; + break; + case WINDIVERT_EVENT_REFLECT_CLOSE: + event_str = "WINDIVERT_EVENT_REFLECT_CLOSE"; + break; + default: + event_str = "unknown"; + } + + return fmt::format( + "Windivert WINDIVERT_ADDRESS -- Timestamp: {}, Layer: {}, Event: {}, Sniffed: {}, " + "Outbound: {}, Loopback: {}, Imposter: {}, IPv6: {}, IPChecksum: {}, TCPChecksum: {}, " + "UDPChecksum: {}, {}", + addr.Timestamp, + layer_str, + event_str, + addr.Sniffed ? "true" : "false", + addr.Outbound ? "true" : "false", + addr.Loopback ? "true" : "false", + addr.Impostor ? "true" : "false", + addr.IPv6 ? "true" : "false", + addr.IPChecksum ? "true" : "false", + addr.TCPChecksum ? "true" : "false", + addr.UDPChecksum ? "true" : "false", + ifidx_str); + } +} // namespace + namespace llarp::win32 { static auto logcat = log::Cat("windivert"); @@ -23,6 +111,7 @@ namespace llarp::win32 decltype(::WinDivertOpen)* open = nullptr; decltype(::WinDivertClose)* close = nullptr; decltype(::WinDivertShutdown)* shutdown = nullptr; + decltype(::WinDivertHelperCalcChecksums)* calc_checksum = nullptr; decltype(::WinDivertSend)* send = nullptr; decltype(::WinDivertRecv)* recv = nullptr; decltype(::WinDivertHelperFormatIPv4Address)* format_ip4 = nullptr; @@ -41,6 +130,7 @@ namespace llarp::win32 "WinDivertOpen", open, "WinDivertClose", close, "WinDivertShutdown", shutdown, + "WinDivertHelperCalcChecksums", calc_checksum, "WinDivertSend", send, "WinDivertRecv", recv, "WinDivertHelperFormatIPv4Address", format_ip4, @@ -106,18 +196,28 @@ namespace llarp::win32 throw win32::error{ err, fmt::format("failed to receive packet from windivert (code={})", err)}; } - log::trace(logcat, "got packet of size {}B", sz); pkt.resize(sz); + + log::trace(logcat, "got packet of size {}B", sz); + log::trace(logcat, "{}", windivert_addr_to_string(addr)); return Packet{std::move(pkt), std::move(addr)}; } void - send_packet(const Packet& w_pkt) const + send_packet(Packet w_pkt) const { - const auto& pkt = w_pkt.pkt; - const auto* addr = &w_pkt.addr; + auto& pkt = w_pkt.pkt; + auto* addr = &w_pkt.addr; + + addr->Outbound = !addr->Outbound; // re-used from recv, so invert direction + log::trace(logcat, "send dns packet of size {}B", pkt.size()); + log::trace(logcat, "{}", windivert_addr_to_string(w_pkt.addr)); + UINT sz{}; + // recalc IP packet checksum in case it needs it + wd::calc_checksum(pkt.data(), pkt.size(), addr, 0); + if (!wd::send(m_Handle, pkt.data(), pkt.size(), &sz, addr)) throw win32::error{"windivert send failed"}; }