diff --git a/src/network/kernel/qdnslookup.cpp b/src/network/kernel/qdnslookup.cpp index e776a8eb76..97a402901e 100644 --- a/src/network/kernel/qdnslookup.cpp +++ b/src/network/kernel/qdnslookup.cpp @@ -482,7 +482,7 @@ void QDnsLookup::lookup() Q_D(QDnsLookup); d->isFinished = false; d->reply = QDnsLookupReply(); - d->runnable = new QDnsLookupRunnable(d->type, QUrl::toAce(d->name)); + d->runnable = new QDnsLookupRunnable(d->type, QUrl::toAce(d->name), d->nameserver); connect(d->runnable, SIGNAL(finished(QDnsLookupReply)), this, SLOT(_q_lookupFinished(QDnsLookupReply)), Qt::BlockingQueuedConnection); @@ -990,7 +990,7 @@ void QDnsLookupRunnable::run() } // Perform request. - query(requestType, requestName, &reply); + query(requestType, requestName, nameserver, &reply); // Sort results. if (!theDnsLookupSeedStorage()->hasLocalData()) { diff --git a/src/network/kernel/qdnslookup_android.cpp b/src/network/kernel/qdnslookup_android.cpp index dff81dba0c..1ace5727c2 100644 --- a/src/network/kernel/qdnslookup_android.cpp +++ b/src/network/kernel/qdnslookup_android.cpp @@ -43,10 +43,11 @@ QT_BEGIN_NAMESPACE -void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestName, QDnsLookupReply *reply) +void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestName, const QHostAddress &nameserver, QDnsLookupReply *reply) { Q_UNUSED(requestType); Q_UNUSED(requestName); + Q_UNUSED(nameserver); Q_UNUSED(reply); qWarning() << Q_FUNC_INFO << "Not yet supported on Android"; reply->error = QDnsLookup::ResolverError; diff --git a/src/network/kernel/qdnslookup_p.h b/src/network/kernel/qdnslookup_p.h index 4bd3bd7603..7c0b0e862a 100644 --- a/src/network/kernel/qdnslookup_p.h +++ b/src/network/kernel/qdnslookup_p.h @@ -112,9 +112,10 @@ class QDnsLookupRunnable : public QObject, public QRunnable Q_OBJECT public: - QDnsLookupRunnable(QDnsLookup::Type type, const QByteArray &name) + QDnsLookupRunnable(QDnsLookup::Type type, const QByteArray &name, const QHostAddress &nameserver) : requestType(type) , requestName(name) + , nameserver(nameserver) { } void run(); @@ -122,9 +123,10 @@ signals: void finished(const QDnsLookupReply &reply); private: - static void query(const int requestType, const QByteArray &requestName, QDnsLookupReply *reply); + static void query(const int requestType, const QByteArray &requestName, const QHostAddress &nameserver, QDnsLookupReply *reply); QDnsLookup::Type requestType; QByteArray requestName; + QHostAddress nameserver; }; class QDnsLookupThreadPool : public QThreadPool diff --git a/src/network/kernel/qdnslookup_unix.cpp b/src/network/kernel/qdnslookup_unix.cpp index 9fb488cee6..26834dff57 100644 --- a/src/network/kernel/qdnslookup_unix.cpp +++ b/src/network/kernel/qdnslookup_unix.cpp @@ -115,7 +115,7 @@ static void resolveLibrary() local_res_nquery = res_nquery_proto(lib.resolve("res_nquery")); } -void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestName, QDnsLookupReply *reply) +void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestName, const QHostAddress &nameserver, QDnsLookupReply *reply) { // Load dn_expand, res_ninit and res_nquery on demand. static QBasicAtomicInt triedResolve = Q_BASIC_ATOMIC_INITIALIZER(false); @@ -142,6 +142,43 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN reply->errorString = tr("Resolver initialization failed"); return; } + + //Check if a nameserver was set. If so, use it + if (!nameserver.isNull()) { + if (nameserver.protocol() == QAbstractSocket::IPv4Protocol) { + state.nsaddr_list[0].sin_addr.s_addr = htonl(nameserver.toIPv4Address()); + state.nscount = 1; + } else if (nameserver.protocol() == QAbstractSocket::IPv6Protocol) { +#if defined(Q_OS_LINUX) + struct sockaddr_in6 *ns; + ns = state._u._ext.nsaddrs[0]; + // nsaddrs will be NULL if no nameserver is set in /etc/resolv.conf + if (!ns) { + // Memory allocated here will be free'd in res_close() as we + // have done res_init() above. + ns = (struct sockaddr_in6*) calloc(1, sizeof(struct sockaddr_in6)); + Q_CHECK_PTR(ns); + state._u._ext.nsaddrs[0] = ns; + } + // Set nsmap[] to indicate that nsaddrs[0] is an IPv6 address + // See: https://sourceware.org/ml/libc-hacker/2002-05/msg00035.html + state._u._ext.nsmap[0] = MAXNS + 1; + state._u._ext.nscount6 = 1; + ns->sin6_family = AF_INET6; + ns->sin6_port = htons(53); + + Q_IPV6ADDR ipv6Address = nameserver.toIPv6Address(); + for (int i=0; i<16; i++) { + ns->sin6_addr.s6_addr[i] = ipv6Address[i]; + } +#else + qWarning() << Q_FUNC_INFO << "IPv6 addresses for nameservers is currently not supported"; + reply->error = QDnsLookup::ResolverError; + reply->errorString = tr("IPv6 addresses for nameservers is currently not supported"); + return; +#endif + } + } #ifdef QDNSLOOKUP_DEBUG state.options |= RES_DEBUG; #endif diff --git a/src/network/kernel/qdnslookup_win.cpp b/src/network/kernel/qdnslookup_win.cpp index bf80a23297..6f58e64440 100644 --- a/src/network/kernel/qdnslookup_win.cpp +++ b/src/network/kernel/qdnslookup_win.cpp @@ -48,15 +48,33 @@ #include #include +#include QT_BEGIN_NAMESPACE -void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestName, QDnsLookupReply *reply) +void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestName, const QHostAddress &nameserver, QDnsLookupReply *reply) { // Perform DNS query. PDNS_RECORD dns_records = 0; const QString requestNameUtf16 = QString::fromUtf8(requestName.data(), requestName.size()); - const DNS_STATUS status = DnsQuery_W(reinterpret_cast(requestNameUtf16.utf16()), requestType, DNS_QUERY_STANDARD, NULL, &dns_records, NULL); + IP4_ARRAY srvList; + memset(&srvList, 0, sizeof(IP4_ARRAY)); + if (!nameserver.isNull()) { + if (nameserver.protocol() == QAbstractSocket::IPv4Protocol) { + // The below code is referenced from: http://support.microsoft.com/kb/831226 + srvList.AddrCount = 1; + srvList.AddrArray[0] = htonl(nameserver.toIPv4Address()); + } else if (nameserver.protocol() == QAbstractSocket::IPv6Protocol) { + // For supoprting IPv6 nameserver addresses, we'll need to switch + // from DnsQuey() to DnsQueryEx() as it supports passing an IPv6 + // address in the nameserver list + qWarning() << Q_FUNC_INFO << "IPv6 addresses for nameservers is currently not supported"; + reply->error = QDnsLookup::ResolverError; + reply->errorString = tr("IPv6 addresses for nameservers is currently not supported"); + return; + } + } + const DNS_STATUS status = DnsQuery_W(reinterpret_cast(requestNameUtf16.utf16()), requestType, DNS_QUERY_STANDARD, &srvList, &dns_records, NULL); switch (status) { case ERROR_SUCCESS: break; diff --git a/src/network/kernel/qdnslookup_winrt.cpp b/src/network/kernel/qdnslookup_winrt.cpp index a5d16e4b63..6ac944934a 100644 --- a/src/network/kernel/qdnslookup_winrt.cpp +++ b/src/network/kernel/qdnslookup_winrt.cpp @@ -42,6 +42,7 @@ #include "qdnslookup_p.h" #include +#include #include #include @@ -59,8 +60,12 @@ using namespace ABI::Windows::Networking::Sockets; QT_BEGIN_NAMESPACE -void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestName, QDnsLookupReply *reply) +void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestName, const QHostAddress &nameserver, QDnsLookupReply *reply) { + // TODO: Add nameserver support for winRT + if (!nameserver.isNull()) + qWarning() << "Ignoring nameserver as its currently not supported on WinRT"; + // TODO: is there any way to do "proper" dns lookup? if (requestType != QDnsLookup::A && requestType != QDnsLookup::AAAA && requestType != QDnsLookup::ANY) {