File indexing completed on 2024-04-21 15:06:25

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     deviceStatistics = DeviceStatistics::Ptr(new NetworkManager::DeviceStatistics(uni), &QObject::deleteLater);
0120 
0121     // Get all Device's properties at once
0122     QVariantMap initialProperties = NetworkManagerPrivate::retrieveInitialProperties(deviceIface.staticInterfaceName(), uni);
0123     if (!initialProperties.isEmpty()) {
0124         propertiesChanged(initialProperties);
0125     }
0126 
0127 }
0128 
0129 NetworkManager::Device::MeteredStatus NetworkManager::DevicePrivate::convertMeteredStatus(uint metered)
0130 {
0131     NetworkManager::Device::MeteredStatus ourMeteredStatus = (NetworkManager::Device::MeteredStatus)metered;
0132     return ourMeteredStatus;
0133 }
0134 
0135 NetworkManager::Device::Capabilities NetworkManager::DevicePrivate::convertCapabilities(uint theirCaps)
0136 {
0137     NetworkManager::Device::Capabilities ourCaps = (NetworkManager::Device::Capabilities)theirCaps;
0138     return ourCaps;
0139 }
0140 
0141 NetworkManager::Device::State NetworkManager::DevicePrivate::convertState(uint theirState)
0142 {
0143     NetworkManager::Device::State ourState = static_cast<NetworkManager::Device::State>(theirState);
0144     return ourState;
0145 }
0146 
0147 NetworkManager::Device::StateChangeReason NetworkManager::DevicePrivate::convertReason(uint theirReason)
0148 {
0149     NetworkManager::Device::StateChangeReason ourReason = (NetworkManager::Device::StateChangeReason)theirReason;
0150     return ourReason;
0151 }
0152 
0153 NetworkManager::Device::Type NetworkManager::DevicePrivate::convertType(uint type)
0154 {
0155     // These are identical to NM enums
0156     if (type <= NM_DEVICE_TYPE_TEAM) {
0157         return (NetworkManager::Device::Type)type;
0158     }
0159 
0160     switch (type) {
0161     case 16:
0162         // NM_DEVICE_TYPE_TUN
0163         return NetworkManager::Device::Tun;
0164     case 17:
0165         // NM_DEVICE_TYPE_IP_TUNNEL
0166         return NetworkManager::Device::IpTunnel;
0167     case 18:
0168         // NM_DEVICE_TYPE_MACVLAN
0169         return NetworkManager::Device::MacVlan;
0170     case 19:
0171         // NM_DEVICE_TYPE_VXLAN
0172         return NetworkManager::Device::VxLan;
0173     case 20:
0174         // NM_DEVICE_TYPE_VETH
0175         return NetworkManager::Device::Veth;
0176     case 21:
0177         // NM_DEVICE_TYPE_MACSEC
0178         return NetworkManager::Device::MacSec;
0179     case 22:
0180         // NM_DEVICE_TYPE_DUMMY
0181         return NetworkManager::Device::Dummy;
0182     case 23:
0183         // NM_DEVICE_TYPE_PPP
0184         return NetworkManager::Device::Ppp;
0185     case 24:
0186         // NM_DEVICE_TYPE_OVS_INTERFACE
0187         return NetworkManager::Device::OvsInterface;
0188     case 25:
0189         // NM_DEVICE_TYPE_OVS_PORT
0190         return NetworkManager::Device::OvsPort;
0191     case 26:
0192         // NM_DEVICE_TYPE_OVS_BRIDGE
0193         return NetworkManager::Device::OvsBridge;
0194     case 27:
0195         // NM_DEVICE_TYPE_WPAN
0196         return NetworkManager::Device::Wpan;
0197     case 28:
0198         // NM_DEVICE_TYPE_6LOWPAN
0199         return NetworkManager::Device::Lowpan;
0200     case 29:
0201         // NM_DEVICE_TYPE_NM_DEVICE_TYPE_WIREGUARD
0202         return NetworkManager::Device::WireGuard;
0203     case 30:
0204         // NM_DEVICE_TYPE_WIFI_P2P
0205         return NetworkManager::Device::WifiP2P;
0206     }
0207 
0208     return NetworkManager::Device::UnknownType;
0209 }
0210 
0211 NetworkManager::Device::Device(const QString &path, QObject *parent)
0212     : QObject(parent)
0213     , d_ptr(new DevicePrivate(path, this))
0214 {
0215     Q_D(Device);
0216 
0217     d->init();
0218 }
0219 
0220 NetworkManager::Device::Device(DevicePrivate &dd, QObject *parent)
0221     : QObject(parent)
0222     , d_ptr(&dd)
0223 {
0224     Q_D(Device);
0225 
0226     d->init();
0227 }
0228 
0229 void NetworkManager::DevicePrivate::propertyChanged(const QString &property, const QVariant &value)
0230 {
0231     Q_Q(Device);
0232 
0233     // qCDebug(NMQT) << property  << " - " << value;
0234     if (property == QLatin1String("ActiveConnection")) {
0235         // FIXME workaround, because NM doesn't Q_EMIT correct value
0236         // d->activeConnection = value.value<QDBusObjectPath>.path();
0237         activeConnection = deviceIface.activeConnection().path();
0238         Q_EMIT q->activeConnectionChanged();
0239     } else if (property == QLatin1String("Autoconnect")) {
0240         autoconnect = value.toBool();
0241         Q_EMIT q->autoconnectChanged();
0242     } else if (property == QLatin1String("AvailableConnections")) {
0243         QStringList newAvailableConnections;
0244         const QList<QDBusObjectPath> availableConnectionsTmp = qdbus_cast<QList<QDBusObjectPath>>(value);
0245         for (const QDBusObjectPath &availableConnection : availableConnectionsTmp) {
0246             newAvailableConnections << availableConnection.path();
0247             if (!availableConnections.contains(availableConnection.path())) {
0248                 availableConnections << availableConnection.path();
0249                 Q_EMIT q->availableConnectionAppeared(availableConnection.path());
0250             }
0251         }
0252         auto it = availableConnections.begin();
0253         while (it != availableConnections.end()) {
0254             const QString availableConnection = *it;
0255             if (!newAvailableConnections.contains(availableConnection)) {
0256                 it = availableConnections.erase(it);
0257                 Q_EMIT q->availableConnectionDisappeared(availableConnection);
0258             } else {
0259                 ++it;
0260             }
0261         }
0262         Q_EMIT q->availableConnectionChanged();
0263     } else if (property == QLatin1String("Capabilities")) {
0264         capabilities = NetworkManager::DevicePrivate::convertCapabilities(value.toUInt());
0265         Q_EMIT q->capabilitiesChanged();
0266     } else if (property == QLatin1String("DeviceType")) {
0267         deviceType = convertType(value.toUInt());
0268     } else if (property == QLatin1String("Dhcp4Config")) {
0269         QDBusObjectPath dhcp4ConfigPathTmp = value.value<QDBusObjectPath>();
0270         if (dhcp4ConfigPathTmp.path().isNull()) {
0271             dhcp4Config.clear();
0272             dhcp4ConfigPath.clear();
0273         } else if (!dhcp4Config || dhcp4Config->path() != dhcp4ConfigPathTmp.path()) {
0274             dhcp4Config.clear();
0275             dhcp4ConfigPath = dhcp4ConfigPathTmp.path();
0276         }
0277         Q_EMIT q->dhcp4ConfigChanged();
0278     } else if (property == QLatin1String("Dhcp6Config")) {
0279         QDBusObjectPath dhcp6ConfigPathTmp = value.value<QDBusObjectPath>();
0280         if (dhcp6ConfigPathTmp.path().isNull()) {
0281             dhcp6Config.clear();
0282             dhcp6ConfigPath.clear();
0283         } else if (!dhcp6Config || dhcp6Config->path() != dhcp6ConfigPathTmp.path()) {
0284             dhcp6Config.clear();
0285             dhcp6ConfigPath = dhcp6ConfigPathTmp.path();
0286         }
0287         Q_EMIT q->dhcp6ConfigChanged();
0288     } else if (property == QLatin1String("Driver")) {
0289         driver = value.toString();
0290         Q_EMIT q->driverChanged();
0291     } else if (property == QLatin1String("DriverVersion")) {
0292         driverVersion = value.toString();
0293         Q_EMIT q->driverVersionChanged();
0294     } else if (property == QLatin1String("FirmwareMissing")) {
0295         firmwareMissing = value.toBool();
0296         Q_EMIT q->firmwareMissingChanged();
0297     } else if (property == QLatin1String("FirmwareVersion")) {
0298         firmwareVersion = value.toString();
0299         Q_EMIT q->firmwareVersionChanged();
0300     } else if (property == QLatin1String("Interface")) {
0301         interfaceName = value.toString();
0302         Q_EMIT q->interfaceNameChanged();
0303     } else if (property == QLatin1String("Ip4Address")) {
0304         ipV4Address = QHostAddress(ntohl(value.toUInt()));
0305         Q_EMIT q->ipV4AddressChanged();
0306     } else if (property == QLatin1String("Ip4Config")) {
0307         QDBusObjectPath ip4ConfigObjectPathTmp = value.value<QDBusObjectPath>();
0308         if (ip4ConfigObjectPathTmp.path().isNull() || ip4ConfigObjectPathTmp.path() == QLatin1String("/")) {
0309             ipV4ConfigPath.clear();
0310         } else {
0311             ipV4ConfigPath = ip4ConfigObjectPathTmp.path();
0312         }
0313         ipV4Config = IpConfig();
0314         Q_EMIT q->ipV4ConfigChanged();
0315     } else if (property == QLatin1String("Ip6Config")) {
0316         QDBusObjectPath ip6ConfigObjectPathTmp = value.value<QDBusObjectPath>();
0317         if (ip6ConfigObjectPathTmp.path().isNull() || ip6ConfigObjectPathTmp.path() == QLatin1String("/")) {
0318             ipV6ConfigPath.clear();
0319         } else {
0320             ipV6ConfigPath = ip6ConfigObjectPathTmp.path();
0321         }
0322         ipV6Config = IpConfig();
0323         Q_EMIT q->ipV6ConfigChanged();
0324     } else if (property == QLatin1String("IpInterface")) {
0325         ipInterface = value.toString();
0326         Q_EMIT q->ipInterfaceChanged();
0327     } else if (property == QLatin1String("Managed")) {
0328         managed = value.toBool();
0329         Q_EMIT q->managedChanged();
0330     } else if (property == QLatin1String("State")) {
0331         connectionState = NetworkManager::DevicePrivate::convertState(value.toUInt());
0332         // FIXME NetworkManager 0.9.8 (maybe greater) doesn't
0333         // update ActiveConnection when disconnected
0334         // This is fixed in NM 73d128bbd17120225bb4986e3f05566f10fab581
0335         if (connectionState == NetworkManager::Device::Disconnected && activeConnection != QLatin1String("/")) {
0336             activeConnection = QLatin1Char('/');
0337             Q_EMIT q->activeConnectionChanged();
0338         }
0339         Q_EMIT q->connectionStateChanged();
0340     } else if (property == QLatin1String("StateReason")) { // just extracting the reason
0341         reason = NetworkManager::DevicePrivate::convertReason(qdbus_cast<DeviceDBusStateReason>(value).reason);
0342         Q_EMIT q->stateReasonChanged();
0343     } else if (property == QLatin1String("Udi")) {
0344         udi = value.toString();
0345         Q_EMIT q->udiChanged();
0346     } else if (property == QLatin1String("PhysicalPortId")) {
0347         physicalPortId = value.toString();
0348         Q_EMIT q->physicalPortIdChanged();
0349     } else if (property == QLatin1String("Mtu")) {
0350         mtu = value.toUInt();
0351         Q_EMIT q->mtuChanged();
0352     } else if (property == QLatin1String("NmPluginMissing")) {
0353         nmPluginMissing = value.toBool();
0354         Q_EMIT q->nmPluginMissingChanged(nmPluginMissing);
0355     } else if (property == QLatin1String("Metered")) {
0356         metered = NetworkManager::DevicePrivate::convertMeteredStatus(value.toUInt());
0357         Q_EMIT q->meteredChanged(metered);
0358     } else {
0359         qCDebug(NMQT) << Q_FUNC_INFO << "Unhandled property" << property;
0360     }
0361 }
0362 
0363 NetworkManager::Device::~Device()
0364 {
0365     Q_D(Device);
0366     delete d;
0367 }
0368 
0369 QString NetworkManager::Device::uni() const
0370 {
0371     Q_D(const Device);
0372     return d->uni;
0373 }
0374 
0375 QString NetworkManager::Device::interfaceName() const
0376 {
0377     Q_D(const Device);
0378     return d->interfaceName;
0379 }
0380 
0381 QString NetworkManager::Device::ipInterfaceName() const
0382 {
0383     Q_D(const Device);
0384     return d->ipInterface;
0385 }
0386 
0387 QString NetworkManager::Device::driver() const
0388 {
0389     Q_D(const Device);
0390     return d->driver;
0391 }
0392 
0393 QString NetworkManager::Device::driverVersion() const
0394 {
0395     Q_D(const Device);
0396     return d->driverVersion;
0397 }
0398 
0399 QString NetworkManager::Device::firmwareVersion() const
0400 {
0401     Q_D(const Device);
0402     return d->firmwareVersion;
0403 }
0404 
0405 NetworkManager::ActiveConnection::Ptr NetworkManager::Device::activeConnection() const
0406 {
0407     Q_D(const Device);
0408     return NetworkManager::findActiveConnection(d->activeConnection);
0409 }
0410 
0411 NetworkManager::Connection::List NetworkManager::Device::availableConnections()
0412 {
0413     Q_D(const Device);
0414 
0415     NetworkManager::Connection::List list;
0416     for (const QString &availableConnection : std::as_const(d->availableConnections)) {
0417         NetworkManager::Connection::Ptr connection = NetworkManager::findConnection(availableConnection);
0418         if (connection) {
0419             list << connection;
0420         }
0421     }
0422 
0423     return list;
0424 }
0425 
0426 bool NetworkManager::Device::firmwareMissing() const
0427 {
0428     Q_D(const Device);
0429     return d->firmwareMissing;
0430 }
0431 
0432 bool NetworkManager::Device::autoconnect() const
0433 {
0434     Q_D(const Device);
0435     return d->autoconnect;
0436 }
0437 
0438 void NetworkManager::Device::setAutoconnect(bool autoconnect)
0439 {
0440     Q_D(Device);
0441     d->deviceIface.setAutoconnect(autoconnect);
0442 }
0443 
0444 QString NetworkManager::Device::udi() const
0445 {
0446     Q_D(const Device);
0447     return d->udi;
0448 }
0449 
0450 QString NetworkManager::Device::physicalPortId() const
0451 {
0452     Q_D(const Device);
0453     return d->physicalPortId;
0454 }
0455 
0456 QHostAddress NetworkManager::Device::ipV4Address() const
0457 {
0458     Q_D(const Device);
0459     return d->ipV4Address;
0460 }
0461 
0462 NetworkManager::DeviceStateReason NetworkManager::Device::stateReason() const
0463 {
0464     Q_D(const Device);
0465     return DeviceStateReason(d->connectionState, d->reason);
0466 }
0467 
0468 NetworkManager::IpConfig NetworkManager::Device::ipV4Config() const
0469 {
0470     Q_D(const Device);
0471     if (!d->ipV4Config.isValid() && !d->ipV4ConfigPath.isNull()) {
0472         d->ipV4Config.setIPv4Path(d->ipV4ConfigPath);
0473     }
0474     return d->ipV4Config;
0475 }
0476 
0477 NetworkManager::IpConfig NetworkManager::Device::ipV6Config() const
0478 {
0479     Q_D(const Device);
0480     if (!d->ipV6Config.isValid() && !d->ipV6ConfigPath.isNull()) {
0481         d->ipV6Config.setIPv6Path(d->ipV6ConfigPath);
0482     }
0483     return d->ipV6Config;
0484 }
0485 
0486 NetworkManager::Dhcp4Config::Ptr NetworkManager::Device::dhcp4Config() const
0487 {
0488     Q_D(const Device);
0489     if (!d->dhcp4Config && !d->dhcp4ConfigPath.isNull()) {
0490         d->dhcp4Config = NetworkManager::Dhcp4Config::Ptr(new Dhcp4Config(d->dhcp4ConfigPath), &QObject::deleteLater);
0491     }
0492     return d->dhcp4Config;
0493 }
0494 
0495 NetworkManager::Dhcp6Config::Ptr NetworkManager::Device::dhcp6Config() const
0496 {
0497     Q_D(const Device);
0498     if (!d->dhcp6Config && !d->dhcp6ConfigPath.isNull()) {
0499         d->dhcp6Config = NetworkManager::Dhcp6Config::Ptr(new Dhcp6Config(d->dhcp6ConfigPath), &QObject::deleteLater);
0500     }
0501     return d->dhcp6Config;
0502 }
0503 
0504 bool NetworkManager::Device::isActive() const
0505 {
0506     Q_D(const Device);
0507     /* clang-format off */
0508     return !(d->connectionState == NetworkManager::Device::Unavailable
0509              || d->connectionState == NetworkManager::Device::Unmanaged
0510              || d->connectionState == NetworkManager::Device::Disconnected
0511              || d->connectionState == NetworkManager::Device::Failed);
0512     /* clang-format on */
0513 }
0514 
0515 bool NetworkManager::Device::isValid() const
0516 {
0517     Q_D(const Device);
0518     return d->deviceIface.isValid();
0519 }
0520 
0521 bool NetworkManager::Device::managed() const
0522 {
0523     Q_D(const Device);
0524     return d->managed;
0525 }
0526 
0527 uint NetworkManager::Device::mtu() const
0528 {
0529     Q_D(const Device);
0530     return d->mtu;
0531 }
0532 
0533 bool NetworkManager::Device::nmPluginMissing() const
0534 {
0535     Q_D(const Device);
0536     return d->nmPluginMissing;
0537 }
0538 
0539 NetworkManager::Device::MeteredStatus NetworkManager::Device::metered() const
0540 {
0541     Q_D(const Device);
0542     return d->metered;
0543 }
0544 
0545 QDBusPendingReply<> NetworkManager::Device::reapplyConnection(const NMVariantMapMap &connection, qulonglong version_id, uint flags)
0546 {
0547     Q_D(Device);
0548     return d->deviceIface.Reapply(connection, version_id, flags);
0549 }
0550 
0551 QDBusPendingReply<> NetworkManager::Device::disconnectInterface()
0552 {
0553     Q_D(Device);
0554     return d->deviceIface.Disconnect();
0555 }
0556 
0557 QDBusPendingReply<> NetworkManager::Device::deleteInterface()
0558 {
0559     if (NetworkManager::checkVersion(1, 0, 0)) {
0560         Q_D(Device);
0561         return d->deviceIface.Delete();
0562     } else {
0563         return QDBusPendingReply<>();
0564     }
0565 }
0566 
0567 NetworkManager::Device::State NetworkManager::Device::state() const
0568 {
0569     Q_D(const Device);
0570     return d->connectionState;
0571 }
0572 
0573 int NetworkManager::Device::designSpeed() const
0574 {
0575     Q_D(const Device);
0576     return d->designSpeed;
0577 }
0578 
0579 NetworkManager::Device::Capabilities NetworkManager::Device::capabilities() const
0580 {
0581     Q_D(const Device);
0582     return d->capabilities;
0583 }
0584 
0585 QVariant NetworkManager::Device::capabilitiesV() const
0586 {
0587     Q_D(const Device);
0588     return QVariant(d->capabilities);
0589 }
0590 
0591 NetworkManager::DeviceStatistics::Ptr NetworkManager::Device::deviceStatistics() const
0592 {
0593     Q_D(const Device);
0594     return d->deviceStatistics;
0595 }
0596 
0597 void NetworkManager::DevicePrivate::deviceStateChanged(uint newState, uint oldState, uint reason)
0598 {
0599     Q_Q(Device);
0600     connectionState = NetworkManager::DevicePrivate::convertState(newState);
0601     reason = NetworkManager::DevicePrivate::convertReason(reason);
0602 
0603     Q_EMIT q->stateChanged(connectionState, NetworkManager::DevicePrivate::convertState(oldState), NetworkManager::DevicePrivate::convertReason(reason));
0604 }
0605 
0606 void NetworkManager::DevicePrivate::dbusPropertiesChanged(const QString &interfaceName, const QVariantMap &properties, const QStringList &invalidatedProperties)
0607 {
0608     Q_UNUSED(invalidatedProperties);
0609     if (interfaceName.contains(QLatin1String("org.freedesktop.NetworkManager.Device"))
0610         && interfaceName != QLatin1String("org.freedesktop.NetworkManager.Device.Statistics")) {
0611         propertiesChanged(properties);
0612     }
0613 }
0614 
0615 void NetworkManager::DevicePrivate::propertiesChanged(const QVariantMap &properties)
0616 {
0617     // qCDebug(NMQT) << Q_FUNC_INFO << properties;
0618 
0619     QVariantMap::const_iterator it = properties.constBegin();
0620     while (it != properties.constEnd()) {
0621         propertyChanged(it.key(), it.value());
0622         ++it;
0623     }
0624 
0625     // FIXME workaround, we need to get a path to updated IPv[46]Config,
0626     // because NM doesn't Q_EMIT the updated value when the device is activated
0627     // BUG: https://bugzilla.gnome.org/show_bug.cgi?id=725657
0628     if (properties.contains(QLatin1String("State")) && connectionState == NetworkManager::Device::Activated) {
0629         propertyChanged(QLatin1String("Ip4Config"), QVariant::fromValue<QDBusObjectPath>(deviceIface.ip4Config()));
0630         propertyChanged(QLatin1String("Ip6Config"), QVariant::fromValue<QDBusObjectPath>(deviceIface.ip6Config()));
0631     }
0632 }
0633 
0634 NetworkManager::Device::Type NetworkManager::Device::type() const
0635 {
0636     Q_D(const Device);
0637     return d->deviceType;
0638 }
0639 
0640 #include "moc_device.cpp"
0641 #include "moc_device_p.cpp"