11#include <private/qnativesocketengine_p.h>
12#include <private/qtnetwork-config_p.h>
17#include <netinet/in.h>
18#include <arpa/nameser.h>
19#if __has_include(<arpa/nameser_compat.h>)
20# include <arpa/nameser_compat.h>
29# define T_OPT ns_t_opt
52 HFIXEDSZ + QFIXEDSZ + MAXCDNAME + 1 +
sizeof(
Edns0Record);
66#if QT_CONFIG(res_setservers)
71 if (!nameserver.
isNull()) {
72 union res_sockaddr_union u;
73 setSockaddr(
reinterpret_cast<sockaddr *
>(&u.sin), nameserver,
port);
74 res_setservers(
state, &u, 1);
79template <
typename T>
void setNsMap(T &
ext, std::enable_if_t<
sizeof(T::nsmap) != 0, uint16_t>
v)
92template <
bool Condition>
93using EnableIfIPv6 = std::enable_if_t<Condition, const QHostAddress *>;
95template <
typename State>
101 struct sockaddr_in6 *
ns =
state->_u._ext.nsaddrs[0];
107 ns =
static_cast<struct sockaddr_in6*
>(calloc(1,
sizeof(
struct sockaddr_in6)));
109 state->_u._ext.nsaddrs[0] =
ns;
113 state->_u._ext.nscount6 = 1;
130 state->nsaddr_list[0].sin_family = AF_UNSPEC;
133 setSockaddr(&
state->nsaddr_list[0], nameserver,
port);
142 int queryLength = res_nmkquery(
state, QUERY,
label, C_IN,
type,
nullptr, 0,
nullptr,
151 reinterpret_cast<HEADER *
>(
buffer.data())->arcount = qToBigEndian<quint16>(1);
159 std::remove_pointer_t<res_state>
state = {};
160 if (res_ninit(&
state) < 0) {
170 QDnsLookup::tr(
"IPv6 nameservers are currently not supported on this OS"));
171#ifdef QDNSLOOKUP_DEBUG
172 state.options |= RES_DEBUG;
179 return reply->makeResolverSystemError();
183 auto attemptToSend = [&]() {
184 std::memset(
buffer.data(), 0, HFIXEDSZ);
185 int responseLength = res_nsend(&
state, qbuffer.data(), queryLength,
buffer.data(),
buffer.size());
186 if (responseLength < 0) {
188 if (errno == ETIMEDOUT)
189 reply->makeTimeoutError();
191 reply->makeResolverSystemError();
193 return responseLength;
197 state.options |= RES_IGNTC;
198 int responseLength = attemptToSend();
199 if (responseLength < 0)
203 auto header =
reinterpret_cast<HEADER *
>(
buffer.data());
210 reinterpret_cast<HEADER *
>(qbuffer.data())->arcount = 0;
214 state.options |= RES_USEVC;
215 responseLength = attemptToSend();
219 QDnsLookup::tr(
"Reply was too large"));
222 if (responseLength < 0)
226 if (responseLength <
int(
sizeof(HEADER)))
227 return reply->makeInvalidReplyError();
234 unsigned char *response =
buffer.data();
240 if (
offset + 1 < responseLength) {
241 int id = ((
n & ~NS_CMPRSFLGS) << 8) | response[
offset + 1];
242 auto it = std::find_if(
cache.constBegin(),
cache.constEnd(),
243 [
id](
const QDnsCachedName &
n) { return n.code == id; });
252 char host[MAXCDNAME + 1];
253 status = dn_expand(response, response + responseLength, response +
offset,
259 reply->makeInvalidReplyError(QDnsLookup::tr(
"Could not expand domain name"));
263 if (ntohs(
header->qdcount) == 1) {
268 if (
offset + status + 4 >= responseLength)
273 if (ntohs(
header->qdcount) > 1)
274 return reply->makeInvalidReplyError();
277 const int answerCount = ntohs(
header->ancount);
279 while ((
offset < responseLength) && (answerIndex < answerCount)) {
285 if (
offset + RRFIXEDSZ > responseLength) {
290 const qint16 rrclass = qFromBigEndian<quint16>(response +
offset + 2);
291 const quint32 ttl = qFromBigEndian<quint32>(response +
offset + 4);
301 return reply->makeInvalidReplyError(QDnsLookup::tr(
"Invalid IPv4 address record"));
305 record.d->timeToLive = ttl;
310 return reply->makeInvalidReplyError(QDnsLookup::tr(
"Invalid IPv6 address record"));
313 record.d->timeToLive = ttl;
319 record.d->timeToLive = ttl;
322 return reply->makeInvalidReplyError(QDnsLookup::tr(
"Invalid canonical name record"));
327 record.d->timeToLive = ttl;
330 return reply->makeInvalidReplyError(QDnsLookup::tr(
"Invalid name server record"));
335 record.d->timeToLive = ttl;
338 return reply->makeInvalidReplyError(QDnsLookup::tr(
"Invalid pointer record"));
341 const quint16 preference = qFromBigEndian<quint16>(response +
offset);
345 record.d->preference = preference;
346 record.d->timeToLive = ttl;
348 return reply->makeInvalidReplyError(QDnsLookup::tr(
"Invalid mail exchange record"));
351 const quint16 priority = qFromBigEndian<quint16>(response +
offset);
358 record.d->priority = priority;
359 record.d->timeToLive = ttl;
362 return reply->makeInvalidReplyError(QDnsLookup::tr(
"Invalid service record"));
367 record.d->timeToLive = ttl;
370 const unsigned char length = response[
txt];
373 return reply->makeInvalidReplyError(QDnsLookup::tr(
"Invalid text record"));
static constexpr auto IPv6Protocol
QByteArray toByteArray() const
The QDnsDomainNameRecord class stores information about a domain name record.
The QDnsHostAddressRecord class stores information about a host address record.
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 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
void resize(qsizetype size)
Sets the size of the string to size characters.
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 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)
static constexpr qsizetype ReplyBufferSize
std::enable_if_t< Condition, const QHostAddress * > EnableIfIPv6
void setNsMap(T &ext, std::enable_if_t< sizeof(T::nsmap) !=0, uint16_t > v)
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
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])