12#include <private/qnativesocketengine_p.h>
13#include <private/qtnetwork-config_p.h>
18#include <netinet/in.h>
19#include <arpa/nameser.h>
20#if __has_include(<arpa/nameser_compat.h>)
21# include <arpa/nameser_compat.h>
30# define T_OPT ns_t_opt
51 HFIXEDSZ + QFIXEDSZ + MAXCDNAME + 1 +
sizeof(
Edns0Record);
63using Cache = QList<QDnsCachedName>;
65#if QT_CONFIG(res_setservers)
70 union res_sockaddr_union u;
71 setSockaddr(
reinterpret_cast<sockaddr *
>(&u.sin), nameserver,
port);
72 res_setservers(
state, &u, 1);
76template <
typename T>
void setNsMap(T &ext, std::enable_if_t<
sizeof(T::nsmap) != 0, uint16_t>
v)
89template <
bool Condition>
90using EnableIfIPv6 = std::enable_if_t<Condition, const QHostAddress *>;
92template <
typename State>
98 struct sockaddr_in6 *
ns =
state->_u._ext.nsaddrs[0];
104 ns =
static_cast<struct sockaddr_in6*
>(calloc(1,
sizeof(
struct sockaddr_in6)));
106 state->_u._ext.nsaddrs[0] =
ns;
110 state->_u._ext.nscount6 = 1;
124 state->nsaddr_list[0].sin_family = AF_UNSPEC;
127 setSockaddr(&
state->nsaddr_list[0], nameserver,
port);
136 int queryLength = res_nmkquery(
state, QUERY,
label, C_IN,
type,
nullptr, 0,
nullptr,
145 reinterpret_cast<HEADER *
>(
buffer.data())->arcount = qToBigEndian<quint16>(1);
154 if (!nameserver.
isNull()) {
157 QDnsLookup::tr(
"IPv6 nameservers are currently not supported on this OS"));
162 reinterpret_cast<HEADER *
>(
buffer.data())->ad =
true;
167 state->options |= RES_TRUSTAD;
171 auto attemptToSend = [&]() {
172 std::memset(
buffer.data(), 0, HFIXEDSZ);
173 int responseLength = res_nsend(
state, qbuffer.data(), qbuffer.size(),
buffer.data(),
buffer.size());
174 if (responseLength >= 0)
175 return responseLength;
178 if (errno == ECONNREFUSED)
180 else if (errno != ETIMEDOUT)
181 reply->makeResolverSystemError();
183 auto query =
reinterpret_cast<HEADER *
>(qbuffer.data());
184 auto header =
reinterpret_cast<HEADER *
>(
buffer.data());
188 reply->makeTimeoutError();
193 state->options |= RES_IGNTC;
194 int responseLength = attemptToSend();
195 if (responseLength < 0)
196 return responseLength;
199 auto header =
reinterpret_cast<HEADER *
>(
buffer.data());
202 buffer.resize(std::numeric_limits<quint16>::max());
206 reinterpret_cast<HEADER *
>(qbuffer.data())->arcount = 0;
207 qbuffer = qbuffer.first(qbuffer.size() -
sizeof(
Edns0Record));
210 state->options |= RES_USEVC;
211 responseLength = attemptToSend();
228 return responseLength;
234 std::remove_pointer_t<res_state>
state = {};
235 if (res_ninit(&
state) < 0) {
242#ifdef QDNSLOOKUP_DEBUG
243 state.options |= RES_DEBUG;
250 return reply->makeResolverSystemError();
254 int responseLength = -1;
262 responseLength =
buffer.size();
266 if (responseLength < 0)
270 if (responseLength <
int(
sizeof(HEADER)))
271 return reply->makeInvalidReplyError();
274 auto header =
reinterpret_cast<HEADER *
>(
buffer.data());
279 unsigned char *response =
buffer.data();
285 if (
offset + 1 < responseLength) {
286 int id = ((
n & ~NS_CMPRSFLGS) << 8) | response[
offset + 1];
287 auto it = std::find_if(
cache.constBegin(),
cache.constEnd(),
288 [
id](
const QDnsCachedName &
n) { return n.code == id; });
297 char host[MAXCDNAME + 1];
298 status = dn_expand(response, response + responseLength, response +
offset,
304 reply->makeInvalidReplyError(QDnsLookup::tr(
"Could not expand domain name"));
308 if (ntohs(
header->qdcount) == 1) {
313 if (
offset + status + 4 > responseLength)
318 if (ntohs(
header->qdcount) > 1)
319 return reply->makeInvalidReplyError();
322 const int answerCount = ntohs(
header->ancount);
324 while ((
offset < responseLength) && (answerIndex < answerCount)) {
330 if (
offset + RRFIXEDSZ > responseLength) {
335 const qint16 rrclass = qFromBigEndian<quint16>(response +
offset + 2);
336 const quint32 ttl = qFromBigEndian<quint32>(response +
offset + 4);
346 return reply->makeInvalidReplyError(QDnsLookup::tr(
"Invalid IPv4 address record"));
350 record.d->timeToLive = ttl;
355 return reply->makeInvalidReplyError(QDnsLookup::tr(
"Invalid IPv6 address record"));
358 record.d->timeToLive = ttl;
364 record.d->timeToLive = ttl;
367 return reply->makeInvalidReplyError(QDnsLookup::tr(
"Invalid canonical name record"));
372 record.d->timeToLive = ttl;
375 return reply->makeInvalidReplyError(QDnsLookup::tr(
"Invalid name server record"));
380 record.d->timeToLive = ttl;
383 return reply->makeInvalidReplyError(QDnsLookup::tr(
"Invalid pointer record"));
386 const quint16 preference = qFromBigEndian<quint16>(response +
offset);
390 record.d->preference = preference;
391 record.d->timeToLive = ttl;
393 return reply->makeInvalidReplyError(QDnsLookup::tr(
"Invalid mail exchange record"));
397 return reply->makeInvalidReplyError(QDnsLookup::tr(
"Invalid service record"));
398 const quint16 priority = qFromBigEndian<quint16>(response +
offset);
405 record.d->priority = priority;
406 record.d->timeToLive = ttl;
409 return reply->makeInvalidReplyError(QDnsLookup::tr(
"Invalid service record"));
414 return reply->makeInvalidReplyError(QDnsLookup::tr(
"Invalid TLS association record"));
422 record.d->timeToLive = ttl;
427 reply->tlsAssociationRecords.append(std::move(
record));
431 record.d->timeToLive = ttl;
434 const unsigned char length = response[
txt];
437 return reply->makeInvalidReplyError(QDnsLookup::tr(
"Invalid text record"));
static constexpr auto IPv6Protocol
QByteArray toByteArray() const
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
The QDnsDomainNameRecord class stores information about a domain name record.
The QDnsHostAddressRecord class stores information about a host address record.
static constexpr qsizetype ReplyBufferSize
bool sendDnsOverTls(QDnsLookupReply *reply, QSpan< unsigned char > query, ReplyBuffer &response)
QVarLengthArray< unsigned char, ReplyBufferSize > ReplyBuffer
The QDnsMailExchangeRecord class stores information about a DNS MX record.
The QDnsServiceRecord class stores information about a DNS SRV record.
The QDnsTextRecord class stores information about a DNS TXT record.
The QDnsTlsAssociationRecord class stores information about a DNS TLSA record.
CertificateUsage
This enumeration contains valid values for the certificate usage field of TLS Association queries.
Selector
This enumeration contains valid values for the selector field of TLS Association queries.
MatchingType
This enumeration contains valid values for the matching type field of TLS Association queries.
The QHostAddress class provides an IP address.
bool isNull() const
Returns true if this host address is not valid for any host or interface.
NetworkLayerProtocol protocol() const
Returns the network layer protocol of the host address.
void setError(NetworkError errorCode, const QString &errorString)
Sets the error condition to be errorCode.
\macro QT_RESTRICTED_CAST_FROM_ASCII
static constexpr qsizetype PreallocatedSize
QCache< int, Employee > cache
[0]
QSet< QString >::iterator it
void qErrnoWarning(const char *msg,...)
Combined button and popup list for selecting options.
DBusConnection const char DBusError * error
static QString header(const QString &name)
static int sendStandardDns(QDnsLookupReply *reply, res_state state, QSpan< unsigned char > qbuffer, ReplyBuffer &buffer, const QHostAddress &nameserver, quint16 port)
static bool applyNameServer(res_state state, const QHostAddress &nameserver, quint16 port)
std::array< unsigned char,(QueryBufferSize+15)/16 *16 > QueryBuffer
static constexpr qsizetype QueryBufferSize
static int prepareQueryBuffer(res_state state, QueryBuffer &buffer, const char *label, ns_rcode type)
static constexpr unsigned char Edns0Record[]
bool setIpv6NameServer(State *state, EnableIfIPv6< sizeof(std::declval< State >()._u._ext.nsaddrs) !=0 > addr, quint16 port)
std::enable_if_t< Condition, const QHostAddress * > EnableIfIPv6
void setNsMap(T &ext, std::enable_if_t< sizeof(T::nsmap) !=0, uint16_t > v)
Q_DECL_COLD_FUNCTION Q_CORE_EXPORT QString qt_error_string(int errorCode=-1)
GLsizei const GLfloat * v
[13]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint GLenum GLsizei length
GLuint GLuint GLfloat weight
GLuint GLsizei const GLchar * label
[43]
GLenum GLuint GLintptr offset
GLsizeiptr const void GLenum usage
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
#define QT_REQUIRE_CONFIG(feature)
#define Q_DECLARE_TYPEINFO(TYPE, FLAGS)
Q_CHECK_PTR(a=new int[80])
QFileSelector selector
[1]