From 633ee99d0be3bc7c9eb41fa130ff40f0c2dd9fe8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Mon, 14 Apr 2025 13:48:06 +0200 Subject: [PATCH] NetworkDiscovery: Fix localhost lookup and prevent usage of IPv6 on host lookup --- .../network/networkdevicediscoveryimpl.cpp | 60 +++++++++++-------- .../network/networkdevicediscoveryimpl.h | 2 - libnymea/network/ping.cpp | 26 ++++++-- 3 files changed, 55 insertions(+), 33 deletions(-) diff --git a/libnymea-core/hardware/network/networkdevicediscoveryimpl.cpp b/libnymea-core/hardware/network/networkdevicediscoveryimpl.cpp index ada5477b..20252018 100644 --- a/libnymea-core/hardware/network/networkdevicediscoveryimpl.cpp +++ b/libnymea-core/hardware/network/networkdevicediscoveryimpl.cpp @@ -274,32 +274,37 @@ NetworkDeviceMonitor *NetworkDeviceDiscoveryImpl::registerMonitor(Thing *thing) connect(reply, &NetworkDeviceDiscoveryReply::finished, reply, &NetworkDeviceDiscoveryReply::deleteLater); } - // Find and set the network device info - for (int i = 0; i < m_networkInfoCache.count(); i++) { - const NetworkDeviceInfo networkDeviceInfo = m_networkInfoCache.at(i); + if (address == QHostAddress::LocalHost || hostName == "localhost") { + // Special case, we create for localhost a networkdevice info, since we are not discovering localhost + internalMonitor->setNetworkDeviceInfo(NetworkDeviceInfo(QHostAddress("127.0.0.1"))); + } else { + // Find and set the network device info + for (int i = 0; i < m_networkInfoCache.count(); i++) { + const NetworkDeviceInfo networkDeviceInfo = m_networkInfoCache.at(i); - switch (internalMonitor->monitorMode()) { - case NetworkDeviceInfo::MonitorModeMac: - // Search the unique mac address - if (networkDeviceInfo.macAddressInfos().hasMacAddress(internalMonitor->macAddress())) { - qCDebug(dcNetworkDeviceDiscovery()) << "MAC monitor:" << networkDeviceInfo; - internalMonitor->setNetworkDeviceInfo(networkDeviceInfo); + switch (internalMonitor->monitorMode()) { + case NetworkDeviceInfo::MonitorModeMac: + // Search the unique mac address + if (networkDeviceInfo.macAddressInfos().hasMacAddress(internalMonitor->macAddress())) { + qCDebug(dcNetworkDeviceDiscovery()) << "MAC monitor:" << networkDeviceInfo; + internalMonitor->setNetworkDeviceInfo(networkDeviceInfo); + } + break; + case NetworkDeviceInfo::MonitorModeHostName: + // Search the hostname in the cache + if (networkDeviceInfo.hostName() == internalMonitor->hostName()) { + qCDebug(dcNetworkDeviceDiscovery()) << "Host name monitor:" << networkDeviceInfo; + internalMonitor->setNetworkDeviceInfo(networkDeviceInfo); + } + break; + case NetworkDeviceInfo::MonitorModeIp: + // Search the IP in the cache + if (networkDeviceInfo.address() == internalMonitor->address()) { + qCDebug(dcNetworkDeviceDiscovery()) << "IP monitor:" << networkDeviceInfo; + internalMonitor->setNetworkDeviceInfo(networkDeviceInfo); + } + break; } - break; - case NetworkDeviceInfo::MonitorModeHostName: - // Search the hostname in the cache - if (networkDeviceInfo.hostName() == internalMonitor->hostName()) { - qCDebug(dcNetworkDeviceDiscovery()) << "Host name monitor:" << networkDeviceInfo; - internalMonitor->setNetworkDeviceInfo(networkDeviceInfo); - } - break; - case NetworkDeviceInfo::MonitorModeIp: - // Search the IP in the cache - if (networkDeviceInfo.address() == internalMonitor->address()) { - qCDebug(dcNetworkDeviceDiscovery()) << "IP monitor:" << networkDeviceInfo; - internalMonitor->setNetworkDeviceInfo(networkDeviceInfo); - } - break; } } @@ -609,6 +614,11 @@ void NetworkDeviceDiscoveryImpl::loadNetworkDeviceCache() qCInfo(dcNetworkDeviceDiscovery()) << "Loaded" << m_networkInfoCache.count() << "network device infos from cache."; + // Add the localhost + NetworkDeviceInfo localhostInfo(QHostAddress::LocalHost); + localhostInfo.setHostName("localhost"); + m_networkInfoCache.append(localhostInfo); + // We just did some housekeeping while loading from the cache m_lastCacheHousekeeping = QDateTime::currentDateTime(); } @@ -630,7 +640,7 @@ void NetworkDeviceDiscoveryImpl::removeFromNetworkDeviceCache(const QHostAddress void NetworkDeviceDiscoveryImpl::saveNetworkDeviceCache(const NetworkDeviceInfo &deviceInfo) { - if (!deviceInfo.isValid() || !deviceInfo.isComplete()) + if (!deviceInfo.isValid() || !deviceInfo.isComplete() || deviceInfo.address() == QHostAddress::LocalHost) return; m_cacheSettings->beginGroup("NetworkDeviceInfos"); diff --git a/libnymea-core/hardware/network/networkdevicediscoveryimpl.h b/libnymea-core/hardware/network/networkdevicediscoveryimpl.h index 339fda87..0d469b22 100644 --- a/libnymea-core/hardware/network/networkdevicediscoveryimpl.h +++ b/libnymea-core/hardware/network/networkdevicediscoveryimpl.h @@ -139,8 +139,6 @@ private: void processArpTraffic(const QNetworkInterface &interface, const QHostAddress &address, const MacAddress &macAddress); - void testPingMonitor(NetworkDeviceMonitorImpl *monitor); - // Time helpers bool longerAgoThan(const QDateTime &dateTime, uint minutes); QDateTime convertMinuteBased(const QDateTime &dateTime = QDateTime()); diff --git a/libnymea/network/ping.cpp b/libnymea/network/ping.cpp index 94071503..43bd394c 100644 --- a/libnymea/network/ping.cpp +++ b/libnymea/network/ping.cpp @@ -162,7 +162,9 @@ void Ping::sendNextReply() return; m_currentReply = m_replyQueue.dequeue(); - qCDebug(dcPing()).nospace().noquote() << "Send next reply " << m_currentReply->targetHostAddress().toString() << " ID: " << QString("0x%1").arg(m_currentReply->requestId(), 4, 16, QChar('0')) << ", " << m_replyQueue.count() << "left in queue"; + qCDebug(dcPing()).nospace().noquote() << "Send next reply " << m_currentReply->targetHostAddress().toString() + << " ID: " << QString("0x%1").arg(m_currentReply->requestId(), 4, 16, QChar('0')) + << ", " << m_replyQueue.count() << " left in queue"; m_queueTimer->start(); QTimer::singleShot(0, this, [=]() { if (!m_currentReply) @@ -195,8 +197,6 @@ void Ping::performPing(PingReply *reply) pingAddress.sin_port = 0; pingAddress.sin_addr.s_addr = *(long*)hostname->h_addr; - QHostAddress targetHostAddress = QHostAddress(qFromBigEndian(pingAddress.sin_addr.s_addr)); - // Build the ICMP echo request packet struct icmpPacket requestPacket; memset(&requestPacket, 0, sizeof(requestPacket)); @@ -593,9 +593,23 @@ void Ping::onHostLookupFinished(const QHostInfo &info) qCWarning(dcPing()) << "Looked up address finished succesfully but there are no addresses available for" << info.hostName(); pingError = PingReply::ErrorHostNameNotFound; } else { - reply->m_targetHostAddress = info.addresses().first(); - reply->m_networkInterface = NetworkUtils::getInterfaceForHostaddress(reply->targetHostAddress()); - pingError = PingReply::ErrorNoError; + QHostAddress targetHostAddress; + foreach (const QHostAddress &lookedUpAddress, info.addresses()) { + // Select the first valid IPv4 address, skip IPv6 + if (!lookedUpAddress.isNull() && lookedUpAddress.protocol() == QAbstractSocket::IPv4Protocol) { + targetHostAddress = lookedUpAddress; + break; + } + } + + if (targetHostAddress.isNull()) { + qCDebug(dcPing()) << "No IPv4 address found in looked up addresses:" << reply->hostName() << info.addresses(); + pingError = PingReply::ErrorHostNameNotFound; + } else { + reply->m_targetHostAddress = targetHostAddress; + reply->m_networkInterface = NetworkUtils::getInterfaceForHostaddress(reply->targetHostAddress()); + pingError = PingReply::ErrorNoError; + } } break; case QHostInfo::HostNotFound: