active-connection: add parent active connection tracking
[NetworkManager.git] / src / nm-active-connection.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) 2008 - 2014 Red Hat, Inc.
19  */
20
21 #include "nm-default.h"
22
23 #include "nm-active-connection.h"
24 #include "nm-dbus-interface.h"
25 #include "nm-device.h"
26 #include "nm-settings-connection.h"
27 #include "nm-simple-connection.h"
28 #include "nm-auth-utils.h"
29 #include "nm-auth-subject.h"
30 #include "NetworkManagerUtils.h"
31 #include "nm-core-internal.h"
32
33 #include "nmdbus-active-connection.h"
34
35 /* Base class for anything implementing the Connection.Active D-Bus interface */
36 G_DEFINE_ABSTRACT_TYPE (NMActiveConnection, nm_active_connection, NM_TYPE_EXPORTED_OBJECT)
37
38 #define NM_ACTIVE_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
39                                              NM_TYPE_ACTIVE_CONNECTION, \
40                                              NMActiveConnectionPrivate))
41
42 typedef struct {
43         NMSettingsConnection *settings_connection;
44         NMConnection *applied_connection;
45         char *specific_object;
46         NMDevice *device;
47
48         guint64 version_id;
49
50         char *pending_activation_id;
51
52         gboolean is_default;
53         gboolean is_default6;
54         NMActiveConnectionState state;
55         gboolean state_set;
56         gboolean vpn;
57
58         NMAuthSubject *subject;
59         NMActiveConnection *master;
60         gboolean master_ready;
61
62         NMActiveConnection *parent;
63
64         gboolean assumed;
65
66         NMAuthChain *chain;
67         const char *wifi_shared_permission;
68         NMActiveConnectionAuthResultFunc result_func;
69         gpointer user_data1;
70         gpointer user_data2;
71 } NMActiveConnectionPrivate;
72
73 enum {
74         PROP_0,
75         PROP_CONNECTION,
76         PROP_ID,
77         PROP_UUID,
78         PROP_TYPE,
79         PROP_SPECIFIC_OBJECT,
80         PROP_DEVICES,
81         PROP_STATE,
82         PROP_DEFAULT,
83         PROP_IP4_CONFIG,
84         PROP_DHCP4_CONFIG,
85         PROP_DEFAULT6,
86         PROP_IP6_CONFIG,
87         PROP_DHCP6_CONFIG,
88         PROP_VPN,
89         PROP_MASTER,
90
91         PROP_INT_SETTINGS_CONNECTION,
92         PROP_INT_DEVICE,
93         PROP_INT_SUBJECT,
94         PROP_INT_MASTER,
95         PROP_INT_MASTER_READY,
96
97         LAST_PROP
98 };
99
100 enum {
101         DEVICE_CHANGED,
102         DEVICE_METERED_CHANGED,
103         PARENT_ACTIVE,
104         LAST_SIGNAL
105 };
106 static guint signals[LAST_SIGNAL] = { 0 };
107
108 static void check_master_ready (NMActiveConnection *self);
109 static void _device_cleanup (NMActiveConnection *self);
110
111 /****************************************************************/
112
113 #define _NMLOG_DOMAIN         LOGD_DEVICE
114 #define _NMLOG_PREFIX_NAME    "active-connection"
115 #define _NMLOG(level, ...) \
116     G_STMT_START { \
117         char _sbuf[64]; \
118         \
119         nm_log ((level), _NMLOG_DOMAIN, \
120                 "%s%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \
121                 _NMLOG_PREFIX_NAME, \
122                 self ? nm_sprintf_buf (_sbuf, "[%p]", self) : "" \
123                 _NM_UTILS_MACRO_REST (__VA_ARGS__)); \
124     } G_STMT_END
125
126 /****************************************************************/
127
128 NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_state_to_string, NMActiveConnectionState,
129         NM_UTILS_LOOKUP_DEFAULT (NULL),
130         NM_UTILS_LOOKUP_STR_ITEM (NM_ACTIVE_CONNECTION_STATE_UNKNOWN,      "unknown"),
131         NM_UTILS_LOOKUP_STR_ITEM (NM_ACTIVE_CONNECTION_STATE_ACTIVATING,   "activating"),
132         NM_UTILS_LOOKUP_STR_ITEM (NM_ACTIVE_CONNECTION_STATE_ACTIVATED,    "activated"),
133         NM_UTILS_LOOKUP_STR_ITEM (NM_ACTIVE_CONNECTION_STATE_DEACTIVATING, "deactivating"),
134         NM_UTILS_LOOKUP_STR_ITEM (NM_ACTIVE_CONNECTION_STATE_DEACTIVATED,  "deactivated"),
135 );
136 #define state_to_string(state) NM_UTILS_LOOKUP_STR (_state_to_string, state)
137
138 /****************************************************************/
139
140 NMActiveConnectionState
141 nm_active_connection_get_state (NMActiveConnection *self)
142 {
143         return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->state;
144 }
145
146 void
147 nm_active_connection_set_state (NMActiveConnection *self,
148                                 NMActiveConnectionState new_state)
149 {
150         NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
151         NMActiveConnectionState old_state;
152
153         if (priv->state == new_state)
154                 return;
155
156         /* DEACTIVATED is a terminal state */
157         if (priv->state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED)
158                 g_return_if_fail (new_state != NM_ACTIVE_CONNECTION_STATE_DEACTIVATED);
159
160         _LOGD ("set state %s (was %s)",
161                state_to_string (new_state),
162                state_to_string (priv->state));
163
164         old_state = priv->state;
165         priv->state = new_state;
166         priv->state_set = TRUE;
167         g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_STATE);
168
169         check_master_ready (self);
170
171         if (   new_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED
172             || old_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
173                 nm_settings_connection_update_timestamp (priv->settings_connection,
174                                                          (guint64) time (NULL), TRUE);
175         }
176
177         if (priv->device) {
178                 if (   old_state < NM_ACTIVE_CONNECTION_STATE_ACTIVATED
179                     && new_state >= NM_ACTIVE_CONNECTION_STATE_ACTIVATED &&
180                     priv->pending_activation_id)
181                 {
182                         nm_device_remove_pending_action (priv->device, priv->pending_activation_id, TRUE);
183                         g_clear_pointer (&priv->pending_activation_id, g_free);
184                 }
185         }
186
187         if (   new_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED
188             || old_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
189                 g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_IP4_CONFIG);
190                 g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_DHCP4_CONFIG);
191                 g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_IP6_CONFIG);
192                 g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_DHCP6_CONFIG);
193         }
194
195         if (priv->state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) {
196                 /* Device is no longer relevant when deactivated. So remove it and
197                  * emit property change notification so clients re-read the value,
198                  * which will be NULL due to conditions in get_property().
199                  */
200                 _device_cleanup (self);
201                 g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_DEVICES);
202         }
203 }
204
205 const char *
206 nm_active_connection_get_settings_connection_id (NMActiveConnection *self)
207 {
208         NMSettingsConnection *con;
209
210         g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), NULL);
211
212         con = NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->settings_connection;
213         return con
214                ? nm_connection_get_id (NM_CONNECTION (con))
215                : NULL;
216 }
217
218 NMSettingsConnection *
219 _nm_active_connection_get_settings_connection (NMActiveConnection *self)
220 {
221         g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), NULL);
222
223         return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->settings_connection;
224 }
225
226 NMSettingsConnection *
227 nm_active_connection_get_settings_connection (NMActiveConnection *self)
228 {
229         NMSettingsConnection *con;
230
231         con = _nm_active_connection_get_settings_connection (self);
232
233         /* Only call this function on an active-connection that is already
234          * fully set-up (i.e. that has a settings-connection). Other uses
235          * indicate a bug. */
236         g_return_val_if_fail (con, NULL);
237         return con;
238 }
239
240 NMConnection *
241 nm_active_connection_get_applied_connection (NMActiveConnection *self)
242 {
243         NMConnection *con;
244
245         g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), NULL);
246
247         con = NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->applied_connection;
248
249         /* Only call this function on an active-connection that is already
250          * fully set-up (i.e. that has a settings-connection). Other uses
251          * indicate a bug. */
252         g_return_val_if_fail (con, NULL);
253         return con;
254 }
255
256 void
257 nm_active_connection_set_settings_connection (NMActiveConnection *self,
258                                               NMSettingsConnection *connection)
259 {
260         NMActiveConnectionPrivate *priv;
261
262         g_return_if_fail (NM_IS_ACTIVE_CONNECTION (self));
263
264         priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
265
266         g_return_if_fail (NM_IS_SETTINGS_CONNECTION (connection));
267         g_return_if_fail (!priv->settings_connection);
268         g_return_if_fail (!priv->applied_connection);
269
270         /* Can't change connection after the ActiveConnection is exported over D-Bus.
271          *
272          * Later, we want to change the settings-connection of an activated connection.
273          * When doing that, this changes the assumption that the settings-connection
274          * never changes (once it's set). That has effects for NMVpnConnection and
275          * NMActivationRequest.
276          * For example, we'd have to cancel all pending seret requests. */
277         g_return_if_fail (!nm_exported_object_is_exported (NM_EXPORTED_OBJECT (self)));
278
279         priv->settings_connection = g_object_ref (connection);
280         priv->applied_connection = nm_simple_connection_new_clone (NM_CONNECTION (priv->settings_connection));
281         nm_connection_clear_secrets (priv->applied_connection);
282 }
283
284 gboolean
285 nm_active_connection_has_unmodified_applied_connection (NMActiveConnection *self, NMSettingCompareFlags compare_flags)
286 {
287         NMActiveConnectionPrivate *priv;
288
289         g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), FALSE);
290
291         priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
292
293         g_return_val_if_fail (priv->settings_connection, FALSE);
294
295         return nm_settings_connection_has_unmodified_applied_connection (priv->settings_connection,
296                                                                          priv->applied_connection,
297                                                                          compare_flags);
298 }
299
300 /*******************************************************************/
301
302 void
303 nm_active_connection_clear_secrets (NMActiveConnection *self)
304 {
305         NMActiveConnectionPrivate *priv;
306
307         g_return_if_fail (NM_IS_ACTIVE_CONNECTION (self));
308
309         priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
310
311         if (nm_settings_connection_has_unmodified_applied_connection (priv->settings_connection,
312                                                                       priv->applied_connection,
313                                                                       NM_SETTING_COMPARE_FLAG_NONE))
314                 nm_connection_clear_secrets ((NMConnection *) priv->settings_connection);
315         nm_connection_clear_secrets (priv->applied_connection);
316 }
317
318 /*******************************************************************/
319
320 const char *
321 nm_active_connection_get_specific_object (NMActiveConnection *self)
322 {
323         return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->specific_object;
324 }
325
326 void
327 nm_active_connection_set_specific_object (NMActiveConnection *self,
328                                           const char *specific_object)
329 {
330         NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
331
332         /* Nothing that calls this function should be using paths from D-Bus,
333          * where NM uses "/" to mean NULL.
334          */
335         g_assert (g_strcmp0 (specific_object, "/") != 0);
336
337         if (g_strcmp0 (priv->specific_object, specific_object) == 0)
338                 return;
339
340         g_free (priv->specific_object);
341         priv->specific_object = g_strdup (specific_object);
342         g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT);
343 }
344
345 void
346 nm_active_connection_set_default (NMActiveConnection *self, gboolean is_default)
347 {
348         NMActiveConnectionPrivate *priv;
349
350         g_return_if_fail (NM_IS_ACTIVE_CONNECTION (self));
351
352         is_default = !!is_default;
353
354         priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
355         if (priv->is_default == is_default)
356                 return;
357
358         priv->is_default = is_default;
359         g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_DEFAULT);
360 }
361
362 gboolean
363 nm_active_connection_get_default (NMActiveConnection *self)
364 {
365         g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), FALSE);
366
367         return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->is_default;
368 }
369
370 void
371 nm_active_connection_set_default6 (NMActiveConnection *self, gboolean is_default6)
372 {
373         NMActiveConnectionPrivate *priv;
374
375         g_return_if_fail (NM_IS_ACTIVE_CONNECTION (self));
376
377         is_default6 = !!is_default6;
378
379         priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
380         if (priv->is_default6 == is_default6)
381                 return;
382
383         priv->is_default6 = is_default6;
384         g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_DEFAULT6);
385 }
386
387 gboolean
388 nm_active_connection_get_default6 (NMActiveConnection *self)
389 {
390         g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), FALSE);
391
392         return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->is_default6;
393 }
394
395 NMAuthSubject *
396 nm_active_connection_get_subject (NMActiveConnection *self)
397 {
398         g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), NULL);
399
400         return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->subject;
401 }
402
403 gboolean
404 nm_active_connection_get_user_requested (NMActiveConnection *self)
405 {
406         g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), FALSE);
407
408         return nm_auth_subject_is_unix_process (NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->subject);
409 }
410
411 NMDevice *
412 nm_active_connection_get_device (NMActiveConnection *self)
413 {
414         g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), NULL);
415
416         return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->device;
417 }
418
419 static void
420 device_state_changed (NMDevice *device,
421                       NMDeviceState new_state,
422                       NMDeviceState old_state,
423                       NMDeviceStateReason reason,
424                       gpointer user_data)
425 {
426         NMActiveConnection *self = NM_ACTIVE_CONNECTION (user_data);
427         NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
428
429         /* When already deactivated or before activation, device state changes are useless */
430         if (priv->state >= NM_ACTIVE_CONNECTION_STATE_DEACTIVATED)
431                 return;
432         if (old_state < NM_DEVICE_STATE_DISCONNECTED)
433                 return;
434
435         /* Let subclasses handle the state change */
436         if (NM_ACTIVE_CONNECTION_GET_CLASS (self)->device_state_changed)
437                 NM_ACTIVE_CONNECTION_GET_CLASS (self)->device_state_changed (self, device, new_state, old_state);
438 }
439
440 static void
441 device_master_changed (GObject *object,
442                        GParamSpec *pspec,
443                        gpointer user_data)
444 {
445         NMDevice *device = NM_DEVICE (object);
446         NMActiveConnection *self = NM_ACTIVE_CONNECTION (user_data);
447         NMActiveConnection *master;
448         NMActiveConnectionState master_state;
449
450         if (NM_ACTIVE_CONNECTION (nm_device_get_act_request (device)) != self)
451                 return;
452         if (!nm_device_get_master (device))
453                 return;
454         if (!nm_active_connection_get_master (self))
455                 return;
456         g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_master_changed), self);
457
458         master = nm_active_connection_get_master (self);
459         master_state = nm_active_connection_get_state (master);
460         if (master_state >= NM_ACTIVE_CONNECTION_STATE_DEACTIVATING) {
461                 /* Master failed before attaching the slave */
462                 if (NM_ACTIVE_CONNECTION_GET_CLASS (self)->master_failed)
463                         NM_ACTIVE_CONNECTION_GET_CLASS (self)->master_failed (self);
464         }
465 }
466
467 static void
468 device_metered_changed (GObject *object,
469                         GParamSpec *pspec,
470                         gpointer user_data)
471 {
472         NMActiveConnection *self = (NMActiveConnection *) user_data;
473         NMDevice *device = NM_DEVICE (object);
474
475         g_return_if_fail (NM_IS_ACTIVE_CONNECTION (self));
476         g_signal_emit (self, signals[DEVICE_METERED_CHANGED], 0, nm_device_get_metered (device));
477 }
478
479 gboolean
480 nm_active_connection_set_device (NMActiveConnection *self, NMDevice *device)
481 {
482         NMActiveConnectionPrivate *priv;
483         gs_unref_object NMDevice *old_device = NULL;
484
485         g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), FALSE);
486         g_return_val_if_fail (!device || NM_IS_DEVICE (device), FALSE);
487
488         priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
489         if (device == priv->device)
490                 return TRUE;
491
492         _LOGD ("set device %s%s%s [%p]",
493                NM_PRINT_FMT_QUOTED (device && nm_device_get_iface (device),
494                                     "\"",
495                                     nm_device_get_iface (device),
496                                     "\"",
497                                     device ? "(unknown)" : "(null)"),
498                device);
499
500         old_device = priv->device ? g_object_ref (priv->device) : NULL;
501         _device_cleanup (self);
502
503         if (device) {
504                 /* Device obviously can't be its own master */
505                 g_return_val_if_fail (!priv->master || device != nm_active_connection_get_device (priv->master), FALSE);
506
507                 priv->device = g_object_ref (device);
508
509                 g_signal_connect (device, NM_DEVICE_STATE_CHANGED,
510                                   G_CALLBACK (device_state_changed), self);
511                 g_signal_connect (device, "notify::master",
512                                   G_CALLBACK (device_master_changed), self);
513                 g_signal_connect (device, "notify::" NM_DEVICE_METERED,
514                                   G_CALLBACK (device_metered_changed), self);
515
516                 if (!priv->assumed) {
517                         priv->pending_activation_id = g_strdup_printf ("activation::%p", (void *)self);
518                         nm_device_add_pending_action (device, priv->pending_activation_id, TRUE);
519                 }
520         } else {
521                 /* The ActiveConnection's device can only be cleared after the
522                  * connection is activated.
523                  */
524                 g_warn_if_fail (priv->state > NM_ACTIVE_CONNECTION_STATE_UNKNOWN);
525                 priv->device = NULL;
526         }
527         g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_INT_DEVICE);
528
529         g_signal_emit (self, signals[DEVICE_CHANGED], 0, priv->device, old_device);
530
531         g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_DEVICES);
532
533         return TRUE;
534 }
535
536 NMActiveConnection *
537 nm_active_connection_get_master (NMActiveConnection *self)
538 {
539         g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), NULL);
540
541         return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->master;
542 }
543
544 /**
545  * nm_active_connection_get_master_ready:
546  * @self: the #NMActiveConnection
547  *
548  * Returns: %TRUE if the connection has a master connection, and that
549  * master connection is ready to accept slaves.  Otherwise %FALSE.
550  */
551 gboolean
552 nm_active_connection_get_master_ready (NMActiveConnection *self)
553 {
554         g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), FALSE);
555
556         return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->master_ready;
557 }
558
559 static void
560 check_master_ready (NMActiveConnection *self)
561 {
562         NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
563         gboolean signalling = FALSE;
564
565         /* ActiveConnetions don't enter the ACTIVATING state until they have a
566          * NMDevice in PREPARE or higher states, so the master active connection's
567          * device will be ready to accept slaves when the master is in ACTIVATING
568          * or higher states.
569          */
570         if (   !priv->master_ready
571             && priv->master
572             && priv->state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING
573             && NM_IN_SET (nm_active_connection_get_state (priv->master),
574                           NM_ACTIVE_CONNECTION_STATE_ACTIVATING,
575                           NM_ACTIVE_CONNECTION_STATE_ACTIVATED)) {
576                 signalling = TRUE;
577         }
578
579         _LOGD ("check-master-ready: %s (state %s, %s)",
580                signalling
581                    ? "signal"
582                    : (priv->master_ready ? "already signalled" : "not signalling"),
583                state_to_string (priv->state),
584                priv->master
585                    ? nm_sprintf_bufa (128, "master %p is in state %s",
586                                       priv->master,
587                                       state_to_string (nm_active_connection_get_state (priv->master)))
588                    : "no master");
589
590         if (signalling) {
591                 priv->master_ready = TRUE;
592                 g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_INT_MASTER_READY);
593
594                 /* Also notify clients to recheck the exported 'master' property to
595                  * ensure that if the master connection was created without a device
596                  * that we notify clients when the master device is known.
597                  */
598                 g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_MASTER);
599         }
600 }
601
602 static void
603 master_state_cb (NMActiveConnection *master,
604                  GParamSpec *pspec,
605                  gpointer user_data)
606 {
607         NMActiveConnection *self = NM_ACTIVE_CONNECTION (user_data);
608         NMActiveConnectionState master_state = nm_active_connection_get_state (master);
609         NMDevice *master_device = nm_active_connection_get_device (master);
610
611         check_master_ready (self);
612
613         if (   master_state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATING
614             && (!master_device || !nm_device_is_real (master_device))) {
615                 /* Master failed without ever creating or realizing its device */
616                 if (NM_ACTIVE_CONNECTION_GET_CLASS (self)->master_failed)
617                         NM_ACTIVE_CONNECTION_GET_CLASS (self)->master_failed (self);
618         }
619 }
620
621 /**
622  * nm_active_connection_set_master:
623  * @self: the #NMActiveConnection
624  * @master: if the activation depends on another device (ie, bond or bridge
625  * master to which this device will be enslaved) pass the #NMActiveConnection
626  * that this activation request is a child of
627  *
628  * Sets the master active connection of @self.
629  */
630 void
631 nm_active_connection_set_master (NMActiveConnection *self, NMActiveConnection *master)
632 {
633         NMActiveConnectionPrivate *priv;
634
635         g_return_if_fail (NM_IS_ACTIVE_CONNECTION (self));
636         g_return_if_fail (NM_IS_ACTIVE_CONNECTION (master));
637
638         priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
639
640         /* Master is write-once, and must be set before exporting the object */
641         g_return_if_fail (priv->master == NULL);
642         g_return_if_fail (!nm_exported_object_is_exported (NM_EXPORTED_OBJECT (self)));
643         if (priv->device) {
644                 /* Note, the master ActiveConnection may not yet have a device */
645                 g_return_if_fail (priv->device != nm_active_connection_get_device (master));
646         }
647
648         _LOGD ("set master %p, %s, state %s",
649                master,
650                nm_active_connection_get_settings_connection_id (master),
651                state_to_string (nm_active_connection_get_state (master)));
652
653         priv->master = g_object_ref (master);
654         g_signal_connect (priv->master,
655                           "notify::" NM_ACTIVE_CONNECTION_STATE,
656                           (GCallback) master_state_cb,
657                           self);
658
659         check_master_ready (self);
660 }
661
662 void
663 nm_active_connection_set_assumed (NMActiveConnection *self, gboolean assumed)
664 {
665         NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
666
667         g_return_if_fail (priv->assumed == FALSE);
668         priv->assumed = assumed;
669
670         if (priv->pending_activation_id) {
671                 nm_device_remove_pending_action (priv->device, priv->pending_activation_id, TRUE);
672                 g_clear_pointer (&priv->pending_activation_id, g_free);
673         }
674 }
675
676 gboolean
677 nm_active_connection_get_assumed (NMActiveConnection *self)
678 {
679         return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->assumed;
680 }
681
682 /****************************************************************/
683
684 static void unwatch_parent (NMActiveConnection *self);
685
686 static void
687 parent_destroyed (gpointer user_data, GObject *parent)
688 {
689         NMActiveConnection *self = user_data;
690
691         unwatch_parent (self);
692         g_signal_emit (self, signals[PARENT_ACTIVE], 0, NULL);
693 }
694
695 static void
696 parent_state_cb (NMActiveConnection *parent_ac,
697                  GParamSpec *pspec,
698                  gpointer user_data)
699 {
700         NMActiveConnection *self = user_data;
701         NMActiveConnectionState parent_state = nm_active_connection_get_state (parent_ac);
702
703         if (parent_state < NM_ACTIVE_CONNECTION_STATE_ACTIVATED)
704                 return;
705
706         unwatch_parent (self);
707         g_signal_emit (self, signals[PARENT_ACTIVE], 0, parent_ac);
708 }
709
710 static void
711 unwatch_parent (NMActiveConnection *self)
712 {
713         NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
714
715         g_signal_handlers_disconnect_by_func (priv->parent,
716                                               (GCallback) parent_state_cb,
717                                               self);
718         g_object_weak_unref ((GObject *) priv->parent, parent_destroyed, self);
719         priv->parent = NULL;
720 }
721
722 /**
723  * nm_active_connection_set_parent:
724  * @self: the #NMActiveConnection
725  * @parent: The #NMActiveConnection that must be active before the manager
726  * can proceed progressing the device to disconnected state for us.
727  *
728  * Sets the parent connection of @self. A "parent-active" signal will be
729  * emitted when the parent connection becomes active.
730  */
731 void
732 nm_active_connection_set_parent (NMActiveConnection *self, NMActiveConnection *parent)
733 {
734         NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
735
736         g_return_if_fail (priv->parent == NULL);
737         priv->parent = parent;
738         g_signal_connect (priv->parent,
739                           "notify::" NM_ACTIVE_CONNECTION_STATE,
740                           (GCallback) parent_state_cb,
741                           self);
742         g_object_weak_ref ((GObject *) priv->parent, parent_destroyed, self);
743 }
744
745 /****************************************************************/
746
747 static void
748 auth_done (NMAuthChain *chain,
749            GError *error,
750            GDBusMethodInvocation *unused,
751            gpointer user_data)
752 {
753         NMActiveConnection *self = NM_ACTIVE_CONNECTION (user_data);
754         NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
755         NMAuthCallResult result;
756
757         g_assert (priv->chain == chain);
758         g_assert (priv->result_func != NULL);
759
760         /* Must stay alive over the callback */
761         g_object_ref (self);
762
763         if (error) {
764                 priv->result_func (self, FALSE, error->message, priv->user_data1, priv->user_data2);
765                 goto done;
766         }
767
768         /* Caller has had a chance to obtain authorization, so we only need to
769          * check for 'yes' here.
770          */
771         result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL);
772         if (result != NM_AUTH_CALL_RESULT_YES) {
773                 priv->result_func (self,
774                                    FALSE,
775                                    "Not authorized to control networking.",
776                                    priv->user_data1,
777                                    priv->user_data2);
778                 goto done;
779         }
780
781         if (priv->wifi_shared_permission) {
782                 result = nm_auth_chain_get_result (chain, priv->wifi_shared_permission);
783                 if (result != NM_AUTH_CALL_RESULT_YES) {
784                         priv->result_func (self,
785                                            FALSE,
786                                            "Not authorized to share connections via wifi.",
787                                            priv->user_data1,
788                                            priv->user_data2);
789                         goto done;
790                 }
791         }
792
793         /* Otherwise authorized and available to activate */
794         priv->result_func (self, TRUE, NULL, priv->user_data1, priv->user_data2);
795
796 done:
797         nm_auth_chain_unref (chain);
798         priv->chain = NULL;
799         priv->result_func = NULL;
800         priv->user_data1 = NULL;
801         priv->user_data2 = NULL;
802
803         g_object_unref (self);
804 }
805
806 /**
807  * nm_active_connection_authorize:
808  * @self: the #NMActiveConnection
809  * @initial_connection: (allow-none): for add-and-activate, there
810  *   is no @settings_connection available when creating the active connection.
811  *   Instead pass an alternative connection.
812  * @result_func: function to be called on success or error
813  * @user_data1: pointer passed to @result_func
814  * @user_data2: additional pointer passed to @result_func
815  *
816  * Checks whether the subject that initiated the active connection (read from
817  * the #NMActiveConnection::subject property) is authorized to complete this
818  * activation request.
819  */
820 void
821 nm_active_connection_authorize (NMActiveConnection *self,
822                                 NMConnection *initial_connection,
823                                 NMActiveConnectionAuthResultFunc result_func,
824                                 gpointer user_data1,
825                                 gpointer user_data2)
826 {
827         NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
828         const char *wifi_permission = NULL;
829         NMConnection *con;
830
831         g_return_if_fail (result_func != NULL);
832         g_return_if_fail (priv->chain == NULL);
833
834         if (initial_connection) {
835                 g_return_if_fail (NM_IS_CONNECTION (initial_connection));
836                 g_return_if_fail (!priv->settings_connection);
837                 g_return_if_fail (!priv->applied_connection);
838                 con = initial_connection;
839         } else {
840                 g_return_if_fail (NM_IS_SETTINGS_CONNECTION (priv->settings_connection));
841                 g_return_if_fail (NM_IS_CONNECTION (priv->applied_connection));
842                 con = priv->applied_connection;
843         }
844
845         priv->chain = nm_auth_chain_new_subject (priv->subject, NULL, auth_done, self);
846         g_assert (priv->chain);
847
848         /* Check that the subject is allowed to use networking at all */
849         nm_auth_chain_add_call (priv->chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE);
850
851         /* Shared wifi connections require special permissions too */
852         wifi_permission = nm_utils_get_shared_wifi_permission (con);
853         if (wifi_permission) {
854                 priv->wifi_shared_permission = wifi_permission;
855                 nm_auth_chain_add_call (priv->chain, wifi_permission, TRUE);
856         }
857
858         /* Wait for authorization */
859         priv->result_func = result_func;
860         priv->user_data1 = user_data1;
861         priv->user_data2 = user_data2;
862 }
863
864 /****************************************************************/
865
866 static guint64
867 _version_id_new (void)
868 {
869         static guint64 id = 0;
870
871         return ++id;
872 }
873
874 guint64
875 nm_active_connection_version_id_get (NMActiveConnection *self)
876 {
877         g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), 0);
878
879         return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->version_id;
880 }
881
882 guint64
883 nm_active_connection_version_id_bump (NMActiveConnection *self)
884 {
885         NMActiveConnectionPrivate *priv;
886
887         g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), 0);
888
889         priv = NM_ACTIVE_CONNECTION_GET_PRIVATE  (self);
890         priv->version_id = _version_id_new ();
891         _LOGT ("new version-id %llu", (long long unsigned) priv->version_id);
892         return priv->version_id;
893 }
894
895 /****************************************************************/
896
897 static void
898 nm_active_connection_init (NMActiveConnection *self)
899 {
900         NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
901
902         _LOGT ("creating");
903
904         priv->version_id = _version_id_new ();
905 }
906
907 static void
908 constructed (GObject *object)
909 {
910         NMActiveConnection *self = (NMActiveConnection *) object;
911         NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
912
913         G_OBJECT_CLASS (nm_active_connection_parent_class)->constructed (object);
914
915         _LOGD ("constructed (%s, version-id %llu)", G_OBJECT_TYPE_NAME (self), (long long unsigned) priv->version_id);
916
917         g_return_if_fail (priv->subject);
918 }
919
920 static void
921 set_property (GObject *object, guint prop_id,
922               const GValue *value, GParamSpec *pspec)
923 {
924         NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object);
925         const char *tmp;
926         NMSettingsConnection *con;
927
928         switch (prop_id) {
929         case PROP_INT_SETTINGS_CONNECTION:
930                 /* construct-only */
931                 con = g_value_get_object (value);
932                 if (con) {
933                         priv->settings_connection = g_object_ref (con);
934                         priv->applied_connection = nm_simple_connection_new_clone (NM_CONNECTION (con));
935                         nm_connection_clear_secrets (priv->applied_connection);
936                 }
937                 break;
938         case PROP_INT_DEVICE:
939                 /* construct-only */
940                 nm_active_connection_set_device (NM_ACTIVE_CONNECTION (object), g_value_get_object (value));
941                 break;
942         case PROP_INT_SUBJECT:
943                 priv->subject = g_value_dup_object (value);
944                 break;
945         case PROP_INT_MASTER:
946                 nm_active_connection_set_master (NM_ACTIVE_CONNECTION (object), g_value_get_object (value));
947                 break;
948         case PROP_SPECIFIC_OBJECT:
949                 tmp = g_value_get_string (value);
950                 /* NM uses "/" to mean NULL */
951                 if (g_strcmp0 (tmp, "/") != 0)
952                         priv->specific_object = g_strdup (tmp);
953                 break;
954         case PROP_DEFAULT:
955                 priv->is_default = !!g_value_get_boolean (value);
956                 break;
957         case PROP_DEFAULT6:
958                 priv->is_default6 = !!g_value_get_boolean (value);
959                 break;
960         case PROP_VPN:
961                 priv->vpn = g_value_get_boolean (value);
962                 break;
963         case PROP_MASTER:
964                 break;
965         default:
966                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
967                 break;
968         }
969 }
970
971 static void
972 get_property (GObject *object, guint prop_id,
973               GValue *value, GParamSpec *pspec)
974 {
975         NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object);
976         GPtrArray *devices;
977         NMDevice *master_device = NULL;
978
979         switch (prop_id) {
980         case PROP_CONNECTION:
981                 g_value_set_string (value, nm_connection_get_path (NM_CONNECTION (priv->settings_connection)));
982                 break;
983         case PROP_ID:
984                 g_value_set_string (value, nm_connection_get_id (NM_CONNECTION (priv->settings_connection)));
985                 break;
986         case PROP_UUID:
987                 g_value_set_string (value, nm_connection_get_uuid (NM_CONNECTION (priv->settings_connection)));
988                 break;
989         case PROP_TYPE:
990                 g_value_set_string (value, nm_connection_get_connection_type (NM_CONNECTION (priv->settings_connection)));
991                 break;
992         case PROP_SPECIFIC_OBJECT:
993                 g_value_set_string (value, priv->specific_object ? priv->specific_object : "/");
994                 break;
995         case PROP_DEVICES:
996                 devices = g_ptr_array_sized_new (2);
997                 if (priv->device && priv->state < NM_ACTIVE_CONNECTION_STATE_DEACTIVATED)
998                         g_ptr_array_add (devices, g_strdup (nm_exported_object_get_path (NM_EXPORTED_OBJECT (priv->device))));
999                 g_ptr_array_add (devices, NULL);
1000                 g_value_take_boxed (value, (char **) g_ptr_array_free (devices, FALSE));
1001                 break;
1002         case PROP_STATE:
1003                 if (priv->state_set)
1004                         g_value_set_uint (value, priv->state);
1005                 else {
1006                         /* When the AC has just been created, its externally-visible state should
1007                          * be "ACTIVATING", even though internally it is "UNKNOWN".
1008                          */
1009                         g_value_set_uint (value, NM_ACTIVE_CONNECTION_STATE_ACTIVATING);
1010                 }
1011                 break;
1012         case PROP_DEFAULT:
1013                 g_value_set_boolean (value, priv->is_default);
1014                 break;
1015         case PROP_IP4_CONFIG:
1016                 /* The IP and DHCP config properties may be overridden by a subclass */
1017                 g_value_set_string (value, "/");
1018                 break;
1019         case PROP_DHCP4_CONFIG:
1020                 g_value_set_string (value, "/");
1021                 break;
1022         case PROP_DEFAULT6:
1023                 g_value_set_boolean (value, priv->is_default6);
1024                 break;
1025         case PROP_IP6_CONFIG:
1026                 g_value_set_string (value, "/");
1027                 break;
1028         case PROP_DHCP6_CONFIG:
1029                 g_value_set_string (value, "/");
1030                 break;
1031         case PROP_VPN:
1032                 g_value_set_boolean (value, priv->vpn);
1033                 break;
1034         case PROP_MASTER:
1035                 if (priv->master)
1036                         master_device = nm_active_connection_get_device (priv->master);
1037                 nm_utils_g_value_set_object_path (value, master_device);
1038                 break;
1039         case PROP_INT_SUBJECT:
1040                 g_value_set_object (value, priv->subject);
1041                 break;
1042         case PROP_INT_MASTER_READY:
1043                 g_value_set_boolean (value, priv->master_ready);
1044                 break;
1045         default:
1046                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1047                 break;
1048         }
1049 }
1050
1051 static void
1052 _device_cleanup (NMActiveConnection *self)
1053 {
1054         NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
1055
1056         if (priv->device) {
1057                 g_signal_handlers_disconnect_by_func (priv->device, G_CALLBACK (device_state_changed), self);
1058                 g_signal_handlers_disconnect_by_func (priv->device, G_CALLBACK (device_master_changed), self);
1059                 g_signal_handlers_disconnect_by_func (priv->device, G_CALLBACK (device_metered_changed), self);
1060         }
1061
1062         if (priv->pending_activation_id) {
1063                 nm_device_remove_pending_action (priv->device, priv->pending_activation_id, TRUE);
1064                 g_clear_pointer (&priv->pending_activation_id, g_free);
1065         }
1066
1067         g_clear_object (&priv->device);
1068 }
1069
1070 static void
1071 dispose (GObject *object)
1072 {
1073         NMActiveConnection *self = NM_ACTIVE_CONNECTION (object);
1074         NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
1075
1076         _LOGD ("disposing");
1077
1078         if (priv->chain) {
1079                 nm_auth_chain_unref (priv->chain);
1080                 priv->chain = NULL;
1081         }
1082
1083         g_free (priv->specific_object);
1084         priv->specific_object = NULL;
1085
1086         g_clear_object (&priv->settings_connection);
1087         g_clear_object (&priv->applied_connection);
1088
1089         _device_cleanup (self);
1090
1091         if (priv->master) {
1092                 g_signal_handlers_disconnect_by_func (priv->master,
1093                                                       (GCallback) master_state_cb,
1094                                                       self);
1095         }
1096         g_clear_object (&priv->master);
1097
1098         if (priv->parent)
1099                 unwatch_parent (self);
1100
1101         g_clear_object (&priv->subject);
1102
1103         G_OBJECT_CLASS (nm_active_connection_parent_class)->dispose (object);
1104 }
1105
1106 static void
1107 nm_active_connection_class_init (NMActiveConnectionClass *ac_class)
1108 {
1109         GObjectClass *object_class = G_OBJECT_CLASS (ac_class);
1110         NMExportedObjectClass *exported_object_class = NM_EXPORTED_OBJECT_CLASS (ac_class);
1111
1112         g_type_class_add_private (ac_class, sizeof (NMActiveConnectionPrivate));
1113
1114         exported_object_class->export_path = NM_DBUS_PATH "/ActiveConnection/%u";
1115
1116         /* virtual methods */
1117         object_class->get_property = get_property;
1118         object_class->set_property = set_property;
1119         object_class->constructed = constructed;
1120         object_class->dispose = dispose;
1121
1122         /* D-Bus exported properties */
1123         g_object_class_install_property
1124                 (object_class, PROP_CONNECTION,
1125                  g_param_spec_string (NM_ACTIVE_CONNECTION_CONNECTION, "", "",
1126                                       NULL,
1127                                       G_PARAM_READABLE |
1128                                       G_PARAM_STATIC_STRINGS));
1129
1130         g_object_class_install_property
1131                 (object_class, PROP_ID,
1132                  g_param_spec_string (NM_ACTIVE_CONNECTION_ID, "", "",
1133                                       NULL,
1134                                       G_PARAM_READABLE |
1135                                       G_PARAM_STATIC_STRINGS));
1136
1137         g_object_class_install_property
1138                 (object_class, PROP_UUID,
1139                  g_param_spec_string (NM_ACTIVE_CONNECTION_UUID, "", "",
1140                                       NULL,
1141                                       G_PARAM_READABLE |
1142                                       G_PARAM_STATIC_STRINGS));
1143
1144         g_object_class_install_property
1145                 (object_class, PROP_TYPE,
1146                  g_param_spec_string (NM_ACTIVE_CONNECTION_TYPE, "", "",
1147                                       NULL,
1148                                       G_PARAM_READABLE |
1149                                       G_PARAM_STATIC_STRINGS));
1150
1151         g_object_class_install_property
1152                 (object_class, PROP_SPECIFIC_OBJECT,
1153                  g_param_spec_string (NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT, "", "",
1154                                       NULL,
1155                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
1156                                       G_PARAM_STATIC_STRINGS));
1157
1158         g_object_class_install_property
1159                 (object_class, PROP_DEVICES,
1160                  g_param_spec_boxed (NM_ACTIVE_CONNECTION_DEVICES, "", "",
1161                                      G_TYPE_STRV,
1162                                      G_PARAM_READABLE |
1163                                      G_PARAM_STATIC_STRINGS));
1164
1165         g_object_class_install_property
1166                 (object_class, PROP_STATE,
1167                  g_param_spec_uint (NM_ACTIVE_CONNECTION_STATE, "", "",
1168                                     NM_ACTIVE_CONNECTION_STATE_UNKNOWN,
1169                                     NM_ACTIVE_CONNECTION_STATE_DEACTIVATING,
1170                                     NM_ACTIVE_CONNECTION_STATE_UNKNOWN,
1171                                     G_PARAM_READABLE |
1172                                     G_PARAM_STATIC_STRINGS));
1173
1174         g_object_class_install_property
1175                 (object_class, PROP_DEFAULT,
1176                  g_param_spec_boolean (NM_ACTIVE_CONNECTION_DEFAULT, "", "",
1177                                        FALSE,
1178                                        G_PARAM_READWRITE |
1179                                        G_PARAM_STATIC_STRINGS));
1180
1181         g_object_class_install_property
1182                 (object_class, PROP_IP4_CONFIG,
1183                  g_param_spec_string (NM_ACTIVE_CONNECTION_IP4_CONFIG, "", "",
1184                                       NULL,
1185                                       G_PARAM_READABLE |
1186                                       G_PARAM_STATIC_STRINGS));
1187
1188         g_object_class_install_property
1189                 (object_class, PROP_DHCP4_CONFIG,
1190                  g_param_spec_string (NM_ACTIVE_CONNECTION_DHCP4_CONFIG, "", "",
1191                                       NULL,
1192                                       G_PARAM_READABLE |
1193                                       G_PARAM_STATIC_STRINGS));
1194
1195         g_object_class_install_property
1196                 (object_class, PROP_DEFAULT6,
1197                  g_param_spec_boolean (NM_ACTIVE_CONNECTION_DEFAULT6, "", "",
1198                                        FALSE,
1199                                        G_PARAM_READWRITE |
1200                                        G_PARAM_STATIC_STRINGS));
1201
1202         g_object_class_install_property
1203                 (object_class, PROP_IP6_CONFIG,
1204                  g_param_spec_string (NM_ACTIVE_CONNECTION_IP6_CONFIG, "", "",
1205                                       NULL,
1206                                       G_PARAM_READABLE |
1207                                       G_PARAM_STATIC_STRINGS));
1208
1209         g_object_class_install_property
1210                 (object_class, PROP_DHCP6_CONFIG,
1211                  g_param_spec_string (NM_ACTIVE_CONNECTION_DHCP6_CONFIG, "", "",
1212                                       NULL,
1213                                       G_PARAM_READABLE |
1214                                       G_PARAM_STATIC_STRINGS));
1215
1216         g_object_class_install_property
1217                 (object_class, PROP_VPN,
1218                  g_param_spec_boolean (NM_ACTIVE_CONNECTION_VPN, "", "",
1219                                        FALSE,
1220                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
1221                                        G_PARAM_STATIC_STRINGS));
1222
1223         g_object_class_install_property
1224                 (object_class, PROP_MASTER,
1225                  g_param_spec_string (NM_ACTIVE_CONNECTION_MASTER, "", "",
1226                                       NULL,
1227                                       G_PARAM_READABLE |
1228                                       G_PARAM_STATIC_STRINGS));
1229
1230         /* Internal properties */
1231         g_object_class_install_property
1232                 (object_class, PROP_INT_SETTINGS_CONNECTION,
1233                  g_param_spec_object (NM_ACTIVE_CONNECTION_INT_SETTINGS_CONNECTION, "", "",
1234                                       NM_TYPE_SETTINGS_CONNECTION,
1235                                       G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
1236                                       G_PARAM_STATIC_STRINGS));
1237
1238         g_object_class_install_property
1239                 (object_class, PROP_INT_DEVICE,
1240                  g_param_spec_object (NM_ACTIVE_CONNECTION_INT_DEVICE, "", "",
1241                                       NM_TYPE_DEVICE,
1242                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
1243                                       G_PARAM_STATIC_STRINGS));
1244
1245         g_object_class_install_property
1246                 (object_class, PROP_INT_SUBJECT,
1247                  g_param_spec_object (NM_ACTIVE_CONNECTION_INT_SUBJECT, "", "",
1248                                       NM_TYPE_AUTH_SUBJECT,
1249                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
1250                                       G_PARAM_STATIC_STRINGS));
1251
1252         g_object_class_install_property
1253                 (object_class, PROP_INT_MASTER,
1254                  g_param_spec_object (NM_ACTIVE_CONNECTION_INT_MASTER, "", "",
1255                                       NM_TYPE_ACTIVE_CONNECTION,
1256                                       G_PARAM_READWRITE |
1257                                       G_PARAM_STATIC_STRINGS));
1258
1259         g_object_class_install_property
1260                 (object_class, PROP_INT_MASTER_READY,
1261                  g_param_spec_boolean (NM_ACTIVE_CONNECTION_INT_MASTER_READY, "", "",
1262                                        FALSE, G_PARAM_READABLE |
1263                                        G_PARAM_STATIC_STRINGS));
1264
1265         signals[DEVICE_CHANGED] =
1266                 g_signal_new (NM_ACTIVE_CONNECTION_DEVICE_CHANGED,
1267                               G_OBJECT_CLASS_TYPE (object_class),
1268                               G_SIGNAL_RUN_FIRST,
1269                               G_STRUCT_OFFSET (NMActiveConnectionClass, device_changed),
1270                               NULL, NULL, NULL,
1271                               G_TYPE_NONE, 2, NM_TYPE_DEVICE, NM_TYPE_DEVICE);
1272
1273         signals[DEVICE_METERED_CHANGED] =
1274                 g_signal_new (NM_ACTIVE_CONNECTION_DEVICE_METERED_CHANGED,
1275                               G_OBJECT_CLASS_TYPE (object_class),
1276                               G_SIGNAL_RUN_FIRST,
1277                               G_STRUCT_OFFSET (NMActiveConnectionClass, device_metered_changed),
1278                               NULL, NULL, NULL,
1279                               G_TYPE_NONE, 1, G_TYPE_UINT);
1280
1281         signals[PARENT_ACTIVE] =
1282                 g_signal_new (NM_ACTIVE_CONNECTION_PARENT_ACTIVE,
1283                               G_OBJECT_CLASS_TYPE (object_class),
1284                               G_SIGNAL_RUN_FIRST,
1285                               G_STRUCT_OFFSET (NMActiveConnectionClass, parent_active),
1286                               NULL, NULL, NULL,
1287                               G_TYPE_NONE, 1, NM_TYPE_ACTIVE_CONNECTION);
1288
1289         nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (ac_class),
1290                                                 NMDBUS_TYPE_ACTIVE_CONNECTION_SKELETON,
1291                                                 NULL);
1292 }
1293