diff options
author | Thomas Haller <thaller@redhat.com> | 2016-02-11 09:04:58 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2016-02-16 11:24:49 +0100 |
commit | 6898e2169e2fc2ca9d938208ad84a112ccb3f23e (patch) | |
tree | 2940e8b5a28f066adba262e45109a2764af93b40 | |
parent | b96a40c2ec9e4318e7d2a578396236f68e487710 (diff) | |
download | NetworkManager-6898e2169e2fc2ca9d938208ad84a112ccb3f23e.tar.gz |
all: add version-id argument to device's Reapply method
This breaks API and ABI for the functions related to Reapply,
which got introduced in the current 1.1 development phase.
The version-id is here to allow users to error out if the connection
on the device was changed by a concurrent action.
https://bugzilla.gnome.org/show_bug.cgi?id=761714
-rw-r--r-- | clients/cli/devices.c | 2 | ||||
-rw-r--r-- | introspection/nm-device.xml | 7 | ||||
-rw-r--r-- | libnm-core/nm-errors.h | 2 | ||||
-rw-r--r-- | libnm/nm-device.c | 12 | ||||
-rw-r--r-- | libnm/nm-device.h | 2 | ||||
-rw-r--r-- | src/devices/nm-device.c | 40 |
6 files changed, 59 insertions, 6 deletions
diff --git a/clients/cli/devices.c b/clients/cli/devices.c index c960c54eb4..d2cb9fcba9 100644 --- a/clients/cli/devices.c +++ b/clients/cli/devices.c @@ -1928,7 +1928,7 @@ do_device_reapply (NmCli *nmc, int argc, char **argv) info->queue = g_slist_prepend (info->queue, g_object_ref (device)); /* Now reapply the connection to the device */ - nm_device_reapply_async (device, NULL, 0, NULL, reapply_device_cb, info); + nm_device_reapply_async (device, NULL, 0, 0, NULL, reapply_device_cb, info); } error: diff --git a/introspection/nm-device.xml b/introspection/nm-device.xml index 2930cf067e..eada289f28 100644 --- a/introspection/nm-device.xml +++ b/introspection/nm-device.xml @@ -176,6 +176,13 @@ settings from the connection that is active on the device will be used. </tp:docstring> </arg> + <arg name="version_id" type="t" direction="in"> + <tp:docstring> + If non-zero, the current version id of the applied connection must match. + This optional argument allows to catch concurrent modifications when + reapplying the currently applied connection with modifications. + </tp:docstring> + </arg> <arg name="flags" type="u" direction="in"> <tp:docstring> Flags which would modify the behavior of the Reapply call. diff --git a/libnm-core/nm-errors.h b/libnm-core/nm-errors.h index a9857445b7..f5e08f9a6b 100644 --- a/libnm-core/nm-errors.h +++ b/libnm-core/nm-errors.h @@ -142,6 +142,7 @@ GQuark nm_crypto_error_quark (void); * @NM_DEVICE_ERROR_SPECIFIC_OBJECT_NOT_FOUND: the "specific object" in the * activation request (eg, the #NMAccessPoint or #NMWimaxNsp) was not * found. + * @NM_DEVICE_ERROR_VERSION_ID_MISMATCH: the version id did not match. * * Device-related errors. * @@ -158,6 +159,7 @@ typedef enum { NM_DEVICE_ERROR_NOT_SOFTWARE, /*< nick=NotSoftware >*/ NM_DEVICE_ERROR_NOT_ALLOWED, /*< nick=NotAllowed >*/ NM_DEVICE_ERROR_SPECIFIC_OBJECT_NOT_FOUND, /*< nick=SpecificObjectNotFound >*/ + NM_DEVICE_ERROR_VERSION_ID_MISMATCH, /*< nick=VersionIdMismatch >*/ } NMDeviceError; #define NM_DEVICE_ERROR nm_device_error_quark () diff --git a/libnm/nm-device.c b/libnm/nm-device.c index 49e1e5f7e9..e1e77efc58 100644 --- a/libnm/nm-device.c +++ b/libnm/nm-device.c @@ -2167,6 +2167,9 @@ nm_device_is_software (NMDevice *device) * nm_device_reapply: * @device: a #NMDevice * @connection: the #NMConnection to replace the applied settings with or %NULL to reuse existing + * @version_id: zero or the expected version id of the applied connection. If specified + * and the version id mismatches, the call fails without modification. This allows to + * catch concurrent accesses. * @flags: always set this to zero * @cancellable: a #GCancellable, or %NULL * @error: location for a #GError, or %NULL @@ -2181,6 +2184,7 @@ nm_device_is_software (NMDevice *device) gboolean nm_device_reapply (NMDevice *device, NMConnection *connection, + guint64 version_id, guint flags, GCancellable *cancellable, GError **error) @@ -2197,7 +2201,7 @@ nm_device_reapply (NMDevice *device, ret = nmdbus_device_call_reapply_sync (NM_DEVICE_GET_PRIVATE (device)->proxy, - dict, flags, cancellable, error); + dict, version_id, flags, cancellable, error); if (error && *error) g_dbus_error_strip_remote_error (*error); return ret; @@ -2226,6 +2230,9 @@ device_reapply_cb (GObject *proxy, * nm_device_reapply_async: * @device: a #NMDevice * @connection: the #NMConnection to replace the applied settings with or %NULL to reuse existing + * @version_id: zero or the expected version id of the applied connection. If specified + * and the version id mismatches, the call fails without modification. This allows to + * catch concurrent accesses. * @flags: always set this to zero * @cancellable: a #GCancellable, or %NULL * @callback: callback to be called when the reapply operation completes @@ -2239,6 +2246,7 @@ device_reapply_cb (GObject *proxy, void nm_device_reapply_async (NMDevice *device, NMConnection *connection, + guint64 version_id, guint flags, GCancellable *cancellable, GAsyncReadyCallback callback, @@ -2258,7 +2266,7 @@ nm_device_reapply_async (NMDevice *device, nm_device_reapply_async); nmdbus_device_call_reapply (NM_DEVICE_GET_PRIVATE (device)->proxy, - dict, flags, cancellable, + dict, version_id, flags, cancellable, device_reapply_cb, simple); } diff --git a/libnm/nm-device.h b/libnm/nm-device.h index bf845cebff..816acb7483 100644 --- a/libnm/nm-device.h +++ b/libnm/nm-device.h @@ -140,12 +140,14 @@ char ** nm_device_disambiguate_names (NMDevice **devices, NM_AVAILABLE_IN_1_2 gboolean nm_device_reapply (NMDevice *device, NMConnection *connection, + guint64 version_id, guint flags, GCancellable *cancellable, GError **error); NM_AVAILABLE_IN_1_2 void nm_device_reapply_async (NMDevice *device, NMConnection *connection, + guint64 version_id, guint flags, GCancellable *cancellable, GAsyncReadyCallback callback, diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index c33a19db65..5d9903dc91 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -7162,6 +7162,8 @@ nm_device_reactivate_ip6_config (NMDevice *self, /* reapply_connection: * @connection: the new connection settings to be applied or %NULL to reapply * the current settings connection + * @version_id: either zero, or the current version id for the applied + * connection. * @error: the error if %FALSE is returned * * Change configuration of an already configured device if possible. @@ -7172,6 +7174,7 @@ nm_device_reactivate_ip6_config (NMDevice *self, static gboolean reapply_connection (NMDevice *self, NMConnection *connection, + guint64 version_id, GError **error) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); @@ -7181,7 +7184,6 @@ reapply_connection (NMDevice *self, NMConnection *con_old, *con_new; NMSettingIPConfig *s_ip4_old, *s_ip4_new; NMSettingIPConfig *s_ip6_old, *s_ip6_new; - guint64 version_id; if (priv->state != NM_DEVICE_STATE_ACTIVATED) { g_set_error_literal (error, @@ -7213,6 +7215,15 @@ reapply_connection (NMDevice *self, NM_SETTING_CONNECTION_METERED)) return FALSE; + if ( version_id != 0 + && version_id != nm_active_connection_version_id_get ((NMActiveConnection *) priv->act_request)) { + g_set_error_literal (error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_VERSION_ID_MISMATCH, + "Reapply failed because device changed in the meantime and the version-id mismatches"); + return FALSE; + } + /************************************************************************** * Update applied connection *************************************************************************/ @@ -7249,6 +7260,11 @@ reapply_connection (NMDevice *self, return TRUE; } +typedef struct { + NMConnection *connection; + guint64 version_id; +} ReapplyData; + static void reapply_cb (NMDevice *self, GDBusMethodInvocation *context, @@ -7256,9 +7272,17 @@ reapply_cb (NMDevice *self, GError *error, gpointer user_data) { - gs_unref_object NMConnection *connection = NM_CONNECTION (user_data); + ReapplyData *reapply_data = user_data; + guint64 version_id = 0; + gs_unref_object NMConnection *connection = NULL; GError *local = NULL; + if (reapply_data) { + connection = reapply_data->connection; + version_id = reapply_data->version_id; + g_slice_free (ReapplyData, reapply_data); + } + if (error) { nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, subject, error->message); g_dbus_method_invocation_return_gerror (context, error); @@ -7267,6 +7291,7 @@ reapply_cb (NMDevice *self, if (!reapply_connection (self, connection ? : (NMConnection *) nm_device_get_settings_connection (self), + version_id, &local)) { nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, subject, local->message); g_dbus_method_invocation_take_error (context, local); @@ -7281,12 +7306,14 @@ static void impl_device_reapply (NMDevice *self, GDBusMethodInvocation *context, GVariant *settings, + guint64 version_id, guint flags) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMSettingsConnection *settings_connection; NMConnection *connection = NULL; GError *error = NULL; + ReapplyData *reapply_data; /* No flags supported as of now. */ if (flags != 0) { @@ -7322,6 +7349,13 @@ impl_device_reapply (NMDevice *self, nm_connection_clear_secrets (connection); } + if (connection || version_id) { + reapply_data = g_slice_new (ReapplyData); + reapply_data->connection = connection; + reapply_data->version_id = version_id; + } else + reapply_data = NULL; + /* Ask the manager to authenticate this request for us */ g_signal_emit (self, signals[AUTH_REQUEST], 0, context, @@ -7329,7 +7363,7 @@ impl_device_reapply (NMDevice *self, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE, reapply_cb, - connection); + reapply_data); } static void |