1/*
2 SPDX-FileCopyrightText: 2008, 2010 Will Stephenson <wstephenson@kde.org>
3 SPDX-FileCopyrightText: 2013 Daniel Nicoletti <dantti12@gmail.com>
4 SPDX-FileCopyrightText: 2013 Jan Grulich <jgrulich@redhat.com>
5
6 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
7*/
8
9#include "connection.h"
10#include "device_p.h"
11#include "manager.h"
12#include "manager_p.h"
13#include "nmdebug.h"
14#include "settings.h"
15
16#include <arpa/inet.h>
17
18#include <QDBusMetaType>
19#include <QDBusObjectPath>
20
21// logging category for this framework, default: log stuff >= warning
22Q_LOGGING_CATEGORY(NMQT, "kf.networkmanagerqt", QtWarningMsg)
23
24namespace NetworkManager
25{
26class DeviceStateReasonPrivate
27{
28public:
29 DeviceStateReasonPrivate(Device::State st, Device::StateChangeReason rsn)
30 : state(st)
31 , reason(rsn)
32 {
33 }
34 DeviceStateReasonPrivate()
35 : state(Device::UnknownState)
36 , reason(Device::UnknownReason)
37 {
38 }
39 Device::State state;
40 Device::StateChangeReason reason;
41};
42}
43
44NetworkManager::DeviceStateReason::DeviceStateReason(Device::State state, Device::StateChangeReason reason)
45 : d_ptr(new DeviceStateReasonPrivate(state, reason))
46{
47}
48
49NetworkManager::DeviceStateReason::DeviceStateReason(const NetworkManager::DeviceStateReason &other)
50 : d_ptr(new DeviceStateReasonPrivate(*other.d_ptr))
51{
52}
53
54NetworkManager::DeviceStateReason::~DeviceStateReason()
55{
56 delete d_ptr;
57}
58
59NetworkManager::Device::State NetworkManager::DeviceStateReason::state() const
60{
61 Q_D(const DeviceStateReason);
62 return d->state;
63}
64
65NetworkManager::Device::StateChangeReason NetworkManager::DeviceStateReason::reason() const
66{
67 Q_D(const DeviceStateReason);
68 return d->reason;
69}
70
71NetworkManager::DeviceStateReason &NetworkManager::DeviceStateReason::operator=(const NetworkManager::DeviceStateReason &other)
72{
73 if (&other != this) {
74 *d_ptr = *other.d_ptr;
75 }
76 return *this;
77}
78
79NetworkManager::DevicePrivate::DevicePrivate(const QString &path, NetworkManager::Device *q)
80#ifdef NMQT_STATIC
81 : deviceIface(NetworkManagerPrivate::DBUS_SERVICE, path, QDBusConnection::sessionBus())
82#else
83 : deviceIface(NetworkManagerPrivate::DBUS_SERVICE, path, QDBusConnection::systemBus())
84#endif
85 , uni(path)
86 , designSpeed(0)
87 , deviceType(Device::UnknownType)
88 , dhcp4Config(nullptr)
89 , dhcp6Config(nullptr)
90 , mtu(0)
91 , q_ptr(q)
92{
93}
94
95NetworkManager::DevicePrivate::~DevicePrivate()
96{
97}
98
99void NetworkManager::DevicePrivate::init()
100{
101 qDBusRegisterMetaType<UIntList>();
102 qDBusRegisterMetaType<UIntListList>();
103 qDBusRegisterMetaType<IpV6DBusAddress>();
104 qDBusRegisterMetaType<IpV6DBusAddressList>();
105 qDBusRegisterMetaType<IpV6DBusNameservers>();
106 qDBusRegisterMetaType<IpV6DBusRoute>();
107 qDBusRegisterMetaType<IpV6DBusRouteList>();
108 qDBusRegisterMetaType<DeviceDBusStateReason>();
109
110 QDBusConnection::systemBus().connect(service: NetworkManagerPrivate::DBUS_SERVICE,
111 path: uni,
112 interface: NetworkManagerPrivate::FDO_DBUS_PROPERTIES,
113 name: QLatin1String("PropertiesChanged"),
114 receiver: this,
115 SLOT(dbusPropertiesChanged(QString, QVariantMap, QStringList)));
116 QObject::connect(sender: &deviceIface, signal: &OrgFreedesktopNetworkManagerDeviceInterface::StateChanged, context: this, slot: &DevicePrivate::deviceStateChanged);
117
118
119 // The interfaceFlags will return NM_DEVICE_INTERFACE_FLAG_NONE when runtime NM < 1.22
120 // we initialize the interfaceFlags
121 interfaceFlags = NetworkManager::Device::Interfaceflag::None;
122 deviceStatistics = DeviceStatistics::Ptr(new NetworkManager::DeviceStatistics(uni), &QObject::deleteLater);
123
124 // Get all Device's properties at once
125 QVariantMap initialProperties = NetworkManagerPrivate::retrieveInitialProperties(interfaceName: deviceIface.staticInterfaceName(), path: uni);
126 if (!initialProperties.isEmpty()) {
127 propertiesChanged(properties: initialProperties);
128 }
129
130}
131
132NetworkManager::Device::MeteredStatus NetworkManager::DevicePrivate::convertMeteredStatus(uint metered)
133{
134 NetworkManager::Device::MeteredStatus ourMeteredStatus = (NetworkManager::Device::MeteredStatus)metered;
135 return ourMeteredStatus;
136}
137
138NetworkManager::Device::Capabilities NetworkManager::DevicePrivate::convertCapabilities(uint theirCaps)
139{
140 NetworkManager::Device::Capabilities ourCaps = (NetworkManager::Device::Capabilities)theirCaps;
141 return ourCaps;
142}
143
144NetworkManager::Device::Interfaceflags NetworkManager::DevicePrivate::convertInterfaceflags(uint flags)
145{
146 NetworkManager::Device::Interfaceflags ourFlags = static_cast<NetworkManager::Device::Interfaceflags>(flags);
147 return ourFlags;
148}
149
150NetworkManager::Device::State NetworkManager::DevicePrivate::convertState(uint theirState)
151{
152 NetworkManager::Device::State ourState = static_cast<NetworkManager::Device::State>(theirState);
153 return ourState;
154}
155
156NetworkManager::Device::StateChangeReason NetworkManager::DevicePrivate::convertReason(uint theirReason)
157{
158 NetworkManager::Device::StateChangeReason ourReason = (NetworkManager::Device::StateChangeReason)theirReason;
159 return ourReason;
160}
161
162NetworkManager::Device::Type NetworkManager::DevicePrivate::convertType(uint type)
163{
164 // These are identical to NM enums
165 if (type <= NM_DEVICE_TYPE_TEAM) {
166 return (NetworkManager::Device::Type)type;
167 }
168
169 switch (type) {
170 case 16:
171 // NM_DEVICE_TYPE_TUN
172 return NetworkManager::Device::Tun;
173 case 17:
174 // NM_DEVICE_TYPE_IP_TUNNEL
175 return NetworkManager::Device::IpTunnel;
176 case 18:
177 // NM_DEVICE_TYPE_MACVLAN
178 return NetworkManager::Device::MacVlan;
179 case 19:
180 // NM_DEVICE_TYPE_VXLAN
181 return NetworkManager::Device::VxLan;
182 case 20:
183 // NM_DEVICE_TYPE_VETH
184 return NetworkManager::Device::Veth;
185 case 21:
186 // NM_DEVICE_TYPE_MACSEC
187 return NetworkManager::Device::MacSec;
188 case 22:
189 // NM_DEVICE_TYPE_DUMMY
190 return NetworkManager::Device::Dummy;
191 case 23:
192 // NM_DEVICE_TYPE_PPP
193 return NetworkManager::Device::Ppp;
194 case 24:
195 // NM_DEVICE_TYPE_OVS_INTERFACE
196 return NetworkManager::Device::OvsInterface;
197 case 25:
198 // NM_DEVICE_TYPE_OVS_PORT
199 return NetworkManager::Device::OvsPort;
200 case 26:
201 // NM_DEVICE_TYPE_OVS_BRIDGE
202 return NetworkManager::Device::OvsBridge;
203 case 27:
204 // NM_DEVICE_TYPE_WPAN
205 return NetworkManager::Device::Wpan;
206 case 28:
207 // NM_DEVICE_TYPE_6LOWPAN
208 return NetworkManager::Device::Lowpan;
209 case 29:
210 // NM_DEVICE_TYPE_NM_DEVICE_TYPE_WIREGUARD
211 return NetworkManager::Device::WireGuard;
212 case 30:
213 // NM_DEVICE_TYPE_WIFI_P2P
214 return NetworkManager::Device::WifiP2P;
215 case 31:
216 // NM_DEVICE_TYPE_VRF
217 return NetworkManager::Device::VRF;
218 case 32:
219 // NM_DEVICE_TYPE_LOOPBACK
220 return NetworkManager::Device::Loopback;
221 }
222
223 return NetworkManager::Device::UnknownType;
224}
225
226NetworkManager::Device::Device(const QString &path, QObject *parent)
227 : QObject(parent)
228 , d_ptr(new DevicePrivate(path, this))
229{
230 Q_D(Device);
231
232 d->init();
233}
234
235NetworkManager::Device::Device(DevicePrivate &dd, QObject *parent)
236 : QObject(parent)
237 , d_ptr(&dd)
238{
239 Q_D(Device);
240
241 d->init();
242}
243
244void NetworkManager::DevicePrivate::propertyChanged(const QString &property, const QVariant &value)
245{
246 Q_Q(Device);
247
248 // qCDebug(NMQT) << property << " - " << value;
249 if (property == QLatin1String("ActiveConnection")) {
250 activeConnection = value.value<QDBusObjectPath>().path();
251 Q_EMIT q->activeConnectionChanged();
252 } else if (property == QLatin1String("Autoconnect")) {
253 autoconnect = value.toBool();
254 Q_EMIT q->autoconnectChanged();
255 } else if (property == QLatin1String("AvailableConnections")) {
256 QStringList newAvailableConnections;
257 const QList<QDBusObjectPath> availableConnectionsTmp = qdbus_cast<QList<QDBusObjectPath>>(v: value);
258 for (const QDBusObjectPath &availableConnection : availableConnectionsTmp) {
259 newAvailableConnections << availableConnection.path();
260 if (!availableConnections.contains(str: availableConnection.path())) {
261 availableConnections << availableConnection.path();
262 Q_EMIT q->availableConnectionAppeared(connection: availableConnection.path());
263 }
264 }
265 auto it = availableConnections.begin();
266 while (it != availableConnections.end()) {
267 const QString availableConnection = *it;
268 if (!newAvailableConnections.contains(str: availableConnection)) {
269 it = availableConnections.erase(pos: it);
270 Q_EMIT q->availableConnectionDisappeared(connection: availableConnection);
271 } else {
272 ++it;
273 }
274 }
275 Q_EMIT q->availableConnectionChanged();
276 } else if (property == QLatin1String("Capabilities")) {
277 capabilities = NetworkManager::DevicePrivate::convertCapabilities(theirCaps: value.toUInt());
278 Q_EMIT q->capabilitiesChanged();
279 } else if (property == QLatin1String("DeviceType")) {
280 deviceType = convertType(type: value.toUInt());
281 } else if (property == QLatin1String("Dhcp4Config")) {
282 QDBusObjectPath dhcp4ConfigPathTmp = value.value<QDBusObjectPath>();
283 if (dhcp4ConfigPathTmp.path().isNull()) {
284 dhcp4Config.clear();
285 dhcp4ConfigPath.clear();
286 } else if (!dhcp4Config || dhcp4Config->path() != dhcp4ConfigPathTmp.path()) {
287 dhcp4Config.clear();
288 dhcp4ConfigPath = dhcp4ConfigPathTmp.path();
289 }
290 Q_EMIT q->dhcp4ConfigChanged();
291 } else if (property == QLatin1String("Dhcp6Config")) {
292 QDBusObjectPath dhcp6ConfigPathTmp = value.value<QDBusObjectPath>();
293 if (dhcp6ConfigPathTmp.path().isNull()) {
294 dhcp6Config.clear();
295 dhcp6ConfigPath.clear();
296 } else if (!dhcp6Config || dhcp6Config->path() != dhcp6ConfigPathTmp.path()) {
297 dhcp6Config.clear();
298 dhcp6ConfigPath = dhcp6ConfigPathTmp.path();
299 }
300 Q_EMIT q->dhcp6ConfigChanged();
301 } else if (property == QLatin1String("Driver")) {
302 driver = value.toString();
303 Q_EMIT q->driverChanged();
304 } else if (property == QLatin1String("DriverVersion")) {
305 driverVersion = value.toString();
306 Q_EMIT q->driverVersionChanged();
307 } else if (property == QLatin1String("FirmwareMissing")) {
308 firmwareMissing = value.toBool();
309 Q_EMIT q->firmwareMissingChanged();
310 } else if (property == QLatin1String("FirmwareVersion")) {
311 firmwareVersion = value.toString();
312 Q_EMIT q->firmwareVersionChanged();
313 } else if (property == QLatin1String("Interface")) {
314 interfaceName = value.toString();
315 Q_EMIT q->interfaceNameChanged();
316 } else if (property == QLatin1String("InterfaceFlags")) {
317 interfaceFlags = NetworkManager::DevicePrivate::convertInterfaceflags(flags: value.toUInt());
318 Q_EMIT q->interfaceFlagsChanged();
319 } else if (property == QLatin1String("Ip4Address")) {
320 ipV4Address = QHostAddress(ntohl(netlong: value.toUInt()));
321 Q_EMIT q->ipV4AddressChanged();
322 } else if (property == QLatin1String("Ip4Config")) {
323 QDBusObjectPath ip4ConfigObjectPathTmp = value.value<QDBusObjectPath>();
324 if (ip4ConfigObjectPathTmp.path().isNull() || ip4ConfigObjectPathTmp.path() == QLatin1String("/")) {
325 ipV4ConfigPath.clear();
326 } else {
327 ipV4ConfigPath = ip4ConfigObjectPathTmp.path();
328 }
329 ipV4Config = IpConfig();
330 Q_EMIT q->ipV4ConfigChanged();
331 } else if (property == QLatin1String("Ip6Config")) {
332 QDBusObjectPath ip6ConfigObjectPathTmp = value.value<QDBusObjectPath>();
333 if (ip6ConfigObjectPathTmp.path().isNull() || ip6ConfigObjectPathTmp.path() == QLatin1String("/")) {
334 ipV6ConfigPath.clear();
335 } else {
336 ipV6ConfigPath = ip6ConfigObjectPathTmp.path();
337 }
338 ipV6Config = IpConfig();
339 Q_EMIT q->ipV6ConfigChanged();
340 } else if (property == QLatin1String("IpInterface")) {
341 ipInterface = value.toString();
342 Q_EMIT q->ipInterfaceChanged();
343 } else if (property == QLatin1String("Managed")) {
344 managed = value.toBool();
345 Q_EMIT q->managedChanged();
346 } else if (property == QLatin1String("State")) {
347 connectionState = NetworkManager::DevicePrivate::convertState(theirState: value.toUInt());
348 // FIXME NetworkManager 0.9.8 (maybe greater) doesn't
349 // update ActiveConnection when disconnected
350 // This is fixed in NM 73d128bbd17120225bb4986e3f05566f10fab581
351 if (connectionState == NetworkManager::Device::Disconnected && activeConnection != QLatin1String("/")) {
352 activeConnection = QLatin1Char('/');
353 Q_EMIT q->activeConnectionChanged();
354 }
355 Q_EMIT q->connectionStateChanged();
356 } else if (property == QLatin1String("StateReason")) { // just extracting the reason
357 reason = NetworkManager::DevicePrivate::convertReason(theirReason: qdbus_cast<DeviceDBusStateReason>(v: value).reason);
358 Q_EMIT q->stateReasonChanged();
359 } else if (property == QLatin1String("Udi")) {
360 udi = value.toString();
361 Q_EMIT q->udiChanged();
362 } else if (property == QLatin1String("PhysicalPortId")) {
363 physicalPortId = value.toString();
364 Q_EMIT q->physicalPortIdChanged();
365 } else if (property == QLatin1String("Mtu")) {
366 mtu = value.toUInt();
367 Q_EMIT q->mtuChanged();
368 } else if (property == QLatin1String("NmPluginMissing")) {
369 nmPluginMissing = value.toBool();
370 Q_EMIT q->nmPluginMissingChanged(nmPluginMissing);
371 } else if (property == QLatin1String("Metered")) {
372 metered = NetworkManager::DevicePrivate::convertMeteredStatus(metered: value.toUInt());
373 Q_EMIT q->meteredChanged(metered);
374 } else {
375 qCDebug(NMQT) << Q_FUNC_INFO << "Unhandled property" << property;
376 }
377}
378
379NetworkManager::Device::~Device()
380{
381 Q_D(Device);
382 delete d;
383}
384
385QString NetworkManager::Device::uni() const
386{
387 Q_D(const Device);
388 return d->uni;
389}
390
391QString NetworkManager::Device::interfaceName() const
392{
393 Q_D(const Device);
394 return d->interfaceName;
395}
396
397QString NetworkManager::Device::ipInterfaceName() const
398{
399 Q_D(const Device);
400 return d->ipInterface;
401}
402
403QString NetworkManager::Device::driver() const
404{
405 Q_D(const Device);
406 return d->driver;
407}
408
409QString NetworkManager::Device::driverVersion() const
410{
411 Q_D(const Device);
412 return d->driverVersion;
413}
414
415QString NetworkManager::Device::firmwareVersion() const
416{
417 Q_D(const Device);
418 return d->firmwareVersion;
419}
420
421NetworkManager::ActiveConnection::Ptr NetworkManager::Device::activeConnection() const
422{
423 Q_D(const Device);
424 return NetworkManager::findActiveConnection(uni: d->activeConnection);
425}
426
427NetworkManager::Connection::List NetworkManager::Device::availableConnections()
428{
429 Q_D(const Device);
430
431 NetworkManager::Connection::List list;
432 for (const QString &availableConnection : std::as_const(t: d->availableConnections)) {
433 NetworkManager::Connection::Ptr connection = NetworkManager::findConnection(path: availableConnection);
434 if (connection) {
435 list << connection;
436 }
437 }
438
439 return list;
440}
441
442bool NetworkManager::Device::firmwareMissing() const
443{
444 Q_D(const Device);
445 return d->firmwareMissing;
446}
447
448bool NetworkManager::Device::autoconnect() const
449{
450 Q_D(const Device);
451 return d->autoconnect;
452}
453
454void NetworkManager::Device::setAutoconnect(bool autoconnect)
455{
456 Q_D(Device);
457 d->deviceIface.setAutoconnect(autoconnect);
458}
459
460QString NetworkManager::Device::udi() const
461{
462 Q_D(const Device);
463 return d->udi;
464}
465
466QString NetworkManager::Device::physicalPortId() const
467{
468 Q_D(const Device);
469 return d->physicalPortId;
470}
471
472QHostAddress NetworkManager::Device::ipV4Address() const
473{
474 Q_D(const Device);
475 return d->ipV4Address;
476}
477
478NetworkManager::DeviceStateReason NetworkManager::Device::stateReason() const
479{
480 Q_D(const Device);
481 return DeviceStateReason(d->connectionState, d->reason);
482}
483
484NetworkManager::IpConfig NetworkManager::Device::ipV4Config() const
485{
486 Q_D(const Device);
487 if (!d->ipV4Config.isValid() && !d->ipV4ConfigPath.isNull()) {
488 d->ipV4Config.setIPv4Path(d->ipV4ConfigPath);
489 }
490 return d->ipV4Config;
491}
492
493NetworkManager::IpConfig NetworkManager::Device::ipV6Config() const
494{
495 Q_D(const Device);
496 if (!d->ipV6Config.isValid() && !d->ipV6ConfigPath.isNull()) {
497 d->ipV6Config.setIPv6Path(d->ipV6ConfigPath);
498 }
499 return d->ipV6Config;
500}
501
502NetworkManager::Dhcp4Config::Ptr NetworkManager::Device::dhcp4Config() const
503{
504 Q_D(const Device);
505 if (!d->dhcp4Config && !d->dhcp4ConfigPath.isNull()) {
506 d->dhcp4Config = NetworkManager::Dhcp4Config::Ptr(new Dhcp4Config(d->dhcp4ConfigPath), &QObject::deleteLater);
507 }
508 return d->dhcp4Config;
509}
510
511NetworkManager::Dhcp6Config::Ptr NetworkManager::Device::dhcp6Config() const
512{
513 Q_D(const Device);
514 if (!d->dhcp6Config && !d->dhcp6ConfigPath.isNull()) {
515 d->dhcp6Config = NetworkManager::Dhcp6Config::Ptr(new Dhcp6Config(d->dhcp6ConfigPath), &QObject::deleteLater);
516 }
517 return d->dhcp6Config;
518}
519
520bool NetworkManager::Device::isActive() const
521{
522 Q_D(const Device);
523 /* clang-format off */
524 return !(d->connectionState == NetworkManager::Device::Unavailable
525 || d->connectionState == NetworkManager::Device::Unmanaged
526 || d->connectionState == NetworkManager::Device::Disconnected
527 || d->connectionState == NetworkManager::Device::Failed);
528 /* clang-format on */
529}
530
531bool NetworkManager::Device::isValid() const
532{
533 Q_D(const Device);
534 return d->deviceIface.isValid();
535}
536
537bool NetworkManager::Device::managed() const
538{
539 Q_D(const Device);
540 return d->managed;
541}
542
543void NetworkManager::Device::setManaged(bool managed)
544{
545 Q_D(Device);
546 d->deviceIface.setManaged(managed);
547}
548
549NetworkManager::Device::Interfaceflags NetworkManager::Device::interfaceFlags() const
550{
551 Q_D(const Device);
552 return d->interfaceFlags;
553}
554
555uint NetworkManager::Device::mtu() const
556{
557 Q_D(const Device);
558 return d->mtu;
559}
560
561bool NetworkManager::Device::nmPluginMissing() const
562{
563 Q_D(const Device);
564 return d->nmPluginMissing;
565}
566
567NetworkManager::Device::MeteredStatus NetworkManager::Device::metered() const
568{
569 Q_D(const Device);
570 return d->metered;
571}
572
573QDBusPendingReply<> NetworkManager::Device::reapplyConnection(const NMVariantMapMap &connection, qulonglong version_id, uint flags)
574{
575 Q_D(Device);
576 return d->deviceIface.Reapply(connection, version_id, flags);
577}
578
579QDBusPendingReply<> NetworkManager::Device::disconnectInterface()
580{
581 Q_D(Device);
582 return d->deviceIface.Disconnect();
583}
584
585QDBusPendingReply<> NetworkManager::Device::deleteInterface()
586{
587 if (NetworkManager::checkVersion(x: 1, y: 0, z: 0)) {
588 Q_D(Device);
589 return d->deviceIface.Delete();
590 } else {
591 return QDBusPendingReply<>();
592 }
593}
594
595NetworkManager::Device::State NetworkManager::Device::state() const
596{
597 Q_D(const Device);
598 return d->connectionState;
599}
600
601int NetworkManager::Device::designSpeed() const
602{
603 Q_D(const Device);
604 return d->designSpeed;
605}
606
607NetworkManager::Device::Capabilities NetworkManager::Device::capabilities() const
608{
609 Q_D(const Device);
610 return d->capabilities;
611}
612
613QVariant NetworkManager::Device::capabilitiesV() const
614{
615 Q_D(const Device);
616 return QVariant(d->capabilities);
617}
618
619NetworkManager::DeviceStatistics::Ptr NetworkManager::Device::deviceStatistics() const
620{
621 Q_D(const Device);
622 return d->deviceStatistics;
623}
624
625void NetworkManager::DevicePrivate::deviceStateChanged(uint newState, uint oldState, uint reason)
626{
627 Q_Q(Device);
628 connectionState = NetworkManager::DevicePrivate::convertState(theirState: newState);
629 reason = NetworkManager::DevicePrivate::convertReason(theirReason: reason);
630
631 Q_EMIT q->stateChanged(newstate: connectionState, oldstate: NetworkManager::DevicePrivate::convertState(theirState: oldState), reason: NetworkManager::DevicePrivate::convertReason(theirReason: reason));
632}
633
634void NetworkManager::DevicePrivate::dbusPropertiesChanged(const QString &interfaceName, const QVariantMap &properties, const QStringList &invalidatedProperties)
635{
636 Q_UNUSED(invalidatedProperties);
637 if (interfaceName.contains(s: QLatin1String("org.freedesktop.NetworkManager.Device"))
638 && interfaceName != QLatin1String("org.freedesktop.NetworkManager.Device.Statistics")) {
639 propertiesChanged(properties);
640 }
641}
642
643void NetworkManager::DevicePrivate::propertiesChanged(const QVariantMap &properties)
644{
645 // qCDebug(NMQT) << Q_FUNC_INFO << properties;
646
647 QVariantMap::const_iterator it = properties.constBegin();
648 while (it != properties.constEnd()) {
649 propertyChanged(property: it.key(), value: it.value());
650 ++it;
651 }
652
653 // FIXME workaround, we need to get a path to updated IPv[46]Config,
654 // because NM doesn't Q_EMIT the updated value when the device is activated
655 // BUG: https://bugzilla.gnome.org/show_bug.cgi?id=725657
656 if (properties.contains(key: QLatin1String("State")) && connectionState == NetworkManager::Device::Activated) {
657 propertyChanged(property: QLatin1String("Ip4Config"), value: QVariant::fromValue<QDBusObjectPath>(value: deviceIface.ip4Config()));
658 propertyChanged(property: QLatin1String("Ip6Config"), value: QVariant::fromValue<QDBusObjectPath>(value: deviceIface.ip6Config()));
659 }
660}
661
662NetworkManager::Device::Type NetworkManager::Device::type() const
663{
664 Q_D(const Device);
665 return d->deviceType;
666}
667
668#include "moc_device.cpp"
669#include "moc_device_p.cpp"
670

source code of networkmanager-qt/src/device.cpp