wifi/iwd: merge branch 'balrog-kun:iwd-config-writing'

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/866
This commit is contained in:
Thomas Haller 2021-05-26 17:08:08 +02:00
commit ebbf740c64
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728
4 changed files with 107 additions and 17 deletions

View file

@ -497,17 +497,24 @@ no-auto-default=*
<term><varname>iwd-config-path</varname></term>
<listitem>
<para>
If the value points to an existing directory, Network
Manager will attempt to write copies of new or modified
Wi-Fi connection profiles, converted into the IWD
format, into this directory thus making IWD connection
properties editable. This will only happen if the IWD
backend is active meaning that at least one Wi-Fi device
must exist.
If the value is "auto" (the default), IWD is queried for its
current state directory when it appears on D-Bus -- the
directory where IWD keeps its network configuration files --
usually /var/lib/iwd. NetworkManager will then attempt to
write copies of new or modified Wi-Fi connection profiles,
converted into the IWD format, into this directory thus making
IWD connection properties editable. NM will overwrite existing
files without preserving their contents.
</para>
<para>
This allows editing connection profile settings such as
the 802.1x configuration using Network Manager clients.
The path can also be overriden by pointing to a specific
existing and writable directory. On the other hand setting
this to an empty string or any other value disables the
profile conversion mechanism.
</para>
<para>
This mechanism allows editing connection profile settings such
as the 802.1x configuration using NetworkManager clients.
Without it such changes have no effect in IWD.
</para>
</listitem>

View file

@ -47,6 +47,7 @@ typedef struct {
char * agent_path;
GHashTable * known_networks;
NMDeviceIwd * last_agent_call_device;
char * last_state_dir;
} NMIwdManagerPrivate;
struct _NMIwdManager {
@ -452,6 +453,21 @@ iwd_config_write(GKeyFile * config,
return nm_utils_file_set_contents(filepath, data, length, 0600, times, NULL, error);
}
static const char *
get_config_path(NMIwdManager *self)
{
NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self);
const char * path = nm_config_data_get_iwd_config_path(NM_CONFIG_GET_DATA);
if (!path || nm_streq0(path, "auto"))
return priv->last_state_dir;
if (path[0] != '\0' && g_file_test(path, G_FILE_TEST_IS_DIR))
return path;
return NULL;
}
static void
sett_conn_changed(NMSettingsConnection * sett_conn,
guint update_reason,
@ -487,8 +503,8 @@ sett_conn_changed(NMSettingsConnection * sett_conn,
if (NM_FLAGS_HAS(flags, NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED))
return;
iwd_dir = nm_config_data_get_iwd_config_path(NM_CONFIG_GET_DATA);
if (!iwd_dir || iwd_dir[0] == '\0' || !g_file_test(iwd_dir, G_FILE_TEST_IS_DIR)) {
iwd_dir = get_config_path(nm_iwd_manager_get());
if (!iwd_dir) {
gboolean nm_autoconnectable = nm_setting_connection_get_autoconnect(s_conn);
gboolean iwd_autoconnectable = get_property_bool(data->known_network, "AutoConnect", TRUE);
@ -1119,8 +1135,8 @@ try_delete_file:
if (mirror_connection(self, &id, FALSE, NULL))
return;
iwd_dir = nm_config_data_get_iwd_config_path(NM_CONFIG_GET_DATA);
if (!iwd_dir || iwd_dir[0] == '\0' || !g_file_test(iwd_dir, G_FILE_TEST_IS_DIR))
iwd_dir = get_config_path(self);
if (!iwd_dir)
return;
filename = nm_wifi_utils_get_iwd_config_filename(id.name, ssid_len, id.security);
@ -1147,8 +1163,8 @@ connection_added(NMSettings *settings, NMSettingsConnection *sett_conn, gpointer
if (!nm_streq(nm_settings_connection_get_connection_type(sett_conn), "802-11-wireless"))
return;
iwd_dir = nm_config_data_get_iwd_config_path(NM_CONFIG_GET_DATA);
if (!iwd_dir || iwd_dir[0] == '\0' || !g_file_test(iwd_dir, G_FILE_TEST_IS_DIR))
iwd_dir = get_config_path(self);
if (!iwd_dir)
return;
/* If this is a generated connection it may be ourselves creating it and
@ -1392,6 +1408,56 @@ object_compare_interfaces(gconstpointer a, gconstpointer b)
return rank_a - rank_b;
}
static void
get_daemon_info_cb(GObject *source, GAsyncResult *res, gpointer user_data)
{
NMIwdManager * self = user_data;
NMIwdManagerPrivate *priv;
gs_unref_variant GVariant *properties = NULL;
gs_free_error GError *error = NULL;
GVariantIter * properties_iter;
const char * key;
GVariant * value;
properties = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error);
if (!properties) {
if (nm_utils_error_is_cancelled(error))
return;
nm_log_warn(LOGD_WIFI, "iwd: Daemon.GetInfo() failed: %s", error->message);
return;
}
priv = NM_IWD_MANAGER_GET_PRIVATE(self);
if (!g_variant_is_of_type(properties, G_VARIANT_TYPE("(a{sv})"))) {
_LOGE("Daemon.GetInfo returned type %s instead of (a{sv})",
g_variant_get_type_string(properties));
return;
}
g_variant_get(properties, "(a{sv})", &properties_iter);
while (g_variant_iter_next(properties_iter, "{&sv}", &key, &value)) {
if (nm_streq(key, "StateDirectory")) {
if (!g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
_LOGE("Daemon.GetInfo property %s is typed '%s' instead of 's'",
key,
g_variant_get_type_string(value));
goto next;
}
nm_clear_g_free(&priv->last_state_dir);
priv->last_state_dir = g_variant_dup_string(value, NULL);
}
next:
g_variant_unref(value);
}
g_variant_iter_free(properties_iter);
}
static void
got_object_manager(GObject *object, GAsyncResult *result, gpointer user_data)
{
@ -1429,7 +1495,8 @@ got_object_manager(GObject *object, GAsyncResult *result, gpointer user_data)
}
if (_om_has_name_owner(object_manager)) {
GList *objects, *iter;
GList * objects, *iter;
gs_unref_object GDBusInterface *daemon = NULL;
priv->running = true;
@ -1455,6 +1522,19 @@ got_object_manager(GObject *object, GAsyncResult *result, gpointer user_data)
if (priv->agent_id)
register_agent(self);
daemon = g_dbus_object_manager_get_interface(object_manager,
"/net/connman/iwd", /* IWD 1.15+ */
NM_IWD_DAEMON_INTERFACE);
if (daemon)
g_dbus_proxy_call(G_DBUS_PROXY(daemon),
"GetInfo",
g_variant_new("()"),
G_DBUS_CALL_FLAGS_NONE,
-1,
priv->cancellable,
get_daemon_info_cb,
self);
}
}
@ -1615,6 +1695,8 @@ dispose(GObject *object)
priv->last_agent_call_device = NULL;
nm_clear_g_free(&priv->last_state_dir);
G_OBJECT_CLASS(nm_iwd_manager_parent_class)->dispose(object);
}

View file

@ -13,6 +13,7 @@
#define NM_IWD_BUS_TYPE G_BUS_TYPE_SYSTEM
#define NM_IWD_SERVICE "net.connman.iwd"
#define NM_IWD_DAEMON_INTERFACE "net.connman.iwd.Daemon"
#define NM_IWD_AGENT_MANAGER_INTERFACE "net.connman.iwd.AgentManager"
#define NM_IWD_WIPHY_INTERFACE "net.connman.iwd.Adapter"
#define NM_IWD_DEVICE_INTERFACE "net.connman.iwd.Device"

View file

@ -1057,7 +1057,7 @@ eap_certs_to_iwd_config(GKeyFile * file,
: nm_setting_802_1x_get_ca_cert_scheme(s_8021x);
NMSetting8021xCKScheme client_cert_scheme =
phase2 ? nm_setting_802_1x_get_phase2_client_cert_scheme(s_8021x)
: nm_setting_802_1x_get_ca_cert_scheme(s_8021x);
: nm_setting_802_1x_get_client_cert_scheme(s_8021x);
NMSetting8021xCKScheme key_scheme;
NMSettingSecretFlags key_password_flags;
const char * ca_path = phase2 ? nm_setting_802_1x_get_phase2_ca_path(s_8021x)