summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <[email protected]>2023-05-12 09:42:00 -0700
committerThiago Macieira <[email protected]>2023-05-26 06:46:32 -0700
commit5ecdce0c352d924962f8cd79f2c0bea7f078ddf1 (patch)
tree89bfb7462a58c5c0f8a01627cb5d39f68b2bb16d
parentdf07d982437c989997508e9e5e85ae1d5bf69b12 (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.cpp22
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);