about summary refs log tree commit diff
path: root/libnm/nm-client.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2018-06-04 00:07:45 +0200
committerMichael Biebl <biebl@debian.org>2018-06-04 00:07:45 +0200
commit04bc9e1cd3544445d883ad29ea108c1645c8e7b7 (patch)
treed10c354b1b980ca8a7b9e48ec9019e8ed88bde2b /libnm/nm-client.c
parentee9c73a923909e23a649407be77e25235d769e25 (diff)
New upstream version 1.11.4 upstream/1.11.4
Diffstat (limited to 'libnm/nm-client.c')
-rw-r--r--libnm/nm-client.c436
1 files changed, 417 insertions, 19 deletions
diff --git a/libnm/nm-client.c b/libnm/nm-client.c
index 4653b272..18d3e318 100644
--- a/libnm/nm-client.c
+++ b/libnm/nm-client.c
@@ -50,6 +50,7 @@
 
 #include "nm-access-point.h"
 #include "nm-active-connection.h"
+#include "nm-checkpoint.h"
 #include "nm-device-adsl.h"
 #include "nm-device-bond.h"
 #include "nm-device-bridge.h"
@@ -109,6 +110,7 @@ typedef struct {
 	GDBusObjectManager *object_manager;
 	GCancellable *new_object_manager_cancellable;
 	struct udev *udev;
+	bool udev_inited:1;
 } NMClientPrivate;
 
 enum {
@@ -139,6 +141,7 @@ enum {
 	PROP_DNS_MODE,
 	PROP_DNS_RC_MANAGER,
 	PROP_DNS_CONFIGURATION,
+	PROP_CHECKPOINTS,
 
 	LAST_PROP
 };
@@ -752,7 +755,6 @@ nm_client_check_connectivity_finish (NMClient *client,
 	return (NMConnectivityState) g_simple_async_result_get_op_res_gssize (simple);
 }
 
-
 /**
  * nm_client_save_hostname:
  * @client: the %NMClient
@@ -2076,6 +2078,385 @@ dns_notify (GObject *object,
 	}
 }
 
+static void
+checkpoint_create_cb (GObject *object,
+                      GAsyncResult *result,
+                      gpointer user_data)
+{
+	GSimpleAsyncResult *simple = user_data;
+	NMCheckpoint *checkpoint;
+	GError *error = NULL;
+
+	checkpoint = nm_manager_checkpoint_create_finish (NM_MANAGER (object), result, &error);
+	if (checkpoint)
+		g_simple_async_result_set_op_res_gpointer (simple, checkpoint, g_object_unref);
+	else
+		g_simple_async_result_take_error (simple, error);
+
+	g_simple_async_result_complete (simple);
+	g_object_unref (simple);
+}
+
+/**
+ * nm_client_get_checkpoints:
+ * @client: a #NMClient
+ *
+ * Gets all the active checkpoints.
+ *
+ * Returns: (transfer none) (element-type NMCheckpoint): a #GPtrArray
+ * containing all the #NMCheckpoint.  The returned array is owned by the
+ * #NMClient object and should not be modified.
+ *
+ * Since: 1.12
+ **/
+const GPtrArray *
+nm_client_get_checkpoints (NMClient *client)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
+
+	if (!nm_client_get_nm_running (client))
+		return &empty;
+
+	return nm_manager_get_checkpoints (NM_CLIENT_GET_PRIVATE (client)->manager);
+}
+
+/**
+ * nm_client_checkpoint_create:
+ * @client: the %NMClient
+ * @devices: (element-type NMDevice): a list of devices for which a
+ *   checkpoint should be created.
+ * @rollback_timeout: the rollback timeout in seconds
+ * @flags: creation flags
+ * @cancellable: a #GCancellable, or %NULL
+ * @callback: (scope async): callback to be called when the add operation completes
+ * @user_data: (closure): caller-specific data passed to @callback
+ *
+ * Creates a checkpoint of the current networking configuration
+ * for given interfaces. An empty @devices argument means all
+ * devices. If @rollback_timeout is not zero, a rollback is
+ * automatically performed after the given timeout.
+ *
+ * Since: 1.12
+ **/
+void
+nm_client_checkpoint_create (NMClient *client,
+                             const GPtrArray *devices,
+                             guint32 rollback_timeout,
+                             NMCheckpointCreateFlags flags,
+                             GCancellable *cancellable,
+                             GAsyncReadyCallback callback,
+                             gpointer user_data)
+{
+	GSimpleAsyncResult *simple;
+	GError *error = NULL;
+
+	g_return_if_fail (NM_IS_CLIENT (client));
+
+	if (!_nm_client_check_nm_running (client, &error)) {
+		g_simple_async_report_take_gerror_in_idle (G_OBJECT (client), callback, user_data, error);
+		return;
+	}
+
+	simple = g_simple_async_result_new (G_OBJECT (client), callback, user_data,
+	                                    nm_client_checkpoint_create);
+	if (cancellable)
+		g_simple_async_result_set_check_cancellable (simple, cancellable);
+	nm_manager_checkpoint_create (NM_CLIENT_GET_PRIVATE (client)->manager,
+	                              devices, rollback_timeout, flags,
+	                              cancellable, checkpoint_create_cb, simple);
+}
+
+/**
+ * nm_client_checkpoint_create_finish:
+ * @client: the #NMClient
+ * @result: the result passed to the #GAsyncReadyCallback
+ * @error: location for a #GError, or %NULL
+ *
+ * Gets the result of a call to nm_client_checkpoint_create().
+ *
+ * Returns: (transfer full): the new #NMCheckpoint on success, %NULL on
+ *   failure, in which case @error will be set.
+ *
+ * Since: 1.12
+ **/
+NMCheckpoint *
+nm_client_checkpoint_create_finish (NMClient *client,
+                                    GAsyncResult *result,
+                                    GError **error)
+{
+	GSimpleAsyncResult *simple;
+
+	g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
+	g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), NULL);
+
+	simple = G_SIMPLE_ASYNC_RESULT (result);
+	if (g_simple_async_result_propagate_error (simple, error))
+		return NULL;
+	else
+		return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
+}
+
+static void
+checkpoint_destroy_cb (GObject *object,
+                       GAsyncResult *result,
+                       gpointer user_data)
+{
+	GSimpleAsyncResult *simple = user_data;
+	GError *error = NULL;
+
+	if (nm_manager_checkpoint_destroy_finish (NM_MANAGER (object), result, &error))
+		g_simple_async_result_set_op_res_gboolean (simple, TRUE);
+	else
+		g_simple_async_result_take_error (simple, error);
+
+	g_simple_async_result_complete (simple);
+	g_object_unref (simple);
+}
+
+/**
+ * nm_client_checkpoint_destroy:
+ * @client: the %NMClient
+ * @checkpoint_path: the D-Bus path for the checkpoint
+ * @cancellable: a #GCancellable, or %NULL
+ * @callback: (scope async): callback to be called when the add operation completes
+ * @user_data: (closure): caller-specific data passed to @callback
+ *
+ * Destroys an existing checkpoint without performing a rollback.
+ *
+ * Since: 1.12
+ **/
+void
+nm_client_checkpoint_destroy (NMClient *client,
+                              const char *checkpoint_path,
+                              GCancellable *cancellable,
+                              GAsyncReadyCallback callback,
+                              gpointer user_data)
+{
+	GSimpleAsyncResult *simple;
+	GError *error = NULL;
+
+	g_return_if_fail (NM_IS_CLIENT (client));
+	g_return_if_fail (checkpoint_path && checkpoint_path[0] == '/');
+
+	if (!_nm_client_check_nm_running (client, &error)) {
+		g_simple_async_report_take_gerror_in_idle (G_OBJECT (client), callback, user_data, error);
+		return;
+	}
+
+	simple = g_simple_async_result_new (G_OBJECT (client), callback, user_data,
+	                                    nm_client_checkpoint_destroy);
+	if (cancellable)
+		g_simple_async_result_set_check_cancellable (simple, cancellable);
+	nm_manager_checkpoint_destroy (NM_CLIENT_GET_PRIVATE (client)->manager,
+	                               checkpoint_path,
+	                               cancellable, checkpoint_destroy_cb, simple);
+}
+
+/**
+ * nm_client_checkpoint_destroy_finish:
+ * @client: an #NMClient
+ * @result: the result passed to the #GAsyncReadyCallback
+ * @error: location for a #GError, or %NULL
+ *
+ * Gets the result of a call to nm_client_checkpoint_destroy().
+ *
+ * Returns: %TRUE on success or %FALSE on failure, in which case
+ *   @error will be set.
+ *
+ * Since: 1.12
+ **/
+gboolean
+nm_client_checkpoint_destroy_finish (NMClient *client,
+                                     GAsyncResult *result,
+                                     GError **error)
+{
+	GSimpleAsyncResult *simple;
+
+	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
+	g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE);
+
+	simple = G_SIMPLE_ASYNC_RESULT (result);
+	if (g_simple_async_result_propagate_error (simple, error))
+		return FALSE;
+	else
+		return g_simple_async_result_get_op_res_gboolean (simple);
+}
+
+static void
+checkpoint_rollback_cb (GObject *object,
+                        GAsyncResult *result,
+                        gpointer user_data)
+{
+	GSimpleAsyncResult *simple = user_data;
+	GHashTable *hash;
+	GError *error = NULL;
+
+	hash = nm_manager_checkpoint_rollback_finish (NM_MANAGER (object), result, &error);
+	if (hash)
+		g_simple_async_result_set_op_res_gpointer (simple, hash, (GDestroyNotify) g_hash_table_unref);
+	else
+		g_simple_async_result_take_error (simple, error);
+
+	g_simple_async_result_complete (simple);
+	g_object_unref (simple);
+}
+
+/**
+ * nm_client_checkpoint_rollback:
+ * @client: the %NMClient
+ * @checkpoint_path: the D-Bus path to the checkpoint
+ * @cancellable: a #GCancellable, or %NULL
+ * @callback: (scope async): callback to be called when the add operation completes
+ * @user_data: (closure): caller-specific data passed to @callback
+ *
+ * Performs the rollback of a checkpoint before the timeout is reached.
+ *
+ * Since: 1.12
+ **/
+void
+nm_client_checkpoint_rollback (NMClient *client,
+                               const char *checkpoint_path,
+                               GCancellable *cancellable,
+                               GAsyncReadyCallback callback,
+                               gpointer user_data)
+{
+	GSimpleAsyncResult *simple;
+	GError *error = NULL;
+
+	g_return_if_fail (NM_IS_CLIENT (client));
+	g_return_if_fail (checkpoint_path && checkpoint_path[0] == '/');
+
+	if (!_nm_client_check_nm_running (client, &error)) {
+		g_simple_async_report_take_gerror_in_idle (G_OBJECT (client), callback, user_data, error);
+		return;
+	}
+
+	simple = g_simple_async_result_new (G_OBJECT (client), callback, user_data,
+	                                    nm_client_checkpoint_rollback);
+	if (cancellable)
+		g_simple_async_result_set_check_cancellable (simple, cancellable);
+	nm_manager_checkpoint_rollback (NM_CLIENT_GET_PRIVATE (client)->manager,
+	                                checkpoint_path,
+	                                cancellable, checkpoint_rollback_cb, simple);
+}
+
+/**
+ * nm_client_checkpoint_rollback_finish:
+ * @client: an #NMClient
+ * @result: the result passed to the #GAsyncReadyCallback
+ * @error: location for a #GError, or %NULL
+ *
+ * Gets the result of a call to nm_client_checkpoint_rollback().
+ *
+ * Returns: (transfer full) (element-type utf8 guint32): an hash table of
+ *   devices and results. Devices are represented by their original
+ *   D-Bus path; each result is a #NMRollbackResult.
+ *
+ * Since: 1.12
+ **/
+GHashTable *
+nm_client_checkpoint_rollback_finish (NMClient *client,
+                                      GAsyncResult *result,
+                                      GError **error)
+{
+	GSimpleAsyncResult *simple;
+	GHashTable *hash;
+
+	g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
+	g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), NULL);
+
+	simple = G_SIMPLE_ASYNC_RESULT (result);
+	if (g_simple_async_result_propagate_error (simple, error))
+		return NULL;
+	else {
+		hash = g_simple_async_result_get_op_res_gpointer (simple);
+		return g_hash_table_ref (hash);
+	}
+}
+
+static void
+checkpoint_adjust_rollback_timeout_cb (GObject *object,
+                                       GAsyncResult *result,
+                                       gpointer user_data)
+{
+	gs_unref_object GSimpleAsyncResult *simple = user_data;
+	GError *error = NULL;
+
+	if (nm_manager_checkpoint_adjust_rollback_timeout_finish (NM_MANAGER (object), result, &error))
+		g_simple_async_result_set_op_res_gboolean (simple, TRUE);
+	else
+		g_simple_async_result_take_error (simple, error);
+
+	g_simple_async_result_complete (simple);
+}
+
+/**
+ * nm_client_checkpoint_adjust_rollback_timeout:
+ * @client: the %NMClient
+ * @checkpoint_path: a D-Bus path to a checkpoint
+ * @add_timeout: the timeout in seconds counting from now.
+ *   Set to zero, to disable the timeout.
+ * @cancellable: a #GCancellable, or %NULL
+ * @callback: (scope async): callback to be called when the add operation completes
+ * @user_data: (closure): caller-specific data passed to @callback
+ *
+ * Resets the timeout for the checkpoint with path @checkpoint_path
+ * to @timeout_add.
+ *
+ * Since: 1.12
+ **/
+void
+nm_client_checkpoint_adjust_rollback_timeout (NMClient *client,
+                                              const char *checkpoint_path,
+                                              guint32 add_timeout,
+                                              GCancellable *cancellable,
+                                              GAsyncReadyCallback callback,
+                                              gpointer user_data)
+{
+	GSimpleAsyncResult *simple;
+	GError *error = NULL;
+
+	g_return_if_fail (NM_IS_CLIENT (client));
+	g_return_if_fail (checkpoint_path && checkpoint_path[0] == '/');
+
+	if (!_nm_client_check_nm_running (client, &error)) {
+		g_simple_async_report_take_gerror_in_idle (G_OBJECT (client), callback, user_data, error);
+		return;
+	}
+
+	simple = g_simple_async_result_new (G_OBJECT (client), callback, user_data,
+	                                    nm_client_checkpoint_rollback);
+	if (cancellable)
+		g_simple_async_result_set_check_cancellable (simple, cancellable);
+	nm_manager_checkpoint_adjust_rollback_timeout (NM_CLIENT_GET_PRIVATE (client)->manager,
+	                                               checkpoint_path, add_timeout,
+	                                               cancellable, checkpoint_adjust_rollback_timeout_cb, simple);
+}
+
+/**
+ * nm_client_checkpoint_adjust_rollback_timeout_finish:
+ * @client: an #NMClient
+ * @result: the result passed to the #GAsyncReadyCallback
+ * @error: location for a #GError, or %NULL
+ *
+ * Gets the result of a call to nm_client_checkpoint_adjust_rollback_timeout().
+ *
+ * Returns: %TRUE on success or %FALSE on failure.
+ *
+ * Since: 1.12
+ **/
+gboolean
+nm_client_checkpoint_adjust_rollback_timeout_finish (NMClient *client,
+                                                     GAsyncResult *result,
+                                                     GError **error)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
+	g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE);
+
+	return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result),
+	                                               error);
+}
+
 /****************************************************************/
 /* Object Initialization                                        */
 /****************************************************************/
@@ -2206,6 +2587,8 @@ obj_nm_for_gdbus_object (NMClient *self, GDBusObject *object, GDBusObjectManager
 			type = NM_TYPE_VPN_CONNECTION;
 		else if (strcmp (ifname, NM_DBUS_INTERFACE_WIMAX_NSP) == 0)
 			type = NM_TYPE_WIMAX_NSP;
+		else if (strcmp (ifname, NM_DBUS_INTERFACE_CHECKPOINT) == 0)
+			type = NM_TYPE_CHECKPOINT;
 
 		if (type != G_TYPE_INVALID)
 			break;
@@ -2221,9 +2604,14 @@ obj_nm_for_gdbus_object (NMClient *self, GDBusObject *object, GDBusObjectManager
 	                       NULL);
 	if (NM_IS_DEVICE (obj_nm)) {
 		priv = NM_CLIENT_GET_PRIVATE (self);
-		if (!priv->udev)
-			priv->udev = udev_new ();
-		_nm_device_set_udev (NM_DEVICE (obj_nm), priv->udev);
+		if (G_UNLIKELY (!priv->udev_inited)) {
+			priv->udev_inited = TRUE;
+			/* for testing, we don't want to use udev in libnm. */
+			if (!nm_streq0 (g_getenv ("LIBNM_USE_NO_UDEV"), "1"))
+				priv->udev = udev_new ();
+		}
+		if (priv->udev)
+			_nm_device_set_udev (NM_DEVICE (obj_nm), priv->udev);
 	}
 	g_object_set_qdata_full (G_OBJECT (object), _nm_object_obj_nm_quark (),
 	                         obj_nm, g_object_unref);
@@ -2240,7 +2628,6 @@ obj_nm_inited (GObject *object, GAsyncResult *result, gpointer user_data)
 	}
 }
 
-
 static void
 object_added (GDBusObjectManager *object_manager, GDBusObject *object, gpointer user_data)
 {
@@ -2357,7 +2744,6 @@ objects_created (NMClient *client, GDBusObjectManager *object_manager, GError **
 		                  G_CALLBACK (dns_notify), client);
 	}
 
-
 	/* The handlers don't really use the client instance. However
 	 * it makes it convenient to unhook them by data. */
 	g_signal_connect (object_manager, "object-added",
@@ -2783,6 +3169,12 @@ get_property (GObject *object, guint prop_id,
 	case PROP_ALL_DEVICES:
 		g_value_take_boxed (value, _nm_utils_copy_object_array (nm_client_get_all_devices (self)));
 		break;
+	case PROP_CHECKPOINTS:
+		if (priv->manager)
+			g_object_get_property (G_OBJECT (priv->manager), pspec->name, value);
+		else
+			g_value_take_boxed (value, g_ptr_array_new ());
+		break;
 
 	/* Settings properties. */
 	case PROP_CONNECTIONS:
@@ -2976,11 +3368,9 @@ nm_client_class_init (NMClientClass *client_class)
 		                       G_PARAM_STATIC_STRINGS));
 
 	/**
-	 * NMClient:active-connections:
+	 * NMClient:active-connections: (type GPtrArray(NMActiveConnection))
 	 *
 	 * The active connections.
-	 *
-	 * Element-type: NMActiveConnection
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_ACTIVE_CONNECTIONS,
@@ -3057,11 +3447,9 @@ nm_client_class_init (NMClientClass *client_class)
 		                      G_PARAM_STATIC_STRINGS));
 
 	/**
-	 * NMClient:devices:
+	 * NMClient:devices: (type GPtrArray(NMDevice))
 	 *
 	 * List of real network devices.  Does not include placeholder devices.
-	 *
-	 * Element-type: NMDevice
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_DEVICES,
@@ -3071,11 +3459,9 @@ nm_client_class_init (NMClientClass *client_class)
 		                     G_PARAM_STATIC_STRINGS));
 
 	/**
-	 * NMClient:all-devices:
+	 * NMClient:all-devices: (type GPtrArray(NMDevice))
 	 *
 	 * List of both real devices and device placeholders.
-	 *
-	 * Element-type: NMDevice
 	 * Since: 1.2
 	 **/
 	g_object_class_install_property
@@ -3086,14 +3472,12 @@ nm_client_class_init (NMClientClass *client_class)
 		                     G_PARAM_STATIC_STRINGS));
 
 	/**
-	 * NMClient:connections:
+	 * NMClient:connections: (type GPtrArray(NMRemoteConnection))
 	 *
 	 * The list of configured connections that are available to the user. (Note
 	 * that this differs from the underlying D-Bus property, which may also
 	 * contain the object paths of connections that the user does not have
 	 * permission to read the details of.)
-	 *
-	 * Element-type: NMRemoteConnection
 	 */
 	g_object_class_install_property
 		(object_class, PROP_CONNECTIONS,
@@ -3170,7 +3554,7 @@ nm_client_class_init (NMClientClass *client_class)
 		                      G_PARAM_STATIC_STRINGS));
 
 	/**
-	 * NMClient:dns-configuration:
+	 * NMClient:dns-configuration: (type GPtrArray(GVariant))
 	 *
 	 * The current DNS configuration represented as an array of
 	 * dictionaries.  Each dictionary has the "nameservers",
@@ -3189,6 +3573,20 @@ nm_client_class_init (NMClientClass *client_class)
 		                     G_PARAM_READABLE |
 		                     G_PARAM_STATIC_STRINGS));
 
+	/**
+	 * NMClient:checkpoints: (type GPtrArray(NMCheckpoint))
+	 *
+	 * The list of active checkpoints.
+	 *
+	 * Since: 1.12
+	 */
+	g_object_class_install_property
+		(object_class, PROP_CHECKPOINTS,
+		 g_param_spec_boxed (NM_MANAGER_CHECKPOINTS, "", "",
+		                     G_TYPE_PTR_ARRAY,
+		                     G_PARAM_READABLE |
+		                     G_PARAM_STATIC_STRINGS));
+
 	/* signals */
 
 	/**