device: renew dhcp leases on awake for software devices
[NetworkManager.git] / libnm / nm-manager.c
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 /*
3  * This library is free software; you can redistribute it and/or
4  * modify it under the terms of the GNU Lesser General Public
5  * License as published by the Free Software Foundation; either
6  * version 2 of the License, or (at your option) any later version.
7  *
8  * This library is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public
14  * License along with this library; if not, write to the
15  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16  * Boston, MA 02110-1301 USA.
17  *
18  * Copyright 2007 - 2008 Novell, Inc.
19  * Copyright 2007 - 2014 Red Hat, Inc.
20  */
21
22 #include "nm-default.h"
23
24 #include "nm-manager.h"
25
26 #include <string.h>
27
28 #include "nm-utils.h"
29 #include "nm-device-ethernet.h"
30 #include "nm-device-wifi.h"
31 #include "nm-device-private.h"
32 #include "nm-core-internal.h"
33 #include "nm-object-private.h"
34 #include "nm-active-connection.h"
35 #include "nm-vpn-connection.h"
36 #include "nm-object-cache.h"
37 #include "nm-dbus-helpers.h"
38
39 #include "nmdbus-manager.h"
40
41 void _nm_device_wifi_set_wireless_enabled (NMDeviceWifi *device, gboolean enabled);
42
43 static void nm_manager_initable_iface_init (GInitableIface *iface);
44 static void nm_manager_async_initable_iface_init (GAsyncInitableIface *iface);
45 static GInitableIface *nm_manager_parent_initable_iface;
46 static GAsyncInitableIface *nm_manager_parent_async_initable_iface;
47
48 G_DEFINE_TYPE_WITH_CODE (NMManager, nm_manager, NM_TYPE_OBJECT,
49                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_manager_initable_iface_init);
50                          G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_manager_async_initable_iface_init);
51                          )
52
53 #define NM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MANAGER, NMManagerPrivate))
54
55 typedef struct {
56         NMDBusManager *manager_proxy;
57         GCancellable *props_cancellable;
58         char *version;
59         NMState state;
60         gboolean startup;
61         GPtrArray *devices;
62         GPtrArray *all_devices;
63         GPtrArray *active_connections;
64         NMConnectivityState connectivity;
65         NMActiveConnection *primary_connection;
66         NMActiveConnection *activating_connection;
67         NMMetered metered;
68
69         GCancellable *perm_call_cancellable;
70         GHashTable *permissions;
71
72         /* Activations waiting for their NMActiveConnection
73          * to appear and then their callback to be called.
74          */
75         GSList *pending_activations;
76
77         gboolean networking_enabled;
78         gboolean wireless_enabled;
79         gboolean wireless_hw_enabled;
80
81         gboolean wwan_enabled;
82         gboolean wwan_hw_enabled;
83
84         gboolean wimax_enabled;
85         gboolean wimax_hw_enabled;
86 } NMManagerPrivate;
87
88 enum {
89         PROP_0,
90         PROP_VERSION,
91         PROP_STATE,
92         PROP_STARTUP,
93         PROP_NM_RUNNING,
94         PROP_NETWORKING_ENABLED,
95         PROP_WIRELESS_ENABLED,
96         PROP_WIRELESS_HARDWARE_ENABLED,
97         PROP_WWAN_ENABLED,
98         PROP_WWAN_HARDWARE_ENABLED,
99         PROP_WIMAX_ENABLED,
100         PROP_WIMAX_HARDWARE_ENABLED,
101         PROP_ACTIVE_CONNECTIONS,
102         PROP_CONNECTIVITY,
103         PROP_PRIMARY_CONNECTION,
104         PROP_ACTIVATING_CONNECTION,
105         PROP_DEVICES,
106         PROP_METERED,
107         PROP_ALL_DEVICES,
108
109         LAST_PROP
110 };
111
112 enum {
113         DEVICE_ADDED,
114         DEVICE_REMOVED,
115         ANY_DEVICE_ADDED,
116         ANY_DEVICE_REMOVED,
117         ACTIVE_CONNECTION_ADDED,
118         ACTIVE_CONNECTION_REMOVED,
119         PERMISSION_CHANGED,
120
121         LAST_SIGNAL
122 };
123
124 static guint signals[LAST_SIGNAL] = { 0 };
125
126 static void nm_running_changed_cb (GObject *object,
127                                    GParamSpec *pspec,
128                                    gpointer user_data);
129
130 /**********************************************************************/
131
132 static void
133 nm_manager_init (NMManager *manager)
134 {
135         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
136
137         priv->state = NM_STATE_UNKNOWN;
138         priv->connectivity = NM_CONNECTIVITY_UNKNOWN;
139
140         priv->permissions = g_hash_table_new (g_direct_hash, g_direct_equal);
141         priv->devices = g_ptr_array_new ();
142         priv->all_devices = g_ptr_array_new ();
143         priv->active_connections = g_ptr_array_new ();
144 }
145
146 static void
147 poke_wireless_devices_with_rf_status (NMManager *manager)
148 {
149         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
150         int i;
151
152         for (i = 0; i < priv->all_devices->len; i++) {
153                 NMDevice *device = g_ptr_array_index (priv->all_devices, i);
154
155                 if (NM_IS_DEVICE_WIFI (device))
156                         _nm_device_wifi_set_wireless_enabled (NM_DEVICE_WIFI (device), priv->wireless_enabled);
157         }
158 }
159
160 static void
161 wireless_enabled_cb (GObject *object, GParamSpec *pspec, gpointer user_data)
162 {
163         poke_wireless_devices_with_rf_status (NM_MANAGER (object));
164 }
165
166 static void manager_recheck_permissions (NMDBusManager *proxy, gpointer user_data);
167
168 static void
169 init_dbus (NMObject *object)
170 {
171         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (object);
172         const NMPropertiesInfo property_info[] = {
173                 { NM_MANAGER_VERSION,                   &priv->version },
174                 { NM_MANAGER_STATE,                     &priv->state },
175                 { NM_MANAGER_STARTUP,                   &priv->startup },
176                 { NM_MANAGER_NETWORKING_ENABLED,        &priv->networking_enabled },
177                 { NM_MANAGER_WIRELESS_ENABLED,          &priv->wireless_enabled },
178                 { NM_MANAGER_WIRELESS_HARDWARE_ENABLED, &priv->wireless_hw_enabled },
179                 { NM_MANAGER_WWAN_ENABLED,              &priv->wwan_enabled },
180                 { NM_MANAGER_WWAN_HARDWARE_ENABLED,     &priv->wwan_hw_enabled },
181                 { NM_MANAGER_WIMAX_ENABLED,             &priv->wimax_enabled },
182                 { NM_MANAGER_WIMAX_HARDWARE_ENABLED,    &priv->wimax_hw_enabled },
183                 { NM_MANAGER_ACTIVE_CONNECTIONS,        &priv->active_connections, NULL, NM_TYPE_ACTIVE_CONNECTION, "active-connection" },
184                 { NM_MANAGER_CONNECTIVITY,              &priv->connectivity },
185                 { NM_MANAGER_PRIMARY_CONNECTION,        &priv->primary_connection, NULL, NM_TYPE_ACTIVE_CONNECTION },
186                 { NM_MANAGER_ACTIVATING_CONNECTION,     &priv->activating_connection, NULL, NM_TYPE_ACTIVE_CONNECTION },
187                 { NM_MANAGER_DEVICES,                   &priv->devices, NULL, NM_TYPE_DEVICE, "device" },
188                 { NM_MANAGER_METERED,                   &priv->metered },
189                 { NM_MANAGER_ALL_DEVICES,               &priv->all_devices, NULL, NM_TYPE_DEVICE, "any-device" },
190                 { NULL },
191         };
192
193         NM_OBJECT_CLASS (nm_manager_parent_class)->init_dbus (object);
194
195         priv->manager_proxy = NMDBUS_MANAGER (_nm_object_get_proxy (object, NM_DBUS_INTERFACE));
196         _nm_object_register_properties (object,
197                                         NM_DBUS_INTERFACE,
198                                         property_info);
199
200         /* Permissions */
201         g_signal_connect (priv->manager_proxy, "check-permissions",
202                           G_CALLBACK (manager_recheck_permissions), object);
203 }
204
205 #define NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK     "org.freedesktop.NetworkManager.enable-disable-network"
206 #define NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI        "org.freedesktop.NetworkManager.enable-disable-wifi"
207 #define NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN        "org.freedesktop.NetworkManager.enable-disable-wwan"
208 #define NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX       "org.freedesktop.NetworkManager.enable-disable-wimax"
209 #define NM_AUTH_PERMISSION_SLEEP_WAKE                 "org.freedesktop.NetworkManager.sleep-wake"
210 #define NM_AUTH_PERMISSION_NETWORK_CONTROL            "org.freedesktop.NetworkManager.network-control"
211 #define NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED       "org.freedesktop.NetworkManager.wifi.share.protected"
212 #define NM_AUTH_PERMISSION_WIFI_SHARE_OPEN            "org.freedesktop.NetworkManager.wifi.share.open"
213 #define NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM     "org.freedesktop.NetworkManager.settings.modify.system"
214 #define NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN        "org.freedesktop.NetworkManager.settings.modify.own"
215 #define NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME   "org.freedesktop.NetworkManager.settings.modify.hostname"
216
217 static NMClientPermission
218 nm_permission_to_client (const char *nm)
219 {
220         if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK))
221                 return NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK;
222         else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI))
223                 return NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI;
224         else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN))
225                 return NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN;
226         else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX))
227                 return NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX;
228         else if (!strcmp (nm, NM_AUTH_PERMISSION_SLEEP_WAKE))
229                 return NM_CLIENT_PERMISSION_SLEEP_WAKE;
230         else if (!strcmp (nm, NM_AUTH_PERMISSION_NETWORK_CONTROL))
231                 return NM_CLIENT_PERMISSION_NETWORK_CONTROL;
232         else if (!strcmp (nm, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED))
233                 return NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED;
234         else if (!strcmp (nm, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN))
235                 return NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN;
236         else if (!strcmp (nm, NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM))
237                 return NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM;
238         else if (!strcmp (nm, NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN))
239                 return NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN;
240         else if (!strcmp (nm, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME))
241                 return NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME;
242
243         return NM_CLIENT_PERMISSION_NONE;
244 }
245
246 static NMClientPermissionResult
247 nm_permission_result_to_client (const char *nm)
248 {
249         if (!strcmp (nm, "yes"))
250                 return NM_CLIENT_PERMISSION_RESULT_YES;
251         else if (!strcmp (nm, "no"))
252                 return NM_CLIENT_PERMISSION_RESULT_NO;
253         else if (!strcmp (nm, "auth"))
254                 return NM_CLIENT_PERMISSION_RESULT_AUTH;
255         return NM_CLIENT_PERMISSION_RESULT_UNKNOWN;
256 }
257
258 static void
259 update_permissions (NMManager *self, GVariant *permissions)
260 {
261         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
262         GHashTableIter iter;
263         gpointer key, value;
264         NMClientPermission perm;
265         NMClientPermissionResult perm_result;
266         GList *keys, *keys_iter;
267
268         /* get list of old permissions for change notification */
269         keys = g_hash_table_get_keys (priv->permissions);
270         g_hash_table_remove_all (priv->permissions);
271
272         if (permissions) {
273                 GVariantIter viter;
274                 const char *pkey, *pvalue;
275
276                 /* Process new permissions */
277                 g_variant_iter_init (&viter, permissions);
278                 while (g_variant_iter_next (&viter, "{&s&s}", &pkey, &pvalue)) {
279                         perm = nm_permission_to_client (pkey);
280                         perm_result = nm_permission_result_to_client (pvalue);
281                         if (perm) {
282                                 g_hash_table_insert (priv->permissions,
283                                                      GUINT_TO_POINTER (perm),
284                                                      GUINT_TO_POINTER (perm_result));
285
286                                 /* Remove this permission from the list of previous permissions
287                                  * we'll be sending NM_CLIENT_PERMISSION_RESULT_UNKNOWN for
288                                  * in the change signal since it is still a known permission.
289                                  */
290                                 keys = g_list_remove (keys, GUINT_TO_POINTER (perm));
291                         }
292                 }
293         }
294
295         /* Signal changes in all updated permissions */
296         g_hash_table_iter_init (&iter, priv->permissions);
297         while (g_hash_table_iter_next (&iter, &key, &value)) {
298                 g_signal_emit (self, signals[PERMISSION_CHANGED], 0,
299                                GPOINTER_TO_UINT (key),
300                                GPOINTER_TO_UINT (value));
301         }
302
303         /* And signal changes in all permissions that used to be valid but for
304          * some reason weren't received in the last request (if any).
305          */
306         for (keys_iter = keys; keys_iter; keys_iter = g_list_next (keys_iter)) {
307                 g_signal_emit (self, signals[PERMISSION_CHANGED], 0,
308                                GPOINTER_TO_UINT (keys_iter->data),
309                                NM_CLIENT_PERMISSION_RESULT_UNKNOWN);
310         }
311         g_list_free (keys);
312 }
313
314 static gboolean
315 get_permissions_sync (NMManager *self, GError **error)
316 {
317         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
318         GVariant *permissions;
319
320         if (nmdbus_manager_call_get_permissions_sync (priv->manager_proxy,
321                                                       &permissions,
322                                                       NULL, error)) {
323                 update_permissions (self, permissions);
324                 g_variant_unref (permissions);
325                 return TRUE;
326         } else {
327                 if (error && *error)
328                         g_dbus_error_strip_remote_error (*error);
329                 update_permissions (self, NULL);
330                 return FALSE;
331         }
332 }
333
334 static void
335 get_permissions_reply (GObject *object,
336                        GAsyncResult *result,
337                        gpointer user_data)
338 {
339         NMManager *self;
340         NMManagerPrivate *priv;
341         GVariant *permissions = NULL;
342         GError *error = NULL;
343
344         /* WARNING: this may be called after the manager is disposed, so we can't
345          * look at self/priv until after we've determined that that isn't the case.
346          */
347
348         nmdbus_manager_call_get_permissions_finish (NMDBUS_MANAGER (object),
349                                                     &permissions,
350                                                     result, &error);
351         if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
352                 /* @self has been disposed. */
353                 g_error_free (error);
354                 return;
355         }
356
357         self = user_data;
358         priv = NM_MANAGER_GET_PRIVATE (self);
359
360         update_permissions (self, permissions);
361
362         g_clear_pointer (&permissions, g_variant_unref);
363         g_clear_error (&error);
364         g_clear_object (&priv->perm_call_cancellable);
365 }
366
367 static void
368 manager_recheck_permissions (NMDBusManager *proxy, gpointer user_data)
369 {
370         NMManager *self = NM_MANAGER (user_data);
371         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
372
373         if (priv->perm_call_cancellable)
374                 return;
375
376         priv->perm_call_cancellable = g_cancellable_new ();
377         nmdbus_manager_call_get_permissions (priv->manager_proxy,
378                                              priv->perm_call_cancellable,
379                                              get_permissions_reply,
380                                              self);
381 }
382
383 const char *
384 nm_manager_get_version (NMManager *manager)
385 {
386         g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
387
388         return NM_MANAGER_GET_PRIVATE (manager)->version;
389 }
390
391 NMState
392 nm_manager_get_state (NMManager *manager)
393 {
394         g_return_val_if_fail (NM_IS_MANAGER (manager), NM_STATE_UNKNOWN);
395
396         return NM_MANAGER_GET_PRIVATE (manager)->state;
397 }
398
399 gboolean
400 nm_manager_get_startup (NMManager *manager)
401 {
402         g_return_val_if_fail (NM_IS_MANAGER (manager), NM_STATE_UNKNOWN);
403
404         return NM_MANAGER_GET_PRIVATE (manager)->startup;
405 }
406
407 gboolean
408 nm_manager_get_nm_running (NMManager *manager)
409 {
410         g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE);
411
412         return _nm_object_get_nm_running (NM_OBJECT (manager));
413 }
414
415 gboolean
416 nm_manager_networking_get_enabled (NMManager *manager)
417 {
418         g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE);
419
420         return NM_MANAGER_GET_PRIVATE (manager)->networking_enabled;
421 }
422
423 gboolean
424 nm_manager_networking_set_enabled (NMManager *manager, gboolean enable, GError **error)
425 {
426         gboolean ret;
427
428         g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE);
429
430         ret = nmdbus_manager_call_enable_sync (NM_MANAGER_GET_PRIVATE (manager)->manager_proxy,
431                                                enable,
432                                                NULL, error);
433         if (error && *error)
434                 g_dbus_error_strip_remote_error (*error);
435         return ret;
436 }
437
438 gboolean
439 nm_manager_wireless_get_enabled (NMManager *manager)
440 {
441         g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE);
442
443         return NM_MANAGER_GET_PRIVATE (manager)->wireless_enabled;
444 }
445
446 void
447 nm_manager_wireless_set_enabled (NMManager *manager, gboolean enabled)
448 {
449         g_return_if_fail (NM_IS_MANAGER (manager));
450
451         _nm_object_set_property (NM_OBJECT (manager),
452                                  NM_DBUS_INTERFACE,
453                                  "WirelessEnabled",
454                                  "b", enabled);
455 }
456
457 gboolean
458 nm_manager_wireless_hardware_get_enabled (NMManager *manager)
459 {
460         g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE);
461
462         return NM_MANAGER_GET_PRIVATE (manager)->wireless_hw_enabled;
463 }
464
465 gboolean
466 nm_manager_wwan_get_enabled (NMManager *manager)
467 {
468         g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE);
469
470         return NM_MANAGER_GET_PRIVATE (manager)->wwan_enabled;
471 }
472
473 void
474 nm_manager_wwan_set_enabled (NMManager *manager, gboolean enabled)
475 {
476         g_return_if_fail (NM_IS_MANAGER (manager));
477
478         _nm_object_set_property (NM_OBJECT (manager),
479                                  NM_DBUS_INTERFACE,
480                                  "WwanEnabled",
481                                  "b", enabled);
482 }
483
484 gboolean
485 nm_manager_wwan_hardware_get_enabled (NMManager *manager)
486 {
487         g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE);
488
489         return NM_MANAGER_GET_PRIVATE (manager)->wwan_hw_enabled;
490 }
491
492 gboolean
493 nm_manager_wimax_get_enabled (NMManager *manager)
494 {
495         g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE);
496
497         return NM_MANAGER_GET_PRIVATE (manager)->wimax_enabled;
498 }
499
500 void
501 nm_manager_wimax_set_enabled (NMManager *manager, gboolean enabled)
502 {
503         g_return_if_fail (NM_IS_MANAGER (manager));
504
505         _nm_object_set_property (NM_OBJECT (manager),
506                                  NM_DBUS_INTERFACE,
507                                  "WimaxEnabled",
508                                  "b", enabled);
509 }
510
511 gboolean
512 nm_manager_wimax_hardware_get_enabled (NMManager *manager)
513 {
514         g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE);
515
516         return NM_MANAGER_GET_PRIVATE (manager)->wimax_hw_enabled;
517 }
518
519 gboolean
520 nm_manager_get_logging (NMManager *manager, char **level, char **domains, GError **error)
521 {
522         gboolean ret;
523
524         g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE);
525         g_return_val_if_fail (level == NULL || *level == NULL, FALSE);
526         g_return_val_if_fail (domains == NULL || *domains == NULL, FALSE);
527         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
528
529         if (!level && !domains)
530                 return TRUE;
531
532         ret = nmdbus_manager_call_get_logging_sync (NM_MANAGER_GET_PRIVATE (manager)->manager_proxy,
533                                                     level, domains,
534                                                     NULL, error);
535         if (error && *error)
536                 g_dbus_error_strip_remote_error (*error);
537         return ret;
538 }
539
540 gboolean
541 nm_manager_set_logging (NMManager *manager, const char *level, const char *domains, GError **error)
542 {
543         gboolean ret;
544
545         g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE);
546         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
547
548         if (!level && !domains)
549                 return TRUE;
550
551         if (!level)
552                 level = "";
553         if (!domains)
554                 domains = "";
555
556         ret = nmdbus_manager_call_set_logging_sync (NM_MANAGER_GET_PRIVATE (manager)->manager_proxy,
557                                                     level, domains,
558                                                     NULL, error);
559         if (error && *error)
560                 g_dbus_error_strip_remote_error (*error);
561         return ret;
562 }
563
564 NMClientPermissionResult
565 nm_manager_get_permission_result (NMManager *manager, NMClientPermission permission)
566 {
567         gpointer result;
568
569         g_return_val_if_fail (NM_IS_MANAGER (manager), NM_CLIENT_PERMISSION_RESULT_UNKNOWN);
570
571         result = g_hash_table_lookup (NM_MANAGER_GET_PRIVATE (manager)->permissions,
572                                       GUINT_TO_POINTER (permission));
573         return GPOINTER_TO_UINT (result);
574 }
575
576 NMConnectivityState
577 nm_manager_get_connectivity (NMManager *manager)
578 {
579         g_return_val_if_fail (NM_IS_MANAGER (manager), NM_CONNECTIVITY_UNKNOWN);
580
581         return NM_MANAGER_GET_PRIVATE (manager)->connectivity;
582 }
583
584 NMConnectivityState
585 nm_manager_check_connectivity (NMManager *manager,
586                                GCancellable *cancellable,
587                                GError **error)
588 {
589         NMManagerPrivate *priv;
590         guint32 connectivity;
591
592         g_return_val_if_fail (NM_IS_MANAGER (manager), NM_CONNECTIVITY_UNKNOWN);
593         priv = NM_MANAGER_GET_PRIVATE (manager);
594
595         if (nmdbus_manager_call_check_connectivity_sync (priv->manager_proxy,
596                                                          &connectivity,
597                                                          cancellable, error))
598                 return connectivity;
599         else {
600                 if (error && *error)
601                         g_dbus_error_strip_remote_error (*error);
602                 return NM_CONNECTIVITY_UNKNOWN;
603         }
604 }
605
606 static void
607 check_connectivity_cb (GObject *object,
608                        GAsyncResult *result,
609                        gpointer user_data)
610 {
611         GSimpleAsyncResult *simple = user_data;
612         guint32 connectivity;
613         GError *error = NULL;
614
615         if (nmdbus_manager_call_check_connectivity_finish (NMDBUS_MANAGER (object),
616                                                            &connectivity,
617                                                            result, &error))
618                 g_simple_async_result_set_op_res_gssize (simple, connectivity);
619         else {
620                 g_dbus_error_strip_remote_error (error);
621                 g_simple_async_result_take_error (simple, error);
622         }
623
624         g_simple_async_result_complete (simple);
625         g_object_unref (simple);
626 }
627
628 void
629 nm_manager_check_connectivity_async (NMManager *manager,
630                                      GCancellable *cancellable,
631                                      GAsyncReadyCallback callback,
632                                      gpointer user_data)
633 {
634         NMManagerPrivate *priv;
635         GSimpleAsyncResult *simple;
636
637         g_return_if_fail (NM_IS_MANAGER (manager));
638         priv = NM_MANAGER_GET_PRIVATE (manager);
639
640         simple = g_simple_async_result_new (G_OBJECT (manager), callback, user_data,
641                                             nm_manager_check_connectivity_async);
642         nmdbus_manager_call_check_connectivity (priv->manager_proxy,
643                                                 cancellable,
644                                                 check_connectivity_cb, simple);
645 }
646
647 NMConnectivityState
648 nm_manager_check_connectivity_finish (NMManager *manager,
649                                       GAsyncResult *result,
650                                       GError **error)
651 {
652         GSimpleAsyncResult *simple;
653
654         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (manager), nm_manager_check_connectivity_async), NM_CONNECTIVITY_UNKNOWN);
655
656         simple = G_SIMPLE_ASYNC_RESULT (result);
657
658         if (g_simple_async_result_propagate_error (simple, error))
659                 return NM_CONNECTIVITY_UNKNOWN;
660         return (NMConnectivityState) g_simple_async_result_get_op_res_gssize (simple);
661 }
662
663 /****************************************************************/
664 /* Devices                                                      */
665 /****************************************************************/
666
667 const GPtrArray *
668 nm_manager_get_devices (NMManager *manager)
669 {
670         g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
671
672         return NM_MANAGER_GET_PRIVATE (manager)->devices;
673 }
674
675 const GPtrArray *
676 nm_manager_get_all_devices (NMManager *manager)
677 {
678         g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
679
680         return NM_MANAGER_GET_PRIVATE (manager)->all_devices;
681 }
682
683 NMDevice *
684 nm_manager_get_device_by_path (NMManager *manager, const char *object_path)
685 {
686         const GPtrArray *devices;
687         int i;
688         NMDevice *device = NULL;
689
690         g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
691         g_return_val_if_fail (object_path, NULL);
692
693         devices = nm_manager_get_devices (manager);
694         for (i = 0; i < devices->len; i++) {
695                 NMDevice *candidate = g_ptr_array_index (devices, i);
696                 if (!strcmp (nm_object_get_path (NM_OBJECT (candidate)), object_path)) {
697                         device = candidate;
698                         break;
699                 }
700         }
701
702         return device;
703 }
704
705 NMDevice *
706 nm_manager_get_device_by_iface (NMManager *manager, const char *iface)
707 {
708         const GPtrArray *devices;
709         int i;
710         NMDevice *device = NULL;
711
712         g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
713         g_return_val_if_fail (iface, NULL);
714
715         devices = nm_manager_get_devices (manager);
716         for (i = 0; i < devices->len; i++) {
717                 NMDevice *candidate = g_ptr_array_index (devices, i);
718                 if (!strcmp (nm_device_get_iface (candidate), iface)) {
719                         device = candidate;
720                         break;
721                 }
722         }
723
724         return device;
725 }
726
727 /****************************************************************/
728 /* Active Connections                                           */
729 /****************************************************************/
730
731 const GPtrArray *
732 nm_manager_get_active_connections (NMManager *manager)
733 {
734         g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
735
736         return NM_MANAGER_GET_PRIVATE (manager)->active_connections;
737 }
738
739 NMActiveConnection *
740 nm_manager_get_primary_connection (NMManager *manager)
741 {
742         g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
743
744         return NM_MANAGER_GET_PRIVATE (manager)->primary_connection;
745 }
746
747 NMActiveConnection *
748 nm_manager_get_activating_connection (NMManager *manager)
749 {
750         g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
751
752         return NM_MANAGER_GET_PRIVATE (manager)->activating_connection;
753 }
754
755 typedef struct {
756         NMManager *manager;
757         GSimpleAsyncResult *simple;
758         GCancellable *cancellable;
759         gulong cancelled_id;
760         char *active_path;
761         char *new_connection_path;
762 } ActivateInfo;
763
764 static void active_removed (NMObject *object, NMActiveConnection *active, gpointer user_data);
765
766 static void
767 activate_info_complete (ActivateInfo *info,
768                         NMActiveConnection *active,
769                         GError *error)
770 {
771         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (info->manager);
772
773         g_signal_handlers_disconnect_by_func (info->manager, G_CALLBACK (active_removed), info);
774         if (active)
775                 g_simple_async_result_set_op_res_gpointer (info->simple, g_object_ref (active), g_object_unref);
776         else
777                 g_simple_async_result_set_from_error (info->simple, error);
778         g_simple_async_result_complete (info->simple);
779
780         priv->pending_activations = g_slist_remove (priv->pending_activations, info);
781
782         g_free (info->active_path);
783         g_free (info->new_connection_path);
784         g_object_unref (info->simple);
785         if (info->cancellable) {
786                 if (info->cancelled_id)
787                         g_signal_handler_disconnect (info->cancellable, info->cancelled_id);
788                 g_object_unref (info->cancellable);
789         }
790         g_slice_free (ActivateInfo, info);
791 }
792
793 static NMActiveConnection *
794 find_active_connection_by_path (NMManager *self, const char *ac_path)
795 {
796         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
797         int i;
798
799         for (i = 0; i < priv->active_connections->len; i++) {
800                 NMActiveConnection *candidate = g_ptr_array_index (priv->active_connections, i);
801                 const char *candidate_path = nm_object_get_path (NM_OBJECT (candidate));
802
803                 if (g_strcmp0 (ac_path, candidate_path) == 0)
804                         return candidate;
805         }
806
807         return NULL;
808 }
809
810 static void
811 recheck_pending_activations (NMManager *self)
812 {
813         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
814         GSList *iter, *next;
815         NMActiveConnection *candidate;
816         const GPtrArray *devices;
817         NMDevice *device;
818
819         /* For each pending activation, look for an active connection that has the
820          * pending activation's object path, where the active connection and its
821          * device have both updated their properties to point to each other, and
822          * call the pending connection's callback.
823          */
824         for (iter = priv->pending_activations; iter; iter = next) {
825                 ActivateInfo *info = iter->data;
826
827                 next = g_slist_next (iter);
828
829                 candidate = find_active_connection_by_path (self, info->active_path);
830                 if (!candidate)
831                         continue;
832
833                 /* Check that the AC and device are both ready */
834                 devices = nm_active_connection_get_devices (candidate);
835                 if (devices->len == 0)
836                         continue;
837
838                 if (!NM_IS_VPN_CONNECTION (candidate)) {
839                         device = devices->pdata[0];
840                         if (nm_device_get_active_connection (device) != candidate)
841                                 continue;
842                 }
843
844                 activate_info_complete (info, candidate, NULL);
845                 break;
846         }
847 }
848
849 static void
850 activation_cancelled (GCancellable *cancellable,
851                       gpointer user_data)
852 {
853         ActivateInfo *info = user_data;
854         GError *error = NULL;
855
856         if (!g_cancellable_set_error_if_cancelled (cancellable, &error))
857                 return;
858
859         activate_info_complete (info, NULL, error);
860         g_clear_error (&error);
861 }
862
863 static void
864 active_removed (NMObject *object, NMActiveConnection *active, gpointer user_data)
865 {
866         ActivateInfo *info = user_data;
867         GError *error = NULL;
868
869         if (strcmp (info->active_path, nm_object_get_path (NM_OBJECT (active))))
870                 return;
871
872         error = g_error_new_literal (NM_CLIENT_ERROR,
873                                      NM_CLIENT_ERROR_FAILED,
874                                      _("Active connection could not be attached to the device"));
875         activate_info_complete (info, NULL, error);
876         g_clear_error (&error);
877 }
878
879 static void
880 activate_cb (GObject *object,
881              GAsyncResult *result,
882              gpointer user_data)
883 {
884         ActivateInfo *info = user_data;
885         GError *error = NULL;
886
887         if (nmdbus_manager_call_activate_connection_finish (NMDBUS_MANAGER (object),
888                                                             &info->active_path,
889                                                             result, &error)) {
890                 if (info->cancellable) {
891                         info->cancelled_id = g_signal_connect (info->cancellable, "cancelled",
892                                                                G_CALLBACK (activation_cancelled), info);
893                 }
894
895                 g_signal_connect (info->manager, "active-connection-removed",
896                                   G_CALLBACK (active_removed), info);
897
898                 recheck_pending_activations (info->manager);
899         } else {
900                 g_dbus_error_strip_remote_error (error);
901                 activate_info_complete (info, NULL, error);
902                 g_clear_error (&error);
903         }
904 }
905
906 void
907 nm_manager_activate_connection_async (NMManager *manager,
908                                       NMConnection *connection,
909                                       NMDevice *device,
910                                       const char *specific_object,
911                                       GCancellable *cancellable,
912                                       GAsyncReadyCallback callback,
913                                       gpointer user_data)
914 {
915         NMManagerPrivate *priv;
916         ActivateInfo *info;
917
918         g_return_if_fail (NM_IS_MANAGER (manager));
919         if (device)
920                 g_return_if_fail (NM_IS_DEVICE (device));
921         if (connection)
922                 g_return_if_fail (NM_IS_CONNECTION (connection));
923
924         info = g_slice_new0 (ActivateInfo);
925         info->manager = manager;
926         info->simple = g_simple_async_result_new (G_OBJECT (manager), callback, user_data,
927                                                   nm_manager_activate_connection_async);
928         info->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
929
930         priv = NM_MANAGER_GET_PRIVATE (manager);
931         priv->pending_activations = g_slist_prepend (priv->pending_activations, info);
932
933         nmdbus_manager_call_activate_connection (priv->manager_proxy,
934                                                  connection ? nm_connection_get_path (connection) : "/",
935                                                  device ? nm_object_get_path (NM_OBJECT (device)) : "/",
936                                                  specific_object ? specific_object : "/",
937                                                  cancellable,
938                                                  activate_cb, info);
939 }
940
941 NMActiveConnection *
942 nm_manager_activate_connection_finish (NMManager *manager,
943                                        GAsyncResult *result,
944                                        GError **error)
945 {
946         GSimpleAsyncResult *simple;
947
948         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (manager), nm_manager_activate_connection_async), NULL);
949
950         simple = G_SIMPLE_ASYNC_RESULT (result);
951         if (g_simple_async_result_propagate_error (simple, error))
952                 return NULL;
953         else
954                 return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
955 }
956
957 static void
958 add_activate_cb (GObject *object,
959                  GAsyncResult *result,
960                  gpointer user_data)
961 {
962         ActivateInfo *info = user_data;
963         GError *error = NULL;
964
965         if (nmdbus_manager_call_add_and_activate_connection_finish (NMDBUS_MANAGER (object),
966                                                                     NULL,
967                                                                     &info->active_path,
968                                                                     result, &error)) {
969                 if (info->cancellable) {
970                         info->cancelled_id = g_signal_connect (info->cancellable, "cancelled",
971                                                                G_CALLBACK (activation_cancelled), info);
972                 }
973
974                 g_signal_connect (info->manager, "active-connection-removed",
975                                   G_CALLBACK (active_removed), info);
976
977                 recheck_pending_activations (info->manager);
978         } else {
979                 g_dbus_error_strip_remote_error (error);
980                 activate_info_complete (info, NULL, error);
981                 g_clear_error (&error);
982         }
983 }
984
985 void
986 nm_manager_add_and_activate_connection_async (NMManager *manager,
987                                               NMConnection *partial,
988                                               NMDevice *device,
989                                               const char *specific_object,
990                                               GCancellable *cancellable,
991                                               GAsyncReadyCallback callback,
992                                               gpointer user_data)
993 {
994         NMManagerPrivate *priv;
995         GVariant *dict = NULL;
996         ActivateInfo *info;
997
998         g_return_if_fail (NM_IS_MANAGER (manager));
999         g_return_if_fail (NM_IS_DEVICE (device));
1000         if (partial)
1001                 g_return_if_fail (NM_IS_CONNECTION (partial));
1002
1003         info = g_slice_new0 (ActivateInfo);
1004         info->manager = manager;
1005         info->simple = g_simple_async_result_new (G_OBJECT (manager), callback, user_data,
1006                                                   nm_manager_add_and_activate_connection_async);
1007         info->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
1008
1009         priv = NM_MANAGER_GET_PRIVATE (manager);
1010         priv->pending_activations = g_slist_prepend (priv->pending_activations, info);
1011
1012         if (partial)
1013                 dict = nm_connection_to_dbus (partial, NM_CONNECTION_SERIALIZE_ALL);
1014         if (!dict)
1015                 dict = g_variant_new_array (G_VARIANT_TYPE ("{sa{sv}}"), NULL, 0);
1016
1017         nmdbus_manager_call_add_and_activate_connection (priv->manager_proxy,
1018                                                          dict,
1019                                                          nm_object_get_path (NM_OBJECT (device)),
1020                                                          specific_object ? specific_object : "/",
1021                                                          cancellable,
1022                                                          add_activate_cb, info);
1023 }
1024
1025 NMActiveConnection *
1026 nm_manager_add_and_activate_connection_finish (NMManager *manager,
1027                                                GAsyncResult *result,
1028                                                GError **error)
1029 {
1030         GSimpleAsyncResult *simple;
1031
1032         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (manager), nm_manager_add_and_activate_connection_async), NULL);
1033
1034         simple = G_SIMPLE_ASYNC_RESULT (result);
1035         if (g_simple_async_result_propagate_error (simple, error))
1036                 return NULL;
1037         else
1038                 return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
1039 }
1040
1041 static void
1042 device_ac_changed (GObject *object, GParamSpec *pspec, gpointer user_data)
1043 {
1044         NMManager *self = user_data;
1045
1046         recheck_pending_activations (self);
1047 }
1048
1049 static void
1050 device_added (NMManager *self, NMDevice *device)
1051 {
1052         g_signal_connect (device, "notify::" NM_DEVICE_ACTIVE_CONNECTION,
1053                           G_CALLBACK (device_ac_changed), self);
1054 }
1055
1056 static void
1057 device_removed (NMManager *self, NMDevice *device)
1058 {
1059         g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_ac_changed), self);
1060 }
1061
1062 static void
1063 ac_devices_changed (GObject *object, GParamSpec *pspec, gpointer user_data)
1064 {
1065         NMManager *self = user_data;
1066
1067         recheck_pending_activations (self);
1068 }
1069
1070 static void
1071 active_connection_added (NMManager *self, NMActiveConnection *ac)
1072 {
1073         g_signal_connect (ac, "notify::" NM_ACTIVE_CONNECTION_DEVICES,
1074                           G_CALLBACK (ac_devices_changed), self);
1075         recheck_pending_activations (self);
1076 }
1077
1078 static void
1079 active_connection_removed (NMManager *self, NMActiveConnection *ac)
1080 {
1081         g_signal_handlers_disconnect_by_func (ac, G_CALLBACK (ac_devices_changed), self);
1082 }
1083
1084 static void
1085 object_creation_failed (NMObject *object, const char *failed_path)
1086 {
1087         NMManager *self = NM_MANAGER (object);
1088         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1089         GError *error;
1090         GSList *iter;
1091
1092         /* A newly activated connection failed due to some immediate error
1093          * and disappeared from active connection list.  Make sure the
1094          * callback gets called.
1095          */
1096         error = g_error_new_literal (NM_CLIENT_ERROR,
1097                                      NM_CLIENT_ERROR_OBJECT_CREATION_FAILED,
1098                                      _("Active connection removed before it was initialized"));
1099
1100         for (iter = priv->pending_activations; iter; iter = iter->next) {
1101                 ActivateInfo *info = iter->data;
1102
1103                 if (g_strcmp0 (failed_path, info->active_path) == 0) {
1104                         activate_info_complete (info, NULL, error);
1105                         g_error_free (error);
1106                         return;
1107                 }
1108         }
1109 }
1110
1111 gboolean
1112 nm_manager_deactivate_connection (NMManager *manager,
1113                                   NMActiveConnection *active,
1114                                   GCancellable *cancellable,
1115                                   GError **error)
1116 {
1117         const char *path;
1118         gboolean ret;
1119
1120         g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE);
1121         g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (active), FALSE);
1122
1123         path = nm_object_get_path (NM_OBJECT (active));
1124         ret = nmdbus_manager_call_deactivate_connection_sync (NM_MANAGER_GET_PRIVATE (manager)->manager_proxy,
1125                                                               path,
1126                                                               cancellable, error);
1127         if (error && *error)
1128                 g_dbus_error_strip_remote_error (*error);
1129         return ret;
1130 }
1131
1132 static void
1133 deactivated_cb (GObject *object,
1134                 GAsyncResult *result,
1135                 gpointer user_data)
1136 {
1137         GSimpleAsyncResult *simple = user_data;
1138         GError *error = NULL;
1139
1140         if (nmdbus_manager_call_deactivate_connection_finish (NMDBUS_MANAGER (object),
1141                                                               result, &error))
1142                 g_simple_async_result_set_op_res_gboolean (simple, TRUE);
1143         else {
1144                 g_dbus_error_strip_remote_error (error);
1145                 g_simple_async_result_take_error (simple, error);
1146         }
1147         g_simple_async_result_complete (simple);
1148         g_object_unref (simple);
1149 }
1150
1151 void
1152 nm_manager_deactivate_connection_async (NMManager *manager,
1153                                         NMActiveConnection *active,
1154                                         GCancellable *cancellable,
1155                                         GAsyncReadyCallback callback,
1156                                         gpointer user_data)
1157 {
1158         const char *path;
1159         GSimpleAsyncResult *simple;
1160
1161         g_return_if_fail (NM_IS_MANAGER (manager));
1162         g_return_if_fail (NM_IS_ACTIVE_CONNECTION (active));
1163
1164         simple = g_simple_async_result_new (G_OBJECT (manager), callback, user_data,
1165                                             nm_manager_deactivate_connection_async);
1166
1167         path = nm_object_get_path (NM_OBJECT (active));
1168         nmdbus_manager_call_deactivate_connection (NM_MANAGER_GET_PRIVATE (manager)->manager_proxy,
1169                                                    path,
1170                                                    cancellable,
1171                                                    deactivated_cb, simple);
1172 }
1173
1174 gboolean
1175 nm_manager_deactivate_connection_finish (NMManager *manager,
1176                                          GAsyncResult *result,
1177                                          GError **error)
1178 {
1179         GSimpleAsyncResult *simple;
1180
1181         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (manager), nm_manager_deactivate_connection_async), FALSE);
1182
1183         simple = G_SIMPLE_ASYNC_RESULT (result);
1184         if (g_simple_async_result_propagate_error (simple, error))
1185                 return FALSE;
1186         else
1187                 return g_simple_async_result_get_op_res_gboolean (simple);
1188 }
1189
1190 /****************************************************************/
1191
1192 static void
1193 free_devices (NMManager *manager, gboolean in_dispose)
1194 {
1195         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
1196         gs_unref_ptrarray GPtrArray *real_devices = NULL;
1197         gs_unref_ptrarray GPtrArray *all_devices = NULL;
1198         GPtrArray *devices = NULL;
1199         guint i, j;
1200
1201         real_devices = priv->devices;
1202         all_devices = priv->all_devices;
1203
1204         if (in_dispose) {
1205                 priv->devices = NULL;
1206                 priv->all_devices = NULL;
1207                 return;
1208         }
1209
1210         priv->devices = g_ptr_array_new_with_free_func (g_object_unref);
1211         priv->all_devices = g_ptr_array_new_with_free_func (g_object_unref);
1212
1213         if (all_devices && all_devices->len > 0)
1214                 devices = all_devices;
1215         else if (real_devices && real_devices->len > 0)
1216                 devices = real_devices;
1217
1218         if (real_devices && devices != real_devices) {
1219                 for (i = 0; i < real_devices->len; i++) {
1220                         NMDevice *d = real_devices->pdata[i];
1221
1222                         if (all_devices) {
1223                                 for (j = 0; j < all_devices->len; j++) {
1224                                         if (d == all_devices->pdata[j])
1225                                                 goto next;
1226                                 }
1227                         }
1228                         g_signal_emit (manager, signals[DEVICE_REMOVED], 0, d);
1229 next:
1230                         ;
1231                 }
1232         }
1233         if (devices) {
1234                 for (i = 0; i < devices->len; i++)
1235                         g_signal_emit (manager, signals[DEVICE_REMOVED], 0, devices->pdata[i]);
1236         }
1237 }
1238
1239 static void
1240 free_active_connections (NMManager *manager, gboolean in_dispose)
1241 {
1242         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
1243         GPtrArray *active_connections;
1244         NMActiveConnection *active_connection;
1245         int i;
1246
1247         if (!priv->active_connections)
1248                 return;
1249
1250         active_connections = priv->active_connections;
1251         if (in_dispose)
1252                 priv->active_connections = NULL;
1253         else
1254                 priv->active_connections = g_ptr_array_new ();
1255
1256         for (i = 0; i < active_connections->len; i++) {
1257                 active_connection = active_connections->pdata[i];
1258                 g_signal_emit (manager, signals[ACTIVE_CONNECTION_REMOVED], 0, active_connection);
1259                 /* Break circular refs */
1260                 g_object_run_dispose (G_OBJECT (active_connection));
1261         }
1262         g_ptr_array_unref (active_connections);
1263
1264         if (!in_dispose)
1265                 g_object_notify (G_OBJECT (manager), NM_MANAGER_ACTIVE_CONNECTIONS);
1266 }
1267
1268 static void
1269 updated_properties (GObject *object, GAsyncResult *result, gpointer user_data)
1270 {
1271         NMManager *manager = NM_MANAGER (user_data);
1272         GError *error = NULL;
1273
1274         if (!_nm_object_reload_properties_finish (NM_OBJECT (object), result, &error)) {
1275                 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
1276                         g_warning ("%s: error reading NMManager properties: %s", __func__, error->message);
1277                 g_error_free (error);
1278         }
1279
1280         _nm_object_queue_notify (NM_OBJECT (manager), NM_MANAGER_NM_RUNNING);
1281 }
1282
1283 static void
1284 nm_running_changed_cb (GObject *object,
1285                        GParamSpec *pspec,
1286                        gpointer user_data)
1287 {
1288         NMManager *manager = NM_MANAGER (object);
1289         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
1290
1291         if (!nm_manager_get_nm_running (manager)) {
1292                 nm_clear_g_cancellable (&priv->props_cancellable);
1293
1294                 priv->state = NM_STATE_UNKNOWN;
1295                 priv->startup = FALSE;
1296                 _nm_object_queue_notify (NM_OBJECT (manager), NM_MANAGER_NM_RUNNING);
1297                 _nm_object_suppress_property_updates (NM_OBJECT (manager), TRUE);
1298                 poke_wireless_devices_with_rf_status (manager);
1299                 free_devices (manager, FALSE);
1300                 free_active_connections (manager, FALSE);
1301                 update_permissions (manager, NULL);
1302                 priv->wireless_enabled = FALSE;
1303                 priv->wireless_hw_enabled = FALSE;
1304                 priv->wwan_enabled = FALSE;
1305                 priv->wwan_hw_enabled = FALSE;
1306                 priv->wimax_enabled = FALSE;
1307                 priv->wimax_hw_enabled = FALSE;
1308                 g_free (priv->version);
1309                 priv->version = NULL;
1310
1311                 /* Clear object cache to ensure bad refcounting by managers doesn't
1312                  * keep objects in the cache.
1313                  */
1314                 _nm_object_cache_clear ();
1315         } else {
1316                 _nm_object_suppress_property_updates (NM_OBJECT (manager), FALSE);
1317
1318                 nm_clear_g_cancellable (&priv->props_cancellable);
1319                 priv->props_cancellable = g_cancellable_new ();
1320                 _nm_object_reload_properties_async (NM_OBJECT (manager), priv->props_cancellable, updated_properties, manager);
1321
1322                 manager_recheck_permissions (priv->manager_proxy, manager);
1323         }
1324 }
1325
1326 /****************************************************************/
1327
1328 static void
1329 constructed (GObject *object)
1330 {
1331         G_OBJECT_CLASS (nm_manager_parent_class)->constructed (object);
1332
1333         g_signal_connect (object, "notify::" NM_OBJECT_NM_RUNNING,
1334                           G_CALLBACK (nm_running_changed_cb), NULL);
1335
1336         g_signal_connect (object, "notify::" NM_MANAGER_WIRELESS_ENABLED,
1337                           G_CALLBACK (wireless_enabled_cb), NULL);
1338 }
1339
1340 static gboolean
1341 init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
1342 {
1343         NMManager *manager = NM_MANAGER (initable);
1344
1345         if (!nm_manager_parent_initable_iface->init (initable, cancellable, error))
1346                 return FALSE;
1347
1348         if (   nm_manager_get_nm_running (manager)
1349             && !get_permissions_sync (manager, error))
1350                 return FALSE;
1351
1352         return TRUE;
1353 }
1354
1355 typedef struct {
1356         NMManager *manager;
1357         GCancellable *cancellable;
1358         GSimpleAsyncResult *result;
1359 } NMManagerInitData;
1360
1361 static void
1362 init_async_complete (NMManagerInitData *init_data)
1363 {
1364         g_simple_async_result_complete (init_data->result);
1365         g_object_unref (init_data->result);
1366         g_clear_object (&init_data->cancellable);
1367         g_slice_free (NMManagerInitData, init_data);
1368 }
1369
1370 static void
1371 init_async_got_permissions (GObject *object, GAsyncResult *result, gpointer user_data)
1372 {
1373         NMManagerInitData *init_data = user_data;
1374         GVariant *permissions;
1375
1376         if (nmdbus_manager_call_get_permissions_finish (NMDBUS_MANAGER (object),
1377                                                         &permissions,
1378                                                         result, NULL)) {
1379                 update_permissions (init_data->manager, permissions);
1380                 g_variant_unref (permissions);
1381         } else
1382                 update_permissions (init_data->manager, NULL);
1383
1384         init_async_complete (init_data);
1385 }
1386
1387 static void
1388 init_async_parent_inited (GObject *source, GAsyncResult *result, gpointer user_data)
1389 {
1390         NMManagerInitData *init_data = user_data;
1391         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (init_data->manager);
1392         GError *error = NULL;
1393
1394         if (!nm_manager_parent_async_initable_iface->init_finish (G_ASYNC_INITABLE (source), result, &error)) {
1395                 g_simple_async_result_take_error (init_data->result, error);
1396                 init_async_complete (init_data);
1397                 return;
1398         }
1399
1400         if (!nm_manager_get_nm_running (init_data->manager)) {
1401                 init_async_complete (init_data);
1402                 return;
1403         }
1404
1405         nmdbus_manager_call_get_permissions (priv->manager_proxy,
1406                                              init_data->cancellable,
1407                                              init_async_got_permissions, init_data);
1408 }
1409
1410 static void
1411 init_async (GAsyncInitable *initable, int io_priority,
1412             GCancellable *cancellable, GAsyncReadyCallback callback,
1413             gpointer user_data)
1414 {
1415         NMManagerInitData *init_data;
1416
1417         init_data = g_slice_new0 (NMManagerInitData);
1418         init_data->manager = NM_MANAGER (initable);
1419         init_data->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
1420         init_data->result = g_simple_async_result_new (G_OBJECT (initable), callback,
1421                                                        user_data, init_async);
1422         g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE);
1423
1424         nm_manager_parent_async_initable_iface->init_async (initable, io_priority, cancellable,
1425                                                            init_async_parent_inited, init_data);
1426 }
1427
1428 static gboolean
1429 init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error)
1430 {
1431         GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
1432
1433         if (g_simple_async_result_propagate_error (simple, error))
1434                 return FALSE;
1435         else
1436                 return TRUE;
1437 }
1438
1439 static void
1440 dispose (GObject *object)
1441 {
1442         NMManager *manager = NM_MANAGER (object);
1443         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (object);
1444
1445         if (priv->perm_call_cancellable) {
1446                 g_cancellable_cancel (priv->perm_call_cancellable);
1447                 g_clear_object (&priv->perm_call_cancellable);
1448         }
1449
1450         free_devices (manager, TRUE);
1451         free_active_connections (manager, TRUE);
1452         g_clear_object (&priv->primary_connection);
1453         g_clear_object (&priv->activating_connection);
1454
1455         /* Each activation should hold a ref on @manager, so if we're being disposed,
1456          * there shouldn't be any pending.
1457          */
1458         g_warn_if_fail (priv->pending_activations == NULL);
1459
1460         g_hash_table_destroy (priv->permissions);
1461         priv->permissions = NULL;
1462
1463         G_OBJECT_CLASS (nm_manager_parent_class)->dispose (object);
1464 }
1465
1466 static void
1467 finalize (GObject *object)
1468 {
1469         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (object);
1470
1471         g_free (priv->version);
1472
1473         G_OBJECT_CLASS (nm_manager_parent_class)->finalize (object);
1474 }
1475
1476 static void
1477 set_property (GObject *object, guint prop_id,
1478               const GValue *value, GParamSpec *pspec)
1479 {
1480         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (object);
1481         gboolean b;
1482
1483         switch (prop_id) {
1484         case PROP_NETWORKING_ENABLED:
1485                 b = g_value_get_boolean (value);
1486                 if (priv->networking_enabled != b) {
1487                         nm_manager_networking_set_enabled (NM_MANAGER (object), b, NULL);
1488                         /* Let the property value flip when we get the change signal from NM */
1489                 }
1490                 break;
1491         case PROP_WIRELESS_ENABLED:
1492                 b = g_value_get_boolean (value);
1493                 if (priv->wireless_enabled != b) {
1494                         nm_manager_wireless_set_enabled (NM_MANAGER (object), b);
1495                         /* Let the property value flip when we get the change signal from NM */
1496                 }
1497                 break;
1498         case PROP_WWAN_ENABLED:
1499                 b = g_value_get_boolean (value);
1500                 if (priv->wwan_enabled != b) {
1501                         nm_manager_wwan_set_enabled (NM_MANAGER (object), b);
1502                         /* Let the property value flip when we get the change signal from NM */
1503                 }
1504                 break;
1505         case PROP_WIMAX_ENABLED:
1506                 b = g_value_get_boolean (value);
1507                 if (priv->wimax_enabled != b) {
1508                         nm_manager_wimax_set_enabled (NM_MANAGER (object), b);
1509                         /* Let the property value flip when we get the change signal from NM */
1510                 }
1511                 break;
1512         default:
1513                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1514                 break;
1515         }
1516 }
1517
1518 static void
1519 get_property (GObject *object,
1520               guint prop_id,
1521               GValue *value,
1522               GParamSpec *pspec)
1523 {
1524         NMManager *self = NM_MANAGER (object);
1525         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1526
1527         switch (prop_id) {
1528         case PROP_VERSION:
1529                 g_value_set_string (value, nm_manager_get_version (self));
1530                 break;
1531         case PROP_STATE:
1532                 g_value_set_enum (value, nm_manager_get_state (self));
1533                 break;
1534         case PROP_STARTUP:
1535                 g_value_set_boolean (value, nm_manager_get_startup (self));
1536                 break;
1537         case PROP_NM_RUNNING:
1538                 g_value_set_boolean (value, nm_manager_get_nm_running (self));
1539                 break;
1540         case PROP_NETWORKING_ENABLED:
1541                 g_value_set_boolean (value, nm_manager_networking_get_enabled (self));
1542                 break;
1543         case PROP_WIRELESS_ENABLED:
1544                 g_value_set_boolean (value, priv->wireless_enabled);
1545                 break;
1546         case PROP_WIRELESS_HARDWARE_ENABLED:
1547                 g_value_set_boolean (value, priv->wireless_hw_enabled);
1548                 break;
1549         case PROP_WWAN_ENABLED:
1550                 g_value_set_boolean (value, priv->wwan_enabled);
1551                 break;
1552         case PROP_WWAN_HARDWARE_ENABLED:
1553                 g_value_set_boolean (value, priv->wwan_hw_enabled);
1554                 break;
1555         case PROP_WIMAX_ENABLED:
1556                 g_value_set_boolean (value, priv->wimax_enabled);
1557                 break;
1558         case PROP_WIMAX_HARDWARE_ENABLED:
1559                 g_value_set_boolean (value, priv->wimax_hw_enabled);
1560                 break;
1561         case PROP_ACTIVE_CONNECTIONS:
1562                 g_value_take_boxed (value, _nm_utils_copy_object_array (nm_manager_get_active_connections (self)));
1563                 break;
1564         case PROP_CONNECTIVITY:
1565                 g_value_set_enum (value, priv->connectivity);
1566                 break;
1567         case PROP_PRIMARY_CONNECTION:
1568                 g_value_set_object (value, priv->primary_connection);
1569                 break;
1570         case PROP_ACTIVATING_CONNECTION:
1571                 g_value_set_object (value, priv->activating_connection);
1572                 break;
1573         case PROP_DEVICES:
1574                 g_value_take_boxed (value, _nm_utils_copy_object_array (nm_manager_get_devices (self)));
1575                 break;
1576         case PROP_METERED:
1577                 g_value_set_uint (value, priv->metered);
1578                 break;
1579         case PROP_ALL_DEVICES:
1580                 g_value_take_boxed (value, _nm_utils_copy_object_array (nm_manager_get_all_devices (self)));
1581                 break;
1582         default:
1583                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1584                 break;
1585         }
1586 }
1587
1588 static void
1589 nm_manager_class_init (NMManagerClass *manager_class)
1590 {
1591         GObjectClass *object_class = G_OBJECT_CLASS (manager_class);
1592         NMObjectClass *nm_object_class = NM_OBJECT_CLASS (manager_class);
1593
1594         g_type_class_add_private (manager_class, sizeof (NMManagerPrivate));
1595
1596         _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE);
1597         _nm_dbus_register_proxy_type (NM_DBUS_INTERFACE, NMDBUS_TYPE_MANAGER_PROXY);
1598
1599         /* virtual methods */
1600         object_class->constructed = constructed;
1601         object_class->set_property = set_property;
1602         object_class->get_property = get_property;
1603         object_class->dispose = dispose;
1604         object_class->finalize = finalize;
1605
1606         nm_object_class->init_dbus = init_dbus;
1607         nm_object_class->object_creation_failed = object_creation_failed;
1608
1609         manager_class->device_added = device_added;
1610         manager_class->device_removed = device_removed;
1611         manager_class->active_connection_added = active_connection_added;
1612         manager_class->active_connection_removed = active_connection_removed;
1613
1614         /* properties */
1615
1616         g_object_class_install_property
1617                 (object_class, PROP_VERSION,
1618                  g_param_spec_string (NM_MANAGER_VERSION, "", "",
1619                                       NULL,
1620                                       G_PARAM_READABLE |
1621                                       G_PARAM_STATIC_STRINGS));
1622         g_object_class_install_property
1623                 (object_class, PROP_STATE,
1624                  g_param_spec_enum (NM_CLIENT_STATE, "", "",
1625                                     NM_TYPE_STATE,
1626                                     NM_STATE_UNKNOWN,
1627                                     G_PARAM_READABLE |
1628                                     G_PARAM_STATIC_STRINGS));
1629         g_object_class_install_property
1630                 (object_class, PROP_STARTUP,
1631                  g_param_spec_boolean (NM_MANAGER_STARTUP, "", "",
1632                                        FALSE,
1633                                        G_PARAM_READABLE |
1634                                        G_PARAM_STATIC_STRINGS));
1635         g_object_class_install_property
1636                 (object_class, PROP_NM_RUNNING,
1637                  g_param_spec_boolean (NM_MANAGER_NM_RUNNING, "", "",
1638                                        FALSE,
1639                                        G_PARAM_READABLE |
1640                                        G_PARAM_STATIC_STRINGS));
1641         g_object_class_install_property
1642                 (object_class, PROP_NETWORKING_ENABLED,
1643                  g_param_spec_boolean (NM_MANAGER_NETWORKING_ENABLED, "", "",
1644                                        TRUE,
1645                                        G_PARAM_READWRITE |
1646                                        G_PARAM_STATIC_STRINGS));
1647         g_object_class_install_property
1648                 (object_class, PROP_WIRELESS_ENABLED,
1649                  g_param_spec_boolean (NM_MANAGER_WIRELESS_ENABLED, "", "",
1650                                        FALSE,
1651                                        G_PARAM_READWRITE |
1652                                        G_PARAM_STATIC_STRINGS));
1653         g_object_class_install_property
1654                 (object_class, PROP_WIRELESS_HARDWARE_ENABLED,
1655                  g_param_spec_boolean (NM_MANAGER_WIRELESS_HARDWARE_ENABLED, "", "",
1656                                        TRUE,
1657                                        G_PARAM_READABLE |
1658                                        G_PARAM_STATIC_STRINGS));
1659         g_object_class_install_property
1660                 (object_class, PROP_WWAN_ENABLED,
1661                  g_param_spec_boolean (NM_MANAGER_WWAN_ENABLED, "", "",
1662                                        FALSE,
1663                                        G_PARAM_READWRITE |
1664                                        G_PARAM_STATIC_STRINGS));
1665         g_object_class_install_property
1666                 (object_class, PROP_WWAN_HARDWARE_ENABLED,
1667                  g_param_spec_boolean (NM_MANAGER_WWAN_HARDWARE_ENABLED, "", "",
1668                                        FALSE,
1669                                        G_PARAM_READABLE |
1670                                        G_PARAM_STATIC_STRINGS));
1671         g_object_class_install_property
1672                 (object_class, PROP_WIMAX_ENABLED,
1673                  g_param_spec_boolean (NM_MANAGER_WIMAX_ENABLED, "", "",
1674                                        FALSE,
1675                                        G_PARAM_READWRITE |
1676                                        G_PARAM_STATIC_STRINGS));
1677         g_object_class_install_property
1678                 (object_class, PROP_WIMAX_HARDWARE_ENABLED,
1679                  g_param_spec_boolean (NM_MANAGER_WIMAX_HARDWARE_ENABLED, "", "",
1680                                        FALSE,
1681                                        G_PARAM_READABLE |
1682                                        G_PARAM_STATIC_STRINGS));
1683         g_object_class_install_property
1684                 (object_class, PROP_ACTIVE_CONNECTIONS,
1685                  g_param_spec_boxed (NM_MANAGER_ACTIVE_CONNECTIONS, "", "",
1686                                      G_TYPE_PTR_ARRAY,
1687                                      G_PARAM_READABLE |
1688                                      G_PARAM_STATIC_STRINGS));
1689         g_object_class_install_property
1690                 (object_class, PROP_CONNECTIVITY,
1691                  g_param_spec_enum (NM_CLIENT_CONNECTIVITY, "", "",
1692                                     NM_TYPE_CONNECTIVITY_STATE,
1693                                     NM_CONNECTIVITY_UNKNOWN,
1694                                     G_PARAM_READABLE |
1695                                     G_PARAM_STATIC_STRINGS));
1696         g_object_class_install_property
1697                 (object_class, PROP_PRIMARY_CONNECTION,
1698                  g_param_spec_object (NM_MANAGER_PRIMARY_CONNECTION, "", "",
1699                                       NM_TYPE_ACTIVE_CONNECTION,
1700                                       G_PARAM_READABLE |
1701                                       G_PARAM_STATIC_STRINGS));
1702         g_object_class_install_property
1703                 (object_class, PROP_ACTIVATING_CONNECTION,
1704                  g_param_spec_object (NM_MANAGER_ACTIVATING_CONNECTION, "", "",
1705                                       NM_TYPE_ACTIVE_CONNECTION,
1706                                       G_PARAM_READABLE |
1707                                       G_PARAM_STATIC_STRINGS));
1708         g_object_class_install_property
1709                 (object_class, PROP_DEVICES,
1710                  g_param_spec_boxed (NM_MANAGER_DEVICES, "", "",
1711                                      G_TYPE_PTR_ARRAY,
1712                                      G_PARAM_READABLE |
1713                                      G_PARAM_STATIC_STRINGS));
1714         /**
1715          * NMManager:metered:
1716          *
1717          * Whether the connectivity is metered.
1718          *
1719          * Since: 1.2
1720          **/
1721         g_object_class_install_property
1722                 (object_class, PROP_METERED,
1723                  g_param_spec_uint (NM_MANAGER_METERED, "", "",
1724                                     0, G_MAXUINT32, NM_METERED_UNKNOWN,
1725                                     G_PARAM_READABLE |
1726                                     G_PARAM_STATIC_STRINGS));
1727
1728         g_object_class_install_property
1729                 (object_class, PROP_ALL_DEVICES,
1730                  g_param_spec_boxed (NM_MANAGER_ALL_DEVICES, "", "",
1731                                      G_TYPE_PTR_ARRAY,
1732                                      G_PARAM_READABLE |
1733                                      G_PARAM_STATIC_STRINGS));
1734
1735         /* signals */
1736
1737         signals[DEVICE_ADDED] =
1738                 g_signal_new ("device-added",
1739                               G_OBJECT_CLASS_TYPE (object_class),
1740                               G_SIGNAL_RUN_FIRST,
1741                               G_STRUCT_OFFSET (NMManagerClass, device_added),
1742                               NULL, NULL, NULL,
1743                               G_TYPE_NONE, 1,
1744                               G_TYPE_OBJECT);
1745         signals[DEVICE_REMOVED] =
1746                 g_signal_new ("device-removed",
1747                               G_OBJECT_CLASS_TYPE (object_class),
1748                               G_SIGNAL_RUN_FIRST,
1749                               G_STRUCT_OFFSET (NMManagerClass, device_removed),
1750                               NULL, NULL, NULL,
1751                               G_TYPE_NONE, 1,
1752                               G_TYPE_OBJECT);
1753         signals[ANY_DEVICE_ADDED] =
1754                 g_signal_new ("any-device-added",
1755                               G_OBJECT_CLASS_TYPE (object_class),
1756                               G_SIGNAL_RUN_FIRST,
1757                               0,
1758                               NULL, NULL, NULL,
1759                               G_TYPE_NONE, 1,
1760                               G_TYPE_OBJECT);
1761         signals[ANY_DEVICE_REMOVED] =
1762                 g_signal_new ("any-device-removed",
1763                               G_OBJECT_CLASS_TYPE (object_class),
1764                               G_SIGNAL_RUN_FIRST,
1765                               0,
1766                               NULL, NULL, NULL,
1767                               G_TYPE_NONE, 1,
1768                               G_TYPE_OBJECT);
1769         signals[ACTIVE_CONNECTION_ADDED] =
1770                 g_signal_new ("active-connection-added",
1771                               G_OBJECT_CLASS_TYPE (object_class),
1772                               G_SIGNAL_RUN_FIRST,
1773                               G_STRUCT_OFFSET (NMManagerClass, active_connection_added),
1774                               NULL, NULL, NULL,
1775                               G_TYPE_NONE, 1,
1776                               G_TYPE_OBJECT);
1777         signals[ACTIVE_CONNECTION_REMOVED] =
1778                 g_signal_new ("active-connection-removed",
1779                               G_OBJECT_CLASS_TYPE (object_class),
1780                               G_SIGNAL_RUN_FIRST,
1781                               G_STRUCT_OFFSET (NMManagerClass, active_connection_removed),
1782                               NULL, NULL, NULL,
1783                               G_TYPE_NONE, 1,
1784                               G_TYPE_OBJECT);
1785         signals[PERMISSION_CHANGED] =
1786                 g_signal_new ("permission-changed",
1787                               G_OBJECT_CLASS_TYPE (object_class),
1788                               G_SIGNAL_RUN_FIRST,
1789                               0, NULL, NULL, NULL,
1790                               G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
1791 }
1792
1793 static void
1794 nm_manager_initable_iface_init (GInitableIface *iface)
1795 {
1796         nm_manager_parent_initable_iface = g_type_interface_peek_parent (iface);
1797
1798         iface->init = init_sync;
1799 }
1800
1801 static void
1802 nm_manager_async_initable_iface_init (GAsyncInitableIface *iface)
1803 {
1804         nm_manager_parent_async_initable_iface = g_type_interface_peek_parent (iface);
1805
1806         iface->init_async = init_async;
1807         iface->init_finish = init_finish;
1808 }