diff options
author | Lubomir Rintel <lkundrak@v3.sk> | 2015-11-02 15:32:38 +0100 |
---|---|---|
committer | Lubomir Rintel <lkundrak@v3.sk> | 2016-01-10 23:13:34 +0100 |
commit | 1490c36bb96cc836f0fd882c7410bd9a0153662c (patch) | |
tree | 734ee281fb8dd798c84b7d21f7b4d278136d3e35 | |
parent | 21fa044df00a2c4ab37f151ad8ce2d407c606e80 (diff) | |
download | NetworkManager-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.xml | 21 | ||||
-rw-r--r-- | src/devices/nm-device.c | 170 |
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); |