fix: add support system with nscd service

This commit is contained in:
NickVs2015
2026-04-10 23:08:32 +03:00
parent 37d2b8716d
commit 9166e17a23
3 changed files with 58 additions and 49 deletions
+48 -24
View File
@@ -1,6 +1,3 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "dnsutilslinux.h" #include "dnsutilslinux.h"
@@ -26,7 +23,6 @@ DnsUtilsLinux::~DnsUtilsLinux() {
logger.debug() << "DnsUtilsLinux destroyed."; logger.debug() << "DnsUtilsLinux destroyed.";
} }
void DnsUtilsLinux::writeResolvConf(const QList<QHostAddress>& resolvers) { void DnsUtilsLinux::writeResolvConf(const QList<QHostAddress>& resolvers) {
if (resolvers.isEmpty()) return; if (resolvers.isEmpty()) return;
@@ -38,16 +34,28 @@ void DnsUtilsLinux::writeResolvConf(const QList<QHostAddress>& resolvers) {
m_resolvConfOriginal = fi.symLinkTarget(); m_resolvConfOriginal = fi.symLinkTarget();
logger.debug() << "Saved resolv.conf symlink target:" logger.debug() << "Saved resolv.conf symlink target:"
<< m_resolvConfOriginal; << m_resolvConfOriginal;
if (!m_stateFilePath.isEmpty()) {
QFile sf(m_stateFilePath);
if (sf.open(QIODevice::WriteOnly | QIODevice::Text))
sf.write(m_resolvConfOriginal.toUtf8());
}
} else { } else {
m_resolvConfOriginal = QStringLiteral("__file__"); QFile orig(kPath);
logger.debug() if (orig.open(QIODevice::ReadOnly | QIODevice::Text)) {
<< "resolv.conf is a regular file; will restore stub on disconnect"; QByteArray content = orig.readAll();
} orig.close();
m_resolvConfOriginal = QStringLiteral("__file__");
if (!m_stateFilePath.isEmpty()) { logger.debug() << "resolv.conf is a regular file; saved content for restore";
QFile sf(m_stateFilePath); if (!m_stateFilePath.isEmpty()) {
if (sf.open(QIODevice::WriteOnly | QIODevice::Text)) QFile sf(m_stateFilePath);
sf.write(m_resolvConfOriginal.toUtf8()); if (sf.open(QIODevice::WriteOnly | QIODevice::Text)) {
sf.write("__file__:");
sf.write(content);
}
}
} else {
m_resolvConfOriginal = QStringLiteral("__file__");
}
} }
} }
@@ -81,16 +89,25 @@ void DnsUtilsLinux::restoreResolvConf() {
QFile::remove(m_stateFilePath); QFile::remove(m_stateFilePath);
static const char* kPath = "/etc/resolv.conf"; static const char* kPath = "/etc/resolv.conf";
static const char* kStub = "/run/systemd/resolve/stub-resolv.conf";
QFile::remove(kPath); QFile::remove(kPath);
const QString target = (original == QStringLiteral("__file__")) if (original == QStringLiteral("__file__")) {
? QLatin1String(kStub) if (!m_resolvConfSavedContent.isEmpty()) {
: original; QFile f(kPath);
if (f.open(QIODevice::WriteOnly | QIODevice::Text)) {
QFile::link(target, kPath); f.write(m_resolvConfSavedContent.toUtf8());
logger.debug() << "Restored resolv.conf symlink to" << target; logger.debug() << "Restored resolv.conf from saved content";
}
m_resolvConfSavedContent.clear();
} else if (QFile::exists(QStringLiteral("/run/systemd/resolve/stub-resolv.conf"))) {
QFile::link(QStringLiteral("/run/systemd/resolve/stub-resolv.conf"), kPath);
logger.debug() << "Restored resolv.conf symlink to stub-resolv.conf";
}
} else {
QFile::link(original, kPath);
logger.debug() << "Restored resolv.conf symlink to" << original;
}
} }
bool DnsUtilsLinux::updateResolvers(const QString& ifname, bool DnsUtilsLinux::updateResolvers(const QString& ifname,
@@ -114,6 +131,7 @@ bool DnsUtilsLinux::restoreResolvers() {
if (!m_stateFilePath.isEmpty()) { if (!m_stateFilePath.isEmpty()) {
candidates << m_stateFilePath; candidates << m_stateFilePath;
} else { } else {
QDir runDir(QStringLiteral("/run")); QDir runDir(QStringLiteral("/run"));
for (const QString& name : runDir.entryList( for (const QString& name : runDir.entryList(
{QStringLiteral("amnezia-dns-*")}, QDir::Files)) { {QStringLiteral("amnezia-dns-*")}, QDir::Files)) {
@@ -122,10 +140,16 @@ bool DnsUtilsLinux::restoreResolvers() {
} }
for (const QString& path : candidates) { for (const QString& path : candidates) {
QFile sf(path); QFile sf(path);
if (sf.open(QIODevice::ReadOnly | QIODevice::Text)) { if (sf.open(QIODevice::ReadOnly)) {
m_resolvConfOriginal = QString::fromUtf8(sf.readAll()).trimmed(); QByteArray data = sf.readAll();
m_stateFilePath = path;
sf.close(); sf.close();
m_stateFilePath = path;
if (data.startsWith("__file__:")) {
m_resolvConfOriginal = QStringLiteral("__file__");
m_resolvConfSavedContent = QString::fromUtf8(data.mid(9));
} else {
m_resolvConfOriginal = QString::fromUtf8(data).trimmed();
}
logger.debug() << "Recovered DNS original from" << path << ":" logger.debug() << "Recovered DNS original from" << path << ":"
<< m_resolvConfOriginal; << m_resolvConfOriginal;
break; break;
@@ -136,7 +160,7 @@ bool DnsUtilsLinux::restoreResolvers() {
const bool hadDnsState = !m_resolvConfOriginal.isEmpty(); const bool hadDnsState = !m_resolvConfOriginal.isEmpty();
restoreResolvConf(); restoreResolvConf();
if (hadDnsState) { if (hadDnsState && QFile::exists(QStringLiteral("/run/systemd/resolve"))) {
QProcess::startDetached("systemctl", {"restart", "systemd-resolved"}); QProcess::startDetached("systemctl", {"restart", "systemd-resolved"});
} }
@@ -1,6 +1,3 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef DNSUTILSLINUX_H #ifndef DNSUTILSLINUX_H
#define DNSUTILSLINUX_H #define DNSUTILSLINUX_H
@@ -27,8 +24,10 @@ class DnsUtilsLinux final : public DnsUtils {
void restoreResolvConf(); void restoreResolvConf();
private: private:
QString m_resolvConfOriginal; QString m_resolvConfOriginal;
QString m_resolvConfSavedContent;
QString m_stateFilePath; QString m_stateFilePath;
}; };
#endif // DNSUTILSLINUX_H #endif
+7 -21
View File
@@ -41,15 +41,14 @@ bool RouterLinux::routeAdd(const QString &ipWithSubnet, const QString &gw, const
struct rtentry route; struct rtentry route;
memset(&route, 0, sizeof( route )); memset(&route, 0, sizeof( route ));
// set gateway
((struct sockaddr_in *)&route.rt_gateway)->sin_family = AF_INET; ((struct sockaddr_in *)&route.rt_gateway)->sin_family = AF_INET;
((struct sockaddr_in *)&route.rt_gateway)->sin_addr.s_addr = inet_addr(gw.toStdString().c_str()); ((struct sockaddr_in *)&route.rt_gateway)->sin_addr.s_addr = inet_addr(gw.toStdString().c_str());
((struct sockaddr_in *)&route.rt_gateway)->sin_port = 0; ((struct sockaddr_in *)&route.rt_gateway)->sin_port = 0;
// set host rejecting
((struct sockaddr_in *)&route.rt_dst)->sin_family = AF_INET; ((struct sockaddr_in *)&route.rt_dst)->sin_family = AF_INET;
((struct sockaddr_in *)&route.rt_dst)->sin_addr.s_addr = inet_addr(ip.toStdString().c_str()); ((struct sockaddr_in *)&route.rt_dst)->sin_addr.s_addr = inet_addr(ip.toStdString().c_str());
((struct sockaddr_in *)&route.rt_dst)->sin_port = 0; ((struct sockaddr_in *)&route.rt_dst)->sin_port = 0;
// set mask
((struct sockaddr_in *)&route.rt_genmask)->sin_family = AF_INET; ((struct sockaddr_in *)&route.rt_genmask)->sin_family = AF_INET;
((struct sockaddr_in *)&route.rt_genmask)->sin_addr.s_addr = inet_addr(mask.toStdString().c_str()); ((struct sockaddr_in *)&route.rt_genmask)->sin_addr.s_addr = inet_addr(mask.toStdString().c_str());
((struct sockaddr_in *)&route.rt_genmask)->sin_port = 0; ((struct sockaddr_in *)&route.rt_genmask)->sin_port = 0;
@@ -116,22 +115,20 @@ bool RouterLinux::routeDelete(const QString &ipWithSubnet, const QString &gw, co
struct rtentry route; struct rtentry route;
memset(&route, 0, sizeof( route )); memset(&route, 0, sizeof( route ));
// set gateway
((struct sockaddr_in *)&route.rt_gateway)->sin_family = AF_INET; ((struct sockaddr_in *)&route.rt_gateway)->sin_family = AF_INET;
((struct sockaddr_in *)&route.rt_gateway)->sin_addr.s_addr = inet_addr(gw.toStdString().c_str()); ((struct sockaddr_in *)&route.rt_gateway)->sin_addr.s_addr = inet_addr(gw.toStdString().c_str());
((struct sockaddr_in *)&route.rt_gateway)->sin_port = 0; ((struct sockaddr_in *)&route.rt_gateway)->sin_port = 0;
// set host rejecting
((struct sockaddr_in *)&route.rt_dst)->sin_family = AF_INET; ((struct sockaddr_in *)&route.rt_dst)->sin_family = AF_INET;
((struct sockaddr_in *)&route.rt_dst)->sin_addr.s_addr = inet_addr(ip.toStdString().c_str()); ((struct sockaddr_in *)&route.rt_dst)->sin_addr.s_addr = inet_addr(ip.toStdString().c_str());
((struct sockaddr_in *)&route.rt_dst)->sin_port = 0; ((struct sockaddr_in *)&route.rt_dst)->sin_port = 0;
// set mask
((struct sockaddr_in *)&route.rt_genmask)->sin_family = AF_INET; ((struct sockaddr_in *)&route.rt_genmask)->sin_family = AF_INET;
((struct sockaddr_in *)&route.rt_genmask)->sin_addr.s_addr = inet_addr(mask.toStdString().c_str()); ((struct sockaddr_in *)&route.rt_genmask)->sin_addr.s_addr = inet_addr(mask.toStdString().c_str());
((struct sockaddr_in *)&route.rt_genmask)->sin_port = 0; ((struct sockaddr_in *)&route.rt_genmask)->sin_port = 0;
route.rt_flags = RTF_UP | RTF_GATEWAY; route.rt_flags = RTF_UP | RTF_GATEWAY;
route.rt_metric = 0; route.rt_metric = 0;
//route.rt_dev = "ens33";
if (ioctl(sock, SIOCDELRT, &route) < 0) if (ioctl(sock, SIOCDELRT, &route) < 0)
{ {
@@ -164,21 +161,10 @@ bool RouterLinux::isServiceActive(const QString &serviceName) {
bool RouterLinux::flushDns() bool RouterLinux::flushDns()
{ {
//check what the dns manager use
if (isServiceActive("nscd.service")) { if (isServiceActive("nscd.service")) {
qDebug() << "Restarting nscd.service"; qDebug() << "Flushing nscd cache";
QProcess p; QProcess::startDetached("nscd", { "--invalidate=hosts" });
p.setProcessChannelMode(QProcess::MergedChannels);
p.start("systemctl", { "restart", "nscd" });
if (!p.waitForFinished(3000)) {
qDebug() << "nscd restart timed out, killing process";
p.kill();
p.waitForFinished(500);
}
QByteArray output(p.readAll());
if (!output.isEmpty())
qDebug().noquote() << "OUTPUT systemctl restart nscd: " + output;
qDebug().noquote() << "Flush dns completed";
return true; return true;
} else if (isServiceActive("systemd-resolved.service")) { } else if (isServiceActive("systemd-resolved.service")) {
qDebug() << "Flushing systemd-resolved cache"; qDebug() << "Flushing systemd-resolved cache";