summaryrefslogtreecommitdiffstats
path: root/src/network/kernel/qdnslookup_unix.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/kernel/qdnslookup_unix.cpp')
-rw-r--r--src/network/kernel/qdnslookup_unix.cpp24
1 files changed, 16 insertions, 8 deletions
diff --git a/src/network/kernel/qdnslookup_unix.cpp b/src/network/kernel/qdnslookup_unix.cpp
index 02172933485..5696a3ca701 100644
--- a/src/network/kernel/qdnslookup_unix.cpp
+++ b/src/network/kernel/qdnslookup_unix.cpp
@@ -183,14 +183,22 @@ void QDnsLookupRunnable::query(QDnsLookupReply *reply)
auto attemptToSend = [&]() {
std::memset(buffer.data(), 0, HFIXEDSZ); // the header is enough
int responseLength = res_nsend(&state, qbuffer.data(), queryLength, buffer.data(), buffer.size());
- if (responseLength < 0) {
- // network error of some sort
- if (errno == ETIMEDOUT)
- reply->makeTimeoutError();
- else
- reply->makeResolverSystemError();
- }
- return responseLength;
+ if (responseLength >= 0)
+ return responseLength; // success
+
+ // libresolv uses ETIMEDOUT for resolver errors ("no answer")
+ if (errno == ECONNREFUSED)
+ reply->setError(QDnsLookup::ServerRefusedError, qt_error_string());
+ else if (errno != ETIMEDOUT)
+ reply->makeResolverSystemError(); // some other error
+
+ auto query = reinterpret_cast<HEADER *>(qbuffer.data());
+ auto header = reinterpret_cast<HEADER *>(buffer.data());
+ if (query->id == header->id && header->qr)
+ reply->makeDnsRcodeError(header->rcode);
+ else
+ reply->makeTimeoutError(); // must really be a timeout
+ return -1;
};
// strictly use UDP, we'll deal with truncated replies ourselves