Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qhostinfo_unix.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4//#define QHOSTINFO_DEBUG
5
6#include "qhostinfo_p.h"
7
8#include <qbytearray.h>
9#include <qfile.h>
10#include <qplatformdefs.h>
11#include <qurl.h>
12
13#include <sys/types.h>
14#include <netdb.h>
15#include <netinet/in.h>
16
17#if QT_CONFIG(libresolv)
18# include <resolv.h>
19#endif
20
21#ifndef _PATH_RESCONF
22# define _PATH_RESCONF "/etc/resolv.conf"
23#endif
24
26
27using namespace Qt::StringLiterals;
28
30{
31#if defined(RES_NORELOAD)
32 // If RES_NORELOAD is defined, then the libc is capable of watching
33 // /etc/resolv.conf for changes and reloading as necessary. So accept
34 // whatever is configured.
35 return;
36#elif defined(Q_OS_DARWIN)
37 // Apple's libsystem_info.dylib:getaddrinfo() uses the
38 // libsystem_dnssd.dylib to resolve hostnames. Using res_init() has no
39 // effect on it and is thread-unsafe.
40 return;
41#elif defined(Q_OS_FREEBSD)
42 // FreeBSD automatically refreshes:
43 // https://github.com/freebsd/freebsd-src/blob/b3fe5d932264445cbf9a1c4eab01afb6179b499b/lib/libc/resolv/res_state.c#L69
44 return;
45#elif defined(Q_OS_OPENBSD)
46 // OpenBSD automatically refreshes:
47 // https://github.com/ligurio/openbsd-src/blob/b1ce0da17da254cc15b8aff25b3d55d3c7a82cec/lib/libc/asr/asr.c#L367
48 return;
49#elif defined(Q_OS_QNX)
50 // res_init() is not thread-safe; executing it leads to state corruption.
51 // Whether it reloads resolv.conf on its own is unknown.
52 return;
53#endif
54
55#if QT_CONFIG(libresolv)
56 // OSes known or thought to reach here: AIX, NetBSD, Solaris,
57 // Linux with MUSL (though res_init() does nothing and is unnecessary)
58
59 Q_CONSTINIT static QT_STATBUF lastStat = {};
60 Q_CONSTINIT static QBasicMutex mutex = {};
61 if (QT_STATBUF st; QT_STAT(_PATH_RESCONF, &st) == 0) {
62 QMutexLocker locker(&mutex);
63 bool refresh = false;
64 if ((_res.options & RES_INIT) == 0)
65 refresh = true;
66 else if (lastStat.st_ctime != st.st_ctime)
67 refresh = true; // file was updated
68 else if (lastStat.st_dev != st.st_dev || lastStat.st_ino != st.st_ino)
69 refresh = true; // file was replaced
70 if (refresh) {
71 lastStat = st;
72 res_init();
73 }
74 }
75#endif
76}
77
79{
81
82#if defined(QHOSTINFO_DEBUG)
83 qDebug("QHostInfoAgent::fromName(%s) looking up...",
84 hostName.toLatin1().constData());
85#endif
86
88
90 if (address.setAddress(hostName))
91 return reverseLookup(address);
92
93 return lookup(hostName);
94}
95
97{
98#if QT_CONFIG(libresolv)
99 auto domainNameFromRes = [](res_state r) {
100 QString domainName;
101 if (r->defdname[0])
102 domainName = QUrl::fromAce(r->defdname);
103 if (domainName.isEmpty())
104 domainName = QUrl::fromAce(r->dnsrch[0]);
105 return domainName;
106 };
107 std::remove_pointer_t<res_state> state = {};
108 if (res_ninit(&state) == 0) {
109 // using thread-safe version
110 auto guard = qScopeGuard([&] { res_nclose(&state); });
111 return domainNameFromRes(&state);
112 }
113
114 // using thread-unsafe version
116 return domainNameFromRes(&_res);
117#endif // !QT_CONFIG(libresolv)
118
119 // nothing worked, try doing it by ourselves:
120 QFile resolvconf;
121 resolvconf.setFileName(_PATH_RESCONF ""_L1);
122 if (!resolvconf.open(QIODevice::ReadOnly))
123 return QString(); // failure
124
125 QString domainName;
126 while (!resolvconf.atEnd()) {
127 const QByteArray lineArray = resolvconf.readLine();
129 constexpr QByteArrayView domainWithSpace = "domain ";
130 if (line.startsWith(domainWithSpace))
131 return QUrl::fromAce(line.mid(domainWithSpace.size()).trimmed().toByteArray());
132
133 // in case there's no "domain" line, fall back to the first "search" entry
134 constexpr QByteArrayView searchWithSpace = "search ";
135 if (domainName.isEmpty() && line.startsWith(searchWithSpace)) {
136 QByteArrayView searchDomain = line.mid(searchWithSpace.size()).trimmed();
137 int pos = searchDomain.indexOf(' ');
138 if (pos != -1)
139 searchDomain.truncate(pos);
140 domainName = QUrl::fromAce(searchDomain.toByteArray());
141 }
142 }
143
144 // return the fallen-back-to searched domain
145 return domainName;
146}
147
QByteArrayView trimmed() const noexcept
\inmodule QtCore
Definition qbytearray.h:57
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:124
\inmodule QtCore
Definition qfile.h:93
void setFileName(const QString &name)
Sets the name of the file.
Definition qfile.cpp:302
The QHostAddress class provides an IP address.
static QHostInfo lookup(const QString &hostName)
static QHostInfo reverseLookup(const QHostAddress &address)
static QHostInfo fromName(const QString &hostName)
The QHostInfo class provides static functions for host name lookups.
Definition qhostinfo.h:19
static QString localDomainName()
Returns the DNS domain of this machine.
\inmodule QtCore
Definition qmutex.h:313
\inmodule QtCore
Definition qmutex.h:281
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QByteArray toLatin1() const &
Definition qstring.h:630
qsizetype indexOf(QLatin1StringView s, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.cpp:4517
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition qstring.cpp:5455
QString mid(qsizetype position, qsizetype n=-1) const &
Definition qstring.cpp:5300
QString trimmed() const &
Definition qstring.h:447
static QString fromAce(const QByteArray &domain, AceProcessingOptions options={})
Definition qurl.cpp:3041
else opt state
[0]
Combined button and popup list for selecting options.
static void maybeRefreshResolver()
#define _PATH_RESCONF
#define qDebug
[1]
Definition qlogging.h:164
GLboolean r
[2]
GLuint GLuint64EXT address
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
Definition qscopeguard.h:60
QMutex mutex
[2]