Add support for configuring the wired network

add-support-for-wired-network-config
Michael Zanetti 2022-10-06 13:36:35 +02:00
parent 15539812b7
commit e1f01118ed
10 changed files with 286 additions and 53 deletions

5
debian/changelog vendored
View File

@ -1,3 +1,8 @@
libnymea-networkmanager (1.5.0) UNRELEASED; urgency=medium
-- jenkins <developer@nymea.io> Fri, 23 Sep 2022 16:33:36 +0200
libnymea-networkmanager (1.4.1) jammy; urgency=medium

View File

@ -183,13 +183,22 @@ public:
QDBusObjectPath ip4Config() const;
QList<QDBusObjectPath> availableConnections() const;
// Method
void disconnectDevice();
static QString deviceTypeToString(const NetworkDeviceType &deviceType);
static QString deviceStateToString(const NetworkDeviceState &deviceState);
static QString deviceStateReasonToString(const NetworkDeviceStateReason &deviceStateReason);
signals:
void deviceChanged();
void stateChanged(const NetworkDeviceState &state);
private slots:
void onStateChanged(uint newState, uint oldState, uint reason);
private:
QStringList readIpAddresses(const QString &property, const QString &interface);
private:
QDBusInterface *m_networkDeviceInterface = nullptr;
QDBusObjectPath m_objectPath;
@ -215,17 +224,6 @@ private:
QList<QDBusObjectPath> m_availableConnections;
private:
QStringList readIpAddresses(const QString &property, const QString &interface);
private slots:
void onStateChanged(uint newState, uint oldState, uint reason);
signals:
void deviceChanged();
void stateChanged(const NetworkDeviceState &state);
};
QDebug operator<<(QDebug debug, NetworkDevice *device);

View File

@ -46,6 +46,8 @@
#include <QTimer>
#include <QMetaEnum>
#include <arpa/inet.h>
/*! Constructs a new \l{NetworkManager} object with the given \a parent. */
NetworkManager::NetworkManager(QObject *parent) :
QObject(parent)
@ -222,7 +224,7 @@ NetworkManager::NetworkManagerError NetworkManager::connectWifi(const QString &i
NetworkManager::NetworkManagerError NetworkManager::startAccessPoint(const QString &interface, const QString &ssid, const QString &password)
{
qCDebug(dcNetworkManager()) << "Start an access point for" << interface << "SSID:" << ssid << "password:" << password;
qCDebug(dcNetworkManager()) << "Starting access point for" << interface << "SSID:" << ssid << "password:" << password;
// Check interface
if (!getNetworkDevice(interface))
@ -303,6 +305,224 @@ NetworkManager::NetworkManagerError NetworkManager::startAccessPoint(const QStri
return NetworkManagerErrorNoError;
}
NetworkManager::NetworkManagerError NetworkManager::createWiredAutoConnection(const QString &interface)
{
qCDebug(dcNetworkManager()) << "Creating auto connection for" << interface;
NetworkDevice *networkDevice = getNetworkDevice(interface);
if (!networkDevice) {
return NetworkManagerErrorNetworkInterfaceNotFound;
}
QVariantMap ethernetMode {
{"duplex", "full"}
};
QVariantMap connectionSettings {
{"id", "auto"},
{"autoconnect", true},
{"uuid", QUuid::createUuid().toString().remove(QRegExp("[{}]"))},
{"type", "802-3-ethernet"}
};
QVariantMap ipv4Settings {
{"method", "auto"}
};
QVariantMap ipv6Settings {
{"method", "auto"}
};
ConnectionSettings settings;
settings.insert("connection", connectionSettings);
settings.insert("ipv4", ipv4Settings);
settings.insert("ipv6", ipv6Settings);
settings.insert("802-3-ethernet", ethernetMode);
// Remove old configuration (if there is any)
foreach (NetworkConnection *connection, m_networkSettings->connections()) {
if (connection->id() == connectionSettings.value("id")) {
connection->deleteConnection();
}
}
// Add connection
QDBusObjectPath connectionObjectPath = m_networkSettings->addConnection(settings);
if (connectionObjectPath.path().isEmpty())
return NetworkManagerErrorUnknownError;
qCDebug(dcNetworkManager()) << "Connection added" << connectionObjectPath.path();
// Activate connection
QDBusMessage query = m_networkManagerInterface->call("ActivateConnection",
QVariant::fromValue(connectionObjectPath),
QVariant::fromValue(networkDevice->objectPath()),
QVariant::fromValue(QDBusObjectPath("/")));
if (query.type() != QDBusMessage::ReplyMessage) {
qCWarning(dcNetworkManager()) << query.errorName() << query.errorMessage();
return NetworkManagerErrorUnknownError;
}
return NetworkManagerErrorNoError;
}
NetworkManager::NetworkManagerError NetworkManager::createWiredManualConnection(const QString &interface, const QHostAddress &ip, quint8 prefix, const QHostAddress &gateway, const QHostAddress &dns)
{
qCDebug(dcNetworkManager()) << "Creating manual connection for" << interface << ip << prefix << gateway << dns;
NetworkDevice *networkDevice = getNetworkDevice(interface);
if (!networkDevice) {
return NetworkManagerErrorNetworkInterfaceNotFound;
}
if (ip.isNull() || prefix < 8) {
return NetworkManagerErrorInvalidConfiguration;
}
QVariantMap ethernetMode {
{"duplex", "full"}
};
QVariantMap connectionSettings {
{"id", "manual"},
{"autoconnect", true},
{"uuid", QUuid::createUuid().toString().remove(QRegExp("[{}]"))},
{"type", "802-3-ethernet"}
};
NMIntListList addresses;
QList<uint> address;
address << inet_addr(ip.toString().toLocal8Bit().data());
address << prefix;
address << inet_addr(gateway.toString().toLocal8Bit().data());
addresses << address;
NMVariantMapList addressData;
addressData.append({{"address", ip.toString()}, {"prefix", prefix}});
QVariantMap ipv4Settings {
{"method", "manual"},
{"addresses", QVariant::fromValue(addresses)}, // Deprecated but for our supported platforms still required
{"address-data", QVariant::fromValue(addressData)} // New style, but ignored by NM as long as addresses is still supported and given
};
if (!dns.isNull()) {
ipv4Settings.insert("dns", QVariant::fromValue(NMIntList{inet_addr(dns.toString().toLocal8Bit().data())}));
}
// This is ignored if addresses is given, but it's required once the deprecated addresses entry is removed
if (!gateway.isNull()) {
ipv4Settings.insert("gateway", gateway.toString());
}
QVariantMap ipv6Settings {
{"method", "disabled"}
};
ConnectionSettings settings;
settings.insert("connection", connectionSettings);
settings.insert("ipv4", ipv4Settings);
settings.insert("ipv6", ipv6Settings);
settings.insert("802-3-ethernet", ethernetMode);
// Remove old configuration (if there is any)
foreach (NetworkConnection *connection, m_networkSettings->connections()) {
if (connection->id() == connectionSettings.value("id")) {
connection->deleteConnection();
}
}
// Add connection
QDBusObjectPath connectionObjectPath = m_networkSettings->addConnection(settings);
if (connectionObjectPath.path().isEmpty())
return NetworkManagerErrorUnknownError;
qCDebug(dcNetworkManager()) << "Connection added" << connectionObjectPath.path();
// Activate connection
QDBusMessage query = m_networkManagerInterface->call("ActivateConnection",
QVariant::fromValue(connectionObjectPath),
QVariant::fromValue(networkDevice->objectPath()),
QVariant::fromValue(QDBusObjectPath("/")));
if (query.type() != QDBusMessage::ReplyMessage) {
qCWarning(dcNetworkManager()) << query.errorName() << query.errorMessage();
return NetworkManagerErrorUnknownError;
}
return NetworkManagerErrorNoError;
}
NetworkManager::NetworkManagerError NetworkManager::createSharedConnection(const QString &interface, const QHostAddress &ip, quint8 prefix)
{
qCDebug(dcNetworkManager()) << "Starting shared connection for" << interface;
NetworkDevice *networkDevice = getNetworkDevice(interface);
if (!networkDevice) {
return NetworkManagerErrorNetworkInterfaceNotFound;
}
QVariantMap connectionSettings;
connectionSettings.insert("id", "shared");
connectionSettings.insert("autoconnect", true);
connectionSettings.insert("uuid", QUuid::createUuid().toString().remove("{").remove("}"));
connectionSettings.insert("type", "802-3-ethernet");
NMIntListList addresses;
QList<uint> address;
address << inet_addr(ip.toString().toLocal8Bit().data());
address << prefix;
address << 0;
addresses << address;
NMVariantMapList addressData;
addressData.append({{"address", ip.toString()}, {"prefix", prefix}});
QVariantMap ipv4Settings {
{"method", "shared"}
};
if (!ip.isNull()) {
ipv4Settings.insert("addresses", QVariant::fromValue(addresses)); // Deprecated but for our supported platforms still required
ipv4Settings.insert("address-data", QVariant::fromValue(addressData)); // New style, but ignored by NM as long as addresses is still supported and given
}
QVariantMap ipv6Settings;
ipv6Settings.insert("method", "disabled");
// Build connection object
ConnectionSettings settings;
settings.insert("connection", connectionSettings);
settings.insert("ipv4", ipv4Settings);
settings.insert("ipv6", ipv6Settings);
// Remove old configuration (if there is any)
foreach (NetworkConnection *connection, m_networkSettings->connections()) {
if (connection->id() == connectionSettings.value("id")) {
connection->deleteConnection();
}
}
// Add connection
QDBusObjectPath connectionObjectPath = m_networkSettings->addConnection(settings);
if (connectionObjectPath.path().isEmpty())
return NetworkManagerErrorUnknownError;
qCDebug(dcNetworkManager()) << "Connection added" << connectionObjectPath.path();
// Activate connection
QDBusMessage query = m_networkManagerInterface->call("ActivateConnection",
QVariant::fromValue(connectionObjectPath),
QVariant::fromValue(networkDevice->objectPath()),
QVariant::fromValue(QDBusObjectPath("/")));
if (query.type() != QDBusMessage::ReplyMessage) {
qCWarning(dcNetworkManager()) << query.errorName() << query.errorMessage();
return NetworkManagerErrorUnknownError;
}
return NetworkManagerErrorNoError;
}
/*! Returns true if the networking of this \l{NetworkManager} is enabled. */
bool NetworkManager::networkingEnabled() const
{
@ -630,13 +850,13 @@ void NetworkManager::onPropertiesChanged(const QVariantMap &properties)
void NetworkManager::onWirelessDeviceChanged()
{
WirelessNetworkDevice *networkDevice = static_cast<WirelessNetworkDevice *>(sender());
WirelessNetworkDevice *networkDevice = qobject_cast<WirelessNetworkDevice *>(sender());
emit wirelessDeviceChanged(networkDevice);
}
void NetworkManager::onWiredDeviceChanged()
{
WiredNetworkDevice *networkDevice = static_cast<WiredNetworkDevice *>(sender());
WiredNetworkDevice *networkDevice = qobject_cast<WiredNetworkDevice *>(sender());
emit wiredDeviceChanged(networkDevice);
}

View File

@ -38,6 +38,7 @@
#include <QDBusInterface>
#include <QDBusConnection>
#include <QDBusServiceWatcher>
#include <QHostAddress>
#include "networksettings.h"
#include "wirednetworkdevice.h"
@ -85,7 +86,8 @@ public:
NetworkManagerErrorWirelessNetworkingDisabled,
NetworkManagerErrorWirelessConnectionFailed,
NetworkManagerErrorNetworkingDisabled,
NetworkManagerErrorNetworkManagerNotAvailable
NetworkManagerErrorNetworkManagerNotAvailable,
NetworkManagerErrorInvalidConfiguration,
};
Q_ENUM(NetworkManagerError)
@ -110,6 +112,9 @@ public:
NetworkManagerError connectWifi(const QString &interface, const QString &ssid, const QString &password, bool hidden = false);
NetworkManagerError startAccessPoint(const QString &interface, const QString &ssid, const QString &password);
NetworkManagerError createWiredAutoConnection(const QString &interface);
NetworkManagerError createWiredManualConnection(const QString &interface, const QHostAddress &ip, quint8 prefix, const QHostAddress &gateway, const QHostAddress &dns);
NetworkManagerError createSharedConnection(const QString& interface, const QHostAddress &ip, quint8 prefix);
// Networking
bool networkingEnabled() const;

View File

@ -46,6 +46,10 @@
NetworkSettings::NetworkSettings(QObject *parent) :
QObject(parent)
{
qDBusRegisterMetaType<NMVariantMapList>();
qDBusRegisterMetaType<NMIntListList>();
qDBusRegisterMetaType<NMIntList>();
m_settingsInterface = new QDBusInterface(NetworkManagerUtils::networkManagerServiceString(), NetworkManagerUtils::settingsPathString(), NetworkManagerUtils::settingsInterfaceString(), QDBusConnection::systemBus(), this);
if(!m_settingsInterface->isValid()) {
qCWarning(dcNetworkManager()) << "Invalid DBus network settings interface";

View File

@ -41,6 +41,15 @@
class NetworkConnection;
typedef QList<QVariantMap> NMVariantMapList;
Q_DECLARE_METATYPE(NMVariantMapList)
typedef QList<QList<uint>> NMIntListList;
Q_DECLARE_METATYPE(NMIntListList)
typedef QList<uint> NMIntList;
Q_DECLARE_METATYPE(NMIntList)
class NetworkSettings : public QObject
{
Q_OBJECT

View File

@ -58,11 +58,11 @@ WiredNetworkDevice::WiredNetworkDevice(const QDBusObjectPath &objectPath, QObjec
return;
}
setMacAddress(m_wiredInterface->property("HwAddress").toString());
setBitRate(m_wiredInterface->property("Bitrate").toInt());
setPluggedIn(m_wiredInterface->property("Carrier").toBool());
m_macAddress = m_wiredInterface->property("HwAddress").toString();
m_bitRate = m_wiredInterface->property("Bitrate").toInt();
m_pluggedIn = m_wiredInterface->property("Carrier").toBool();
QDBusConnection::systemBus().connect(NetworkManagerUtils::networkManagerServiceString(), this->objectPath().path(), NetworkManagerUtils::wiredInterfaceString(), "PropertiesChanged", this, SLOT(propertiesChanged(QVariantMap)));
QDBusConnection::systemBus().connect(NetworkManagerUtils::networkManagerServiceString(), this->objectPath().path(), "org.freedesktop.DBus.Properties", "PropertiesChanged", this, SLOT(propertiesChanged(QString, QVariantMap, QStringList)));
}
/*! Returns the mac address of this \l{WiredNetworkDevice}. */
@ -83,26 +83,16 @@ bool WiredNetworkDevice::pluggedIn() const
return m_pluggedIn;
}
void WiredNetworkDevice::setMacAddress(const QString &macAddress)
void WiredNetworkDevice::propertiesChanged(const QString &interface_name, const QVariantMap &changed_properties, const QStringList &invalidated_properties)
{
m_macAddress = macAddress;
}
void WiredNetworkDevice::setBitRate(int bitRate)
{
m_bitRate = bitRate;
}
void WiredNetworkDevice::setPluggedIn(bool pluggedIn)
{
m_pluggedIn = pluggedIn;
}
void WiredNetworkDevice::propertiesChanged(const QVariantMap &properties)
{
if (properties.contains("Carrier"))
setPluggedIn(properties.value("Carrier").toBool());
Q_UNUSED(interface_name)
Q_UNUSED(invalidated_properties)
if (changed_properties.contains("Carrier")) {
m_pluggedIn = changed_properties.value("Carrier").toBool();
emit pluggedInChanged(m_pluggedIn);
}
emit deviceChanged();
}
QDebug operator<<(QDebug debug, WiredNetworkDevice *networkDevice)

View File

@ -46,6 +46,12 @@ public:
int bitRate() const;
bool pluggedIn() const;
signals:
void pluggedInChanged(bool pluggedIn);
private slots:
void propertiesChanged(const QString &interface_name, const QVariantMap &changed_properties, const QStringList &invalidated_properties);
private:
QDBusInterface *m_wiredInterface = nullptr;
@ -53,13 +59,6 @@ private:
int m_bitRate = 0;
bool m_pluggedIn = false;
void setMacAddress(const QString &macAddress);
void setBitRate(int bitRate);
void setPluggedIn(bool pluggedIn);
private slots:
void propertiesChanged(const QVariantMap &properties);
};
QDebug operator<<(QDebug debug, WiredNetworkDevice *networkDevice);

View File

@ -219,28 +219,31 @@ void WirelessNetworkDevice::accessPointRemoved(const QDBusObjectPath &objectPath
accessPoint->deleteLater();
}
void WirelessNetworkDevice::propertiesChanged(const QVariantMap &properties)
void WirelessNetworkDevice::propertiesChanged(const QString &interface_name, const QVariantMap &changed_properties, const QStringList &invalidated_properties)
{
Q_UNUSED(interface_name)
Q_UNUSED(invalidated_properties)
//qCDebug(dcNetworkManager()) << "WirelessNetworkDevice: Property changed" << properties;
if (properties.contains("Bitrate")) {
m_bitRate = properties.value("Bitrate").toInt() / 1000;
if (changed_properties.contains("Bitrate")) {
m_bitRate = changed_properties.value("Bitrate").toInt() / 1000;
emit bitRateChanged(m_bitRate);
}
if (properties.contains("Mode")) {
if (changed_properties.contains("Mode")) {
m_wirelessMode = static_cast<WirelessMode>(m_wirelessInterface->property("Mode").toUInt());
emit wirelessModeChanged(m_wirelessMode);
}
// Note: available since 1.12 (-1 means never scanned)
if (properties.contains("LastScan")) {
if (changed_properties.contains("LastScan")) {
m_lastScan = m_wirelessInterface->property("LastScan").toInt();
emit lastScanChanged(m_lastScan);
}
if (properties.contains("ActiveAccessPoint")) {
setActiveAccessPoint(qdbus_cast<QDBusObjectPath>(properties.value("ActiveAccessPoint")));
if (changed_properties.contains("ActiveAccessPoint")) {
setActiveAccessPoint(qdbus_cast<QDBusObjectPath>(changed_properties.value("ActiveAccessPoint")));
}
emit deviceChanged();

View File

@ -78,7 +78,7 @@ signals:
private slots:
void accessPointAdded(const QDBusObjectPath &objectPath);
void accessPointRemoved(const QDBusObjectPath &objectPath);
void propertiesChanged(const QVariantMap &properties);
void propertiesChanged(const QString &interface_name, const QVariantMap &changed_properties, const QStringList &invalidated_properties);
private:
QDBusInterface *m_wirelessInterface = nullptr;