Qt 6.x
The Qt SDK
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#include <resolv.h>
17
18#ifndef _PATH_RESCONF
19# define _PATH_RESCONF "/etc/resolv.conf"
20#endif
21
23
24using namespace Qt::StringLiterals;
25
27{
28#if defined(RES_NORELOAD)
29 // If RES_NORELOAD is defined, then the libc is capable of watching
30 // /etc/resolv.conf for changes and reloading as necessary. So accept
31 // whatever is configured.
32 return;
33#elif defined(Q_OS_DARWIN)
34 // Apple's libsystem_info.dylib:getaddrinfo() uses the
35 // libsystem_dnssd.dylib to resolve hostnames. Using res_init() has no
36 // effect on it and is thread-unsafe.
37 return;
38#elif defined(Q_OS_FREEBSD)
39 // FreeBSD automatically refreshes:
40 // https://github.com/freebsd/freebsd-src/blob/b3fe5d932264445cbf9a1c4eab01afb6179b499b/lib/libc/resolv/res_state.c#L69
41 return;
42#elif defined(Q_OS_OPENBSD)
43 // OpenBSD automatically refreshes:
44 // https://github.com/ligurio/openbsd-src/blob/b1ce0da17da254cc15b8aff25b3d55d3c7a82cec/lib/libc/asr/asr.c#L367
45 return;
46#elif defined(Q_OS_QNX)
47 // res_init() is not thread-safe; executing it leads to state corruption.
48 // Whether it reloads resolv.conf on its own is unknown.
49 return;
50#endif
51
52#if QT_CONFIG(libresolv)
53 // OSes known or thought to reach here: AIX, NetBSD, Solaris,
54 // Linux with MUSL (though res_init() does nothing and is unnecessary)
55
56 Q_CONSTINIT static QT_STATBUF lastStat = {};
57 Q_CONSTINIT static QBasicMutex mutex = {};
58 if (QT_STATBUF st; QT_STAT(_PATH_RESCONF, &st) == 0) {
59 QMutexLocker locker(&mutex);
60 bool refresh = false;
61 if ((_res.options & RES_INIT) == 0)
62 refresh = true;
63 else if (lastStat.st_ctime != st.st_ctime)
64 refresh = true; // file was updated
65 else if (lastStat.st_dev != st.st_dev || lastStat.st_ino != st.st_ino)
66 refresh = true; // file was replaced
67 if (refresh) {
68 lastStat = st;
69 res_init();
70 }
71 }
72#endif
73}
74
76{
78
79#if defined(QHOSTINFO_DEBUG)
80 qDebug("QHostInfoAgent::fromName(%s) looking up...",
81 hostName.toLatin1().constData());
82#endif
83
85
87 if (address.setAddress(hostName))
88 return reverseLookup(address);
89
90 return lookup(hostName);
91}
92
94{
95#if QT_CONFIG(libresolv)
96 auto domainNameFromRes = [](res_state r) {
97 QString domainName;
98 if (r->defdname[0])
99 domainName = QUrl::fromAce(r->defdname);
100 if (domainName.isEmpty())
101 domainName = QUrl::fromAce(r->dnsrch[0]);
102 return domainName;
103 };
104 std::remove_pointer_t<res_state> state = {};
105 if (res_ninit(&state) == 0) {
106 // using thread-safe version
107 auto guard = qScopeGuard([&] { res_nclose(&state); });
108 return domainNameFromRes(&state);
109 }
110
111 // using thread-unsafe version
113 return domainNameFromRes(&_res);
114#endif // !QT_CONFIG(libresolv)
115
116 // nothing worked, try doing it by ourselves:
117 QFile resolvconf;
118 resolvconf.setFileName(_PATH_RESCONF ""_L1);
119 if (!resolvconf.open(QIODevice::ReadOnly))
120 return QString(); // failure
121
122 QString domainName;
123 while (!resolvconf.atEnd()) {
124 QByteArray line = resolvconf.readLine().trimmed();
125 if (line.startsWith("domain "))
126 return QUrl::fromAce(line.mid(sizeof "domain " - 1).trimmed());
127
128 // in case there's no "domain" line, fall back to the first "search" entry
129 if (domainName.isEmpty() && line.startsWith("search ")) {
130 QByteArray searchDomain = line.mid(sizeof "search " - 1).trimmed();
131 int pos = searchDomain.indexOf(' ');
132 if (pos != -1)
133 searchDomain.truncate(pos);
134 domainName = QUrl::fromAce(searchDomain);
135 }
136 }
137
138 // return the fallen-back-to searched domain
139 return domainName;
140}
141
\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:122
qsizetype indexOf(char c, qsizetype from=0) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
void truncate(qsizetype pos)
Truncates the byte array at index position pos.
bool atEnd() const override
Returns true if the end of the file has been reached; otherwise returns false.
\inmodule QtCore
Definition qfile.h:93
bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:881
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.
qint64 readLine(char *data, qint64 maxlen)
This function reads a line of ASCII characters from the device, up to a maximum of maxSize - 1 bytes,...
\inmodule QtCore
Definition qmutex.h:317
\inmodule QtCore
Definition qmutex.h:285
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
QByteArray toLatin1() const &
Definition qstring.h:559
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:5299
QString mid(qsizetype position, qsizetype n=-1) const
Returns a string that contains n characters of this string, starting at the specified position index.
Definition qstring.cpp:5204
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
QString trimmed() const &
Definition qstring.h:380
static QString fromAce(const QByteArray &domain, AceProcessingOptions options={})
Definition qurl.cpp:3038
else opt state
[0]
Combined button and popup list for selecting options.
static void maybeRefreshResolver()
#define _PATH_RESCONF
#define qDebug
[1]
Definition qlogging.h:160
GLboolean r
[2]
GLuint GLuint64EXT address
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
Definition qscopeguard.h:60
QMutex mutex
[2]