From 10c0632df0b576df100d7ab0bb6b30822f2c382b Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 16 Jun 2017 13:06:26 +0200 Subject: [PATCH] device: fix taking over device after modifying external connection For externally managed interfaces, we create an in-memory connection and keep the device with sys-iface-state=external. When the user actively modifies the connection, we persist it to storage. But we also must take over managing the device. One problem is that nm_device_reapply() errors out if the device is still activating. It's unclear how to reapply the connection while the device is in the process of activation. So, if the user modifies the created connection very quickly, reapplying the settings will fail. https://bugzilla.redhat.com/show_bug.cgi?id=1462223 --- src/devices/nm-device.c | 24 ++++++++++++++++++++---- src/devices/nm-device.h | 3 +++ src/nm-active-connection.c | 10 +++++++++- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index d7635dcfa..b27e1ff18 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -9099,10 +9099,12 @@ check_and_reapply_connection (NMDevice *self, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS, &diffs); - if (diffs && nm_audit_manager_audit_enabled (nm_audit_manager_get ())) - *audit_args = nm_utils_format_con_diff_for_audit (diffs); - else - *audit_args = NULL; + if (audit_args) { + if (diffs && nm_audit_manager_audit_enabled (nm_audit_manager_get ())) + *audit_args = nm_utils_format_con_diff_for_audit (diffs); + else + *audit_args = NULL; + } /************************************************************************** * check for unsupported changes and reject to reapply @@ -9204,6 +9206,20 @@ check_and_reapply_connection (NMDevice *self, return TRUE; } +gboolean +nm_device_reapply (NMDevice *self, + NMConnection *connection, + GError **error) +{ + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + + return check_and_reapply_connection (self, + connection, + 0, + NULL, + error); +} + typedef struct { NMConnection *connection; guint64 version_id; diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index 71000834f..0323a7829 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -700,6 +700,9 @@ const NMPlatformIP6Route *nm_device_get_ip6_default_route (NMDevice *self, gbool void nm_device_spawn_iface_helper (NMDevice *self); +gboolean nm_device_reapply (NMDevice *self, + NMConnection *connection, + GError **error); void nm_device_reapply_settings_immediately (NMDevice *self); void nm_device_update_firewall_zone (NMDevice *self); diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c index f7088fa08..862754f9b 100644 --- a/src/nm-active-connection.c +++ b/src/nm-active-connection.c @@ -793,6 +793,8 @@ _settings_connection_notify_flags (NMSettingsConnection *settings_connection, GParamSpec *param, NMActiveConnection *self) { + GError *error = NULL; + nm_assert (NM_IS_ACTIVE_CONNECTION (self)); nm_assert (NM_IS_SETTINGS_CONNECTION (settings_connection)); nm_assert (nm_active_connection_get_activation_type (self) == NM_ACTIVATION_TYPE_EXTERNAL); @@ -802,7 +804,13 @@ _settings_connection_notify_flags (NMSettingsConnection *settings_connection, return; _set_activation_type_managed (self); - nm_device_reapply_settings_immediately (nm_active_connection_get_device (self)); + if (!nm_device_reapply (nm_active_connection_get_device (self), + NM_CONNECTION (nm_active_connection_get_settings_connection (self)), + &error)) { + _LOGW ("failed to reapply new device settings on previously externally managed device: %s", + error->message); + g_error_free (error); + } } /*****************************************************************************/