NetworkDeviceDiscovery: Skip duplicated discovery if there are multiple network interfaces connected to the same network
This commit is contained in:
parent
da6d7b8efe
commit
285abcdd36
@ -29,10 +29,11 @@
|
|||||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
#include "networkdevicediscoveryimpl.h"
|
#include "networkdevicediscoveryimpl.h"
|
||||||
|
|
||||||
#include "nymeasettings.h"
|
#include "nymeasettings.h"
|
||||||
#include "loggingcategories.h"
|
#include "loggingcategories.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#include <network/ping.h>
|
#include <network/ping.h>
|
||||||
#include <network/arpsocket.h>
|
#include <network/arpsocket.h>
|
||||||
#include <network/networkutils.h>
|
#include <network/networkutils.h>
|
||||||
@ -339,6 +340,9 @@ void NetworkDeviceDiscoveryImpl::setEnabled(bool enabled)
|
|||||||
|
|
||||||
void NetworkDeviceDiscoveryImpl::pingAllNetworkDevices()
|
void NetworkDeviceDiscoveryImpl::pingAllNetworkDevices()
|
||||||
{
|
{
|
||||||
|
QList<QHostAddress> ownAddresses;
|
||||||
|
QList<TargetNetwork> targetNetworks;
|
||||||
|
|
||||||
qCDebug(dcNetworkDeviceDiscovery()) << "Starting ping for all network devices...";
|
qCDebug(dcNetworkDeviceDiscovery()) << "Starting ping for all network devices...";
|
||||||
foreach (const QNetworkInterface &networkInterface, QNetworkInterface::allInterfaces()) {
|
foreach (const QNetworkInterface &networkInterface, QNetworkInterface::allInterfaces()) {
|
||||||
if (networkInterface.flags().testFlag(QNetworkInterface::IsLoopBack))
|
if (networkInterface.flags().testFlag(QNetworkInterface::IsLoopBack))
|
||||||
@ -352,56 +356,88 @@ void NetworkDeviceDiscoveryImpl::pingAllNetworkDevices()
|
|||||||
|
|
||||||
qCDebug(dcNetworkDeviceDiscovery()) << "Verifying network interface" << networkInterface.name() << networkInterface.hardwareAddress() << "...";
|
qCDebug(dcNetworkDeviceDiscovery()) << "Verifying network interface" << networkInterface.name() << networkInterface.hardwareAddress() << "...";
|
||||||
foreach (const QNetworkAddressEntry &entry, networkInterface.addressEntries()) {
|
foreach (const QNetworkAddressEntry &entry, networkInterface.addressEntries()) {
|
||||||
qCDebug(dcNetworkDeviceDiscovery()) << " Checking entry" << entry.ip().toString();
|
|
||||||
|
|
||||||
// Only IPv4
|
// Only IPv4
|
||||||
if (entry.ip().protocol() != QAbstractSocket::IPv4Protocol)
|
if (entry.ip().protocol() != QAbstractSocket::IPv4Protocol)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// Store the own address of this network interface in any case,
|
||||||
|
// since we don't want to ping our self
|
||||||
|
ownAddresses.append(entry.ip());
|
||||||
|
|
||||||
|
TargetNetwork targetNetwork;
|
||||||
|
targetNetwork.networkInterface = networkInterface;
|
||||||
|
targetNetwork.addressEntry = entry;
|
||||||
|
targetNetwork.address = QHostAddress(entry.ip().toIPv4Address() & entry.netmask().toIPv4Address());
|
||||||
|
|
||||||
|
qCDebug(dcNetworkDeviceDiscovery()) << " Checking entry" << entry.ip().toString();
|
||||||
qCDebug(dcNetworkDeviceDiscovery()) << " Host address:" << entry.ip().toString();
|
qCDebug(dcNetworkDeviceDiscovery()) << " Host address:" << entry.ip().toString();
|
||||||
|
qCDebug(dcNetworkDeviceDiscovery()) << " Network address:" << targetNetwork.address.toString();
|
||||||
qCDebug(dcNetworkDeviceDiscovery()) << " Broadcast address:" << entry.broadcast().toString();
|
qCDebug(dcNetworkDeviceDiscovery()) << " Broadcast address:" << entry.broadcast().toString();
|
||||||
qCDebug(dcNetworkDeviceDiscovery()) << " Netmask:" << entry.netmask().toString();
|
qCDebug(dcNetworkDeviceDiscovery()) << " Netmask:" << entry.netmask().toString();
|
||||||
quint32 addressRangeStart = entry.ip().toIPv4Address() & entry.netmask().toIPv4Address();
|
qCDebug(dcNetworkDeviceDiscovery()) << " Address rang from" << targetNetwork.address.toString() << "-->" << targetNetwork.addressEntry.broadcast().toString();
|
||||||
quint32 addressRangeStop = entry.broadcast().toIPv4Address() | addressRangeStart;
|
|
||||||
quint32 range = addressRangeStop - addressRangeStart;
|
|
||||||
|
|
||||||
// Let's scan only 255.255.255.0 networks for now
|
// Let's scan only 255.255.255.0 networks for now
|
||||||
if (range > 255)
|
if (entry.prefixLength() < 24) {
|
||||||
|
qCDebug(dcNetworkDeviceDiscovery()) << "Skipping network interface" << networkInterface.name() << "because there are to many hosts to contact. The network detector was designed for /24 networks.";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter out duplicated networks (for example connected using wifi and ethernet to the same network) ...
|
||||||
|
|
||||||
|
bool duplicatedNetwork = false;
|
||||||
|
foreach (const TargetNetwork &tn, targetNetworks) {
|
||||||
|
if (tn.address == targetNetwork.address && tn.addressEntry.netmask() == targetNetwork.addressEntry.netmask()) {
|
||||||
|
qCDebug(dcNetworkDeviceDiscovery()) << "Skipping network interface" << targetNetwork.networkInterface.name() << targetNetwork.address.toString() << "as ping target network because it seems to be the same network as" << tn.networkInterface.name() << tn.address.toString();
|
||||||
|
duplicatedNetwork = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (duplicatedNetwork)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
qCDebug(dcNetworkDeviceDiscovery()) << " Address range" << range << " | from" << QHostAddress(addressRangeStart).toString() << "-->" << QHostAddress(addressRangeStop).toString();
|
targetNetworks.append(targetNetwork);
|
||||||
// Send ping request to each address within the range
|
}
|
||||||
for (quint32 i = 1; i < range; i++) {
|
}
|
||||||
quint32 address = addressRangeStart + i;
|
|
||||||
QHostAddress targetAddress(address);
|
|
||||||
|
|
||||||
// Skip our self
|
foreach (const TargetNetwork &targetNetwork, targetNetworks) {
|
||||||
if (targetAddress == entry.ip())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Retry only once to ping a device and lookup the hostname on success
|
// Send ping request to each address within the range
|
||||||
PingReply *reply = ping(targetAddress, true, 1);
|
quint32 targetHostsCount = pow(2, 32 - targetNetwork.addressEntry.prefixLength()) - 1;
|
||||||
m_runningPingReplies.append(reply);
|
for (quint32 i = 1; i < targetHostsCount; i++) {
|
||||||
connect(reply, &PingReply::finished, this, [=](){
|
QHostAddress targetAddress(targetNetwork.address.toIPv4Address() + i);
|
||||||
m_runningPingReplies.removeAll(reply);
|
|
||||||
if (reply->error() == PingReply::ErrorNoError) {
|
// Skip the broadcast
|
||||||
qCDebug(dcNetworkDeviceDiscovery()) << "Ping response from" << targetAddress.toString() << reply->hostName() << reply->duration() << "ms";
|
if (targetAddress == targetNetwork.addressEntry.broadcast())
|
||||||
if (m_currentDiscoveryReply) {
|
continue;
|
||||||
m_currentDiscoveryReply->processPingResponse(targetAddress, reply->hostName());
|
|
||||||
}
|
// Skip our self
|
||||||
|
if (ownAddresses.contains(targetAddress))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Retry only once to ping a device and lookup the hostname on success
|
||||||
|
PingReply *reply = ping(targetAddress, true, 1);
|
||||||
|
m_runningPingReplies.append(reply);
|
||||||
|
connect(reply, &PingReply::finished, this, [=](){
|
||||||
|
m_runningPingReplies.removeAll(reply);
|
||||||
|
if (reply->error() == PingReply::ErrorNoError) {
|
||||||
|
qCDebug(dcNetworkDeviceDiscovery()) << "Ping response from" << targetAddress.toString() << reply->hostName() << reply->duration() << "ms";
|
||||||
|
if (m_currentDiscoveryReply) {
|
||||||
|
m_currentDiscoveryReply->processPingResponse(targetAddress, reply->hostName());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (m_runningPingReplies.isEmpty() && !m_runningMacDatabaseReplies.isEmpty()) {
|
if (m_runningPingReplies.isEmpty() && !m_runningMacDatabaseReplies.isEmpty()) {
|
||||||
qCDebug(dcNetworkDeviceDiscovery()) << "All ping replies have finished but there are still" << m_runningMacDatabaseReplies.count() << "mac db lookups pending. Waiting for them to finish...";
|
qCDebug(dcNetworkDeviceDiscovery()) << "All ping replies have finished but there are still" << m_runningMacDatabaseReplies.count() << "mac db lookups pending. Waiting for them to finish...";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_runningPingReplies.isEmpty() && m_runningMacDatabaseReplies.isEmpty() && m_currentDiscoveryReply && !m_discoveryTimer->isActive()) {
|
if (m_runningPingReplies.isEmpty() && m_runningMacDatabaseReplies.isEmpty() && m_currentDiscoveryReply && !m_discoveryTimer->isActive()) {
|
||||||
qCDebug(dcNetworkDeviceDiscovery()) << "All pending replies have finished.";
|
qCDebug(dcNetworkDeviceDiscovery()) << "All pending replies have finished.";
|
||||||
finishDiscovery();
|
finishDiscovery();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -85,6 +85,12 @@ protected:
|
|||||||
void setEnabled(bool enabled) override;
|
void setEnabled(bool enabled) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
typedef struct TargetNetwork {
|
||||||
|
QNetworkInterface networkInterface;
|
||||||
|
QNetworkAddressEntry addressEntry;
|
||||||
|
QHostAddress address;
|
||||||
|
} TargetNetwork;
|
||||||
|
|
||||||
MacAddressDatabase *m_macAddressDatabase = nullptr;
|
MacAddressDatabase *m_macAddressDatabase = nullptr;
|
||||||
ArpSocket *m_arpSocket = nullptr;
|
ArpSocket *m_arpSocket = nullptr;
|
||||||
Ping *m_ping = nullptr;
|
Ping *m_ping = nullptr;
|
||||||
|
|||||||
Reference in New Issue
Block a user