diff --git a/src/utils.cpp b/src/utils.cpp index 2deb163..90f3f41 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -1,523 +1,555 @@ /* Copyright 2009 Will Stephenson Copyright 2012-2013 Jan Grulich This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "utils.h" +#include "time.h" QHostAddress NetworkManager::ipv6AddressAsHostAddress(const QByteArray &address) { // Q_ASSERT(address.size() == 16); Q_IPV6ADDR tmp; for (int i = 0; i < 16; ++i) { tmp[i] = address[i]; } QHostAddress hostaddress(tmp); Q_ASSERT(hostaddress.protocol() == QAbstractSocket::IPv6Protocol); return hostaddress; } QByteArray NetworkManager::ipv6AddressFromHostAddress(const QHostAddress &address) { // Q_ASSERT(address.protocol() == QAbstractSocket::IPv6Protocol); Q_IPV6ADDR tmp = address.toIPv6Address(); QByteArray assembledAddress; for (int i = 0; i < 16; ++i) { assembledAddress[i] = tmp[i]; } return assembledAddress; } QString NetworkManager::macAddressAsString(const QByteArray &ba) { QStringList mac; for (int i = 0; i < ba.size(); ++i) { mac << QString("%1").arg((quint8)ba[i], 2, 16, QLatin1Char('0')).toUpper(); } return mac.join(":"); } QByteArray NetworkManager::macAddressFromString(const QString &s) { QStringList macStringList = s.split(':'); // Q_ASSERT(macStringList.size() == 6); QByteArray ba; if (!s.isEmpty()) { ba.resize(6); int i = 0; Q_FOREACH (const QString & macPart, macStringList) { ba[i++] = macPart.toUInt(nullptr, 16); } } return ba; } bool NetworkManager::macAddressIsValid(const QString &macAddress) { QRegExp macAddressCheck = QRegExp("([a-fA-F0-9][a-fA-F0-9]:){5}[0-9a-fA-F][0-9a-fA-F]"); return macAddress.contains(macAddressCheck); } bool NetworkManager::macAddressIsValid(const QByteArray &macAddress) { return macAddressIsValid(macAddressAsString(macAddress)); } int NetworkManager::findChannel(int freq) { int channel; if (freq < 2500) { channel = 0; int i = 0; QList > bFreqs = getBFreqs(); while (i < bFreqs.size()) { if (bFreqs.at(i).second <= freq) { channel = bFreqs.at(i).first; } else { break; } i++; } return channel; } channel = 0; int i = 0; QList > aFreqs = getAFreqs(); while (i < aFreqs.size()) { if (aFreqs.at(i).second <= freq) { channel = aFreqs.at(i).first; } else { break; } i++; } return channel; } NetworkManager::WirelessSetting::FrequencyBand NetworkManager::findFrequencyBand(int freq) { if (freq < 2500) { return WirelessSetting::Bg; } return WirelessSetting::A; } bool NetworkManager::deviceSupportsApCiphers(NetworkManager::WirelessDevice::Capabilities interfaceCaps, NetworkManager::AccessPoint::WpaFlags apCiphers, WirelessSecurityType type) { bool havePair = false; bool haveGroup = true; if (type == NetworkManager::StaticWep) { havePair = true; } else { if (interfaceCaps.testFlag(NetworkManager::WirelessDevice::Wep40) && apCiphers.testFlag(NetworkManager::AccessPoint::PairWep40)) { havePair = true; } if (interfaceCaps.testFlag(NetworkManager::WirelessDevice::Wep104) && apCiphers.testFlag(NetworkManager::AccessPoint::PairWep104)) { havePair = true; } if (interfaceCaps.testFlag(NetworkManager::WirelessDevice::Tkip) && apCiphers.testFlag(NetworkManager::AccessPoint::PairTkip)) { havePair = true; } if (interfaceCaps.testFlag(NetworkManager::WirelessDevice::Ccmp) && apCiphers.testFlag(NetworkManager::AccessPoint::PairCcmp)) { havePair = true; } } if (interfaceCaps.testFlag(NetworkManager::WirelessDevice::Wep40) && apCiphers.testFlag(NetworkManager::AccessPoint::GroupWep40)) { haveGroup = true; } if (interfaceCaps.testFlag(NetworkManager::WirelessDevice::Wep104) && apCiphers.testFlag(NetworkManager::AccessPoint::GroupWep104)) { haveGroup = true; } if (type != StaticWep) { if (interfaceCaps.testFlag(NetworkManager::WirelessDevice::Tkip) && apCiphers.testFlag(NetworkManager::AccessPoint::GroupTkip)) { haveGroup = true; } if (interfaceCaps.testFlag(NetworkManager::WirelessDevice::Ccmp) && apCiphers.testFlag(NetworkManager::AccessPoint::GroupCcmp)) { haveGroup = true; } } return (havePair && haveGroup); } // Keep this in sync with NetworkManager/libnm-util/nm-utils.c:nm_utils_security_valid() bool NetworkManager::securityIsValid(WirelessSecurityType type, NetworkManager::WirelessDevice::Capabilities interfaceCaps, bool haveAp, bool adhoc, NetworkManager::AccessPoint::Capabilities apCaps, NetworkManager::AccessPoint::WpaFlags apWpa, NetworkManager::AccessPoint::WpaFlags apRsn) { bool good = true; //kDebug() << "type(" << type << ") interfaceCaps(" << interfaceCaps << ") haveAp(" << haveAp << ") adhoc(" << adhoc << ") apCaps(" << apCaps << ") apWpa(" << apWpa << " apRsn(" << apRsn << ")"; if (!haveAp) { if (type == NoneSecurity) { return true; } if ((type == StaticWep) || ((type == DynamicWep) && !adhoc) || ((type == Leap) && !adhoc)) { if (interfaceCaps.testFlag(NetworkManager::WirelessDevice::Wep40) || interfaceCaps.testFlag(NetworkManager::WirelessDevice::Wep104)) { return true; } } // apCaps.testFlag(Privacy) == true for StaticWep, Leap and DynamicWep // see libs/internals/wirelessinterfaceconnectionhelpers.cpp // TODO: this is not in nm-utils.c // if (type == Knm::WirelessSecurity::WpaPsk // || ((type == Knm::WirelessSecurity::WpaEap) && !adhoc)) { // if (interfaceCaps.testFlag(NetworkManager::WirelessDevice::Wpa) && // !apCaps.testFlag(NetworkManager::AccessPoint::Privacy)) { // return true; // } // } // if (type == Knm::WirelessSecurity::Wpa2Psk // || ((type == Knm::WirelessSecurity::Wpa2Eap) && !adhoc)) { // if (interfaceCaps.testFlag(NetworkManager::WirelessDevice::Rsn) && // !apCaps.testFlag(NetworkManager::AccessPoint::Privacy)) { // return true; // } // } return false; } switch (type) { case NoneSecurity: Q_ASSERT(haveAp); if (apCaps.testFlag(NetworkManager::AccessPoint::Privacy)) { return false; } if (apWpa || apRsn) { return false; } break; case Leap: /* require PRIVACY bit for LEAP? */ if (adhoc) { return false; } /* Fall through */ case StaticWep: Q_ASSERT(haveAp); if (!apCaps.testFlag(NetworkManager::AccessPoint::Privacy)) { return false; } if (apWpa || apRsn) { if (!deviceSupportsApCiphers(interfaceCaps, apWpa, StaticWep)) if (!deviceSupportsApCiphers(interfaceCaps, apRsn, StaticWep)) { return false; } } break; case DynamicWep: if (adhoc) { return false; } Q_ASSERT(haveAp); if (apRsn || !(apCaps.testFlag(NetworkManager::AccessPoint::Privacy))) { return false; } /* Some APs broadcast minimal WPA-enabled beacons that must be handled */ if (apWpa) { if (!apWpa.testFlag(NetworkManager::AccessPoint::KeyMgmt8021x)) { return false; } if (!deviceSupportsApCiphers(interfaceCaps, apWpa, DynamicWep)) { return false; } } break; case WpaPsk: if (!interfaceCaps.testFlag(NetworkManager::WirelessDevice::Wpa)) { return false; } if (haveAp) { /* Ad-Hoc WPA APs won't necessarily have the PSK flag set */ if (adhoc) { if (apWpa.testFlag(NetworkManager::AccessPoint::GroupTkip) && interfaceCaps.testFlag(NetworkManager::WirelessDevice::Tkip)) { return true; } if (apWpa.testFlag(NetworkManager::AccessPoint::GroupCcmp) && interfaceCaps.testFlag(NetworkManager::WirelessDevice::Ccmp)) { return true; } } else if (apWpa.testFlag(NetworkManager::AccessPoint::KeyMgmtPsk)) { if (apWpa.testFlag(NetworkManager::AccessPoint::PairTkip) && interfaceCaps.testFlag(NetworkManager::WirelessDevice::Tkip)) { return true; } if (apWpa.testFlag(NetworkManager::AccessPoint::PairCcmp) && interfaceCaps.testFlag(NetworkManager::WirelessDevice::Ccmp)) { return true; } } return false; } break; case Wpa2Psk: if (!interfaceCaps.testFlag(NetworkManager::WirelessDevice::Rsn)) { return false; } if (haveAp) { /* Ad-Hoc WPA APs won't necessarily have the PSK flag set */ if (apRsn.testFlag(NetworkManager::AccessPoint::KeyMgmtPsk) || adhoc) { if (apRsn.testFlag(NetworkManager::AccessPoint::PairTkip) && interfaceCaps.testFlag(NetworkManager::WirelessDevice::Tkip)) { return true; } if (apRsn.testFlag(NetworkManager::AccessPoint::PairCcmp) && interfaceCaps.testFlag(NetworkManager::WirelessDevice::Ccmp)) { return true; } } return false; } break; case WpaEap: if (adhoc) { return false; } if (!interfaceCaps.testFlag(NetworkManager::WirelessDevice::Wpa)) { return false; } if (haveAp) { if (!apWpa.testFlag(NetworkManager::AccessPoint::KeyMgmt8021x)) { return false; } /* Ensure at least one WPA cipher is supported */ if (!deviceSupportsApCiphers(interfaceCaps, apWpa, WpaEap)) { return false; } } break; case Wpa2Eap: if (adhoc) { return false; } if (!interfaceCaps.testFlag(NetworkManager::WirelessDevice::Rsn)) { return false; } if (haveAp) { if (!apRsn.testFlag(NetworkManager::AccessPoint::KeyMgmt8021x)) { return false; } /* Ensure at least one WPA cipher is supported */ if (!deviceSupportsApCiphers(interfaceCaps, apRsn, Wpa2Eap)) { return false; } } break; default: good = false; break; } return good; } NetworkManager::WirelessSecurityType NetworkManager::findBestWirelessSecurity(NetworkManager::WirelessDevice::Capabilities interfaceCaps, bool haveAp, bool adHoc, NetworkManager::AccessPoint::Capabilities apCaps, NetworkManager::AccessPoint::WpaFlags apWpa, NetworkManager::AccessPoint::WpaFlags apRsn) { QList types; // The ordering of this list is a pragmatic combination of security level and popularity. // Therefore static WEP is before LEAP and Dynamic WEP because there is no way to detect // if an AP is capable of Dynamic WEP and showing Dynamic WEP first would confuse // Static WEP users. types << NetworkManager::Wpa2Eap << NetworkManager::Wpa2Psk << NetworkManager::WpaEap << NetworkManager::WpaPsk << NetworkManager::StaticWep << NetworkManager::DynamicWep << NetworkManager::Leap << NetworkManager::NoneSecurity; Q_FOREACH (NetworkManager::WirelessSecurityType type, types) { if (NetworkManager::securityIsValid(type, interfaceCaps, haveAp, adHoc, apCaps, apWpa, apRsn)) { return type; } } return NetworkManager::UnknownSecurity; } bool NetworkManager::wepKeyIsValid(const QString &key, NetworkManager::WirelessSecuritySetting::WepKeyType type) { if (key.isEmpty()) { return false; } const int keylen = key.length(); if (type != WirelessSecuritySetting::NotSpecified) { if (type == WirelessSecuritySetting::Hex) { if (keylen == 10 || keylen == 26) { /* Hex key */ for (int i = 0; i < keylen; ++i) { if (!(key.at(i).isDigit() || (key.at(i) >= 'A' && key.at(i) <= 'F') || (key.at(i) >= 'a' && key.at(i) <= 'f'))) { return false; } } return true; } else if (keylen == 5 || keylen == 13) { /* ASCII KEY */ for (int i = 0; i < keylen; ++i) { if (!key.at(i).isPrint()) { return false; } } return true; } return false; } else if (type == WirelessSecuritySetting::Passphrase) { if (!keylen || keylen > 64) { return false; } return true; } } return false; } bool NetworkManager::wpaPskIsValid(const QString &psk) { if (psk.isEmpty()) { return false; } const int psklen = psk.length(); if (psklen < 8 || psklen > 64) { return false; } if (psklen == 64) { /* Hex PSK */ for (int i = 0; i < psklen; ++i) { if (!psk.at(i).isLetterOrNumber()) { return false; } } } return true; } NetworkManager::WirelessSecurityType NetworkManager::securityTypeFromConnectionSetting(const NetworkManager::ConnectionSettings::Ptr &settings) { NetworkManager::WirelessSecuritySetting::Ptr wifiSecuritySetting = settings->setting(Setting::WirelessSecurity).dynamicCast(); if (wifiSecuritySetting->keyMgmt() == WirelessSecuritySetting::Wep) { return StaticWep; } else if (wifiSecuritySetting->keyMgmt() == WirelessSecuritySetting::Ieee8021x) { if (wifiSecuritySetting->authAlg() == WirelessSecuritySetting::Leap) { return Leap; } else { return DynamicWep; } } else if (wifiSecuritySetting->keyMgmt() == WirelessSecuritySetting::WpaPsk) { if (wifiSecuritySetting->proto().contains(WirelessSecuritySetting::Wpa) && !wifiSecuritySetting->proto().contains(WirelessSecuritySetting::Rsn)) { return WpaPsk; } return Wpa2Psk; } else if (wifiSecuritySetting->keyMgmt() == WirelessSecuritySetting::WpaEap) { if (wifiSecuritySetting->proto().contains(WirelessSecuritySetting::Wpa) && !wifiSecuritySetting->proto().contains(WirelessSecuritySetting::Rsn)) { return WpaEap; } return Wpa2Eap; } return NoneSecurity; } QList > NetworkManager::getBFreqs() { QList > freqs; freqs.append(QPair(1, 2412)); freqs.append(QPair(2, 2417)); freqs.append(QPair(3, 2422)); freqs.append(QPair(4, 2427)); freqs.append(QPair(5, 2432)); freqs.append(QPair(6, 2437)); freqs.append(QPair(7, 2442)); freqs.append(QPair(8, 2447)); freqs.append(QPair(9, 2452)); freqs.append(QPair(10, 2457)); freqs.append(QPair(11, 2462)); freqs.append(QPair(12, 2467)); freqs.append(QPair(13, 2472)); freqs.append(QPair(14, 2484)); return freqs; } QList > NetworkManager::getAFreqs() { QList > freqs; freqs.append(QPair(7, 5035)); freqs.append(QPair(8, 5040)); freqs.append(QPair(9, 5045)); freqs.append(QPair(11, 5055)); freqs.append(QPair(12, 5060)); freqs.append(QPair(16, 5080)); freqs.append(QPair(34, 5170)); freqs.append(QPair(36, 5180)); freqs.append(QPair(38, 5190)); freqs.append(QPair(40, 5200)); freqs.append(QPair(42, 5210)); freqs.append(QPair(44, 5220)); freqs.append(QPair(46, 5230)); freqs.append(QPair(48, 5240)); freqs.append(QPair(52, 5260)); freqs.append(QPair(56, 5280)); freqs.append(QPair(60, 5300)); freqs.append(QPair(64, 5320)); freqs.append(QPair(100, 5500)); freqs.append(QPair(104, 5520)); freqs.append(QPair(108, 5540)); freqs.append(QPair(112, 5560)); freqs.append(QPair(116, 5580)); freqs.append(QPair(120, 5600)); freqs.append(QPair(124, 5620)); freqs.append(QPair(128, 5640)); freqs.append(QPair(132, 5660)); freqs.append(QPair(136, 5680)); freqs.append(QPair(140, 5700)); freqs.append(QPair(149, 5745)); freqs.append(QPair(153, 5765)); freqs.append(QPair(157, 5785)); freqs.append(QPair(161, 5805)); freqs.append(QPair(165, 5825)); freqs.append(QPair(183, 4915)); freqs.append(QPair(184, 4920)); freqs.append(QPair(185, 4925)); freqs.append(QPair(187, 4935)); freqs.append(QPair(188, 4940)); freqs.append(QPair(189, 4945)); freqs.append(QPair(192, 4960)); freqs.append(QPair(196, 4980)); return freqs; } + +QDateTime NetworkManager::clockBootTimeToDateTime(qlonglong clockBootime) { + + clockid_t clk_id = CLOCK_BOOTTIME; + struct timespec tp; + int r; + + // now is used as a point of reference + // with the timespec that contains the number of msec since boot + QDateTime now = QDateTime::currentDateTime(); + r = clock_gettime (clk_id, &tp); + if (r == -1 && errno == EINVAL) { + clk_id = CLOCK_MONOTONIC; + r = clock_gettime (clk_id, &tp); + } + + // convert to msecs + long now_msecs = tp.tv_sec * 1000 + tp.tv_nsec / 1000000; + + // diff the msecs and construct a QDateTime based on the offset + QDateTime res; + if (clockBootime > now_msecs) { + qlonglong offset = clockBootime - now_msecs; + res = QDateTime::fromMSecsSinceEpoch(now.toMSecsSinceEpoch() + offset); + } else { + qlonglong offset = now_msecs - clockBootime; + res = QDateTime::fromMSecsSinceEpoch(now.toMSecsSinceEpoch() - offset); + } + + return res; +} diff --git a/src/utils.h b/src/utils.h index 6b6a1d7..08c5c0d 100644 --- a/src/utils.h +++ b/src/utils.h @@ -1,87 +1,89 @@ /* Copyright 2012-2013 Jan Grulich This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #ifndef NETWORKMANAGERQT_UTILS_H #define NETWORKMANAGERQT_UTILS_H #include #include #include #include "wirelessdevice.h" #include "wirelesssecuritysetting.h" #include "wirelesssetting.h" namespace NetworkManager { enum WirelessSecurityType { UnknownSecurity = -1, NoneSecurity, StaticWep, DynamicWep, Leap, WpaPsk, WpaEap, Wpa2Psk, Wpa2Eap }; /** * @return QHostAddress representation of an ipv6 address * @param address byte array containing the binary representation of the address */ NETWORKMANAGERQT_EXPORT QHostAddress ipv6AddressAsHostAddress(const QByteArray &address); /** * @return binary representation of an ipv6 address * @param address qhostaddress containing the address */ NETWORKMANAGERQT_EXPORT QByteArray ipv6AddressFromHostAddress(const QHostAddress &address); /** * @return String representation of a mac address. * @param ba byte array containing the binary repesentation of the address */ NETWORKMANAGERQT_EXPORT QString macAddressAsString(const QByteArray &ba); /** * @return binary repesentation of a mac address. * @param s string representation of the address */ NETWORKMANAGERQT_EXPORT QByteArray macAddressFromString(const QString &s); NETWORKMANAGERQT_EXPORT bool macAddressIsValid(const QString &macAddress); NETWORKMANAGERQT_EXPORT bool macAddressIsValid(const QByteArray &macAddress); /** * @param freq frequency of a wireless network * @return The frequency channel. */ NETWORKMANAGERQT_EXPORT int findChannel(int freq); NETWORKMANAGERQT_EXPORT NetworkManager::WirelessSetting::FrequencyBand findFrequencyBand(int freq); NETWORKMANAGERQT_EXPORT bool deviceSupportsApCiphers(NetworkManager::WirelessDevice::Capabilities, NetworkManager::AccessPoint::WpaFlags ciphers, WirelessSecurityType type); NETWORKMANAGERQT_EXPORT bool securityIsValid(WirelessSecurityType type, NetworkManager::WirelessDevice::Capabilities interfaceCaps, bool haveAp, bool adHoc, NetworkManager::AccessPoint::Capabilities apCaps, NetworkManager::AccessPoint::WpaFlags apWpa, NetworkManager::AccessPoint::WpaFlags apRsn); NETWORKMANAGERQT_EXPORT WirelessSecurityType findBestWirelessSecurity(NetworkManager::WirelessDevice::Capabilities, bool haveAp, bool adHoc, NetworkManager::AccessPoint::Capabilities apCaps, NetworkManager::AccessPoint::WpaFlags apWpa, NetworkManager::AccessPoint::WpaFlags apRsn); NETWORKMANAGERQT_EXPORT bool wepKeyIsValid(const QString &key, NetworkManager::WirelessSecuritySetting::WepKeyType type); NETWORKMANAGERQT_EXPORT bool wpaPskIsValid(const QString &psk); NETWORKMANAGERQT_EXPORT WirelessSecurityType securityTypeFromConnectionSetting(const NetworkManager::ConnectionSettings::Ptr &settings); NETWORKMANAGERQT_EXPORT QList > getBFreqs(); NETWORKMANAGERQT_EXPORT QList > getAFreqs(); + + NETWORKMANAGERQT_EXPORT QDateTime clockBootTimeToDateTime(qlonglong clockBootime); } #endif // NETWORKMANAGERQT_UTILS_H diff --git a/src/wirelessdevice.cpp b/src/wirelessdevice.cpp index 833ab47..9bc043c 100644 --- a/src/wirelessdevice.cpp +++ b/src/wirelessdevice.cpp @@ -1,268 +1,285 @@ /* Copyright 2008,2011 Will Stephenson Copyright 2013 Daniel Nicoletti Copyright 2013 Jan Grulich This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "wirelessdevice.h" #include "wirelessdevice_p.h" #undef signals #include #define signals Q_SIGNALS #include "accesspoint.h" #include "manager_p.h" #include "nmdebug.h" +#include "utils.h" NetworkManager::WirelessDevicePrivate::WirelessDevicePrivate(const QString &path, WirelessDevice *q) : DevicePrivate(path, q) #ifdef NMQT_STATIC , wirelessIface(NetworkManagerPrivate::DBUS_SERVICE, path, QDBusConnection::sessionBus()) #else , wirelessIface(NetworkManagerPrivate::DBUS_SERVICE, path, QDBusConnection::systemBus()) #endif , bitRate(0) { } NetworkManager::WirelessDevice::WirelessDevice(const QString &path, QObject *parent) : Device(*new WirelessDevicePrivate(path, this), parent) { Q_D(WirelessDevice); qDBusRegisterMetaType >(); QList aps = d->wirelessIface.accessPoints(); // qCDebug(NMQT) << "AccessPoint list"; Q_FOREACH (const QDBusObjectPath & op, aps) { // qCDebug(NMQT) << " " << op.path(); d->accessPointAdded(op); } // Get all WirelessDevices's properties at once QVariantMap initialProperties = NetworkManagerPrivate::retrieveInitialProperties(d->wirelessIface.staticInterfaceName(), path); if (!initialProperties.isEmpty()) { d->propertiesChanged(initialProperties); } #ifndef NMQT_STATIC QDBusConnection::systemBus().connect(NetworkManagerPrivate::DBUS_SERVICE, d->uni, NetworkManagerPrivate::FDO_DBUS_PROPERTIES, QLatin1String("PropertiesChanged"), d, SLOT(dbusPropertiesChanged(QString,QVariantMap,QStringList))); #endif #ifdef NMQT_STATIC connect(&d->wirelessIface, &OrgFreedesktopNetworkManagerDeviceWirelessInterface::PropertiesChanged, d, &WirelessDevicePrivate::propertiesChanged); #endif connect(&d->wirelessIface, &OrgFreedesktopNetworkManagerDeviceWirelessInterface::AccessPointAdded, d, &WirelessDevicePrivate::accessPointAdded); connect(&d->wirelessIface, &OrgFreedesktopNetworkManagerDeviceWirelessInterface::AccessPointRemoved, d, &WirelessDevicePrivate::accessPointRemoved); } NetworkManager::WirelessDevice::~WirelessDevice() { } NetworkManager::Device::Type NetworkManager::WirelessDevice::type() const { return NetworkManager::Device::Wifi; } QStringList NetworkManager::WirelessDevice::accessPoints() const { Q_D(const WirelessDevice); return d->apMap.keys(); } QDBusPendingReply<> NetworkManager::WirelessDevice::requestScan(const QVariantMap &options) { Q_D(WirelessDevice); + d->lastRequestScanTime = QDateTime::currentDateTime(); return d->wirelessIface.RequestScan(options); } NetworkManager::AccessPoint::Ptr NetworkManager::WirelessDevice::activeAccessPoint() const { Q_D(const WirelessDevice); return d->activeAccessPoint; } QString NetworkManager::WirelessDevice::hardwareAddress() const { Q_D(const WirelessDevice); return d->hardwareAddress; } QString NetworkManager::WirelessDevice::permanentHardwareAddress() const { Q_D(const WirelessDevice); return d->permanentHardwareAddress; } NetworkManager::WirelessDevice::OperationMode NetworkManager::WirelessDevice::mode() const { Q_D(const WirelessDevice); return d->mode; } int NetworkManager::WirelessDevice::bitRate() const { Q_D(const WirelessDevice); return d->bitRate; } +QDateTime NetworkManager::WirelessDevice::lastScan() const +{ + Q_D(const WirelessDevice); + return d->lastScan; +} + +QDateTime NetworkManager::WirelessDevice::lastRequestScanTime() const +{ + Q_D(const WirelessDevice); + return d->lastRequestScanTime; +} + NetworkManager::WirelessDevice::Capabilities NetworkManager::WirelessDevice::wirelessCapabilities() const { Q_D(const WirelessDevice); return d->wirelessCapabilities; } NetworkManager::AccessPoint::Ptr NetworkManager::WirelessDevice::findAccessPoint(const QString &uni) { Q_D(WirelessDevice); NetworkManager::AccessPoint::Ptr accessPoint; QMap::ConstIterator mapIt = d->apMap.constFind(uni); if (mapIt != d->apMap.constEnd()) { accessPoint = mapIt.value(); } else if (!uni.isEmpty() && uni != QLatin1String("/")) { d->accessPointAdded(QDBusObjectPath(uni)); mapIt = d->apMap.constFind(uni); if (mapIt != d->apMap.constEnd()) { accessPoint = mapIt.value(); } } return accessPoint; } NetworkManager::WirelessNetwork::List NetworkManager::WirelessDevice::networks() const { Q_D(const WirelessDevice); return d->networks.values(); } NetworkManager::WirelessNetwork::Ptr NetworkManager::WirelessDevice::findNetwork(const QString &ssid) const { Q_D(const WirelessDevice); NetworkManager::WirelessNetwork::Ptr ret; if (d->networks.contains(ssid)) { ret = d->networks.value(ssid); } return ret; } void NetworkManager::WirelessDevicePrivate::accessPointAdded(const QDBusObjectPath &accessPoint) { //kDebug(1441) << apPath.path(); Q_Q(WirelessDevice); if (!apMap.contains(accessPoint.path())) { NetworkManager::AccessPoint::Ptr accessPointPtr(new NetworkManager::AccessPoint(accessPoint.path()), &QObject::deleteLater); apMap.insert(accessPoint.path(), accessPointPtr); Q_EMIT q->accessPointAppeared(accessPoint.path()); const QString ssid = accessPointPtr->ssid(); if (!ssid.isEmpty() && !networks.contains(ssid)) { NetworkManager::WirelessNetwork::Ptr wifiNetwork(new NetworkManager::WirelessNetwork(accessPointPtr, q), &QObject::deleteLater); networks.insert(ssid, wifiNetwork); connect(wifiNetwork.data(), &WirelessNetwork::disappeared, this, &WirelessDevicePrivate::removeNetwork); Q_EMIT q->networkAppeared(ssid); } } } void NetworkManager::WirelessDevicePrivate::accessPointRemoved(const QDBusObjectPath &accessPoint) { //kDebug(1441) << apPath.path(); Q_Q(WirelessDevice); if (!apMap.contains(accessPoint.path())) { qCDebug(NMQT) << "Access point list lookup failed for " << accessPoint.path(); } Q_EMIT q->accessPointDisappeared(accessPoint.path()); apMap.remove(accessPoint.path()); } void NetworkManager::WirelessDevicePrivate::removeNetwork(const QString &network) { Q_Q(WirelessDevice); if (networks.contains(network)) { networks.remove(network); Q_EMIT q->networkDisappeared(network); } } void NetworkManager::WirelessDevicePrivate::propertyChanged(const QString &property, const QVariant &value) { Q_Q(WirelessDevice); if (property == QLatin1String("ActiveAccessPoint")) { QDBusObjectPath activeAccessPointTmp = qdbus_cast(value); activeAccessPoint = q->findAccessPoint(activeAccessPointTmp.path()); Q_EMIT q->activeAccessPointChanged(activeAccessPointTmp.path()); } else if (property == QLatin1String("HwAddress")) { hardwareAddress = value.toString(); Q_EMIT q->hardwareAddressChanged(hardwareAddress); } else if (property == QLatin1String("PermHwAddress")) { permanentHardwareAddress = value.toString(); Q_EMIT q->permanentHardwareAddressChanged(permanentHardwareAddress); } else if (property == QLatin1String("Bitrate")) { bitRate = value.toUInt(); Q_EMIT q->bitRateChanged(bitRate); } else if (property == QLatin1String("Mode")) { mode = q->convertOperationMode(value.toUInt()); Q_EMIT q->modeChanged(mode); } else if (property == QLatin1String("WirelessCapabilities")) { wirelessCapabilities = q->convertCapabilities(value.toUInt()); Q_EMIT q->wirelessCapabilitiesChanged(wirelessCapabilities); + } else if (property == QLatin1String("LastScan")) { + lastScan = NetworkManager::clockBootTimeToDateTime(value.toLongLong()); + Q_EMIT q->lastScanChanged(lastScan); } else if (property == QLatin1String("AccessPoints")) { // TODO use this instead AccessPointAdded/Removed signals? } else { DevicePrivate::propertyChanged(property, value); } } NetworkManager::WirelessDevice::OperationMode NetworkManager::WirelessDevice::convertOperationMode(uint theirMode) { NetworkManager::WirelessDevice::OperationMode ourMode = NetworkManager::WirelessDevice::Unknown; switch (theirMode) { case NM_802_11_MODE_UNKNOWN: ourMode = NetworkManager::WirelessDevice::Unknown; break; case NM_802_11_MODE_ADHOC: ourMode = NetworkManager::WirelessDevice::Adhoc; break; case NM_802_11_MODE_INFRA: ourMode = NetworkManager::WirelessDevice::Infra; break; case NM_802_11_MODE_AP: ourMode = NetworkManager::WirelessDevice::ApMode; break; default: qCDebug(NMQT) << Q_FUNC_INFO << "Unhandled mode" << theirMode; } return ourMode; } NetworkManager::WirelessDevice::Capabilities NetworkManager::WirelessDevice::convertCapabilities(uint caps) { return (NetworkManager::WirelessDevice::Capabilities)caps; } diff --git a/src/wirelessdevice.h b/src/wirelessdevice.h index 5a869a9..c735324 100644 --- a/src/wirelessdevice.h +++ b/src/wirelessdevice.h @@ -1,220 +1,240 @@ /* Copyright 2008,2011 Will Stephenson Copyright 2011-2013 Lamarque V. Souza Copyright 2013 Daniel Nicoletti Copyright 2013 Jan Grulich This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #ifndef NETWORKMANAGERQT_WIRELESSDEVICE_H #define NETWORKMANAGERQT_WIRELESSDEVICE_H #include #include "device.h" #include "accesspoint.h" #include "wirelessnetwork.h" #include #include namespace NetworkManager { class WirelessDevicePrivate; /** * A wireless network interface */ class NETWORKMANAGERQT_EXPORT WirelessDevice : public Device { Q_OBJECT public: typedef QSharedPointer Ptr; typedef QList List; /** * The device's current operating mode */ enum OperationMode { Unknown = 0, /**< not associated with a network */ Adhoc, /**< part of an adhoc network */ Infra, /**< a station in an infrastructure wireless network */ ApMode /**< access point in an infrastructure network */ }; Q_ENUM(OperationMode) /** * Capabilities (currently all encryption/authentication related) of the device * @note FreqValid, Freq2Ghz, Freq5Ghz are available in runtime NM >= 1.0.2 */ enum Capability { NoCapability = 0x0, /**< Null capability */ Wep40 = 0x1, /**< 40 bit WEP cipher */ Wep104 = 0x2, /**< 104 bit WEP cipher */ Tkip = 0x4, /**< TKIP encryption cipher */ Ccmp = 0x8, /**< CCMP encryption cipher */ Wpa = 0x10, /**< WPA authentication protocol */ Rsn = 0x20, /**< RSN authethication protocol */ ApCap = 0x40, /**< The device supports Access Point mode. */ AdhocCap = 0x80, /**< The device supports Ad-Hoc mode. */ FreqValid = 0x100, /**< The device properly reports information about supported frequencies */ Freq2Ghz = 0x200, /**< The device supports 2.4Ghz frequencies */ Freq5Ghz = 0x400 /**< The device supports 5Ghz frequencies */ }; Q_DECLARE_FLAGS(Capabilities, Capability) /** * Creates a new WirelessDevice object. * * @param path the DBus path of the devise */ explicit WirelessDevice(const QString &path, QObject *parent = nullptr); /** * Destroys a WirelessDevice object. */ ~WirelessDevice() override; /** * Return the type */ Type type() const override; /** * List of wireless networks currently visible to the hardware */ QStringList accessPoints() const; /** * Asks the device for a new scan of available wireless networks * @param options Options of scan * No documentation for options yet, see http://projects.gnome.org/NetworkManager/developers/api/09/spec.html#org.freedesktop.NetworkManager.Device.Wireless */ QDBusPendingReply<> requestScan(const QVariantMap &options = QVariantMap()); /** * AccessPoint pointer this interface is currently associated with */ AccessPoint::Ptr activeAccessPoint() const; /** * The permanent hardware address of the network interface */ QString permanentHardwareAddress() const; /** * The hardware address currently used by the network interface */ QString hardwareAddress() const; /** * Retrieves the operation mode of this network. * * @return the current mode * @see OperationMode */ WirelessDevice::OperationMode mode() const; /** * Retrieves the effective bit rate currently attainable by this device. * * @return the bitrate in Kbit/s */ int bitRate() const; + /** + * The LastScan property value, converted to QDateTime + * @since 5.62.0 + * @note will always return invalid QDateTime when runtime NM < 1.12 + * @return + */ + QDateTime lastScan() const; + /** + * The time the last RequestScan function was called + * @since 5.62.0 + * @return + */ + QDateTime lastRequestScanTime() const; /** * Retrieves the capabilities of this wifi network. * * @return the flag set describing the capabilities * @see Capabilities */ WirelessDevice::Capabilities wirelessCapabilities() const; /** * Helper method to convert wire representation of operation mode to enum */ static WirelessDevice::OperationMode convertOperationMode(uint); /** * Helper method to convert wire representation of capabilities to enum */ static WirelessDevice::Capabilities convertCapabilities(uint); /** * Finds access point object given its Unique Network Identifier. * * @param uni the identifier of the AP to find from this network interface * @returns a valid AccessPoint object if a network having the given UNI for this device is known to the system, 0 otherwise */ AccessPoint::Ptr findAccessPoint(const QString &uni); /** * Return the current list of networks */ WirelessNetwork::List networks() const; /** * Find a network with the given @p ssid, a Null object is * returned if it can not be found */ WirelessNetwork::Ptr findNetwork(const QString &ssid) const; Q_SIGNALS: /** * This signal is emitted when the bitrate of this network has changed. * * @param bitrate the new bitrate value for this network */ void bitRateChanged(int bitrate); /** * The active network changed. */ void activeAccessPointChanged(const QString &); /** * The device switched operating mode. */ void modeChanged(WirelessDevice::OperationMode); /** * The device changed its capabilities */ void wirelessCapabilitiesChanged(Capabilities); /** * The device changed its hardware address */ void hardwareAddressChanged(const QString &); /** * The device changed its permanent hardware address */ void permanentHardwareAddressChanged(const QString &); /** * The device changed its properties */ void wirelessPropertiesChanged(uint); // TODO this is bogus, remove /** * A new wireless access point appeared */ void accessPointAppeared(const QString &uni); /** * A wireless access point disappeared */ void accessPointDisappeared(const QString &uni); /** * A wireless network appeared */ void networkAppeared(const QString &ssid); /** * A wireless network disappeared */ void networkDisappeared(const QString &ssid); + /** + * The LastScan property has changed, meaning a scan has just finished + * @since 5.62.0 + * @note will never be emitted when runtime NM < 1.12 + * @see lastScanTime + */ + void lastScanChanged(const QDateTime &dateTime); private: Q_DECLARE_PRIVATE(WirelessDevice) }; } // namespace NetworkManager #endif //NETWORKMANAGERQT_WIRELESSDEVICE_H diff --git a/src/wirelessdevice_p.h b/src/wirelessdevice_p.h index aa110f0..d6c5540 100644 --- a/src/wirelessdevice_p.h +++ b/src/wirelessdevice_p.h @@ -1,64 +1,66 @@ /* Copyright 2008,2011 Will Stephenson Copyright 2013 Jan Grulich This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #ifndef NETWORKMANAGERQT_WIRELESSDEVICE_P_H #define NETWORKMANAGERQT_WIRELESSDEVICE_P_H #include "device_p.h" #include "dbus/wirelessdeviceinterface.h" namespace NetworkManager { class WirelessDevicePrivate : public DevicePrivate { Q_OBJECT public: explicit WirelessDevicePrivate(const QString &path, WirelessDevice *q); OrgFreedesktopNetworkManagerDeviceWirelessInterface wirelessIface; QString permanentHardwareAddress; QString hardwareAddress; QHash networks; QMap apMap; // index of the active AP or -1 if none AccessPoint::Ptr activeAccessPoint; WirelessDevice::OperationMode mode; uint bitRate; WirelessDevice::Capabilities wirelessCapabilities; + QDateTime lastScan; + QDateTime lastRequestScanTime; Q_DECLARE_PUBLIC(WirelessDevice) protected: /** * When subclassing make sure to call the parent class method * if the property was not useful to your new class */ void propertyChanged(const QString &property, const QVariant &value) override; protected Q_SLOTS: void accessPointAdded(const QDBusObjectPath &); void accessPointRemoved(const QDBusObjectPath &); void removeNetwork(const QString &network); }; } #endif