Skip to content

Commit 498607c

Browse files
committed
Add collecting dns from interface settings on Linux
1 parent cd03e11 commit 498607c

File tree

1 file changed

+135
-1
lines changed

1 file changed

+135
-1
lines changed

client/core/networkUtilities.cpp

Lines changed: 135 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,15 @@
3030
#include <QDBusMessage>
3131
#include <QDBusReply>
3232
#include <QDBusArgument>
33+
#include <QDBusObjectPath>
3334
#include <QVariant>
35+
#include <QVariantMap>
3436
#include <QFile>
3537
#include <QTextStream>
38+
#include <QNetworkInterface>
39+
#include <algorithm>
40+
#include <climits>
41+
#include <limits>
3642
#include "platforms/linux/daemon/dbustypeslinux.h"
3743

3844
constexpr const char* DBUS_RESOLVE_SERVICE = "org.freedesktop.resolve1";
@@ -500,6 +506,117 @@ QString NetworkUtilities::getGatewayAndIface()
500506
#endif
501507
}
502508

509+
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
510+
namespace {
511+
struct LinkInfo {
512+
int ifindex;
513+
bool defaultRoute;
514+
quint32 routeMetric;
515+
QStringList dnsServers;
516+
517+
bool operator<(const LinkInfo& other) const {
518+
// Sort by defaultRoute first (true comes first), then by routeMetric (lower is better)
519+
if (defaultRoute != other.defaultRoute) {
520+
return defaultRoute > other.defaultRoute;
521+
}
522+
return routeMetric < other.routeMetric;
523+
}
524+
};
525+
526+
QStringList extractDnsFromDbusArgument(const QDBusArgument& arg) {
527+
QStringList dnsServers;
528+
QDBusArgument dnsArg = arg;
529+
QList<DnsResolver> resolverList = qdbus_cast<QList<DnsResolver>>(dnsArg);
530+
531+
for (const auto& resolver : resolverList) {
532+
if (resolver.protocol() == QAbstractSocket::IPv4Protocol) {
533+
const QString dnsStr = resolver.toString();
534+
if (NetworkUtilities::checkIPv4Format(dnsStr) && !dnsServers.contains(dnsStr)) {
535+
dnsServers.append(dnsStr);
536+
}
537+
}
538+
}
539+
return dnsServers;
540+
}
541+
542+
QList<LinkInfo> getDnsFromInterfaces(const QDBusConnection& bus) {
543+
QList<LinkInfo> links;
544+
545+
// Get all network interfaces
546+
QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
547+
548+
for (const QNetworkInterface& iface : interfaces) {
549+
int ifindex = iface.index();
550+
if (ifindex <= 0) {
551+
continue;
552+
}
553+
554+
// Call GetLink to get the link object path
555+
QDBusMessage getLinkMsg = QDBusMessage::createMethodCall(
556+
DBUS_RESOLVE_SERVICE, DBUS_RESOLVE_PATH, DBUS_RESOLVE_MANAGER, "GetLink");
557+
getLinkMsg << ifindex;
558+
559+
QDBusReply<QDBusObjectPath> linkReply = bus.call(getLinkMsg);
560+
if (!linkReply.isValid()) {
561+
continue;
562+
}
563+
564+
QString linkPath = linkReply.value().path();
565+
566+
// Get properties from the link object
567+
QDBusMessage getPropMsg = QDBusMessage::createMethodCall(
568+
DBUS_RESOLVE_SERVICE, linkPath, DBUS_PROPERTY_INTERFACE, "GetAll");
569+
getPropMsg << QString("org.freedesktop.resolve1.Link");
570+
571+
QDBusReply<QVariantMap> propReply = bus.call(getPropMsg);
572+
if (!propReply.isValid()) {
573+
continue;
574+
}
575+
576+
QVariantMap properties = propReply.value();
577+
578+
// Check if DefaultRoute is true
579+
bool defaultRoute = properties.value("DefaultRoute").toBool();
580+
581+
// Get RouteMetric (default to maximum if not available)
582+
quint32 routeMetric = std::numeric_limits<quint32>::max();
583+
if (properties.contains("RouteMetric")) {
584+
routeMetric = properties.value("RouteMetric").toUInt();
585+
}
586+
587+
// Get DNS servers - use Get method directly for DNS property
588+
QDBusMessage getDnsMsg = QDBusMessage::createMethodCall(
589+
DBUS_RESOLVE_SERVICE, linkPath, DBUS_PROPERTY_INTERFACE, "Get");
590+
getDnsMsg << QString("org.freedesktop.resolve1.Link");
591+
getDnsMsg << QString("DNS");
592+
593+
QDBusReply<QVariant> dnsReply = bus.call(getDnsMsg);
594+
if (!dnsReply.isValid()) {
595+
continue;
596+
}
597+
598+
QVariant dnsVariant = dnsReply.value();
599+
QStringList dnsServers;
600+
if (dnsVariant.canConvert<QDBusArgument>()) {
601+
QDBusArgument dnsArg = qvariant_cast<QDBusArgument>(dnsVariant);
602+
dnsServers = extractDnsFromDbusArgument(dnsArg);
603+
}
604+
605+
if (!dnsServers.isEmpty()) {
606+
LinkInfo info;
607+
info.ifindex = ifindex;
608+
info.defaultRoute = defaultRoute;
609+
info.routeMetric = routeMetric;
610+
info.dnsServers = dnsServers;
611+
links.append(info);
612+
}
613+
}
614+
615+
return links;
616+
}
617+
}
618+
#endif
619+
503620
QPair<QString, QString> NetworkUtilities::getSystemDnsAddress()
504621
{
505622
QPair<QString, QString> result;
@@ -509,7 +626,6 @@ QPair<QString, QString> NetworkUtilities::getSystemDnsAddress()
509626
QDBusConnection bus = QDBusConnection::systemBus();
510627
if (bus.isConnected()) {
511628
// Try to get DNS from Resolve DNS property using org.freedesktop.DBus.Properties
512-
// Use the same approach as in dnsutilslinux.cpp
513629
QDBusMessage message = QDBusMessage::createMethodCall(
514630
DBUS_RESOLVE_SERVICE, DBUS_RESOLVE_PATH, DBUS_PROPERTY_INTERFACE, "Get");
515631
message << QString(DBUS_RESOLVE_MANAGER);
@@ -539,6 +655,24 @@ QPair<QString, QString> NetworkUtilities::getSystemDnsAddress()
539655
return result;
540656
}
541657
}
658+
659+
// If no global DNS, try to get DNS from interfaces
660+
QList<LinkInfo> links = getDnsFromInterfaces(bus);
661+
if (!links.isEmpty()) {
662+
// Sort by priority: DefaultRoute first, then by RouteMetric
663+
std::sort(links.begin(), links.end());
664+
665+
// Get DNS from the highest priority interface
666+
const LinkInfo& bestLink = links.first();
667+
result.first = bestLink.dnsServers.first();
668+
if (bestLink.dnsServers.size() > 1) {
669+
result.second = bestLink.dnsServers.at(1);
670+
}
671+
qDebug() << "Got DNS from interface" << bestLink.ifindex
672+
<< "DefaultRoute:" << bestLink.defaultRoute
673+
<< "RouteMetric:" << bestLink.routeMetric;
674+
return result;
675+
}
542676
}
543677

544678
// Fallback to /etc/resolv.conf

0 commit comments

Comments
 (0)