diff options
| author | Michael Biebl <biebl@debian.org> | 2021-02-11 18:11:46 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2021-02-11 18:11:46 +0100 |
| commit | 80ec1decc49c72efec2a8b87c06245c92c0ab807 (patch) | |
| tree | e3b229aa94e8dcf0590f2317664176e7b8f7607b /src/nm-active-connection.c | |
| parent | 65f86e8f56267192d42f2b629fc6b0c99fb9cd0c (diff) | |
New upstream version 1.29.90 upstream/1.29.90
Diffstat (limited to 'src/nm-active-connection.c')
| -rw-r--r-- | src/nm-active-connection.c | 1848 |
1 files changed, 0 insertions, 1848 deletions
diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c deleted file mode 100644 index a8b8e2f3..00000000 --- a/src/nm-active-connection.c +++ /dev/null @@ -1,1848 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (C) 2008 - 2014 Red Hat, Inc. - */ - -#include "nm-default.h" - -#include "nm-active-connection.h" - -#include "nm-libnm-core-intern/nm-common-macros.h" -#include "nm-dbus-interface.h" -#include "devices/nm-device.h" -#include "settings/nm-settings-connection.h" -#include "nm-simple-connection.h" -#include "nm-auth-utils.h" -#include "nm-auth-manager.h" -#include "nm-libnm-core-intern/nm-auth-subject.h" -#include "nm-keep-alive.h" -#include "NetworkManagerUtils.h" -#include "nm-core-internal.h" - -#define AUTH_CALL_ID_SHARED_WIFI_PERMISSION_FAILED ((NMAuthManagerCallId *) GINT_TO_POINTER(1)) - -typedef struct _NMActiveConnectionPrivate { - NMDBusTrackObjPath settings_connection; - NMConnection * applied_connection; - char * specific_object; - NMDevice * device; - - guint64 version_id; - - char *pending_activation_id; - - NMActivationStateFlags state_flags; - - NMActiveConnectionState state; - bool is_default : 1; - bool is_default6 : 1; - bool state_set : 1; - bool vpn : 1; - bool master_ready : 1; - - NMActivationType activation_type : 3; - - /* capture the original reason why the connection was activated. - * For example with NM_ACTIVATION_REASON_ASSUME, the connection - * will later change to become fully managed. But the original - * reason never changes. */ - NMActivationReason activation_reason : 4; - - NMAuthSubject * subject; - NMActiveConnection *master; - - NMActiveConnection *parent; - - struct { - NMAuthManagerCallId *call_id_network_control; - NMAuthManagerCallId *call_id_wifi_shared_permission; - - NMActiveConnectionAuthResultFunc result_func; - gpointer user_data; - } auth; - - NMKeepAlive *keep_alive; -} NMActiveConnectionPrivate; - -NM_GOBJECT_PROPERTIES_DEFINE(NMActiveConnection, - PROP_CONNECTION, - PROP_ID, - PROP_UUID, - PROP_TYPE, - PROP_SPECIFIC_OBJECT, - PROP_DEVICES, - PROP_STATE, - PROP_STATE_FLAGS, - PROP_DEFAULT, - PROP_IP4_CONFIG, - PROP_DHCP4_CONFIG, - PROP_DEFAULT6, - PROP_IP6_CONFIG, - PROP_DHCP6_CONFIG, - PROP_VPN, - PROP_MASTER, - - PROP_INT_SETTINGS_CONNECTION, - PROP_INT_APPLIED_CONNECTION, - PROP_INT_DEVICE, - PROP_INT_SUBJECT, - PROP_INT_MASTER, - PROP_INT_MASTER_READY, - PROP_INT_ACTIVATION_TYPE, - PROP_INT_ACTIVATION_REASON, ); - -enum { DEVICE_CHANGED, DEVICE_METERED_CHANGED, PARENT_ACTIVE, STATE_CHANGED, LAST_SIGNAL }; -static guint signals[LAST_SIGNAL] = {0}; - -G_DEFINE_ABSTRACT_TYPE(NMActiveConnection, nm_active_connection, NM_TYPE_DBUS_OBJECT) - -#define NM_ACTIVE_CONNECTION_GET_PRIVATE(self) \ - _NM_GET_PRIVATE_PTR(self, NMActiveConnection, NM_IS_ACTIVE_CONNECTION) - -/*****************************************************************************/ - -static const NMDBusInterfaceInfoExtended interface_info_active_connection; -static const GDBusSignalInfo signal_info_state_changed; - -static void check_master_ready(NMActiveConnection *self); -static void _device_cleanup(NMActiveConnection *self); -static void _settings_connection_flags_changed(NMSettingsConnection *settings_connection, - NMActiveConnection * self); -static void _set_activation_type_managed(NMActiveConnection *self); - -static void auth_complete(NMActiveConnection *self, gboolean result, const char *message); - -/*****************************************************************************/ - -#define _NMLOG_DOMAIN LOGD_DEVICE -#define _NMLOG_PREFIX_NAME "active-connection" -#define _NMLOG(level, ...) \ - G_STMT_START \ - { \ - char _sbuf[64]; \ - NMActiveConnectionPrivate *_priv = self ? NM_ACTIVE_CONNECTION_GET_PRIVATE(self) : NULL; \ - \ - nm_log((level), \ - _NMLOG_DOMAIN, \ - (_priv && _priv->device) ? nm_device_get_iface(_priv->device) : NULL, \ - (_priv && _priv->applied_connection) \ - ? nm_connection_get_uuid(_priv->applied_connection) \ - : NULL, \ - "%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - _NMLOG_PREFIX_NAME, \ - self ? nm_sprintf_buf(_sbuf, "[%p]", self) : "" _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ - } \ - G_STMT_END - -/*****************************************************************************/ - -static NM_UTILS_LOOKUP_STR_DEFINE( - _state_to_string, - NMActiveConnectionState, - NM_UTILS_LOOKUP_DEFAULT(NULL), - NM_UTILS_LOOKUP_STR_ITEM(NM_ACTIVE_CONNECTION_STATE_UNKNOWN, "unknown"), - NM_UTILS_LOOKUP_STR_ITEM(NM_ACTIVE_CONNECTION_STATE_ACTIVATING, "activating"), - NM_UTILS_LOOKUP_STR_ITEM(NM_ACTIVE_CONNECTION_STATE_ACTIVATED, "activated"), - NM_UTILS_LOOKUP_STR_ITEM(NM_ACTIVE_CONNECTION_STATE_DEACTIVATING, "deactivating"), - NM_UTILS_LOOKUP_STR_ITEM(NM_ACTIVE_CONNECTION_STATE_DEACTIVATED, "deactivated"), ); - -#define state_to_string_a(state) NM_UTILS_LOOKUP_STR_A(_state_to_string, state) - -/* the maximum required buffer size for _state_flags_to_string(). */ -#define _NM_ACTIVATION_STATE_FLAG_TO_STRING_BUFSIZE (255) - -static NM_UTILS_FLAGS2STR_DEFINE( - _state_flags_to_string, - NMActivationStateFlags, - NM_UTILS_FLAGS2STR(NM_ACTIVATION_STATE_FLAG_NONE, "none"), - NM_UTILS_FLAGS2STR(NM_ACTIVATION_STATE_FLAG_IS_MASTER, "is-master"), - NM_UTILS_FLAGS2STR(NM_ACTIVATION_STATE_FLAG_IS_SLAVE, "is-slave"), - NM_UTILS_FLAGS2STR(NM_ACTIVATION_STATE_FLAG_LAYER2_READY, "layer2-ready"), - NM_UTILS_FLAGS2STR(NM_ACTIVATION_STATE_FLAG_IP4_READY, "ip4-ready"), - NM_UTILS_FLAGS2STR(NM_ACTIVATION_STATE_FLAG_IP6_READY, "ip6-ready"), - NM_UTILS_FLAGS2STR(NM_ACTIVATION_STATE_FLAG_MASTER_HAS_SLAVES, "master-has-slaves"), - NM_UTILS_FLAGS2STR(NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY, - "lifetime-bound-to-profile-visibility"), - NM_UTILS_FLAGS2STR(NM_ACTIVATION_STATE_FLAG_EXTERNAL, "external"), ); - -/*****************************************************************************/ - -static void -_settings_connection_updated(NMSettingsConnection *sett_conn, - guint update_reason_u, - gpointer user_data) -{ - NMActiveConnection *self = user_data; - - /* we don't know which properties actually changed. Just to be sure, - * notify about all possible properties. After all, an update of a - * connection is a rare event. */ - - _notify(self, PROP_ID); - - /* it's a bit odd to update the TYPE of an active connection. But the alternative - * is unexpected too. */ - _notify(self, PROP_TYPE); - - /* currently, the UUID and the exported CONNECTION path cannot change. Later, we might - * want to support a re-link operation, which associates an active-connection with a different - * settings-connection. */ -} - -static void -_set_settings_connection(NMActiveConnection *self, NMSettingsConnection *sett_conn) -{ - NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - - if (priv->settings_connection.obj == sett_conn) - return; - - if (priv->settings_connection.obj) { - g_signal_handlers_disconnect_by_func(priv->settings_connection.obj, - _settings_connection_updated, - self); - g_signal_handlers_disconnect_by_func(priv->settings_connection.obj, - _settings_connection_flags_changed, - self); - } - if (sett_conn) { - g_signal_connect(sett_conn, - NM_SETTINGS_CONNECTION_UPDATED_INTERNAL, - (GCallback) _settings_connection_updated, - self); - if (nm_active_connection_get_activation_type(self) == NM_ACTIVATION_TYPE_EXTERNAL) - g_signal_connect(sett_conn, - NM_SETTINGS_CONNECTION_FLAGS_CHANGED, - (GCallback) _settings_connection_flags_changed, - self); - } - - nm_dbus_track_obj_path_set(&priv->settings_connection, sett_conn, TRUE); -} - -NMActiveConnectionState -nm_active_connection_get_state(NMActiveConnection *self) -{ - return NM_ACTIVE_CONNECTION_GET_PRIVATE(self)->state; -} - -static void -emit_state_changed(NMActiveConnection *self, guint state, guint reason) -{ - nm_dbus_object_emit_signal(NM_DBUS_OBJECT(self), - &interface_info_active_connection, - &signal_info_state_changed, - "(uu)", - (guint32) state, - (guint32) reason); - g_signal_emit(self, signals[STATE_CHANGED], 0, state, reason); -} - -void -nm_active_connection_set_state(NMActiveConnection * self, - NMActiveConnectionState new_state, - NMActiveConnectionStateReason reason) -{ - NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - NMActiveConnectionState old_state; - - /* DEACTIVATED is a terminal state */ - g_return_if_fail(priv->state != NM_ACTIVE_CONNECTION_STATE_DEACTIVATED - || new_state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED); - - if (priv->state == new_state) - return; - - _LOGD("set state %s (was %s)", state_to_string_a(new_state), state_to_string_a(priv->state)); - - if (new_state > NM_ACTIVE_CONNECTION_STATE_ACTIVATED) { - /* once we are about to deactivate, we don't need the keep-alive instance - * anymore. Freeze/disarm it. */ - nm_keep_alive_disarm(priv->keep_alive); - } - - if (new_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED - && priv->activation_type == NM_ACTIVATION_TYPE_ASSUME) { - /* assuming connections mean to gracefully take over an externally - * configured device. Once activation is complete, an assumed - * activation *is* the same as a full activation. */ - _set_activation_type_managed(self); - } - - old_state = priv->state; - priv->state = new_state; - priv->state_set = TRUE; - emit_state_changed(self, new_state, reason); - _notify(self, PROP_STATE); - - check_master_ready(self); - - if (new_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED - || old_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) { - nm_settings_connection_update_timestamp(priv->settings_connection.obj, - (guint64) time(NULL)); - } - - if (priv->device) { - if (old_state < NM_ACTIVE_CONNECTION_STATE_ACTIVATED - && new_state >= NM_ACTIVE_CONNECTION_STATE_ACTIVATED && priv->pending_activation_id) { - nm_device_remove_pending_action(priv->device, priv->pending_activation_id, TRUE); - nm_clear_g_free(&priv->pending_activation_id); - } - } - - if (new_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED - || old_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) { - _notify(self, PROP_IP4_CONFIG); - _notify(self, PROP_DHCP4_CONFIG); - _notify(self, PROP_IP6_CONFIG); - _notify(self, PROP_DHCP6_CONFIG); - } - - if (priv->state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) { - _nm_unused gs_unref_object NMActiveConnection *self_keep_alive = g_object_ref(self); - - auth_complete(self, FALSE, "Authorization request cancelled"); - - /* Device is no longer relevant when deactivated. So remove it and - * emit property change notification so clients re-read the value, - * which will be NULL due to conditions in get_property(). - */ - _device_cleanup(self); - _notify(self, PROP_DEVICES); - } -} - -void -nm_active_connection_set_state_fail(NMActiveConnection * self, - NMActiveConnectionStateReason reason, - const char * error_desc) -{ - NMActiveConnectionState s; - - g_return_if_fail(NM_IS_ACTIVE_CONNECTION(self)); - - if (error_desc) { - _LOGD("Failed to activate '%s': %s", - nm_active_connection_get_settings_connection_id(self), - error_desc); - } - - s = nm_active_connection_get_state(self); - if (s >= NM_ACTIVE_CONNECTION_STATE_ACTIVATING && s < NM_ACTIVE_CONNECTION_STATE_DEACTIVATING) { - nm_active_connection_set_state(self, NM_ACTIVE_CONNECTION_STATE_DEACTIVATING, reason); - s = nm_active_connection_get_state(self); - } - if (s < NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) { - nm_active_connection_set_state(self, NM_ACTIVE_CONNECTION_STATE_DEACTIVATED, reason); - } -} - -NMActivationStateFlags -nm_active_connection_get_state_flags(NMActiveConnection *self) -{ - NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - - return priv->state_flags - | (priv->activation_type == NM_ACTIVATION_TYPE_EXTERNAL - ? NM_ACTIVATION_STATE_FLAG_EXTERNAL - : NM_ACTIVATION_STATE_FLAG_NONE); -} - -void -nm_active_connection_set_state_flags_full(NMActiveConnection * self, - NMActivationStateFlags state_flags, - NMActivationStateFlags mask) -{ - NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - NMActivationStateFlags f; - - nm_assert(!NM_FLAGS_HAS(mask, NM_ACTIVATION_STATE_FLAG_EXTERNAL)); - - f = (priv->state_flags & ~mask) | (state_flags & mask); - if (f != priv->state_flags) { - char buf1[_NM_ACTIVATION_STATE_FLAG_TO_STRING_BUFSIZE]; - char buf2[_NM_ACTIVATION_STATE_FLAG_TO_STRING_BUFSIZE]; - - _LOGD("set state-flags %s (was %s)", - _state_flags_to_string(f, buf1, sizeof(buf1)), - _state_flags_to_string(priv->state_flags, buf2, sizeof(buf2))); - priv->state_flags = f; - _notify(self, PROP_STATE_FLAGS); - - nm_keep_alive_set_settings_connection_watch_visible( - priv->keep_alive, - NM_FLAGS_HAS(priv->state_flags, - NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY) - ? priv->settings_connection.obj - : NULL); - } -} - -const char * -nm_active_connection_get_settings_connection_id(NMActiveConnection *self) -{ - NMSettingsConnection *sett_conn; - - g_return_val_if_fail(NM_IS_ACTIVE_CONNECTION(self), NULL); - - sett_conn = NM_ACTIVE_CONNECTION_GET_PRIVATE(self)->settings_connection.obj; - return sett_conn ? nm_settings_connection_get_id(sett_conn) : NULL; -} - -NMSettingsConnection * -_nm_active_connection_get_settings_connection(NMActiveConnection *self) -{ - g_return_val_if_fail(NM_IS_ACTIVE_CONNECTION(self), NULL); - - return NM_ACTIVE_CONNECTION_GET_PRIVATE(self)->settings_connection.obj; -} - -NMSettingsConnection * -nm_active_connection_get_settings_connection(NMActiveConnection *self) -{ - NMSettingsConnection *sett_conn; - - sett_conn = _nm_active_connection_get_settings_connection(self); - - /* Only call this function on an active-connection that is already - * fully set-up (i.e. that has a settings-connection). Other uses - * indicate a bug. */ - g_return_val_if_fail(sett_conn, NULL); - return sett_conn; -} - -NMConnection * -nm_active_connection_get_applied_connection(NMActiveConnection *self) -{ - NMConnection *connection; - - g_return_val_if_fail(NM_IS_ACTIVE_CONNECTION(self), NULL); - - connection = NM_ACTIVE_CONNECTION_GET_PRIVATE(self)->applied_connection; - - /* Only call this function on an active-connection that is already - * fully set-up (i.e. that has a settings-connection). Other uses - * indicate a bug. */ - g_return_val_if_fail(connection, NULL); - return connection; -} - -static void -_set_applied_connection_take(NMActiveConnection *self, NMConnection *applied_connection) -{ - NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - NMSettingConnection * s_con; - NMActivationStateFlags flags_val = 0; - - nm_assert(NM_IS_CONNECTION(applied_connection)); - nm_assert(!priv->applied_connection); - - /* we take ownership of @applied_connection. Ensure to pass in a reference. */ - priv->applied_connection = applied_connection; - nm_connection_clear_secrets(priv->applied_connection); - - /* we determine whether the connection is a master/slave, based solely - * on the connection properties itself. */ - s_con = nm_connection_get_setting_connection(priv->applied_connection); - if (nm_setting_connection_get_master(s_con)) - flags_val |= NM_ACTIVATION_STATE_FLAG_IS_SLAVE; - - if (_nm_connection_type_is_master(nm_setting_connection_get_connection_type(s_con))) - flags_val |= NM_ACTIVATION_STATE_FLAG_IS_MASTER; - - nm_active_connection_set_state_flags_full(self, - flags_val, - NM_ACTIVATION_STATE_FLAG_IS_MASTER - | NM_ACTIVATION_STATE_FLAG_IS_SLAVE); -} - -void -nm_active_connection_set_settings_connection(NMActiveConnection * self, - NMSettingsConnection *sett_conn) -{ - NMActiveConnectionPrivate *priv; - - g_return_if_fail(NM_IS_ACTIVE_CONNECTION(self)); - - priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - - g_return_if_fail(NM_IS_SETTINGS_CONNECTION(sett_conn)); - g_return_if_fail(!priv->settings_connection.obj); - g_return_if_fail(!priv->applied_connection); - - /* Can't change connection after the ActiveConnection is exported over D-Bus. - * - * Later, we want to change the settings-connection of an activated connection. - * When doing that, this changes the assumption that the settings-connection - * never changes (once it's set). That has effects for NMVpnConnection and - * NMActivationRequest. - * For example, we'd have to cancel all pending seret requests. */ - g_return_if_fail(!nm_dbus_object_is_exported(NM_DBUS_OBJECT(self))); - - _set_settings_connection(self, sett_conn); - - _set_applied_connection_take( - self, - nm_simple_connection_new_clone( - nm_settings_connection_get_connection(priv->settings_connection.obj))); -} - -gboolean -nm_active_connection_has_unmodified_applied_connection(NMActiveConnection * self, - NMSettingCompareFlags compare_flags) -{ - NMActiveConnectionPrivate *priv; - - g_return_val_if_fail(NM_IS_ACTIVE_CONNECTION(self), FALSE); - - priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - - g_return_val_if_fail(priv->settings_connection.obj, FALSE); - - return nm_settings_connection_has_unmodified_applied_connection(priv->settings_connection.obj, - priv->applied_connection, - compare_flags); -} - -/*****************************************************************************/ - -void -nm_active_connection_clear_secrets(NMActiveConnection *self) -{ - NMActiveConnectionPrivate *priv; - - g_return_if_fail(NM_IS_ACTIVE_CONNECTION(self)); - - priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - - if (nm_settings_connection_has_unmodified_applied_connection(priv->settings_connection.obj, - priv->applied_connection, - NM_SETTING_COMPARE_FLAG_NONE)) { - nm_settings_connection_clear_secrets(priv->settings_connection.obj, FALSE, FALSE); - } - nm_connection_clear_secrets(priv->applied_connection); -} - -/*****************************************************************************/ - -const char * -nm_active_connection_get_specific_object(NMActiveConnection *self) -{ - return NM_ACTIVE_CONNECTION_GET_PRIVATE(self)->specific_object; -} - -void -nm_active_connection_set_specific_object(NMActiveConnection *self, const char *specific_object) -{ - NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - - /* Nothing that calls this function should be using paths from D-Bus, - * where NM uses "/" to mean NULL. - */ - nm_assert(!nm_streq0(specific_object, "/")); - - if (nm_streq0(priv->specific_object, specific_object)) - return; - - g_free(priv->specific_object); - priv->specific_object = g_strdup(specific_object); - _notify(self, PROP_SPECIFIC_OBJECT); -} - -void -nm_active_connection_set_default(NMActiveConnection *self, int addr_family, gboolean is_default) -{ - NMActiveConnectionPrivate *priv; - - g_return_if_fail(NM_IS_ACTIVE_CONNECTION(self)); - nm_assert(NM_IN_SET(addr_family, AF_UNSPEC, AF_INET, AF_INET6)); - - is_default = !!is_default; - - priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - if (NM_IN_SET(addr_family, AF_UNSPEC, AF_INET)) { - if (priv->is_default != is_default) { - priv->is_default = is_default; - _notify(self, PROP_DEFAULT); - } - } - if (NM_IN_SET(addr_family, AF_UNSPEC, AF_INET6)) { - if (priv->is_default6 != is_default) { - priv->is_default6 = is_default; - _notify(self, PROP_DEFAULT6); - } - } -} - -gboolean -nm_active_connection_get_default(NMActiveConnection *self, int addr_family) -{ - NMActiveConnectionPrivate *priv; - - g_return_val_if_fail(NM_IS_ACTIVE_CONNECTION(self), FALSE); - nm_assert(NM_IN_SET(addr_family, AF_UNSPEC, AF_INET, AF_INET6)); - - priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - switch (addr_family) { - case AF_INET: - return priv->is_default; - case AF_INET6: - return priv->is_default6; - default: - return priv->is_default || priv->is_default6; - } -} - -NMAuthSubject * -nm_active_connection_get_subject(NMActiveConnection *self) -{ - g_return_val_if_fail(NM_IS_ACTIVE_CONNECTION(self), NULL); - - return NM_ACTIVE_CONNECTION_GET_PRIVATE(self)->subject; -} - -gboolean -nm_active_connection_get_user_requested(NMActiveConnection *self) -{ - g_return_val_if_fail(NM_IS_ACTIVE_CONNECTION(self), FALSE); - - return nm_auth_subject_get_subject_type(NM_ACTIVE_CONNECTION_GET_PRIVATE(self)->subject) - == NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS; -} - -NMDevice * -nm_active_connection_get_device(NMActiveConnection *self) -{ - g_return_val_if_fail(NM_IS_ACTIVE_CONNECTION(self), NULL); - - return NM_ACTIVE_CONNECTION_GET_PRIVATE(self)->device; -} - -static void -device_state_changed(NMDevice * device, - NMDeviceState new_state, - NMDeviceState old_state, - NMDeviceStateReason reason, - gpointer user_data) -{ - NMActiveConnection * self = NM_ACTIVE_CONNECTION(user_data); - NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - - /* When already deactivated or before activation, device state changes are useless */ - if (priv->state >= NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) - return; - if (old_state < NM_DEVICE_STATE_DISCONNECTED) - return; - - /* Let subclasses handle the state change */ - if (NM_ACTIVE_CONNECTION_GET_CLASS(self)->device_state_changed) - NM_ACTIVE_CONNECTION_GET_CLASS(self)->device_state_changed(self, - device, - new_state, - old_state); -} - -static void -device_master_changed(GObject *object, GParamSpec *pspec, gpointer user_data) -{ - NMDevice * device = NM_DEVICE(object); - NMActiveConnection * self = NM_ACTIVE_CONNECTION(user_data); - NMActiveConnection * master; - NMActiveConnectionState master_state; - - if (NM_ACTIVE_CONNECTION(nm_device_get_act_request(device)) != self) - return; - if (!nm_device_get_master(device)) - return; - if (!nm_active_connection_get_master(self)) - return; - g_signal_handlers_disconnect_by_func(device, G_CALLBACK(device_master_changed), self); - - master = nm_active_connection_get_master(self); - master_state = nm_active_connection_get_state(master); - if (master_state >= NM_ACTIVE_CONNECTION_STATE_DEACTIVATING) { - /* Master failed before attaching the slave */ - if (NM_ACTIVE_CONNECTION_GET_CLASS(self)->master_failed) - NM_ACTIVE_CONNECTION_GET_CLASS(self)->master_failed(self); - } -} - -static void -device_metered_changed(GObject *object, GParamSpec *pspec, gpointer user_data) -{ - NMActiveConnection *self = (NMActiveConnection *) user_data; - NMDevice * device = NM_DEVICE(object); - - g_return_if_fail(NM_IS_ACTIVE_CONNECTION(self)); - g_signal_emit(self, signals[DEVICE_METERED_CHANGED], 0, nm_device_get_metered(device)); -} - -gboolean -nm_active_connection_set_device(NMActiveConnection *self, NMDevice *device) -{ - NMActiveConnectionPrivate *priv; - gs_unref_object NMDevice *old_device = NULL; - - g_return_val_if_fail(NM_IS_ACTIVE_CONNECTION(self), FALSE); - g_return_val_if_fail(!device || NM_IS_DEVICE(device), FALSE); - - priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - if (device == priv->device) - return TRUE; - - _LOGD("set device %s%s%s [%p]", - NM_PRINT_FMT_QUOTED(device && nm_device_get_iface(device), - "\"", - nm_device_get_iface(device), - "\"", - device ? "(unknown)" : "(null)"), - device); - - old_device = priv->device ? g_object_ref(priv->device) : NULL; - _device_cleanup(self); - - if (device) { - /* Device obviously can't be its own master */ - g_return_val_if_fail(!priv->master - || device != nm_active_connection_get_device(priv->master), - FALSE); - - priv->device = g_object_ref(device); - - g_signal_connect(device, NM_DEVICE_STATE_CHANGED, G_CALLBACK(device_state_changed), self); - g_signal_connect(device, - "notify::" NM_DEVICE_MASTER, - G_CALLBACK(device_master_changed), - self); - g_signal_connect(device, - "notify::" NM_DEVICE_METERED, - G_CALLBACK(device_metered_changed), - self); - - if (priv->activation_type != NM_ACTIVATION_TYPE_EXTERNAL) { - priv->pending_activation_id = - g_strdup_printf(NM_PENDING_ACTIONPREFIX_ACTIVATION "%" G_GUINT64_FORMAT, - priv->version_id); - nm_device_add_pending_action(device, priv->pending_activation_id, TRUE); - } - } else { - /* The ActiveConnection's device can only be cleared after the - * connection is activated. - */ - g_warn_if_fail(priv->state > NM_ACTIVE_CONNECTION_STATE_UNKNOWN); - priv->device = NULL; - } - _notify(self, PROP_INT_DEVICE); - - g_signal_emit(self, signals[DEVICE_CHANGED], 0, priv->device, old_device); - - _notify(self, PROP_DEVICES); - - return TRUE; -} - -NMActiveConnection * -nm_active_connection_get_master(NMActiveConnection *self) -{ - g_return_val_if_fail(NM_IS_ACTIVE_CONNECTION(self), NULL); - - return NM_ACTIVE_CONNECTION_GET_PRIVATE(self)->master; -} - -/** - * nm_active_connection_get_master_ready: - * @self: the #NMActiveConnection - * - * Returns: %TRUE if the connection has a master connection, and that - * master connection is ready to accept slaves. Otherwise, %FALSE. - */ -gboolean -nm_active_connection_get_master_ready(NMActiveConnection *self) -{ - g_return_val_if_fail(NM_IS_ACTIVE_CONNECTION(self), FALSE); - - return NM_ACTIVE_CONNECTION_GET_PRIVATE(self)->master_ready; -} - -static void -check_master_ready(NMActiveConnection *self) -{ - NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - gboolean signalling = FALSE; - - /* ActiveConnetions don't enter the ACTIVATING state until they have a - * NMDevice in PREPARE or higher states, so the master active connection's - * device will be ready to accept slaves when the master is in ACTIVATING - * or higher states. - */ - if (!priv->master_ready && priv->master && priv->state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING - && NM_IN_SET(nm_active_connection_get_state(priv->master), - NM_ACTIVE_CONNECTION_STATE_ACTIVATING, - NM_ACTIVE_CONNECTION_STATE_ACTIVATED)) { - signalling = TRUE; - } - - _LOGD("check-master-ready: %s (state %s, %s)", - signalling ? "signal" : (priv->master_ready ? "already signalled" : "not signalling"), - state_to_string_a(priv->state), - priv->master - ? nm_sprintf_bufa(128, - "master %p is in state %s", - priv->master, - state_to_string_a(nm_active_connection_get_state(priv->master))) - : "no master"); - - if (signalling) { - priv->master_ready = TRUE; - _notify(self, PROP_INT_MASTER_READY); - - /* Also notify clients to recheck the exported 'master' property to - * ensure that if the master connection was created without a device - * that we notify clients when the master device is known. - */ - _notify(self, PROP_MASTER); - } -} - -static void -master_state_cb(NMActiveConnection *master, GParamSpec *pspec, gpointer user_data) -{ - NMActiveConnection * self = NM_ACTIVE_CONNECTION(user_data); - NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - NMActiveConnectionState master_state = nm_active_connection_get_state(master); - - check_master_ready(self); - - if (master_state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATING && !priv->master_ready) { - /* Master disconnected before the slave was added */ - if (NM_ACTIVE_CONNECTION_GET_CLASS(self)->master_failed) - NM_ACTIVE_CONNECTION_GET_CLASS(self)->master_failed(self); - } -} - -/** - * nm_active_connection_set_master: - * @self: the #NMActiveConnection - * @master: if the activation depends on another device (ie, bond or bridge - * master to which this device will be enslaved) pass the #NMActiveConnection - * that this activation request is a child of - * - * Sets the master active connection of @self. - */ -void -nm_active_connection_set_master(NMActiveConnection *self, NMActiveConnection *master) -{ - NMActiveConnectionPrivate *priv; - - g_return_if_fail(NM_IS_ACTIVE_CONNECTION(self)); - g_return_if_fail(NM_IS_ACTIVE_CONNECTION(master)); - - priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - - /* Master is write-once, and must be set before exporting the object */ - g_return_if_fail(priv->master == NULL); - g_return_if_fail(!nm_dbus_object_is_exported(NM_DBUS_OBJECT(self))); - if (priv->device) { - /* Note, the master ActiveConnection may not yet have a device */ - g_return_if_fail(priv->device != nm_active_connection_get_device(master)); - } - - _LOGD("set master %p, %s, state %s", - master, - nm_active_connection_get_settings_connection_id(master), - state_to_string_a(nm_active_connection_get_state(master))); - - priv->master = g_object_ref(master); - g_signal_connect(priv->master, - "notify::" NM_ACTIVE_CONNECTION_STATE, - (GCallback) master_state_cb, - self); - - check_master_ready(self); -} - -NMActivationType -nm_active_connection_get_activation_type(NMActiveConnection *self) -{ - g_return_val_if_fail(NM_IS_ACTIVE_CONNECTION(self), NM_ACTIVATION_TYPE_MANAGED); - - return NM_ACTIVE_CONNECTION_GET_PRIVATE(self)->activation_type; -} - -static void -_set_activation_type(NMActiveConnection *self, NMActivationType activation_type) -{ - NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - gboolean state_flags_changed; - - if (priv->activation_type == activation_type) - return; - - state_flags_changed = (priv->activation_type == NM_ACTIVATION_TYPE_EXTERNAL) - != (activation_type == NM_ACTIVATION_TYPE_EXTERNAL); - - priv->activation_type = activation_type; - - if (priv->settings_connection.obj) { - if (activation_type == NM_ACTIVATION_TYPE_EXTERNAL) - g_signal_connect(priv->settings_connection.obj, - NM_SETTINGS_CONNECTION_FLAGS_CHANGED, - (GCallback) _settings_connection_flags_changed, - self); - else - g_signal_handlers_disconnect_by_func(priv->settings_connection.obj, - _settings_connection_flags_changed, - self); - } - - if (state_flags_changed) - _notify(self, PROP_STATE_FLAGS); -} - -static void -_set_activation_type_managed(NMActiveConnection *self) -{ - NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - - if (priv->activation_type == NM_ACTIVATION_TYPE_MANAGED) - return; - - _LOGD("update activation type from %s to %s", - nm_activation_type_to_string(priv->activation_type), - nm_activation_type_to_string(NM_ACTIVATION_TYPE_MANAGED)); - - _set_activation_type(self, NM_ACTIVATION_TYPE_MANAGED); - - if (priv->device && self == NM_ACTIVE_CONNECTION(nm_device_get_act_request(priv->device)) - && NM_IN_SET(nm_device_sys_iface_state_get(priv->device), - NM_DEVICE_SYS_IFACE_STATE_EXTERNAL, - NM_DEVICE_SYS_IFACE_STATE_ASSUME)) - nm_device_sys_iface_state_set(priv->device, NM_DEVICE_SYS_IFACE_STATE_MANAGED); -} - -NMActivationReason -nm_active_connection_get_activation_reason(NMActiveConnection *self) -{ - g_return_val_if_fail(NM_IS_ACTIVE_CONNECTION(self), NM_ACTIVATION_REASON_UNSET); - - return NM_ACTIVE_CONNECTION_GET_PRIVATE(self)->activation_reason; -} - -/*****************************************************************************/ - -/** - * nm_active_connection_get_keep_alive: - * @self: the #NMActiveConnection instance - * - * Gives the #NMKeepAlive instance of the active connection. Note that - * @self is guaranteed not to swap the keep-alive instance, so it is - * in particular safe to assume that the keep-alive instance is alive - * as long as @self, and that nm_active_connection_get_keep_alive() - * will return always the same instance. - * - * In particular this means, that it is safe and encouraged, that you - * register to the notify:alive property changed signal of the returned - * instance. - * - * Returns: the #NMKeepAlive instance. - */ -NMKeepAlive * -nm_active_connection_get_keep_alive(NMActiveConnection *self) -{ - g_return_val_if_fail(NM_IS_ACTIVE_CONNECTION(self), NULL); - - return NM_ACTIVE_CONNECTION_GET_PRIVATE(self)->keep_alive; -} - -/*****************************************************************************/ - -static void -_settings_connection_flags_changed(NMSettingsConnection *settings_connection, - NMActiveConnection * self) -{ - NMDevice *device; - - nm_assert(NM_IS_ACTIVE_CONNECTION(self)); - nm_assert(NM_IS_SETTINGS_CONNECTION(settings_connection)); - nm_assert(nm_active_connection_get_activation_type(self) == NM_ACTIVATION_TYPE_EXTERNAL); - nm_assert(NM_ACTIVE_CONNECTION_GET_PRIVATE(self)->settings_connection.obj - == settings_connection); - - if (NM_FLAGS_HAS(nm_settings_connection_get_flags(settings_connection), - NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL)) - return; - - _set_activation_type_managed(self); - - device = nm_active_connection_get_device(self); - if (device) { - gs_free_error GError *error = NULL; - - if (!nm_device_reapply(device, - nm_settings_connection_get_connection( - nm_active_connection_get_settings_connection(self)), - &error)) { - _LOGW( - "failed to reapply new device settings on previously externally managed device: %s", - error->message); - } - } -} - -/*****************************************************************************/ - -static void unwatch_parent(NMActiveConnection *self, gboolean unref); - -static void -parent_destroyed(gpointer user_data, GObject *parent) -{ - NMActiveConnection *self = user_data; - - unwatch_parent(self, FALSE); - g_signal_emit(self, signals[PARENT_ACTIVE], 0, NULL); -} - -static void -parent_state_cb(NMActiveConnection *parent_ac, GParamSpec *pspec, gpointer user_data) -{ - NMActiveConnection * self = user_data; - NMActiveConnectionState parent_state = nm_active_connection_get_state(parent_ac); - - if (parent_state < NM_ACTIVE_CONNECTION_STATE_ACTIVATED) - return; - - unwatch_parent(self, TRUE); - - if (parent_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) - g_signal_emit(self, signals[PARENT_ACTIVE], 0, parent_ac); -} - -static void -unwatch_parent(NMActiveConnection *self, gboolean unref) -{ - NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - - g_signal_handlers_disconnect_by_func(priv->parent, (GCallback) parent_state_cb, self); - if (unref) - g_object_weak_unref((GObject *) priv->parent, parent_destroyed, self); - priv->parent = NULL; -} - -/** - * nm_active_connection_set_parent: - * @self: the #NMActiveConnection - * @parent: The #NMActiveConnection that must be active before the manager - * can proceed progressing the device to disconnected state for us. - * - * Sets the parent connection of @self. A "parent-active" signal will be - * emitted when the parent connection becomes active. - */ -void -nm_active_connection_set_parent(NMActiveConnection *self, NMActiveConnection *parent) -{ - NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - - g_return_if_fail(priv->parent == NULL); - priv->parent = parent; - g_signal_connect(priv->parent, - "notify::" NM_ACTIVE_CONNECTION_STATE, - (GCallback) parent_state_cb, - self); - g_object_weak_ref((GObject *) priv->parent, parent_destroyed, self); -} - -/*****************************************************************************/ - -static void -auth_complete(NMActiveConnection *self, gboolean result, const char *message) -{ - NMActiveConnectionPrivate * priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - NMActiveConnectionAuthResultFunc result_func; - gpointer user_data; - - if (priv->auth.call_id_network_control) - nm_auth_manager_check_authorization_cancel(priv->auth.call_id_network_control); - if (priv->auth.call_id_wifi_shared_permission) { - if (priv->auth.call_id_wifi_shared_permission == AUTH_CALL_ID_SHARED_WIFI_PERMISSION_FAILED) - priv->auth.call_id_wifi_shared_permission = NULL; - else - nm_auth_manager_check_authorization_cancel(priv->auth.call_id_wifi_shared_permission); - } - - nm_assert(!priv->auth.call_id_network_control); - nm_assert(!priv->auth.call_id_wifi_shared_permission); - if (priv->auth.result_func) { - result_func = priv->auth.result_func; - priv->auth.result_func = NULL; - user_data = g_steal_pointer(&priv->auth.user_data); - - result_func(self, result, message, user_data); - } -} - -static void -auth_complete_keep_alive(NMActiveConnection *self, gboolean result, const char *message) -{ - _nm_unused gs_unref_object NMActiveConnection *self_keep_alive = g_object_ref(self); - - auth_complete(self, result, message); -} - -static void -auth_done(NMAuthManager * auth_mgr, - NMAuthManagerCallId *auth_call_id, - gboolean is_authorized, - gboolean is_challenge, - GError * error, - gpointer user_data) - -{ - NMActiveConnection * self = NM_ACTIVE_CONNECTION(user_data); - NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - NMAuthCallResult result; - - nm_assert(auth_call_id); - nm_assert(priv->auth.result_func); - - if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - if (auth_call_id == priv->auth.call_id_network_control) - priv->auth.call_id_network_control = NULL; - else { - nm_assert(auth_call_id == priv->auth.call_id_wifi_shared_permission); - priv->auth.call_id_wifi_shared_permission = NULL; - } - return; - } - - result = nm_auth_call_result_eval(is_authorized, is_challenge, error); - - if (auth_call_id == priv->auth.call_id_network_control) { - priv->auth.call_id_network_control = NULL; - if (result != NM_AUTH_CALL_RESULT_YES) { - auth_complete_keep_alive(self, FALSE, "Not authorized to control networking."); - return; - } - } else { - nm_assert(auth_call_id == priv->auth.call_id_wifi_shared_permission); - if (result != NM_AUTH_CALL_RESULT_YES) { - /* we don't fail right away. Instead, we mark that wifi-shared-permissions - * are missing. We prefer to report the failure about network-control. - * Below, we will wait longer for call_id_network_control (if it's still - * pending). */ - priv->auth.call_id_wifi_shared_permission = AUTH_CALL_ID_SHARED_WIFI_PERMISSION_FAILED; - } else - priv->auth.call_id_wifi_shared_permission = NULL; - } - - if (priv->auth.call_id_network_control) - return; - - if (priv->auth.call_id_wifi_shared_permission) { - if (priv->auth.call_id_wifi_shared_permission == AUTH_CALL_ID_SHARED_WIFI_PERMISSION_FAILED) - auth_complete_keep_alive(self, FALSE, "Not authorized to share connections via wifi."); - return; - } - - auth_complete_keep_alive(self, TRUE, NULL); -} - -/** - * nm_active_connection_authorize: - * @self: the #NMActiveConnection - * @initial_connection: (allow-none): for add-and-activate, there - * is no @settings_connection available when creating the active connection. - * Instead pass an alternative connection. - * @result_func: function to be called on success or error - * @user_data: pointer passed to @result_func - * - * Checks whether the subject that initiated the active connection (read from - * the #NMActiveConnection::subject property) is authorized to complete this - * activation request. - */ -void -nm_active_connection_authorize(NMActiveConnection * self, - NMConnection * initial_connection, - NMActiveConnectionAuthResultFunc result_func, - gpointer user_data) -{ - NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - const char * wifi_permission = NULL; - NMConnection * connection; - - g_return_if_fail(result_func); - g_return_if_fail(!priv->auth.call_id_network_control); - nm_assert(!priv->auth.call_id_wifi_shared_permission); - - if (initial_connection) { - g_return_if_fail(NM_IS_CONNECTION(initial_connection)); - g_return_if_fail(!priv->settings_connection.obj); - g_return_if_fail(!priv->applied_connection); - connection = initial_connection; - } else { - g_return_if_fail(NM_IS_SETTINGS_CONNECTION(priv->settings_connection.obj)); - g_return_if_fail(NM_IS_CONNECTION(priv->applied_connection)); - connection = priv->applied_connection; - } - - priv->auth.call_id_network_control = - nm_auth_manager_check_authorization(nm_auth_manager_get(), - priv->subject, - NM_AUTH_PERMISSION_NETWORK_CONTROL, - TRUE, - auth_done, - self); - - /* Shared wifi connections require special permissions too */ - wifi_permission = nm_utils_get_shared_wifi_permission(connection); - if (wifi_permission) { - priv->auth.call_id_wifi_shared_permission = - nm_auth_manager_check_authorization(nm_auth_manager_get(), - priv->subject, - wifi_permission, - TRUE, - auth_done, - self); - } - - priv->auth.result_func = result_func; - priv->auth.user_data = user_data; -} - -/*****************************************************************************/ - -static guint64 -_version_id_new(void) -{ - static guint64 id = 0; - - return ++id; -} - -guint64 -nm_active_connection_version_id_get(NMActiveConnection *self) -{ - g_return_val_if_fail(NM_IS_ACTIVE_CONNECTION(self), 0); - - return NM_ACTIVE_CONNECTION_GET_PRIVATE(self)->version_id; -} - -guint64 -nm_active_connection_version_id_bump(NMActiveConnection *self) -{ - NMActiveConnectionPrivate *priv; - - g_return_val_if_fail(NM_IS_ACTIVE_CONNECTION(self), 0); - - priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - priv->version_id = _version_id_new(); - _LOGT("new version-id %llu", (unsigned long long) priv->version_id); - return priv->version_id; -} - -/*****************************************************************************/ - -static void -_device_cleanup(NMActiveConnection *self) -{ - NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - - if (priv->device) { - g_signal_handlers_disconnect_by_func(priv->device, G_CALLBACK(device_state_changed), self); - g_signal_handlers_disconnect_by_func(priv->device, G_CALLBACK(device_master_changed), self); - g_signal_handlers_disconnect_by_func(priv->device, - G_CALLBACK(device_metered_changed), - self); - } - - if (priv->pending_activation_id) { - nm_device_remove_pending_action(priv->device, priv->pending_activation_id, TRUE); - nm_clear_g_free(&priv->pending_activation_id); - } - - g_clear_object(&priv->device); -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMActiveConnection * self = NM_ACTIVE_CONNECTION(object); - NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - char ** strv; - NMDevice * master_device = NULL; - - switch (prop_id) { - /* note that while priv->settings_connection.obj might not be set initially, - * it will be set before the object is exported on D-Bus. Hence, - * nobody is calling these property getters before the object is - * exported, at which point we will have a valid settings-connection. - * - * Therefore, intentionally not check whether priv->settings_connection.obj - * is set, to get an assertion failure if somebody tries to access the - * getters at the wrong time. */ - case PROP_CONNECTION: - g_value_set_string(value, nm_dbus_track_obj_path_get(&priv->settings_connection)); - break; - case PROP_ID: - g_value_set_string(value, nm_settings_connection_get_id(priv->settings_connection.obj)); - break; - case PROP_UUID: - g_value_set_string(value, nm_settings_connection_get_uuid(priv->settings_connection.obj)); - break; - case PROP_TYPE: - g_value_set_string( - value, - nm_settings_connection_get_connection_type(priv->settings_connection.obj)); - break; - - case PROP_SPECIFIC_OBJECT: - g_value_set_string(value, priv->specific_object); - break; - case PROP_DEVICES: - strv = g_new0(char *, 2); - if (priv->device && priv->state < NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) - strv[0] = g_strdup(nm_dbus_object_get_path(NM_DBUS_OBJECT(priv->device))); - g_value_take_boxed(value, strv); - break; - case PROP_STATE: - if (priv->state_set) - g_value_set_uint(value, priv->state); - else { - /* When the AC has just been created, its externally-visible state should - * be "ACTIVATING", even though internally it is "UNKNOWN". - */ - g_value_set_uint(value, NM_ACTIVE_CONNECTION_STATE_ACTIVATING); - } - break; - case PROP_STATE_FLAGS: - g_value_set_uint(value, nm_active_connection_get_state_flags(self)); - break; - case PROP_DEFAULT: - g_value_set_boolean(value, priv->is_default); - break; - case PROP_IP4_CONFIG: - /* The IP and DHCP config properties may be overridden by a subclass */ - g_value_set_string(value, NULL); - break; - case PROP_DHCP4_CONFIG: - g_value_set_string(value, NULL); - break; - case PROP_DEFAULT6: - g_value_set_boolean(value, priv->is_default6); - break; - case PROP_IP6_CONFIG: - g_value_set_string(value, NULL); - break; - case PROP_DHCP6_CONFIG: - g_value_set_string(value, NULL); - break; - case PROP_VPN: - g_value_set_boolean(value, priv->vpn); - break; - case PROP_MASTER: - if (priv->master) - master_device = nm_active_connection_get_device(priv->master); - nm_dbus_utils_g_value_set_object_path(value, master_device); - break; - case PROP_INT_SUBJECT: - g_value_set_object(value, priv->subject); - break; - case PROP_INT_MASTER_READY: - g_value_set_boolean(value, priv->master_ready); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMActiveConnection * self = (NMActiveConnection *) object; - NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - const char * tmp; - NMSettingsConnection * sett_conn; - NMConnection * acon; - int i; - - switch (prop_id) { - case PROP_INT_SETTINGS_CONNECTION: - /* construct-only */ - sett_conn = g_value_get_object(value); - if (sett_conn) - _set_settings_connection(self, sett_conn); - break; - case PROP_INT_APPLIED_CONNECTION: - /* construct-only */ - acon = g_value_get_object(value); - if (acon) { - /* we don't call _set_applied_connection_take() yet, because the instance - * is not yet fully initialized. We are currently in the process of setting - * the constructor properties. - * - * For now, just piggyback the connection, but call _set_applied_connection_take() - * in constructed(). */ - priv->applied_connection = g_object_ref(acon); - } - break; - case PROP_INT_DEVICE: - /* construct-only */ - nm_active_connection_set_device(self, g_value_get_object(value)); - break; - case PROP_INT_SUBJECT: - /* construct-only */ - priv->subject = g_value_dup_object(value); - break; - case PROP_INT_MASTER: - nm_active_connection_set_master(self, g_value_get_object(value)); - break; - case PROP_INT_ACTIVATION_TYPE: - /* construct-only */ - i = g_value_get_int(value); - if (!NM_IN_SET(i, - NM_ACTIVATION_TYPE_MANAGED, - NM_ACTIVATION_TYPE_ASSUME, - NM_ACTIVATION_TYPE_EXTERNAL)) - g_return_if_reached(); - _set_activation_type(self, (NMActivationType) i); - break; - case PROP_STATE_FLAGS: - /* construct-only */ - priv->state_flags = g_value_get_uint(value); - nm_assert((guint) priv->state_flags == g_value_get_uint(value)); - nm_assert(!NM_FLAGS_ANY(priv->state_flags, - ~NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY)); - break; - case PROP_INT_ACTIVATION_REASON: - /* construct-only */ - i = g_value_get_int(value); - priv->activation_reason = i; - nm_assert(priv->activation_reason == ((NMActivationReason) i)); - break; - case PROP_SPECIFIC_OBJECT: - /* construct-only */ - tmp = g_value_get_string(value); - tmp = nm_dbus_path_not_empty(tmp); - priv->specific_object = g_strdup(tmp); - break; - case PROP_DEFAULT: - priv->is_default = g_value_get_boolean(value); - break; - case PROP_DEFAULT6: - priv->is_default6 = g_value_get_boolean(value); - break; - case PROP_VPN: - /* construct-only */ - priv->vpn = g_value_get_boolean(value); - break; - case PROP_MASTER: - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_active_connection_init(NMActiveConnection *self) -{ - NMActiveConnectionPrivate *priv; - - priv = G_TYPE_INSTANCE_GET_PRIVATE(self, NM_TYPE_ACTIVE_CONNECTION, NMActiveConnectionPrivate); - self->_priv = priv; - - nm_dbus_track_obj_path_init(&priv->settings_connection, - G_OBJECT(self), - obj_properties[PROP_CONNECTION]); - - c_list_init(&self->active_connections_lst); - - _LOGT("creating"); - - priv->activation_type = NM_ACTIVATION_TYPE_MANAGED; - priv->version_id = _version_id_new(); - - /* the keep-alive instance must never change. Callers rely on that. */ - priv->keep_alive = nm_keep_alive_new(); - _nm_keep_alive_set_owner(priv->keep_alive, G_OBJECT(self)); -} - -static void -constructed(GObject *object) -{ - NMActiveConnection * self = (NMActiveConnection *) object; - NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - - G_OBJECT_CLASS(nm_active_connection_parent_class)->constructed(object); - - if (!priv->applied_connection && priv->settings_connection.obj) - priv->applied_connection = nm_simple_connection_new_clone( - nm_settings_connection_get_connection(priv->settings_connection.obj)); - - _LOGD("constructed (%s, version-id %llu, type %s)", - G_OBJECT_TYPE_NAME(self), - (unsigned long long) priv->version_id, - nm_activation_type_to_string(priv->activation_type)); - - if (priv->applied_connection) { - /* priv->applied_connection was set during the construction of the object. - * It's not yet fully initialized, so do that now. - * - * We delayed that, because we may log in _set_applied_connection_take(), and the - * first logging line should be "constructed" above). */ - _set_applied_connection_take(self, g_steal_pointer(&priv->applied_connection)); - } - - if (NM_FLAGS_HAS(priv->state_flags, - NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY)) - nm_keep_alive_set_settings_connection_watch_visible(priv->keep_alive, - priv->settings_connection.obj); - - g_return_if_fail(priv->subject); - g_return_if_fail(priv->activation_reason != NM_ACTIVATION_REASON_UNSET); -} - -static void -dispose(GObject *object) -{ - NMActiveConnection * self = NM_ACTIVE_CONNECTION(object); - NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - - nm_assert(!c_list_is_linked(&self->active_connections_lst)); - - _LOGD("disposing"); - - auth_complete(self, FALSE, "Authorization aborted"); - - nm_clear_g_free(&priv->specific_object); - - _set_settings_connection(self, NULL); - g_clear_object(&priv->applied_connection); - - _device_cleanup(self); - - if (priv->master) { - g_signal_handlers_disconnect_by_func(priv->master, (GCallback) master_state_cb, self); - } - g_clear_object(&priv->master); - - if (priv->parent) - unwatch_parent(self, TRUE); - - g_clear_object(&priv->subject); - - G_OBJECT_CLASS(nm_active_connection_parent_class)->dispose(object); -} - -static void -finalize(GObject *object) -{ - NMActiveConnection * self = NM_ACTIVE_CONNECTION(object); - NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE(self); - - nm_dbus_track_obj_path_set(&priv->settings_connection, NULL, FALSE); - - nm_clear_pointer(&priv->keep_alive, nm_keep_alive_destroy); - - G_OBJECT_CLASS(nm_active_connection_parent_class)->finalize(object); -} - -static const GDBusSignalInfo signal_info_state_changed = NM_DEFINE_GDBUS_SIGNAL_INFO_INIT( - "StateChanged", - .args = NM_DEFINE_GDBUS_ARG_INFOS(NM_DEFINE_GDBUS_ARG_INFO("state", "u"), - NM_DEFINE_GDBUS_ARG_INFO("reason", "u"), ), ); - -static const NMDBusInterfaceInfoExtended interface_info_active_connection = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( - NM_DBUS_INTERFACE_ACTIVE_CONNECTION, - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, - &signal_info_state_changed, ), - .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Connection", - "o", - NM_ACTIVE_CONNECTION_CONNECTION), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("SpecificObject", - "o", - NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Id", "s", NM_ACTIVE_CONNECTION_ID), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Uuid", - "s", - NM_ACTIVE_CONNECTION_UUID), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Type", - "s", - NM_ACTIVE_CONNECTION_TYPE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Devices", - "ao", - NM_ACTIVE_CONNECTION_DEVICES), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("State", - "u", - NM_ACTIVE_CONNECTION_STATE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("StateFlags", - "u", - NM_ACTIVE_CONNECTION_STATE_FLAGS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Default", - "b", - NM_ACTIVE_CONNECTION_DEFAULT), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Ip4Config", - "o", - NM_ACTIVE_CONNECTION_IP4_CONFIG), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Dhcp4Config", - "o", - NM_ACTIVE_CONNECTION_DHCP4_CONFIG), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Default6", - "b", - NM_ACTIVE_CONNECTION_DEFAULT6), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Ip6Config", - "o", - NM_ACTIVE_CONNECTION_IP6_CONFIG), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Dhcp6Config", - "o", - NM_ACTIVE_CONNECTION_DHCP6_CONFIG), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Vpn", "b", NM_ACTIVE_CONNECTION_VPN), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Master", - "o", - NM_ACTIVE_CONNECTION_MASTER), ), ), - .legacy_property_changed = TRUE, -}; - -static void -nm_active_connection_class_init(NMActiveConnectionClass *ac_class) -{ - GObjectClass * object_class = G_OBJECT_CLASS(ac_class); - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(ac_class); - - g_type_class_add_private(ac_class, sizeof(NMActiveConnectionPrivate)); - - dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_NUMBERED(NM_DBUS_PATH "/ActiveConnection"); - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_active_connection); - - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->constructed = constructed; - object_class->dispose = dispose; - object_class->finalize = finalize; - - obj_properties[PROP_CONNECTION] = - g_param_spec_string(NM_ACTIVE_CONNECTION_CONNECTION, - "", - "", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_ID] = g_param_spec_string(NM_ACTIVE_CONNECTION_ID, - "", - "", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_UUID] = g_param_spec_string(NM_ACTIVE_CONNECTION_UUID, - "", - "", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_TYPE] = g_param_spec_string(NM_ACTIVE_CONNECTION_TYPE, - "", - "", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_SPECIFIC_OBJECT] = - g_param_spec_string(NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_DEVICES] = g_param_spec_boxed(NM_ACTIVE_CONNECTION_DEVICES, - "", - "", - G_TYPE_STRV, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_STATE] = g_param_spec_uint(NM_ACTIVE_CONNECTION_STATE, - "", - "", - NM_ACTIVE_CONNECTION_STATE_UNKNOWN, - NM_ACTIVE_CONNECTION_STATE_DEACTIVATING, - NM_ACTIVE_CONNECTION_STATE_UNKNOWN, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_STATE_FLAGS] = - g_param_spec_uint(NM_ACTIVE_CONNECTION_STATE_FLAGS, - "", - "", - 0, - G_MAXUINT32, - NM_ACTIVATION_STATE_FLAG_NONE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_DEFAULT] = g_param_spec_boolean(NM_ACTIVE_CONNECTION_DEFAULT, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_IP4_CONFIG] = - g_param_spec_string(NM_ACTIVE_CONNECTION_IP4_CONFIG, - "", - "", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_DHCP4_CONFIG] = - g_param_spec_string(NM_ACTIVE_CONNECTION_DHCP4_CONFIG, - "", - "", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_DEFAULT6] = - g_param_spec_boolean(NM_ACTIVE_CONNECTION_DEFAULT6, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_IP6_CONFIG] = - g_param_spec_string(NM_ACTIVE_CONNECTION_IP6_CONFIG, - "", - "", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_DHCP6_CONFIG] = - g_param_spec_string(NM_ACTIVE_CONNECTION_DHCP6_CONFIG, - "", - "", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_VPN] = - g_param_spec_boolean(NM_ACTIVE_CONNECTION_VPN, - "", - "", - FALSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_MASTER] = g_param_spec_string(NM_ACTIVE_CONNECTION_MASTER, - "", - "", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - - /* Internal properties */ - obj_properties[PROP_INT_SETTINGS_CONNECTION] = - g_param_spec_object(NM_ACTIVE_CONNECTION_INT_SETTINGS_CONNECTION, - "", - "", - NM_TYPE_SETTINGS_CONNECTION, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_INT_APPLIED_CONNECTION] = - g_param_spec_object(NM_ACTIVE_CONNECTION_INT_APPLIED_CONNECTION, - "", - "", - NM_TYPE_CONNECTION, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_INT_DEVICE] = - g_param_spec_object(NM_ACTIVE_CONNECTION_INT_DEVICE, - "", - "", - NM_TYPE_DEVICE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_INT_SUBJECT] = - g_param_spec_object(NM_ACTIVE_CONNECTION_INT_SUBJECT, - "", - "", - NM_TYPE_AUTH_SUBJECT, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_INT_MASTER] = - g_param_spec_object(NM_ACTIVE_CONNECTION_INT_MASTER, - "", - "", - NM_TYPE_ACTIVE_CONNECTION, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_INT_MASTER_READY] = - g_param_spec_boolean(NM_ACTIVE_CONNECTION_INT_MASTER_READY, - "", - "", - FALSE, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_INT_ACTIVATION_TYPE] = - g_param_spec_int(NM_ACTIVE_CONNECTION_INT_ACTIVATION_TYPE, - "", - "", - NM_ACTIVATION_TYPE_MANAGED, - NM_ACTIVATION_TYPE_EXTERNAL, - NM_ACTIVATION_TYPE_MANAGED, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_INT_ACTIVATION_REASON] = - g_param_spec_int(NM_ACTIVE_CONNECTION_INT_ACTIVATION_REASON, - "", - "", - NM_ACTIVATION_REASON_UNSET, - NM_ACTIVATION_REASON_USER_REQUEST, - NM_ACTIVATION_REASON_UNSET, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - signals[DEVICE_CHANGED] = g_signal_new(NM_ACTIVE_CONNECTION_DEVICE_CHANGED, - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(NMActiveConnectionClass, device_changed), - NULL, - NULL, - NULL, - G_TYPE_NONE, - 2, - NM_TYPE_DEVICE, - NM_TYPE_DEVICE); - - signals[DEVICE_METERED_CHANGED] = - g_signal_new(NM_ACTIVE_CONNECTION_DEVICE_METERED_CHANGED, - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(NMActiveConnectionClass, device_metered_changed), - NULL, - NULL, - NULL, - G_TYPE_NONE, - 1, - G_TYPE_UINT); - - signals[PARENT_ACTIVE] = g_signal_new(NM_ACTIVE_CONNECTION_PARENT_ACTIVE, - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(NMActiveConnectionClass, parent_active), - NULL, - NULL, - NULL, - G_TYPE_NONE, - 1, - NM_TYPE_ACTIVE_CONNECTION); - - signals[STATE_CHANGED] = g_signal_new(NM_ACTIVE_CONNECTION_STATE_CHANGED, - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, - NULL, - NULL, - G_TYPE_NONE, - 2, - G_TYPE_UINT, - G_TYPE_UINT); -} |