diff --git a/cmake/FindWrapResolv.cmake b/cmake/FindWrapResolv.cmake new file mode 100644 index 00000000000..9720c96c00b --- /dev/null +++ b/cmake/FindWrapResolv.cmake @@ -0,0 +1,49 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# Copyright (C) 2023 Intel Corpotation. +# SPDX-License-Identifier: BSD-3-Clause + +# We can't create the same interface imported target multiple times, CMake will complain if we do +# that. This can happen if the find_package call is done in multiple different subdirectories. +if(TARGET WrapResolv::WrapResolv) + set(WrapResolv_FOUND ON) + return() +endif() + +set(WrapResolv_FOUND OFF) + +include(CheckCXXSourceCompiles) +include(CMakePushCheckState) + +if(QNX) + find_library(LIBRESOLV socket) +else() + find_library(LIBRESOLV resolv) +endif() + +cmake_push_check_state() +if(LIBRESOLV) + list(APPEND CMAKE_REQUIRED_LIBRARIES "${LIBRESOLV}") +endif() + +check_cxx_source_compiles(" +#include +#include + +int main(int, char **) +{ + res_init(); +} +" HAVE_RES_INIT) + +cmake_pop_check_state() + +if(HAVE_RES_INIT) + set(WrapResolv_FOUND ON) + add_library(WrapResolv::WrapResolv INTERFACE IMPORTED) + if(LIBRESOLV) + target_link_libraries(WrapResolv::WrapResolv INTERFACE "${LIBRESOLV}") + endif() +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(WrapResolv DEFAULT_MSG WrapResolv_FOUND) diff --git a/src/network/CMakeLists.txt b/src/network/CMakeLists.txt index 827fc0648bd..ac0e45fb9e5 100644 --- a/src/network/CMakeLists.txt +++ b/src/network/CMakeLists.txt @@ -174,15 +174,6 @@ qt_internal_extend_target(Network CONDITION UNIX kernel/qhostinfo_unix.cpp socket/qnativesocketengine_unix.cpp socket/qnet_unix_p.h - NO_UNITY_BUILD_SOURCES - kernel/qhostinfo_unix.cpp # Temporary exclusion until, this, - # https://codereview.qt-project.org/c/qt/qtbase/+/463670 - # is merged. -) - -qt_internal_extend_target(Network CONDITION QT_FEATURE_dlopen AND UNIX - LIBRARIES - ${CMAKE_DL_LIBS} ) qt_internal_extend_target(Network CONDITION QT_FEATURE_linux_netlink AND UNIX @@ -195,11 +186,6 @@ qt_internal_extend_target(Network CONDITION UNIX AND NOT QT_FEATURE_linux_netlin kernel/qnetworkinterface_unix.cpp ) -qt_internal_extend_target(Network CONDITION ANDROID AND QT_FEATURE_dnslookup - SOURCES - kernel/qdnslookup_android.cpp -) - qt_internal_extend_target(Network CONDITION WIN32 SOURCES kernel/qhostinfo_win.cpp @@ -214,11 +200,6 @@ qt_internal_extend_target(Network CONDITION WIN32 winhttp ) -qt_internal_extend_target(Network CONDITION QT_FEATURE_dnslookup AND WIN32 - SOURCES - kernel/qdnslookup_win.cpp -) - qt_internal_extend_target(Network CONDITION APPLE AND NOT UIKIT LIBRARIES ${FWCoreServices} @@ -236,6 +217,22 @@ qt_internal_extend_target(Network CONDITION APPLE ${FWCFNetwork} ) +qt_internal_extend_target(Network CONDITION QT_FEATURE_dnslookup AND TEST_res_ninit + SOURCES + kernel/qdnslookup_unix.cpp + LIBRARIES + WrapResolv::WrapResolv +) + +qt_internal_extend_target(Network CONDITION QT_FEATURE_dnslookup AND WIN32 + SOURCES + kernel/qdnslookup_win.cpp +) + +qt_internal_extend_target(Network CONDITION QT_FEATURE_dnslookup AND NOT TEST_res_ninit AND NOT WIN32 + SOURCES + kernel/qdnslookup_dummy.cpp +) qt_internal_extend_target(Network CONDITION IOS OR MACOS SOURCES @@ -369,10 +366,6 @@ qt_internal_extend_target(Network CONDITION QT_FEATURE_ocsp AND QT_FEATURE_opens ssl/qocsp_p.h ) -qt_internal_extend_target(Network CONDITION QT_FEATURE_dnslookup AND UNIX AND NOT ANDROID - SOURCES - kernel/qdnslookup_unix.cpp -) qt_internal_add_docs(Network doc/qtnetwork.qdocconf ) diff --git a/src/network/configure.cmake b/src/network/configure.cmake index 32603dff954..0fd3a103b26 100644 --- a/src/network/configure.cmake +++ b/src/network/configure.cmake @@ -12,7 +12,7 @@ qt_find_package(Libproxy PROVIDED_TARGETS PkgConfig::Libproxy MODULE_NAME networ qt_find_package(GSSAPI PROVIDED_TARGETS GSSAPI::GSSAPI MODULE_NAME network QMAKE_LIB gssapi) qt_find_package(GLIB2 OPTIONAL_COMPONENTS GOBJECT PROVIDED_TARGETS GLIB2::GOBJECT MODULE_NAME core QMAKE_LIB gobject) qt_find_package(GLIB2 OPTIONAL_COMPONENTS GIO PROVIDED_TARGETS GLIB2::GIO MODULE_NAME core QMAKE_LIB gio) - +qt_find_package(WrapResolv PROVIDED_TARGETS WrapResolv::WrapResolv MODULE_NAME network QMAKE_LIB libresolv) #### Tests @@ -100,6 +100,25 @@ ci.ifa_prefered = ci.ifa_valid = 0; } ") +# res_ninit +qt_config_compile_test(res_ninit + LABEL "res_ninit()" + LIBRARIES + WrapResolv::WrapResolv + CODE +"#include +#include +#include +int main() +{ + res_state state; + res_ninit(state); + res_nclose(state); + return 0; +} +" +) + # sctp qt_config_compile_test(sctp LABEL "SCTP support" @@ -211,6 +230,11 @@ qt_feature("linux-netlink" PRIVATE LABEL "Linux AF_NETLINK" CONDITION LINUX AND NOT ANDROID AND TEST_linux_netlink ) +qt_feature("res_ninit" PRIVATE + LABEL "res_ninit()" + CONDITION TEST_res_ninit + AUTODETECT UNIX +) qt_feature("securetransport" PUBLIC LABEL "SecureTransport" CONDITION APPLE diff --git a/src/network/kernel/qdnslookup_android.cpp b/src/network/kernel/qdnslookup_dummy.cpp similarity index 90% rename from src/network/kernel/qdnslookup_android.cpp rename to src/network/kernel/qdnslookup_dummy.cpp index 8fc1265e800..d17cc66dce4 100644 --- a/src/network/kernel/qdnslookup_android.cpp +++ b/src/network/kernel/qdnslookup_dummy.cpp @@ -13,7 +13,7 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN Q_UNUSED(reply); qWarning("Not yet supported on Android"); reply->error = QDnsLookup::ResolverError; - reply->errorString = tr("Not yet supported on Android"); + reply->errorString = tr("Not yet supported on this OS"); return; } diff --git a/src/network/kernel/qdnslookup_unix.cpp b/src/network/kernel/qdnslookup_unix.cpp index 75f7c6c440e..05e0663aeff 100644 --- a/src/network/kernel/qdnslookup_unix.cpp +++ b/src/network/kernel/qdnslookup_unix.cpp @@ -3,130 +3,36 @@ #include "qdnslookup_p.h" -#if QT_CONFIG(library) -#include -#endif -#include #include #include -#include +#include +#include // for SetSALen +#include + +QT_REQUIRE_CONFIG(res_ninit); #include #include #include -#if !defined(Q_OS_OPENBSD) +#if __has_include() # include #endif #include -#if defined(__GNU_LIBRARY__) && !defined(__UCLIBC__) -# include -#endif - -#if defined(Q_OS_FREEBSD) || QT_CONFIG(dlopen) -# include -#endif - -#include - QT_BEGIN_NAMESPACE using namespace Qt::StringLiterals; -#if QT_CONFIG(library) - -#if defined(Q_OS_OPENBSD) -typedef struct __res_state* res_state; -#endif -typedef int (*dn_expand_proto)(const unsigned char *, const unsigned char *, const unsigned char *, char *, int); -static dn_expand_proto local_dn_expand = nullptr; -typedef void (*res_nclose_proto)(res_state); -static res_nclose_proto local_res_nclose = nullptr; -typedef int (*res_ninit_proto)(res_state); -static res_ninit_proto local_res_ninit = nullptr; -typedef int (*res_nquery_proto)(res_state, const char *, int, int, unsigned char *, int); -static res_nquery_proto local_res_nquery = nullptr; - -// Custom deleter to close resolver state. - -struct QDnsLookupStateDeleter -{ - static inline void cleanup(struct __res_state *pointer) - { - local_res_nclose(pointer); - } -}; - -static QFunctionPointer resolveSymbol(QLibrary &lib, const char *sym) -{ - if (lib.isLoaded()) - return lib.resolve(sym); - -#if defined(RTLD_DEFAULT) && (defined(Q_OS_FREEBSD) || QT_CONFIG(dlopen)) - return reinterpret_cast(dlsym(RTLD_DEFAULT, sym)); -#else - return nullptr; -#endif -} - -static bool resolveLibraryInternal() -{ - QLibrary lib; -#ifdef LIBRESOLV_SO - lib.setFileName(QStringLiteral(LIBRESOLV_SO)); - if (!lib.load()) -#endif - { - lib.setFileName("resolv"_L1); - lib.load(); - } - - local_dn_expand = dn_expand_proto(resolveSymbol(lib, "__dn_expand")); - if (!local_dn_expand) - local_dn_expand = dn_expand_proto(resolveSymbol(lib, "dn_expand")); - - local_res_nclose = res_nclose_proto(resolveSymbol(lib, "__res_nclose")); - if (!local_res_nclose) - local_res_nclose = res_nclose_proto(resolveSymbol(lib, "res_9_nclose")); - if (!local_res_nclose) - local_res_nclose = res_nclose_proto(resolveSymbol(lib, "res_nclose")); - - local_res_ninit = res_ninit_proto(resolveSymbol(lib, "__res_ninit")); - if (!local_res_ninit) - local_res_ninit = res_ninit_proto(resolveSymbol(lib, "res_9_ninit")); - if (!local_res_ninit) - local_res_ninit = res_ninit_proto(resolveSymbol(lib, "res_ninit")); - - local_res_nquery = res_nquery_proto(resolveSymbol(lib, "__res_nquery")); - if (!local_res_nquery) - local_res_nquery = res_nquery_proto(resolveSymbol(lib, "res_9_nquery")); - if (!local_res_nquery) - local_res_nquery = res_nquery_proto(resolveSymbol(lib, "res_nquery")); - - return true; -} -Q_GLOBAL_STATIC_WITH_ARGS(bool, resolveLibrary, (resolveLibraryInternal())) - void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestName, const QHostAddress &nameserver, QDnsLookupReply *reply) { - // Load dn_expand, res_ninit and res_nquery on demand. - resolveLibrary(); - - // If dn_expand, res_ninit or res_nquery is missing, fail. - if (!local_dn_expand || !local_res_nclose || !local_res_ninit || !local_res_nquery) { - reply->error = QDnsLookup::ResolverError; - reply->errorString = tr("Resolver functions not found"); - return; - } - // Initialize state. - struct __res_state state; - std::memset(&state, 0, sizeof(state)); - if (local_res_ninit(&state) < 0) { + std::remove_pointer_t state = {}; + if (res_ninit(&state) < 0) { reply->error = QDnsLookup::ResolverError; reply->errorString = tr("Resolver initialization failed"); return; } + auto guard = qScopeGuard([&] { res_nclose(&state); }); //Check if a nameserver was set. If so, use it if (!nameserver.isNull()) { @@ -170,16 +76,15 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN #ifdef QDNSLOOKUP_DEBUG state.options |= RES_DEBUG; #endif - QScopedPointer state_ptr(&state); // Perform DNS query. QVarLengthArray buffer(PACKETSZ); std::memset(buffer.data(), 0, buffer.size()); - int responseLength = local_res_nquery(&state, requestName, C_IN, requestType, buffer.data(), buffer.size()); + int responseLength = res_nquery(&state, requestName, C_IN, requestType, buffer.data(), buffer.size()); if (Q_UNLIKELY(responseLength > PACKETSZ)) { buffer.resize(responseLength); std::memset(buffer.data(), 0, buffer.size()); - responseLength = local_res_nquery(&state, requestName, C_IN, requestType, buffer.data(), buffer.size()); + responseLength = res_nquery(&state, requestName, C_IN, requestType, buffer.data(), buffer.size()); if (Q_UNLIKELY(responseLength > buffer.size())) { // Ok, we give up. reply->error = QDnsLookup::ResolverError; @@ -229,7 +134,7 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN // Skip the query host, type (2 bytes) and class (2 bytes). char host[PACKETSZ], answer[PACKETSZ]; unsigned char *p = response + sizeof(HEADER); - int status = local_dn_expand(response, response + responseLength, p, host, sizeof(host)); + int status = dn_expand(response, response + responseLength, p, host, sizeof(host)); if (status < 0) { reply->error = QDnsLookup::InvalidReplyError; reply->errorString = tr("Could not expand domain name"); @@ -240,7 +145,7 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN // Extract results. int answerIndex = 0; while ((p < response + responseLength) && (answerIndex < answerCount)) { - status = local_dn_expand(response, response + responseLength, p, host, sizeof(host)); + status = dn_expand(response, response + responseLength, p, host, sizeof(host)); if (status < 0) { reply->error = QDnsLookup::InvalidReplyError; reply->errorString = tr("Could not expand domain name"); @@ -281,7 +186,7 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN record.d->value = QHostAddress(p); reply->hostAddressRecords.append(record); } else if (type == QDnsLookup::CNAME) { - status = local_dn_expand(response, response + responseLength, p, answer, sizeof(answer)); + status = dn_expand(response, response + responseLength, p, answer, sizeof(answer)); if (status < 0) { reply->error = QDnsLookup::InvalidReplyError; reply->errorString = tr("Invalid canonical name record"); @@ -293,7 +198,7 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN record.d->value = QUrl::fromAce(answer); reply->canonicalNameRecords.append(record); } else if (type == QDnsLookup::NS) { - status = local_dn_expand(response, response + responseLength, p, answer, sizeof(answer)); + status = dn_expand(response, response + responseLength, p, answer, sizeof(answer)); if (status < 0) { reply->error = QDnsLookup::InvalidReplyError; reply->errorString = tr("Invalid name server record"); @@ -305,7 +210,7 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN record.d->value = QUrl::fromAce(answer); reply->nameServerRecords.append(record); } else if (type == QDnsLookup::PTR) { - status = local_dn_expand(response, response + responseLength, p, answer, sizeof(answer)); + status = dn_expand(response, response + responseLength, p, answer, sizeof(answer)); if (status < 0) { reply->error = QDnsLookup::InvalidReplyError; reply->errorString = tr("Invalid pointer record"); @@ -318,7 +223,7 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN reply->pointerRecords.append(record); } else if (type == QDnsLookup::MX) { const quint16 preference = (p[0] << 8) | p[1]; - status = local_dn_expand(response, response + responseLength, p + 2, answer, sizeof(answer)); + status = dn_expand(response, response + responseLength, p + 2, answer, sizeof(answer)); if (status < 0) { reply->error = QDnsLookup::InvalidReplyError; reply->errorString = tr("Invalid mail exchange record"); @@ -334,7 +239,7 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN const quint16 priority = (p[0] << 8) | p[1]; const quint16 weight = (p[2] << 8) | p[3]; const quint16 port = (p[4] << 8) | p[5]; - status = local_dn_expand(response, response + responseLength, p + 6, answer, sizeof(answer)); + status = dn_expand(response, response + responseLength, p + 6, answer, sizeof(answer)); if (status < 0) { reply->error = QDnsLookup::InvalidReplyError; reply->errorString = tr("Invalid service record"); @@ -371,17 +276,4 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN } } -#else -void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestName, const QHostAddress &nameserver, QDnsLookupReply *reply) -{ - Q_UNUSED(requestType); - Q_UNUSED(requestName); - Q_UNUSED(nameserver); - reply->error = QDnsLookup::ResolverError; - reply->errorString = tr("Resolver library can't be loaded: No runtime library loading support"); - return; -} - -#endif /* QT_CONFIG(library) */ - QT_END_NAMESPACE diff --git a/src/network/kernel/qhostinfo_unix.cpp b/src/network/kernel/qhostinfo_unix.cpp index 12d8c04d104..331c5fbf455 100644 --- a/src/network/kernel/qhostinfo_unix.cpp +++ b/src/network/kernel/qhostinfo_unix.cpp @@ -3,140 +3,75 @@ //#define QHOSTINFO_DEBUG -#include "qplatformdefs.h" - #include "qhostinfo_p.h" -#include "private/qnativesocketengine_p.h" -#include "qiodevice.h" -#include -#if QT_CONFIG(library) -#include -#endif -#include -#include -#include -#include -#include "QtCore/qapplicationstatic.h" +#include +#include +#include +#include #include #include -#include -#if defined(Q_OS_VXWORKS) -# include -#else -# include -#endif +#include +#include -#if defined(__GNU_LIBRARY__) && !defined(__UCLIBC__) -# include -#endif - -#if defined(Q_OS_FREEBSD) || QT_CONFIG(dlopen) -# include +#ifndef _PATH_RESCONF +# define _PATH_RESCONF "/etc/resolv.conf" #endif QT_BEGIN_NAMESPACE using namespace Qt::StringLiterals; -enum LibResolvFeature { - NeedResInit, - NeedResNInit -}; - -typedef struct __res_state *res_state_ptr; - -typedef int (*res_init_proto)(void); -static res_init_proto local_res_init = nullptr; -typedef int (*res_ninit_proto)(res_state_ptr); -static res_ninit_proto local_res_ninit = nullptr; -typedef void (*res_nclose_proto)(res_state_ptr); -static res_nclose_proto local_res_nclose = nullptr; -static res_state_ptr local_res = nullptr; - -#if QT_CONFIG(library) && !defined(Q_OS_QNX) -namespace { -struct LibResolv +static void maybeRefreshResolver() { - enum { -#ifdef RES_NORELOAD - // If RES_NORELOAD is defined, then the libc is capable of watching - // /etc/resolv.conf for changes and reloading as necessary. So accept - // whatever is configured. - ReinitNecessary = false -#else - ReinitNecessary = true +#if defined(RES_NORELOAD) + // If RES_NORELOAD is defined, then the libc is capable of watching + // /etc/resolv.conf for changes and reloading as necessary. So accept + // whatever is configured. + return; +#elif defined(Q_OS_DARWIN) + // Apple's libsystem_info.dylib:getaddrinfo() uses the + // libsystem_dnssd.dylib to resolve hostnames. Using res_init() has no + // effect on it and is thread-unsafe. + return; +#elif defined(Q_OS_FREEBSD) + // FreeBSD automatically refreshes: + // https://github.com/freebsd/freebsd-src/blob/b3fe5d932264445cbf9a1c4eab01afb6179b499b/lib/libc/resolv/res_state.c#L69 + return; +#elif defined(Q_OS_OPENBSD) + // OpenBSD automatically refreshes: + // https://github.com/ligurio/openbsd-src/blob/b1ce0da17da254cc15b8aff25b3d55d3c7a82cec/lib/libc/asr/asr.c#L367 + return; +#elif defined(Q_OS_QNX) + // res_init() is not thread-safe; executing it leads to state corruption. + // Whether it reloads resolv.conf on its own is unknown. + return; #endif - }; - QLibrary lib; - LibResolv(); - ~LibResolv() { lib.unload(); } -}; -} +#if QT_CONFIG(res_ninit) + // OSes known or thought to reach here: AIX, NetBSD, Solaris, + // Linux with MUSL (though res_init() does nothing and is unnecessary) -static QFunctionPointer resolveSymbol(QLibrary &lib, const char *sym) -{ - if (lib.isLoaded()) - return lib.resolve(sym); - -#if defined(RTLD_DEFAULT) && (defined(Q_OS_FREEBSD) || QT_CONFIG(dlopen)) - return reinterpret_cast(dlsym(RTLD_DEFAULT, sym)); -#else - return nullptr; -#endif -} - -LibResolv::LibResolv() -{ -#ifdef LIBRESOLV_SO - lib.setFileName(QStringLiteral(LIBRESOLV_SO)); - if (!lib.load()) -#endif - { - lib.setFileName("resolv"_L1); - lib.load(); - } - - // res_ninit is required for localDomainName() - local_res_ninit = res_ninit_proto(resolveSymbol(lib, "__res_ninit")); - if (!local_res_ninit) - local_res_ninit = res_ninit_proto(resolveSymbol(lib, "res_ninit")); - if (local_res_ninit) { - // we must now find res_nclose - local_res_nclose = res_nclose_proto(resolveSymbol(lib, "res_nclose")); - if (!local_res_nclose) - local_res_nclose = res_nclose_proto(resolveSymbol(lib, "__res_nclose")); - if (!local_res_nclose) - local_res_ninit = nullptr; - } - - if (ReinitNecessary || !local_res_ninit) { - local_res_init = res_init_proto(resolveSymbol(lib, "__res_init")); - if (!local_res_init) - local_res_init = res_init_proto(resolveSymbol(lib, "res_init")); - - if (local_res_init && !local_res_ninit) { - // if we can't get a thread-safe context, we have to use the global _res state - local_res = res_state_ptr(resolveSymbol(lib, "_res")); + Q_CONSTINIT static QT_STATBUF lastStat = {}; + Q_CONSTINIT static QBasicMutex mutex = {}; + if (QT_STATBUF st; QT_STAT(_PATH_RESCONF, &st) == 0) { + QMutexLocker locker(&mutex); + bool refresh = false; + if ((_res.options & RES_INIT) == 0) + refresh = true; + else if (lastStat.st_ctime != st.st_ctime) + refresh = true; // file was updated + else if (lastStat.st_dev != st.st_dev || lastStat.st_ino != st.st_ino) + refresh = true; // file was replaced + if (refresh) { + lastStat = st; + res_init(); } } +#endif } -Q_APPLICATION_STATIC(LibResolv, libResolv) - -static void resolveLibrary(LibResolvFeature f) -{ - if (LibResolv::ReinitNecessary || f == NeedResNInit) - libResolv(); -} -#else // QT_CONFIG(library) || Q_OS_QNX -static void resolveLibrary(LibResolvFeature) -{ -} -#endif // QT_CONFIG(library) || Q_OS_QNX - QHostInfo QHostInfoAgent::fromName(const QString &hostName) { QHostInfo results; @@ -146,12 +81,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) hostName.toLatin1().constData()); #endif - // Load res_init on demand. - resolveLibrary(NeedResInit); - - // If res_init is available, poll it. - if (local_res_init) - local_res_init(); + maybeRefreshResolver(); QHostAddress address; if (address.setAddress(hostName)) @@ -162,40 +92,30 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) QString QHostInfo::localDomainName() { -#if !defined(Q_OS_VXWORKS) && !defined(Q_OS_ANDROID) - resolveLibrary(NeedResNInit); - if (local_res_ninit) { +#if QT_CONFIG(res_ninit) + auto domainNameFromRes = [](res_state r) { + QString domainName; + if (r->defdname[0]) + domainName = QUrl::fromAce(r->defdname); + if (domainName.isEmpty()) + domainName = QUrl::fromAce(r->dnsrch[0]); + return domainName; + }; + std::remove_pointer_t state = {}; + if (res_ninit(&state) == 0) { // using thread-safe version - res_state_ptr state = res_state_ptr(malloc(sizeof(*state))); - Q_CHECK_PTR(state); - memset(state, 0, sizeof(*state)); - local_res_ninit(state); - QString domainName = QUrl::fromAce(state->defdname); - if (domainName.isEmpty()) - domainName = QUrl::fromAce(state->dnsrch[0]); - local_res_nclose(state); - free(state); - - return domainName; + auto guard = qScopeGuard([&] { res_nclose(&state); }); + return domainNameFromRes(&state); } - if (local_res_init && local_res) { - // using thread-unsafe version + // using thread-unsafe version + maybeRefreshResolver(); + return domainNameFromRes(&_res); +#endif // !QT_CONFIG(res_ninit) - local_res_init(); - QString domainName = QUrl::fromAce(local_res->defdname); - if (domainName.isEmpty()) - domainName = QUrl::fromAce(local_res->dnsrch[0]); - return domainName; - } -#endif // nothing worked, try doing it by ourselves: QFile resolvconf; -#if defined(_PATH_RESCONF) - resolvconf.setFileName(QFile::decodeName(_PATH_RESCONF)); -#else - resolvconf.setFileName("/etc/resolv.conf"_L1); -#endif + resolvconf.setFileName(_PATH_RESCONF ""_L1); if (!resolvconf.open(QIODevice::ReadOnly)) return QString(); // failure diff --git a/tests/auto/network/kernel/CMakeLists.txt b/tests/auto/network/kernel/CMakeLists.txt index 2f5f935f292..f5760c9b0bf 100644 --- a/tests/auto/network/kernel/CMakeLists.txt +++ b/tests/auto/network/kernel/CMakeLists.txt @@ -1,7 +1,7 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -if(NOT INTEGRITY) +if(WIN32 OR TEST_res_ninit) add_subdirectory(qdnslookup) add_subdirectory(qdnslookup_appless) endif() diff --git a/tests/auto/network/kernel/qdnslookup/tst_qdnslookup.cpp b/tests/auto/network/kernel/qdnslookup/tst_qdnslookup.cpp index d22d858b269..764fe9aee43 100644 --- a/tests/auto/network/kernel/qdnslookup/tst_qdnslookup.cpp +++ b/tests/auto/network/kernel/qdnslookup/tst_qdnslookup.cpp @@ -202,11 +202,6 @@ void tst_QDnsLookup::lookup() lookup.lookup(); QTRY_VERIFY_WITH_TIMEOUT(lookup.isFinished(), Timeout); -#if defined(Q_OS_ANDROID) - if (lookup.errorString() == QStringLiteral("Not yet supported on Android")) - QEXPECT_FAIL("", "Not yet supported on Android", Abort); -#endif - QVERIFY2(int(lookup.error()) == error, msgDnsLookup(lookup.error(), error, domain, cname, host, srv, mx, ns, ptr, lookup.errorString())); if (error == QDnsLookup::NoError) @@ -301,11 +296,6 @@ void tst_QDnsLookup::lookupReuse() lookup.lookup(); QTRY_VERIFY_WITH_TIMEOUT(lookup.isFinished(), Timeout); -#if defined(Q_OS_ANDROID) - if (lookup.errorString() == QStringLiteral("Not yet supported on Android")) - QEXPECT_FAIL("", "Not yet supported on Android", Abort); -#endif - QCOMPARE(int(lookup.error()), int(QDnsLookup::NoError)); QVERIFY(!lookup.hostAddressRecords().isEmpty()); QCOMPARE(lookup.hostAddressRecords().first().name(), domainName("a-single")); @@ -342,11 +332,6 @@ void tst_QDnsLookup::lookupAbortRetry() lookup.lookup(); QTRY_VERIFY_WITH_TIMEOUT(lookup.isFinished(), Timeout); -#if defined(Q_OS_ANDROID) - if (lookup.errorString() == QStringLiteral("Not yet supported on Android")) - QEXPECT_FAIL("", "Not yet supported on Android", Abort); -#endif - QCOMPARE(int(lookup.error()), int(QDnsLookup::NoError)); QVERIFY(!lookup.hostAddressRecords().isEmpty()); QCOMPARE(lookup.hostAddressRecords().first().name(), domainName("aaaa-single")); diff --git a/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp index 48925343625..273bf3a0357 100644 --- a/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp +++ b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp @@ -506,6 +506,7 @@ protected: inline void run() override { QHostInfo info = QHostInfo::fromName("a-single" TEST_DOMAIN); + QCOMPARE(info.errorString(), "Unknown error"); // no error QCOMPARE(info.error(), QHostInfo::NoError); QVERIFY(info.addresses().size() > 0); QCOMPARE(info.addresses().at(0).toString(), QString("192.0.2.1"));