QDnsLookup/Unix: handle more error conditions from res_nsend()

It does set ECONNREFUSED explicitly. So let's reuse ServerRefusedError
for it too (it was so far only used when we got a REFUSED DNS answer),
which allows tst_QDnsLookup to handle this as an ignorable failure.

For almost everything else, it sets ETIMEDOUT to indicate "no answer",
which isn't useful. So let's inspect the reply to see if it has
something.

Change-Id: I455fe22ef4ad4b2f9b01fffd17c771ffa4a998be
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
(cherry picked from commit f19e9f2521ff7784223ec34fc6794583f4faa2a5)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Thiago Macieira 2024-04-18 11:05:26 -07:00 committed by Qt Cherry-pick Bot
parent 81d8bf1c54
commit ae302ef016

View File

@ -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();
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->makeResolverSystemError();
}
return responseLength;
reply->makeTimeoutError(); // must really be a timeout
return -1;
};
// strictly use UDP, we'll deal with truncated replies ourselves