From e199710d0ea804e4481042f41b91b5234540f5d5 Mon Sep 17 00:00:00 2001 From: Davide Beatrici Date: Sat, 6 Apr 2019 08:01:11 +0200 Subject: [PATCH] QHostInfo: use dlsym() with RTLD_DEFAULT in case libs cannot be loaded The current code only tries to load the required functions from LIBRESOLV_SO (if defined) and resolv, but on FreeBSD they are in libc: https://www.freebsd.org/cgi/man.cgi?query=res_query&sektion=3&apropos=0&manpath=freebsd This commit changes the code so that, after failing to load the non-existent libraries, it attempts to load the functions with dlsym() using the special handle RTLD_DEFAULT, which searches for the specified symbol in the loaded libraries. This is a follow-up to 8eeb5150ed99914e252a84f1637f179e3de04659. Change-Id: I19d90b0ca8703398bf4f5f4edd5ae31e346ef251 Reviewed-by: Thiago Macieira --- src/network/kernel/kernel.pri | 7 +++--- src/network/kernel/qhostinfo_unix.cpp | 33 +++++++++++++++++++-------- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/network/kernel/kernel.pri b/src/network/kernel/kernel.pri index d7a92a12eb..7074fcd5eb 100644 --- a/src/network/kernel/kernel.pri +++ b/src/network/kernel/kernel.pri @@ -38,13 +38,12 @@ qtConfig(dnslookup) { } unix { - !integrity:qtConfig(dnslookup) { - SOURCES += kernel/qdnslookup_unix.cpp - qtConfig(dlopen): QMAKE_USE_PRIVATE += libdl - } + !integrity:qtConfig(dnslookup): SOURCES += kernel/qdnslookup_unix.cpp SOURCES += kernel/qhostinfo_unix.cpp + qtConfig(dlopen): QMAKE_USE_PRIVATE += libdl + qtConfig(linux-netlink): SOURCES += kernel/qnetworkinterface_linux.cpp else: SOURCES += kernel/qnetworkinterface_unix.cpp } diff --git a/src/network/kernel/qhostinfo_unix.cpp b/src/network/kernel/qhostinfo_unix.cpp index d22608e22f..e4810d68ee 100644 --- a/src/network/kernel/qhostinfo_unix.cpp +++ b/src/network/kernel/qhostinfo_unix.cpp @@ -66,6 +66,10 @@ # include #endif +#if defined(Q_OS_FREEBSD) || QT_CONFIG(dlopen) +# include +#endif + QT_BEGIN_NAMESPACE // Almost always the same. If not, specify in qplatformdefs.h. @@ -115,6 +119,18 @@ struct LibResolv }; } +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() { QLibrary lib; @@ -124,31 +140,30 @@ LibResolv::LibResolv() #endif { lib.setFileName(QLatin1String("resolv")); - if (!lib.load()) - return; + lib.load(); } // res_ninit is required for localDomainName() - local_res_ninit = res_ninit_proto(lib.resolve("__res_ninit")); + local_res_ninit = res_ninit_proto(resolveSymbol(lib, "__res_ninit")); if (!local_res_ninit) - local_res_ninit = res_ninit_proto(lib.resolve("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(lib.resolve("res_nclose")); + local_res_nclose = res_nclose_proto(resolveSymbol(lib, "res_nclose")); if (!local_res_nclose) - local_res_nclose = res_nclose_proto(lib.resolve("__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(lib.resolve("__res_init")); + local_res_init = res_init_proto(resolveSymbol(lib, "__res_init")); if (!local_res_init) - local_res_init = res_init_proto(lib.resolve("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(lib.resolve("_res")); + local_res = res_state_ptr(resolveSymbol(lib, "_res")); } } }