summary refs log tree commit diff
path: root/libnm/nm-client.c
diff options
context:
space:
mode:
Diffstat (limited to 'libnm/nm-client.c')
-rw-r--r--libnm/nm-client.c2238
1 files changed, 2238 insertions, 0 deletions
diff --git a/libnm/nm-client.c b/libnm/nm-client.c
new file mode 100644
index 00000000..ef73e329
--- /dev/null
+++ b/libnm/nm-client.c
@@ -0,0 +1,2238 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2008 Novell, Inc.
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <nm-utils.h>
+
+#include "nm-client.h"
+#include "nm-manager.h"
+#include "nm-remote-settings.h"
+#include "nm-device-ethernet.h"
+#include "nm-device-wifi.h"
+#include "nm-device-private.h"
+#include "nm-core-internal.h"
+#include "nm-active-connection.h"
+#include "nm-vpn-connection.h"
+#include "nm-remote-connection.h"
+#include "nm-object-cache.h"
+#include "nm-glib-compat.h"
+#include "nm-dbus-helpers.h"
+
+void _nm_device_wifi_set_wireless_enabled (NMDeviceWifi *device, gboolean enabled);
+
+static void nm_client_initable_iface_init (GInitableIface *iface);
+static void nm_client_async_initable_iface_init (GAsyncInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (NMClient, nm_client, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_client_initable_iface_init);
+                         G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_client_async_initable_iface_init);
+                         )
+
+#define NM_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CLIENT, NMClientPrivate))
+
+typedef struct {
+	NMManager *manager;
+	NMRemoteSettings *settings;
+} NMClientPrivate;
+
+enum {
+	PROP_0,
+	PROP_VERSION,
+	PROP_STATE,
+	PROP_STARTUP,
+	PROP_NM_RUNNING,
+	PROP_NETWORKING_ENABLED,
+	PROP_WIRELESS_ENABLED,
+	PROP_WIRELESS_HARDWARE_ENABLED,
+	PROP_WWAN_ENABLED,
+	PROP_WWAN_HARDWARE_ENABLED,
+	PROP_WIMAX_ENABLED,
+	PROP_WIMAX_HARDWARE_ENABLED,
+	PROP_ACTIVE_CONNECTIONS,
+	PROP_CONNECTIVITY,
+	PROP_PRIMARY_CONNECTION,
+	PROP_ACTIVATING_CONNECTION,
+	PROP_DEVICES,
+	PROP_CONNECTIONS,
+	PROP_HOSTNAME,
+	PROP_CAN_MODIFY,
+
+	LAST_PROP
+};
+
+enum {
+	DEVICE_ADDED,
+	DEVICE_REMOVED,
+	PERMISSION_CHANGED,
+	CONNECTION_ADDED,
+	CONNECTION_REMOVED,
+
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+/**********************************************************************/
+
+/**
+ * nm_client_error_quark:
+ *
+ * Registers an error quark for #NMClient if necessary.
+ *
+ * Returns: the error quark used for #NMClient errors.
+ **/
+GQuark
+nm_client_error_quark (void)
+{
+	static GQuark quark;
+
+	if (G_UNLIKELY (!quark))
+		quark = g_quark_from_static_string ("nm-client-error-quark");
+	return quark;
+}
+
+/**********************************************************************/
+
+static void
+nm_client_init (NMClient *client)
+{
+}
+
+static gboolean
+_nm_client_check_nm_running (NMClient *client, GError **error)
+{
+	if (nm_client_get_nm_running (client))
+		return TRUE;
+	else {
+		g_set_error_literal (error,
+		                     NM_CLIENT_ERROR,
+		                     NM_CLIENT_ERROR_MANAGER_NOT_RUNNING,
+		                     "NetworkManager is not running");
+		return FALSE;
+	}
+}
+
+/**
+ * nm_client_get_version:
+ * @client: a #NMClient
+ *
+ * Gets NetworkManager version.
+ *
+ * Returns: string with the version (or %NULL if NetworkManager is not running)
+ **/
+const char *
+nm_client_get_version (NMClient *client)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
+
+	return nm_manager_get_version (NM_CLIENT_GET_PRIVATE (client)->manager);
+}
+
+/**
+ * nm_client_get_state:
+ * @client: a #NMClient
+ *
+ * Gets the current daemon state.
+ *
+ * Returns: the current %NMState
+ **/
+NMState
+nm_client_get_state (NMClient *client)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), NM_STATE_UNKNOWN);
+
+	return nm_manager_get_state (NM_CLIENT_GET_PRIVATE (client)->manager);
+}
+
+/**
+ * nm_client_get_startup:
+ * @client: a #NMClient
+ *
+ * Tests whether the daemon is still in the process of activating
+ * connections at startup.
+ *
+ * Returns: whether the daemon is still starting up
+ **/
+gboolean
+nm_client_get_startup (NMClient *client)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), NM_STATE_UNKNOWN);
+
+	return nm_manager_get_startup (NM_CLIENT_GET_PRIVATE (client)->manager);
+}
+
+/**
+ * nm_client_get_nm_running:
+ * @client: a #NMClient
+ *
+ * Determines whether the daemon is running.
+ *
+ * Returns: %TRUE if the daemon is running
+ **/
+gboolean
+nm_client_get_nm_running (NMClient *client)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
+
+	return nm_manager_get_nm_running (NM_CLIENT_GET_PRIVATE (client)->manager);
+}
+
+/**
+ * nm_client_networking_get_enabled:
+ * @client: a #NMClient
+ *
+ * Whether networking is enabled or disabled.
+ *
+ * Returns: %TRUE if networking is enabled, %FALSE if networking is disabled
+ **/
+gboolean
+nm_client_networking_get_enabled (NMClient *client)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
+
+	return nm_manager_networking_get_enabled (NM_CLIENT_GET_PRIVATE (client)->manager);
+}
+
+/**
+ * nm_client_networking_set_enabled:
+ * @client: a #NMClient
+ * @enabled: %TRUE to set networking enabled, %FALSE to set networking disabled
+ * @error: (allow-none): return location for a #GError, or %NULL
+ *
+ * Enables or disables networking.  When networking is disabled, all controlled
+ * interfaces are disconnected and deactivated.  When networking is enabled,
+ * all controlled interfaces are available for activation.
+ *
+ * Returns: %TRUE on success, %FALSE otherwise
+ **/
+gboolean
+nm_client_networking_set_enabled (NMClient *client, gboolean enable, GError **error)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
+
+	if (!_nm_client_check_nm_running (client, error))
+		return FALSE;
+
+	return nm_manager_networking_set_enabled (NM_CLIENT_GET_PRIVATE (client)->manager,
+	                                          enable, error);
+}
+
+/**
+ * nm_client_wireless_get_enabled:
+ * @client: a #NMClient
+ *
+ * Determines whether the wireless is enabled.
+ *
+ * Returns: %TRUE if wireless is enabled
+ **/
+gboolean
+nm_client_wireless_get_enabled (NMClient *client)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
+
+	return nm_manager_wireless_get_enabled (NM_CLIENT_GET_PRIVATE (client)->manager);
+}
+
+/**
+ * nm_client_wireless_set_enabled:
+ * @client: a #NMClient
+ * @enabled: %TRUE to enable wireless
+ *
+ * Enables or disables wireless devices.
+ **/
+void
+nm_client_wireless_set_enabled (NMClient *client, gboolean enabled)
+{
+	g_return_if_fail (NM_IS_CLIENT (client));
+
+	if (!_nm_client_check_nm_running (client, NULL))
+		return;
+
+	nm_manager_wireless_set_enabled (NM_CLIENT_GET_PRIVATE (client)->manager, enabled);
+}
+
+/**
+ * nm_client_wireless_hardware_get_enabled:
+ * @client: a #NMClient
+ *
+ * Determines whether the wireless hardware is enabled.
+ *
+ * Returns: %TRUE if the wireless hardware is enabled
+ **/
+gboolean
+nm_client_wireless_hardware_get_enabled (NMClient *client)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
+
+	return nm_manager_wireless_hardware_get_enabled (NM_CLIENT_GET_PRIVATE (client)->manager);
+}
+
+/**
+ * nm_client_wwan_get_enabled:
+ * @client: a #NMClient
+ *
+ * Determines whether WWAN is enabled.
+ *
+ * Returns: %TRUE if WWAN is enabled
+ **/
+gboolean
+nm_client_wwan_get_enabled (NMClient *client)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
+
+	return nm_manager_wwan_get_enabled (NM_CLIENT_GET_PRIVATE (client)->manager);
+}
+
+/**
+ * nm_client_wwan_set_enabled:
+ * @client: a #NMClient
+ * @enabled: %TRUE to enable WWAN
+ *
+ * Enables or disables WWAN devices.
+ **/
+void
+nm_client_wwan_set_enabled (NMClient *client, gboolean enabled)
+{
+	g_return_if_fail (NM_IS_CLIENT (client));
+
+	if (!_nm_client_check_nm_running (client, NULL))
+		return;
+
+	nm_manager_wwan_set_enabled (NM_CLIENT_GET_PRIVATE (client)->manager, enabled);
+}
+
+/**
+ * nm_client_wwan_hardware_get_enabled:
+ * @client: a #NMClient
+ *
+ * Determines whether the WWAN hardware is enabled.
+ *
+ * Returns: %TRUE if the WWAN hardware is enabled
+ **/
+gboolean
+nm_client_wwan_hardware_get_enabled (NMClient *client)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
+
+	return nm_manager_wwan_hardware_get_enabled (NM_CLIENT_GET_PRIVATE (client)->manager);
+}
+
+/**
+ * nm_client_wimax_get_enabled:
+ * @client: a #NMClient
+ *
+ * Determines whether WiMAX is enabled.
+ *
+ * Returns: %TRUE if WiMAX is enabled
+ **/
+gboolean
+nm_client_wimax_get_enabled (NMClient *client)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
+
+	return nm_manager_wimax_get_enabled (NM_CLIENT_GET_PRIVATE (client)->manager);
+}
+
+/**
+ * nm_client_wimax_set_enabled:
+ * @client: a #NMClient
+ * @enabled: %TRUE to enable WiMAX
+ *
+ * Enables or disables WiMAX devices.
+ **/
+void
+nm_client_wimax_set_enabled (NMClient *client, gboolean enabled)
+{
+	g_return_if_fail (NM_IS_CLIENT (client));
+
+	if (!_nm_client_check_nm_running (client, NULL))
+		return;
+
+	nm_manager_wimax_set_enabled (NM_CLIENT_GET_PRIVATE (client)->manager, enabled);
+}
+
+/**
+ * nm_client_wimax_hardware_get_enabled:
+ * @client: a #NMClient
+ *
+ * Determines whether the WiMAX hardware is enabled.
+ *
+ * Returns: %TRUE if the WiMAX hardware is enabled
+ **/
+gboolean
+nm_client_wimax_hardware_get_enabled (NMClient *client)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
+
+	return nm_manager_wimax_hardware_get_enabled (NM_CLIENT_GET_PRIVATE (client)->manager);
+}
+
+/**
+ * nm_client_get_logging:
+ * @client: a #NMClient
+ * @level: (allow-none): return location for logging level string
+ * @domains: (allow-none): return location for log domains string. The string is
+ *   a list of domains separated by ","
+ * @error: (allow-none): return location for a #GError, or %NULL
+ *
+ * Gets NetworkManager current logging level and domains.
+ *
+ * Returns: %TRUE on success, %FALSE otherwise
+ **/
+gboolean
+nm_client_get_logging (NMClient *client, char **level, char **domains, GError **error)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
+	g_return_val_if_fail (level == NULL || *level == NULL, FALSE);
+	g_return_val_if_fail (domains == NULL || *domains == NULL, FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+	if (!_nm_client_check_nm_running (client, error))
+		return FALSE;
+
+	return nm_manager_get_logging (NM_CLIENT_GET_PRIVATE (client)->manager,
+	                               level, domains, error);
+}
+
+/**
+ * nm_client_set_logging:
+ * @client: a #NMClient
+ * @level: (allow-none): logging level to set (%NULL or an empty string for no change)
+ * @domains: (allow-none): logging domains to set. The string should be a list of log
+ *   domains separated by ",". (%NULL or an empty string for no change)
+ * @error: (allow-none): return location for a #GError, or %NULL
+ *
+ * Sets NetworkManager logging level and/or domains.
+ *
+ * Returns: %TRUE on success, %FALSE otherwise
+ **/
+gboolean
+nm_client_set_logging (NMClient *client, const char *level, const char *domains, GError **error)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+	if (!_nm_client_check_nm_running (client, error))
+		return FALSE;
+
+	return nm_manager_set_logging (NM_CLIENT_GET_PRIVATE (client)->manager,
+	                               level, domains, error);
+}
+
+/**
+ * nm_client_get_permission_result:
+ * @client: a #NMClient
+ * @permission: the permission for which to return the result, one of #NMClientPermission
+ *
+ * Requests the result of a specific permission, which indicates whether the
+ * client can or cannot perform the action the permission represents
+ *
+ * Returns: the permission's result, one of #NMClientPermissionResult
+ **/
+NMClientPermissionResult
+nm_client_get_permission_result (NMClient *client, NMClientPermission permission)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), NM_CLIENT_PERMISSION_RESULT_UNKNOWN);
+
+	return nm_manager_get_permission_result (NM_CLIENT_GET_PRIVATE (client)->manager, permission);
+}
+
+/**
+ * nm_client_get_connectivity:
+ * @client: an #NMClient
+ *
+ * Gets the current network connectivity state. Contrast
+ * nm_client_check_connectivity() and
+ * nm_client_check_connectivity_async(), which re-check the
+ * connectivity state first before returning any information.
+ *
+ * Returns: the current connectivity state
+ */
+NMConnectivityState
+nm_client_get_connectivity (NMClient *client)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), NM_STATE_UNKNOWN);
+
+	return nm_manager_get_connectivity (NM_CLIENT_GET_PRIVATE (client)->manager);
+}
+
+/**
+ * nm_client_check_connectivity:
+ * @client: an #NMClient
+ * @cancellable: a #GCancellable
+ * @error: return location for a #GError
+ *
+ * Updates the network connectivity state and returns the (new)
+ * current state. Contrast nm_client_get_connectivity(), which returns
+ * the most recent known state without re-checking.
+ *
+ * This is a blocking call; use nm_client_check_connectivity_async()
+ * if you do not want to block.
+ *
+ * Returns: the (new) current connectivity state
+ */
+NMConnectivityState
+nm_client_check_connectivity (NMClient *client,
+                              GCancellable *cancellable,
+                              GError **error)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), NM_CONNECTIVITY_UNKNOWN);
+
+	if (!_nm_client_check_nm_running (client, error))
+		return NM_CONNECTIVITY_UNKNOWN;
+
+	return nm_manager_check_connectivity (NM_CLIENT_GET_PRIVATE (client)->manager,
+	                                      cancellable, error);
+}
+
+static void
+check_connectivity_cb (GObject *object,
+                       GAsyncResult *result,
+                       gpointer user_data)
+{
+	GSimpleAsyncResult *simple = user_data;
+	NMConnectivityState connectivity;
+	GError *error = NULL;
+
+	connectivity = nm_manager_check_connectivity_finish (NM_MANAGER (object),
+	                                                     result, &error);
+	if (!error)
+		g_simple_async_result_set_op_res_gssize (simple, connectivity);
+	else
+		g_simple_async_result_take_error (simple, error);
+
+	g_simple_async_result_complete (simple);
+	g_object_unref (simple);
+}
+
+/**
+ * nm_client_check_connectivity_async:
+ * @client: an #NMClient
+ * @cancellable: a #GCancellable
+ * @callback: callback to call with the result
+ * @user_data: data for @callback.
+ *
+ * Asynchronously updates the network connectivity state and invokes
+ * @callback when complete. Contrast nm_client_get_connectivity(),
+ * which (immediately) returns the most recent known state without
+ * re-checking, and nm_client_check_connectivity(), which blocks.
+ */
+void
+nm_client_check_connectivity_async (NMClient *client,
+                                    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_check_connectivity_async);
+	nm_manager_check_connectivity_async (NM_CLIENT_GET_PRIVATE (client)->manager,
+	                                     cancellable, check_connectivity_cb, simple);
+}
+
+/**
+ * nm_client_check_connectivity_finish:
+ * @client: an #NMClient
+ * @result: the #GAsyncResult
+ * @error: return location for a #GError
+ *
+ * Retrieves the result of an nm_client_check_connectivity_async()
+ * call.
+ *
+ * Returns: the (new) current connectivity state
+ */
+NMConnectivityState
+nm_client_check_connectivity_finish (NMClient *client,
+                                     GAsyncResult *result,
+                                     GError **error)
+{
+	GSimpleAsyncResult *simple;
+
+	g_return_val_if_fail (NM_IS_CLIENT (client), NM_CONNECTIVITY_UNKNOWN);
+	g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), NM_CONNECTIVITY_UNKNOWN);
+
+	simple = G_SIMPLE_ASYNC_RESULT (result);
+
+	if (g_simple_async_result_propagate_error (simple, error))
+		return NM_CONNECTIVITY_UNKNOWN;
+	return (NMConnectivityState) g_simple_async_result_get_op_res_gssize (simple);
+}
+
+
+/**
+ * nm_client_save_hostname:
+ * @client: the %NMClient
+ * @hostname: (allow-none): the new persistent hostname to set, or %NULL to
+ *   clear any existing persistent hostname
+ * @cancellable: a #GCancellable, or %NULL
+ * @error: return location for #GError
+ *
+ * Requests that the machine's persistent hostname be set to the specified value
+ * or cleared.
+ *
+ * Returns: %TRUE if the request was successful, %FALSE if it failed
+ **/
+gboolean
+nm_client_save_hostname (NMClient *client,
+                         const char *hostname,
+                         GCancellable *cancellable,
+                         GError **error)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
+
+	return nm_remote_settings_save_hostname (NM_CLIENT_GET_PRIVATE (client)->settings,
+	                                         hostname, cancellable, error);
+}
+
+static void
+save_hostname_cb (GObject *object,
+                  GAsyncResult *result,
+                  gpointer user_data)
+{
+	GSimpleAsyncResult *simple = user_data;
+	GError *error = NULL;
+
+	if (nm_remote_settings_save_hostname_finish (NM_REMOTE_SETTINGS (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_save_hostname_async:
+ * @client: the %NMClient
+ * @hostname: (allow-none): the new persistent hostname to set, or %NULL to
+ *   clear any existing persistent hostname
+ * @cancellable: a #GCancellable, or %NULL
+ * @callback: (scope async): callback to be called when the operation completes
+ * @user_data: (closure): caller-specific data passed to @callback
+ *
+ * Requests that the machine's persistent hostname be set to the specified value
+ * or cleared.
+ **/
+void
+nm_client_save_hostname_async (NMClient *client,
+                               const char *hostname,
+                               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_save_hostname_async);
+	nm_remote_settings_save_hostname_async (NM_CLIENT_GET_PRIVATE (client)->settings,
+	                                        hostname,
+	                                        cancellable, save_hostname_cb, simple);
+}
+
+/**
+ * nm_client_save_hostname_finish:
+ * @client: the %NMClient
+ * @result: the result passed to the #GAsyncReadyCallback
+ * @error: return location for #GError
+ *
+ * Gets the result of an nm_client_save_hostname_async() call.
+ *
+ * Returns: %TRUE if the request was successful, %FALSE if it failed
+ **/
+gboolean
+nm_client_save_hostname_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);
+}
+
+/****************************************************************/
+/* Devices                                                      */
+/****************************************************************/
+
+/**
+ * nm_client_get_devices:
+ * @client: a #NMClient
+ *
+ * Gets all the known network devices.  Use nm_device_get_type() or the
+ * <literal>NM_IS_DEVICE_XXXX</literal> functions to determine what kind of
+ * device member of the returned array is, and then you may use device-specific
+ * methods such as nm_device_ethernet_get_hw_address().
+ *
+ * Returns: (transfer none) (element-type NMDevice): a #GPtrArray
+ * containing all the #NMDevices.  The returned array is owned by the
+ * #NMClient object and should not be modified.
+ **/
+const GPtrArray *
+nm_client_get_devices (NMClient *client)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
+
+	return nm_manager_get_devices (NM_CLIENT_GET_PRIVATE (client)->manager);
+}
+
+/**
+ * nm_client_get_device_by_path:
+ * @client: a #NMClient
+ * @object_path: the object path to search for
+ *
+ * Gets a #NMDevice from a #NMClient.
+ *
+ * Returns: (transfer none): the #NMDevice for the given @object_path or %NULL if none is found.
+ **/
+NMDevice *
+nm_client_get_device_by_path (NMClient *client, const char *object_path)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
+	g_return_val_if_fail (object_path, NULL);
+
+	return nm_manager_get_device_by_path (NM_CLIENT_GET_PRIVATE (client)->manager, object_path);
+}
+
+/**
+ * nm_client_get_device_by_iface:
+ * @client: a #NMClient
+ * @iface: the interface name to search for
+ *
+ * Gets a #NMDevice from a #NMClient.
+ *
+ * Returns: (transfer none): the #NMDevice for the given @iface or %NULL if none is found.
+ **/
+NMDevice *
+nm_client_get_device_by_iface (NMClient *client, const char *iface)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
+	g_return_val_if_fail (iface, NULL);
+
+	return nm_manager_get_device_by_iface (NM_CLIENT_GET_PRIVATE (client)->manager, iface);
+}
+
+/****************************************************************/
+/* Active Connections                                           */
+/****************************************************************/
+
+/**
+ * nm_client_get_active_connections:
+ * @client: a #NMClient
+ *
+ * Gets the active connections.
+ *
+ * Returns: (transfer none) (element-type NMActiveConnection): a #GPtrArray
+ *  containing all the active #NMActiveConnections.
+ * The returned array is owned by the client and should not be modified.
+ **/
+const GPtrArray *
+nm_client_get_active_connections (NMClient *client)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
+
+	return nm_manager_get_active_connections (NM_CLIENT_GET_PRIVATE (client)->manager);
+}
+
+/**
+ * nm_client_get_primary_connection:
+ * @client: an #NMClient
+ *
+ * Gets the #NMActiveConnection corresponding to the primary active
+ * network device.
+ *
+ * In particular, when there is no VPN active, or the VPN does not
+ * have the default route, this returns the active connection that has
+ * the default route. If there is a VPN active with the default route,
+ * then this function returns the active connection that contains the
+ * route to the VPN endpoint.
+ *
+ * If there is no default route, or the default route is over a
+ * non-NetworkManager-recognized device, this will return %NULL.
+ *
+ * Returns: (transfer none): the appropriate #NMActiveConnection, if
+ * any
+ */
+NMActiveConnection *
+nm_client_get_primary_connection (NMClient *client)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
+
+	return nm_manager_get_primary_connection (NM_CLIENT_GET_PRIVATE (client)->manager);
+}
+
+/**
+ * nm_client_get_activating_connection:
+ * @client: an #NMClient
+ *
+ * Gets the #NMActiveConnection corresponding to a
+ * currently-activating connection that is expected to become the new
+ * #NMClient:primary-connection upon successful activation.
+ *
+ * Returns: (transfer none): the appropriate #NMActiveConnection, if
+ * any.
+ */
+NMActiveConnection *
+nm_client_get_activating_connection (NMClient *client)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
+
+	return nm_manager_get_activating_connection (NM_CLIENT_GET_PRIVATE (client)->manager);
+}
+
+static void
+activate_cb (GObject *object,
+             GAsyncResult *result,
+             gpointer user_data)
+{
+	GSimpleAsyncResult *simple = user_data;
+	NMActiveConnection *ac;
+	GError *error = NULL;
+
+	ac = nm_manager_activate_connection_finish (NM_MANAGER (object), result, &error);
+	if (ac)
+		g_simple_async_result_set_op_res_gpointer (simple, ac, g_object_unref);
+	else
+		g_simple_async_result_take_error (simple, error);
+
+	g_simple_async_result_complete (simple);
+	g_object_unref (simple);
+}
+
+/**
+ * nm_client_activate_connection_async:
+ * @client: a #NMClient
+ * @connection: (allow-none): an #NMConnection
+ * @device: (allow-none): the #NMDevice
+ * @specific_object: (allow-none): the object path of a connection-type-specific
+ *   object this activation should use. This parameter is currently ignored for
+ *   wired and mobile broadband connections, and the value of %NULL should be used
+ *   (ie, no specific object).  For Wi-Fi or WiMAX connections, pass the object
+ *   path of a #NMAccessPoint or #NMWimaxNsp owned by @device, which you can
+ *   get using nm_object_get_path(), and which will be used to complete the
+ *   details of the newly added connection.
+ * @cancellable: a #GCancellable, or %NULL
+ * @callback: callback to be called when the activation has started
+ * @user_data: caller-specific data passed to @callback
+ *
+ * Asynchronously starts a connection to a particular network using the
+ * configuration settings from @connection and the network device @device.
+ * Certain connection types also take a "specific object" which is the object
+ * path of a connection- specific object, like an #NMAccessPoint for Wi-Fi
+ * connections, or an #NMWimaxNsp for WiMAX connections, to which you wish to
+ * connect.  If the specific object is not given, NetworkManager can, in some
+ * cases, automatically determine which network to connect to given the settings
+ * in @connection.
+ *
+ * If @connection is not given for a device-based activation, NetworkManager
+ * picks the best available connection for the device and activates it.
+ *
+ * Note that the callback is invoked when NetworkManager has started activating
+ * the new connection, not when it finishes. You can used the returned
+ * #NMActiveConnection object (in particular, #NMActiveConnection:state) to
+ * track the activation to its completion.
+ **/
+void
+nm_client_activate_connection_async (NMClient *client,
+                                     NMConnection *connection,
+                                     NMDevice *device,
+                                     const char *specific_object,
+                                     GCancellable *cancellable,
+                                     GAsyncReadyCallback callback,
+                                     gpointer user_data)
+{
+	GSimpleAsyncResult *simple;
+	GError *error = NULL;
+
+	g_return_if_fail (NM_IS_CLIENT (client));
+	if (device)
+		g_return_if_fail (NM_IS_DEVICE (device));
+	if (connection)
+		g_return_if_fail (NM_IS_CONNECTION (connection));
+
+	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_activate_connection_async);
+	nm_manager_activate_connection_async (NM_CLIENT_GET_PRIVATE (client)->manager,
+	                                      connection, device, specific_object,
+	                                      cancellable, activate_cb, simple);
+}
+
+/**
+ * nm_client_activate_connection_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_activate_connection_async().
+ *
+ * Returns: (transfer full): the new #NMActiveConnection on success, %NULL on
+ *   failure, in which case @error will be set.
+ **/
+NMActiveConnection *
+nm_client_activate_connection_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
+add_activate_cb (GObject *object,
+                 GAsyncResult *result,
+                 gpointer user_data)
+{
+	GSimpleAsyncResult *simple = user_data;
+	NMActiveConnection *ac;
+	GError *error = NULL;
+
+	ac = nm_manager_add_and_activate_connection_finish (NM_MANAGER (object), result, &error);
+	if (ac)
+		g_simple_async_result_set_op_res_gpointer (simple, ac, g_object_unref);
+	else
+		g_simple_async_result_take_error (simple, error);
+
+	g_simple_async_result_complete (simple);
+	g_object_unref (simple);
+}
+
+/**
+ * nm_client_add_and_activate_connection_async:
+ * @client: a #NMClient
+ * @partial: (allow-none): an #NMConnection to add; the connection may be
+ *   partially filled (or even %NULL) and will be completed by NetworkManager
+ *   using the given @device and @specific_object before being added
+ * @device: the #NMDevice
+ * @specific_object: (allow-none): the object path of a connection-type-specific
+ *   object this activation should use. This parameter is currently ignored for
+ *   wired and mobile broadband connections, and the value of %NULL should be used
+ *   (ie, no specific object).  For Wi-Fi or WiMAX connections, pass the object
+ *   path of a #NMAccessPoint or #NMWimaxNsp owned by @device, which you can
+ *   get using nm_object_get_path(), and which will be used to complete the
+ *   details of the newly added connection.
+ * @cancellable: a #GCancellable, or %NULL
+ * @callback: callback to be called when the activation has started
+ * @user_data: caller-specific data passed to @callback
+ *
+ * Adds a new connection using the given details (if any) as a template,
+ * automatically filling in missing settings with the capabilities of the given
+ * device and specific object.  The new connection is then asynchronously
+ * activated as with nm_client_activate_connection_async(). Cannot be used for
+ * VPN connections at this time.
+ *
+ * Note that the callback is invoked when NetworkManager has started activating
+ * the new connection, not when it finishes. You can used the returned
+ * #NMActiveConnection object (in particular, #NMActiveConnection:state) to
+ * track the activation to its completion.
+ **/
+void
+nm_client_add_and_activate_connection_async (NMClient *client,
+                                             NMConnection *partial,
+                                             NMDevice *device,
+                                             const char *specific_object,
+                                             GCancellable *cancellable,
+                                             GAsyncReadyCallback callback,
+                                             gpointer user_data)
+{
+	GSimpleAsyncResult *simple;
+	GError *error = NULL;
+
+	g_return_if_fail (NM_IS_CLIENT (client));
+	g_return_if_fail (NM_IS_DEVICE (device));
+	if (partial)
+		g_return_if_fail (NM_IS_CONNECTION (partial));
+
+	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_add_and_activate_connection_async);
+	nm_manager_add_and_activate_connection_async (NM_CLIENT_GET_PRIVATE (client)->manager,
+	                                              partial, device, specific_object,
+	                                              cancellable, add_activate_cb, simple);
+}
+
+/**
+ * nm_client_add_and_activate_connection_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_add_and_activate_connection_async().
+ *
+ * You can call nm_active_connection_get_connection() on the returned
+ * #NMActiveConnection to find the path of the created #NMConnection.
+ *
+ * Returns: (transfer full): the new #NMActiveConnection on success, %NULL on
+ *   failure, in which case @error will be set.
+ **/
+NMActiveConnection *
+nm_client_add_and_activate_connection_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));
+}
+
+/**
+ * nm_client_deactivate_connection:
+ * @client: a #NMClient
+ * @active: the #NMActiveConnection to deactivate
+ * @cancellable: a #GCancellable, or %NULL
+ * @error: location for a #GError, or %NULL
+ *
+ * Deactivates an active #NMActiveConnection.
+ *
+ * Returns: success or failure
+ **/
+gboolean
+nm_client_deactivate_connection (NMClient *client,
+                                 NMActiveConnection *active,
+                                 GCancellable *cancellable,
+                                 GError **error)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
+	g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (active), FALSE);
+
+	if (!_nm_client_check_nm_running (client, NULL))
+		return TRUE;
+
+	return nm_manager_deactivate_connection (NM_CLIENT_GET_PRIVATE (client)->manager,
+	                                         active, cancellable, error);
+}
+
+static void
+deactivated_cb (GObject *object,
+                GAsyncResult *result,
+                gpointer user_data)
+{
+	GSimpleAsyncResult *simple = user_data;
+	GError *error = NULL;
+
+	if (nm_manager_deactivate_connection_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_deactivate_connection_async:
+ * @client: a #NMClient
+ * @active: the #NMActiveConnection to deactivate
+ * @cancellable: a #GCancellable, or %NULL
+ * @callback: callback to be called when the deactivation has completed
+ * @user_data: caller-specific data passed to @callback
+ *
+ * Asynchronously deactivates an active #NMActiveConnection.
+ **/
+void
+nm_client_deactivate_connection_async (NMClient *client,
+                                       NMActiveConnection *active,
+                                       GCancellable *cancellable,
+                                       GAsyncReadyCallback callback,
+                                       gpointer user_data)
+{
+	GSimpleAsyncResult *simple;
+
+	g_return_if_fail (NM_IS_CLIENT (client));
+	g_return_if_fail (NM_IS_ACTIVE_CONNECTION (active));
+
+	simple = g_simple_async_result_new (G_OBJECT (client), callback, user_data,
+	                                    nm_client_deactivate_connection_async);
+
+	if (!_nm_client_check_nm_running (client, NULL)) {
+		g_simple_async_result_set_op_res_gboolean (simple, TRUE);
+		g_simple_async_result_complete_in_idle (simple);
+		g_object_unref (simple);
+		return;
+	}
+
+	nm_manager_deactivate_connection_async (NM_CLIENT_GET_PRIVATE (client)->manager,
+	                                        active,
+	                                        cancellable, deactivated_cb, simple);
+}
+
+/**
+ * nm_client_deactivate_connection_finish:
+ * @client: a #NMClient
+ * @result: the result passed to the #GAsyncReadyCallback
+ * @error: location for a #GError, or %NULL
+ *
+ * Gets the result of a call to nm_client_deactivate_connection_async().
+ *
+ * Returns: success or failure
+ **/
+gboolean
+nm_client_deactivate_connection_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);
+}
+
+/****************************************************************/
+/* Connections                                                  */
+/****************************************************************/
+
+/**
+ * nm_client_get_connections:
+ * @client: the %NMClient
+ *
+ * Returns: (transfer none) (element-type NMRemoteConnection): an array
+ * containing all connections provided by the remote settings service.  The
+ * returned array is owned by the #NMClient object and should not be modified.
+ **/
+const GPtrArray *
+nm_client_get_connections (NMClient *client)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
+
+	return nm_remote_settings_get_connections (NM_CLIENT_GET_PRIVATE (client)->settings);
+}
+
+/**
+ * nm_client_get_connection_by_id:
+ * @client: the %NMClient
+ * @id: the id of the remote connection
+ *
+ * Returns the first matching %NMRemoteConnection matching a given @id.
+ *
+ * Returns: (transfer none): the remote connection object on success, or %NULL if no
+ *  matching object was found.
+ **/
+NMRemoteConnection *
+nm_client_get_connection_by_id (NMClient *client, const char *id)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
+	g_return_val_if_fail (id != NULL, NULL);
+
+	return nm_remote_settings_get_connection_by_id (NM_CLIENT_GET_PRIVATE (client)->settings, id);
+}
+
+/**
+ * nm_client_get_connection_by_path:
+ * @client: the %NMClient
+ * @path: the D-Bus object path of the remote connection
+ *
+ * Returns the %NMRemoteConnection representing the connection at @path.
+ *
+ * Returns: (transfer none): the remote connection object on success, or %NULL if the object was
+ *  not known
+ **/
+NMRemoteConnection *
+nm_client_get_connection_by_path (NMClient *client, const char *path)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
+	g_return_val_if_fail (path != NULL, NULL);
+
+	return nm_remote_settings_get_connection_by_path (NM_CLIENT_GET_PRIVATE (client)->settings, path);
+}
+
+/**
+ * nm_client_get_connection_by_uuid:
+ * @client: the %NMClient
+ * @uuid: the UUID of the remote connection
+ *
+ * Returns the %NMRemoteConnection identified by @uuid.
+ *
+ * Returns: (transfer none): the remote connection object on success, or %NULL if the object was
+ *  not known
+ **/
+NMRemoteConnection *
+nm_client_get_connection_by_uuid (NMClient *client, const char *uuid)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
+	g_return_val_if_fail (uuid != NULL, NULL);
+
+	return nm_remote_settings_get_connection_by_uuid (NM_CLIENT_GET_PRIVATE (client)->settings, uuid);
+}
+
+static void
+add_connection_cb (GObject *object,
+                   GAsyncResult *result,
+                   gpointer user_data)
+{
+	GSimpleAsyncResult *simple = user_data;
+	NMRemoteConnection *conn;
+	GError *error = NULL;
+
+	conn = nm_remote_settings_add_connection_finish (NM_REMOTE_SETTINGS (object), result, &error);
+	if (conn)
+		g_simple_async_result_set_op_res_gpointer (simple, conn, g_object_unref);
+	else
+		g_simple_async_result_take_error (simple, error);
+
+	g_simple_async_result_complete (simple);
+	g_object_unref (simple);
+}
+
+/**
+ * nm_client_add_connection_async:
+ * @client: the %NMClient
+ * @connection: the connection to add. Note that this object's settings will be
+ *   added, not the object itself
+ * @save_to_disk: whether to immediately save the connection to disk
+ * @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
+ *
+ * Requests that the remote settings service add the given settings to a new
+ * connection.  If @save_to_disk is %TRUE, the connection is immediately written
+ * to disk; otherwise it is initially only stored in memory, but may be saved
+ * later by calling the connection's nm_remote_connection_commit_changes()
+ * method.
+ *
+ * @connection is untouched by this function and only serves as a template of
+ * the settings to add.  The #NMRemoteConnection object that represents what
+ * NetworkManager actually added is returned to @callback when the addition
+ * operation is complete.
+ *
+ * Note that the #NMRemoteConnection returned in @callback may not contain
+ * identical settings to @connection as NetworkManager may perform automatic
+ * completion and/or normalization of connection properties.
+ **/
+void
+nm_client_add_connection_async (NMClient *client,
+                                NMConnection *connection,
+                                gboolean save_to_disk,
+                                GCancellable *cancellable,
+                                GAsyncReadyCallback callback,
+                                gpointer user_data)
+{
+	GSimpleAsyncResult *simple;
+	GError *error = NULL;
+
+	g_return_if_fail (NM_IS_CLIENT (client));
+	g_return_if_fail (NM_IS_CONNECTION (connection));
+
+	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_deactivate_connection_async);
+	nm_remote_settings_add_connection_async (NM_CLIENT_GET_PRIVATE (client)->settings,
+	                                         connection, save_to_disk,
+	                                         cancellable, add_connection_cb, simple);
+}
+
+/**
+ * nm_client_add_connection_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_add_connection_async().
+ *
+ * Returns: (transfer full): the new #NMRemoteConnection on success, %NULL on
+ *   failure, in which case @error will be set.
+ **/
+NMRemoteConnection *
+nm_client_add_connection_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));
+}
+
+/**
+ * nm_client_load_connections:
+ * @client: the %NMClient
+ * @filenames: %NULL-terminated array of filenames to load
+ * @failures: (out) (transfer full): on return, a %NULL-terminated array of
+ *   filenames that failed to load
+ * @cancellable: a #GCancellable, or %NULL
+ * @error: return location for #GError
+ *
+ * Requests that the remote settings service load or reload the given files,
+ * adding or updating the connections described within.
+ *
+ * The changes to the indicated files will not yet be reflected in
+ * @client's connections array when the function returns.
+ *
+ * If all of the indicated files were successfully loaded, the
+ * function will return %TRUE, and @failures will be set to %NULL. If
+ * NetworkManager tried to load the files, but some (or all) failed,
+ * then @failures will be set to a %NULL-terminated array of the
+ * filenames that failed to load.
+ *
+ * Returns: %TRUE if NetworkManager at least tried to load @filenames,
+ * %FALSE if an error occurred (eg, permission denied).
+ **/
+gboolean
+nm_client_load_connections (NMClient *client,
+                            char **filenames,
+                            char ***failures,
+                            GCancellable *cancellable,
+                            GError **error)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
+	g_return_val_if_fail (filenames != NULL, FALSE);
+
+	if (!_nm_client_check_nm_running (client, error))
+		return FALSE;
+
+	return nm_remote_settings_load_connections (NM_CLIENT_GET_PRIVATE (client)->settings,
+	                                            filenames, failures,
+	                                            cancellable, error);
+}
+
+static void
+load_connections_cb (GObject *object, GAsyncResult *result, gpointer user_data)
+{
+	GSimpleAsyncResult *simple = user_data;
+	GError *error = NULL;
+	char **failures = NULL;
+
+	if (nm_remote_settings_load_connections_finish (NM_REMOTE_SETTINGS (object),
+	                                                &failures, result, &error))
+		g_simple_async_result_set_op_res_gpointer (simple, failures, (GDestroyNotify) g_strfreev);
+	else
+		g_simple_async_result_take_error (simple, error);
+
+	g_simple_async_result_complete (simple);
+	g_object_unref (simple);
+}
+
+/**
+ * nm_client_load_connections_async:
+ * @client: the %NMClient
+ * @filenames: %NULL-terminated array of filenames to load
+ * @cancellable: a #GCancellable, or %NULL
+ * @callback: (scope async): callback to be called when the operation completes
+ * @user_data: (closure): caller-specific data passed to @callback
+ *
+ * Requests that the remote settings service asynchronously load or reload the
+ * given files, adding or updating the connections described within.
+ *
+ * See nm_client_load_connections() for more details.
+ **/
+void
+nm_client_load_connections_async (NMClient *client,
+                                  char **filenames,
+                                  GCancellable *cancellable,
+                                  GAsyncReadyCallback callback,
+                                  gpointer user_data)
+{
+	GSimpleAsyncResult *simple;
+	GError *error = NULL;
+
+	g_return_if_fail (NM_IS_CLIENT (client));
+	g_return_if_fail (filenames != NULL);
+
+	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_load_connections_async);
+	nm_remote_settings_load_connections_async (NM_CLIENT_GET_PRIVATE (client)->settings,
+	                                           filenames,
+	                                           cancellable, load_connections_cb, simple);
+}
+
+/**
+ * nm_client_load_connections_finish:
+ * @client: the %NMClient
+ * @failures: (out) (transfer full): on return, a %NULL-terminated array of
+ *   filenames that failed to load
+ * @result: the result passed to the #GAsyncReadyCallback
+ * @error: location for a #GError, or %NULL
+ *
+ * Gets the result of an nm_client_load_connections_async() call.
+
+ * See nm_client_load_connections() for more details.
+ *
+ * Returns: %TRUE if NetworkManager at least tried to load @filenames,
+ * %FALSE if an error occurred (eg, permission denied).
+ **/
+gboolean
+nm_client_load_connections_finish (NMClient *client,
+                                   char ***failures,
+                                   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 {
+		if (failures)
+			*failures = g_strdupv (g_simple_async_result_get_op_res_gpointer (simple));
+		return TRUE;
+	}
+}
+
+/**
+ * nm_client_reload_connections:
+ * @client: the #NMClient
+ * @cancellable: a #GCancellable, or %NULL
+ * @error: return location for #GError
+ *
+ * Requests that the remote settings service reload all connection
+ * files from disk, adding, updating, and removing connections until
+ * the in-memory state matches the on-disk state.
+ *
+ * Return value: %TRUE on success, %FALSE on failure
+ **/
+gboolean
+nm_client_reload_connections (NMClient *client,
+                              GCancellable *cancellable,
+                              GError **error)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
+
+	if (!_nm_client_check_nm_running (client, error))
+		return FALSE;
+
+	return nm_remote_settings_reload_connections (NM_CLIENT_GET_PRIVATE (client)->settings,
+	                                              cancellable, error);
+}
+
+static void
+reload_connections_cb (GObject *object, GAsyncResult *result, gpointer user_data)
+{
+	GSimpleAsyncResult *simple = user_data;
+	GError *error = NULL;
+
+	if (nm_remote_settings_reload_connections_finish (NM_REMOTE_SETTINGS (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_reload_connections_async:
+ * @client: the #NMClient
+ * @cancellable: a #GCancellable, or %NULL
+ * @callback: (scope async): callback to be called when the reload operation completes
+ * @user_data: (closure): caller-specific data passed to @callback
+ *
+ * Requests that the remote settings service begin reloading all connection
+ * files from disk, adding, updating, and removing connections until the
+ * in-memory state matches the on-disk state.
+ **/
+void
+nm_client_reload_connections_async (NMClient *client,
+                                    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_reload_connections_async);
+	nm_remote_settings_reload_connections_async (NM_CLIENT_GET_PRIVATE (client)->settings,
+	                                             cancellable, reload_connections_cb, simple);
+}
+
+/**
+ * nm_client_reload_connections_finish:
+ * @client: the #NMClient
+ * @result: the result passed to the #GAsyncReadyCallback
+ * @error: return location for #GError
+ *
+ * Gets the result of an nm_client_reload_connections_async() call.
+ *
+ * Return value: %TRUE on success, %FALSE on failure
+ **/
+gboolean
+nm_client_reload_connections_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);
+}
+
+/****************************************************************/
+
+/**
+ * nm_client_new:
+ * @cancellable: a #GCancellable, or %NULL
+ * @error: location for a #GError, or %NULL
+ *
+ * Creates a new #NMClient.
+ *
+ * Note that this will do blocking D-Bus calls to initialize the
+ * client. You can use nm_client_new_async() if you want to avoid
+ * that.
+ *
+ * Returns: a new #NMClient or NULL on an error
+ **/
+NMClient *
+nm_client_new (GCancellable  *cancellable,
+               GError       **error)
+{
+	return g_initable_new (NM_TYPE_CLIENT, cancellable, error,
+	                       NULL);
+}
+
+static void
+client_inited (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+	GSimpleAsyncResult *simple = user_data;
+	GError *error = NULL;
+
+	if (!g_async_initable_new_finish (G_ASYNC_INITABLE (source), result, &error))
+		g_simple_async_result_take_error (simple, error);
+	else
+		g_simple_async_result_set_op_res_gpointer (simple, source, g_object_unref);
+	g_simple_async_result_complete (simple);
+	g_object_unref (simple);
+}
+
+/**
+ * nm_client_new_async:
+ * @cancellable: a #GCancellable, or %NULL
+ * @callback: callback to call when the client is created
+ * @user_data: data for @callback
+ *
+ * Creates a new #NMClient and begins asynchronously initializing it.
+ * @callback will be called when it is done; use
+ * nm_client_new_finish() to get the result. Note that on an error,
+ * the callback can be invoked with two first parameters as NULL.
+ **/
+void
+nm_client_new_async (GCancellable *cancellable,
+                     GAsyncReadyCallback callback,
+                     gpointer user_data)
+{
+	GSimpleAsyncResult *simple;
+
+	simple = g_simple_async_result_new (NULL, callback, user_data, nm_client_new_async);
+
+	g_async_initable_new_async (NM_TYPE_CLIENT, G_PRIORITY_DEFAULT,
+	                            cancellable, client_inited, simple,
+	                            NULL);
+}
+
+/**
+ * nm_client_new_finish:
+ * @result: a #GAsyncResult
+ * @error: location for a #GError, or %NULL
+ *
+ * Gets the result of an nm_client_new_async() call.
+ *
+ * Returns: a new #NMClient, or %NULL on error
+ **/
+NMClient *
+nm_client_new_finish (GAsyncResult *result, GError **error)
+{
+	GSimpleAsyncResult *simple;
+
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL, nm_client_new_async), NULL);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+	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
+subobject_notify (GObject *object,
+                  GParamSpec *pspec,
+                  gpointer client)
+{
+	if (!g_str_has_suffix (pspec->name, "-internal"))
+		g_object_notify (client, pspec->name);
+}
+
+static void
+manager_device_added (NMManager *manager,
+                      NMDevice *device,
+                      gpointer client)
+{
+	g_signal_emit (client, signals[DEVICE_ADDED], 0, device);
+}
+static void
+manager_device_removed (NMManager *manager,
+                        NMDevice *device,
+                        gpointer client)
+{
+	g_signal_emit (client, signals[DEVICE_REMOVED], 0, device);
+}
+
+static void
+manager_permission_changed (NMManager *manager,
+                            NMClientPermission permission,
+                            NMClientPermissionResult result,
+                            gpointer client)
+{
+	g_signal_emit (client, signals[PERMISSION_CHANGED], 0, permission, result);
+}
+
+static void
+settings_connection_added (NMRemoteSettings *manager,
+                           NMRemoteConnection *connection,
+                           gpointer client)
+{
+	g_signal_emit (client, signals[CONNECTION_ADDED], 0, connection);
+}
+static void
+settings_connection_removed (NMRemoteSettings *manager,
+                             NMRemoteConnection *connection,
+                             gpointer client)
+{
+	g_signal_emit (client, signals[CONNECTION_REMOVED], 0, connection);
+}
+
+static void
+constructed (GObject *object)
+{
+	NMClient *client = NM_CLIENT (object);
+	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
+
+	priv->manager = g_object_new (NM_TYPE_MANAGER,
+	                              NM_OBJECT_PATH, NM_DBUS_PATH,
+	                              NULL);
+	g_signal_connect (priv->manager, "notify",
+	                  G_CALLBACK (subobject_notify), client);
+	g_signal_connect (priv->manager, "device-added",
+	                  G_CALLBACK (manager_device_added), client);
+	g_signal_connect (priv->manager, "device-removed",
+	                  G_CALLBACK (manager_device_removed), client);
+	g_signal_connect (priv->manager, "permission-changed",
+	                  G_CALLBACK (manager_permission_changed), client);
+
+	priv->settings = g_object_new (NM_TYPE_REMOTE_SETTINGS,
+	                               NM_OBJECT_PATH, NM_DBUS_PATH_SETTINGS,
+	                               NULL);
+	g_signal_connect (priv->settings, "notify",
+	                  G_CALLBACK (subobject_notify), client);
+	g_signal_connect (priv->settings, "connection-added",
+	                  G_CALLBACK (settings_connection_added), client);
+	g_signal_connect (priv->settings, "connection-removed",
+	                  G_CALLBACK (settings_connection_removed), client);
+
+	G_OBJECT_CLASS (nm_client_parent_class)->constructed (object);
+}
+
+static gboolean
+init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
+{
+	NMClient *client = NM_CLIENT (initable);
+	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
+
+	if (!g_initable_init (G_INITABLE (priv->manager), cancellable, error))
+		return FALSE;
+	if (!g_initable_init (G_INITABLE (priv->settings), cancellable, error))
+		return FALSE;
+
+	return TRUE;
+}
+
+typedef struct {
+	NMClient *client;
+	GCancellable *cancellable;
+	GSimpleAsyncResult *result;
+	gboolean manager_inited;
+	gboolean settings_inited;
+} NMClientInitData;
+
+static void
+init_async_complete (NMClientInitData *init_data)
+{
+	g_simple_async_result_complete (init_data->result);
+	g_object_unref (init_data->result);
+	g_clear_object (&init_data->cancellable);
+	g_slice_free (NMClientInitData, init_data);
+}
+
+static void
+init_async_inited_manager (GObject *object, GAsyncResult *result, gpointer user_data)
+{
+	NMClientInitData *init_data = user_data;
+	GError *error = NULL;
+
+	if (!g_async_initable_init_finish (G_ASYNC_INITABLE (object), result, &error))
+		g_simple_async_result_take_error (init_data->result, error);
+
+	init_data->manager_inited = TRUE;
+	if (init_data->settings_inited)
+		init_async_complete (init_data);
+}
+
+static void
+init_async_inited_settings (GObject *object, GAsyncResult *result, gpointer user_data)
+{
+	NMClientInitData *init_data = user_data;
+	GError *error = NULL;
+
+	if (!g_async_initable_init_finish (G_ASYNC_INITABLE (object), result, &error))
+		g_simple_async_result_take_error (init_data->result, error);
+
+	init_data->settings_inited = TRUE;
+	if (init_data->manager_inited)
+		init_async_complete (init_data);
+}
+
+static void
+init_async (GAsyncInitable *initable, int io_priority,
+            GCancellable *cancellable, GAsyncReadyCallback callback,
+            gpointer user_data)
+{
+	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (initable);
+	NMClientInitData *init_data;
+
+	init_data = g_slice_new0 (NMClientInitData);
+	init_data->client = NM_CLIENT (initable);
+	init_data->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
+	init_data->result = g_simple_async_result_new (G_OBJECT (initable), callback,
+	                                               user_data, init_async);
+	g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE);
+
+	g_async_initable_init_async (G_ASYNC_INITABLE (priv->manager),
+	                             G_PRIORITY_DEFAULT, init_data->cancellable,
+	                             init_async_inited_manager, init_data);
+	g_async_initable_init_async (G_ASYNC_INITABLE (priv->settings),
+	                             G_PRIORITY_DEFAULT, init_data->cancellable,
+	                             init_async_inited_settings, init_data);
+}
+
+static gboolean
+init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error)
+{
+	GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
+
+	if (g_simple_async_result_propagate_error (simple, error))
+		return FALSE;
+	else
+		return TRUE;
+}
+
+static void
+dispose (GObject *object)
+{
+	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (object);
+
+	if (priv->manager) {
+		g_signal_handlers_disconnect_by_data (priv->manager, object);
+		g_clear_object (&priv->manager);
+	}
+	if (priv->settings) {
+		g_signal_handlers_disconnect_by_data (priv->settings, object);
+		g_clear_object (&priv->settings);
+	}
+
+	G_OBJECT_CLASS (nm_client_parent_class)->dispose (object);
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+              const GValue *value, GParamSpec *pspec)
+{
+	switch (prop_id) {
+	case PROP_NETWORKING_ENABLED:
+	case PROP_WIRELESS_ENABLED:
+	case PROP_WWAN_ENABLED:
+	case PROP_WIMAX_ENABLED:
+		g_object_set_property (G_OBJECT (NM_CLIENT_GET_PRIVATE (object)->manager),
+		                       pspec->name, value);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+              GValue *value, GParamSpec *pspec)
+{
+	switch (prop_id) {
+	case PROP_VERSION:
+	case PROP_STATE:
+	case PROP_STARTUP:
+	case PROP_NM_RUNNING:
+	case PROP_NETWORKING_ENABLED:
+	case PROP_WIRELESS_ENABLED:
+	case PROP_WIRELESS_HARDWARE_ENABLED:
+	case PROP_WWAN_ENABLED:
+	case PROP_WWAN_HARDWARE_ENABLED:
+	case PROP_WIMAX_ENABLED:
+	case PROP_WIMAX_HARDWARE_ENABLED:
+	case PROP_ACTIVE_CONNECTIONS:
+	case PROP_CONNECTIVITY:
+	case PROP_PRIMARY_CONNECTION:
+	case PROP_ACTIVATING_CONNECTION:
+	case PROP_DEVICES:
+		g_object_get_property (G_OBJECT (NM_CLIENT_GET_PRIVATE (object)->manager),
+		                       pspec->name, value);
+		break;
+	case PROP_CONNECTIONS:
+	case PROP_HOSTNAME:
+	case PROP_CAN_MODIFY:
+		g_object_get_property (G_OBJECT (NM_CLIENT_GET_PRIVATE (object)->settings),
+		                       pspec->name, value);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_client_class_init (NMClientClass *client_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (client_class);
+
+	g_type_class_add_private (client_class, sizeof (NMClientPrivate));
+
+	/* virtual methods */
+	object_class->constructed = constructed;
+	object_class->set_property = set_property;
+	object_class->get_property = get_property;
+	object_class->dispose = dispose;
+
+	/* properties */
+
+	/**
+	 * NMClient:version:
+	 *
+	 * The NetworkManager version.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_VERSION,
+		 g_param_spec_string (NM_CLIENT_VERSION, "", "",
+		                      NULL,
+		                      G_PARAM_READABLE |
+		                      G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMClient:state:
+	 *
+	 * The current daemon state.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_STATE,
+		 g_param_spec_enum (NM_CLIENT_STATE, "", "",
+		                    NM_TYPE_STATE,
+		                    NM_STATE_UNKNOWN,
+		                    G_PARAM_READABLE |
+		                    G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMClient:startup:
+	 *
+	 * Whether the daemon is still starting up.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_STARTUP,
+		 g_param_spec_boolean (NM_CLIENT_STARTUP, "", "",
+		                       FALSE,
+		                       G_PARAM_READABLE |
+		                       G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMClient:nm-running:
+	 *
+	 * Whether the daemon is running.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_NM_RUNNING,
+		 g_param_spec_boolean (NM_CLIENT_NM_RUNNING, "", "",
+		                       FALSE,
+		                       G_PARAM_READABLE |
+		                       G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMClient:networking-enabled:
+	 *
+	 * Whether networking is enabled.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_NETWORKING_ENABLED,
+		 g_param_spec_boolean (NM_CLIENT_NETWORKING_ENABLED, "", "",
+		                       TRUE,
+		                       G_PARAM_READWRITE |
+		                       G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMClient:wireless-enabled:
+	 *
+	 * Whether wireless is enabled.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_WIRELESS_ENABLED,
+		 g_param_spec_boolean (NM_CLIENT_WIRELESS_ENABLED, "", "",
+		                       FALSE,
+		                       G_PARAM_READWRITE |
+		                       G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMClient:wireless-hardware-enabled:
+	 *
+	 * Whether the wireless hardware is enabled.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_WIRELESS_HARDWARE_ENABLED,
+		 g_param_spec_boolean (NM_CLIENT_WIRELESS_HARDWARE_ENABLED, "", "",
+		                       TRUE,
+		                       G_PARAM_READABLE |
+		                       G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMClient:wwan-enabled:
+	 *
+	 * Whether WWAN functionality is enabled.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_WWAN_ENABLED,
+		 g_param_spec_boolean (NM_CLIENT_WWAN_ENABLED, "", "",
+		                       FALSE,
+		                       G_PARAM_READWRITE |
+		                       G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMClient:wwan-hardware-enabled:
+	 *
+	 * Whether the WWAN hardware is enabled.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_WWAN_HARDWARE_ENABLED,
+		 g_param_spec_boolean (NM_CLIENT_WWAN_HARDWARE_ENABLED, "", "",
+		                       FALSE,
+		                       G_PARAM_READABLE |
+		                       G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMClient:wimax-enabled:
+	 *
+	 * Whether WiMAX functionality is enabled.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_WIMAX_ENABLED,
+		 g_param_spec_boolean (NM_CLIENT_WIMAX_ENABLED, "", "",
+		                       FALSE,
+		                       G_PARAM_READWRITE |
+		                       G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMClient:wimax-hardware-enabled:
+	 *
+	 * Whether the WiMAX hardware is enabled.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_WIMAX_HARDWARE_ENABLED,
+		 g_param_spec_boolean (NM_CLIENT_WIMAX_HARDWARE_ENABLED, "", "",
+		                       FALSE,
+		                       G_PARAM_READABLE |
+		                       G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMClient:active-connections:
+	 *
+	 * The active connections.
+	 *
+	 * Element-type: NMActiveConnection
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_ACTIVE_CONNECTIONS,
+		 g_param_spec_boxed (NM_CLIENT_ACTIVE_CONNECTIONS, "", "",
+		                     G_TYPE_PTR_ARRAY,
+		                     G_PARAM_READABLE |
+		                     G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMClient:connectivity:
+	 *
+	 * The network connectivity state.
+	 */
+	g_object_class_install_property
+		(object_class, PROP_CONNECTIVITY,
+		 g_param_spec_enum (NM_CLIENT_CONNECTIVITY, "", "",
+		                    NM_TYPE_CONNECTIVITY_STATE,
+		                    NM_CONNECTIVITY_UNKNOWN,
+		                    G_PARAM_READABLE |
+		                    G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMClient:primary-connection:
+	 *
+	 * The #NMActiveConnection of the device with the default route;
+	 * see nm_client_get_primary_connection() for more details.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_PRIMARY_CONNECTION,
+		 g_param_spec_object (NM_CLIENT_PRIMARY_CONNECTION, "", "",
+		                      NM_TYPE_ACTIVE_CONNECTION,
+		                      G_PARAM_READABLE |
+		                      G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMClient:activating-connection:
+	 *
+	 * The #NMActiveConnection of the activating connection that is
+	 * likely to become the new #NMClient:primary-connection.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_ACTIVATING_CONNECTION,
+		 g_param_spec_object (NM_CLIENT_ACTIVATING_CONNECTION, "", "",
+		                      NM_TYPE_ACTIVE_CONNECTION,
+		                      G_PARAM_READABLE |
+		                      G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMClient:devices:
+	 *
+	 * List of known network devices.
+	 *
+	 * Element-type: NMDevice
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_DEVICES,
+		 g_param_spec_boxed (NM_CLIENT_DEVICES, "", "",
+		                     G_TYPE_PTR_ARRAY,
+		                     G_PARAM_READABLE |
+		                     G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMClient:connections:
+	 *
+	 * 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,
+		 g_param_spec_boxed (NM_CLIENT_CONNECTIONS, "", "",
+		                     G_TYPE_PTR_ARRAY,
+		                     G_PARAM_READABLE |
+		                     G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMClient:hostname:
+	 *
+	 * The machine hostname stored in persistent configuration. This can be
+	 * modified by calling nm_client_save_hostname().
+	 */
+	g_object_class_install_property
+		(object_class, PROP_HOSTNAME,
+		 g_param_spec_string (NM_CLIENT_HOSTNAME, "", "",
+		                      NULL,
+		                      G_PARAM_READABLE |
+		                      G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMClient:can-modify:
+	 *
+	 * If %TRUE, adding and modifying connections is supported.
+	 */
+	g_object_class_install_property
+		(object_class, PROP_CAN_MODIFY,
+		 g_param_spec_boolean (NM_CLIENT_CAN_MODIFY, "", "",
+		                       FALSE,
+		                       G_PARAM_READABLE |
+		                       G_PARAM_STATIC_STRINGS));
+
+	/* signals */
+
+	/**
+	 * NMClient::device-added:
+	 * @client: the client that received the signal
+	 * @device: (type NMDevice): the new device
+	 *
+	 * Notifies that a #NMDevice is added.
+	 **/
+	signals[DEVICE_ADDED] =
+		g_signal_new (NM_CLIENT_DEVICE_ADDED,
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_FIRST,
+		              G_STRUCT_OFFSET (NMClientClass, device_added),
+		              NULL, NULL, NULL,
+		              G_TYPE_NONE, 1,
+		              G_TYPE_OBJECT);
+
+	/**
+	 * NMClient::device-removed:
+	 * @client: the client that received the signal
+	 * @device: (type NMDevice): the removed device
+	 *
+	 * Notifies that a #NMDevice is removed.
+	 **/
+	signals[DEVICE_REMOVED] =
+		g_signal_new (NM_CLIENT_DEVICE_REMOVED,
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_FIRST,
+		              G_STRUCT_OFFSET (NMClientClass, device_removed),
+		              NULL, NULL, NULL,
+		              G_TYPE_NONE, 1,
+		              G_TYPE_OBJECT);
+
+	/**
+	 * NMClient::permission-changed:
+	 * @client: the client that received the signal
+	 * @permission: a permission from #NMClientPermission
+	 * @result: the permission's result, one of #NMClientPermissionResult
+	 *
+	 * Notifies that a permission has changed
+	 **/
+	signals[PERMISSION_CHANGED] =
+		g_signal_new (NM_CLIENT_PERMISSION_CHANGED,
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_FIRST,
+		              0, NULL, NULL, NULL,
+		              G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
+	/**
+	 * NMClient::connection-added:
+	 * @client: the settings object that received the signal
+	 * @connection: the new connection
+	 *
+	 * Notifies that a #NMConnection has been added.
+	 **/
+	signals[CONNECTION_ADDED] =
+		g_signal_new (NM_CLIENT_CONNECTION_ADDED,
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_FIRST,
+		              G_STRUCT_OFFSET (NMClientClass, connection_added),
+		              NULL, NULL, NULL,
+		              G_TYPE_NONE, 1,
+		              NM_TYPE_REMOTE_CONNECTION);
+
+	/**
+	 * NMClient::connection-removed:
+	 * @client: the settings object that received the signal
+	 * @connection: the removed connection
+	 *
+	 * Notifies that a #NMConnection has been removed.
+	 **/
+	signals[CONNECTION_REMOVED] =
+		g_signal_new (NM_CLIENT_CONNECTION_REMOVED,
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_FIRST,
+		              G_STRUCT_OFFSET (NMClientClass, connection_removed),
+		              NULL, NULL, NULL,
+		              G_TYPE_NONE, 1,
+		              NM_TYPE_REMOTE_CONNECTION);
+}
+
+static void
+nm_client_initable_iface_init (GInitableIface *iface)
+{
+	iface->init = init_sync;
+}
+
+static void
+nm_client_async_initable_iface_init (GAsyncInitableIface *iface)
+{
+	iface->init_async = init_async;
+	iface->init_finish = init_finish;
+}