#include "connectionsettingsengine.h" #include bool ConnectionSettingsEngine::wipeClonedMacAddress = false; QString ConnectionSettingsEngine::targetConnUuidStr = QString(); /* * The configuration map: * * connName: QString * autoconnectEnabled: bool * autoconnectPriority: int * allUsersMayConnect: bool * vpnAutoconnectEnabled: bool * autoconnectVpn: QString * meteredConnection: ConnectionSettingsEngine::Metered * device: QString * clonedMacAddress: QString * mtu: int * * For Ethernet devices only: * autoLinkNegotiation: ConnectionSettingsEngine::LinkNegotiation * linkSpeed: ConnectionSettingsEngine::LinkSpeed * duplexMode: ConnectionSettingsEngine::DuplexMode */ ConnectionSettingsEngine::ConnectionSettingsEngine() { } QVariantMap ConnectionSettingsEngine::readConnectionSettings(QString connUuidStr) { // Contains adapted code from plasma-nm NetworkManager::Connection::Ptr conn = NetworkManager::findConnectionByUuid(connUuidStr); NetworkManager::ConnectionSettings::Ptr connSettings = conn->settings(); NetworkManager::WiredSetting::Ptr connWiredSetting = connSettings->setting(NetworkManager::Setting::Wired).dynamicCast(); NetworkManager::WirelessSetting::Ptr connWirelessSetting = connSettings->setting(NetworkManager::Setting::Wireless).dynamicCast(); QVariantMap result; result.insert("connName", connSettings->id()); result.insert("autoconnectEnabled", connSettings->autoconnect()); result.insert("autoconnectPriority", connSettings->autoconnectPriority()); result.insert("allUsersMayConnect", connSettings->permissions().isEmpty() ? true : false); QStringList secondaryConns = connSettings->secondaries(); NetworkManager::Connection::List list = NetworkManager::listConnections(); QStringList vpnList; for (const NetworkManager::Connection::Ptr &conn : list) { NetworkManager::ConnectionSettings::Ptr conSet = conn->settings(); if (conSet->connectionType() == NetworkManager::ConnectionSettings::Vpn || conSet->connectionType() == NetworkManager::ConnectionSettings::WireGuard) { vpnList.append(conSet->uuid()); } } if (secondaryConns.isEmpty() || vpnList.isEmpty()) { result.insert("vpnAutoconnectEnabled", false); result.insert("autoconnectVpn", ""); } else { for (const QString &vpnKey : vpnList) { if (secondaryConns.contains(vpnKey)) { result.insert("vpnAutoconnectEnabled", true); result.insert("autoconnectVpn", vpnKey); break; } } } switch(connSettings->metered()) { case NetworkManager::ConnectionSettings::MeteredUnknown: case NetworkManager::ConnectionSettings::MeteredGuessYes: case NetworkManager::ConnectionSettings::MeteredGuessNo: result.insert("meteredConnection", ConnectionSettingsEngine::MeteredAutomatic); break; case NetworkManager::ConnectionSettings::MeteredYes: result.insert("meteredConnection", ConnectionSettingsEngine::MeteredYes); break; case NetworkManager::ConnectionSettings::MeteredNo: result.insert("meteredConnection", ConnectionSettingsEngine::MeteredNo); break; } result.insert("device", connSettings->interfaceName()); if (!connWiredSetting.isNull()) { result.insert("clonedMacAddress", NetworkManager::macAddressAsString(connWiredSetting->clonedMacAddress())); result.insert("mtu", connWiredSetting->mtu()); if (connWiredSetting->autoNegotiate()) { result.insert("autoLinkNegotiation", ConnectionSettingsEngine::NegotiationAutomatic); result.insert("linkSpeed", ConnectionSettingsEngine::SpeedUnknown); result.insert("duplexMode", ConnectionSettingsEngine::DuplexUnknown); } else if (connWiredSetting->speed() != 0 && connWiredSetting->duplexType() != NetworkManager::WiredSetting::UnknownDuplexType) { result.insert("autoLinkNegotiation", ConnectionSettingsEngine::NegotiationManual); switch (connWiredSetting->speed()) { case 10: result.insert("linkSpeed", ConnectionSettingsEngine::Speed10Mbps); break; case 100: result.insert("linkSpeed", ConnectionSettingsEngine::Speed100Mbps); break; case 1000: result.insert("linkSpeed", ConnectionSettingsEngine::Speed1Gbps); break; case 2500: result.insert("linkSpeed", ConnectionSettingsEngine::Speed2_5Gbps); break; case 5000: result.insert("linkSpeed", ConnectionSettingsEngine::Speed5Gbps); break; case 10000: result.insert("linkSpeed", ConnectionSettingsEngine::Speed10Gbps); break; case 40000: result.insert("linkSpeed", ConnectionSettingsEngine::Speed40Gbps); break; case 100000: result.insert("linkSpeed", ConnectionSettingsEngine::Speed100Gbps); break; } switch (connWiredSetting->duplexType()) { case NetworkManager::WiredSetting::UnknownDuplexType: result.insert("duplexType", ConnectionSettingsEngine::DuplexUnknown); break; case NetworkManager::WiredSetting::Half: result.insert("duplexType", ConnectionSettingsEngine::DuplexHalf); break; case NetworkManager::WiredSetting::Full: result.insert("duplexType", ConnectionSettingsEngine::DuplexFull); break; } result.insert("duplexMode", connWiredSetting->duplexType()); } else { result.insert("autoLinkNegotiation", ConnectionSettingsEngine::NegotiationIgnore); result.insert("linkSpeed", ConnectionSettingsEngine::SpeedUnknown); result.insert("duplexMode", ConnectionSettingsEngine::DuplexUnknown); } } else if (!connWirelessSetting.isNull()) { result.insert("clonedMacAddress", NetworkManager::macAddressAsString(connWirelessSetting->clonedMacAddress())); result.insert("mtu", connWirelessSetting->mtu()); } // TODO: pick up here return result; } void ConnectionSettingsEngine::modifyConnectionSettings(QString connUuidStr, QVariantMap settings) { // Contains adapted code from plasma-nm wipeClonedMacAddress = false; NetworkManager::Connection::Ptr conn = NetworkManager::findConnectionByUuid(connUuidStr); NetworkManager::ConnectionSettings::Ptr connSettings = conn->settings(); NetworkManager::WiredSetting::Ptr connWiredSetting = connSettings->setting(NetworkManager::Setting::Wired).dynamicCast(); NetworkManager::WirelessSetting::Ptr connWirelessSetting = connSettings->setting(NetworkManager::Setting::Wireless).dynamicCast(); if (settings["connName"].isValid()) { connSettings->setId(settings["connName"].toString()); } if (settings["autoconnectEnabled"].isValid()) { connSettings->setAutoconnect(settings["autoconnectEnabled"].toBool()); } if (settings["autoconnectPriority"].isValid()) { connSettings->setAutoconnectPriority(settings["autoconnectPriority"].toInt()); } if (settings["allUsersMayConnect"].isValid()) { if (settings["allUsersMayConnect"].toBool()) { connSettings->setPermissions(QHash()); } else { if (connSettings->permissions().isEmpty()) { connSettings->addToPermissions(userName(), QString()); } // Otherwise we just leave the permissions as-is } } if (settings["vpnAutoconnectEnabled"].isValid()) { if (settings["vpnAutoconnectEnabled"].toBool()) { connSettings->setSecondaries(QStringList() << settings["autoconnectVpn"].toString()); } } if (settings["meteredConnection"].isValid()) { switch (settings["meteredConnection"].toInt()) { case ConnectionSettingsEngine::MeteredAutomatic: connSettings->setMetered(NetworkManager::ConnectionSettings::MeteredUnknown); break; case ConnectionSettingsEngine::MeteredYes: connSettings->setMetered(NetworkManager::ConnectionSettings::MeteredYes); break; case ConnectionSettingsEngine::MeteredNo: connSettings->setMetered(NetworkManager::ConnectionSettings::MeteredNo); break; } } if (settings["device"].isValid()) { connSettings->setInterfaceName(settings["device"].toString()); } QByteArray macBin = NetworkManager::macAddressFromString(settings["clonedMacAddress"].toString()); if (settings["clonedMacAddress"].toString().length() != 17) { wipeClonedMacAddress = true; } if (!connWiredSetting.isNull()) { if (!wipeClonedMacAddress) { connWiredSetting->setClonedMacAddress(macBin); } if (settings["mtu"].isValid()) { connWiredSetting->setMtu(settings["mtu"].toUInt()); } if (settings["autoLinkNegotiation"].isValid()) { if (settings["autoLinkNegotiation"].toInt() == ConnectionSettingsEngine::NegotiationAutomatic) { connWiredSetting->setAutoNegotiate(true); connWiredSetting->setSpeed(0); connWiredSetting->setDuplexType(NetworkManager::WiredSetting::UnknownDuplexType); } else if (settings["autoLinkNegotiation"].toInt() == ConnectionSettingsEngine::NegotiationManual) { connWiredSetting->setAutoNegotiate(false); switch (settings["linkSpeed"].toInt()) { case ConnectionSettingsEngine::Speed10Mbps: connWiredSetting->setSpeed(10); break; case ConnectionSettingsEngine::Speed100Mbps: connWiredSetting->setSpeed(100); break; case ConnectionSettingsEngine::Speed1Gbps: connWiredSetting->setSpeed(1000); break; case ConnectionSettingsEngine::Speed2_5Gbps: connWiredSetting->setSpeed(2500); break; case ConnectionSettingsEngine::Speed5Gbps: connWiredSetting->setSpeed(5000); break; case ConnectionSettingsEngine::Speed10Gbps: connWiredSetting->setSpeed(10000); break; case ConnectionSettingsEngine::Speed40Gbps: connWiredSetting->setSpeed(40000); break; case ConnectionSettingsEngine::Speed100Gbps: connWiredSetting->setSpeed(100000); break; } switch (settings["duplexMode"].toInt()) { case ConnectionSettingsEngine::DuplexUnknown: connWiredSetting->setDuplexType(NetworkManager::WiredSetting::UnknownDuplexType); break; case ConnectionSettingsEngine::DuplexHalf: connWiredSetting->setDuplexType(NetworkManager::WiredSetting::Half); break; case ConnectionSettingsEngine::DuplexFull: connWiredSetting->setDuplexType(NetworkManager::WiredSetting::Full); break; } } else { connWiredSetting->setAutoNegotiate(false); connWiredSetting->setSpeed(0); connWiredSetting->setDuplexType(NetworkManager::WiredSetting::UnknownDuplexType); } } } else if (!connWirelessSetting.isNull()) { if (!wipeClonedMacAddress) { connWirelessSetting->setClonedMacAddress(macBin); } if (settings["mtu"].isValid()) { connWirelessSetting->setMtu(settings["mtu"].toUInt()); } } // TODO: pick up here targetConnUuidStr = connUuidStr; QDBusPendingReply<> reply = conn->update(connSettings->toMap()); auto watcher = new QDBusPendingCallWatcher(reply); QObject::connect(watcher, &QDBusPendingCallWatcher::finished, saveReplyFinished); } void ConnectionSettingsEngine::saveReplyFinished() { NetworkManager::Connection::Ptr conn = NetworkManager::findConnectionByUuid(targetConnUuidStr); NetworkManager::ConnectionSettings::Ptr connSettings = conn->settings(); NetworkManager::WiredSetting::Ptr connWiredSetting = connSettings->setting(NetworkManager::Setting::Wired).dynamicCast(); NetworkManager::WirelessSetting::Ptr connWirelessSetting = connSettings->setting(NetworkManager::Setting::Wireless).dynamicCast(); if (wipeClonedMacAddress) { // Wiping a MAC address with NetworkManagerQt is surprisingly difficult, so we do it with nmcli instead. QProcess clonedMacWiper; clonedMacWiper.setProgram("bash"); if (!connWiredSetting.isNull()) { clonedMacWiper.setArguments(QStringList() << QString("-c") << QString("nmcli connection modify %1 ethernet.cloned-mac-address \"\"").arg(conn->uuid())); clonedMacWiper.start(); clonedMacWiper.waitForFinished(); } else if (!connWirelessSetting.isNull()) { clonedMacWiper.setArguments(QStringList() << QString("-c") << QString("nmcli connection modify %1 wifi.cloned-mac-address \"\"").arg(conn->uuid())); clonedMacWiper.start(); clonedMacWiper.waitForFinished(); } } } QString ConnectionSettingsEngine::userName() { QProcess userNameGetter; userNameGetter.setProgram("whoami"); userNameGetter.start(); userNameGetter.waitForFinished(); return QString(userNameGetter.readAllStandardOutput()); }