mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-03 12:50:17 +01:00
wifi/iwd: Create connections for IWD-side known networks
IWD's mechanism for connecting to EAP networks requires a network config file to be present in IWD's storage. NM and its clients however won't allow a connection to be attempted until a valid NMConnection is created on the NM side for the network. To avoid duplicating the settings from the IWD-side profiles in NM, automatically create NMSettingConnections for EAP networks preconfigured on the IWD side, unless a matching connection already exists. These connections will use the "external" EAP method to mean their EAP settings can't be modified through NM, also they won't be valid for devices configured to use the wpa_supplicant backend unfortunately. Those nm-generated connections can be modified by NM users (makes sense for settings not related to the wifi authentication) in which case they get saved as normal profiles and will not be recreated as nm-generated connections on the next run. I want to additionally handle deleting connections from NM clients so that they're also forgotten by IWD, in a later patch.
This commit is contained in:
parent
977d298c5f
commit
2c8161868e
1 changed files with 126 additions and 1 deletions
|
|
@ -29,7 +29,9 @@
|
|||
#include "nm-core-internal.h"
|
||||
#include "nm-manager.h"
|
||||
#include "nm-device-iwd.h"
|
||||
#include "nm-wifi-utils.h"
|
||||
#include "nm-utils/nm-random-utils.h"
|
||||
#include "settings/nm-settings.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -41,6 +43,7 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
GDBusProxy *known_network;
|
||||
NMSettingsConnection *mirror_connection;
|
||||
} KnownNetworkData;
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -311,6 +314,8 @@ known_network_data_free (KnownNetworkData *network)
|
|||
return;
|
||||
|
||||
g_object_unref (network->known_network);
|
||||
if (network->mirror_connection)
|
||||
g_object_unref (network->mirror_connection);
|
||||
g_slice_free (KnownNetworkData, network);
|
||||
}
|
||||
|
||||
|
|
@ -349,6 +354,100 @@ set_device_dbus_object (NMIwdManager *self, GDBusProxy *proxy,
|
|||
nm_device_iwd_set_dbus_object (NM_DEVICE_IWD (device), object);
|
||||
}
|
||||
|
||||
/* Create an in-memory NMConnection for a WPA2-Enterprise network that
|
||||
* has been preprovisioned with an IWD config file so that NM autoconnect
|
||||
* mechanism and the clients know this networks needs no additional EAP
|
||||
* configuration from the user. Only do this if no existing connection
|
||||
* SSID and security type match that network yet.
|
||||
*/
|
||||
static void
|
||||
mirror_8021x_connection (NMIwdManager *self, KnownNetworkId *id,
|
||||
KnownNetworkData *data)
|
||||
{
|
||||
NMSettings *settings = NM_SETTINGS_GET;
|
||||
NMSettingsConnection *const *iter;
|
||||
NMConnection *connection;
|
||||
NMSettingsConnection *settings_connection;
|
||||
char uuid[37];
|
||||
NMSetting *setting;
|
||||
GBytes *ssid;
|
||||
GError *error = NULL;
|
||||
|
||||
for (iter = nm_settings_get_connections (settings, NULL); *iter; iter++) {
|
||||
const NMSettingsConnection *conn = *iter;
|
||||
NMIwdNetworkSecurity security;
|
||||
gs_free char *name = NULL;
|
||||
NMSettingWireless *s_wifi;
|
||||
|
||||
security = nm_wifi_connection_get_iwd_security (NM_CONNECTION (conn), NULL);
|
||||
if (security != NM_IWD_NETWORK_SECURITY_8021X)
|
||||
continue;
|
||||
|
||||
s_wifi = nm_connection_get_setting_wireless (NM_CONNECTION (conn));
|
||||
if (!s_wifi)
|
||||
continue;
|
||||
|
||||
ssid = nm_setting_wireless_get_ssid (s_wifi);
|
||||
if (!ssid)
|
||||
continue;
|
||||
|
||||
name = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL),
|
||||
g_bytes_get_size (ssid));
|
||||
|
||||
/* We already have an NMSettingsConnection matching this
|
||||
* KnownNetwork, whether it's saved or an in-memory connection
|
||||
* potentially created by ourselves. Nothing to do here.
|
||||
*/
|
||||
if (!strcmp (name, id->name))
|
||||
return;
|
||||
}
|
||||
|
||||
connection = nm_simple_connection_new ();
|
||||
|
||||
setting = NM_SETTING (g_object_new (NM_TYPE_SETTING_CONNECTION,
|
||||
NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME,
|
||||
NM_SETTING_CONNECTION_ID, id->name,
|
||||
NM_SETTING_CONNECTION_UUID, nm_utils_uuid_generate_buf (uuid),
|
||||
NM_SETTING_CONNECTION_READ_ONLY, TRUE,
|
||||
NULL));
|
||||
nm_connection_add_setting (connection, setting);
|
||||
|
||||
ssid = g_bytes_new (id->name, strlen (id->name));
|
||||
setting = NM_SETTING (g_object_new (NM_TYPE_SETTING_WIRELESS,
|
||||
NM_SETTING_WIRELESS_SSID, ssid,
|
||||
NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_INFRA,
|
||||
NULL));
|
||||
nm_connection_add_setting (connection, setting);
|
||||
|
||||
setting = NM_SETTING (g_object_new (NM_TYPE_SETTING_WIRELESS_SECURITY,
|
||||
NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open",
|
||||
NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap",
|
||||
NULL));
|
||||
nm_connection_add_setting (connection, setting);
|
||||
|
||||
setting = NM_SETTING (g_object_new (NM_TYPE_SETTING_802_1X, NULL));
|
||||
nm_setting_802_1x_add_eap_method (NM_SETTING_802_1X (setting), "external");
|
||||
nm_connection_add_setting (connection, setting);
|
||||
|
||||
settings_connection = nm_settings_add_connection (settings, connection,
|
||||
FALSE, &error);
|
||||
g_object_unref (connection);
|
||||
|
||||
if (!settings_connection) {
|
||||
_LOGW ("failed to add a mirror NMConnection for IWD's Known Network '%s': %s",
|
||||
id->name, NM_G_ERROR_MSG (error));
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
nm_settings_connection_set_flags (settings_connection,
|
||||
NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED |
|
||||
NM_SETTINGS_CONNECTION_INT_FLAGS_UNSAVED,
|
||||
TRUE);
|
||||
|
||||
data->mirror_connection = g_object_ref (settings_connection);
|
||||
}
|
||||
|
||||
static void
|
||||
interface_added (GDBusObjectManager *object_manager, GDBusObject *object,
|
||||
GDBusInterface *interface, gpointer user_data)
|
||||
|
|
@ -393,9 +492,13 @@ interface_added (GDBusObjectManager *object_manager, GDBusObject *object,
|
|||
|
||||
id = known_network_id_new (name, security);
|
||||
|
||||
data = g_slice_new (KnownNetworkData);
|
||||
data = g_slice_new0 (KnownNetworkData);
|
||||
data->known_network = (GDBusProxy *) g_object_ref (proxy);
|
||||
g_hash_table_insert (priv->known_networks, id, data);
|
||||
|
||||
if (security == NM_IWD_NETWORK_SECURITY_8021X)
|
||||
mirror_8021x_connection (self, id, data);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -421,6 +524,7 @@ interface_removed (GDBusObjectManager *object_manager, GDBusObject *object,
|
|||
|
||||
if (nm_streq (iface_name, NM_IWD_KNOWN_NETWORK_INTERFACE)) {
|
||||
KnownNetworkId id;
|
||||
KnownNetworkData *data;
|
||||
const char *type_str;
|
||||
|
||||
type_str = get_property_string_or_null (proxy, "Type");
|
||||
|
|
@ -437,6 +541,27 @@ interface_removed (GDBusObjectManager *object_manager, GDBusObject *object,
|
|||
else
|
||||
return;
|
||||
|
||||
data = g_hash_table_lookup (priv->known_networks, &id);
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
if (data->mirror_connection) {
|
||||
NMSettingsConnectionIntFlags flags;
|
||||
NMSettingsConnection *mirror_connection = data->mirror_connection;
|
||||
|
||||
flags = nm_settings_connection_get_flags (mirror_connection);
|
||||
|
||||
/* If connection has not been saved since we created it
|
||||
* in interface_added it too can be removed now. */
|
||||
if (flags & NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED) {
|
||||
data->mirror_connection = NULL;
|
||||
|
||||
nm_settings_connection_delete (mirror_connection, NULL);
|
||||
|
||||
g_object_unref (mirror_connection);
|
||||
}
|
||||
}
|
||||
|
||||
g_hash_table_remove (priv->known_networks, &id);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue