summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2023-05-08 21:54:59 -0700
committerThiago Macieira <thiago.macieira@intel.com>2023-05-23 21:23:42 -0700
commitbce7009f552ed1e28ac2687ef004203f285ee21c (patch)
tree5ad99be5209589f5c0c3f85789bdcf43a7c881fc /tests
parent029e0bf55203846fa2335e1594689c6160c30113 (diff)
QDnsLookup: add support for setting the port number of the server
I couldn't make my Windows 10 or 11 query a non-standard port. It kept complaining about "The parameter is incorrect.", so as a result the unit test doesn't actually test the new feature there. I can't find a single example of this on the Internet; my speculation is that the backend API that DnsQueryEx uses does not support setting port numbers (DnsQuery_{A,W} didn't offer that option). [ChangeLog][QtNetwork][QDnsLookup] Added setNameserverPort(). Change-Id: I3e3bfef633af4130a03afffd175d60a581cc0a9c Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/network/kernel/qdnslookup/tst_qdnslookup.cpp70
-rw-r--r--tests/manual/qdnslookup/main.cpp31
2 files changed, 95 insertions, 6 deletions
diff --git a/tests/auto/network/kernel/qdnslookup/tst_qdnslookup.cpp b/tests/auto/network/kernel/qdnslookup/tst_qdnslookup.cpp
index 1d0da9dbe3..568f0d84b8 100644
--- a/tests/auto/network/kernel/qdnslookup/tst_qdnslookup.cpp
+++ b/tests/auto/network/kernel/qdnslookup/tst_qdnslookup.cpp
@@ -7,7 +7,11 @@
#include <QSignalSpy>
#include <QtNetwork/QDnsLookup>
+
+#include <QtCore/QRandomGenerator>
#include <QtNetwork/QHostAddress>
+#include <QtNetwork/QNetworkDatagram>
+#include <QtNetwork/QUdpSocket>
using namespace Qt::StringLiterals;
static const int Timeout = 15000; // 15s
@@ -35,6 +39,7 @@ private slots:
void lookupReuse();
void lookupAbortRetry();
+ void setNameserverLoopback();
void bindingsAndProperties();
};
@@ -351,6 +356,62 @@ void tst_QDnsLookup::lookupAbortRetry()
QCOMPARE(lookup.hostAddressRecords().first().value(), QHostAddress("2001:db8::1"));
}
+void tst_QDnsLookup::setNameserverLoopback()
+{
+#ifdef Q_OS_WIN
+ // Windows doesn't like sending DNS requests to ports other than 53, so
+ // let's try it first.
+ constexpr quint16 DesiredPort = 53;
+#else
+ // Trying to bind to port 53 will fail on Unix systems unless this test is
+ // run as root, so we try mDNS's port (to help decoding in a packet capture).
+ constexpr quint16 DesiredPort = 5353; // mDNS
+#endif
+ // random loopback address so multiple copies of this test can run
+ QHostAddress desiredAddress(0x7f000000 | QRandomGenerator::system()->bounded(0xffffff));
+
+ QUdpSocket server;
+ if (!server.bind(desiredAddress, DesiredPort)) {
+ // port in use, try a random one
+ server.bind(QHostAddress::LocalHost, 0);
+ }
+ QCOMPARE(server.state(), QUdpSocket::BoundState);
+
+ QDnsLookup lookup(QDnsLookup::Type::A, u"somelabel.somedomain"_s);
+ QSignalSpy spy(&lookup, SIGNAL(finished()));
+ lookup.setNameserver(server.localAddress(), server.localPort());
+
+ // QDnsLookup is threaded, so we can answer on the main thread
+ QObject::connect(&server, &QUdpSocket::readyRead,
+ &QTestEventLoop::instance(), &QTestEventLoop::exitLoop);
+ QObject::connect(&lookup, &QDnsLookup::finished,
+ &QTestEventLoop::instance(), &QTestEventLoop::exitLoop);
+ lookup.lookup();
+ QTestEventLoop::instance().enterLoop(5);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+ QVERIFY2(spy.isEmpty(), qPrintable(lookup.errorString()));
+
+ QNetworkDatagram dgram = server.receiveDatagram();
+ QByteArray data = dgram.data();
+ QCOMPARE_GT(data.size(), HeaderSize);
+
+ quint8 opcode = (quint8(data.at(3)) >> 4) & 0xF;
+ QCOMPARE(opcode, 0); // standard query
+
+ // send an NXDOMAIN reply to release the lookup thread
+ QByteArray reply = data;
+ reply[2] = 0x80; // header->qr = true;
+ reply[3] = 3; // header->rcode = NXDOMAIN;
+ server.writeDatagram(dgram.makeReply(reply));
+ server.close();
+
+ // now check that the QDnsLookup finished
+ QTestEventLoop::instance().enterLoop(5);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+ QCOMPARE(spy.size(), 1);
+ QCOMPARE(lookup.error(), QDnsLookup::NotFoundError);
+}
+
void tst_QDnsLookup::bindingsAndProperties()
{
QDnsLookup lookup;
@@ -383,14 +444,23 @@ void tst_QDnsLookup::bindingsAndProperties()
QProperty<QHostAddress> nameserverProp;
lookup.bindableNameserver().setBinding(Qt::makePropertyBinding(nameserverProp));
const QSignalSpy nameserverChangeSpy(&lookup, &QDnsLookup::nameserverChanged);
+ const QSignalSpy nameserverPortChangeSpy(&lookup, &QDnsLookup::nameserverPortChanged);
nameserverProp = QHostAddress::LocalHost;
QCOMPARE(nameserverChangeSpy.size(), 1);
+ QCOMPARE(nameserverPortChangeSpy.size(), 0);
QCOMPARE(lookup.nameserver(), QHostAddress::LocalHost);
nameserverProp.setBinding(lookup.bindableNameserver().makeBinding());
lookup.setNameserver(QHostAddress::Any);
QCOMPARE(nameserverProp.value(), QHostAddress::Any);
+ QCOMPARE(nameserverChangeSpy.size(), 2);
+ QCOMPARE(nameserverPortChangeSpy.size(), 0);
+
+ lookup.setNameserver(QHostAddress::LocalHostIPv6, 10053);
+ QCOMPARE(nameserverProp.value(), QHostAddress::LocalHostIPv6);
+ QCOMPARE(nameserverChangeSpy.size(), 3);
+ QCOMPARE(nameserverPortChangeSpy.size(), 1);
}
QTEST_MAIN(tst_QDnsLookup)
diff --git a/tests/manual/qdnslookup/main.cpp b/tests/manual/qdnslookup/main.cpp
index 3ddf84063e..19aeeeb4b8 100644
--- a/tests/manual/qdnslookup/main.cpp
+++ b/tests/manual/qdnslookup/main.cpp
@@ -6,6 +6,7 @@
#include <QtCore/QElapsedTimer>
#include <QtCore/QMetaEnum>
#include <QtCore/QTimer>
+#include <QtCore/QUrl>
#include <QtNetwork/QHostAddress>
#include <QtNetwork/QHostInfo>
#include <QtNetwork/QDnsLookup>
@@ -38,6 +39,24 @@ static int showHelp(const char *argv0, int exitcode)
return exitcode;
}
+static auto parseServerAddress(QString server)
+{
+ struct R {
+ QHostAddress address;
+ int port = -1;
+ } r;
+
+ // let's use QUrl to help us
+ QUrl url;
+ url.setAuthority(server);
+ if (!url.isValid() || !url.userInfo().isNull())
+ return r; // failed
+
+ r.port = url.port();
+ r.address.setAddress(url.host());
+ return r;
+}
+
static void printAnswers(const QDnsLookup &lookup)
{
printf("\n;; ANSWER:\n");
@@ -96,7 +115,7 @@ static void printResults(const QDnsLookup &lookup, QElapsedTimer::Duration durat
printf("\n;; Query time: %lld ms\n", qint64(duration_cast<milliseconds>(duration).count()));
if (QHostAddress server = lookup.nameserver(); !server.isNull())
- printf(";; SERVER: %s#53\n", qPrintable(server.toString()));
+ printf(";; SERVER: %s#%d\n", qPrintable(server.toString()), lookup.nameserverPort());
}
int main(int argc, char *argv[])
@@ -138,15 +157,15 @@ int main(int argc, char *argv[])
QDnsLookup lookup(type, domain);
if (!server.isEmpty()) {
- QHostAddress addr(server);
- if (addr.isNull())
- addr = QHostInfo::fromName(server).addresses().value(0);
- if (addr.isNull()) {
+ auto addr = parseServerAddress(server);
+ if (addr.address.isNull()) {
fprintf(stderr, "%s: could not parse name server address '%s'\n",
argv[0], qPrintable(server));
return EXIT_FAILURE;
}
- lookup.setNameserver(addr);
+ lookup.setNameserver(addr.address);
+ if (addr.port > 0)
+ lookup.setNameserverPort(addr.port);
}
// execute the lookup