diff --git a/introspection/nm-device.xml b/introspection/nm-device.xml index eada289f28..f1033c73f2 100644 --- a/introspection/nm-device.xml +++ b/introspection/nm-device.xml @@ -172,15 +172,18 @@ - 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. - 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. + 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. @@ -190,10 +193,54 @@ - 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. + + + + + + + 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. + + + + + The effective connection settings that the connection has currently applied. + + + + + 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. + + + + 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. diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 5d9903dc91..f20a0fc581 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -7366,6 +7366,100 @@ impl_device_reapply (NMDevice *self, 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, @@ -11724,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);