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+
503620QPair<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