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