File indexing completed on 2024-04-14 03:57:41

0001 /*
0002     SPDX-FileCopyrightText: 2008, 2010 Will Stephenson <wstephenson@kde.org>
0003     SPDX-FileCopyrightText: 2013 Daniel Nicoletti <dantti12@gmail.com>
0004     SPDX-FileCopyrightText: 2013 Jan Grulich <jgrulich@redhat.com>
0005 
0006     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0007 */
0008 
0009 #include "connection.h"
0010 #include "device_p.h"
0011 #include "manager.h"
0012 #include "manager_p.h"
0013 #include "nmdebug.h"
0014 #include "settings.h"
0015 
0016 #include <arpa/inet.h>
0017 
0018 #include <QDBusMetaType>
0019 #include <QDBusObjectPath>
0020 
0021 // logging category for this framework, default: log stuff >= warning
0022 Q_LOGGING_CATEGORY(NMQT, "kf.networkmanagerqt", QtWarningMsg)
0023 
0024 namespace NetworkManager
0025 {
0026 class DeviceStateReasonPrivate
0027 {
0028 public:
0029     DeviceStateReasonPrivate(Device::State st, Device::StateChangeReason rsn)
0030         : state(st)
0031         , reason(rsn)
0032     {
0033     }
0034     DeviceStateReasonPrivate()
0035         : state(Device::UnknownState)
0036         , reason(Device::UnknownReason)
0037     {
0038     }
0039     Device::State state;
0040     Device::StateChangeReason reason;
0041 };
0042 }
0043 
0044 NetworkManager::DeviceStateReason::DeviceStateReason(Device::State state, Device::StateChangeReason reason)
0045     : d_ptr(new DeviceStateReasonPrivate(state, reason))
0046 {
0047 }
0048 
0049 NetworkManager::DeviceStateReason::DeviceStateReason(const NetworkManager::DeviceStateReason &other)
0050     : d_ptr(new DeviceStateReasonPrivate(*other.d_ptr))
0051 {
0052 }
0053 
0054 NetworkManager::DeviceStateReason::~DeviceStateReason()
0055 {
0056     delete d_ptr;
0057 }
0058 
0059 NetworkManager::Device::State NetworkManager::DeviceStateReason::state() const
0060 {
0061     Q_D(const DeviceStateReason);
0062     return d->state;
0063 }
0064 
0065 NetworkManager::Device::StateChangeReason NetworkManager::DeviceStateReason::reason() const
0066 {
0067     Q_D(const DeviceStateReason);
0068     return d->reason;
0069 }
0070 
0071 NetworkManager::DeviceStateReason &NetworkManager::DeviceStateReason::operator=(const NetworkManager::DeviceStateReason &other)
0072 {
0073     if (&other != this) {
0074         *d_ptr = *other.d_ptr;
0075     }
0076     return *this;
0077 }
0078 
0079 NetworkManager::DevicePrivate::DevicePrivate(const QString &path, NetworkManager::Device *q)
0080 #ifdef NMQT_STATIC
0081     : deviceIface(NetworkManagerPrivate::DBUS_SERVICE, path, QDBusConnection::sessionBus())
0082 #else
0083     : deviceIface(NetworkManagerPrivate::DBUS_SERVICE, path, QDBusConnection::systemBus())
0084 #endif
0085     , uni(path)
0086     , designSpeed(0)
0087     , deviceType(Device::UnknownType)
0088     , dhcp4Config(nullptr)
0089     , dhcp6Config(nullptr)
0090     , mtu(0)
0091     , q_ptr(q)
0092 {
0093 }
0094 
0095 NetworkManager::DevicePrivate::~DevicePrivate()
0096 {
0097 }
0098 
0099 void NetworkManager::DevicePrivate::init()
0100 {
0101     qDBusRegisterMetaType<UIntList>();
0102     qDBusRegisterMetaType<UIntListList>();
0103     qDBusRegisterMetaType<IpV6DBusAddress>();
0104     qDBusRegisterMetaType<IpV6DBusAddressList>();
0105     qDBusRegisterMetaType<IpV6DBusNameservers>();
0106     qDBusRegisterMetaType<IpV6DBusRoute>();
0107     qDBusRegisterMetaType<IpV6DBusRouteList>();
0108     qDBusRegisterMetaType<DeviceDBusStateReason>();
0109 
0110     QDBusConnection::systemBus().connect(NetworkManagerPrivate::DBUS_SERVICE,
0111                                          uni,
0112                                          NetworkManagerPrivate::FDO_DBUS_PROPERTIES,
0113                                          QLatin1String("PropertiesChanged"),
0114                                          this,
0115                                          SLOT(dbusPropertiesChanged(QString, QVariantMap, QStringList)));
0116     QObject::connect(&deviceIface, &OrgFreedesktopNetworkManagerDeviceInterface::StateChanged, this, &DevicePrivate::deviceStateChanged);
0117 
0118 
0119     // The interfaceFlags will return NM_DEVICE_INTERFACE_FLAG_NONE when runtime NM < 1.22
0120     // we initialize the interfaceFlags
0121     interfaceFlags = NetworkManager::Device::Interfaceflag::None;
0122     deviceStatistics = DeviceStatistics::Ptr(new NetworkManager::DeviceStatistics(uni), &QObject::deleteLater);
0123 
0124     // Get all Device's properties at once
0125     QVariantMap initialProperties = NetworkManagerPrivate::retrieveInitialProperties(deviceIface.staticInterfaceName(), uni);
0126     if (!initialProperties.isEmpty()) {
0127         propertiesChanged(initialProperties);
0128     }
0129 
0130 }
0131 
0132 NetworkManager::Device::MeteredStatus NetworkManager::DevicePrivate::convertMeteredStatus(uint metered)
0133 {
0134     NetworkManager::Device::MeteredStatus ourMeteredStatus = (NetworkManager::Device::MeteredStatus)metered;
0135     return ourMeteredStatus;
0136 }
0137 
0138 NetworkManager::Device::Capabilities NetworkManager::DevicePrivate::convertCapabilities(uint theirCaps)
0139 {
0140     NetworkManager::Device::Capabilities ourCaps = (NetworkManager::Device::Capabilities)theirCaps;
0141     return ourCaps;
0142 }
0143 
0144 NetworkManager::Device::Interfaceflags NetworkManager::DevicePrivate::convertInterfaceflags(uint flags)
0145 {
0146     NetworkManager::Device::Interfaceflags ourFlags = static_cast<NetworkManager::Device::Interfaceflags>(flags);
0147     return ourFlags;
0148 }
0149 
0150 NetworkManager::Device::State NetworkManager::DevicePrivate::convertState(uint theirState)
0151 {
0152     NetworkManager::Device::State ourState = static_cast<NetworkManager::Device::State>(theirState);
0153     return ourState;
0154 }
0155 
0156 NetworkManager::Device::StateChangeReason NetworkManager::DevicePrivate::convertReason(uint theirReason)
0157 {
0158     NetworkManager::Device::StateChangeReason ourReason = (NetworkManager::Device::StateChangeReason)theirReason;
0159     return ourReason;
0160 }
0161 
0162 NetworkManager::Device::Type NetworkManager::DevicePrivate::convertType(uint type)
0163 {
0164     // These are identical to NM enums
0165     if (type <= NM_DEVICE_TYPE_TEAM) {
0166         return (NetworkManager::Device::Type)type;
0167     }
0168 
0169     switch (type) {
0170     case 16:
0171         // NM_DEVICE_TYPE_TUN
0172         return NetworkManager::Device::Tun;
0173     case 17:
0174         // NM_DEVICE_TYPE_IP_TUNNEL
0175         return NetworkManager::Device::IpTunnel;
0176     case 18:
0177         // NM_DEVICE_TYPE_MACVLAN
0178         return NetworkManager::Device::MacVlan;
0179     case 19:
0180         // NM_DEVICE_TYPE_VXLAN
0181         return NetworkManager::Device::VxLan;
0182     case 20:
0183         // NM_DEVICE_TYPE_VETH
0184         return NetworkManager::Device::Veth;
0185     case 21:
0186         // NM_DEVICE_TYPE_MACSEC
0187         return NetworkManager::Device::MacSec;
0188     case 22:
0189         // NM_DEVICE_TYPE_DUMMY
0190         return NetworkManager::Device::Dummy;
0191     case 23:
0192         // NM_DEVICE_TYPE_PPP
0193         return NetworkManager::Device::Ppp;
0194     case 24:
0195         // NM_DEVICE_TYPE_OVS_INTERFACE
0196         return NetworkManager::Device::OvsInterface;
0197     case 25:
0198         // NM_DEVICE_TYPE_OVS_PORT
0199         return NetworkManager::Device::OvsPort;
0200     case 26:
0201         // NM_DEVICE_TYPE_OVS_BRIDGE
0202         return NetworkManager::Device::OvsBridge;
0203     case 27:
0204         // NM_DEVICE_TYPE_WPAN
0205         return NetworkManager::Device::Wpan;
0206     case 28:
0207         // NM_DEVICE_TYPE_6LOWPAN
0208         return NetworkManager::Device::Lowpan;
0209     case 29:
0210         // NM_DEVICE_TYPE_NM_DEVICE_TYPE_WIREGUARD
0211         return NetworkManager::Device::WireGuard;
0212     case 30:
0213         // NM_DEVICE_TYPE_WIFI_P2P
0214         return NetworkManager::Device::WifiP2P;
0215     }
0216 
0217     return NetworkManager::Device::UnknownType;
0218 }
0219 
0220 NetworkManager::Device::Device(const QString &path, QObject *parent)
0221     : QObject(parent)
0222     , d_ptr(new DevicePrivate(path, this))
0223 {
0224     Q_D(Device);
0225 
0226     d->init();
0227 }
0228 
0229 NetworkManager::Device::Device(DevicePrivate &dd, QObject *parent)
0230     : QObject(parent)
0231     , d_ptr(&dd)
0232 {
0233     Q_D(Device);
0234 
0235     d->init();
0236 }
0237 
0238 void NetworkManager::DevicePrivate::propertyChanged(const QString &property, const QVariant &value)
0239 {
0240     Q_Q(Device);
0241 
0242     // qCDebug(NMQT) << property  << " - " << value;
0243     if (property == QLatin1String("ActiveConnection")) {
0244         // FIXME workaround, because NM doesn't Q_EMIT correct value
0245         // d->activeConnection = value.value<QDBusObjectPath>.path();
0246         activeConnection = deviceIface.activeConnection().path();
0247         Q_EMIT q->activeConnectionChanged();
0248     } else if (property == QLatin1String("Autoconnect")) {
0249         autoconnect = value.toBool();
0250         Q_EMIT q->autoconnectChanged();
0251     } else if (property == QLatin1String("AvailableConnections")) {
0252         QStringList newAvailableConnections;
0253         const QList<QDBusObjectPath> availableConnectionsTmp = qdbus_cast<QList<QDBusObjectPath>>(value);
0254         for (const QDBusObjectPath &availableConnection : availableConnectionsTmp) {
0255             newAvailableConnections << availableConnection.path();
0256             if (!availableConnections.contains(availableConnection.path())) {
0257                 availableConnections << availableConnection.path();
0258                 Q_EMIT q->availableConnectionAppeared(availableConnection.path());
0259             }
0260         }
0261         auto it = availableConnections.begin();
0262         while (it != availableConnections.end()) {
0263             const QString availableConnection = *it;
0264             if (!newAvailableConnections.contains(availableConnection)) {
0265                 it = availableConnections.erase(it);
0266                 Q_EMIT q->availableConnectionDisappeared(availableConnection);
0267             } else {
0268                 ++it;
0269             }
0270         }
0271         Q_EMIT q->availableConnectionChanged();
0272     } else if (property == QLatin1String("Capabilities")) {
0273         capabilities = NetworkManager::DevicePrivate::convertCapabilities(value.toUInt());
0274         Q_EMIT q->capabilitiesChanged();
0275     } else if (property == QLatin1String("DeviceType")) {
0276         deviceType = convertType(value.toUInt());
0277     } else if (property == QLatin1String("Dhcp4Config")) {
0278         QDBusObjectPath dhcp4ConfigPathTmp = value.value<QDBusObjectPath>();
0279         if (dhcp4ConfigPathTmp.path().isNull()) {
0280             dhcp4Config.clear();
0281             dhcp4ConfigPath.clear();
0282         } else if (!dhcp4Config || dhcp4Config->path() != dhcp4ConfigPathTmp.path()) {
0283             dhcp4Config.clear();
0284             dhcp4ConfigPath = dhcp4ConfigPathTmp.path();
0285         }
0286         Q_EMIT q->dhcp4ConfigChanged();
0287     } else if (property == QLatin1String("Dhcp6Config")) {
0288         QDBusObjectPath dhcp6ConfigPathTmp = value.value<QDBusObjectPath>();
0289         if (dhcp6ConfigPathTmp.path().isNull()) {
0290             dhcp6Config.clear();
0291             dhcp6ConfigPath.clear();
0292         } else if (!dhcp6Config || dhcp6Config->path() != dhcp6ConfigPathTmp.path()) {
0293             dhcp6Config.clear();
0294             dhcp6ConfigPath = dhcp6ConfigPathTmp.path();
0295         }
0296         Q_EMIT q->dhcp6ConfigChanged();
0297     } else if (property == QLatin1String("Driver")) {
0298         driver = value.toString();
0299         Q_EMIT q->driverChanged();
0300     } else if (property == QLatin1String("DriverVersion")) {
0301         driverVersion = value.toString();
0302         Q_EMIT q->driverVersionChanged();
0303     } else if (property == QLatin1String("FirmwareMissing")) {
0304         firmwareMissing = value.toBool();
0305         Q_EMIT q->firmwareMissingChanged();
0306     } else if (property == QLatin1String("FirmwareVersion")) {
0307         firmwareVersion = value.toString();
0308         Q_EMIT q->firmwareVersionChanged();
0309     } else if (property == QLatin1String("Interface")) {
0310         interfaceName = value.toString();
0311         Q_EMIT q->interfaceNameChanged();
0312     } else if (property == QLatin1String("InterfaceFlags")) {
0313         interfaceFlags = NetworkManager::DevicePrivate::convertInterfaceflags(value.toUInt());
0314         Q_EMIT q->interfaceFlagsChanged();
0315     } else if (property == QLatin1String("Ip4Address")) {
0316         ipV4Address = QHostAddress(ntohl(value.toUInt()));
0317         Q_EMIT q->ipV4AddressChanged();
0318     } else if (property == QLatin1String("Ip4Config")) {
0319         QDBusObjectPath ip4ConfigObjectPathTmp = value.value<QDBusObjectPath>();
0320         if (ip4ConfigObjectPathTmp.path().isNull() || ip4ConfigObjectPathTmp.path() == QLatin1String("/")) {
0321             ipV4ConfigPath.clear();
0322         } else {
0323             ipV4ConfigPath = ip4ConfigObjectPathTmp.path();
0324         }
0325         ipV4Config = IpConfig();
0326         Q_EMIT q->ipV4ConfigChanged();
0327     } else if (property == QLatin1String("Ip6Config")) {
0328         QDBusObjectPath ip6ConfigObjectPathTmp = value.value<QDBusObjectPath>();
0329         if (ip6ConfigObjectPathTmp.path().isNull() || ip6ConfigObjectPathTmp.path() == QLatin1String("/")) {
0330             ipV6ConfigPath.clear();
0331         } else {
0332             ipV6ConfigPath = ip6ConfigObjectPathTmp.path();
0333         }
0334         ipV6Config = IpConfig();
0335         Q_EMIT q->ipV6ConfigChanged();
0336     } else if (property == QLatin1String("IpInterface")) {
0337         ipInterface = value.toString();
0338         Q_EMIT q->ipInterfaceChanged();
0339     } else if (property == QLatin1String("Managed")) {
0340         managed = value.toBool();
0341         Q_EMIT q->managedChanged();
0342     } else if (property == QLatin1String("State")) {
0343         connectionState = NetworkManager::DevicePrivate::convertState(value.toUInt());
0344         // FIXME NetworkManager 0.9.8 (maybe greater) doesn't
0345         // update ActiveConnection when disconnected
0346         // This is fixed in NM 73d128bbd17120225bb4986e3f05566f10fab581
0347         if (connectionState == NetworkManager::Device::Disconnected && activeConnection != QLatin1String("/")) {
0348             activeConnection = QLatin1Char('/');
0349             Q_EMIT q->activeConnectionChanged();
0350         }
0351         Q_EMIT q->connectionStateChanged();
0352     } else if (property == QLatin1String("StateReason")) { // just extracting the reason
0353         reason = NetworkManager::DevicePrivate::convertReason(qdbus_cast<DeviceDBusStateReason>(value).reason);
0354         Q_EMIT q->stateReasonChanged();
0355     } else if (property == QLatin1String("Udi")) {
0356         udi = value.toString();
0357         Q_EMIT q->udiChanged();
0358     } else if (property == QLatin1String("PhysicalPortId")) {
0359         physicalPortId = value.toString();
0360         Q_EMIT q->physicalPortIdChanged();
0361     } else if (property == QLatin1String("Mtu")) {
0362         mtu = value.toUInt();
0363         Q_EMIT q->mtuChanged();
0364     } else if (property == QLatin1String("NmPluginMissing")) {
0365         nmPluginMissing = value.toBool();
0366         Q_EMIT q->nmPluginMissingChanged(nmPluginMissing);
0367     } else if (property == QLatin1String("Metered")) {
0368         metered = NetworkManager::DevicePrivate::convertMeteredStatus(value.toUInt());
0369         Q_EMIT q->meteredChanged(metered);
0370     } else {
0371         qCDebug(NMQT) << Q_FUNC_INFO << "Unhandled property" << property;
0372     }
0373 }
0374 
0375 NetworkManager::Device::~Device()
0376 {
0377     Q_D(Device);
0378     delete d;
0379 }
0380 
0381 QString NetworkManager::Device::uni() const
0382 {
0383     Q_D(const Device);
0384     return d->uni;
0385 }
0386 
0387 QString NetworkManager::Device::interfaceName() const
0388 {
0389     Q_D(const Device);
0390     return d->interfaceName;
0391 }
0392 
0393 QString NetworkManager::Device::ipInterfaceName() const
0394 {
0395     Q_D(const Device);
0396     return d->ipInterface;
0397 }
0398 
0399 QString NetworkManager::Device::driver() const
0400 {
0401     Q_D(const Device);
0402     return d->driver;
0403 }
0404 
0405 QString NetworkManager::Device::driverVersion() const
0406 {
0407     Q_D(const Device);
0408     return d->driverVersion;
0409 }
0410 
0411 QString NetworkManager::Device::firmwareVersion() const
0412 {
0413     Q_D(const Device);
0414     return d->firmwareVersion;
0415 }
0416 
0417 NetworkManager::ActiveConnection::Ptr NetworkManager::Device::activeConnection() const
0418 {
0419     Q_D(const Device);
0420     return NetworkManager::findActiveConnection(d->activeConnection);
0421 }
0422 
0423 NetworkManager::Connection::List NetworkManager::Device::availableConnections()
0424 {
0425     Q_D(const Device);
0426 
0427     NetworkManager::Connection::List list;
0428     for (const QString &availableConnection : std::as_const(d->availableConnections)) {
0429         NetworkManager::Connection::Ptr connection = NetworkManager::findConnection(availableConnection);
0430         if (connection) {
0431             list << connection;
0432         }
0433     }
0434 
0435     return list;
0436 }
0437 
0438 bool NetworkManager::Device::firmwareMissing() const
0439 {
0440     Q_D(const Device);
0441     return d->firmwareMissing;
0442 }
0443 
0444 bool NetworkManager::Device::autoconnect() const
0445 {
0446     Q_D(const Device);
0447     return d->autoconnect;
0448 }
0449 
0450 void NetworkManager::Device::setAutoconnect(bool autoconnect)
0451 {
0452     Q_D(Device);
0453     d->deviceIface.setAutoconnect(autoconnect);
0454 }
0455 
0456 QString NetworkManager::Device::udi() const
0457 {
0458     Q_D(const Device);
0459     return d->udi;
0460 }
0461 
0462 QString NetworkManager::Device::physicalPortId() const
0463 {
0464     Q_D(const Device);
0465     return d->physicalPortId;
0466 }
0467 
0468 QHostAddress NetworkManager::Device::ipV4Address() const
0469 {
0470     Q_D(const Device);
0471     return d->ipV4Address;
0472 }
0473 
0474 NetworkManager::DeviceStateReason NetworkManager::Device::stateReason() const
0475 {
0476     Q_D(const Device);
0477     return DeviceStateReason(d->connectionState, d->reason);
0478 }
0479 
0480 NetworkManager::IpConfig NetworkManager::Device::ipV4Config() const
0481 {
0482     Q_D(const Device);
0483     if (!d->ipV4Config.isValid() && !d->ipV4ConfigPath.isNull()) {
0484         d->ipV4Config.setIPv4Path(d->ipV4ConfigPath);
0485     }
0486     return d->ipV4Config;
0487 }
0488 
0489 NetworkManager::IpConfig NetworkManager::Device::ipV6Config() const
0490 {
0491     Q_D(const Device);
0492     if (!d->ipV6Config.isValid() && !d->ipV6ConfigPath.isNull()) {
0493         d->ipV6Config.setIPv6Path(d->ipV6ConfigPath);
0494     }
0495     return d->ipV6Config;
0496 }
0497 
0498 NetworkManager::Dhcp4Config::Ptr NetworkManager::Device::dhcp4Config() const
0499 {
0500     Q_D(const Device);
0501     if (!d->dhcp4Config && !d->dhcp4ConfigPath.isNull()) {
0502         d->dhcp4Config = NetworkManager::Dhcp4Config::Ptr(new Dhcp4Config(d->dhcp4ConfigPath), &QObject::deleteLater);
0503     }
0504     return d->dhcp4Config;
0505 }
0506 
0507 NetworkManager::Dhcp6Config::Ptr NetworkManager::Device::dhcp6Config() const
0508 {
0509     Q_D(const Device);
0510     if (!d->dhcp6Config && !d->dhcp6ConfigPath.isNull()) {
0511         d->dhcp6Config = NetworkManager::Dhcp6Config::Ptr(new Dhcp6Config(d->dhcp6ConfigPath), &QObject::deleteLater);
0512     }
0513     return d->dhcp6Config;
0514 }
0515 
0516 bool NetworkManager::Device::isActive() const
0517 {
0518     Q_D(const Device);
0519     /* clang-format off */
0520     return !(d->connectionState == NetworkManager::Device::Unavailable
0521              || d->connectionState == NetworkManager::Device::Unmanaged
0522              || d->connectionState == NetworkManager::Device::Disconnected
0523              || d->connectionState == NetworkManager::Device::Failed);
0524     /* clang-format on */
0525 }
0526 
0527 bool NetworkManager::Device::isValid() const
0528 {
0529     Q_D(const Device);
0530     return d->deviceIface.isValid();
0531 }
0532 
0533 bool NetworkManager::Device::managed() const
0534 {
0535     Q_D(const Device);
0536     return d->managed;
0537 }
0538 
0539 NetworkManager::Device::Interfaceflags NetworkManager::Device::interfaceFlags() const
0540 {
0541     Q_D(const Device);
0542     return d->interfaceFlags;
0543 }
0544 
0545 uint NetworkManager::Device::mtu() const
0546 {
0547     Q_D(const Device);
0548     return d->mtu;
0549 }
0550 
0551 bool NetworkManager::Device::nmPluginMissing() const
0552 {
0553     Q_D(const Device);
0554     return d->nmPluginMissing;
0555 }
0556 
0557 NetworkManager::Device::MeteredStatus NetworkManager::Device::metered() const
0558 {
0559     Q_D(const Device);
0560     return d->metered;
0561 }
0562 
0563 QDBusPendingReply<> NetworkManager::Device::reapplyConnection(const NMVariantMapMap &connection, qulonglong version_id, uint flags)
0564 {
0565     Q_D(Device);
0566     return d->deviceIface.Reapply(connection, version_id, flags);
0567 }
0568 
0569 QDBusPendingReply<> NetworkManager::Device::disconnectInterface()
0570 {
0571     Q_D(Device);
0572     return d->deviceIface.Disconnect();
0573 }
0574 
0575 QDBusPendingReply<> NetworkManager::Device::deleteInterface()
0576 {
0577     if (NetworkManager::checkVersion(1, 0, 0)) {
0578         Q_D(Device);
0579         return d->deviceIface.Delete();
0580     } else {
0581         return QDBusPendingReply<>();
0582     }
0583 }
0584 
0585 NetworkManager::Device::State NetworkManager::Device::state() const
0586 {
0587     Q_D(const Device);
0588     return d->connectionState;
0589 }
0590 
0591 int NetworkManager::Device::designSpeed() const
0592 {
0593     Q_D(const Device);
0594     return d->designSpeed;
0595 }
0596 
0597 NetworkManager::Device::Capabilities NetworkManager::Device::capabilities() const
0598 {
0599     Q_D(const Device);
0600     return d->capabilities;
0601 }
0602 
0603 QVariant NetworkManager::Device::capabilitiesV() const
0604 {
0605     Q_D(const Device);
0606     return QVariant(d->capabilities);
0607 }
0608 
0609 NetworkManager::DeviceStatistics::Ptr NetworkManager::Device::deviceStatistics() const
0610 {
0611     Q_D(const Device);
0612     return d->deviceStatistics;
0613 }
0614 
0615 void NetworkManager::DevicePrivate::deviceStateChanged(uint newState, uint oldState, uint reason)
0616 {
0617     Q_Q(Device);
0618     connectionState = NetworkManager::DevicePrivate::convertState(newState);
0619     reason = NetworkManager::DevicePrivate::convertReason(reason);
0620 
0621     Q_EMIT q->stateChanged(connectionState, NetworkManager::DevicePrivate::convertState(oldState), NetworkManager::DevicePrivate::convertReason(reason));
0622 }
0623 
0624 void NetworkManager::DevicePrivate::dbusPropertiesChanged(const QString &interfaceName, const QVariantMap &properties, const QStringList &invalidatedProperties)
0625 {
0626     Q_UNUSED(invalidatedProperties);
0627     if (interfaceName.contains(QLatin1String("org.freedesktop.NetworkManager.Device"))
0628         && interfaceName != QLatin1String("org.freedesktop.NetworkManager.Device.Statistics")) {
0629         propertiesChanged(properties);
0630     }
0631 }
0632 
0633 void NetworkManager::DevicePrivate::propertiesChanged(const QVariantMap &properties)
0634 {
0635     // qCDebug(NMQT) << Q_FUNC_INFO << properties;
0636 
0637     QVariantMap::const_iterator it = properties.constBegin();
0638     while (it != properties.constEnd()) {
0639         propertyChanged(it.key(), it.value());
0640         ++it;
0641     }
0642 
0643     // FIXME workaround, we need to get a path to updated IPv[46]Config,
0644     // because NM doesn't Q_EMIT the updated value when the device is activated
0645     // BUG: https://bugzilla.gnome.org/show_bug.cgi?id=725657
0646     if (properties.contains(QLatin1String("State")) && connectionState == NetworkManager::Device::Activated) {
0647         propertyChanged(QLatin1String("Ip4Config"), QVariant::fromValue<QDBusObjectPath>(deviceIface.ip4Config()));
0648         propertyChanged(QLatin1String("Ip6Config"), QVariant::fromValue<QDBusObjectPath>(deviceIface.ip6Config()));
0649     }
0650 }
0651 
0652 NetworkManager::Device::Type NetworkManager::Device::type() const
0653 {
0654     Q_D(const Device);
0655     return d->deviceType;
0656 }
0657 
0658 #include "moc_device.cpp"
0659 #include "moc_device_p.cpp"