diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2023-05-08 21:54:59 -0700 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2023-05-23 21:23:42 -0700 |
commit | bce7009f552ed1e28ac2687ef004203f285ee21c (patch) | |
tree | 5ad99be5209589f5c0c3f85789bdcf43a7c881fc /tests | |
parent | 029e0bf55203846fa2335e1594689c6160c30113 (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.cpp | 70 | ||||
-rw-r--r-- | tests/manual/qdnslookup/main.cpp | 31 |
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 |