summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLubomir Rintel <lkundrak@v3.sk>2015-11-02 15:32:38 +0100
committerLubomir Rintel <lkundrak@v3.sk>2016-01-10 23:13:34 +0100
commit1490c36bb96cc836f0fd882c7410bd9a0153662c (patch)
tree734ee281fb8dd798c84b7d21f7b4d278136d3e35
parent21fa044df00a2c4ab37f151ad8ce2d407c606e80 (diff)
downloadNetworkManager-1490c36bb96cc836f0fd882c7410bd9a0153662c.tar.gz
device: add O.FD.NM.Device.Reapply() call
The introspection data and daemon stub. There's no settings that can be reapplied at the moment.
-rw-r--r--introspection/nm-device.xml21
-rw-r--r--src/devices/nm-device.c170
2 files changed, 191 insertions, 0 deletions
diff --git a/introspection/nm-device.xml b/introspection/nm-device.xml
index cf04ac82f8..2930cf067e 100644
--- a/introspection/nm-device.xml
+++ b/introspection/nm-device.xml
@@ -169,6 +169,27 @@
</tp:docstring>
</property>
+ <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.
+ </tp:docstring>
+ </arg>
+ <arg name="flags" type="u" direction="in">
+ <tp:docstring>
+ Flags which would modify the behavior of the Reapply call.
+ There are no flags defined currently and the users should use the value of 0.
+ </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.
+ </tp:docstring>
+ </method>
+
<method name="Disconnect">
<tp:docstring>
Disconnects a device and prevents the device from automatically activating further connections without user intervention.
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index f77f576677..49b3261a57 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -6829,6 +6829,175 @@ _cleanup_ip6_pre (NMDevice *self, CleanupType cleanup_type)
addrconf6_cleanup (self);
}
+/* reapply_connection:
+ * @connection: the new connection settings to be applied
+ * @flags: always zero
+ * @reconfigure: %FALSE if this is a dry-run, %TRUE for an actual action
+ * @error: the error if %FALSE is returned
+ *
+ * Change configuration of an already configured device if possible.
+ * Updates the device's applied connection upon success.
+ *
+ * Return: %FALSE if the new configuration can not be reapplied.
+ */
+static gboolean
+reapply_connection (NMDevice *self,
+ NMConnection *connection,
+ guint flags,
+ gboolean reconfigure,
+ GError **error)
+{
+ NMConnection *applied = nm_device_get_applied_connection (self);
+ NMConnection *old;
+ GHashTable *diffs = NULL;
+ GHashTableIter iter;
+ const char *setting;
+
+ /* No flags supported as of now. */
+ if (flags != 0) {
+ g_set_error (error,
+ NM_DEVICE_ERROR,
+ NM_DEVICE_ERROR_FAILED,
+ "Invalid flags specified");
+ return FALSE;
+ }
+
+ nm_connection_diff (connection,
+ applied,
+ NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP |
+ NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS,
+ &diffs);
+
+ /* Everything set. */
+ if (!diffs)
+ return TRUE;
+
+ old = nm_simple_connection_new_clone (applied);
+ if (reconfigure)
+ nm_connection_replace_settings_from_connection (applied, connection);
+
+ g_hash_table_iter_init (&iter, diffs);
+ while (g_hash_table_iter_next (&iter, (gpointer *)&setting, NULL)) {
+ g_set_error (error,
+ NM_DEVICE_ERROR,
+ NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
+ "Can't reapply changes to '%s' settings",
+ setting);
+ return FALSE;
+ }
+
+ if (reconfigure)
+ nm_connection_replace_settings_from_connection (applied, NM_CONNECTION (connection));
+
+ return TRUE;
+}
+
+typedef struct {
+ NMConnection *connection;
+ guint flags;
+} ReapplyInfo;
+
+static void
+reapply_cb (NMDevice *self,
+ GDBusMethodInvocation *context,
+ NMAuthSubject *subject,
+ GError *error,
+ gpointer user_data)
+{
+ ReapplyInfo *info = (ReapplyInfo *)user_data;
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+ GError *local = NULL;
+
+ if (error) {
+ g_dbus_method_invocation_return_gerror (context, error);
+ goto out;
+ }
+
+ /* Authorized */
+ if (priv->state != NM_DEVICE_STATE_ACTIVATED) {
+ local = g_error_new_literal (NM_DEVICE_ERROR,
+ NM_DEVICE_ERROR_NOT_ACTIVE,
+ "Device is not activated");
+ g_dbus_method_invocation_return_gerror (context, local);
+ g_error_free (local);
+ goto out;
+ }
+
+ if (!reapply_connection (self,
+ info->connection,
+ info->flags,
+ FALSE,
+ &local)) {
+ /* The dry-run check failed, pityfully. */
+ g_dbus_method_invocation_return_gerror (context, local);
+ g_error_free (local);
+ goto out;
+ }
+
+ reapply_connection (self,
+ info->connection,
+ info->flags,
+ TRUE,
+ &local);
+ g_dbus_method_invocation_return_value (context, NULL);
+
+out:
+ g_object_unref (info->connection);
+ g_slice_free (ReapplyInfo, info);
+}
+
+static void
+impl_device_reapply (NMDevice *self,
+ GDBusMethodInvocation *context,
+ GVariant *settings,
+ guint flags)
+{
+ NMSettingsConnection *settings_connection;
+ NMConnection *connection;
+ GError *error = NULL;
+ ReapplyInfo *info;
+
+ if (NM_DEVICE_GET_PRIVATE (self)->act_request == NULL) {
+ error = g_error_new_literal (NM_DEVICE_ERROR,
+ NM_DEVICE_ERROR_NOT_ACTIVE,
+ "This device is not active");
+ g_dbus_method_invocation_return_gerror (context, error);
+ g_error_free (error);
+ return;
+ }
+
+ settings_connection = nm_device_get_settings_connection (self);
+ g_return_if_fail (settings_connection);
+
+ if (settings && g_variant_n_children (settings)) {
+ /* New settings specified inline. */
+ connection = nm_simple_connection_new_from_dbus (settings, &error);
+ if (!connection) {
+ g_prefix_error (&error, "The settings specified are invalid: ");
+ g_dbus_method_invocation_return_gerror (context, error);
+ g_error_free (error);
+ return;
+ }
+ nm_connection_clear_secrets (connection);
+ } else {
+ /* Just reuse whatever is active already. */
+ connection = NM_CONNECTION (g_object_ref (settings_connection));
+ }
+
+ info = g_slice_new0 (ReapplyInfo);
+ info->connection = connection;
+ info->flags = flags;
+
+ /* Ask the manager to authenticate this request for us */
+ g_signal_emit (self, signals[AUTH_REQUEST], 0,
+ context,
+ nm_device_get_applied_connection (self),
+ NM_AUTH_PERMISSION_NETWORK_CONTROL,
+ TRUE,
+ reapply_cb,
+ info);
+}
+
static void
disconnect_cb (NMDevice *self,
GDBusMethodInvocation *context,
@@ -10924,6 +11093,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,
"Disconnect", impl_device_disconnect,
"Delete", impl_device_delete,
NULL);