From 5ecdce0c352d924962f8cd79f2c0bea7f078ddf1 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 12 May 2023 09:42:00 -0700 Subject: [PATCH] QDnsLookup/Unix large replies: manually handle VC [3/3] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current code was inefficient when replies exceeded the initial buffer size because the res_nsend() function switched to VC to get the full reply, but that wouldn't fit our buffer before we enlarged it. This commit tells res_nsend() to only use UDP or only use TCP, avoiding the two unnecessary transactions in the lookup. Since we don't get that second TCP reply now that would tell us the size of the reply, we must allocate the largest possible buffer for a DNS reply. Change-Id: I3e3bfef633af4130a03afffd175e73d2e9fa9bf1 Reviewed-by: MÃ¥rten Nordheim --- src/network/kernel/qdnslookup_unix.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/network/kernel/qdnslookup_unix.cpp b/src/network/kernel/qdnslookup_unix.cpp index 01c90f873a9..6f082cfa7fc 100644 --- a/src/network/kernel/qdnslookup_unix.cpp +++ b/src/network/kernel/qdnslookup_unix.cpp @@ -179,10 +179,25 @@ void QDnsLookupRunnable::query(QDnsLookupReply *reply) return responseLength; }; + // strictly use UDP, we'll deal with truncated replies ourselves + state.options |= RES_IGNTC; int responseLength = attemptToSend(); - if (responseLength > buffer.size()) { - // increase our buffer size - buffer.resize(responseLength); + if (responseLength < 0) + return; + + // check if we need to use the virtual circuit (TCP) + auto header = reinterpret_cast
(buffer.data()); + if (header->rcode == NOERROR && header->tc) { + // yes, increase our buffer size + buffer.resize(std::numeric_limits::max()); + header = reinterpret_cast
(buffer.data()); + + // remove the EDNS record in the query + reinterpret_cast
(qbuffer.data())->arcount = 0; + queryLength -= sizeof(Edns0Record); + + // send using the virtual circuit + state.options |= RES_USEVC; responseLength = attemptToSend(); if (Q_UNLIKELY(responseLength > buffer.size())) { // Ok, we give up. @@ -198,7 +213,6 @@ void QDnsLookupRunnable::query(QDnsLookupReply *reply) return reply->makeInvalidReplyError(); // Parse the reply. - auto header = reinterpret_cast
(buffer.data()); if (header->rcode) return reply->makeDnsRcodeError(header->rcode);