1    	/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2    	/*
3    	 * libnm_glib -- Access network status & information from glib applications
4    	 *
5    	 * This library is free software; you can redistribute it and/or
6    	 * modify it under the terms of the GNU Lesser General Public
7    	 * License as published by the Free Software Foundation; either
8    	 * version 2 of the License, or (at your option) any later version.
9    	 *
10   	 * This library is distributed in the hope that it will be useful,
11   	 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   	 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   	 * Lesser General Public License for more details.
14   	 *
15   	 * You should have received a copy of the GNU Lesser General Public
16   	 * License along with this library; if not, write to the
17   	 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18   	 * Boston, MA 02110-1301 USA.
19   	 *
20   	 * Copyright (C) 2007 - 2008 Novell, Inc.
21   	 * Copyright (C) 2007 - 2013 Red Hat, Inc.
22   	 */
23   	
24   	#include <dbus/dbus-glib.h>
25   	#include <string.h>
26   	#include <nm-utils.h>
27   	
28   	#include "nm-client.h"
29   	#include "nm-device-ethernet.h"
30   	#include "nm-device-wifi.h"
31   	#include "nm-device-private.h"
32   	#include "nm-types-private.h"
33   	#include "nm-object-private.h"
34   	#include "nm-active-connection.h"
35   	#include "nm-vpn-connection.h"
36   	#include "nm-object-cache.h"
37   	#include "nm-dbus-glib-types.h"
38   	#include "nm-glib-compat.h"
39   	
40   	void _nm_device_wifi_set_wireless_enabled (NMDeviceWifi *device, gboolean enabled);
41   	
42   	static void nm_client_initable_iface_init (GInitableIface *iface);
43   	static void nm_client_async_initable_iface_init (GAsyncInitableIface *iface);
44   	static GInitableIface *nm_client_parent_initable_iface;
45   	static GAsyncInitableIface *nm_client_parent_async_initable_iface;
46   	
47   	G_DEFINE_TYPE_WITH_CODE (NMClient, nm_client, NM_TYPE_OBJECT,
48   	                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_client_initable_iface_init);
49   	                         G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_client_async_initable_iface_init);
50   	                         )
51   	
52   	#define NM_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CLIENT, NMClientPrivate))
53   	
54   	typedef struct {
55   		DBusGProxy *client_proxy;
56   		DBusGProxy *bus_proxy;
57   		gboolean manager_running;
58   		char *version;
59   		NMState state;
60   		gboolean startup;
61   		GPtrArray *devices;
62   		GPtrArray *active_connections;
63   		NMConnectivityState connectivity;
64   		NMActiveConnection *primary_connection;
65   		NMActiveConnection *activating_connection;
66   	
67   		DBusGProxyCall *perm_call;
68   		GHashTable *permissions;
69   	
70   		/* Activations waiting for their NMActiveConnection
71   		 * to appear and then their callback to be called.
72   		 */
73   		GSList *pending_activations;
74   	
75   		gboolean networking_enabled;
76   		gboolean wireless_enabled;
77   		gboolean wireless_hw_enabled;
78   	
79   		gboolean wwan_enabled;
80   		gboolean wwan_hw_enabled;
81   	
82   		gboolean wimax_enabled;
83   		gboolean wimax_hw_enabled;
84   	} NMClientPrivate;
85   	
86   	enum {
87   		PROP_0,
88   		PROP_VERSION,
89   		PROP_STATE,
90   		PROP_STARTUP,
91   		PROP_MANAGER_RUNNING,
92   		PROP_NETWORKING_ENABLED,
93   		PROP_WIRELESS_ENABLED,
94   		PROP_WIRELESS_HARDWARE_ENABLED,
95   		PROP_WWAN_ENABLED,
96   		PROP_WWAN_HARDWARE_ENABLED,
97   		PROP_WIMAX_ENABLED,
98   		PROP_WIMAX_HARDWARE_ENABLED,
99   		PROP_ACTIVE_CONNECTIONS,
100  		PROP_CONNECTIVITY,
101  		PROP_PRIMARY_CONNECTION,
102  		PROP_ACTIVATING_CONNECTION,
103  	
104  		LAST_PROP
105  	};
106  	
107  	enum {
108  		DEVICE_ADDED,
109  		DEVICE_REMOVED,
110  		PERMISSION_CHANGED,
111  	
112  		LAST_SIGNAL
113  	};
114  	
115  	static guint signals[LAST_SIGNAL] = { 0 };
116  	
117  	static void proxy_name_owner_changed (DBusGProxy *proxy,
118  										  const char *name,
119  										  const char *old_owner,
120  										  const char *new_owner,
121  										  gpointer user_data);
122  	
123  	static void client_device_added (NMObject *client, NMObject *device);
124  	static void client_device_removed (NMObject *client, NMObject *device);
125  	
126  	/**********************************************************************/
127  	
128  	/**
129  	 * nm_client_error_quark:
130  	 *
131  	 * Registers an error quark for #NMClient if necessary.
132  	 *
133  	 * Returns: the error quark used for #NMClient errors.
134  	 *
135  	 * Since: 0.9.10
136  	 **/
137  	GQuark
138  	nm_client_error_quark (void)
139  	{
140  		static GQuark quark;
141  	
142  		if (G_UNLIKELY (!quark))
143  			quark = g_quark_from_static_string ("nm-client-error-quark");
144  		return quark;
145  	}
146  	
147  	/**********************************************************************/
148  	
149  	static void
150  	nm_client_init (NMClient *client)
151  	{
152  		NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
153  	
154  		priv->state = NM_STATE_UNKNOWN;
155  	
156  		priv->permissions = g_hash_table_new (g_direct_hash, g_direct_equal);
157  	}
158  	
159  	static void
160  	poke_wireless_devices_with_rf_status (NMClient *client)
161  	{
162  		NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
163  		int i;
164  	
165  		for (i = 0; priv->devices && (i < priv->devices->len); i++) {
166  			NMDevice *device = g_ptr_array_index (priv->devices, i);
167  	
168  			if (NM_IS_DEVICE_WIFI (device))
169  				_nm_device_wifi_set_wireless_enabled (NM_DEVICE_WIFI (device), priv->wireless_enabled);
170  		}
171  	}
172  	
173  	static void
174  	wireless_enabled_cb (GObject *object, GParamSpec *pspec, gpointer user_data)
175  	{
176  		poke_wireless_devices_with_rf_status (NM_CLIENT (object));
177  	}
178  	
179  	static void
180  	register_properties (NMClient *client)
181  	{
182  		NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
183  		const NMPropertiesInfo property_info[] = {
184  			{ NM_CLIENT_VERSION,                   &priv->version },
185  			{ NM_CLIENT_STATE,                     &priv->state },
186  			{ NM_CLIENT_STARTUP,                   &priv->startup },
187  			{ NM_CLIENT_NETWORKING_ENABLED,        &priv->networking_enabled },
188  			{ NM_CLIENT_WIRELESS_ENABLED,          &priv->wireless_enabled },
189  			{ NM_CLIENT_WIRELESS_HARDWARE_ENABLED, &priv->wireless_hw_enabled },
190  			{ NM_CLIENT_WWAN_ENABLED,              &priv->wwan_enabled },
191  			{ NM_CLIENT_WWAN_HARDWARE_ENABLED,     &priv->wwan_hw_enabled },
192  			{ NM_CLIENT_WIMAX_ENABLED,             &priv->wimax_enabled },
193  			{ NM_CLIENT_WIMAX_HARDWARE_ENABLED,    &priv->wimax_hw_enabled },
194  			{ NM_CLIENT_ACTIVE_CONNECTIONS,        &priv->active_connections, NULL, NM_TYPE_ACTIVE_CONNECTION },
195  			{ NM_CLIENT_CONNECTIVITY,              &priv->connectivity },
196  			{ NM_CLIENT_PRIMARY_CONNECTION,        &priv->primary_connection, NULL, NM_TYPE_ACTIVE_CONNECTION },
197  			{ NM_CLIENT_ACTIVATING_CONNECTION,     &priv->activating_connection, NULL, NM_TYPE_ACTIVE_CONNECTION },
198  			{ NULL },
199  		};
200  	
201  		_nm_object_register_properties (NM_OBJECT (client),
202  		                                priv->client_proxy,
203  		                                property_info);
204  	
205  		_nm_object_register_pseudo_property (NM_OBJECT (client),
206  		                                     priv->client_proxy,
207  		                                     "Devices",
208  		                                     &priv->devices,
209  		                                     NM_TYPE_DEVICE,
210  		                                     client_device_added,
211  		                                     client_device_removed);
212  	}
213  	
214  	#define NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK     "org.freedesktop.NetworkManager.enable-disable-network"
215  	#define NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI        "org.freedesktop.NetworkManager.enable-disable-wifi"
216  	#define NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN        "org.freedesktop.NetworkManager.enable-disable-wwan"
217  	#define NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX       "org.freedesktop.NetworkManager.enable-disable-wimax"
218  	#define NM_AUTH_PERMISSION_SLEEP_WAKE                 "org.freedesktop.NetworkManager.sleep-wake"
219  	#define NM_AUTH_PERMISSION_NETWORK_CONTROL            "org.freedesktop.NetworkManager.network-control"
220  	#define NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED       "org.freedesktop.NetworkManager.wifi.share.protected"
221  	#define NM_AUTH_PERMISSION_WIFI_SHARE_OPEN            "org.freedesktop.NetworkManager.wifi.share.open"
222  	#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM     "org.freedesktop.NetworkManager.settings.modify.system"
223  	#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN        "org.freedesktop.NetworkManager.settings.modify.own"
224  	#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME   "org.freedesktop.NetworkManager.settings.modify.hostname"
225  	
226  	static NMClientPermission
227  	nm_permission_to_client (const char *nm)
228  	{
229  		if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK))
230  			return NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK;
231  		else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI))
232  			return NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI;
233  		else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN))
234  			return NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN;
235  		else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX))
236  			return NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX;
237  		else if (!strcmp (nm, NM_AUTH_PERMISSION_SLEEP_WAKE))
238  			return NM_CLIENT_PERMISSION_SLEEP_WAKE;
239  		else if (!strcmp (nm, NM_AUTH_PERMISSION_NETWORK_CONTROL))
240  			return NM_CLIENT_PERMISSION_NETWORK_CONTROL;
241  		else if (!strcmp (nm, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED))
242  			return NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED;
243  		else if (!strcmp (nm, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN))
244  			return NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN;
245  		else if (!strcmp (nm, NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM))
246  			return NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM;
247  		else if (!strcmp (nm, NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN))
248  			return NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN;
249  		else if (!strcmp (nm, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME))
250  			return NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME;
251  	
252  		return NM_CLIENT_PERMISSION_NONE;
253  	}
254  	
255  	static NMClientPermissionResult
256  	nm_permission_result_to_client (const char *nm)
257  	{
258  		if (!strcmp (nm, "yes"))
259  			return NM_CLIENT_PERMISSION_RESULT_YES;
260  		else if (!strcmp (nm, "no"))
261  			return NM_CLIENT_PERMISSION_RESULT_NO;
262  		else if (!strcmp (nm, "auth"))
263  			return NM_CLIENT_PERMISSION_RESULT_AUTH;
264  		return NM_CLIENT_PERMISSION_RESULT_UNKNOWN;
265  	}
266  	
267  	static void
268  	update_permissions (NMClient *self, GHashTable *permissions)
269  	{
270  		NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self);
271  		GHashTableIter iter;
272  		gpointer key, value;
273  		NMClientPermission perm;
274  		NMClientPermissionResult perm_result;
275  		GList *keys, *keys_iter;
276  	
277  		/* get list of old permissions for change notification */
278  		keys = g_hash_table_get_keys (priv->permissions);
279  		g_hash_table_remove_all (priv->permissions);
280  	
281  		if (permissions) {
282  			/* Process new permissions */
283  			g_hash_table_iter_init (&iter, permissions);
284  			while (g_hash_table_iter_next (&iter, &key, &value)) {
285  				perm = nm_permission_to_client ((const char *) key);
286  				perm_result = nm_permission_result_to_client ((const char *) value);
287  				if (perm) {
288  					g_hash_table_insert (priv->permissions,
289  					                     GUINT_TO_POINTER (perm),
290  					                     GUINT_TO_POINTER (perm_result));
291  	
292  					/* Remove this permission from the list of previous permissions
293  					 * we'll be sending NM_CLIENT_PERMISSION_RESULT_UNKNOWN for
294  					 * in the change signal since it is still a known permission.
295  					 */
296  					keys = g_list_remove (keys, GUINT_TO_POINTER (perm));
297  				}
298  			}
299  		}
300  	
301  		/* Signal changes in all updated permissions */
302  		g_hash_table_iter_init (&iter, priv->permissions);
303  		while (g_hash_table_iter_next (&iter, &key, &value)) {
304  			g_signal_emit (self, signals[PERMISSION_CHANGED], 0,
305  			               GPOINTER_TO_UINT (key),
306  			               GPOINTER_TO_UINT (value));
307  		}
308  	
309  		/* And signal changes in all permissions that used to be valid but for
310  		 * some reason weren't received in the last request (if any).
311  		 */
312  		for (keys_iter = keys; keys_iter; keys_iter = g_list_next (keys_iter)) {
313  			g_signal_emit (self, signals[PERMISSION_CHANGED], 0,
314  			               GPOINTER_TO_UINT (keys_iter->data),
315  			               NM_CLIENT_PERMISSION_RESULT_UNKNOWN);
316  		}
317  		g_list_free (keys);
318  	}
319  	
320  	static gboolean
321  	get_permissions_sync (NMClient *self, GError **error)
322  	{
323  		gboolean success;
324  		GHashTable *permissions = NULL;
325  	
326  		success = dbus_g_proxy_call_with_timeout (NM_CLIENT_GET_PRIVATE (self)->client_proxy,
327  		                                          "GetPermissions", 3000, error,
328  		                                          G_TYPE_INVALID,
329  		                                          DBUS_TYPE_G_MAP_OF_STRING, &permissions, G_TYPE_INVALID);
330  		update_permissions (self, success ? permissions : NULL);
331  		if (permissions)
332  			g_hash_table_destroy (permissions);
333  	
334  		return success;
335  	}
336  	
337  	static void
338  	get_permissions_reply (DBusGProxy *proxy,
339  	                       DBusGProxyCall *call,
340  	                       gpointer user_data)
341  	{
342  		NMClient *self = NM_CLIENT (user_data);
343  		GHashTable *permissions;
344  		GError *error = NULL;
345  	
346  		dbus_g_proxy_end_call (proxy, call, &error,
347  		                       DBUS_TYPE_G_MAP_OF_STRING, &permissions,
348  		                       G_TYPE_INVALID);
349  		NM_CLIENT_GET_PRIVATE (self)->perm_call = NULL;
350  		update_permissions (NM_CLIENT (user_data), error ? NULL : permissions);
351  		g_clear_error (&error);
352  	}
353  	
354  	static void
355  	client_recheck_permissions (DBusGProxy *proxy, gpointer user_data)
356  	{
357  		NMClient *self = NM_CLIENT (user_data);
358  		NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self);
359  	
360  		if (!priv->perm_call) {
361  			priv->perm_call = dbus_g_proxy_begin_call (NM_CLIENT_GET_PRIVATE (self)->client_proxy, "GetPermissions",
362  			                                           get_permissions_reply, self, NULL,
363  			                                           G_TYPE_INVALID);
364  		}
365  	}
366  	
367  	/**
368  	 * nm_client_get_devices:
369  	 * @client: a #NMClient
370  	 *
371  	 * Gets all the known network devices.  Use nm_device_get_type() or the
372  	 * NM_IS_DEVICE_XXXX() functions to determine what kind of device member of the
373  	 * returned array is, and then you may use device-specific methods such as
374  	 * nm_device_ethernet_get_hw_address().
375  	 *
376  	 * Returns: (transfer none) (element-type NMClient.Device): a #GPtrArray
377  	 * containing all the #NMDevices.  The returned array is owned by the
378  	 * #NMClient object and should not be modified.
379  	 **/
380  	const GPtrArray *
381  	nm_client_get_devices (NMClient *client)
382  	{
383  		g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
384  	
385  		_nm_object_ensure_inited (NM_OBJECT (client));
386  	
387  		return handle_ptr_array_return (NM_CLIENT_GET_PRIVATE (client)->devices);
388  	}
389  	
390  	/**
391  	 * nm_client_get_device_by_path:
392  	 * @client: a #NMClient
393  	 * @object_path: the object path to search for
394  	 *
395  	 * Gets a #NMDevice from a #NMClient.
396  	 *
397  	 * Returns: (transfer none): the #NMDevice for the given @object_path or %NULL if none is found.
398  	 **/
399  	NMDevice *
400  	nm_client_get_device_by_path (NMClient *client, const char *object_path)
401  	{
402  		const GPtrArray *devices;
403  		int i;
404  		NMDevice *device = NULL;
405  	
406  		g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
407  		g_return_val_if_fail (object_path, NULL);
408  	
409  		devices = nm_client_get_devices (client);
410  		if (!devices)
411  			return NULL;
412  	
413  		for (i = 0; i < devices->len; i++) {
414  			NMDevice *candidate = g_ptr_array_index (devices, i);
415  			if (!strcmp (nm_object_get_path (NM_OBJECT (candidate)), object_path)) {
416  				device = candidate;
417  				break;
418  			}
419  		}
420  	
421  		return device;
422  	}
423  	
424  	/**
425  	 * nm_client_get_device_by_iface:
426  	 * @client: a #NMClient
427  	 * @iface: the interface name to search for
428  	 *
429  	 * Gets a #NMDevice from a #NMClient.
430  	 *
431  	 * Returns: (transfer none): the #NMDevice for the given @iface or %NULL if none is found.
432  	 **/
433  	NMDevice *
434  	nm_client_get_device_by_iface (NMClient *client, const char *iface)
435  	{
436  		const GPtrArray *devices;
437  		int i;
438  		NMDevice *device = NULL;
439  	
440  		g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
441  		g_return_val_if_fail (iface, NULL);
442  	
443  		devices = nm_client_get_devices (client);
444  		if (!devices)
445  			return NULL;
446  	
447  		for (i = 0; i < devices->len; i++) {
448  			NMDevice *candidate = g_ptr_array_index (devices, i);
449  			if (!strcmp (nm_device_get_iface (candidate), iface)) {
450  				device = candidate;
451  				break;
452  			}
453  		}
454  	
455  		return device;
456  	}
457  	
458  	typedef struct {
459  		NMClient *client;
460  		NMClientActivateFn act_fn;
461  		NMClientAddActivateFn add_act_fn;
462  		char *active_path;
463  		char *new_connection_path;
464  		guint idle_id;
465  		gpointer user_data;
466  	} ActivateInfo;
467  	
468  	static void
469  	activate_info_free (ActivateInfo *info)
470  	{
471  		if (info->idle_id)
472  			g_source_remove (info->idle_id);
473  		g_free (info->active_path);
474  		g_free (info->new_connection_path);
475  		memset (info, 0, sizeof (*info));
476  		g_slice_free (ActivateInfo, info);
477  	}
478  	
479  	static void
480  	activate_info_complete (ActivateInfo *info,
481  	                        NMActiveConnection *active,
482  	                        GError *error)
483  	{
484  		NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (info->client);
485  	
486  		if (info->act_fn)
487  			info->act_fn (info->client, error ? NULL : active, error, info->user_data);
488  		else if (info->add_act_fn) {
489  			info->add_act_fn (info->client,
490  			                  error ? NULL : active,
491  			                  error ? NULL : info->new_connection_path,
492  			                  error,
493  			                  info->user_data);
494  		} else if (error)
495  			g_warning ("Device activation failed: (%d) %s", error->code, error->message);
496  	
497  		priv->pending_activations = g_slist_remove (priv->pending_activations, info);
498  	}
499  	
500  	static void
501  	recheck_pending_activations (NMClient *self, const char *failed_path, GError *error)
502  	{
503  		NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self);
504  		GSList *iter, *next;
505  		const GPtrArray *active_connections;
506  		gboolean found_in_active = FALSE;
507  		gboolean found_in_pending = FALSE;
508  		ActivateInfo *ainfo = NULL;
509  		int i;
510  	
511  		active_connections = nm_client_get_active_connections (self);
512  	
513  		/* For each pending activation, look for a active connection that has
514  		 * the pending activation's object path, and call pending connection's
515  		 * callback.
516  		 * If the connection to activate doesn't make it to active_connections,
517  		 * due to an error, we have to call the callback for failed_path.
518  		 */
519  		for (iter = priv->pending_activations; iter; iter = next) {
520  			ActivateInfo *info = iter->data;
521  	
522  			next = g_slist_next (iter);
523  	
524  			if (!found_in_pending && failed_path && g_strcmp0 (failed_path, info->active_path) == 0) {
525  				found_in_pending = TRUE;
526  				ainfo = info;
527  			}
528  	
529  			for (i = 0; active_connections && i < active_connections->len; i++) {
530  				NMActiveConnection *active = g_ptr_array_index (active_connections, i);
531  				const char *active_path = nm_object_get_path (NM_OBJECT (active));
532  	
533  				if (!found_in_active && failed_path && g_strcmp0 (failed_path, active_path) == 0)
534  					found_in_active = TRUE;
535  	
536  				if (g_strcmp0 (info->active_path, active_path) == 0) {
537  					/* Call the pending activation's callback and it all up */
538  					activate_info_complete (info, active, NULL);
539  					activate_info_free (info);
540  					break;
541  				}
542  			}
543  		}
544  	
545  		if (!found_in_active && found_in_pending) {
546  			/* A newly activated connection failed due to some immediate error
547  			 * and disappeared from active connection list.  Make sure the
548  			 * callback gets called.
549  			 */
550  			activate_info_complete (ainfo, NULL, error);
551  			activate_info_free (ainfo);
552  		}
553  	}
554  	
555  	static void
556  	activate_cb (DBusGProxy *proxy,
557  	             DBusGProxyCall *call,
558  	             gpointer user_data)
559  	{
560  		ActivateInfo *info = user_data;
561  		char *path;
562  		GError *error = NULL;
563  	
564  		dbus_g_proxy_end_call (proxy, call, &error,
565  		                       DBUS_TYPE_G_OBJECT_PATH, &path,
566  		                       G_TYPE_INVALID);
567  		if (error) {
568  			activate_info_complete (info, NULL, error);
569  			activate_info_free (info);
570  			g_clear_error (&error);
571  		} else {
572  			info->active_path = path;
573  			recheck_pending_activations (info->client, NULL, NULL);
574  		}
575  	}
576  	
577  	static gboolean
578  	activate_nm_not_running (gpointer user_data)
579  	{
580  		ActivateInfo *info = user_data;
581  		GError *error;
582  	
583  		info->idle_id = 0;
584  	
585  		error = g_error_new_literal (NM_CLIENT_ERROR,
586  		                             NM_CLIENT_ERROR_MANAGER_NOT_RUNNING,
587  		                             "NetworkManager is not running");
588  		activate_info_complete (info, NULL, error);
589  		activate_info_free (info);
590  		g_clear_error (&error);
591  		return FALSE;
592  	}
593  	
594  	/**
595  	 * nm_client_activate_connection:
596  	 * @client: a #NMClient
597  	 * @connection: an #NMConnection
598  	 * @device: (allow-none): the #NMDevice
599  	 * @specific_object: (allow-none): the object path of a connection-type-specific
600  	 *   object this activation should use. This parameter is currently ignored for
601  	 *   wired and mobile broadband connections, and the value of %NULL should be used
602  	 *   (ie, no specific object).  For WiFi or WiMAX connections, pass the object
603  	 *   path of a #NMAccessPoint or #NMWimaxNsp owned by @device, which you can
604  	 *   get using nm_object_get_path(), and which will be used to complete the
605  	 *   details of the newly added connection.
606  	 * @callback: (scope async) (allow-none): the function to call when the call is done
607  	 * @user_data: (closure): user data to pass to the callback function
608  	 *
609  	 * Starts a connection to a particular network using the configuration settings
610  	 * from @connection and the network device @device.  Certain connection types
611  	 * also take a "specific object" which is the object path of a connection-
612  	 * specific object, like an #NMAccessPoint for WiFi connections, or an
613  	 * #NMWimaxNsp for WiMAX connections, to which you wish to connect.  If the
614  	 * specific object is not given, NetworkManager can, in some cases, automatically
615  	 * determine which network to connect to given the settings in @connection.
616  	 **/
617  	void
618  	nm_client_activate_connection (NMClient *client,
619  	                               NMConnection *connection,
620  	                               NMDevice *device,
621  	                               const char *specific_object,
622  	                               NMClientActivateFn callback,
623  	                               gpointer user_data)
624  	{
625  		NMClientPrivate *priv;
626  		ActivateInfo *info;
627  	
628  		g_return_if_fail (NM_IS_CLIENT (client));
629  		if (device)
630  			g_return_if_fail (NM_IS_DEVICE (device));
631  		g_return_if_fail (NM_IS_CONNECTION (connection));
632  	
633  		info = g_slice_new0 (ActivateInfo);
634  		info->act_fn = callback;
635  		info->user_data = user_data;
636  		info->client = client;
637  	
638  		priv = NM_CLIENT_GET_PRIVATE (client);
639  		priv->pending_activations = g_slist_prepend (priv->pending_activations, info);
640  	
641  		if (priv->manager_running == FALSE) {
642  			info->idle_id = g_idle_add (activate_nm_not_running, info);
643  			return;
644  		}
645  	
646  		dbus_g_proxy_begin_call (priv->client_proxy, "ActivateConnection",
647  		                         activate_cb, info, NULL,
648  		                         DBUS_TYPE_G_OBJECT_PATH, nm_connection_get_path (connection),
649  		                         DBUS_TYPE_G_OBJECT_PATH, device ? nm_object_get_path (NM_OBJECT (device)) : "/",
650  		                         DBUS_TYPE_G_OBJECT_PATH, specific_object ? specific_object : "/",
651  		                         G_TYPE_INVALID);
652  	}
653  	
654  	static void
655  	add_activate_cb (DBusGProxy *proxy,
656  	                 DBusGProxyCall *call,
657  	                 gpointer user_data)
658  	{
659  		ActivateInfo *info = user_data;
660  		char *connection_path;
661  		char *active_path;
662  		GError *error = NULL;
663  	
664  		dbus_g_proxy_end_call (proxy, call, &error,
665  		                       DBUS_TYPE_G_OBJECT_PATH, &connection_path,
666  		                       DBUS_TYPE_G_OBJECT_PATH, &active_path,
667  		                       G_TYPE_INVALID);
668  		if (error) {
669  			activate_info_complete (info, NULL, error);
670  			activate_info_free (info);
671  		} else {
672  			info->new_connection_path = connection_path;
673  			info->active_path = active_path;
674  			recheck_pending_activations (info->client, NULL, NULL);
675  		}
676  	}
677  	
678  	/**
679  	 * nm_client_add_and_activate_connection:
680  	 * @client: a #NMClient
681  	 * @partial: (allow-none): an #NMConnection to add; the connection may be
682  	 *   partially filled (or even %NULL) and will be completed by NetworkManager
683  	 *   using the given @device and @specific_object before being added
684  	 * @device: the #NMDevice
685  	 * @specific_object: (allow-none): the object path of a connection-type-specific
686  	 *   object this activation should use. This parameter is currently ignored for
687  	 *   wired and mobile broadband connections, and the value of %NULL should be used
688  	 *   (ie, no specific object).  For WiFi or WiMAX connections, pass the object
689  	 *   path of a #NMAccessPoint or #NMWimaxNsp owned by @device, which you can
690  	 *   get using nm_object_get_path(), and which will be used to complete the
691  	 *   details of the newly added connection.
692  	 * @callback: (scope async) (allow-none): the function to call when the call is done
693  	 * @user_data: (closure): user data to pass to the callback function
694  	 *
695  	 * Adds a new connection using the given details (if any) as a template,
696  	 * automatically filling in missing settings with the capabilities of the
697  	 * given device and specific object.  The new connection is then activated.
698  	 * Cannot be used for VPN connections at this time.
699  	 **/
700  	void
701  	nm_client_add_and_activate_connection (NMClient *client,
702  	                                       NMConnection *partial,
703  	                                       NMDevice *device,
704  	                                       const char *specific_object,
705  	                                       NMClientAddActivateFn callback,
706  	                                       gpointer user_data)
707  	{
708  		NMClientPrivate *priv;
709  		ActivateInfo *info;
710  		GHashTable *hash = NULL;
711  	
712  		g_return_if_fail (NM_IS_CLIENT (client));
713  		g_return_if_fail (NM_IS_DEVICE (device));
714  	
715  		info = g_slice_new0 (ActivateInfo);
716  		info->add_act_fn = callback;
717  		info->user_data = user_data;
718  		info->client = client;
719  	
720  		if (partial)
721  			hash = nm_connection_to_hash (partial, NM_SETTING_HASH_FLAG_ALL);
722  		if (!hash)
723  			hash = g_hash_table_new (g_str_hash, g_str_equal);
724  	
725  		priv = NM_CLIENT_GET_PRIVATE (client);
726  		priv->pending_activations = g_slist_prepend (priv->pending_activations, info);
727  	
728  		if (priv->manager_running) {
729  			dbus_g_proxy_begin_call (priv->client_proxy, "AddAndActivateConnection",
730  			                         add_activate_cb, info, NULL,
731  			                         DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, hash,
732  			                         DBUS_TYPE_G_OBJECT_PATH, nm_object_get_path (NM_OBJECT (device)),
733  			                         DBUS_TYPE_G_OBJECT_PATH, specific_object ? specific_object : "/",
734  			                         G_TYPE_INVALID);
735  		} else
736  			info->idle_id = g_idle_add (activate_nm_not_running, info);
737  	
738  		g_hash_table_unref (hash);
739  	}
740  	
741  	static void
742  	active_connections_changed_cb (GObject *object, GParamSpec *pspec, gpointer user_data)
743  	{
744  		recheck_pending_activations (NM_CLIENT (object), NULL, NULL);
745  	}
746  	
747  	static void
748  	object_creation_failed_cb (GObject *object, GError *error, char *failed_path)
749  	{
750  		if (error)
751  			recheck_pending_activations (NM_CLIENT (object), failed_path, error);
752  	}
753  	
754  	/**
755  	 * nm_client_deactivate_connection:
756  	 * @client: a #NMClient
757  	 * @active: the #NMActiveConnection to deactivate
758  	 *
759  	 * Deactivates an active #NMActiveConnection.
760  	 **/
761  	void
762  	nm_client_deactivate_connection (NMClient *client, NMActiveConnection *active)
763  	{
764  		NMClientPrivate *priv;
765  		const char *path;
766  		GError *error = NULL;
767  	
768  		g_return_if_fail (NM_IS_CLIENT (client));
769  		g_return_if_fail (NM_IS_ACTIVE_CONNECTION (active));
770  	
771  		priv = NM_CLIENT_GET_PRIVATE (client);
772  		if (!priv->manager_running)
773  			return;
774  	
775  		path = nm_object_get_path (NM_OBJECT (active));
776  		if (!dbus_g_proxy_call (priv->client_proxy, "DeactivateConnection", &error,
777  		                        DBUS_TYPE_G_OBJECT_PATH, path,
778  		                        G_TYPE_INVALID,
779  		                        G_TYPE_INVALID)) {
780  			g_warning ("Could not deactivate connection '%s': %s", path, error->message);
781  			g_error_free (error);
782  		}
783  	}
784  	
785  	/**
786  	 * nm_client_get_active_connections:
787  	 * @client: a #NMClient
788  	 *
789  	 * Gets the active connections.
790  	 *
791  	 * Returns: (transfer none) (element-type NMClient.ActiveConnection): a #GPtrArray
792  	 *  containing all the active #NMActiveConnections.
793  	 * The returned array is owned by the client and should not be modified.
794  	 **/
795  	const GPtrArray * 
796  	nm_client_get_active_connections (NMClient *client)
797  	{
798  		NMClientPrivate *priv;
799  	
800  		g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
801  	
802  		_nm_object_ensure_inited (NM_OBJECT (client));
803  	
804  		priv = NM_CLIENT_GET_PRIVATE (client);
805  		if (!priv->manager_running)
806  			return NULL;
807  	
808  		return handle_ptr_array_return (priv->active_connections);
809  	}
810  	
811  	/**
812  	 * nm_client_wireless_get_enabled:
813  	 * @client: a #NMClient
814  	 *
815  	 * Determines whether the wireless is enabled.
816  	 *
817  	 * Returns: %TRUE if wireless is enabled
818  	 **/
819  	gboolean
820  	nm_client_wireless_get_enabled (NMClient *client)
821  	{
822  		g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
823  	
824  		_nm_object_ensure_inited (NM_OBJECT (client));
825  		return NM_CLIENT_GET_PRIVATE (client)->wireless_enabled;
826  	}
827  	
828  	/**
829  	 * nm_client_wireless_set_enabled:
830  	 * @client: a #NMClient
831  	 * @enabled: %TRUE to enable wireless
832  	 *
833  	 * Enables or disables wireless devices.
834  	 **/
835  	void
836  	nm_client_wireless_set_enabled (NMClient *client, gboolean enabled)
837  	{
838  		GValue value = G_VALUE_INIT;
839  	
840  		g_return_if_fail (NM_IS_CLIENT (client));
841  	
842  		if (!NM_CLIENT_GET_PRIVATE (client)->manager_running)
843  			return;
844  	
845  		g_value_init (&value, G_TYPE_BOOLEAN);
846  		g_value_set_boolean (&value, enabled);
847  	
848  		_nm_object_set_property (NM_OBJECT (client),
849  		                         NM_DBUS_INTERFACE,
850  		                         "WirelessEnabled",
851  		                         &value);
852  	}
853  	
854  	/**
855  	 * nm_client_wireless_hardware_get_enabled:
856  	 * @client: a #NMClient
857  	 *
858  	 * Determines whether the wireless hardware is enabled.
859  	 *
860  	 * Returns: %TRUE if the wireless hardware is enabled
861  	 **/
862  	gboolean
863  	nm_client_wireless_hardware_get_enabled (NMClient *client)
864  	{
865  		g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
866  	
867  		_nm_object_ensure_inited (NM_OBJECT (client));
868  		return NM_CLIENT_GET_PRIVATE (client)->wireless_hw_enabled;
869  	}
870  	
871  	/**
872  	 * nm_client_wwan_get_enabled:
873  	 * @client: a #NMClient
874  	 *
875  	 * Determines whether WWAN is enabled.
876  	 *
877  	 * Returns: %TRUE if WWAN is enabled
878  	 **/
879  	gboolean
880  	nm_client_wwan_get_enabled (NMClient *client)
881  	{
882  		g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
883  	
884  		_nm_object_ensure_inited (NM_OBJECT (client));
885  		return NM_CLIENT_GET_PRIVATE (client)->wwan_enabled;
886  	}
887  	
888  	/**
889  	 * nm_client_wwan_set_enabled:
890  	 * @client: a #NMClient
891  	 * @enabled: %TRUE to enable WWAN
892  	 *
893  	 * Enables or disables WWAN devices.
894  	 **/
895  	void
896  	nm_client_wwan_set_enabled (NMClient *client, gboolean enabled)
897  	{
898  		GValue value = G_VALUE_INIT;
899  	
900  		g_return_if_fail (NM_IS_CLIENT (client));
901  	
902  		if (!NM_CLIENT_GET_PRIVATE (client)->manager_running)
903  			return;
904  	
905  		g_value_init (&value, G_TYPE_BOOLEAN);
906  		g_value_set_boolean (&value, enabled);
907  	
908  		_nm_object_set_property (NM_OBJECT (client),
909  		                         NM_DBUS_INTERFACE,
910  		                         "WwanEnabled",
911  		                         &value);
912  	}
913  	
914  	/**
915  	 * nm_client_wwan_hardware_get_enabled:
916  	 * @client: a #NMClient
917  	 *
918  	 * Determines whether the WWAN hardware is enabled.
919  	 *
920  	 * Returns: %TRUE if the WWAN hardware is enabled
921  	 **/
922  	gboolean
923  	nm_client_wwan_hardware_get_enabled (NMClient *client)
924  	{
925  		g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
926  	
927  		_nm_object_ensure_inited (NM_OBJECT (client));
928  		return NM_CLIENT_GET_PRIVATE (client)->wwan_hw_enabled;
929  	}
930  	
931  	/**
932  	 * nm_client_wimax_get_enabled:
933  	 * @client: a #NMClient
934  	 *
935  	 * Determines whether WiMAX is enabled.
936  	 *
937  	 * Returns: %TRUE if WiMAX is enabled
938  	 **/
939  	gboolean
940  	nm_client_wimax_get_enabled (NMClient *client)
941  	{
942  		g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
943  	
944  		_nm_object_ensure_inited (NM_OBJECT (client));
945  		return NM_CLIENT_GET_PRIVATE (client)->wimax_enabled;
946  	}
947  	
948  	/**
949  	 * nm_client_wimax_set_enabled:
950  	 * @client: a #NMClient
951  	 * @enabled: %TRUE to enable WiMAX
952  	 *
953  	 * Enables or disables WiMAX devices.
954  	 **/
955  	void
956  	nm_client_wimax_set_enabled (NMClient *client, gboolean enabled)
957  	{
958  		GValue value = G_VALUE_INIT;
959  	
960  		g_return_if_fail (NM_IS_CLIENT (client));
961  	
962  		if (!NM_CLIENT_GET_PRIVATE (client)->manager_running)
963  			return;
964  	
965  		g_value_init (&value, G_TYPE_BOOLEAN);
966  		g_value_set_boolean (&value, enabled);
967  	
968  		_nm_object_set_property (NM_OBJECT (client),
969  		                         NM_DBUS_INTERFACE,
970  		                         "WimaxEnabled",
971  		                         &value);
972  	}
973  	
974  	/**
975  	 * nm_client_wimax_hardware_get_enabled:
976  	 * @client: a #NMClient
977  	 *
978  	 * Determines whether the WiMAX hardware is enabled.
979  	 *
980  	 * Returns: %TRUE if the WiMAX hardware is enabled
981  	 **/
982  	gboolean
983  	nm_client_wimax_hardware_get_enabled (NMClient *client)
984  	{
985  		g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
986  	
987  		_nm_object_ensure_inited (NM_OBJECT (client));
988  		return NM_CLIENT_GET_PRIVATE (client)->wimax_hw_enabled;
989  	}
990  	
991  	/**
992  	 * nm_client_get_version:
993  	 * @client: a #NMClient
994  	 *
995  	 * Gets NetworkManager version.
996  	 *
997  	 * Returns: string with the version
998  	 **/
999  	const char *
1000 	nm_client_get_version (NMClient *client)
1001 	{
1002 		NMClientPrivate *priv;
1003 	
1004 		g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
1005 	
1006 		priv = NM_CLIENT_GET_PRIVATE (client);
1007 	
1008 		_nm_object_ensure_inited (NM_OBJECT (client));
1009 	
1010 		return priv->manager_running ? priv->version : NULL;
1011 	}
1012 	
1013 	/**
1014 	 * nm_client_get_state:
1015 	 * @client: a #NMClient
1016 	 *
1017 	 * Gets the current daemon state.
1018 	 *
1019 	 * Returns: the current %NMState
1020 	 **/
1021 	NMState
1022 	nm_client_get_state (NMClient *client)
1023 	{
1024 		g_return_val_if_fail (NM_IS_CLIENT (client), NM_STATE_UNKNOWN);
1025 	
1026 		_nm_object_ensure_inited (NM_OBJECT (client));
1027 	
1028 		return NM_CLIENT_GET_PRIVATE (client)->state;
1029 	}
1030 	
1031 	/**
1032 	 * nm_client_get_startup:
1033 	 * @client: a #NMClient
1034 	 *
1035 	 * Tests whether the daemon is still in the process of activating
1036 	 * connections at startup.
1037 	 *
1038 	 * Returns: whether the daemon is still starting up
1039 	 *
1040 	 * Since: 0.9.10
1041 	 **/
1042 	gboolean
1043 	nm_client_get_startup (NMClient *client)
1044 	{
1045 		g_return_val_if_fail (NM_IS_CLIENT (client), NM_STATE_UNKNOWN);
1046 	
1047 		_nm_object_ensure_inited (NM_OBJECT (client));
1048 	
1049 		return NM_CLIENT_GET_PRIVATE (client)->startup;
1050 	}
1051 	
1052 	/**
1053 	 * nm_client_networking_get_enabled:
1054 	 * @client: a #NMClient
1055 	 *
1056 	 * Whether networking is enabled or disabled.
1057 	 *
1058 	 * Returns: %TRUE if networking is enabled, %FALSE if networking is disabled
1059 	 **/
1060 	gboolean
1061 	nm_client_networking_get_enabled (NMClient *client)
1062 	{
1063 		g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
1064 	
1065 		_nm_object_ensure_inited (NM_OBJECT (client));
1066 		return NM_CLIENT_GET_PRIVATE (client)->networking_enabled;
1067 	}
1068 	
1069 	/**
1070 	 * nm_client_networking_set_enabled:
1071 	 * @client: a #NMClient
1072 	 * @enabled: %TRUE to set networking enabled, %FALSE to set networking disabled
1073 	 *
1074 	 * Enables or disables networking.  When networking is disabled, all controlled
1075 	 * interfaces are disconnected and deactivated.  When networking is enabled,
1076 	 * all controlled interfaces are available for activation.
1077 	 **/
1078 	void
1079 	nm_client_networking_set_enabled (NMClient *client, gboolean enable)
1080 	{
1081 		GError *err = NULL;
1082 	
1083 		g_return_if_fail (NM_IS_CLIENT (client));
1084 	
1085 		if (!NM_CLIENT_GET_PRIVATE (client)->manager_running)
1086 			return;
1087 	
1088 		if (!dbus_g_proxy_call (NM_CLIENT_GET_PRIVATE (client)->client_proxy, "Enable", &err,
1089 		                        G_TYPE_BOOLEAN, enable,
1090 		                        G_TYPE_INVALID,
1091 		                        G_TYPE_INVALID)) {
1092 			g_warning ("Error enabling/disabling networking: %s", err->message);
1093 			g_error_free (err);
1094 		}
1095 	}
1096 	
1097 	/**
1098 	 * nm_client_sleep:
1099 	 * @client: a #NMClient
1100 	 * @sleep_: %TRUE to put the daemon to sleep
1101 	 *
1102 	 * Deprecated; use nm_client_networking_set_enabled() instead.
1103 	 **/
1104 	void
1105 	nm_client_sleep (NMClient *client, gboolean sleep_)
1106 	{
1107 		nm_client_networking_set_enabled (client, !sleep_);
1108 	}
1109 	
1110 	/**
1111 	 * nm_client_get_manager_running:
1112 	 * @client: a #NMClient
1113 	 *
1114 	 * Determines whether the daemon is running.
1115 	 *
1116 	 * Returns: %TRUE if the daemon is running
1117 	 **/
1118 	gboolean
1119 	nm_client_get_manager_running (NMClient *client)
1120 	{
1121 		g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
1122 	
1123 		return NM_CLIENT_GET_PRIVATE (client)->manager_running;
1124 	}
1125 	
1126 	/**
1127 	 * nm_client_get_permission_result:
1128 	 * @client: a #NMClient
1129 	 * @permission: the permission for which to return the result, one of #NMClientPermission
1130 	 *
1131 	 * Requests the result of a specific permission, which indicates whether the
1132 	 * client can or cannot perform the action the permission represents
1133 	 *
1134 	 * Returns: the permission's result, one of #NMClientPermissionResult
1135 	 **/
1136 	NMClientPermissionResult
1137 	nm_client_get_permission_result (NMClient *client, NMClientPermission permission)
1138 	{
1139 		gpointer result;
1140 	
1141 		g_return_val_if_fail (NM_IS_CLIENT (client), NM_CLIENT_PERMISSION_RESULT_UNKNOWN);
1142 	
1143 		result = g_hash_table_lookup (NM_CLIENT_GET_PRIVATE (client)->permissions,
1144 		                              GUINT_TO_POINTER (permission));
1145 		return GPOINTER_TO_UINT (result);
1146 	}
1147 	
1148 	/**
1149 	 * nm_client_get_logging:
1150 	 * @client: a #NMClient
1151 	 * @level: (allow-none): return location for logging level string
1152 	 * @domains: (allow-none): return location for log domains string. The string is
1153 	 *   a list of domains separated by ","
1154 	 * @error: (allow-none): return location for a #GError, or %NULL
1155 	 *
1156 	 * Gets NetworkManager current logging level and domains.
1157 	 *
1158 	 * Returns: %TRUE on success, %FALSE otherwise
1159 	 *
1160 	 * Since: 0.9.8
1161 	 **/
1162 	gboolean
1163 	nm_client_get_logging (NMClient *client, char **level, char **domains, GError **error)
1164 	{
1165 		NMClientPrivate *priv;
1166 	
1167 		g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
1168 		g_return_val_if_fail (level == NULL || *level == NULL, FALSE);
1169 		g_return_val_if_fail (domains == NULL || *domains == NULL, FALSE);
1170 		g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1171 	
1172 		priv = NM_CLIENT_GET_PRIVATE (client);
1173 		if (!priv->manager_running) {
1174 			g_set_error_literal (error,
1175 			                     NM_CLIENT_ERROR,
1176 			                     NM_CLIENT_ERROR_MANAGER_NOT_RUNNING,
1177 			                     "NetworkManager is not running");
1178 			return FALSE;
1179 		}
1180 	
1181 		if (!level && !domains)
1182 			return TRUE;
1183 	
1184 		return dbus_g_proxy_call (priv->client_proxy, "GetLogging", error,
1185 		                          G_TYPE_INVALID,
1186 		                          G_TYPE_STRING, level,
1187 		                          G_TYPE_STRING, domains,
1188 		                          G_TYPE_INVALID);
1189 	}
1190 	
1191 	/**
1192 	 * nm_client_set_logging:
1193 	 * @client: a #NMClient
1194 	 * @level: (allow-none): logging level to set (%NULL or an empty string for no change)
1195 	 * @domains: (allow-none): logging domains to set. The string should be a list of log
1196 	 *   domains separated by ",". (%NULL or an empty string for no change)
1197 	 * @error: (allow-none): return location for a #GError, or %NULL
1198 	 *
1199 	 * Sets NetworkManager logging level and/or domains.
1200 	 *
1201 	 * Returns: %TRUE on success, %FALSE otherwise
1202 	 *
1203 	 * Since: 0.9.8
1204 	 **/
1205 	gboolean
1206 	nm_client_set_logging (NMClient *client, const char *level, const char *domains, GError **error)
1207 	{
1208 		NMClientPrivate *priv;
1209 	
1210 		g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
1211 		g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1212 	
1213 		priv = NM_CLIENT_GET_PRIVATE (client);
1214 		if (!priv->manager_running) {
1215 			g_set_error_literal (error,
1216 			                     NM_CLIENT_ERROR,
1217 			                     NM_CLIENT_ERROR_MANAGER_NOT_RUNNING,
1218 			                     "NetworkManager is not running");
1219 			return FALSE;
1220 		}
1221 	
1222 		if (!level && !domains)
1223 			return TRUE;
1224 	
1225 		return dbus_g_proxy_call (priv->client_proxy, "SetLogging", error,
1226 		                          G_TYPE_STRING, level ? level : "",
1227 		                          G_TYPE_STRING, domains ? domains : "",
1228 		                          G_TYPE_INVALID,
1229 		                          G_TYPE_INVALID);
1230 	}
1231 	
1232 	/**
1233 	 * nm_client_get_primary_connection:
1234 	 * @client: an #NMClient
1235 	 *
1236 	 * Gets the #NMActiveConnection corresponding to the primary active
1237 	 * network device.
1238 	 *
1239 	 * In particular, when there is no VPN active, or the VPN does not
1240 	 * have the default route, this returns the active connection that has
1241 	 * the default route. If there is a VPN active with the default route,
1242 	 * then this function returns the active connection that contains the
1243 	 * route to the VPN endpoint.
1244 	 *
1245 	 * If there is no default route, or the default route is over a
1246 	 * non-NetworkManager-recognized device, this will return %NULL.
1247 	 *
1248 	 * Returns: (transfer none): the appropriate #NMActiveConnection, if
1249 	 * any
1250 	 *
1251 	 * Since: 0.9.8.6
1252 	 */
1253 	NMActiveConnection *
1254 	nm_client_get_primary_connection (NMClient *client)
1255 	{
1256 		g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
1257 	
1258 		_nm_object_ensure_inited (NM_OBJECT (client));
1259 		return NM_CLIENT_GET_PRIVATE (client)->primary_connection;
1260 	}
1261 	
1262 	/**
1263 	 * nm_client_get_activating_connection:
1264 	 * @client: an #NMClient
1265 	 *
1266 	 * Gets the #NMActiveConnection corresponding to a
1267 	 * currently-activating connection that is expected to become the new
1268 	 * #NMClient:primary-connection upon successful activation.
1269 	 *
1270 	 * Returns: (transfer none): the appropriate #NMActiveConnection, if
1271 	 * any.
1272 	 *
1273 	 * Since: 0.9.8.6
1274 	 */
1275 	NMActiveConnection *
1276 	nm_client_get_activating_connection (NMClient *client)
1277 	{
1278 		g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
1279 	
1280 		_nm_object_ensure_inited (NM_OBJECT (client));
1281 		return NM_CLIENT_GET_PRIVATE (client)->activating_connection;
1282 	}
1283 	
1284 	/****************************************************************/
1285 	
1286 	static void
1287 	free_devices (NMClient *client, gboolean emit_signals)
1288 	{
1289 		NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
1290 		GPtrArray *devices;
1291 		NMDevice *device;
1292 		int i;
1293 	
1294 		if (!priv->devices)
1295 			return;
1296 	
1297 		devices = priv->devices;
1298 		priv->devices = NULL;
1299 		for (i = 0; i < devices->len; i++) {
1300 			device = devices->pdata[i];
1301 			if (emit_signals)
1302 				g_signal_emit (client, signals[DEVICE_REMOVED], 0, device);
1303 			g_object_unref (device);
1304 		}
1305 		g_ptr_array_free (devices, TRUE);
1306 	}
1307 	
1308 	static void
1309 	free_active_connections (NMClient *client, gboolean emit_signals)
1310 	{
1311 		NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
1312 		GPtrArray *active_connections;
1313 		NMActiveConnection *active_connection;
1314 		int i;
1315 	
1316 		if (!priv->active_connections)
1317 			return;
1318 	
1319 		active_connections = priv->active_connections;
1320 		priv->active_connections = NULL;
1321 		for (i = 0; i < active_connections->len; i++) {
1322 			active_connection = active_connections->pdata[i];
1323 			/* Break circular refs */
1324 			g_object_run_dispose (G_OBJECT (active_connection));
1325 			g_object_unref (active_connection);
1326 		}
1327 		g_ptr_array_free (active_connections, TRUE);
1328 	
1329 		if (emit_signals)
1330 			g_object_notify (G_OBJECT (client), NM_CLIENT_ACTIVE_CONNECTIONS);
1331 	}
1332 	
1333 	static void
1334 	updated_properties (GObject *object, GAsyncResult *result, gpointer user_data)
1335 	{
1336 		NMClient *client = NM_CLIENT (user_data);
1337 		GError *error = NULL;
1338 	
1339 		if (!_nm_object_reload_properties_finish (NM_OBJECT (object), result, &error)) {
1340 			g_warning ("%s: error reading NMClient properties: %s", __func__, error->message);
1341 			g_error_free (error);
1342 		}
1343 	
1344 		_nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_MANAGER_RUNNING);
1345 	}
1346 	
1347 	static void
1348 	proxy_name_owner_changed (DBusGProxy *proxy,
1349 							  const char *name,
1350 							  const char *old_owner,
1351 							  const char *new_owner,
1352 							  gpointer user_data)
1353 	{
1354 		NMClient *client = NM_CLIENT (user_data);
1355 		NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
1356 		gboolean old_good = (old_owner && strlen (old_owner));
1357 		gboolean new_good = (new_owner && strlen (new_owner));
1358 		gboolean new_running = FALSE;
1359 	
1360 		if (!name || strcmp (name, NM_DBUS_SERVICE))
1361 			return;
1362 	
1363 		if (!old_good && new_good)
1364 			new_running = TRUE;
1365 		else if (old_good && !new_good)
1366 			new_running = FALSE;
1367 	
1368 		if (new_running == priv->manager_running)
1369 			return;
1370 	
1371 		priv->manager_running = new_running;
1372 		if (!priv->manager_running) {
1373 			priv->state = NM_STATE_UNKNOWN;
1374 			priv->startup = FALSE;
1375 			_nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_MANAGER_RUNNING);
1376 			_nm_object_suppress_property_updates (NM_OBJECT (client), TRUE);
1377 			poke_wireless_devices_with_rf_status (client);
1378 			free_devices (client, TRUE);
1379 			free_active_connections (client, TRUE);
1380 			update_permissions (client, NULL);
1381 			priv->wireless_enabled = FALSE;
1382 			priv->wireless_hw_enabled = FALSE;
1383 			priv->wwan_enabled = FALSE;
1384 			priv->wwan_hw_enabled = FALSE;
1385 			priv->wimax_enabled = FALSE;
1386 			priv->wimax_hw_enabled = FALSE;
1387 			g_free (priv->version);
1388 			priv->version = NULL;
1389 	
1390 			/* Clear object cache to ensure bad refcounting by clients doesn't
1391 			 * keep objects in the cache.
1392 			 */
1393 			_nm_object_cache_clear (NM_OBJECT (client));
1394 		} else {
1395 			_nm_object_suppress_property_updates (NM_OBJECT (client), FALSE);
1396 			_nm_object_reload_properties_async (NM_OBJECT (client), updated_properties, client);
1397 			client_recheck_permissions (priv->client_proxy, client);
1398 		}
1399 	}
1400 	
1401 	static void
1402 	client_device_added (NMObject *client, NMObject *device)
1403 	{
1404 		g_signal_emit (client, signals[DEVICE_ADDED], 0, device);
1405 	}
1406 	
1407 	static void
1408 	client_device_removed (NMObject *client, NMObject *device)
1409 	{
1410 		g_signal_emit (client, signals[DEVICE_REMOVED], 0, device);
1411 	}
1412 	
1413 	/**
1414 	 * nm_client_get_connectivity:
1415 	 * @client: an #NMClient
1416 	 *
1417 	 * Gets the current network connectivity state. Contrast
1418 	 * nm_client_check_connectivity() and
1419 	 * nm_client_check_connectivity_async(), which re-check the
1420 	 * connectivity state first before returning any information.
1421 	 *
1422 	 * Returns: the current connectivity state
1423 	 * Since: 0.9.8.6
1424 	 */
1425 	NMConnectivityState
1426 	nm_client_get_connectivity (NMClient *client)
1427 	{
1428 		NMClientPrivate *priv;
1429 	
1430 		g_return_val_if_fail (NM_IS_CLIENT (client), NM_STATE_UNKNOWN);
1431 		priv = NM_CLIENT_GET_PRIVATE (client);
1432 	
1433 		_nm_object_ensure_inited (NM_OBJECT (client));
1434 	
1435 		return priv->connectivity;
1436 	}
1437 	
1438 	/**
1439 	 * nm_client_check_connectivity:
1440 	 * @client: an #NMClient
1441 	 * @cancellable: a #GCancellable
1442 	 * @error: return location for a #GError
1443 	 *
1444 	 * Updates the network connectivity state and returns the (new)
1445 	 * current state. Contrast nm_client_get_connectivity(), which returns
1446 	 * the most recent known state without re-checking.
1447 	 *
1448 	 * This is a blocking call; use nm_client_check_connectivity_async()
1449 	 * if you do not want to block.
1450 	 *
1451 	 * Returns: the (new) current connectivity state
1452 	 * Since: 0.9.8.6
1453 	 */
1454 	NMConnectivityState
1455 	nm_client_check_connectivity (NMClient *client,
1456 	                              GCancellable *cancellable,
1457 	                              GError **error)
1458 	{
1459 		NMClientPrivate *priv;
1460 		NMConnectivityState connectivity;
1461 	
1462 		g_return_val_if_fail (NM_IS_CLIENT (client), NM_CONNECTIVITY_UNKNOWN);
1463 		priv = NM_CLIENT_GET_PRIVATE (client);
1464 	
1465 		if (!dbus_g_proxy_call (priv->client_proxy, "CheckConnectivity", error,
1466 		                        G_TYPE_INVALID,
1467 		                        G_TYPE_UINT, &connectivity,
1468 		                        G_TYPE_INVALID))
1469 			connectivity = NM_CONNECTIVITY_UNKNOWN;
1470 	
1471 		return connectivity;
1472 	}
1473 	
1474 	typedef struct {
1475 		NMClient *client;
1476 		DBusGProxyCall *call;
1477 		GCancellable *cancellable;
1478 		guint cancelled_id;
1479 		NMConnectivityState connectivity;
1480 	} CheckConnectivityData;
1481 	
1482 	static void
1483 	check_connectivity_data_free (CheckConnectivityData *ccd)
1484 	{
1485 		if (ccd->cancellable) {
1486 			if (ccd->cancelled_id)
1487 				g_signal_handler_disconnect (ccd->cancellable, ccd->cancelled_id);
1488 			g_object_unref (ccd->cancellable);
1489 		}
1490 	
1491 		g_slice_free (CheckConnectivityData, ccd);
1492 	}
1493 	
1494 	static void
1495 	check_connectivity_cb (DBusGProxy *proxy,
1496 	                       DBusGProxyCall *call,
1497 	                       gpointer user_data)
1498 	{
1499 		GSimpleAsyncResult *simple = user_data;
1500 		CheckConnectivityData *ccd = g_simple_async_result_get_op_res_gpointer (simple);
1501 		GError *error = NULL;
1502 	
1503 		if (!dbus_g_proxy_end_call (proxy, call, &error,
1504 		                            G_TYPE_UINT, &ccd->connectivity,
1505 		                            G_TYPE_INVALID))
1506 			g_simple_async_result_take_error (simple, error);
1507 	
1508 		g_simple_async_result_complete (simple);
1509 		g_object_unref (simple);
1510 	}
1511 	
1512 	static void
1513 	check_connectivity_cancelled_cb (GCancellable *cancellable,
1514 	                                 gpointer user_data)
1515 	{
1516 		GSimpleAsyncResult *simple = user_data;
1517 		CheckConnectivityData *ccd = g_simple_async_result_get_op_res_gpointer (simple);
1518 	
1519 		g_signal_handler_disconnect (cancellable, ccd->cancelled_id);
1520 		ccd->cancelled_id = 0;
1521 	
1522 		dbus_g_proxy_cancel_call (NM_CLIENT_GET_PRIVATE (ccd->client)->client_proxy, ccd->call);
1523 		g_simple_async_result_complete_in_idle (simple);
1524 	}
1525 	
1526 	/**
1527 	 * nm_client_check_connectivity_async:
1528 	 * @client: an #NMClient
1529 	 * @cancellable: a #GCancellable
1530 	 * @callback: callback to call with the result
1531 	 * @user_data: data for @callback.
1532 	 *
1533 	 * Asynchronously updates the network connectivity state and invokes
1534 	 * @callback when complete. Contrast nm_client_get_connectivity(),
1535 	 * which (immediately) returns the most recent known state without
1536 	 * re-checking, and nm_client_check_connectivity(), which blocks.
1537 	 *
1538 	 * Since: 0.9.8.6
1539 	 */
1540 	void
1541 	nm_client_check_connectivity_async (NMClient *client,
1542 	                                    GCancellable *cancellable,
1543 	                                    GAsyncReadyCallback callback,
1544 	                                    gpointer user_data)
1545 	{
1546 		NMClientPrivate *priv;
1547 		GSimpleAsyncResult *simple;
1548 		CheckConnectivityData *ccd;
1549 	
1550 		g_return_if_fail (NM_IS_CLIENT (client));
1551 		priv = NM_CLIENT_GET_PRIVATE (client);
1552 	
1553 		ccd = g_slice_new (CheckConnectivityData);
1554 		ccd->client = client;
1555 	
1556 		simple = g_simple_async_result_new (G_OBJECT (client), callback, user_data,
1557 		                                    nm_client_check_connectivity_async);
1558 		g_simple_async_result_set_op_res_gpointer (simple, ccd, (GDestroyNotify) check_connectivity_data_free);
1559 	
1560 		if (cancellable) {
1561 			ccd->cancellable = g_object_ref (cancellable);
1562 			ccd->cancelled_id = g_signal_connect (cancellable, "cancelled",
1563 			                                      G_CALLBACK (check_connectivity_cancelled_cb),
1564 			                                      simple);
1565 			g_simple_async_result_set_check_cancellable (simple, cancellable);
1566 		}
1567 	
1568 		ccd->call = dbus_g_proxy_begin_call (priv->client_proxy, "CheckConnectivity",
1569 		                                     check_connectivity_cb, simple, NULL,
1570 		                                     G_TYPE_INVALID);
1571 	}
1572 	
1573 	/**
1574 	 * nm_client_check_connectivity_finish:
1575 	 * @client: an #NMClient
1576 	 * @result: the #GAsyncResult
1577 	 * @error: return location for a #GError
1578 	 *
1579 	 * Retrieves the result of an nm_client_check_connectivity_async()
1580 	 * call.
1581 	 *
1582 	 * Returns: the (new) current connectivity state
1583 	 * Since: 0.9.8.6
1584 	 */
1585 	NMConnectivityState
1586 	nm_client_check_connectivity_finish (NMClient *client,
1587 	                                     GAsyncResult *result,
1588 	                                     GError **error)
1589 	{
1590 		GSimpleAsyncResult *simple;
1591 		CheckConnectivityData *ccd;
1592 	
1593 		g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (client), nm_client_check_connectivity_async), NM_CONNECTIVITY_UNKNOWN);
1594 	
1595 		simple = G_SIMPLE_ASYNC_RESULT (result);
1596 		ccd = g_simple_async_result_get_op_res_gpointer (simple);
1597 	
1598 		if (g_simple_async_result_propagate_error (simple, error))
1599 			return NM_CONNECTIVITY_UNKNOWN;
1600 	
1601 		return ccd->connectivity;
1602 	}
1603 	
1604 	/****************************************************************/
1605 	
1606 	/**
1607 	 * nm_client_new:
1608 	 *
1609 	 * Creates a new #NMClient.
1610 	 *
1611 	 * Note that this will do blocking D-Bus calls to initialize the
1612 	 * client. You can use nm_client_new_async() if you want to avoid
1613 	 * that.
1614 	 *
1615 	 * NOTE: #NMClient provides information about devices and a mechanism to
1616 	 * control them.  To access and modify network configuration data, use the
1617 	 * #NMRemoteSettings object.
1618 	 *
1619 	 * Returns: a new #NMClient or NULL on an error
1620 	 **/
1621 	NMClient *
1622 	nm_client_new (void)
1623 	{
1624 		NMClient *client;
1625 	
1626 		client = g_object_new (NM_TYPE_CLIENT, NM_OBJECT_DBUS_PATH, NM_DBUS_PATH, NULL);
1627 	
1628 		/* NMObject's constructor() can fail on a D-Bus connection error. So we can
1629 		 * get NULL here instead of a valid NMClient object.
1630 		 */
1631 		if (client)
1632 			_nm_object_ensure_inited (NM_OBJECT (client));
1633 	
1634 		return client;
1635 	}
1636 	
1637 	static void
1638 	client_inited (GObject *source, GAsyncResult *result, gpointer user_data)
1639 	{
1640 		GSimpleAsyncResult *simple = user_data;
1641 		GError *error = NULL;
1642 	
1643 		if (!g_async_initable_init_finish (G_ASYNC_INITABLE (source), result, &error))
1644 			g_simple_async_result_take_error (simple, error);
1645 		else
1646 			g_simple_async_result_set_op_res_gpointer (simple, source, g_object_unref);
1647 		g_simple_async_result_complete (simple);
1648 		g_object_unref (simple);
1649 	}
1650 	
1651 	/**
1652 	 * nm_client_new_async:
1653 	 * @cancellable: a #GCancellable, or %NULL
1654 	 * @callback: callback to call when the client is created
1655 	 * @user_data: data for @callback
1656 	 *
1657 	 * Creates a new #NMClient and begins asynchronously initializing it.
1658 	 * @callback will be called when it is done; use
1659 	 * nm_client_new_finish() to get the result. Note that on an error,
1660 	 * the callback can be invoked with two first parameters as NULL.
1661 	 *
1662 	 * NOTE: #NMClient provides information about devices and a mechanism to
1663 	 * control them.  To access and modify network configuration data, use the
1664 	 * #NMRemoteSettings object.
1665 	 **/
1666 	void
1667 	nm_client_new_async (GCancellable *cancellable,
1668 	                     GAsyncReadyCallback callback,
1669 	                     gpointer user_data)
1670 	{
1671 		NMClient *client;
1672 		GSimpleAsyncResult *simple;
1673 	
1674 		client = g_object_new (NM_TYPE_CLIENT, NM_OBJECT_DBUS_PATH, NM_DBUS_PATH, NULL);
1675 		/* When client is NULL, do no continue with initialization and run callback
1676 		 * directly with result == NULL indicating NMClient creation failure.
1677 		 */
1678 		if (!client) {
1679 			callback (NULL, NULL, user_data);
1680 			return;
1681 		}
1682 	
1683 		simple = g_simple_async_result_new (NULL, callback, user_data, nm_client_new_async);
1684 		g_async_initable_init_async (G_ASYNC_INITABLE (client), G_PRIORITY_DEFAULT,
1685 		                             cancellable, client_inited, simple);
1686 	}
1687 	
1688 	/**
1689 	 * nm_client_new_finish:
1690 	 * @result: a #GAsyncResult
1691 	 * @error: location for a #GError, or %NULL
1692 	 *
1693 	 * Gets the result of an nm_client_new_async() call.
1694 	 *
1695 	 * Returns: a new #NMClient, or %NULL on error
1696 	 **/
1697 	NMClient *
1698 	nm_client_new_finish (GAsyncResult *result, GError **error)
1699 	{
1700 		GSimpleAsyncResult *simple;
1701 	
1702 		g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1703 	
1704 		if (!result) {
1705 			g_set_error_literal (error,
1706 			                     NM_CLIENT_ERROR,
1707 			                     NM_CLIENT_ERROR_UNKNOWN,
1708 			                     "NMClient initialization failed (or you passed NULL 'result' by mistake)");
1709 			return NULL;
1710 		}
1711 	
1712 		g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL, nm_client_new_async), NULL);
1713 	
1714 		simple = G_SIMPLE_ASYNC_RESULT (result);
1715 		if (g_simple_async_result_propagate_error (simple, error))
1716 			return NULL;
1717 		else
1718 			return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
1719 	}
1720 	
1721 	/*
1722 	 * Validate D-Bus object path.
1723 	 * The function is copied and adjusted version of
1724 	 * g_variant_serialiser_is_object_path() from glib.
1725 	 * FIXME: The function can be replaced by g_variant_is_object_path()
1726 	 * when we start using GLib >= 2.24
1727 	 */
1728 	static gboolean
1729 	_nm_client_is_object_path (const char *string)
1730 	{
1731 		gsize i;
1732 	
1733 		if (!g_utf8_validate (string, -1, NULL))
1734 			return FALSE;
1735 	
1736 		/* The path must begin with an ASCII '/' (integer 47) character */
1737 		if (string[0] != '/')
1738 			return FALSE;
1739 	
1740 		for (i = 1; string[i]; i++) {
1741 			/* Each element must only contain the ASCII characters
1742 			 * "[A-Z][a-z][0-9]_"
1743 			 */
1744 			if (g_ascii_isalnum (string[i]) || string[i] == '_')
1745 				;
1746 			/* must consist of elements separated by slash characters. */
1747 			else if (string[i] == '/') {
1748 				/* No element may be the empty string. */
1749 				/* Multiple '/' characters cannot occur in sequence. */
1750 				if (string[i - 1] == '/')
1751 					return FALSE;
1752 			} else
1753 				return FALSE;
1754 		}
1755 	
1756 		/* A trailing '/' character is not allowed unless the path is the
1757 		 * root path (a single '/' character).
1758 		 */
1759 		if (i > 1 && string[i - 1] == '/')
1760 			return FALSE;
1761 	
1762 		return TRUE;
1763 	}
1764 	
1765 	/*
1766 	 * constructor() shouldn't be overriden in most cases, rather constructed()
1767 	 * method is preferred and more useful.
1768 	 * But, this serves as a workaround for bindings (use) calling the constructor()
1769 	 * directly instead of nm_client_new() function, and neither providing
1770 	 * construction properties. So, we fill "dbus-path" here if it was not specified
1771 	 * (was set to default value (NULL)).
1772 	 *
1773 	 * It allows this python code:
1774 	 * from gi.repository import NMClient
1775 	 * nmclient = NMClient.Client()
1776 	 * print nmclient.get_active_connections()
1777 	 *
1778 	 * instead of proper
1779 	 * nmclient = NMClient.Client().new()
1780 	 *
1781 	 * Note:
1782 	 * A nice overview of GObject construction is here:
1783 	 * http://blogs.gnome.org/desrt/2012/02/26/a-gentle-introduction-to-gobject-construction
1784 	 * It is much better explanation than the official docs
1785 	 * http://developer.gnome.org/gobject/unstable/chapter-gobject.html#gobject-instantiation
1786 	 */
1787 	static GObject*
1788 	constructor (GType type,
1789 	             guint n_construct_params,
1790 	             GObjectConstructParam *construct_params)
1791 	{
1792 		GObject *object;
1793 		guint i;
1794 		const char *dbus_path;
1795 	
1796 		for (i = 0; i < n_construct_params; i++) {
1797 			if (strcmp (construct_params[i].pspec->name, NM_OBJECT_DBUS_PATH) == 0) {
1798 				dbus_path = g_value_get_string (construct_params[i].value);
1799 				if (dbus_path == NULL) {
1800 					g_value_set_static_string (construct_params[i].value, NM_DBUS_PATH);
1801 				} else {
1802 					if (!_nm_client_is_object_path (dbus_path)) {
1803 						g_warning ("Passsed D-Bus object path '%s' is invalid; using default '%s' instead",
1804 						            dbus_path, NM_DBUS_PATH);
1805 						g_value_set_static_string (construct_params[i].value, NM_DBUS_PATH);
1806 					}
1807 				}
1808 				break;
1809 			}
1810 		}
1811 	
1812 		object = G_OBJECT_CLASS (nm_client_parent_class)->constructor (type,
1813 		                                                               n_construct_params,
1814 		                                                               construct_params);
1815 	
1816 		return object;
1817 	}
1818 	
1819 	static void
1820 	constructed (GObject *object)
1821 	{
1822 		NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (object);
1823 	
(1) Event check_return: Calling function "nm_utils_init(GError **)" without checking return value (as is done elsewhere 11 out of 12 times).
(7) Event unchecked_value: No check of the return value of "nm_utils_init(NULL)".
Also see events: [example_checked][example_checked][example_checked][example_checked][example_checked]
1824 		nm_utils_init (NULL);
1825 	
1826 		G_OBJECT_CLASS (nm_client_parent_class)->constructed (object);
1827 	
1828 		priv->client_proxy = _nm_object_new_proxy (NM_OBJECT (object), NULL, NM_DBUS_INTERFACE);
1829 	
1830 		register_properties (NM_CLIENT (object));
1831 	
1832 		/* Permissions */
1833 		dbus_g_proxy_add_signal (priv->client_proxy, "CheckPermissions", G_TYPE_INVALID);
1834 		dbus_g_proxy_connect_signal (priv->client_proxy,
1835 		                             "CheckPermissions",
1836 		                             G_CALLBACK (client_recheck_permissions),
1837 		                             object,
1838 		                             NULL);
1839 	
1840 		if (_nm_object_is_connection_private (NM_OBJECT (object)))
1841 			priv->manager_running = TRUE;
1842 		else {
1843 			priv->bus_proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)),
1844 			                                             DBUS_SERVICE_DBUS,
1845 			                                             DBUS_PATH_DBUS,
1846 			                                             DBUS_INTERFACE_DBUS);
1847 			g_assert (priv->bus_proxy);
1848 	
1849 			dbus_g_proxy_add_signal (priv->bus_proxy, "NameOwnerChanged",
1850 			                         G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
1851 			                         G_TYPE_INVALID);
1852 			dbus_g_proxy_connect_signal (priv->bus_proxy,
1853 			                             "NameOwnerChanged",
1854 			                             G_CALLBACK (proxy_name_owner_changed),
1855 			                             object, NULL);
1856 		}
1857 	
1858 		g_signal_connect (object, "notify::" NM_CLIENT_WIRELESS_ENABLED,
1859 		                  G_CALLBACK (wireless_enabled_cb), NULL);
1860 	
1861 		g_signal_connect (object, "notify::" NM_CLIENT_ACTIVE_CONNECTIONS,
1862 		                  G_CALLBACK (active_connections_changed_cb), NULL);
1863 	
1864 		g_signal_connect (object, "object-creation-failed",
1865 		                  G_CALLBACK (object_creation_failed_cb), NULL);
1866 	}
1867 	
1868 	static gboolean
1869 	init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
1870 	{
1871 		NMClient *client = NM_CLIENT (initable);
1872 		NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
1873 	
1874 		if (!nm_client_parent_initable_iface->init (initable, cancellable, error))
1875 			return FALSE;
1876 	
1877 		if (!_nm_object_is_connection_private (NM_OBJECT (client))) {
1878 			if (!dbus_g_proxy_call (priv->bus_proxy,
1879 			                        "NameHasOwner", error,
1880 			                        G_TYPE_STRING, NM_DBUS_SERVICE,
1881 			                        G_TYPE_INVALID,
1882 			                        G_TYPE_BOOLEAN, &priv->manager_running,
1883 			                        G_TYPE_INVALID))
1884 				return FALSE;
1885 		}
1886 	
1887 		if (priv->manager_running && !get_permissions_sync (client, error))
1888 			return FALSE;
1889 	
1890 		return TRUE;
1891 	}
1892 	
1893 	typedef struct {
1894 		NMClient *client;
1895 		GSimpleAsyncResult *result;
1896 		gboolean properties_pending;
1897 		gboolean permissions_pending;
1898 	} NMClientInitData;
1899 	
1900 	static void
1901 	init_async_complete (NMClientInitData *init_data)
1902 	{
1903 		if (init_data->properties_pending || init_data->permissions_pending)
1904 			return;
1905 	
1906 		g_simple_async_result_complete (init_data->result);
1907 		g_object_unref (init_data->result);
1908 		g_slice_free (NMClientInitData, init_data);
1909 	}
1910 	
1911 	static void
1912 	init_async_got_permissions (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
1913 	{
1914 		NMClientInitData *init_data = user_data;
1915 		GHashTable *permissions;
1916 		GError *error = NULL;
1917 	
1918 		dbus_g_proxy_end_call (proxy, call, &error,
1919 		                       DBUS_TYPE_G_MAP_OF_STRING, &permissions,
1920 		                       G_TYPE_INVALID);
1921 		update_permissions (init_data->client, error ? NULL : permissions);
1922 		g_clear_error (&error);
1923 	
1924 		init_data->permissions_pending = FALSE;
1925 		init_async_complete (init_data);
1926 	}
1927 	
1928 	static void
1929 	init_async_got_properties (GObject *source, GAsyncResult *result, gpointer user_data)
1930 	{
1931 		NMClientInitData *init_data = user_data;
1932 		GError *error = NULL;
1933 	
1934 		if (!nm_client_parent_async_initable_iface->init_finish (G_ASYNC_INITABLE (source), result, &error))
1935 			g_simple_async_result_take_error (init_data->result, error);
1936 	
1937 		init_data->properties_pending = FALSE;
1938 		init_async_complete (init_data);
1939 	}
1940 	
1941 	static void
1942 	finish_init (NMClientInitData *init_data)
1943 	{
1944 		NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (init_data->client);
1945 	
1946 		nm_client_parent_async_initable_iface->init_async (G_ASYNC_INITABLE (init_data->client),
1947 		                                                   G_PRIORITY_DEFAULT, NULL, /* FIXME cancellable */
1948 		                                                   init_async_got_properties, init_data);
1949 		init_data->properties_pending = TRUE;
1950 	
1951 		dbus_g_proxy_begin_call (priv->client_proxy, "GetPermissions",
1952 		                         init_async_got_permissions, init_data, NULL,
1953 		                         G_TYPE_INVALID);
1954 		init_data->permissions_pending = TRUE;
1955 	}
1956 	
1957 	static void
1958 	init_async_got_manager_running (DBusGProxy *proxy, DBusGProxyCall *call,
1959 	                                gpointer user_data)
1960 	{
1961 		NMClientInitData *init_data = user_data;
1962 		NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (init_data->client);
1963 		GError *error = NULL;
1964 	
1965 		if (!dbus_g_proxy_end_call (proxy, call, &error,
1966 		                            G_TYPE_BOOLEAN, &priv->manager_running,
1967 		                            G_TYPE_INVALID)) {
1968 			g_simple_async_result_take_error (init_data->result, error);
1969 			init_async_complete (init_data);
1970 			return;
1971 		}
1972 	
1973 		if (!priv->manager_running) {
1974 			init_async_complete (init_data);
1975 			return;
1976 		}
1977 	
1978 		finish_init (init_data);
1979 	}
1980 	
1981 	static void
1982 	init_async (GAsyncInitable *initable, int io_priority,
1983 				GCancellable *cancellable, GAsyncReadyCallback callback,
1984 				gpointer user_data)
1985 	{
1986 		NMClientInitData *init_data;
1987 		NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (initable);
1988 	
1989 		init_data = g_slice_new0 (NMClientInitData);
1990 		init_data->client = NM_CLIENT (initable);
1991 		init_data->result = g_simple_async_result_new (G_OBJECT (initable), callback,
1992 		                                               user_data, init_async);
1993 		g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE);
1994 	
1995 		if (_nm_object_is_connection_private (NM_OBJECT (init_data->client)))
1996 			finish_init (init_data);
1997 		else {
1998 			/* Check if NM is running */
1999 			dbus_g_proxy_begin_call (priv->bus_proxy, "NameHasOwner",
2000 				                     init_async_got_manager_running,
2001 				                     init_data, NULL,
2002 				                     G_TYPE_STRING, NM_DBUS_SERVICE,
2003 				                     G_TYPE_INVALID);
2004 		}
2005 	}
2006 	
2007 	static gboolean
2008 	init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error)
2009 	{
2010 		GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
2011 	
2012 		if (g_simple_async_result_propagate_error (simple, error))
2013 			return FALSE;
2014 		else
2015 			return TRUE;
2016 	}
2017 	
2018 	static void
2019 	dispose (GObject *object)
2020 	{
2021 		NMClient *client = NM_CLIENT (object);
2022 		NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (object);
2023 	
2024 		if (priv->perm_call) {
2025 			dbus_g_proxy_cancel_call (priv->client_proxy, priv->perm_call);
2026 			priv->perm_call = NULL;
2027 		}
2028 	
2029 		g_clear_object (&priv->client_proxy);
2030 		g_clear_object (&priv->bus_proxy);
2031 	
2032 		free_devices (client, FALSE);
2033 		free_active_connections (client, FALSE);
2034 		g_clear_object (&priv->primary_connection);
2035 		g_clear_object (&priv->activating_connection);
2036 	
2037 		g_slist_free_full (priv->pending_activations, (GDestroyNotify) activate_info_free);
2038 		priv->pending_activations = NULL;
2039 	
2040 		g_hash_table_destroy (priv->permissions);
2041 		priv->permissions = NULL;
2042 	
2043 		G_OBJECT_CLASS (nm_client_parent_class)->dispose (object);
2044 	}
2045 	
2046 	static void
2047 	finalize (GObject *object)
2048 	{
2049 		NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (object);
2050 	
2051 		g_free (priv->version);
2052 	
2053 		G_OBJECT_CLASS (nm_client_parent_class)->finalize (object);
2054 	}
2055 	
2056 	static void
2057 	set_property (GObject *object, guint prop_id,
2058 			    const GValue *value, GParamSpec *pspec)
2059 	{
2060 		NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (object);
2061 		gboolean b;
2062 	
2063 		switch (prop_id) {
2064 		case PROP_NETWORKING_ENABLED:
2065 			b = g_value_get_boolean (value);
2066 			if (priv->networking_enabled != b) {
2067 				nm_client_networking_set_enabled (NM_CLIENT (object), b);
2068 				/* Let the property value flip when we get the change signal from NM */
2069 			}
2070 			break;
2071 		case PROP_WIRELESS_ENABLED:
2072 			b = g_value_get_boolean (value);
2073 			if (priv->wireless_enabled != b) {
2074 				nm_client_wireless_set_enabled (NM_CLIENT (object), b);
2075 				/* Let the property value flip when we get the change signal from NM */
2076 			}
2077 			break;
2078 		case PROP_WWAN_ENABLED:
2079 			b = g_value_get_boolean (value);
2080 			if (priv->wwan_enabled != b) {
2081 				nm_client_wwan_set_enabled (NM_CLIENT (object), b);
2082 				/* Let the property value flip when we get the change signal from NM */
2083 			}
2084 			break;
2085 		case PROP_WIMAX_ENABLED:
2086 			b = g_value_get_boolean (value);
2087 			if (priv->wimax_enabled != b) {
2088 				nm_client_wimax_set_enabled (NM_CLIENT (object), b);
2089 				/* Let the property value flip when we get the change signal from NM */
2090 			}
2091 			break;
2092 		default:
2093 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2094 			break;
2095 		}
2096 	}
2097 	
2098 	static void
2099 	get_property (GObject *object,
2100 	              guint prop_id,
2101 	              GValue *value,
2102 	              GParamSpec *pspec)
2103 	{
2104 		NMClient *self = NM_CLIENT (object);
2105 		NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self);
2106 	
2107 		_nm_object_ensure_inited (NM_OBJECT (object));
2108 	
2109 		switch (prop_id) {
2110 		case PROP_VERSION:
2111 			g_value_set_string (value, nm_client_get_version (self));
2112 			break;
2113 		case PROP_STATE:
2114 			g_value_set_uint (value, nm_client_get_state (self));
2115 			break;
2116 		case PROP_STARTUP:
2117 			g_value_set_boolean (value, nm_client_get_startup (self));
2118 			break;
2119 		case PROP_MANAGER_RUNNING:
2120 			g_value_set_boolean (value, priv->manager_running);
2121 			break;
2122 		case PROP_NETWORKING_ENABLED:
2123 			g_value_set_boolean (value, nm_client_networking_get_enabled (self));
2124 			break;
2125 		case PROP_WIRELESS_ENABLED:
2126 			g_value_set_boolean (value, priv->wireless_enabled);
2127 			break;
2128 		case PROP_WIRELESS_HARDWARE_ENABLED:
2129 			g_value_set_boolean (value, priv->wireless_hw_enabled);
2130 			break;
2131 		case PROP_WWAN_ENABLED:
2132 			g_value_set_boolean (value, priv->wwan_enabled);
2133 			break;
2134 		case PROP_WWAN_HARDWARE_ENABLED:
2135 			g_value_set_boolean (value, priv->wwan_hw_enabled);
2136 			break;
2137 		case PROP_WIMAX_ENABLED:
2138 			g_value_set_boolean (value, priv->wimax_enabled);
2139 			break;
2140 		case PROP_WIMAX_HARDWARE_ENABLED:
2141 			g_value_set_boolean (value, priv->wimax_hw_enabled);
2142 			break;
2143 		case PROP_ACTIVE_CONNECTIONS:
2144 			g_value_set_boxed (value, nm_client_get_active_connections (self));
2145 			break;
2146 		case PROP_CONNECTIVITY:
2147 			g_value_set_uint (value, priv->connectivity);
2148 			break;
2149 		case PROP_PRIMARY_CONNECTION:
2150 			g_value_set_object (value, priv->primary_connection);
2151 			break;
2152 		case PROP_ACTIVATING_CONNECTION:
2153 			g_value_set_object (value, priv->activating_connection);
2154 			break;
2155 		default:
2156 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2157 			break;
2158 		}
2159 	}
2160 	
2161 	static void
2162 	nm_client_class_init (NMClientClass *client_class)
2163 	{
2164 		GObjectClass *object_class = G_OBJECT_CLASS (client_class);
2165 	
2166 		g_type_class_add_private (client_class, sizeof (NMClientPrivate));
2167 	
2168 		/* virtual methods */
2169 		object_class->constructor = constructor;
2170 		object_class->constructed = constructed;
2171 		object_class->set_property = set_property;
2172 		object_class->get_property = get_property;
2173 		object_class->dispose = dispose;
2174 		object_class->finalize = finalize;
2175 	
2176 		/* properties */
2177 	
2178 		/**
2179 		 * NMClient:version:
2180 		 *
2181 		 * The NetworkManager version.
2182 		 **/
2183 		g_object_class_install_property (object_class, PROP_VERSION,
2184 		                                 g_param_spec_string (NM_CLIENT_VERSION,
2185 		                                                      "Version",
2186 		                                                      "NetworkManager version",
2187 		                                                       NULL,
2188 		                                                       G_PARAM_READABLE));
2189 	
2190 		/**
2191 		 * NMClient:state:
2192 		 *
2193 		 * The current daemon state.
2194 		 **/
2195 		g_object_class_install_property
2196 			(object_class, PROP_STATE,
2197 			 g_param_spec_uint (NM_CLIENT_STATE,
2198 							    "State",
2199 							    "NetworkManager state",
2200 							    NM_STATE_UNKNOWN, NM_STATE_CONNECTED_GLOBAL, NM_STATE_UNKNOWN,
2201 							    G_PARAM_READABLE));
2202 	
2203 		/**
2204 		 * NMClient:startup:
2205 		 *
2206 		 * Whether the daemon is still starting up.
2207 		 *
2208 		 * Since: 0.9.10
2209 		 **/
2210 		g_object_class_install_property
2211 			(object_class, PROP_STARTUP,
2212 			 g_param_spec_boolean (NM_CLIENT_STARTUP,
2213 			                       "Startup",
2214 			                       "Whether the daemon is still starting up",
2215 			                       FALSE,
2216 			                       G_PARAM_READABLE));
2217 	
2218 		/**
2219 		 * NMClient::manager-running:
2220 		 *
2221 		 * Whether the daemon is running.
2222 		 **/
2223 		g_object_class_install_property
2224 			(object_class, PROP_MANAGER_RUNNING,
2225 			 g_param_spec_boolean (NM_CLIENT_MANAGER_RUNNING,
2226 							       "ManagerRunning",
2227 							       "Whether NetworkManager is running",
2228 							       FALSE,
2229 							       G_PARAM_READABLE));
2230 	
2231 		/**
2232 		 * NMClient::networking-enabled:
2233 		 *
2234 		 * Whether networking is enabled.
2235 		 **/
2236 		g_object_class_install_property
2237 			(object_class, PROP_NETWORKING_ENABLED,
2238 			 g_param_spec_boolean (NM_CLIENT_NETWORKING_ENABLED,
2239 							   "NetworkingEnabled",
2240 							   "Is networking enabled",
2241 							   TRUE,
2242 							   G_PARAM_READWRITE));
2243 	
2244 		/**
2245 		 * NMClient::wireless-enabled:
2246 		 *
2247 		 * Whether wireless is enabled.
2248 		 **/
2249 		g_object_class_install_property
2250 			(object_class, PROP_WIRELESS_ENABLED,
2251 			 g_param_spec_boolean (NM_CLIENT_WIRELESS_ENABLED,
2252 							   "WirelessEnabled",
2253 							   "Is wireless enabled",
2254 							   FALSE,
2255 							   G_PARAM_READWRITE));
2256 	
2257 		/**
2258 		 * NMClient::wireless-hardware-enabled:
2259 		 *
2260 		 * Whether the wireless hardware is enabled.
2261 		 **/
2262 		g_object_class_install_property
2263 			(object_class, PROP_WIRELESS_HARDWARE_ENABLED,
2264 			 g_param_spec_boolean (NM_CLIENT_WIRELESS_HARDWARE_ENABLED,
2265 							   "WirelessHardwareEnabled",
2266 							   "Is wireless hardware enabled",
2267 							   TRUE,
2268 							   G_PARAM_READABLE));
2269 	
2270 		/**
2271 		 * NMClient::wwan-enabled:
2272 		 *
2273 		 * Whether WWAN functionality is enabled.
2274 		 **/
2275 		g_object_class_install_property
2276 			(object_class, PROP_WWAN_ENABLED,
2277 			 g_param_spec_boolean (NM_CLIENT_WWAN_ENABLED,
2278 			                       "WwanEnabled",
2279 			                       "Is WWAN enabled",
2280 			                       FALSE,
2281 			                       G_PARAM_READWRITE));
2282 	
2283 		/**
2284 		 * NMClient::wwan-hardware-enabled:
2285 		 *
2286 		 * Whether the WWAN hardware is enabled.
2287 		 **/
2288 		g_object_class_install_property
2289 			(object_class, PROP_WWAN_HARDWARE_ENABLED,
2290 			 g_param_spec_boolean (NM_CLIENT_WWAN_HARDWARE_ENABLED,
2291 			                       "WwanHardwareEnabled",
2292 			                       "Is WWAN hardware enabled",
2293 			                       FALSE,
2294 			                       G_PARAM_READABLE));
2295 	
2296 		/**
2297 		 * NMClient::wimax-enabled:
2298 		 *
2299 		 * Whether WiMAX functionality is enabled.
2300 		 **/
2301 		g_object_class_install_property
2302 			(object_class, PROP_WIMAX_ENABLED,
2303 			 g_param_spec_boolean (NM_CLIENT_WIMAX_ENABLED,
2304 			                       "WimaxEnabled",
2305 			                       "Is WiMAX enabled",
2306 			                       FALSE,
2307 			                       G_PARAM_READWRITE));
2308 	
2309 		/**
2310 		 * NMClient::wimax-hardware-enabled:
2311 		 *
2312 		 * Whether the WiMAX hardware is enabled.
2313 		 **/
2314 		g_object_class_install_property
2315 			(object_class, PROP_WIMAX_HARDWARE_ENABLED,
2316 			 g_param_spec_boolean (NM_CLIENT_WIMAX_HARDWARE_ENABLED,
2317 			                       "WimaxHardwareEnabled",
2318 			                       "Is WiMAX hardware enabled",
2319 			                       FALSE,
2320 			                       G_PARAM_READABLE));
2321 	
2322 		/**
2323 		 * NMClient::active-connections:
2324 		 *
2325 		 * The active connections.
2326 		 * Type: GPtrArray<NMClient.ActiveConnection>
2327 		 **/
2328 		g_object_class_install_property
2329 			(object_class, PROP_ACTIVE_CONNECTIONS,
2330 			 g_param_spec_boxed (NM_CLIENT_ACTIVE_CONNECTIONS,
2331 							   "Active connections",
2332 							   "Active connections",
2333 							   NM_TYPE_OBJECT_ARRAY,
2334 							   G_PARAM_READABLE));
2335 	
2336 		/**
2337 		 * NMClient:connectivity:
2338 		 *
2339 		 * The network connectivity state.
2340 		 *
2341 		 * Since: 0.9.8.6
2342 		 */
2343 		g_object_class_install_property
2344 			(object_class, PROP_CONNECTIVITY,
2345 			 g_param_spec_uint (NM_CLIENT_CONNECTIVITY,
2346 			                    "Connectivity",
2347 			                    "Connectivity state",
2348 			                    NM_CONNECTIVITY_UNKNOWN, NM_CONNECTIVITY_FULL, NM_CONNECTIVITY_UNKNOWN,
2349 			                    G_PARAM_READABLE));
2350 	
2351 		/**
2352 		 * NMClient:primary-connection:
2353 		 *
2354 		 * The #NMActiveConnection of the device with the default route;
2355 		 * see nm_client_get_primary_connection() for more details.
2356 		 *
2357 		 * Since: 0.9.8.6
2358 		 **/
2359 		g_object_class_install_property
2360 			(object_class, PROP_PRIMARY_CONNECTION,
2361 			 g_param_spec_object (NM_CLIENT_PRIMARY_CONNECTION,
2362 			                      "Primary connection",
2363 			                      "Primary connection",
2364 			                      NM_TYPE_ACTIVE_CONNECTION,
2365 			                      G_PARAM_READABLE));
2366 	
2367 		/**
2368 		 * NMClient:activating-connection:
2369 		 *
2370 		 * The #NMActiveConnection of the activating connection that is
2371 		 * likely to become the new #NMClient:primary-connection.
2372 		 *
2373 		 * Since: 0.9.8.6
2374 		 **/
2375 		g_object_class_install_property
2376 			(object_class, PROP_ACTIVATING_CONNECTION,
2377 			 g_param_spec_object (NM_CLIENT_ACTIVATING_CONNECTION,
2378 			                      "Activating connection",
2379 			                      "Activating connection",
2380 			                      NM_TYPE_ACTIVE_CONNECTION,
2381 			                      G_PARAM_READABLE));
2382 	
2383 		/* signals */
2384 	
2385 		/**
2386 		 * NMClient::device-added:
2387 		 * @client: the client that received the signal
2388 		 * @device: (type NMClient.Device): the new device
2389 		 *
2390 		 * Notifies that a #NMDevice is added.
2391 		 **/
2392 		signals[DEVICE_ADDED] =
2393 			g_signal_new ("device-added",
2394 						  G_OBJECT_CLASS_TYPE (object_class),
2395 						  G_SIGNAL_RUN_FIRST,
2396 						  G_STRUCT_OFFSET (NMClientClass, device_added),
2397 						  NULL, NULL, NULL,
2398 						  G_TYPE_NONE, 1,
2399 						  G_TYPE_OBJECT);
2400 	
2401 		/**
2402 		 * NMClient::device-removed:
2403 		 * @client: the client that received the signal
2404 		 * @device: (type NMClient.Device): the removed device
2405 		 *
2406 		 * Notifies that a #NMDevice is removed.
2407 		 **/
2408 		signals[DEVICE_REMOVED] =
2409 			g_signal_new ("device-removed",
2410 			              G_OBJECT_CLASS_TYPE (object_class),
2411 			              G_SIGNAL_RUN_FIRST,
2412 			              G_STRUCT_OFFSET (NMClientClass, device_removed),
2413 			              NULL, NULL, NULL,
2414 			              G_TYPE_NONE, 1,
2415 			              G_TYPE_OBJECT);
2416 	
2417 		/**
2418 		 * NMClient::permission-changed:
2419 		 * @client: the client that received the signal
2420 		 * @permission: a permission from #NMClientPermission
2421 		 * @result: the permission's result, one of #NMClientPermissionResult
2422 		 *
2423 		 * Notifies that a permission has changed
2424 		 **/
2425 		signals[PERMISSION_CHANGED] =
2426 			g_signal_new ("permission-changed",
2427 			              G_OBJECT_CLASS_TYPE (object_class),
2428 			              G_SIGNAL_RUN_FIRST,
2429 			              0, NULL, NULL, NULL,
2430 			              G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
2431 	}
2432 	
2433 	static void
2434 	nm_client_initable_iface_init (GInitableIface *iface)
2435 	{
2436 		nm_client_parent_initable_iface = g_type_interface_peek_parent (iface);
2437 	
2438 		iface->init = init_sync;
2439 	}
2440 	
2441 	static void
2442 	nm_client_async_initable_iface_init (GAsyncInitableIface *iface)
2443 	{
2444 		nm_client_parent_async_initable_iface = g_type_interface_peek_parent (iface);
2445 	
2446 		iface->init_async = init_async;
2447 		iface->init_finish = init_finish;
2448 	}
2449