diff options
Diffstat (limited to 'src/network/kernel/qdnslookup_p.h')
-rw-r--r-- | src/network/kernel/qdnslookup_p.h | 198 |
1 files changed, 151 insertions, 47 deletions
diff --git a/src/network/kernel/qdnslookup_p.h b/src/network/kernel/qdnslookup_p.h index 21262346b5..811b7336a3 100644 --- a/src/network/kernel/qdnslookup_p.h +++ b/src/network/kernel/qdnslookup_p.h @@ -1,4 +1,5 @@ // Copyright (C) 2012 Jeremy Lainé <jeremy.laine@m4x.org> +// Copyright (C) 2023 Intel Corporation. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QDNSLOOKUP_P_H @@ -18,13 +19,17 @@ #include <QtNetwork/private/qtnetworkglobal_p.h> #include "QtCore/qmutex.h" #include "QtCore/qrunnable.h" -#include "QtCore/qsharedpointer.h" #if QT_CONFIG(thread) #include "QtCore/qthreadpool.h" #endif #include "QtNetwork/qdnslookup.h" #include "QtNetwork/qhostaddress.h" #include "private/qobject_p.h" +#include "private/qurl_p.h" + +#if QT_CONFIG(ssl) +# include "qsslconfiguration.h" +#endif QT_REQUIRE_CONFIG(dnslookup); @@ -32,16 +37,18 @@ QT_BEGIN_NAMESPACE //#define QDNSLOOKUP_DEBUG +constexpr qsizetype MaxDomainNameLength = 255; +constexpr quint16 DnsPort = 53; +constexpr quint16 DnsOverTlsPort = 853; + class QDnsLookupRunnable; +QDebug operator<<(QDebug &, QDnsLookupRunnable *); class QDnsLookupReply { public: - QDnsLookupReply() - : error(QDnsLookup::NoError) - { } - - QDnsLookup::Error error; + QDnsLookup::Error error = QDnsLookup::NoError; + bool authenticData = false; QString errorString; QList<QDnsDomainNameRecord> canonicalNameRecords; @@ -50,24 +57,93 @@ public: QList<QDnsDomainNameRecord> nameServerRecords; QList<QDnsDomainNameRecord> pointerRecords; QList<QDnsServiceRecord> serviceRecords; + QList<QDnsTlsAssociationRecord> tlsAssociationRecords; QList<QDnsTextRecord> textRecords; + +#if QT_CONFIG(ssl) + std::optional<QSslConfiguration> sslConfiguration; +#endif + + // helper methods + void setError(QDnsLookup::Error err, QString &&msg) + { + error = err; + errorString = std::move(msg); + } + + void makeResolverSystemError(int code = -1) + { + Q_ASSERT(allAreEmpty()); + setError(QDnsLookup::ResolverError, qt_error_string(code)); + } + + void makeTimeoutError() + { + Q_ASSERT(allAreEmpty()); + setError(QDnsLookup::TimeoutError, QDnsLookup::tr("Request timed out")); + } + + void makeDnsRcodeError(quint8 rcode) + { + Q_ASSERT(allAreEmpty()); + switch (rcode) { + case 1: // FORMERR + error = QDnsLookup::InvalidRequestError; + errorString = QDnsLookup::tr("Server could not process query"); + return; + case 2: // SERVFAIL + case 4: // NOTIMP + error = QDnsLookup::ServerFailureError; + errorString = QDnsLookup::tr("Server failure"); + return; + case 3: // NXDOMAIN + error = QDnsLookup::NotFoundError; + errorString = QDnsLookup::tr("Non existent domain"); + return; + case 5: // REFUSED + error = QDnsLookup::ServerRefusedError; + errorString = QDnsLookup::tr("Server refused to answer"); + return; + default: + error = QDnsLookup::InvalidReplyError; + errorString = QDnsLookup::tr("Invalid reply received (rcode %1)") + .arg(rcode); + return; + } + } + + void makeInvalidReplyError(QString &&msg = QString()) + { + if (msg.isEmpty()) + msg = QDnsLookup::tr("Invalid reply received"); + else + msg = QDnsLookup::tr("Invalid reply received (%1)").arg(std::move(msg)); + *this = QDnsLookupReply(); // empty our lists + setError(QDnsLookup::InvalidReplyError, std::move(msg)); + } + +private: + bool allAreEmpty() const + { + return canonicalNameRecords.isEmpty() + && hostAddressRecords.isEmpty() + && mailExchangeRecords.isEmpty() + && nameServerRecords.isEmpty() + && pointerRecords.isEmpty() + && serviceRecords.isEmpty() + && textRecords.isEmpty(); + } }; class QDnsLookupPrivate : public QObjectPrivate { public: QDnsLookupPrivate() - : isFinished(false) - , type(QDnsLookup::A) - , runnable(nullptr) + : type(QDnsLookup::A) + , port(0) + , protocol(QDnsLookup::Standard) { } - void _q_lookupFinished(const QDnsLookupReply &reply); - - static const char *msgNoIpV6NameServerAdresses; - - bool isFinished; - void nameChanged() { emit q_func()->nameChanged(name); @@ -75,6 +151,13 @@ public: Q_OBJECT_BINDABLE_PROPERTY(QDnsLookupPrivate, QString, name, &QDnsLookupPrivate::nameChanged); + void nameserverChanged() + { + emit q_func()->nameserverChanged(nameserver); + } + Q_OBJECT_BINDABLE_PROPERTY(QDnsLookupPrivate, QHostAddress, nameserver, + &QDnsLookupPrivate::nameserverChanged); + void typeChanged() { emit q_func()->typeChanged(type); @@ -83,15 +166,29 @@ public: Q_OBJECT_BINDABLE_PROPERTY(QDnsLookupPrivate, QDnsLookup::Type, type, &QDnsLookupPrivate::typeChanged); - void nameserverChanged() + void nameserverPortChanged() { - emit q_func()->nameserverChanged(nameserver); + emit q_func()->nameserverPortChanged(port); } - Q_OBJECT_BINDABLE_PROPERTY(QDnsLookupPrivate, QHostAddress, nameserver, - &QDnsLookupPrivate::nameserverChanged); + + Q_OBJECT_BINDABLE_PROPERTY(QDnsLookupPrivate, quint16, + port, &QDnsLookupPrivate::nameserverPortChanged); + + void nameserverProtocolChanged() + { + emit q_func()->nameserverProtocolChanged(protocol); + } + + Q_OBJECT_BINDABLE_PROPERTY(QDnsLookupPrivate, QDnsLookup::Protocol, + protocol, &QDnsLookupPrivate::nameserverProtocolChanged); QDnsLookupReply reply; - QDnsLookupRunnable *runnable; + QDnsLookupRunnable *runnable = nullptr; + bool isFinished = false; + +#if QT_CONFIG(ssl) + std::optional<QSslConfiguration> sslConfiguration; +#endif Q_DECLARE_PUBLIC(QDnsLookup) }; @@ -101,40 +198,40 @@ class QDnsLookupRunnable : public QObject, public QRunnable Q_OBJECT public: - QDnsLookupRunnable(QDnsLookup::Type type, const QByteArray &name, const QHostAddress &nameserver) - : requestType(type) - , requestName(name) - , nameserver(nameserver) - { } +#ifdef Q_OS_WIN + using EncodedLabel = QString; +#else + using EncodedLabel = QByteArray; +#endif + // minimum IPv6 MTU (1280) minus the IPv6 (40) and UDP headers (8) + static constexpr qsizetype ReplyBufferSize = 1280 - 40 - 8; + using ReplyBuffer = QVarLengthArray<unsigned char, ReplyBufferSize>; + + QDnsLookupRunnable(const QDnsLookupPrivate *d); void run() override; + bool sendDnsOverTls(QDnsLookupReply *reply, QSpan<unsigned char> query, ReplyBuffer &response); signals: void finished(const QDnsLookupReply &reply); private: - static void query(const int requestType, const QByteArray &requestName, const QHostAddress &nameserver, QDnsLookupReply *reply); - QDnsLookup::Type requestType; - QByteArray requestName; - QHostAddress nameserver; -}; - -#if QT_CONFIG(thread) -class QDnsLookupThreadPool : public QThreadPool -{ - Q_OBJECT - -public: - QDnsLookupThreadPool(); - void start(QRunnable *runnable); + template <typename T> static QString decodeLabel(T encodedLabel) + { + return qt_ACE_do(encodedLabel.toString(), NormalizeAce, ForbidLeadingDot); + } + void query(QDnsLookupReply *reply); -private slots: - void _q_applicationDestroyed(); + EncodedLabel requestName; + QHostAddress nameserver; + QDnsLookup::Type requestType; + quint16 port; + QDnsLookup::Protocol protocol; -private: - QMutex signalsMutex; - bool signalsConnected; +#if QT_CONFIG(ssl) + std::optional<QSslConfiguration> sslConfiguration; +#endif + friend QDebug operator<<(QDebug &, QDnsLookupRunnable *); }; -#endif // QT_CONFIG(thread) class QDnsRecordPrivate : public QSharedData { @@ -200,8 +297,15 @@ public: QList<QByteArray> values; }; -QT_END_NAMESPACE +class QDnsTlsAssociationRecordPrivate : public QDnsRecordPrivate +{ +public: + QDnsTlsAssociationRecord::CertificateUsage usage; + QDnsTlsAssociationRecord::Selector selector; + QDnsTlsAssociationRecord::MatchingType matchType; + QByteArray value; +}; -QT_DECL_METATYPE_EXTERN(QDnsLookupReply, Q_NETWORK_EXPORT) +QT_END_NAMESPACE #endif // QDNSLOOKUP_P_H |