diff options
author | Thomas Haller <thaller@redhat.com> | 2016-02-16 11:28:37 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2016-02-16 11:28:37 +0100 |
commit | a058cf41dc8dd6f952c4652ae689f3ed8ac042d6 (patch) | |
tree | 5a444258eb43de59ce1c11f6e66839abec4ec504 | |
parent | 5637d72af2d51b6f2b8dbe70553754f1828fdb66 (diff) | |
parent | f40c4798456d2e16b479e5c85424967124dc51b4 (diff) | |
download | NetworkManager-a058cf41dc8dd6f952c4652ae689f3ed8ac042d6.tar.gz |
device: merge branch 'th/device-applied-connection-bgo760884'
https://bugzilla.gnome.org/show_bug.cgi?id=760884
https://bugzilla.gnome.org/show_bug.cgi?id=761714
-rw-r--r-- | clients/cli/devices.c | 2 | ||||
-rw-r--r-- | introspection/nm-active-connection.xml | 9 | ||||
-rw-r--r-- | introspection/nm-device.xml | 66 | ||||
-rw-r--r-- | libnm-core/nm-errors.h | 2 | ||||
-rw-r--r-- | libnm/libnm.ver | 3 | ||||
-rw-r--r-- | libnm/nm-device.c | 189 | ||||
-rw-r--r-- | libnm/nm-device.h | 24 | ||||
-rw-r--r-- | src/devices/nm-device.c | 152 | ||||
-rw-r--r-- | src/nm-active-connection.c | 39 | ||||
-rw-r--r-- | src/nm-active-connection.h | 3 | ||||
-rw-r--r-- | src/settings/nm-settings-connection.c | 14 |
11 files changed, 475 insertions, 28 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-active-connection.xml b/introspection/nm-active-connection.xml index 4d5d15a1e5..203437b7cc 100644 --- a/introspection/nm-active-connection.xml +++ b/introspection/nm-active-connection.xml @@ -9,6 +9,15 @@ The Connection.Active object tracks the life-cycle of the connection attempt and if successful indicates whether the connected network is the "default" or preferred network for access. + NetworkManager has the concept of connections, which can be thought of as + settings, a profile or a configuration that can be applied on a networking + device. + Such settings-connections are exposed as D-Bus object and the active-connection + expresses this relationship between device and settings-connection. + At any time a settings-connection can only be activated on one device and vice + versa. However, during activation and deactivation multiple active-connections + can reference the same device or settings-connection as they are waiting to + be activated or to be deactivated. </tp:docstring> <property name="Connection" type="o" access="read"> diff --git a/introspection/nm-device.xml b/introspection/nm-device.xml index 2930cf067e..f1033c73f2 100644 --- a/introspection/nm-device.xml +++ b/introspection/nm-device.xml @@ -172,8 +172,18 @@ <method name="Reapply"> <arg name="connection" type="a{sa{sv}}" direction="in"> <tp:docstring> - The effective connection settings and properties to use. If empty, the connection - settings from the connection that is active on the device will be used. + The optional connection settings that will be reapplied on the device. If empty, the + currently active settings-connection will be used. The connection cannot arbitrarly + differ from the current applied-connection otherwise the call will fail. + Only certain changes are supported, like adding or removing IP addresses. + </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. + The current version id can be retrieved via GetAppliedConnection. + This optional argument allows to catch concurrent modifications between + the GetAppliedConnection call and Reapply. </tp:docstring> </arg> <arg name="flags" type="u" direction="in"> @@ -183,10 +193,54 @@ </tp:docstring> </arg> <tp:docstring> - Attempts to update the configuration of a device without deactivating it. - You can either modify the configuration by passing the desired setup via "connection" - argument or just omit the argument to bring it in sync with the connection that - has been activated but could have been modified since. + Attempts to update the configuration of a device without deactivating it. NetworkManager + has the concept of connections, which are profiles that contain the configuration for + a networking device. Those connections are exposed via D-Bus as individual objects + that can be created, modified and deleted. When activating such a settings-connection + on a device, the settings-connection is cloned to become an applied-connection and used to + configure the device (see GetAppliedConnection). Subsequent modification of the + settings-connection don't propagate automatically to the device's applied-connection + (with exception of the firewall-zone and the metered property). For the changes to take + effect, you can either re-activate the settings-connection, or call Reapply. + The Reapply call allows you to directly update the applied-connection and reconfigure + the device. + Reapply can also be useful if the currently applied-connection is equal to the connection + that is about to be reapplied. This allows to reconfigure the device and revert external + changes like removing or adding an IP address (which NetworkManager doesn't revert + automatically because it is assumed that the user made these changes intentionally outside + of NetworkManager). + Reapply can make the applied-connection different from the settings-connection, + just like updating the settings-connection can make them different. + </tp:docstring> + </method> + + <method name="GetAppliedConnection"> + <arg name="flags" type="u" direction="in"> + <tp:docstring> + Flags which would modify the behavior of the GetAppliedConnection call. + There are no flags defined currently and the users should use the value of 0. + </tp:docstring> + </arg> + <arg name="connection" type="a{sa{sv}}" direction="out"> + <tp:docstring> + The effective connection settings that the connection has currently applied. + </tp:docstring> + </arg> + <arg name="version_id" type="t" direction="out"> + <tp:docstring> + The version-id of the currently applied connection. This can be specified during + Reapply to avoid races where you first fetch the applied connection, modify it + and try to reapply it. If the applied connection is modified in the meantime, the + version_id gets incremented and Reapply will fail. + </tp:docstring> + </arg> + <tp:docstring> + Get the currently applied connection on the device. This is a snapshot of the last activated + connection on the device, that is the configuration that is currently applied on the device. + Usually this is the same as GetSettings of the referenced settings connection. However, it + can differ if the settings connection was subsequently modified or the applied connection was + modified by Reapply. The applied connection is set when activating a device or when calling + Reapply. </tp:docstring> </method> 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/libnm.ver b/libnm/libnm.ver index 3867c3df0e..944c49bef3 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -875,6 +875,9 @@ global: nm_connection_get_setting_vxlan; nm_connection_verify_secrets; nm_device_ethernet_get_s390_subchannels; + nm_device_get_applied_connection; + nm_device_get_applied_connection_async; + nm_device_get_applied_connection_finish; nm_device_get_lldp_neighbors; nm_device_get_metered; nm_device_get_nm_plugin_missing; diff --git a/libnm/nm-device.c b/libnm/nm-device.c index 49e1e5f7e9..3e887f79ea 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,7 +2184,8 @@ nm_device_is_software (NMDevice *device) gboolean nm_device_reapply (NMDevice *device, NMConnection *connection, - guint flags, + guint64 version_id, + guint32 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,7 +2246,8 @@ device_reapply_cb (GObject *proxy, void nm_device_reapply_async (NMDevice *device, NMConnection *connection, - guint flags, + guint64 version_id, + guint32 flags, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) @@ -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); } @@ -2291,6 +2299,179 @@ nm_device_reapply_finish (NMDevice *device, return g_simple_async_result_get_op_res_gboolean (simple); } +/*****************************************************************************/ + +/** + * nm_device_get_applied_connection: + * @device: a #NMDevice + * @flags: the flags argument. Currently this value must always be zero. + * @version_id: (out): (allow-none): returns the current version id of + * the applied connection + * @cancellable: a #GCancellable, or %NULL + * @error: location for a #GError, or %NULL + * + * Fetch the currently applied connection on the device. + * + * Returns: (transfer-full): a %NMConnection with the currently applied settings + * or %NULL on error. + * + * Since: 1.2 + **/ +NMConnection * +nm_device_get_applied_connection (NMDevice *device, + guint32 flags, + guint64 *version_id, + GCancellable *cancellable, + GError **error) +{ + gs_unref_variant GVariant *dict = NULL; + guint64 my_version_id; + gboolean success; + NMConnection *connection; + + g_return_val_if_fail (NM_IS_DEVICE (device), NULL); + g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), NULL); + g_return_val_if_fail (!error || !*error, NULL); + + success = nmdbus_device_call_get_applied_connection_sync (NM_DEVICE_GET_PRIVATE (device)->proxy, + flags, &dict, &my_version_id, cancellable, error); + if (!success) { + if (error && *error) + g_dbus_error_strip_remote_error (*error); + return NULL; + } + + connection = nm_simple_connection_new_from_dbus (dict, error); + if (!connection) + return NULL; + + NM_SET_OUT (version_id, my_version_id); + return connection; +} + +typedef struct { + NMConnection *connection; + guint64 version_id; +} GetAppliedConnectionData; + +static void +device_get_applied_connection_data_free (gpointer user_data) +{ + GetAppliedConnectionData *data = user_data; + + g_return_if_fail (data); + + g_object_unref (data->connection); + g_slice_free (GetAppliedConnectionData, data); +} + +static void +device_get_applied_connection_cb (GObject *proxy, + GAsyncResult *result, + gpointer user_data) +{ + gs_unref_object GSimpleAsyncResult *simple = user_data; + gs_unref_variant GVariant *dict = NULL; + guint64 my_version_id; + GError *error = NULL; + NMConnection *connection; + GetAppliedConnectionData *data; + + if (!nmdbus_device_call_get_applied_connection_finish (NMDBUS_DEVICE (proxy), &dict, &my_version_id, result, &error)) { + g_dbus_error_strip_remote_error (error); + g_simple_async_result_take_error (simple, error); + goto out; + } + + connection = nm_simple_connection_new_from_dbus (dict, &error); + if (!connection) { + g_simple_async_result_take_error (simple, error); + goto out; + } + + data = g_slice_new (GetAppliedConnectionData); + data->connection = connection; + data->version_id = my_version_id; + g_simple_async_result_set_op_res_gpointer (simple, data, device_get_applied_connection_data_free); + +out: + g_simple_async_result_complete (simple); +} + +/** + * nm_device_get_applied_connection_async: + * @device: a #NMDevice + * @flags: the flags argument. Currently this value must always be zero. + * @cancellable: a #GCancellable, or %NULL + * @callback: callback to be called when the reapply operation completes + * @user_data: caller-specific data passed to @callback + * + * Asynchronously begins an get the a currently applied connection. + * + * Since: 1.2 + **/ +void +nm_device_get_applied_connection_async (NMDevice *device, + guint32 flags, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + + g_return_if_fail (NM_IS_DEVICE (device)); + g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); + + simple = g_simple_async_result_new (G_OBJECT (device), callback, user_data, + nm_device_get_applied_connection_async); + + nmdbus_device_call_get_applied_connection (NM_DEVICE_GET_PRIVATE (device)->proxy, + flags, cancellable, + device_get_applied_connection_cb, simple); +} + +/** + * nm_device_get_applied_connection_finish: + * @device: a #NMDevice + * @result: the result passed to the #GAsyncReadyCallback + * @version_id: (out): (allow-none): the current version id of the applied + * connection. + * @error: location for a #GError, or %NULL + * + * Gets the result of a call to nm_device_get_applied_connection_async(). + * + * Returns: (transfer-full): a currently applied %NMConnection or %NULL in case + * of error. + * + * Since: 1.2 + **/ +NMConnection * +nm_device_get_applied_connection_finish (NMDevice *device, + GAsyncResult *result, + guint64 *version_id, + GError **error) +{ + GSimpleAsyncResult *simple; + GetAppliedConnectionData *data; + + g_return_val_if_fail (NM_IS_DEVICE (device), NULL); + g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (device), nm_device_get_applied_connection_async), NULL); + g_return_val_if_fail (!error || !*error, NULL); + + simple = G_SIMPLE_ASYNC_RESULT (result); + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + + data = g_simple_async_result_get_op_res_gpointer (simple); + g_return_val_if_fail (data, NULL); + g_return_val_if_fail (NM_IS_CONNECTION (data->connection), NULL); + + NM_SET_OUT (version_id, data->version_id); + return g_object_ref (data->connection); +} + +/*****************************************************************************/ + /** * nm_device_disconnect: * @device: a #NMDevice diff --git a/libnm/nm-device.h b/libnm/nm-device.h index bf845cebff..c16ead9ed2 100644 --- a/libnm/nm-device.h +++ b/libnm/nm-device.h @@ -140,13 +140,15 @@ char ** nm_device_disambiguate_names (NMDevice **devices, NM_AVAILABLE_IN_1_2 gboolean nm_device_reapply (NMDevice *device, NMConnection *connection, - guint flags, + guint64 version_id, + guint32 flags, GCancellable *cancellable, GError **error); NM_AVAILABLE_IN_1_2 void nm_device_reapply_async (NMDevice *device, NMConnection *connection, - guint flags, + guint64 version_id, + guint32 flags, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); @@ -155,6 +157,24 @@ gboolean nm_device_reapply_finish (NMDevice *device, GAsyncResult *result, GError **error); +NM_AVAILABLE_IN_1_2 +NMConnection *nm_device_get_applied_connection (NMDevice *device, + guint32 flags, + guint64 *version_id, + GCancellable *cancellable, + GError **error); +NM_AVAILABLE_IN_1_2 +void nm_device_get_applied_connection_async (NMDevice *device, + guint32 flags, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +NM_AVAILABLE_IN_1_2 +NMConnection *nm_device_get_applied_connection_finish (NMDevice *device, + GAsyncResult *result, + guint64 *version_id, + GError **error); + gboolean nm_device_disconnect (NMDevice *device, GCancellable *cancellable, GError **error); diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 29ebe0e759..e5b5e63472 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); @@ -7212,12 +7215,26 @@ reapply_connection (NMDevice *self, NM_SETTING_CONNECTION_METERED)) return FALSE; - _LOGD (LOGD_DEVICE, "reapply"); + 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 *************************************************************************/ + if (diffs) + nm_active_connection_version_id_bump ((NMActiveConnection *) priv->act_request); + + _LOGD (LOGD_DEVICE, "reapply (version-id %llu%s)", + (long long unsigned) nm_active_connection_version_id_get (((NMActiveConnection *) priv->act_request)), + diffs ? "" : " (unmodified)"); + if (diffs) { con_old = applied_clone = nm_simple_connection_new_clone (applied); con_new = applied; @@ -7243,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, @@ -7250,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); @@ -7261,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); @@ -7275,17 +7306,19 @@ static void impl_device_reapply (NMDevice *self, GDBusMethodInvocation *context, GVariant *settings, - guint flags) + guint64 version_id, + guint32 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) { error = g_error_new_literal (NM_DEVICE_ERROR, - NM_DEVICE_ERROR_NOT_ACTIVE, + NM_DEVICE_ERROR_FAILED, "Invalid flags specified"); nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, context, error->message); g_dbus_method_invocation_take_error (context, error); @@ -7316,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, @@ -7323,9 +7363,103 @@ impl_device_reapply (NMDevice *self, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE, reapply_cb, - connection); + reapply_data); } +/*****************************************************************************/ + +static void +get_applied_connection_cb (NMDevice *self, + GDBusMethodInvocation *context, + NMAuthSubject *subject, + GError *error, + gpointer user_data /* possibly dangling pointer */) +{ + NMDevicePrivate *priv; + NMConnection *applied_connection; + GVariant *settings; + + g_return_if_fail (NM_IS_DEVICE (self)); + + if (error) { + g_dbus_method_invocation_return_gerror (context, error); + return; + } + + priv = NM_DEVICE_GET_PRIVATE (self); + + applied_connection = nm_device_get_applied_connection (self); + + if (!applied_connection) { + error = g_error_new_literal (NM_DEVICE_ERROR, + NM_DEVICE_ERROR_NOT_ACTIVE, + "Device is not activated"); + g_dbus_method_invocation_take_error (context, error); + return; + } + + if (applied_connection != user_data) { + /* The applied connection changed due to a race. Reauthenticate. */ + g_signal_emit (self, signals[AUTH_REQUEST], 0, + context, + applied_connection, + NM_AUTH_PERMISSION_NETWORK_CONTROL, + TRUE, + get_applied_connection_cb, + applied_connection /* no need take a ref. We will not dereference this pointer. */); + return; + } + + settings = nm_connection_to_dbus (applied_connection, NM_CONNECTION_SERIALIZE_NO_SECRETS); + if (!settings) + settings = g_variant_new_array (G_VARIANT_TYPE ("{sa{sv}}"), NULL, 0); + + g_dbus_method_invocation_return_value (context, + g_variant_new ("(@a{sa{sv}}t)", + settings, + nm_active_connection_version_id_get ((NMActiveConnection *) priv->act_request))); +} + +static void +impl_device_get_applied_connection (NMDevice *self, + GDBusMethodInvocation *context, + guint32 flags) +{ + NMConnection *applied_connection; + GError *error = NULL; + + g_return_if_fail (NM_IS_DEVICE (self)); + + /* No flags supported as of now. */ + if (flags != 0) { + error = g_error_new_literal (NM_DEVICE_ERROR, + NM_DEVICE_ERROR_FAILED, + "Invalid flags specified"); + g_dbus_method_invocation_take_error (context, error); + return; + } + + applied_connection = nm_device_get_applied_connection (self); + if (!applied_connection) { + error = g_error_new_literal (NM_DEVICE_ERROR, + NM_DEVICE_ERROR_NOT_ACTIVE, + "Device is not activated"); + g_dbus_method_invocation_take_error (context, error); + return; + } + + /* Ask the manager to authenticate this request for us */ + g_signal_emit (self, signals[AUTH_REQUEST], 0, + context, + applied_connection, + NM_AUTH_PERMISSION_NETWORK_CONTROL, + TRUE, + get_applied_connection_cb, + applied_connection /* no need take a ref. We will not dereference this pointer. */); +} + +/*****************************************************************************/ + static void disconnect_cb (NMDevice *self, GDBusMethodInvocation *context, @@ -9218,6 +9352,7 @@ nm_device_reapply_settings_immediately (NMDevice *self) NMSettingConnection *s_con_applied; const char *zone; NMMetered metered; + guint64 version_id; g_return_if_fail (NM_IS_DEVICE (self)); @@ -9240,7 +9375,8 @@ nm_device_reapply_settings_immediately (NMDevice *self) if (g_strcmp0 ((zone = nm_setting_connection_get_zone (s_con_settings)), nm_setting_connection_get_zone (s_con_applied)) != 0) { - _LOGD (LOGD_DEVICE, "reapply setting: zone = %s%s%s", NM_PRINT_FMT_QUOTE_STRING (zone)); + version_id = nm_active_connection_version_id_bump ((NMActiveConnection *) self->priv->act_request); + _LOGD (LOGD_DEVICE, "reapply setting: zone = %s%s%s (version-id %llu)", NM_PRINT_FMT_QUOTE_STRING (zone), (long long unsigned) version_id); g_object_set (G_OBJECT (s_con_applied), NM_SETTING_CONNECTION_ZONE, zone, @@ -9251,7 +9387,8 @@ nm_device_reapply_settings_immediately (NMDevice *self) if ((metered = nm_setting_connection_get_metered (s_con_settings)) != nm_setting_connection_get_metered (s_con_applied)) { - _LOGD (LOGD_DEVICE, "reapply setting: metered = %d", (int) metered); + version_id = nm_active_connection_version_id_bump ((NMActiveConnection *) self->priv->act_request); + _LOGD (LOGD_DEVICE, "reapply setting: metered = %d (version-id %llu)", (int) metered, (long long unsigned) version_id); g_object_set (G_OBJECT (s_con_applied), NM_SETTING_CONNECTION_METERED, metered, @@ -11681,6 +11818,7 @@ nm_device_class_init (NMDeviceClass *klass) nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), NMDBUS_TYPE_DEVICE_SKELETON, "Reapply", impl_device_reapply, + "GetAppliedConnection", impl_device_get_applied_connection, "Disconnect", impl_device_disconnect, "Delete", impl_device_delete, NULL); diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c index 91068e56a7..f7506022a1 100644 --- a/src/nm-active-connection.c +++ b/src/nm-active-connection.c @@ -46,6 +46,8 @@ typedef struct { char *specific_object; NMDevice *device; + guint64 version_id; + char *pending_activation_id; gboolean is_default; @@ -796,10 +798,45 @@ nm_active_connection_authorize (NMActiveConnection *self, /****************************************************************/ +static guint64 +_version_id_new (void) +{ + static guint64 id = 0; + + return ++id; +} + +guint64 +nm_active_connection_version_id_get (NMActiveConnection *self) +{ + g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), 0); + + return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->version_id; +} + +guint64 +nm_active_connection_version_id_bump (NMActiveConnection *self) +{ + NMActiveConnectionPrivate *priv; + + g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), 0); + + priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self); + priv->version_id = _version_id_new (); + _LOGT ("new version-id %llu", (long long unsigned) priv->version_id); + return priv->version_id; +} + +/****************************************************************/ + static void nm_active_connection_init (NMActiveConnection *self) { + NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self); + _LOGT ("creating"); + + priv->version_id = _version_id_new (); } static void @@ -810,7 +847,7 @@ constructed (GObject *object) G_OBJECT_CLASS (nm_active_connection_parent_class)->constructed (object); - _LOGD ("constructed (%s)", G_OBJECT_TYPE_NAME (self)); + _LOGD ("constructed (%s, version-id %llu)", G_OBJECT_TYPE_NAME (self), (long long unsigned) priv->version_id); g_return_if_fail (priv->subject); } diff --git a/src/nm-active-connection.h b/src/nm-active-connection.h index f57f2081f1..a7b3d0cd34 100644 --- a/src/nm-active-connection.h +++ b/src/nm-active-connection.h @@ -83,6 +83,9 @@ typedef struct { NMMetered new_value); } NMActiveConnectionClass; +guint64 nm_active_connection_version_id_get (NMActiveConnection *self); +guint64 nm_active_connection_version_id_bump (NMActiveConnection *self); + GType nm_active_connection_get_type (void); typedef void (*NMActiveConnectionAuthResultFunc) (NMActiveConnection *self, diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c index f7e5002cd3..287cb69a7c 100644 --- a/src/settings/nm-settings-connection.c +++ b/src/settings/nm-settings-connection.c @@ -1716,10 +1716,10 @@ get_update_modify_permission (NMConnection *old, NMConnection *new) } static void -impl_settings_connection_update_helper (NMSettingsConnection *self, - GDBusMethodInvocation *context, - GVariant *new_settings, - gboolean save_to_disk) +settings_connection_update_helper (NMSettingsConnection *self, + GDBusMethodInvocation *context, + GVariant *new_settings, + gboolean save_to_disk) { NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); NMAuthSubject *subject = NULL; @@ -1790,7 +1790,7 @@ impl_settings_connection_update (NMSettingsConnection *self, GDBusMethodInvocation *context, GVariant *new_settings) { - impl_settings_connection_update_helper (self, context, new_settings, TRUE); + settings_connection_update_helper (self, context, new_settings, TRUE); } static void @@ -1798,7 +1798,7 @@ impl_settings_connection_update_unsaved (NMSettingsConnection *self, GDBusMethodInvocation *context, GVariant *new_settings) { - impl_settings_connection_update_helper (self, context, new_settings, FALSE); + settings_connection_update_helper (self, context, new_settings, FALSE); } static void @@ -1807,7 +1807,7 @@ impl_settings_connection_save (NMSettingsConnection *self, { /* Do nothing if the connection is already synced with disk */ if (nm_settings_connection_get_unsaved (self)) - impl_settings_connection_update_helper (self, context, NULL, TRUE); + settings_connection_update_helper (self, context, NULL, TRUE); else g_dbus_method_invocation_return_value (context, NULL); } |