diff options
author | Thiago Macieira <[email protected]> | 2023-05-12 09:42:00 -0700 |
---|---|---|
committer | Thiago Macieira <[email protected]> | 2023-05-26 06:46:32 -0700 |
commit | 5ecdce0c352d924962f8cd79f2c0bea7f078ddf1 (patch) | |
tree | 89bfb7462a58c5c0f8a01627cb5d39f68b2bb16d | |
parent | df07d982437c989997508e9e5e85ae1d5bf69b12 (diff) |
QDnsLookup/Unix large replies: manually handle VC [3/3]
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 <[email protected]>
-rw-r--r-- | src/network/kernel/qdnslookup_unix.cpp | 22 |
1 files 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<HEADER *>(buffer.data()); + if (header->rcode == NOERROR && header->tc) { + // yes, increase our buffer size + buffer.resize(std::numeric_limits<quint16>::max()); + header = reinterpret_cast<HEADER *>(buffer.data()); + + // remove the EDNS record in the query + reinterpret_cast<HEADER *>(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<HEADER *>(buffer.data()); if (header->rcode) return reply->makeDnsRcodeError(header->rcode); |