1    	/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2    	/* NetworkManager -- Network link manager
3    	 *
4    	 * This program is free software; you can redistribute it and/or modify
5    	 * it under the terms of the GNU General Public License as published by
6    	 * the Free Software Foundation; either version 2 of the License, or
7    	 * (at your option) any later version.
8    	 *
9    	 * This program is distributed in the hope that it will be useful,
10   	 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   	 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   	 * GNU General Public License for more details.
13   	 *
14   	 * You should have received a copy of the GNU General Public License along
15   	 * with this program; if not, write to the Free Software Foundation, Inc.,
16   	 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17   	 *
18   	 * Copyright (C) 2007 - 2009 Novell, Inc.
19   	 * Copyright (C) 2007 - 2012 Red Hat, Inc.
20   	 */
21   	
22   	#include <config.h>
23   	
24   	#include <stdlib.h>
25   	#include <netinet/ether.h>
26   	#include <fcntl.h>
27   	#include <errno.h>
28   	#include <string.h>
29   	#include <unistd.h>
30   	#include <sys/types.h>
31   	#include <sys/stat.h>
32   	#include <dbus/dbus-glib-lowlevel.h>
33   	#include <dbus/dbus-glib.h>
34   	#include <gio/gio.h>
35   	#include <glib/gi18n.h>
36   	
37   	#include "nm-glib-compat.h"
38   	#include "nm-manager.h"
39   	#include "nm-logging.h"
40   	#include "nm-dbus-manager.h"
41   	#include "nm-vpn-manager.h"
42   	#include "nm-modem-manager.h"
43   	#include "nm-device-bt.h"
44   	#include "nm-device.h"
45   	#include "nm-device-ethernet.h"
46   	#include "nm-device-wifi.h"
47   	#include "nm-device-olpc-mesh.h"
48   	#include "nm-device-modem.h"
49   	#include "nm-device-infiniband.h"
50   	#include "nm-device-bond.h"
51   	#include "nm-device-team.h"
52   	#include "nm-device-bridge.h"
53   	#include "nm-device-vlan.h"
54   	#include "nm-device-adsl.h"
55   	#include "nm-device-generic.h"
56   	#include "nm-device-veth.h"
57   	#include "nm-device-tun.h"
58   	#include "nm-device-macvlan.h"
59   	#include "nm-device-gre.h"
60   	#include "nm-setting-private.h"
61   	#include "nm-setting-bluetooth.h"
62   	#include "nm-setting-connection.h"
63   	#include "nm-setting-wireless.h"
64   	#include "nm-setting-vpn.h"
65   	#include "nm-dbus-glib-types.h"
66   	#include "nm-platform.h"
67   	#include "nm-atm-manager.h"
68   	#include "nm-rfkill-manager.h"
69   	#include "nm-hostname-provider.h"
70   	#include "nm-bluez-manager.h"
71   	#include "nm-bluez-common.h"
72   	#include "nm-settings.h"
73   	#include "nm-settings-connection.h"
74   	#include "nm-manager-auth.h"
75   	#include "NetworkManagerUtils.h"
76   	#include "nm-utils.h"
77   	#include "nm-device-factory.h"
78   	#include "nm-enum-types.h"
79   	#include "nm-sleep-monitor.h"
80   	#include "nm-connectivity.h"
81   	#include "nm-policy.h"
82   	
83   	
84   	#define NM_AUTOIP_DBUS_SERVICE "org.freedesktop.nm_avahi_autoipd"
85   	#define NM_AUTOIP_DBUS_IFACE   "org.freedesktop.nm_avahi_autoipd"
86   	
87   	static gboolean impl_manager_get_devices (NMManager *manager,
88   	                                          GPtrArray **devices,
89   	                                          GError **err);
90   	
91   	static gboolean impl_manager_get_device_by_ip_iface (NMManager *self,
92   	                                                     const char *iface,
93   	                                                     char **out_object_path,
94   	                                                     GError **error);
95   	
96   	static void impl_manager_activate_connection (NMManager *manager,
97   	                                              const char *connection_path,
98   	                                              const char *device_path,
99   	                                              const char *specific_object_path,
100  	                                              DBusGMethodInvocation *context);
101  	
102  	static void impl_manager_add_and_activate_connection (NMManager *manager,
103  	                                                      GHashTable *settings,
104  	                                                      const char *device_path,
105  	                                                      const char *specific_object_path,
106  	                                                      DBusGMethodInvocation *context);
107  	
108  	static void impl_manager_deactivate_connection (NMManager *manager,
109  	                                                const char *connection_path,
110  	                                                DBusGMethodInvocation *context);
111  	
112  	static void impl_manager_sleep (NMManager *manager,
113  	                                gboolean do_sleep,
114  	                                DBusGMethodInvocation *context);
115  	
116  	static void impl_manager_enable (NMManager *manager,
117  	                                 gboolean enable,
118  	                                 DBusGMethodInvocation *context);
119  	
120  	static void impl_manager_get_permissions (NMManager *manager,
121  	                                          DBusGMethodInvocation *context);
122  	
123  	static gboolean impl_manager_get_state (NMManager *manager,
124  	                                        guint32 *state,
125  	                                        GError **error);
126  	
127  	static gboolean impl_manager_set_logging (NMManager *manager,
128  	                                          const char *level,
129  	                                          const char *domains,
130  	                                          GError **error);
131  	
132  	static void impl_manager_get_logging (NMManager *manager,
133  	                                      char **level,
134  	                                      char **domains);
135  	
136  	static void impl_manager_check_connectivity (NMManager *manager,
137  	                                             DBusGMethodInvocation *context);
138  	
139  	#include "nm-manager-glue.h"
140  	
141  	static void bluez_manager_bdaddr_added_cb (NMBluezManager *bluez_mgr,
142  	                                           NMBluezDevice *bt_device,
143  	                                           const char *bdaddr,
144  	                                           const char *name,
145  	                                           const char *object_path,
146  	                                           guint32 uuids,
147  	                                           NMManager *manager);
148  	
149  	static void bluez_manager_bdaddr_removed_cb (NMBluezManager *bluez_mgr,
150  	                                             const char *bdaddr,
151  	                                             const char *object_path,
152  	                                             gpointer user_data);
153  	
154  	static void add_device (NMManager *self, NMDevice *device);
155  	static void remove_device (NMManager *self, NMDevice *device, gboolean quitting);
156  	
157  	static void hostname_provider_init (NMHostnameProvider *provider_class);
158  	
159  	static NMActiveConnection *internal_activate_device (NMManager *manager,
160  	                                                     NMDevice *device,
161  	                                                     NMConnection *connection,
162  	                                                     const char *specific_object,
163  	                                                     gboolean user_requested,
164  	                                                     gulong sender_uid,
165  	                                                     const char *dbus_sender,
166  	                                                     gboolean assumed,
167  	                                                     NMActiveConnection *master,
168  	                                                     GError **error);
169  	
170  	static NMDevice *find_device_by_ip_iface (NMManager *self, const gchar *iface);
171  	
172  	static void rfkill_change_wifi (const char *desc, gboolean enabled);
173  	
174  	static void
175  	platform_link_added_cb (NMPlatform *platform,
176  	                        int ifindex,
177  	                        NMPlatformLink *plink,
178  	                        NMPlatformReason reason,
179  	                        gpointer user_data);
180  	
181  	#define SSD_POKE_INTERVAL 120
182  	#define ORIGDEV_TAG "originating-device"
183  	
184  	typedef struct PendingActivation PendingActivation;
185  	typedef void (*PendingActivationFunc) (PendingActivation *pending,
186  	                                       GError *error);
187  	
188  	struct PendingActivation {
189  		NMManager *manager;
190  	
191  		DBusGMethodInvocation *context;
192  		PendingActivationFunc callback;
193  		NMAuthChain *chain;
194  		const char *wifi_shared_permission;
195  	
196  		char *connection_path;
197  		NMConnection *connection;
198  		char *specific_object_path;
199  		char *device_path;
200  	};
201  	
202  	typedef struct {
203  		gboolean user_enabled;
204  		gboolean daemon_enabled;
205  		gboolean sw_enabled;
206  		gboolean hw_enabled;
207  		RfKillType rtype;
208  		const char *desc;
209  		const char *key;
210  		const char *prop;
211  		const char *hw_prop;
212  		RfKillState (*other_enabled_func) (NMManager *);
213  		RfKillState (*daemon_enabled_func) (NMManager *);
214  	} RadioState;
215  	
216  	typedef struct {
217  		char *state_file;
218  	
219  		GSList *active_connections;
220  		guint ac_cleanup_id;
221  		NMActiveConnection *primary_connection;
222  		NMActiveConnection *activating_connection;
223  	
224  		GSList *devices;
225  		NMState state;
226  		NMConnectivity *connectivity;
227  	
228  		NMPolicy *policy;
229  	
230  		NMDBusManager *dbus_mgr;
231  		guint          dbus_connection_changed_id;
232  		NMAtmManager *atm_mgr;
233  		NMRfkillManager *rfkill_mgr;
234  		NMBluezManager *bluez_mgr;
235  	
236  		/* List of NMDeviceFactoryFunc pointers sorted in priority order */
237  		GSList *factories;
238  	
239  		NMSettings *settings;
240  		char *hostname;
241  	
242  		RadioState radio_states[RFKILL_TYPE_MAX];
243  		gboolean sleeping;
244  		gboolean net_enabled;
245  	
246  		NMVPNManager *vpn_manager;
247  	
248  		NMModemManager *modem_manager;
249  		guint modem_added_id;
250  		guint modem_removed_id;
251  	
252  		DBusGProxy *aipd_proxy;
253  		NMSleepMonitor *sleep_monitor;
254  	
255  		GSList *auth_chains;
256  	
257  		/* Firmware dir monitor */
258  		GFileMonitor *fw_monitor;
259  		guint fw_monitor_id;
260  		guint fw_changed_id;
261  	
262  		guint timestamp_update_id;
263  	
264  		GHashTable *nm_bridges;
265  	
266  		/* Track auto-activation for software devices */
267  		GHashTable *noauto_sw_devices;
268  	
269  		gboolean startup;
270  		gboolean disposed;
271  	} NMManagerPrivate;
272  	
273  	#define NM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MANAGER, NMManagerPrivate))
274  	
275  	G_DEFINE_TYPE_EXTENDED (NMManager, nm_manager, G_TYPE_OBJECT, 0,
276  							G_IMPLEMENT_INTERFACE (NM_TYPE_HOSTNAME_PROVIDER,
277  												   hostname_provider_init))
278  	
279  	enum {
280  		DEVICE_ADDED,
281  		DEVICE_REMOVED,
282  		STATE_CHANGED,
283  		CHECK_PERMISSIONS,
284  		USER_PERMISSIONS_CHANGED,
285  		ACTIVE_CONNECTION_ADDED,
286  		ACTIVE_CONNECTION_REMOVED,
287  	
288  		LAST_SIGNAL
289  	};
290  	
291  	static guint signals[LAST_SIGNAL] = { 0 };
292  	
293  	enum {
294  		PROP_0,
295  		PROP_VERSION,
296  		PROP_STATE,
297  		PROP_STARTUP,
298  		PROP_NETWORKING_ENABLED,
299  		PROP_WIRELESS_ENABLED,
300  		PROP_WIRELESS_HARDWARE_ENABLED,
301  		PROP_WWAN_ENABLED,
302  		PROP_WWAN_HARDWARE_ENABLED,
303  		PROP_WIMAX_ENABLED,
304  		PROP_WIMAX_HARDWARE_ENABLED,
305  		PROP_ACTIVE_CONNECTIONS,
306  		PROP_CONNECTIVITY,
307  		PROP_PRIMARY_CONNECTION,
308  		PROP_ACTIVATING_CONNECTION,
309  	
310  		/* Not exported */
311  		PROP_HOSTNAME,
312  		PROP_SLEEPING,
313  	
314  		LAST_PROP
315  	};
316  	
317  	
318  	/************************************************************************/
319  	
320  	#define NM_MANAGER_ERROR (nm_manager_error_quark ())
321  	
322  	static GQuark
323  	nm_manager_error_quark (void)
324  	{
325  		static GQuark quark = 0;
326  		if (!quark)
327  			quark = g_quark_from_static_string ("nm-manager-error");
328  		return quark;
329  	}
330  	
331  	/************************************************************************/
332  	
333  	static void active_connection_state_changed (NMActiveConnection *active,
334  	                                             GParamSpec *pspec,
335  	                                             NMManager *self);
336  	
337  	static void
338  	active_connection_removed (NMManager *self, NMActiveConnection *active)
339  	{
340  		g_signal_emit (self, signals[ACTIVE_CONNECTION_REMOVED], 0, active);
341  		g_signal_handlers_disconnect_by_func (active, active_connection_state_changed, self);
342  		g_object_unref (active);
343  	}
344  	
345  	static gboolean
346  	_active_connection_cleanup (gpointer user_data)
347  	{
348  		NMManager *self = NM_MANAGER (user_data);
349  		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
350  		GSList *iter;
351  		gboolean changed = FALSE;
352  	
353  		priv->ac_cleanup_id = 0;
354  	
355  		iter = priv->active_connections;
356  		while (iter) {
357  			NMActiveConnection *ac = iter->data;
358  	
359  			iter = iter->next;
360  			if (nm_active_connection_get_state (ac) == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) {
361  				priv->active_connections = g_slist_remove (priv->active_connections, ac);
362  				active_connection_removed (self, ac);
363  				changed = TRUE;
364  			}
365  		}
366  	
367  		if (changed)
368  			g_object_notify (G_OBJECT (self), NM_MANAGER_ACTIVE_CONNECTIONS);
369  	
370  		return FALSE;
371  	}
372  	
373  	static void
374  	active_connection_state_changed (NMActiveConnection *active,
375  	                                 GParamSpec *pspec,
376  	                                 NMManager *self)
377  	{
378  		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
379  		NMActiveConnectionState state;
380  	
381  		state = nm_active_connection_get_state (active);
382  		if (state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) {
383  			/* Destroy active connections from an idle handler to ensure that
384  			 * their last property change notifications go out, which wouldn't
385  			 * happen if we destroyed them immediately when their state was set
386  			 * to DEACTIVATED.
387  			 */
388  			if (!priv->ac_cleanup_id)
389  				priv->ac_cleanup_id = g_idle_add (_active_connection_cleanup, self);
390  		}
391  	}
392  	
393  	static void
394  	active_connection_add (NMManager *self, NMActiveConnection *active)
395  	{
396  		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
397  	
398  		g_return_if_fail (g_slist_find (priv->active_connections, active) == FALSE);
399  	
400  		priv->active_connections = g_slist_prepend (priv->active_connections, active);
401  		g_signal_connect (active, "notify::" NM_ACTIVE_CONNECTION_STATE,
402  		                  G_CALLBACK (active_connection_state_changed),
403  		                  self);
404  	
405  		g_signal_emit (self, signals[ACTIVE_CONNECTION_ADDED], 0, active);
406  		g_object_notify (G_OBJECT (self), NM_MANAGER_ACTIVE_CONNECTIONS);
407  	}
408  	
409  	const GSList *
410  	nm_manager_get_active_connections (NMManager *manager)
411  	{
412  		return NM_MANAGER_GET_PRIVATE (manager)->active_connections;
413  	}
414  	
415  	static NMActiveConnection *
416  	active_connection_get_by_path (NMManager *manager, const char *path)
417  	{
418  		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
419  		GSList *iter;
420  	
421  		g_return_val_if_fail (manager != NULL, NULL);
422  		g_return_val_if_fail (path != NULL, NULL);
423  	
424  		for (iter = priv->active_connections; iter; iter = g_slist_next (iter)) {
425  			NMActiveConnection *candidate = iter->data;
426  	
427  			if (strcmp (path, nm_active_connection_get_path (candidate)) == 0)
428  				return candidate;
429  		}
430  		return NULL;
431  	}
432  	
433  	/************************************************************************/
434  	
435  	static NMDevice *
436  	nm_manager_get_device_by_udi (NMManager *manager, const char *udi)
437  	{
438  		GSList *iter;
439  	
440  		g_return_val_if_fail (udi != NULL, NULL);
441  	
442  		for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) {
443  			if (!strcmp (nm_device_get_udi (NM_DEVICE (iter->data)), udi))
444  				return NM_DEVICE (iter->data);
445  		}
446  		return NULL;
447  	}
448  	
449  	static NMDevice *
450  	nm_manager_get_device_by_path (NMManager *manager, const char *path)
451  	{
452  		GSList *iter;
453  	
454  		g_return_val_if_fail (path != NULL, NULL);
455  	
456  		for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) {
457  			if (!strcmp (nm_device_get_path (NM_DEVICE (iter->data)), path))
458  				return NM_DEVICE (iter->data);
459  		}
460  		return NULL;
461  	}
462  	
463  	NMDevice *
464  	nm_manager_get_device_by_master (NMManager *manager, const char *master, const char *driver)
465  	{
466  		GSList *iter;
467  	
468  		g_return_val_if_fail (master != NULL, NULL);
469  	
470  		for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) {
471  			NMDevice *device = NM_DEVICE (iter->data);
472  	
473  			if (!strcmp (nm_device_get_iface (device), master) &&
474  			    (!driver || !strcmp (nm_device_get_driver (device), driver)))
475  				return device;
476  		}
477  	
478  		return NULL;
479  	}
480  	
481  	NMDevice *
482  	nm_manager_get_device_by_ifindex (NMManager *manager, int ifindex)
483  	{
484  		GSList *iter;
485  	
486  		for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) {
487  			NMDevice *device = NM_DEVICE (iter->data);
488  	
489  			if (nm_device_get_ifindex (device) == ifindex)
490  				return device;
491  		}
492  	
493  		return NULL;
494  	}
495  	
496  	static gboolean
497  	manager_sleeping (NMManager *self)
498  	{
499  		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
500  	
501  		if (priv->sleeping || !priv->net_enabled)
502  			return TRUE;
503  		return FALSE;
504  	}
505  	
506  	static void
507  	modem_added (NMModemManager *modem_manager,
508  				 NMModem *modem,
509  				 const char *driver,
510  				 gpointer user_data)
511  	{
512  		NMManager *self = NM_MANAGER (user_data);
513  		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
514  		NMDevice *replace_device, *device = NULL;
515  		const char *modem_iface;
516  		GSList *iter;
517  	
518  		/* Don't rely only on the data port; use the control port if available */
519  		modem_iface = nm_modem_get_data_port (modem);
520  		if (!modem_iface)
521  			modem_iface = nm_modem_get_control_port (modem);
522  		g_return_if_fail (modem_iface);
523  	
524  		replace_device = find_device_by_ip_iface (NM_MANAGER (user_data), modem_iface);
525  		if (replace_device)
526  			remove_device (NM_MANAGER (user_data), replace_device, FALSE);
527  	
528  		/* Give Bluetooth DUN devices first chance to claim the modem */
529  		for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
530  			if (nm_device_get_device_type (iter->data) == NM_DEVICE_TYPE_BT) {
531  				if (nm_device_bt_modem_added (NM_DEVICE_BT (iter->data), modem, driver))
532  					return;
533  			}
534  		}
535  	
536  		/* If it was a Bluetooth modem and no bluetooth device claimed it, ignore
537  		 * it.  The rfcomm port (and thus the modem) gets created automatically
538  		 * by the Bluetooth code during the connection process.
539  		 */
540  		if (driver && !strcmp (driver, "bluetooth")) {
541  			nm_log_info (LOGD_MB, "ignoring modem '%s' (no associated Bluetooth device)", modem_iface);
542  			return;
543  		}
544  	
545  		/* Make the new modem device */
546  		device = nm_device_modem_new (modem, driver);
547  		if (device)
548  			add_device (self, device);
549  	}
550  	
551  	static void
552  	set_state (NMManager *manager, NMState state)
553  	{
554  		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
555  		const char *state_str;
556  	
557  		if (priv->state == state)
558  			return;
559  	
560  		priv->state = state;
561  	
562  		switch (state) {
563  		case NM_STATE_ASLEEP:
564  			state_str = "ASLEEP";
565  			break;
566  		case NM_STATE_DISCONNECTED:
567  			state_str = "DISCONNECTED";
568  			break;
569  		case NM_STATE_DISCONNECTING:
570  			state_str = "DISCONNECTING";
571  			break;
572  		case NM_STATE_CONNECTING:
573  			state_str = "CONNECTING";
574  			break;
575  		case NM_STATE_CONNECTED_LOCAL:
576  			state_str = "CONNECTED_LOCAL";
577  			break;
578  		case NM_STATE_CONNECTED_SITE:
579  			state_str = "CONNECTED_SITE";
580  			break;
581  		case NM_STATE_CONNECTED_GLOBAL:
582  			state_str = "CONNECTED_GLOBAL";
583  			break;
584  		case NM_STATE_UNKNOWN:
585  		default:
586  			state_str = "UNKNOWN";
587  			break;
588  		}
589  	
590  		nm_log_info (LOGD_CORE, "NetworkManager state is now %s", state_str);
591  	
592  		g_object_notify (G_OBJECT (manager), NM_MANAGER_STATE);
593  		g_signal_emit (manager, signals[STATE_CHANGED], 0, priv->state);
594  	}
595  	
596  	static void
597  	checked_connectivity (GObject *object, GAsyncResult *result, gpointer user_data)
598  	{
599  		NMManager *manager = user_data;
600  		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
601  		NMConnectivityState connectivity;
602  	
603  		if (priv->state == NM_STATE_CONNECTING || priv->state == NM_STATE_CONNECTED_SITE) {
604  			connectivity = nm_connectivity_check_finish (priv->connectivity, result, NULL);
605  	
606  			if (connectivity == NM_CONNECTIVITY_FULL)
607  				set_state (manager, NM_STATE_CONNECTED_GLOBAL);
608  			else if (   connectivity == NM_CONNECTIVITY_PORTAL
609  			         || connectivity == NM_CONNECTIVITY_LIMITED)
610  				set_state (manager, NM_STATE_CONNECTED_SITE);
611  		}
612  	
613  		g_object_unref (manager);
614  	}
615  	
616  	static void
617  	nm_manager_update_state (NMManager *manager)
618  	{
619  		NMManagerPrivate *priv;
620  		NMState new_state = NM_STATE_DISCONNECTED;
621  		GSList *iter;
622  		gboolean want_connectivity_check = FALSE;
623  	
624  		g_return_if_fail (NM_IS_MANAGER (manager));
625  	
626  		priv = NM_MANAGER_GET_PRIVATE (manager);
627  	
628  		if (manager_sleeping (manager))
629  			new_state = NM_STATE_ASLEEP;
630  		else {
631  			for (iter = priv->devices; iter; iter = iter->next) {
632  				NMDevice *dev = NM_DEVICE (iter->data);
633  				NMDeviceState state = nm_device_get_state (dev);
634  	
635  				if (state == NM_DEVICE_STATE_ACTIVATED) {
636  					nm_connectivity_set_online (priv->connectivity, TRUE);
637  					if (nm_connectivity_get_state (priv->connectivity) != NM_CONNECTIVITY_FULL) {
638  						new_state = NM_STATE_CONNECTING;
639  						want_connectivity_check = TRUE;
640  					} else {
641  						new_state = NM_STATE_CONNECTED_GLOBAL;
642  						break;
643  					}
644  				}
645  	
646  				if (nm_device_is_activating (dev))
647  					new_state = NM_STATE_CONNECTING;
648  				else if (new_state != NM_STATE_CONNECTING) {
649  					if (state == NM_DEVICE_STATE_DEACTIVATING)
650  						new_state = NM_STATE_DISCONNECTING;
651  				}
652  			}
653  		}
654  	
655  		if (new_state == NM_STATE_CONNECTING && want_connectivity_check) {
656  			nm_connectivity_check_async (priv->connectivity,
657  			                             checked_connectivity,
658  			                             g_object_ref (manager));
659  			return;
660  		}
661  	
662  		nm_connectivity_set_online (priv->connectivity, new_state >= NM_STATE_CONNECTED_LOCAL);
663  		set_state (manager, new_state);
664  	}
665  	
666  	static void
667  	manager_device_state_changed (NMDevice *device,
668  	                              NMDeviceState new_state,
669  	                              NMDeviceState old_state,
670  	                              NMDeviceStateReason reason,
671  	                              gpointer user_data)
672  	{
673  		NMManager *self = NM_MANAGER (user_data);
674  	
675  		switch (new_state) {
676  		case NM_DEVICE_STATE_UNMANAGED:
677  		case NM_DEVICE_STATE_UNAVAILABLE:
678  		case NM_DEVICE_STATE_DISCONNECTED:
679  		case NM_DEVICE_STATE_PREPARE:
680  		case NM_DEVICE_STATE_FAILED:
681  			g_object_notify (G_OBJECT (self), NM_MANAGER_ACTIVE_CONNECTIONS);
682  			break;
683  		default:
684  			break;
685  		}
686  	
687  		nm_manager_update_state (self);
688  	}
689  	
690  	static void device_has_pending_action_changed (NMDevice *device,
691  	                                               GParamSpec *pspec,
692  	                                               NMManager *self);
693  	
694  	static void
695  	check_if_startup_complete (NMManager *self)
696  	{
697  		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
698  		GSList *iter;
699  	
700  		if (!priv->startup)
701  			return;
702  	
703  		for (iter = priv->devices; iter; iter = iter->next) {
704  			NMDevice *dev = iter->data;
705  	
706  			if (nm_device_has_pending_action (dev)) {
707  				nm_log_dbg (LOGD_CORE, "check_if_startup_complete returns FALSE because of %s",
708  				            nm_device_get_iface (dev));
709  				return;
710  			}
711  		}
712  	
713  		nm_log_info (LOGD_CORE, "startup complete");
714  	
715  		priv->startup = FALSE;
716  		g_object_notify (G_OBJECT (self), "startup");
717  	
718  		/* We don't have to watch notify::has-pending-action any more. */
719  		for (iter = priv->devices; iter; iter = iter->next) {
720  			NMDevice *dev = iter->data;
721  	
722  			g_signal_handlers_disconnect_by_func (dev, G_CALLBACK (device_has_pending_action_changed), self);
723  		}
724  	}
725  	
726  	static void
727  	device_has_pending_action_changed (NMDevice *device,
728  	                                   GParamSpec *pspec,
729  	                                   NMManager *self)
730  	{
731  		check_if_startup_complete (self);
732  	}
733  	
734  	static void
735  	remove_device (NMManager *manager, NMDevice *device, gboolean quitting)
736  	{
737  		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
738  	
739  		if (nm_device_get_managed (device)) {
740  			/* When quitting, we want to leave up interfaces & connections
741  			 * that can be taken over again (ie, "assumed") when NM restarts
742  			 * so that '/etc/init.d/NetworkManager restart' will not distrupt
743  			 * networking for interfaces that support connection assumption.
744  			 * All other devices get unmanaged when NM quits so that their
745  			 * connections get torn down and the interface is deactivated.
746  			 */
747  	
748  			if (   !nm_device_can_assume_connections (device)
749  			    || (nm_device_get_state (device) != NM_DEVICE_STATE_ACTIVATED)
750  			    || !quitting)
751  				nm_device_set_manager_managed (device, FALSE, NM_DEVICE_STATE_REASON_REMOVED);
752  		}
753  	
754  		g_signal_handlers_disconnect_matched (device, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, manager);
755  	
756  		nm_settings_device_removed (priv->settings, device);
757  		g_signal_emit (manager, signals[DEVICE_REMOVED], 0, device);
758  		g_object_unref (device);
759  	
760  		priv->devices = g_slist_remove (priv->devices, device);
761  	
762  		if (priv->startup)
763  			check_if_startup_complete (manager);
764  	}
765  	
766  	static void
767  	modem_removed (NMModemManager *modem_manager,
768  				   NMModem *modem,
769  				   gpointer user_data)
770  	{
771  		NMManager *self = NM_MANAGER (user_data);
772  		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
773  		NMDevice *found;
774  		GSList *iter;
775  	
776  		/* Give Bluetooth DUN devices first chance to handle the modem removal */
777  		for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
778  			if (nm_device_get_device_type (iter->data) == NM_DEVICE_TYPE_BT) {
779  				if (nm_device_bt_modem_removed (NM_DEVICE_BT (iter->data), modem))
780  					return;
781  			}
782  		}
783  	
784  		/* Otherwise remove the standalone modem */
785  		found = nm_manager_get_device_by_udi (self, nm_modem_get_path (modem));
786  		if (found)
787  			remove_device (self, found, FALSE);
788  	}
789  	
790  	static void
791  	aipd_handle_event (DBusGProxy *proxy,
792  	                   const char *event,
793  	                   const char *iface,
794  	                   const char *address,
795  	                   gpointer user_data)
796  	{
797  		NMManager *manager = NM_MANAGER (user_data);
798  		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
799  		GSList *iter;
800  		gboolean handled = FALSE;
801  	
802  		if (!event || !iface) {
803  			nm_log_warn (LOGD_AUTOIP4, "incomplete message received from avahi-autoipd");
804  			return;
805  		}
806  	
807  		if (   (strcmp (event, "BIND") != 0)
808  		    && (strcmp (event, "CONFLICT") != 0)
809  		    && (strcmp (event, "UNBIND") != 0)
810  		    && (strcmp (event, "STOP") != 0)) {
811  			nm_log_warn (LOGD_AUTOIP4, "unknown event '%s' received from avahi-autoipd", event);
812  			return;
813  		}
814  	
815  		for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
816  			NMDevice *candidate = NM_DEVICE (iter->data);
817  	
818  			if (!strcmp (nm_device_get_iface (candidate), iface)) {
819  				nm_device_handle_autoip4_event (candidate, event, address);
820  				handled = TRUE;
821  				break;
822  			}
823  		}
824  	
825  		if (!handled)
826  			nm_log_warn (LOGD_AUTOIP4, "(%s): unhandled avahi-autoipd event", iface);
827  	}
828  	
829  	static const char *
830  	hostname_provider_get_hostname (NMHostnameProvider *provider)
831  	{
832  		return NM_MANAGER_GET_PRIVATE (provider)->hostname;
833  	}
834  	
835  	static void
836  	hostname_provider_init (NMHostnameProvider *provider_class)
837  	{
838  		provider_class->get_hostname = hostname_provider_get_hostname;
839  	}
840  	
841  	NMState
842  	nm_manager_get_state (NMManager *manager)
843  	{
844  		g_return_val_if_fail (NM_IS_MANAGER (manager), NM_STATE_UNKNOWN);
845  	
846  		return NM_MANAGER_GET_PRIVATE (manager)->state;
847  	}
848  	
849  	static gboolean
850  	might_be_vpn (NMConnection *connection)
851  	{
852  		NMSettingConnection *s_con;
853  		const char *ctype = NULL;
854  	
855  		if (nm_connection_get_setting_vpn (connection))
856  			return TRUE;
857  	
858  		/* Make sure it's not a VPN, which we can't autocomplete yet */
859  		s_con = nm_connection_get_setting_connection (connection);
860  		if (s_con)
861  			ctype = nm_setting_connection_get_connection_type (s_con);
862  	
863  		return (g_strcmp0 (ctype, NM_SETTING_VPN_SETTING_NAME) == 0);
864  	}
865  	
866  	static gboolean
867  	try_complete_vpn (NMConnection *connection, GSList *existing, GError **error)
868  	{
869  		g_assert (might_be_vpn (connection) == TRUE);
870  	
871  		if (!nm_connection_get_setting_vpn (connection)) {
872  			g_set_error_literal (error,
873  				                 NM_MANAGER_ERROR,
874  				                 NM_MANAGER_ERROR_UNSUPPORTED_CONNECTION_TYPE,
875  				                 "VPN connections require a 'vpn' setting");
876  			return FALSE;
877  		}
878  	
879  		nm_utils_complete_generic (connection,
880  		                           NM_SETTING_VPN_SETTING_NAME,
881  		                           existing,
882  		                           _("VPN connection %d"),
883  		                           NULL,
884  		                           FALSE); /* No IPv6 by default for now */
885  	
886  		return TRUE;
887  	}
888  	
889  	static PendingActivation *
890  	pending_activation_new (NMManager *manager,
891  	                        DBusGMethodInvocation *context,
892  	                        const char *device_path,
893  	                        const char *connection_path,
894  	                        GHashTable *settings,
895  	                        const char *specific_object_path,
896  	                        PendingActivationFunc callback,
897  	                        GError **error)
898  	{
899  		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
900  		PendingActivation *pending;
901  		NMDevice *device = NULL;
902  		NMConnection *connection = NULL;
903  		GSList *all_connections = NULL;
904  		gboolean success;
905  	
906  		g_return_val_if_fail (manager != NULL, NULL);
907  		g_return_val_if_fail (context != NULL, NULL);
908  		g_return_val_if_fail (device_path != NULL, NULL);
909  	
910  		/* A object path of "/" means NULL */
911  		if (g_strcmp0 (specific_object_path, "/") == 0)
912  			specific_object_path = NULL;
913  		if (g_strcmp0 (device_path, "/") == 0)
914  			device_path = NULL;
915  	
916  		/* Create the partial connection from the given settings */
917  		if (settings) {
918  			if (device_path)
919  				device = nm_manager_get_device_by_path (manager, device_path);
920  			if (!device) {
921  				g_set_error_literal (error,
922  					                 NM_MANAGER_ERROR,
923  					                 NM_MANAGER_ERROR_UNKNOWN_DEVICE,
924  					                 "Device not found");
925  				return NULL;
926  			}
927  	
928  			connection = nm_connection_new ();
929  			nm_connection_replace_settings (connection, settings, NULL);
930  	
931  			all_connections = nm_settings_get_connections (priv->settings);
932  	
933  			if (might_be_vpn (connection)) {
934  				/* Try to fill the VPN's connection setting and name at least */
935  				success = try_complete_vpn (connection, all_connections, error);
936  			} else {
937  				/* Let each device subclass complete the connection */
938  				success = nm_device_complete_connection (device,
939  				                                         connection,
940  				                                         specific_object_path,
941  				                                         all_connections,
942  				                                         error);
943  			}
944  			g_slist_free (all_connections);
945  	
946  			if (success == FALSE) {
947  				g_object_unref (connection);
948  				return NULL;
949  			}
950  		}
951  	
952  		pending = g_slice_new0 (PendingActivation);
953  		pending->manager = manager;
954  		pending->context = context;
955  		pending->callback = callback;
956  	
957  		pending->connection_path = g_strdup (connection_path);
958  		pending->connection = connection;
959  	
960  		/* "/" is special-cased to NULL to get through D-Bus */
961  		if (specific_object_path && strcmp (specific_object_path, "/"))
962  			pending->specific_object_path = g_strdup (specific_object_path);
963  		if (device_path && strcmp (device_path, "/"))
964  			pending->device_path = g_strdup (device_path);
965  	
966  		return pending;
967  	}
968  	
969  	static void
970  	pending_auth_done (NMAuthChain *chain,
971  	                   GError *error,
972  	                   DBusGMethodInvocation *context,
973  	                   gpointer user_data)
974  	{
975  		PendingActivation *pending = user_data;
976  		NMAuthCallResult result;
977  		GError *tmp_error = NULL;
978  	
979  		/* Caller has had a chance to obtain authorization, so we only need to
980  		 * check for 'yes' here.
981  		 */
982  		result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL);
983  		if (error)
984  			tmp_error = g_error_copy (error);
985  		else if (result != NM_AUTH_CALL_RESULT_YES) {
986  			tmp_error = g_error_new_literal (NM_MANAGER_ERROR,
987  			                                 NM_MANAGER_ERROR_PERMISSION_DENIED,
988  			                                 "Not authorized to control networking.");
989  		} else if (pending->wifi_shared_permission) {
990  			result = nm_auth_chain_get_result (chain, pending->wifi_shared_permission);
991  			if (result != NM_AUTH_CALL_RESULT_YES) {
992  				tmp_error = g_error_new_literal (NM_MANAGER_ERROR,
993  				                                 NM_MANAGER_ERROR_PERMISSION_DENIED,
994  				                                 "Not authorized to share connections via wifi.");
995  			}
996  		}
997  	
998  		pending->callback (pending, tmp_error);
999  		g_clear_error (&tmp_error);
1000 	}
1001 	
1002 	static void
1003 	pending_activation_check_authorized (PendingActivation *pending)
1004 	{
1005 		GError *error;
1006 		const char *wifi_permission = NULL;
1007 		NMConnection *connection;
1008 		NMSettings *settings;
1009 		const char *error_desc = NULL;
1010 	
1011 		g_return_if_fail (pending != NULL);
1012 	
1013 		/* By this point we have an auto-completed connection (for AddAndActivate)
1014 		 * or an existing connection (for Activate).
1015 		 */
1016 		connection = pending->connection;
1017 		if (!connection) {
1018 			settings = NM_MANAGER_GET_PRIVATE (pending->manager)->settings;
1019 			connection = (NMConnection *) nm_settings_get_connection_by_path (settings, pending->connection_path);
1020 		}
1021 	
1022 		if (!connection) {
1023 			error = g_error_new_literal (NM_MANAGER_ERROR,
1024 			                             NM_MANAGER_ERROR_UNKNOWN_CONNECTION,
1025 			                             "Connection could not be found.");
1026 			pending->callback (pending, error);
1027 			g_error_free (error);
1028 			return;
1029 		}
1030 	
1031 		/* First check if the user is allowed to use networking at all, giving
1032 		 * the user a chance to authenticate to gain the permission.
1033 		 */
1034 		pending->chain = nm_auth_chain_new (pending->context,
1035 		                                    pending_auth_done,
1036 		                                    pending,
1037 		                                    &error_desc);
1038 		if (pending->chain) {
1039 			nm_auth_chain_add_call (pending->chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE);
1040 	
1041 			/* Shared wifi connections require special permissions too */
1042 			wifi_permission = nm_utils_get_shared_wifi_permission (connection);
1043 			if (wifi_permission) {
1044 				pending->wifi_shared_permission = wifi_permission;
1045 				nm_auth_chain_add_call (pending->chain, wifi_permission, TRUE);
1046 			}
1047 		} else {
1048 			error = g_error_new_literal (NM_MANAGER_ERROR,
1049 			                             NM_MANAGER_ERROR_PERMISSION_DENIED,
1050 			                             error_desc);
1051 			pending->callback (pending, error);
1052 			g_error_free (error);
1053 		}
1054 	}
1055 	
1056 	static void
1057 	pending_activation_destroy (PendingActivation *pending,
1058 	                            GError *error,
1059 	                            NMActiveConnection *ac)
1060 	{
1061 		g_return_if_fail (pending != NULL);
1062 	
1063 		if (error)
1064 			dbus_g_method_return_error (pending->context, error);
1065 		else if (ac) {
1066 			if (pending->connection) {
1067 				dbus_g_method_return (pending->context,
1068 				                      pending->connection_path,
1069 				                      nm_active_connection_get_path (ac));
1070 			} else {
1071 				dbus_g_method_return (pending->context,
1072 				                      nm_active_connection_get_path (ac));
1073 			}
1074 		}
1075 	
1076 		g_free (pending->connection_path);
1077 		g_free (pending->specific_object_path);
1078 		g_free (pending->device_path);
1079 		if (pending->connection)
1080 			g_object_unref (pending->connection);
1081 	
1082 		if (pending->chain)
1083 			nm_auth_chain_unref (pending->chain);
1084 	
1085 		memset (pending, 0, sizeof (PendingActivation));
1086 		g_slice_free (PendingActivation, pending);
1087 	}
1088 	
1089 	/*******************************************************************/
1090 	/* Settings stuff via NMSettings                                   */
1091 	/*******************************************************************/
1092 	
1093 	static NMDevice *
1094 	get_device_from_hwaddr (NMManager *self, const GByteArray *setting_mac)
1095 	{
1096 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1097 		const guint8 *device_mac;
1098 		guint device_mac_len;
1099 		GSList *iter;
1100 	
1101 		if (!setting_mac)
1102 			return NULL;
1103 	
1104 		for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
1105 			NMDevice *device = iter->data;
1106 	
1107 			device_mac = nm_device_get_hw_address (iter->data, &device_mac_len);
1108 			if (   setting_mac->len == device_mac_len
1109 			    && memcmp (setting_mac->data, device_mac, device_mac_len) == 0)
1110 				return device;
1111 		}
1112 		return NULL;
1113 	}
1114 	
1115 	static NMDevice *
1116 	find_vlan_parent (NMManager *self,
1117 	                  NMConnection *connection)
1118 	{
1119 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1120 		NMSettingVlan *s_vlan;
1121 		NMSettingWired *s_wired;
1122 		NMConnection *parent_connection;
1123 		const char *parent_iface;
1124 		NMDevice *parent = NULL;
1125 		const GByteArray *setting_mac;
1126 		GSList *iter;
1127 	
1128 		/* The 'parent' property could be given by an interface name, a
1129 		 * connection UUID, or the MAC address of an NMSettingWired.
1130 		 */
1131 		s_vlan = nm_connection_get_setting_vlan (connection);
1132 		g_return_val_if_fail (s_vlan != NULL, NULL);
1133 	
1134 		s_wired = nm_connection_get_setting_wired (connection);
1135 		setting_mac = s_wired ? nm_setting_wired_get_mac_address (s_wired) : NULL;
1136 	
1137 		parent_iface = nm_setting_vlan_get_parent (s_vlan);
1138 		if (parent_iface) {
1139 			parent = find_device_by_ip_iface (self, parent_iface);
1140 			if (parent)
1141 				return parent;
1142 	
1143 			if (nm_utils_is_uuid (parent_iface)) {
1144 				/* Try as a connection UUID */
1145 				parent_connection = (NMConnection *) nm_settings_get_connection_by_uuid (priv->settings, parent_iface);
1146 				if (parent_connection) {
1147 					/* Check if the parent connection is activated on some device already */
1148 					for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
1149 						NMActRequest *req;
1150 						NMConnection *candidate;
1151 	
1152 						req = nm_device_get_act_request (NM_DEVICE (iter->data));
1153 						if (req) {
1154 							candidate = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (req));
1155 							if (candidate == parent_connection)
1156 								return NM_DEVICE (iter->data);
1157 						}
1158 					}
1159 	
1160 					/* Check the hardware address of the parent connection */
1161 					return get_device_from_hwaddr (self, setting_mac);
1162 				}
1163 				return NULL;
1164 			}
1165 		}
1166 	
1167 		/* Try the hardware address from the VLAN connection's hardware setting */
1168 		return get_device_from_hwaddr (self, setting_mac);
1169 	}
1170 	
1171 	static NMDevice *
1172 	find_infiniband_parent (NMManager *self,
1173 	                        NMConnection *connection)
1174 	{
1175 		NMSettingInfiniband *s_infiniband;
1176 		const char *parent_iface;
1177 		NMDevice *parent = NULL;
1178 		const GByteArray *setting_mac;
1179 	
1180 		s_infiniband = nm_connection_get_setting_infiniband (connection);
1181 		g_return_val_if_fail (s_infiniband != NULL, NULL);
1182 	
1183 		parent_iface = nm_setting_infiniband_get_parent (s_infiniband);
1184 		if (parent_iface) {
1185 			parent = find_device_by_ip_iface (self, parent_iface);
1186 			if (parent)
1187 				return parent;
1188 		}
1189 	
1190 		setting_mac = nm_setting_infiniband_get_mac_address (s_infiniband);
1191 		return get_device_from_hwaddr (self, setting_mac);
1192 	}
1193 	
1194 	/**
1195 	 * get_virtual_iface_name:
1196 	 * @self: the #NMManager
1197 	 * @connection: the #NMConnection representing a virtual interface
1198 	 * @out_parent: on success, the parent device if any
1199 	 *
1200 	 * Given @connection, returns the interface name that the connection
1201 	 * would represent.  If the interface name is not given by the connection,
1202 	 * this may require constructing it based on information in the connection
1203 	 * and existing network interfaces.
1204 	 *
1205 	 * Returns: the expected interface name (caller takes ownership), or %NULL
1206 	 */
1207 	static char *
1208 	get_virtual_iface_name (NMManager *self,
1209 	                        NMConnection *connection,
1210 	                        NMDevice **out_parent)
1211 	{
1212 		NMDevice *parent = NULL;
1213 	
1214 		if (out_parent)
1215 			*out_parent = NULL;
1216 	
1217 		if (nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME))
1218 			return g_strdup (nm_connection_get_virtual_iface_name (connection));
1219 	
1220 		if (nm_connection_is_type (connection, NM_SETTING_TEAM_SETTING_NAME))
1221 			return g_strdup (nm_connection_get_virtual_iface_name (connection));
1222 	
1223 		if (nm_connection_is_type (connection, NM_SETTING_BRIDGE_SETTING_NAME))
1224 			return g_strdup (nm_connection_get_virtual_iface_name (connection));
1225 	
1226 		if (nm_connection_is_type (connection, NM_SETTING_VLAN_SETTING_NAME)) {
1227 			NMSettingVlan *s_vlan;
1228 			const char *ifname;
1229 			char *vname;
1230 	
1231 			s_vlan = nm_connection_get_setting_vlan (connection);
1232 			g_return_val_if_fail (s_vlan != NULL, NULL);
1233 	
1234 			parent = find_vlan_parent (self, connection);
1235 			if (parent) {
1236 				ifname = nm_connection_get_virtual_iface_name (connection);
1237 	
1238 				if (!nm_device_supports_vlans (parent)) {
1239 					nm_log_warn (LOGD_DEVICE, "(%s): No support for VLANs on interface %s of type %s",
1240 					             ifname ? ifname : nm_connection_get_id (connection),
1241 					             nm_device_get_ip_iface (parent),
1242 					             nm_device_get_type_desc (parent));
1243 					return NULL;
1244 				}
1245 	
1246 				/* If the connection doesn't specify the interface name for the VLAN
1247 				 * device, we create one for it using the VLAN ID and the parent
1248 				 * interface's name.
1249 				 */
1250 				if (ifname)
1251 					vname = g_strdup (ifname);
1252 				else {
1253 					vname = nm_utils_new_vlan_name (nm_device_get_ip_iface (parent),
1254 					                                nm_setting_vlan_get_id (s_vlan));
1255 				}
1256 				if (out_parent)
1257 					*out_parent = parent;
1258 				return vname;
1259 			}
1260 		}
1261 	
1262 		if (nm_connection_is_type (connection, NM_SETTING_INFINIBAND_SETTING_NAME)) {
1263 			const char *ifname;
1264 			char *name;
1265 	
1266 			parent = find_infiniband_parent (self, connection);
1267 			if (parent) {
1268 				ifname = nm_connection_get_virtual_iface_name (connection);
1269 				if (ifname)
1270 					name = g_strdup (ifname);
1271 				else {
1272 					NMSettingInfiniband *s_infiniband;
1273 					int p_key;
1274 	
1275 					ifname = nm_device_get_iface (parent);
1276 					s_infiniband = nm_connection_get_setting_infiniband (connection);
1277 					p_key = nm_setting_infiniband_get_p_key (s_infiniband);
1278 					name = g_strdup_printf ("%s.%04x", ifname, p_key);
1279 				}
1280 				if (out_parent)
1281 					*out_parent = parent;
1282 				return name;
1283 			}
1284 		}
1285 	
1286 		return NULL;
1287 	}
1288 	
1289 	static gboolean
1290 	connection_needs_virtual_device (NMConnection *connection)
1291 	{
1292 		if (   nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME)
1293 		    || nm_connection_is_type (connection, NM_SETTING_TEAM_SETTING_NAME)
1294 		    || nm_connection_is_type (connection, NM_SETTING_BRIDGE_SETTING_NAME)
1295 		    || nm_connection_is_type (connection, NM_SETTING_VLAN_SETTING_NAME))
1296 			return TRUE;
1297 	
1298 		if (nm_connection_is_type (connection, NM_SETTING_INFINIBAND_SETTING_NAME)) {
1299 			NMSettingInfiniband *s_infiniband;
1300 	
1301 			s_infiniband = nm_connection_get_setting_infiniband (connection);
1302 			g_return_val_if_fail (s_infiniband != NULL, FALSE);
1303 			if (nm_setting_infiniband_get_p_key (s_infiniband) != -1)
1304 				return TRUE;
1305 		}
1306 	
1307 		return FALSE;
1308 	}
1309 	
1310 	/***************************/
1311 	
1312 	/* FIXME: remove when we handle bridges non-destructively */
1313 	
1314 	#define NM_BRIDGE_FILE  NMRUNDIR "/nm-bridges"
1315 	
1316 	static void
1317 	read_nm_created_bridges (NMManager *self)
1318 	{
1319 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1320 		char *contents;
1321 		char **lines, **iter;
1322 		GTimeVal tv;
1323 		glong ts;
1324 	
1325 		if (!g_file_get_contents (NM_BRIDGE_FILE, &contents, NULL, NULL))
1326 			return;
1327 	
1328 		g_get_current_time (&tv);
1329 	
1330 		lines = g_strsplit_set (contents, "\n", 0);
1331 		g_free (contents);
1332 	
1333 		for (iter = lines; iter && *iter; iter++) {
1334 			if (g_str_has_prefix (*iter, "ts=")) {
1335 				errno = 0;
1336 				ts = strtol (*iter + 3, NULL, 10);
1337 				/* allow 30 minutes time difference before we ignore the file */
1338 				if (errno || ABS (tv.tv_sec - ts) > 1800)
1339 					goto out;
1340 			} else if (g_str_has_prefix (*iter, "iface="))
1341 				g_hash_table_insert (priv->nm_bridges, g_strdup (*iter + 6), GUINT_TO_POINTER (1));
1342 		}
1343 	
1344 	out:
1345 		g_strfreev (lines);
1346 		unlink (NM_BRIDGE_FILE);
1347 	}
1348 	
1349 	static void
1350 	write_nm_created_bridges (NMManager *self)
1351 	{
1352 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1353 		GString *br_list;
1354 		GSList *iter;
1355 		GError *error = NULL;
1356 		GTimeVal tv;
1357 		gboolean found = FALSE;
1358 	
1359 		/* write out nm-created bridges list */
1360 		br_list = g_string_sized_new (50);
1361 	
1362 		/* Timestamp is first line */
1363 		g_get_current_time (&tv);
1364 		g_string_append_printf (br_list, "ts=%ld\n", tv.tv_sec);
1365 	
1366 		for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
1367 			NMDevice *device = iter->data;
1368 	
1369 			if (nm_device_get_device_type (device) == NM_DEVICE_TYPE_BRIDGE) {
1370 				g_string_append_printf (br_list, "iface=%s\n", nm_device_get_iface (device));
1371 				found = TRUE;
1372 			}
1373 		}
1374 	
1375 		if (found) {
1376 			if (!g_file_set_contents (NM_BRIDGE_FILE, br_list->str, -1, &error)) {
1377 				nm_log_warn (LOGD_BRIDGE, "Failed to write NetworkManager-created bridge list; "
1378 				             "on restart bridges may not be recognized. (%s)",
1379 				             error ? error->message : "unknown");
1380 				g_clear_error (&error);
1381 			}
1382 		}
1383 		g_string_free (br_list, TRUE);
1384 	}
1385 	
1386 	static gboolean
1387 	bridge_created_by_nm (NMManager *self, const char *iface)
1388 	{
1389 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1390 	
1391 		return (priv->nm_bridges && g_hash_table_lookup (priv->nm_bridges, iface));
1392 	}
1393 	
1394 	/***************************/
1395 	
1396 	/**
1397 	 * system_create_virtual_device:
1398 	 * @self: the #NMManager
1399 	 * @connection: the connection which might require a virtual device
1400 	 *
1401 	 * If @connection requires a virtual device and one does not yet exist for it,
1402 	 * creates that device.
1403 	 *
1404 	 * Returns: the #NMDevice if successfully created, %NULL if not
1405 	 */
1406 	static NMDevice *
1407 	system_create_virtual_device (NMManager *self, NMConnection *connection)
1408 	{
1409 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1410 		GSList *iter;
1411 		char *iface = NULL;
1412 		NMDevice *device = NULL, *parent = NULL;
1413 	
1414 		iface = get_virtual_iface_name (self, connection, &parent);
1415 		if (!iface) {
1416 			nm_log_warn (LOGD_DEVICE, "(%s) failed to determine virtual interface name",
1417 			             nm_connection_get_id (connection));
1418 			return NULL;
1419 		}
1420 	
1421 		/* Make sure we didn't create a device for this connection already */
1422 		for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
1423 			NMDevice *candidate = iter->data;
1424 			GError *error = NULL;
1425 	
1426 			if (   g_strcmp0 (nm_device_get_iface (candidate), iface) == 0
1427 			    || nm_device_check_connection_compatible (candidate, connection, &error)) {
1428 				g_clear_error (&error);
1429 				goto out;
1430 			}
1431 			g_clear_error (&error);
1432 		}
1433 	
1434 		/* Block notification of link added since we're creating the device
1435 		 * explicitly here, otherwise adding the platform/kernel device would
1436 		 * create it before this function can do the rest of the setup.
1437 		 */
1438 		g_signal_handlers_block_by_func (nm_platform_get (), G_CALLBACK (platform_link_added_cb), self);
1439 	
1440 		if (nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME)) {
1441 			device = nm_device_bond_new_for_connection (connection);
1442 		} else if (nm_connection_is_type (connection, NM_SETTING_TEAM_SETTING_NAME)) {
1443 			device = nm_device_team_new_for_connection (connection);
1444 		} else if (nm_connection_is_type (connection, NM_SETTING_BRIDGE_SETTING_NAME)) {
1445 			/* FIXME: remove when we handle bridges non-destructively */
1446 			if (nm_platform_link_get_ifindex (iface) > 0 && !bridge_created_by_nm (self, iface)) {
1447 				nm_log_warn (LOGD_DEVICE, "(%s): cannot use existing bridge for '%s'",
1448 				             iface, nm_connection_get_id (connection));
1449 			} else
1450 				device = nm_device_bridge_new_for_connection (connection);
1451 		} else if (nm_connection_is_type (connection, NM_SETTING_VLAN_SETTING_NAME)) {
1452 			device = nm_device_vlan_new_for_connection (connection, parent);
1453 		} else if (nm_connection_is_type (connection, NM_SETTING_INFINIBAND_SETTING_NAME)) {
1454 			device = nm_device_infiniband_new_partition (connection, parent);
1455 		}
1456 	
1457 		if (device) {
1458 			nm_device_set_is_nm_owned (device, TRUE);
1459 			add_device (self, device);
1460 		}
1461 	
1462 		g_signal_handlers_unblock_by_func (nm_platform_get (), G_CALLBACK (platform_link_added_cb), self);
1463 	
1464 	out:
1465 		g_free (iface);
1466 		return device;
1467 	}
1468 	
1469 	static void
1470 	system_create_virtual_devices (NMManager *self)
1471 	{
1472 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1473 		GSList *iter, *connections;
1474 	
1475 		nm_log_dbg (LOGD_CORE, "creating virtual devices...");
1476 	
1477 		connections = nm_settings_get_connections (priv->settings);
1478 		for (iter = connections; iter; iter = g_slist_next (iter)) {
1479 			NMConnection *connection = iter->data;
1480 			NMSettingConnection *s_con = nm_connection_get_setting_connection (connection);
1481 	
1482 			g_assert (s_con);
1483 			if (connection_needs_virtual_device (connection)) {
1484 				/* We only create a virtual interface if the connection can autoconnect */
1485 				if (nm_setting_connection_get_autoconnect (s_con))
1486 					system_create_virtual_device (self, connection);
1487 			}
1488 		}
1489 		g_slist_free (connections);
1490 	}
1491 	
1492 	static void
1493 	connection_added (NMSettings *settings,
1494 	                  NMSettingsConnection *settings_connection,
1495 	                  NMManager *manager)
1496 	{
1497 		NMConnection *connection = NM_CONNECTION (settings_connection);
1498 	
1499 		if (connection_needs_virtual_device (connection)) {
1500 			NMSettingConnection *s_con = nm_connection_get_setting_connection (connection);
1501 	
1502 			g_assert (s_con);
1503 			if (nm_setting_connection_get_autoconnect (s_con))
1504 				system_create_virtual_device (manager, connection);
1505 		}
1506 	}
1507 	
1508 	static void
1509 	connection_changed (NMSettings *settings,
1510 	                    NMSettingsConnection *connection,
1511 	                    NMManager *manager)
1512 	{
1513 		/* FIXME: Some virtual devices may need to be updated in the future. */
1514 	}
1515 	
1516 	static void
1517 	connection_removed (NMSettings *settings,
1518 	                    NMSettingsConnection *connection,
1519 	                    NMManager *manager)
1520 	{
1521 		/*
1522 		 * Do not delete existing virtual devices to keep connectivity up.
1523 		 * Virtual devices are reused when NetworkManager is restarted.
1524 		 */
1525 	}
1526 	
1527 	static void
1528 	system_unmanaged_devices_changed_cb (NMSettings *settings,
1529 	                                     GParamSpec *pspec,
1530 	                                     gpointer user_data)
1531 	{
1532 		NMManager *self = NM_MANAGER (user_data);
1533 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1534 		const GSList *unmanaged_specs, *iter;
1535 	
1536 		unmanaged_specs = nm_settings_get_unmanaged_specs (priv->settings);
1537 		for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
1538 			NMDevice *device = NM_DEVICE (iter->data);
1539 			gboolean managed;
1540 	
1541 			managed = !nm_device_spec_match_list (device, unmanaged_specs);
1542 			nm_device_set_manager_managed (device,
1543 			                               managed,
1544 			                               managed ? NM_DEVICE_STATE_REASON_NOW_MANAGED :
1545 			                                         NM_DEVICE_STATE_REASON_NOW_UNMANAGED);
1546 		}
1547 	}
1548 	
1549 	static void
1550 	system_hostname_changed_cb (NMSettings *settings,
1551 	                            GParamSpec *pspec,
1552 	                            gpointer user_data)
1553 	{
1554 		NMManager *self = NM_MANAGER (user_data);
1555 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1556 		char *hostname;
1557 	
1558 		hostname = nm_settings_get_hostname (priv->settings);
1559 		if (!hostname && !priv->hostname)
1560 			return;
1561 		if (hostname && priv->hostname && !strcmp (hostname, priv->hostname))
1562 			return;
1563 	
1564 		g_free (priv->hostname);
1565 		priv->hostname = (hostname && strlen (hostname)) ? g_strdup (hostname) : NULL;
1566 		g_object_notify (G_OBJECT (self), NM_MANAGER_HOSTNAME);
1567 	
1568 		g_free (hostname);
1569 	}
1570 	
1571 	/*******************************************************************/
1572 	/* General NMManager stuff                                         */
1573 	/*******************************************************************/
1574 	
1575 	/* Store value into key-file; supported types: boolean, int, string */
1576 	static gboolean
1577 	write_value_to_state_file (const char *filename,
1578 	                           const char *group,
1579 	                           const char *key,
1580 	                           GType value_type,
1581 	                           gpointer value,
1582 	                           GError **error)
1583 	{
1584 		GKeyFile *key_file;
1585 		char *data;
1586 		gsize len = 0;
1587 		gboolean ret = FALSE;
1588 	
1589 		g_return_val_if_fail (filename != NULL, FALSE);
1590 		g_return_val_if_fail (group != NULL, FALSE);
1591 		g_return_val_if_fail (key != NULL, FALSE);
1592 		g_return_val_if_fail (value_type == G_TYPE_BOOLEAN ||
1593 		                      value_type == G_TYPE_INT ||
1594 		                      value_type == G_TYPE_STRING,
1595 		                      FALSE);
1596 	
1597 		key_file = g_key_file_new ();
1598 	
1599 		g_key_file_set_list_separator (key_file, ',');
1600 		g_key_file_load_from_file (key_file, filename, G_KEY_FILE_KEEP_COMMENTS, NULL);
1601 		switch (value_type) {
1602 		case G_TYPE_BOOLEAN:
1603 			g_key_file_set_boolean (key_file, group, key, *((gboolean *) value));
1604 			break;
1605 		case G_TYPE_INT:
1606 			g_key_file_set_integer (key_file, group, key, *((gint *) value));
1607 			break;
1608 		case G_TYPE_STRING:
1609 			g_key_file_set_string (key_file, group, key, *((const gchar **) value));
1610 			break;
1611 		}
1612 	
1613 		data = g_key_file_to_data (key_file, &len, NULL);
1614 		if (data) {
1615 			ret = g_file_set_contents (filename, data, len, error);
1616 			g_free (data);
1617 		}
1618 		g_key_file_free (key_file);
1619 	
1620 		return ret;
1621 	}
1622 	
1623 	static gboolean
1624 	radio_enabled_for_rstate (RadioState *rstate, gboolean check_changeable)
1625 	{
1626 		gboolean enabled;
1627 	
1628 		enabled = rstate->user_enabled && rstate->hw_enabled;
1629 		if (check_changeable) {
1630 			enabled &= rstate->sw_enabled;
1631 			if (rstate->daemon_enabled_func)
1632 				enabled &= rstate->daemon_enabled;
1633 		}
1634 		return enabled;
1635 	}
1636 	
1637 	static gboolean
1638 	radio_enabled_for_type (NMManager *self, RfKillType rtype, gboolean check_changeable)
1639 	{
1640 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1641 	
1642 		return radio_enabled_for_rstate (&priv->radio_states[rtype], check_changeable);
1643 	}
1644 	
1645 	static void
1646 	manager_update_radio_enabled (NMManager *self,
1647 	                              RadioState *rstate,
1648 	                              gboolean enabled)
1649 	{
1650 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1651 		GSList *iter;
1652 	
1653 		/* Do nothing for radio types not yet implemented */
1654 		if (!rstate->prop)
1655 			return;
1656 	
1657 		g_object_notify (G_OBJECT (self), rstate->prop);
1658 	
1659 		/* Don't touch devices if asleep/networking disabled */
1660 		if (manager_sleeping (self))
1661 			return;
1662 	
1663 		/* enable/disable wireless devices as required */
1664 		for (iter = priv->devices; iter; iter = iter->next) {
1665 			NMDevice *device = NM_DEVICE (iter->data);
1666 	
1667 			if (nm_device_get_rfkill_type (device) == rstate->rtype) {
1668 				nm_log_dbg (LOGD_RFKILL, "(%s): setting radio %s",
1669 				            nm_device_get_iface (device),
1670 				            enabled ? "enabled" : "disabled");
1671 				nm_device_set_enabled (device, enabled);
1672 			}
1673 		}
1674 	}
1675 	
1676 	static void
1677 	manager_hidden_ap_found (NMDevice *device,
1678 	                         NMAccessPoint *ap,
1679 	                         gpointer user_data)
1680 	{
1681 		NMManager *manager = NM_MANAGER (user_data);
1682 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
1683 		const struct ether_addr *bssid;
1684 		GSList *iter;
1685 		GSList *connections;
1686 		gboolean done = FALSE;
1687 	
1688 		g_return_if_fail (nm_ap_get_ssid (ap) == NULL);
1689 	
1690 		bssid = nm_ap_get_address (ap);
1691 		g_assert (bssid);
1692 	
1693 		/* Look for this AP's BSSID in the seen-bssids list of a connection,
1694 		 * and if a match is found, copy over the SSID */
1695 		connections = nm_settings_get_connections (priv->settings);
1696 		for (iter = connections; iter && !done; iter = g_slist_next (iter)) {
1697 			NMConnection *connection = NM_CONNECTION (iter->data);
1698 			NMSettingWireless *s_wifi;
1699 	
1700 			s_wifi = nm_connection_get_setting_wireless (connection);
1701 			if (s_wifi) {
1702 				if (nm_settings_connection_has_seen_bssid (NM_SETTINGS_CONNECTION (connection), bssid))
1703 					nm_ap_set_ssid (ap, nm_setting_wireless_get_ssid (s_wifi));
1704 			}
1705 		}
1706 		g_slist_free (connections);
1707 	}
1708 	
1709 	static RfKillState
1710 	nm_manager_get_ipw_rfkill_state (NMManager *self)
1711 	{
1712 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1713 		GSList *iter;
1714 		RfKillState ipw_state = RFKILL_UNBLOCKED;
1715 	
1716 		for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
1717 			NMDevice *candidate = NM_DEVICE (iter->data);
1718 			RfKillState candidate_state;
1719 	
1720 			if (nm_device_get_device_type (candidate) == NM_DEVICE_TYPE_WIFI) {
1721 				candidate_state = nm_device_wifi_get_ipw_rfkill_state (NM_DEVICE_WIFI (candidate));
1722 	
1723 				if (candidate_state > ipw_state)
1724 					ipw_state = candidate_state;
1725 			}
1726 		}
1727 	
1728 		return ipw_state;
1729 	}
1730 	
1731 	static RfKillState
1732 	nm_manager_get_modem_enabled_state (NMManager *self)
1733 	{
1734 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1735 		GSList *iter;
1736 		RfKillState wwan_state = RFKILL_UNBLOCKED;
1737 	
1738 		for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
1739 			NMDevice *candidate = NM_DEVICE (iter->data);
1740 			RfKillState candidate_state = RFKILL_UNBLOCKED;
1741 	
1742 			if (nm_device_get_rfkill_type (candidate) == RFKILL_TYPE_WWAN) {
1743 				if (!nm_device_get_enabled (candidate))
1744 					candidate_state = RFKILL_SOFT_BLOCKED;
1745 	
1746 				if (candidate_state > wwan_state)
1747 					wwan_state = candidate_state;
1748 			}
1749 		}
1750 	
1751 		return wwan_state;
1752 	}
1753 	
1754 	static void
1755 	update_rstate_from_rfkill (RadioState *rstate, RfKillState rfkill)
1756 	{
1757 		if (rfkill == RFKILL_UNBLOCKED) {
1758 			rstate->sw_enabled = TRUE;
1759 			rstate->hw_enabled = TRUE;
1760 		} else if (rfkill == RFKILL_SOFT_BLOCKED) {
1761 			rstate->sw_enabled = FALSE;
1762 			rstate->hw_enabled = TRUE;
1763 		} else if (rfkill == RFKILL_HARD_BLOCKED) {
1764 			rstate->sw_enabled = FALSE;
1765 			rstate->hw_enabled = FALSE;
1766 		}
1767 	}
1768 	
1769 	static void
1770 	manager_rfkill_update_one_type (NMManager *self,
1771 	                                RadioState *rstate,
1772 	                                RfKillType rtype)
1773 	{
1774 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1775 		RfKillState udev_state = RFKILL_UNBLOCKED;
1776 		RfKillState other_state = RFKILL_UNBLOCKED;
1777 		RfKillState composite;
1778 		gboolean old_enabled, new_enabled, old_rfkilled, new_rfkilled;
1779 		gboolean old_hwe, old_daemon_enabled = FALSE;
1780 	
1781 		old_enabled = radio_enabled_for_rstate (rstate, TRUE);
1782 		old_rfkilled = rstate->hw_enabled && rstate->sw_enabled;
1783 		old_hwe = rstate->hw_enabled;
1784 	
1785 		udev_state = nm_rfkill_manager_get_rfkill_state (priv->rfkill_mgr, rtype);
1786 	
1787 		if (rstate->other_enabled_func)
1788 			other_state = rstate->other_enabled_func (self);
1789 	
1790 		/* The composite state is the "worst" of either udev or other states */
1791 		if (udev_state == RFKILL_HARD_BLOCKED || other_state == RFKILL_HARD_BLOCKED)
1792 			composite = RFKILL_HARD_BLOCKED;
1793 		else if (udev_state == RFKILL_SOFT_BLOCKED || other_state == RFKILL_SOFT_BLOCKED)
1794 			composite = RFKILL_SOFT_BLOCKED;
1795 		else
1796 			composite = RFKILL_UNBLOCKED;
1797 	
1798 		update_rstate_from_rfkill (rstate, composite);
1799 	
1800 		/* If the device has a management daemon that can affect enabled state, check that now */
1801 		if (rstate->daemon_enabled_func) {
1802 			old_daemon_enabled = rstate->daemon_enabled;
1803 			rstate->daemon_enabled = (rstate->daemon_enabled_func (self) == RFKILL_UNBLOCKED);
1804 			if (old_daemon_enabled != rstate->daemon_enabled) {
1805 				nm_log_info (LOGD_RFKILL, "%s now %s by management service",
1806 					         rstate->desc,
1807 					         rstate->daemon_enabled ? "enabled" : "disabled");
1808 			}
1809 		}
1810 	
1811 		/* Print out all states affecting device enablement */
1812 		if (rstate->desc) {
1813 			if (rstate->daemon_enabled_func) {
1814 				nm_log_dbg (LOGD_RFKILL, "%s hw-enabled %d sw-enabled %d daemon-enabled %d",
1815 				            rstate->desc, rstate->hw_enabled, rstate->sw_enabled, rstate->daemon_enabled);
1816 			} else {
1817 				nm_log_dbg (LOGD_RFKILL, "%s hw-enabled %d sw-enabled %d",
1818 				            rstate->desc, rstate->hw_enabled, rstate->sw_enabled);
1819 			}
1820 		}
1821 	
1822 		/* Log new killswitch state */
1823 		new_rfkilled = rstate->hw_enabled && rstate->sw_enabled;
1824 		if (old_rfkilled != new_rfkilled) {
1825 			nm_log_info (LOGD_RFKILL, "%s now %s by radio killswitch",
1826 			             rstate->desc,
1827 			             new_rfkilled ? "enabled" : "disabled");
1828 		}
1829 	
1830 		/* Send out property changed signal for HW enabled */
1831 		if (rstate->hw_enabled != old_hwe) {
1832 			if (rstate->hw_prop)
1833 				g_object_notify (G_OBJECT (self), rstate->hw_prop);
1834 		}
1835 	
1836 		/* And finally update the actual device radio state itself; respect the
1837 		 * daemon state here because this is never called from user-triggered
1838 		 * radio changes and we only want to ignore the daemon enabled state when
1839 		 * handling user radio change requests.
1840 		 */
1841 		new_enabled = radio_enabled_for_rstate (rstate, TRUE);
1842 		if (new_enabled != old_enabled)
1843 			manager_update_radio_enabled (self, rstate, new_enabled);
1844 	}
1845 	
1846 	static void
1847 	nm_manager_rfkill_update (NMManager *self, RfKillType rtype)
1848 	{
1849 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1850 		guint i;
1851 	
1852 		if (rtype != RFKILL_TYPE_UNKNOWN)
1853 			manager_rfkill_update_one_type (self, &priv->radio_states[rtype], rtype);
1854 		else {
1855 			/* Otherwise sync all radio types */
1856 			for (i = 0; i < RFKILL_TYPE_MAX; i++)
1857 				manager_rfkill_update_one_type (self, &priv->radio_states[i], i);
1858 		}
1859 	}
1860 	
1861 	static void
1862 	manager_ipw_rfkill_state_changed (NMDeviceWifi *device,
1863 	                                  GParamSpec *pspec,
1864 	                                  gpointer user_data)
1865 	{
1866 		nm_manager_rfkill_update (NM_MANAGER (user_data), RFKILL_TYPE_WLAN);
1867 	}
1868 	
1869 	static void
1870 	manager_modem_enabled_changed (NMDevice *device, gpointer user_data)
1871 	{
1872 		nm_manager_rfkill_update (NM_MANAGER (user_data), RFKILL_TYPE_WWAN);
1873 	}
1874 	
1875 	static void
1876 	device_auth_done_cb (NMAuthChain *chain,
1877 	                     GError *auth_error,
1878 	                     DBusGMethodInvocation *context,
1879 	                     gpointer user_data)
1880 	{
1881 		NMManager *self = NM_MANAGER (user_data);
1882 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1883 		GError *error = NULL;
1884 		NMAuthCallResult result;
1885 		NMDevice *device;
1886 		const char *permission;
1887 		NMDeviceAuthRequestFunc callback;
1888 	
1889 		priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
1890 	
1891 		permission = nm_auth_chain_get_data (chain, "requested-permission");
1892 		g_assert (permission);
1893 		callback = nm_auth_chain_get_data (chain, "callback");
1894 		g_assert (callback);
1895 		device = nm_auth_chain_get_data (chain, "device");
1896 		g_assert (device);
1897 	
1898 		result = nm_auth_chain_get_result (chain, permission);
1899 	
1900 		if (auth_error) {
1901 			/* translate the auth error into a manager permission denied error */
1902 			nm_log_dbg (LOGD_CORE, "%s request failed: %s", permission, auth_error->message);
1903 			error = g_error_new (NM_MANAGER_ERROR,
1904 			                     NM_MANAGER_ERROR_PERMISSION_DENIED,
1905 			                     "%s request failed: %s",
1906 			                     permission, auth_error->message);
1907 		} else if (result != NM_AUTH_CALL_RESULT_YES) {
1908 			nm_log_dbg (LOGD_CORE, "%s request failed: not authorized", permission);
1909 			error = g_error_new (NM_MANAGER_ERROR,
1910 			                     NM_MANAGER_ERROR_PERMISSION_DENIED,
1911 			                     "%s request failed: not authorized",
1912 			                     permission);
1913 		}
1914 	
1915 		g_assert (error || (result == NM_AUTH_CALL_RESULT_YES));
1916 	
1917 		callback (device,
1918 		          context,
1919 		          error,
1920 		          nm_auth_chain_get_data (chain, "user-data"));
1921 	
1922 		g_clear_error (&error);
1923 		nm_auth_chain_unref (chain);
1924 	}
1925 	
1926 	static void
1927 	device_auth_request_cb (NMDevice *device,
1928 	                        DBusGMethodInvocation *context,
1929 	                        const char *permission,
1930 	                        gboolean allow_interaction,
1931 	                        NMDeviceAuthRequestFunc callback,
1932 	                        gpointer user_data,
1933 	                        NMManager *self)
1934 	{
1935 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1936 		GError *error = NULL;
1937 		NMAuthChain *chain;
1938 		const char *error_desc = NULL;
1939 	
1940 		/* Validate the request */
1941 		chain = nm_auth_chain_new (context, device_auth_done_cb, self, &error_desc);
1942 		if (chain) {
1943 			priv->auth_chains = g_slist_append (priv->auth_chains, chain);
1944 	
1945 			nm_auth_chain_set_data (chain, "device", g_object_ref (device), g_object_unref);
1946 			nm_auth_chain_set_data (chain, "requested-permission", g_strdup (permission), g_free);
1947 			nm_auth_chain_set_data (chain, "callback", callback, NULL);
1948 			nm_auth_chain_set_data (chain, "user-data", user_data, NULL);
1949 			nm_auth_chain_add_call (chain, permission, allow_interaction);
1950 		} else {
1951 			error = g_error_new_literal (NM_MANAGER_ERROR,
1952 			                             NM_MANAGER_ERROR_PERMISSION_DENIED,
1953 			                             error_desc);
1954 			callback (device, context, error, user_data);
1955 			g_error_free (error);
1956 		}
1957 	}
1958 	
1959 	/* This should really be moved to gsystem. */
1960 	#define free_slist __attribute__ ((cleanup(local_slist_free)))
1961 	static void
1962 	local_slist_free (void *loc)
1963 	{
1964 		GSList **location = loc;
1965 	
1966 		if (location)
1967 			g_slist_free (*location);
1968 	}
1969 	
1970 	/**
1971 	 * get_connection:
1972 	 * @manager: #NMManager instance
1973 	 * @device: #NMDevice instance
1974 	 *
1975 	 * Returns one of the following:
1976 	 *
1977 	 * 1) An existing #NMSettingsConnection to be assumed.
1978 	 *
1979 	 * 2) A generated #NMConnection to be assumed. You can distinguish this
1980 	 * case using NM_IS_SETTINGS_CONNECTION().
1981 	 *
1982 	 * 3) %NULL when no connection was detected or the @device doesn't support
1983 	 * generating connections.
1984 	 *
1985 	 * Supports both nm-device's match_l2_config() and update_connection().
1986 	 */
1987 	static NMConnection *
1988 	get_connection (NMManager *manager, NMDevice *device)
1989 	{
1990 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
1991 		free_slist GSList *connections = nm_settings_get_connections (priv->settings);
1992 		NMConnection *connection = NULL;
1993 		GSList *iter;
1994 	
1995 		/* We still support the older API to match a NMDevice object to an
1996 		 * existing connection using nm_device_find_assumable_connection().
1997 		 *
1998 		 * When the older API is still available for a particular device
1999 		 * type, we use it. To opt for the newer interface, the NMDevice
2000 		 * subclass must omit the match_l2_config virtual function
2001 		 * implementation.
2002 		 */
2003 		if (NM_DEVICE_GET_CLASS (device)->match_l2_config) {
2004 			NMConnection *candidate = nm_device_find_assumable_connection (device, connections);
2005 	
2006 			if (candidate) {
2007 				nm_log_info (LOGD_DEVICE, "(%s): Found matching connection '%s' (legacy API)",
2008 				            nm_device_get_iface (device),
2009 				            nm_connection_get_id (candidate));
2010 				return candidate;
2011 			}
2012 		}
2013 	
2014 		/* The core of the API is nm_device_generate_connection() function and
2015 		 * update_connection() virtual method and the convenient connection_type
2016 		 * class attribute. Subclasses supporting the new API must have
2017 		 * update_connection() implemented, otherwise nm_device_generate_connection()
2018 		 * returns NULL.
2019 		 */
2020 		connection = nm_device_generate_connection (device);
2021 		if (!connection) {
2022 			nm_log_info (LOGD_DEVICE, "(%s): No existing connection detected.",
2023 			             nm_device_get_iface (device));
2024 			return NULL;
2025 		}
2026 	
2027 		/* Now we need to compare the generated connection to each configured
2028 		 * connection. The comparison function is the heart of the connection
2029 		 * assumption implementation and it must compare the connections very
2030 		 * carefully to sort out various corner cases. Also, the comparison is
2031 		 * not entirely symmetric.
2032 		 *
2033 		 * When no configured connection matches the generated connection, we keep
2034 		 * the generated connection instead.
2035 		 */
2036 		for (iter = connections; iter; iter = iter->next) {
2037 			NMConnection *candidate = NM_CONNECTION (iter->data);
2038 	
2039 			if (nm_connection_compare (connection, candidate, NM_SETTING_COMPARE_FLAG_CANDIDATE)) {
2040 				nm_log_info (LOGD_DEVICE, "(%s): Found matching connection: '%s'",
2041 							 nm_device_get_iface (device),
2042 							 nm_connection_get_id (candidate));
2043 				g_object_unref (connection);
2044 				return candidate;
2045 			}
2046 		}
2047 	
2048 		nm_log_info (LOGD_DEVICE, "(%s): Using generated connection: '%s'",
2049 					 nm_device_get_iface (device),
2050 					 nm_connection_get_id (connection));
2051 		return connection;
2052 	}
2053 	
2054 	static void
2055 	add_device (NMManager *self, NMDevice *device)
2056 	{
2057 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
2058 		const char *iface, *driver, *type_desc;
2059 		char *path;
2060 		static guint32 devcount = 0;
2061 		const GSList *unmanaged_specs;
2062 		NMConnection *connection;
2063 		gboolean enabled = FALSE;
2064 		RfKillType rtype;
2065 		NMDeviceType devtype;
2066 	
2067 		iface = nm_device_get_ip_iface (device);
2068 		g_assert (iface);
2069 	
2070 		devtype = nm_device_get_device_type (device);
2071 	
2072 		/* Ignore the device if we already know about it.  But some modems will
2073 		 * provide pseudo-ethernet devices that NM has already claimed while
2074 		 * ModemManager is still detecting the modem's serial ports, so when the
2075 		 * MM modem object finally shows up it may have the same IP interface as the
2076 		 * ethernet interface we've already detected.  In this case we skip the
2077 		 * check for an existing device with the same IP interface name and kill
2078 		 * the ethernet device later in favor of the modem device.
2079 		 */
2080 		if ((devtype != NM_DEVICE_TYPE_MODEM) && find_device_by_ip_iface (self, iface)) {
2081 			g_object_unref (device);
2082 			return;
2083 		}
2084 	
2085 		nm_device_set_connection_provider (device, NM_CONNECTION_PROVIDER (priv->settings));
2086 	
2087 		priv->devices = g_slist_append (priv->devices, device);
2088 	
2089 		g_signal_connect (device, "state-changed",
2090 						  G_CALLBACK (manager_device_state_changed),
2091 						  self);
2092 	
2093 		g_signal_connect (device, NM_DEVICE_AUTH_REQUEST,
2094 		                  G_CALLBACK (device_auth_request_cb),
2095 		                  self);
2096 	
2097 		if (priv->startup) {
2098 			g_signal_connect (device, "notify::" NM_DEVICE_HAS_PENDING_ACTION,
2099 			                  G_CALLBACK (device_has_pending_action_changed),
2100 			                  self);
2101 		}
2102 	
2103 		if (devtype == NM_DEVICE_TYPE_WIFI) {
2104 			/* Attach to the access-point-added signal so that the manager can fill
2105 			 * non-SSID-broadcasting APs with an SSID.
2106 			 */
2107 			g_signal_connect (device, "hidden-ap-found",
2108 							  G_CALLBACK (manager_hidden_ap_found),
2109 							  self);
2110 	
2111 			/* Hook up rfkill handling for ipw-based cards until they get converted
2112 			 * to use the kernel's rfkill subsystem in 2.6.33.
2113 			 */
2114 			g_signal_connect (device, "notify::" NM_DEVICE_WIFI_IPW_RFKILL_STATE,
2115 			                  G_CALLBACK (manager_ipw_rfkill_state_changed),
2116 			                  self);
2117 		} else if (devtype == NM_DEVICE_TYPE_MODEM) {
2118 			g_signal_connect (device, NM_DEVICE_MODEM_ENABLE_CHANGED,
2119 			                  G_CALLBACK (manager_modem_enabled_changed),
2120 			                  self);
2121 		}
2122 	
2123 		/* Update global rfkill state for this device type with the device's
2124 		 * rfkill state, and then set this device's rfkill state based on the
2125 		 * global state.
2126 		 */
2127 		rtype = nm_device_get_rfkill_type (device);
2128 		if (rtype != RFKILL_TYPE_UNKNOWN) {
2129 			nm_manager_rfkill_update (self, rtype);
2130 			enabled = radio_enabled_for_type (self, rtype, TRUE);
2131 			nm_device_set_enabled (device, enabled);
2132 		}
2133 	
2134 		type_desc = nm_device_get_type_desc (device);
2135 		g_assert (type_desc);
2136 		driver = nm_device_get_driver (device);
2137 		if (!driver)
2138 			driver = "unknown";
2139 		nm_log_info (LOGD_HW, "(%s): new %s device (driver: '%s' ifindex: %d)",
2140 		             iface, type_desc, driver, nm_device_get_ifindex (device));
2141 	
2142 		path = g_strdup_printf ("/org/freedesktop/NetworkManager/Devices/%d", devcount++);
2143 		nm_device_set_path (device, path);
2144 		nm_dbus_manager_register_object (priv->dbus_mgr, path, device);
2145 		nm_log_info (LOGD_CORE, "(%s): exported as %s", iface, path);
2146 		g_free (path);
2147 	
2148 		connection = get_connection (self, device);
2149 	
2150 		/* Start the device if it's supposed to be managed */
2151 		unmanaged_specs = nm_settings_get_unmanaged_specs (priv->settings);
2152 		if (   !manager_sleeping (self)
2153 		    && !nm_device_spec_match_list (device, unmanaged_specs)) {
2154 			nm_device_set_manager_managed (device,
2155 			                               TRUE,
2156 			                               connection ? NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED :
2157 			                                          NM_DEVICE_STATE_REASON_NOW_MANAGED);
2158 		}
2159 	
2160 		nm_settings_device_added (priv->settings, device);
2161 		g_signal_emit (self, signals[DEVICE_ADDED], 0, device);
2162 	
2163 		/* New devices might be master interfaces for virtual interfaces; so we may
2164 		 * need to create new virtual interfaces now.
2165 		 */
2166 		system_create_virtual_devices (self);
2167 	
2168 		/* If the device has a connection it can assume, do that now */
2169 		if (connection && nm_device_can_activate (device, connection)) {
2170 			NMActiveConnection *ac;
2171 			GError *error = NULL;
2172 	
2173 			nm_log_dbg (LOGD_DEVICE, "(%s): will attempt to assume connection",
2174 			            nm_device_get_iface (device));
2175 	
2176 			ac = internal_activate_device (self, device, connection, NULL, FALSE, 0, NULL, TRUE, NULL, &error);
2177 			if (ac)
2178 				active_connection_add (self, ac);
2179 			else {
2180 				nm_log_warn (LOGD_DEVICE, "assumed connection %s failed to activate: (%d) %s",
2181 				             nm_connection_get_path (connection),
2182 				             error ? error->code : -1,
2183 				             error && error->message ? error->message : "(unknown)");
2184 				g_error_free (error);
2185 			}
2186 		}
2187 	}
2188 	
2189 	static void
2190 	bluez_manager_bdaddr_added_cb (NMBluezManager *bluez_mgr,
2191 	                               NMBluezDevice *bt_device,
2192 	                               const char *bdaddr,
2193 	                               const char *name,
2194 	                               const char *object_path,
2195 	                               guint32 capabilities,
2196 	                               NMManager *manager)
2197 	{
2198 		NMDevice *device;
2199 		gboolean has_dun = (capabilities & NM_BT_CAPABILITY_DUN);
2200 		gboolean has_nap = (capabilities & NM_BT_CAPABILITY_NAP);
2201 	
2202 		g_return_if_fail (bdaddr != NULL);
2203 		g_return_if_fail (name != NULL);
2204 		g_return_if_fail (object_path != NULL);
2205 		g_return_if_fail (capabilities != NM_BT_CAPABILITY_NONE);
2206 		g_return_if_fail (NM_IS_BLUEZ_DEVICE (bt_device));
2207 	
2208 		/* Make sure the device is not already in the device list */
2209 		if (nm_manager_get_device_by_udi (manager, object_path))
2210 			return;
2211 	
2212 		device = nm_device_bt_new (bt_device, object_path, bdaddr, name, capabilities);
2213 		if (device) {
2214 			nm_log_info (LOGD_HW, "BT device %s (%s) added (%s%s%s)",
2215 			             name,
2216 			             bdaddr,
2217 			             has_dun ? "DUN" : "",
2218 			             has_dun && has_nap ? " " : "",
2219 			             has_nap ? "NAP" : "");
2220 	
2221 			add_device (manager, device);
2222 		}
2223 	}
2224 	
2225 	static void
2226 	bluez_manager_bdaddr_removed_cb (NMBluezManager *bluez_mgr,
2227 	                                 const char *bdaddr,
2228 	                                 const char *object_path,
2229 	                                 gpointer user_data)
2230 	{
2231 		NMManager *self = NM_MANAGER (user_data);
2232 		NMDevice *device;
2233 	
2234 		g_return_if_fail (bdaddr != NULL);
2235 		g_return_if_fail (object_path != NULL);
2236 	
2237 		device = nm_manager_get_device_by_udi (self, object_path);
2238 		if (device) {
2239 			nm_log_info (LOGD_HW, "BT device %s removed", bdaddr);
2240 			remove_device (self, device, FALSE);
2241 		}
2242 	}
2243 	
2244 	static NMDevice *
2245 	find_device_by_ip_iface (NMManager *self, const gchar *iface)
2246 	{
2247 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
2248 		GSList *iter;
2249 	
2250 		for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
2251 			NMDevice *candidate = iter->data;
2252 	
2253 			if (g_strcmp0 (nm_device_get_ip_iface (candidate), iface) == 0)
2254 				return candidate;
2255 		}
2256 		return NULL;
2257 	}
2258 	
2259 	static NMDevice *
2260 	find_device_by_iface (NMManager *self, const gchar *iface)
2261 	{
2262 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
2263 		GSList *iter;
2264 	
2265 		for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
2266 			NMDevice *candidate = iter->data;
2267 	
2268 			if (g_strcmp0 (nm_device_get_iface (candidate), iface) == 0)
2269 				return candidate;
2270 		}
2271 		return NULL;
2272 	}
2273 	
2274 	static NMDevice *
2275 	find_device_by_ifindex (NMManager *self, guint32 ifindex)
2276 	{
2277 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
2278 		GSList *iter;
2279 	
2280 		for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
2281 			NMDevice *candidate = NM_DEVICE (iter->data);
2282 	
2283 			if (ifindex == nm_device_get_ifindex (candidate))
2284 				return candidate;
2285 		}
2286 		return NULL;
2287 	}
2288 	
2289 	#define PLUGIN_PREFIX "libnm-device-plugin-"
2290 	
2291 	typedef struct {
2292 		NMDeviceType t;
2293 		guint priority;
2294 		NMDeviceFactoryCreateFunc create_func;
2295 	} PluginInfo;
2296 	
2297 	static gint
2298 	plugin_sort (PluginInfo *a, PluginInfo *b)
2299 	{
2300 		/* Higher priority means sort earlier in the list (ie, return -1) */
2301 		if (a->priority > b->priority)
2302 			return -1;
2303 		else if (a->priority < b->priority)
2304 			return 1;
2305 		return 0;
2306 	}
2307 	
2308 	static void
2309 	load_device_factories (NMManager *self)
2310 	{
2311 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
2312 		GDir *dir;
2313 		GError *error = NULL;
2314 		const char *item;
2315 		char *path;
2316 		GSList *list = NULL, *iter;
2317 	
2318 		dir = g_dir_open (NMPLUGINDIR, 0, &error);
2319 		if (!dir) {
2320 			nm_log_warn (LOGD_HW, "Failed to open plugin directory %s: %s",
2321 			             NMPLUGINDIR,
2322 			             (error && error->message) ? error->message : "(unknown)");
2323 			g_clear_error (&error);
2324 			return;
2325 		}
2326 	
2327 		while ((item = g_dir_read_name (dir))) {
2328 			GModule *plugin;
2329 			NMDeviceFactoryCreateFunc create_func;
2330 			NMDeviceFactoryPriorityFunc priority_func;
2331 			NMDeviceFactoryTypeFunc type_func;
2332 			PluginInfo *info = NULL;
2333 			NMDeviceType plugin_type;
2334 	
2335 			if (!g_str_has_prefix (item, PLUGIN_PREFIX))
2336 				continue;
2337 	
2338 			path = g_module_build_path (NMPLUGINDIR, item);
2339 			g_assert (path);
2340 			plugin = g_module_open (path, G_MODULE_BIND_LOCAL);
2341 			g_free (path);
2342 	
2343 			if (!plugin) {
2344 				nm_log_warn (LOGD_HW, "(%s): failed to load plugin: %s", item, g_module_error ());
2345 				continue;
2346 			}
2347 	
2348 			if (!g_module_symbol (plugin, "nm_device_factory_get_type", (gpointer) (&type_func))) {
2349 				nm_log_warn (LOGD_HW, "(%s): failed to find device factory: %s", item, g_module_error ());
2350 				g_module_close (plugin);
2351 				continue;
2352 			}
2353 	
2354 			/* Make sure we don't double-load plugins */
2355 			plugin_type = type_func ();
2356 			for (iter = list; iter; iter = g_slist_next (iter)) {
2357 				PluginInfo *candidate = iter->data;
2358 	
2359 				if (plugin_type == candidate->t) {
2360 					info = candidate;
2361 					break;
2362 				}
2363 			}
2364 			if (info) {
2365 				g_module_close (plugin);
2366 				continue;
2367 			}
2368 	
2369 			if (!g_module_symbol (plugin, "nm_device_factory_create_device", (gpointer) (&create_func))) {
2370 				nm_log_warn (LOGD_HW, "(%s): failed to find device creator: %s", item, g_module_error ());
2371 				g_module_close (plugin);
2372 				continue;
2373 			}
2374 	
2375 			info = g_malloc0 (sizeof (*info));
2376 			info->create_func = create_func;
2377 			info->t = plugin_type;
2378 	
2379 			/* Grab priority; higher number equals higher priority */
2380 			if (g_module_symbol (plugin, "nm_device_factory_get_priority", (gpointer) (&priority_func)))
2381 				info->priority = priority_func ();
2382 			else {
2383 				nm_log_dbg (LOGD_HW, "(%s): failed to find device factory priority func: %s",
2384 				            item, g_module_error ());
2385 			}
2386 	
2387 			g_module_make_resident (plugin);
2388 			list = g_slist_insert_sorted (list, info, (GCompareFunc) plugin_sort);
2389 	
2390 			nm_log_info (LOGD_HW, "Loaded device factory: %s", g_module_name (plugin));
2391 		};
2392 		g_dir_close (dir);
2393 	
2394 		/* Ditch the priority info and copy the factory functions to our private data */
2395 		for (iter = list; iter; iter = g_slist_next (iter)) {
2396 			PluginInfo *info = iter->data;
2397 	
2398 			priv->factories = g_slist_append (priv->factories, info->create_func);
2399 			g_free (info);
2400 		}
2401 		g_slist_free (list);
2402 	}
2403 	
2404 	static void
2405 	platform_link_added_cb (NMPlatform *platform,
2406 	                        int ifindex,
2407 	                        NMPlatformLink *plink,
2408 	                        NMPlatformReason reason,
2409 	                        gpointer user_data)
2410 	{
2411 		NMManager *self = NM_MANAGER (user_data);
2412 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
2413 		NMDevice *device = NULL;
2414 		GSList *iter;
2415 		GError *error = NULL;
2416 	
2417 		g_return_if_fail (ifindex > 0);
2418 	
2419 		if (find_device_by_ifindex (self, ifindex))
2420 			return;
2421 	
2422 		/* Try registered device factories */
2423 		for (iter = priv->factories; iter; iter = g_slist_next (iter)) {
2424 			NMDeviceFactoryCreateFunc create_func = iter->data;
2425 	
2426 			g_clear_error (&error);
2427 			device = (NMDevice *) create_func (plink, &error);
2428 			if (device && NM_IS_DEVICE (device)) {
2429 				g_assert_no_error (error);
2430 				break;  /* success! */
2431 			}
2432 	
2433 			if (error) {
2434 				nm_log_warn (LOGD_HW, "%s: factory failed to create device: (%d) %s",
2435 				             plink->udi,
2436 				             error ? error->code : -1,
2437 				             error ? error->message : "(unknown)");
2438 				g_clear_error (&error);
2439 				return;
2440 			}
2441 		}
2442 	
2443 		if (device == NULL) {
2444 			int parent_ifindex = -1;
2445 			NMDevice *parent;
2446 	
2447 			switch (plink->type) {
2448 			case NM_LINK_TYPE_ETHERNET:
2449 				device = nm_device_ethernet_new (plink);
2450 				break;
2451 			case NM_LINK_TYPE_INFINIBAND:
2452 				device = nm_device_infiniband_new (plink);
2453 				break;
2454 			case NM_LINK_TYPE_OLPC_MESH:
2455 				device = nm_device_olpc_mesh_new (plink);
2456 				break;
2457 			case NM_LINK_TYPE_WIFI:
2458 				device = nm_device_wifi_new (plink);
2459 				break;
2460 			case NM_LINK_TYPE_BOND:
2461 				device = nm_device_bond_new (plink);
2462 				break;
2463 			case NM_LINK_TYPE_TEAM:
2464 				device = nm_device_team_new (plink);
2465 				break;
2466 			case NM_LINK_TYPE_BRIDGE:
2467 				/* FIXME: always create device when we handle bridges non-destructively */
2468 				if (bridge_created_by_nm (self, plink->name))
2469 					device = nm_device_bridge_new (plink);
2470 				else
2471 					nm_log_info (LOGD_BRIDGE, "(%s): ignoring bridge not created by NetworkManager", plink->name);
2472 				break;
2473 			case NM_LINK_TYPE_VLAN:
2474 				/* Have to find the parent device */
(17) Event example_checked: Example2: "nm_platform_vlan_get_info(ifindex, &parent_ifindex, NULL)" has its value checked in "nm_platform_vlan_get_info(ifindex, &parent_ifindex, NULL)".
Also see events: [check_return][example_checked][example_checked][example_checked][example_checked][unchecked_value]
2475 				if (nm_platform_vlan_get_info (ifindex, &parent_ifindex, NULL)) {
2476 					parent = find_device_by_ifindex (self, parent_ifindex);
2477 					if (parent)
2478 						device = nm_device_vlan_new (plink, parent);
2479 					else {
2480 						/* If udev signaled the VLAN interface before it signaled
2481 						 * the VLAN's parent at startup we may not know about the
2482 						 * parent device yet.  But we'll find it on the second pass
2483 						 * from nm_manager_start().
2484 						 */
2485 						nm_log_dbg (LOGD_HW, "(%s): VLAN parent interface unknown", plink->name);
2486 					}
2487 				} else
2488 					nm_log_err (LOGD_HW, "(%s): failed to get VLAN parent ifindex", plink->name);
2489 				break;
2490 			case NM_LINK_TYPE_VETH:
2491 				device = nm_device_veth_new (plink);
2492 				break;
2493 			case NM_LINK_TYPE_TUN:
2494 			case NM_LINK_TYPE_TAP:
2495 				device = nm_device_tun_new (plink);
2496 				break;
2497 			case NM_LINK_TYPE_MACVLAN:
2498 			case NM_LINK_TYPE_MACVTAP:
2499 				device = nm_device_macvlan_new (plink);
2500 				break;
2501 			case NM_LINK_TYPE_GRE:
2502 			case NM_LINK_TYPE_GRETAP:
2503 				device = nm_device_gre_new (plink);
2504 				break;
2505 	
2506 			case NM_LINK_TYPE_WWAN_ETHERNET:
2507 				/* WWAN pseudo-ethernet interfaces are handled automatically by
2508 				 * their NMDeviceModem and don't get a separate NMDevice object.
2509 				 */
2510 				break;
2511 	
2512 			case NM_LINK_TYPE_WIMAX:
2513 				/* If the WiMAX plugin is not installed, we can't control the
2514 				 * interface, so ignore it.
2515 				 */
2516 				break;
2517 	
2518 			default:
2519 				device = nm_device_generic_new (plink);
2520 				break;
2521 			}
2522 		}
2523 	
2524 		if (device)
2525 			add_device (self, device);
2526 	}
2527 	
2528 	static void
2529 	platform_link_removed_cb (NMPlatform *platform,
2530 	                          int ifindex,
2531 	                          NMPlatformLink *plink,
2532 	                          NMPlatformReason reason,
2533 	                          gpointer user_data)
2534 	{
2535 		NMManager *self = NM_MANAGER (user_data);
2536 		NMDevice *device;
2537 	
2538 		device = find_device_by_ifindex (self, ifindex);
2539 		if (device)
2540 			remove_device (self, device, FALSE);
2541 	}
2542 	
2543 	static void
2544 	atm_device_added_cb (NMAtmManager *atm_mgr,
2545 	                     const char *iface,
2546 	                     const char *sysfs_path,
2547 	                     const char *driver,
2548 	                     gpointer user_data)
2549 	{
2550 		NMManager *self = NM_MANAGER (user_data);
2551 		NMDevice *device;
2552 	
2553 		g_return_if_fail (iface != NULL);
2554 		g_return_if_fail (sysfs_path != NULL);
2555 	
2556 		device = find_device_by_iface (self, iface);
2557 		if (device)
2558 			return;
2559 	
2560 		device = nm_device_adsl_new (sysfs_path, iface, driver);
2561 		if (device)
2562 			add_device (self, device);
2563 	}
2564 	
2565 	static void
2566 	atm_device_removed_cb (NMAtmManager *manager,
2567 	                       const char *iface,
2568 	                       gpointer user_data)
2569 	{
2570 		NMManager *self = NM_MANAGER (user_data);
2571 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
2572 		NMDevice *device = NULL;
2573 		GSList *iter;
2574 	
2575 		for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
2576 			if (g_strcmp0 (nm_device_get_iface (NM_DEVICE (iter->data)), iface) == 0) {
2577 				device = iter->data;
2578 				break;
2579 			}
2580 		}
2581 	
2582 		if (device)
2583 			remove_device (self, device, FALSE);
2584 	}
2585 	
2586 	static void
2587 	rfkill_manager_rfkill_changed_cb (NMRfkillManager *rfkill_mgr,
2588 	                                  RfKillType rtype,
2589 	                                  RfKillState udev_state,
2590 	                                  gpointer user_data)
2591 	{
2592 		nm_manager_rfkill_update (NM_MANAGER (user_data), rtype);
2593 	}
2594 	
2595 	GSList *
2596 	nm_manager_get_devices (NMManager *manager)
2597 	{
2598 		g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
2599 	
2600 		return NM_MANAGER_GET_PRIVATE (manager)->devices;
2601 	}
2602 	
2603 	static gboolean
2604 	impl_manager_get_devices (NMManager *manager, GPtrArray **devices, GError **err)
2605 	{
2606 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
2607 		GSList *iter;
2608 	
2609 		*devices = g_ptr_array_sized_new (g_slist_length (priv->devices));
2610 	
2611 		for (iter = priv->devices; iter; iter = iter->next)
2612 			g_ptr_array_add (*devices, g_strdup (nm_device_get_path (NM_DEVICE (iter->data))));
2613 	
2614 		return TRUE;
2615 	}
2616 	
2617 	static gboolean
2618 	impl_manager_get_device_by_ip_iface (NMManager *self,
2619 	                                     const char *iface,
2620 	                                     char **out_object_path,
2621 	                                     GError **error)
2622 	{
2623 		NMDevice *device;
2624 		const char *path = NULL;
2625 	
2626 		device = find_device_by_ip_iface (self, iface);
2627 		if (device) {
2628 			path = nm_device_get_path (device);
2629 			if (path)
2630 				*out_object_path = g_strdup (path);
2631 		}
2632 	
2633 		if (path == NULL) {
2634 			g_set_error_literal (error,
2635 			                     NM_MANAGER_ERROR,
2636 			                     NM_MANAGER_ERROR_UNKNOWN_DEVICE,
2637 			                     "No device found for the requested iface.");
2638 		}
2639 	
2640 		return path ? TRUE : FALSE;
2641 	}
2642 	
2643 	static NMActiveConnection *
2644 	internal_activate_device (NMManager *manager,
2645 	                          NMDevice *device,
2646 	                          NMConnection *connection,
2647 	                          const char *specific_object,
2648 	                          gboolean user_requested,
2649 	                          gulong sender_uid,
2650 	                          const char *dbus_sender,
2651 	                          gboolean assumed,
2652 	                          NMActiveConnection *master,
2653 	                          GError **error)
2654 	{
2655 		NMActRequest *req;
2656 		NMDevice *master_device = NULL;
2657 	
2658 		g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
2659 		g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
2660 		g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
2661 	
2662 		/* Ensure the requested connection is compatible with the device */
2663 		if (!nm_device_check_connection_compatible (device, connection, error))
2664 			return NULL;
2665 	
2666 		/* Tear down any existing connection */
2667 		if (nm_device_get_act_request (device)) {
2668 			nm_log_info (LOGD_DEVICE, "(%s): disconnecting for new activation request.",
2669 			             nm_device_get_iface (device));
2670 			nm_device_state_changed (device,
2671 			                         NM_DEVICE_STATE_DISCONNECTED,
2672 			                         NM_DEVICE_STATE_REASON_NONE);
2673 		}
2674 	
2675 		if (master)
2676 			master_device = nm_active_connection_get_device (master);
2677 	
2678 		req = nm_act_request_new (connection,
2679 		                          specific_object,
2680 		                          user_requested,
2681 		                          sender_uid,
2682 		                          dbus_sender,
2683 		                          device,
2684 		                          master_device);
2685 		g_assert (req);
2686 		nm_device_activate (device, req);
2687 	
2688 		return NM_ACTIVE_CONNECTION (req);
2689 	}
2690 	
2691 	/**
2692 	 * find_master:
2693 	 * @self: #NMManager object
2694 	 * @connection: the #NMConnection to find the master connection and device for
2695 	 * @device: the #NMDevice, if any, which will activate @connection
2696 	 * @out_master_connection: on success, the master connection of @connection if
2697 	 *   that master connection was found
2698 	 * @out_master_device: on success, the master device of @connection if that
2699 	 *   master device was found
2700 	 *
2701 	 * Given an #NMConnection, attempts to find its master connection and/or its
2702 	 * master device.  This function may return a master connection, a master device,
2703 	 * or both.  If only a connection is returned, that master connection is not
2704 	 * currently active on any device.  If only a device is returned, that device
2705 	 * is not currently activated with any connection.  If both are returned, then
2706 	 * the device is currently activated or activating with the returned master
2707 	 * connection.
2708 	 *
2709 	 * Returns: %TRUE if the master device and/or connection could be found or if
2710 	 *  the connection did not require a master, %FALSE otherwise
2711 	 **/
2712 	static gboolean
2713 	find_master (NMManager *self,
2714 	             NMConnection *connection,
2715 	             NMDevice *device,
2716 	             NMConnection **out_master_connection,
2717 	             NMDevice **out_master_device)
2718 	{
2719 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
2720 		NMSettingConnection *s_con;
2721 		const char *master;
2722 		NMDevice *master_device = NULL;
2723 		NMConnection *master_connection = NULL;
2724 		GSList *iter, *connections = NULL;
2725 	
2726 		s_con = nm_connection_get_setting_connection (connection);
2727 		g_assert (s_con);
2728 		master = nm_setting_connection_get_master (s_con);
2729 	
2730 		if (master == NULL)
2731 			return TRUE;  /* success, but no master */
2732 	
2733 		/* Try as an interface name first */
2734 		master_device = find_device_by_ip_iface (self, master);
2735 		if (master_device) {
2736 			/* A device obviously can't be its own master */
2737 			if (master_device == device)
2738 				return FALSE;
2739 		} else {
2740 			/* Try master as a connection UUID */
2741 			master_connection = (NMConnection *) nm_settings_get_connection_by_uuid (priv->settings, master);
2742 			if (master_connection) {
2743 				/* Check if the master connection is activated on some device already */
2744 				for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
2745 					NMDevice *candidate = NM_DEVICE (iter->data);
2746 	
2747 					if (candidate == device)
2748 						continue;
2749 	
2750 					if (nm_device_get_connection (candidate) == master_connection) {
2751 						master_device = candidate;
2752 						break;
2753 					}
2754 				}
2755 			} else {
2756 				/* Might be a virtual interface that hasn't been created yet, so
2757 				 * look through the interface names of connections that require
2758 				 * virtual interfaces and see if one of their virtual interface
2759 				 * names matches the master.
2760 				 */
2761 				connections = nm_settings_get_connections (priv->settings);
2762 				for (iter = connections; iter && !master_connection; iter = g_slist_next (iter)) {
2763 					NMConnection *candidate = iter->data;
2764 					char *vname;
2765 	
2766 					if (connection_needs_virtual_device (candidate)) {
2767 						vname = get_virtual_iface_name (self, candidate, NULL);
2768 						if (g_strcmp0 (master, vname) == 0)
2769 							master_connection = candidate;
2770 						g_free (vname);
2771 					}
2772 				}
2773 				g_slist_free (connections);
2774 			}
2775 		}
2776 	
2777 		if (out_master_connection)
2778 			*out_master_connection = master_connection;
2779 		if (out_master_device)
2780 			*out_master_device = master_device;
2781 	
2782 	    return master_device || master_connection;
2783 	}
2784 	
2785 	static gboolean
2786 	is_compatible_with_slave (NMConnection *master, NMConnection *slave)
2787 	{
2788 		NMSettingConnection *s_con;
2789 	
2790 		g_return_val_if_fail (master, FALSE);
2791 		g_return_val_if_fail (slave, FALSE);
2792 	
2793 		s_con = nm_connection_get_setting_connection (slave);
2794 		g_assert (s_con);
2795 	
2796 		return nm_connection_is_type (master, nm_setting_connection_get_slave_type (s_con));
2797 	}
2798 	
2799 	/**
2800 	 * ensure_master_active_connection:
2801 	 *
2802 	 * @self: the #NMManager
2803 	 * @dbus_sender: if the request was initiated by a user via D-Bus, the
2804 	 *   dbus sender name of the client that requested the activation; for auto
2805 	 *   activated connections use %NULL
2806 	 * @connection: the connection that should depend on @master_connection
2807 	 * @device: the #NMDevice, if any, which will activate @connection
2808 	 * @master_connection: the master connection
2809 	 * @master_device: the master device
2810 	 * @error: the error, if an error occurred
2811 	 *
2812 	 * Determines whether a given #NMConnection depends on another connection to
2813 	 * be activated, and if so, finds that master connection or creates it.
2814 	 *
2815 	 * Returns: the master #NMActiveConnection that the caller should depend on, or
2816 	 * %NULL if an error occurred
2817 	 */
2818 	static NMActiveConnection *
2819 	ensure_master_active_connection (NMManager *self,
2820 	                                 const char *dbus_sender,
2821 	                                 NMConnection *connection,
2822 	                                 NMDevice *device,
2823 	                                 NMConnection *master_connection,
2824 	                                 NMDevice *master_device,
2825 	                                 GError **error)
2826 	{
2827 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
2828 		NMActiveConnection *master_ac = NULL;
2829 		NMDeviceState master_state;
2830 		GSList *iter;
2831 	
2832 		g_assert (connection);
2833 		g_assert (master_connection || master_device);
2834 	
2835 		/* If the master device isn't activated then we need to activate it using
2836 		 * compatible connection.  If it's already activating we can just proceed.
2837 		 */
2838 		if (master_device) {
2839 			/* If we're passed a connection and a device, we require that connection
2840 			 * be already activated on the device, eg returned from find_master().
2841 			 */
2842 			if (master_connection)
2843 				g_assert (nm_device_get_connection (master_device) == master_connection);
2844 	
2845 			master_state = nm_device_get_state (master_device);
2846 			if (   (master_state == NM_DEVICE_STATE_ACTIVATED)
2847 			    || nm_device_is_activating (master_device)) {
2848 				/* Device already using master_connection */
2849 				return NM_ACTIVE_CONNECTION (nm_device_get_act_request (master_device));
2850 			}
2851 	
2852 			/* If the device is disconnected, find a compabile connection and
2853 			 * activate it on the device.
2854 			 */
2855 			if (master_state == NM_DEVICE_STATE_DISCONNECTED) {
2856 				GSList *connections;
2857 	
2858 				g_assert (master_connection == NULL);
2859 	
2860 				/* Find a compatible connection and activate this device using it */
2861 				connections = nm_settings_get_connections (priv->settings);
2862 				for (iter = connections; iter; iter = g_slist_next (iter)) {
2863 					NMConnection *candidate = NM_CONNECTION (iter->data);
2864 	
2865 					/* Ensure eg bond/team slave and the candidate master is a
2866 					 * bond/team master
2867 					 */
2868 					if (!is_compatible_with_slave (candidate, connection))
2869 						continue;
2870 	
2871 					if (nm_device_check_connection_compatible (master_device, candidate, NULL)) {
2872 						master_ac = nm_manager_activate_connection (self,
2873 						                                            candidate,
2874 						                                            NULL,
2875 						                                            nm_device_get_path (master_device),
2876 						                                            dbus_sender,
2877 						                                            error);
2878 						if (!master_ac)
2879 							g_prefix_error (error, "%s", "Master device activation failed: ");
2880 						g_slist_free (connections);
2881 						return master_ac;
2882 					}
2883 				}
2884 				g_slist_free (connections);
2885 	
2886 				g_set_error (error,
2887 				             NM_MANAGER_ERROR,
2888 				             NM_MANAGER_ERROR_UNKNOWN_CONNECTION,
2889 				             "No compatible connection found for master device %s.",
2890 				             nm_device_get_iface (master_device));
2891 				return NULL;
2892 			}
2893 	
2894 			/* Otherwise, the device is unmanaged, unavailable, or disconnecting */
2895 			g_set_error (error,
2896 			             NM_MANAGER_ERROR,
2897 			             NM_MANAGER_ERROR_UNMANAGED_DEVICE,
2898 			             "Master device %s unmanaged or not available for activation",
2899 			             nm_device_get_iface (master_device));
2900 		} else if (master_connection) {
2901 			gboolean found_device = FALSE;
2902 	
2903 			/* Find a compatible device and activate it using this connection */
2904 			for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
2905 				NMDevice *candidate = NM_DEVICE (iter->data);
2906 	
2907 				if (candidate == device) {
2908 					/* A device obviously can't be its own master */
2909 					continue;
2910 				}
2911 	
2912 				if (!nm_device_check_connection_compatible (candidate, master_connection, NULL))
2913 					continue;
2914 	
2915 				found_device = TRUE;
2916 				master_state = nm_device_get_state (candidate);
2917 				if (master_state != NM_DEVICE_STATE_DISCONNECTED)
2918 					continue;
2919 	
2920 				master_ac = nm_manager_activate_connection (self,
2921 				                                            master_connection,
2922 				                                            NULL,
2923 				                                            nm_device_get_path (candidate),
2924 				                                            dbus_sender,
2925 				                                            error);
2926 				if (!master_ac)
2927 					g_prefix_error (error, "%s", "Master device activation failed: ");
2928 				return master_ac;
2929 			}
2930 	
2931 			/* Device described by master_connection may be a virtual one that's
2932 			 * not created yet.
2933 			 */
2934 			if (!found_device && connection_needs_virtual_device (master_connection)) {
2935 				master_ac = nm_manager_activate_connection (self,
2936 				                                            master_connection,
2937 				                                            NULL,
2938 				                                            NULL,
2939 				                                            dbus_sender,
2940 				                                            error);
2941 				if (!master_ac)
2942 					g_prefix_error (error, "%s", "Master device activation failed: ");
2943 				return master_ac;
2944 			}
2945 	
2946 			g_set_error (error,
2947 			             NM_MANAGER_ERROR,
2948 			             NM_MANAGER_ERROR_UNKNOWN_DEVICE,
2949 			             "No compatible disconnected device found for master connection %s.",
2950 			             nm_connection_get_uuid (master_connection));
2951 		} else
2952 			g_assert_not_reached ();
2953 	
2954 		return NULL;
2955 	}
2956 	
2957 	static NMActiveConnection *
2958 	activate_vpn_connection (NMManager *self,
2959 	                         NMConnection *connection,
2960 	                         const char *specific_object,
2961 	                         gulong sender_uid,
2962 	                         GError **error)
2963 	{
2964 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
2965 		NMActiveConnection *parent = NULL;
2966 		NMDevice *device = NULL;
2967 		GSList *iter;
2968 	
2969 		if (specific_object) {
2970 			/* Find the specifc connection the client requested we use */
2971 			parent = active_connection_get_by_path (self, specific_object);
2972 			if (!parent) {
2973 				g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE,
2974 				                     "Base connection for VPN connection not active.");
2975 				return NULL;
2976 			}
2977 		} else {
2978 			for (iter = priv->active_connections; iter; iter = g_slist_next (iter)) {
2979 				NMActiveConnection *candidate = iter->data;
2980 	
2981 				if (nm_active_connection_get_default (candidate)) {
2982 					parent = candidate;
2983 					break;
2984 				}
2985 			}
2986 		}
2987 	
2988 		if (!parent) {
2989 			g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_CONNECTION,
2990 			                     "Could not find source connection.");
2991 			return NULL;
2992 		}
2993 	
2994 		device = nm_active_connection_get_device (parent);
2995 		if (!device) {
2996 			g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE,
2997 			                     "Source connection had no active device.");
2998 			return NULL;
2999 		}
3000 	
3001 		return nm_vpn_manager_activate_connection (priv->vpn_manager,
3002 		                                           connection,
3003 		                                           device,
3004 		                                           nm_active_connection_get_path (parent),
3005 		                                           TRUE,
3006 		                                           sender_uid,
3007 		                                           error);
3008 	}
3009 	
3010 	NMActiveConnection *
3011 	nm_manager_activate_connection (NMManager *manager,
3012 	                                NMConnection *connection,
3013 	                                const char *specific_object,
3014 	                                const char *device_path,
3015 	                                const char *dbus_sender,
3016 	                                GError **error)
3017 	{
3018 		NMManagerPrivate *priv;
3019 		NMDevice *device = NULL;
3020 		gulong sender_uid = G_MAXULONG;
3021 		char *iface;
3022 		NMDevice *master_device = NULL;
3023 		NMConnection *master_connection = NULL;
3024 		NMActiveConnection *master_ac = NULL, *ac = NULL;
3025 		gboolean matched;
3026 	
3027 		g_return_val_if_fail (manager != NULL, NULL);
3028 		g_return_val_if_fail (connection != NULL, NULL);
3029 		g_return_val_if_fail (error != NULL, NULL);
3030 		g_return_val_if_fail (*error == NULL, NULL);
3031 	
3032 		priv = NM_MANAGER_GET_PRIVATE (manager);
3033 	
3034 		/* Get the UID of the user that originated the request, if any */
3035 		if (dbus_sender) {
3036 			if (!nm_dbus_manager_get_unix_user (priv->dbus_mgr, dbus_sender, &sender_uid)) {
3037 				g_set_error_literal (error,
3038 				                     NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED,
3039 				                     "Failed to get unix user for dbus sender");
3040 				return NULL;
3041 			}
3042 		} else {
3043 			/* No sender means an internal/automatic activation request */
3044 			sender_uid = 0;
3045 		}
3046 	
3047 		/* VPN ? */
3048 		if (nm_connection_is_type (connection, NM_SETTING_VPN_SETTING_NAME)) {
3049 			ac = activate_vpn_connection (manager, connection, specific_object, sender_uid, error);
3050 			goto activated;
3051 		}
3052 	
3053 		/* Device-based connection */
3054 		if (device_path) {
3055 			device = nm_manager_get_device_by_path (manager, device_path);
3056 			if (!device) {
3057 				g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE,
3058 				                     "Device not found");
3059 				return NULL;
3060 			}
3061 	
3062 			/* If it's a virtual interface make sure the device given by the
3063 			 * path matches the connection's interface details.
3064 			 */
3065 			if (connection_needs_virtual_device (connection)) {
3066 				iface = get_virtual_iface_name (manager, connection, NULL);
3067 				if (!iface) {
3068 					g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE,
3069 					                     "Failed to determine connection's virtual interface name");
3070 					return NULL;
3071 				}
3072 	
3073 				matched = g_str_equal (iface, nm_device_get_ip_iface (device));
3074 				g_free (iface);
3075 				if (!matched) {
3076 					g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE,
3077 					                     "Device given by path did not match connection's virtual interface name");
3078 					return NULL;
3079 				}
3080 			}
3081 		} else {
3082 			/* Virtual connections (VLAN, bond, team, etc) may not specify
3083 			 * a device path because the device may not be created yet,
3084 			 * or it be given by the connection's properties instead.
3085 			 * Find the device the connection refers to, or create it
3086 			 * if needed.
3087 			 */
3088 			if (!connection_needs_virtual_device (connection)) {
3089 				g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE,
3090 				                     "This connection requires an existing device.");
3091 				return NULL;
3092 			}
3093 	
3094 			iface = get_virtual_iface_name (manager, connection, NULL);
3095 			if (!iface) {
3096 				g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE,
3097 				                     "Failed to determine connection's virtual interface name");
3098 				return NULL;
3099 			}
3100 	
3101 			device = find_device_by_ip_iface (manager, iface);
3102 			if (!device) {
3103 				/* Create the software device. Only exception is when:
3104 				 * - this is an auto-activation *and* the device denies auto-activation
3105 				 *   at this time (the device was manually disconnected/deleted before)
3106 				 */
3107 				if (!nm_manager_can_device_auto_connect (manager, iface)) {
3108 					if (dbus_sender) {
3109 						/* Manual activation - allow device auto-activation again */
3110 						nm_manager_prevent_device_auto_connect (manager, iface, FALSE);
3111 					} else {
3112 						g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_AUTOCONNECT_NOT_ALLOWED,
3113 						             "'%s' does not allow automatic connections at this time => software device '%s' not created for '%s'",
3114 						             iface, iface, nm_connection_get_id (connection));
3115 						g_free (iface);
3116 						return NULL;
3117 					}
3118 				}
3119 	
3120 				device = system_create_virtual_device (manager, connection);
3121 				if (!device) {
3122 					g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE,
3123 					             "Failed to create virtual interface '%s'", iface);
3124 					g_free (iface);
3125 					return NULL;
3126 				}
3127 	
3128 				/* A newly created device, if allowed to be managed by NM, will be
3129 				 * in the UNAVAILABLE state here.  To ensure it can be activated
3130 				 * immediately, we transition it to DISCONNECTED so it passes the
3131 				 * nm_device_can_activate() check below.
3132 				 */
3133 				if (   nm_device_is_available (device)
3134 				    && (nm_device_get_state (device) == NM_DEVICE_STATE_UNAVAILABLE)) {
3135 					nm_device_state_changed (device,
3136 					                         NM_DEVICE_STATE_DISCONNECTED,
3137 					                         NM_DEVICE_STATE_REASON_NONE);
3138 				}
3139 			}
3140 			g_free (iface);
3141 		}
3142 	
3143 		if (!nm_device_can_activate (device, connection)) {
3144 			g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNMANAGED_DEVICE,
3145 			                     "Device not managed by NetworkManager or unavailable");
3146 			return NULL;
3147 		}
3148 	
3149 		/* If this is an autoconnect request, but the device isn't allowing autoconnect
3150 		 * right now, we reject it.
3151 		 */
3152 		if (!dbus_sender && !nm_device_autoconnect_allowed (device)) {
3153 			g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_AUTOCONNECT_NOT_ALLOWED,
3154 			             "%s does not allow automatic connections at this time",
3155 			             nm_device_get_iface (device));
3156 			return NULL;
3157 		}
3158 	
3159 		/* Try to find the master connection/device if the connection has a dependency */
3160 		if (!find_master (manager, connection, device, &master_connection, &master_device)) {
3161 			g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE,
3162 			                     "Master connection not found or invalid");
3163 			return NULL;
3164 		}
3165 	
3166 		/* Ensure there's a master active connection the new connection we're
3167 		 * activating can depend on.
3168 		 */
3169 		if (master_connection || master_device) {
3170 			if (master_connection) {
3171 				nm_log_dbg (LOGD_CORE, "Activation of '%s' requires master connection '%s'",
3172 				            nm_connection_get_id (connection),
3173 				            nm_connection_get_id (master_connection));
3174 			}
3175 			if (master_device) {
3176 				nm_log_dbg (LOGD_CORE, "Activation of '%s' requires master device '%s'",
3177 				            nm_connection_get_id (connection),
3178 				            nm_device_get_ip_iface (master_device));
3179 			}
3180 	
3181 			/* Ensure eg bond/team slave and the candidate master is
3182 			 * a bond/team master
3183 			 */
3184 			if (master_connection && !is_compatible_with_slave (master_connection, connection)) {
3185 				g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_DEPENDENCY_FAILED,
3186 				                     "The master connection was not compatible");
3187 				return NULL;
3188 			}
3189 	
3190 			master_ac = ensure_master_active_connection (manager,
3191 			                                             dbus_sender,
3192 			                                             connection,
3193 			                                             device,
3194 			                                             master_connection,
3195 			                                             master_device,
3196 			                                             error);
3197 			if (!master_ac) {
3198 				if (error)
3199 					g_assert (*error);
3200 				return NULL;
3201 			}
3202 	
3203 			nm_log_dbg (LOGD_CORE, "Activation of '%s' depends on active connection %s",
3204 			            nm_connection_get_id (connection),
3205 			            nm_active_connection_get_path (master_ac));
3206 		}
3207 	
3208 		ac = internal_activate_device (manager,
3209 		                               device,
3210 		                               connection,
3211 		                               specific_object,
3212 		                               dbus_sender ? TRUE : FALSE,
3213 		                               dbus_sender ? sender_uid : 0,
3214 		                               dbus_sender,
3215 		                               FALSE,
3216 		                               master_ac,
3217 		                               error);
3218 	
3219 	activated:
3220 		if (ac)
3221 			active_connection_add (manager, ac);
3222 	
3223 		return ac;
3224 	}
3225 	
3226 	/* 
3227 	 * TODO this function was created and named in the era of user settings, where
3228 	 * we could get activation requests for a connection before we got the settings
3229 	 * data of that connection. Now that user settings are gone, flatten or rename
3230 	 * it.
3231 	 */
3232 	static void
3233 	pending_activate (NMManager *self, PendingActivation *pending)
3234 	{
3235 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
3236 		NMSettingsConnection *connection;
3237 		NMActiveConnection *ac = NULL;
3238 		GError *error = NULL;
3239 		char *sender = NULL;
3240 	
3241 		/* Ok, we're authorized */
3242 	
3243 		connection = nm_settings_get_connection_by_path (priv->settings, pending->connection_path);
3244 		if (!connection) {
3245 			error = g_error_new_literal (NM_MANAGER_ERROR,
3246 			                             NM_MANAGER_ERROR_UNKNOWN_CONNECTION,
3247 			                             "Connection could not be found.");
3248 			goto out;
3249 		}
3250 	
3251 		if (!nm_dbus_manager_get_caller_info (priv->dbus_mgr,
3252 		                                      pending->context,
3253 		                                      &sender,
3254 		                                      NULL)) {
3255 			error = g_error_new_literal (NM_MANAGER_ERROR,
3256 			                             NM_MANAGER_ERROR_PERMISSION_DENIED,
3257 			                             "D-Bus sendder could not be determined.");
3258 			goto out;
3259 		}
3260 	
3261 		g_assert (sender);
3262 		ac = nm_manager_activate_connection (self,
3263 		                                     NM_CONNECTION (connection),
3264 		                                     pending->specific_object_path,
3265 		                                     pending->device_path,
3266 		                                     sender,
3267 		                                     &error);
3268 		g_free (sender);
3269 	
3270 		if (!ac) {
3271 			nm_log_warn (LOGD_CORE, "connection %s failed to activate: (%d) %s",
3272 			             pending->connection_path,
3273 			             error ? error->code : -1,
3274 			             error && error->message ? error->message : "(unknown)");
3275 		}
3276 	
3277 	out:
3278 		pending_activation_destroy (pending, error, ac);
3279 		g_clear_error (&error);
3280 	}
3281 	
3282 	static void
3283 	activation_auth_done (PendingActivation *pending, GError *error)
3284 	{
3285 		if (error)
3286 			pending_activation_destroy (pending, error, NULL);
3287 		else
3288 			pending_activate (pending->manager, pending);
3289 	}
3290 	
3291 	static void
3292 	impl_manager_activate_connection (NMManager *self,
3293 	                                  const char *connection_path,
3294 	                                  const char *device_path,
3295 	                                  const char *specific_object_path,
3296 	                                  DBusGMethodInvocation *context)
3297 	{
3298 		PendingActivation *pending;
3299 		GError *error = NULL;
3300 	
3301 		/* Need to check the caller's permissions and stuff before we can
3302 		 * activate the connection.
3303 		 */
3304 		pending = pending_activation_new (self,
3305 		                                  context,
3306 		                                  device_path,
3307 		                                  connection_path,
3308 		                                  NULL,
3309 		                                  specific_object_path,
3310 		                                  activation_auth_done,
3311 		                                  &error);
3312 		if (pending)
3313 			pending_activation_check_authorized (pending);
3314 		else {
3315 			g_assert (error);
3316 			dbus_g_method_return_error (context, error);
3317 			g_error_free (error);
3318 		}
3319 	}
3320 	
3321 	static void
3322 	activation_add_done (NMSettings *self,
3323 	                     NMSettingsConnection *connection,
3324 	                     GError *error,
3325 	                     DBusGMethodInvocation *context,
3326 	                     gpointer user_data)
3327 	{
3328 		PendingActivation *pending = user_data;
3329 	
3330 		if (error)
3331 			pending_activation_destroy (pending, error, NULL);
3332 		else {
3333 			/* Save the new connection's D-Bus path */
3334 			pending->connection_path = g_strdup (nm_connection_get_path (NM_CONNECTION (connection)));
3335 	
3336 			/* And activate it */
3337 			pending_activate (pending->manager, pending);
3338 		}
3339 	}
3340 	
3341 	static void
3342 	add_and_activate_auth_done (PendingActivation *pending, GError *error)
3343 	{
3344 		if (error)
3345 			pending_activation_destroy (pending, error, NULL);
3346 		else {
3347 			NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (pending->manager);
3348 	
3349 			/* Basic sender auth checks performed; try to add the connection */
3350 			nm_settings_add_connection_dbus (priv->settings,
3351 			                                 pending->connection,
3352 			                                 TRUE,
3353 			                                 pending->context,
3354 			                                 activation_add_done,
3355 			                                 pending);
3356 		}
3357 	}
3358 	
3359 	static void
3360 	impl_manager_add_and_activate_connection (NMManager *self,
3361 	                                          GHashTable *settings,
3362 	                                          const char *device_path,
3363 	                                          const char *specific_object_path,
3364 	                                          DBusGMethodInvocation *context)
3365 	{
3366 		PendingActivation *pending;
3367 		GError *error = NULL;
3368 	
3369 		/* Need to check the caller's permissions and stuff before we can
3370 		 * activate the connection.
3371 		 */
3372 		pending = pending_activation_new (self,
3373 		                                  context,
3374 		                                  device_path,
3375 		                                  NULL,
3376 		                                  settings,
3377 		                                  specific_object_path,
3378 		                                  add_and_activate_auth_done,
3379 		                                  &error);
3380 		if (pending)
3381 			pending_activation_check_authorized (pending);
3382 		else {
3383 			g_assert (error);
3384 			dbus_g_method_return_error (context, error);
3385 			g_error_free (error);
3386 		}
3387 	}
3388 	
3389 	gboolean
3390 	nm_manager_deactivate_connection (NMManager *manager,
3391 	                                  const char *connection_path,
3392 	                                  NMDeviceStateReason reason,
3393 	                                  GError **error)
3394 	{
3395 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
3396 		NMActiveConnection *active;
3397 		gboolean success = FALSE;
3398 	
3399 		active = active_connection_get_by_path (manager, connection_path);
3400 		if (!active) {
3401 			g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE,
3402 			                     "The connection was not active.");
3403 			return FALSE;
3404 		}
3405 	
3406 		if (NM_IS_VPN_CONNECTION (active)) {
3407 			NMVPNConnectionStateReason vpn_reason = NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED;
3408 	
3409 			if (reason == NM_DEVICE_STATE_REASON_CONNECTION_REMOVED)
3410 				vpn_reason = NM_VPN_CONNECTION_STATE_REASON_CONNECTION_REMOVED;
3411 			if (nm_vpn_manager_deactivate_connection (priv->vpn_manager, NM_VPN_CONNECTION (active), vpn_reason))
3412 				success = TRUE;
3413 			else
3414 				g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE,
3415 				                     "The VPN connection was not active.");
3416 		} else {
3417 			g_assert (NM_IS_ACT_REQUEST (active));
3418 			/* FIXME: use DEACTIVATING state */
3419 			nm_device_state_changed (nm_active_connection_get_device (active),
3420 			                         NM_DEVICE_STATE_DISCONNECTED,
3421 			                         reason);
3422 			success = TRUE;
3423 		}
3424 	
3425 		if (success)
3426 			g_object_notify (G_OBJECT (manager), NM_MANAGER_ACTIVE_CONNECTIONS);
3427 	
3428 		return success;
3429 	}
3430 	
3431 	static void
3432 	deactivate_net_auth_done_cb (NMAuthChain *chain,
3433 	                             GError *auth_error,
3434 	                             DBusGMethodInvocation *context,
3435 	                             gpointer user_data)
3436 	{
3437 		NMManager *self = NM_MANAGER (user_data);
3438 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
3439 		GError *error = NULL;
3440 		NMAuthCallResult result;
3441 	
3442 		priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
3443 	
3444 		result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL);
3445 	
3446 		if (auth_error) {
3447 			nm_log_dbg (LOGD_CORE, "Disconnect request failed: %s", auth_error->message);
3448 			error = g_error_new (NM_MANAGER_ERROR,
3449 			                     NM_MANAGER_ERROR_PERMISSION_DENIED,
3450 			                     "Deactivate request failed: %s",
3451 			                     auth_error->message);
3452 		} else if (result != NM_AUTH_CALL_RESULT_YES) {
3453 			error = g_error_new_literal (NM_MANAGER_ERROR,
3454 			                             NM_MANAGER_ERROR_PERMISSION_DENIED,
3455 			                             "Not authorized to deactivate connections");
3456 		} else {
3457 			/* success; deactivation allowed */
3458 			if (!nm_manager_deactivate_connection (self,
3459 			                                       nm_auth_chain_get_data (chain, "path"),
3460 			                                       NM_DEVICE_STATE_REASON_USER_REQUESTED,
3461 			                                       &error))
3462 				g_assert (error);
3463 		}
3464 	
3465 		if (error)
3466 			dbus_g_method_return_error (context, error);
3467 		else
3468 			dbus_g_method_return (context);
3469 	
3470 		g_clear_error (&error);
3471 		nm_auth_chain_unref (chain);
3472 	}
3473 	
3474 	static void
3475 	impl_manager_deactivate_connection (NMManager *self,
3476 	                                    const char *active_path,
3477 	                                    DBusGMethodInvocation *context)
3478 	{
3479 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
3480 		NMConnection *connection = NULL;
3481 		GError *error = NULL;
3482 		GSList *iter;
3483 		NMAuthChain *chain;
3484 		const char *error_desc = NULL;
3485 	
3486 		/* Find the connection by its object path */
3487 		for (iter = priv->active_connections; iter; iter = g_slist_next (iter)) {
3488 			NMActiveConnection *ac = iter->data;
3489 	
3490 			if (g_strcmp0 (nm_active_connection_get_path (ac), active_path) == 0) {
3491 				connection = nm_active_connection_get_connection (ac);
3492 				break;
3493 			}
3494 		}
3495 	
3496 		if (!connection) {
3497 			error = g_error_new_literal (NM_MANAGER_ERROR,
3498 			                             NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE,
3499 			                             "The connection was not active.");
3500 			dbus_g_method_return_error (context, error);
3501 			g_error_free (error);
3502 			return;
3503 		}
3504 	
3505 		/* Validate the user request */
3506 		chain = nm_auth_chain_new (context, deactivate_net_auth_done_cb, self, &error_desc);
3507 		if (chain) {
3508 			priv->auth_chains = g_slist_append (priv->auth_chains, chain);
3509 	
3510 			nm_auth_chain_set_data (chain, "path", g_strdup (active_path), g_free);
3511 			nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE);
3512 		} else {
3513 			error = g_error_new_literal (NM_MANAGER_ERROR,
3514 			                             NM_MANAGER_ERROR_PERMISSION_DENIED,
3515 			                             error_desc);
3516 			dbus_g_method_return_error (context, error);
3517 			g_error_free (error);
3518 		}
3519 	}
3520 	
3521 	/*
3522 	 * Track (software) devices that cannot auto activate.
3523 	 * It is needed especially for software devices, that can be removed and added
3524 	 * again. So we can't simply use a flag inside the device.
3525 	 */
3526 	void
3527 	nm_manager_prevent_device_auto_connect (NMManager *manager, const char *ifname, gboolean prevent)
3528 	{
3529 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
3530 	
3531 		if (prevent)
3532 			g_hash_table_add (priv->noauto_sw_devices, g_strdup (ifname));
3533 		else
3534 			g_hash_table_remove (priv->noauto_sw_devices, ifname);
3535 	}
3536 	
3537 	gboolean
3538 	nm_manager_can_device_auto_connect (NMManager *manager, const char *ifname)
3539 	{
3540 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
3541 	
3542 		return !g_hash_table_contains (priv->noauto_sw_devices, ifname);
3543 	}
3544 	
3545 	static void
3546 	do_sleep_wake (NMManager *self)
3547 	{
3548 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
3549 		const GSList *unmanaged_specs;
3550 		GSList *iter;
3551 	
3552 		if (manager_sleeping (self)) {
3553 			nm_log_info (LOGD_SUSPEND, "sleeping or disabling...");
3554 	
3555 			/* Just deactivate and down all devices from the device list,
3556 			 * to keep things fast the device list will get resynced when
3557 			 * the manager wakes up.
3558 			 */
3559 			for (iter = priv->devices; iter; iter = iter->next)
3560 				nm_device_set_manager_managed (NM_DEVICE (iter->data), FALSE, NM_DEVICE_STATE_REASON_SLEEPING);
3561 	
3562 		} else {
3563 			nm_log_info (LOGD_SUSPEND, "waking up and re-enabling...");
3564 	
3565 			unmanaged_specs = nm_settings_get_unmanaged_specs (priv->settings);
3566 	
3567 			/* Ensure rfkill state is up-to-date since we don't respond to state
3568 			 * changes during sleep.
3569 			 */
3570 			nm_manager_rfkill_update (self, RFKILL_TYPE_UNKNOWN);
3571 	
3572 			/* Re-manage managed devices */
3573 			for (iter = priv->devices; iter; iter = iter->next) {
3574 				NMDevice *device = NM_DEVICE (iter->data);
3575 				guint i;
3576 	
3577 				/* enable/disable wireless devices since that we don't respond
3578 				 * to killswitch changes during sleep.
3579 				 */
3580 				for (i = 0; i < RFKILL_TYPE_MAX; i++) {
3581 					RadioState *rstate = &priv->radio_states[i];
3582 					gboolean enabled = radio_enabled_for_rstate (rstate, TRUE);
3583 	
3584 					if (rstate->desc) {
3585 						nm_log_dbg (LOGD_RFKILL, "%s %s devices (hw_enabled %d, sw_enabled %d, user_enabled %d)",
3586 						            enabled ? "enabling" : "disabling",
3587 						            rstate->desc, rstate->hw_enabled, rstate->sw_enabled, rstate->user_enabled);
3588 					}
3589 	
3590 					if (nm_device_get_rfkill_type (device) == rstate->rtype)
3591 						nm_device_set_enabled (device, enabled);
3592 				}
3593 	
3594 				g_object_set (G_OBJECT (device), NM_DEVICE_AUTOCONNECT, TRUE, NULL);
3595 	
3596 				if (nm_device_spec_match_list (device, unmanaged_specs))
3597 					nm_device_set_manager_managed (device, FALSE, NM_DEVICE_STATE_REASON_NOW_UNMANAGED);
3598 				else
3599 					nm_device_set_manager_managed (device, TRUE, NM_DEVICE_STATE_REASON_NOW_MANAGED);
3600 			}
3601 		}
3602 	
3603 		nm_manager_update_state (self);
3604 	}
3605 	
3606 	static void
3607 	_internal_sleep (NMManager *self, gboolean do_sleep)
3608 	{
3609 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
3610 	
3611 		if (priv->sleeping == do_sleep)
3612 			return;
3613 	
3614 		nm_log_info (LOGD_SUSPEND, "%s requested (sleeping: %s  enabled: %s)",
3615 		             do_sleep ? "sleep" : "wake",
3616 		             priv->sleeping ? "yes" : "no",
3617 		             priv->net_enabled ? "yes" : "no");
3618 	
3619 		priv->sleeping = do_sleep;
3620 	
3621 		do_sleep_wake (self);
3622 	
3623 		g_object_notify (G_OBJECT (self), NM_MANAGER_SLEEPING);
3624 	}
3625 	
3626 	#if 0
3627 	static void
3628 	sleep_auth_done_cb (NMAuthChain *chain,
3629 	                    GError *error,
3630 	                    DBusGMethodInvocation *context,
3631 	                    gpointer user_data)
3632 	{
3633 		NMManager *self = NM_MANAGER (user_data);
3634 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
3635 		GError *ret_error;
3636 		NMAuthCallResult result;
3637 		gboolean do_sleep;
3638 	
3639 		priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
3640 	
3641 		result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_SLEEP_WAKE);
3642 		if (error) {
3643 			nm_log_dbg (LOGD_SUSPEND, "Sleep/wake request failed: %s", error->message);
3644 			ret_error = g_error_new (NM_MANAGER_ERROR,
3645 			                         NM_MANAGER_ERROR_PERMISSION_DENIED,
3646 			                         "Sleep/wake request failed: %s",
3647 			                         error->message);
3648 			dbus_g_method_return_error (context, ret_error);
3649 			g_error_free (ret_error);
3650 		} else if (result != NM_AUTH_CALL_RESULT_YES) {
3651 			ret_error = g_error_new_literal (NM_MANAGER_ERROR,
3652 			                                 NM_MANAGER_ERROR_PERMISSION_DENIED,
3653 			                                 "Not authorized to sleep/wake");
3654 			dbus_g_method_return_error (context, ret_error);
3655 			g_error_free (ret_error);
3656 		} else {
3657 			/* Auth success */
3658 			do_sleep = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "sleep"));
3659 			_internal_sleep (self, do_sleep);
3660 			dbus_g_method_return (context);
3661 		}
3662 	
3663 		nm_auth_chain_unref (chain);
3664 	}
3665 	#endif
3666 	
3667 	static void
3668 	impl_manager_sleep (NMManager *self,
3669 	                    gboolean do_sleep,
3670 	                    DBusGMethodInvocation *context)
3671 	{
3672 		NMManagerPrivate *priv;
3673 		GError *error = NULL;
3674 	#if 0
3675 		NMAuthChain *chain;
3676 		const char *error_desc = NULL;
3677 	#endif
3678 	
3679 		g_return_if_fail (NM_IS_MANAGER (self));
3680 	
3681 		priv = NM_MANAGER_GET_PRIVATE (self);
3682 	
3683 		if (priv->sleeping == do_sleep) {
3684 			error = g_error_new (NM_MANAGER_ERROR,
3685 			                     NM_MANAGER_ERROR_ALREADY_ASLEEP_OR_AWAKE,
3686 			                     "Already %s", do_sleep ? "asleep" : "awake");
3687 			dbus_g_method_return_error (context, error);
3688 			g_error_free (error);
3689 			return;
3690 		}
3691 	
3692 		/* Unconditionally allow the request.  Previously it was polkit protected
3693 		 * but unfortunately that doesn't work for short-lived processes like
3694 		 * pm-utils.  It uses dbus-send without --print-reply, which quits
3695 		 * immediately after sending the request, and NM is unable to obtain the
3696 		 * sender's UID as dbus-send has already dropped off the bus.  Thus NM
3697 		 * fails the request.  Instead, don't validate the request, but rely on
3698 		 * D-Bus permissions to restrict the call to root.
3699 		 */
3700 		_internal_sleep (self, do_sleep);
3701 		dbus_g_method_return (context);
3702 		return;
3703 	
3704 	#if 0
3705 		chain = nm_auth_chain_new (context, sleep_auth_done_cb, self, &error_desc);
3706 		if (chain) {
3707 			priv->auth_chains = g_slist_append (priv->auth_chains, chain);
3708 			nm_auth_chain_set_data (chain, "sleep", GUINT_TO_POINTER (do_sleep), NULL);
3709 			nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SLEEP_WAKE, TRUE);
3710 		} else {
3711 			error = g_error_new_literal (NM_MANAGER_ERROR,
3712 			                             NM_MANAGER_ERROR_PERMISSION_DENIED,
3713 			                             error_desc);
3714 			dbus_g_method_return_error (context, error);
3715 			g_error_free (error);
3716 		}
3717 	#endif
3718 	}
3719 	
3720 	static void
3721 	sleeping_cb (DBusGProxy *proxy, gpointer user_data)
3722 	{
3723 		nm_log_dbg (LOGD_SUSPEND, "Received sleeping signal");
3724 		_internal_sleep (NM_MANAGER (user_data), TRUE);
3725 	}
3726 	
3727 	static void
3728 	resuming_cb (DBusGProxy *proxy, gpointer user_data)
3729 	{
3730 		nm_log_dbg (LOGD_SUSPEND, "Received resuming signal");
3731 		_internal_sleep (NM_MANAGER (user_data), FALSE);
3732 	}
3733 	
3734 	static void
3735 	_internal_enable (NMManager *self, gboolean enable)
3736 	{
3737 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
3738 		GError *err = NULL;
3739 	
3740 		/* Update "NetworkingEnabled" key in state file */
3741 		if (priv->state_file) {
3742 			if (!write_value_to_state_file (priv->state_file,
3743 			                                "main", "NetworkingEnabled",
3744 			                                G_TYPE_BOOLEAN, (gpointer) &enable,
3745 			                                &err)) {
3746 				/* Not a hard error */
3747 				nm_log_warn (LOGD_SUSPEND, "writing to state file %s failed: (%d) %s.",
3748 				             priv->state_file,
3749 				             err ? err->code : -1,
3750 				             (err && err->message) ? err->message : "unknown");
3751 			}
3752 		}
3753 	
3754 		nm_log_info (LOGD_SUSPEND, "%s requested (sleeping: %s  enabled: %s)",
3755 		             enable ? "enable" : "disable",
3756 		             priv->sleeping ? "yes" : "no",
3757 		             priv->net_enabled ? "yes" : "no");
3758 	
3759 		priv->net_enabled = enable;
3760 	
3761 		do_sleep_wake (self);
3762 	
3763 		g_object_notify (G_OBJECT (self), NM_MANAGER_NETWORKING_ENABLED);
3764 	}
3765 	
3766 	static void
3767 	enable_net_done_cb (NMAuthChain *chain,
3768 	                    GError *error,
3769 	                    DBusGMethodInvocation *context,
3770 	                    gpointer user_data)
3771 	{
3772 		NMManager *self = NM_MANAGER (user_data);
3773 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
3774 		GError *ret_error = NULL;
3775 		NMAuthCallResult result;
3776 		gboolean enable;
3777 	
3778 		priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
3779 	
3780 		result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK);
3781 		if (error) {
3782 			nm_log_dbg (LOGD_CORE, "Enable request failed: %s", error->message);
3783 			ret_error = g_error_new (NM_MANAGER_ERROR,
3784 			                         NM_MANAGER_ERROR_PERMISSION_DENIED,
3785 			                         "Enable request failed: %s",
3786 			                         error->message);
3787 		} else if (result != NM_AUTH_CALL_RESULT_YES) {
3788 			ret_error = g_error_new_literal (NM_MANAGER_ERROR,
3789 			                                 NM_MANAGER_ERROR_PERMISSION_DENIED,
3790 			                                 "Not authorized to enable/disable networking");
3791 		} else {
3792 			/* Auth success */
3793 			enable = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "enable"));
3794 			_internal_enable (self, enable);
3795 			dbus_g_method_return (context);
3796 		}
3797 	
3798 		if (ret_error) {
3799 			dbus_g_method_return_error (context, ret_error);
3800 			g_error_free (ret_error);
3801 		}
3802 	
3803 		nm_auth_chain_unref (chain);
3804 	}
3805 	
3806 	static void
3807 	impl_manager_enable (NMManager *self,
3808 	                     gboolean enable,
3809 	                     DBusGMethodInvocation *context)
3810 	{
3811 		NMManagerPrivate *priv;
3812 		NMAuthChain *chain;
3813 		GError *error = NULL;
3814 		const char *error_desc;
3815 	
3816 		g_return_if_fail (NM_IS_MANAGER (self));
3817 	
3818 		priv = NM_MANAGER_GET_PRIVATE (self);
3819 	
3820 		if (priv->net_enabled == enable) {
3821 			error = g_error_new (NM_MANAGER_ERROR,
3822 			                     NM_MANAGER_ERROR_ALREADY_ENABLED_OR_DISABLED,
3823 			                     "Already %s", enable ? "enabled" : "disabled");
3824 			dbus_g_method_return_error (context, error);
3825 			g_error_free (error);
3826 			return;
3827 		}
3828 	
3829 		chain = nm_auth_chain_new (context, enable_net_done_cb, self, &error_desc);
3830 		if (chain) {
3831 			priv->auth_chains = g_slist_append (priv->auth_chains, chain);
3832 	
3833 			nm_auth_chain_set_data (chain, "enable", GUINT_TO_POINTER (enable), NULL);
3834 			nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK, TRUE);
3835 		} else {
3836 			error = g_error_new_literal (NM_MANAGER_ERROR,
3837 			                             NM_MANAGER_ERROR_PERMISSION_DENIED,
3838 			                             error_desc);
3839 			dbus_g_method_return_error (context, error);
3840 			g_error_free (error);
3841 		}
3842 	}
3843 	
3844 	/* Permissions */
3845 	
3846 	static void
3847 	get_perm_add_result (NMAuthChain *chain, GHashTable *results, const char *permission)
3848 	{
3849 		NMAuthCallResult result;
3850 	
3851 		result = nm_auth_chain_get_result (chain, permission);
3852 		if (result == NM_AUTH_CALL_RESULT_YES)
3853 			g_hash_table_insert (results, (char *) permission, "yes");
3854 		else if (result == NM_AUTH_CALL_RESULT_NO)
3855 			g_hash_table_insert (results, (char *) permission, "no");
3856 		else if (result == NM_AUTH_CALL_RESULT_AUTH)
3857 			g_hash_table_insert (results, (char *) permission, "auth");
3858 		else {
3859 			nm_log_dbg (LOGD_CORE, "unknown auth chain result %d", result);
3860 		}
3861 	}
3862 	
3863 	static void
3864 	get_permissions_done_cb (NMAuthChain *chain,
3865 	                         GError *error,
3866 	                         DBusGMethodInvocation *context,
3867 	                         gpointer user_data)
3868 	{
3869 		NMManager *self = NM_MANAGER (user_data);
3870 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
3871 		GError *ret_error;
3872 		GHashTable *results;
3873 	
3874 		priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
3875 		if (error) {
3876 			nm_log_dbg (LOGD_CORE, "Permissions request failed: %s", error->message);
3877 			ret_error = g_error_new (NM_MANAGER_ERROR,
3878 			                         NM_MANAGER_ERROR_PERMISSION_DENIED,
3879 			                         "Permissions request failed: %s",
3880 			                         error->message);
3881 			dbus_g_method_return_error (context, ret_error);
3882 			g_error_free (ret_error);
3883 		} else {
3884 			results = g_hash_table_new (g_str_hash, g_str_equal);
3885 	
3886 			get_perm_add_result (chain, results, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK);
3887 			get_perm_add_result (chain, results, NM_AUTH_PERMISSION_SLEEP_WAKE);
3888 			get_perm_add_result (chain, results, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI);
3889 			get_perm_add_result (chain, results, NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN);
3890 			get_perm_add_result (chain, results, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX);
3891 			get_perm_add_result (chain, results, NM_AUTH_PERMISSION_NETWORK_CONTROL);
3892 			get_perm_add_result (chain, results, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED);
3893 			get_perm_add_result (chain, results, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN);
3894 			get_perm_add_result (chain, results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM);
3895 			get_perm_add_result (chain, results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN);
3896 			get_perm_add_result (chain, results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME);
3897 	
3898 			dbus_g_method_return (context, results);
3899 			g_hash_table_destroy (results);
3900 		}
3901 	
3902 		nm_auth_chain_unref (chain);
3903 	}
3904 	
3905 	static void
3906 	impl_manager_get_permissions (NMManager *self,
3907 	                              DBusGMethodInvocation *context)
3908 	{
3909 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
3910 		NMAuthChain *chain;
3911 		const char *error_desc = NULL;
3912 		GError *error;
3913 	
3914 		chain = nm_auth_chain_new (context, get_permissions_done_cb, self, &error_desc);
3915 		if (chain) {
3916 			priv->auth_chains = g_slist_append (priv->auth_chains, chain);
3917 	
3918 			nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK, FALSE);
3919 			nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SLEEP_WAKE, FALSE);
3920 			nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI, FALSE);
3921 			nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN, FALSE);
3922 			nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX, FALSE);
3923 			nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, FALSE);
3924 			nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED, FALSE);
3925 			nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN, FALSE);
3926 			nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM, FALSE);
3927 			nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN, FALSE);
3928 			nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME, FALSE);
3929 		} else {
3930 			error = g_error_new_literal (NM_MANAGER_ERROR,
3931 			                             NM_MANAGER_ERROR_PERMISSION_DENIED,
3932 			                             error_desc);
3933 			dbus_g_method_return_error (context, error);
3934 			g_error_free (error);
3935 		}
3936 	}
3937 	
3938 	static gboolean
3939 	impl_manager_get_state (NMManager *manager, guint32 *state, GError **error)
3940 	{
3941 		nm_manager_update_state (manager);
3942 		*state = NM_MANAGER_GET_PRIVATE (manager)->state;
3943 		return TRUE;
3944 	}
3945 	
3946 	static gboolean
3947 	impl_manager_set_logging (NMManager *manager,
3948 	                          const char *level,
3949 	                          const char *domains,
3950 	                          GError **error)
3951 	{
3952 		if (nm_logging_setup (level, domains, error)) {
3953 			char *new_domains = nm_logging_domains_to_string ();
3954 	
3955 			nm_log_info (LOGD_CORE, "logging: level '%s' domains '%s'",
3956 			             nm_logging_level_to_string (),
3957 			             new_domains);
3958 			g_free (new_domains);
3959 			return TRUE;
3960 		}
3961 		return FALSE;
3962 	}
3963 	
3964 	static void
3965 	impl_manager_get_logging (NMManager *manager,
3966 	                          char **level,
3967 	                          char **domains)
3968 	{
3969 		*level = g_strdup (nm_logging_level_to_string ());
3970 		*domains = g_strdup (nm_logging_domains_to_string ());
3971 	}
3972 	
3973 	static void
3974 	connectivity_check_done (GObject *object,
3975 	                         GAsyncResult *result,
3976 	                         gpointer user_data)
3977 	{
3978 		DBusGMethodInvocation *context = user_data;
3979 		NMConnectivityState state;
3980 		GError *error = NULL;
3981 	
3982 		state = nm_connectivity_check_finish (NM_CONNECTIVITY (object), result, &error);
3983 		if (error) {
3984 			dbus_g_method_return_error (context, error);
3985 			g_error_free (error);
3986 		} else
3987 			dbus_g_method_return (context, state);
3988 	}
3989 	
3990 	
3991 	static void
3992 	check_connectivity_auth_done_cb (NMAuthChain *chain,
3993 	                                 GError *auth_error,
3994 	                                 DBusGMethodInvocation *context,
3995 	                                 gpointer user_data)
3996 	{
3997 		NMManager *self = NM_MANAGER (user_data);
3998 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
3999 		GError *error = NULL;
4000 		NMAuthCallResult result;
4001 	
4002 		priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
4003 	
4004 		result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL);
4005 	
4006 		if (auth_error) {
4007 			nm_log_dbg (LOGD_CORE, "CheckConnectivity request failed: %s", auth_error->message);
4008 			error = g_error_new (NM_MANAGER_ERROR,
4009 			                     NM_MANAGER_ERROR_PERMISSION_DENIED,
4010 			                     "Connectivity check request failed: %s",
4011 			                     auth_error->message);
4012 		} else if (result != NM_AUTH_CALL_RESULT_YES) {
4013 			error = g_error_new_literal (NM_MANAGER_ERROR,
4014 			                             NM_MANAGER_ERROR_PERMISSION_DENIED,
4015 			                             "Not authorized to recheck connectivity");
4016 		} else {
4017 			/* it's allowed */
4018 			nm_connectivity_check_async (priv->connectivity,
4019 			                             connectivity_check_done,
4020 			                             context);
4021 		}
4022 	
4023 		if (error) {
4024 			dbus_g_method_return_error (context, error);
4025 			g_error_free (error);
4026 		}
4027 		nm_auth_chain_unref (chain);
4028 	}
4029 	
4030 	static void
4031 	impl_manager_check_connectivity (NMManager *manager,
4032 	                                 DBusGMethodInvocation *context)
4033 	{
4034 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
4035 		NMAuthChain *chain;
4036 		const char *error_desc = NULL;
4037 		GError *error;
4038 	
4039 		/* Validate the user request */
4040 		chain = nm_auth_chain_new (context, check_connectivity_auth_done_cb, manager, &error_desc);
4041 		if (chain) {
4042 			priv->auth_chains = g_slist_append (priv->auth_chains, chain);
4043 	
4044 			nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE);
4045 		} else {
4046 			error = g_error_new_literal (NM_MANAGER_ERROR,
4047 			                             NM_MANAGER_ERROR_PERMISSION_DENIED,
4048 			                             error_desc);
4049 			dbus_g_method_return_error (context, error);
4050 			g_error_free (error);
4051 		}
4052 	}
4053 	
4054 	void
4055 	nm_manager_start (NMManager *self)
4056 	{
4057 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
4058 		guint i;
4059 	
4060 		/* Set initial radio enabled/disabled state */
4061 		for (i = 0; i < RFKILL_TYPE_MAX; i++) {
4062 			RadioState *rstate = &priv->radio_states[i];
4063 			RfKillState udev_state;
4064 			gboolean enabled;
4065 	
4066 			if (!rstate->desc)
4067 				continue;
4068 	
4069 			udev_state = nm_rfkill_manager_get_rfkill_state (priv->rfkill_mgr, i);
4070 			update_rstate_from_rfkill (rstate, udev_state);
4071 	
4072 			if (rstate->desc) {
4073 				nm_log_info (LOGD_RFKILL, "%s %s by radio killswitch; %s by state file",
4074 					         rstate->desc,
4075 					         (rstate->hw_enabled && rstate->sw_enabled) ? "enabled" : "disabled",
4076 					         rstate->user_enabled ? "enabled" : "disabled");
4077 			}
4078 			enabled = radio_enabled_for_rstate (rstate, TRUE);
4079 			manager_update_radio_enabled (self, rstate, enabled);
4080 		}
4081 	
4082 		/* Log overall networking status - enabled/disabled */
4083 		nm_log_info (LOGD_CORE, "Networking is %s by state file",
4084 		             priv->net_enabled ? "enabled" : "disabled");
4085 	
4086 		system_unmanaged_devices_changed_cb (priv->settings, NULL, self);
4087 		system_hostname_changed_cb (priv->settings, NULL, self);
4088 	
4089 		/* FIXME: remove when we handle bridges non-destructively */
4090 		/* Read a list of bridges NM managed when it last quit, and only
4091 		 * manage those bridges to avoid conflicts with external tools.
4092 		 */
4093 		priv->nm_bridges = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
4094 		read_nm_created_bridges (self);
4095 	
4096 		nm_platform_query_devices ();
4097 		nm_atm_manager_query_devices (priv->atm_mgr);
4098 		nm_bluez_manager_query_devices (priv->bluez_mgr);
4099 	
4100 		/*
4101 		 * Connections added before the manager is started do not emit
4102 		 * connection-added signals thus devices have to be created manually.
4103 		 */
4104 		system_create_virtual_devices (self);
4105 	
4106 		/* FIXME: remove when we handle bridges non-destructively */
4107 		g_hash_table_unref (priv->nm_bridges);
4108 		priv->nm_bridges = NULL;
4109 	
4110 		check_if_startup_complete (self);
4111 	}
4112 	
4113 	static gboolean
4114 	handle_firmware_changed (gpointer user_data)
4115 	{
4116 		NMManager *self = NM_MANAGER (user_data);
4117 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
4118 		GSList *iter;
4119 	
4120 		priv->fw_changed_id = 0;
4121 	
4122 		if (manager_sleeping (self))
4123 			return FALSE;
4124 	
4125 		/* Try to re-enable devices with missing firmware */
4126 		for (iter = priv->devices; iter; iter = iter->next) {
4127 			NMDevice *candidate = NM_DEVICE (iter->data);
4128 			NMDeviceState state = nm_device_get_state (candidate);
4129 	
4130 			if (   nm_device_get_firmware_missing (candidate)
4131 			    && (state == NM_DEVICE_STATE_UNAVAILABLE)) {
4132 				nm_log_info (LOGD_CORE, "(%s): firmware may now be available",
4133 				             nm_device_get_iface (candidate));
4134 	
4135 				/* Re-set unavailable state to try bringing the device up again */
4136 				nm_device_state_changed (candidate,
4137 				                         NM_DEVICE_STATE_UNAVAILABLE,
4138 				                         NM_DEVICE_STATE_REASON_NONE);
4139 			}
4140 		}
4141 	
4142 		return FALSE;
4143 	}
4144 	
4145 	static void
4146 	connectivity_changed (NMConnectivity *connectivity,
4147 	                      GParamSpec *pspec,
4148 	                      gpointer user_data)
4149 	{
4150 		NMManager *self = NM_MANAGER (user_data);
4151 		NMConnectivityState state;
4152 		static const char *connectivity_states[] = { "UNKNOWN", "NONE", "PORTAL", "LIMITED", "FULL" };
4153 	
4154 		state = nm_connectivity_get_state (connectivity);
4155 		nm_log_dbg (LOGD_CORE, "connectivity checking indicates %s",
4156 		            connectivity_states[state]);
4157 	
4158 		nm_manager_update_state (self);
4159 	}
4160 	
4161 	static void
4162 	firmware_dir_changed (GFileMonitor *monitor,
4163 	                      GFile *file,
4164 	                      GFile *other_file,
4165 	                      GFileMonitorEvent event_type,
4166 	                      gpointer user_data)
4167 	{
4168 		NMManager *self = NM_MANAGER (user_data);
4169 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
4170 	
4171 		switch (event_type) {
4172 		case G_FILE_MONITOR_EVENT_CREATED:
4173 		case G_FILE_MONITOR_EVENT_CHANGED:
4174 		case G_FILE_MONITOR_EVENT_MOVED:
4175 		case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
4176 		case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
4177 			if (!priv->fw_changed_id) {
4178 				priv->fw_changed_id = g_timeout_add_seconds (4, handle_firmware_changed, self);
4179 				nm_log_info (LOGD_CORE, "kernel firmware directory '%s' changed",
4180 				             KERNEL_FIRMWARE_DIR);
4181 			}
4182 			break;
4183 		default:
4184 			break;
4185 		}
4186 	}
4187 	
4188 	static void
4189 	policy_default_device_changed (GObject *object, GParamSpec *pspec, gpointer user_data)
4190 	{
4191 		NMManager *self = NM_MANAGER (user_data);
4192 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
4193 		NMDevice *best;
4194 		NMActiveConnection *ac;
4195 	
4196 		/* Note: this assumes that it's not possible for the IP4 default
4197 		 * route to be going over the default-ip6-device. If that changes,
4198 		 * we need something more complicated here.
4199 		 */
4200 		best = nm_policy_get_default_ip4_device (priv->policy);
4201 		if (!best)
4202 			best = nm_policy_get_default_ip6_device (priv->policy);
4203 	
4204 		if (best)
4205 			ac = NM_ACTIVE_CONNECTION (nm_device_get_act_request (best));
4206 		else
4207 			ac = NULL;
4208 	
4209 		if (ac != priv->primary_connection) {
4210 			g_clear_object (&priv->primary_connection);
4211 			priv->primary_connection = ac ? g_object_ref (ac) : NULL;
4212 			nm_log_dbg (LOGD_CORE, "PrimaryConnection now %s", ac ? nm_active_connection_get_name (ac) : "(none)");
4213 			g_object_notify (G_OBJECT (self), NM_MANAGER_PRIMARY_CONNECTION);
4214 		}
4215 	}
4216 	
4217 	static void
4218 	policy_activating_device_changed (GObject *object, GParamSpec *pspec, gpointer user_data)
4219 	{
4220 		NMManager *self = NM_MANAGER (user_data);
4221 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
4222 		NMDevice *activating, *best;
4223 		NMActiveConnection *ac;
4224 	
4225 		/* We only look at activating-ip6-device if activating-ip4-device
4226 		 * AND default-ip4-device are NULL; if default-ip4-device is
4227 		 * non-NULL, then activating-ip6-device is irrelevant, since while
4228 		 * that device might become the new default-ip6-device, it can't
4229 		 * become primary-connection while default-ip4-device is set to
4230 		 * something else.
4231 		 */
4232 		activating = nm_policy_get_activating_ip4_device (priv->policy);
4233 		best = nm_policy_get_default_ip4_device (priv->policy);
4234 		if (!activating && !best)
4235 			activating = nm_policy_get_activating_ip6_device (priv->policy);
4236 	
4237 		if (activating)
4238 			ac = NM_ACTIVE_CONNECTION (nm_device_get_act_request (activating));
4239 		else
4240 			ac = NULL;
4241 	
4242 		if (ac != priv->activating_connection) {
4243 			g_clear_object (&priv->activating_connection);
4244 			priv->activating_connection = ac ? g_object_ref (ac) : NULL;
4245 			nm_log_dbg (LOGD_CORE, "ActivatingConnection now %s", ac ? nm_active_connection_get_name (ac) : "(none)");
4246 			g_object_notify (G_OBJECT (self), NM_MANAGER_ACTIVATING_CONNECTION);
4247 		}
4248 	}
4249 	
4250 	#define NM_PERM_DENIED_ERROR "org.freedesktop.NetworkManager.PermissionDenied"
4251 	#define DEV_PERM_DENIED_ERROR "org.freedesktop.NetworkManager.Device.PermissionDenied"
4252 	
4253 	static void
4254 	prop_set_auth_done_cb (NMAuthChain *chain,
4255 	                       GError *error,
4256 	                       DBusGMethodInvocation *context,
4257 	                       gpointer user_data)
4258 	{
4259 		NMManager *self = NM_MANAGER (user_data);
4260 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
4261 		DBusConnection *connection;
4262 		NMAuthCallResult result;
4263 		DBusMessage *reply = NULL, *message;
4264 		const char *permission, *prop;
4265 		GObject *obj;
4266 		gboolean set_enabled = TRUE;
4267 	
4268 		priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
4269 	
4270 		message = nm_auth_chain_get_data (chain, "message");
4271 		permission = nm_auth_chain_get_data (chain, "permission");
4272 		prop = nm_auth_chain_get_data (chain, "prop");
4273 		set_enabled = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "enabled"));
4274 		obj = nm_auth_chain_get_data (chain, "object");
4275 	
4276 		result = nm_auth_chain_get_result (chain, permission);
4277 		if (error || (result != NM_AUTH_CALL_RESULT_YES)) {
4278 			reply = dbus_message_new_error (message,
4279 			                                NM_IS_DEVICE (obj) ? DEV_PERM_DENIED_ERROR : NM_PERM_DENIED_ERROR,
4280 			                                "Not authorized to perform this operation");
4281 		} else {
4282 			g_object_set (obj, prop, set_enabled, NULL);
4283 			reply = dbus_message_new_method_return (message);
4284 		}
4285 	
4286 		g_assert (reply);
4287 		connection = nm_auth_chain_get_data (chain, "connection");
4288 		g_assert (connection);
4289 		dbus_connection_send (connection, reply, NULL);
4290 		dbus_message_unref (reply);
4291 	
4292 		nm_auth_chain_unref (chain);
4293 	}
4294 	
4295 	static DBusHandlerResult
4296 	prop_filter (DBusConnection *connection,
4297 	             DBusMessage *message,
4298 	             void *user_data)
4299 	{
4300 		NMManager *self = NM_MANAGER (user_data);
4301 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
4302 		DBusMessageIter iter;
4303 		DBusMessageIter sub;
4304 		const char *propiface = NULL;
4305 		const char *propname = NULL;
4306 		const char *glib_propname = NULL, *permission = NULL;
4307 		gulong caller_uid = G_MAXULONG;
4308 		DBusMessage *reply = NULL;
4309 		gboolean set_enabled = FALSE;
4310 		NMAuthChain *chain;
4311 		GObject *obj;
4312 	
4313 		/* The sole purpose of this function is to validate property accesses
4314 		 * on the NMManager object since dbus-glib doesn't yet give us this
4315 		 * functionality.
4316 		 */
4317 	
4318 		if (!dbus_message_is_method_call (message, DBUS_INTERFACE_PROPERTIES, "Set"))
4319 			return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
4320 	
4321 		dbus_message_iter_init (message, &iter);
4322 	
4323 		/* Get the D-Bus interface of the property to set */
4324 		if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
4325 			return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
4326 		dbus_message_iter_get_basic (&iter, &propiface);
4327 		if (!propiface || (strcmp (propiface, NM_DBUS_INTERFACE) && strcmp (propiface, NM_DBUS_INTERFACE_DEVICE)))
4328 			return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
4329 		dbus_message_iter_next (&iter);
4330 	
4331 		/* Get the property name that's going to be set */
4332 		if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
4333 			return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
4334 		dbus_message_iter_get_basic (&iter, &propname);
4335 		dbus_message_iter_next (&iter);
4336 	
4337 		if (!strcmp (propname, "WirelessEnabled")) {
4338 			glib_propname = NM_MANAGER_WIRELESS_ENABLED;
4339 			permission = NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI;
4340 		} else if (!strcmp (propname, "WwanEnabled")) {
4341 			glib_propname = NM_MANAGER_WWAN_ENABLED;
4342 			permission = NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN;
4343 		} else if (!strcmp (propname, "WimaxEnabled")) {
4344 			glib_propname = NM_MANAGER_WIMAX_ENABLED;
4345 			permission = NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX;
4346 		} else if (!strcmp (propname, "Autoconnect")) {
4347 			glib_propname = NM_DEVICE_AUTOCONNECT;
4348 			permission = NM_AUTH_PERMISSION_NETWORK_CONTROL;
4349 		} else
4350 			return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
4351 	
4352 		/* Get the new value for the property */
4353 		if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_VARIANT)
4354 			return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
4355 		dbus_message_iter_recurse (&iter, &sub);
4356 		if (dbus_message_iter_get_arg_type (&sub) != DBUS_TYPE_BOOLEAN)
4357 			return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
4358 		dbus_message_iter_get_basic (&sub, &set_enabled);
4359 	
4360 		/* Make sure the object exists */
4361 		obj = dbus_g_connection_lookup_g_object (dbus_connection_get_g_connection (connection),
4362 		                                         dbus_message_get_path (message));
4363 		if (!obj) {
4364 			reply = dbus_message_new_error (message, NM_PERM_DENIED_ERROR,
4365 			                                "Object does not exist");
4366 			goto out;
4367 		}
4368 	
4369 		if (!nm_dbus_manager_get_caller_info_from_message (priv->dbus_mgr,
4370 		                                                   connection,
4371 		                                                   message,
4372 		                                                   NULL,
4373 		                                                   &caller_uid)) {
4374 			reply = dbus_message_new_error (message, NM_PERM_DENIED_ERROR,
4375 			                                "Could not determine request UID.");
4376 			goto out;
4377 		}
4378 	
4379 		/* Validate the user request */
4380 		chain = nm_auth_chain_new_raw_message (message, caller_uid, prop_set_auth_done_cb, self);
4381 		g_assert (chain);
4382 		priv->auth_chains = g_slist_append (priv->auth_chains, chain);
4383 		nm_auth_chain_set_data (chain, "prop", g_strdup (glib_propname), g_free);
4384 		nm_auth_chain_set_data (chain, "permission", g_strdup (permission), g_free);
4385 		nm_auth_chain_set_data (chain, "enabled", GUINT_TO_POINTER (set_enabled), NULL);
4386 		nm_auth_chain_set_data (chain, "message", dbus_message_ref (message), (GDestroyNotify) dbus_message_unref);
4387 		nm_auth_chain_set_data (chain, "connection", dbus_connection_ref (connection), (GDestroyNotify) dbus_connection_unref);
4388 		nm_auth_chain_set_data (chain, "object", g_object_ref (obj), (GDestroyNotify) g_object_unref);
4389 		nm_auth_chain_add_call (chain, permission, TRUE);
4390 	
4391 	out:
4392 		if (reply) {
4393 			dbus_connection_send (connection, reply, NULL);
4394 			dbus_message_unref (reply);
4395 		}
4396 		return DBUS_HANDLER_RESULT_HANDLED;
4397 	}
4398 	
4399 	static NMManager *singleton = NULL;
4400 	
4401 	NMManager *
4402 	nm_manager_get (void)
4403 	{
4404 		g_assert (singleton);
4405 		return g_object_ref (singleton);
4406 	}
4407 	
4408 	NMManager *
4409 	nm_manager_new (NMSettings *settings,
4410 	                const char *state_file,
4411 	                gboolean initial_net_enabled,
4412 	                gboolean initial_wifi_enabled,
4413 	                gboolean initial_wwan_enabled,
4414 	                gboolean initial_wimax_enabled,
4415 	                GError **error)
4416 	{
4417 		NMManagerPrivate *priv;
4418 		DBusGConnection *bus;
4419 		DBusConnection *dbus_connection;
4420 	
4421 		g_assert (settings);
4422 	
4423 		/* Can only be called once */
4424 		g_assert (singleton == NULL);
4425 		singleton = (NMManager *) g_object_new (NM_TYPE_MANAGER, NULL);
4426 		g_assert (singleton);
4427 	
4428 		priv = NM_MANAGER_GET_PRIVATE (singleton);
4429 	
4430 		priv->policy = nm_policy_new (singleton, settings);
4431 		g_signal_connect (priv->policy, "notify::" NM_POLICY_DEFAULT_IP4_DEVICE,
4432 		                  G_CALLBACK (policy_default_device_changed), singleton);
4433 		g_signal_connect (priv->policy, "notify::" NM_POLICY_DEFAULT_IP6_DEVICE,
4434 		                  G_CALLBACK (policy_default_device_changed), singleton);
4435 		g_signal_connect (priv->policy, "notify::" NM_POLICY_ACTIVATING_IP4_DEVICE,
4436 		                  G_CALLBACK (policy_activating_device_changed), singleton);
4437 		g_signal_connect (priv->policy, "notify::" NM_POLICY_ACTIVATING_IP6_DEVICE,
4438 		                  G_CALLBACK (policy_activating_device_changed), singleton);
4439 	
4440 		priv->connectivity = nm_connectivity_new ();
4441 		g_signal_connect (priv->connectivity, "notify::" NM_CONNECTIVITY_STATE,
4442 		                  G_CALLBACK (connectivity_changed), singleton);
4443 	
4444 		bus = nm_dbus_manager_get_connection (priv->dbus_mgr);
4445 		g_assert (bus);
4446 		dbus_connection = dbus_g_connection_get_connection (bus);
4447 		g_assert (dbus_connection);
4448 	
4449 		if (!dbus_connection_add_filter (dbus_connection, prop_filter, singleton, NULL)) {
4450 			nm_log_err (LOGD_CORE, "failed to register DBus connection filter");
4451 			g_object_unref (singleton);
4452 			return NULL;
4453 	    }
4454 	
4455 		priv->settings = g_object_ref (settings);
4456 	
4457 		priv->state_file = g_strdup (state_file);
4458 	
4459 		priv->net_enabled = initial_net_enabled;
4460 	
4461 		priv->radio_states[RFKILL_TYPE_WLAN].user_enabled = initial_wifi_enabled;
4462 		priv->radio_states[RFKILL_TYPE_WWAN].user_enabled = initial_wwan_enabled;
4463 		priv->radio_states[RFKILL_TYPE_WIMAX].user_enabled = initial_wimax_enabled;
4464 	
4465 		g_signal_connect (priv->settings, "notify::" NM_SETTINGS_UNMANAGED_SPECS,
4466 		                  G_CALLBACK (system_unmanaged_devices_changed_cb), singleton);
4467 		g_signal_connect (priv->settings, "notify::" NM_SETTINGS_HOSTNAME,
4468 		                  G_CALLBACK (system_hostname_changed_cb), singleton);
4469 		g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_ADDED,
4470 		                  G_CALLBACK (connection_added), singleton);
4471 		g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED,
4472 		                  G_CALLBACK (connection_changed), singleton);
4473 		g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_REMOVED,
4474 		                  G_CALLBACK (connection_removed), singleton);
4475 		g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_VISIBILITY_CHANGED,
4476 		                  G_CALLBACK (connection_changed), singleton);
4477 	
4478 		nm_dbus_manager_register_object (priv->dbus_mgr, NM_DBUS_PATH, singleton);
4479 	
4480 		g_signal_connect (nm_platform_get (),
4481 		                  NM_PLATFORM_LINK_ADDED,
4482 		                  G_CALLBACK (platform_link_added_cb),
4483 		                  singleton);
4484 		g_signal_connect (nm_platform_get (),
4485 		                  NM_PLATFORM_LINK_REMOVED,
4486 		                  G_CALLBACK (platform_link_removed_cb),
4487 		                  singleton);
4488 	
4489 		priv->atm_mgr = nm_atm_manager_new ();
4490 		g_signal_connect (priv->atm_mgr,
4491 		                  "device-added",
4492 		                  G_CALLBACK (atm_device_added_cb),
4493 		                  singleton);
4494 		g_signal_connect (priv->atm_mgr,
4495 		                  "device-removed",
4496 		                  G_CALLBACK (atm_device_removed_cb),
4497 		                  singleton);
4498 	
4499 		priv->rfkill_mgr = nm_rfkill_manager_new ();
4500 		g_signal_connect (priv->rfkill_mgr,
4501 		                  "rfkill-changed",
4502 		                  G_CALLBACK (rfkill_manager_rfkill_changed_cb),
4503 		                  singleton);
4504 	
4505 		priv->bluez_mgr = nm_bluez_manager_new (NM_CONNECTION_PROVIDER (priv->settings));
4506 	
4507 		g_signal_connect (priv->bluez_mgr,
4508 		                  NM_BLUEZ_MANAGER_BDADDR_ADDED,
4509 		                  G_CALLBACK (bluez_manager_bdaddr_added_cb),
4510 		                  singleton);
4511 	
4512 		g_signal_connect (priv->bluez_mgr,
4513 		                  NM_BLUEZ_MANAGER_BDADDR_REMOVED,
4514 		                  G_CALLBACK (bluez_manager_bdaddr_removed_cb),
4515 		                  singleton);
4516 	
4517 		/* Force kernel WiFi rfkill state to follow NM saved wifi state in case
4518 		 * the BIOS doesn't save rfkill state, and to be consistent with user
4519 		 * changes to the WirelessEnabled property which toggles kernel rfkill.
4520 		 */
4521 		rfkill_change_wifi (priv->radio_states[RFKILL_TYPE_WLAN].desc, initial_wifi_enabled);
4522 	
4523 		return singleton;
4524 	}
4525 	
4526 	static void
4527 	authority_changed_cb (gpointer user_data)
4528 	{
4529 		/* Let clients know they should re-check their authorization */
4530 		g_signal_emit (NM_MANAGER (user_data), signals[CHECK_PERMISSIONS], 0);
4531 	}
4532 	
4533 	static void
4534 	dispose (GObject *object)
4535 	{
4536 		NMManager *manager = NM_MANAGER (object);
4537 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
4538 		DBusGConnection *bus;
4539 		DBusConnection *dbus_connection;
4540 		GSList *iter;
4541 	
4542 		if (priv->disposed) {
4543 			G_OBJECT_CLASS (nm_manager_parent_class)->dispose (object);
4544 			return;
4545 		}
4546 		priv->disposed = TRUE;
4547 	
4548 		g_slist_free_full (priv->auth_chains, (GDestroyNotify) nm_auth_chain_unref);
4549 	
4550 		nm_auth_changed_func_unregister (authority_changed_cb, manager);
4551 	
4552 		/* FIXME: remove when we handle bridges non-destructively */
4553 		write_nm_created_bridges (manager);
4554 	
4555 		/* Remove all devices */
4556 		while (priv->devices)
4557 			remove_device (manager, NM_DEVICE (priv->devices->data), TRUE);
4558 	
4559 		if (priv->ac_cleanup_id) {
4560 			g_source_remove (priv->ac_cleanup_id);
4561 			priv->ac_cleanup_id = 0;
4562 		}
4563 	
4564 		for (iter = priv->active_connections; iter; iter = g_slist_next (iter))
4565 			active_connection_removed (manager, NM_ACTIVE_CONNECTION (iter->data));
4566 		g_slist_free (priv->active_connections);
4567 		priv->active_connections = NULL;
4568 		g_clear_object (&priv->primary_connection);
4569 		g_clear_object (&priv->activating_connection);
4570 	
4571 		g_clear_object (&priv->connectivity);
4572 	
4573 		g_free (priv->hostname);
4574 	
4575 		g_signal_handlers_disconnect_by_func (priv->policy, G_CALLBACK (policy_default_device_changed), singleton);
4576 		g_signal_handlers_disconnect_by_func (priv->policy, G_CALLBACK (policy_activating_device_changed), singleton);
4577 		g_object_unref (priv->policy);
4578 	
4579 		g_object_unref (priv->settings);
4580 		g_object_unref (priv->vpn_manager);
4581 	
4582 		if (priv->modem_added_id) {
4583 			g_source_remove (priv->modem_added_id);
4584 			priv->modem_added_id = 0;
4585 		}
4586 		if (priv->modem_removed_id) {
4587 			g_source_remove (priv->modem_removed_id);
4588 			priv->modem_removed_id = 0;
4589 		}
4590 		g_object_unref (priv->modem_manager);
4591 	
4592 		/* Unregister property filter */
4593 		bus = nm_dbus_manager_get_connection (priv->dbus_mgr);
4594 		if (bus) {
4595 			dbus_connection = dbus_g_connection_get_connection (bus);
4596 			g_assert (dbus_connection);
4597 			dbus_connection_remove_filter (dbus_connection, prop_filter, manager);
4598 		}
4599 		g_signal_handler_disconnect (priv->dbus_mgr, priv->dbus_connection_changed_id);
4600 		priv->dbus_mgr = NULL;
4601 	
4602 		if (priv->bluez_mgr)
4603 			g_object_unref (priv->bluez_mgr);
4604 	
4605 		if (priv->aipd_proxy)
4606 			g_object_unref (priv->aipd_proxy);
4607 	
4608 		if (priv->sleep_monitor)
4609 			g_object_unref (priv->sleep_monitor);
4610 	
4611 		if (priv->fw_monitor) {
4612 			if (priv->fw_monitor_id)
4613 				g_signal_handler_disconnect (priv->fw_monitor, priv->fw_monitor_id);
4614 	
4615 			if (priv->fw_changed_id)
4616 				g_source_remove (priv->fw_changed_id);
4617 	
4618 			g_file_monitor_cancel (priv->fw_monitor);
4619 			g_object_unref (priv->fw_monitor);
4620 		}
4621 	
4622 		g_hash_table_unref (priv->noauto_sw_devices);
4623 	
4624 		g_slist_free (priv->factories);
4625 	
4626 		if (priv->timestamp_update_id) {
4627 			g_source_remove (priv->timestamp_update_id);
4628 			priv->timestamp_update_id = 0;
4629 		}
4630 	
4631 		G_OBJECT_CLASS (nm_manager_parent_class)->dispose (object);
4632 	}
4633 	
4634 	#define KERN_RFKILL_OP_CHANGE_ALL 3
4635 	#define KERN_RFKILL_TYPE_WLAN     1
4636 	struct rfkill_event {
4637 		__u32 idx;
4638 		__u8  type;
4639 		__u8  op;
4640 		__u8  soft, hard;
4641 	} __attribute__((packed));
4642 	
4643 	static void
4644 	rfkill_change_wifi (const char *desc, gboolean enabled)
4645 	{
4646 		int fd;
4647 		struct rfkill_event event;
4648 		ssize_t len;
4649 	
4650 		errno = 0;
4651 		fd = open ("/dev/rfkill", O_RDWR);
4652 		if (fd < 0) {
4653 			if (errno == EACCES)
4654 				nm_log_warn (LOGD_RFKILL, "(%s): failed to open killswitch device "
4655 				             "for WiFi radio control", desc);
4656 			return;
4657 		}
4658 	
4659 		if (fcntl (fd, F_SETFL, O_NONBLOCK) < 0) {
4660 			nm_log_warn (LOGD_RFKILL, "(%s): failed to set killswitch device for "
4661 			             "non-blocking operation", desc);
4662 			close (fd);
4663 			return;
4664 		}
4665 	
4666 		memset (&event, 0, sizeof (event));
4667 		event.op = KERN_RFKILL_OP_CHANGE_ALL;
4668 		event.type = KERN_RFKILL_TYPE_WLAN;
4669 		event.soft = enabled ? 0 : 1;
4670 	
4671 		len = write (fd, &event, sizeof (event));
4672 		if (len < 0) {
4673 			nm_log_warn (LOGD_RFKILL, "(%s): failed to change WiFi killswitch state: (%d) %s",
4674 			             desc, errno, g_strerror (errno));
4675 		} else if (len == sizeof (event)) {
4676 			nm_log_info (LOGD_RFKILL, "%s hardware radio set %s",
4677 			             desc, enabled ? "enabled" : "disabled");
4678 		} else {
4679 			/* Failed to write full structure */
4680 			nm_log_warn (LOGD_RFKILL, "(%s): failed to change WiFi killswitch state", desc);
4681 		}
4682 	
4683 		close (fd);
4684 	}
4685 	
4686 	static void
4687 	manager_radio_user_toggled (NMManager *self,
4688 	                            RadioState *rstate,
4689 	                            gboolean enabled)
4690 	{
4691 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
4692 		GError *error = NULL;
4693 		gboolean old_enabled, new_enabled;
4694 	
4695 		if (rstate->desc) {
4696 			nm_log_dbg (LOGD_RFKILL, "(%s): setting radio %s by user",
4697 			            rstate->desc,
4698 			            enabled ? "enabled" : "disabled");
4699 		}
4700 	
4701 		/* Update enabled key in state file */
4702 		if (priv->state_file) {
4703 			if (!write_value_to_state_file (priv->state_file,
4704 			                                "main", rstate->key,
4705 			                                G_TYPE_BOOLEAN, (gpointer) &enabled,
4706 			                                &error)) {
4707 				nm_log_warn (LOGD_CORE, "writing to state file %s failed: (%d) %s.",
4708 				             priv->state_file,
4709 				             error ? error->code : -1,
4710 				             (error && error->message) ? error->message : "unknown");
4711 				g_clear_error (&error);
4712 			}
4713 		}
4714 	
4715 		/* When the user toggles the radio, their request should override any
4716 		 * daemon (like ModemManager) enabled state that can be changed.  For WWAN
4717 		 * for example, we want the WwanEnabled property to reflect the daemon state
4718 		 * too so that users can toggle the modem powered, but we don't want that
4719 		 * daemon state to affect whether or not the user *can* turn it on, which is
4720 		 * what the kernel rfkill state does.  So we ignore daemon enabled state
4721 		 * when determining what the new state should be since it shouldn't block
4722 		 * the user's request.
4723 		 */
4724 		old_enabled = radio_enabled_for_rstate (rstate, TRUE);
4725 		rstate->user_enabled = enabled;
4726 		new_enabled = radio_enabled_for_rstate (rstate, FALSE);
4727 		if (new_enabled != old_enabled) {
4728 			manager_update_radio_enabled (self, rstate, new_enabled);
4729 	
4730 			/* For WiFi only (for now) set the actual kernel rfkill state */
4731 			if (rstate->rtype == RFKILL_TYPE_WLAN)
4732 				rfkill_change_wifi (rstate->desc, new_enabled);
4733 		}
4734 	}
4735 	
4736 	static void
4737 	set_property (GObject *object, guint prop_id,
4738 				  const GValue *value, GParamSpec *pspec)
4739 	{
4740 		NMManager *self = NM_MANAGER (object);
4741 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
4742 	
4743 		switch (prop_id) {
4744 		case PROP_NETWORKING_ENABLED:
4745 			/* Construct only for now */
4746 			priv->net_enabled = g_value_get_boolean (value);
4747 			break;
4748 		case PROP_WIRELESS_ENABLED:
4749 			manager_radio_user_toggled (NM_MANAGER (object),
4750 			                            &priv->radio_states[RFKILL_TYPE_WLAN],
4751 			                            g_value_get_boolean (value));
4752 			break;
4753 		case PROP_WWAN_ENABLED:
4754 			manager_radio_user_toggled (NM_MANAGER (object),
4755 			                            &priv->radio_states[RFKILL_TYPE_WWAN],
4756 			                            g_value_get_boolean (value));
4757 			break;
4758 		case PROP_WIMAX_ENABLED:
4759 			manager_radio_user_toggled (NM_MANAGER (object),
4760 			                            &priv->radio_states[RFKILL_TYPE_WIMAX],
4761 			                            g_value_get_boolean (value));
4762 			break;
4763 		default:
4764 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
4765 			break;
4766 		}
4767 	}
4768 	
4769 	static void
4770 	get_property (GObject *object, guint prop_id,
4771 				  GValue *value, GParamSpec *pspec)
4772 	{
4773 		NMManager *self = NM_MANAGER (object);
4774 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
4775 		GSList *iter;
4776 		GPtrArray *active;
4777 		const char *path;
4778 	
4779 		switch (prop_id) {
4780 		case PROP_VERSION:
4781 			g_value_set_string (value, VERSION);
4782 			break;
4783 		case PROP_STATE:
4784 			nm_manager_update_state (self);
4785 			g_value_set_uint (value, priv->state);
4786 			break;
4787 		case PROP_STARTUP:
4788 			g_value_set_boolean (value, priv->startup);
4789 			break;
4790 		case PROP_NETWORKING_ENABLED:
4791 			g_value_set_boolean (value, priv->net_enabled);
4792 			break;
4793 		case PROP_WIRELESS_ENABLED:
4794 			g_value_set_boolean (value, radio_enabled_for_type (self, RFKILL_TYPE_WLAN, TRUE));
4795 			break;
4796 		case PROP_WIRELESS_HARDWARE_ENABLED:
4797 			g_value_set_boolean (value, priv->radio_states[RFKILL_TYPE_WLAN].hw_enabled);
4798 			break;
4799 		case PROP_WWAN_ENABLED:
4800 			g_value_set_boolean (value, radio_enabled_for_type (self, RFKILL_TYPE_WWAN, TRUE));
4801 			break;
4802 		case PROP_WWAN_HARDWARE_ENABLED:
4803 			g_value_set_boolean (value, priv->radio_states[RFKILL_TYPE_WWAN].hw_enabled);
4804 			break;
4805 		case PROP_WIMAX_ENABLED:
4806 			g_value_set_boolean (value, radio_enabled_for_type (self, RFKILL_TYPE_WIMAX, TRUE));
4807 			break;
4808 		case PROP_WIMAX_HARDWARE_ENABLED:
4809 			g_value_set_boolean (value, priv->radio_states[RFKILL_TYPE_WIMAX].hw_enabled);
4810 			break;
4811 		case PROP_ACTIVE_CONNECTIONS:
4812 			active = g_ptr_array_sized_new (3);
4813 			for (iter = priv->active_connections; iter; iter = g_slist_next (iter)) {
4814 				path = nm_active_connection_get_path (NM_ACTIVE_CONNECTION (iter->data));
4815 				g_ptr_array_add (active, g_strdup (path));
4816 			}
4817 			g_value_take_boxed (value, active);
4818 			break;
4819 		case PROP_CONNECTIVITY:
4820 			g_value_set_uint (value, nm_connectivity_get_state (priv->connectivity));
4821 			break;
4822 		case PROP_PRIMARY_CONNECTION:
4823 			path = priv->primary_connection ? nm_active_connection_get_path (priv->primary_connection) : "/";
4824 			g_value_set_boxed (value, path);
4825 			break;
4826 		case PROP_ACTIVATING_CONNECTION:
4827 			path = priv->activating_connection ? nm_active_connection_get_path (priv->activating_connection) : "/";
4828 			g_value_set_boxed (value, path);
4829 			break;
4830 		case PROP_HOSTNAME:
4831 			g_value_set_string (value, priv->hostname);
4832 			break;
4833 		case PROP_SLEEPING:
4834 			g_value_set_boolean (value, priv->sleeping);
4835 			break;
4836 		default:
4837 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
4838 			break;
4839 		}
4840 	}
4841 	
4842 	static gboolean
4843 	periodic_update_active_connection_timestamps (gpointer user_data)
4844 	{
4845 		NMManager *manager = NM_MANAGER (user_data);
4846 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
4847 		GSList *iter;
4848 	
4849 		for (iter = priv->active_connections; iter; iter = g_slist_next (iter)) {
4850 			NMActiveConnection *ac = iter->data;
4851 			NMSettingsConnection *connection;
4852 	
4853 			if (nm_active_connection_get_state (ac) == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
4854 				connection = NM_SETTINGS_CONNECTION (nm_active_connection_get_connection (ac));
4855 				nm_settings_connection_update_timestamp (connection, (guint64) time (NULL), FALSE);
4856 			}
4857 		}
4858 	
4859 		return TRUE;
4860 	}
4861 	
4862 	static void
4863 	dbus_connection_changed_cb (NMDBusManager *dbus_mgr,
4864 	                            DBusConnection *dbus_connection,
4865 	                            gpointer user_data)
4866 	{
4867 		NMManager *self = NM_MANAGER (user_data);
4868 	
4869 		if (dbus_connection) {
4870 			/* Register property filter on new connection; there's no reason this
4871 			 * should fail except out-of-memory or program error; if it does fail
4872 			 * then there's no Manager property access control, which is bad.
4873 			 */
4874 			g_assert (dbus_connection_add_filter (dbus_connection, prop_filter, self, NULL));
4875 		}
4876 	}
4877 	
4878 	static void
4879 	nm_manager_init (NMManager *manager)
4880 	{
4881 		NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
4882 		DBusGConnection *g_connection;
4883 		guint i;
4884 		GFile *file;
4885 	
4886 		/* Initialize rfkill structures and states */
4887 		memset (priv->radio_states, 0, sizeof (priv->radio_states));
4888 	
4889 		priv->radio_states[RFKILL_TYPE_WLAN].user_enabled = TRUE;
4890 		priv->radio_states[RFKILL_TYPE_WLAN].key = "WirelessEnabled";
4891 		priv->radio_states[RFKILL_TYPE_WLAN].prop = NM_MANAGER_WIRELESS_ENABLED;
4892 		priv->radio_states[RFKILL_TYPE_WLAN].hw_prop = NM_MANAGER_WIRELESS_HARDWARE_ENABLED;
4893 		priv->radio_states[RFKILL_TYPE_WLAN].desc = "WiFi";
4894 		priv->radio_states[RFKILL_TYPE_WLAN].other_enabled_func = nm_manager_get_ipw_rfkill_state;
4895 		priv->radio_states[RFKILL_TYPE_WLAN].rtype = RFKILL_TYPE_WLAN;
4896 	
4897 		priv->radio_states[RFKILL_TYPE_WWAN].user_enabled = TRUE;
4898 		priv->radio_states[RFKILL_TYPE_WWAN].key = "WWANEnabled";
4899 		priv->radio_states[RFKILL_TYPE_WWAN].prop = NM_MANAGER_WWAN_ENABLED;
4900 		priv->radio_states[RFKILL_TYPE_WWAN].hw_prop = NM_MANAGER_WWAN_HARDWARE_ENABLED;
4901 		priv->radio_states[RFKILL_TYPE_WWAN].desc = "WWAN";
4902 		priv->radio_states[RFKILL_TYPE_WWAN].daemon_enabled_func = nm_manager_get_modem_enabled_state;
4903 		priv->radio_states[RFKILL_TYPE_WWAN].rtype = RFKILL_TYPE_WWAN;
4904 	
4905 		priv->radio_states[RFKILL_TYPE_WIMAX].user_enabled = TRUE;
4906 		priv->radio_states[RFKILL_TYPE_WIMAX].key = "WiMAXEnabled";
4907 		priv->radio_states[RFKILL_TYPE_WIMAX].prop = NM_MANAGER_WIMAX_ENABLED;
4908 		priv->radio_states[RFKILL_TYPE_WIMAX].hw_prop = NM_MANAGER_WIMAX_HARDWARE_ENABLED;
4909 		priv->radio_states[RFKILL_TYPE_WIMAX].desc = "WiMAX";
4910 		priv->radio_states[RFKILL_TYPE_WIMAX].other_enabled_func = NULL;
4911 		priv->radio_states[RFKILL_TYPE_WIMAX].rtype = RFKILL_TYPE_WIMAX;
4912 	
4913 		for (i = 0; i < RFKILL_TYPE_MAX; i++)
4914 			priv->radio_states[i].hw_enabled = TRUE;
4915 	
4916 		priv->sleeping = FALSE;
4917 		priv->state = NM_STATE_DISCONNECTED;
4918 		priv->startup = TRUE;
4919 	
4920 		priv->dbus_mgr = nm_dbus_manager_get ();
4921 		priv->dbus_connection_changed_id = g_signal_connect (priv->dbus_mgr,
4922 		                                                     NM_DBUS_MANAGER_DBUS_CONNECTION_CHANGED,
4923 		                                                     G_CALLBACK (dbus_connection_changed_cb),
4924 		                                                     manager);
4925 	
4926 		priv->modem_manager = nm_modem_manager_get ();
4927 		priv->modem_added_id = g_signal_connect (priv->modem_manager, "modem-added",
4928 		                                         G_CALLBACK (modem_added), manager);
4929 		priv->modem_removed_id = g_signal_connect (priv->modem_manager, "modem-removed",
4930 		                                           G_CALLBACK (modem_removed), manager);
4931 	
4932 		priv->vpn_manager = nm_vpn_manager_get ();
4933 	
4934 		g_connection = nm_dbus_manager_get_connection (priv->dbus_mgr);
4935 	
4936 		/* avahi-autoipd stuff */
4937 		priv->aipd_proxy = dbus_g_proxy_new_for_name (g_connection,
4938 		                                              NM_AUTOIP_DBUS_SERVICE,
4939 		                                              "/",
4940 		                                              NM_AUTOIP_DBUS_IFACE);
4941 		if (priv->aipd_proxy) {
4942 			dbus_g_object_register_marshaller (g_cclosure_marshal_generic,
4943 			                                   G_TYPE_NONE,
4944 			                                   G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
4945 			                                   G_TYPE_INVALID);
4946 	
4947 			dbus_g_proxy_add_signal (priv->aipd_proxy,
4948 			                         "Event",
4949 			                         G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
4950 			                         G_TYPE_INVALID);
4951 	
4952 			dbus_g_proxy_connect_signal (priv->aipd_proxy, "Event",
4953 			                             G_CALLBACK (aipd_handle_event),
4954 			                             manager,
4955 			                             NULL);
4956 		} else
4957 			nm_log_warn (LOGD_AUTOIP4, "could not initialize avahi-autoipd D-Bus proxy");
4958 	
4959 		/* sleep/wake handling */
4960 		priv->sleep_monitor = nm_sleep_monitor_get ();
4961 		g_signal_connect (priv->sleep_monitor, "sleeping",
4962 		                  G_CALLBACK (sleeping_cb), manager);
4963 		g_signal_connect (priv->sleep_monitor, "resuming",
4964 		                  G_CALLBACK (resuming_cb), manager);
4965 	
4966 		/* Listen for authorization changes */
4967 		nm_auth_changed_func_register (authority_changed_cb, manager);
4968 	
4969 		/* Monitor the firmware directory */
4970 		if (strlen (KERNEL_FIRMWARE_DIR)) {
4971 			file = g_file_new_for_path (KERNEL_FIRMWARE_DIR "/");
4972 			priv->fw_monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL);
4973 			g_object_unref (file);
4974 		}
4975 	
4976 		if (priv->fw_monitor) {
4977 			priv->fw_monitor_id = g_signal_connect (priv->fw_monitor, "changed",
4978 			                                        G_CALLBACK (firmware_dir_changed),
4979 			                                        manager);
4980 			nm_log_info (LOGD_CORE, "monitoring kernel firmware directory '%s'.",
4981 			             KERNEL_FIRMWARE_DIR);
4982 		} else {
4983 			nm_log_warn (LOGD_CORE, "failed to monitor kernel firmware directory '%s'.",
4984 			             KERNEL_FIRMWARE_DIR);
4985 		}
4986 	
4987 		/* Hash table storing software devices that should not auto activate */
4988 		priv->noauto_sw_devices = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
4989 	
4990 		load_device_factories (manager);
4991 	
4992 		/* Update timestamps in active connections */
4993 		priv->timestamp_update_id = g_timeout_add_seconds (300, (GSourceFunc) periodic_update_active_connection_timestamps, manager);
4994 	}
4995 	
4996 	static void
4997 	nm_manager_class_init (NMManagerClass *manager_class)
4998 	{
4999 		GObjectClass *object_class = G_OBJECT_CLASS (manager_class);
5000 	
5001 		g_type_class_add_private (manager_class, sizeof (NMManagerPrivate));
5002 	
5003 		/* virtual methods */
5004 		object_class->set_property = set_property;
5005 		object_class->get_property = get_property;
5006 		object_class->dispose = dispose;
5007 	
5008 		/* properties */
5009 		g_object_class_install_property
5010 			(object_class, PROP_VERSION,
5011 			 g_param_spec_string (NM_MANAGER_VERSION,
5012 			                      "Version",
5013 			                      "NetworkManager version",
5014 			                      NULL,
5015 			                      G_PARAM_READABLE));
5016 	
5017 		g_object_class_install_property
5018 			(object_class, PROP_STATE,
5019 			 g_param_spec_uint (NM_MANAGER_STATE,
5020 			                    "State",
5021 			                    "Current state",
5022 			                    0, NM_STATE_DISCONNECTED, 0,
5023 			                    G_PARAM_READABLE));
5024 	
5025 		g_object_class_install_property
5026 			(object_class, PROP_STARTUP,
5027 			 g_param_spec_boolean (NM_MANAGER_STARTUP,
5028 			                       "Startup",
5029 			                       "Is NetworkManager still starting up",
5030 			                       TRUE,
5031 			                       G_PARAM_READABLE));
5032 	
5033 		g_object_class_install_property
5034 			(object_class, PROP_NETWORKING_ENABLED,
5035 			 g_param_spec_boolean (NM_MANAGER_NETWORKING_ENABLED,
5036 			                       "NetworkingEnabled",
5037 			                       "Is networking enabled",
5038 			                       TRUE,
5039 			                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
5040 	
5041 		g_object_class_install_property
5042 			(object_class, PROP_WIRELESS_ENABLED,
5043 			 g_param_spec_boolean (NM_MANAGER_WIRELESS_ENABLED,
5044 			                       "WirelessEnabled",
5045 			                       "Is wireless enabled",
5046 			                       TRUE,
5047 			                       G_PARAM_READWRITE));
5048 	
5049 		g_object_class_install_property
5050 			(object_class, PROP_WIRELESS_HARDWARE_ENABLED,
5051 			 g_param_spec_boolean (NM_MANAGER_WIRELESS_HARDWARE_ENABLED,
5052 			                       "WirelessHardwareEnabled",
5053 			                       "RF kill state",
5054 			                       TRUE,
5055 			                       G_PARAM_READABLE));
5056 	
5057 		g_object_class_install_property
5058 			(object_class, PROP_WWAN_ENABLED,
5059 			 g_param_spec_boolean (NM_MANAGER_WWAN_ENABLED,
5060 			                       "WwanEnabled",
5061 			                       "Is mobile broadband enabled",
5062 			                       TRUE,
5063 			                       G_PARAM_READWRITE));
5064 	
5065 		g_object_class_install_property
5066 			(object_class, PROP_WWAN_HARDWARE_ENABLED,
5067 			 g_param_spec_boolean (NM_MANAGER_WWAN_HARDWARE_ENABLED,
5068 			                       "WwanHardwareEnabled",
5069 			                       "Whether WWAN is disabled by a hardware switch or not",
5070 			                       TRUE,
5071 			                       G_PARAM_READABLE));
5072 	
5073 		g_object_class_install_property
5074 			(object_class, PROP_WIMAX_ENABLED,
5075 			 g_param_spec_boolean (NM_MANAGER_WIMAX_ENABLED,
5076 			                       "WimaxEnabled",
5077 			                       "Is WiMAX enabled",
5078 			                       TRUE,
5079 			                       G_PARAM_READWRITE));
5080 	
5081 		g_object_class_install_property
5082 			(object_class, PROP_WIMAX_HARDWARE_ENABLED,
5083 			 g_param_spec_boolean (NM_MANAGER_WIMAX_HARDWARE_ENABLED,
5084 			                       "WimaxHardwareEnabled",
5085 			                       "Whether WiMAX is disabled by a hardware switch or not",
5086 			                       TRUE,
5087 			                       G_PARAM_READABLE));
5088 	
5089 		g_object_class_install_property
5090 			(object_class, PROP_ACTIVE_CONNECTIONS,
5091 			 g_param_spec_boxed (NM_MANAGER_ACTIVE_CONNECTIONS,
5092 			                     "Active connections",
5093 			                     "Active connections",
5094 			                     DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH,
5095 			                     G_PARAM_READABLE));
5096 	
5097 		g_object_class_install_property
5098 			(object_class, PROP_CONNECTIVITY,
5099 			 g_param_spec_uint (NM_MANAGER_CONNECTIVITY,
5100 			                    "Connectivity",
5101 			                    "Connectivity state",
5102 			                    NM_CONNECTIVITY_UNKNOWN, NM_CONNECTIVITY_FULL, NM_CONNECTIVITY_UNKNOWN,
5103 			                    G_PARAM_READABLE));
5104 	
5105 		g_object_class_install_property
5106 			(object_class, PROP_PRIMARY_CONNECTION,
5107 			 g_param_spec_boxed (NM_MANAGER_PRIMARY_CONNECTION,
5108 			                     "Primary connection",
5109 			                     "Primary connection",
5110 			                     DBUS_TYPE_G_OBJECT_PATH,
5111 			                     G_PARAM_READABLE));
5112 	
5113 		g_object_class_install_property
5114 			(object_class, PROP_ACTIVATING_CONNECTION,
5115 			 g_param_spec_boxed (NM_MANAGER_ACTIVATING_CONNECTION,
5116 			                     "Activating connection",
5117 			                     "Activating connection",
5118 			                     DBUS_TYPE_G_OBJECT_PATH,
5119 			                     G_PARAM_READABLE));
5120 	
5121 		/* Hostname is not exported over D-Bus */
5122 		g_object_class_install_property
5123 			(object_class, PROP_HOSTNAME,
5124 			 g_param_spec_string (NM_MANAGER_HOSTNAME,
5125 			                      "Hostname",
5126 			                      "Hostname",
5127 			                      NULL,
5128 			                      G_PARAM_READABLE));
5129 	
5130 		/* Sleeping is not exported over D-Bus */
5131 		g_object_class_install_property
5132 			(object_class, PROP_SLEEPING,
5133 			 g_param_spec_boolean (NM_MANAGER_SLEEPING,
5134 			                       "Sleeping",
5135 			                       "Sleeping",
5136 			                       FALSE,
5137 			                       G_PARAM_READABLE));
5138 	
5139 		/* signals */
5140 		signals[DEVICE_ADDED] =
5141 			g_signal_new ("device-added",
5142 			              G_OBJECT_CLASS_TYPE (object_class),
5143 			              G_SIGNAL_RUN_FIRST,
5144 			              G_STRUCT_OFFSET (NMManagerClass, device_added),
5145 			              NULL, NULL, NULL,
5146 			              G_TYPE_NONE, 1, G_TYPE_OBJECT);
5147 	
5148 		signals[DEVICE_REMOVED] =
5149 			g_signal_new ("device-removed",
5150 			              G_OBJECT_CLASS_TYPE (object_class),
5151 			              G_SIGNAL_RUN_FIRST,
5152 			              G_STRUCT_OFFSET (NMManagerClass, device_removed),
5153 			              NULL, NULL, NULL,
5154 			              G_TYPE_NONE, 1, G_TYPE_OBJECT);
5155 	
5156 		signals[STATE_CHANGED] =
5157 			g_signal_new ("state-changed",
5158 			              G_OBJECT_CLASS_TYPE (object_class),
5159 			              G_SIGNAL_RUN_FIRST,
5160 			              G_STRUCT_OFFSET (NMManagerClass, state_changed),
5161 			              NULL, NULL, NULL,
5162 			              G_TYPE_NONE, 1, G_TYPE_UINT);
5163 	
5164 		signals[CHECK_PERMISSIONS] =
5165 			g_signal_new ("check-permissions",
5166 			              G_OBJECT_CLASS_TYPE (object_class),
5167 			              G_SIGNAL_RUN_FIRST,
5168 			              0, NULL, NULL, NULL,
5169 			              G_TYPE_NONE, 0);
5170 	
5171 		signals[USER_PERMISSIONS_CHANGED] =
5172 			g_signal_new ("user-permissions-changed",
5173 			              G_OBJECT_CLASS_TYPE (object_class),
5174 			              G_SIGNAL_RUN_FIRST,
5175 			              0, NULL, NULL, NULL,
5176 			              G_TYPE_NONE, 0);
5177 	
5178 		signals[ACTIVE_CONNECTION_ADDED] =
5179 			g_signal_new (NM_MANAGER_ACTIVE_CONNECTION_ADDED,
5180 			              G_OBJECT_CLASS_TYPE (object_class),
5181 			              G_SIGNAL_RUN_FIRST,
5182 			              0, NULL, NULL, NULL,
5183 			              G_TYPE_NONE, 1, G_TYPE_OBJECT);
5184 	
5185 		signals[ACTIVE_CONNECTION_REMOVED] =
5186 			g_signal_new (NM_MANAGER_ACTIVE_CONNECTION_REMOVED,
5187 			              G_OBJECT_CLASS_TYPE (object_class),
5188 			              G_SIGNAL_RUN_FIRST,
5189 			              0, NULL, NULL, NULL,
5190 			              G_TYPE_NONE, 1, G_TYPE_OBJECT);
5191 	
5192 		nm_dbus_manager_register_exported_type (nm_dbus_manager_get (),
5193 		                                        G_TYPE_FROM_CLASS (manager_class),
5194 		                                        &dbus_glib_nm_manager_object_info);
5195 	
5196 		dbus_g_error_domain_register (NM_MANAGER_ERROR, NULL, NM_TYPE_MANAGER_ERROR);
5197 		dbus_g_error_domain_register (NM_LOGGING_ERROR, "org.freedesktop.NetworkManager.Logging", NM_TYPE_LOGGING_ERROR);
5198 	}
5199 	
5200