Ensure WoL works properly on multi-homed hosts. Fixes #135

This commit is contained in:
Cameron Gutman
2019-01-04 20:05:31 -08:00
parent 11c7131875
commit 5a2cfc15a6
+35 -16
View File
@@ -2,6 +2,7 @@
#include <QUdpSocket> #include <QUdpSocket>
#include <QHostInfo> #include <QHostInfo>
#include <QNetworkInterface>
#define SER_NAME "hostname" #define SER_NAME "hostname"
#define SER_UUID "uuid" #define SER_UUID "uuid"
@@ -172,6 +173,32 @@ bool NvComputer::wake()
QVector<QString> addressList = uniqueAddresses(); QVector<QString> addressList = uniqueAddresses();
addressList.append("255.255.255.255"); addressList.append("255.255.255.255");
// Try to broadcast on all available NICs
for (const QNetworkInterface& nic : QNetworkInterface::allInterfaces()) {
// Ensure the interface is up and skip the loopback adapter
if ((nic.flags() & QNetworkInterface::IsUp) == 0 ||
(nic.flags() & QNetworkInterface::IsLoopBack) != 0) {
continue;
}
QHostAddress allNodesMulticast("FF02::1");
for (const QNetworkAddressEntry& addr : nic.addressEntries()) {
// Store the scope ID for this NIC if IPv6 is enabled
if (!addr.ip().scopeId().isEmpty()) {
allNodesMulticast.setScopeId(addr.ip().scopeId());
}
// Skip IPv6 which doesn't support broadcast
if (!addr.broadcast().isNull()) {
addressList.append(addr.broadcast().toString());
}
}
if (!allNodesMulticast.scopeId().isEmpty()) {
addressList.append(allNodesMulticast.toString());
}
}
// Try all unique address strings or host names // Try all unique address strings or host names
bool success = false; bool success = false;
for (QString& addressString : addressList) { for (QString& addressString : addressList) {
@@ -186,23 +213,15 @@ bool NvComputer::wake()
for (QHostAddress& address : hostInfo.addresses()) { for (QHostAddress& address : hostInfo.addresses()) {
QUdpSocket sock; QUdpSocket sock;
// Bind to any address on the correct protocol // Send to all ports
if (sock.bind(address.protocol() == QUdpSocket::IPv4Protocol ? for (quint16 port : WOL_PORTS) {
QHostAddress::AnyIPv4 : QHostAddress::AnyIPv6)) { if (sock.writeDatagram(wolPayload, address, port)) {
qInfo().nospace().noquote() << "Sent WoL packet to " << name << " via " << address.toString() << ":" << port;
// Send to all ports success = true;
for (quint16 port : WOL_PORTS) { }
if (sock.writeDatagram(wolPayload, address, port)) { else {
qInfo().nospace().noquote() << "Sent WoL packet to " << name << " via " << address.toString() << ":" << port; qWarning() << "Send failed:" << sock.error();
success = true;
}
else {
qWarning() << "Send failed:" << sock.error();
}
} }
}
else {
qWarning() << "Bind failed:" << sock.error();
} }
} }
} }