manager: allow delaying the device activation when the parent is not real
[NetworkManager.git] / src / nm-manager.c
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 "nm-default.h"
23
24 #include <stdlib.h>
25 #include <fcntl.h>
26 #include <errno.h>
27 #include <string.h>
28 #include <unistd.h>
29
30 #include "nm-manager.h"
31 #include "nm-bus-manager.h"
32 #include "nm-vpn-manager.h"
33 #include "nm-device.h"
34 #include "nm-device-generic.h"
35 #include "nm-platform.h"
36 #include "nm-rfkill-manager.h"
37 #include "nm-dhcp-manager.h"
38 #include "nm-settings.h"
39 #include "nm-settings-connection.h"
40 #include "nm-auth-utils.h"
41 #include "nm-auth-manager.h"
42 #include "NetworkManagerUtils.h"
43 #include "nm-device-factory.h"
44 #include "nm-enum-types.h"
45 #include "nm-sleep-monitor.h"
46 #include "nm-connectivity.h"
47 #include "nm-policy.h"
48 #include "nm-connection-provider.h"
49 #include "nm-session-monitor.h"
50 #include "nm-activation-request.h"
51 #include "nm-core-internal.h"
52 #include "nm-config.h"
53 #include "nm-audit-manager.h"
54 #include "nm-dbus-compat.h"
55 #include "NetworkManagerUtils.h"
56
57 #include "nmdbus-manager.h"
58 #include "nmdbus-device.h"
59
60 static gboolean add_device (NMManager *self, NMDevice *device, GError **error);
61
62 static NMActiveConnection *_new_active_connection (NMManager *self,
63                                                    NMConnection *connection,
64                                                    const char *specific_object,
65                                                    NMDevice *device,
66                                                    NMAuthSubject *subject,
67                                                    GError **error);
68
69 static void policy_activating_device_changed (GObject *object, GParamSpec *pspec, gpointer user_data);
70
71 static void rfkill_change (const char *desc, RfKillType rtype, gboolean enabled);
72
73 static gboolean find_master (NMManager *self,
74                              NMConnection *connection,
75                              NMDevice *device,
76                              NMSettingsConnection **out_master_connection,
77                              NMDevice **out_master_device,
78                              NMActiveConnection **out_master_ac,
79                              GError **error);
80
81 static void nm_manager_update_state (NMManager *manager);
82
83 static void connection_changed (NMSettings *settings, NMConnection *connection,
84                                 NMManager *manager);
85
86 #define TAG_ACTIVE_CONNETION_ADD_AND_ACTIVATE "act-con-add-and-activate"
87
88 typedef struct {
89         gboolean user_enabled;
90         gboolean sw_enabled;
91         gboolean hw_enabled;
92         RfKillType rtype;
93         const char *desc;
94         const char *key;
95         const char *prop;
96         const char *hw_prop;
97 } RadioState;
98
99 typedef struct {
100         char *state_file;
101
102         GSList *active_connections;
103         GSList *authorizing_connections;
104         guint ac_cleanup_id;
105         NMActiveConnection *primary_connection;
106         NMActiveConnection *activating_connection;
107         NMMetered metered;
108
109         GSList *devices;
110         NMState state;
111         NMConfig *config;
112         NMConnectivity *connectivity;
113
114         NMPolicy *policy;
115
116         NMBusManager  *dbus_mgr;
117         struct {
118                 GDBusConnection *connection;
119                 guint            id;
120         } prop_filter;
121         NMRfkillManager *rfkill_mgr;
122
123         NMSettings *settings;
124         char *hostname;
125
126         RadioState radio_states[RFKILL_TYPE_MAX];
127         gboolean sleeping;
128         gboolean net_enabled;
129
130         NMVpnManager *vpn_manager;
131
132         NMSleepMonitor *sleep_monitor;
133
134         GSList *auth_chains;
135
136         /* Firmware dir monitor */
137         GFileMonitor *fw_monitor;
138         guint fw_changed_id;
139
140         guint timestamp_update_id;
141
142         gboolean startup;
143         gboolean devices_inited;
144 } NMManagerPrivate;
145
146 #define NM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MANAGER, NMManagerPrivate))
147
148 G_DEFINE_TYPE (NMManager, nm_manager, NM_TYPE_EXPORTED_OBJECT)
149
150 enum {
151         DEVICE_ADDED,
152         INTERNAL_DEVICE_ADDED,
153         DEVICE_REMOVED,
154         INTERNAL_DEVICE_REMOVED,
155         STATE_CHANGED,
156         CHECK_PERMISSIONS,
157         USER_PERMISSIONS_CHANGED,
158         ACTIVE_CONNECTION_ADDED,
159         ACTIVE_CONNECTION_REMOVED,
160         CONFIGURE_QUIT,
161
162         LAST_SIGNAL
163 };
164
165 static guint signals[LAST_SIGNAL] = { 0 };
166
167 enum {
168         PROP_0,
169         PROP_VERSION,
170         PROP_STATE,
171         PROP_STATE_FILE,
172         PROP_STARTUP,
173         PROP_NETWORKING_ENABLED,
174         PROP_WIRELESS_ENABLED,
175         PROP_WIRELESS_HARDWARE_ENABLED,
176         PROP_WWAN_ENABLED,
177         PROP_WWAN_HARDWARE_ENABLED,
178         PROP_WIMAX_ENABLED,
179         PROP_WIMAX_HARDWARE_ENABLED,
180         PROP_ACTIVE_CONNECTIONS,
181         PROP_CONNECTIVITY,
182         PROP_PRIMARY_CONNECTION,
183         PROP_PRIMARY_CONNECTION_TYPE,
184         PROP_ACTIVATING_CONNECTION,
185         PROP_DEVICES,
186         PROP_METERED,
187         PROP_GLOBAL_DNS_CONFIGURATION,
188         PROP_ALL_DEVICES,
189
190         /* Not exported */
191         PROP_HOSTNAME,
192         PROP_SLEEPING,
193
194         LAST_PROP
195 };
196
197 NM_DEFINE_SINGLETON_INSTANCE (NMManager);
198
199 /************************************************************************/
200
201 #define _NMLOG_PREFIX_NAME      "manager"
202 #define _NMLOG(level, domain, ...) \
203     G_STMT_START { \
204         const NMLogLevel __level = (level); \
205         const NMLogDomain __domain = (domain); \
206         \
207         if (nm_logging_enabled (__level, __domain)) { \
208             const NMManager *const __self = (self); \
209             char __sbuf[32]; \
210             \
211             _nm_log (__level, __domain, 0, \
212                      "%s%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \
213                      _NMLOG_PREFIX_NAME, \
214                      (__self && __self != singleton_instance) \
215                          ? nm_sprintf_buf (__sbuf, "[%p]", __self) \
216                          : "" \
217                      _NM_UTILS_MACRO_REST (__VA_ARGS__)); \
218         } \
219     } G_STMT_END
220
221 /************************************************************************/
222
223 static void active_connection_state_changed (NMActiveConnection *active,
224                                              GParamSpec *pspec,
225                                              NMManager *self);
226 static void active_connection_default_changed (NMActiveConnection *active,
227                                                GParamSpec *pspec,
228                                                NMManager *self);
229 static void active_connection_parent_active (NMActiveConnection *active,
230                                              NMActiveConnection *parent_ac,
231                                              NMManager *self);
232
233 /* Returns: whether to notify D-Bus of the removal or not */
234 static gboolean
235 active_connection_remove (NMManager *self, NMActiveConnection *active)
236 {
237         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
238         gboolean notify = nm_exported_object_is_exported (NM_EXPORTED_OBJECT (active));
239         GSList *found;
240
241         /* FIXME: switch to a GList for faster removal */
242         found = g_slist_find (priv->active_connections, active);
243         if (found) {
244                 NMSettingsConnection *connection;
245
246                 priv->active_connections = g_slist_remove (priv->active_connections, active);
247                 g_signal_emit (self, signals[ACTIVE_CONNECTION_REMOVED], 0, active);
248                 g_signal_handlers_disconnect_by_func (active, active_connection_state_changed, self);
249                 g_signal_handlers_disconnect_by_func (active, active_connection_default_changed, self);
250                 g_signal_handlers_disconnect_by_func (active, active_connection_parent_active, self);
251
252                 if (   nm_active_connection_get_assumed (active)
253                     && (connection = nm_active_connection_get_settings_connection (active))
254                     && nm_settings_connection_get_nm_generated_assumed (connection))
255                         g_object_ref (connection);
256                 else
257                         connection = NULL;
258
259                 nm_exported_object_clear_and_unexport (&active);
260
261                 if (   connection
262                     && nm_settings_has_connection (priv->settings, connection)) {
263                         _LOGD (LOGD_DEVICE, "assumed connection disconnected. Deleting generated connection '%s' (%s)",
264                                nm_settings_connection_get_id (connection), nm_settings_connection_get_uuid (connection));
265                         nm_settings_connection_delete (NM_SETTINGS_CONNECTION (connection), NULL, NULL);
266                         g_object_unref (connection);
267                 }
268         }
269
270         return found && notify;
271 }
272
273 static gboolean
274 _active_connection_cleanup (gpointer user_data)
275 {
276         NMManager *self = NM_MANAGER (user_data);
277         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
278         GSList *iter;
279
280         priv->ac_cleanup_id = 0;
281
282         g_object_freeze_notify (G_OBJECT (self));
283         iter = priv->active_connections;
284         while (iter) {
285                 NMActiveConnection *ac = iter->data;
286
287                 iter = iter->next;
288                 if (nm_active_connection_get_state (ac) == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) {
289                         if (active_connection_remove (self, ac))
290                                 g_object_notify (G_OBJECT (self), NM_MANAGER_ACTIVE_CONNECTIONS);
291                 }
292         }
293         g_object_thaw_notify (G_OBJECT (self));
294
295         return FALSE;
296 }
297
298 static void
299 active_connection_state_changed (NMActiveConnection *active,
300                                  GParamSpec *pspec,
301                                  NMManager *self)
302 {
303         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
304         NMActiveConnectionState state;
305
306         state = nm_active_connection_get_state (active);
307         if (state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) {
308                 /* Destroy active connections from an idle handler to ensure that
309                  * their last property change notifications go out, which wouldn't
310                  * happen if we destroyed them immediately when their state was set
311                  * to DEACTIVATED.
312                  */
313                 if (!priv->ac_cleanup_id)
314                         priv->ac_cleanup_id = g_idle_add (_active_connection_cleanup, self);
315         }
316
317         nm_manager_update_state (self);
318 }
319
320 static void
321 active_connection_default_changed (NMActiveConnection *active,
322                                    GParamSpec *pspec,
323                                    NMManager *self)
324 {
325         nm_manager_update_state (self);
326 }
327
328 /**
329  * active_connection_add():
330  * @self: the #NMManager
331  * @active: the #NMActiveConnection to manage
332  *
333  * Begins to track and manage @active.  Increases the refcount of @active.
334  */
335 static void
336 active_connection_add (NMManager *self, NMActiveConnection *active)
337 {
338         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
339
340         g_return_if_fail (g_slist_find (priv->active_connections, active) == FALSE);
341
342         priv->active_connections = g_slist_prepend (priv->active_connections,
343                                                     g_object_ref (active));
344
345         g_signal_connect (active,
346                           "notify::" NM_ACTIVE_CONNECTION_STATE,
347                           G_CALLBACK (active_connection_state_changed),
348                           self);
349         g_signal_connect (active,
350                           "notify::" NM_ACTIVE_CONNECTION_DEFAULT,
351                           G_CALLBACK (active_connection_default_changed),
352                           self);
353         g_signal_connect (active,
354                           "notify::" NM_ACTIVE_CONNECTION_DEFAULT6,
355                           G_CALLBACK (active_connection_default_changed),
356                           self);
357
358         g_signal_emit (self, signals[ACTIVE_CONNECTION_ADDED], 0, active);
359
360         /* Only notify D-Bus if the active connection is actually exported */
361         if (nm_exported_object_is_exported (NM_EXPORTED_OBJECT (active)))
362                 g_object_notify (G_OBJECT (self), NM_MANAGER_ACTIVE_CONNECTIONS);
363 }
364
365 const GSList *
366 nm_manager_get_active_connections (NMManager *manager)
367 {
368         return NM_MANAGER_GET_PRIVATE (manager)->active_connections;
369 }
370
371 static NMActiveConnection *
372 find_ac_for_connection (NMManager *manager, NMConnection *connection)
373 {
374         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
375         GSList *iter;
376         const char *uuid = NULL;
377         gboolean is_settings_connection;
378
379         is_settings_connection = NM_IS_SETTINGS_CONNECTION (connection);
380
381         if (!is_settings_connection)
382                 uuid = nm_connection_get_uuid (connection);
383
384         for (iter = priv->active_connections; iter; iter = iter->next) {
385                 NMActiveConnection *ac = iter->data;
386                 NMSettingsConnection *con;
387
388                 con = nm_active_connection_get_settings_connection (ac);
389
390                 /* depending on whether we have a NMSettingsConnection or a NMConnection,
391                  * we lookup by UUID or by reference. */
392                 if (is_settings_connection) {
393                         if (con != (NMSettingsConnection *) connection)
394                                 continue;
395                 } else {
396                         if (strcmp (uuid, nm_connection_get_uuid (NM_CONNECTION (con))) != 0)
397                                 continue;
398                 }
399                 if (nm_active_connection_get_state (ac) < NM_ACTIVE_CONNECTION_STATE_DEACTIVATED)
400                         return ac;
401         }
402
403         return NULL;
404 }
405
406 /* Filter out connections that are already active.
407  * nm_settings_get_connections() returns sorted list. We need to preserve the
408  * order so that we didn't change auto-activation order (recent timestamps
409  * are first).
410  * Caller is responsible for freeing the returned list with g_slist_free().
411  */
412 GSList *
413 nm_manager_get_activatable_connections (NMManager *manager)
414 {
415         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
416         GSList *all_connections = nm_settings_get_connections (priv->settings);
417         GSList *connections = NULL, *iter;
418         NMSettingsConnection *connection;
419
420         for (iter = all_connections; iter; iter = iter->next) {
421                 connection = iter->data;
422
423                 if (!find_ac_for_connection (manager, NM_CONNECTION (connection)))
424                         connections = g_slist_prepend (connections, connection);
425         }
426
427         g_slist_free (all_connections);
428         return g_slist_reverse (connections);
429 }
430
431 static NMActiveConnection *
432 active_connection_get_by_path (NMManager *manager, const char *path)
433 {
434         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
435         GSList *iter;
436
437         g_return_val_if_fail (manager != NULL, NULL);
438         g_return_val_if_fail (path != NULL, NULL);
439
440         for (iter = priv->active_connections; iter; iter = g_slist_next (iter)) {
441                 NMActiveConnection *candidate = iter->data;
442
443                 if (g_strcmp0 (path, nm_exported_object_get_path (NM_EXPORTED_OBJECT (candidate))) == 0)
444                         return candidate;
445         }
446         return NULL;
447 }
448
449 /************************************************************************/
450
451 static void
452 _config_changed_cb (NMConfig *config, NMConfigData *config_data, NMConfigChangeFlags changes, NMConfigData *old_data, NMManager *self)
453 {
454         g_object_set (NM_MANAGER_GET_PRIVATE (self)->connectivity,
455                       NM_CONNECTIVITY_URI, nm_config_data_get_connectivity_uri (config_data),
456                       NM_CONNECTIVITY_INTERVAL, nm_config_data_get_connectivity_interval (config_data),
457                       NM_CONNECTIVITY_RESPONSE, nm_config_data_get_connectivity_response (config_data),
458                       NULL);
459
460         if (NM_FLAGS_HAS (changes, NM_CONFIG_CHANGE_GLOBAL_DNS_CONFIG))
461                 g_object_notify (G_OBJECT (self), NM_MANAGER_GLOBAL_DNS_CONFIGURATION);
462 }
463
464 /************************************************************************/
465
466 static NMDevice *
467 nm_manager_get_device_by_path (NMManager *manager, const char *path)
468 {
469         GSList *iter;
470
471         g_return_val_if_fail (path != NULL, NULL);
472
473         for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) {
474                 if (!strcmp (nm_exported_object_get_path (NM_EXPORTED_OBJECT (iter->data)), path))
475                         return NM_DEVICE (iter->data);
476         }
477         return NULL;
478 }
479
480 NMDevice *
481 nm_manager_get_device_by_ifindex (NMManager *manager, int ifindex)
482 {
483         GSList *iter;
484
485         for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) {
486                 NMDevice *device = NM_DEVICE (iter->data);
487
488                 if (nm_device_get_ifindex (device) == ifindex)
489                         return device;
490         }
491
492         return NULL;
493 }
494
495 static NMDevice *
496 find_device_by_hw_addr (NMManager *manager, const char *hwaddr)
497 {
498         GSList *iter;
499         const char *device_addr;
500
501         g_return_val_if_fail (hwaddr != NULL, NULL);
502
503         if (nm_utils_hwaddr_valid (hwaddr, -1)) {
504                 for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) {
505                         device_addr = nm_device_get_hw_address (NM_DEVICE (iter->data));
506                         if (device_addr && nm_utils_hwaddr_matches (hwaddr, -1, device_addr, -1))
507                                 return NM_DEVICE (iter->data);
508                 }
509         }
510         return NULL;
511 }
512
513 static NMDevice *
514 find_device_by_ip_iface (NMManager *self, const gchar *iface)
515 {
516         GSList *iter;
517
518         g_return_val_if_fail (iface != NULL, NULL);
519
520         for (iter = NM_MANAGER_GET_PRIVATE (self)->devices; iter; iter = g_slist_next (iter)) {
521                 NMDevice *candidate = iter->data;
522
523                 if (   nm_device_is_real (candidate)
524                     && g_strcmp0 (nm_device_get_ip_iface (candidate), iface) == 0)
525                         return candidate;
526         }
527         return NULL;
528 }
529
530 /**
531  * find_device_by_iface:
532  * @self: the #NMManager
533  * @iface: the device interface to find
534  * @connection: a connection to ensure the returned device is compatible with
535  * @slave: a slave connection to ensure a master is compatible with
536  *
537  * Finds a device by interface name, preferring realized devices.  If @slave
538  * is given, this function will only return master devices and will ensure
539  * @slave, when activated, can be a slave of the returned master device.  If
540  * @connection is given, this function will only consider devices that are
541  * compatible with @connection.
542  *
543  * Returns: the matching #NMDevice
544  */
545 static NMDevice *
546 find_device_by_iface (NMManager *self,
547                       const char *iface,
548                       NMConnection *connection,
549                       NMConnection *slave)
550 {
551         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
552         NMDevice *fallback = NULL;
553         GSList *iter;
554
555         g_return_val_if_fail (iface != NULL, NULL);
556
557         for (iter = priv->devices; iter; iter = iter->next) {
558                 NMDevice *candidate = iter->data;
559
560                 if (strcmp (nm_device_get_iface (candidate), iface))
561                         continue;
562                 if (connection && !nm_device_check_connection_compatible (candidate, connection))
563                         continue;
564                 if (slave) {
565                         if (!nm_device_is_master (candidate))
566                                 continue;
567                         if (!nm_device_check_slave_connection_compatible (candidate, slave))
568                                 continue;
569                 }
570
571                 if (nm_device_is_real (candidate))
572                         return candidate;
573                 else if (!fallback)
574                         fallback = candidate;
575         }
576         return fallback;
577 }
578
579 static gboolean
580 manager_sleeping (NMManager *self)
581 {
582         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
583
584         if (priv->sleeping || !priv->net_enabled)
585                 return TRUE;
586         return FALSE;
587 }
588
589 static const char *
590 _nm_state_to_string (NMState state)
591 {
592         switch (state) {
593         case NM_STATE_ASLEEP:
594                 return "ASLEEP";
595         case NM_STATE_DISCONNECTED:
596                 return "DISCONNECTED";
597         case NM_STATE_DISCONNECTING:
598                 return "DISCONNECTING";
599         case NM_STATE_CONNECTING:
600                 return "CONNECTING";
601         case NM_STATE_CONNECTED_LOCAL:
602                 return "CONNECTED_LOCAL";
603         case NM_STATE_CONNECTED_SITE:
604                 return "CONNECTED_SITE";
605         case NM_STATE_CONNECTED_GLOBAL:
606                 return "CONNECTED_GLOBAL";
607         case NM_STATE_UNKNOWN:
608         default:
609                 return "UNKNOWN";
610         }
611 }
612
613 static void
614 set_state (NMManager *self, NMState state)
615 {
616         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
617
618         if (priv->state == state)
619                 return;
620
621         priv->state = state;
622
623         _LOGI (LOGD_CORE, "NetworkManager state is now %s", _nm_state_to_string (state));
624
625         g_object_notify (G_OBJECT (self), NM_MANAGER_STATE);
626         g_signal_emit (self, signals[STATE_CHANGED], 0, priv->state);
627 }
628
629 static void
630 checked_connectivity (GObject *object, GAsyncResult *result, gpointer user_data)
631 {
632         NMManager *manager = user_data;
633         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
634         NMConnectivityState connectivity;
635
636         if (priv->state == NM_STATE_CONNECTING || priv->state == NM_STATE_CONNECTED_SITE) {
637                 connectivity = nm_connectivity_check_finish (priv->connectivity, result, NULL);
638
639                 if (connectivity == NM_CONNECTIVITY_FULL)
640                         set_state (manager, NM_STATE_CONNECTED_GLOBAL);
641                 else if (   connectivity == NM_CONNECTIVITY_PORTAL
642                          || connectivity == NM_CONNECTIVITY_LIMITED)
643                         set_state (manager, NM_STATE_CONNECTED_SITE);
644                 g_object_notify (G_OBJECT (manager), NM_MANAGER_CONNECTIVITY);
645         }
646
647         g_object_unref (manager);
648 }
649
650 static NMState
651 find_best_device_state (NMManager *manager)
652 {
653         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
654         NMState best_state = NM_STATE_DISCONNECTED;
655         GSList *iter;
656
657         for (iter = priv->active_connections; iter; iter = iter->next) {
658                 NMActiveConnection *ac = NM_ACTIVE_CONNECTION (iter->data);
659                 NMActiveConnectionState ac_state = nm_active_connection_get_state (ac);
660
661                 switch (ac_state) {
662                 case NM_ACTIVE_CONNECTION_STATE_ACTIVATED:
663                         if (   nm_active_connection_get_default (ac)
664                             || nm_active_connection_get_default6 (ac)) {
665                                 if (nm_connectivity_get_state (priv->connectivity) == NM_CONNECTIVITY_FULL)
666                                         return NM_STATE_CONNECTED_GLOBAL;
667
668                                 best_state = NM_STATE_CONNECTED_SITE;
669                         } else {
670                                 if (best_state < NM_STATE_CONNECTING)
671                                         best_state = NM_STATE_CONNECTED_LOCAL;
672                         }
673                         break;
674                 case NM_ACTIVE_CONNECTION_STATE_ACTIVATING:
675                         if (!nm_active_connection_get_assumed (ac)) {
676                                 if (best_state != NM_STATE_CONNECTED_GLOBAL)
677                                         best_state = NM_STATE_CONNECTING;
678                         }
679                         break;
680                 case NM_ACTIVE_CONNECTION_STATE_DEACTIVATING:
681                         if (!nm_active_connection_get_assumed (ac)) {
682                                 if (best_state < NM_STATE_DISCONNECTING)
683                                         best_state = NM_STATE_DISCONNECTING;
684                         }
685                         break;
686                 default:
687                         break;
688                 }
689         }
690
691         return best_state;
692 }
693
694 static void
695 nm_manager_update_metered (NMManager *self)
696 {
697         NMManagerPrivate *priv;
698         NMDevice *device;
699         NMMetered value = NM_METERED_UNKNOWN;
700
701         g_return_if_fail (NM_IS_MANAGER (self));
702         priv = NM_MANAGER_GET_PRIVATE (self);
703
704         if (priv->primary_connection) {
705                 device =  nm_active_connection_get_device (priv->primary_connection);
706                 if (device)
707                         value = nm_device_get_metered (device);
708         }
709
710         if (value != priv->metered) {
711                 priv->metered = value;
712                 _LOGD (LOGD_CORE, "new metered value: %d", (int) priv->metered);
713                 g_object_notify (G_OBJECT (self), NM_MANAGER_METERED);
714         }
715 }
716
717 static void
718 nm_manager_update_state (NMManager *manager)
719 {
720         NMManagerPrivate *priv;
721         NMState new_state = NM_STATE_DISCONNECTED;
722
723         g_return_if_fail (NM_IS_MANAGER (manager));
724
725         priv = NM_MANAGER_GET_PRIVATE (manager);
726
727         if (manager_sleeping (manager))
728                 new_state = NM_STATE_ASLEEP;
729         else
730                 new_state = find_best_device_state (manager);
731
732         nm_connectivity_set_online (priv->connectivity, new_state >= NM_STATE_CONNECTED_LOCAL);
733
734         if (new_state == NM_STATE_CONNECTED_SITE) {
735                 nm_connectivity_check_async (priv->connectivity,
736                                              checked_connectivity,
737                                              g_object_ref (manager));
738         }
739
740         set_state (manager, new_state);
741 }
742
743 static void
744 manager_device_state_changed (NMDevice *device,
745                               NMDeviceState new_state,
746                               NMDeviceState old_state,
747                               NMDeviceStateReason reason,
748                               gpointer user_data)
749 {
750         NMManager *self = NM_MANAGER (user_data);
751         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
752
753         switch (new_state) {
754         case NM_DEVICE_STATE_UNMANAGED:
755         case NM_DEVICE_STATE_UNAVAILABLE:
756         case NM_DEVICE_STATE_DISCONNECTED:
757         case NM_DEVICE_STATE_PREPARE:
758         case NM_DEVICE_STATE_FAILED:
759                 g_object_notify (G_OBJECT (self), NM_MANAGER_ACTIVE_CONNECTIONS);
760                 break;
761         default:
762                 break;
763         }
764
765         if (   new_state == NM_DEVICE_STATE_UNAVAILABLE
766             || new_state == NM_DEVICE_STATE_DISCONNECTED)
767                 nm_settings_device_added (priv->settings, device);
768 }
769
770 static void device_has_pending_action_changed (NMDevice *device,
771                                                GParamSpec *pspec,
772                                                NMManager *self);
773
774 static void
775 check_if_startup_complete (NMManager *self)
776 {
777         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
778         GSList *iter;
779
780         if (!priv->startup)
781                 return;
782
783         if (!priv->devices_inited)
784                 return;
785
786         if (!nm_settings_get_startup_complete (priv->settings)) {
787                 _LOGD (LOGD_CORE, "check_if_startup_complete returns FALSE because of NMSettings");
788                 return;
789         }
790
791         for (iter = priv->devices; iter; iter = iter->next) {
792                 NMDevice *dev = iter->data;
793
794                 if (nm_device_has_pending_action (dev)) {
795                         _LOGD (LOGD_CORE, "check_if_startup_complete returns FALSE because of %s",
796                                nm_device_get_iface (dev));
797                         return;
798                 }
799         }
800
801         _LOGI (LOGD_CORE, "startup complete");
802
803         priv->startup = FALSE;
804         g_object_notify (G_OBJECT (self), "startup");
805
806         /* We don't have to watch notify::has-pending-action any more. */
807         for (iter = priv->devices; iter; iter = iter->next) {
808                 NMDevice *dev = iter->data;
809
810                 g_signal_handlers_disconnect_by_func (dev, G_CALLBACK (device_has_pending_action_changed), self);
811         }
812
813         if (nm_config_get_configure_and_quit (nm_config_get ()))
814                 g_signal_emit (self, signals[CONFIGURE_QUIT], 0);
815 }
816
817 static void
818 device_has_pending_action_changed (NMDevice *device,
819                                    GParamSpec *pspec,
820                                    NMManager *self)
821 {
822         check_if_startup_complete (self);
823 }
824
825 static void
826 settings_startup_complete_changed (NMSettings *settings,
827                                    GParamSpec *pspec,
828                                    NMManager *self)
829 {
830         check_if_startup_complete (self);
831 }
832
833 static void
834 remove_device (NMManager *self,
835                NMDevice *device,
836                gboolean quitting,
837                gboolean allow_unmanage)
838 {
839         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
840
841         _LOGD (LOGD_DEVICE, "(%s): removing device (allow_unmanage %d, managed %d)",
842                nm_device_get_iface (device), allow_unmanage, nm_device_get_managed (device, FALSE));
843
844         if (allow_unmanage && nm_device_get_managed (device, FALSE)) {
845                 NMActRequest *req = nm_device_get_act_request (device);
846                 gboolean unmanage = FALSE;
847
848                 /* Leave activated interfaces up when quitting so their configuration
849                  * can be taken over when NM restarts.  This ensures connectivity while
850                  * NM is stopped. Devices which do not support connection assumption
851                  * cannot be left up.
852                  */
853                 if (!quitting)  /* Forced removal; device already gone */
854                         unmanage = TRUE;
855                 else if (!nm_device_can_assume_active_connection (device))
856                         unmanage = TRUE;
857                 else if (!req)
858                         unmanage = TRUE;
859
860                 if (unmanage) {
861                         if (quitting)
862                                 nm_device_set_unmanaged_by_quitting (device);
863                         else
864                                 nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_PLATFORM_INIT, TRUE, NM_DEVICE_STATE_REASON_REMOVED);
865                 } else if (quitting && nm_config_get_configure_and_quit (nm_config_get ())) {
866                         nm_device_spawn_iface_helper (device);
867                 }
868         }
869
870         g_signal_handlers_disconnect_matched (device, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
871
872         nm_settings_device_removed (priv->settings, device, quitting);
873         priv->devices = g_slist_remove (priv->devices, device);
874
875         if (nm_device_is_real (device)) {
876                 g_signal_emit (self, signals[DEVICE_REMOVED], 0, device);
877                 g_object_notify (G_OBJECT (self), NM_MANAGER_DEVICES);
878                 nm_device_removed (device);
879         }
880         g_signal_emit (self, signals[INTERNAL_DEVICE_REMOVED], 0, device);
881         g_object_notify (G_OBJECT (self), NM_MANAGER_ALL_DEVICES);
882
883         nm_exported_object_clear_and_unexport (&device);
884
885         check_if_startup_complete (self);
886 }
887
888 static void
889 device_removed_cb (NMDevice *device, gpointer user_data)
890 {
891         remove_device (NM_MANAGER (user_data), device, FALSE, TRUE);
892 }
893
894 NMState
895 nm_manager_get_state (NMManager *manager)
896 {
897         g_return_val_if_fail (NM_IS_MANAGER (manager), NM_STATE_UNKNOWN);
898
899         return NM_MANAGER_GET_PRIVATE (manager)->state;
900 }
901
902 /***************************/
903
904 static NMDevice *
905 find_parent_device_for_connection (NMManager *self, NMConnection *connection, NMDeviceFactory *cached_factory)
906 {
907         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
908         NMDeviceFactory *factory;
909         const char *parent_name = NULL;
910         NMSettingsConnection *parent_connection;
911         NMDevice *parent, *first_compatible = NULL;
912         GSList *iter;
913
914         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
915
916         if (!cached_factory) {
917                 factory = nm_device_factory_manager_find_factory_for_connection (connection);
918                 if (!factory)
919                         return NULL;
920         } else
921                 factory = cached_factory;
922
923         parent_name = nm_device_factory_get_connection_parent (factory, connection);
924         if (!parent_name)
925                 return NULL;
926
927         /* Try as an interface name of a parent device */
928         parent = find_device_by_iface (self, parent_name, NULL, NULL);
929         if (parent)
930                 return parent;
931
932         /* Maybe a hardware address */
933         parent = find_device_by_hw_addr (self, parent_name);
934         if (parent)
935                 return parent;
936
937         /* Maybe a connection UUID */
938         parent_connection = nm_settings_get_connection_by_uuid (priv->settings, parent_name);
939         if (!parent_connection)
940                 return NULL;
941
942         /* Check if the parent connection is currently activated or is comaptible
943          * with some known device.
944          */
945         for (iter = priv->devices; iter; iter = iter->next) {
946                 NMDevice *candidate = iter->data;
947
948                 if (nm_device_get_settings_connection (candidate) == parent_connection)
949                         return candidate;
950
951                 if (   !first_compatible
952                     && nm_device_check_connection_compatible (candidate, NM_CONNECTION (parent_connection)))
953                         first_compatible = candidate;
954         }
955
956         return first_compatible;
957 }
958
959 /**
960  * nm_manager_get_connection_iface:
961  * @self: the #NMManager
962  * @connection: the #NMConnection to get the interface for
963  * @out_parent: on success, the parent device if any
964  * @error: an error if determining the virtual interface name failed
965  *
966  * Given @connection, returns the interface name that the connection
967  * would need to use when activated. %NULL is returned if the name
968  * is not specified in connection or a the name for a virtual device
969  * could not be generated.
970  *
971  * Returns: the expected interface name (caller takes ownership), or %NULL
972  */
973 char *
974 nm_manager_get_connection_iface (NMManager *self,
975                                  NMConnection *connection,
976                                  NMDevice **out_parent,
977                                  GError **error)
978 {
979         NMDeviceFactory *factory;
980         char *iface = NULL;
981         NMDevice *parent = NULL;
982
983         if (out_parent)
984                 *out_parent = NULL;
985
986         factory = nm_device_factory_manager_find_factory_for_connection (connection);
987         if (!factory) {
988                 g_set_error (error,
989                              NM_MANAGER_ERROR,
990                              NM_MANAGER_ERROR_FAILED,
991                              "NetworkManager plugin for '%s' unavailable",
992                              nm_connection_get_connection_type (connection));
993                 return NULL;
994         }
995
996         if (   !out_parent
997             && !NM_DEVICE_FACTORY_GET_INTERFACE (factory)->get_connection_iface) {
998                 /* optimization. Shortcut lookup of the partent device. */
999                 iface = g_strdup (nm_connection_get_interface_name (connection));
1000                 if (!iface) {
1001                         g_set_error (error,
1002                                      NM_MANAGER_ERROR,
1003                                      NM_MANAGER_ERROR_FAILED,
1004                                      "failed to determine interface name: error determine name for %s",
1005                                      nm_connection_get_connection_type (connection));
1006                 }
1007                 return iface;
1008         }
1009
1010         parent = find_parent_device_for_connection (self, connection, factory);
1011         iface = nm_device_factory_get_connection_iface (factory,
1012                                                         connection,
1013                                                         parent ? nm_device_get_ip_iface (parent) : NULL,
1014                                                         error);
1015         if (!iface)
1016                 return NULL;
1017
1018         if (out_parent)
1019                 *out_parent = parent;
1020         return iface;
1021 }
1022
1023 /**
1024  * system_create_virtual_device:
1025  * @self: the #NMManager
1026  * @connection: the connection which might require a virtual device
1027  *
1028  * If @connection requires a virtual device and one does not yet exist for it,
1029  * creates that device.
1030  *
1031  * Returns: A #NMDevice that was just realized; %NULL if none
1032  */
1033 static NMDevice *
1034 system_create_virtual_device (NMManager *self, NMConnection *connection)
1035 {
1036         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1037         NMDeviceFactory *factory;
1038         gs_free_slist GSList *connections = NULL;
1039         GSList *iter;
1040         gs_free char *iface = NULL;
1041         NMDevice *device = NULL, *parent = NULL;
1042         GError *error = NULL;
1043
1044         g_return_val_if_fail (NM_IS_MANAGER (self), NULL);
1045         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
1046
1047         iface = nm_manager_get_connection_iface (self, connection, &parent, &error);
1048         if (!iface) {
1049                 _LOGW (LOGD_DEVICE, "(%s) can't get a name of a virtual device: %s",
1050                        nm_connection_get_id (connection), error->message);
1051                 g_error_free (error);
1052                 return NULL;
1053         }
1054
1055         /* See if there's a device that is already compatible with this connection */
1056         for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
1057                 NMDevice *candidate = iter->data;
1058
1059                 if (nm_device_check_connection_compatible (candidate, connection)) {
1060                         if (nm_device_is_real (candidate)) {
1061                                 _LOGD (LOGD_DEVICE, "(%s) already created virtual interface name %s",
1062                                        nm_connection_get_id (connection), iface);
1063                                 return NULL;
1064                         }
1065
1066                         device = candidate;
1067                         break;
1068                 }
1069         }
1070
1071         if (!device) {
1072                 /* No matching device found. Proceed creating a new one. */
1073
1074                 factory = nm_device_factory_manager_find_factory_for_connection (connection);
1075                 if (!factory) {
1076                         _LOGE (LOGD_DEVICE, "(%s:%s) NetworkManager plugin for '%s' unavailable",
1077                                nm_connection_get_id (connection), iface,
1078                                nm_connection_get_connection_type (connection));
1079                         return NULL;
1080                 }
1081
1082                 device = nm_device_factory_create_device (factory, iface, NULL, connection, NULL, &error);
1083                 if (!device) {
1084                         _LOGW (LOGD_DEVICE, "(%s) factory can't create the device: %s",
1085                                nm_connection_get_id (connection), error->message);
1086                         g_error_free (error);
1087                         return NULL;
1088                 }
1089
1090                 if (!add_device (self, device, &error)) {
1091                         _LOGW (LOGD_DEVICE, "(%s) can't register the device with manager: %s",
1092                                nm_connection_get_id (connection), error->message);
1093                         g_error_free (error);
1094                         g_object_unref (device);
1095                         return NULL;
1096                 }
1097
1098                 /* Add device takes a reference that NMManager still owns, so it's
1099                  * safe to unref here and still return @device.
1100                  */
1101                 g_object_unref (device);
1102         }
1103
1104         /* Create backing resources if the device has any autoconnect connections */
1105         connections = nm_settings_get_connections (priv->settings);
1106         for (iter = connections; iter; iter = g_slist_next (iter)) {
1107                 NMConnection *candidate = iter->data;
1108                 NMSettingConnection *s_con;
1109
1110                 if (!nm_device_check_connection_compatible (device, candidate))
1111                         continue;
1112
1113                 s_con = nm_connection_get_setting_connection (candidate);
1114                 g_assert (s_con);
1115                 if (!nm_setting_connection_get_autoconnect (s_con))
1116                         continue;
1117
1118                 /* Create any backing resources the device needs */
1119                 if (!nm_device_create_and_realize (device, connection, parent, &error)) {
1120                         _LOGW (LOGD_DEVICE, "(%s) couldn't create the device: %s",
1121                                nm_connection_get_id (connection), error->message);
1122                         g_error_free (error);
1123                         remove_device (self, device, FALSE, TRUE);
1124                         return NULL;
1125                 }
1126                 break;
1127         }
1128
1129         return device;
1130 }
1131
1132 static void
1133 retry_connections_for_parent_device (NMManager *self, NMDevice *device)
1134 {
1135         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1136         GSList *connections, *iter;
1137
1138         g_return_if_fail (device);
1139
1140         connections = nm_settings_get_connections (priv->settings);
1141         for (iter = connections; iter; iter = g_slist_next (iter)) {
1142                 NMConnection *candidate = iter->data;
1143                 gs_free_error GError *error = NULL;
1144                 gs_free char *ifname = NULL;
1145                 NMDevice *parent;
1146
1147                 parent = find_parent_device_for_connection (self, candidate, NULL);
1148                 if (parent == device) {
1149                         /* Only try to activate devices that don't already exist */
1150                         ifname = nm_manager_get_connection_iface (self, candidate, &parent, &error);
1151                         if (ifname) {
1152                                 if (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, ifname))
1153                                         connection_changed (priv->settings, candidate, self);
1154                         }
1155                 }
1156         }
1157
1158         g_slist_free (connections);
1159 }
1160
1161 static void
1162 connection_changed (NMSettings *settings,
1163                     NMConnection *connection,
1164                     NMManager *manager)
1165 {
1166         NMDevice *device;
1167
1168         if (!nm_connection_is_virtual (connection))
1169                 return;
1170
1171         device = system_create_virtual_device (manager, connection);
1172         if (!device)
1173                 return;
1174
1175         /* Maybe the device that was created was needed by some other
1176          * connection's device (parent of a VLAN). Let the connections
1177          * can use the newly created device as a parent know. */
1178         retry_connections_for_parent_device (manager, device);
1179 }
1180
1181 static void
1182 connection_removed (NMSettings *settings,
1183                     NMSettingsConnection *connection,
1184                     NMManager *manager)
1185 {
1186         /*
1187          * Do not delete existing virtual devices to keep connectivity up.
1188          * Virtual devices are reused when NetworkManager is restarted.
1189          */
1190 }
1191
1192 static void
1193 system_unmanaged_devices_changed_cb (NMSettings *settings,
1194                                      GParamSpec *pspec,
1195                                      gpointer user_data)
1196 {
1197         NMManager *self = NM_MANAGER (user_data);
1198         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1199         const GSList *unmanaged_specs, *iter;
1200
1201         unmanaged_specs = nm_settings_get_unmanaged_specs (priv->settings);
1202         for (iter = priv->devices; iter; iter = g_slist_next (iter))
1203                 nm_device_set_unmanaged_by_user_config (NM_DEVICE (iter->data), unmanaged_specs);
1204 }
1205
1206 static void
1207 system_hostname_changed_cb (NMSettings *settings,
1208                             GParamSpec *pspec,
1209                             gpointer user_data)
1210 {
1211         NMManager *self = NM_MANAGER (user_data);
1212         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1213         char *hostname;
1214
1215         hostname = nm_settings_get_hostname (priv->settings);
1216
1217         /* nm_settings_get_hostname() does not return an empty hostname. */
1218         nm_assert (!hostname || *hostname);
1219
1220         if (!hostname && !priv->hostname)
1221                 return;
1222         if (hostname && priv->hostname && !strcmp (hostname, priv->hostname)) {
1223                 g_free (hostname);
1224                 return;
1225         }
1226
1227         /* realloc, to free possibly trailing data after NUL. */
1228         if (hostname)
1229                 hostname = g_realloc (hostname, strlen (hostname) + 1);
1230
1231         g_free (priv->hostname);
1232         priv->hostname = hostname;
1233         g_object_notify (G_OBJECT (self), NM_MANAGER_HOSTNAME);
1234
1235         nm_dhcp_manager_set_default_hostname (nm_dhcp_manager_get (), priv->hostname);
1236 }
1237
1238 /*******************************************************************/
1239 /* General NMManager stuff                                         */
1240 /*******************************************************************/
1241
1242 /* Store value into key-file; supported types: boolean, int, string */
1243 static gboolean
1244 write_value_to_state_file (const char *filename,
1245                            const char *group,
1246                            const char *key,
1247                            GType value_type,
1248                            gpointer value,
1249                            GError **error)
1250 {
1251         GKeyFile *key_file;
1252         char *data;
1253         gsize len = 0;
1254         gboolean ret = FALSE;
1255
1256         g_return_val_if_fail (filename != NULL, FALSE);
1257         g_return_val_if_fail (group != NULL, FALSE);
1258         g_return_val_if_fail (key != NULL, FALSE);
1259         g_return_val_if_fail (value_type == G_TYPE_BOOLEAN ||
1260                               value_type == G_TYPE_INT ||
1261                               value_type == G_TYPE_STRING,
1262                               FALSE);
1263
1264         key_file = g_key_file_new ();
1265
1266         g_key_file_set_list_separator (key_file, ',');
1267         g_key_file_load_from_file (key_file, filename, G_KEY_FILE_KEEP_COMMENTS, NULL);
1268         switch (value_type) {
1269         case G_TYPE_BOOLEAN:
1270                 g_key_file_set_boolean (key_file, group, key, *((gboolean *) value));
1271                 break;
1272         case G_TYPE_INT:
1273                 g_key_file_set_integer (key_file, group, key, *((gint *) value));
1274                 break;
1275         case G_TYPE_STRING:
1276                 g_key_file_set_string (key_file, group, key, *((const gchar **) value));
1277                 break;
1278         }
1279
1280         data = g_key_file_to_data (key_file, &len, NULL);
1281         if (data) {
1282                 ret = g_file_set_contents (filename, data, len, error);
1283                 g_free (data);
1284         }
1285         g_key_file_free (key_file);
1286
1287         return ret;
1288 }
1289
1290 static gboolean
1291 radio_enabled_for_rstate (RadioState *rstate, gboolean check_changeable)
1292 {
1293         gboolean enabled;
1294
1295         enabled = rstate->user_enabled && rstate->hw_enabled;
1296         if (check_changeable)
1297                 enabled &= rstate->sw_enabled;
1298         return enabled;
1299 }
1300
1301 static gboolean
1302 radio_enabled_for_type (NMManager *self, RfKillType rtype, gboolean check_changeable)
1303 {
1304         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1305
1306         return radio_enabled_for_rstate (&priv->radio_states[rtype], check_changeable);
1307 }
1308
1309 static void
1310 manager_update_radio_enabled (NMManager *self,
1311                               RadioState *rstate,
1312                               gboolean enabled)
1313 {
1314         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1315         GSList *iter;
1316
1317         /* Do nothing for radio types not yet implemented */
1318         if (!rstate->prop)
1319                 return;
1320
1321         g_object_notify (G_OBJECT (self), rstate->prop);
1322
1323         /* Don't touch devices if asleep/networking disabled */
1324         if (manager_sleeping (self))
1325                 return;
1326
1327         /* enable/disable wireless devices as required */
1328         for (iter = priv->devices; iter; iter = iter->next) {
1329                 NMDevice *device = NM_DEVICE (iter->data);
1330
1331                 if (nm_device_get_rfkill_type (device) == rstate->rtype) {
1332                         _LOGD (LOGD_RFKILL, "(%s): setting radio %s",
1333                                nm_device_get_iface (device),
1334                                enabled ? "enabled" : "disabled");
1335                         nm_device_set_enabled (device, enabled);
1336                 }
1337         }
1338 }
1339
1340 static void
1341 update_rstate_from_rfkill (NMRfkillManager *rfkill_mgr, RadioState *rstate)
1342 {
1343         switch (nm_rfkill_manager_get_rfkill_state (rfkill_mgr, rstate->rtype)) {
1344         case RFKILL_UNBLOCKED:
1345                 rstate->sw_enabled = TRUE;
1346                 rstate->hw_enabled = TRUE;
1347                 break;
1348         case RFKILL_SOFT_BLOCKED:
1349                 rstate->sw_enabled = FALSE;
1350                 rstate->hw_enabled = TRUE;
1351                 break;
1352         case RFKILL_HARD_BLOCKED:
1353                 rstate->sw_enabled = FALSE;
1354                 rstate->hw_enabled = FALSE;
1355                 break;
1356         default:
1357                 g_warn_if_reached ();
1358                 break;
1359         }
1360 }
1361
1362 static void
1363 manager_rfkill_update_one_type (NMManager *self,
1364                                 RadioState *rstate,
1365                                 RfKillType rtype)
1366 {
1367         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1368         gboolean old_enabled, new_enabled, old_rfkilled, new_rfkilled, old_hwe;
1369
1370         old_enabled = radio_enabled_for_rstate (rstate, TRUE);
1371         old_rfkilled = rstate->hw_enabled && rstate->sw_enabled;
1372         old_hwe = rstate->hw_enabled;
1373
1374         /* recheck kernel rfkill state */
1375         update_rstate_from_rfkill (priv->rfkill_mgr, rstate);
1376
1377         /* Print out all states affecting device enablement */
1378         if (rstate->desc) {
1379                 _LOGD (LOGD_RFKILL, "%s hw-enabled %d sw-enabled %d",
1380                        rstate->desc, rstate->hw_enabled, rstate->sw_enabled);
1381         }
1382
1383         /* Log new killswitch state */
1384         new_rfkilled = rstate->hw_enabled && rstate->sw_enabled;
1385         if (old_rfkilled != new_rfkilled) {
1386                 _LOGI (LOGD_RFKILL, "%s now %s by radio killswitch",
1387                        rstate->desc,
1388                        new_rfkilled ? "enabled" : "disabled");
1389         }
1390
1391         /* Send out property changed signal for HW enabled */
1392         if (rstate->hw_enabled != old_hwe) {
1393                 if (rstate->hw_prop)
1394                         g_object_notify (G_OBJECT (self), rstate->hw_prop);
1395         }
1396
1397         /* And finally update the actual device radio state itself; respect the
1398          * daemon state here because this is never called from user-triggered
1399          * radio changes and we only want to ignore the daemon enabled state when
1400          * handling user radio change requests.
1401          */
1402         new_enabled = radio_enabled_for_rstate (rstate, TRUE);
1403         if (new_enabled != old_enabled)
1404                 manager_update_radio_enabled (self, rstate, new_enabled);
1405 }
1406
1407 static void
1408 nm_manager_rfkill_update (NMManager *self, RfKillType rtype)
1409 {
1410         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1411         guint i;
1412
1413         if (rtype != RFKILL_TYPE_UNKNOWN)
1414                 manager_rfkill_update_one_type (self, &priv->radio_states[rtype], rtype);
1415         else {
1416                 /* Otherwise sync all radio types */
1417                 for (i = 0; i < RFKILL_TYPE_MAX; i++)
1418                         manager_rfkill_update_one_type (self, &priv->radio_states[i], i);
1419         }
1420 }
1421
1422 static void
1423 device_auth_done_cb (NMAuthChain *chain,
1424                      GError *auth_error,
1425                      GDBusMethodInvocation *context,
1426                      gpointer user_data)
1427 {
1428         NMManager *self = NM_MANAGER (user_data);
1429         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1430         GError *error = NULL;
1431         NMAuthCallResult result;
1432         NMDevice *device;
1433         const char *permission;
1434         NMDeviceAuthRequestFunc callback;
1435         NMAuthSubject *subject;
1436
1437         g_assert (context);
1438
1439         priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
1440
1441         permission = nm_auth_chain_get_data (chain, "requested-permission");
1442         g_assert (permission);
1443         callback = nm_auth_chain_get_data (chain, "callback");
1444         g_assert (callback);
1445         device = nm_auth_chain_get_data (chain, "device");
1446         g_assert (device);
1447
1448         result = nm_auth_chain_get_result (chain, permission);
1449         subject = nm_auth_chain_get_subject (chain);
1450
1451         if (auth_error) {
1452                 /* translate the auth error into a manager permission denied error */
1453                 _LOGD (LOGD_CORE, "%s request failed: %s", permission, auth_error->message);
1454                 error = g_error_new (NM_MANAGER_ERROR,
1455                                      NM_MANAGER_ERROR_PERMISSION_DENIED,
1456                                      "%s request failed: %s",
1457                                      permission, auth_error->message);
1458         } else if (result != NM_AUTH_CALL_RESULT_YES) {
1459                 _LOGD (LOGD_CORE, "%s request failed: not authorized", permission);
1460                 error = g_error_new (NM_MANAGER_ERROR,
1461                                      NM_MANAGER_ERROR_PERMISSION_DENIED,
1462                                      "%s request failed: not authorized",
1463                                      permission);
1464         }
1465
1466         g_assert (error || (result == NM_AUTH_CALL_RESULT_YES));
1467
1468         callback (device,
1469                   context,
1470                   subject,
1471                   error,
1472                   nm_auth_chain_get_data (chain, "user-data"));
1473
1474         g_clear_error (&error);
1475         nm_auth_chain_unref (chain);
1476 }
1477
1478 static void
1479 device_auth_request_cb (NMDevice *device,
1480                         GDBusMethodInvocation *context,
1481                         NMConnection *connection,
1482                         const char *permission,
1483                         gboolean allow_interaction,
1484                         NMDeviceAuthRequestFunc callback,
1485                         gpointer user_data,
1486                         NMManager *self)
1487 {
1488         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1489         GError *error = NULL;
1490         NMAuthSubject *subject = NULL;
1491         char *error_desc = NULL;
1492         NMAuthChain *chain;
1493
1494         /* Validate the caller */
1495         subject = nm_auth_subject_new_unix_process_from_context (context);
1496         if (!subject) {
1497                 error = g_error_new_literal (NM_MANAGER_ERROR,
1498                                              NM_MANAGER_ERROR_PERMISSION_DENIED,
1499                                              "Failed to get request UID.");
1500                 goto done;
1501         }
1502
1503         /* Ensure the subject has permissions for this connection */
1504         if (connection && !nm_auth_is_subject_in_acl (connection,
1505                                                       subject,
1506                                                       &error_desc)) {
1507                 error = g_error_new_literal (NM_MANAGER_ERROR,
1508                                              NM_MANAGER_ERROR_PERMISSION_DENIED,
1509                                              error_desc);
1510                 g_free (error_desc);
1511                 goto done;
1512         }
1513
1514         /* Validate the request */
1515         chain = nm_auth_chain_new_subject (subject, context, device_auth_done_cb, self);
1516         if (!chain) {
1517                 error = g_error_new_literal (NM_MANAGER_ERROR,
1518                                              NM_MANAGER_ERROR_PERMISSION_DENIED,
1519                                              "Unable to authenticate request.");
1520                 goto done;
1521         }
1522
1523         priv->auth_chains = g_slist_append (priv->auth_chains, chain);
1524         nm_auth_chain_set_data (chain, "device", g_object_ref (device), g_object_unref);
1525         nm_auth_chain_set_data (chain, "requested-permission", g_strdup (permission), g_free);
1526         nm_auth_chain_set_data (chain, "callback", callback, NULL);
1527         nm_auth_chain_set_data (chain, "user-data", user_data, NULL);
1528         nm_auth_chain_add_call (chain, permission, allow_interaction);
1529
1530 done:
1531         if (error)
1532                 callback (device, context, subject, error, user_data);
1533
1534         g_clear_object (&subject);
1535         g_clear_error (&error);
1536 }
1537
1538 static gboolean
1539 match_connection_filter (NMConnection *connection, gpointer user_data)
1540 {
1541         if (nm_settings_connection_get_nm_generated_assumed (NM_SETTINGS_CONNECTION (connection)))
1542                 return FALSE;
1543
1544         return nm_device_check_connection_compatible (NM_DEVICE (user_data), connection);
1545 }
1546
1547 /**
1548  * get_existing_connection:
1549  * @manager: #NMManager instance
1550  * @device: #NMDevice instance
1551  * @out_generated: (allow-none): return TRUE, if the connection was generated.
1552  *
1553  * Returns: a #NMSettingsConnection to be assumed by the device, or %NULL if
1554  *   the device does not support assuming existing connections.
1555  */
1556 static NMSettingsConnection *
1557 get_existing_connection (NMManager *self, NMDevice *device, gboolean *out_generated)
1558 {
1559         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1560         gs_free_slist GSList *connections = nm_manager_get_activatable_connections (self);
1561         NMConnection *connection = NULL;
1562         NMSettingsConnection *matched;
1563         NMSettingsConnection *added = NULL;
1564         GError *error = NULL;
1565         NMDevice *master = NULL;
1566         int ifindex = nm_device_get_ifindex (device);
1567
1568         if (out_generated)
1569                 *out_generated = FALSE;
1570
1571         nm_device_capture_initial_config (device);
1572
1573         if (ifindex) {
1574                 int master_ifindex = nm_platform_link_get_master (NM_PLATFORM_GET, ifindex);
1575
1576                 if (master_ifindex) {
1577                         master = nm_manager_get_device_by_ifindex (self, master_ifindex);
1578                         if (!master) {
1579                                 _LOGD (LOGD_DEVICE, "(%s): cannot generate connection for slave before its master (%s/%d)",
1580                                        nm_device_get_iface (device), nm_platform_link_get_name (NM_PLATFORM_GET, master_ifindex), master_ifindex);
1581                                 return NULL;
1582                         }
1583                         if (!nm_device_get_act_request (master)) {
1584                                 _LOGD (LOGD_DEVICE, "(%s): cannot generate connection for slave before master %s activates",
1585                                        nm_device_get_iface (device), nm_device_get_iface (master));
1586                                 return NULL;
1587                         }
1588                 }
1589         }
1590
1591         /* The core of the API is nm_device_generate_connection() function and
1592          * update_connection() virtual method and the convenient connection_type
1593          * class attribute. Subclasses supporting the new API must have
1594          * update_connection() implemented, otherwise nm_device_generate_connection()
1595          * returns NULL.
1596          */
1597         connection = nm_device_generate_connection (device, master);
1598         if (!connection)
1599                 return NULL;
1600
1601         /* Now we need to compare the generated connection to each configured
1602          * connection. The comparison function is the heart of the connection
1603          * assumption implementation and it must compare the connections very
1604          * carefully to sort out various corner cases. Also, the comparison is
1605          * not entirely symmetric.
1606          *
1607          * When no configured connection matches the generated connection, we keep
1608          * the generated connection instead.
1609          */
1610         connections = g_slist_reverse (g_slist_sort (connections, nm_settings_sort_connections));
1611         matched = NM_SETTINGS_CONNECTION (nm_utils_match_connection (connections,
1612                                                                      connection,
1613                                                                      nm_device_has_carrier (device),
1614                                                                      nm_device_get_ip4_route_metric (device),
1615                                                                      nm_device_get_ip6_route_metric (device),
1616                                                                      match_connection_filter,
1617                                                                      device));
1618         if (matched) {
1619                 _LOGI (LOGD_DEVICE, "(%s): found matching connection '%s'",
1620                        nm_device_get_iface (device),
1621                        nm_settings_connection_get_id (matched));
1622                 g_object_unref (connection);
1623                 return matched;
1624         }
1625
1626         _LOGD (LOGD_DEVICE, "(%s): generated connection '%s'",
1627                nm_device_get_iface (device),
1628                nm_connection_get_id (connection));
1629
1630         added = nm_settings_add_connection (priv->settings, connection, FALSE, &error);
1631         if (added) {
1632                 nm_settings_connection_set_flags (NM_SETTINGS_CONNECTION (added),
1633                                                   NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED |
1634                                                   NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED_ASSUMED,
1635                                                   TRUE);
1636                 if (out_generated)
1637                         *out_generated = TRUE;
1638         } else {
1639                 _LOGW (LOGD_SETTINGS, "(%s) Couldn't save generated connection '%s': %s",
1640                        nm_device_get_iface (device),
1641                        nm_connection_get_id (connection),
1642                        error->message);
1643                 g_clear_error (&error);
1644         }
1645         g_object_unref (connection);
1646
1647         return added ? added : NULL;
1648 }
1649
1650 static gboolean
1651 assume_connection (NMManager *self, NMDevice *device, NMSettingsConnection *connection)
1652 {
1653         NMActiveConnection *active, *master_ac;
1654         NMAuthSubject *subject;
1655         GError *error = NULL;
1656
1657         _LOGD (LOGD_DEVICE, "(%s): will attempt to assume connection",
1658                nm_device_get_iface (device));
1659
1660         /* Move device to DISCONNECTED to activate the connection */
1661         if (nm_device_get_state (device) == NM_DEVICE_STATE_UNAVAILABLE) {
1662                 nm_device_state_changed (device,
1663                                          NM_DEVICE_STATE_DISCONNECTED,
1664                                          NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED);
1665         }
1666         g_return_val_if_fail (nm_device_get_state (device) >= NM_DEVICE_STATE_DISCONNECTED, FALSE);
1667
1668         subject = nm_auth_subject_new_internal ();
1669         active = _new_active_connection (self, NM_CONNECTION (connection), NULL, device, subject, &error);
1670         g_object_unref (subject);
1671
1672         if (!active) {
1673                 _LOGW (LOGD_DEVICE, "assumed connection %s failed to activate: %s",
1674                        nm_connection_get_path (NM_CONNECTION (connection)),
1675                        error->message);
1676                 g_error_free (error);
1677                 return FALSE;
1678         }
1679
1680         /* If the device is a slave or VLAN, find the master ActiveConnection */
1681         master_ac = NULL;
1682         if (find_master (self, NM_CONNECTION (connection), device, NULL, NULL, &master_ac, NULL) && master_ac)
1683                 nm_active_connection_set_master (active, master_ac);
1684
1685         nm_active_connection_set_assumed (active, TRUE);
1686         nm_exported_object_export (NM_EXPORTED_OBJECT (active));
1687         active_connection_add (self, active);
1688         nm_device_queue_activation (device, NM_ACT_REQUEST (active));
1689         g_object_unref (active);
1690
1691         return TRUE;
1692 }
1693
1694 static gboolean
1695 recheck_assume_connection (NMManager *self, NMDevice *device)
1696 {
1697         NMSettingsConnection *connection;
1698         gboolean was_unmanaged = FALSE, success, generated = FALSE;
1699         NMDeviceState state;
1700
1701         g_return_val_if_fail (NM_IS_MANAGER (self), FALSE);
1702         g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
1703
1704         if (nm_device_get_is_nm_owned (device))
1705                 return FALSE;
1706
1707         if (!nm_device_get_managed (device, FALSE))
1708                 return FALSE;
1709
1710         state = nm_device_get_state (device);
1711         if (state > NM_DEVICE_STATE_DISCONNECTED)
1712                 return FALSE;
1713
1714         connection = get_existing_connection (self, device, &generated);
1715         if (!connection) {
1716                 _LOGD (LOGD_DEVICE, "(%s): can't assume; no connection",
1717                        nm_device_get_iface (device));
1718                 return FALSE;
1719         }
1720
1721         if (state == NM_DEVICE_STATE_UNMANAGED) {
1722                 was_unmanaged = TRUE;
1723                 nm_device_state_changed (device,
1724                                          NM_DEVICE_STATE_UNAVAILABLE,
1725                                          NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED);
1726         }
1727
1728         success = assume_connection (self, device, connection);
1729         if (!success) {
1730                 if (was_unmanaged) {
1731                         nm_device_state_changed (device,
1732                                                  NM_DEVICE_STATE_UNAVAILABLE,
1733                                                  NM_DEVICE_STATE_REASON_CONFIG_FAILED);
1734                 }
1735
1736                 if (generated) {
1737                         _LOGD (LOGD_DEVICE, "(%s): connection assumption failed. Deleting generated connection",
1738                                nm_device_get_iface (device));
1739
1740                         nm_settings_connection_delete (connection, NULL, NULL);
1741                 }
1742         }
1743
1744         return success;
1745 }
1746
1747 static void
1748 recheck_assume_connection_cb (NMDevice *device, gpointer user_data)
1749 {
1750         recheck_assume_connection (user_data, device);
1751 }
1752
1753 static void
1754 device_ip_iface_changed (NMDevice *device,
1755                          GParamSpec *pspec,
1756                          NMManager *self)
1757 {
1758         const char *ip_iface = nm_device_get_ip_iface (device);
1759         GSList *iter;
1760
1761         /* Remove NMDevice objects that are actually child devices of others,
1762          * when the other device finally knows its IP interface name.  For example,
1763          * remove the PPP interface that's a child of a WWAN device, since it's
1764          * not really a standalone NMDevice.
1765          */
1766         for (iter = NM_MANAGER_GET_PRIVATE (self)->devices; iter; iter = iter->next) {
1767                 NMDevice *candidate = NM_DEVICE (iter->data);
1768
1769                 if (   candidate != device
1770                     && g_strcmp0 (nm_device_get_iface (candidate), ip_iface) == 0
1771                     && nm_device_is_real (candidate)) {
1772                         remove_device (self, candidate, FALSE, FALSE);
1773                         break;
1774                 }
1775         }
1776 }
1777
1778 static void
1779 device_iface_changed (NMDevice *device,
1780                       GParamSpec *pspec,
1781                       NMManager *self)
1782 {
1783         /* Virtual connections may refer to the new device name as
1784          * parent device, retry to activate them.
1785          */
1786         retry_connections_for_parent_device (self, device);
1787 }
1788
1789
1790 static void
1791 device_realized (NMDevice *device,
1792                  GParamSpec *pspec,
1793                  NMManager *self)
1794 {
1795         /* Emit D-Bus signals */
1796         g_signal_emit (self, signals[DEVICE_ADDED], 0, device);
1797         g_object_notify (G_OBJECT (self), NM_MANAGER_DEVICES);
1798 }
1799
1800 static void
1801 _device_realize_finish (NMManager *self, NMDevice *device, const NMPlatformLink *plink)
1802 {
1803         g_return_if_fail (NM_IS_MANAGER (self));
1804         g_return_if_fail (NM_IS_DEVICE (device));
1805
1806         nm_device_realize_finish (device, plink);
1807
1808         if (!nm_device_get_managed (device, FALSE))
1809                 return;
1810
1811         if (recheck_assume_connection (self, device))
1812                 return;
1813
1814         /* if we failed to assume a connection for the managed device, but the device
1815          * is still unavailable. Set UNAVAILABLE state again, this time with NOW_MANAGED. */
1816         nm_device_state_changed (device,
1817                                  NM_DEVICE_STATE_UNAVAILABLE,
1818                                  NM_DEVICE_STATE_REASON_NOW_MANAGED);
1819         nm_device_emit_recheck_auto_activate (device);
1820 }
1821
1822 /**
1823  * add_device:
1824  * @self: the #NMManager
1825  * @device: the #NMDevice to add
1826  * @error: (out): the #GError
1827  *
1828  * If successful, this function will increase the references count of @device.
1829  * Callers should decrease the reference count.
1830  */
1831 static gboolean
1832 add_device (NMManager *self, NMDevice *device, GError **error)
1833 {
1834         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
1835         const char *iface, *type_desc;
1836         RfKillType rtype;
1837         GSList *iter, *remove = NULL;
1838         int ifindex;
1839         const char *dbus_path;
1840
1841         /* No duplicates */
1842         ifindex = nm_device_get_ifindex (device);
1843         if (ifindex > 0 && nm_manager_get_device_by_ifindex (self, ifindex)) {
1844                 g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED,
1845                              "A device with ifindex %d already exists", ifindex);
1846                 return FALSE;
1847         }
1848
1849         /* Remove existing devices owned by the new device; eg remove ethernet
1850          * ports that are owned by a WWAN modem, since udev may announce them
1851          * before the modem is fully discovered.
1852          *
1853          * FIXME: use parent/child device relationships instead of removing
1854          * the child NMDevice entirely
1855          */
1856         for (iter = priv->devices; iter; iter = iter->next) {
1857                 NMDevice *candidate = iter->data;
1858
1859                 iface = nm_device_get_ip_iface (candidate);
1860                 if (nm_device_is_real (candidate) && nm_device_owns_iface (device, iface))
1861                         remove = g_slist_prepend (remove, candidate);
1862         }
1863         for (iter = remove; iter; iter = iter->next)
1864                 remove_device (self, NM_DEVICE (iter->data), FALSE, FALSE);
1865         g_slist_free (remove);
1866
1867         priv->devices = g_slist_append (priv->devices, g_object_ref (device));
1868
1869         g_signal_connect (device, NM_DEVICE_STATE_CHANGED,
1870                           G_CALLBACK (manager_device_state_changed),
1871                           self);
1872
1873         g_signal_connect (device, NM_DEVICE_AUTH_REQUEST,
1874                           G_CALLBACK (device_auth_request_cb),
1875                           self);
1876
1877         g_signal_connect (device, NM_DEVICE_REMOVED,
1878                           G_CALLBACK (device_removed_cb),
1879                           self);
1880
1881         g_signal_connect (device, NM_DEVICE_RECHECK_ASSUME,
1882                           G_CALLBACK (recheck_assume_connection_cb),
1883                           self);
1884
1885         g_signal_connect (device, "notify::" NM_DEVICE_IP_IFACE,
1886                           G_CALLBACK (device_ip_iface_changed),
1887                           self);
1888
1889         g_signal_connect (device, "notify::" NM_DEVICE_IFACE,
1890                           G_CALLBACK (device_iface_changed),
1891                           self);
1892
1893         g_signal_connect (device, "notify::" NM_DEVICE_REAL,
1894                           G_CALLBACK (device_realized),
1895                           self);
1896
1897         if (priv->startup) {
1898                 g_signal_connect (device, "notify::" NM_DEVICE_HAS_PENDING_ACTION,
1899                                   G_CALLBACK (device_has_pending_action_changed),
1900                                   self);
1901         }
1902
1903         /* Update global rfkill state for this device type with the device's
1904          * rfkill state, and then set this device's rfkill state based on the
1905          * global state.
1906          */
1907         rtype = nm_device_get_rfkill_type (device);
1908         if (rtype != RFKILL_TYPE_UNKNOWN) {
1909                 nm_manager_rfkill_update (self, rtype);
1910                 nm_device_set_enabled (device, radio_enabled_for_type (self, rtype, TRUE));
1911         }
1912
1913         iface = nm_device_get_iface (device);
1914         g_assert (iface);
1915         type_desc = nm_device_get_type_desc (device);
1916         g_assert (type_desc);
1917
1918         nm_device_set_unmanaged_by_user_config (device, nm_settings_get_unmanaged_specs (priv->settings));
1919
1920         nm_device_set_unmanaged_flags (device,
1921                                        NM_UNMANAGED_SLEEPING,
1922                                        manager_sleeping (self));
1923
1924         dbus_path = nm_exported_object_export (NM_EXPORTED_OBJECT (device));
1925         _LOGI (LOGD_DEVICE, "(%s): new %s device (%s)", iface, type_desc, dbus_path);
1926
1927         nm_settings_device_added (priv->settings, device);
1928         g_signal_emit (self, signals[INTERNAL_DEVICE_ADDED], 0, device);
1929         g_object_notify (G_OBJECT (self), NM_MANAGER_ALL_DEVICES);
1930
1931         for (iter = priv->devices; iter; iter = iter->next) {
1932                 NMDevice *d = iter->data;
1933
1934                 if (d != device)
1935                         nm_device_notify_new_device_added (d, device);
1936         }
1937
1938         /* Virtual connections may refer to the new device as
1939          * parent device, retry to activate them.
1940          */
1941         retry_connections_for_parent_device (self, device);
1942
1943         return TRUE;
1944 }
1945
1946 /*******************************************************************/
1947
1948 static void
1949 factory_device_added_cb (NMDeviceFactory *factory,
1950                          NMDevice *device,
1951                          gpointer user_data)
1952 {
1953         NMManager *self = user_data;
1954         GError *error = NULL;
1955
1956         g_return_if_fail (NM_IS_MANAGER (self));
1957
1958         if (nm_device_realize_start (device, NULL, NULL, &error)) {
1959                 add_device (self, device, NULL);
1960                 _device_realize_finish (self, device, NULL);
1961         } else {
1962                 _LOGW (LOGD_DEVICE, "(%s): failed to realize device: %s",
1963                        nm_device_get_iface (device), error->message);
1964                 g_error_free (error);
1965         }
1966 }
1967
1968 static gboolean
1969 factory_component_added_cb (NMDeviceFactory *factory,
1970                             GObject *component,
1971                             gpointer user_data)
1972 {
1973         GSList *iter;
1974
1975         g_return_val_if_fail (NM_IS_MANAGER (user_data), FALSE);
1976
1977         for (iter = NM_MANAGER_GET_PRIVATE (user_data)->devices; iter; iter = iter->next) {
1978                 if (nm_device_notify_component_added ((NMDevice *) iter->data, component))
1979                         return TRUE;
1980         }
1981         return FALSE;
1982 }
1983
1984 static void
1985 _register_device_factory (NMDeviceFactory *factory, gpointer user_data)
1986 {
1987         NMManager *self = NM_MANAGER (user_data);
1988
1989         g_signal_connect (factory,
1990                           NM_DEVICE_FACTORY_DEVICE_ADDED,
1991                           G_CALLBACK (factory_device_added_cb),
1992                           self);
1993         g_signal_connect (factory,
1994                           NM_DEVICE_FACTORY_COMPONENT_ADDED,
1995                           G_CALLBACK (factory_component_added_cb),
1996                           self);
1997 }
1998
1999 /*******************************************************************/
2000
2001 static void
2002 platform_link_added (NMManager *self,
2003                      int ifindex,
2004                      const NMPlatformLink *plink)
2005 {
2006         NMDeviceFactory *factory;
2007         NMDevice *device = NULL;
2008         GError *error = NULL;
2009         gboolean nm_plugin_missing = FALSE;
2010         GSList *iter;
2011
2012         g_return_if_fail (ifindex > 0);
2013
2014         if (nm_manager_get_device_by_ifindex (self, ifindex))
2015                 return;
2016
2017         /* Let unrealized devices try to realize themselves with the link */
2018         for (iter = NM_MANAGER_GET_PRIVATE (self)->devices; iter; iter = iter->next) {
2019                 NMDevice *candidate = iter->data;
2020                 gboolean compatible = TRUE;
2021
2022                 if (strcmp (nm_device_get_iface (candidate), plink->name))
2023                         continue;
2024
2025                 if (nm_device_is_real (candidate)) {
2026                         /* Ignore the link added event since there's already a realized
2027                          * device with the link's name.
2028                          */
2029                         return;
2030                 } else if (nm_device_realize_start (candidate, plink, &compatible, &error)) {
2031                         /* Success */
2032                         _device_realize_finish (self, candidate, plink);
2033                         return;
2034                 }
2035
2036                 _LOGD (LOGD_DEVICE, "(%s): failed to realize from plink: '%s'",
2037                        plink->name, error->message);
2038                 g_clear_error (&error);
2039
2040                 /* Try next unrealized device */
2041         }
2042
2043         /* Try registered device factories */
2044         factory = nm_device_factory_manager_find_factory_for_link_type (plink->type);
2045         if (factory) {
2046                 gboolean ignore = FALSE;
2047
2048                 device = nm_device_factory_create_device (factory, plink->name, plink, NULL, &ignore, &error);
2049                 if (!device) {
2050                         if (!ignore) {
2051                                 _LOGW (LOGD_HW, "%s: factory failed to create device: %s",
2052                                        plink->name, error->message);
2053                                 g_clear_error (&error);
2054                         }
2055                         return;
2056                 }
2057         }
2058
2059         if (device == NULL) {
2060                 switch (plink->type) {
2061                 case NM_LINK_TYPE_WWAN_ETHERNET:
2062                 case NM_LINK_TYPE_BNEP:
2063                 case NM_LINK_TYPE_OLPC_MESH:
2064                 case NM_LINK_TYPE_TEAM:
2065                 case NM_LINK_TYPE_WIFI:
2066                         _LOGI (LOGD_HW, "(%s): '%s' plugin not available; creating generic device",
2067                                plink->name, nm_link_type_to_string (plink->type));
2068                         nm_plugin_missing = TRUE;
2069                         /* fall through */
2070                 default:
2071                         device = nm_device_generic_new (plink);
2072                         break;
2073                 }
2074         }
2075
2076         if (device) {
2077                 if (nm_plugin_missing)
2078                         nm_device_set_nm_plugin_missing (device, TRUE);
2079                 if (nm_device_realize_start (device, plink, NULL, &error)) {
2080                         add_device (self, device, NULL);
2081                         _device_realize_finish (self, device, plink);
2082                 } else {
2083                         _LOGW (LOGD_DEVICE, "%s: failed to realize device: %s",
2084                                plink->name, error->message);
2085                         g_clear_error (&error);
2086                 }
2087                 g_object_unref (device);
2088         }
2089 }
2090
2091 typedef struct {
2092         NMManager *self;
2093         int ifindex;
2094 } PlatformLinkCbData;
2095
2096 static gboolean
2097 _platform_link_cb_idle (PlatformLinkCbData *data)
2098 {
2099         NMManager *self = data->self;
2100         const NMPlatformLink *l;
2101
2102         if (!self)
2103                 goto out;
2104
2105         g_object_remove_weak_pointer (G_OBJECT (self), (gpointer *) &data->self);
2106
2107         l = nm_platform_link_get (NM_PLATFORM_GET, data->ifindex);
2108         if (l) {
2109                 NMPlatformLink pllink;
2110
2111                 pllink = *l; /* make a copy of the link instance */
2112                 platform_link_added (self, data->ifindex, &pllink);
2113         } else {
2114                 NMDevice *device;
2115                 GError *error = NULL;
2116
2117                 device = nm_manager_get_device_by_ifindex (self, data->ifindex);
2118                 if (device) {
2119                         if (nm_device_is_software (device)) {
2120                                 /* Our software devices stick around until their connection is removed */
2121                                 if (!nm_device_unrealize (device, FALSE, &error)) {
2122                                         _LOGW (LOGD_DEVICE, "(%s): failed to unrealize: %s",
2123                                                nm_device_get_iface (device),
2124                                                error->message);
2125                                         g_clear_error (&error);
2126                                         remove_device (self, device, FALSE, TRUE);
2127                                 }
2128                         } else {
2129                                 /* Hardware and external devices always get removed when their kernel link is gone */
2130                                 remove_device (self, device, FALSE, TRUE);
2131                         }
2132                 }
2133         }
2134
2135 out:
2136         g_slice_free (PlatformLinkCbData, data);
2137         return G_SOURCE_REMOVE;
2138 }
2139
2140 static void
2141 platform_link_cb (NMPlatform *platform,
2142                   NMPObjectType obj_type,
2143                   int ifindex,
2144                   NMPlatformLink *plink,
2145                   NMPlatformSignalChangeType change_type,
2146                   gpointer user_data)
2147 {
2148         PlatformLinkCbData *data;
2149
2150         switch (change_type) {
2151         case NM_PLATFORM_SIGNAL_ADDED:
2152         case NM_PLATFORM_SIGNAL_REMOVED:
2153                 data = g_slice_new (PlatformLinkCbData);
2154                 data->self = NM_MANAGER (user_data);
2155                 data->ifindex = ifindex;
2156                 g_object_add_weak_pointer (G_OBJECT (data->self), (gpointer *) &data->self);
2157                 g_idle_add ((GSourceFunc) _platform_link_cb_idle, data);
2158                 break;
2159         default:
2160                 break;
2161         }
2162 }
2163
2164 static void
2165 platform_query_devices (NMManager *self)
2166 {
2167         GArray *links_array;
2168         NMPlatformLink *links;
2169         int i;
2170
2171         links_array = nm_platform_link_get_all (NM_PLATFORM_GET);
2172         links = (NMPlatformLink *) links_array->data;
2173         for (i = 0; i < links_array->len; i++)
2174                 platform_link_added (self, links[i].ifindex, &links[i]);
2175
2176         g_array_unref (links_array);
2177 }
2178
2179 static void
2180 rfkill_manager_rfkill_changed_cb (NMRfkillManager *rfkill_mgr,
2181                                   RfKillType rtype,
2182                                   RfKillState udev_state,
2183                                   gpointer user_data)
2184 {
2185         nm_manager_rfkill_update (NM_MANAGER (user_data), rtype);
2186 }
2187
2188 const GSList *
2189 nm_manager_get_devices (NMManager *manager)
2190 {
2191         g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
2192
2193         return NM_MANAGER_GET_PRIVATE (manager)->devices;
2194 }
2195
2196 static NMDevice *
2197 nm_manager_get_connection_device (NMManager *self,
2198                                   NMConnection *connection)
2199 {
2200         NMActiveConnection *ac = find_ac_for_connection (self, connection);
2201         if (ac == NULL)
2202                 return NULL;
2203
2204         return nm_active_connection_get_device (ac);
2205 }
2206
2207 static NMDevice *
2208 nm_manager_get_best_device_for_connection (NMManager *self,
2209                                            NMConnection *connection,
2210                                            gboolean for_user_request)
2211 {
2212         const GSList *devices, *iter;
2213         NMDevice *act_device = nm_manager_get_connection_device (self, connection);
2214         NMDeviceCheckConAvailableFlags flags;
2215
2216         if (act_device)
2217                 return act_device;
2218
2219         flags = for_user_request ? NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST : NM_DEVICE_CHECK_CON_AVAILABLE_NONE;
2220
2221         /* Pick the first device that's compatible with the connection. */
2222         devices = nm_manager_get_devices (self);
2223         for (iter = devices; iter; iter = g_slist_next (iter)) {
2224                 NMDevice *device = NM_DEVICE (iter->data);
2225
2226                 if (nm_device_check_connection_available (device, connection, flags, NULL))
2227                         return device;
2228         }
2229
2230         /* No luck. :( */
2231         return NULL;
2232 }
2233
2234 static void
2235 _get_devices (NMManager *self,
2236               GDBusMethodInvocation *context,
2237               gboolean all_devices)
2238 {
2239         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
2240         gs_free const char **paths = NULL;
2241         guint i;
2242         GSList *iter;
2243
2244         paths = g_new (const char *, g_slist_length (priv->devices) + 1);
2245
2246         for (i = 0, iter = priv->devices; iter; iter = iter->next) {
2247                 const char *path;
2248
2249                 path = nm_exported_object_get_path (NM_EXPORTED_OBJECT (iter->data));
2250                 if (   path
2251                     && (all_devices || nm_device_is_real (iter->data)))
2252                         paths[i++] = path;
2253         }
2254         paths[i++] = NULL;
2255
2256         g_dbus_method_invocation_return_value (context,
2257                                                g_variant_new ("(^ao)", (char **) paths));
2258 }
2259
2260 static void
2261 impl_manager_get_devices (NMManager *self,
2262                           GDBusMethodInvocation *context)
2263 {
2264         _get_devices (self, context, FALSE);
2265 }
2266
2267 static void
2268 impl_manager_get_all_devices (NMManager *self,
2269                               GDBusMethodInvocation *context)
2270 {
2271         _get_devices (self, context, TRUE);
2272 }
2273
2274 static void
2275 impl_manager_get_device_by_ip_iface (NMManager *self,
2276                                      GDBusMethodInvocation *context,
2277                                      const char *iface)
2278 {
2279         NMDevice *device;
2280         const char *path = NULL;
2281
2282         device = find_device_by_ip_iface (self, iface);
2283         if (device)
2284                 path = nm_exported_object_get_path (NM_EXPORTED_OBJECT (device));
2285
2286         if (path == NULL) {
2287                 g_dbus_method_invocation_return_error (context,
2288                                                        NM_MANAGER_ERROR,
2289                                                        NM_MANAGER_ERROR_UNKNOWN_DEVICE,
2290                                                        "No device found for the requested iface.");
2291         } else {
2292                 g_dbus_method_invocation_return_value (context,
2293                                                        g_variant_new ("(o)", path));
2294         }
2295 }
2296
2297 static gboolean
2298 is_compatible_with_slave (NMConnection *master, NMConnection *slave)
2299 {
2300         NMSettingConnection *s_con;
2301
2302         g_return_val_if_fail (master, FALSE);
2303         g_return_val_if_fail (slave, FALSE);
2304
2305         s_con = nm_connection_get_setting_connection (slave);
2306         g_assert (s_con);
2307
2308         return nm_connection_is_type (master, nm_setting_connection_get_slave_type (s_con));
2309 }
2310
2311 /**
2312  * find_master:
2313  * @self: #NMManager object
2314  * @connection: the #NMConnection to find the master connection and device for
2315  * @device: the #NMDevice, if any, which will activate @connection
2316  * @out_master_connection: on success, the master connection of @connection if
2317  *   that master connection was found
2318  * @out_master_device: on success, the master device of @connection if that
2319  *   master device was found
2320  * @out_master_ac: on success, the master ActiveConnection of @connection if
2321  *   there already is one
2322  * @error: the error, if an error occurred
2323  *
2324  * Given an #NMConnection, attempts to find its master. If @connection has
2325  * no master, this will return %TRUE and @out_master_connection and
2326  * @out_master_device will be untouched.
2327  *
2328  * If @connection does have a master, then the outputs depend on what is in its
2329  * #NMSettingConnection:master property:
2330  *
2331  * If "master" is the ifname of an existing #NMDevice, and that device has a
2332  * compatible master connection activated or activating on it, then
2333  * @out_master_device, @out_master_connection, and @out_master_ac will all be
2334  * set. If the device exists and is idle, only @out_master_device will be set.
2335  * If the device exists and has an incompatible connection on it, an error
2336  * will be returned.
2337  *
2338  * If "master" is the ifname of a non-existent device, then @out_master_device
2339  * will be %NULL, and @out_master_connection will be a connection whose
2340  * activation would cause the creation of that device. @out_master_ac MAY be
2341  * set in this case as well (if the connection has started activating, but has
2342  * not yet created its device).
2343  *
2344  * If "master" is the UUID of a compatible master connection, then
2345  * @out_master_connection will be the identified connection, and @out_master_device
2346  * and/or @out_master_ac will be set if the connection is currently activating.
2347  * (@out_master_device will not be set if the device exists but does not have
2348  * @out_master_connection active/activating on it.)
2349  *
2350  * Returns: %TRUE if the master device and/or connection could be found or if
2351  *  the connection did not require a master, %FALSE otherwise
2352  **/
2353 static gboolean
2354 find_master (NMManager *self,
2355              NMConnection *connection,
2356              NMDevice *device,
2357              NMSettingsConnection **out_master_connection,
2358              NMDevice **out_master_device,
2359              NMActiveConnection **out_master_ac,
2360              GError **error)
2361 {
2362         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
2363         NMSettingConnection *s_con;
2364         const char *master;
2365         NMDevice *master_device = NULL;
2366         NMSettingsConnection *master_connection = NULL;
2367         GSList *iter;
2368
2369         s_con = nm_connection_get_setting_connection (connection);
2370         g_assert (s_con);
2371         master = nm_setting_connection_get_master (s_con);
2372
2373         if (master == NULL)
2374                 return TRUE;  /* success, but no master */
2375
2376         /* Try as an interface name first */
2377         master_device = find_device_by_iface (self, master, NULL, connection);
2378         if (master_device) {
2379                 if (master_device == device) {
2380                         g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_DEPENDENCY_FAILED,
2381                                              "Device cannot be its own master");
2382                         return FALSE;
2383                 }
2384
2385                 master_connection = nm_device_get_settings_connection (master_device);
2386                 if (master_connection && !is_compatible_with_slave (NM_CONNECTION (master_connection), connection)) {
2387                         g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_DEPENDENCY_FAILED,
2388                                      "The active connection on %s is not a valid master for '%s'",
2389                                      nm_device_get_iface (master_device),
2390                                      nm_connection_get_id (connection));
2391                         return FALSE;
2392                 }
2393         } else {
2394                 /* Try master as a connection UUID */
2395                 master_connection = nm_settings_get_connection_by_uuid (priv->settings, master);
2396                 if (master_connection) {
2397                         /* Check if the master connection is activated on some device already */
2398                         for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
2399                                 NMDevice *candidate = NM_DEVICE (iter->data);
2400
2401                                 if (candidate == device)
2402                                         continue;
2403
2404                                 if (nm_device_get_settings_connection (candidate) == master_connection) {
2405                                         master_device = candidate;
2406                                         break;
2407                                 }
2408                         }
2409                 }
2410         }
2411
2412         if (out_master_connection)
2413                 *out_master_connection = master_connection;
2414         if (out_master_device)
2415                 *out_master_device = master_device;
2416         if (out_master_ac && master_connection)
2417                 *out_master_ac = find_ac_for_connection (self, NM_CONNECTION (master_connection));
2418
2419         if (master_device || master_connection)
2420                 return TRUE;
2421         else {
2422                 g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE,
2423                                      "Master connection not found or invalid");
2424                 return FALSE;
2425         }
2426 }
2427
2428 /**
2429  * ensure_master_active_connection:
2430  * @self: the #NMManager
2431  * @subject: the #NMAuthSubject representing the requestor of this activation
2432  * @connection: the connection that should depend on @master_connection
2433  * @device: the #NMDevice, if any, which will activate @connection
2434  * @master_connection: the master connection, or %NULL
2435  * @master_device: the master device, or %NULL
2436  * @error: the error, if an error occurred
2437  *
2438  * Determines whether a given #NMConnection depends on another connection to
2439  * be activated, and if so, finds that master connection or creates it.
2440  *
2441  * If @master_device and @master_connection are both set then @master_connection
2442  * MUST already be activated or activating on @master_device, and the function will
2443  * return the existing #NMActiveConnection.
2444  *
2445  * If only @master_device is set, and it has an #NMActiveConnection, then the
2446  * function will return it if it is a compatible master, or an error if not. If it
2447  * doesn't have an AC, then the function will create one if a compatible master
2448  * connection exists, or return an error if not.
2449  *
2450  * If only @master_connection is set, then this will try to find or create a compatible
2451  * #NMDevice, and either activate @master_connection on that device or return an error.
2452  *
2453  * Returns: the master #NMActiveConnection that the caller should depend on, or
2454  * %NULL if an error occurred
2455  */
2456 static NMActiveConnection *
2457 ensure_master_active_connection (NMManager *self,
2458                                  NMAuthSubject *subject,
2459                                  NMConnection *connection,
2460                                  NMDevice *device,
2461                                  NMSettingsConnection *master_connection,
2462                                  NMDevice *master_device,
2463                                  GError **error)
2464 {
2465         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
2466         NMActiveConnection *master_ac = NULL;
2467         NMDeviceState master_state;
2468         GSList *iter;
2469
2470         g_assert (connection);
2471         g_assert (master_connection || master_device);
2472
2473         /* If the master device isn't activated then we need to activate it using
2474          * compatible connection.  If it's already activating we can just proceed.
2475          */
2476         if (master_device) {
2477                 NMSettingsConnection *device_connection = nm_device_get_settings_connection (master_device);
2478
2479                 /* If we're passed a connection and a device, we require that connection
2480                  * be already activated on the device, eg returned from find_master().
2481                  */
2482                 g_assert (!master_connection || master_connection == device_connection);
2483                 if (device_connection && !is_compatible_with_slave (NM_CONNECTION (device_connection), connection)) {
2484                         g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_DEPENDENCY_FAILED,
2485                                      "The active connection on %s is not a valid master for '%s'",
2486                                      nm_device_get_iface (master_device),
2487                                      nm_connection_get_id (connection));
2488                         return NULL;
2489                 }
2490
2491                 master_state = nm_device_get_state (master_device);
2492                 if (   (master_state == NM_DEVICE_STATE_ACTIVATED)
2493                     || nm_device_is_activating (master_device)) {
2494                         /* Device already using master_connection */
2495                         g_assert (device_connection);
2496                         return NM_ACTIVE_CONNECTION (nm_device_get_act_request (master_device));
2497                 }
2498
2499                 /* If the device is disconnected, find a compatible connection and
2500                  * activate it on the device.
2501                  */
2502                 if (master_state == NM_DEVICE_STATE_DISCONNECTED || !nm_device_is_real (master_device)) {
2503                         GSList *connections;
2504
2505                         g_assert (master_connection == NULL);
2506
2507                         /* Find a compatible connection and activate this device using it */
2508                         connections = nm_manager_get_activatable_connections (self);
2509                         for (iter = connections; iter; iter = g_slist_next (iter)) {
2510                                 NMSettingsConnection *candidate = NM_SETTINGS_CONNECTION (iter->data);
2511
2512                                 /* Ensure eg bond/team slave and the candidate master is a
2513                                  * bond/team master
2514                                  */
2515                                 if (!is_compatible_with_slave (NM_CONNECTION (candidate), connection))
2516                                         continue;
2517
2518                                 if (nm_device_check_connection_available (master_device, NM_CONNECTION (candidate), NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST, NULL)) {
2519                                         master_ac = nm_manager_activate_connection (self,
2520                                                                                     candidate,
2521                                                                                     NULL,
2522                                                                                     master_device,
2523                                                                                     subject,
2524                                                                                     error);
2525                                         if (!master_ac)
2526                                                 g_prefix_error (error, "%s", "Master device activation failed: ");
2527                                         g_slist_free (connections);
2528                                         return master_ac;
2529                                 }
2530                         }
2531                         g_slist_free (connections);
2532
2533                         g_set_error (error,
2534                                      NM_MANAGER_ERROR,
2535                                      NM_MANAGER_ERROR_UNKNOWN_CONNECTION,
2536                                      "No compatible connection found for master device %s.",
2537                                      nm_device_get_iface (master_device));
2538                         return NULL;
2539                 }
2540
2541                 /* Otherwise, the device is unmanaged, unavailable, or disconnecting */
2542                 g_set_error (error,
2543                              NM_MANAGER_ERROR,
2544                              NM_MANAGER_ERROR_DEPENDENCY_FAILED,
2545                              "Master device %s unmanaged or not available for activation",
2546                              nm_device_get_iface (master_device));
2547         } else if (master_connection) {
2548                 gboolean found_device = FALSE;
2549
2550                 /* Find a compatible device and activate it using this connection */
2551                 for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
2552                         NMDevice *candidate = NM_DEVICE (iter->data);
2553
2554                         if (candidate == device) {
2555                                 /* A device obviously can't be its own master */
2556                                 continue;
2557                         }
2558
2559                         if (!nm_device_check_connection_available (candidate, NM_CONNECTION (master_connection), NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST, NULL))
2560                                 continue;
2561
2562                         found_device = TRUE;
2563                         if (!nm_device_is_software (candidate)) {
2564                                 master_state = nm_device_get_state (candidate);
2565                                 if (nm_device_is_real (candidate) && master_state != NM_DEVICE_STATE_DISCONNECTED)
2566                                         continue;
2567                         }
2568
2569                         master_ac = nm_manager_activate_connection (self,
2570                                                                     master_connection,
2571                                                                     NULL,
2572                                                                     candidate,
2573                                                                     subject,
2574                                                                     error);
2575                         if (!master_ac)
2576                                 g_prefix_error (error, "%s", "Master device activation failed: ");
2577                         return master_ac;
2578                 }
2579
2580                 g_set_error (error,
2581                              NM_MANAGER_ERROR,
2582                              NM_MANAGER_ERROR_UNKNOWN_DEVICE,
2583                              "No compatible disconnected device found for master connection %s.",
2584                              nm_settings_connection_get_uuid (master_connection));
2585         } else
2586                 g_assert_not_reached ();
2587
2588         return NULL;
2589 }
2590
2591 /**
2592  * find_slaves:
2593  * @manager: #NMManager object
2594  * @connection: the master #NMSettingsConnection to find slave connections for
2595  * @device: the master #NMDevice for the @connection
2596  *
2597  * Given an #NMSettingsConnection, attempts to find its slaves. If @connection is not
2598  * master, or has not any slaves, this will return %NULL.
2599  *
2600  * Returns: list of slave connections for given master @connection, or %NULL
2601  **/
2602 static GSList *
2603 find_slaves (NMManager *manager,
2604              NMSettingsConnection *connection,
2605              NMDevice *device)
2606 {
2607         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
2608         GSList *all_connections, *iter;
2609         GSList *slaves = NULL;
2610         NMSettingConnection *s_con;
2611         const char *master;
2612
2613         s_con = nm_connection_get_setting_connection (NM_CONNECTION (connection));
2614         g_assert (s_con);
2615         master = nm_setting_connection_get_master (s_con);
2616
2617         if (master != NULL)
2618                 return NULL;  /* connection is not master */
2619
2620         /* Search through all connections, not only inactive ones, because
2621          * even if a slave was already active, it might be deactivated during
2622          * master reactivation.
2623          */
2624         all_connections = nm_settings_get_connections (priv->settings);
2625         for (iter = all_connections; iter; iter = iter->next) {
2626                 NMSettingsConnection *master_connection = NULL;
2627                 NMDevice *master_device = NULL;
2628                 NMConnection *candidate = iter->data;
2629
2630                 find_master (manager, candidate, NULL, &master_connection, &master_device, NULL, NULL);
2631                 if (   (master_connection && master_connection == connection)
2632                     || (master_device && master_device == device)) {
2633                         slaves = g_slist_prepend (slaves, candidate);
2634                 }
2635         }
2636         g_slist_free (all_connections);
2637
2638         return g_slist_reverse (slaves);
2639 }
2640
2641 static gboolean
2642 should_connect_slaves (NMConnection *connection, NMDevice *device)
2643 {
2644         NMSettingConnection *s_con;
2645         NMSettingConnectionAutoconnectSlaves autoconnect_slaves;
2646         gs_free char *value = NULL;
2647
2648         s_con = nm_connection_get_setting_connection (connection);
2649         g_assert (s_con);
2650
2651         /* Check autoconnect-slaves property */
2652         autoconnect_slaves = nm_setting_connection_get_autoconnect_slaves (s_con);
2653         if (autoconnect_slaves != NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_DEFAULT)
2654                 goto out;
2655
2656         /* Check configuration default for autoconnect-slaves property */
2657         value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
2658                                                        "connection.autoconnect-slaves", device);
2659         if (value)
2660                 autoconnect_slaves = _nm_utils_ascii_str_to_int64 (value, 10, 0, 1, -1);
2661
2662 out:
2663         if (autoconnect_slaves == NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_NO)
2664                 return FALSE;
2665         if (autoconnect_slaves == NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_YES)
2666                 return TRUE;
2667         return FALSE;
2668 }
2669
2670 static gboolean
2671 autoconnect_slaves (NMManager *self,
2672                     NMSettingsConnection *master_connection,
2673                     NMDevice *master_device,
2674                     NMAuthSubject *subject)
2675 {
2676         GError *local_err = NULL;
2677         gboolean ret = FALSE;
2678
2679         if (should_connect_slaves (NM_CONNECTION (master_connection), master_device)) {
2680                 GSList *slaves, *iter;
2681
2682                 iter = slaves = find_slaves (self, master_connection, master_device);
2683                 ret = slaves != NULL;
2684
2685                 while (iter) {
2686                         NMSettingsConnection *slave_connection = iter->data;
2687
2688                         iter = iter->next;
2689                         _LOGD (LOGD_CORE, "will activate slave connection '%s' (%s) as a dependency for master '%s' (%s)",
2690                                nm_settings_connection_get_id (slave_connection),
2691                                nm_settings_connection_get_uuid (slave_connection),
2692                                nm_settings_connection_get_id (master_connection),
2693                                nm_settings_connection_get_uuid (master_connection));
2694
2695                         /* Schedule slave activation */
2696                         nm_manager_activate_connection (self,
2697                                                         slave_connection,
2698                                                         NULL,
2699                                                         nm_manager_get_best_device_for_connection (self, NM_CONNECTION (slave_connection), FALSE),
2700                                                         subject,
2701                                                         &local_err);
2702                         if (local_err) {
2703                                 _LOGW (LOGD_CORE, "Slave connection activation failed: %s", local_err->message);
2704                                 g_error_free (local_err);
2705                         }
2706                 }
2707                 g_slist_free (slaves);
2708         }
2709         return ret;
2710 }
2711
2712 static gboolean
2713 _internal_activate_vpn (NMManager *self, NMActiveConnection *active, GError **error)
2714 {
2715         gboolean success;
2716
2717         g_assert (NM_IS_VPN_CONNECTION (active));
2718
2719         nm_exported_object_export (NM_EXPORTED_OBJECT (active));
2720         success = nm_vpn_manager_activate_connection (NM_MANAGER_GET_PRIVATE (self)->vpn_manager,
2721                                                       NM_VPN_CONNECTION (active),
2722                                                       error);
2723         if (success)
2724                 g_object_notify (G_OBJECT (self), NM_MANAGER_ACTIVE_CONNECTIONS);
2725         else
2726                 nm_exported_object_unexport (NM_EXPORTED_OBJECT (active));
2727         return success;
2728 }
2729
2730 /* Traverse the device to disconnected state. This means that the device is ready
2731  * for connection and will proceed activating if there's an activation request
2732  * enqueued.
2733  */
2734 static void
2735 unmanaged_to_disconnected (NMDevice *device)
2736 {
2737         /* when creating the software device, it can happen that the device is
2738          * still unmanaged by NM_UNMANAGED_PLATFORM_INIT because we didn't yet
2739          * get the udev event. At this point, we can no longer delay the activation
2740          * and force the device to be managed. */
2741         nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_PLATFORM_INIT, FALSE, NM_DEVICE_STATE_REASON_USER_REQUESTED);
2742
2743         nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_USER_EXPLICIT, FALSE, NM_DEVICE_STATE_REASON_USER_REQUESTED);
2744
2745         g_return_if_fail (nm_device_get_managed (device, FALSE));
2746
2747         if (nm_device_get_state (device) == NM_DEVICE_STATE_UNMANAGED) {
2748                 nm_device_state_changed (device,
2749                                          NM_DEVICE_STATE_UNAVAILABLE,
2750                                          NM_DEVICE_STATE_REASON_USER_REQUESTED);
2751         }
2752
2753         if (   nm_device_is_available (device, NM_DEVICE_CHECK_DEV_AVAILABLE_FOR_USER_REQUEST)
2754             && (nm_device_get_state (device) == NM_DEVICE_STATE_UNAVAILABLE)) {
2755                 nm_device_state_changed (device,
2756                                          NM_DEVICE_STATE_DISCONNECTED,
2757                                          NM_DEVICE_STATE_REASON_USER_REQUESTED);
2758         }
2759 }
2760
2761 /* The parent connection is ready; we can proceed realizing the device and
2762  * progressing the device to disconencted state.
2763  */
2764 static void
2765 active_connection_parent_active (NMActiveConnection *active,
2766                                  NMActiveConnection *parent_ac,
2767                                  NMManager *self)
2768 {
2769         NMDevice *device = nm_active_connection_get_device (active);
2770         GError *error = NULL;
2771
2772         g_signal_handlers_disconnect_by_func (active,
2773                                               (GCallback) active_connection_parent_active,
2774                                               self);
2775
2776         if (parent_ac) {
2777                 NMSettingsConnection *connection = nm_active_connection_get_settings_connection (active);
2778                 NMDevice *parent = nm_active_connection_get_device (parent_ac);
2779
2780                 if (nm_device_create_and_realize (device, (NMConnection *) connection, parent, &error)) {
2781                         /* We can now proceed to disconnected state so that activation proceeds. */
2782                         unmanaged_to_disconnected (device);
2783                 } else {
2784                         nm_log_warn (LOGD_CORE, "Could not realize device '%s': %s",
2785                                      nm_device_get_iface (device), error->message);
2786                         nm_active_connection_set_state (active, NM_ACTIVE_CONNECTION_STATE_DEACTIVATED);
2787                 }
2788         } else {
2789                 nm_log_warn (LOGD_CORE, "The parent connection device '%s' depended on disappeared.",
2790                              nm_device_get_iface (device));
2791                 nm_active_connection_set_state (active, NM_ACTIVE_CONNECTION_STATE_DEACTIVATED);
2792         }
2793 }
2794
2795 static gboolean
2796 _internal_activate_device (NMManager *self, NMActiveConnection *active, GError **error)
2797 {
2798         NMDevice *device, *existing, *master_device = NULL;
2799         NMConnection *applied;
2800         NMSettingsConnection *connection;
2801         NMSettingsConnection *master_connection = NULL;
2802         NMConnection *existing_connection = NULL;
2803         NMActiveConnection *master_ac = NULL;
2804         NMAuthSubject *subject;
2805         char *error_desc = NULL;
2806
2807         g_return_val_if_fail (NM_IS_MANAGER (self), FALSE);
2808         g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (active), FALSE);
2809         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2810
2811         g_assert (NM_IS_VPN_CONNECTION (active) == FALSE);
2812
2813         connection = nm_active_connection_get_settings_connection (active);
2814         g_assert (connection);
2815
2816         applied = nm_active_connection_get_applied_connection (active);
2817
2818         device = nm_active_connection_get_device (active);
2819         g_return_val_if_fail (device != NULL, FALSE);
2820
2821         /* If the device is active and its connection is not visible to the
2822          * user that's requesting this new activation, fail, since other users
2823          * should not be allowed to implicitly deactivate private connections
2824          * by activating a connection of their own.
2825          */
2826         existing_connection = nm_device_get_applied_connection (device);
2827         subject = nm_active_connection_get_subject (active);
2828         if (existing_connection &&
2829             !nm_auth_is_subject_in_acl (existing_connection,
2830                                         subject,
2831                                         &error_desc)) {
2832                 g_set_error (error,
2833                              NM_MANAGER_ERROR,
2834                              NM_MANAGER_ERROR_PERMISSION_DENIED,
2835                              "Private connection already active on the device: %s",
2836                              error_desc);
2837                 g_free (error_desc);
2838                 return FALSE;
2839         }
2840
2841         /* Final connection must be available on device */
2842         if (!nm_device_check_connection_available (device, applied, NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST, NULL)) {
2843                 g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_CONNECTION,
2844                              "Connection '%s' is not available on the device %s at this time.",
2845                              nm_settings_connection_get_id (connection), nm_device_get_iface (device));
2846                 return FALSE;
2847         }
2848
2849         /* Create any backing resources the device needs */
2850         if (!nm_device_is_real (device)) {
2851                 NMDevice *parent;
2852
2853                 parent = find_parent_device_for_connection (self, (NMConnection *) connection, NULL);
2854
2855                 if (parent && !nm_device_is_real (parent)) {
2856                         NMSettingsConnection *parent_con;
2857                         NMActiveConnection *parent_ac;
2858
2859                         parent_con = nm_device_get_best_connection (parent, NULL, error);
2860                         if (!parent_con) {
2861                                 g_prefix_error (error, "%s failed to create parent: ", nm_device_get_iface (device));
2862                                 return FALSE;
2863                         }
2864
2865                         parent_ac = nm_manager_activate_connection (self, parent_con, NULL, parent, subject, error);
2866                         if (!parent_ac) {
2867                                 g_prefix_error (error, "%s failed to activate parent: ", nm_device_get_iface (device));
2868                                 return FALSE;
2869                         }
2870
2871                         /* We can't realize now; defer until the parent device is ready. */
2872                         g_signal_connect (active,
2873                                           NM_ACTIVE_CONNECTION_PARENT_ACTIVE,
2874                                           (GCallback) active_connection_parent_active,
2875                                           self);
2876                         nm_active_connection_set_parent (active, parent_ac);
2877                 } else {
2878                         /* We can realize now; no need to wait for a parent device. */
2879                         if (!nm_device_create_and_realize (device, (NMConnection *) connection, parent, error)) {
2880                                 g_prefix_error (error, "%s failed to create resources: ", nm_device_get_iface (device));
2881                                 return FALSE;
2882                         }
2883                 }
2884         }
2885
2886         /* Try to find the master connection/device if the connection has a dependency */
2887         if (!find_master (self, applied, device,
2888                           &master_connection, &master_device, &master_ac,
2889                           error))
2890                 return FALSE;
2891
2892         /* Ensure there's a master active connection the new connection we're
2893          * activating can depend on.
2894          */
2895         if (master_connection || master_device) {
2896                 if (master_connection) {
2897                         _LOGD (LOGD_CORE, "Activation of '%s' requires master connection '%s'",
2898                                nm_settings_connection_get_id (connection),
2899                                nm_settings_connection_get_id (master_connection));
2900                 }
2901                 if (master_device) {
2902                         _LOGD (LOGD_CORE, "Activation of '%s' requires master device '%s'",
2903                                nm_settings_connection_get_id (connection),
2904                                nm_device_get_ip_iface (master_device));
2905                 }
2906
2907                 /* Ensure eg bond slave and the candidate master is a bond master */
2908                 if (master_connection && !is_compatible_with_slave (NM_CONNECTION (master_connection), applied)) {
2909                         g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_DEPENDENCY_FAILED,
2910                                              "The master connection was not compatible");
2911                         return FALSE;
2912                 }
2913
2914                 if (!master_ac) {
2915                         master_ac = ensure_master_active_connection (self,
2916                                                                      nm_active_connection_get_subject (active),
2917                                                                      applied,
2918                                                                      device,
2919                                                                      master_connection,
2920                                                                      master_device,
2921                                                                      error);
2922                         if (!master_ac) {
2923                                 if (error)
2924                                         g_assert (*error);
2925                                 return FALSE;
2926                         }
2927                 }
2928
2929                 nm_active_connection_set_master (active, master_ac);
2930                 _LOGD (LOGD_CORE, "Activation of '%s' depends on active connection %p %s",
2931                        nm_settings_connection_get_id (connection),
2932                        master_ac,
2933                        nm_exported_object_get_path (NM_EXPORTED_OBJECT  (master_ac)) ?: "");
2934         }
2935
2936         /* Check slaves for master connection and possibly activate them */
2937         autoconnect_slaves (self, connection, device, nm_active_connection_get_subject (active));
2938
2939         /* Disconnect the connection if connected or queued on another device */
2940         existing = nm_manager_get_connection_device (self, NM_CONNECTION (connection));
2941         if (existing)
2942                 nm_device_steal_connection (existing, connection);
2943
2944         /* If the device is there, we can ready it for the activation. */
2945         if (nm_device_is_real (device))
2946                 unmanaged_to_disconnected (device);
2947
2948         /* Export the new ActiveConnection to clients and start it on the device */
2949         nm_exported_object_export (NM_EXPORTED_OBJECT (active));
2950         g_object_notify (G_OBJECT (self), NM_MANAGER_ACTIVE_CONNECTIONS);
2951         nm_device_queue_activation (device, NM_ACT_REQUEST (active));
2952         return TRUE;
2953 }
2954
2955 static gboolean
2956 _internal_activate_generic (NMManager *self, NMActiveConnection *active, GError **error)
2957 {
2958         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
2959         gboolean success = FALSE;
2960
2961         /* Ensure activation request is still valid, eg that its device hasn't gone
2962          * away or that some other dependency has not failed.
2963          */
2964         if (nm_active_connection_get_state (active) >= NM_ACTIVE_CONNECTION_STATE_DEACTIVATING) {
2965                 g_set_error_literal (error,
2966                                      NM_MANAGER_ERROR,
2967                                      NM_MANAGER_ERROR_DEPENDENCY_FAILED,
2968                                      "Activation failed because dependencies failed.");
2969                 return FALSE;
2970         }
2971
2972         if (NM_IS_VPN_CONNECTION (active))
2973                 success = _internal_activate_vpn (self, active, error);
2974         else
2975                 success = _internal_activate_device (self, active, error);
2976
2977         if (success) {
2978                 /* Force an update of the Manager's activating-connection property.
2979                  * The device changes state before the AC gets exported, which causes
2980                  * the manager's 'activating-connection' property to be NULL since the
2981                  * AC only gets a D-Bus path when it's exported.  So now that the AC
2982                  * is exported, make sure the manager's activating-connection property
2983                  * is up-to-date.
2984                  */
2985                 active_connection_add (self, active);
2986                 policy_activating_device_changed (G_OBJECT (priv->policy), NULL, self);
2987         }
2988
2989         return success;
2990 }
2991
2992 static NMActiveConnection *
2993 _new_vpn_active_connection (NMManager *self,
2994                             NMSettingsConnection *settings_connection,
2995                             const char *specific_object,
2996                             NMAuthSubject *subject,
2997                             GError **error)
2998 {
2999         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
3000         NMActiveConnection *parent = NULL;
3001         NMDevice *device = NULL;
3002
3003         g_return_val_if_fail (!settings_connection || NM_IS_SETTINGS_CONNECTION (settings_connection), NULL);
3004
3005         if (specific_object) {
3006                 /* Find the specific connection the client requested we use */
3007                 parent = active_connection_get_by_path (self, specific_object);
3008                 if (!parent) {
3009                         g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE,
3010                                              "Base connection for VPN connection not active.");
3011                         return NULL;
3012                 }
3013         } else
3014                 parent = priv->primary_connection;
3015
3016         if (!parent) {
3017                 g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_CONNECTION,
3018                                      "Could not find source connection.");
3019                 return NULL;
3020         }
3021
3022         device = nm_active_connection_get_device (parent);
3023         if (!device) {
3024                 g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE,
3025                                      "Source connection had no active device.");
3026                 return NULL;
3027         }
3028
3029         return (NMActiveConnection *) nm_vpn_connection_new (settings_connection,
3030                                                              device,
3031                                                              nm_exported_object_get_path (NM_EXPORTED_OBJECT (parent)),
3032                                                              subject);
3033 }
3034
3035 static NMActiveConnection *
3036 _new_active_connection (NMManager *self,
3037                         NMConnection *connection,
3038                         const char *specific_object,
3039                         NMDevice *device,
3040                         NMAuthSubject *subject,
3041                         GError **error)
3042 {
3043         NMSettingsConnection *settings_connection = NULL;
3044         NMActiveConnection *existing_ac;
3045         gboolean is_vpn;
3046
3047         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
3048         g_return_val_if_fail (NM_IS_AUTH_SUBJECT (subject), NULL);
3049
3050         /* Can't create new AC for already-active connection */
3051         existing_ac = find_ac_for_connection (self, connection);
3052         if (NM_IS_VPN_CONNECTION (existing_ac)) {
3053                 g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_ALREADY_ACTIVE,
3054                              "Connection '%s' is already active",
3055                              nm_connection_get_id (connection));
3056                 return NULL;
3057         }
3058
3059         /* Normalize the specific object */
3060         if (specific_object && g_strcmp0 (specific_object, "/") == 0)
3061                 specific_object = NULL;
3062
3063         is_vpn = nm_connection_is_type (NM_CONNECTION (connection), NM_SETTING_VPN_SETTING_NAME);
3064
3065         if (NM_IS_SETTINGS_CONNECTION (connection))
3066                 settings_connection = (NMSettingsConnection *) connection;
3067
3068         if (is_vpn) {
3069                 return _new_vpn_active_connection (self,
3070                                                    settings_connection,
3071                                                    specific_object,
3072                                                    subject,
3073                                                    error);
3074         }
3075
3076         return (NMActiveConnection *) nm_act_request_new (settings_connection,
3077                                                           specific_object,
3078                                                           subject,
3079                                                           device);
3080 }
3081
3082 static void
3083 _internal_activation_failed (NMManager *self,
3084                              NMActiveConnection *active,
3085                              const char *error_desc)
3086 {
3087         _LOGD (LOGD_CORE, "Failed to activate '%s': %s",
3088                nm_active_connection_get_settings_connection_id (active),
3089                error_desc);
3090
3091         if (nm_active_connection_get_state (active) <= NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
3092                 nm_active_connection_set_state (active, NM_ACTIVE_CONNECTION_STATE_DEACTIVATING);
3093                 nm_active_connection_set_state (active, NM_ACTIVE_CONNECTION_STATE_DEACTIVATED);
3094         }
3095 }
3096
3097 static void
3098 _internal_activation_auth_done (NMActiveConnection *active,
3099                                 gboolean success,
3100                                 const char *error_desc,
3101                                 gpointer user_data1,
3102                                 gpointer user_data2)
3103 {
3104         NMManager *self = user_data1;
3105         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
3106         GError *error = NULL;
3107
3108         priv->authorizing_connections = g_slist_remove (priv->authorizing_connections, active);
3109
3110         if (success) {
3111                 if (_internal_activate_generic (self, active, &error)) {
3112                         g_object_unref (active);
3113                         return;
3114                 }
3115         }
3116
3117         g_assert (error_desc || error);
3118         _internal_activation_failed (self, active, error_desc ? error_desc : error->message);
3119         g_object_unref (active);
3120         g_clear_error (&error);
3121 }
3122
3123 /**
3124  * nm_manager_activate_connection():
3125  * @self: the #NMManager
3126  * @connection: the #NMSettingsConnection to activate on @device
3127  * @specific_object: the specific object path, if any, for the activation
3128  * @device: the #NMDevice to activate @connection on
3129  * @subject: the subject which requested activation
3130  * @error: return location for an error
3131  *
3132  * Begins a new internally-initiated activation of @connection on @device.
3133  * @subject should be the subject of the activation that triggered this
3134  * one, or if this is an autoconnect request, a new internal subject.
3135  * The returned #NMActiveConnection is owned by the Manager and should be
3136  * referenced by the caller if the caller continues to use it.
3137  *
3138  * Returns: (transfer none): the new #NMActiveConnection that tracks
3139  * activation of @connection on @device
3140  */
3141 NMActiveConnection *
3142 nm_manager_activate_connection (NMManager *self,
3143                                 NMSettingsConnection *connection,
3144                                 const char *specific_object,
3145                                 NMDevice *device,
3146                                 NMAuthSubject *subject,
3147                                 GError **error)
3148 {
3149         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
3150         NMActiveConnection *active;
3151         char *error_desc = NULL;
3152         GSList *iter;
3153
3154         g_return_val_if_fail (self != NULL, NULL);
3155         g_return_val_if_fail (connection != NULL, NULL);
3156         g_return_val_if_fail (error != NULL, NULL);
3157         g_return_val_if_fail (*error == NULL, NULL);
3158
3159         /* Ensure the subject has permissions for this connection */
3160         if (!nm_auth_is_subject_in_acl (NM_CONNECTION (connection),
3161                                         subject,
3162                                         &error_desc)) {
3163                 g_set_error_literal (error,
3164                                      NM_MANAGER_ERROR,
3165                                      NM_MANAGER_ERROR_PERMISSION_DENIED,
3166                                      error_desc);
3167                 g_free (error_desc);
3168                 return NULL;
3169         }
3170
3171         /* Look for a active connection that's equivalent and is already pending authorization
3172          * and eventual activation. This is used to de-duplicate concurrent activations which would
3173          * otherwise race and cause the device to disconnect and reconnect repeatedly.
3174          * In particular, this allows the master and multiple slaves to concurrently auto-activate
3175          * while all the slaves would use the same active-connection. */
3176         for (iter = priv->authorizing_connections; iter; iter = g_slist_next (iter)) {
3177                 active = iter->data;
3178
3179                 if (   connection == nm_active_connection_get_settings_connection (active)
3180                     && g_strcmp0 (nm_active_connection_get_specific_object (active), specific_object) == 0
3181                     && nm_active_connection_get_device (active) == device
3182                     && nm_auth_subject_is_internal (nm_active_connection_get_subject (active))
3183                     && nm_auth_subject_is_internal (subject))
3184                         return active;
3185         }
3186
3187         active = _new_active_connection (self,
3188                                          NM_CONNECTION (connection),
3189                                          specific_object,
3190                                          device,
3191                                          subject,
3192                                          error);
3193         if (active) {
3194                 priv->authorizing_connections = g_slist_prepend (priv->authorizing_connections, active);
3195                 nm_active_connection_authorize (active, NULL, _internal_activation_auth_done, self, NULL);
3196         }
3197         return active;
3198 }
3199
3200 /**
3201  * validate_activation_request:
3202  * @self: the #NMManager
3203  * @context: the D-Bus context of the requestor
3204  * @connection: the partial or complete #NMConnection to be activated
3205  * @device_path: the object path of the device to be activated, or "/"
3206  * @out_device: on successful reutrn, the #NMDevice to be activated with @connection
3207  * @out_vpn: on successful return, %TRUE if @connection is a VPN connection
3208  * @error: location to store an error on failure
3209  *
3210  * Performs basic validation on an activation request, including ensuring that
3211  * the requestor is a valid Unix process, is not disallowed in @connection
3212  * permissions, and that a device exists that can activate @connection.
3213  *
3214  * Returns: on success, the #NMAuthSubject representing the requestor, or
3215  *   %NULL on error
3216  */
3217 static NMAuthSubject *
3218 validate_activation_request (NMManager *self,
3219                              GDBusMethodInvocation *context,
3220                              NMConnection *connection,
3221                              const char *device_path,
3222                              NMDevice **out_device,
3223                              gboolean *out_vpn,
3224                              GError **error)
3225 {
3226         NMDevice *device = NULL;
3227         gboolean vpn = FALSE;
3228         NMAuthSubject *subject = NULL;
3229         char *error_desc = NULL;
3230
3231         g_assert (connection);
3232         g_assert (out_device);
3233         g_assert (out_vpn);
3234
3235         /* Validate the caller */
3236         subject = nm_auth_subject_new_unix_process_from_context (context);
3237         if (!subject) {
3238                 g_set_error_literal (error,
3239                                      NM_MANAGER_ERROR,
3240                                      NM_MANAGER_ERROR_PERMISSION_DENIED,
3241                                      "Failed to get request UID.");
3242                 return NULL;
3243         }
3244
3245         /* Ensure the subject has permissions for this connection */
3246         if (!nm_auth_is_subject_in_acl (connection,
3247                                         subject,
3248                                         &error_desc)) {
3249                 g_set_error_literal (error,
3250                                      NM_MANAGER_ERROR,
3251                                      NM_MANAGER_ERROR_PERMISSION_DENIED,
3252                                      error_desc);
3253                 g_free (error_desc);
3254                 goto error;
3255         }
3256
3257         /* Not implemented yet, we want to fail early */
3258         if (   nm_connection_get_setting_connection (connection)
3259             && nm_connection_get_setting_ip6_config (connection)
3260             && !strcmp (nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG),
3261                         NM_SETTING_IP6_CONFIG_METHOD_SHARED)) {
3262                 g_set_error_literal (error,
3263                                      NM_MANAGER_ERROR,
3264                                      NM_MANAGER_ERROR_CONNECTION_NOT_AVAILABLE,
3265                                      "Sharing IPv6 connections is not supported yet.");
3266                 return NULL;
3267         }
3268
3269         /* Check whether it's a VPN or not */
3270         if (   nm_connection_get_setting_vpn (connection)
3271             || nm_connection_is_type (connection, NM_SETTING_VPN_SETTING_NAME))
3272                 vpn = TRUE;
3273
3274         /* Normalize device path */
3275         if (device_path && g_strcmp0 (device_path, "/") == 0)
3276                 device_path = NULL;
3277
3278         /* And validate it */
3279         if (device_path) {
3280                 device = nm_manager_get_device_by_path (self, device_path);
3281                 if (!device) {
3282                         g_set_error_literal (error,
3283                                              NM_MANAGER_ERROR,
3284                                              NM_MANAGER_ERROR_UNKNOWN_DEVICE,
3285                                              "Device not found");
3286                         goto error;
3287                 }
3288         } else
3289                 device = nm_manager_get_best_device_for_connection (self, connection, TRUE);
3290
3291         if (!device && !vpn) {
3292                 gboolean is_software = nm_connection_is_virtual (connection);
3293
3294                 /* VPN and software-device connections don't need a device yet */
3295                 if (!is_software) {
3296                         g_set_error_literal (error,
3297                                              NM_MANAGER_ERROR,
3298                                              NM_MANAGER_ERROR_UNKNOWN_DEVICE,
3299                                              "No suitable device found for this connection.");
3300                         goto error;
3301                 }
3302
3303                 if (is_software) {
3304                         char *iface;
3305
3306                         /* Look for an existing device with the connection's interface name */
3307                         iface = nm_manager_get_connection_iface (self, connection, NULL, error);
3308                         if (!iface)
3309                                 goto error;
3310
3311                         device = find_device_by_iface (self, iface, connection, NULL);
3312                         g_free (iface);
3313                 }
3314         }
3315
3316         if ((!vpn || device_path) && !device) {
3317                 g_set_error_literal (error,
3318                                      NM_MANAGER_ERROR,
3319                                      NM_MANAGER_ERROR_UNKNOWN_DEVICE,
3320                                      "Failed to find a compatible device for this connection");
3321                 goto error;
3322         }
3323
3324         *out_device = device;
3325         *out_vpn = vpn;
3326         return subject;
3327
3328 error:
3329         g_object_unref (subject);
3330         return NULL;
3331 }
3332
3333 /***********************************************************************/
3334
3335 static void
3336 _activation_auth_done (NMActiveConnection *active,
3337                        gboolean success,
3338                        const char *error_desc,
3339                        gpointer user_data1,
3340                        gpointer user_data2)
3341 {
3342         NMManager *self = user_data1;
3343         GDBusMethodInvocation *context = user_data2;
3344         GError *error = NULL;
3345         NMAuthSubject *subject;
3346         NMSettingsConnection *connection;
3347
3348         subject = nm_active_connection_get_subject (active);
3349         connection = nm_active_connection_get_settings_connection (active);
3350
3351         if (success) {
3352                 if (_internal_activate_generic (self, active, &error)) {
3353                         g_dbus_method_invocation_return_value (context,
3354                                                                g_variant_new ("(o)",
3355                                                                nm_exported_object_get_path (NM_EXPORTED_OBJECT (active))));
3356                         nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ACTIVATE, connection, TRUE,
3357                                                     subject, NULL);
3358                         g_object_unref (active);
3359                         return;
3360                 }
3361         } else {
3362                 error = g_error_new_literal (NM_MANAGER_ERROR,
3363                                              NM_MANAGER_ERROR_PERMISSION_DENIED,
3364                                              error_desc);
3365         }
3366
3367         g_assert (error);
3368         nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ACTIVATE, connection, FALSE,
3369                                     subject, error->message);
3370         _internal_activation_failed (self, active, error->message);
3371
3372         g_object_unref (active);
3373         g_dbus_method_invocation_take_error (context, error);
3374 }
3375
3376 static void
3377 impl_manager_activate_connection (NMManager *self,
3378                                   GDBusMethodInvocation *context,
3379                                   const char *connection_path,
3380                                   const char *device_path,
3381                                   const char *specific_object_path)
3382 {
3383         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
3384         NMActiveConnection *active = NULL;
3385         NMAuthSubject *subject = NULL;
3386         NMSettingsConnection *connection = NULL;
3387         NMDevice *device = NULL;
3388         gboolean is_vpn = FALSE;
3389         GError *error = NULL;
3390
3391         /* Normalize object paths */
3392         if (g_strcmp0 (connection_path, "/") == 0)
3393                 connection_path = NULL;
3394         if (g_strcmp0 (specific_object_path, "/") == 0)
3395                 specific_object_path = NULL;
3396         if (g_strcmp0 (device_path, "/") == 0)
3397                 device_path = NULL;
3398
3399         /* If the connection path is given and valid, that connection is activated.
3400          * Otherwise the "best" connection for the device is chosen and activated,
3401          * regardless of whether that connection is autoconnect-enabled or not
3402          * (since this is an explicit request, not an auto-activation request).
3403          */
3404         if (connection_path) {
3405                 connection = nm_settings_get_connection_by_path (priv->settings, connection_path);
3406                 if (!connection) {
3407                         error = g_error_new_literal (NM_MANAGER_ERROR,
3408                                                      NM_MANAGER_ERROR_UNKNOWN_CONNECTION,
3409                                                      "Connection could not be found.");
3410                         goto error;
3411                 }
3412         } else {
3413                 /* If no connection is given, find a suitable connection for the given device path */
3414                 if (!device_path) {
3415                         error = g_error_new_literal (NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE,
3416                                                      "Only devices may be activated without a specifying a connection");
3417                         goto error;
3418                 }
3419                 device = nm_manager_get_device_by_path (self, device_path);
3420                 if (!device) {
3421                         error = g_error_new (NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE,
3422                                              "Cannot activate unknown device %s", device_path);
3423                         goto error;
3424                 }
3425
3426                 connection = nm_device_get_best_connection (device, specific_object_path, &error);
3427                 if (!connection)
3428                         goto error;
3429         }
3430
3431         subject = validate_activation_request (self,
3432                                                context,
3433                                                NM_CONNECTION (connection),
3434                                                device_path,
3435                                                &device,
3436                                                &is_vpn,
3437                                                &error);
3438         if (!subject)
3439                 goto error;
3440
3441         active = _new_active_connection (self,
3442                                          NM_CONNECTION (connection),
3443                                          specific_object_path,
3444                                          device,
3445                                          subject,
3446                                          &error);
3447         if (!active)
3448                 goto error;
3449
3450         nm_active_connection_authorize (active, NULL, _activation_auth_done, self, context);
3451         g_clear_object (&subject);
3452         return;
3453
3454 error:
3455         if (connection) {
3456                 nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ACTIVATE, connection, FALSE,
3457                                             subject, error->message);
3458         }
3459         g_clear_object (&active);
3460         g_clear_object (&subject);
3461
3462         g_assert (error);
3463         g_dbus_method_invocation_take_error (context, error);
3464 }
3465
3466 /***********************************************************************/
3467
3468 typedef struct {
3469         NMManager *manager;
3470         NMActiveConnection *active;
3471 } AddAndActivateInfo;
3472
3473 static void
3474 activation_add_done (NMSettings *settings,
3475                      NMSettingsConnection *new_connection,
3476                      GError *error,
3477                      GDBusMethodInvocation *context,
3478                      NMAuthSubject *subject,
3479                      gpointer user_data)
3480 {
3481         AddAndActivateInfo *info = user_data;
3482         NMManager *self;
3483         gs_unref_object NMActiveConnection *active = NULL;
3484         GError *local = NULL;
3485
3486         self = info->manager;
3487         active = info->active;
3488         g_slice_free (AddAndActivateInfo, info);
3489
3490         if (!error) {
3491                 nm_active_connection_set_settings_connection (active, new_connection);
3492
3493                 if (_internal_activate_generic (self, active, &local)) {
3494                         nm_settings_connection_commit_changes (new_connection,
3495                                                                NM_SETTINGS_CONNECTION_COMMIT_REASON_USER_ACTION | NM_SETTINGS_CONNECTION_COMMIT_REASON_ID_CHANGED,
3496                                                                NULL, NULL);
3497                         g_dbus_method_invocation_return_value (
3498                             context,
3499                             g_variant_new ("(oo)",
3500                                            nm_connection_get_path (NM_CONNECTION (new_connection)),
3501                                            nm_exported_object_get_path (NM_EXPORTED_OBJECT (active))));
3502                         nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD_ACTIVATE,
3503                                                     nm_active_connection_get_settings_connection (active),
3504                                                     TRUE,
3505                                                     nm_active_connection_get_subject (active),
3506                                                     NULL);
3507                         return;
3508                 }
3509                 error = local;
3510         }
3511
3512         g_assert (error);
3513         _internal_activation_failed (self, active, error->message);
3514         nm_settings_connection_delete (new_connection, NULL, NULL);
3515         g_dbus_method_invocation_return_gerror (context, error);
3516         nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD_ACTIVATE,
3517                                     NULL,
3518                                     FALSE,
3519                                     nm_active_connection_get_subject (active),
3520                                     error->message);
3521         g_clear_error (&local);
3522 }
3523
3524 static void
3525 _add_and_activate_auth_done (NMActiveConnection *active,
3526                              gboolean success,
3527                              const char *error_desc,
3528                              gpointer user_data1,
3529                              gpointer user_data2)
3530 {
3531         NMManager *self = user_data1;
3532         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
3533         GDBusMethodInvocation *context = user_data2;
3534         AddAndActivateInfo *info;
3535         GError *error = NULL;
3536
3537         if (success) {
3538                 NMConnection *connection;
3539
3540                 connection = g_object_steal_data (G_OBJECT (active),
3541                                                   TAG_ACTIVE_CONNETION_ADD_AND_ACTIVATE);
3542
3543                 info = g_slice_new (AddAndActivateInfo);
3544                 info->manager = self;
3545                 info->active = g_object_ref (active);
3546
3547                 /* Basic sender auth checks performed; try to add the connection */
3548                 nm_settings_add_connection_dbus (priv->settings,
3549                                                  connection,
3550                                                  FALSE,
3551                                                  context,
3552                                                  activation_add_done,
3553                                                  info);
3554                 g_object_unref (connection);
3555         } else {
3556                 g_assert (error_desc);
3557                 error = g_error_new_literal (NM_MANAGER_ERROR,
3558                                              NM_MANAGER_ERROR_PERMISSION_DENIED,
3559                                              error_desc);
3560                 nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD_ACTIVATE,
3561                                             NULL,
3562                                             FALSE,
3563                                             nm_active_connection_get_subject (active),
3564                                             error->message);
3565                 g_dbus_method_invocation_take_error (context, error);
3566         }
3567
3568         g_object_unref (active);
3569 }
3570
3571 static void
3572 impl_manager_add_and_activate_connection (NMManager *self,
3573                                           GDBusMethodInvocation *context,
3574                                           GVariant *settings,
3575                                           const char *device_path,
3576                                           const char *specific_object_path)
3577 {
3578         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
3579         NMConnection *connection = NULL;
3580         GSList *all_connections = NULL;
3581         NMActiveConnection *active = NULL;
3582         NMAuthSubject *subject = NULL;
3583         GError *error = NULL;
3584         NMDevice *device = NULL;
3585         gboolean vpn = FALSE;
3586
3587         /* Normalize object paths */
3588         if (g_strcmp0 (specific_object_path, "/") == 0)
3589                 specific_object_path = NULL;
3590         if (g_strcmp0 (device_path, "/") == 0)
3591                 device_path = NULL;
3592
3593         /* Try to create a new connection with the given settings.
3594          * We allow empty settings for AddAndActivateConnection(). In that case,
3595          * the connection will be completed in nm_utils_complete_generic() or
3596          * nm_device_complete_connection() below. Just make sure we don't expect
3597          * specific data being in the connection till then (especially in
3598          * validate_activation_request()).
3599          */
3600         connection = nm_simple_connection_new ();
3601         if (settings && g_variant_n_children (settings))
3602                 nm_connection_replace_settings (connection, settings, NULL);
3603
3604         subject = validate_activation_request (self,
3605                                                context,
3606                                                connection,
3607                                                device_path,
3608                                                &device,
3609                                                &vpn,
3610                                                &error);
3611         if (!subject)
3612                 goto error;
3613
3614         all_connections = nm_settings_get_connections (priv->settings);
3615         if (vpn) {
3616                 /* Try to fill the VPN's connection setting and name at least */
3617                 if (!nm_connection_get_setting_vpn (connection)) {
3618                         error = g_error_new_literal (NM_CONNECTION_ERROR,
3619                                                      NM_CONNECTION_ERROR_MISSING_SETTING,
3620                                                      "VPN connections require a 'vpn' setting");
3621                         g_prefix_error (&error, "%s: ", NM_SETTING_VPN_SETTING_NAME);
3622                         goto error;
3623                 }
3624
3625                 nm_utils_complete_generic (NM_PLATFORM_GET,
3626                                            connection,
3627                                            NM_SETTING_VPN_SETTING_NAME,
3628                                            all_connections,
3629                                            NULL,
3630                                            _("VPN connection"),
3631                                            NULL,
3632                                            FALSE); /* No IPv6 by default for now */
3633         } else {
3634                 /* Let each device subclass complete the connection */
3635                 if (!nm_device_complete_connection (device,
3636                                                     connection,
3637                                                     specific_object_path,
3638                                                     all_connections,
3639                                                     &error))
3640                         goto error;
3641         }
3642         g_slist_free (all_connections);
3643         all_connections = NULL;
3644
3645         active = _new_active_connection (self,
3646                                          connection,
3647                                          specific_object_path,
3648                                          device,
3649                                          subject,
3650                                          &error);
3651         if (!active)
3652                 goto error;
3653
3654         g_object_set_data_full (G_OBJECT (active),
3655                                 TAG_ACTIVE_CONNETION_ADD_AND_ACTIVATE,
3656                                 connection,
3657                                 g_object_unref);
3658
3659         nm_active_connection_authorize (active, connection, _add_and_activate_auth_done, self, context);
3660         g_object_unref (subject);
3661         return;
3662
3663 error:
3664         nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD_ACTIVATE, NULL, FALSE, subject, error->message);
3665         g_clear_object (&connection);
3666         g_slist_free (all_connections);
3667         g_clear_object (&subject);
3668         g_clear_object (&active);
3669
3670         g_assert (error);
3671         g_dbus_method_invocation_take_error (context, error);
3672 }
3673
3674 /***********************************************************************/
3675
3676 gboolean
3677 nm_manager_deactivate_connection (NMManager *manager,
3678                                   const char *connection_path,
3679                                   NMDeviceStateReason reason,
3680                                   GError **error)
3681 {
3682         NMActiveConnection *active;
3683         gboolean success = FALSE;
3684
3685         active = active_connection_get_by_path (manager, connection_path);
3686         if (!active) {
3687                 g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE,
3688                                      "The connection was not active.");
3689                 return FALSE;
3690         }
3691
3692         if (NM_IS_VPN_CONNECTION (active)) {
3693                 NMVpnConnectionStateReason vpn_reason = NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED;
3694
3695                 if (reason == NM_DEVICE_STATE_REASON_CONNECTION_REMOVED)
3696                         vpn_reason = NM_VPN_CONNECTION_STATE_REASON_CONNECTION_REMOVED;
3697                 if (nm_vpn_connection_deactivate (NM_VPN_CONNECTION (active), vpn_reason, FALSE))
3698                         success = TRUE;
3699                 else
3700                         g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE,
3701                                              "The VPN connection was not active.");
3702         } else {
3703                 g_assert (NM_IS_ACT_REQUEST (active));
3704                 nm_device_state_changed (nm_active_connection_get_device (active),
3705                                          NM_DEVICE_STATE_DEACTIVATING,
3706                                          reason);
3707                 success = TRUE;
3708         }
3709
3710         if (success)
3711                 g_object_notify (G_OBJECT (manager), NM_MANAGER_ACTIVE_CONNECTIONS);
3712
3713         return success;
3714 }
3715
3716 static void
3717 deactivate_net_auth_done_cb (NMAuthChain *chain,
3718                              GError *auth_error,
3719                              GDBusMethodInvocation *context,
3720                              gpointer user_data)
3721 {
3722         NMManager *self = NM_MANAGER (user_data);
3723         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
3724         GError *error = NULL;
3725         NMAuthCallResult result;
3726         NMActiveConnection *active;
3727         char *path;
3728
3729         g_assert (context);
3730
3731         priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
3732
3733         path = nm_auth_chain_get_data (chain, "path");
3734         result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL);
3735
3736         if (auth_error) {
3737                 _LOGD (LOGD_CORE, "Disconnect request failed: %s", auth_error->message);
3738                 error = g_error_new (NM_MANAGER_ERROR,
3739                                      NM_MANAGER_ERROR_PERMISSION_DENIED,
3740                                      "Deactivate request failed: %s",
3741                                      auth_error->message);
3742         } else if (result != NM_AUTH_CALL_RESULT_YES) {
3743                 error = g_error_new_literal (NM_MANAGER_ERROR,
3744                                              NM_MANAGER_ERROR_PERMISSION_DENIED,
3745                                              "Not authorized to deactivate connections");
3746         } else {
3747                 /* success; deactivation allowed */
3748                 if (!nm_manager_deactivate_connection (self,
3749                                                        path,
3750                                                        NM_DEVICE_STATE_REASON_USER_REQUESTED,
3751                                                        &error))
3752                         nm_assert (error);
3753         }
3754
3755         active = active_connection_get_by_path (self, path);
3756         if (active) {
3757                 nm_audit_log_connection_op (NM_AUDIT_OP_CONN_DEACTIVATE,
3758                                             nm_active_connection_get_settings_connection (active),
3759                                             !error,
3760                                             nm_auth_chain_get_subject (chain),
3761                                             error ? error->message : NULL);
3762         }
3763
3764         if (error)
3765                 g_dbus_method_invocation_take_error (context, error);
3766         else
3767                 g_dbus_method_invocation_return_value (context, NULL);
3768
3769         nm_auth_chain_unref (chain);
3770 }
3771
3772 static void
3773 impl_manager_deactivate_connection (NMManager *self,
3774                                     GDBusMethodInvocation *context,
3775                                     const char *active_path)
3776 {
3777         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
3778         NMActiveConnection *ac;
3779         NMSettingsConnection *connection = NULL;
3780         GError *error = NULL;
3781         NMAuthSubject *subject = NULL;
3782         NMAuthChain *chain;
3783         char *error_desc = NULL;
3784
3785         /* Find the connection by its object path */
3786         ac = active_connection_get_by_path (self, active_path);
3787         if (ac)
3788                 connection = nm_active_connection_get_settings_connection (ac);
3789
3790         if (!connection) {
3791                 error = g_error_new_literal (NM_MANAGER_ERROR,
3792                                              NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE,
3793                                              "The connection was not active.");
3794                 goto done;
3795         }
3796
3797         /* Validate the caller */
3798         subject = nm_auth_subject_new_unix_process_from_context (context);
3799         if (!subject) {
3800                 error = g_error_new_literal (NM_MANAGER_ERROR,
3801                                              NM_MANAGER_ERROR_PERMISSION_DENIED,
3802                                              "Failed to get request UID.");
3803                 goto done;
3804         }
3805
3806         /* Ensure the subject has permissions for this connection */
3807         if (!nm_auth_is_subject_in_acl (NM_CONNECTION (connection),
3808                                         subject,
3809                                         &error_desc)) {
3810                 error = g_error_new_literal (NM_MANAGER_ERROR,
3811                                              NM_MANAGER_ERROR_PERMISSION_DENIED,
3812                                              error_desc);
3813                 g_free (error_desc);
3814                 goto done;
3815         }
3816
3817         /* Validate the user request */
3818         chain = nm_auth_chain_new_subject (subject, context, deactivate_net_auth_done_cb, self);
3819         if (!chain) {
3820                 error = g_error_new_literal (NM_MANAGER_ERROR,
3821                                              NM_MANAGER_ERROR_PERMISSION_DENIED,
3822                                              "Unable to authenticate request.");
3823                 goto done;
3824         }
3825
3826         priv->auth_chains = g_slist_append (priv->auth_chains, chain);
3827         nm_auth_chain_set_data (chain, "path", g_strdup (active_path), g_free);
3828         nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE);
3829
3830 done:
3831         if (error) {
3832                 if (connection) {
3833                         nm_audit_log_connection_op (NM_AUDIT_OP_CONN_DEACTIVATE, connection, FALSE,
3834                                                     subject, error->message);
3835                 }
3836                 g_dbus_method_invocation_take_error (context, error);
3837         }
3838         g_clear_object (&subject);
3839 }
3840
3841 static gboolean
3842 device_is_wake_on_lan (NMDevice *device)
3843 {
3844         return nm_platform_link_get_wake_on_lan (NM_PLATFORM_GET, nm_device_get_ip_ifindex (device));
3845 }
3846
3847 static void
3848 do_sleep_wake (NMManager *self, gboolean sleeping_changed)
3849 {
3850         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
3851         gboolean suspending, waking_from_suspend;
3852         GSList *iter;
3853
3854         suspending = sleeping_changed && priv->sleeping;
3855         waking_from_suspend = sleeping_changed && !priv->sleeping;
3856
3857         if (manager_sleeping (self)) {
3858                 _LOGI (LOGD_SUSPEND, "%s...", suspending ? "sleeping" : "disabling");
3859
3860                 /* FIXME: are there still hardware devices that need to be disabled around
3861                  * suspend/resume?
3862                  */
3863                 for (iter = priv->devices; iter; iter = iter->next) {
3864                         NMDevice *device = iter->data;
3865
3866                         /* FIXME: shouldn't we be unmanaging software devices if !suspending? */
3867                         if (nm_device_is_software (device))
3868                                 continue;
3869                         /* Wake-on-LAN devices will be taken down post-suspend rather than pre- */
3870                         if (suspending && device_is_wake_on_lan (device))
3871                                 continue;
3872
3873                         nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_SLEEPING, TRUE, NM_DEVICE_STATE_REASON_SLEEPING);
3874                 }
3875         } else {
3876                 _LOGI (LOGD_SUSPEND, "%s...", waking_from_suspend ? "waking up" : "re-enabling");
3877
3878                 if (waking_from_suspend) {
3879                         /* Belatedly take down Wake-on-LAN devices; ideally we wouldn't have to do this
3880                          * but for now it's the only way to make sure we re-check their connectivity.
3881                          */
3882                         for (iter = priv->devices; iter; iter = iter->next) {
3883                                 NMDevice *device = iter->data;
3884
3885                                 if (nm_device_is_software (device))
3886                                         continue;
3887                                 if (device_is_wake_on_lan (device))
3888                                         nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_SLEEPING, TRUE, NM_DEVICE_STATE_REASON_SLEEPING);
3889                         }
3890                 }
3891
3892                 /* Ensure rfkill state is up-to-date since we don't respond to state
3893                  * changes during sleep.
3894                  */
3895                 nm_manager_rfkill_update (self, RFKILL_TYPE_UNKNOWN);
3896
3897                 /* Re-manage managed devices */
3898                 for (iter = priv->devices; iter; iter = iter->next) {
3899                         NMDevice *device = NM_DEVICE (iter->data);
3900                         guint i;
3901
3902                         if (nm_device_is_software (device))
3903                                 continue;
3904
3905                         /* enable/disable wireless devices since that we don't respond
3906                          * to killswitch changes during sleep.
3907                          */
3908                         for (i = 0; i < RFKILL_TYPE_MAX; i++) {
3909                                 RadioState *rstate = &priv->radio_states[i];
3910                                 gboolean enabled = radio_enabled_for_rstate (rstate, TRUE);
3911
3912                                 if (rstate->desc) {
3913                                         _LOGD (LOGD_RFKILL, "%s %s devices (hw_enabled %d, sw_enabled %d, user_enabled %d)",
3914                                                enabled ? "enabling" : "disabling",
3915                                                rstate->desc, rstate->hw_enabled, rstate->sw_enabled, rstate->user_enabled);
3916                                 }
3917
3918                                 if (nm_device_get_rfkill_type (device) == rstate->rtype)
3919                                         nm_device_set_enabled (device, enabled);
3920                         }
3921
3922                         nm_device_set_autoconnect (device, TRUE);
3923
3924                         nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_SLEEPING, FALSE, NM_DEVICE_STATE_REASON_NOW_MANAGED);
3925                 }
3926         }
3927
3928         nm_manager_update_state (self);
3929 }
3930
3931 static void
3932 _internal_sleep (NMManager *self, gboolean do_sleep)
3933 {
3934         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
3935
3936         if (priv->sleeping == do_sleep)
3937                 return;
3938
3939         _LOGI (LOGD_SUSPEND, "%s requested (sleeping: %s  enabled: %s)",
3940                do_sleep ? "sleep" : "wake",
3941                priv->sleeping ? "yes" : "no",
3942                priv->net_enabled ? "yes" : "no");
3943
3944         priv->sleeping = do_sleep;
3945
3946         do_sleep_wake (self, TRUE);
3947
3948         g_object_notify (G_OBJECT (self), NM_MANAGER_SLEEPING);
3949 }
3950
3951 #if 0
3952 static void
3953 sleep_auth_done_cb (NMAuthChain *chain,
3954                     GError *error,
3955                     GDBusMethodInvocation *context,
3956                     gpointer user_data)
3957 {
3958         NMManager *self = NM_MANAGER (user_data);
3959         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
3960         GError *ret_error;
3961         NMAuthCallResult result;
3962         gboolean do_sleep;
3963
3964         priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
3965
3966         result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_SLEEP_WAKE);
3967         if (error) {
3968                 _LOGD (LOGD_SUSPEND, "Sleep/wake request failed: %s", error->message);
3969                 ret_error = g_error_new (NM_MANAGER_ERROR,
3970                                          NM_MANAGER_ERROR_PERMISSION_DENIED,
3971                                          "Sleep/wake request failed: %s",
3972                                          error->message);
3973                 g_dbus_method_invocation_take_error (context, ret_error);
3974         } else if (result != NM_AUTH_CALL_RESULT_YES) {
3975                 ret_error = g_error_new_literal (NM_MANAGER_ERROR,
3976                                                  NM_MANAGER_ERROR_PERMISSION_DENIED,
3977                                                  "Not authorized to sleep/wake");
3978                 g_dbus_method_invocation_take_error (context, ret_error);
3979         } else {
3980                 /* Auth success */
3981                 do_sleep = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "sleep"));
3982                 _internal_sleep (self, do_sleep);
3983                 g_dbus_method_invocation_return_value (context, NULL);
3984         }
3985
3986         nm_auth_chain_unref (chain);
3987 }
3988 #endif
3989
3990 static void
3991 impl_manager_sleep (NMManager *self,
3992                     GDBusMethodInvocation *context,
3993                     gboolean do_sleep)
3994 {
3995         NMManagerPrivate *priv;
3996         GError *error = NULL;
3997         gs_unref_object NMAuthSubject *subject = NULL;
3998 #if 0
3999         NMAuthChain *chain;
4000         const char *error_desc = NULL;
4001 #endif
4002
4003         g_return_if_fail (NM_IS_MANAGER (self));
4004
4005         priv = NM_MANAGER_GET_PRIVATE (self);
4006         subject = nm_auth_subject_new_unix_process_from_context (context);
4007
4008         if (priv->sleeping == do_sleep) {
4009                 error = g_error_new (NM_MANAGER_ERROR,
4010                                      NM_MANAGER_ERROR_ALREADY_ASLEEP_OR_AWAKE,
4011                                      "Already %s", do_sleep ? "asleep" : "awake");
4012                 nm_audit_log_control_op (NM_AUDIT_OP_SLEEP_CONTROL, do_sleep ? "on" : "off", FALSE, subject,
4013                                          error->message);
4014                 g_dbus_method_invocation_take_error (context, error);
4015                 return;
4016         }
4017
4018         /* Unconditionally allow the request.  Previously it was polkit protected
4019          * but unfortunately that doesn't work for short-lived processes like
4020          * pm-utils.  It uses dbus-send without --print-reply, which quits
4021          * immediately after sending the request, and NM is unable to obtain the
4022          * sender's UID as dbus-send has already dropped off the bus.  Thus NM
4023          * fails the request.  Instead, don't validate the request, but rely on
4024          * D-Bus permissions to restrict the call to root.
4025          */
4026         _internal_sleep (self, do_sleep);
4027         nm_audit_log_control_op (NM_AUDIT_OP_SLEEP_CONTROL, do_sleep ? "on" : "off", TRUE, subject, NULL);
4028         g_dbus_method_invocation_return_value (context, NULL);
4029         return;
4030
4031 #if 0
4032         chain = nm_auth_chain_new (context, sleep_auth_done_cb, self, &error_desc);
4033         if (chain) {
4034                 priv->auth_chains = g_slist_append (priv->auth_chains, chain);
4035                 nm_auth_chain_set_data (chain, "sleep", GUINT_TO_POINTER (do_sleep), NULL);
4036                 nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SLEEP_WAKE, TRUE);
4037         } else {
4038                 error = g_error_new_literal (NM_MANAGER_ERROR,
4039                                              NM_MANAGER_ERROR_PERMISSION_DENIED,
4040                                              error_desc);
4041                 g_dbus_method_invocation_take_error (context, error);
4042         }
4043 #endif
4044 }
4045
4046 static void
4047 sleeping_cb (NMSleepMonitor *monitor, gpointer user_data)
4048 {
4049         nm_log_dbg (LOGD_SUSPEND, "Received sleeping signal");
4050         _internal_sleep (NM_MANAGER (user_data), TRUE);
4051 }
4052
4053 static void
4054 resuming_cb (NMSleepMonitor *monitor, gpointer user_data)
4055 {
4056         nm_log_dbg (LOGD_SUSPEND, "Received resuming signal");
4057         _internal_sleep (NM_MANAGER (user_data), FALSE);
4058 }
4059
4060 static void
4061 _internal_enable (NMManager *self, gboolean enable)
4062 {
4063         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
4064         GError *err = NULL;
4065
4066         /* Update "NetworkingEnabled" key in state file */
4067         if (priv->state_file) {
4068                 if (!write_value_to_state_file (priv->state_file,
4069                                                 "main", "NetworkingEnabled",
4070                                                 G_TYPE_BOOLEAN, (gpointer) &enable,
4071                                                 &err)) {
4072                         /* Not a hard error */
4073                         _LOGW (LOGD_SUSPEND, "writing to state file %s failed: %s",
4074                                priv->state_file,
4075                                err->message);
4076                 }
4077         }
4078
4079         _LOGI (LOGD_SUSPEND, "%s requested (sleeping: %s  enabled: %s)",
4080                enable ? "enable" : "disable",
4081                priv->sleeping ? "yes" : "no",
4082                priv->net_enabled ? "yes" : "no");
4083
4084         priv->net_enabled = enable;
4085
4086         do_sleep_wake (self, FALSE);
4087
4088         g_object_notify (G_OBJECT (self), NM_MANAGER_NETWORKING_ENABLED);
4089 }
4090
4091 static void
4092 enable_net_done_cb (NMAuthChain *chain,
4093                     GError *error,
4094                     GDBusMethodInvocation *context,
4095                     gpointer user_data)
4096 {
4097         NMManager *self = NM_MANAGER (user_data);
4098         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
4099         GError *ret_error = NULL;
4100         NMAuthCallResult result;
4101         gboolean enable;
4102         NMAuthSubject *subject;
4103
4104         g_assert (context);
4105
4106         priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
4107         enable = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "enable"));
4108         subject = nm_auth_chain_get_subject (chain);
4109
4110         result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK);
4111         if (error) {
4112                 _LOGD (LOGD_CORE, "Enable request failed: %s", error->message);
4113                 ret_error = g_error_new (NM_MANAGER_ERROR,
4114                                          NM_MANAGER_ERROR_PERMISSION_DENIED,
4115                                          "Enable request failed: %s",
4116                                          error->message);
4117         } else if (result != NM_AUTH_CALL_RESULT_YES) {
4118                 ret_error = g_error_new_literal (NM_MANAGER_ERROR,
4119                                                  NM_MANAGER_ERROR_PERMISSION_DENIED,
4120                                                  "Not authorized to enable/disable networking");
4121         } else {
4122                 /* Auth success */
4123                 _internal_enable (self, enable);
4124                 g_dbus_method_invocation_return_value (context, NULL);
4125                 nm_audit_log_control_op (NM_AUDIT_OP_NET_CONTROL, enable ? "on" : "off", TRUE,
4126                                          subject, NULL);
4127         }
4128
4129         if (ret_error) {
4130                 nm_audit_log_control_op (NM_AUDIT_OP_NET_CONTROL, enable ? "on" : "off", FALSE,
4131                                          subject, ret_error->message);
4132                 g_dbus_method_invocation_take_error (context, ret_error);
4133         }
4134
4135         nm_auth_chain_unref (chain);
4136 }
4137
4138 static void
4139 impl_manager_enable (NMManager *self,
4140                      GDBusMethodInvocation *context,
4141                      gboolean enable)
4142 {
4143         NMManagerPrivate *priv;
4144         NMAuthChain *chain;
4145         GError *error = NULL;
4146
4147         g_return_if_fail (NM_IS_MANAGER (self));
4148
4149         priv = NM_MANAGER_GET_PRIVATE (self);
4150
4151         if (priv->net_enabled == enable) {
4152                 error = g_error_new (NM_MANAGER_ERROR,
4153                                      NM_MANAGER_ERROR_ALREADY_ENABLED_OR_DISABLED,
4154                                      "Already %s", enable ? "enabled" : "disabled");
4155                 goto done;
4156         }
4157
4158         chain = nm_auth_chain_new_context (context, enable_net_done_cb, self);
4159         if (!chain) {
4160                 error = g_error_new_literal (NM_MANAGER_ERROR,
4161                                              NM_MANAGER_ERROR_PERMISSION_DENIED,
4162                                              "Unable to authenticate request.");
4163                 goto done;
4164         }
4165
4166         priv->auth_chains = g_slist_append (priv->auth_chains, chain);
4167         nm_auth_chain_set_data (chain, "enable", GUINT_TO_POINTER (enable), NULL);
4168         nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK, TRUE);
4169
4170 done:
4171         if (error)
4172                 g_dbus_method_invocation_take_error (context, error);
4173 }
4174
4175 /* Permissions */
4176
4177 static void
4178 get_perm_add_result (NMAuthChain *chain, GVariantBuilder *results, const char *permission)
4179 {
4180         NMAuthCallResult result;
4181
4182         result = nm_auth_chain_get_result (chain, permission);
4183         if (result == NM_AUTH_CALL_RESULT_YES)
4184                 g_variant_builder_add (results, "{ss}", permission, "yes");
4185         else if (result == NM_AUTH_CALL_RESULT_NO)
4186                 g_variant_builder_add (results, "{ss}", permission, "no");
4187         else if (result == NM_AUTH_CALL_RESULT_AUTH)
4188                 g_variant_builder_add (results, "{ss}", permission, "auth");
4189         else {
4190                 nm_log_dbg (LOGD_CORE, "unknown auth chain result %d", result);
4191         }
4192 }
4193
4194 static void
4195 get_permissions_done_cb (NMAuthChain *chain,
4196                          GError *error,
4197                          GDBusMethodInvocation *context,
4198                          gpointer user_data)
4199 {
4200         NMManager *self = NM_MANAGER (user_data);
4201         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
4202         GError *ret_error;
4203         GVariantBuilder results;
4204
4205         g_assert (context);
4206
4207         priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
4208         if (error) {
4209                 _LOGD (LOGD_CORE, "Permissions request failed: %s", error->message);
4210                 ret_error = g_error_new (NM_MANAGER_ERROR,
4211                                          NM_MANAGER_ERROR_PERMISSION_DENIED,
4212                                          "Permissions request failed: %s",
4213                                          error->message);
4214                 g_dbus_method_invocation_take_error (context, ret_error);
4215         } else {
4216                 g_variant_builder_init (&results, G_VARIANT_TYPE ("a{ss}"));
4217
4218                 get_perm_add_result (chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK);
4219                 get_perm_add_result (chain, &results, NM_AUTH_PERMISSION_SLEEP_WAKE);
4220                 get_perm_add_result (chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI);
4221                 get_perm_add_result (chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN);
4222                 get_perm_add_result (chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX);
4223                 get_perm_add_result (chain, &results, NM_AUTH_PERMISSION_NETWORK_CONTROL);
4224                 get_perm_add_result (chain, &results, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED);
4225                 get_perm_add_result (chain, &results, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN);
4226                 get_perm_add_result (chain, &results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM);
4227                 get_perm_add_result (chain, &results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN);
4228                 get_perm_add_result (chain, &results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME);
4229
4230                 g_dbus_method_invocation_return_value (context,
4231                                                        g_variant_new ("(a{ss})", &results));
4232         }
4233
4234         nm_auth_chain_unref (chain);
4235 }
4236
4237 static void
4238 impl_manager_get_permissions (NMManager *self,
4239                               GDBusMethodInvocation *context)
4240 {
4241         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
4242         NMAuthChain *chain;
4243         GError *error = NULL;
4244
4245         chain = nm_auth_chain_new_context (context, get_permissions_done_cb, self);
4246         if (!chain) {
4247                 error = g_error_new_literal (NM_MANAGER_ERROR,
4248                                              NM_MANAGER_ERROR_PERMISSION_DENIED,
4249                                              "Unable to authenticate request.");
4250                 g_dbus_method_invocation_take_error (context, error);
4251                 return;
4252         }
4253
4254         priv->auth_chains = g_slist_append (priv->auth_chains, chain);
4255         nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK, FALSE);
4256         nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SLEEP_WAKE, FALSE);
4257         nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI, FALSE);
4258         nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN, FALSE);
4259         nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX, FALSE);
4260         nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, FALSE);
4261         nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED, FALSE);
4262         nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN, FALSE);
4263         nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM, FALSE);
4264         nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN, FALSE);
4265         nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME, FALSE);
4266 }
4267
4268 static void
4269 impl_manager_get_state (NMManager *self,
4270                         GDBusMethodInvocation *context)
4271 {
4272         nm_manager_update_state (self);
4273         g_dbus_method_invocation_return_value (context,
4274                                                g_variant_new ("(u)", NM_MANAGER_GET_PRIVATE (self)->state));
4275 }
4276
4277 static void
4278 impl_manager_set_logging (NMManager *self,
4279                           GDBusMethodInvocation *context,
4280                           const char *level,
4281                           const char *domains)
4282 {
4283         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
4284         GError *error = NULL;
4285         gulong caller_uid = G_MAXULONG;
4286
4287         if (!nm_bus_manager_get_caller_info (priv->dbus_mgr, context, NULL, &caller_uid, NULL)) {
4288                 error = g_error_new_literal (NM_MANAGER_ERROR,
4289                                              NM_MANAGER_ERROR_PERMISSION_DENIED,
4290                                              "Failed to get request UID.");
4291                 goto done;
4292         }
4293
4294         if (0 != caller_uid) {
4295                 error = g_error_new_literal (NM_MANAGER_ERROR,
4296                                              NM_MANAGER_ERROR_PERMISSION_DENIED,
4297                                              "Permission denied");
4298                 goto done;
4299         }
4300
4301         if (nm_logging_setup (level, domains, NULL, &error)) {
4302                 _LOGI (LOGD_CORE, "logging: level '%s' domains '%s'",
4303                        nm_logging_level_to_string (), nm_logging_domains_to_string ());
4304         }
4305
4306 done:
4307         if (error)
4308                 g_dbus_method_invocation_take_error (context, error);
4309         else
4310                 g_dbus_method_invocation_return_value (context, NULL);
4311 }
4312
4313 static void
4314 impl_manager_get_logging (NMManager *manager,
4315                           GDBusMethodInvocation *context)
4316 {
4317         g_dbus_method_invocation_return_value (context,
4318                                                g_variant_new ("(ss)",
4319                                                               nm_logging_level_to_string (),
4320                                                               nm_logging_domains_to_string ()));
4321 }
4322
4323 static void
4324 connectivity_check_done (GObject *object,
4325                          GAsyncResult *result,
4326                          gpointer user_data)
4327 {
4328         GDBusMethodInvocation *context = user_data;
4329         NMConnectivityState state;
4330         GError *error = NULL;
4331
4332         state = nm_connectivity_check_finish (NM_CONNECTIVITY (object), result, &error);
4333         if (error)
4334                 g_dbus_method_invocation_take_error (context, error);
4335         else {
4336                 g_dbus_method_invocation_return_value (context,
4337                                                        g_variant_new ("(u)", state));
4338         }
4339 }
4340
4341
4342 static void
4343 check_connectivity_auth_done_cb (NMAuthChain *chain,
4344                                  GError *auth_error,
4345                                  GDBusMethodInvocation *context,
4346                                  gpointer user_data)
4347 {
4348         NMManager *self = NM_MANAGER (user_data);
4349         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
4350         GError *error = NULL;
4351         NMAuthCallResult result;
4352
4353         priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
4354
4355         result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL);
4356
4357         if (auth_error) {
4358                 _LOGD (LOGD_CORE, "CheckConnectivity request failed: %s", auth_error->message);
4359                 error = g_error_new (NM_MANAGER_ERROR,
4360                                      NM_MANAGER_ERROR_PERMISSION_DENIED,
4361                                      "Connectivity check request failed: %s",
4362                                      auth_error->message);
4363         } else if (result != NM_AUTH_CALL_RESULT_YES) {
4364                 error = g_error_new_literal (NM_MANAGER_ERROR,
4365                                              NM_MANAGER_ERROR_PERMISSION_DENIED,
4366                                              "Not authorized to recheck connectivity");
4367         } else {
4368                 /* it's allowed */
4369                 nm_connectivity_check_async (priv->connectivity,
4370                                              connectivity_check_done,
4371                                              context);
4372         }
4373
4374         if (error)
4375                 g_dbus_method_invocation_take_error (context, error);
4376         nm_auth_chain_unref (chain);
4377 }
4378
4379 static void
4380 impl_manager_check_connectivity (NMManager *self,
4381                                  GDBusMethodInvocation *context)
4382 {
4383         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
4384         NMAuthChain *chain;
4385         GError *error = NULL;
4386
4387         /* Validate the request */
4388         chain = nm_auth_chain_new_context (context, check_connectivity_auth_done_cb, self);
4389         if (!chain) {
4390                 error = g_error_new_literal (NM_MANAGER_ERROR,
4391                                              NM_MANAGER_ERROR_PERMISSION_DENIED,
4392                                              "Unable to authenticate request.");
4393                 g_dbus_method_invocation_take_error (context, error);
4394                 return;
4395         }
4396
4397         priv->auth_chains = g_slist_append (priv->auth_chains, chain);
4398         nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE);
4399 }
4400
4401 static void
4402 start_factory (NMDeviceFactory *factory, gpointer user_data)
4403 {
4404         nm_device_factory_start (factory);
4405 }
4406
4407 gboolean
4408 nm_manager_start (NMManager *self, GError **error)
4409 {
4410         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
4411         GSList *iter, *connections;
4412         guint i;
4413
4414         if (!nm_settings_start (priv->settings, error))
4415                 return FALSE;
4416
4417         g_signal_connect (NM_PLATFORM_GET,
4418                           NM_PLATFORM_SIGNAL_LINK_CHANGED,
4419                           G_CALLBACK (platform_link_cb),
4420                           self);
4421
4422         /* Set initial radio enabled/disabled state */
4423         for (i = 0; i < RFKILL_TYPE_MAX; i++) {
4424                 RadioState *rstate = &priv->radio_states[i];
4425                 gboolean enabled;
4426
4427                 if (!rstate->desc)
4428                         continue;
4429
4430                 /* recheck kernel rfkill state */
4431                 update_rstate_from_rfkill (priv->rfkill_mgr, rstate);
4432
4433                 if (rstate->desc) {
4434                         _LOGI (LOGD_RFKILL, "%s %s by radio killswitch; %s by state file",
4435                                rstate->desc,
4436                                (rstate->hw_enabled && rstate->sw_enabled) ? "enabled" : "disabled",
4437                                rstate->user_enabled ? "enabled" : "disabled");
4438                 }
4439                 enabled = radio_enabled_for_rstate (rstate, TRUE);
4440                 manager_update_radio_enabled (self, rstate, enabled);
4441         }
4442
4443         /* Log overall networking status - enabled/disabled */
4444         _LOGI (LOGD_CORE, "Networking is %s by state file",
4445                priv->net_enabled ? "enabled" : "disabled");
4446
4447         system_unmanaged_devices_changed_cb (priv->settings, NULL, self);
4448         system_hostname_changed_cb (priv->settings, NULL, self);
4449
4450         /* Start device factories */
4451         nm_device_factory_manager_load_factories (_register_device_factory, self);
4452         nm_device_factory_manager_for_each_factory (start_factory, NULL);
4453
4454         platform_query_devices (self);
4455
4456         /* Load VPN plugins */
4457         priv->vpn_manager = g_object_ref (nm_vpn_manager_get ());
4458
4459         /* Connections added before the manager is started do not emit
4460          * connection-added signals thus devices have to be created manually.
4461          */
4462         _LOGD (LOGD_CORE, "creating virtual devices...");
4463         connections = nm_settings_get_connections (priv->settings);
4464         for (iter = connections; iter; iter = iter->next)
4465                 connection_changed (priv->settings, NM_CONNECTION (iter->data), self);
4466         g_slist_free (connections);
4467
4468         priv->devices_inited = TRUE;
4469
4470         check_if_startup_complete (self);
4471
4472         return TRUE;
4473 }
4474
4475 void
4476 nm_manager_stop (NMManager *self)
4477 {
4478         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
4479
4480         /* Remove all devices */
4481         while (priv->devices)
4482                 remove_device (self, NM_DEVICE (priv->devices->data), TRUE, TRUE);
4483
4484         _active_connection_cleanup (self);
4485 }
4486
4487 static gboolean
4488 handle_firmware_changed (gpointer user_data)
4489 {
4490         NMManager *self = NM_MANAGER (user_data);
4491         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
4492         GSList *iter;
4493
4494         priv->fw_changed_id = 0;
4495
4496         /* Try to re-enable devices with missing firmware */
4497         for (iter = priv->devices; iter; iter = iter->next) {
4498                 NMDevice *candidate = NM_DEVICE (iter->data);
4499                 NMDeviceState state = nm_device_get_state (candidate);
4500
4501                 if (   nm_device_get_firmware_missing (candidate)
4502                     && (state == NM_DEVICE_STATE_UNAVAILABLE)) {
4503                         _LOGI (LOGD_CORE, "(%s): firmware may now be available",
4504                                nm_device_get_iface (candidate));
4505
4506                         /* Re-set unavailable state to try bringing the device up again */
4507                         nm_device_state_changed (candidate,
4508                                                  NM_DEVICE_STATE_UNAVAILABLE,
4509                                                  NM_DEVICE_STATE_REASON_NONE);
4510                 }
4511         }
4512
4513         return FALSE;
4514 }
4515
4516 static void
4517 connectivity_changed (NMConnectivity *connectivity,
4518                       GParamSpec *pspec,
4519                       gpointer user_data)
4520 {
4521         NMManager *self = NM_MANAGER (user_data);
4522
4523         _LOGD (LOGD_CORE, "connectivity checking indicates %s",
4524                nm_connectivity_state_to_string (nm_connectivity_get_state (connectivity)));
4525
4526         nm_manager_update_state (self);
4527         g_object_notify (G_OBJECT (self), NM_MANAGER_CONNECTIVITY);
4528 }
4529
4530 static void
4531 firmware_dir_changed (GFileMonitor *monitor,
4532                       GFile *file,
4533                       GFile *other_file,
4534                       GFileMonitorEvent event_type,
4535                       gpointer user_data)
4536 {
4537         NMManager *self = NM_MANAGER (user_data);
4538         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
4539
4540         switch (event_type) {
4541         case G_FILE_MONITOR_EVENT_CREATED:
4542         case G_FILE_MONITOR_EVENT_CHANGED:
4543         case G_FILE_MONITOR_EVENT_MOVED:
4544         case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
4545         case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
4546                 if (!priv->fw_changed_id) {
4547                         priv->fw_changed_id = g_timeout_add_seconds (4, handle_firmware_changed, self);
4548                         _LOGI (LOGD_CORE, "kernel firmware directory '%s' changed",
4549                                KERNEL_FIRMWARE_DIR);
4550                 }
4551                 break;
4552         default:
4553                 break;
4554         }
4555 }
4556
4557 static void
4558 connection_metered_changed (GObject *object,
4559                             NMMetered metered,
4560                             gpointer user_data)
4561 {
4562         nm_manager_update_metered (NM_MANAGER (user_data));
4563 }
4564
4565 static void
4566 policy_default_device_changed (GObject *object, GParamSpec *pspec, gpointer user_data)
4567 {
4568         NMManager *self = NM_MANAGER (user_data);
4569         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
4570         NMDevice *best;
4571         NMActiveConnection *ac;
4572
4573         /* Note: this assumes that it's not possible for the IP4 default
4574          * route to be going over the default-ip6-device. If that changes,
4575          * we need something more complicated here.
4576          */
4577         best = nm_policy_get_default_ip4_device (priv->policy);
4578         if (!best)
4579                 best = nm_policy_get_default_ip6_device (priv->policy);
4580
4581         if (best)
4582                 ac = NM_ACTIVE_CONNECTION (nm_device_get_act_request (best));
4583         else
4584                 ac = NULL;
4585
4586         if (ac != priv->primary_connection) {
4587                 if (priv->primary_connection) {
4588                         g_signal_handlers_disconnect_by_func (priv->primary_connection,
4589                                                               G_CALLBACK (connection_metered_changed),
4590                                                               self);
4591                         g_clear_object (&priv->primary_connection);
4592                 }
4593
4594                 priv->primary_connection = ac ? g_object_ref (ac) : NULL;
4595
4596                 if (priv->primary_connection) {
4597                         g_signal_connect (priv->primary_connection, NM_ACTIVE_CONNECTION_DEVICE_METERED_CHANGED,
4598                                           G_CALLBACK (connection_metered_changed), self);
4599                 }
4600                 _LOGD (LOGD_CORE, "PrimaryConnection now %s", ac ? nm_active_connection_get_settings_connection_id (ac) : "(none)");
4601                 g_object_notify (G_OBJECT (self), NM_MANAGER_PRIMARY_CONNECTION);
4602                 g_object_notify (G_OBJECT (self), NM_MANAGER_PRIMARY_CONNECTION_TYPE);
4603                 nm_manager_update_metered (self);
4604         }
4605 }
4606
4607 static void
4608 policy_activating_device_changed (GObject *object, GParamSpec *pspec, gpointer user_data)
4609 {
4610         NMManager *self = NM_MANAGER (user_data);
4611         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
4612         NMDevice *activating, *best;
4613         NMActiveConnection *ac;
4614
4615         /* We only look at activating-ip6-device if activating-ip4-device
4616          * AND default-ip4-device are NULL; if default-ip4-device is
4617          * non-NULL, then activating-ip6-device is irrelevant, since while
4618          * that device might become the new default-ip6-device, it can't
4619          * become primary-connection while default-ip4-device is set to
4620          * something else.
4621          */
4622         activating = nm_policy_get_activating_ip4_device (priv->policy);
4623         best = nm_policy_get_default_ip4_device (priv->policy);
4624         if (!activating && !best)
4625                 activating = nm_policy_get_activating_ip6_device (priv->policy);
4626
4627         if (activating)
4628                 ac = NM_ACTIVE_CONNECTION (nm_device_get_act_request (activating));
4629         else
4630                 ac = NULL;
4631
4632         if (ac != priv->activating_connection) {
4633                 g_clear_object (&priv->activating_connection);
4634                 priv->activating_connection = ac ? g_object_ref (ac) : NULL;
4635                 _LOGD (LOGD_CORE, "ActivatingConnection now %s", ac ? nm_active_connection_get_settings_connection_id (ac) : "(none)");
4636                 g_object_notify (G_OBJECT (self), NM_MANAGER_ACTIVATING_CONNECTION);
4637         }
4638 }
4639
4640 #define NM_PERM_DENIED_ERROR "org.freedesktop.NetworkManager.PermissionDenied"
4641
4642 typedef struct {
4643         NMManager *self;
4644         GDBusConnection *connection;
4645         GDBusMessage *message;
4646         NMAuthSubject *subject;
4647         const char *permission;
4648         const char *audit_op;
4649         char *audit_prop_value;
4650         GType interface_type;
4651         const char *glib_propname;
4652 } PropertyFilterData;
4653
4654 static void
4655 free_property_filter_data (PropertyFilterData *pfd)
4656 {
4657         g_object_unref (pfd->self);
4658         g_object_unref (pfd->connection);
4659         g_object_unref (pfd->message);
4660         g_clear_object (&pfd->subject);
4661         g_free (pfd->audit_prop_value);
4662         g_slice_free (PropertyFilterData, pfd);
4663 }
4664
4665 static void
4666 prop_set_auth_done_cb (NMAuthChain *chain,
4667                        GError *error,
4668                        GDBusMethodInvocation *context, /* NULL */
4669                        gpointer user_data)
4670 {
4671         PropertyFilterData *pfd = user_data;
4672         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (pfd->self);
4673         NMAuthCallResult result;
4674         GDBusMessage *reply = NULL;
4675         const char *error_message;
4676         gs_unref_object NMExportedObject *object = NULL;
4677         const NMGlobalDnsConfig *global_dns;
4678         gs_unref_variant GVariant *value = NULL;
4679         GVariant *args;
4680
4681         priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
4682         result = nm_auth_chain_get_result (chain, pfd->permission);
4683         if (error || (result != NM_AUTH_CALL_RESULT_YES)) {
4684                 reply = g_dbus_message_new_method_error (pfd->message,
4685                                                          NM_PERM_DENIED_ERROR,
4686                                                          (error_message = "Not authorized to perform this operation"));
4687                 if (error)
4688                         error_message = error->message;
4689                 goto done;
4690         }
4691
4692         object = NM_EXPORTED_OBJECT (nm_bus_manager_get_registered_object (priv->dbus_mgr,
4693                                                                            g_dbus_message_get_path (pfd->message)));
4694         if (!object) {
4695                 reply = g_dbus_message_new_method_error (pfd->message,
4696                                                          "org.freedesktop.DBus.Error.UnknownObject",
4697                                                          (error_message = "Object doesn't exist."));
4698                 goto done;
4699         }
4700
4701         /* do some extra type checking... */
4702         if (!nm_exported_object_get_interface_by_type (object, pfd->interface_type)) {
4703                 reply = g_dbus_message_new_method_error (pfd->message,
4704                                                          "org.freedesktop.DBus.Error.InvalidArgs",
4705                                                          (error_message = "Object is of unexpected type."));
4706                 goto done;
4707         }
4708
4709         args = g_dbus_message_get_body (pfd->message);
4710         g_variant_get (args, "(&s&sv)", NULL, NULL, &value);
4711         g_assert (pfd->glib_propname);
4712
4713         if (!strcmp (pfd->glib_propname, NM_MANAGER_GLOBAL_DNS_CONFIGURATION)) {
4714                 g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE ("a{sv}")));
4715                 global_dns = nm_config_data_get_global_dns_config (nm_config_get_data (priv->config));
4716
4717                 if (global_dns && !nm_global_dns_config_is_internal (global_dns)) {
4718                         reply = g_dbus_message_new_method_error (pfd->message,
4719                                                                  NM_PERM_DENIED_ERROR,
4720                                                                  (error_message = "Global DNS configuration already set via configuration file"));
4721                         goto done;
4722                 }
4723                 /* ... but set the property on the @object itself. It would be correct to set the property
4724                  * on the skeleton interface, but as it is now, the result is the same. */
4725                 g_object_set (object, pfd->glib_propname, value, NULL);
4726         } else {
4727                 g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN));
4728                 /* the same here */
4729                 g_object_set (object, pfd->glib_propname, g_variant_get_boolean (value), NULL);
4730         }
4731
4732         reply = g_dbus_message_new_method_reply (pfd->message);
4733         g_dbus_message_set_body (reply, g_variant_new_tuple (NULL, 0));
4734         error_message = NULL;
4735 done:
4736         nm_audit_log_control_op (pfd->audit_op, pfd->audit_prop_value, !error_message, pfd->subject, error_message);
4737
4738         g_dbus_connection_send_message (pfd->connection, reply,
4739                                         G_DBUS_SEND_MESSAGE_FLAGS_NONE,
4740                                         NULL, NULL);
4741         g_object_unref (reply);
4742         nm_auth_chain_unref (chain);
4743
4744         free_property_filter_data (pfd);
4745 }
4746
4747 static gboolean
4748 do_set_property_check (gpointer user_data)
4749 {
4750         PropertyFilterData *pfd = user_data;
4751         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (pfd->self);
4752         GDBusMessage *reply = NULL;
4753         NMAuthChain *chain;
4754         const char *error_message = NULL;
4755
4756         pfd->subject = nm_auth_subject_new_unix_process_from_message (pfd->connection, pfd->message);
4757         if (!pfd->subject) {
4758                 reply = g_dbus_message_new_method_error (pfd->message,
4759                                                          NM_PERM_DENIED_ERROR,
4760                                                          (error_message = "Could not determine request UID."));
4761                 goto out;
4762         }
4763
4764         /* Validate the user request */
4765         chain = nm_auth_chain_new_subject (pfd->subject, NULL, prop_set_auth_done_cb, pfd);
4766         if (!chain) {
4767                 reply = g_dbus_message_new_method_error (pfd->message,
4768                                                          NM_PERM_DENIED_ERROR,
4769                                                          (error_message = "Could not authenticate request."));
4770                 goto out;
4771         }
4772
4773         priv->auth_chains = g_slist_append (priv->auth_chains, chain);
4774         nm_auth_chain_add_call (chain, pfd->permission, TRUE);
4775
4776 out:
4777         if (reply) {
4778                 nm_audit_log_control_op (pfd->audit_op, pfd->audit_prop_value, FALSE, pfd->subject, error_message);
4779                 g_dbus_connection_send_message (pfd->connection, reply,
4780                                                 G_DBUS_SEND_MESSAGE_FLAGS_NONE,
4781                                                 NULL, NULL);
4782                 g_object_unref (reply);
4783                 free_property_filter_data (pfd);
4784         }
4785
4786         return FALSE;
4787 }
4788
4789 static GDBusMessage *
4790 prop_filter (GDBusConnection *connection,
4791              GDBusMessage *message,
4792              gboolean incoming,
4793              gpointer user_data)
4794 {
4795         gs_unref_object NMManager *self = NULL;
4796         GVariant *args;
4797         const char *propiface = NULL;
4798         const char *propname = NULL;
4799         const char *glib_propname = NULL, *permission = NULL;
4800         const char *audit_op = NULL;
4801         GType interface_type = G_TYPE_INVALID;
4802         PropertyFilterData *pfd;
4803         const GVariantType *expected_type = G_VARIANT_TYPE_BOOLEAN;
4804         gs_unref_variant GVariant *value = NULL;
4805
4806         self = g_weak_ref_get (user_data);
4807         if (!self)
4808                 return message;
4809
4810         /* The sole purpose of this function is to validate property accesses on the
4811          * NMManager object since gdbus doesn't give us this functionality.
4812          */
4813
4814         /* Only filter org.freedesktop.DBus.Properties.Set calls */
4815         if (   !incoming
4816             || g_dbus_message_get_message_type (message) != G_DBUS_MESSAGE_TYPE_METHOD_CALL
4817             || g_strcmp0 (g_dbus_message_get_interface (message), DBUS_INTERFACE_PROPERTIES) != 0
4818             || g_strcmp0 (g_dbus_message_get_member (message), "Set") != 0)
4819                 return message;
4820
4821         args = g_dbus_message_get_body (message);
4822         if (!g_variant_is_of_type (args, G_VARIANT_TYPE ("(ssv)")))
4823                 return message;
4824         g_variant_get (args, "(&s&sv)", &propiface, &propname, &value);
4825
4826         /* Only filter calls to filtered properties, on existing objects */
4827         if (!strcmp (propiface, NM_DBUS_INTERFACE)) {
4828                 if (!strcmp (propname, "WirelessEnabled")) {
4829                         glib_propname = NM_MANAGER_WIRELESS_ENABLED;
4830                         permission = NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI;
4831                         audit_op = NM_AUDIT_OP_RADIO_CONTROL;
4832                 } else if (!strcmp (propname, "WwanEnabled")) {
4833                         glib_propname = NM_MANAGER_WWAN_ENABLED;
4834                         permission = NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN;
4835                         audit_op = NM_AUDIT_OP_RADIO_CONTROL;
4836                 } else if (!strcmp (propname, "WimaxEnabled")) {
4837                         glib_propname = NM_MANAGER_WIMAX_ENABLED;
4838                         permission = NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX;
4839                         audit_op = NM_AUDIT_OP_RADIO_CONTROL;
4840                 } else if (!strcmp (propname, "GlobalDnsConfiguration")) {
4841                         glib_propname = NM_MANAGER_GLOBAL_DNS_CONFIGURATION;
4842                         permission = NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS;
4843                         audit_op = NM_AUDIT_OP_NET_CONTROL;
4844                         expected_type = G_VARIANT_TYPE ("a{sv}");
4845                 } else
4846                         return message;
4847                 interface_type = NMDBUS_TYPE_MANAGER_SKELETON;
4848         } else if (!strcmp (propiface, NM_DBUS_INTERFACE_DEVICE)) {
4849                 if (!strcmp (propname, "Autoconnect")) {
4850                         glib_propname = NM_DEVICE_AUTOCONNECT;
4851                         permission = NM_AUTH_PERMISSION_NETWORK_CONTROL;
4852                         audit_op = NM_AUDIT_OP_DEVICE_AUTOCONNECT;
4853                 } else if (!strcmp (propname, "Managed")) {
4854                         glib_propname = NM_DEVICE_MANAGED;
4855                         permission = NM_AUTH_PERMISSION_NETWORK_CONTROL;
4856                         audit_op = NM_AUDIT_OP_DEVICE_MANAGED;
4857                 } else
4858                         return message;
4859                 interface_type = NMDBUS_TYPE_DEVICE_SKELETON;
4860         } else
4861                 return message;
4862
4863         if (!g_variant_is_of_type (value, expected_type))
4864                 return message;
4865
4866         /* This filter function is called from a gdbus worker thread which we can't
4867          * make other D-Bus calls from. In particular, we cannot call
4868          * org.freedesktop.DBus.GetConnectionUnixUser to find the remote UID.
4869          */
4870         pfd = g_slice_new0 (PropertyFilterData);
4871         pfd->self = self;
4872         self = NULL;
4873         pfd->connection = g_object_ref (connection);
4874         pfd->message = message;
4875         pfd->permission = permission;
4876         pfd->interface_type = interface_type;
4877         pfd->glib_propname = glib_propname;
4878         pfd->audit_op = audit_op;
4879         if (g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN)) {
4880                 pfd->audit_prop_value = g_strdup_printf ("%s:%d", pfd->glib_propname,
4881                                                          g_variant_get_boolean (value));
4882         } else
4883                 pfd->audit_prop_value = g_strdup (pfd->glib_propname);
4884
4885         g_idle_add (do_set_property_check, pfd);
4886
4887         return NULL;
4888 }
4889
4890 /******************************************************************************/
4891
4892 static int
4893 _set_prop_filter_free2 (gpointer user_data)
4894 {
4895         g_slice_free (GWeakRef, user_data);
4896         return G_SOURCE_REMOVE;
4897 }
4898
4899 static void
4900 _set_prop_filter_free (gpointer user_data)
4901 {
4902         g_weak_ref_clear (user_data);
4903
4904         /* Delay the final deletion of the user_data. There is a race when
4905          * calling g_dbus_connection_remove_filter() that the callback and user_data
4906          * might have been copied and being executed after the destroy function
4907          * runs (bgo #704568).
4908          * This doesn't really fix the race, but it should work well enough. */
4909         g_timeout_add_seconds (2, _set_prop_filter_free2, user_data);
4910 }
4911
4912 static void
4913 _set_prop_filter (NMManager *self, GDBusConnection *connection)
4914 {
4915         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
4916
4917         nm_assert ((!priv->prop_filter.connection) == (!priv->prop_filter.id));
4918
4919         if (priv->prop_filter.connection == connection)
4920                 return;
4921
4922         if (priv->prop_filter.connection) {
4923                 g_dbus_connection_remove_filter (priv->prop_filter.connection, priv->prop_filter.id);
4924                 priv->prop_filter.id = 0;
4925                 g_clear_object (&priv->prop_filter.connection);
4926         }
4927         if (connection) {
4928                 GWeakRef *wptr;
4929
4930                 wptr = g_slice_new (GWeakRef);
4931                 g_weak_ref_init  (wptr, self);
4932                 priv->prop_filter.id = g_dbus_connection_add_filter (connection, prop_filter, wptr, _set_prop_filter_free);
4933                 priv->prop_filter.connection = g_object_ref (connection);
4934         }
4935 }
4936
4937 /******************************************************************************/
4938
4939 static void
4940 authority_changed_cb (NMAuthManager *auth_manager, gpointer user_data)
4941 {
4942         /* Let clients know they should re-check their authorization */
4943         g_signal_emit (NM_MANAGER (user_data), signals[CHECK_PERMISSIONS], 0);
4944 }
4945
4946 #define KERN_RFKILL_OP_CHANGE_ALL 3
4947 #define KERN_RFKILL_TYPE_WLAN     1
4948 #define KERN_RFKILL_TYPE_WWAN     5
4949 struct rfkill_event {
4950         __u32 idx;
4951         __u8  type;
4952         __u8  op;
4953         __u8  soft, hard;
4954 } __attribute__((packed));
4955
4956 static void
4957 rfkill_change (const char *desc, RfKillType rtype, gboolean enabled)
4958 {
4959         int fd;
4960         struct rfkill_event event;
4961         ssize_t len;
4962
4963         g_return_if_fail (rtype == RFKILL_TYPE_WLAN || rtype == RFKILL_TYPE_WWAN);
4964
4965         errno = 0;
4966         fd = open ("/dev/rfkill", O_RDWR);
4967         if (fd < 0) {
4968                 if (errno == EACCES)
4969                         nm_log_warn (LOGD_RFKILL, "(%s): failed to open killswitch device", desc);
4970                 return;
4971         }
4972
4973         if (fcntl (fd, F_SETFL, O_NONBLOCK) < 0) {
4974                 nm_log_warn (LOGD_RFKILL, "(%s): failed to set killswitch device for "
4975                              "non-blocking operation", desc);
4976                 close (fd);
4977                 return;
4978         }
4979
4980         memset (&event, 0, sizeof (event));
4981         event.op = KERN_RFKILL_OP_CHANGE_ALL;
4982         switch (rtype) {
4983         case RFKILL_TYPE_WLAN:
4984                 event.type = KERN_RFKILL_TYPE_WLAN;
4985                 break;
4986         case RFKILL_TYPE_WWAN:
4987                 event.type = KERN_RFKILL_TYPE_WWAN;
4988                 break;
4989         default:
4990                 g_assert_not_reached ();
4991         }
4992         event.soft = enabled ? 0 : 1;
4993
4994         len = write (fd, &event, sizeof (event));
4995         if (len < 0) {
4996                 nm_log_warn (LOGD_RFKILL, "(%s): failed to change WiFi killswitch state: (%d) %s",
4997                              desc, errno, g_strerror (errno));
4998         } else if (len == sizeof (event)) {
4999                 nm_log_info (LOGD_RFKILL, "%s hardware radio set %s",
5000                              desc, enabled ? "enabled" : "disabled");
5001         } else {
5002                 /* Failed to write full structure */
5003                 nm_log_warn (LOGD_RFKILL, "(%s): failed to change WiFi killswitch state", desc);
5004         }
5005
5006         close (fd);
5007 }
5008
5009 static void
5010 manager_radio_user_toggled (NMManager *self,
5011                             RadioState *rstate,
5012                             gboolean enabled)
5013 {
5014         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
5015         GError *error = NULL;
5016         gboolean old_enabled, new_enabled;
5017
5018         /* Don't touch devices if asleep/networking disabled */
5019         if (manager_sleeping (self))
5020                 return;
5021
5022         if (rstate->desc) {
5023                 _LOGD (LOGD_RFKILL, "(%s): setting radio %s by user",
5024                        rstate->desc,
5025                        enabled ? "enabled" : "disabled");
5026         }
5027
5028         /* Update enabled key in state file */
5029         if (priv->state_file) {
5030                 if (!write_value_to_state_file (priv->state_file,
5031                                                 "main", rstate->key,
5032                                                 G_TYPE_BOOLEAN, (gpointer) &enabled,
5033                                                 &error)) {
5034                         _LOGW (LOGD_CORE, "writing to state file %s failed: %s",
5035                                priv->state_file,
5036                                error->message);
5037                         g_clear_error (&error);
5038                 }
5039         }
5040
5041         /* When the user toggles the radio, their request should override any
5042          * daemon (like ModemManager) enabled state that can be changed.  For WWAN
5043          * for example, we want the WwanEnabled property to reflect the daemon state
5044          * too so that users can toggle the modem powered, but we don't want that
5045          * daemon state to affect whether or not the user *can* turn it on, which is
5046          * what the kernel rfkill state does.  So we ignore daemon enabled state
5047          * when determining what the new state should be since it shouldn't block
5048          * the user's request.
5049          */
5050         old_enabled = radio_enabled_for_rstate (rstate, TRUE);
5051         rstate->user_enabled = enabled;
5052         new_enabled = radio_enabled_for_rstate (rstate, FALSE);
5053         if (new_enabled != old_enabled) {
5054                 /* Try to change the kernel rfkill state */
5055                 if (rstate->rtype == RFKILL_TYPE_WLAN || rstate->rtype == RFKILL_TYPE_WWAN)
5056                         rfkill_change (rstate->desc, rstate->rtype, new_enabled);
5057
5058                 manager_update_radio_enabled (self, rstate, new_enabled);
5059         }
5060 }
5061
5062 static gboolean
5063 periodic_update_active_connection_timestamps (gpointer user_data)
5064 {
5065         NMManager *manager = NM_MANAGER (user_data);
5066         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
5067         GSList *iter;
5068
5069         for (iter = priv->active_connections; iter; iter = g_slist_next (iter)) {
5070                 NMActiveConnection *ac = iter->data;
5071                 NMSettingsConnection *connection;
5072
5073                 if (nm_active_connection_get_state (ac) == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
5074                         connection = nm_active_connection_get_settings_connection (ac);
5075                         nm_settings_connection_update_timestamp (connection, (guint64) time (NULL), FALSE);
5076                 }
5077         }
5078
5079         return TRUE;
5080 }
5081
5082 static void
5083 dbus_connection_changed_cb (NMBusManager *dbus_mgr,
5084                             GDBusConnection *connection,
5085                             gpointer user_data)
5086 {
5087         _set_prop_filter (NM_MANAGER (user_data), connection);
5088 }
5089
5090 /**********************************************************************/
5091
5092 NM_DEFINE_SINGLETON_REGISTER (NMManager);
5093
5094 NMManager *
5095 nm_manager_get (void)
5096 {
5097         g_return_val_if_fail (singleton_instance, NULL);
5098         return singleton_instance;
5099 }
5100
5101 NMConnectionProvider *
5102 nm_connection_provider_get (void)
5103 {
5104         NMConnectionProvider *p;
5105
5106         g_return_val_if_fail (singleton_instance, NULL);
5107
5108         p = NM_CONNECTION_PROVIDER (NM_MANAGER_GET_PRIVATE (singleton_instance)->settings);
5109         g_return_val_if_fail (p, NULL);
5110         return p;
5111 }
5112
5113 NMManager *
5114 nm_manager_setup (const char *state_file,
5115                   gboolean initial_net_enabled,
5116                   gboolean initial_wifi_enabled,
5117                   gboolean initial_wwan_enabled)
5118 {
5119         NMManager *self;
5120
5121         g_return_val_if_fail (!singleton_instance, singleton_instance);
5122
5123         self = g_object_new (NM_TYPE_MANAGER,
5124                              NM_MANAGER_NETWORKING_ENABLED, initial_net_enabled,
5125                              NM_MANAGER_WIRELESS_ENABLED, initial_wifi_enabled,
5126                              NM_MANAGER_WWAN_ENABLED, initial_wwan_enabled,
5127                              NM_MANAGER_STATE_FILE, state_file,
5128                              NULL);
5129         nm_assert (NM_IS_MANAGER (self));
5130         singleton_instance = self;
5131
5132         nm_singleton_instance_register ();
5133         _LOGD (LOGD_CORE, "setup %s singleton (%p)", "NMManager", singleton_instance);
5134
5135         nm_exported_object_export ((NMExportedObject *) self);
5136
5137         return self;
5138 }
5139
5140 static void
5141 constructed (GObject *object)
5142 {
5143         NMManager *self = NM_MANAGER (object);
5144         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
5145         NMConfigData *config_data;
5146
5147         G_OBJECT_CLASS (nm_manager_parent_class)->constructed (object);
5148
5149         _set_prop_filter (self, nm_bus_manager_get_connection (priv->dbus_mgr));
5150
5151         priv->settings = nm_settings_new ();
5152         g_signal_connect (priv->settings, "notify::" NM_SETTINGS_STARTUP_COMPLETE,
5153                           G_CALLBACK (settings_startup_complete_changed), self);
5154         g_signal_connect (priv->settings, "notify::" NM_SETTINGS_UNMANAGED_SPECS,
5155                           G_CALLBACK (system_unmanaged_devices_changed_cb), self);
5156         g_signal_connect (priv->settings, "notify::" NM_SETTINGS_HOSTNAME,
5157                           G_CALLBACK (system_hostname_changed_cb), self);
5158         g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_ADDED,
5159                           G_CALLBACK (connection_changed), self);
5160         g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED_BY_USER,
5161                           G_CALLBACK (connection_changed), self);
5162         g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_REMOVED,
5163                           G_CALLBACK (connection_removed), self);
5164
5165         priv->policy = nm_policy_new (self, priv->settings);
5166         g_signal_connect (priv->policy, "notify::" NM_POLICY_DEFAULT_IP4_DEVICE,
5167                           G_CALLBACK (policy_default_device_changed), self);
5168         g_signal_connect (priv->policy, "notify::" NM_POLICY_DEFAULT_IP6_DEVICE,
5169                           G_CALLBACK (policy_default_device_changed), self);
5170         g_signal_connect (priv->policy, "notify::" NM_POLICY_ACTIVATING_IP4_DEVICE,
5171                           G_CALLBACK (policy_activating_device_changed), self);
5172         g_signal_connect (priv->policy, "notify::" NM_POLICY_ACTIVATING_IP6_DEVICE,
5173                           G_CALLBACK (policy_activating_device_changed), self);
5174
5175         priv->config = g_object_ref (nm_config_get ());
5176         g_signal_connect (G_OBJECT (priv->config),
5177                           NM_CONFIG_SIGNAL_CONFIG_CHANGED,
5178                           G_CALLBACK (_config_changed_cb),
5179                           self);
5180
5181         config_data = nm_config_get_data (priv->config);
5182         priv->connectivity = nm_connectivity_new (nm_config_data_get_connectivity_uri (config_data),
5183                                                   nm_config_data_get_connectivity_interval (config_data),
5184                                                   nm_config_data_get_connectivity_response (config_data));
5185         g_signal_connect (priv->connectivity, "notify::" NM_CONNECTIVITY_STATE,
5186                           G_CALLBACK (connectivity_changed), self);
5187
5188         priv->rfkill_mgr = nm_rfkill_manager_new ();
5189         g_signal_connect (priv->rfkill_mgr,
5190                           "rfkill-changed",
5191                           G_CALLBACK (rfkill_manager_rfkill_changed_cb),
5192                           self);
5193
5194         /* Force kernel WiFi/WWAN rfkill state to follow NM saved WiFi/WWAN state
5195          * in case the BIOS doesn't save rfkill state, and to be consistent with user
5196          * changes to the WirelessEnabled/WWANEnabled properties which toggle kernel
5197          * rfkill.
5198          */
5199         rfkill_change (priv->radio_states[RFKILL_TYPE_WLAN].desc, RFKILL_TYPE_WLAN, priv->radio_states[RFKILL_TYPE_WLAN].user_enabled);
5200         rfkill_change (priv->radio_states[RFKILL_TYPE_WWAN].desc, RFKILL_TYPE_WWAN, priv->radio_states[RFKILL_TYPE_WWAN].user_enabled);
5201 }
5202
5203 static void
5204 nm_manager_init (NMManager *self)
5205 {
5206         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
5207         guint i;
5208         GFile *file;
5209
5210         /* Initialize rfkill structures and states */
5211         memset (priv->radio_states, 0, sizeof (priv->radio_states));
5212
5213         priv->radio_states[RFKILL_TYPE_WLAN].user_enabled = TRUE;
5214         priv->radio_states[RFKILL_TYPE_WLAN].key = "WirelessEnabled";
5215         priv->radio_states[RFKILL_TYPE_WLAN].prop = NM_MANAGER_WIRELESS_ENABLED;
5216         priv->radio_states[RFKILL_TYPE_WLAN].hw_prop = NM_MANAGER_WIRELESS_HARDWARE_ENABLED;
5217         priv->radio_states[RFKILL_TYPE_WLAN].desc = "WiFi";
5218         priv->radio_states[RFKILL_TYPE_WLAN].rtype = RFKILL_TYPE_WLAN;
5219
5220         priv->radio_states[RFKILL_TYPE_WWAN].user_enabled = TRUE;
5221         priv->radio_states[RFKILL_TYPE_WWAN].key = "WWANEnabled";
5222         priv->radio_states[RFKILL_TYPE_WWAN].prop = NM_MANAGER_WWAN_ENABLED;
5223         priv->radio_states[RFKILL_TYPE_WWAN].hw_prop = NM_MANAGER_WWAN_HARDWARE_ENABLED;
5224         priv->radio_states[RFKILL_TYPE_WWAN].desc = "WWAN";
5225         priv->radio_states[RFKILL_TYPE_WWAN].rtype = RFKILL_TYPE_WWAN;
5226
5227         for (i = 0; i < RFKILL_TYPE_MAX; i++)
5228                 priv->radio_states[i].hw_enabled = TRUE;
5229
5230         priv->sleeping = FALSE;
5231         priv->state = NM_STATE_DISCONNECTED;
5232         priv->startup = TRUE;
5233
5234         priv->dbus_mgr = g_object_ref (nm_bus_manager_get ());
5235         g_signal_connect (priv->dbus_mgr,
5236                           NM_BUS_MANAGER_DBUS_CONNECTION_CHANGED,
5237                           G_CALLBACK (dbus_connection_changed_cb),
5238                           self);
5239
5240         /* sleep/wake handling */
5241         priv->sleep_monitor = g_object_ref (nm_sleep_monitor_get ());
5242         g_signal_connect (priv->sleep_monitor, NM_SLEEP_MONITOR_SLEEPING,
5243                           G_CALLBACK (sleeping_cb), self);
5244         g_signal_connect (priv->sleep_monitor, NM_SLEEP_MONITOR_RESUMING,
5245                           G_CALLBACK (resuming_cb), self);
5246
5247         /* Listen for authorization changes */
5248         g_signal_connect (nm_auth_manager_get (),
5249                           NM_AUTH_MANAGER_SIGNAL_CHANGED,
5250                           G_CALLBACK (authority_changed_cb),
5251                           self);
5252
5253
5254         /* Monitor the firmware directory */
5255         if (strlen (KERNEL_FIRMWARE_DIR)) {
5256                 file = g_file_new_for_path (KERNEL_FIRMWARE_DIR "/");
5257                 priv->fw_monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL);
5258                 g_object_unref (file);
5259         }
5260
5261         if (priv->fw_monitor) {
5262                 g_signal_connect (priv->fw_monitor, "changed",
5263                                   G_CALLBACK (firmware_dir_changed),
5264                                   self);
5265                 _LOGI (LOGD_CORE, "monitoring kernel firmware directory '%s'.",
5266                              KERNEL_FIRMWARE_DIR);
5267         } else {
5268                 _LOGW (LOGD_CORE, "failed to monitor kernel firmware directory '%s'.",
5269                        KERNEL_FIRMWARE_DIR);
5270         }
5271
5272         /* Update timestamps in active connections */
5273         priv->timestamp_update_id = g_timeout_add_seconds (300, (GSourceFunc) periodic_update_active_connection_timestamps, self);
5274
5275         priv->metered = NM_METERED_UNKNOWN;
5276 }
5277
5278 static gboolean
5279 device_is_real (GObject *device, gpointer user_data)
5280 {
5281         return nm_device_is_real (NM_DEVICE (device));
5282 }
5283
5284 static void
5285 get_property (GObject *object, guint prop_id,
5286               GValue *value, GParamSpec *pspec)
5287 {
5288         NMManager *self = NM_MANAGER (object);
5289         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
5290         NMConfigData *config_data;
5291         const NMGlobalDnsConfig *dns_config;
5292         const char *type;
5293
5294         switch (prop_id) {
5295         case PROP_VERSION:
5296                 g_value_set_string (value, VERSION);
5297                 break;
5298         case PROP_STATE:
5299                 nm_manager_update_state (self);
5300                 g_value_set_uint (value, priv->state);
5301                 break;
5302         case PROP_STARTUP:
5303                 g_value_set_boolean (value, priv->startup);
5304                 break;
5305         case PROP_NETWORKING_ENABLED:
5306                 g_value_set_boolean (value, priv->net_enabled);
5307                 break;
5308         case PROP_WIRELESS_ENABLED:
5309                 g_value_set_boolean (value, radio_enabled_for_type (self, RFKILL_TYPE_WLAN, TRUE));
5310                 break;
5311         case PROP_WIRELESS_HARDWARE_ENABLED:
5312                 g_value_set_boolean (value, priv->radio_states[RFKILL_TYPE_WLAN].hw_enabled);
5313                 break;
5314         case PROP_WWAN_ENABLED:
5315                 g_value_set_boolean (value, radio_enabled_for_type (self, RFKILL_TYPE_WWAN, TRUE));
5316                 break;
5317         case PROP_WWAN_HARDWARE_ENABLED:
5318                 g_value_set_boolean (value, priv->radio_states[RFKILL_TYPE_WWAN].hw_enabled);
5319                 break;
5320         case PROP_WIMAX_ENABLED:
5321                 g_value_set_boolean (value, FALSE);
5322                 break;
5323         case PROP_WIMAX_HARDWARE_ENABLED:
5324                 g_value_set_boolean (value, FALSE);
5325                 break;
5326         case PROP_ACTIVE_CONNECTIONS:
5327                 nm_utils_g_value_set_object_path_array (value, priv->active_connections, NULL, NULL);
5328                 break;
5329         case PROP_CONNECTIVITY:
5330                 g_value_set_uint (value, nm_connectivity_get_state (priv->connectivity));
5331                 break;
5332         case PROP_PRIMARY_CONNECTION:
5333                 nm_utils_g_value_set_object_path (value, priv->primary_connection);
5334                 break;
5335         case PROP_PRIMARY_CONNECTION_TYPE:
5336                 type = NULL;
5337                 if (priv->primary_connection) {
5338                         NMConnection *con;
5339
5340                         con = nm_active_connection_get_applied_connection (priv->primary_connection);
5341                         if (con)
5342                                 type = nm_connection_get_connection_type (con);
5343                 }
5344                 g_value_set_string (value, type ? type : "");
5345                 break;
5346         case PROP_ACTIVATING_CONNECTION:
5347                 nm_utils_g_value_set_object_path (value, priv->activating_connection);
5348                 break;
5349         case PROP_HOSTNAME:
5350                 g_value_set_string (value, priv->hostname);
5351                 break;
5352         case PROP_SLEEPING:
5353                 g_value_set_boolean (value, priv->sleeping);
5354                 break;
5355         case PROP_DEVICES:
5356                 nm_utils_g_value_set_object_path_array (value, priv->devices, device_is_real, NULL);
5357                 break;
5358         case PROP_METERED:
5359                 g_value_set_uint (value, priv->metered);
5360                 break;
5361         case PROP_GLOBAL_DNS_CONFIGURATION:
5362                 config_data = nm_config_get_data (priv->config);
5363                 dns_config = nm_config_data_get_global_dns_config (config_data);
5364                 nm_global_dns_config_to_dbus (dns_config, value);
5365                 break;
5366         case PROP_ALL_DEVICES:
5367                 nm_utils_g_value_set_object_path_array (value, priv->devices, NULL, NULL);
5368                 break;
5369         default:
5370                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
5371                 break;
5372         }
5373 }
5374
5375 static void
5376 set_property (GObject *object, guint prop_id,
5377               const GValue *value, GParamSpec *pspec)
5378 {
5379         NMManager *self = NM_MANAGER (object);
5380         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
5381         NMGlobalDnsConfig *dns_config;
5382         GError *error = NULL;
5383
5384         switch (prop_id) {
5385         case PROP_STATE_FILE:
5386                 /* construct-only */
5387                 priv->state_file = g_value_dup_string (value);
5388                 break;
5389         case PROP_NETWORKING_ENABLED:
5390                 /* construct-only */
5391                 priv->net_enabled = g_value_get_boolean (value);
5392                 break;
5393         case PROP_WIRELESS_ENABLED:
5394                 if (!priv->rfkill_mgr) {
5395                         /* called during object construction. */
5396                         priv->radio_states[RFKILL_TYPE_WLAN].user_enabled = g_value_get_boolean (value);
5397                 } else {
5398                         manager_radio_user_toggled (NM_MANAGER (object),
5399                                                     &priv->radio_states[RFKILL_TYPE_WLAN],
5400                                                     g_value_get_boolean (value));
5401                 }
5402                 break;
5403         case PROP_WWAN_ENABLED:
5404                 if (!priv->rfkill_mgr) {
5405                         /* called during object construction. */
5406                         priv->radio_states[RFKILL_TYPE_WWAN].user_enabled = g_value_get_boolean (value);
5407                 } else {
5408                         manager_radio_user_toggled (NM_MANAGER (object),
5409                                                     &priv->radio_states[RFKILL_TYPE_WWAN],
5410                                                     g_value_get_boolean (value));
5411                 }
5412                 break;
5413         case PROP_WIMAX_ENABLED:
5414                 /* WIMAX is depreacted. This does nothing. */
5415                 break;
5416         case PROP_GLOBAL_DNS_CONFIGURATION:
5417                 dns_config = nm_global_dns_config_from_dbus (value, &error);
5418                 if (!error)
5419                         nm_config_set_global_dns (priv->config, dns_config, &error);
5420
5421                 nm_global_dns_config_free (dns_config);
5422
5423                 if (error) {
5424                         _LOGD (LOGD_CORE, "set global DNS failed with error: %s", error->message);
5425                         g_error_free (error);
5426                 }
5427                 break;
5428         default:
5429                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
5430                 break;
5431         }
5432 }
5433
5434 static void
5435 _deinit_device_factory (NMDeviceFactory *factory, gpointer user_data)
5436 {
5437         g_signal_handlers_disconnect_matched (factory, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, NM_MANAGER (user_data));
5438 }
5439
5440 static void
5441 dispose (GObject *object)
5442 {
5443         NMManager *manager = NM_MANAGER (object);
5444         NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
5445
5446         g_slist_free_full (priv->auth_chains, (GDestroyNotify) nm_auth_chain_unref);
5447         priv->auth_chains = NULL;
5448
5449         g_signal_handlers_disconnect_by_func (nm_auth_manager_get (),
5450                                               G_CALLBACK (authority_changed_cb),
5451                                               manager);
5452
5453         g_assert (priv->devices == NULL);
5454
5455         nm_clear_g_source (&priv->ac_cleanup_id);
5456
5457         while (priv->active_connections)
5458                 active_connection_remove (manager, NM_ACTIVE_CONNECTION (priv->active_connections->data));
5459         g_clear_pointer (&priv->active_connections, g_slist_free);
5460         g_clear_object (&priv->primary_connection);
5461         g_clear_object (&priv->activating_connection);
5462
5463         if (priv->config) {
5464                 g_signal_handlers_disconnect_by_func (priv->config, _config_changed_cb, manager);
5465                 g_clear_object (&priv->config);
5466         }
5467         if (priv->connectivity) {
5468                 g_signal_handlers_disconnect_by_func (priv->connectivity, connectivity_changed, manager);
5469                 g_clear_object (&priv->connectivity);
5470         }
5471
5472         g_free (priv->hostname);
5473
5474         if (priv->policy) {
5475                 g_signal_handlers_disconnect_by_func (priv->policy, policy_default_device_changed, manager);
5476                 g_signal_handlers_disconnect_by_func (priv->policy, policy_activating_device_changed, manager);
5477                 g_clear_object (&priv->policy);
5478         }
5479
5480         if (priv->settings) {
5481                 g_signal_handlers_disconnect_by_func (priv->settings, settings_startup_complete_changed, manager);
5482                 g_signal_handlers_disconnect_by_func (priv->settings, system_unmanaged_devices_changed_cb, manager);
5483                 g_signal_handlers_disconnect_by_func (priv->settings, system_hostname_changed_cb, manager);
5484                 g_signal_handlers_disconnect_by_func (priv->settings, connection_changed, manager);
5485                 g_signal_handlers_disconnect_by_func (priv->settings, connection_removed, manager);
5486                 g_clear_object (&priv->settings);
5487         }
5488
5489         g_clear_pointer (&priv->state_file, g_free);
5490         g_clear_object (&priv->vpn_manager);
5491
5492         /* Unregister property filter */
5493         if (priv->dbus_mgr) {
5494                 g_signal_handlers_disconnect_by_func (priv->dbus_mgr, dbus_connection_changed_cb, manager);
5495                 g_clear_object (&priv->dbus_mgr);
5496         }
5497         _set_prop_filter (manager, NULL);
5498
5499         if (priv->sleep_monitor) {
5500                 g_signal_handlers_disconnect_by_func (priv->sleep_monitor, sleeping_cb, manager);
5501                 g_signal_handlers_disconnect_by_func (priv->sleep_monitor, resuming_cb, manager);
5502                 g_clear_object (&priv->sleep_monitor);
5503         }
5504
5505         if (priv->fw_monitor) {
5506                 g_signal_handlers_disconnect_by_func (priv->fw_monitor, firmware_dir_changed, manager);
5507
5508                 nm_clear_g_source (&priv->fw_changed_id);
5509
5510                 g_file_monitor_cancel (priv->fw_monitor);
5511                 g_clear_object (&priv->fw_monitor);
5512         }
5513
5514         if (priv->rfkill_mgr) {
5515                 g_signal_handlers_disconnect_by_func (priv->rfkill_mgr, rfkill_manager_rfkill_changed_cb, manager);
5516                 g_clear_object (&priv->rfkill_mgr);
5517         }
5518
5519         nm_device_factory_manager_for_each_factory (_deinit_device_factory, manager);
5520
5521         nm_clear_g_source (&priv->timestamp_update_id);
5522
5523         G_OBJECT_CLASS (nm_manager_parent_class)->dispose (object);
5524 }
5525
5526 static void
5527 nm_manager_class_init (NMManagerClass *manager_class)
5528 {
5529         GObjectClass *object_class = G_OBJECT_CLASS (manager_class);
5530         NMExportedObjectClass *exported_object_class = NM_EXPORTED_OBJECT_CLASS (manager_class);
5531
5532         g_type_class_add_private (manager_class, sizeof (NMManagerPrivate));
5533
5534         exported_object_class->export_path = NM_DBUS_PATH;
5535
5536         /* virtual methods */
5537         object_class->constructed = constructed;
5538         object_class->set_property = set_property;
5539         object_class->get_property = get_property;
5540         object_class->dispose = dispose;
5541
5542         /* properties */
5543         g_object_class_install_property
5544                 (object_class, PROP_VERSION,
5545                  g_param_spec_string (NM_MANAGER_VERSION, "", "",
5546                                       NULL,
5547                                       G_PARAM_READABLE |
5548                                       G_PARAM_STATIC_STRINGS));
5549
5550         g_object_class_install_property (object_class,
5551                                          PROP_STATE_FILE,
5552                                          g_param_spec_string (NM_MANAGER_STATE_FILE, "", "",
5553                                                               NULL,
5554                                                               G_PARAM_WRITABLE |
5555                                                               G_PARAM_CONSTRUCT_ONLY |
5556                                                               G_PARAM_STATIC_STRINGS));
5557
5558         g_object_class_install_property
5559                 (object_class, PROP_STATE,
5560                  g_param_spec_uint (NM_MANAGER_STATE, "", "",
5561                                     0, NM_STATE_DISCONNECTED, 0,
5562                                     G_PARAM_READABLE |
5563                                     G_PARAM_STATIC_STRINGS));
5564
5565         g_object_class_install_property
5566                 (object_class, PROP_STARTUP,
5567                  g_param_spec_boolean (NM_MANAGER_STARTUP, "", "",
5568                                        TRUE,
5569                                        G_PARAM_READABLE |
5570                                        G_PARAM_STATIC_STRINGS));
5571
5572         g_object_class_install_property
5573                 (object_class, PROP_NETWORKING_ENABLED,
5574                  g_param_spec_boolean (NM_MANAGER_NETWORKING_ENABLED, "", "",
5575                                        TRUE,
5576                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
5577                                        G_PARAM_STATIC_STRINGS));
5578
5579         g_object_class_install_property
5580                 (object_class, PROP_WIRELESS_ENABLED,
5581                  g_param_spec_boolean (NM_MANAGER_WIRELESS_ENABLED, "", "",
5582                                        TRUE,
5583                                        G_PARAM_READWRITE |
5584                                        G_PARAM_CONSTRUCT |
5585                                        G_PARAM_STATIC_STRINGS));
5586
5587         g_object_class_install_property
5588                 (object_class, PROP_WIRELESS_HARDWARE_ENABLED,
5589                  g_param_spec_boolean (NM_MANAGER_WIRELESS_HARDWARE_ENABLED, "", "",
5590                                        TRUE,
5591                                        G_PARAM_READABLE |
5592                                        G_PARAM_STATIC_STRINGS));
5593
5594         g_object_class_install_property
5595                 (object_class, PROP_WWAN_ENABLED,
5596                  g_param_spec_boolean (NM_MANAGER_WWAN_ENABLED, "", "",
5597                                        TRUE,
5598                                        G_PARAM_READWRITE |
5599                                        G_PARAM_CONSTRUCT |
5600                                        G_PARAM_STATIC_STRINGS));
5601
5602         g_object_class_install_property
5603                 (object_class, PROP_WWAN_HARDWARE_ENABLED,
5604                  g_param_spec_boolean (NM_MANAGER_WWAN_HARDWARE_ENABLED, "", "",
5605                                        TRUE,
5606                                        G_PARAM_READABLE |
5607                                        G_PARAM_STATIC_STRINGS));
5608
5609         g_object_class_install_property
5610                 (object_class, PROP_WIMAX_ENABLED,
5611                  g_param_spec_boolean (NM_MANAGER_WIMAX_ENABLED, "", "",
5612                                        TRUE,
5613                                        G_PARAM_READWRITE |
5614                                        G_PARAM_STATIC_STRINGS));
5615
5616         g_object_class_install_property
5617                 (object_class, PROP_WIMAX_HARDWARE_ENABLED,
5618                  g_param_spec_boolean (NM_MANAGER_WIMAX_HARDWARE_ENABLED, "", "",
5619                                        TRUE,
5620                                        G_PARAM_READABLE |
5621                                        G_PARAM_STATIC_STRINGS));
5622
5623         g_object_class_install_property
5624                 (object_class, PROP_ACTIVE_CONNECTIONS,
5625                  g_param_spec_boxed (NM_MANAGER_ACTIVE_CONNECTIONS, "", "",
5626                                      G_TYPE_STRV,
5627                                      G_PARAM_READABLE |
5628                                      G_PARAM_STATIC_STRINGS));
5629
5630         g_object_class_install_property
5631                 (object_class, PROP_CONNECTIVITY,
5632                  g_param_spec_uint (NM_MANAGER_CONNECTIVITY, "", "",
5633                                     NM_CONNECTIVITY_UNKNOWN, NM_CONNECTIVITY_FULL, NM_CONNECTIVITY_UNKNOWN,
5634                                     G_PARAM_READABLE |
5635                                     G_PARAM_STATIC_STRINGS));
5636
5637         g_object_class_install_property
5638                 (object_class, PROP_PRIMARY_CONNECTION,
5639                  g_param_spec_string (NM_MANAGER_PRIMARY_CONNECTION, "", "",
5640                                       NULL,
5641                                       G_PARAM_READABLE |
5642                                       G_PARAM_STATIC_STRINGS));
5643
5644         g_object_class_install_property
5645                 (object_class, PROP_PRIMARY_CONNECTION_TYPE,
5646                  g_param_spec_string (NM_MANAGER_PRIMARY_CONNECTION_TYPE, "", "",
5647                                       NULL,
5648                                       G_PARAM_READABLE |
5649                                       G_PARAM_STATIC_STRINGS));
5650
5651
5652         g_object_class_install_property
5653                 (object_class, PROP_ACTIVATING_CONNECTION,
5654                  g_param_spec_string (NM_MANAGER_ACTIVATING_CONNECTION, "", "",
5655                                       NULL,
5656                                       G_PARAM_READABLE |
5657                                       G_PARAM_STATIC_STRINGS));
5658
5659         /* Hostname is not exported over D-Bus */
5660         g_object_class_install_property
5661                 (object_class, PROP_HOSTNAME,
5662                  g_param_spec_string (NM_MANAGER_HOSTNAME, "", "",
5663                                       NULL,
5664                                       G_PARAM_READABLE |
5665                                       G_PARAM_STATIC_STRINGS));
5666
5667         /* Sleeping is not exported over D-Bus */
5668         g_object_class_install_property
5669                 (object_class, PROP_SLEEPING,
5670                  g_param_spec_boolean (NM_MANAGER_SLEEPING, "", "",
5671                                        FALSE,
5672                                        G_PARAM_READABLE |
5673                                        G_PARAM_STATIC_STRINGS));
5674
5675         g_object_class_install_property
5676                 (object_class, PROP_DEVICES,
5677                  g_param_spec_boxed (NM_MANAGER_DEVICES, "", "",
5678                                      G_TYPE_STRV,
5679                                      G_PARAM_READABLE |
5680                                      G_PARAM_STATIC_STRINGS));
5681
5682         /**
5683          * NMManager:metered:
5684          *
5685          * Whether the connectivity is metered.
5686          *
5687          * Since: 1.2
5688          **/
5689         g_object_class_install_property
5690                 (object_class, PROP_METERED,
5691                  g_param_spec_uint (NM_MANAGER_METERED, "", "",
5692                                     0, G_MAXUINT32, NM_METERED_UNKNOWN,
5693                                     G_PARAM_READABLE |
5694                                     G_PARAM_STATIC_STRINGS));
5695
5696         /**
5697          * NMManager:global-dns-configuration:
5698          *
5699          * The global DNS configuration.
5700          *
5701          * Since: 1.2
5702          **/
5703         g_object_class_install_property
5704                 (object_class, PROP_GLOBAL_DNS_CONFIGURATION,
5705                  g_param_spec_variant (NM_MANAGER_GLOBAL_DNS_CONFIGURATION, "", "",
5706                                        G_VARIANT_TYPE ("a{sv}"),
5707                                        NULL,
5708                                        G_PARAM_READWRITE |
5709                                        G_PARAM_STATIC_STRINGS));
5710
5711         /**
5712          * NMManager:all-devices:
5713          *
5714          * All devices, including those that are not realized.
5715          *
5716          * Since: 1.2
5717          **/
5718         g_object_class_install_property
5719                 (object_class, PROP_ALL_DEVICES,
5720                  g_param_spec_boxed (NM_MANAGER_ALL_DEVICES, "", "",
5721                                      G_TYPE_STRV,
5722                                      G_PARAM_READABLE |
5723                                      G_PARAM_STATIC_STRINGS));
5724
5725         /* signals */
5726
5727         /* D-Bus exported; emitted only for realized devices */
5728         signals[DEVICE_ADDED] =
5729                 g_signal_new ("device-added",
5730                               G_OBJECT_CLASS_TYPE (object_class),
5731                               G_SIGNAL_RUN_FIRST,
5732                               G_STRUCT_OFFSET (NMManagerClass, device_added),
5733                               NULL, NULL, NULL,
5734                               G_TYPE_NONE, 1, NM_TYPE_DEVICE);
5735
5736         /* Emitted for both realized devices and placeholder devices */
5737         signals[INTERNAL_DEVICE_ADDED] =
5738                 g_signal_new ("internal-device-added",
5739                               G_OBJECT_CLASS_TYPE (object_class),
5740                               G_SIGNAL_RUN_FIRST, 0,
5741                               NULL, NULL, NULL,
5742                               G_TYPE_NONE, 1, G_TYPE_OBJECT);
5743
5744         /* D-Bus exported; emitted only for realized devices */
5745         signals[DEVICE_REMOVED] =
5746                 g_signal_new ("device-removed",
5747                               G_OBJECT_CLASS_TYPE (object_class),
5748                               G_SIGNAL_RUN_FIRST,
5749                               G_STRUCT_OFFSET (NMManagerClass, device_removed),
5750                               NULL, NULL, NULL,
5751                               G_TYPE_NONE, 1, NM_TYPE_DEVICE);
5752
5753         /* Emitted for both realized devices and placeholder devices */
5754         signals[INTERNAL_DEVICE_REMOVED] =
5755                 g_signal_new ("internal-device-removed",
5756                               G_OBJECT_CLASS_TYPE (object_class),
5757                               G_SIGNAL_RUN_FIRST, 0,
5758                               NULL, NULL, NULL,
5759                               G_TYPE_NONE, 1, G_TYPE_OBJECT);
5760
5761         signals[STATE_CHANGED] =
5762                 g_signal_new (NM_MANAGER_STATE_CHANGED,
5763                               G_OBJECT_CLASS_TYPE (object_class),
5764                               G_SIGNAL_RUN_FIRST,
5765                               G_STRUCT_OFFSET (NMManagerClass, state_changed),
5766                               NULL, NULL, NULL,
5767                               G_TYPE_NONE, 1, G_TYPE_UINT);
5768
5769         signals[CHECK_PERMISSIONS] =
5770                 g_signal_new ("check-permissions",
5771                               G_OBJECT_CLASS_TYPE (object_class),
5772                               G_SIGNAL_RUN_FIRST,
5773                               0, NULL, NULL, NULL,
5774                               G_TYPE_NONE, 0);
5775
5776         signals[USER_PERMISSIONS_CHANGED] =
5777                 g_signal_new ("user-permissions-changed",
5778                               G_OBJECT_CLASS_TYPE (object_class),
5779                               G_SIGNAL_RUN_FIRST,
5780                               0, NULL, NULL, NULL,
5781                               G_TYPE_NONE, 0);
5782
5783         signals[ACTIVE_CONNECTION_ADDED] =
5784                 g_signal_new (NM_MANAGER_ACTIVE_CONNECTION_ADDED,
5785                               G_OBJECT_CLASS_TYPE (object_class),
5786                               G_SIGNAL_RUN_FIRST,
5787                               0, NULL, NULL, NULL,
5788                               G_TYPE_NONE, 1, NM_TYPE_ACTIVE_CONNECTION);
5789
5790         signals[ACTIVE_CONNECTION_REMOVED] =
5791                 g_signal_new (NM_MANAGER_ACTIVE_CONNECTION_REMOVED,
5792                               G_OBJECT_CLASS_TYPE (object_class),
5793                               G_SIGNAL_RUN_FIRST,
5794                               0, NULL, NULL, NULL,
5795                               G_TYPE_NONE, 1, NM_TYPE_ACTIVE_CONNECTION);
5796
5797         signals[CONFIGURE_QUIT] =
5798                 g_signal_new (NM_MANAGER_CONFIGURE_QUIT,
5799                               G_OBJECT_CLASS_TYPE (object_class),
5800                               G_SIGNAL_RUN_FIRST,
5801                               0, NULL, NULL, NULL,
5802                               G_TYPE_NONE, 0);
5803
5804         nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (manager_class),
5805                                                 NMDBUS_TYPE_MANAGER_SKELETON,
5806                                                 "GetDevices", impl_manager_get_devices,
5807                                                 "GetAllDevices", impl_manager_get_all_devices,
5808                                                 "GetDeviceByIpIface", impl_manager_get_device_by_ip_iface,
5809                                                 "ActivateConnection", impl_manager_activate_connection,
5810                                                 "AddAndActivateConnection", impl_manager_add_and_activate_connection,
5811                                                 "DeactivateConnection", impl_manager_deactivate_connection,
5812                                                 "Sleep", impl_manager_sleep,
5813                                                 "Enable", impl_manager_enable,
5814                                                 "GetPermissions", impl_manager_get_permissions,
5815                                                 "SetLogging", impl_manager_set_logging,
5816                                                 "GetLogging", impl_manager_get_logging,
5817                                                 "CheckConnectivity", impl_manager_check_connectivity,
5818                                                 "state", impl_manager_get_state,
5819                                                 NULL);
5820 }
5821