diff options
Diffstat (limited to 'src/nm-manager.c')
| -rw-r--r-- | src/nm-manager.c | 14397 |
1 files changed, 7305 insertions, 7092 deletions
diff --git a/src/nm-manager.c b/src/nm-manager.c index 778e3b94..a04ca0e6 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2007 - 2009 Novell, Inc. * Copyright (C) 2007 - 2017 Red Hat, Inc. @@ -55,867 +55,875 @@ /*****************************************************************************/ typedef struct { - gboolean user_enabled; - gboolean sw_enabled; - gboolean hw_enabled; - RfKillType rtype; - NMConfigRunStatePropertyType key; - const char *desc; - const char *prop; - const char *hw_prop; + gboolean user_enabled; + gboolean sw_enabled; + gboolean hw_enabled; + RfKillType rtype; + NMConfigRunStatePropertyType key; + const char * desc; + const char * prop; + const char * hw_prop; } RadioState; typedef enum { - ASYNC_OP_TYPE_AC_AUTH_ACTIVATE_INTERNAL, - ASYNC_OP_TYPE_AC_AUTH_ACTIVATE_USER, - ASYNC_OP_TYPE_AC_AUTH_ADD_AND_ACTIVATE, - ASYNC_OP_TYPE_AC_AUTH_ADD_AND_ACTIVATE2, + ASYNC_OP_TYPE_AC_AUTH_ACTIVATE_INTERNAL, + ASYNC_OP_TYPE_AC_AUTH_ACTIVATE_USER, + ASYNC_OP_TYPE_AC_AUTH_ADD_AND_ACTIVATE, + ASYNC_OP_TYPE_AC_AUTH_ADD_AND_ACTIVATE2, } AsyncOpType; typedef struct { - CList async_op_lst; - NMManager *self; - AsyncOpType async_op_type; - union { - struct { - NMActiveConnection *active; - union { - struct { - GDBusMethodInvocation *invocation; - } activate_user; - struct { - GDBusMethodInvocation *invocation; - NMConnection *connection; - NMSettingsConnectionPersistMode persist_mode; - bool is_volatile:1; - } add_and_activate; - }; - } ac_auth; - }; + CList async_op_lst; + NMManager * self; + AsyncOpType async_op_type; + union { + struct { + NMActiveConnection *active; + union { + struct { + GDBusMethodInvocation *invocation; + } activate_user; + struct { + GDBusMethodInvocation * invocation; + NMConnection * connection; + NMSettingsConnectionPersistMode persist_mode; + bool is_volatile : 1; + } add_and_activate; + }; + } ac_auth; + }; } AsyncOpData; enum { - DEVICE_ADDED, - INTERNAL_DEVICE_ADDED, - DEVICE_REMOVED, - INTERNAL_DEVICE_REMOVED, - ACTIVE_CONNECTION_ADDED, - ACTIVE_CONNECTION_REMOVED, - CONFIGURE_QUIT, - - LAST_SIGNAL + DEVICE_ADDED, + INTERNAL_DEVICE_ADDED, + DEVICE_REMOVED, + INTERNAL_DEVICE_REMOVED, + ACTIVE_CONNECTION_ADDED, + ACTIVE_CONNECTION_REMOVED, + CONFIGURE_QUIT, + + LAST_SIGNAL }; -static guint signals[LAST_SIGNAL] = { 0 }; - -NM_GOBJECT_PROPERTIES_DEFINE (NMManager, - PROP_VERSION, - PROP_CAPABILITIES, - PROP_STATE, - PROP_STARTUP, - PROP_NETWORKING_ENABLED, - PROP_WIRELESS_ENABLED, - PROP_WIRELESS_HARDWARE_ENABLED, - PROP_WWAN_ENABLED, - PROP_WWAN_HARDWARE_ENABLED, - PROP_WIMAX_ENABLED, - PROP_WIMAX_HARDWARE_ENABLED, - PROP_ACTIVE_CONNECTIONS, - PROP_CONNECTIVITY, - PROP_CONNECTIVITY_CHECK_AVAILABLE, - PROP_CONNECTIVITY_CHECK_ENABLED, - PROP_CONNECTIVITY_CHECK_URI, - PROP_PRIMARY_CONNECTION, - PROP_PRIMARY_CONNECTION_TYPE, - PROP_ACTIVATING_CONNECTION, - PROP_DEVICES, - PROP_METERED, - PROP_GLOBAL_DNS_CONFIGURATION, - PROP_ALL_DEVICES, - PROP_CHECKPOINTS, - - /* Not exported */ - PROP_SLEEPING, -); +static guint signals[LAST_SIGNAL] = {0}; + +NM_GOBJECT_PROPERTIES_DEFINE(NMManager, + PROP_VERSION, + PROP_CAPABILITIES, + PROP_STATE, + PROP_STARTUP, + PROP_NETWORKING_ENABLED, + PROP_WIRELESS_ENABLED, + PROP_WIRELESS_HARDWARE_ENABLED, + PROP_WWAN_ENABLED, + PROP_WWAN_HARDWARE_ENABLED, + PROP_WIMAX_ENABLED, + PROP_WIMAX_HARDWARE_ENABLED, + PROP_ACTIVE_CONNECTIONS, + PROP_CONNECTIVITY, + PROP_CONNECTIVITY_CHECK_AVAILABLE, + PROP_CONNECTIVITY_CHECK_ENABLED, + PROP_CONNECTIVITY_CHECK_URI, + PROP_PRIMARY_CONNECTION, + PROP_PRIMARY_CONNECTION_TYPE, + PROP_ACTIVATING_CONNECTION, + PROP_DEVICES, + PROP_METERED, + PROP_GLOBAL_DNS_CONFIGURATION, + PROP_ALL_DEVICES, + PROP_CHECKPOINTS, + + /* Not exported */ + PROP_SLEEPING, ); typedef struct { - NMPlatform *platform; + NMPlatform *platform; - GArray *capabilities; + GArray *capabilities; - CList active_connections_lst_head; - CList async_op_lst_head; - guint ac_cleanup_id; - NMActiveConnection *primary_connection; - NMActiveConnection *activating_connection; - NMMetered metered; + CList active_connections_lst_head; + CList async_op_lst_head; + guint ac_cleanup_id; + NMActiveConnection *primary_connection; + NMActiveConnection *activating_connection; + NMMetered metered; - CList devices_lst_head; + CList devices_lst_head; - NMState state; - NMConfig *config; - NMConnectivity *concheck_mgr; - NMPolicy *policy; - NMHostnameManager *hostname_manager; + NMState state; + NMConfig * config; + NMConnectivity * concheck_mgr; + NMPolicy * policy; + NMHostnameManager *hostname_manager; - struct { - GDBusConnection *connection; - guint id; - } prop_filter; - NMRfkillManager *rfkill_mgr; + struct { + GDBusConnection *connection; + guint id; + } prop_filter; + NMRfkillManager *rfkill_mgr; - CList link_cb_lst; + CList link_cb_lst; - NMCheckpointManager *checkpoint_mgr; + NMCheckpointManager *checkpoint_mgr; - NMSettings *settings; + NMSettings *settings; - RadioState radio_states[RFKILL_TYPE_MAX]; - NMVpnManager *vpn_manager; + RadioState radio_states[RFKILL_TYPE_MAX]; + NMVpnManager *vpn_manager; - NMSleepMonitor *sleep_monitor; + NMSleepMonitor *sleep_monitor; - NMAuthManager *auth_mgr; + NMAuthManager *auth_mgr; - GHashTable *device_route_metrics; + GHashTable *device_route_metrics; - CList auth_lst_head; + CList auth_lst_head; - GHashTable *sleep_devices; + GHashTable *sleep_devices; - /* Firmware dir monitor */ - GFileMonitor *fw_monitor; - guint fw_changed_id; + /* Firmware dir monitor */ + GFileMonitor *fw_monitor; + guint fw_changed_id; - guint timestamp_update_id; + guint timestamp_update_id; - guint devices_inited_id; + guint devices_inited_id; - NMConnectivityState connectivity_state; + NMConnectivityState connectivity_state; - guint8 device_state_prune_ratelimit_count; + guint8 device_state_prune_ratelimit_count; - bool startup:1; - bool devices_inited:1; + bool startup : 1; + bool devices_inited : 1; - bool sleeping:1; - bool net_enabled:1; + bool sleeping : 1; + bool net_enabled : 1; - unsigned connectivity_check_enabled_last:2; + unsigned connectivity_check_enabled_last : 2; - guint delete_volatile_connection_idle_id; - CList delete_volatile_connection_lst_head; + guint delete_volatile_connection_idle_id; + CList delete_volatile_connection_lst_head; } NMManagerPrivate; struct _NMManager { - NMDBusObject parent; - NMManagerPrivate _priv; + NMDBusObject parent; + NMManagerPrivate _priv; }; typedef struct { - NMDBusObjectClass parent; + NMDBusObjectClass parent; } NMManagerClass; -G_DEFINE_TYPE (NMManager, nm_manager, NM_TYPE_DBUS_OBJECT) +G_DEFINE_TYPE(NMManager, nm_manager, NM_TYPE_DBUS_OBJECT) #define NM_MANAGER_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMManager, NM_IS_MANAGER) /*****************************************************************************/ -NM_DEFINE_SINGLETON_INSTANCE (NMManager); +NM_DEFINE_SINGLETON_INSTANCE(NMManager); /*****************************************************************************/ -#define _NMLOG_PREFIX_NAME "manager" -#define _NMLOG(level, domain, ...) \ - G_STMT_START { \ - const NMLogLevel _level = (level); \ - const NMLogDomain _domain = (domain); \ - \ - if (nm_logging_enabled (_level, _domain)) { \ - const NMManager *const _self = (self); \ - char _sbuf[32]; \ - \ - _nm_log (_level, _domain, 0, NULL, NULL, \ - "%s%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ - _NMLOG_PREFIX_NAME, \ - ((_self && _self != singleton_instance) \ - ? nm_sprintf_buf (_sbuf, "[%p]", _self) \ - : "") \ - _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ - } \ - } G_STMT_END - -#define _NMLOG2(level, domain, device, ...) \ - G_STMT_START { \ - const NMLogLevel _level = (level); \ - const NMLogDomain _domain = (domain); \ - \ - if (nm_logging_enabled (_level, _domain)) { \ - const NMManager *const _self = (self); \ - const char *const _ifname = _nm_device_get_iface (device); \ - char _sbuf[32]; \ - \ - _nm_log (_level, _domain, 0, \ - _ifname, NULL, \ - "%s%s: %s%s%s" _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ - _NMLOG_PREFIX_NAME, \ - ((_self && _self != singleton_instance) \ - ? nm_sprintf_buf (_sbuf, "[%p]", _self) \ - : ""), \ - NM_PRINT_FMT_QUOTED (_ifname, "(", _ifname, "): ", "") \ - _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ - } \ - } G_STMT_END - -#define _NMLOG3(level, domain, connection, ...) \ - G_STMT_START { \ - const NMLogLevel _level = (level); \ - const NMLogDomain _domain = (domain); \ - \ - if (nm_logging_enabled (_level, _domain)) { \ - const NMManager *const _self = (self); \ - NMConnection *const _connection = (connection); \ - const char *const _con_id = _nm_connection_get_id (_connection); \ - char _sbuf[32]; \ - \ - _nm_log (_level, _domain, 0, \ - NULL, _nm_connection_get_uuid (_connection), \ - "%s%s: %s%s%s" _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ - _NMLOG_PREFIX_NAME, \ - ((_self && _self != singleton_instance) \ - ? nm_sprintf_buf (_sbuf, "[%p]", _self) \ - : ""), \ - NM_PRINT_FMT_QUOTED (_con_id, "(", _con_id, ") ", "") \ - _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ - } \ - } G_STMT_END +#define _NMLOG_PREFIX_NAME "manager" +#define _NMLOG(level, domain, ...) \ + G_STMT_START \ + { \ + const NMLogLevel _level = (level); \ + const NMLogDomain _domain = (domain); \ + \ + if (nm_logging_enabled(_level, _domain)) { \ + const NMManager *const _self = (self); \ + char _sbuf[32]; \ + \ + _nm_log(_level, \ + _domain, \ + 0, \ + NULL, \ + NULL, \ + "%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, \ + ((_self && _self != singleton_instance) ? nm_sprintf_buf(_sbuf, "[%p]", _self) \ + : "") \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + } \ + G_STMT_END + +#define _NMLOG2(level, domain, device, ...) \ + G_STMT_START \ + { \ + const NMLogLevel _level = (level); \ + const NMLogDomain _domain = (domain); \ + \ + if (nm_logging_enabled(_level, _domain)) { \ + const NMManager *const _self = (self); \ + const char *const _ifname = _nm_device_get_iface(device); \ + char _sbuf[32]; \ + \ + _nm_log(_level, \ + _domain, \ + 0, \ + _ifname, \ + NULL, \ + "%s%s: %s%s%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, \ + ((_self && _self != singleton_instance) ? nm_sprintf_buf(_sbuf, "[%p]", _self) \ + : ""), \ + NM_PRINT_FMT_QUOTED(_ifname, "(", _ifname, "): ", "") \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + } \ + G_STMT_END + +#define _NMLOG3(level, domain, connection, ...) \ + G_STMT_START \ + { \ + const NMLogLevel _level = (level); \ + const NMLogDomain _domain = (domain); \ + \ + if (nm_logging_enabled(_level, _domain)) { \ + const NMManager *const _self = (self); \ + NMConnection *const _connection = (connection); \ + const char *const _con_id = _nm_connection_get_id(_connection); \ + char _sbuf[32]; \ + \ + _nm_log(_level, \ + _domain, \ + 0, \ + NULL, \ + _nm_connection_get_uuid(_connection), \ + "%s%s: %s%s%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, \ + ((_self && _self != singleton_instance) ? nm_sprintf_buf(_sbuf, "[%p]", _self) \ + : ""), \ + NM_PRINT_FMT_QUOTED(_con_id, "(", _con_id, ") ", "") \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + } \ + G_STMT_END /*****************************************************************************/ static const NMDBusInterfaceInfoExtended interface_info_manager; -static const GDBusSignalInfo signal_info_check_permissions; -static const GDBusSignalInfo signal_info_state_changed; -static const GDBusSignalInfo signal_info_device_added; -static const GDBusSignalInfo signal_info_device_removed; - -static void update_connectivity_value (NMManager *self); - -static gboolean add_device (NMManager *self, NMDevice *device, GError **error); - -static void _emit_device_added_removed (NMManager *self, - NMDevice *device, - gboolean is_added); - -static NMActiveConnection *_new_active_connection (NMManager *self, - gboolean is_vpn, - NMSettingsConnection *sett_conn, - NMConnection *incompl_conn, - NMConnection *applied, - const char *specific_object, - NMDevice *device, - NMAuthSubject *subject, - NMActivationType activation_type, - NMActivationReason activation_reason, - NMActivationStateFlags initial_state_flags, - GError **error); - -static void policy_activating_ac_changed (GObject *object, GParamSpec *pspec, gpointer user_data); - -static gboolean find_master (NMManager *self, - NMConnection *connection, - NMDevice *device, - NMSettingsConnection **out_master_connection, - NMDevice **out_master_device, - NMActiveConnection **out_master_ac, - GError **error); - -static void nm_manager_update_state (NMManager *manager); - -static void connection_changed (NMManager *self, - NMSettingsConnection *sett_conn); -static void device_sleep_cb (NMDevice *device, - GParamSpec *pspec, - NMManager *self); - -static void settings_startup_complete_changed (NMSettings *settings, - GParamSpec *pspec, - NMManager *self); - -static void retry_connections_for_parent_device (NMManager *self, NMDevice *device); - -static void active_connection_state_changed (NMActiveConnection *active, - GParamSpec *pspec, - NMManager *self); -static void active_connection_default_changed (NMActiveConnection *active, - GParamSpec *pspec, - NMManager *self); -static void active_connection_parent_active (NMActiveConnection *active, - NMActiveConnection *parent_ac, - NMManager *self); - -static NMActiveConnection *active_connection_find (NMManager *self, - NMSettingsConnection *sett_conn, - const char *uuid, - NMActiveConnectionState max_state, - GPtrArray **out_all_matching); - -static NMConnectivity *concheck_get_mgr (NMManager *self); - -static void _internal_activation_auth_done (NMManager *self, - NMActiveConnection *active, - gboolean success, - const char *error_desc); -static void _add_and_activate_auth_done (NMManager *self, - AsyncOpType async_op_type, - NMActiveConnection *active, - NMConnection *connection, - GDBusMethodInvocation *invocation, - NMSettingsConnectionPersistMode persist_mode, - gboolean is_volatile, - gboolean success, - const char *error_desc); -static void _activation_auth_done (NMManager *self, - NMActiveConnection *active, - GDBusMethodInvocation *invocation, - gboolean success, - const char *error_desc); +static const GDBusSignalInfo signal_info_check_permissions; +static const GDBusSignalInfo signal_info_state_changed; +static const GDBusSignalInfo signal_info_device_added; +static const GDBusSignalInfo signal_info_device_removed; + +static void update_connectivity_value(NMManager *self); + +static gboolean add_device(NMManager *self, NMDevice *device, GError **error); + +static void _emit_device_added_removed(NMManager *self, NMDevice *device, gboolean is_added); + +static NMActiveConnection *_new_active_connection(NMManager * self, + gboolean is_vpn, + NMSettingsConnection * sett_conn, + NMConnection * incompl_conn, + NMConnection * applied, + const char * specific_object, + NMDevice * device, + NMAuthSubject * subject, + NMActivationType activation_type, + NMActivationReason activation_reason, + NMActivationStateFlags initial_state_flags, + GError ** error); + +static void policy_activating_ac_changed(GObject *object, GParamSpec *pspec, gpointer user_data); + +static gboolean find_master(NMManager * self, + NMConnection * connection, + NMDevice * device, + NMSettingsConnection **out_master_connection, + NMDevice ** out_master_device, + NMActiveConnection ** out_master_ac, + GError ** error); + +static void nm_manager_update_state(NMManager *manager); + +static void connection_changed(NMManager *self, NMSettingsConnection *sett_conn); +static void device_sleep_cb(NMDevice *device, GParamSpec *pspec, NMManager *self); + +static void +settings_startup_complete_changed(NMSettings *settings, GParamSpec *pspec, NMManager *self); + +static void retry_connections_for_parent_device(NMManager *self, NMDevice *device); + +static void +active_connection_state_changed(NMActiveConnection *active, GParamSpec *pspec, NMManager *self); +static void +active_connection_default_changed(NMActiveConnection *active, GParamSpec *pspec, NMManager *self); +static void active_connection_parent_active(NMActiveConnection *active, + NMActiveConnection *parent_ac, + NMManager * self); + +static NMActiveConnection *active_connection_find(NMManager * self, + NMSettingsConnection * sett_conn, + const char * uuid, + NMActiveConnectionState max_state, + GPtrArray ** out_all_matching); + +static NMConnectivity *concheck_get_mgr(NMManager *self); + +static void _internal_activation_auth_done(NMManager * self, + NMActiveConnection *active, + gboolean success, + const char * error_desc); +static void _add_and_activate_auth_done(NMManager * self, + AsyncOpType async_op_type, + NMActiveConnection * active, + NMConnection * connection, + GDBusMethodInvocation * invocation, + NMSettingsConnectionPersistMode persist_mode, + gboolean is_volatile, + gboolean success, + const char * error_desc); +static void _activation_auth_done(NMManager * self, + NMActiveConnection * active, + GDBusMethodInvocation *invocation, + gboolean success, + const char * error_desc); /*****************************************************************************/ -static -NM_CACHED_QUARK_FCN ("autoconnect-root", autoconnect_root_quark) +static NM_CACHED_QUARK_FCN("autoconnect-root", autoconnect_root_quark); /*****************************************************************************/ static gboolean -_connection_is_vpn (NMConnection *connection) +_connection_is_vpn(NMConnection *connection) { - const char *type; + const char *type; - type = nm_connection_get_connection_type (connection); - if (type) - return nm_streq (type, NM_SETTING_VPN_SETTING_NAME); + type = nm_connection_get_connection_type(connection); + if (type) + return nm_streq(type, NM_SETTING_VPN_SETTING_NAME); - /* we have an incomplete (invalid) connection at hand. That can only - * happen during AddAndActivate. Determine whether it's VPN type based - * on the existence of a [vpn] section. */ - return !!nm_connection_get_setting_vpn (connection); + /* we have an incomplete (invalid) connection at hand. That can only + * happen during AddAndActivate. Determine whether it's VPN type based + * on the existence of a [vpn] section. */ + return !!nm_connection_get_setting_vpn(connection); } /*****************************************************************************/ static gboolean -concheck_enabled (NMManager *self, gboolean *out_changed) +concheck_enabled(NMManager *self, gboolean *out_changed) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - guint check_enabled; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + guint check_enabled; - check_enabled = nm_connectivity_check_enabled (concheck_get_mgr (self)) - ? 1 : 2; - if (priv->connectivity_check_enabled_last == check_enabled) - NM_SET_OUT (out_changed, FALSE); - else { - NM_SET_OUT (out_changed, TRUE); - priv->connectivity_check_enabled_last = check_enabled; - } - return check_enabled == 1; + check_enabled = nm_connectivity_check_enabled(concheck_get_mgr(self)) ? 1 : 2; + if (priv->connectivity_check_enabled_last == check_enabled) + NM_SET_OUT(out_changed, FALSE); + else { + NM_SET_OUT(out_changed, TRUE); + priv->connectivity_check_enabled_last = check_enabled; + } + return check_enabled == 1; } static void -concheck_config_changed_cb (NMConnectivity *connectivity, - NMManager *self) +concheck_config_changed_cb(NMConnectivity *connectivity, NMManager *self) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device; - gboolean changed; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + NMDevice * device; + gboolean changed; - concheck_enabled (self, &changed); - if (changed) - _notify (self, PROP_CONNECTIVITY_CHECK_ENABLED); + concheck_enabled(self, &changed); + if (changed) + _notify(self, PROP_CONNECTIVITY_CHECK_ENABLED); - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) - nm_device_check_connectivity_update_interval (device); + c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) + nm_device_check_connectivity_update_interval(device); } static NMConnectivity * -concheck_get_mgr (NMManager *self) +concheck_get_mgr(NMManager *self) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); - if (G_UNLIKELY (!priv->concheck_mgr)) { - priv->concheck_mgr = g_object_ref (nm_connectivity_get ()); - g_signal_connect (priv->concheck_mgr, - NM_CONNECTIVITY_CONFIG_CHANGED, - G_CALLBACK (concheck_config_changed_cb), - self); - } - return priv->concheck_mgr; + if (G_UNLIKELY(!priv->concheck_mgr)) { + priv->concheck_mgr = g_object_ref(nm_connectivity_get()); + g_signal_connect(priv->concheck_mgr, + NM_CONNECTIVITY_CONFIG_CHANGED, + G_CALLBACK(concheck_config_changed_cb), + self); + } + return priv->concheck_mgr; } /*****************************************************************************/ static AsyncOpData * -_async_op_data_new_authorize_activate_internal (NMManager *self, NMActiveConnection *active_take) +_async_op_data_new_authorize_activate_internal(NMManager *self, NMActiveConnection *active_take) { - AsyncOpData *async_op_data; + AsyncOpData *async_op_data; - async_op_data = g_slice_new0 (AsyncOpData); - async_op_data->async_op_type = ASYNC_OP_TYPE_AC_AUTH_ACTIVATE_INTERNAL; - async_op_data->self = g_object_ref (self); - async_op_data->ac_auth.active = active_take; - c_list_link_tail (&NM_MANAGER_GET_PRIVATE (self)->async_op_lst_head, &async_op_data->async_op_lst); - return async_op_data; + async_op_data = g_slice_new0(AsyncOpData); + async_op_data->async_op_type = ASYNC_OP_TYPE_AC_AUTH_ACTIVATE_INTERNAL; + async_op_data->self = g_object_ref(self); + async_op_data->ac_auth.active = active_take; + c_list_link_tail(&NM_MANAGER_GET_PRIVATE(self)->async_op_lst_head, + &async_op_data->async_op_lst); + return async_op_data; } static AsyncOpData * -_async_op_data_new_ac_auth_activate_user (NMManager *self, - NMActiveConnection *active_take, - GDBusMethodInvocation *invocation_take) +_async_op_data_new_ac_auth_activate_user(NMManager * self, + NMActiveConnection * active_take, + GDBusMethodInvocation *invocation_take) { - AsyncOpData *async_op_data; + AsyncOpData *async_op_data; - async_op_data = g_slice_new0 (AsyncOpData); - async_op_data->async_op_type = ASYNC_OP_TYPE_AC_AUTH_ACTIVATE_USER; - async_op_data->self = g_object_ref (self); - async_op_data->ac_auth.active = active_take; - async_op_data->ac_auth.activate_user.invocation = invocation_take; - c_list_link_tail (&NM_MANAGER_GET_PRIVATE (self)->async_op_lst_head, &async_op_data->async_op_lst); - return async_op_data; + async_op_data = g_slice_new0(AsyncOpData); + async_op_data->async_op_type = ASYNC_OP_TYPE_AC_AUTH_ACTIVATE_USER; + async_op_data->self = g_object_ref(self); + async_op_data->ac_auth.active = active_take; + async_op_data->ac_auth.activate_user.invocation = invocation_take; + c_list_link_tail(&NM_MANAGER_GET_PRIVATE(self)->async_op_lst_head, + &async_op_data->async_op_lst); + return async_op_data; } static AsyncOpData * -_async_op_data_new_ac_auth_add_and_activate (NMManager *self, - AsyncOpType async_op_type, - NMActiveConnection *active_take, - GDBusMethodInvocation *invocation_take, - NMConnection *connection_take, - NMSettingsConnectionPersistMode persist_mode, - gboolean is_volatile) -{ - AsyncOpData *async_op_data; - - nm_assert (NM_IN_SET (async_op_type, ASYNC_OP_TYPE_AC_AUTH_ADD_AND_ACTIVATE, - ASYNC_OP_TYPE_AC_AUTH_ADD_AND_ACTIVATE2)); - - async_op_data = g_slice_new0 (AsyncOpData); - async_op_data->async_op_type = async_op_type; - async_op_data->self = g_object_ref (self); - async_op_data->ac_auth.active = active_take; - async_op_data->ac_auth.add_and_activate.invocation = invocation_take; - async_op_data->ac_auth.add_and_activate.connection = connection_take; - async_op_data->ac_auth.add_and_activate.persist_mode = persist_mode; - async_op_data->ac_auth.add_and_activate.is_volatile = is_volatile; - c_list_link_tail (&NM_MANAGER_GET_PRIVATE (self)->async_op_lst_head, &async_op_data->async_op_lst); - return async_op_data; +_async_op_data_new_ac_auth_add_and_activate(NMManager * self, + AsyncOpType async_op_type, + NMActiveConnection * active_take, + GDBusMethodInvocation * invocation_take, + NMConnection * connection_take, + NMSettingsConnectionPersistMode persist_mode, + gboolean is_volatile) +{ + AsyncOpData *async_op_data; + + nm_assert(NM_IN_SET(async_op_type, + ASYNC_OP_TYPE_AC_AUTH_ADD_AND_ACTIVATE, + ASYNC_OP_TYPE_AC_AUTH_ADD_AND_ACTIVATE2)); + + async_op_data = g_slice_new0(AsyncOpData); + async_op_data->async_op_type = async_op_type; + async_op_data->self = g_object_ref(self); + async_op_data->ac_auth.active = active_take; + async_op_data->ac_auth.add_and_activate.invocation = invocation_take; + async_op_data->ac_auth.add_and_activate.connection = connection_take; + async_op_data->ac_auth.add_and_activate.persist_mode = persist_mode; + async_op_data->ac_auth.add_and_activate.is_volatile = is_volatile; + c_list_link_tail(&NM_MANAGER_GET_PRIVATE(self)->async_op_lst_head, + &async_op_data->async_op_lst); + return async_op_data; } static void -_async_op_complete_ac_auth_cb (NMActiveConnection *active, - gboolean success, - const char *error_desc, - gpointer user_data) -{ - AsyncOpData *async_op_data = user_data; - - nm_assert (async_op_data); - nm_assert (NM_IS_MANAGER (async_op_data->self)); - nm_assert (nm_c_list_contains_entry (&NM_MANAGER_GET_PRIVATE (async_op_data->self)->async_op_lst_head, async_op_data, async_op_lst)); - nm_assert (NM_IS_ACTIVE_CONNECTION (active)); - nm_assert (active == async_op_data->ac_auth.active); - - c_list_unlink (&async_op_data->async_op_lst); - - switch (async_op_data->async_op_type) { - case ASYNC_OP_TYPE_AC_AUTH_ACTIVATE_INTERNAL: - _internal_activation_auth_done (async_op_data->self, - async_op_data->ac_auth.active, - success, - error_desc); - break; - case ASYNC_OP_TYPE_AC_AUTH_ACTIVATE_USER: - _activation_auth_done (async_op_data->self, - async_op_data->ac_auth.active, - async_op_data->ac_auth.activate_user.invocation, - success, - error_desc); - break; - case ASYNC_OP_TYPE_AC_AUTH_ADD_AND_ACTIVATE: - case ASYNC_OP_TYPE_AC_AUTH_ADD_AND_ACTIVATE2: - _add_and_activate_auth_done (async_op_data->self, - async_op_data->async_op_type, - async_op_data->ac_auth.active, - async_op_data->ac_auth.add_and_activate.connection, - async_op_data->ac_auth.add_and_activate.invocation, - async_op_data->ac_auth.add_and_activate.persist_mode, - async_op_data->ac_auth.add_and_activate.is_volatile, - success, - error_desc); - g_object_unref (async_op_data->ac_auth.add_and_activate.connection); - break; - default: - nm_assert_not_reached (); - break; - } - - g_object_unref (async_op_data->ac_auth.active); - g_object_unref (async_op_data->self); - g_slice_free (AsyncOpData, async_op_data); +_async_op_complete_ac_auth_cb(NMActiveConnection *active, + gboolean success, + const char * error_desc, + gpointer user_data) +{ + AsyncOpData *async_op_data = user_data; + + nm_assert(async_op_data); + nm_assert(NM_IS_MANAGER(async_op_data->self)); + nm_assert( + nm_c_list_contains_entry(&NM_MANAGER_GET_PRIVATE(async_op_data->self)->async_op_lst_head, + async_op_data, + async_op_lst)); + nm_assert(NM_IS_ACTIVE_CONNECTION(active)); + nm_assert(active == async_op_data->ac_auth.active); + + c_list_unlink(&async_op_data->async_op_lst); + + switch (async_op_data->async_op_type) { + case ASYNC_OP_TYPE_AC_AUTH_ACTIVATE_INTERNAL: + _internal_activation_auth_done(async_op_data->self, + async_op_data->ac_auth.active, + success, + error_desc); + break; + case ASYNC_OP_TYPE_AC_AUTH_ACTIVATE_USER: + _activation_auth_done(async_op_data->self, + async_op_data->ac_auth.active, + async_op_data->ac_auth.activate_user.invocation, + success, + error_desc); + break; + case ASYNC_OP_TYPE_AC_AUTH_ADD_AND_ACTIVATE: + case ASYNC_OP_TYPE_AC_AUTH_ADD_AND_ACTIVATE2: + _add_and_activate_auth_done(async_op_data->self, + async_op_data->async_op_type, + async_op_data->ac_auth.active, + async_op_data->ac_auth.add_and_activate.connection, + async_op_data->ac_auth.add_and_activate.invocation, + async_op_data->ac_auth.add_and_activate.persist_mode, + async_op_data->ac_auth.add_and_activate.is_volatile, + success, + error_desc); + g_object_unref(async_op_data->ac_auth.add_and_activate.connection); + break; + default: + nm_assert_not_reached(); + break; + } + + g_object_unref(async_op_data->ac_auth.active); + g_object_unref(async_op_data->self); + g_slice_free(AsyncOpData, async_op_data); } /*****************************************************************************/ typedef struct { - int ifindex; - guint32 aspired_metric; - guint32 effective_metric; + int ifindex; + guint32 aspired_metric; + guint32 effective_metric; } DeviceRouteMetricData; static DeviceRouteMetricData * -_device_route_metric_data_new (int ifindex, guint32 aspired_metric, guint32 effective_metric) +_device_route_metric_data_new(int ifindex, guint32 aspired_metric, guint32 effective_metric) { - DeviceRouteMetricData *data; + DeviceRouteMetricData *data; - nm_assert (ifindex > 0); + nm_assert(ifindex > 0); - /* For IPv4, metrics can use the entire uint32 bit range. For IPv6, - * zero is treated like 1024. Since we handle IPv4 and IPv6 identically, - * we cannot allow a zero metric here. - */ - nm_assert (aspired_metric > 0); - nm_assert (effective_metric == 0 || aspired_metric <= effective_metric); + /* For IPv4, metrics can use the entire uint32 bit range. For IPv6, + * zero is treated like 1024. Since we handle IPv4 and IPv6 identically, + * we cannot allow a zero metric here. + */ + nm_assert(aspired_metric > 0); + nm_assert(effective_metric == 0 || aspired_metric <= effective_metric); - data = g_slice_new0 (DeviceRouteMetricData); - data->ifindex = ifindex; - data->aspired_metric = aspired_metric; - data->effective_metric = effective_metric ?: aspired_metric; - return data; + data = g_slice_new0(DeviceRouteMetricData); + data->ifindex = ifindex; + data->aspired_metric = aspired_metric; + data->effective_metric = effective_metric ?: aspired_metric; + return data; } static guint -_device_route_metric_data_by_ifindex_hash (gconstpointer p) +_device_route_metric_data_by_ifindex_hash(gconstpointer p) { - const DeviceRouteMetricData *data = p; - NMHashState h; + const DeviceRouteMetricData *data = p; + NMHashState h; - nm_hash_init (&h, 1030338191); - nm_hash_update_vals (&h, data->ifindex); - return nm_hash_complete (&h); + nm_hash_init(&h, 1030338191); + nm_hash_update_vals(&h, data->ifindex); + return nm_hash_complete(&h); } static gboolean -_device_route_metric_data_by_ifindex_equal (gconstpointer pa, gconstpointer pb) +_device_route_metric_data_by_ifindex_equal(gconstpointer pa, gconstpointer pb) { - const DeviceRouteMetricData *a = pa; - const DeviceRouteMetricData *b = pb; + const DeviceRouteMetricData *a = pa; + const DeviceRouteMetricData *b = pb; - return a->ifindex == b->ifindex; + return a->ifindex == b->ifindex; } static guint32 -_device_route_metric_get (NMManager *self, - int ifindex, - NMDeviceType device_type, - gboolean lookup_only, - guint32 *out_aspired_metric) -{ - NMManagerPrivate *priv; - const DeviceRouteMetricData *d2; - DeviceRouteMetricData *data; - DeviceRouteMetricData data_lookup; - const NMDedupMultiHeadEntry *all_links_head; - NMPObject links_needle; - guint n_links; - gboolean cleaned = FALSE; - GHashTableIter h_iter; - guint32 metric; - - g_return_val_if_fail (NM_IS_MANAGER (self), 0); - - NM_SET_OUT (out_aspired_metric, 0); - - if (ifindex <= 0) { - if (lookup_only) - return 0; - metric = nm_device_get_route_metric_default (device_type); - NM_SET_OUT (out_aspired_metric, metric); - return metric; - } - - priv = NM_MANAGER_GET_PRIVATE (self); - - if ( lookup_only - && !priv->device_route_metrics) - return 0; - - if (G_UNLIKELY (!priv->device_route_metrics)) { - const GHashTable *h; - const NMConfigDeviceStateData *device_state; - - priv->device_route_metrics = g_hash_table_new_full (_device_route_metric_data_by_ifindex_hash, - _device_route_metric_data_by_ifindex_equal, - NULL, - nm_g_slice_free_fcn (DeviceRouteMetricData)); - cleaned = TRUE; - - /* we need to pre-populate the cache for all (still existing) devices from the state-file */ - h = nm_config_device_state_get_all (priv->config); - if (!h) - goto initited; - - g_hash_table_iter_init (&h_iter, (GHashTable *) h); - while (g_hash_table_iter_next (&h_iter, NULL, (gpointer *) &device_state)) { - if (!device_state->route_metric_default_effective) - continue; - if (!nm_platform_link_get (priv->platform, device_state->ifindex)) { - /* we have the entry in the state file, but (currently) no such - * ifindex exists in platform. Most likely the entry is obsolete, - * hence we skip it. */ - continue; - } - if (!g_hash_table_add (priv->device_route_metrics, - _device_route_metric_data_new (device_state->ifindex, - device_state->route_metric_default_aspired, - device_state->route_metric_default_effective))) - nm_assert_not_reached (); - } - } +_device_route_metric_get(NMManager * self, + int ifindex, + NMDeviceType device_type, + gboolean lookup_only, + guint32 * out_aspired_metric) +{ + NMManagerPrivate * priv; + const DeviceRouteMetricData *d2; + DeviceRouteMetricData * data; + DeviceRouteMetricData data_lookup; + const NMDedupMultiHeadEntry *all_links_head; + NMPObject links_needle; + guint n_links; + gboolean cleaned = FALSE; + GHashTableIter h_iter; + guint32 metric; + + g_return_val_if_fail(NM_IS_MANAGER(self), 0); + + NM_SET_OUT(out_aspired_metric, 0); + + if (ifindex <= 0) { + if (lookup_only) + return 0; + metric = nm_device_get_route_metric_default(device_type); + NM_SET_OUT(out_aspired_metric, metric); + return metric; + } + + priv = NM_MANAGER_GET_PRIVATE(self); + + if (lookup_only && !priv->device_route_metrics) + return 0; + + if (G_UNLIKELY(!priv->device_route_metrics)) { + const GHashTable * h; + const NMConfigDeviceStateData *device_state; + + priv->device_route_metrics = + g_hash_table_new_full(_device_route_metric_data_by_ifindex_hash, + _device_route_metric_data_by_ifindex_equal, + NULL, + nm_g_slice_free_fcn(DeviceRouteMetricData)); + cleaned = TRUE; + + /* we need to pre-populate the cache for all (still existing) devices from the state-file */ + h = nm_config_device_state_get_all(priv->config); + if (!h) + goto initited; + + g_hash_table_iter_init(&h_iter, (GHashTable *) h); + while (g_hash_table_iter_next(&h_iter, NULL, (gpointer *) &device_state)) { + if (!device_state->route_metric_default_effective) + continue; + if (!nm_platform_link_get(priv->platform, device_state->ifindex)) { + /* we have the entry in the state file, but (currently) no such + * ifindex exists in platform. Most likely the entry is obsolete, + * hence we skip it. */ + continue; + } + if (!g_hash_table_add( + priv->device_route_metrics, + _device_route_metric_data_new(device_state->ifindex, + device_state->route_metric_default_aspired, + device_state->route_metric_default_effective))) + nm_assert_not_reached(); + } + } initited: - data_lookup.ifindex = ifindex; - - data = g_hash_table_lookup (priv->device_route_metrics, &data_lookup); - if (data) - goto out; - if (lookup_only) - return 0; - - if (!cleaned) { - /* get the number of all links in the platform cache. */ - all_links_head = nm_platform_lookup_all (priv->platform, - NMP_CACHE_ID_TYPE_OBJECT_TYPE, - nmp_object_stackinit_id_link (&links_needle, 1)); - n_links = all_links_head ? all_links_head->len : 0; - - /* on systems where a lot of devices are created and go away, the index contains - * a lot of stale entries. We must from time to time clean them up. - * - * Do do this cleanup, whenever we have more enties then 2 times the number of links. */ - if (G_UNLIKELY (g_hash_table_size (priv->device_route_metrics) > NM_MAX (20, n_links * 2))) { - /* from time to time, we need to do some house-keeping and prune stale entries. - * Otherwise, on a system where interfaces frequently come and go (docker), we - * keep growing this cache for ifindexes that no longer exist. */ - g_hash_table_iter_init (&h_iter, priv->device_route_metrics); - while (g_hash_table_iter_next (&h_iter, NULL, (gpointer *) &d2)) { - if (!nm_platform_link_get (priv->platform, d2->ifindex)) - g_hash_table_iter_remove (&h_iter); - } - cleaned = TRUE; - } - } - - data = _device_route_metric_data_new (ifindex, nm_device_get_route_metric_default (device_type), 0); - - /* unfortunately, there is no stright forward way to lookup all reserved metrics. - * Note, that we don't only have to know which metrics are currently reserved, - * but also, which metrics are now seemingly un-used but caused another reserved - * metric to be bumped. Hence, the naive O(n^2) search :( - * - * Well, technically, since we limit bumping the metric to 50, this entire - * loop runs at most 50 times, so it's still O(n). Let's just say, it's not - * very efficient. */ + data_lookup.ifindex = ifindex; + + data = g_hash_table_lookup(priv->device_route_metrics, &data_lookup); + if (data) + goto out; + if (lookup_only) + return 0; + + if (!cleaned) { + /* get the number of all links in the platform cache. */ + all_links_head = nm_platform_lookup_all(priv->platform, + NMP_CACHE_ID_TYPE_OBJECT_TYPE, + nmp_object_stackinit_id_link(&links_needle, 1)); + n_links = all_links_head ? all_links_head->len : 0; + + /* on systems where a lot of devices are created and go away, the index contains + * a lot of stale entries. We must from time to time clean them up. + * + * Do do this cleanup, whenever we have more entries then 2 times the number of links. */ + if (G_UNLIKELY(g_hash_table_size(priv->device_route_metrics) > NM_MAX(20, n_links * 2))) { + /* from time to time, we need to do some house-keeping and prune stale entries. + * Otherwise, on a system where interfaces frequently come and go (docker), we + * keep growing this cache for ifindexes that no longer exist. */ + g_hash_table_iter_init(&h_iter, priv->device_route_metrics); + while (g_hash_table_iter_next(&h_iter, NULL, (gpointer *) &d2)) { + if (!nm_platform_link_get(priv->platform, d2->ifindex)) + g_hash_table_iter_remove(&h_iter); + } + cleaned = TRUE; + } + } + + data = + _device_route_metric_data_new(ifindex, nm_device_get_route_metric_default(device_type), 0); + + /* unfortunately, there is no stright forward way to lookup all reserved metrics. + * Note, that we don't only have to know which metrics are currently reserved, + * but also, which metrics are now seemingly un-used but caused another reserved + * metric to be bumped. Hence, the naive O(n^2) search :( + * + * Well, technically, since we limit bumping the metric to 50, this entire + * loop runs at most 50 times, so it's still O(n). Let's just say, it's not + * very efficient. */ again: - g_hash_table_iter_init (&h_iter, priv->device_route_metrics); - while (g_hash_table_iter_next (&h_iter, NULL, (gpointer *) &d2)) { - if ( data->effective_metric < d2->aspired_metric - || data->effective_metric > d2->effective_metric) { - /* no overlap. Skip. */ - continue; - } - if ( !cleaned - && !nm_platform_link_get (priv->platform, d2->ifindex)) { - /* the metric seems taken, but there is no such interface. This entry - * is stale, forget about it. */ - g_hash_table_iter_remove (&h_iter); - continue; - } - - if (d2->effective_metric == G_MAXUINT32) { - /* we cannot bump the metric any further. Done. - * - * Actually, this can currently not happen because the aspired_metric - * are small numbers and we limit the bumping to 50. Still, for - * completeness... */ - data->effective_metric = G_MAXUINT32; - break; - } - - if (d2->effective_metric - data->aspired_metric >= 50) { - /* as one active interface reserves an entire range of metrics - * (from aspired_metric to effective_metric), that means if you - * alternatingly activate two interfaces, their metric will - * bump each other. - * - * Limit this, bump the metric at most 50 points. */ - data->effective_metric = data->aspired_metric + 50; - break; - } - - /* bump the metric, and search again. */ - data->effective_metric = d2->effective_metric + 1; - goto again; - } - - _LOGT (LOGD_DEVICE, "default-route-metric: ifindex %d reserves metric %u (aspired %u)", - data->ifindex, data->effective_metric, data->aspired_metric); - - if (!g_hash_table_add (priv->device_route_metrics, data)) - nm_assert_not_reached (); + g_hash_table_iter_init(&h_iter, priv->device_route_metrics); + while (g_hash_table_iter_next(&h_iter, NULL, (gpointer *) &d2)) { + if (data->effective_metric < d2->aspired_metric + || data->effective_metric > d2->effective_metric) { + /* no overlap. Skip. */ + continue; + } + if (!cleaned && !nm_platform_link_get(priv->platform, d2->ifindex)) { + /* the metric seems taken, but there is no such interface. This entry + * is stale, forget about it. */ + g_hash_table_iter_remove(&h_iter); + continue; + } + + if (d2->effective_metric == G_MAXUINT32) { + /* we cannot bump the metric any further. Done. + * + * Actually, this can currently not happen because the aspired_metric + * are small numbers and we limit the bumping to 50. Still, for + * completeness... */ + data->effective_metric = G_MAXUINT32; + break; + } + + if (d2->effective_metric - data->aspired_metric >= 50) { + /* as one active interface reserves an entire range of metrics + * (from aspired_metric to effective_metric), that means if you + * alternatingly activate two interfaces, their metric will + * bump each other. + * + * Limit this, bump the metric at most 50 points. */ + data->effective_metric = data->aspired_metric + 50; + break; + } + + /* bump the metric, and search again. */ + data->effective_metric = d2->effective_metric + 1; + goto again; + } + + _LOGT(LOGD_DEVICE, + "default-route-metric: ifindex %d reserves metric %u (aspired %u)", + data->ifindex, + data->effective_metric, + data->aspired_metric); + + if (!g_hash_table_add(priv->device_route_metrics, data)) + nm_assert_not_reached(); out: - NM_SET_OUT (out_aspired_metric, data->aspired_metric); - return data->effective_metric; + NM_SET_OUT(out_aspired_metric, data->aspired_metric); + return data->effective_metric; } guint32 -nm_manager_device_route_metric_reserve (NMManager *self, - int ifindex, - NMDeviceType device_type) +nm_manager_device_route_metric_reserve(NMManager *self, int ifindex, NMDeviceType device_type) { - guint32 metric; + guint32 metric; - metric = _device_route_metric_get (self, ifindex, device_type, FALSE, NULL); - nm_assert (metric != 0); - return metric; + metric = _device_route_metric_get(self, ifindex, device_type, FALSE, NULL); + nm_assert(metric != 0); + return metric; } void -nm_manager_device_route_metric_clear (NMManager *self, - int ifindex) +nm_manager_device_route_metric_clear(NMManager *self, int ifindex) { - NMManagerPrivate *priv; - DeviceRouteMetricData data_lookup; + NMManagerPrivate * priv; + DeviceRouteMetricData data_lookup; - priv = NM_MANAGER_GET_PRIVATE (self); + priv = NM_MANAGER_GET_PRIVATE(self); - if (!priv->device_route_metrics) - return; - data_lookup.ifindex = ifindex; - if (g_hash_table_remove (priv->device_route_metrics, &data_lookup)) { - _LOGT (LOGD_DEVICE, "default-route-metric: ifindex %d released", - ifindex); - } + if (!priv->device_route_metrics) + return; + data_lookup.ifindex = ifindex; + if (g_hash_table_remove(priv->device_route_metrics, &data_lookup)) { + _LOGT(LOGD_DEVICE, "default-route-metric: ifindex %d released", ifindex); + } } /*****************************************************************************/ static void -_delete_volatile_connection_do (NMManager *self, - NMSettingsConnection *connection) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - - if (!NM_FLAGS_ANY (nm_settings_connection_get_flags (connection), - NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE - | NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL)) - return; - if (!nm_settings_has_connection (priv->settings, connection)) - return; - if (active_connection_find (self, - connection, - NULL, - NM_ACTIVE_CONNECTION_STATE_DEACTIVATED, - NULL)) - return; - - _LOGD (LOGD_DEVICE, "volatile connection disconnected. Deleting connection '%s' (%s)", - nm_settings_connection_get_id (connection), nm_settings_connection_get_uuid (connection)); - nm_settings_connection_delete (connection, FALSE); +_delete_volatile_connection_do(NMManager *self, NMSettingsConnection *connection) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + + if (!NM_FLAGS_ANY(nm_settings_connection_get_flags(connection), + NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE + | NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL)) + return; + if (!nm_settings_has_connection(priv->settings, connection)) + return; + if (active_connection_find(self, + connection, + NULL, + NM_ACTIVE_CONNECTION_STATE_DEACTIVATED, + NULL)) + return; + + _LOGD(LOGD_DEVICE, + "volatile connection disconnected. Deleting connection '%s' (%s)", + nm_settings_connection_get_id(connection), + nm_settings_connection_get_uuid(connection)); + nm_settings_connection_delete(connection, FALSE); } /* Returns: whether to notify D-Bus of the removal or not */ static gboolean -active_connection_remove (NMManager *self, NMActiveConnection *active) +active_connection_remove(NMManager *self, NMActiveConnection *active) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - gs_unref_object NMSettingsConnection *connection = NULL; - gboolean notify; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + gs_unref_object NMSettingsConnection *connection = NULL; + gboolean notify; - nm_assert (NM_IS_ACTIVE_CONNECTION (active)); - nm_assert (c_list_contains (&priv->active_connections_lst_head, &active->active_connections_lst)); + nm_assert(NM_IS_ACTIVE_CONNECTION(active)); + nm_assert(c_list_contains(&priv->active_connections_lst_head, &active->active_connections_lst)); - notify = nm_dbus_object_is_exported (NM_DBUS_OBJECT (active)); + notify = nm_dbus_object_is_exported(NM_DBUS_OBJECT(active)); - c_list_unlink (&active->active_connections_lst); - g_signal_emit (self, signals[ACTIVE_CONNECTION_REMOVED], 0, active); - g_signal_handlers_disconnect_by_func (active, active_connection_state_changed, self); - g_signal_handlers_disconnect_by_func (active, active_connection_default_changed, self); - g_signal_handlers_disconnect_by_func (active, active_connection_parent_active, self); + c_list_unlink(&active->active_connections_lst); + g_signal_emit(self, signals[ACTIVE_CONNECTION_REMOVED], 0, active); + g_signal_handlers_disconnect_by_func(active, active_connection_state_changed, self); + g_signal_handlers_disconnect_by_func(active, active_connection_default_changed, self); + g_signal_handlers_disconnect_by_func(active, active_connection_parent_active, self); - connection = nm_g_object_ref (nm_active_connection_get_settings_connection (active)); + connection = nm_g_object_ref(nm_active_connection_get_settings_connection(active)); - nm_dbus_object_clear_and_unexport (&active); + nm_dbus_object_clear_and_unexport(&active); - if (connection) - _delete_volatile_connection_do (self, connection); + if (connection) + _delete_volatile_connection_do(self, connection); - return notify; + return notify; } static gboolean -_active_connection_cleanup (gpointer user_data) +_active_connection_cleanup(gpointer user_data) { - NMManager *self = NM_MANAGER (user_data); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMActiveConnection *ac, *ac_safe; + NMManager * self = NM_MANAGER(user_data); + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + NMActiveConnection *ac, *ac_safe; - priv->ac_cleanup_id = 0; + priv->ac_cleanup_id = 0; - g_object_freeze_notify (G_OBJECT (self)); - c_list_for_each_entry_safe (ac, ac_safe, &priv->active_connections_lst_head, active_connections_lst) { - if (nm_active_connection_get_state (ac) == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) { - if (active_connection_remove (self, ac)) - _notify (self, PROP_ACTIVE_CONNECTIONS); - } - } - g_object_thaw_notify (G_OBJECT (self)); + g_object_freeze_notify(G_OBJECT(self)); + c_list_for_each_entry_safe (ac, + ac_safe, + &priv->active_connections_lst_head, + active_connections_lst) { + if (nm_active_connection_get_state(ac) == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) { + if (active_connection_remove(self, ac)) + _notify(self, PROP_ACTIVE_CONNECTIONS); + } + } + g_object_thaw_notify(G_OBJECT(self)); - return FALSE; + return FALSE; } static void -active_connection_state_changed (NMActiveConnection *active, - GParamSpec *pspec, - NMManager *self) +active_connection_state_changed(NMActiveConnection *active, GParamSpec *pspec, NMManager *self) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMActiveConnectionState state; - NMSettingsConnection *con; + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + NMActiveConnectionState state; + NMSettingsConnection * con; - state = nm_active_connection_get_state (active); - if (state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) { - /* Destroy active connections from an idle handler to ensure that - * their last property change notifications go out, which wouldn't - * happen if we destroyed them immediately when their state was set - * to DEACTIVATED. - */ - if (!priv->ac_cleanup_id) - priv->ac_cleanup_id = g_idle_add (_active_connection_cleanup, self); + state = nm_active_connection_get_state(active); + if (state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) { + /* Destroy active connections from an idle handler to ensure that + * their last property change notifications go out, which wouldn't + * happen if we destroyed them immediately when their state was set + * to DEACTIVATED. + */ + if (!priv->ac_cleanup_id) + priv->ac_cleanup_id = g_idle_add(_active_connection_cleanup, self); - con = nm_active_connection_get_settings_connection (active); - if (con) - g_object_set_qdata (G_OBJECT (con), autoconnect_root_quark (), NULL); - } + con = nm_active_connection_get_settings_connection(active); + if (con) + g_object_set_qdata(G_OBJECT(con), autoconnect_root_quark(), NULL); + } - nm_manager_update_state (self); + nm_manager_update_state(self); } static void -active_connection_default_changed (NMActiveConnection *active, - GParamSpec *pspec, - NMManager *self) +active_connection_default_changed(NMActiveConnection *active, GParamSpec *pspec, NMManager *self) { - nm_manager_update_state (self); + nm_manager_update_state(self); } /** @@ -926,380 +934,376 @@ active_connection_default_changed (NMActiveConnection *active, * Begins to track and manage @active. Increases the refcount of @active. */ static void -active_connection_add (NMManager *self, - NMActiveConnection *active) +active_connection_add(NMManager *self, NMActiveConnection *active) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); - nm_assert (NM_IS_ACTIVE_CONNECTION (active)); - nm_assert (!c_list_is_linked (&active->active_connections_lst)); + nm_assert(NM_IS_ACTIVE_CONNECTION(active)); + nm_assert(!c_list_is_linked(&active->active_connections_lst)); - c_list_link_front (&priv->active_connections_lst_head, &active->active_connections_lst); - g_object_ref (active); + c_list_link_front(&priv->active_connections_lst_head, &active->active_connections_lst); + g_object_ref(active); - g_signal_connect (active, - "notify::" NM_ACTIVE_CONNECTION_STATE, - G_CALLBACK (active_connection_state_changed), - self); - g_signal_connect (active, - "notify::" NM_ACTIVE_CONNECTION_DEFAULT, - G_CALLBACK (active_connection_default_changed), - self); - g_signal_connect (active, - "notify::" NM_ACTIVE_CONNECTION_DEFAULT6, - G_CALLBACK (active_connection_default_changed), - self); + g_signal_connect(active, + "notify::" NM_ACTIVE_CONNECTION_STATE, + G_CALLBACK(active_connection_state_changed), + self); + g_signal_connect(active, + "notify::" NM_ACTIVE_CONNECTION_DEFAULT, + G_CALLBACK(active_connection_default_changed), + self); + g_signal_connect(active, + "notify::" NM_ACTIVE_CONNECTION_DEFAULT6, + G_CALLBACK(active_connection_default_changed), + self); - if (!nm_dbus_object_is_exported (NM_DBUS_OBJECT (active))) - nm_dbus_object_export (NM_DBUS_OBJECT (active)); + if (!nm_dbus_object_is_exported(NM_DBUS_OBJECT(active))) + nm_dbus_object_export(NM_DBUS_OBJECT(active)); - g_signal_emit (self, signals[ACTIVE_CONNECTION_ADDED], 0, active); + g_signal_emit(self, signals[ACTIVE_CONNECTION_ADDED], 0, active); - _notify (self, PROP_ACTIVE_CONNECTIONS); + _notify(self, PROP_ACTIVE_CONNECTIONS); } const CList * -nm_manager_get_active_connections (NMManager *manager) +nm_manager_get_active_connections(NMManager *manager) { - return &NM_MANAGER_GET_PRIVATE (manager)->active_connections_lst_head; + return &NM_MANAGER_GET_PRIVATE(manager)->active_connections_lst_head; } static NMActiveConnection * -active_connection_find (NMManager *self, - NMSettingsConnection *sett_conn, - const char *uuid, - NMActiveConnectionState max_state /* candidates in state @max_state will be found */, - GPtrArray **out_all_matching) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMActiveConnection *ac; - NMActiveConnection *best_ac = NULL; - GPtrArray *all = NULL; - - nm_assert (!sett_conn || NM_IS_SETTINGS_CONNECTION (sett_conn)); - nm_assert (!out_all_matching || !*out_all_matching); - - c_list_for_each_entry (ac, &priv->active_connections_lst_head, active_connections_lst) { - NMSettingsConnection *ac_conn; - - ac_conn = nm_active_connection_get_settings_connection (ac); - if ( sett_conn - && sett_conn != ac_conn) - continue; - if ( uuid - && !nm_streq0 (uuid, nm_settings_connection_get_uuid (ac_conn))) - continue; - if (nm_active_connection_get_state (ac) > max_state) - continue; - - if (!out_all_matching) - return ac; - - if (!best_ac) { - best_ac = ac; - continue; - } - - if (!all) { - all = g_ptr_array_new_with_free_func (g_object_unref); - g_ptr_array_add (all, g_object_ref (best_ac)); - } - g_ptr_array_add (all, g_object_ref (ac)); - } - - if (!best_ac) - return NULL; - - /* as an optimization, we only allocate out_all_matching, if there are more - * than one result. If there is only one result, we only return the single - * element and don't bother allocating an array. That's the common case. - * - * Also, in case we have multiple results, we return the *first* one - * as @best_ac. */ - nm_assert ( !all - || ( all->len >= 2 - && all->pdata[0] == best_ac)); - - *out_all_matching = all; - return best_ac; +active_connection_find( + NMManager * self, + NMSettingsConnection * sett_conn, + const char * uuid, + NMActiveConnectionState max_state /* candidates in state @max_state will be found */, + GPtrArray ** out_all_matching) +{ + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + NMActiveConnection *ac; + NMActiveConnection *best_ac = NULL; + GPtrArray * all = NULL; + + nm_assert(!sett_conn || NM_IS_SETTINGS_CONNECTION(sett_conn)); + nm_assert(!out_all_matching || !*out_all_matching); + + c_list_for_each_entry (ac, &priv->active_connections_lst_head, active_connections_lst) { + NMSettingsConnection *ac_conn; + + ac_conn = nm_active_connection_get_settings_connection(ac); + if (sett_conn && sett_conn != ac_conn) + continue; + if (uuid && !nm_streq0(uuid, nm_settings_connection_get_uuid(ac_conn))) + continue; + if (nm_active_connection_get_state(ac) > max_state) + continue; + + if (!out_all_matching) + return ac; + + if (!best_ac) { + best_ac = ac; + continue; + } + + if (!all) { + all = g_ptr_array_new_with_free_func(g_object_unref); + g_ptr_array_add(all, g_object_ref(best_ac)); + } + g_ptr_array_add(all, g_object_ref(ac)); + } + + if (!best_ac) + return NULL; + + /* as an optimization, we only allocate out_all_matching, if there are more + * than one result. If there is only one result, we only return the single + * element and don't bother allocating an array. That's the common case. + * + * Also, in case we have multiple results, we return the *first* one + * as @best_ac. */ + nm_assert(!all || (all->len >= 2 && all->pdata[0] == best_ac)); + + *out_all_matching = all; + return best_ac; } static NMActiveConnection * -active_connection_find_by_connection (NMManager *self, - NMSettingsConnection *sett_conn, - NMConnection *connection, - NMActiveConnectionState max_state, - GPtrArray **out_all_matching) -{ - nm_assert (NM_IS_MANAGER (self)); - nm_assert (!sett_conn || NM_IS_SETTINGS_CONNECTION (sett_conn)); - nm_assert (!connection || NM_IS_CONNECTION (connection)); - nm_assert (sett_conn || connection); - nm_assert (!connection || !sett_conn || connection == nm_settings_connection_get_connection (sett_conn)); - - /* Depending on whether connection is a settings connection, - * either lookup by object-identity of @connection, or compare the UUID */ - return active_connection_find (self, - sett_conn, - sett_conn ? NULL : nm_connection_get_uuid (connection), - max_state, - out_all_matching); +active_connection_find_by_connection(NMManager * self, + NMSettingsConnection * sett_conn, + NMConnection * connection, + NMActiveConnectionState max_state, + GPtrArray ** out_all_matching) +{ + nm_assert(NM_IS_MANAGER(self)); + nm_assert(!sett_conn || NM_IS_SETTINGS_CONNECTION(sett_conn)); + nm_assert(!connection || NM_IS_CONNECTION(connection)); + nm_assert(sett_conn || connection); + nm_assert(!connection || !sett_conn + || connection == nm_settings_connection_get_connection(sett_conn)); + + /* Depending on whether connection is a settings connection, + * either lookup by object-identity of @connection, or compare the UUID */ + return active_connection_find(self, + sett_conn, + sett_conn ? NULL : nm_connection_get_uuid(connection), + max_state, + out_all_matching); } typedef struct { - NMManager *self; - gboolean for_auto_activation; + NMManager *self; + gboolean for_auto_activation; } GetActivatableConnectionsFilterData; static gboolean -_get_activatable_connections_filter (NMSettings *settings, - NMSettingsConnection *sett_conn, - gpointer user_data) -{ - const GetActivatableConnectionsFilterData *d = user_data; - NMConnectionMultiConnect multi_connect; - - if (NM_FLAGS_ANY (nm_settings_connection_get_flags (sett_conn), - NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE - | NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL)) - return FALSE; - - multi_connect = _nm_connection_get_multi_connect (nm_settings_connection_get_connection (sett_conn)); - if ( multi_connect == NM_CONNECTION_MULTI_CONNECT_MULTIPLE - || ( multi_connect == NM_CONNECTION_MULTI_CONNECT_MANUAL_MULTIPLE - && !d->for_auto_activation)) - return TRUE; - - /* the connection is activatable, if it has no active-connections that are in state - * activated, activating, or waiting to be activated. */ - return !active_connection_find (d->self, - sett_conn, - NULL, - NM_ACTIVE_CONNECTION_STATE_ACTIVATED, - NULL); +_get_activatable_connections_filter(NMSettings * settings, + NMSettingsConnection *sett_conn, + gpointer user_data) +{ + const GetActivatableConnectionsFilterData *d = user_data; + NMConnectionMultiConnect multi_connect; + + if (NM_FLAGS_ANY(nm_settings_connection_get_flags(sett_conn), + NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE + | NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL)) + return FALSE; + + multi_connect = + _nm_connection_get_multi_connect(nm_settings_connection_get_connection(sett_conn)); + if (multi_connect == NM_CONNECTION_MULTI_CONNECT_MULTIPLE + || (multi_connect == NM_CONNECTION_MULTI_CONNECT_MANUAL_MULTIPLE + && !d->for_auto_activation)) + return TRUE; + + /* the connection is activatable, if it has no active-connections that are in state + * activated, activating, or waiting to be activated. */ + return !active_connection_find(d->self, + sett_conn, + NULL, + NM_ACTIVE_CONNECTION_STATE_ACTIVATED, + NULL); } NMSettingsConnection ** -nm_manager_get_activatable_connections (NMManager *manager, - gboolean for_auto_activation, - gboolean sort, - guint *out_len) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - const GetActivatableConnectionsFilterData d = { - .self = manager, - .for_auto_activation = for_auto_activation, - }; - - return nm_settings_get_connections_clone (priv->settings, out_len, - _get_activatable_connections_filter, - (gpointer) &d, - sort ? nm_settings_connection_cmp_autoconnect_priority_p_with_data : NULL, - NULL); +nm_manager_get_activatable_connections(NMManager *manager, + gboolean for_auto_activation, + gboolean sort, + guint * out_len) +{ + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(manager); + const GetActivatableConnectionsFilterData d = { + .self = manager, + .for_auto_activation = for_auto_activation, + }; + + return nm_settings_get_connections_clone( + priv->settings, + out_len, + _get_activatable_connections_filter, + (gpointer) &d, + sort ? nm_settings_connection_cmp_autoconnect_priority_p_with_data : NULL, + NULL); } static NMActiveConnection * -active_connection_get_by_path (NMManager *self, const char *path) +active_connection_get_by_path(NMManager *self, const char *path) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMActiveConnection *ac; + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + NMActiveConnection *ac; - ac = nm_dbus_manager_lookup_object (nm_dbus_object_get_manager (NM_DBUS_OBJECT (self)), - path); - if ( !ac - || !NM_IS_ACTIVE_CONNECTION (ac) - || c_list_is_empty (&ac->active_connections_lst)) - return NULL; + ac = nm_dbus_manager_lookup_object(nm_dbus_object_get_manager(NM_DBUS_OBJECT(self)), path); + if (!ac || !NM_IS_ACTIVE_CONNECTION(ac) || c_list_is_empty(&ac->active_connections_lst)) + return NULL; - nm_assert (c_list_contains (&priv->active_connections_lst_head, &ac->active_connections_lst)); - return ac; + nm_assert(c_list_contains(&priv->active_connections_lst_head, &ac->active_connections_lst)); + return ac; } /*****************************************************************************/ static void -_config_changed_cb (NMConfig *config, NMConfigData *config_data, NMConfigChangeFlags changes, NMConfigData *old_data, NMManager *self) +_config_changed_cb(NMConfig * config, + NMConfigData * config_data, + NMConfigChangeFlags changes, + NMConfigData * old_data, + NMManager * self) { - g_object_freeze_notify (G_OBJECT (self)); + g_object_freeze_notify(G_OBJECT(self)); - if (NM_FLAGS_HAS (changes, NM_CONFIG_CHANGE_GLOBAL_DNS_CONFIG)) - _notify (self, PROP_GLOBAL_DNS_CONFIGURATION); + if (NM_FLAGS_HAS(changes, NM_CONFIG_CHANGE_GLOBAL_DNS_CONFIG)) + _notify(self, PROP_GLOBAL_DNS_CONFIGURATION); - if (!nm_streq0 (nm_config_data_get_connectivity_uri (config_data), - nm_config_data_get_connectivity_uri (old_data))) { - if ((!nm_config_data_get_connectivity_uri (config_data)) != (!nm_config_data_get_connectivity_uri (old_data))) - _notify (self, PROP_CONNECTIVITY_CHECK_AVAILABLE); - _notify (self, PROP_CONNECTIVITY_CHECK_URI); - } + if (!nm_streq0(nm_config_data_get_connectivity_uri(config_data), + nm_config_data_get_connectivity_uri(old_data))) { + if ((!nm_config_data_get_connectivity_uri(config_data)) + != (!nm_config_data_get_connectivity_uri(old_data))) + _notify(self, PROP_CONNECTIVITY_CHECK_AVAILABLE); + _notify(self, PROP_CONNECTIVITY_CHECK_URI); + } - g_object_thaw_notify (G_OBJECT (self)); + g_object_thaw_notify(G_OBJECT(self)); } static void -_reload_auth_cb (NMAuthChain *chain, - GDBusMethodInvocation *context, - gpointer user_data) -{ - NMManager *self = NM_MANAGER (user_data); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - GError *ret_error = NULL; - NMAuthCallResult result; - guint32 flags; - NMAuthSubject *subject; - char s_buf[60]; - NMConfigChangeFlags reload_type = NM_CONFIG_CHANGE_NONE; - - nm_assert (G_IS_DBUS_METHOD_INVOCATION (context)); - - c_list_unlink (nm_auth_chain_parent_lst_list (chain)); - flags = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "flags")); - - subject = nm_auth_chain_get_subject (chain); - - result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_RELOAD); - if (result != NM_AUTH_CALL_RESULT_YES) { - ret_error = g_error_new_literal (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - "Not authorized to reload configuration"); - } else { - if (NM_FLAGS_ANY (flags, ~NM_MANAGER_RELOAD_FLAG_ALL)) { - /* invalid flags */ - } else if (flags == 0) - reload_type = NM_CONFIG_CHANGE_CAUSE_SIGHUP; - else { - if (NM_FLAGS_HAS (flags, NM_MANAGER_RELOAD_FLAG_CONF)) - reload_type |= NM_CONFIG_CHANGE_CAUSE_CONF; - if (NM_FLAGS_HAS (flags, NM_MANAGER_RELOAD_FLAG_DNS_RC)) - reload_type |= NM_CONFIG_CHANGE_CAUSE_DNS_RC; - if (NM_FLAGS_HAS (flags, NM_MANAGER_RELOAD_FLAG_DNS_FULL)) - reload_type |= NM_CONFIG_CHANGE_CAUSE_DNS_FULL; - } - - if (reload_type == NM_CONFIG_CHANGE_NONE) { - ret_error = g_error_new_literal (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_INVALID_ARGUMENTS, - "Invalid flags for reload"); - } - } - - nm_audit_log_control_op (NM_AUDIT_OP_RELOAD, - nm_sprintf_buf (s_buf, "%u", flags), - ret_error == NULL, subject, - ret_error ? ret_error->message : NULL); - - if (ret_error) { - g_dbus_method_invocation_take_error (context, ret_error); - return; - } - - nm_config_reload (priv->config, reload_type, TRUE); - g_dbus_method_invocation_return_value (context, NULL); +_reload_auth_cb(NMAuthChain *chain, GDBusMethodInvocation *context, gpointer user_data) +{ + NMManager * self = NM_MANAGER(user_data); + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + GError * ret_error = NULL; + NMAuthCallResult result; + guint32 flags; + NMAuthSubject * subject; + char s_buf[60]; + NMConfigChangeFlags reload_type = NM_CONFIG_CHANGE_NONE; + + nm_assert(G_IS_DBUS_METHOD_INVOCATION(context)); + + c_list_unlink(nm_auth_chain_parent_lst_list(chain)); + flags = GPOINTER_TO_UINT(nm_auth_chain_get_data(chain, "flags")); + + subject = nm_auth_chain_get_subject(chain); + + result = nm_auth_chain_get_result(chain, NM_AUTH_PERMISSION_RELOAD); + if (result != NM_AUTH_CALL_RESULT_YES) { + ret_error = g_error_new_literal(NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + "Not authorized to reload configuration"); + } else { + if (NM_FLAGS_ANY(flags, ~NM_MANAGER_RELOAD_FLAG_ALL)) { + /* invalid flags */ + } else if (flags == 0) + reload_type = NM_CONFIG_CHANGE_CAUSE_SIGHUP; + else { + if (NM_FLAGS_HAS(flags, NM_MANAGER_RELOAD_FLAG_CONF)) + reload_type |= NM_CONFIG_CHANGE_CAUSE_CONF; + if (NM_FLAGS_HAS(flags, NM_MANAGER_RELOAD_FLAG_DNS_RC)) + reload_type |= NM_CONFIG_CHANGE_CAUSE_DNS_RC; + if (NM_FLAGS_HAS(flags, NM_MANAGER_RELOAD_FLAG_DNS_FULL)) + reload_type |= NM_CONFIG_CHANGE_CAUSE_DNS_FULL; + } + + if (reload_type == NM_CONFIG_CHANGE_NONE) { + ret_error = g_error_new_literal(NM_MANAGER_ERROR, + NM_MANAGER_ERROR_INVALID_ARGUMENTS, + "Invalid flags for reload"); + } + } + + nm_audit_log_control_op(NM_AUDIT_OP_RELOAD, + nm_sprintf_buf(s_buf, "%u", flags), + ret_error == NULL, + subject, + ret_error ? ret_error->message : NULL); + + if (ret_error) { + g_dbus_method_invocation_take_error(context, ret_error); + return; + } + + nm_config_reload(priv->config, reload_type, TRUE); + g_dbus_method_invocation_return_value(context, NULL); } static void -impl_manager_reload (NMDBusObject *obj, - const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended *method_info, - GDBusConnection *connection, - const char *sender, - GDBusMethodInvocation *invocation, - GVariant *parameters) -{ - NMManager *self = NM_MANAGER (obj); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMAuthChain *chain; - guint32 flags; - - g_variant_get (parameters, "(u)", &flags); - - chain = nm_auth_chain_new_context (invocation, _reload_auth_cb, self); - if (!chain) { - g_dbus_method_invocation_return_error_literal (invocation, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - NM_UTILS_ERROR_MSG_REQ_AUTH_FAILED); - return; - } - - c_list_link_tail (&priv->auth_lst_head, nm_auth_chain_parent_lst_list (chain)); - nm_auth_chain_set_data (chain, "flags", GUINT_TO_POINTER (flags), NULL); - nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_RELOAD, TRUE); +impl_manager_reload(NMDBusObject * obj, + const NMDBusInterfaceInfoExtended *interface_info, + const NMDBusMethodInfoExtended * method_info, + GDBusConnection * connection, + const char * sender, + GDBusMethodInvocation * invocation, + GVariant * parameters) +{ + NMManager * self = NM_MANAGER(obj); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + NMAuthChain * chain; + guint32 flags; + + g_variant_get(parameters, "(u)", &flags); + + chain = nm_auth_chain_new_context(invocation, _reload_auth_cb, self); + if (!chain) { + g_dbus_method_invocation_return_error_literal(invocation, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + NM_UTILS_ERROR_MSG_REQ_AUTH_FAILED); + return; + } + + c_list_link_tail(&priv->auth_lst_head, nm_auth_chain_parent_lst_list(chain)); + nm_auth_chain_set_data(chain, "flags", GUINT_TO_POINTER(flags), NULL); + nm_auth_chain_add_call(chain, NM_AUTH_PERMISSION_RELOAD, TRUE); } /*****************************************************************************/ NMDevice * -nm_manager_get_device_by_path (NMManager *self, const char *path) +nm_manager_get_device_by_path(NMManager *self, const char *path) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + NMDevice * device; - g_return_val_if_fail (path, NULL); + g_return_val_if_fail(path, NULL); - device = nm_dbus_manager_lookup_object (nm_dbus_object_get_manager (NM_DBUS_OBJECT (self)), - path); - if ( !device - || !NM_IS_DEVICE (device) - || c_list_is_empty (&device->devices_lst)) - return NULL; + device = nm_dbus_manager_lookup_object(nm_dbus_object_get_manager(NM_DBUS_OBJECT(self)), path); + if (!device || !NM_IS_DEVICE(device) || c_list_is_empty(&device->devices_lst)) + return NULL; - nm_assert (c_list_contains (&priv->devices_lst_head, &device->devices_lst)); - return device; + nm_assert(c_list_contains(&priv->devices_lst_head, &device->devices_lst)); + return device; } NMDevice * -nm_manager_get_device_by_ifindex (NMManager *self, int ifindex) +nm_manager_get_device_by_ifindex(NMManager *self, int ifindex) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + NMDevice * device; - if (ifindex > 0) { - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { - if (nm_device_get_ifindex (device) == ifindex) - return device; - } - } + if (ifindex > 0) { + c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { + if (nm_device_get_ifindex(device) == ifindex) + return device; + } + } - return NULL; + return NULL; } static NMDevice * -find_device_by_permanent_hw_addr (NMManager *self, const char *hwaddr) +find_device_by_permanent_hw_addr(NMManager *self, const char *hwaddr) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device; - const char *device_addr; - guint8 hwaddr_bin[NM_UTILS_HWADDR_LEN_MAX]; - gsize hwaddr_len; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + NMDevice * device; + const char * device_addr; + guint8 hwaddr_bin[NM_UTILS_HWADDR_LEN_MAX]; + gsize hwaddr_len; - g_return_val_if_fail (hwaddr != NULL, NULL); + g_return_val_if_fail(hwaddr != NULL, NULL); - if (!_nm_utils_hwaddr_aton (hwaddr, hwaddr_bin, sizeof (hwaddr_bin), &hwaddr_len)) - return NULL; + if (!_nm_utils_hwaddr_aton(hwaddr, hwaddr_bin, sizeof(hwaddr_bin), &hwaddr_len)) + return NULL; - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { - device_addr = nm_device_get_permanent_hw_address (device); - if ( device_addr - && nm_utils_hwaddr_matches (hwaddr_bin, hwaddr_len, device_addr, -1)) - return device; - } - return NULL; + c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { + device_addr = nm_device_get_permanent_hw_address(device); + if (device_addr && nm_utils_hwaddr_matches(hwaddr_bin, hwaddr_len, device_addr, -1)) + return device; + } + return NULL; } static NMDevice * -find_device_by_ip_iface (NMManager *self, const char *iface) +find_device_by_ip_iface(NMManager *self, const char *iface) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + NMDevice * device; - g_return_val_if_fail (iface, NULL); + g_return_val_if_fail(iface, NULL); - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { - if ( nm_device_is_real (device) - && nm_streq0 (nm_device_get_ip_iface (device), iface)) - return device; - } - return NULL; + c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { + if (nm_device_is_real(device) && nm_streq0(nm_device_get_ip_iface(device), iface)) + return device; + } + return NULL; } /** @@ -1318,505 +1322,499 @@ find_device_by_ip_iface (NMManager *self, const char *iface) * Returns: the matching #NMDevice */ static NMDevice * -find_device_by_iface (NMManager *self, - const char *iface, - NMConnection *connection, - NMConnection *slave) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *fallback = NULL; - NMDevice *candidate; - - g_return_val_if_fail (iface != NULL, NULL); - - c_list_for_each_entry (candidate, &priv->devices_lst_head, devices_lst) { - - if (strcmp (nm_device_get_iface (candidate), iface)) - continue; - if (connection && !nm_device_check_connection_compatible (candidate, connection, NULL)) - continue; - if (slave) { - if (!nm_device_is_master (candidate)) - continue; - if (!nm_device_check_slave_connection_compatible (candidate, slave)) - continue; - } - - if (nm_device_is_real (candidate)) - return candidate; - else if (!fallback) - fallback = candidate; - } - return fallback; +find_device_by_iface(NMManager * self, + const char * iface, + NMConnection *connection, + NMConnection *slave) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + NMDevice * fallback = NULL; + NMDevice * candidate; + + g_return_val_if_fail(iface != NULL, NULL); + + c_list_for_each_entry (candidate, &priv->devices_lst_head, devices_lst) { + if (!nm_streq(nm_device_get_iface(candidate), iface)) + continue; + if (connection && !nm_device_check_connection_compatible(candidate, connection, NULL)) + continue; + if (slave) { + if (!nm_device_is_master(candidate)) + continue; + if (!nm_device_check_slave_connection_compatible(candidate, slave)) + continue; + } + + if (nm_device_is_real(candidate)) + return candidate; + else if (!fallback) + fallback = candidate; + } + return fallback; } static gboolean -manager_sleeping (NMManager *self) +manager_sleeping(NMManager *self) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); - if (priv->sleeping || !priv->net_enabled) - return TRUE; - return FALSE; + if (priv->sleeping || !priv->net_enabled) + return TRUE; + return FALSE; } static const char * -_nm_state_to_string (NMState state) -{ - switch (state) { - case NM_STATE_ASLEEP: - return "ASLEEP"; - case NM_STATE_DISCONNECTED: - return "DISCONNECTED"; - case NM_STATE_DISCONNECTING: - return "DISCONNECTING"; - case NM_STATE_CONNECTING: - return "CONNECTING"; - case NM_STATE_CONNECTED_LOCAL: - return "CONNECTED_LOCAL"; - case NM_STATE_CONNECTED_SITE: - return "CONNECTED_SITE"; - case NM_STATE_CONNECTED_GLOBAL: - return "CONNECTED_GLOBAL"; - case NM_STATE_UNKNOWN: - default: - return "UNKNOWN"; - } +_nm_state_to_string(NMState state) +{ + switch (state) { + case NM_STATE_ASLEEP: + return "ASLEEP"; + case NM_STATE_DISCONNECTED: + return "DISCONNECTED"; + case NM_STATE_DISCONNECTING: + return "DISCONNECTING"; + case NM_STATE_CONNECTING: + return "CONNECTING"; + case NM_STATE_CONNECTED_LOCAL: + return "CONNECTED_LOCAL"; + case NM_STATE_CONNECTED_SITE: + return "CONNECTED_SITE"; + case NM_STATE_CONNECTED_GLOBAL: + return "CONNECTED_GLOBAL"; + case NM_STATE_UNKNOWN: + default: + return "UNKNOWN"; + } } static NMState -find_best_device_state (NMManager *manager) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - NMState best_state = NM_STATE_DISCONNECTED; - NMActiveConnection *ac; - - c_list_for_each_entry (ac, &priv->active_connections_lst_head, active_connections_lst) { - NMActiveConnectionState ac_state = nm_active_connection_get_state (ac); - - switch (ac_state) { - case NM_ACTIVE_CONNECTION_STATE_ACTIVATED: - if (nm_active_connection_get_default (ac, AF_UNSPEC)) { - if (priv->connectivity_state == NM_CONNECTIVITY_FULL) - return NM_STATE_CONNECTED_GLOBAL; - - best_state = NM_STATE_CONNECTED_SITE; - } else { - if (best_state < NM_STATE_CONNECTING) - best_state = NM_STATE_CONNECTED_LOCAL; - } - break; - case NM_ACTIVE_CONNECTION_STATE_ACTIVATING: - if (!NM_IN_SET (nm_active_connection_get_activation_type (ac), - NM_ACTIVATION_TYPE_EXTERNAL, - NM_ACTIVATION_TYPE_ASSUME)) { - if (best_state != NM_STATE_CONNECTED_GLOBAL) - best_state = NM_STATE_CONNECTING; - } - break; - case NM_ACTIVE_CONNECTION_STATE_DEACTIVATING: - if (!NM_IN_SET (nm_active_connection_get_activation_type (ac), - NM_ACTIVATION_TYPE_EXTERNAL, - NM_ACTIVATION_TYPE_ASSUME)) { - if (best_state < NM_STATE_DISCONNECTING) - best_state = NM_STATE_DISCONNECTING; - } - break; - default: - break; - } - } - - return best_state; +find_best_device_state(NMManager *manager) +{ + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(manager); + NMState best_state = NM_STATE_DISCONNECTED; + NMActiveConnection *ac; + + c_list_for_each_entry (ac, &priv->active_connections_lst_head, active_connections_lst) { + NMActiveConnectionState ac_state = nm_active_connection_get_state(ac); + + switch (ac_state) { + case NM_ACTIVE_CONNECTION_STATE_ACTIVATED: + if (nm_active_connection_get_default(ac, AF_UNSPEC)) { + if (priv->connectivity_state == NM_CONNECTIVITY_FULL) + return NM_STATE_CONNECTED_GLOBAL; + + best_state = NM_STATE_CONNECTED_SITE; + } else { + if (best_state < NM_STATE_CONNECTING) + best_state = NM_STATE_CONNECTED_LOCAL; + } + break; + case NM_ACTIVE_CONNECTION_STATE_ACTIVATING: + if (!NM_IN_SET(nm_active_connection_get_activation_type(ac), + NM_ACTIVATION_TYPE_EXTERNAL, + NM_ACTIVATION_TYPE_ASSUME)) { + if (best_state != NM_STATE_CONNECTED_GLOBAL) + best_state = NM_STATE_CONNECTING; + } + break; + case NM_ACTIVE_CONNECTION_STATE_DEACTIVATING: + if (!NM_IN_SET(nm_active_connection_get_activation_type(ac), + NM_ACTIVATION_TYPE_EXTERNAL, + NM_ACTIVATION_TYPE_ASSUME)) { + if (best_state < NM_STATE_DISCONNECTING) + best_state = NM_STATE_DISCONNECTING; + } + break; + default: + break; + } + } + + return best_state; } static void -nm_manager_update_metered (NMManager *self) +nm_manager_update_metered(NMManager *self) { - NMManagerPrivate *priv; - NMDevice *device; - NMMetered value = NM_METERED_UNKNOWN; + NMManagerPrivate *priv; + NMDevice * device; + NMMetered value = NM_METERED_UNKNOWN; - g_return_if_fail (NM_IS_MANAGER (self)); - priv = NM_MANAGER_GET_PRIVATE (self); + g_return_if_fail(NM_IS_MANAGER(self)); + priv = NM_MANAGER_GET_PRIVATE(self); - if (priv->primary_connection) { - device = nm_active_connection_get_device (priv->primary_connection); - if (device) - value = nm_device_get_metered (device); - } + if (priv->primary_connection) { + device = nm_active_connection_get_device(priv->primary_connection); + if (device) + value = nm_device_get_metered(device); + } - if (value != priv->metered) { - priv->metered = value; - _LOGD (LOGD_CORE, "new metered value: %d", (int) priv->metered); - _notify (self, PROP_METERED); - } + if (value != priv->metered) { + priv->metered = value; + _LOGD(LOGD_CORE, "new metered value: %d", (int) priv->metered); + _notify(self, PROP_METERED); + } } NMMetered -nm_manager_get_metered (NMManager *self) +nm_manager_get_metered(NMManager *self) { - g_return_val_if_fail (NM_IS_MANAGER (self), NM_METERED_UNKNOWN); + g_return_val_if_fail(NM_IS_MANAGER(self), NM_METERED_UNKNOWN); - return NM_MANAGER_GET_PRIVATE (self)->metered; + return NM_MANAGER_GET_PRIVATE(self)->metered; } static void -nm_manager_update_state (NMManager *self) +nm_manager_update_state(NMManager *self) { - NMManagerPrivate *priv; - NMState new_state = NM_STATE_DISCONNECTED; + NMManagerPrivate *priv; + NMState new_state = NM_STATE_DISCONNECTED; - g_return_if_fail (NM_IS_MANAGER (self)); + g_return_if_fail(NM_IS_MANAGER(self)); - priv = NM_MANAGER_GET_PRIVATE (self); + priv = NM_MANAGER_GET_PRIVATE(self); - if (manager_sleeping (self)) - new_state = NM_STATE_ASLEEP; - else - new_state = find_best_device_state (self); + if (manager_sleeping(self)) + new_state = NM_STATE_ASLEEP; + else + new_state = find_best_device_state(self); - if ( new_state >= NM_STATE_CONNECTED_LOCAL - && priv->connectivity_state == NM_CONNECTIVITY_FULL) { - new_state = NM_STATE_CONNECTED_GLOBAL; - } + if (new_state >= NM_STATE_CONNECTED_LOCAL && priv->connectivity_state == NM_CONNECTIVITY_FULL) { + new_state = NM_STATE_CONNECTED_GLOBAL; + } - if (priv->state == new_state) - return; + if (priv->state == new_state) + return; - priv->state = new_state; + priv->state = new_state; - _LOGI (LOGD_CORE, "NetworkManager state is now %s", _nm_state_to_string (new_state)); + _LOGI(LOGD_CORE, "NetworkManager state is now %s", _nm_state_to_string(new_state)); - _notify (self, PROP_STATE); - nm_dbus_object_emit_signal (NM_DBUS_OBJECT (self), - &interface_info_manager, - &signal_info_state_changed, - "(u)", - (guint32) priv->state); + _notify(self, PROP_STATE); + nm_dbus_object_emit_signal(NM_DBUS_OBJECT(self), + &interface_info_manager, + &signal_info_state_changed, + "(u)", + (guint32) priv->state); } static void -manager_device_state_changed (NMDevice *device, - NMDeviceState new_state, - NMDeviceState old_state, - NMDeviceStateReason reason, - gpointer user_data) -{ - NMManager *self = NM_MANAGER (user_data); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - - if ( old_state == NM_DEVICE_STATE_UNMANAGED - && new_state > NM_DEVICE_STATE_UNMANAGED) - retry_connections_for_parent_device (self, device); - - if (NM_IN_SET (new_state, - NM_DEVICE_STATE_UNMANAGED, - NM_DEVICE_STATE_UNAVAILABLE, - NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_PREPARE, - NM_DEVICE_STATE_FAILED)) - _notify (self, PROP_ACTIVE_CONNECTIONS); - - if (NM_IN_SET (new_state, - NM_DEVICE_STATE_UNMANAGED, - NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_ACTIVATED)) { - nm_manager_write_device_state (self, device, NULL); - - G_STATIC_ASSERT_EXPR (DEVICE_STATE_PRUNE_RATELIMIT_MAX < G_MAXUINT8); - if (priv->device_state_prune_ratelimit_count++ > DEVICE_STATE_PRUNE_RATELIMIT_MAX) { - /* We write the device state to /run. The state files are named after the - * ifindex (which is assumed to be unique and not repeat -- in practice - * it may repeat). So from time to time, we prune device state files - * for interfaces that no longer exist. - * - * Otherwise, the files might pile up if you create (and destroy) a large - * number of software devices. */ - priv->device_state_prune_ratelimit_count = 0; - nm_config_device_state_prune_stale (NULL, priv->platform); - } - } - - if (NM_IN_SET (new_state, - NM_DEVICE_STATE_UNAVAILABLE, - NM_DEVICE_STATE_DISCONNECTED)) - nm_settings_device_added (priv->settings, device); -} - -static void device_has_pending_action_changed (NMDevice *device, - GParamSpec *pspec, - NMManager *self); +manager_device_state_changed(NMDevice * device, + NMDeviceState new_state, + NMDeviceState old_state, + NMDeviceStateReason reason, + gpointer user_data) +{ + NMManager * self = NM_MANAGER(user_data); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + + if (old_state == NM_DEVICE_STATE_UNMANAGED && new_state > NM_DEVICE_STATE_UNMANAGED) + retry_connections_for_parent_device(self, device); + + if (NM_IN_SET(new_state, + NM_DEVICE_STATE_UNMANAGED, + NM_DEVICE_STATE_UNAVAILABLE, + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_PREPARE, + NM_DEVICE_STATE_FAILED)) + _notify(self, PROP_ACTIVE_CONNECTIONS); + + if (NM_IN_SET(new_state, + NM_DEVICE_STATE_UNMANAGED, + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_ACTIVATED)) { + nm_manager_write_device_state(self, device, NULL); + + G_STATIC_ASSERT_EXPR(DEVICE_STATE_PRUNE_RATELIMIT_MAX < G_MAXUINT8); + if (priv->device_state_prune_ratelimit_count++ > DEVICE_STATE_PRUNE_RATELIMIT_MAX) { + /* We write the device state to /run. The state files are named after the + * ifindex (which is assumed to be unique and not repeat -- in practice + * it may repeat). So from time to time, we prune device state files + * for interfaces that no longer exist. + * + * Otherwise, the files might pile up if you create (and destroy) a large + * number of software devices. */ + priv->device_state_prune_ratelimit_count = 0; + nm_config_device_state_prune_stale(NULL, priv->platform); + } + } + + if (NM_IN_SET(new_state, NM_DEVICE_STATE_UNAVAILABLE, NM_DEVICE_STATE_DISCONNECTED)) + nm_settings_device_added(priv->settings, device); +} + +static void device_has_pending_action_changed(NMDevice *device, GParamSpec *pspec, NMManager *self); static void -check_if_startup_complete (NMManager *self) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device; - const char *reason; - - if (!priv->startup) - return; - - if (!priv->devices_inited) - return; - - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { - reason = nm_device_has_pending_action_reason (device); - if (reason) { - _LOGD (LOGD_CORE, "startup complete is waiting for device '%s' (%s)", - nm_device_get_iface (device), - reason); - return; - } - } - - /* All NMDevice must be ready. But also NMSettings tracks profiles that wait for - * ready devices via "connection.wait-device-timeout". - * - * Note that we only re-check nm_settings_get_startup_complete_blocked_reason() when - * all of the devices become ready (again). - * - * For example, assume we have device "eth1" and "profile-eth2" which waits for "eth2". - * If "eth1" is ready (no pending action), we only need to re-evaluate "profile-eth2" - * if we have another device ("eth2"), that becomes non-ready (had pending actions) - * and again become ready. We don't need to check "profile-eth2" until "eth2" becomes - * non-ready. - * That is why nm_settings_get_startup_complete_blocked_reason() only has any significance - * if all devices are ready too. It allows us to cut down the number of checks whether - * NMSettings is ready. That's because we don't need to re-evaluate on minor changes of - * a device, only when all devices become managed and ready. */ - - g_signal_handlers_block_by_func (priv->settings, settings_startup_complete_changed, self); - reason = nm_settings_get_startup_complete_blocked_reason (priv->settings, TRUE); - g_signal_handlers_unblock_by_func (priv->settings, settings_startup_complete_changed, self); - if (reason) { - _LOGD (LOGD_CORE, "startup complete is waiting for connection (%s)", - reason); - return; - } - - _LOGI (LOGD_CORE, "startup complete"); - - priv->startup = FALSE; - - /* we no longer care about these signals. Startup-complete only - * happens once. */ - g_signal_handlers_disconnect_by_func (priv->settings, G_CALLBACK (settings_startup_complete_changed), self); - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { - g_signal_handlers_disconnect_by_func (device, - G_CALLBACK (device_has_pending_action_changed), - self); - } - - _notify (self, PROP_STARTUP); - - if (nm_config_get_configure_and_quit (priv->config)) - g_signal_emit (self, signals[CONFIGURE_QUIT], 0); +check_if_startup_complete(NMManager *self) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + NMDevice * device; + const char * reason; + + if (!priv->startup) + return; + + if (!priv->devices_inited) + return; + + c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { + reason = nm_device_has_pending_action_reason(device); + if (reason) { + _LOGD(LOGD_CORE, + "startup complete is waiting for device '%s' (%s)", + nm_device_get_iface(device), + reason); + return; + } + } + + /* All NMDevice must be ready. But also NMSettings tracks profiles that wait for + * ready devices via "connection.wait-device-timeout". + * + * Note that we only re-check nm_settings_get_startup_complete_blocked_reason() when + * all of the devices become ready (again). + * + * For example, assume we have device "eth1" and "profile-eth2" which waits for "eth2". + * If "eth1" is ready (no pending action), we only need to re-evaluate "profile-eth2" + * if we have another device ("eth2"), that becomes non-ready (had pending actions) + * and again become ready. We don't need to check "profile-eth2" until "eth2" becomes + * non-ready. + * That is why nm_settings_get_startup_complete_blocked_reason() only has any significance + * if all devices are ready too. It allows us to cut down the number of checks whether + * NMSettings is ready. That's because we don't need to re-evaluate on minor changes of + * a device, only when all devices become managed and ready. */ + + g_signal_handlers_block_by_func(priv->settings, settings_startup_complete_changed, self); + reason = nm_settings_get_startup_complete_blocked_reason(priv->settings, TRUE); + g_signal_handlers_unblock_by_func(priv->settings, settings_startup_complete_changed, self); + if (reason) { + _LOGD(LOGD_CORE, "startup complete is waiting for connection (%s)", reason); + return; + } + + _LOGI(LOGD_CORE, "startup complete"); + + priv->startup = FALSE; + + /* we no longer care about these signals. Startup-complete only + * happens once. */ + g_signal_handlers_disconnect_by_func(priv->settings, + G_CALLBACK(settings_startup_complete_changed), + self); + c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { + g_signal_handlers_disconnect_by_func(device, + G_CALLBACK(device_has_pending_action_changed), + self); + } + + _notify(self, PROP_STARTUP); + + if (nm_config_get_configure_and_quit(priv->config)) + g_signal_emit(self, signals[CONFIGURE_QUIT], 0); } static void -device_has_pending_action_changed (NMDevice *device, - GParamSpec *pspec, - NMManager *self) +device_has_pending_action_changed(NMDevice *device, GParamSpec *pspec, NMManager *self) { - check_if_startup_complete (self); + check_if_startup_complete(self); } static void -settings_startup_complete_changed (NMSettings *settings, - GParamSpec *pspec, - NMManager *self) +settings_startup_complete_changed(NMSettings *settings, GParamSpec *pspec, NMManager *self) { - check_if_startup_complete (self); + check_if_startup_complete(self); } static void -_parent_notify_changed (NMManager *self, - NMDevice *device, - gboolean device_removed) +_parent_notify_changed(NMManager *self, NMDevice *device, gboolean device_removed) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *candidate; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + NMDevice * candidate; - nm_assert (NM_IS_DEVICE (device)); + nm_assert(NM_IS_DEVICE(device)); again: - c_list_for_each_entry (candidate, &priv->devices_lst_head, devices_lst) { - if (nm_device_parent_notify_changed (candidate, device, device_removed)) { - /* in the unlikely event that this changes anything, we start iterating - * again, to be sure that the device list is up-to-date. */ - goto again; - } - } + c_list_for_each_entry (candidate, &priv->devices_lst_head, devices_lst) { + if (nm_device_parent_notify_changed(candidate, device, device_removed)) { + /* in the unlikely event that this changes anything, we start iterating + * again, to be sure that the device list is up-to-date. */ + goto again; + } + } } static gboolean -device_is_wake_on_lan (NMPlatform *platform, NMDevice *device) +device_is_wake_on_lan(NMPlatform *platform, NMDevice *device) { - int ifindex; + int ifindex; - ifindex = nm_device_get_ip_ifindex (device); - if (ifindex <= 0) - return FALSE; - return nm_platform_link_get_wake_on_lan (platform, ifindex); + ifindex = nm_device_get_ip_ifindex(device); + if (ifindex <= 0) + return FALSE; + return nm_platform_link_get_wake_on_lan(platform, ifindex); } static void -remove_device (NMManager *self, - NMDevice *device, - gboolean quitting) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - gboolean unmanage = FALSE; - - _LOG2D (LOGD_DEVICE, device, "removing device (managed %d, wol %d)", - nm_device_get_managed (device, FALSE), - device_is_wake_on_lan (priv->platform, device)); - - if (nm_device_get_managed (device, FALSE)) { - - if (quitting) { - /* Leave configured if wo(w)lan and quitting */ - if (device_is_wake_on_lan (priv->platform, device)) - unmanage = FALSE; - else - unmanage = nm_device_unmanage_on_quit (device); - } else { - /* the device is already gone. Unmanage it. */ - unmanage = TRUE; - } - - if (unmanage) { - if (quitting) - nm_device_set_unmanaged_by_quitting (device); - else { - nm_device_sys_iface_state_set (device, NM_DEVICE_SYS_IFACE_STATE_REMOVED); - nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_PLATFORM_INIT, TRUE, NM_DEVICE_STATE_REASON_REMOVED); - } - } else if (quitting && nm_config_get_configure_and_quit (priv->config) == NM_CONFIG_CONFIGURE_AND_QUIT_ENABLED) { - nm_device_spawn_iface_helper (device); - } - } - - g_signal_handlers_disconnect_matched (device, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self); - - nm_settings_device_removed (priv->settings, device, quitting); - - c_list_unlink (&device->devices_lst); - - _parent_notify_changed (self, device, TRUE); - - if (nm_device_is_real (device)) { - gboolean unconfigure_ip_config = !quitting || unmanage; - - /* When we don't unmanage the device on shutdown, we want to preserve the DNS - * configuration in resolv.conf. For that, we must leak the configuration - * in NMPolicy/NMDnsManager. We do that, by emitting the device-removed signal - * with device's ip-config object still uncleared. In that case, NMPolicy - * never learns to unconfigure the ip-config objects and does not remove them - * from DNS on shutdown (which is ugly, because we don't cleanup the memory - * properly). - * - * Control that by passing @unconfigure_ip_config. */ - nm_device_removed (device, unconfigure_ip_config); - - _emit_device_added_removed (self, device, FALSE); - } else { - /* unrealize() does not release a slave device from master and - * clear IP configurations, do it here */ - nm_device_removed (device, TRUE); - } - - g_signal_emit (self, signals[INTERNAL_DEVICE_REMOVED], 0, device); - _notify (self, PROP_ALL_DEVICES); - - update_connectivity_value (self); - - nm_dbus_object_clear_and_unexport (&device); - - check_if_startup_complete (self); +remove_device(NMManager *self, NMDevice *device, gboolean quitting) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + gboolean unmanage = FALSE; + + _LOG2D(LOGD_DEVICE, + device, + "removing device (managed %d, wol %d)", + nm_device_get_managed(device, FALSE), + device_is_wake_on_lan(priv->platform, device)); + + if (nm_device_get_managed(device, FALSE)) { + if (quitting) { + /* Leave configured if wo(w)lan and quitting */ + if (device_is_wake_on_lan(priv->platform, device)) + unmanage = FALSE; + else + unmanage = nm_device_unmanage_on_quit(device); + } else { + /* the device is already gone. Unmanage it. */ + unmanage = TRUE; + } + + if (unmanage) { + if (quitting) + nm_device_set_unmanaged_by_quitting(device); + else { + nm_device_sys_iface_state_set(device, NM_DEVICE_SYS_IFACE_STATE_REMOVED); + nm_device_set_unmanaged_by_flags(device, + NM_UNMANAGED_PLATFORM_INIT, + TRUE, + NM_DEVICE_STATE_REASON_REMOVED); + } + } else if (quitting + && nm_config_get_configure_and_quit(priv->config) + == NM_CONFIG_CONFIGURE_AND_QUIT_ENABLED) { + nm_device_spawn_iface_helper(device); + } + } + + g_signal_handlers_disconnect_matched(device, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self); + + nm_settings_device_removed(priv->settings, device, quitting); + + c_list_unlink(&device->devices_lst); + + _parent_notify_changed(self, device, TRUE); + + if (nm_device_is_real(device)) { + gboolean unconfigure_ip_config = !quitting || unmanage; + + /* When we don't unmanage the device on shutdown, we want to preserve the DNS + * configuration in resolv.conf. For that, we must leak the configuration + * in NMPolicy/NMDnsManager. We do that, by emitting the device-removed signal + * with device's ip-config object still uncleared. In that case, NMPolicy + * never learns to unconfigure the ip-config objects and does not remove them + * from DNS on shutdown (which is ugly, because we don't cleanup the memory + * properly). + * + * Control that by passing @unconfigure_ip_config. */ + nm_device_removed(device, unconfigure_ip_config); + + _emit_device_added_removed(self, device, FALSE); + } else { + /* unrealize() does not release a slave device from master and + * clear IP configurations, do it here */ + nm_device_removed(device, TRUE); + } + + g_signal_emit(self, signals[INTERNAL_DEVICE_REMOVED], 0, device); + _notify(self, PROP_ALL_DEVICES); + + update_connectivity_value(self); + + nm_dbus_object_clear_and_unexport(&device); + + check_if_startup_complete(self); } static void -device_removed_cb (NMDevice *device, gpointer user_data) +device_removed_cb(NMDevice *device, gpointer user_data) { - remove_device (NM_MANAGER (user_data), device, FALSE); + remove_device(NM_MANAGER(user_data), device, FALSE); } NMState -nm_manager_get_state (NMManager *manager) +nm_manager_get_state(NMManager *manager) { - g_return_val_if_fail (NM_IS_MANAGER (manager), NM_STATE_UNKNOWN); + g_return_val_if_fail(NM_IS_MANAGER(manager), NM_STATE_UNKNOWN); - return NM_MANAGER_GET_PRIVATE (manager)->state; + return NM_MANAGER_GET_PRIVATE(manager)->state; } /*****************************************************************************/ static NMDevice * -find_parent_device_for_connection (NMManager *self, - NMConnection *connection, - NMDeviceFactory *cached_factory, - const char **out_parent_spec) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDeviceFactory *factory; - const char *parent_name = NULL; - NMSettingsConnection *parent_connection; - NMDevice *parent, *first_compatible = NULL; - NMDevice *candidate; - - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - NM_SET_OUT (out_parent_spec, NULL); - - if (!cached_factory) { - factory = nm_device_factory_manager_find_factory_for_connection (connection); - if (!factory) - return NULL; - } else - factory = cached_factory; - - parent_name = nm_device_factory_get_connection_parent (factory, connection); - if (!parent_name) - return NULL; - - NM_SET_OUT (out_parent_spec, parent_name); - - /* Try as an interface name of a parent device */ - parent = find_device_by_iface (self, parent_name, NULL, NULL); - if (parent) - return parent; - - /* Maybe a hardware address */ - parent = find_device_by_permanent_hw_addr (self, parent_name); - if (parent) - return parent; - - /* Maybe a connection UUID */ - parent_connection = nm_settings_get_connection_by_uuid (priv->settings, parent_name); - if (!parent_connection) - return NULL; - - /* Check if the parent connection is currently activated or is compatible - * with some known device. - */ - c_list_for_each_entry (candidate, &priv->devices_lst_head, devices_lst) { - /* Unmanaged devices are not compatible with any connection */ - if (!nm_device_get_managed (candidate, FALSE)) - continue; - - if (nm_device_get_settings_connection (candidate) == parent_connection) - return candidate; - - if ( !first_compatible - && nm_device_check_connection_compatible (candidate, - nm_settings_connection_get_connection (parent_connection), - NULL)) - first_compatible = candidate; - } - - return first_compatible; +find_parent_device_for_connection(NMManager * self, + NMConnection * connection, + NMDeviceFactory *cached_factory, + const char ** out_parent_spec) +{ + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + NMDeviceFactory * factory; + const char * parent_name = NULL; + NMSettingsConnection *parent_connection; + NMDevice * parent, *first_compatible = NULL; + NMDevice * candidate; + + g_return_val_if_fail(NM_IS_CONNECTION(connection), NULL); + NM_SET_OUT(out_parent_spec, NULL); + + if (!cached_factory) { + factory = nm_device_factory_manager_find_factory_for_connection(connection); + if (!factory) + return NULL; + } else + factory = cached_factory; + + parent_name = nm_device_factory_get_connection_parent(factory, connection); + if (!parent_name) + return NULL; + + NM_SET_OUT(out_parent_spec, parent_name); + + /* Try as an interface name of a parent device */ + parent = find_device_by_iface(self, parent_name, NULL, NULL); + if (parent) + return parent; + + /* Maybe a hardware address */ + parent = find_device_by_permanent_hw_addr(self, parent_name); + if (parent) + return parent; + + /* Maybe a connection UUID */ + parent_connection = nm_settings_get_connection_by_uuid(priv->settings, parent_name); + if (!parent_connection) + return NULL; + + /* Check if the parent connection is currently activated or is compatible + * with some known device. + */ + c_list_for_each_entry (candidate, &priv->devices_lst_head, devices_lst) { + /* Unmanaged devices are not compatible with any connection */ + if (!nm_device_get_managed(candidate, FALSE)) + continue; + + if (nm_device_get_settings_connection(candidate) == parent_connection) + return candidate; + + if (!first_compatible + && nm_device_check_connection_compatible( + candidate, + nm_settings_connection_get_connection(parent_connection), + NULL)) + first_compatible = candidate; + } + + return first_compatible; } /** @@ -1837,62 +1835,62 @@ find_parent_device_for_connection (NMManager *self, * Returns: the expected interface name (caller takes ownership), or %NULL */ char * -nm_manager_get_connection_iface (NMManager *self, - NMConnection *connection, - NMDevice **out_parent, - const char **out_parent_spec, - GError **error) -{ - NMDeviceFactory *factory; - char *iface = NULL; - NMDevice *parent = NULL; - - NM_SET_OUT (out_parent, NULL); - NM_SET_OUT (out_parent_spec, NULL); - - factory = nm_device_factory_manager_find_factory_for_connection (connection); - if (!factory) { - if (nm_streq0 (nm_connection_get_connection_type (connection), NM_SETTING_GENERIC_SETTING_NAME)) { - /* the generic type doesn't have a factory. */ - goto return_ifname_fom_connection; - } - - g_set_error (error, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_FAILED, - "NetworkManager plugin for '%s' unavailable", - nm_connection_get_connection_type (connection)); - return NULL; - } - - if ( !out_parent - && !NM_DEVICE_FACTORY_GET_CLASS (factory)->get_connection_iface) { - /* optimization. Shortcut lookup of the partent device. */ - goto return_ifname_fom_connection; - } - - parent = find_parent_device_for_connection (self, connection, factory, out_parent_spec); - iface = nm_device_factory_get_connection_iface (factory, - connection, - parent ? nm_device_get_ip_iface (parent) : NULL, - error); - if (!iface) - return NULL; - - if (out_parent) - *out_parent = parent; - return iface; +nm_manager_get_connection_iface(NMManager * self, + NMConnection *connection, + NMDevice ** out_parent, + const char ** out_parent_spec, + GError ** error) +{ + NMDeviceFactory *factory; + char * iface = NULL; + NMDevice * parent = NULL; + + NM_SET_OUT(out_parent, NULL); + NM_SET_OUT(out_parent_spec, NULL); + + factory = nm_device_factory_manager_find_factory_for_connection(connection); + if (!factory) { + if (nm_streq0(nm_connection_get_connection_type(connection), + NM_SETTING_GENERIC_SETTING_NAME)) { + /* the generic type doesn't have a factory. */ + goto return_ifname_fom_connection; + } + + g_set_error(error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_FAILED, + "NetworkManager plugin for '%s' unavailable", + nm_connection_get_connection_type(connection)); + return NULL; + } + + if (!out_parent && !NM_DEVICE_FACTORY_GET_CLASS(factory)->get_connection_iface) { + /* optimization. Shortcut lookup of the partent device. */ + goto return_ifname_fom_connection; + } + + parent = find_parent_device_for_connection(self, connection, factory, out_parent_spec); + iface = nm_device_factory_get_connection_iface(factory, + connection, + parent ? nm_device_get_ip_iface(parent) : NULL, + error); + if (!iface) + return NULL; + + if (out_parent) + *out_parent = parent; + return iface; return_ifname_fom_connection: - iface = g_strdup (nm_connection_get_interface_name (connection)); - if (!iface) { - g_set_error (error, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_FAILED, - "failed to determine interface name: error determine name for %s", - nm_connection_get_connection_type (connection)); - } - return iface; + iface = g_strdup(nm_connection_get_interface_name(connection)); + if (!iface) { + g_set_error(error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_FAILED, + "failed to determine interface name: error determine name for %s", + nm_connection_get_connection_type(connection)); + } + return iface; } /** @@ -1907,47 +1905,47 @@ return_ifname_fom_connection: * Returns: An interface name; %NULL if none matches */ const char * -nm_manager_iface_for_uuid (NMManager *self, const char *uuid) +nm_manager_iface_for_uuid(NMManager *self, const char *uuid) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMSettingsConnection *sett_conn; + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + NMSettingsConnection *sett_conn; - sett_conn = nm_settings_get_connection_by_uuid (priv->settings, uuid); - if (!sett_conn) - return NULL; + sett_conn = nm_settings_get_connection_by_uuid(priv->settings, uuid); + if (!sett_conn) + return NULL; - return nm_connection_get_interface_name (nm_settings_connection_get_connection (sett_conn)); + return nm_connection_get_interface_name(nm_settings_connection_get_connection(sett_conn)); } NMDevice * -nm_manager_get_device (NMManager *self, const char *ifname, NMDeviceType device_type) +nm_manager_get_device(NMManager *self, const char *ifname, NMDeviceType device_type) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + NMDevice * device; - g_return_val_if_fail (ifname, NULL); - g_return_val_if_fail (device_type != NM_DEVICE_TYPE_UNKNOWN, NULL); + g_return_val_if_fail(ifname, NULL); + g_return_val_if_fail(device_type != NM_DEVICE_TYPE_UNKNOWN, NULL); - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { - if ( nm_device_get_device_type (device) == device_type - && nm_streq0 (nm_device_get_iface (device), ifname)) - return device; - } + c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { + if (nm_device_get_device_type(device) == device_type + && nm_streq0(nm_device_get_iface(device), ifname)) + return device; + } - return NULL; + return NULL; } gboolean -nm_manager_remove_device (NMManager *self, const char *ifname, NMDeviceType device_type) +nm_manager_remove_device(NMManager *self, const char *ifname, NMDeviceType device_type) { - NMDevice *d; + NMDevice *d; - d = nm_manager_get_device (self, ifname, device_type); - if (!d) - return FALSE; + d = nm_manager_get_device(self, ifname, device_type); + if (!d) + return FALSE; - remove_device (self, d, FALSE); - return TRUE; + remove_device(self, d, FALSE); + return TRUE; } /** @@ -1961,299 +1959,297 @@ nm_manager_remove_device (NMManager *self, const char *ifname, NMDeviceType devi * Returns: A #NMDevice that was just realized; %NULL if none */ static NMDevice * -system_create_virtual_device (NMManager *self, NMConnection *connection) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDeviceFactory *factory; - gs_free NMSettingsConnection **connections = NULL; - guint i; - gs_free char *iface = NULL; - const char *parent_spec; - NMDevice *device = NULL, *parent = NULL; - NMDevice *dev_candidate; - GError *error = NULL; - NMLogLevel log_level; - - g_return_val_if_fail (NM_IS_MANAGER (self), NULL); - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - iface = nm_manager_get_connection_iface (self, connection, &parent, &parent_spec, &error); - if (!iface) { - _LOG3D (LOGD_DEVICE, connection, "can't get a name of a virtual device: %s", - error->message); - g_error_free (error); - return NULL; - } - - if (parent_spec && !parent) { - /* parent is not ready, wait */ - return NULL; - } - - /* See if there's a device that is already compatible with this connection */ - c_list_for_each_entry (dev_candidate, &priv->devices_lst_head, devices_lst) { - if (nm_device_check_connection_compatible (dev_candidate, connection, NULL)) { - if (nm_device_is_real (dev_candidate)) { - _LOG3D (LOGD_DEVICE, connection, "already created virtual interface name %s", - iface); - return NULL; - } - - device = dev_candidate; - break; - } - } - - if (!device) { - /* No matching device found. Proceed creating a new one. */ - - factory = nm_device_factory_manager_find_factory_for_connection (connection); - if (!factory) { - _LOG3E (LOGD_DEVICE, connection, "(%s) NetworkManager plugin for '%s' unavailable", - iface, - nm_connection_get_connection_type (connection)); - return NULL; - } - - device = nm_device_factory_create_device (factory, iface, NULL, connection, NULL, &error); - if (!device) { - _LOG3W (LOGD_DEVICE, connection, "factory can't create the device: %s", - error->message); - g_error_free (error); - return NULL; - } - - _LOG3D (LOGD_DEVICE, connection, "create virtual device %s", - nm_device_get_iface (device)); - - if (!add_device (self, device, &error)) { - _LOG3W (LOGD_DEVICE, connection, "can't register the device with manager: %s", - error->message); - g_error_free (error); - g_object_unref (device); - return NULL; - } - - /* Add device takes a reference that NMManager still owns, so it's - * safe to unref here and still return @device. - */ - g_object_unref (device); - } - - if (!nm_device_check_unrealized_device_managed (device)) { - _LOG3D (LOGD_DEVICE, connection, - "skip activation because virtual device '%s' is unmanaged", - nm_device_get_iface (device)); - return device; - } - - if (!find_master (self, - connection, - device, - NULL, - NULL, - NULL, - &error)) { - _LOG3D (LOGD_DEVICE, connection, - "skip activation: %s", - error->message); - g_error_free (error); - return device; - } - - /* Create backing resources if the device has any autoconnect connections */ - connections = nm_settings_get_connections_clone (priv->settings, NULL, - NULL, NULL, - nm_settings_connection_cmp_autoconnect_priority_p_with_data, NULL); - for (i = 0; connections[i]; i++) { - NMConnection *candidate = nm_settings_connection_get_connection (connections[i]); - NMSettingConnection *s_con; - - if (!nm_device_check_connection_compatible (device, candidate, NULL)) - continue; - - s_con = nm_connection_get_setting_connection (candidate); - g_assert (s_con); - if ( !nm_setting_connection_get_autoconnect (s_con) - || nm_settings_connection_autoconnect_is_blocked (connections[i])) - continue; - - /* Create any backing resources the device needs */ - if (!nm_device_create_and_realize (device, connection, parent, &error)) { - log_level = g_error_matches (error, - NM_DEVICE_ERROR, - NM_DEVICE_ERROR_MISSING_DEPENDENCIES) - ? LOGL_DEBUG - : LOGL_ERR; - _NMLOG3 (log_level, LOGD_DEVICE, connection, - "couldn't create the device: %s", - error->message); - g_error_free (error); - return NULL; - } - - retry_connections_for_parent_device (self, device); - break; - } - - return device; +system_create_virtual_device(NMManager *self, NMConnection *connection) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + NMDeviceFactory * factory; + gs_free NMSettingsConnection **connections = NULL; + guint i; + gs_free char * iface = NULL; + const char * parent_spec; + NMDevice * device = NULL, *parent = NULL; + NMDevice * dev_candidate; + GError * error = NULL; + NMLogLevel log_level; + + g_return_val_if_fail(NM_IS_MANAGER(self), NULL); + g_return_val_if_fail(NM_IS_CONNECTION(connection), NULL); + + iface = nm_manager_get_connection_iface(self, connection, &parent, &parent_spec, &error); + if (!iface) { + _LOG3D(LOGD_DEVICE, connection, "can't get a name of a virtual device: %s", error->message); + g_error_free(error); + return NULL; + } + + if (parent_spec && !parent) { + /* parent is not ready, wait */ + return NULL; + } + + /* See if there's a device that is already compatible with this connection */ + c_list_for_each_entry (dev_candidate, &priv->devices_lst_head, devices_lst) { + if (nm_device_check_connection_compatible(dev_candidate, connection, NULL)) { + if (nm_device_is_real(dev_candidate)) { + _LOG3D(LOGD_DEVICE, connection, "already created virtual interface name %s", iface); + return NULL; + } + + device = dev_candidate; + break; + } + } + + if (!device) { + /* No matching device found. Proceed creating a new one. */ + + factory = nm_device_factory_manager_find_factory_for_connection(connection); + if (!factory) { + _LOG3E(LOGD_DEVICE, + connection, + "(%s) NetworkManager plugin for '%s' unavailable", + iface, + nm_connection_get_connection_type(connection)); + return NULL; + } + + device = nm_device_factory_create_device(factory, iface, NULL, connection, NULL, &error); + if (!device) { + _LOG3W(LOGD_DEVICE, connection, "factory can't create the device: %s", error->message); + g_error_free(error); + return NULL; + } + + _LOG3D(LOGD_DEVICE, connection, "create virtual device %s", nm_device_get_iface(device)); + + if (!add_device(self, device, &error)) { + _LOG3W(LOGD_DEVICE, + connection, + "can't register the device with manager: %s", + error->message); + g_error_free(error); + g_object_unref(device); + return NULL; + } + + /* Add device takes a reference that NMManager still owns, so it's + * safe to unref here and still return @device. + */ + g_object_unref(device); + } + + if (!nm_device_check_unrealized_device_managed(device)) { + _LOG3D(LOGD_DEVICE, + connection, + "skip activation because virtual device '%s' is unmanaged", + nm_device_get_iface(device)); + return device; + } + + if (!find_master(self, connection, device, NULL, NULL, NULL, &error)) { + _LOG3D(LOGD_DEVICE, connection, "skip activation: %s", error->message); + g_error_free(error); + return device; + } + + /* Create backing resources if the device has any autoconnect connections */ + connections = nm_settings_get_connections_clone( + priv->settings, + NULL, + NULL, + NULL, + nm_settings_connection_cmp_autoconnect_priority_p_with_data, + NULL); + for (i = 0; connections[i]; i++) { + NMConnection * candidate = nm_settings_connection_get_connection(connections[i]); + NMSettingConnection *s_con; + + if (!nm_device_check_connection_compatible(device, candidate, NULL)) + continue; + + s_con = nm_connection_get_setting_connection(candidate); + g_assert(s_con); + if (!nm_setting_connection_get_autoconnect(s_con) + || nm_settings_connection_autoconnect_is_blocked(connections[i])) + continue; + + /* Create any backing resources the device needs */ + if (!nm_device_create_and_realize(device, connection, parent, &error)) { + log_level = + g_error_matches(error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_MISSING_DEPENDENCIES) + ? LOGL_DEBUG + : LOGL_ERR; + _NMLOG3(log_level, + LOGD_DEVICE, + connection, + "couldn't create the device: %s", + error->message); + g_error_free(error); + return NULL; + } + + retry_connections_for_parent_device(self, device); + break; + } + + return device; } static void -retry_connections_for_parent_device (NMManager *self, NMDevice *device) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - gs_free NMSettingsConnection **connections = NULL; - guint i; - - g_return_if_fail (device); - - connections = nm_settings_get_connections_clone (priv->settings, NULL, - NULL, NULL, - nm_settings_connection_cmp_autoconnect_priority_p_with_data, NULL); - for (i = 0; connections[i]; i++) { - NMSettingsConnection *sett_conn = connections[i]; - NMConnection *connection = nm_settings_connection_get_connection (sett_conn); - gs_free_error GError *error = NULL; - gs_free char *ifname = NULL; - NMDevice *parent; - - parent = find_parent_device_for_connection (self, connection, NULL, NULL); - if (parent == device) { - /* Only try to activate devices that don't already exist */ - ifname = nm_manager_get_connection_iface (self, connection, &parent, NULL, &error); - if (ifname) { - if (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, ifname)) - connection_changed (self, sett_conn); - } - } - } +retry_connections_for_parent_device(NMManager *self, NMDevice *device) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + gs_free NMSettingsConnection **connections = NULL; + guint i; + + g_return_if_fail(device); + + connections = nm_settings_get_connections_clone( + priv->settings, + NULL, + NULL, + NULL, + nm_settings_connection_cmp_autoconnect_priority_p_with_data, + NULL); + for (i = 0; connections[i]; i++) { + NMSettingsConnection *sett_conn = connections[i]; + NMConnection * connection = nm_settings_connection_get_connection(sett_conn); + gs_free_error GError *error = NULL; + gs_free char * ifname = NULL; + NMDevice * parent; + + parent = find_parent_device_for_connection(self, connection, NULL, NULL); + if (parent == device) { + /* Only try to activate devices that don't already exist */ + ifname = nm_manager_get_connection_iface(self, connection, &parent, NULL, &error); + if (ifname) { + if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, ifname)) + connection_changed(self, sett_conn); + } + } + } } static void -connection_changed (NMManager *self, - NMSettingsConnection *sett_conn) +connection_changed(NMManager *self, NMSettingsConnection *sett_conn) { - NMConnection *connection; - NMDevice *device; + NMConnection *connection; + NMDevice * device; - if (NM_FLAGS_ANY (nm_settings_connection_get_flags (sett_conn), - NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE - | NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL)) - return; + if (NM_FLAGS_ANY(nm_settings_connection_get_flags(sett_conn), + NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE + | NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL)) + return; - connection = nm_settings_connection_get_connection (sett_conn); + connection = nm_settings_connection_get_connection(sett_conn); - if (!nm_connection_is_virtual (connection)) - return; + if (!nm_connection_is_virtual(connection)) + return; - device = system_create_virtual_device (self, connection); - if (!device) - return; + device = system_create_virtual_device(self, connection); + if (!device) + return; - /* Maybe the device that was created was needed by some other - * connection's device (parent of a VLAN). Let the connections - * can use the newly created device as a parent know. */ - retry_connections_for_parent_device (self, device); + /* Maybe the device that was created was needed by some other + * connection's device (parent of a VLAN). Let the connections + * can use the newly created device as a parent know. */ + retry_connections_for_parent_device(self, device); } static void -connection_added_cb (NMSettings *settings, - NMSettingsConnection *sett_conn, - NMManager *self) +connection_added_cb(NMSettings *settings, NMSettingsConnection *sett_conn, NMManager *self) { - connection_changed (self, sett_conn); + connection_changed(self, sett_conn); } static void -connection_updated_cb (NMSettings *settings, - NMSettingsConnection *sett_conn, - guint update_reason_u, - NMManager *self) +connection_updated_cb(NMSettings * settings, + NMSettingsConnection *sett_conn, + guint update_reason_u, + NMManager * self) { - connection_changed (self, sett_conn); + connection_changed(self, sett_conn); } /*****************************************************************************/ static void -_delete_volatile_connection_all (NMManager *self, gboolean do_delete) +_delete_volatile_connection_all(NMManager *self, gboolean do_delete) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMCListElem *elem; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + NMCListElem * elem; - while ((elem = c_list_first_entry (&priv->delete_volatile_connection_lst_head, NMCListElem, lst))) { - gs_unref_object NMSettingsConnection *connection = NULL; + while ( + (elem = c_list_first_entry(&priv->delete_volatile_connection_lst_head, NMCListElem, lst))) { + gs_unref_object NMSettingsConnection *connection = NULL; - connection = nm_c_list_elem_free_steal (elem); - if (do_delete) - _delete_volatile_connection_do (self, connection); - } + connection = nm_c_list_elem_free_steal(elem); + if (do_delete) + _delete_volatile_connection_do(self, connection); + } } static gboolean -_delete_volatile_connection_cb (gpointer user_data) +_delete_volatile_connection_cb(gpointer user_data) { - NMManager *self = user_data; - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + NMManager * self = user_data; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); - priv->delete_volatile_connection_idle_id = 0; - _delete_volatile_connection_all (self, TRUE); - return G_SOURCE_REMOVE; + priv->delete_volatile_connection_idle_id = 0; + _delete_volatile_connection_all(self, TRUE); + return G_SOURCE_REMOVE; } static void -connection_flags_changed (NMSettings *settings, - NMSettingsConnection *connection, - gpointer user_data) +connection_flags_changed(NMSettings *settings, NMSettingsConnection *connection, gpointer user_data) { - NMManager *self = user_data; - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + NMManager * self = user_data; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); - if (!NM_FLAGS_ANY (nm_settings_connection_get_flags (connection), - NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE - | NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL)) - return; + if (!NM_FLAGS_ANY(nm_settings_connection_get_flags(connection), + NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE + | NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL)) + return; - if (active_connection_find (self, connection, NULL, NM_ACTIVE_CONNECTION_STATE_DEACTIVATED, NULL)) { - /* the connection still has an active-connection. It will be purged - * when the active connection(s) get(s) removed. */ - return; - } + if (active_connection_find(self, + connection, + NULL, + NM_ACTIVE_CONNECTION_STATE_DEACTIVATED, + NULL)) { + /* the connection still has an active-connection. It will be purged + * when the active connection(s) get(s) removed. */ + return; + } - c_list_link_tail (&priv->delete_volatile_connection_lst_head, - &nm_c_list_elem_new_stale (g_object_ref (connection))->lst); - if (!priv->delete_volatile_connection_idle_id) - priv->delete_volatile_connection_idle_id = g_idle_add (_delete_volatile_connection_cb, self); + c_list_link_tail(&priv->delete_volatile_connection_lst_head, + &nm_c_list_elem_new_stale(g_object_ref(connection))->lst); + if (!priv->delete_volatile_connection_idle_id) + priv->delete_volatile_connection_idle_id = g_idle_add(_delete_volatile_connection_cb, self); } /*****************************************************************************/ static void -system_unmanaged_devices_changed_cb (NMSettings *settings, - GParamSpec *pspec, - gpointer user_data) +system_unmanaged_devices_changed_cb(NMSettings *settings, GParamSpec *pspec, gpointer user_data) { - NMManager *self = NM_MANAGER (user_data); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device; + NMManager * self = NM_MANAGER(user_data); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + NMDevice * device; - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) - nm_device_set_unmanaged_by_user_settings (device); + c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) + nm_device_set_unmanaged_by_user_settings(device); } static void -hostname_changed_cb (NMHostnameManager *hostname_manager, - GParamSpec *pspec, - NMManager *self) +hostname_changed_cb(NMHostnameManager *hostname_manager, GParamSpec *pspec, NMManager *self) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - const char *hostname; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + const char * hostname; - hostname = nm_hostname_manager_get_hostname (priv->hostname_manager); + hostname = nm_hostname_manager_get_hostname(priv->hostname_manager); - nm_dispatcher_call_hostname (NULL, NULL, NULL); - nm_dhcp_manager_set_default_hostname (nm_dhcp_manager_get (), hostname); + nm_dispatcher_call_hostname(NULL, NULL, NULL); + nm_dhcp_manager_set_default_hostname(nm_dhcp_manager_get(), hostname); } /*****************************************************************************/ @@ -2261,292 +2257,292 @@ hostname_changed_cb (NMHostnameManager *hostname_manager, /*****************************************************************************/ static gboolean -radio_enabled_for_rstate (RadioState *rstate, gboolean check_changeable) +radio_enabled_for_rstate(RadioState *rstate, gboolean check_changeable) { - gboolean enabled; + gboolean enabled; - enabled = rstate->user_enabled && rstate->hw_enabled; - if (check_changeable) - enabled &= rstate->sw_enabled; - return enabled; + enabled = rstate->user_enabled && rstate->hw_enabled; + if (check_changeable) + enabled &= rstate->sw_enabled; + return enabled; } static gboolean -radio_enabled_for_type (NMManager *self, RfKillType rtype, gboolean check_changeable) +radio_enabled_for_type(NMManager *self, RfKillType rtype, gboolean check_changeable) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); - return radio_enabled_for_rstate (&priv->radio_states[rtype], check_changeable); + return radio_enabled_for_rstate(&priv->radio_states[rtype], check_changeable); } static void -manager_update_radio_enabled (NMManager *self, - RadioState *rstate, - gboolean enabled) +manager_update_radio_enabled(NMManager *self, RadioState *rstate, gboolean enabled) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + NMDevice * device; - /* Do nothing for radio types not yet implemented */ - if (!rstate->prop) - return; + /* Do nothing for radio types not yet implemented */ + if (!rstate->prop) + return; - g_object_notify (G_OBJECT (self), rstate->prop); + g_object_notify(G_OBJECT(self), rstate->prop); - /* Don't touch devices if asleep/networking disabled */ - if (manager_sleeping (self)) - return; + /* Don't touch devices if asleep/networking disabled */ + if (manager_sleeping(self)) + return; - /* enable/disable wireless devices as required */ - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { - if (nm_device_get_rfkill_type (device) == rstate->rtype) { - _LOG2D (LOGD_RFKILL, device, "rfkill: setting radio %s", enabled ? "enabled" : "disabled"); - nm_device_set_enabled (device, enabled); - } - } + /* enable/disable wireless devices as required */ + c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { + if (nm_device_get_rfkill_type(device) == rstate->rtype) { + _LOG2D(LOGD_RFKILL, + device, + "rfkill: setting radio %s", + enabled ? "enabled" : "disabled"); + nm_device_set_enabled(device, enabled); + } + } } static void -update_rstate_from_rfkill (NMRfkillManager *rfkill_mgr, RadioState *rstate) -{ - switch (nm_rfkill_manager_get_rfkill_state (rfkill_mgr, rstate->rtype)) { - case RFKILL_UNBLOCKED: - rstate->sw_enabled = TRUE; - rstate->hw_enabled = TRUE; - break; - case RFKILL_SOFT_BLOCKED: - rstate->sw_enabled = FALSE; - rstate->hw_enabled = TRUE; - break; - case RFKILL_HARD_BLOCKED: - rstate->sw_enabled = FALSE; - rstate->hw_enabled = FALSE; - break; - default: - g_warn_if_reached (); - break; - } +update_rstate_from_rfkill(NMRfkillManager *rfkill_mgr, RadioState *rstate) +{ + switch (nm_rfkill_manager_get_rfkill_state(rfkill_mgr, rstate->rtype)) { + case RFKILL_UNBLOCKED: + rstate->sw_enabled = TRUE; + rstate->hw_enabled = TRUE; + break; + case RFKILL_SOFT_BLOCKED: + rstate->sw_enabled = FALSE; + rstate->hw_enabled = TRUE; + break; + case RFKILL_HARD_BLOCKED: + rstate->sw_enabled = FALSE; + rstate->hw_enabled = FALSE; + break; + default: + g_warn_if_reached(); + break; + } } static void -manager_rfkill_update_one_type (NMManager *self, - RadioState *rstate, - RfKillType rtype) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - gboolean old_enabled, new_enabled, old_rfkilled, new_rfkilled, old_hwe; - - old_enabled = radio_enabled_for_rstate (rstate, TRUE); - old_rfkilled = rstate->hw_enabled && rstate->sw_enabled; - old_hwe = rstate->hw_enabled; - - /* recheck kernel rfkill state */ - update_rstate_from_rfkill (priv->rfkill_mgr, rstate); - - /* Print out all states affecting device enablement */ - if (rstate->desc) { - _LOGD (LOGD_RFKILL, "rfkill: %s hw-enabled %d sw-enabled %d", - rstate->desc, rstate->hw_enabled, rstate->sw_enabled); - } - - /* Log new killswitch state */ - new_rfkilled = rstate->hw_enabled && rstate->sw_enabled; - if (old_rfkilled != new_rfkilled) { - _LOGI (LOGD_RFKILL, "rfkill: %s now %s by radio killswitch", - rstate->desc, - new_rfkilled ? "enabled" : "disabled"); - } - - /* Send out property changed signal for HW enabled */ - if (rstate->hw_enabled != old_hwe) { - if (rstate->hw_prop) - g_object_notify (G_OBJECT (self), rstate->hw_prop); - } - - /* And finally update the actual device radio state itself; respect the - * daemon state here because this is never called from user-triggered - * radio changes and we only want to ignore the daemon enabled state when - * handling user radio change requests. - */ - new_enabled = radio_enabled_for_rstate (rstate, TRUE); - if (new_enabled != old_enabled) - manager_update_radio_enabled (self, rstate, new_enabled); +manager_rfkill_update_one_type(NMManager *self, RadioState *rstate, RfKillType rtype) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + gboolean old_enabled, new_enabled, old_rfkilled, new_rfkilled, old_hwe; + + old_enabled = radio_enabled_for_rstate(rstate, TRUE); + old_rfkilled = rstate->hw_enabled && rstate->sw_enabled; + old_hwe = rstate->hw_enabled; + + /* recheck kernel rfkill state */ + update_rstate_from_rfkill(priv->rfkill_mgr, rstate); + + /* Print out all states affecting device enablement */ + if (rstate->desc) { + _LOGD(LOGD_RFKILL, + "rfkill: %s hw-enabled %d sw-enabled %d", + rstate->desc, + rstate->hw_enabled, + rstate->sw_enabled); + } + + /* Log new killswitch state */ + new_rfkilled = rstate->hw_enabled && rstate->sw_enabled; + if (old_rfkilled != new_rfkilled) { + _LOGI(LOGD_RFKILL, + "rfkill: %s now %s by radio killswitch", + rstate->desc, + new_rfkilled ? "enabled" : "disabled"); + } + + /* Send out property changed signal for HW enabled */ + if (rstate->hw_enabled != old_hwe) { + if (rstate->hw_prop) + g_object_notify(G_OBJECT(self), rstate->hw_prop); + } + + /* And finally update the actual device radio state itself; respect the + * daemon state here because this is never called from user-triggered + * radio changes and we only want to ignore the daemon enabled state when + * handling user radio change requests. + */ + new_enabled = radio_enabled_for_rstate(rstate, TRUE); + if (new_enabled != old_enabled) + manager_update_radio_enabled(self, rstate, new_enabled); } static void -nm_manager_rfkill_update (NMManager *self, RfKillType rtype) +nm_manager_rfkill_update(NMManager *self, RfKillType rtype) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - guint i; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + guint i; - if (rtype != RFKILL_TYPE_UNKNOWN) - manager_rfkill_update_one_type (self, &priv->radio_states[rtype], rtype); - else { - /* Otherwise sync all radio types */ - for (i = 0; i < RFKILL_TYPE_MAX; i++) - manager_rfkill_update_one_type (self, &priv->radio_states[i], i); - } + if (rtype != RFKILL_TYPE_UNKNOWN) + manager_rfkill_update_one_type(self, &priv->radio_states[rtype], rtype); + else { + /* Otherwise, sync all radio types */ + for (i = 0; i < RFKILL_TYPE_MAX; i++) + manager_rfkill_update_one_type(self, &priv->radio_states[i], i); + } } static void -device_auth_done_cb (NMAuthChain *chain, - GDBusMethodInvocation *context, - gpointer user_data) -{ - NMManager *self = NM_MANAGER (user_data); - gs_free_error GError *error = NULL; - NMAuthCallResult result; - NMDevice *device; - GCancellable *cancellable; - const char *permission; - NMManagerDeviceAuthRequestFunc callback; - NMAuthSubject *subject; - - nm_assert (G_IS_DBUS_METHOD_INVOCATION (context)); - - c_list_unlink (nm_auth_chain_parent_lst_list (chain)); - - permission = nm_auth_chain_get_data (chain, "perm"); - nm_assert (permission); - callback = nm_auth_chain_get_data (chain, "callback"); - nm_assert (callback); - device = nm_auth_chain_get_data (chain, "device"); - nm_assert (NM_IS_DEVICE (device)); - - cancellable = nm_auth_chain_get_cancellable (chain); - nm_assert (!cancellable || G_IS_CANCELLABLE (cancellable)); - - result = nm_auth_chain_get_result (chain, permission); - subject = nm_auth_chain_get_subject (chain); - - if ( cancellable - && g_cancellable_set_error_if_cancelled (cancellable, &error)) { - /* pass. */ - } else { - if (result != NM_AUTH_CALL_RESULT_YES) { - _LOGD (LOGD_CORE, "%s request failed: not authorized", permission); - error = g_error_new (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - "%s request failed: not authorized", - permission); - } - - nm_assert (error || (result == NM_AUTH_CALL_RESULT_YES)); - } - - callback (device, - context, - subject, - error, - nm_auth_chain_get_data (chain, "user-data")); +device_auth_done_cb(NMAuthChain *chain, GDBusMethodInvocation *context, gpointer user_data) +{ + NMManager * self = NM_MANAGER(user_data); + gs_free_error GError * error = NULL; + NMAuthCallResult result; + NMDevice * device; + GCancellable * cancellable; + const char * permission; + NMManagerDeviceAuthRequestFunc callback; + NMAuthSubject * subject; + + nm_assert(G_IS_DBUS_METHOD_INVOCATION(context)); + + c_list_unlink(nm_auth_chain_parent_lst_list(chain)); + + permission = nm_auth_chain_get_data(chain, "perm"); + nm_assert(permission); + callback = nm_auth_chain_get_data(chain, "callback"); + nm_assert(callback); + device = nm_auth_chain_get_data(chain, "device"); + nm_assert(NM_IS_DEVICE(device)); + + cancellable = nm_auth_chain_get_cancellable(chain); + nm_assert(!cancellable || G_IS_CANCELLABLE(cancellable)); + + result = nm_auth_chain_get_result(chain, permission); + subject = nm_auth_chain_get_subject(chain); + + if (cancellable && g_cancellable_set_error_if_cancelled(cancellable, &error)) { + /* pass. */ + } else { + if (result != NM_AUTH_CALL_RESULT_YES) { + _LOGD(LOGD_CORE, "%s request failed: not authorized", permission); + error = g_error_new(NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + "%s request failed: not authorized", + permission); + } + + nm_assert(error || (result == NM_AUTH_CALL_RESULT_YES)); + } + + callback(device, context, subject, error, nm_auth_chain_get_data(chain, "user-data")); } static void -_device_auth_done_fail_on_idle (gpointer user_data, GCancellable *cancellable) +_device_auth_done_fail_on_idle(gpointer user_data, GCancellable *cancellable) { - gs_unref_object NMManager *self = NULL; - gs_unref_object NMDevice *device = NULL; - gs_unref_object GDBusMethodInvocation *context = NULL; - gs_unref_object NMAuthSubject *subject = NULL; - gs_free_error GError *error_original = NULL; - gs_free_error GError *error_cancelled = NULL; - NMManagerDeviceAuthRequestFunc callback; - gpointer callback_user_data; + gs_unref_object NMManager *self = NULL; + gs_unref_object NMDevice *device = NULL; + gs_unref_object GDBusMethodInvocation *context = NULL; + gs_unref_object NMAuthSubject *subject = NULL; + gs_free_error GError *error_original = NULL; + gs_free_error GError * error_cancelled = NULL; + NMManagerDeviceAuthRequestFunc callback; + gpointer callback_user_data; - nm_utils_user_data_unpack (&self, &device, &context, &subject, &error_original, &callback, &callback_user_data); + nm_utils_user_data_unpack(&self, + &device, + &context, + &subject, + &error_original, + &callback, + &callback_user_data); - g_cancellable_set_error_if_cancelled (cancellable, &error_cancelled); + g_cancellable_set_error_if_cancelled(cancellable, &error_cancelled); - callback (device, - context, - subject, - error_cancelled ?: error_original, - callback_user_data); + callback(device, context, subject, error_cancelled ?: error_original, callback_user_data); } void -nm_manager_device_auth_request (NMManager *self, - NMDevice *device, - GDBusMethodInvocation *context, - NMConnection *connection, - const char *permission, - gboolean allow_interaction, - GCancellable *cancellable, - NMManagerDeviceAuthRequestFunc callback, - gpointer user_data) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - gs_free_error GError *error = NULL; - gs_unref_object NMAuthSubject *subject = NULL; - NMAuthChain *chain; - char *permission_dup; - - /* Validate the caller */ - subject = nm_dbus_manager_new_auth_subject_from_context (context); - if (!subject) { - g_set_error_literal (&error, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - NM_UTILS_ERROR_MSG_REQ_UID_UKNOWN); - goto fail_on_idle; - } - - /* Ensure the subject has permissions for this connection */ - if ( connection - && !nm_auth_is_subject_in_acl_set_error (connection, - subject, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - &error)) - goto fail_on_idle; - - /* Validate the request */ - chain = nm_auth_chain_new_subject (subject, context, device_auth_done_cb, self); - if (!chain) { - g_set_error (&error, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - NM_UTILS_ERROR_MSG_REQ_AUTH_FAILED); - goto fail_on_idle; - } - - if (cancellable) - nm_auth_chain_set_cancellable (chain, cancellable); - - permission_dup = g_strdup (permission); - - c_list_link_tail (&priv->auth_lst_head, nm_auth_chain_parent_lst_list (chain)); - nm_auth_chain_set_data (chain, "device", g_object_ref (device), g_object_unref); - nm_auth_chain_set_data (chain, "callback", callback, NULL); - nm_auth_chain_set_data (chain, "user-data", user_data, NULL); - nm_auth_chain_set_data (chain, "perm", permission_dup /* transfer ownership */, g_free); - nm_auth_chain_add_call_unsafe (chain, permission_dup, allow_interaction); - return; +nm_manager_device_auth_request(NMManager * self, + NMDevice * device, + GDBusMethodInvocation * context, + NMConnection * connection, + const char * permission, + gboolean allow_interaction, + GCancellable * cancellable, + NMManagerDeviceAuthRequestFunc callback, + gpointer user_data) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + gs_free_error GError *error = NULL; + gs_unref_object NMAuthSubject *subject = NULL; + NMAuthChain * chain; + char * permission_dup; + + /* Validate the caller */ + subject = nm_dbus_manager_new_auth_subject_from_context(context); + if (!subject) { + g_set_error_literal(&error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + NM_UTILS_ERROR_MSG_REQ_UID_UKNOWN); + goto fail_on_idle; + } + + /* Ensure the subject has permissions for this connection */ + if (connection + && !nm_auth_is_subject_in_acl_set_error(connection, + subject, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + &error)) + goto fail_on_idle; + + /* Validate the request */ + chain = nm_auth_chain_new_subject(subject, context, device_auth_done_cb, self); + if (!chain) { + g_set_error(&error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + NM_UTILS_ERROR_MSG_REQ_AUTH_FAILED); + goto fail_on_idle; + } + + if (cancellable) + nm_auth_chain_set_cancellable(chain, cancellable); + + permission_dup = g_strdup(permission); + + c_list_link_tail(&priv->auth_lst_head, nm_auth_chain_parent_lst_list(chain)); + nm_auth_chain_set_data(chain, "device", g_object_ref(device), g_object_unref); + nm_auth_chain_set_data(chain, "callback", callback, NULL); + nm_auth_chain_set_data(chain, "user-data", user_data, NULL); + nm_auth_chain_set_data(chain, "perm", permission_dup /* transfer ownership */, g_free); + nm_auth_chain_add_call_unsafe(chain, permission_dup, allow_interaction); + return; fail_on_idle: - nm_utils_invoke_on_idle (cancellable, - _device_auth_done_fail_on_idle, - nm_utils_user_data_pack (g_object_ref (self), - g_object_ref (device), - g_object_ref (context), - g_steal_pointer (&subject), - g_steal_pointer (&error), - callback, - user_data)); + nm_utils_invoke_on_idle(cancellable, + _device_auth_done_fail_on_idle, + nm_utils_user_data_pack(g_object_ref(self), + g_object_ref(device), + g_object_ref(context), + g_steal_pointer(&subject), + g_steal_pointer(&error), + callback, + user_data)); } static gboolean -new_activation_allowed_for_connection (NMManager *self, - NMSettingsConnection *connection) +new_activation_allowed_for_connection(NMManager *self, NMSettingsConnection *connection) { - if (NM_IN_SET (_nm_connection_get_multi_connect (nm_settings_connection_get_connection (connection)), - NM_CONNECTION_MULTI_CONNECT_MANUAL_MULTIPLE, - NM_CONNECTION_MULTI_CONNECT_MULTIPLE)) - return TRUE; + if (NM_IN_SET( + _nm_connection_get_multi_connect(nm_settings_connection_get_connection(connection)), + NM_CONNECTION_MULTI_CONNECT_MANUAL_MULTIPLE, + NM_CONNECTION_MULTI_CONNECT_MULTIPLE)) + return TRUE; - return !active_connection_find (self, connection, NULL, - NM_ACTIVE_CONNECTION_STATE_ACTIVATED, - NULL); + return !active_connection_find(self, + connection, + NULL, + NM_ACTIVE_CONNECTION_STATE_ACTIVATED, + NULL); } /** @@ -2559,595 +2555,598 @@ new_activation_allowed_for_connection (NMManager *self, * the device does not support assuming existing connections. */ static NMSettingsConnection * -get_existing_connection (NMManager *self, - NMDevice *device, - gboolean *out_generated) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - gs_unref_object NMConnection *connection = NULL; - NMSettingsConnection *added; - GError *error = NULL; - gs_free_error GError *gen_error = NULL; - NMDevice *master = NULL; - int ifindex = nm_device_get_ifindex (device); - NMSettingsConnection *matched = NULL; - NMSettingsConnection *connection_checked = NULL; - gboolean assume_state_guess_assume = FALSE; - const char *assume_state_connection_uuid = NULL; - gboolean maybe_later, only_by_uuid = FALSE; - - if (out_generated) - *out_generated = FALSE; - - nm_device_capture_initial_config (device); - - if (ifindex) { - int master_ifindex = nm_platform_link_get_master (priv->platform, ifindex); - - /* Check that the master is activating before assuming a - * slave connection. However, ignore ovs-system master as - * we never manage it. - */ - if ( master_ifindex - && nm_platform_link_get_type (priv->platform, master_ifindex) != NM_LINK_TYPE_OPENVSWITCH) { - master = nm_manager_get_device_by_ifindex (self, master_ifindex); - if (!master) { - _LOG2D (LOGD_DEVICE, device, "assume: don't assume because " - "cannot generate connection for slave before its master (%s/%d)", - nm_platform_link_get_name (priv->platform, master_ifindex), master_ifindex); - return NULL; - } - if (!nm_device_get_act_request (master)) { - _LOG2D (LOGD_DEVICE, device, "assume: don't assume because " - "cannot generate connection for slave before master %s activates", - nm_device_get_iface (master)); - return NULL; - } - } - } - - /* The core of the API is nm_device_generate_connection() function and - * update_connection() virtual method and the convenient connection_type - * class attribute. Subclasses supporting the new API must have - * update_connection() implemented, otherwise nm_device_generate_connection() - * returns NULL. - */ - connection = nm_device_generate_connection (device, master, &maybe_later, &gen_error); - if (!connection) { - if (maybe_later) { - /* The device can generate a connection, but it failed for now. - * Give it a chance to match a connection from the state file. */ - only_by_uuid = TRUE; - } else { - nm_device_assume_state_reset (device); - _LOG2D (LOGD_DEVICE, device, "assume: cannot generate connection: %s", - gen_error->message); - return NULL; - } - } - - nm_device_assume_state_get (device, - &assume_state_guess_assume, - &assume_state_connection_uuid); - - /* Now we need to compare the generated connection to each configured - * connection. The comparison function is the heart of the connection - * assumption implementation and it must compare the connections very - * carefully to sort out various corner cases. Also, the comparison is - * not entirely symmetric. - * - * When no configured connection matches the generated connection, we keep - * the generated connection instead. - */ - if ( assume_state_connection_uuid - && (connection_checked = nm_settings_get_connection_by_uuid (priv->settings, assume_state_connection_uuid)) - && new_activation_allowed_for_connection (self, connection_checked) - && nm_device_check_connection_compatible (device, - nm_settings_connection_get_connection (connection_checked), - NULL)) { - - if (connection) { - NMConnection *con = nm_settings_connection_get_connection (connection_checked); - - if (nm_utils_match_connection ((NMConnection *[]) { con, NULL }, - connection, - TRUE, - nm_device_has_carrier (device), - nm_device_get_route_metric (device, AF_INET), - nm_device_get_route_metric (device, AF_INET6), - NULL, NULL)) - matched = connection_checked; - } else - matched = connection_checked; - } - - if (!matched && only_by_uuid) { - _LOG2D (LOGD_DEVICE, device, "assume: cannot generate connection: %s", - gen_error->message); - return NULL; - } - - if (!matched && assume_state_guess_assume) { - gs_free NMSettingsConnection **sett_conns = NULL; - guint len, i, j; - - /* the state file doesn't indicate a connection UUID to assume. Search the - * persistent connections for a matching candidate. */ - sett_conns = nm_manager_get_activatable_connections (self, FALSE, FALSE, &len); - if (len > 0) { - for (i = 0, j = 0; i < len; i++) { - NMSettingsConnection *sett_conn = sett_conns[i]; - - if ( sett_conn != connection_checked - && nm_device_check_connection_compatible (device, - nm_settings_connection_get_connection (sett_conn), - NULL)) - sett_conns[j++] = sett_conn; - } - sett_conns[j] = NULL; - len = j; - if (len > 0) { - gs_free NMConnection **conns = NULL; - NMConnection *con; - - g_qsort_with_data (sett_conns, len, sizeof (sett_conns[0]), - nm_settings_connection_cmp_timestamp_p_with_data, NULL); - - conns = nm_settings_connections_array_to_connections (sett_conns, len); - - con = nm_utils_match_connection (conns, - connection, - FALSE, - nm_device_has_carrier (device), - nm_device_get_route_metric (device, AF_INET), - nm_device_get_route_metric (device, AF_INET6), - NULL, - NULL); - if (con) { - for (i = 0; i < len; i++) { - if (conns[i] == con) { - matched = sett_conns[i]; - break; - } - } - nm_assert (matched); - } - } - } - } - - if (matched) { - - if (NM_FLAGS_HAS (nm_settings_connection_get_flags (matched), NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL)) { - _LOG2D (LOGD_DEVICE, device, "assume: take over previous connection '%s' (%s)", - nm_settings_connection_get_id (matched), - nm_settings_connection_get_uuid (matched)); - NM_SET_OUT (out_generated, TRUE); - } else { - _LOG2I (LOGD_DEVICE, device, "assume: will attempt to assume matching connection '%s' (%s)%s", - nm_settings_connection_get_id (matched), - nm_settings_connection_get_uuid (matched), - assume_state_connection_uuid && nm_streq (assume_state_connection_uuid, nm_settings_connection_get_uuid (matched)) - ? " (indicated)" : " (guessed)"); - } - nm_device_assume_state_reset (device); - return matched; - } - - _LOG2D (LOGD_DEVICE, device, "assume: generated connection '%s' (%s)", - nm_connection_get_id (connection), - nm_connection_get_uuid (connection)); - - nm_device_assume_state_reset (device); - - if (!nm_settings_add_connection (priv->settings, - connection, - NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY, - NM_SETTINGS_CONNECTION_ADD_REASON_NONE, - NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED - | NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE - | NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL, - &added, - &error)) { - _LOG2W (LOGD_SETTINGS, device, "assume: failure to save generated connection '%s': %s", - nm_connection_get_id (connection), - error->message); - g_error_free (error); - return NULL; - } - - NM_SET_OUT (out_generated, TRUE); - return added; +get_existing_connection(NMManager *self, NMDevice *device, gboolean *out_generated) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + gs_unref_object NMConnection *connection = NULL; + NMSettingsConnection * added; + GError * error = NULL; + gs_free_error GError *gen_error = NULL; + NMDevice * master = NULL; + int ifindex = nm_device_get_ifindex(device); + NMSettingsConnection *matched = NULL; + NMSettingsConnection *connection_checked = NULL; + gboolean assume_state_guess_assume = FALSE; + const char * assume_state_connection_uuid = NULL; + gboolean maybe_later, only_by_uuid = FALSE; + + if (out_generated) + *out_generated = FALSE; + + nm_device_capture_initial_config(device); + + if (ifindex) { + int master_ifindex = nm_platform_link_get_master(priv->platform, ifindex); + + /* Check that the master is activating before assuming a + * slave connection. However, ignore ovs-system master as + * we never manage it. + */ + if (master_ifindex + && nm_platform_link_get_type(priv->platform, master_ifindex) + != NM_LINK_TYPE_OPENVSWITCH) { + master = nm_manager_get_device_by_ifindex(self, master_ifindex); + if (!master) { + _LOG2D(LOGD_DEVICE, + device, + "assume: don't assume because " + "cannot generate connection for slave before its master (%s/%d)", + nm_platform_link_get_name(priv->platform, master_ifindex), + master_ifindex); + return NULL; + } + if (!nm_device_get_act_request(master)) { + _LOG2D(LOGD_DEVICE, + device, + "assume: don't assume because " + "cannot generate connection for slave before master %s activates", + nm_device_get_iface(master)); + return NULL; + } + } + } + + /* The core of the API is nm_device_generate_connection() function and + * update_connection() virtual method and the convenient connection_type + * class attribute. Subclasses supporting the new API must have + * update_connection() implemented, otherwise nm_device_generate_connection() + * returns NULL. + */ + connection = nm_device_generate_connection(device, master, &maybe_later, &gen_error); + if (!connection) { + if (maybe_later) { + /* The device can generate a connection, but it failed for now. + * Give it a chance to match a connection from the state file. */ + only_by_uuid = TRUE; + } else { + nm_device_assume_state_reset(device); + _LOG2D(LOGD_DEVICE, + device, + "assume: cannot generate connection: %s", + gen_error->message); + return NULL; + } + } + + nm_device_assume_state_get(device, &assume_state_guess_assume, &assume_state_connection_uuid); + + /* Now we need to compare the generated connection to each configured + * connection. The comparison function is the heart of the connection + * assumption implementation and it must compare the connections very + * carefully to sort out various corner cases. Also, the comparison is + * not entirely symmetric. + * + * When no configured connection matches the generated connection, we keep + * the generated connection instead. + */ + if (assume_state_connection_uuid + && (connection_checked = + nm_settings_get_connection_by_uuid(priv->settings, assume_state_connection_uuid)) + && new_activation_allowed_for_connection(self, connection_checked) + && nm_device_check_connection_compatible( + device, + nm_settings_connection_get_connection(connection_checked), + NULL)) { + if (connection) { + NMConnection *con = nm_settings_connection_get_connection(connection_checked); + + if (nm_utils_match_connection((NMConnection *[]){con, NULL}, + connection, + TRUE, + nm_device_has_carrier(device), + nm_device_get_route_metric(device, AF_INET), + nm_device_get_route_metric(device, AF_INET6), + NULL, + NULL)) + matched = connection_checked; + } else + matched = connection_checked; + } + + if (!matched && only_by_uuid) { + _LOG2D(LOGD_DEVICE, device, "assume: cannot generate connection: %s", gen_error->message); + return NULL; + } + + if (!matched && assume_state_guess_assume) { + gs_free NMSettingsConnection **sett_conns = NULL; + guint len, i, j; + + /* the state file doesn't indicate a connection UUID to assume. Search the + * persistent connections for a matching candidate. */ + sett_conns = nm_manager_get_activatable_connections(self, FALSE, FALSE, &len); + if (len > 0) { + for (i = 0, j = 0; i < len; i++) { + NMSettingsConnection *sett_conn = sett_conns[i]; + + if (sett_conn != connection_checked + && nm_device_check_connection_compatible( + device, + nm_settings_connection_get_connection(sett_conn), + NULL)) + sett_conns[j++] = sett_conn; + } + sett_conns[j] = NULL; + len = j; + if (len > 0) { + gs_free NMConnection **conns = NULL; + NMConnection * con; + + g_qsort_with_data(sett_conns, + len, + sizeof(sett_conns[0]), + nm_settings_connection_cmp_timestamp_p_with_data, + NULL); + + conns = nm_settings_connections_array_to_connections(sett_conns, len); + + con = nm_utils_match_connection(conns, + connection, + FALSE, + nm_device_has_carrier(device), + nm_device_get_route_metric(device, AF_INET), + nm_device_get_route_metric(device, AF_INET6), + NULL, + NULL); + if (con) { + for (i = 0; i < len; i++) { + if (conns[i] == con) { + matched = sett_conns[i]; + break; + } + } + nm_assert(matched); + } + } + } + } + + if (matched) { + if (NM_FLAGS_HAS(nm_settings_connection_get_flags(matched), + NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL)) { + _LOG2D(LOGD_DEVICE, + device, + "assume: take over previous connection '%s' (%s)", + nm_settings_connection_get_id(matched), + nm_settings_connection_get_uuid(matched)); + NM_SET_OUT(out_generated, TRUE); + } else { + _LOG2I(LOGD_DEVICE, + device, + "assume: will attempt to assume matching connection '%s' (%s)%s", + nm_settings_connection_get_id(matched), + nm_settings_connection_get_uuid(matched), + assume_state_connection_uuid + && nm_streq(assume_state_connection_uuid, + nm_settings_connection_get_uuid(matched)) + ? " (indicated)" + : " (guessed)"); + } + nm_device_assume_state_reset(device); + return matched; + } + + _LOG2D(LOGD_DEVICE, + device, + "assume: generated connection '%s' (%s)", + nm_connection_get_id(connection), + nm_connection_get_uuid(connection)); + + nm_device_assume_state_reset(device); + + if (!nm_settings_add_connection(priv->settings, + connection, + NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY, + NM_SETTINGS_CONNECTION_ADD_REASON_NONE, + NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED + | NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE + | NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL, + &added, + &error)) { + _LOG2W(LOGD_SETTINGS, + device, + "assume: failure to save generated connection '%s': %s", + nm_connection_get_id(connection), + error->message); + g_error_free(error); + return NULL; + } + + NM_SET_OUT(out_generated, TRUE); + return added; } static gboolean -copy_lease (const char *src, const char *dst) +copy_lease(const char *src, const char *dst) { - nm_auto_close int src_fd = -1; - int dst_fd; - ssize_t res, size = SSIZE_MAX; + nm_auto_close int src_fd = -1; + int dst_fd; + ssize_t res, size = SSIZE_MAX; - src_fd = open (src, O_RDONLY|O_CLOEXEC); - if (src_fd < 0) - return FALSE; + src_fd = open(src, O_RDONLY | O_CLOEXEC); + if (src_fd < 0) + return FALSE; - dst_fd = open (dst, O_CREAT|O_EXCL|O_CLOEXEC|O_WRONLY, 0644); - if (dst_fd < 0) - return FALSE; + dst_fd = open(dst, O_CREAT | O_EXCL | O_CLOEXEC | O_WRONLY, 0644); + if (dst_fd < 0) + return FALSE; - while ((res = sendfile (dst_fd, src_fd, NULL, size)) > 0) - size -= res; + while ((res = sendfile(dst_fd, src_fd, NULL, size)) > 0) + size -= res; - nm_close (dst_fd); + nm_close(dst_fd); - if (res != 0) { - unlink (dst); - return FALSE; - } + if (res != 0) { + unlink(dst); + return FALSE; + } - return TRUE; + return TRUE; } static gboolean -recheck_assume_connection (NMManager *self, - NMDevice *device) -{ - NMSettingsConnection *sett_conn; - gboolean was_unmanaged = FALSE; - gboolean generated = FALSE; - NMDeviceState state; - gboolean activation_type_assume; - - g_return_val_if_fail (NM_IS_MANAGER (self), FALSE); - g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); - - if (!nm_device_get_managed (device, FALSE)) { - nm_device_assume_state_reset (device); - _LOG2D (LOGD_DEVICE, device, "assume: don't assume because %s", "not managed"); - return FALSE; - } - - state = nm_device_get_state (device); - if (state > NM_DEVICE_STATE_DISCONNECTED) { - nm_device_assume_state_reset (device); - _LOG2D (LOGD_DEVICE, device, "assume: don't assume due to device state %s", - nm_device_state_to_str (state)); - return FALSE; - } - - sett_conn = get_existing_connection (self, device, &generated); - /* log no reason. get_existing_connection() already does it. */ - if (!sett_conn) - return FALSE; - - activation_type_assume = !generated; - - if (state == NM_DEVICE_STATE_UNMANAGED) { - gs_free char *initramfs_lease = g_strdup_printf (RUNSTATEDIR "/initramfs/net.%s.lease", - nm_device_get_iface (device)); - gs_free char *connection_lease = g_strdup_printf (NMRUNDIR "/dhclient-%s-%s.lease", - nm_settings_connection_get_uuid (sett_conn), - nm_device_get_iface (device)); - - if (copy_lease (initramfs_lease, connection_lease)) { - unlink (initramfs_lease); - /* - * We've managed to steal the lease used by initramfs before it - * killed off the dhclient. We need to take ownership of the configured - * connection and act like the device was configured by us. - * Otherwise the address would just expire. - */ - _LOG2I (LOGD_DEVICE, device, "assume: taking over an initramfs-configured connection"); - activation_type_assume = TRUE; - - if (generated) { - /* Reset the IPv4 setting to empty method=auto, regardless of what assumption guessed. */ - nm_connection_add_setting (nm_settings_connection_get_connection (sett_conn), - g_object_new (NM_TYPE_SETTING_IP4_CONFIG, - NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, - NULL)); - - nm_settings_connection_update (sett_conn, - NULL, - NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP, - NM_SETTINGS_CONNECTION_INT_FLAGS_NONE, - NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE - | NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL, - NM_SETTINGS_CONNECTION_UPDATE_REASON_NONE, - "assume-initrd", - NULL); - } - } - } - - nm_device_sys_iface_state_set (device, - activation_type_assume - ? NM_DEVICE_SYS_IFACE_STATE_ASSUME - : NM_DEVICE_SYS_IFACE_STATE_EXTERNAL); - - /* Move device to DISCONNECTED to activate the connection */ - if (state == NM_DEVICE_STATE_UNMANAGED) { - was_unmanaged = TRUE; - nm_device_state_changed (device, - NM_DEVICE_STATE_UNAVAILABLE, - NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); - } - if (nm_device_get_state (device) == NM_DEVICE_STATE_UNAVAILABLE) { - nm_device_state_changed (device, - NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); - } - - g_return_val_if_fail (nm_device_get_state (device) >= NM_DEVICE_STATE_DISCONNECTED, FALSE); - - { - gs_unref_object NMActiveConnection *active = NULL; - gs_unref_object NMAuthSubject *subject = NULL; - NMActiveConnection *master_ac; - GError *error = NULL; - - subject = nm_auth_subject_new_internal (); - - /* Note: the lifetime of the activation connection is always bound to the profiles visibility - * via NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY. - * - * This only makes a difference, if the profile actually has "connection.permissions" - * set to limit visibility (which is not the case for externally managed, generated profiles). - * - * If we assume a previously active connection whose lifetime was unbound, we now bind it - * after restart. That is not correct, and can mean that the profile becomes subject to - * deactivation after restart (if the user logs out). - * - * This should be improved, but it's unclear how. */ - active = _new_active_connection (self, - FALSE, - sett_conn, - NULL, - NULL, - NULL, - device, - subject, - activation_type_assume ? NM_ACTIVATION_TYPE_ASSUME : NM_ACTIVATION_TYPE_EXTERNAL, - activation_type_assume ? NM_ACTIVATION_REASON_ASSUME : NM_ACTIVATION_REASON_EXTERNAL, - NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY, - &error); - - if (!active) { - _LOGW (LOGD_DEVICE, "assume: assumed connection %s failed to activate: %s", - nm_dbus_object_get_path (NM_DBUS_OBJECT (sett_conn)), - error->message); - g_error_free (error); - - if (was_unmanaged) { - nm_device_state_changed (device, - NM_DEVICE_STATE_UNAVAILABLE, - NM_DEVICE_STATE_REASON_CONFIG_FAILED); - } - - if ( generated - && !activation_type_assume) { - _LOG2D (LOGD_DEVICE, device, "assume: deleting generated connection after assuming failed"); - nm_settings_connection_delete (sett_conn, FALSE); - } else { - if (nm_device_sys_iface_state_get (device) == NM_DEVICE_SYS_IFACE_STATE_ASSUME) - nm_device_sys_iface_state_set (device, NM_DEVICE_SYS_IFACE_STATE_EXTERNAL); - } - return FALSE; - } - - /* If the device is a slave or VLAN, find the master ActiveConnection */ - master_ac = NULL; - if ( find_master (self, - nm_settings_connection_get_connection (sett_conn), - device, - NULL, - NULL, - &master_ac, - NULL) - && master_ac) - nm_active_connection_set_master (active, master_ac); - - active_connection_add (self, active); - nm_device_queue_activation (device, NM_ACT_REQUEST (active)); - } - - return TRUE; +recheck_assume_connection(NMManager *self, NMDevice *device) +{ + NMSettingsConnection *sett_conn; + gboolean was_unmanaged = FALSE; + gboolean generated = FALSE; + NMDeviceState state; + gboolean activation_type_assume; + + g_return_val_if_fail(NM_IS_MANAGER(self), FALSE); + g_return_val_if_fail(NM_IS_DEVICE(device), FALSE); + + if (!nm_device_get_managed(device, FALSE)) { + nm_device_assume_state_reset(device); + _LOG2D(LOGD_DEVICE, device, "assume: don't assume because %s", "not managed"); + return FALSE; + } + + state = nm_device_get_state(device); + if (state > NM_DEVICE_STATE_DISCONNECTED) { + nm_device_assume_state_reset(device); + _LOG2D(LOGD_DEVICE, + device, + "assume: don't assume due to device state %s", + nm_device_state_to_str(state)); + return FALSE; + } + + sett_conn = get_existing_connection(self, device, &generated); + /* log no reason. get_existing_connection() already does it. */ + if (!sett_conn) + return FALSE; + + activation_type_assume = !generated; + + if (state == NM_DEVICE_STATE_UNMANAGED) { + gs_free char *initramfs_lease = + g_strdup_printf(RUNSTATEDIR "/initramfs/net.%s.lease", nm_device_get_iface(device)); + gs_free char *connection_lease = g_strdup_printf(NMRUNDIR "/dhclient-%s-%s.lease", + nm_settings_connection_get_uuid(sett_conn), + nm_device_get_iface(device)); + + if (copy_lease(initramfs_lease, connection_lease)) { + unlink(initramfs_lease); + /* + * We've managed to steal the lease used by initramfs before it + * killed off the dhclient. We need to take ownership of the configured + * connection and act like the device was configured by us. + * Otherwise, the address would just expire. + */ + _LOG2I(LOGD_DEVICE, device, "assume: taking over an initramfs-configured connection"); + activation_type_assume = TRUE; + + if (generated) { + /* Reset the IPv4 setting to empty method=auto, regardless of what assumption guessed. */ + nm_connection_add_setting(nm_settings_connection_get_connection(sett_conn), + g_object_new(NM_TYPE_SETTING_IP4_CONFIG, + NM_SETTING_IP_CONFIG_METHOD, + NM_SETTING_IP4_CONFIG_METHOD_AUTO, + NULL)); + + nm_settings_connection_update(sett_conn, + NULL, + NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP, + NM_SETTINGS_CONNECTION_INT_FLAGS_NONE, + NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE + | NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL, + NM_SETTINGS_CONNECTION_UPDATE_REASON_NONE, + "assume-initrd", + NULL); + } + } + } + + nm_device_sys_iface_state_set(device, + activation_type_assume ? NM_DEVICE_SYS_IFACE_STATE_ASSUME + : NM_DEVICE_SYS_IFACE_STATE_EXTERNAL); + + /* Move device to DISCONNECTED to activate the connection */ + if (state == NM_DEVICE_STATE_UNMANAGED) { + was_unmanaged = TRUE; + nm_device_state_changed(device, + NM_DEVICE_STATE_UNAVAILABLE, + NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); + } + if (nm_device_get_state(device) == NM_DEVICE_STATE_UNAVAILABLE) { + nm_device_state_changed(device, + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); + } + + g_return_val_if_fail(nm_device_get_state(device) >= NM_DEVICE_STATE_DISCONNECTED, FALSE); + + { + gs_unref_object NMActiveConnection *active = NULL; + gs_unref_object NMAuthSubject *subject = NULL; + NMActiveConnection * master_ac; + GError * error = NULL; + + subject = nm_auth_subject_new_internal(); + + /* Note: the lifetime of the activation connection is always bound to the profiles visibility + * via NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY. + * + * This only makes a difference, if the profile actually has "connection.permissions" + * set to limit visibility (which is not the case for externally managed, generated profiles). + * + * If we assume a previously active connection whose lifetime was unbound, we now bind it + * after restart. That is not correct, and can mean that the profile becomes subject to + * deactivation after restart (if the user logs out). + * + * This should be improved, but it's unclear how. */ + active = _new_active_connection( + self, + FALSE, + sett_conn, + NULL, + NULL, + NULL, + device, + subject, + activation_type_assume ? NM_ACTIVATION_TYPE_ASSUME : NM_ACTIVATION_TYPE_EXTERNAL, + activation_type_assume ? NM_ACTIVATION_REASON_ASSUME : NM_ACTIVATION_REASON_EXTERNAL, + NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY, + &error); + + if (!active) { + _LOGW(LOGD_DEVICE, + "assume: assumed connection %s failed to activate: %s", + nm_dbus_object_get_path(NM_DBUS_OBJECT(sett_conn)), + error->message); + g_error_free(error); + + if (was_unmanaged) { + nm_device_state_changed(device, + NM_DEVICE_STATE_UNAVAILABLE, + NM_DEVICE_STATE_REASON_CONFIG_FAILED); + } + + if (generated && !activation_type_assume) { + _LOG2D(LOGD_DEVICE, + device, + "assume: deleting generated connection after assuming failed"); + nm_settings_connection_delete(sett_conn, FALSE); + } else { + if (nm_device_sys_iface_state_get(device) == NM_DEVICE_SYS_IFACE_STATE_ASSUME) + nm_device_sys_iface_state_set(device, NM_DEVICE_SYS_IFACE_STATE_EXTERNAL); + } + return FALSE; + } + + /* If the device is a slave or VLAN, find the master ActiveConnection */ + master_ac = NULL; + if (find_master(self, + nm_settings_connection_get_connection(sett_conn), + device, + NULL, + NULL, + &master_ac, + NULL) + && master_ac) + nm_active_connection_set_master(active, master_ac); + + active_connection_add(self, active); + nm_device_queue_activation(device, NM_ACT_REQUEST(active)); + } + + return TRUE; } static void -recheck_assume_connection_cb (NMManager *self, NMDevice *device) +recheck_assume_connection_cb(NMManager *self, NMDevice *device) { - recheck_assume_connection (self, device); + recheck_assume_connection(self, device); } static void -device_ifindex_changed (NMDevice *device, - GParamSpec *pspec, - NMManager *self) +device_ifindex_changed(NMDevice *device, GParamSpec *pspec, NMManager *self) { - _parent_notify_changed (self, device, FALSE); + _parent_notify_changed(self, device, FALSE); } static void -device_ip_iface_changed (NMDevice *device, - GParamSpec *pspec, - NMManager *self) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - const char *ip_iface = nm_device_get_ip_iface (device); - NMDeviceType device_type = nm_device_get_device_type (device); - NMDevice *candidate; - - /* Remove NMDevice objects that are actually child devices of others, - * when the other device finally knows its IP interface name. For example, - * remove the PPP interface that's a child of a WWAN device, since it's - * not really a standalone NMDevice. - */ - c_list_for_each_entry (candidate, &priv->devices_lst_head, devices_lst) { - if ( candidate != device - && g_strcmp0 (nm_device_get_iface (candidate), ip_iface) == 0 - && nm_device_get_device_type (candidate) == device_type - && nm_device_is_real (candidate)) { - remove_device (self, candidate, FALSE); - break; - } - } +device_ip_iface_changed(NMDevice *device, GParamSpec *pspec, NMManager *self) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + const char * ip_iface = nm_device_get_ip_iface(device); + NMDeviceType device_type = nm_device_get_device_type(device); + NMDevice * candidate; + + /* Remove NMDevice objects that are actually child devices of others, + * when the other device finally knows its IP interface name. For example, + * remove the PPP interface that's a child of a WWAN device, since it's + * not really a standalone NMDevice. + */ + c_list_for_each_entry (candidate, &priv->devices_lst_head, devices_lst) { + if (candidate != device && nm_streq0(nm_device_get_iface(candidate), ip_iface) + && nm_device_get_device_type(candidate) == device_type + && nm_device_is_real(candidate)) { + remove_device(self, candidate, FALSE); + break; + } + } } static void -device_iface_changed (NMDevice *device, - GParamSpec *pspec, - NMManager *self) +device_iface_changed(NMDevice *device, GParamSpec *pspec, NMManager *self) { - /* Virtual connections may refer to the new device name as - * parent device, retry to activate them. - */ - retry_connections_for_parent_device (self, device); + /* Virtual connections may refer to the new device name as + * parent device, retry to activate them. + */ + retry_connections_for_parent_device(self, device); } static void -_emit_device_added_removed (NMManager *self, - NMDevice *device, - gboolean is_added) -{ - nm_dbus_object_emit_signal (NM_DBUS_OBJECT (self), - &interface_info_manager, - is_added - ? &signal_info_device_added - : &signal_info_device_removed, - "(o)", - nm_dbus_object_get_path (NM_DBUS_OBJECT (device))); - g_signal_emit (self, - signals[is_added ? DEVICE_ADDED : DEVICE_REMOVED], - 0, - device); - _notify (self, PROP_DEVICES); +_emit_device_added_removed(NMManager *self, NMDevice *device, gboolean is_added) +{ + nm_dbus_object_emit_signal(NM_DBUS_OBJECT(self), + &interface_info_manager, + is_added ? &signal_info_device_added : &signal_info_device_removed, + "(o)", + nm_dbus_object_get_path(NM_DBUS_OBJECT(device))); + g_signal_emit(self, signals[is_added ? DEVICE_ADDED : DEVICE_REMOVED], 0, device); + _notify(self, PROP_DEVICES); } static void -device_realized (NMDevice *device, - GParamSpec *pspec, - NMManager *self) +device_realized(NMDevice *device, GParamSpec *pspec, NMManager *self) { - _emit_device_added_removed (self, device, nm_device_is_real (device)); + _emit_device_added_removed(self, device, nm_device_is_real(device)); } static NMConnectivityState -_get_best_connectivity (NMManager *self, int addr_family) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMConnectivityState best_state; - NMDevice *dev; - gint64 best_metric; - - if (addr_family == AF_UNSPEC) { - best_state = _get_best_connectivity (self, AF_INET); - if (nm_connectivity_state_cmp (best_state, NM_CONNECTIVITY_FULL) >= 0) { - /* already FULL IPv4 connectivity. No need to check IPv6, it doesn't get - * better. */ - return best_state; - } - return NM_MAX_WITH_CMP (nm_connectivity_state_cmp, - best_state, - _get_best_connectivity (self, AF_INET6)); - } - - nm_assert_addr_family (addr_family); - - best_state = NM_CONNECTIVITY_UNKNOWN; - best_metric = G_MAXINT64; - c_list_for_each_entry (dev, &priv->devices_lst_head, devices_lst) { - const NMPObject *r; - NMConnectivityState state; - gint64 metric; - - r = nm_device_get_best_default_route (dev, addr_family); - if (r) - metric = NMP_OBJECT_CAST_IP_ROUTE (r)->metric; - else { - /* if all devices have no default-route, we still include the best - * of all connectivity state of all the devices. */ - metric = G_MAXINT64; - } - - if (metric > best_metric) { - /* we already have a default route with better metric. The connectivity state - * of this device is irreleavnt. */ - continue; - } - - state = nm_device_get_connectivity_state (dev, addr_family); - if (metric < best_metric) { - /* this device has a better default route. It wins. */ - best_metric = metric; - best_state = state; - } else { - best_state = NM_MAX_WITH_CMP (nm_connectivity_state_cmp, - best_state, - state); - } - - if (nm_connectivity_state_cmp (best_state, NM_CONNECTIVITY_FULL) >= 0) { - /* it doesn't get better than FULL. We are done. */ - break; - } - } - - return best_state; +_get_best_connectivity(NMManager *self, int addr_family) +{ + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + NMConnectivityState best_state; + NMDevice * dev; + gint64 best_metric; + + if (addr_family == AF_UNSPEC) { + best_state = _get_best_connectivity(self, AF_INET); + if (nm_connectivity_state_cmp(best_state, NM_CONNECTIVITY_FULL) >= 0) { + /* already FULL IPv4 connectivity. No need to check IPv6, it doesn't get + * better. */ + return best_state; + } + return NM_MAX_WITH_CMP(nm_connectivity_state_cmp, + best_state, + _get_best_connectivity(self, AF_INET6)); + } + + nm_assert_addr_family(addr_family); + + best_state = NM_CONNECTIVITY_UNKNOWN; + best_metric = G_MAXINT64; + c_list_for_each_entry (dev, &priv->devices_lst_head, devices_lst) { + const NMPObject * r; + NMConnectivityState state; + gint64 metric; + + r = nm_device_get_best_default_route(dev, addr_family); + if (r) + metric = NMP_OBJECT_CAST_IP_ROUTE(r)->metric; + else { + /* if all devices have no default-route, we still include the best + * of all connectivity state of all the devices. */ + metric = G_MAXINT64; + } + + if (metric > best_metric) { + /* we already have a default route with better metric. The connectivity state + * of this device is irreleavnt. */ + continue; + } + + state = nm_device_get_connectivity_state(dev, addr_family); + if (metric < best_metric) { + /* this device has a better default route. It wins. */ + best_metric = metric; + best_state = state; + } else { + best_state = NM_MAX_WITH_CMP(nm_connectivity_state_cmp, best_state, state); + } + + if (nm_connectivity_state_cmp(best_state, NM_CONNECTIVITY_FULL) >= 0) { + /* it doesn't get better than FULL. We are done. */ + break; + } + } + + return best_state; } static void -device_connectivity_changed (NMDevice *device, - GParamSpec *pspec, - NMManager *self) +device_connectivity_changed(NMDevice *device, GParamSpec *pspec, NMManager *self) { - update_connectivity_value (self); + update_connectivity_value(self); } static void -update_connectivity_value (NMManager *self) +update_connectivity_value(NMManager *self) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMConnectivityState best_state; + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + NMConnectivityState best_state; - best_state = _get_best_connectivity (self, AF_UNSPEC); - if (best_state == priv->connectivity_state) - return; + best_state = _get_best_connectivity(self, AF_UNSPEC); + if (best_state == priv->connectivity_state) + return; - priv->connectivity_state = best_state; + priv->connectivity_state = best_state; - _LOGD (LOGD_CORE, "connectivity checking indicates %s", - nm_connectivity_state_to_string (priv->connectivity_state)); + _LOGD(LOGD_CORE, + "connectivity checking indicates %s", + nm_connectivity_state_to_string(priv->connectivity_state)); - nm_manager_update_state (self); - _notify (self, PROP_CONNECTIVITY); - nm_dispatcher_call_connectivity (priv->connectivity_state, NULL, NULL, NULL); + nm_manager_update_state(self); + _notify(self, PROP_CONNECTIVITY); + nm_dispatcher_call_connectivity(priv->connectivity_state, NULL, NULL, NULL); } static void -_device_realize_finish (NMManager *self, - NMDevice *device, - const NMPlatformLink *plink) +_device_realize_finish(NMManager *self, NMDevice *device, const NMPlatformLink *plink) { - g_return_if_fail (NM_IS_MANAGER (self)); - g_return_if_fail (NM_IS_DEVICE (device)); + g_return_if_fail(NM_IS_MANAGER(self)); + g_return_if_fail(NM_IS_DEVICE(device)); - nm_device_realize_finish (device, plink); + nm_device_realize_finish(device, plink); - if (!nm_device_get_managed (device, FALSE)) { - nm_device_assume_state_reset (device); - return; - } + if (!nm_device_get_managed(device, FALSE)) { + nm_device_assume_state_reset(device); + return; + } - if (recheck_assume_connection (self, device)) - return; + if (recheck_assume_connection(self, device)) + return; - /* if we failed to assume a connection for the managed device, but the device - * is still unavailable. Set UNAVAILABLE state again, this time with NOW_MANAGED. */ - nm_device_state_changed (device, - NM_DEVICE_STATE_UNAVAILABLE, - NM_DEVICE_STATE_REASON_NOW_MANAGED); - nm_device_emit_recheck_auto_activate (device); + /* if we failed to assume a connection for the managed device, but the device + * is still unavailable. Set UNAVAILABLE state again, this time with NOW_MANAGED. */ + nm_device_state_changed(device, + NM_DEVICE_STATE_UNAVAILABLE, + NM_DEVICE_STATE_REASON_NOW_MANAGED); + nm_device_emit_recheck_auto_activate(device); } /** @@ -3160,822 +3159,838 @@ _device_realize_finish (NMManager *self, * Callers should decrease the reference count. */ static gboolean -add_device (NMManager *self, NMDevice *device, GError **error) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - const char *iface, *type_desc; - RfKillType rtype; - GSList *iter, *remove = NULL; - int ifindex; - const char *dbus_path; - NMDevice *candidate; - - /* No duplicates */ - ifindex = nm_device_get_ifindex (device); - if (ifindex > 0 && nm_manager_get_device_by_ifindex (self, ifindex)) { - g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, - "A device with ifindex %d already exists", ifindex); - return FALSE; - } - - /* Remove existing devices owned by the new device; eg remove ethernet - * ports that are owned by a WWAN modem, since udev may announce them - * before the modem is fully discovered. - * - * FIXME: use parent/child device relationships instead of removing - * the child NMDevice entirely - */ - c_list_for_each_entry (candidate, &priv->devices_lst_head, devices_lst) { - if ( nm_device_is_real (candidate) - && (iface = nm_device_get_ip_iface (candidate)) - && nm_device_owns_iface (device, iface)) - remove = g_slist_prepend (remove, candidate); - } - for (iter = remove; iter; iter = iter->next) - remove_device (self, NM_DEVICE (iter->data), FALSE); - g_slist_free (remove); - - g_object_ref (device); - - nm_assert (c_list_is_empty (&device->devices_lst)); - c_list_link_tail (&priv->devices_lst_head, &device->devices_lst); - - g_signal_connect (device, NM_DEVICE_STATE_CHANGED, - G_CALLBACK (manager_device_state_changed), - self); - - g_signal_connect (device, NM_DEVICE_REMOVED, - G_CALLBACK (device_removed_cb), - self); - - g_signal_connect_data (device, NM_DEVICE_RECHECK_ASSUME, - G_CALLBACK (recheck_assume_connection_cb), - self, NULL, G_CONNECT_SWAPPED); - - g_signal_connect (device, "notify::" NM_DEVICE_IP_IFACE, - G_CALLBACK (device_ip_iface_changed), - self); - - g_signal_connect (device, "notify::" NM_DEVICE_IFINDEX, - G_CALLBACK (device_ifindex_changed), - self); - - g_signal_connect (device, "notify::" NM_DEVICE_IFACE, - G_CALLBACK (device_iface_changed), - self); - - g_signal_connect (device, "notify::" NM_DEVICE_REAL, - G_CALLBACK (device_realized), - self); - - g_signal_connect (device, "notify::" NM_DEVICE_IP4_CONNECTIVITY, - G_CALLBACK (device_connectivity_changed), - self); - g_signal_connect (device, "notify::" NM_DEVICE_IP6_CONNECTIVITY, - G_CALLBACK (device_connectivity_changed), - self); - - if (priv->startup) { - g_signal_connect (device, "notify::" NM_DEVICE_HAS_PENDING_ACTION, - G_CALLBACK (device_has_pending_action_changed), - self); - } - - /* Update global rfkill state for this device type with the device's - * rfkill state, and then set this device's rfkill state based on the - * global state. - */ - rtype = nm_device_get_rfkill_type (device); - if (rtype != RFKILL_TYPE_UNKNOWN) { - nm_manager_rfkill_update (self, rtype); - nm_device_set_enabled (device, radio_enabled_for_type (self, rtype, TRUE)); - } - - iface = nm_device_get_iface (device); - g_assert (iface); - type_desc = nm_device_get_type_desc (device); - g_assert (type_desc); - - nm_device_set_unmanaged_by_user_settings (device); - - nm_device_set_unmanaged_flags (device, - NM_UNMANAGED_SLEEPING, - manager_sleeping (self)); - - dbus_path = nm_dbus_object_export (NM_DBUS_OBJECT (device)); - _LOG2I (LOGD_DEVICE, device, "new %s device (%s)", type_desc, dbus_path); - - nm_settings_device_added (priv->settings, device); - g_signal_emit (self, signals[INTERNAL_DEVICE_ADDED], 0, device); - _notify (self, PROP_ALL_DEVICES); - - _parent_notify_changed (self, device, FALSE); - - return TRUE; +add_device(NMManager *self, NMDevice *device, GError **error) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + const char * iface, *type_desc; + RfKillType rtype; + GSList * iter, *remove = NULL; + int ifindex; + const char * dbus_path; + NMDevice * candidate; + + /* No duplicates */ + ifindex = nm_device_get_ifindex(device); + if (ifindex > 0 && nm_manager_get_device_by_ifindex(self, ifindex)) { + g_set_error(error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_FAILED, + "A device with ifindex %d already exists", + ifindex); + return FALSE; + } + + /* Remove existing devices owned by the new device; eg remove ethernet + * ports that are owned by a WWAN modem, since udev may announce them + * before the modem is fully discovered. + * + * FIXME: use parent/child device relationships instead of removing + * the child NMDevice entirely + */ + c_list_for_each_entry (candidate, &priv->devices_lst_head, devices_lst) { + if (nm_device_is_real(candidate) && (iface = nm_device_get_ip_iface(candidate)) + && nm_device_owns_iface(device, iface)) + remove = g_slist_prepend(remove, candidate); + } + for (iter = remove; iter; iter = iter->next) + remove_device(self, NM_DEVICE(iter->data), FALSE); + g_slist_free(remove); + + g_object_ref(device); + + nm_assert(c_list_is_empty(&device->devices_lst)); + c_list_link_tail(&priv->devices_lst_head, &device->devices_lst); + + g_signal_connect(device, + NM_DEVICE_STATE_CHANGED, + G_CALLBACK(manager_device_state_changed), + self); + + g_signal_connect(device, NM_DEVICE_REMOVED, G_CALLBACK(device_removed_cb), self); + + g_signal_connect_data(device, + NM_DEVICE_RECHECK_ASSUME, + G_CALLBACK(recheck_assume_connection_cb), + self, + NULL, + G_CONNECT_SWAPPED); + + g_signal_connect(device, + "notify::" NM_DEVICE_IP_IFACE, + G_CALLBACK(device_ip_iface_changed), + self); + + g_signal_connect(device, + "notify::" NM_DEVICE_IFINDEX, + G_CALLBACK(device_ifindex_changed), + self); + + g_signal_connect(device, "notify::" NM_DEVICE_IFACE, G_CALLBACK(device_iface_changed), self); + + g_signal_connect(device, "notify::" NM_DEVICE_REAL, G_CALLBACK(device_realized), self); + + g_signal_connect(device, + "notify::" NM_DEVICE_IP4_CONNECTIVITY, + G_CALLBACK(device_connectivity_changed), + self); + g_signal_connect(device, + "notify::" NM_DEVICE_IP6_CONNECTIVITY, + G_CALLBACK(device_connectivity_changed), + self); + + if (priv->startup) { + g_signal_connect(device, + "notify::" NM_DEVICE_HAS_PENDING_ACTION, + G_CALLBACK(device_has_pending_action_changed), + self); + } + + /* Update global rfkill state for this device type with the device's + * rfkill state, and then set this device's rfkill state based on the + * global state. + */ + rtype = nm_device_get_rfkill_type(device); + if (rtype != RFKILL_TYPE_UNKNOWN) { + nm_manager_rfkill_update(self, rtype); + nm_device_set_enabled(device, radio_enabled_for_type(self, rtype, TRUE)); + } + + iface = nm_device_get_iface(device); + g_assert(iface); + type_desc = nm_device_get_type_desc(device); + g_assert(type_desc); + + nm_device_set_unmanaged_by_user_settings(device); + + nm_device_set_unmanaged_flags(device, NM_UNMANAGED_SLEEPING, manager_sleeping(self)); + + dbus_path = nm_dbus_object_export(NM_DBUS_OBJECT(device)); + _LOG2I(LOGD_DEVICE, device, "new %s device (%s)", type_desc, dbus_path); + + nm_settings_device_added(priv->settings, device); + g_signal_emit(self, signals[INTERNAL_DEVICE_ADDED], 0, device); + _notify(self, PROP_ALL_DEVICES); + + _parent_notify_changed(self, device, FALSE); + + return TRUE; } /*****************************************************************************/ static void -factory_device_added_cb (NMDeviceFactory *factory, - NMDevice *device, - gpointer user_data) -{ - NMManager *self = user_data; - GError *error = NULL; - - g_return_if_fail (NM_IS_MANAGER (self)); - - if (nm_device_realize_start (device, - NULL, - FALSE, /* assume_state_guess_assume */ - NULL, /* assume_state_connection_uuid */ - FALSE, /* set_nm_owned */ - NM_UNMAN_FLAG_OP_FORGET, - NULL, - &error)) { - add_device (self, device, NULL); - _device_realize_finish (self, device, NULL); - retry_connections_for_parent_device (self, device); - } else { - _LOG2W (LOGD_DEVICE, device, "failed to realize device: %s", error->message); - g_error_free (error); - } +factory_device_added_cb(NMDeviceFactory *factory, NMDevice *device, gpointer user_data) +{ + NMManager *self = user_data; + GError * error = NULL; + + g_return_if_fail(NM_IS_MANAGER(self)); + + if (nm_device_realize_start(device, + NULL, + FALSE, /* assume_state_guess_assume */ + NULL, /* assume_state_connection_uuid */ + FALSE, /* set_nm_owned */ + NM_UNMAN_FLAG_OP_FORGET, + NULL, + &error)) { + add_device(self, device, NULL); + _device_realize_finish(self, device, NULL); + retry_connections_for_parent_device(self, device); + } else { + _LOG2W(LOGD_DEVICE, device, "failed to realize device: %s", error->message); + g_error_free(error); + } } static void -_register_device_factory (NMDeviceFactory *factory, gpointer user_data) +_register_device_factory(NMDeviceFactory *factory, gpointer user_data) { - NMManager *self = NM_MANAGER (user_data); + NMManager *self = NM_MANAGER(user_data); - g_signal_connect (factory, - NM_DEVICE_FACTORY_DEVICE_ADDED, - G_CALLBACK (factory_device_added_cb), - self); + g_signal_connect(factory, + NM_DEVICE_FACTORY_DEVICE_ADDED, + G_CALLBACK(factory_device_added_cb), + self); } /*****************************************************************************/ void -nm_manager_notify_device_availibility_maybe_changed (NMManager *self) +nm_manager_notify_device_availability_maybe_changed(NMManager *self) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + NMDevice * device; - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) - nm_device_notify_availability_maybe_changed (device); + c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) + nm_device_notify_availability_maybe_changed(device); } /*****************************************************************************/ static void -platform_link_added (NMManager *self, - int ifindex, - const NMPlatformLink *plink, - gboolean guess_assume, - const NMConfigDeviceStateData *dev_state) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDeviceFactory *factory; - NMDevice *device = NULL; - NMDevice *candidate; - - g_return_if_fail (ifindex > 0); - - if (nm_manager_get_device_by_ifindex (self, ifindex)) - return; - - /* Let unrealized devices try to realize themselves with the link */ - c_list_for_each_entry (candidate, &priv->devices_lst_head, devices_lst) { - gboolean compatible = TRUE; - gs_free_error GError *error = NULL; - - if (nm_device_get_link_type (candidate) != plink->type) - continue; - - if (strcmp (nm_device_get_iface (candidate), plink->name)) - continue; - - if (nm_device_is_real (candidate)) { - /* There's already a realized device with the link's name - * and a different ifindex. - */ - if (nm_device_get_ifindex (candidate) <= 0) - nm_device_update_from_platform_link (candidate, plink); - else { - /* The ifindex of a device can't be changed after - * initialization because it is used as a key by - * the dns-manager. - */ - _LOGD (LOGD_DEVICE, "(%s): removing old device %p after ifindex change from %d to %d", - plink->name, candidate, nm_device_get_ifindex (candidate), ifindex); - remove_device (self, candidate, FALSE); - goto add; - } - return; - } else if (nm_device_realize_start (candidate, - plink, - FALSE, /* assume_state_guess_assume */ - NULL, /* assume_state_connection_uuid */ - FALSE, /* set_nm_owned */ - NM_UNMAN_FLAG_OP_FORGET, - &compatible, - &error)) { - _device_realize_finish (self, candidate, plink); - return; - } - - _LOGD (LOGD_DEVICE, "(%s): failed to realize from plink: '%s'", - plink->name, error->message); - - /* Try next unrealized device */ - } +platform_link_added(NMManager * self, + int ifindex, + const NMPlatformLink * plink, + gboolean guess_assume, + const NMConfigDeviceStateData *dev_state) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + NMDeviceFactory * factory; + NMDevice * device = NULL; + NMDevice * candidate; + + g_return_if_fail(ifindex > 0); + + if (nm_manager_get_device_by_ifindex(self, ifindex)) + return; + + /* Let unrealized devices try to realize themselves with the link */ + c_list_for_each_entry (candidate, &priv->devices_lst_head, devices_lst) { + gboolean compatible = TRUE; + gs_free_error GError *error = NULL; + + if (nm_device_get_link_type(candidate) != plink->type) + continue; + + if (!nm_streq(nm_device_get_iface(candidate), plink->name)) + continue; + + if (nm_device_is_real(candidate)) { + /* There's already a realized device with the link's name + * and a different ifindex. + */ + if (nm_device_get_ifindex(candidate) <= 0) + nm_device_update_from_platform_link(candidate, plink); + else { + /* The ifindex of a device can't be changed after + * initialization because it is used as a key by + * the dns-manager. + */ + _LOGD(LOGD_DEVICE, + "(%s): removing old device %p after ifindex change from %d to %d", + plink->name, + candidate, + nm_device_get_ifindex(candidate), + ifindex); + remove_device(self, candidate, FALSE); + goto add; + } + return; + } else if (nm_device_realize_start(candidate, + plink, + FALSE, /* assume_state_guess_assume */ + NULL, /* assume_state_connection_uuid */ + FALSE, /* set_nm_owned */ + NM_UNMAN_FLAG_OP_FORGET, + &compatible, + &error)) { + _device_realize_finish(self, candidate, plink); + return; + } + + _LOGD(LOGD_DEVICE, "(%s): failed to realize from plink: '%s'", plink->name, error->message); + + /* Try next unrealized device */ + } add: - /* Try registered device factories */ - factory = nm_device_factory_manager_find_factory_for_link_type (plink->type); - if (factory) { - gboolean ignore = FALSE; - gs_free_error GError *error = NULL; - - device = nm_device_factory_create_device (factory, plink->name, plink, NULL, &ignore, &error); - if (!device) { - if (!ignore) { - _LOGW (LOGD_PLATFORM, "%s: factory failed to create device: %s", - plink->name, error->message); - } else { - _LOGD (LOGD_PLATFORM, "%s: factory failed to create device: %s", - plink->name, error->message); - } - return; - } - } - - if (device == NULL) { - gboolean nm_plugin_missing = FALSE; - - switch (plink->type) { - case NM_LINK_TYPE_WWAN_NET: - case NM_LINK_TYPE_BNEP: - case NM_LINK_TYPE_OLPC_MESH: - case NM_LINK_TYPE_TEAM: - case NM_LINK_TYPE_WIFI: - _LOGI (LOGD_PLATFORM, "(%s): '%s' plugin not available; creating generic device", - plink->name, nm_link_type_to_string (plink->type)); - nm_plugin_missing = TRUE; - /* fall-through */ - default: - device = nm_device_generic_new (plink, nm_plugin_missing); - break; - } - } - - if (device) { - gs_free_error GError *error = NULL; - NMUnmanFlagOp unmanaged_user_explicit = NM_UNMAN_FLAG_OP_FORGET; - - if (dev_state) { - switch (dev_state->managed) { - case NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_MANAGED: - unmanaged_user_explicit = NM_UNMAN_FLAG_OP_SET_MANAGED; - break; - case NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_UNMANAGED: - unmanaged_user_explicit = NM_UNMAN_FLAG_OP_SET_UNMANAGED; - break; - case NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_UNKNOWN: - break; - } - } - - if (nm_device_realize_start (device, - plink, - guess_assume, - dev_state ? dev_state->connection_uuid : NULL, - dev_state ? (dev_state->nm_owned == 1) : FALSE, - unmanaged_user_explicit, - NULL, - &error)) { - add_device (self, device, NULL); - _device_realize_finish (self, device, plink); - retry_connections_for_parent_device (self, device); - } else { - _LOGW (LOGD_DEVICE, "%s: failed to realize device: %s", - plink->name, error->message); - } - g_object_unref (device); - } + /* Try registered device factories */ + factory = nm_device_factory_manager_find_factory_for_link_type(plink->type); + if (factory) { + gboolean ignore = FALSE; + gs_free_error GError *error = NULL; + + device = + nm_device_factory_create_device(factory, plink->name, plink, NULL, &ignore, &error); + if (!device) { + if (!ignore) { + _LOGW(LOGD_PLATFORM, + "%s: factory failed to create device: %s", + plink->name, + error->message); + } else { + _LOGD(LOGD_PLATFORM, + "%s: factory failed to create device: %s", + plink->name, + error->message); + } + return; + } + } + + if (device == NULL) { + gboolean nm_plugin_missing = FALSE; + + switch (plink->type) { + case NM_LINK_TYPE_WWAN_NET: + case NM_LINK_TYPE_BNEP: + case NM_LINK_TYPE_OLPC_MESH: + case NM_LINK_TYPE_TEAM: + case NM_LINK_TYPE_WIFI: + _LOGI(LOGD_PLATFORM, + "(%s): '%s' plugin not available; creating generic device", + plink->name, + nm_link_type_to_string(plink->type)); + nm_plugin_missing = TRUE; + /* fall-through */ + default: + device = nm_device_generic_new(plink, nm_plugin_missing); + break; + } + } + + if (device) { + gs_free_error GError *error = NULL; + NMUnmanFlagOp unmanaged_user_explicit = NM_UNMAN_FLAG_OP_FORGET; + + if (dev_state) { + switch (dev_state->managed) { + case NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_MANAGED: + unmanaged_user_explicit = NM_UNMAN_FLAG_OP_SET_MANAGED; + break; + case NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_UNMANAGED: + unmanaged_user_explicit = NM_UNMAN_FLAG_OP_SET_UNMANAGED; + break; + case NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_UNKNOWN: + break; + } + } + + if (nm_device_realize_start(device, + plink, + guess_assume, + dev_state ? dev_state->connection_uuid : NULL, + dev_state ? (dev_state->nm_owned == 1) : FALSE, + unmanaged_user_explicit, + NULL, + &error)) { + add_device(self, device, NULL); + _device_realize_finish(self, device, plink); + retry_connections_for_parent_device(self, device); + } else { + _LOGW(LOGD_DEVICE, "%s: failed to realize device: %s", plink->name, error->message); + } + g_object_unref(device); + } } typedef struct { - CList lst; - NMManager *self; - int ifindex; - guint idle_id; + CList lst; + NMManager *self; + int ifindex; + guint idle_id; } PlatformLinkCbData; static gboolean -_platform_link_cb_idle (PlatformLinkCbData *data) -{ - int ifindex = data->ifindex; - NMManager *self = data->self; - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - const NMPlatformLink *plink; - - c_list_unlink_stale (&data->lst); - g_slice_free (PlatformLinkCbData, data); - - plink = nm_platform_link_get (priv->platform, ifindex); - if (plink) { - const NMPObject *plink_keep_alive = nmp_object_ref (NMP_OBJECT_UP_CAST (plink)); - - platform_link_added (self, ifindex, plink, FALSE, NULL); - nmp_object_unref (plink_keep_alive); - } else { - NMDevice *device; - GError *error = NULL; - - device = nm_manager_get_device_by_ifindex (self, ifindex); - if (device) { - if (nm_device_is_software (device)) { - nm_device_sys_iface_state_set (device, NM_DEVICE_SYS_IFACE_STATE_REMOVED); - /* Our software devices stick around until their connection is removed */ - if (!nm_device_unrealize (device, FALSE, &error)) { - _LOG2W (LOGD_DEVICE, device, "failed to unrealize: %s", error->message); - g_clear_error (&error); - remove_device (self, device, FALSE); - } else { - nm_device_update_from_platform_link (device, NULL); - } - } else { - /* Hardware and external devices always get removed when their kernel link is gone */ - remove_device (self, device, FALSE); - } - } - } - - return G_SOURCE_REMOVE; +_platform_link_cb_idle(PlatformLinkCbData *data) +{ + int ifindex = data->ifindex; + NMManager * self = data->self; + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + const NMPlatformLink *plink; + + c_list_unlink_stale(&data->lst); + g_slice_free(PlatformLinkCbData, data); + + plink = nm_platform_link_get(priv->platform, ifindex); + if (plink) { + const NMPObject *plink_keep_alive = nmp_object_ref(NMP_OBJECT_UP_CAST(plink)); + + platform_link_added(self, ifindex, plink, FALSE, NULL); + nmp_object_unref(plink_keep_alive); + } else { + NMDevice *device; + GError * error = NULL; + + device = nm_manager_get_device_by_ifindex(self, ifindex); + if (device) { + if (nm_device_is_software(device)) { + nm_device_sys_iface_state_set(device, NM_DEVICE_SYS_IFACE_STATE_REMOVED); + /* Our software devices stick around until their connection is removed */ + if (!nm_device_unrealize(device, FALSE, &error)) { + _LOG2W(LOGD_DEVICE, device, "failed to unrealize: %s", error->message); + g_clear_error(&error); + remove_device(self, device, FALSE); + } else { + nm_device_update_from_platform_link(device, NULL); + } + } else { + /* Hardware and external devices always get removed when their kernel link is gone */ + remove_device(self, device, FALSE); + } + } + } + + return G_SOURCE_REMOVE; } static void -platform_link_cb (NMPlatform *platform, - int obj_type_i, - int ifindex, - NMPlatformLink *plink, - int change_type_i, - gpointer user_data) -{ - NMManager *self; - NMManagerPrivate *priv; - const NMPlatformSignalChangeType change_type = change_type_i; - PlatformLinkCbData *data; - - switch (change_type) { - case NM_PLATFORM_SIGNAL_ADDED: - case NM_PLATFORM_SIGNAL_REMOVED: - self = NM_MANAGER (user_data); - priv = NM_MANAGER_GET_PRIVATE (self); - - data = g_slice_new (PlatformLinkCbData); - data->self = self; - data->ifindex = ifindex; - c_list_link_tail (&priv->link_cb_lst, &data->lst); - data->idle_id = g_idle_add ((GSourceFunc) _platform_link_cb_idle, data); - break; - default: - break; - } +platform_link_cb(NMPlatform * platform, + int obj_type_i, + int ifindex, + NMPlatformLink *plink, + int change_type_i, + gpointer user_data) +{ + NMManager * self; + NMManagerPrivate * priv; + const NMPlatformSignalChangeType change_type = change_type_i; + PlatformLinkCbData * data; + + switch (change_type) { + case NM_PLATFORM_SIGNAL_ADDED: + case NM_PLATFORM_SIGNAL_REMOVED: + self = NM_MANAGER(user_data); + priv = NM_MANAGER_GET_PRIVATE(self); + + data = g_slice_new(PlatformLinkCbData); + data->self = self; + data->ifindex = ifindex; + c_list_link_tail(&priv->link_cb_lst, &data->lst); + data->idle_id = g_idle_add((GSourceFunc) _platform_link_cb_idle, data); + break; + default: + break; + } } static void -platform_query_devices (NMManager *self) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - gs_unref_ptrarray GPtrArray *links = NULL; - int i; - gboolean guess_assume; - gs_free char *order = NULL; - - guess_assume = nm_config_get_first_start (nm_config_get ()); - order = nm_config_data_get_value (NM_CONFIG_GET_DATA, - NM_CONFIG_KEYFILE_GROUP_MAIN, - NM_CONFIG_KEYFILE_KEY_MAIN_SLAVES_ORDER, - NM_CONFIG_GET_VALUE_STRIP); - links = nm_platform_link_get_all (priv->platform, !nm_streq0 (order, "index")); - if (!links) - return; - for (i = 0; i < links->len; i++) { - const NMPlatformLink *link = NMP_OBJECT_CAST_LINK (links->pdata[i]); - const NMConfigDeviceStateData *dev_state; - - dev_state = nm_config_device_state_get (priv->config, link->ifindex); - platform_link_added (self, - link->ifindex, - link, - guess_assume && (!dev_state || !dev_state->connection_uuid), - dev_state); - } +platform_query_devices(NMManager *self) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + gs_unref_ptrarray GPtrArray *links = NULL; + int i; + gboolean guess_assume; + gs_free char * order = NULL; + + guess_assume = nm_config_get_first_start(nm_config_get()); + order = nm_config_data_get_value(NM_CONFIG_GET_DATA, + NM_CONFIG_KEYFILE_GROUP_MAIN, + NM_CONFIG_KEYFILE_KEY_MAIN_SLAVES_ORDER, + NM_CONFIG_GET_VALUE_STRIP); + links = nm_platform_link_get_all(priv->platform, !nm_streq0(order, "index")); + if (!links) + return; + for (i = 0; i < links->len; i++) { + const NMPlatformLink * link = NMP_OBJECT_CAST_LINK(links->pdata[i]); + const NMConfigDeviceStateData *dev_state; + + dev_state = nm_config_device_state_get(priv->config, link->ifindex); + platform_link_added(self, + link->ifindex, + link, + guess_assume && (!dev_state || !dev_state->connection_uuid), + dev_state); + } } static void -rfkill_manager_rfkill_changed_cb (NMRfkillManager *rfkill_mgr, - RfKillType rtype, - RfKillState udev_state, - gpointer user_data) +rfkill_manager_rfkill_changed_cb(NMRfkillManager *rfkill_mgr, + RfKillType rtype, + RfKillState udev_state, + gpointer user_data) { - nm_manager_rfkill_update (NM_MANAGER (user_data), rtype); + nm_manager_rfkill_update(NM_MANAGER(user_data), rtype); } const CList * -nm_manager_get_devices (NMManager *manager) +nm_manager_get_devices(NMManager *manager) { - g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); + g_return_val_if_fail(NM_IS_MANAGER(manager), NULL); - return &NM_MANAGER_GET_PRIVATE (manager)->devices_lst_head; + return &NM_MANAGER_GET_PRIVATE(manager)->devices_lst_head; } typedef enum { - DEVICE_ACTIVATION_PRIO_NONE, - DEVICE_ACTIVATION_PRIO_UNMANAGED, - DEVICE_ACTIVATION_PRIO_UNAVAILABLE, - DEVICE_ACTIVATION_PRIO_DEACTIVATING, - DEVICE_ACTIVATION_PRIO_ACTIVATING, - DEVICE_ACTIVATION_PRIO_ACTIVATED, - DEVICE_ACTIVATION_PRIO_DISCONNECTED, - - _DEVICE_ACTIVATION_PRIO_BEST = DEVICE_ACTIVATION_PRIO_DISCONNECTED, + DEVICE_ACTIVATION_PRIO_NONE, + DEVICE_ACTIVATION_PRIO_UNMANAGED, + DEVICE_ACTIVATION_PRIO_UNAVAILABLE, + DEVICE_ACTIVATION_PRIO_DEACTIVATING, + DEVICE_ACTIVATION_PRIO_ACTIVATING, + DEVICE_ACTIVATION_PRIO_ACTIVATED, + DEVICE_ACTIVATION_PRIO_DISCONNECTED, + + _DEVICE_ACTIVATION_PRIO_BEST = DEVICE_ACTIVATION_PRIO_DISCONNECTED, } DeviceActivationPrio; static DeviceActivationPrio -_device_get_activation_prio (NMDevice *device) -{ - if (!nm_device_get_managed (device, TRUE)) - return DEVICE_ACTIVATION_PRIO_NONE; - - switch (nm_device_get_state (device)) { - case NM_DEVICE_STATE_DISCONNECTED: - return DEVICE_ACTIVATION_PRIO_DISCONNECTED; - case NM_DEVICE_STATE_ACTIVATED: - return DEVICE_ACTIVATION_PRIO_ACTIVATED; - case NM_DEVICE_STATE_PREPARE: - case NM_DEVICE_STATE_CONFIG: - case NM_DEVICE_STATE_NEED_AUTH: - case NM_DEVICE_STATE_IP_CONFIG: - case NM_DEVICE_STATE_IP_CHECK: - case NM_DEVICE_STATE_SECONDARIES: - return DEVICE_ACTIVATION_PRIO_ACTIVATING; - case NM_DEVICE_STATE_DEACTIVATING: - case NM_DEVICE_STATE_FAILED: - return DEVICE_ACTIVATION_PRIO_DEACTIVATING; - case NM_DEVICE_STATE_UNAVAILABLE: - return DEVICE_ACTIVATION_PRIO_UNAVAILABLE; - case NM_DEVICE_STATE_UNKNOWN: - case NM_DEVICE_STATE_UNMANAGED: - return DEVICE_ACTIVATION_PRIO_UNMANAGED; - } - - g_return_val_if_reached (DEVICE_ACTIVATION_PRIO_UNAVAILABLE); +_device_get_activation_prio(NMDevice *device) +{ + if (!nm_device_get_managed(device, TRUE)) + return DEVICE_ACTIVATION_PRIO_NONE; + + switch (nm_device_get_state(device)) { + case NM_DEVICE_STATE_DISCONNECTED: + return DEVICE_ACTIVATION_PRIO_DISCONNECTED; + case NM_DEVICE_STATE_ACTIVATED: + return DEVICE_ACTIVATION_PRIO_ACTIVATED; + case NM_DEVICE_STATE_PREPARE: + case NM_DEVICE_STATE_CONFIG: + case NM_DEVICE_STATE_NEED_AUTH: + case NM_DEVICE_STATE_IP_CONFIG: + case NM_DEVICE_STATE_IP_CHECK: + case NM_DEVICE_STATE_SECONDARIES: + return DEVICE_ACTIVATION_PRIO_ACTIVATING; + case NM_DEVICE_STATE_DEACTIVATING: + case NM_DEVICE_STATE_FAILED: + return DEVICE_ACTIVATION_PRIO_DEACTIVATING; + case NM_DEVICE_STATE_UNAVAILABLE: + return DEVICE_ACTIVATION_PRIO_UNAVAILABLE; + case NM_DEVICE_STATE_UNKNOWN: + case NM_DEVICE_STATE_UNMANAGED: + return DEVICE_ACTIVATION_PRIO_UNMANAGED; + } + + g_return_val_if_reached(DEVICE_ACTIVATION_PRIO_UNAVAILABLE); } static NMDevice * -nm_manager_get_best_device_for_connection (NMManager *self, - NMSettingsConnection *sett_conn, - NMConnection *connection, - gboolean for_user_request, - GHashTable *unavailable_devices, - GError **error) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMActiveConnectionState ac_state; - NMActiveConnection *ac; - NMDevice *ac_device; - NMDevice *device; - struct { - NMDevice *device; - DeviceActivationPrio prio; - } best = { - .device = NULL, - .prio = DEVICE_ACTIVATION_PRIO_NONE, - }; - NMDeviceCheckConAvailableFlags flags; - gs_unref_ptrarray GPtrArray *all_ac_arr = NULL; - gs_free_error GError *local_best = NULL; - NMConnectionMultiConnect multi_connect; - - nm_assert (!sett_conn || NM_IS_SETTINGS_CONNECTION (sett_conn)); - nm_assert (!connection || NM_IS_CONNECTION (connection)); - nm_assert (sett_conn || connection); - nm_assert (!connection || !sett_conn || connection == nm_settings_connection_get_connection (sett_conn)); - - if (!connection) - connection = nm_settings_connection_get_connection (sett_conn); - - multi_connect = _nm_connection_get_multi_connect (connection); - - if (!for_user_request) - flags = NM_DEVICE_CHECK_CON_AVAILABLE_NONE; - else { - /* if the profile is multi-connect=single, we also consider devices which - * are marked as unmanaged. And explicit user-request shows sufficient user - * intent to make the device managed. - * That is also, because we expect that such profile is suitably tied - * to the intended device. So when an unmanaged device matches, the user's - * intent is clear. - * - * For multi-connect != single devices that is different. The profile - * is not restricted to a particular device. - * For that reason, plain `nmcli connection up "$MULIT_PROFILE"` seems - * less suitable for multi-connect profiles, because the target device is - * left unspecified. Anyway, if a user issues - * - * $ nmcli device set "$DEVICE" managed no - * $ nmcli connection up "$MULIT_PROFILE" - * - * then it is reasonable for multi-connect profiles to not consider - * the device a suitable candidate. - * - * This may be seen inconsistent, but I think that it makes a lot of - * sense. Also note that "connection.multi-connect" work quite differently - * in aspects like activation. E.g. `nmcli connection up` of multi-connect - * "single" profile, will deactivate the profile if it is active already. - * That is different from multi-connect profiles, where it will aim to - * activate the profile one more time on an hitherto disconnected device. - */ - if (multi_connect == NM_CONNECTION_MULTI_CONNECT_SINGLE) - flags = NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST; - else - flags = NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST & ~_NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_OVERRULE_UNMANAGED; - } - - if ( multi_connect == NM_CONNECTION_MULTI_CONNECT_SINGLE - && (ac = active_connection_find_by_connection (self, sett_conn, connection, NM_ACTIVE_CONNECTION_STATE_DEACTIVATING, &all_ac_arr))) { - /* if we have a profile which may activate on only one device (multi-connect single), then - * we prefer the device on which the profile is already active. It means to reactivate - * the profile on the same device. - * - * If the profile can be activated on multiple devices, we don't do this. In fact, the - * check below for the DeviceActivationPrio will prefer devices which are not already - * activated (with this or another) profile. */ - - ac_device = nm_active_connection_get_device (ac); - if ( ac_device - && ( (unavailable_devices && g_hash_table_contains (unavailable_devices, ac_device)) - || !nm_device_check_connection_available (ac_device, connection, flags, NULL, NULL))) - ac_device = NULL; - - if (all_ac_arr) { - guint i; - - ac_state = nm_active_connection_get_state (ac); - - /* we found several active connections. See which one is the most suitable... */ - nm_assert (ac == all_ac_arr->pdata[0]); - for (i = 1; i < all_ac_arr->len; i++) { - NMActiveConnection *ac2 = all_ac_arr->pdata[i]; - NMDevice *ac_device2 = nm_active_connection_get_device (ac2); - NMActiveConnectionState ac_state2; - - if ( !ac_device2 - || (unavailable_devices && g_hash_table_contains (unavailable_devices, ac_device2)) - || !nm_device_check_connection_available (ac_device2, connection, flags, NULL, NULL)) - continue; - - ac_state2 = nm_active_connection_get_state (ac2); - - if (!ac_device) - goto found_better; - - if (ac_state == ac_state2) { - /* active-connections are in their list in the order in which they are connected. - * If we have two with same state, the later (newer) one is preferred. */ - goto found_better; - } - - switch (ac_state) { - case NM_ACTIVE_CONNECTION_STATE_UNKNOWN: - if (NM_IN_SET (ac_state2, NM_ACTIVE_CONNECTION_STATE_ACTIVATING, NM_ACTIVE_CONNECTION_STATE_ACTIVATED, NM_ACTIVE_CONNECTION_STATE_DEACTIVATING)) - goto found_better; - break; - case NM_ACTIVE_CONNECTION_STATE_ACTIVATING: - if (NM_IN_SET (ac_state2, NM_ACTIVE_CONNECTION_STATE_ACTIVATED)) - goto found_better; - break; - case NM_ACTIVE_CONNECTION_STATE_ACTIVATED: - break; - case NM_ACTIVE_CONNECTION_STATE_DEACTIVATING: - if (NM_IN_SET (ac_state2, NM_ACTIVE_CONNECTION_STATE_ACTIVATING, NM_ACTIVE_CONNECTION_STATE_ACTIVATED)) - goto found_better; - break; - default: - nm_assert_not_reached (); - goto found_better; - } - - continue; +nm_manager_get_best_device_for_connection(NMManager * self, + NMSettingsConnection *sett_conn, + NMConnection * connection, + gboolean for_user_request, + GHashTable * unavailable_devices, + GError ** error) +{ + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + NMActiveConnectionState ac_state; + NMActiveConnection * ac; + NMDevice * ac_device; + NMDevice * device; + struct { + NMDevice * device; + DeviceActivationPrio prio; + } best = { + .device = NULL, + .prio = DEVICE_ACTIVATION_PRIO_NONE, + }; + NMDeviceCheckConAvailableFlags flags; + gs_unref_ptrarray GPtrArray *all_ac_arr = NULL; + gs_free_error GError * local_best = NULL; + NMConnectionMultiConnect multi_connect; + + nm_assert(!sett_conn || NM_IS_SETTINGS_CONNECTION(sett_conn)); + nm_assert(!connection || NM_IS_CONNECTION(connection)); + nm_assert(sett_conn || connection); + nm_assert(!connection || !sett_conn + || connection == nm_settings_connection_get_connection(sett_conn)); + + if (!connection) + connection = nm_settings_connection_get_connection(sett_conn); + + multi_connect = _nm_connection_get_multi_connect(connection); + + if (!for_user_request) + flags = NM_DEVICE_CHECK_CON_AVAILABLE_NONE; + else { + /* if the profile is multi-connect=single, we also consider devices which + * are marked as unmanaged. And explicit user-request shows sufficient user + * intent to make the device managed. + * That is also, because we expect that such profile is suitably tied + * to the intended device. So when an unmanaged device matches, the user's + * intent is clear. + * + * For multi-connect != single devices that is different. The profile + * is not restricted to a particular device. + * For that reason, plain `nmcli connection up "$MULIT_PROFILE"` seems + * less suitable for multi-connect profiles, because the target device is + * left unspecified. Anyway, if a user issues + * + * $ nmcli device set "$DEVICE" managed no + * $ nmcli connection up "$MULIT_PROFILE" + * + * then it is reasonable for multi-connect profiles to not consider + * the device a suitable candidate. + * + * This may be seen inconsistent, but I think that it makes a lot of + * sense. Also note that "connection.multi-connect" work quite differently + * in aspects like activation. E.g. `nmcli connection up` of multi-connect + * "single" profile, will deactivate the profile if it is active already. + * That is different from multi-connect profiles, where it will aim to + * activate the profile one more time on an hitherto disconnected device. + */ + if (multi_connect == NM_CONNECTION_MULTI_CONNECT_SINGLE) + flags = NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST; + else + flags = NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST + & ~_NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_OVERRULE_UNMANAGED; + } + + if (multi_connect == NM_CONNECTION_MULTI_CONNECT_SINGLE + && (ac = active_connection_find_by_connection(self, + sett_conn, + connection, + NM_ACTIVE_CONNECTION_STATE_DEACTIVATING, + &all_ac_arr))) { + /* if we have a profile which may activate on only one device (multi-connect single), then + * we prefer the device on which the profile is already active. It means to reactivate + * the profile on the same device. + * + * If the profile can be activated on multiple devices, we don't do this. In fact, the + * check below for the DeviceActivationPrio will prefer devices which are not already + * activated (with this or another) profile. */ + + ac_device = nm_active_connection_get_device(ac); + if (ac_device + && ((unavailable_devices && g_hash_table_contains(unavailable_devices, ac_device)) + || !nm_device_check_connection_available(ac_device, connection, flags, NULL, NULL))) + ac_device = NULL; + + if (all_ac_arr) { + guint i; + + ac_state = nm_active_connection_get_state(ac); + + /* we found several active connections. See which one is the most suitable... */ + nm_assert(ac == all_ac_arr->pdata[0]); + for (i = 1; i < all_ac_arr->len; i++) { + NMActiveConnection * ac2 = all_ac_arr->pdata[i]; + NMDevice * ac_device2 = nm_active_connection_get_device(ac2); + NMActiveConnectionState ac_state2; + + if (!ac_device2 + || (unavailable_devices + && g_hash_table_contains(unavailable_devices, ac_device2)) + || !nm_device_check_connection_available(ac_device2, + connection, + flags, + NULL, + NULL)) + continue; + + ac_state2 = nm_active_connection_get_state(ac2); + + if (!ac_device) + goto found_better; + + if (ac_state == ac_state2) { + /* active-connections are in their list in the order in which they are connected. + * If we have two with same state, the later (newer) one is preferred. */ + goto found_better; + } + + switch (ac_state) { + case NM_ACTIVE_CONNECTION_STATE_UNKNOWN: + if (NM_IN_SET(ac_state2, + NM_ACTIVE_CONNECTION_STATE_ACTIVATING, + NM_ACTIVE_CONNECTION_STATE_ACTIVATED, + NM_ACTIVE_CONNECTION_STATE_DEACTIVATING)) + goto found_better; + break; + case NM_ACTIVE_CONNECTION_STATE_ACTIVATING: + if (NM_IN_SET(ac_state2, NM_ACTIVE_CONNECTION_STATE_ACTIVATED)) + goto found_better; + break; + case NM_ACTIVE_CONNECTION_STATE_ACTIVATED: + break; + case NM_ACTIVE_CONNECTION_STATE_DEACTIVATING: + if (NM_IN_SET(ac_state2, + NM_ACTIVE_CONNECTION_STATE_ACTIVATING, + NM_ACTIVE_CONNECTION_STATE_ACTIVATED)) + goto found_better; + break; + default: + nm_assert_not_reached(); + goto found_better; + } + + continue; found_better: - ac = ac2; - ac_state = ac_state2; - ac_device = ac_device2; - } - } - - if (ac_device) - return ac_device; - } - - /* Pick the first device that's compatible with the connection. */ - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { - GError *local = NULL; - DeviceActivationPrio prio; - - if ( unavailable_devices - && g_hash_table_contains (unavailable_devices, device)) - continue; - - /* determine the priority of this device. Currently this priority is independent - * of the profile (connection) and the device's details (aside the state). - * - * Maybe nm_device_check_connection_available() should instead return a priority, - * as it has more information available. - * - * For example, if you have multiple Wi-Fi devices, currently a user-request would - * also select the device if the AP is not visible. Optimally, if one of the two - * devices sees the AP and the other one doesn't, the former would be preferred. - * For that, the priority would need to be determined by nm_device_check_connection_available(). */ - prio = _device_get_activation_prio (device); - if ( prio <= best.prio - && best.device) { - /* we already have a matching device with a better priority. This candidate - * cannot be better. Skip the check. - * - * Also note, that below we collect the best error message @local_best. - * Since we already have best.device, the error message does not matter - * either, and we can skip nm_device_check_connection_available() altogether. */ - continue; - } - - if (nm_device_check_connection_available (device, - connection, - flags, - NULL, - error ? &local : NULL)) { - if (prio == _DEVICE_ACTIVATION_PRIO_BEST) { - /* this device already has the best priority. It cannot get better - * and finish the search. */ - return device; - } - best.prio = prio; - best.device = device; - continue; - } - - if (error) { - gboolean reset_error; - - if (!local_best) - reset_error = TRUE; - else if (local_best->domain != NM_UTILS_ERROR) - reset_error = (local->domain == NM_UTILS_ERROR); - else { - reset_error = ( local->domain == NM_UTILS_ERROR - && local_best->code < local->code); - } - - if (reset_error) { - g_clear_error (&local_best); - g_set_error (&local_best, - local->domain, - local->code, - "device %s not available because %s", - nm_device_get_iface (device), - local->message); - } - g_error_free (local); - } - } - - if (best.device) - return best.device; - - if (error) { - if (local_best) - g_propagate_error (error, g_steal_pointer (&local_best)); - else { - nm_utils_error_set_literal (error, - NM_UTILS_ERROR_UNKNOWN, - "no suitable device found"); - } - } - return NULL; + ac = ac2; + ac_state = ac_state2; + ac_device = ac_device2; + } + } + + if (ac_device) + return ac_device; + } + + /* Pick the first device that's compatible with the connection. */ + c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { + GError * local = NULL; + DeviceActivationPrio prio; + + if (unavailable_devices && g_hash_table_contains(unavailable_devices, device)) + continue; + + /* determine the priority of this device. Currently, this priority is independent + * of the profile (connection) and the device's details (aside the state). + * + * Maybe nm_device_check_connection_available() should instead return a priority, + * as it has more information available. + * + * For example, if you have multiple Wi-Fi devices, currently a user-request would + * also select the device if the AP is not visible. Optimally, if one of the two + * devices sees the AP and the other one doesn't, the former would be preferred. + * For that, the priority would need to be determined by nm_device_check_connection_available(). */ + prio = _device_get_activation_prio(device); + if (prio <= best.prio && best.device) { + /* we already have a matching device with a better priority. This candidate + * cannot be better. Skip the check. + * + * Also note, that below we collect the best error message @local_best. + * Since we already have best.device, the error message does not matter + * either, and we can skip nm_device_check_connection_available() altogether. */ + continue; + } + + if (nm_device_check_connection_available(device, + connection, + flags, + NULL, + error ? &local : NULL)) { + if (prio == _DEVICE_ACTIVATION_PRIO_BEST) { + /* this device already has the best priority. It cannot get better + * and finish the search. */ + return device; + } + best.prio = prio; + best.device = device; + continue; + } + + if (error) { + gboolean reset_error; + + if (!local_best) + reset_error = TRUE; + else if (local_best->domain != NM_UTILS_ERROR) + reset_error = (local->domain == NM_UTILS_ERROR); + else { + reset_error = (local->domain == NM_UTILS_ERROR && local_best->code < local->code); + } + + if (reset_error) { + g_clear_error(&local_best); + g_set_error(&local_best, + local->domain, + local->code, + "device %s not available because %s", + nm_device_get_iface(device), + local->message); + } + g_error_free(local); + } + } + + if (best.device) + return best.device; + + if (error) { + if (local_best) + g_propagate_error(error, g_steal_pointer(&local_best)); + else { + nm_utils_error_set_literal(error, NM_UTILS_ERROR_UNKNOWN, "no suitable device found"); + } + } + return NULL; } static const char ** -_get_devices_paths (NMManager *self, - gboolean all_devices) +_get_devices_paths(NMManager *self, gboolean all_devices) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - const char **paths = NULL; - guint i; - NMDevice *device; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + const char ** paths = NULL; + guint i; + NMDevice * device; - paths = g_new (const char *, c_list_length (&priv->devices_lst_head) + 1); + paths = g_new(const char *, c_list_length(&priv->devices_lst_head) + 1); - i = 0; - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { - const char *path; + i = 0; + c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { + const char *path; - path = nm_dbus_object_get_path (NM_DBUS_OBJECT (device)); - if (!path) - continue; + path = nm_dbus_object_get_path(NM_DBUS_OBJECT(device)); + if (!path) + continue; - if ( !all_devices - && !nm_device_is_real (device)) - continue; + if (!all_devices && !nm_device_is_real(device)) + continue; - paths[i++] = path; - } - paths[i++] = NULL; + paths[i++] = path; + } + paths[i++] = NULL; - return paths; + return paths; } static void -impl_manager_get_devices (NMDBusObject *obj, - const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended *method_info, - GDBusConnection *connection, - const char *sender, - GDBusMethodInvocation *invocation, - GVariant *parameters) +impl_manager_get_devices(NMDBusObject * obj, + const NMDBusInterfaceInfoExtended *interface_info, + const NMDBusMethodInfoExtended * method_info, + GDBusConnection * connection, + const char * sender, + GDBusMethodInvocation * invocation, + GVariant * parameters) { - NMManager *self = NM_MANAGER (obj); - gs_free const char **paths = NULL; + NMManager * self = NM_MANAGER(obj); + gs_free const char **paths = NULL; - paths = _get_devices_paths (self, FALSE); - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(^ao)", (char **) paths)); + paths = _get_devices_paths(self, FALSE); + g_dbus_method_invocation_return_value(invocation, g_variant_new("(^ao)", (char **) paths)); } static void -impl_manager_get_all_devices (NMDBusObject *obj, - const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended *method_info, - GDBusConnection *connection, - const char *sender, - GDBusMethodInvocation *invocation, - GVariant *parameters) +impl_manager_get_all_devices(NMDBusObject * obj, + const NMDBusInterfaceInfoExtended *interface_info, + const NMDBusMethodInfoExtended * method_info, + GDBusConnection * connection, + const char * sender, + GDBusMethodInvocation * invocation, + GVariant * parameters) { - NMManager *self = NM_MANAGER (obj); - gs_free const char **paths = NULL; + NMManager * self = NM_MANAGER(obj); + gs_free const char **paths = NULL; - paths = _get_devices_paths (self, TRUE); - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(^ao)", (char **) paths)); + paths = _get_devices_paths(self, TRUE); + g_dbus_method_invocation_return_value(invocation, g_variant_new("(^ao)", (char **) paths)); } static void -impl_manager_get_device_by_ip_iface (NMDBusObject *obj, - const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended *method_info, - GDBusConnection *connection, - const char *sender, - GDBusMethodInvocation *invocation, - GVariant *parameters) +impl_manager_get_device_by_ip_iface(NMDBusObject * obj, + const NMDBusInterfaceInfoExtended *interface_info, + const NMDBusMethodInfoExtended * method_info, + GDBusConnection * connection, + const char * sender, + GDBusMethodInvocation * invocation, + GVariant * parameters) { - NMManager *self = NM_MANAGER (obj); - NMDevice *device; - const char *path = NULL; - const char *iface; + NMManager * self = NM_MANAGER(obj); + NMDevice * device; + const char *path = NULL; + const char *iface; - g_variant_get (parameters, "(&s)", &iface); + g_variant_get(parameters, "(&s)", &iface); - device = find_device_by_ip_iface (self, iface); - if (device) - path = nm_dbus_object_get_path (NM_DBUS_OBJECT (device)); + device = find_device_by_ip_iface(self, iface); + if (device) + path = nm_dbus_object_get_path(NM_DBUS_OBJECT(device)); - if (!path) { - g_dbus_method_invocation_return_error (invocation, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_UNKNOWN_DEVICE, - "No device found for the requested iface."); - return; - } + if (!path) { + g_dbus_method_invocation_return_error(invocation, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "No device found for the requested iface."); + return; + } - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(o)", path)); + g_dbus_method_invocation_return_value(invocation, g_variant_new("(o)", path)); } static gboolean -is_compatible_with_slave (NMConnection *master, NMConnection *slave) +is_compatible_with_slave(NMConnection *master, NMConnection *slave) { - NMSettingConnection *s_con; + NMSettingConnection *s_con; - g_return_val_if_fail (master, FALSE); - g_return_val_if_fail (slave, FALSE); + g_return_val_if_fail(master, FALSE); + g_return_val_if_fail(slave, FALSE); - s_con = nm_connection_get_setting_connection (slave); - g_assert (s_con); + s_con = nm_connection_get_setting_connection(slave); + g_assert(s_con); - return nm_connection_is_type (master, nm_setting_connection_get_slave_type (s_con)); + return nm_connection_is_type(master, nm_setting_connection_get_slave_type(s_con)); } /** @@ -4021,81 +4036,89 @@ is_compatible_with_slave (NMConnection *master, NMConnection *slave) * the connection did not require a master, %FALSE otherwise **/ static gboolean -find_master (NMManager *self, - NMConnection *connection, - NMDevice *device, - NMSettingsConnection **out_master_connection, - NMDevice **out_master_device, - NMActiveConnection **out_master_ac, - GError **error) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMSettingConnection *s_con; - const char *master; - NMDevice *master_device = NULL; - NMSettingsConnection *master_connection; - - s_con = nm_connection_get_setting_connection (connection); - g_assert (s_con); - master = nm_setting_connection_get_master (s_con); - - if (master == NULL) - return TRUE; /* success, but no master */ - - /* Try as an interface name first */ - master_device = find_device_by_iface (self, master, NULL, connection); - if (master_device) { - if (master_device == device) { - g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_DEPENDENCY_FAILED, - "Device cannot be its own master"); - return FALSE; - } - - master_connection = nm_device_get_settings_connection (master_device); - if ( master_connection - && !is_compatible_with_slave (nm_settings_connection_get_connection (master_connection), - connection)) { - g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_DEPENDENCY_FAILED, - "The active connection on %s is not compatible", - nm_device_get_iface (master_device)); - return FALSE; - } - } else { - /* Try master as a connection UUID */ - master_connection = nm_settings_get_connection_by_uuid (priv->settings, master); - if (master_connection) { - NMDevice *candidate; - - /* Check if the master connection is activated on some device already */ - c_list_for_each_entry (candidate, &priv->devices_lst_head, devices_lst) { - if (candidate == device) - continue; - - if (nm_device_get_settings_connection (candidate) == master_connection) { - master_device = candidate; - break; - } - } - } - } - - if (out_master_connection) - *out_master_connection = master_connection; - if (out_master_device) - *out_master_device = master_device; - if (out_master_ac && master_connection) { - *out_master_ac = active_connection_find (self, master_connection, NULL, - NM_ACTIVE_CONNECTION_STATE_DEACTIVATING, - NULL); - } - - if (master_device || master_connection) - return TRUE; - else { - g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, - "Master connection not found or invalid"); - return FALSE; - } +find_master(NMManager * self, + NMConnection * connection, + NMDevice * device, + NMSettingsConnection **out_master_connection, + NMDevice ** out_master_device, + NMActiveConnection ** out_master_ac, + GError ** error) +{ + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + NMSettingConnection * s_con; + const char * master; + NMDevice * master_device = NULL; + NMSettingsConnection *master_connection; + + s_con = nm_connection_get_setting_connection(connection); + g_assert(s_con); + master = nm_setting_connection_get_master(s_con); + + if (master == NULL) + return TRUE; /* success, but no master */ + + /* Try as an interface name first */ + master_device = find_device_by_iface(self, master, NULL, connection); + if (master_device) { + if (master_device == device) { + g_set_error_literal(error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_DEPENDENCY_FAILED, + "Device cannot be its own master"); + return FALSE; + } + + master_connection = nm_device_get_settings_connection(master_device); + if (master_connection + && !is_compatible_with_slave(nm_settings_connection_get_connection(master_connection), + connection)) { + g_set_error(error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_DEPENDENCY_FAILED, + "The active connection on %s is not compatible", + nm_device_get_iface(master_device)); + return FALSE; + } + } else { + /* Try master as a connection UUID */ + master_connection = nm_settings_get_connection_by_uuid(priv->settings, master); + if (master_connection) { + NMDevice *candidate; + + /* Check if the master connection is activated on some device already */ + c_list_for_each_entry (candidate, &priv->devices_lst_head, devices_lst) { + if (candidate == device) + continue; + + if (nm_device_get_settings_connection(candidate) == master_connection) { + master_device = candidate; + break; + } + } + } + } + + if (out_master_connection) + *out_master_connection = master_connection; + if (out_master_device) + *out_master_device = master_device; + if (out_master_ac && master_connection) { + *out_master_ac = active_connection_find(self, + master_connection, + NULL, + NM_ACTIVE_CONNECTION_STATE_DEACTIVATING, + NULL); + } + + if (master_device || master_connection) + return TRUE; + else { + g_set_error_literal(error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "Master connection not found or invalid"); + return FALSE; + } } /** @@ -4128,167 +4151,174 @@ find_master (NMManager *self, * %NULL if an error occurred */ static NMActiveConnection * -ensure_master_active_connection (NMManager *self, - NMAuthSubject *subject, - NMConnection *connection, - NMDevice *device, - NMSettingsConnection *master_connection, - NMDevice *master_device, - NMActivationReason activation_reason, - GError **error) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMActiveConnection *ac; - NMActiveConnection *master_ac = NULL; - NMDeviceState master_state; - gboolean bind_lifetime_to_profile_visibility; - - g_return_val_if_fail (connection, NULL); - g_return_val_if_fail (master_connection || master_device, FALSE); - - bind_lifetime_to_profile_visibility = NM_FLAGS_HAS (nm_device_get_activation_state_flags (device), - NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY); - - /* If the master device isn't activated then we need to activate it using - * compatible connection. If it's already activating we can just proceed. - */ - if (master_device) { - NMSettingsConnection *device_connection = nm_device_get_settings_connection (master_device); - - /* If we're passed a connection and a device, we require that connection - * be already activated on the device, eg returned from find_master(). - */ - g_assert (!master_connection || master_connection == device_connection); - if ( device_connection - && !is_compatible_with_slave (nm_settings_connection_get_connection (device_connection), - connection)) { - g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_DEPENDENCY_FAILED, - "The active connection %s is not compatible", - nm_connection_get_id (connection)); - return NULL; - } - - master_state = nm_device_get_state (master_device); - if ( (master_state == NM_DEVICE_STATE_ACTIVATED) - || nm_device_is_activating (master_device)) { - /* Device already using master_connection */ - ac = NM_ACTIVE_CONNECTION (nm_device_get_act_request (master_device)); - g_return_val_if_fail (device_connection, ac); - - if (!bind_lifetime_to_profile_visibility) { - /* unbind the lifetime. */ - nm_active_connection_set_state_flags_clear (ac, - NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY); - } - - return ac; - } - - /* If the device is disconnected, find a compatible connection and - * activate it on the device. - */ - if (master_state == NM_DEVICE_STATE_DISCONNECTED || !nm_device_is_real (master_device)) { - gs_free NMSettingsConnection **connections = NULL; - guint i; - - g_assert (master_connection == NULL); - - /* Find a compatible connection and activate this device using it */ - connections = nm_manager_get_activatable_connections (self, FALSE, TRUE, NULL); - for (i = 0; connections[i]; i++) { - NMSettingsConnection *candidate = connections[i]; - NMConnection *cand_conn = nm_settings_connection_get_connection (candidate); - - /* Ensure eg bond/team slave and the candidate master is a - * bond/team master - */ - if (!is_compatible_with_slave (cand_conn, connection)) - continue; - - if (nm_device_check_connection_available (master_device, - cand_conn, - NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST, - NULL, - NULL)) { - master_ac = nm_manager_activate_connection (self, - candidate, - NULL, - NULL, - master_device, - subject, - NM_ACTIVATION_TYPE_MANAGED, - activation_reason, - bind_lifetime_to_profile_visibility - ? NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY - : NM_ACTIVATION_STATE_FLAG_NONE, - error); - return master_ac; - } - } - - g_set_error (error, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_UNKNOWN_CONNECTION, - "No compatible connection found."); - return NULL; - } - - /* Otherwise, the device is unmanaged, unavailable, or disconnecting */ - g_set_error (error, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_DEPENDENCY_FAILED, - "Device unmanaged or not available for activation"); - } else if (master_connection) { - NMDevice *candidate; - - /* Find a compatible device and activate it using this connection */ - c_list_for_each_entry (candidate, &priv->devices_lst_head, devices_lst) { - if (candidate == device) { - /* A device obviously can't be its own master */ - continue; - } - - if (!nm_device_check_connection_available (candidate, - nm_settings_connection_get_connection (master_connection), - NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST, - NULL, - NULL)) - continue; - - if (!nm_device_is_software (candidate)) { - master_state = nm_device_get_state (candidate); - if (nm_device_is_real (candidate) && master_state != NM_DEVICE_STATE_DISCONNECTED) - continue; - } - - master_ac = nm_manager_activate_connection (self, - master_connection, - NULL, - NULL, - candidate, - subject, - NM_ACTIVATION_TYPE_MANAGED, - activation_reason, - bind_lifetime_to_profile_visibility - ? NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY - : NM_ACTIVATION_STATE_FLAG_NONE, - error); - return master_ac; - } - - g_set_error (error, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_UNKNOWN_DEVICE, - "No device available"); - } else - g_assert_not_reached (); - - return NULL; +ensure_master_active_connection(NMManager * self, + NMAuthSubject * subject, + NMConnection * connection, + NMDevice * device, + NMSettingsConnection *master_connection, + NMDevice * master_device, + NMActivationReason activation_reason, + GError ** error) +{ + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + NMActiveConnection *ac; + NMActiveConnection *master_ac = NULL; + NMDeviceState master_state; + gboolean bind_lifetime_to_profile_visibility; + + g_return_val_if_fail(connection, NULL); + g_return_val_if_fail(master_connection || master_device, FALSE); + + bind_lifetime_to_profile_visibility = + NM_FLAGS_HAS(nm_device_get_activation_state_flags(device), + NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY); + + /* If the master device isn't activated then we need to activate it using + * compatible connection. If it's already activating we can just proceed. + */ + if (master_device) { + NMSettingsConnection *device_connection = nm_device_get_settings_connection(master_device); + + /* If we're passed a connection and a device, we require that connection + * be already activated on the device, eg returned from find_master(). + */ + g_assert(!master_connection || master_connection == device_connection); + if (device_connection + && !is_compatible_with_slave(nm_settings_connection_get_connection(device_connection), + connection)) { + g_set_error(error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_DEPENDENCY_FAILED, + "The active connection %s is not compatible", + nm_connection_get_id(connection)); + return NULL; + } + + master_state = nm_device_get_state(master_device); + if ((master_state == NM_DEVICE_STATE_ACTIVATED) || nm_device_is_activating(master_device)) { + /* Device already using master_connection */ + ac = NM_ACTIVE_CONNECTION(nm_device_get_act_request(master_device)); + g_return_val_if_fail(device_connection, ac); + + if (!bind_lifetime_to_profile_visibility) { + /* unbind the lifetime. */ + nm_active_connection_set_state_flags_clear( + ac, + NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY); + } + + return ac; + } + + /* If the device is disconnected, find a compatible connection and + * activate it on the device. + */ + if (master_state == NM_DEVICE_STATE_DISCONNECTED || !nm_device_is_real(master_device)) { + gs_free NMSettingsConnection **connections = NULL; + guint i; + + g_assert(master_connection == NULL); + + /* Find a compatible connection and activate this device using it */ + connections = nm_manager_get_activatable_connections(self, FALSE, TRUE, NULL); + for (i = 0; connections[i]; i++) { + NMSettingsConnection *candidate = connections[i]; + NMConnection * cand_conn = nm_settings_connection_get_connection(candidate); + + /* Ensure eg bond/team slave and the candidate master is a + * bond/team master + */ + if (!is_compatible_with_slave(cand_conn, connection)) + continue; + + if (nm_device_check_connection_available( + master_device, + cand_conn, + NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST, + NULL, + NULL)) { + master_ac = nm_manager_activate_connection( + self, + candidate, + NULL, + NULL, + master_device, + subject, + NM_ACTIVATION_TYPE_MANAGED, + activation_reason, + bind_lifetime_to_profile_visibility + ? NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY + : NM_ACTIVATION_STATE_FLAG_NONE, + error); + return master_ac; + } + } + + g_set_error(error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_UNKNOWN_CONNECTION, + "No compatible connection found."); + return NULL; + } + + /* Otherwise, the device is unmanaged, unavailable, or disconnecting */ + g_set_error(error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_DEPENDENCY_FAILED, + "Device unmanaged or not available for activation"); + } else if (master_connection) { + NMDevice *candidate; + + /* Find a compatible device and activate it using this connection */ + c_list_for_each_entry (candidate, &priv->devices_lst_head, devices_lst) { + if (candidate == device) { + /* A device obviously can't be its own master */ + continue; + } + + if (!nm_device_check_connection_available( + candidate, + nm_settings_connection_get_connection(master_connection), + NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST, + NULL, + NULL)) + continue; + + if (!nm_device_is_software(candidate)) { + master_state = nm_device_get_state(candidate); + if (nm_device_is_real(candidate) && master_state != NM_DEVICE_STATE_DISCONNECTED) + continue; + } + + master_ac = nm_manager_activate_connection( + self, + master_connection, + NULL, + NULL, + candidate, + subject, + NM_ACTIVATION_TYPE_MANAGED, + activation_reason, + bind_lifetime_to_profile_visibility + ? NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY + : NM_ACTIVATION_STATE_FLAG_NONE, + error); + return master_ac; + } + + g_set_error(error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "No device available"); + } else + g_assert_not_reached(); + + return NULL; } typedef struct { - NMSettingsConnection *connection; - NMDevice *device; + NMSettingsConnection *connection; + NMDevice * device; } SlaveConnectionInfo; /** @@ -4304,237 +4334,248 @@ typedef struct { * Returns: an array of #SlaveConnectionInfo for given master @sett_conn, or %NULL **/ static SlaveConnectionInfo * -find_slaves (NMManager *manager, - NMSettingsConnection *sett_conn, - NMDevice *device, - guint *out_n_slaves, - gboolean for_user_request) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - gs_free NMSettingsConnection **all_connections = NULL; - guint n_all_connections; - guint i; - SlaveConnectionInfo *slaves = NULL; - guint n_slaves = 0; - NMSettingConnection *s_con; - gs_unref_hashtable GHashTable *devices = NULL; - - nm_assert (out_n_slaves); - - s_con = nm_connection_get_setting_connection (nm_settings_connection_get_connection (sett_conn)); - g_return_val_if_fail (s_con, NULL); - - devices = g_hash_table_new (nm_direct_hash, NULL); - - /* Search through all connections, not only inactive ones, because - * even if a slave was already active, it might be deactivated during - * master reactivation. - */ - all_connections = nm_settings_get_connections_clone (priv->settings, &n_all_connections, - NULL, NULL, - nm_settings_connection_cmp_autoconnect_priority_p_with_data, NULL); - for (i = 0; i < n_all_connections; i++) { - NMSettingsConnection *master_connection = NULL; - NMDevice *master_device = NULL, *slave_device; - NMSettingsConnection *candidate = all_connections[i]; - - find_master (manager, - nm_settings_connection_get_connection (candidate), - NULL, - &master_connection, - &master_device, - NULL, - NULL); - if ( (master_connection && master_connection == sett_conn) - || (master_device && master_device == device)) { - slave_device = nm_manager_get_best_device_for_connection (manager, - candidate, - NULL, - for_user_request, - devices, - NULL); - - if (!slaves) { - /* what we allocate is quite likely much too large. Don't bother, it is only - * a temporary buffer. */ - slaves = g_new (SlaveConnectionInfo, n_all_connections); - } - - nm_assert (n_slaves < n_all_connections); - slaves[n_slaves].connection = candidate, - slaves[n_slaves].device = slave_device, - n_slaves++; - - if (slave_device) - g_hash_table_add (devices, slave_device); - } - } - - *out_n_slaves = n_slaves; - - /* Warning: returns NULL if n_slaves is zero. */ - return slaves; +find_slaves(NMManager * manager, + NMSettingsConnection *sett_conn, + NMDevice * device, + guint * out_n_slaves, + gboolean for_user_request) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(manager); + gs_free NMSettingsConnection **all_connections = NULL; + guint n_all_connections; + guint i; + SlaveConnectionInfo * slaves = NULL; + guint n_slaves = 0; + NMSettingConnection * s_con; + gs_unref_hashtable GHashTable *devices = NULL; + + nm_assert(out_n_slaves); + + s_con = nm_connection_get_setting_connection(nm_settings_connection_get_connection(sett_conn)); + g_return_val_if_fail(s_con, NULL); + + devices = g_hash_table_new(nm_direct_hash, NULL); + + /* Search through all connections, not only inactive ones, because + * even if a slave was already active, it might be deactivated during + * master reactivation. + */ + all_connections = nm_settings_get_connections_clone( + priv->settings, + &n_all_connections, + NULL, + NULL, + nm_settings_connection_cmp_autoconnect_priority_p_with_data, + NULL); + for (i = 0; i < n_all_connections; i++) { + NMSettingsConnection *master_connection = NULL; + NMDevice * master_device = NULL, *slave_device; + NMSettingsConnection *candidate = all_connections[i]; + + find_master(manager, + nm_settings_connection_get_connection(candidate), + NULL, + &master_connection, + &master_device, + NULL, + NULL); + if ((master_connection && master_connection == sett_conn) + || (master_device && master_device == device)) { + slave_device = nm_manager_get_best_device_for_connection(manager, + candidate, + NULL, + for_user_request, + devices, + NULL); + + if (!slaves) { + /* what we allocate is quite likely much too large. Don't bother, it is only + * a temporary buffer. */ + slaves = g_new(SlaveConnectionInfo, n_all_connections); + } + + nm_assert(n_slaves < n_all_connections); + slaves[n_slaves].connection = candidate, slaves[n_slaves].device = slave_device, + n_slaves++; + + if (slave_device) + g_hash_table_add(devices, slave_device); + } + } + + *out_n_slaves = n_slaves; + + /* Warning: returns NULL if n_slaves is zero. */ + return slaves; } static gboolean -should_connect_slaves (NMConnection *connection, NMDevice *device) +should_connect_slaves(NMConnection *connection, NMDevice *device) { - NMSettingConnection *s_con; - NMSettingConnectionAutoconnectSlaves val; + NMSettingConnection * s_con; + NMSettingConnectionAutoconnectSlaves val; - s_con = nm_connection_get_setting_connection (connection); - g_assert (s_con); + s_con = nm_connection_get_setting_connection(connection); + g_assert(s_con); - val = nm_setting_connection_get_autoconnect_slaves (s_con); - if (val != NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_DEFAULT) - goto out; + val = nm_setting_connection_get_autoconnect_slaves(s_con); + if (val != NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_DEFAULT) + goto out; - val = nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA, - NM_CON_DEFAULT ("connection.autoconnect-slaves"), - device, - 0, 1, -1); + val = + nm_config_data_get_connection_default_int64(NM_CONFIG_GET_DATA, + NM_CON_DEFAULT("connection.autoconnect-slaves"), + device, + 0, + 1, + -1); out: - if (val == NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_NO) - return FALSE; - if (val == NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_YES) - return TRUE; - return FALSE; + if (val == NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_NO) + return FALSE; + if (val == NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_YES) + return TRUE; + return FALSE; } static int -compare_slaves (gconstpointer a, gconstpointer b, gpointer sort_by_name) +compare_slaves(gconstpointer a, gconstpointer b, gpointer sort_by_name) { - const SlaveConnectionInfo *a_info = a; - const SlaveConnectionInfo *b_info = b; + const SlaveConnectionInfo *a_info = a; + const SlaveConnectionInfo *b_info = b; - /* Slaves without a device at the end */ - if (!a_info->device) - return 1; - if (!b_info->device) - return -1; + /* Slaves without a device at the end */ + if (!a_info->device) + return 1; + if (!b_info->device) + return -1; - if (GPOINTER_TO_INT (sort_by_name)) { - return g_strcmp0 (nm_device_get_iface (a_info->device), - nm_device_get_iface (b_info->device)); - } + if (GPOINTER_TO_INT(sort_by_name)) { + return nm_strcmp0(nm_device_get_iface(a_info->device), nm_device_get_iface(b_info->device)); + } - return nm_device_get_ifindex (a_info->device) - nm_device_get_ifindex (b_info->device); + return nm_device_get_ifindex(a_info->device) - nm_device_get_ifindex(b_info->device); } static void -autoconnect_slaves (NMManager *self, - NMSettingsConnection *master_connection, - NMDevice *master_device, - NMAuthSubject *subject, - gboolean for_user_request) -{ - GError *local_err = NULL; - - if (should_connect_slaves (nm_settings_connection_get_connection (master_connection), - master_device)) { - gs_free SlaveConnectionInfo *slaves = NULL; - guint i, n_slaves = 0; - gboolean bind_lifetime_to_profile_visibility; - - slaves = find_slaves (self, master_connection, master_device, &n_slaves, for_user_request); - if (n_slaves > 1) { - gs_free char *value = NULL; - - value = nm_config_data_get_value (NM_CONFIG_GET_DATA, - NM_CONFIG_KEYFILE_GROUP_MAIN, - NM_CONFIG_KEYFILE_KEY_MAIN_SLAVES_ORDER, - NM_CONFIG_GET_VALUE_STRIP); - g_qsort_with_data (slaves, n_slaves, sizeof (slaves[0]), - compare_slaves, - GINT_TO_POINTER (!nm_streq0 (value, "index"))); - } - - bind_lifetime_to_profile_visibility = n_slaves > 0 - && NM_FLAGS_HAS (nm_device_get_activation_state_flags (master_device), - NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY); - - for (i = 0; i < n_slaves; i++) { - SlaveConnectionInfo *slave = &slaves[i]; - const char *uuid; - - /* To avoid loops when autoconnecting slaves, we propagate - * the UUID of the initial connection down to slaves until - * the same connection is found. - */ - uuid = g_object_get_qdata (G_OBJECT (master_connection), - autoconnect_root_quark ()); - if (nm_streq0 (nm_settings_connection_get_uuid (slave->connection), uuid)) { - _LOGI (LOGD_CORE, - "will NOT activate slave connection '%s' (%s) as a dependency for master '%s' (%s): " - "circular dependency detected", - nm_settings_connection_get_id (slave->connection), - nm_settings_connection_get_uuid (slave->connection), - nm_settings_connection_get_id (master_connection), - nm_settings_connection_get_uuid (master_connection)); - continue; - } - - if (!uuid) - uuid = nm_settings_connection_get_uuid (master_connection); - g_object_set_qdata_full (G_OBJECT (slave->connection), - autoconnect_root_quark (), - g_strdup (uuid), - g_free); - - if (!slave->device) { - _LOGD (LOGD_CORE, - "will NOT activate slave connection '%s' (%s) as a dependency for master '%s' (%s): " - "no compatible device found", - nm_settings_connection_get_id (slave->connection), - nm_settings_connection_get_uuid (slave->connection), - nm_settings_connection_get_id (master_connection), - nm_settings_connection_get_uuid (master_connection)); - continue; - } - - _LOGD (LOGD_CORE, "will activate slave connection '%s' (%s) as a dependency for master '%s' (%s)", - nm_settings_connection_get_id (slave->connection), - nm_settings_connection_get_uuid (slave->connection), - nm_settings_connection_get_id (master_connection), - nm_settings_connection_get_uuid (master_connection)); - - /* Schedule slave activation */ - nm_manager_activate_connection (self, - slave->connection, - NULL, - NULL, - slave->device, - subject, - NM_ACTIVATION_TYPE_MANAGED, - NM_ACTIVATION_REASON_AUTOCONNECT_SLAVES, - bind_lifetime_to_profile_visibility - ? NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY - : NM_ACTIVATION_STATE_FLAG_NONE, - &local_err); - if (local_err) { - _LOGW (LOGD_CORE, "Slave connection activation failed: %s", local_err->message); - g_clear_error (&local_err); - } - } - } +autoconnect_slaves(NMManager * self, + NMSettingsConnection *master_connection, + NMDevice * master_device, + NMAuthSubject * subject, + gboolean for_user_request) +{ + GError *local_err = NULL; + + if (should_connect_slaves(nm_settings_connection_get_connection(master_connection), + master_device)) { + gs_free SlaveConnectionInfo *slaves = NULL; + guint i, n_slaves = 0; + gboolean bind_lifetime_to_profile_visibility; + + slaves = find_slaves(self, master_connection, master_device, &n_slaves, for_user_request); + if (n_slaves > 1) { + gs_free char *value = NULL; + + value = nm_config_data_get_value(NM_CONFIG_GET_DATA, + NM_CONFIG_KEYFILE_GROUP_MAIN, + NM_CONFIG_KEYFILE_KEY_MAIN_SLAVES_ORDER, + NM_CONFIG_GET_VALUE_STRIP); + g_qsort_with_data(slaves, + n_slaves, + sizeof(slaves[0]), + compare_slaves, + GINT_TO_POINTER(!nm_streq0(value, "index"))); + } + + bind_lifetime_to_profile_visibility = + n_slaves > 0 + && NM_FLAGS_HAS(nm_device_get_activation_state_flags(master_device), + NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY); + + for (i = 0; i < n_slaves; i++) { + SlaveConnectionInfo *slave = &slaves[i]; + const char * uuid; + + /* To avoid loops when autoconnecting slaves, we propagate + * the UUID of the initial connection down to slaves until + * the same connection is found. + */ + uuid = g_object_get_qdata(G_OBJECT(master_connection), autoconnect_root_quark()); + if (nm_streq0(nm_settings_connection_get_uuid(slave->connection), uuid)) { + _LOGI(LOGD_CORE, + "will NOT activate slave connection '%s' (%s) as a dependency for master " + "'%s' (%s): " + "circular dependency detected", + nm_settings_connection_get_id(slave->connection), + nm_settings_connection_get_uuid(slave->connection), + nm_settings_connection_get_id(master_connection), + nm_settings_connection_get_uuid(master_connection)); + continue; + } + + if (!uuid) + uuid = nm_settings_connection_get_uuid(master_connection); + g_object_set_qdata_full(G_OBJECT(slave->connection), + autoconnect_root_quark(), + g_strdup(uuid), + g_free); + + if (!slave->device) { + _LOGD(LOGD_CORE, + "will NOT activate slave connection '%s' (%s) as a dependency for master " + "'%s' (%s): " + "no compatible device found", + nm_settings_connection_get_id(slave->connection), + nm_settings_connection_get_uuid(slave->connection), + nm_settings_connection_get_id(master_connection), + nm_settings_connection_get_uuid(master_connection)); + continue; + } + + _LOGD(LOGD_CORE, + "will activate slave connection '%s' (%s) as a dependency for master '%s' (%s)", + nm_settings_connection_get_id(slave->connection), + nm_settings_connection_get_uuid(slave->connection), + nm_settings_connection_get_id(master_connection), + nm_settings_connection_get_uuid(master_connection)); + + /* Schedule slave activation */ + nm_manager_activate_connection( + self, + slave->connection, + NULL, + NULL, + slave->device, + subject, + NM_ACTIVATION_TYPE_MANAGED, + NM_ACTIVATION_REASON_AUTOCONNECT_SLAVES, + bind_lifetime_to_profile_visibility + ? NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY + : NM_ACTIVATION_STATE_FLAG_NONE, + &local_err); + if (local_err) { + _LOGW(LOGD_CORE, "Slave connection activation failed: %s", local_err->message); + g_clear_error(&local_err); + } + } + } } static gboolean -_internal_activate_vpn (NMManager *self, NMActiveConnection *active, GError **error) +_internal_activate_vpn(NMManager *self, NMActiveConnection *active, GError **error) { - nm_assert (NM_IS_VPN_CONNECTION (active)); + nm_assert(NM_IS_VPN_CONNECTION(active)); - nm_dbus_object_export (NM_DBUS_OBJECT (active)); - if (!nm_vpn_manager_activate_connection (NM_MANAGER_GET_PRIVATE (self)->vpn_manager, - NM_VPN_CONNECTION (active), - error)) { - nm_dbus_object_unexport (NM_DBUS_OBJECT (active)); - return FALSE; - } + nm_dbus_object_export(NM_DBUS_OBJECT(active)); + if (!nm_vpn_manager_activate_connection(NM_MANAGER_GET_PRIVATE(self)->vpn_manager, + NM_VPN_CONNECTION(active), + error)) { + nm_dbus_object_unexport(NM_DBUS_OBJECT(active)); + return FALSE; + } - active_connection_add (self, active); - return TRUE; + active_connection_add(self, active); + return TRUE; } /* Traverse the device to disconnected state. This means that the device is ready @@ -4542,549 +4583,605 @@ _internal_activate_vpn (NMManager *self, NMActiveConnection *active, GError **er * enqueued. */ static void -unmanaged_to_disconnected (NMDevice *device) -{ - /* when creating the software device, it can happen that the device is - * still unmanaged by NM_UNMANAGED_PLATFORM_INIT because we didn't yet - * get the udev event. At this point, we can no longer delay the activation - * and force the device to be managed. */ - nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_PLATFORM_INIT, FALSE, NM_DEVICE_STATE_REASON_USER_REQUESTED); - - nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_USER_EXPLICIT, FALSE, NM_DEVICE_STATE_REASON_USER_REQUESTED); - - if (!nm_device_get_managed (device, FALSE)) { - /* the device is still marked as unmanaged. Nothing to do. */ - return; - } - - if (nm_device_get_state (device) == NM_DEVICE_STATE_UNMANAGED) { - nm_device_state_changed (device, - NM_DEVICE_STATE_UNAVAILABLE, - NM_DEVICE_STATE_REASON_USER_REQUESTED); - } - - if ( nm_device_get_state (device) == NM_DEVICE_STATE_UNAVAILABLE - && nm_device_is_available (device, NM_DEVICE_CHECK_DEV_AVAILABLE_FOR_USER_REQUEST)) { - nm_device_state_changed (device, - NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_REASON_USER_REQUESTED); - } +unmanaged_to_disconnected(NMDevice *device) +{ + /* when creating the software device, it can happen that the device is + * still unmanaged by NM_UNMANAGED_PLATFORM_INIT because we didn't yet + * get the udev event. At this point, we can no longer delay the activation + * and force the device to be managed. */ + nm_device_set_unmanaged_by_flags(device, + NM_UNMANAGED_PLATFORM_INIT, + FALSE, + NM_DEVICE_STATE_REASON_USER_REQUESTED); + + nm_device_set_unmanaged_by_flags(device, + NM_UNMANAGED_USER_EXPLICIT, + FALSE, + NM_DEVICE_STATE_REASON_USER_REQUESTED); + + if (!nm_device_get_managed(device, FALSE)) { + /* the device is still marked as unmanaged. Nothing to do. */ + return; + } + + if (nm_device_get_state(device) == NM_DEVICE_STATE_UNMANAGED) { + nm_device_state_changed(device, + NM_DEVICE_STATE_UNAVAILABLE, + NM_DEVICE_STATE_REASON_USER_REQUESTED); + } + + if (nm_device_get_state(device) == NM_DEVICE_STATE_UNAVAILABLE + && nm_device_is_available(device, NM_DEVICE_CHECK_DEV_AVAILABLE_FOR_USER_REQUEST)) { + nm_device_state_changed(device, + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_USER_REQUESTED); + } } static NMActivationStateFlags -_activation_bind_lifetime_to_profile_visibility (NMAuthSubject *subject) -{ - if ( nm_auth_subject_get_subject_type (subject) == NM_AUTH_SUBJECT_TYPE_INTERNAL - || nm_auth_subject_get_unix_process_uid (subject) == 0) { - /* internal requests and requests from root are always unbound. */ - return NM_ACTIVATION_STATE_FLAG_NONE; - } - - /* if the activation was not done by internal decision nor root, there - * are the following cases: - * - * - the connection has "connection.permissions" unset and the profile - * is not restricted to a user and commonly always visible. It does - * not hurt to bind the lifetime, because we expect the profile to be - * visible at the moment. If the profile changes (while still being active), - * we want to pick-up changes to the visibility and possibly disconnect. - * - * - the connection has "connection.permissions" set, and the current user - * is the owner: - * - * - Usually, we would expect that the profile is visible at the moment, - * and of course we want to bind the lifetime. The moment the user - * logs out, the connection becomes invisible and disconnects. - * - * - the profile at this time could already be invisible (e.g. if the - * user didn't create a proper session (sudo) and manually activates - * an invisible profile. In this case, we still want to bind the - * lifetime, and it will disconnect after the user logs in and logs - * out again. NMKeepAlive takes care of that. - */ - return NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY; +_activation_bind_lifetime_to_profile_visibility(NMAuthSubject *subject) +{ + if (nm_auth_subject_get_subject_type(subject) == NM_AUTH_SUBJECT_TYPE_INTERNAL + || nm_auth_subject_get_unix_process_uid(subject) == 0) { + /* internal requests and requests from root are always unbound. */ + return NM_ACTIVATION_STATE_FLAG_NONE; + } + + /* if the activation was not done by internal decision nor root, there + * are the following cases: + * + * - the connection has "connection.permissions" unset and the profile + * is not restricted to a user and commonly always visible. It does + * not hurt to bind the lifetime, because we expect the profile to be + * visible at the moment. If the profile changes (while still being active), + * we want to pick-up changes to the visibility and possibly disconnect. + * + * - the connection has "connection.permissions" set, and the current user + * is the owner: + * + * - Usually, we would expect that the profile is visible at the moment, + * and of course we want to bind the lifetime. The moment the user + * logs out, the connection becomes invisible and disconnects. + * + * - the profile at this time could already be invisible (e.g. if the + * user didn't create a proper session (sudo) and manually activates + * an invisible profile. In this case, we still want to bind the + * lifetime, and it will disconnect after the user logs in and logs + * out again. NMKeepAlive takes care of that. + */ + return NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY; } /* The parent connection is ready; we can proceed realizing the device and * progressing the device to disconencted state. */ static void -active_connection_parent_active (NMActiveConnection *active, - NMActiveConnection *parent_ac, - NMManager *self) -{ - NMDevice *device = nm_active_connection_get_device (active); - GError *error = NULL; - NMSettingsConnection *sett_conn; - NMDevice *parent; - - g_signal_handlers_disconnect_by_func (active, - (GCallback) active_connection_parent_active, - self); - - if (!parent_ac) { - _LOGW (LOGD_CORE, "The parent connection device '%s' depended on disappeared.", - nm_device_get_iface (device)); - nm_active_connection_set_state_fail (active, - NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REMOVED, - "parent device disappeared"); - return; - } - - sett_conn = nm_active_connection_get_settings_connection (active); - parent = nm_active_connection_get_device (parent_ac); - - if (!nm_device_create_and_realize (device, - nm_settings_connection_get_connection (sett_conn), - parent, - &error)) { - _LOGW (LOGD_CORE, "Could not realize device '%s': %s", - nm_device_get_iface (device), error->message); - nm_active_connection_set_state_fail (active, - NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REALIZE_FAILED, - "failure to realize device"); - return; - } - - /* We can now proceed to disconnected state so that activation proceeds. */ - unmanaged_to_disconnected (device); +active_connection_parent_active(NMActiveConnection *active, + NMActiveConnection *parent_ac, + NMManager * self) +{ + NMDevice * device = nm_active_connection_get_device(active); + GError * error = NULL; + NMSettingsConnection *sett_conn; + NMDevice * parent; + + g_signal_handlers_disconnect_by_func(active, (GCallback) active_connection_parent_active, self); + + if (!parent_ac) { + _LOGW(LOGD_CORE, + "The parent connection device '%s' depended on disappeared.", + nm_device_get_iface(device)); + nm_active_connection_set_state_fail(active, + NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REMOVED, + "parent device disappeared"); + return; + } + + sett_conn = nm_active_connection_get_settings_connection(active); + parent = nm_active_connection_get_device(parent_ac); + + if (!nm_device_create_and_realize(device, + nm_settings_connection_get_connection(sett_conn), + parent, + &error)) { + _LOGW(LOGD_CORE, + "Could not realize device '%s': %s", + nm_device_get_iface(device), + error->message); + nm_active_connection_set_state_fail(active, + NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REALIZE_FAILED, + "failure to realize device"); + return; + } + + /* We can now proceed to disconnected state so that activation proceeds. */ + unmanaged_to_disconnected(device); } static gboolean -_internal_activate_device (NMManager *self, NMActiveConnection *active, GError **error) -{ - NMDevice *device, *master_device = NULL; - NMConnection *applied; - NMSettingsConnection *sett_conn; - NMSettingsConnection *master_connection = NULL; - NMConnection *existing_connection = NULL; - NMActiveConnection *master_ac = NULL; - NMAuthSubject *subject; - GError *local = NULL; - NMConnectionMultiConnect multi_connect; - const char *parent_spec; - - g_return_val_if_fail (NM_IS_MANAGER (self), FALSE); - g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (active), FALSE); - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - g_assert (NM_IS_VPN_CONNECTION (active) == FALSE); - - device = nm_active_connection_get_device (active); - g_return_val_if_fail (device != NULL, FALSE); - - sett_conn = nm_active_connection_get_settings_connection (active); - nm_assert (sett_conn); - - applied = nm_active_connection_get_applied_connection (active); - - /* If the device is active and its connection is not visible to the - * user that's requesting this new activation, fail, since other users - * should not be allowed to implicitly deactivate private connections - * by activating a connection of their own. - */ - existing_connection = nm_device_get_applied_connection (device); - subject = nm_active_connection_get_subject (active); - if ( existing_connection - && !nm_auth_is_subject_in_acl_set_error (existing_connection, - subject, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - error)) { - g_prefix_error (error, "Private connection already active on the device: "); - return FALSE; - } - - /* Final connection must be available on device */ - if (!nm_device_check_connection_available (device, applied, NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST, NULL, &local)) { - g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_CONNECTION, - "Connection '%s' is not available on device %s because %s", - nm_settings_connection_get_id (sett_conn), - nm_device_get_iface (device), - local->message); - g_error_free (local); - return FALSE; - } - - if (nm_active_connection_get_activation_type (active) == NM_ACTIVATION_TYPE_MANAGED) - nm_device_sys_iface_state_set (device, NM_DEVICE_SYS_IFACE_STATE_MANAGED); - - /* Try to find the master connection/device if the connection has a dependency */ - if (!find_master (self, - applied, - device, - &master_connection, - &master_device, - &master_ac, - error)) { - g_prefix_error (error, "Can not find a master for %s: ", - nm_settings_connection_get_id (sett_conn)); - return FALSE; - } - - /* Create any backing resources the device needs */ - if (!nm_device_is_real (device)) { - NMDevice *parent; - - parent = find_parent_device_for_connection (self, - nm_settings_connection_get_connection (sett_conn), - NULL, - &parent_spec); - - if (parent_spec && !parent) { - g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_DEPENDENCY_FAILED, - "parent device '%s' not found", parent_spec); - return FALSE; - } - - if (parent && !nm_device_is_real (parent)) { - NMSettingsConnection *parent_con; - NMActiveConnection *parent_ac; - - parent_con = nm_device_get_best_connection (parent, NULL, error); - if (!parent_con) { - g_prefix_error (error, "%s failed to create parent: ", nm_device_get_iface (device)); - return FALSE; - } - - if ( nm_active_connection_get_activation_reason (active) == NM_ACTIVATION_REASON_AUTOCONNECT - && NM_FLAGS_HAS (nm_settings_connection_autoconnect_blocked_reason_get (parent_con), - NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST)) { - g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_DEPENDENCY_FAILED, - "the parent connection of %s cannot autoactivate because it is blocked due to user request", - nm_device_get_iface (device)); - return FALSE; - } - - parent_ac = nm_manager_activate_connection (self, - parent_con, - NULL, - NULL, - parent, - subject, - NM_ACTIVATION_TYPE_MANAGED, - nm_active_connection_get_activation_reason (active), - nm_active_connection_get_state_flags (active) - & NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY, - error); - if (!parent_ac) { - g_prefix_error (error, "%s failed to activate parent: ", nm_device_get_iface (device)); - return FALSE; - } - - /* We can't realize now; defer until the parent device is ready. */ - g_signal_connect (active, - NM_ACTIVE_CONNECTION_PARENT_ACTIVE, - (GCallback) active_connection_parent_active, - self); - nm_active_connection_set_parent (active, parent_ac); - } else { - /* We can realize now; no need to wait for a parent device. */ - if (!nm_device_create_and_realize (device, - nm_settings_connection_get_connection (sett_conn), - parent, - error)) { - g_prefix_error (error, "%s failed to create resources: ", nm_device_get_iface (device)); - return FALSE; - } - } - } - - /* Ensure there's a master active connection the new connection we're - * activating can depend on. - */ - if (master_connection || master_device) { - if (master_connection) { - _LOGD (LOGD_CORE, "Activation of '%s' requires master connection '%s'", - nm_settings_connection_get_id (sett_conn), - nm_settings_connection_get_id (master_connection)); - } - if (master_device) { - _LOGD (LOGD_CORE, "Activation of '%s' requires master device '%s'", - nm_settings_connection_get_id (sett_conn), - nm_device_get_ip_iface (master_device)); - } - - /* Ensure eg bond slave and the candidate master is a bond master */ - if ( master_connection - && !is_compatible_with_slave (nm_settings_connection_get_connection (master_connection), - applied)) { - g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_DEPENDENCY_FAILED, - "The master connection '%s' is not compatible with '%s'", - nm_settings_connection_get_id (master_connection), - nm_settings_connection_get_id (sett_conn)); - return FALSE; - } - - if (!master_ac) { - master_ac = ensure_master_active_connection (self, - nm_active_connection_get_subject (active), - applied, - device, - master_connection, - master_device, - nm_active_connection_get_activation_reason (active), - error); - if (!master_ac) { - if (master_device) { - g_prefix_error (error, "Master device '%s' can't be activated: ", - nm_device_get_ip_iface (device)); - } else { - g_prefix_error (error, "Master connection '%s' can't be activated: ", - nm_settings_connection_get_id (sett_conn)); - } - return FALSE; - } - } - - /* Now that we're activating a slave for that master, make sure the master just - * decides to go unmanaged while we're activating (perhaps because other slaves - * go away leaving him with no kids). - */ - if (master_device) { - nm_device_set_unmanaged_by_flags (master_device, NM_UNMANAGED_EXTERNAL_DOWN, - NM_UNMAN_FLAG_OP_FORGET, NM_DEVICE_STATE_REASON_USER_REQUESTED); - } - - nm_active_connection_set_master (active, master_ac); - _LOGD (LOGD_CORE, "Activation of '%s' depends on active connection %p %s", - nm_settings_connection_get_id (sett_conn), - master_ac, - nm_dbus_object_get_path (NM_DBUS_OBJECT (master_ac)) ?: ""); - } - - /* Check slaves for master connection and possibly activate them */ - autoconnect_slaves (self, sett_conn, device, nm_active_connection_get_subject (active), - nm_active_connection_get_activation_reason (active) == NM_ACTIVATION_REASON_USER_REQUEST); - - multi_connect = _nm_connection_get_multi_connect (nm_settings_connection_get_connection (sett_conn)); - if ( multi_connect == NM_CONNECTION_MULTI_CONNECT_MULTIPLE - || ( multi_connect == NM_CONNECTION_MULTI_CONNECT_MANUAL_MULTIPLE - && NM_IN_SET (nm_active_connection_get_activation_reason (active), - NM_ACTIVATION_REASON_ASSUME, - NM_ACTIVATION_REASON_AUTOCONNECT_SLAVES, - NM_ACTIVATION_REASON_USER_REQUEST))) { - /* the profile can be activated multiple times. Proceed. */ - } else { - gs_unref_ptrarray GPtrArray *all_ac_arr = NULL; - NMActiveConnection *ac; - guint i, n_all; - - /* Disconnect the connection if already connected or queued for activation. - * The connection cannot be active multiple times (at the same time). */ - ac = active_connection_find (self, sett_conn, NULL, NM_ACTIVE_CONNECTION_STATE_ACTIVATED, - &all_ac_arr); - if (ac) { - n_all = all_ac_arr ? all_ac_arr->len : ((guint) 1); - for (i = 0; i < n_all; i++) { - nm_device_disconnect_active_connection ( all_ac_arr - ? all_ac_arr->pdata[i] - : ac, - NM_DEVICE_STATE_REASON_NEW_ACTIVATION, - NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN); - } - } - } - - /* If the device is there, we can ready it for the activation. */ - if (nm_device_is_real (device)) { - unmanaged_to_disconnected (device); - - if (!nm_device_get_managed (device, FALSE)) { - /* Unexpectedly, the device is still unmanaged. That can happen for example, - * if the device is forcibly unmanaged due to NM_UNMANAGED_USER_SETTINGS. */ - g_set_error_literal (error, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_DEPENDENCY_FAILED, - "Activation failed because the device is unmanaged"); - return FALSE; - } - } - - /* Export the new ActiveConnection to clients and start it on the device */ - active_connection_add (self, active); - nm_device_queue_activation (device, NM_ACT_REQUEST (active)); - return TRUE; +_internal_activate_device(NMManager *self, NMActiveConnection *active, GError **error) +{ + NMDevice * device, *master_device = NULL; + NMConnection * applied; + NMSettingsConnection * sett_conn; + NMSettingsConnection * master_connection = NULL; + NMConnection * existing_connection = NULL; + NMActiveConnection * master_ac = NULL; + NMAuthSubject * subject; + GError * local = NULL; + NMConnectionMultiConnect multi_connect; + const char * parent_spec; + + g_return_val_if_fail(NM_IS_MANAGER(self), FALSE); + g_return_val_if_fail(NM_IS_ACTIVE_CONNECTION(active), FALSE); + g_return_val_if_fail(error == NULL || *error == NULL, FALSE); + + g_assert(NM_IS_VPN_CONNECTION(active) == FALSE); + + device = nm_active_connection_get_device(active); + g_return_val_if_fail(device != NULL, FALSE); + + sett_conn = nm_active_connection_get_settings_connection(active); + nm_assert(sett_conn); + + applied = nm_active_connection_get_applied_connection(active); + + /* If the device is active and its connection is not visible to the + * user that's requesting this new activation, fail, since other users + * should not be allowed to implicitly deactivate private connections + * by activating a connection of their own. + */ + existing_connection = nm_device_get_applied_connection(device); + subject = nm_active_connection_get_subject(active); + if (existing_connection + && !nm_auth_is_subject_in_acl_set_error(existing_connection, + subject, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + error)) { + g_prefix_error(error, "Private connection already active on the device: "); + return FALSE; + } + + /* Final connection must be available on device */ + if (!nm_device_check_connection_available(device, + applied, + NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST, + NULL, + &local)) { + g_set_error(error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_UNKNOWN_CONNECTION, + "Connection '%s' is not available on device %s because %s", + nm_settings_connection_get_id(sett_conn), + nm_device_get_iface(device), + local->message); + g_error_free(local); + return FALSE; + } + + if (nm_active_connection_get_activation_type(active) == NM_ACTIVATION_TYPE_MANAGED) + nm_device_sys_iface_state_set(device, NM_DEVICE_SYS_IFACE_STATE_MANAGED); + + /* Try to find the master connection/device if the connection has a dependency */ + if (!find_master(self, + applied, + device, + &master_connection, + &master_device, + &master_ac, + error)) { + g_prefix_error(error, + "Can not find a master for %s: ", + nm_settings_connection_get_id(sett_conn)); + return FALSE; + } + + /* Create any backing resources the device needs */ + if (!nm_device_is_real(device)) { + NMDevice *parent; + + parent = find_parent_device_for_connection(self, + nm_settings_connection_get_connection(sett_conn), + NULL, + &parent_spec); + + if (parent_spec && !parent) { + g_set_error(error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_DEPENDENCY_FAILED, + "parent device '%s' not found", + parent_spec); + return FALSE; + } + + if (parent && !nm_device_is_real(parent)) { + NMSettingsConnection *parent_con; + NMActiveConnection * parent_ac; + + parent_con = nm_device_get_best_connection(parent, NULL, error); + if (!parent_con) { + g_prefix_error(error, "%s failed to create parent: ", nm_device_get_iface(device)); + return FALSE; + } + + if (nm_active_connection_get_activation_reason(active) + == NM_ACTIVATION_REASON_AUTOCONNECT + && NM_FLAGS_HAS(nm_settings_connection_autoconnect_blocked_reason_get(parent_con), + NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST)) { + g_set_error(error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_DEPENDENCY_FAILED, + "the parent connection of %s cannot autoactivate because it is blocked " + "due to user request", + nm_device_get_iface(device)); + return FALSE; + } + + parent_ac = nm_manager_activate_connection( + self, + parent_con, + NULL, + NULL, + parent, + subject, + NM_ACTIVATION_TYPE_MANAGED, + nm_active_connection_get_activation_reason(active), + nm_active_connection_get_state_flags(active) + & NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY, + error); + if (!parent_ac) { + g_prefix_error(error, + "%s failed to activate parent: ", + nm_device_get_iface(device)); + return FALSE; + } + + /* We can't realize now; defer until the parent device is ready. */ + g_signal_connect(active, + NM_ACTIVE_CONNECTION_PARENT_ACTIVE, + (GCallback) active_connection_parent_active, + self); + nm_active_connection_set_parent(active, parent_ac); + } else { + /* We can realize now; no need to wait for a parent device. */ + if (!nm_device_create_and_realize(device, + nm_settings_connection_get_connection(sett_conn), + parent, + error)) { + g_prefix_error(error, + "%s failed to create resources: ", + nm_device_get_iface(device)); + return FALSE; + } + } + } + + /* Ensure there's a master active connection the new connection we're + * activating can depend on. + */ + if (master_connection || master_device) { + if (master_connection) { + _LOGD(LOGD_CORE, + "Activation of '%s' requires master connection '%s'", + nm_settings_connection_get_id(sett_conn), + nm_settings_connection_get_id(master_connection)); + } + if (master_device) { + _LOGD(LOGD_CORE, + "Activation of '%s' requires master device '%s'", + nm_settings_connection_get_id(sett_conn), + nm_device_get_ip_iface(master_device)); + } + + /* Ensure eg bond slave and the candidate master is a bond master */ + if (master_connection + && !is_compatible_with_slave(nm_settings_connection_get_connection(master_connection), + applied)) { + g_set_error(error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_DEPENDENCY_FAILED, + "The master connection '%s' is not compatible with '%s'", + nm_settings_connection_get_id(master_connection), + nm_settings_connection_get_id(sett_conn)); + return FALSE; + } + + if (!master_ac) { + master_ac = + ensure_master_active_connection(self, + nm_active_connection_get_subject(active), + applied, + device, + master_connection, + master_device, + nm_active_connection_get_activation_reason(active), + error); + if (!master_ac) { + if (master_device) { + g_prefix_error(error, + "Master device '%s' can't be activated: ", + nm_device_get_ip_iface(device)); + } else { + g_prefix_error(error, + "Master connection '%s' can't be activated: ", + nm_settings_connection_get_id(sett_conn)); + } + return FALSE; + } + } + + /* Now that we're activating a slave for that master, make sure the master just + * decides to go unmanaged while we're activating (perhaps because other slaves + * go away leaving him with no kids). + */ + if (master_device) { + nm_device_set_unmanaged_by_flags(master_device, + NM_UNMANAGED_EXTERNAL_DOWN, + NM_UNMAN_FLAG_OP_FORGET, + NM_DEVICE_STATE_REASON_USER_REQUESTED); + } + + nm_active_connection_set_master(active, master_ac); + _LOGD(LOGD_CORE, + "Activation of '%s' depends on active connection %p %s", + nm_settings_connection_get_id(sett_conn), + master_ac, + nm_dbus_object_get_path(NM_DBUS_OBJECT(master_ac)) ?: ""); + } + + /* Check slaves for master connection and possibly activate them */ + autoconnect_slaves(self, + sett_conn, + device, + nm_active_connection_get_subject(active), + nm_active_connection_get_activation_reason(active) + == NM_ACTIVATION_REASON_USER_REQUEST); + + multi_connect = + _nm_connection_get_multi_connect(nm_settings_connection_get_connection(sett_conn)); + if (multi_connect == NM_CONNECTION_MULTI_CONNECT_MULTIPLE + || (multi_connect == NM_CONNECTION_MULTI_CONNECT_MANUAL_MULTIPLE + && NM_IN_SET(nm_active_connection_get_activation_reason(active), + NM_ACTIVATION_REASON_ASSUME, + NM_ACTIVATION_REASON_AUTOCONNECT_SLAVES, + NM_ACTIVATION_REASON_USER_REQUEST))) { + /* the profile can be activated multiple times. Proceed. */ + } else { + gs_unref_ptrarray GPtrArray *all_ac_arr = NULL; + NMActiveConnection * ac; + guint i, n_all; + + /* Disconnect the connection if already connected or queued for activation. + * The connection cannot be active multiple times (at the same time). */ + ac = active_connection_find(self, + sett_conn, + NULL, + NM_ACTIVE_CONNECTION_STATE_ACTIVATED, + &all_ac_arr); + if (ac) { + n_all = all_ac_arr ? all_ac_arr->len : ((guint) 1); + for (i = 0; i < n_all; i++) { + nm_device_disconnect_active_connection(all_ac_arr ? all_ac_arr->pdata[i] : ac, + NM_DEVICE_STATE_REASON_NEW_ACTIVATION, + NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN); + } + } + } + + /* If the device is there, we can ready it for the activation. */ + if (nm_device_is_real(device)) { + unmanaged_to_disconnected(device); + + if (!nm_device_get_managed(device, FALSE)) { + /* Unexpectedly, the device is still unmanaged. That can happen for example, + * if the device is forcibly unmanaged due to NM_UNMANAGED_USER_SETTINGS. */ + g_set_error_literal(error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_DEPENDENCY_FAILED, + "Activation failed because the device is unmanaged"); + return FALSE; + } + } + + /* Export the new ActiveConnection to clients and start it on the device */ + active_connection_add(self, active); + nm_device_queue_activation(device, NM_ACT_REQUEST(active)); + return TRUE; } static gboolean -_internal_activate_generic (NMManager *self, NMActiveConnection *active, GError **error) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - gboolean success = FALSE; - - /* Ensure activation request is still valid, eg that its device hasn't gone - * away or that some other dependency has not failed. - */ - if (nm_active_connection_get_state (active) >= NM_ACTIVE_CONNECTION_STATE_DEACTIVATING) { - g_set_error_literal (error, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_DEPENDENCY_FAILED, - "Activation failed because dependencies failed."); - return FALSE; - } - - if (NM_IS_VPN_CONNECTION (active)) - success = _internal_activate_vpn (self, active, error); - else - success = _internal_activate_device (self, active, error); - - if (success) { - /* Force an update of the Manager's activating-connection property. - * The device changes state before the AC gets exported, which causes - * the manager's 'activating-connection' property to be NULL since the - * AC only gets a D-Bus path when it's exported. So now that the AC - * is exported, make sure the manager's activating-connection property - * is up-to-date. - */ - policy_activating_ac_changed (G_OBJECT (priv->policy), NULL, self); - } - - return success; +_internal_activate_generic(NMManager *self, NMActiveConnection *active, GError **error) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + gboolean success = FALSE; + + /* Ensure activation request is still valid, eg that its device hasn't gone + * away or that some other dependency has not failed. + */ + if (nm_active_connection_get_state(active) >= NM_ACTIVE_CONNECTION_STATE_DEACTIVATING) { + g_set_error_literal(error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_DEPENDENCY_FAILED, + "Activation failed because dependencies failed."); + return FALSE; + } + + if (NM_IS_VPN_CONNECTION(active)) + success = _internal_activate_vpn(self, active, error); + else + success = _internal_activate_device(self, active, error); + + if (success) { + /* Force an update of the Manager's activating-connection property. + * The device changes state before the AC gets exported, which causes + * the manager's 'activating-connection' property to be NULL since the + * AC only gets a D-Bus path when it's exported. So now that the AC + * is exported, make sure the manager's activating-connection property + * is up-to-date. + */ + policy_activating_ac_changed(G_OBJECT(priv->policy), NULL, self); + } + + return success; } static NMActiveConnection * -_new_active_connection (NMManager *self, - gboolean is_vpn, - NMSettingsConnection *sett_conn, - NMConnection *incompl_conn, - NMConnection *applied, - const char *specific_object, - NMDevice *device, - NMAuthSubject *subject, - NMActivationType activation_type, - NMActivationReason activation_reason, - NMActivationStateFlags initial_state_flags, - GError **error) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *parent_device; - - nm_assert (!sett_conn || NM_IS_SETTINGS_CONNECTION (sett_conn)); - nm_assert (!incompl_conn || NM_IS_CONNECTION (incompl_conn)); - nm_assert ((!incompl_conn) ^ (!sett_conn)); - nm_assert (NM_IS_AUTH_SUBJECT (subject)); - nm_assert (is_vpn == _connection_is_vpn (sett_conn - ? nm_settings_connection_get_connection (sett_conn) - : incompl_conn)); - nm_assert (is_vpn || NM_IS_DEVICE (device)); - nm_assert (!nm_streq0 (specific_object, "/")); - nm_assert (!applied || NM_IS_CONNECTION (applied)); - nm_assert (!is_vpn || !applied); - - if (is_vpn) { - NMActiveConnection *parent; - - /* FIXME: for VPN connections, we don't allow re-activating an - * already active connection. It's a bug, and should be fixed together - * when reworking VPN handling. */ - if (active_connection_find_by_connection (self, - sett_conn, - incompl_conn, - NM_ACTIVE_CONNECTION_STATE_ACTIVATED, - NULL)) { - g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_ALREADY_ACTIVE, - "Connection '%s' is already active", - sett_conn ? nm_settings_connection_get_id (sett_conn) : nm_connection_get_id (incompl_conn)); - return NULL; - } - - if (activation_type != NM_ACTIVATION_TYPE_MANAGED) - g_return_val_if_reached (NULL); - - if (specific_object) { - /* Find the specific connection the client requested we use */ - parent = active_connection_get_by_path (self, specific_object); - if (!parent) { - g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE, - "Base connection for VPN connection not active."); - return NULL; - } - } else - parent = priv->primary_connection; - - if (!parent) { - g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_CONNECTION, - "Could not find source connection."); - return NULL; - } - - parent_device = nm_active_connection_get_device (parent); - if (!parent_device) { - g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, - "Source connection had no active device"); - return NULL; - } - - if (device && device != parent_device) { - g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, - "The device doesn't match the active connection."); - return NULL; - } - - return (NMActiveConnection *) nm_vpn_connection_new (sett_conn, - parent_device, - nm_dbus_object_get_path (NM_DBUS_OBJECT (parent)), - activation_reason, - initial_state_flags, - subject); - } - - return (NMActiveConnection *) nm_act_request_new (sett_conn, - applied, - specific_object, - subject, - activation_type, - activation_reason, - initial_state_flags, - device); +_new_active_connection(NMManager * self, + gboolean is_vpn, + NMSettingsConnection * sett_conn, + NMConnection * incompl_conn, + NMConnection * applied, + const char * specific_object, + NMDevice * device, + NMAuthSubject * subject, + NMActivationType activation_type, + NMActivationReason activation_reason, + NMActivationStateFlags initial_state_flags, + GError ** error) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + NMDevice * parent_device; + + nm_assert(!sett_conn || NM_IS_SETTINGS_CONNECTION(sett_conn)); + nm_assert(!incompl_conn || NM_IS_CONNECTION(incompl_conn)); + nm_assert((!incompl_conn) ^ (!sett_conn)); + nm_assert(NM_IS_AUTH_SUBJECT(subject)); + nm_assert(is_vpn + == _connection_is_vpn(sett_conn ? nm_settings_connection_get_connection(sett_conn) + : incompl_conn)); + nm_assert(is_vpn || NM_IS_DEVICE(device)); + nm_assert(!nm_streq0(specific_object, "/")); + nm_assert(!applied || NM_IS_CONNECTION(applied)); + nm_assert(!is_vpn || !applied); + + if (is_vpn) { + NMActiveConnection *parent; + + /* FIXME: for VPN connections, we don't allow re-activating an + * already active connection. It's a bug, and should be fixed together + * when reworking VPN handling. */ + if (active_connection_find_by_connection(self, + sett_conn, + incompl_conn, + NM_ACTIVE_CONNECTION_STATE_ACTIVATED, + NULL)) { + g_set_error(error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_CONNECTION_ALREADY_ACTIVE, + "Connection '%s' is already active", + sett_conn ? nm_settings_connection_get_id(sett_conn) + : nm_connection_get_id(incompl_conn)); + return NULL; + } + + if (activation_type != NM_ACTIVATION_TYPE_MANAGED) + g_return_val_if_reached(NULL); + + if (specific_object) { + /* Find the specific connection the client requested we use */ + parent = active_connection_get_by_path(self, specific_object); + if (!parent) { + g_set_error_literal(error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE, + "Base connection for VPN connection not active."); + return NULL; + } + } else + parent = priv->primary_connection; + + if (!parent) { + g_set_error_literal(error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_UNKNOWN_CONNECTION, + "Could not find source connection."); + return NULL; + } + + parent_device = nm_active_connection_get_device(parent); + if (!parent_device) { + g_set_error_literal(error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "Source connection had no active device"); + return NULL; + } + + if (device && device != parent_device) { + g_set_error_literal(error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "The device doesn't match the active connection."); + return NULL; + } + + return (NMActiveConnection *) nm_vpn_connection_new( + sett_conn, + parent_device, + nm_dbus_object_get_path(NM_DBUS_OBJECT(parent)), + activation_reason, + initial_state_flags, + subject); + } + + return (NMActiveConnection *) nm_act_request_new(sett_conn, + applied, + specific_object, + subject, + activation_type, + activation_reason, + initial_state_flags, + device); } static void -_internal_activation_auth_done (NMManager *self, - NMActiveConnection *active, - gboolean success, - const char *error_desc) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMActiveConnection *ac; - gs_free_error GError *error = NULL; - - nm_assert (NM_IS_ACTIVE_CONNECTION (active)); - - if (!success) - goto fail; - - /* Don't continue with an autoconnect-activation if a more important activation - * already exists. - * We also check this earlier, but there we may fail to detect a duplicate - * if the existing active connection was undergoing authorization. - */ - if (NM_IN_SET (nm_active_connection_get_activation_reason (active), NM_ACTIVATION_REASON_EXTERNAL, - NM_ACTIVATION_REASON_ASSUME, - NM_ACTIVATION_REASON_AUTOCONNECT)) { - c_list_for_each_entry (ac, &priv->active_connections_lst_head, active_connections_lst) { - if ( nm_active_connection_get_device (ac) == nm_active_connection_get_device (active) - && nm_active_connection_get_settings_connection (ac) == nm_active_connection_get_settings_connection (active) - && nm_active_connection_get_state (ac) <= NM_ACTIVE_CONNECTION_STATE_ACTIVATED) { - g_set_error (&error, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_CONNECTION_ALREADY_ACTIVE, - "Connection '%s' is already active", - nm_active_connection_get_settings_connection_id (active)); - goto fail; - } - } - } - - if (_internal_activate_generic (self, active, &error)) - return; +_internal_activation_auth_done(NMManager * self, + NMActiveConnection *active, + gboolean success, + const char * error_desc) +{ + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + NMActiveConnection *ac; + gs_free_error GError *error = NULL; + + nm_assert(NM_IS_ACTIVE_CONNECTION(active)); + + if (!success) + goto fail; + + /* Don't continue with an autoconnect-activation if a more important activation + * already exists. + * We also check this earlier, but there we may fail to detect a duplicate + * if the existing active connection was undergoing authorization. + */ + if (NM_IN_SET(nm_active_connection_get_activation_reason(active), + NM_ACTIVATION_REASON_EXTERNAL, + NM_ACTIVATION_REASON_ASSUME, + NM_ACTIVATION_REASON_AUTOCONNECT)) { + c_list_for_each_entry (ac, &priv->active_connections_lst_head, active_connections_lst) { + if (nm_active_connection_get_device(ac) == nm_active_connection_get_device(active) + && nm_active_connection_get_settings_connection(ac) + == nm_active_connection_get_settings_connection(active) + && nm_active_connection_get_state(ac) <= NM_ACTIVE_CONNECTION_STATE_ACTIVATED) { + g_set_error(&error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_CONNECTION_ALREADY_ACTIVE, + "Connection '%s' is already active", + nm_active_connection_get_settings_connection_id(active)); + goto fail; + } + } + } + + if (_internal_activate_generic(self, active, &error)) + return; fail: - nm_assert (error_desc || error); - nm_active_connection_set_state_fail (active, - NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN, - error_desc ?: error->message); + nm_assert(error_desc || error); + nm_active_connection_set_state_fail(active, + NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN, + error_desc ?: error->message); } /** @@ -5112,81 +5209,78 @@ fail: * activation of @sett_conn on @device */ NMActiveConnection * -nm_manager_activate_connection (NMManager *self, - NMSettingsConnection *sett_conn, - NMConnection *applied, - const char *specific_object, - NMDevice *device, - NMAuthSubject *subject, - NMActivationType activation_type, - NMActivationReason activation_reason, - NMActivationStateFlags initial_state_flags, - GError **error) -{ - NMManagerPrivate *priv; - NMActiveConnection *active; - AsyncOpData *async_op_data; - gboolean is_vpn; - - g_return_val_if_fail (NM_IS_MANAGER (self), NULL); - g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION (sett_conn), NULL); - is_vpn = _connection_is_vpn (nm_settings_connection_get_connection (sett_conn)); - g_return_val_if_fail (is_vpn || NM_IS_DEVICE (device), NULL); - g_return_val_if_fail (!error || !*error, NULL); - nm_assert (!nm_streq0 (specific_object, "/")); - - priv = NM_MANAGER_GET_PRIVATE (self); - - if (!nm_auth_is_subject_in_acl_set_error (nm_settings_connection_get_connection (sett_conn), - subject, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - error)) - return NULL; - - /* Look for a active connection that's equivalent and is already pending authorization - * and eventual activation. This is used to de-duplicate concurrent activations which would - * otherwise race and cause the device to disconnect and reconnect repeatedly. - * In particular, this allows the master and multiple slaves to concurrently auto-activate - * while all the slaves would use the same active-connection. */ - c_list_for_each_entry (async_op_data, &priv->async_op_lst_head, async_op_lst) { - - if (async_op_data->async_op_type != ASYNC_OP_TYPE_AC_AUTH_ACTIVATE_INTERNAL) - continue; - - active = async_op_data->ac_auth.active; - if ( sett_conn == nm_active_connection_get_settings_connection (active) - && nm_streq0 (nm_active_connection_get_specific_object (active), specific_object) - && (!device || nm_active_connection_get_device (active) == device) - && nm_auth_subject_get_subject_type (nm_active_connection_get_subject (active)) - == NM_AUTH_SUBJECT_TYPE_INTERNAL - && nm_auth_subject_get_subject_type (subject) - == NM_AUTH_SUBJECT_TYPE_INTERNAL - && nm_active_connection_get_activation_reason (active) == activation_reason) - return active; - } - - active = _new_active_connection (self, - is_vpn, - sett_conn, - NULL, - applied, - specific_object, - device, - subject, - activation_type, - activation_reason, - initial_state_flags, - error); - if (!active) - return NULL; - - nm_active_connection_authorize (active, - NULL, - _async_op_complete_ac_auth_cb, - _async_op_data_new_authorize_activate_internal (self, - active)); - return active; +nm_manager_activate_connection(NMManager * self, + NMSettingsConnection * sett_conn, + NMConnection * applied, + const char * specific_object, + NMDevice * device, + NMAuthSubject * subject, + NMActivationType activation_type, + NMActivationReason activation_reason, + NMActivationStateFlags initial_state_flags, + GError ** error) +{ + NMManagerPrivate * priv; + NMActiveConnection *active; + AsyncOpData * async_op_data; + gboolean is_vpn; + + g_return_val_if_fail(NM_IS_MANAGER(self), NULL); + g_return_val_if_fail(NM_IS_SETTINGS_CONNECTION(sett_conn), NULL); + is_vpn = _connection_is_vpn(nm_settings_connection_get_connection(sett_conn)); + g_return_val_if_fail(is_vpn || NM_IS_DEVICE(device), NULL); + g_return_val_if_fail(!error || !*error, NULL); + nm_assert(!nm_streq0(specific_object, "/")); + + priv = NM_MANAGER_GET_PRIVATE(self); + + if (!nm_auth_is_subject_in_acl_set_error(nm_settings_connection_get_connection(sett_conn), + subject, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + error)) + return NULL; + + /* Look for a active connection that's equivalent and is already pending authorization + * and eventual activation. This is used to de-duplicate concurrent activations which would + * otherwise race and cause the device to disconnect and reconnect repeatedly. + * In particular, this allows the master and multiple slaves to concurrently auto-activate + * while all the slaves would use the same active-connection. */ + c_list_for_each_entry (async_op_data, &priv->async_op_lst_head, async_op_lst) { + if (async_op_data->async_op_type != ASYNC_OP_TYPE_AC_AUTH_ACTIVATE_INTERNAL) + continue; + + active = async_op_data->ac_auth.active; + if (sett_conn == nm_active_connection_get_settings_connection(active) + && nm_streq0(nm_active_connection_get_specific_object(active), specific_object) + && (!device || nm_active_connection_get_device(active) == device) + && nm_auth_subject_get_subject_type(nm_active_connection_get_subject(active)) + == NM_AUTH_SUBJECT_TYPE_INTERNAL + && nm_auth_subject_get_subject_type(subject) == NM_AUTH_SUBJECT_TYPE_INTERNAL + && nm_active_connection_get_activation_reason(active) == activation_reason) + return active; + } + + active = _new_active_connection(self, + is_vpn, + sett_conn, + NULL, + applied, + specific_object, + device, + subject, + activation_type, + activation_reason, + initial_state_flags, + error); + if (!active) + return NULL; + + nm_active_connection_authorize(active, + NULL, + _async_op_complete_ac_auth_cb, + _async_op_data_new_authorize_activate_internal(self, active)); + return active; } /** @@ -5212,3222 +5306,3341 @@ nm_manager_activate_connection (NMManager *self, * %NULL on error */ static NMAuthSubject * -validate_activation_request (NMManager *self, - GDBusMethodInvocation *context, - NMSettingsConnection *sett_conn, - NMConnection *connection, - const char *device_path, - NMDevice **out_device, - gboolean *out_is_vpn, - GError **error) -{ - NMDevice *device = NULL; - gboolean is_vpn = FALSE; - gs_unref_object NMAuthSubject *subject = NULL; - - nm_assert (!sett_conn || NM_IS_SETTINGS_CONNECTION (sett_conn)); - nm_assert (!connection || NM_IS_CONNECTION (connection)); - nm_assert (sett_conn || connection); - nm_assert (!connection || !sett_conn || connection == nm_settings_connection_get_connection (sett_conn)); - nm_assert (out_device); - nm_assert (out_is_vpn); - - if (!connection) - connection = nm_settings_connection_get_connection (sett_conn); - - /* Validate the caller */ - subject = nm_dbus_manager_new_auth_subject_from_context (context); - if (!subject) { - g_set_error_literal (error, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - NM_UTILS_ERROR_MSG_REQ_UID_UKNOWN); - return NULL; - } - - if (!nm_auth_is_subject_in_acl_set_error (connection, - subject, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - error)) - return NULL; - - is_vpn = _connection_is_vpn (connection); - - if (*out_device) { - device = *out_device; - nm_assert (NM_IS_DEVICE (device)); - nm_assert (device_path); - nm_assert (nm_streq0 (device_path, nm_dbus_object_get_path (NM_DBUS_OBJECT (device)))); - nm_assert (device == nm_manager_get_device_by_path (self, device_path)); - } else if (device_path) { - device = nm_manager_get_device_by_path (self, device_path); - if (!device) { - g_set_error_literal (error, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_UNKNOWN_DEVICE, - "Device not found"); - return NULL; - } - } else if (!is_vpn) { - gs_free_error GError *local = NULL; - - device = nm_manager_get_best_device_for_connection (self, sett_conn, connection, TRUE, NULL, &local); - if (!device) { - gs_free char *iface = NULL; - - /* VPN and software-device connections don't need a device yet, - * but non-virtual connections do ... */ - if (!nm_connection_is_virtual (connection)) { - g_set_error (error, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_UNKNOWN_DEVICE, - "No suitable device found for this connection (%s).", - local->message); - return NULL; - } - - /* Look for an existing device with the connection's interface name */ - iface = nm_manager_get_connection_iface (self, connection, NULL, NULL, error); - if (!iface) - return NULL; - - device = find_device_by_iface (self, iface, connection, NULL); - if (!device) { - g_set_error_literal (error, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_UNKNOWN_DEVICE, - "Failed to find a compatible device for this connection"); - return NULL; - } - } - } - - nm_assert (is_vpn || NM_IS_DEVICE (device)); - - *out_device = device; - *out_is_vpn = is_vpn; - return g_steal_pointer (&subject); +validate_activation_request(NMManager * self, + GDBusMethodInvocation *context, + NMSettingsConnection * sett_conn, + NMConnection * connection, + const char * device_path, + NMDevice ** out_device, + gboolean * out_is_vpn, + GError ** error) +{ + NMDevice * device = NULL; + gboolean is_vpn = FALSE; + gs_unref_object NMAuthSubject *subject = NULL; + + nm_assert(!sett_conn || NM_IS_SETTINGS_CONNECTION(sett_conn)); + nm_assert(!connection || NM_IS_CONNECTION(connection)); + nm_assert(sett_conn || connection); + nm_assert(!connection || !sett_conn + || connection == nm_settings_connection_get_connection(sett_conn)); + nm_assert(out_device); + nm_assert(out_is_vpn); + + if (!connection) + connection = nm_settings_connection_get_connection(sett_conn); + + /* Validate the caller */ + subject = nm_dbus_manager_new_auth_subject_from_context(context); + if (!subject) { + g_set_error_literal(error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + NM_UTILS_ERROR_MSG_REQ_UID_UKNOWN); + return NULL; + } + + if (!nm_auth_is_subject_in_acl_set_error(connection, + subject, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + error)) + return NULL; + + is_vpn = _connection_is_vpn(connection); + + if (*out_device) { + device = *out_device; + nm_assert(NM_IS_DEVICE(device)); + nm_assert(device_path); + nm_assert(nm_streq0(device_path, nm_dbus_object_get_path(NM_DBUS_OBJECT(device)))); + nm_assert(device == nm_manager_get_device_by_path(self, device_path)); + } else if (device_path) { + device = nm_manager_get_device_by_path(self, device_path); + if (!device) { + g_set_error_literal(error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "Device not found"); + return NULL; + } + } else if (!is_vpn) { + gs_free_error GError *local = NULL; + + device = nm_manager_get_best_device_for_connection(self, + sett_conn, + connection, + TRUE, + NULL, + &local); + if (!device) { + gs_free char *iface = NULL; + + /* VPN and software-device connections don't need a device yet, + * but non-virtual connections do ... */ + if (!nm_connection_is_virtual(connection)) { + g_set_error(error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "No suitable device found for this connection (%s).", + local->message); + return NULL; + } + + /* Look for an existing device with the connection's interface name */ + iface = nm_manager_get_connection_iface(self, connection, NULL, NULL, error); + if (!iface) + return NULL; + + device = find_device_by_iface(self, iface, connection, NULL); + if (!device) { + g_set_error_literal(error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "Failed to find a compatible device for this connection"); + return NULL; + } + } + } + + nm_assert(is_vpn || NM_IS_DEVICE(device)); + + *out_device = device; + *out_is_vpn = is_vpn; + return g_steal_pointer(&subject); } /*****************************************************************************/ static void -_activation_auth_done (NMManager *self, - NMActiveConnection *active, - GDBusMethodInvocation *invocation, - gboolean success, - const char *error_desc) -{ - GError *error = NULL; - NMAuthSubject *subject; - NMSettingsConnection *connection; - - subject = nm_active_connection_get_subject (active); - connection = nm_active_connection_get_settings_connection (active); - - if (!success) { - error = g_error_new_literal (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - error_desc); - goto fail; - } - - if (!_internal_activate_generic (self, active, &error)) - goto fail; - - nm_settings_connection_autoconnect_blocked_reason_set (connection, - NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST, - FALSE); - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(o)", - nm_dbus_object_get_path (NM_DBUS_OBJECT (active)))); - nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ACTIVATE, connection, TRUE, NULL, - subject, NULL); - return; +_activation_auth_done(NMManager * self, + NMActiveConnection * active, + GDBusMethodInvocation *invocation, + gboolean success, + const char * error_desc) +{ + GError * error = NULL; + NMAuthSubject * subject; + NMSettingsConnection *connection; + + subject = nm_active_connection_get_subject(active); + connection = nm_active_connection_get_settings_connection(active); + + if (!success) { + error = + g_error_new_literal(NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED, error_desc); + goto fail; + } + + if (!_internal_activate_generic(self, active, &error)) + goto fail; + + nm_settings_connection_autoconnect_blocked_reason_set( + connection, + NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST, + FALSE); + g_dbus_method_invocation_return_value( + invocation, + g_variant_new("(o)", nm_dbus_object_get_path(NM_DBUS_OBJECT(active)))); + nm_audit_log_connection_op(NM_AUDIT_OP_CONN_ACTIVATE, connection, TRUE, NULL, subject, NULL); + return; fail: - nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ACTIVATE, connection, FALSE, NULL, - subject, error->message); - nm_active_connection_set_state_fail (active, - NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN, - error->message); + nm_audit_log_connection_op(NM_AUDIT_OP_CONN_ACTIVATE, + connection, + FALSE, + NULL, + subject, + error->message); + nm_active_connection_set_state_fail(active, + NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN, + error->message); - g_dbus_method_invocation_take_error (invocation, error); + g_dbus_method_invocation_take_error(invocation, error); } static void -impl_manager_activate_connection (NMDBusObject *obj, - const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended *method_info, - GDBusConnection *dbus_connection, - const char *sender, - GDBusMethodInvocation *invocation, - GVariant *parameters) -{ - NMManager *self = NM_MANAGER (obj); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - gs_unref_object NMActiveConnection *active = NULL; - gs_unref_object NMAuthSubject *subject = NULL; - NMSettingsConnection *sett_conn = NULL; - NMDevice *device = NULL; - gboolean is_vpn = FALSE; - GError *error = NULL; - const char *connection_path; - const char *device_path; - const char *specific_object_path; - - g_variant_get (parameters, "(&o&o&o)", &connection_path, &device_path, &specific_object_path); - - connection_path = nm_dbus_path_not_empty (connection_path); - specific_object_path = nm_dbus_path_not_empty (specific_object_path); - device_path = nm_dbus_path_not_empty (device_path); - - /* If the connection path is given and valid, that connection is activated. - * Otherwise the "best" connection for the device is chosen and activated, - * regardless of whether that connection is autoconnect-enabled or not - * (since this is an explicit request, not an auto-activation request). - */ - if (connection_path) { - sett_conn = nm_settings_get_connection_by_path (priv->settings, connection_path); - if (!sett_conn) { - error = g_error_new_literal (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_UNKNOWN_CONNECTION, - "Connection could not be found."); - goto error; - } - } else { - /* If no connection is given, find a suitable connection for the given device path */ - if (!device_path) { - error = g_error_new_literal (NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, - "Only devices may be activated without a specifying a connection"); - goto error; - } - device = nm_manager_get_device_by_path (self, device_path); - if (!device) { - error = g_error_new (NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, - "Can not activate an unknown device '%s'", device_path); - goto error; - } - - sett_conn = nm_device_get_best_connection (device, specific_object_path, &error); - if (!sett_conn) - goto error; - } - - subject = validate_activation_request (self, - invocation, - sett_conn, - NULL, - device_path, - &device, - &is_vpn, - &error); - if (!subject) - goto error; - - active = _new_active_connection (self, - is_vpn, - sett_conn, - NULL, - NULL, - specific_object_path, - device, - subject, - NM_ACTIVATION_TYPE_MANAGED, - NM_ACTIVATION_REASON_USER_REQUEST, - _activation_bind_lifetime_to_profile_visibility (subject), - &error); - if (!active) - goto error; - - nm_active_connection_authorize (active, - NULL, - _async_op_complete_ac_auth_cb, - _async_op_data_new_ac_auth_activate_user (self, - active, - invocation)); - - /* we passed the pointer on to _async_op_data_new_ac_auth_activate_user() */ - g_steal_pointer (&active); - - return; +impl_manager_activate_connection(NMDBusObject * obj, + const NMDBusInterfaceInfoExtended *interface_info, + const NMDBusMethodInfoExtended * method_info, + GDBusConnection * dbus_connection, + const char * sender, + GDBusMethodInvocation * invocation, + GVariant * parameters) +{ + NMManager * self = NM_MANAGER(obj); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + gs_unref_object NMActiveConnection *active = NULL; + gs_unref_object NMAuthSubject *subject = NULL; + NMSettingsConnection * sett_conn = NULL; + NMDevice * device = NULL; + gboolean is_vpn = FALSE; + GError * error = NULL; + const char * connection_path; + const char * device_path; + const char * specific_object_path; + + g_variant_get(parameters, "(&o&o&o)", &connection_path, &device_path, &specific_object_path); + + connection_path = nm_dbus_path_not_empty(connection_path); + specific_object_path = nm_dbus_path_not_empty(specific_object_path); + device_path = nm_dbus_path_not_empty(device_path); + + /* If the connection path is given and valid, that connection is activated. + * Otherwise, the "best" connection for the device is chosen and activated, + * regardless of whether that connection is autoconnect-enabled or not + * (since this is an explicit request, not an auto-activation request). + */ + if (connection_path) { + sett_conn = nm_settings_get_connection_by_path(priv->settings, connection_path); + if (!sett_conn) { + error = g_error_new_literal(NM_MANAGER_ERROR, + NM_MANAGER_ERROR_UNKNOWN_CONNECTION, + "Connection could not be found."); + goto error; + } + } else { + /* If no connection is given, find a suitable connection for the given device path */ + if (!device_path) { + error = g_error_new_literal( + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "Only devices may be activated without a specifying a connection"); + goto error; + } + device = nm_manager_get_device_by_path(self, device_path); + if (!device) { + error = g_error_new(NM_MANAGER_ERROR, + NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "Can not activate an unknown device '%s'", + device_path); + goto error; + } + + sett_conn = nm_device_get_best_connection(device, specific_object_path, &error); + if (!sett_conn) + goto error; + } + + subject = validate_activation_request(self, + invocation, + sett_conn, + NULL, + device_path, + &device, + &is_vpn, + &error); + if (!subject) + goto error; + + active = _new_active_connection(self, + is_vpn, + sett_conn, + NULL, + NULL, + specific_object_path, + device, + subject, + NM_ACTIVATION_TYPE_MANAGED, + NM_ACTIVATION_REASON_USER_REQUEST, + _activation_bind_lifetime_to_profile_visibility(subject), + &error); + if (!active) + goto error; + + nm_active_connection_authorize( + active, + NULL, + _async_op_complete_ac_auth_cb, + _async_op_data_new_ac_auth_activate_user(self, active, invocation)); + + /* we passed the pointer on to _async_op_data_new_ac_auth_activate_user() */ + g_steal_pointer(&active); + + return; error: - if (sett_conn) { - nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ACTIVATE, sett_conn, FALSE, NULL, - subject, error->message); - } - g_dbus_method_invocation_take_error (invocation, error); + if (sett_conn) { + nm_audit_log_connection_op(NM_AUDIT_OP_CONN_ACTIVATE, + sett_conn, + FALSE, + NULL, + subject, + error->message); + } + g_dbus_method_invocation_take_error(invocation, error); } /*****************************************************************************/ static void -activation_add_done (NMSettings *settings, - NMSettingsConnection *new_connection, - GError *error, - GDBusMethodInvocation *context, - NMAuthSubject *subject, - gpointer user_data) -{ - NMManager *self; - gs_unref_object NMActiveConnection *active = NULL; - gs_free_error GError *local = NULL; - gpointer async_op_type_ptr; - AsyncOpType async_op_type; - GVariant *result_floating; - - nm_utils_user_data_unpack (user_data, &self, &active, &async_op_type_ptr); - async_op_type = GPOINTER_TO_INT (async_op_type_ptr); - - if (error) - goto fail; - - nm_active_connection_set_settings_connection (active, new_connection); - - if (!_internal_activate_generic (self, active, &local)) - goto fail; - - if (async_op_type == ASYNC_OP_TYPE_AC_AUTH_ADD_AND_ACTIVATE) { - result_floating = g_variant_new ("(oo)", - nm_dbus_object_get_path (NM_DBUS_OBJECT (new_connection)), - nm_dbus_object_get_path (NM_DBUS_OBJECT (active))); - } else { - result_floating = g_variant_new ("(oo@a{sv})", - nm_dbus_object_get_path (NM_DBUS_OBJECT (new_connection)), - nm_dbus_object_get_path (NM_DBUS_OBJECT (active)), - g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0)); - } - g_dbus_method_invocation_return_value (context, result_floating); - - nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD_ACTIVATE, - nm_active_connection_get_settings_connection (active), - TRUE, - NULL, - nm_active_connection_get_subject (active), - NULL); - return; +activation_add_done(NMSettings * settings, + NMSettingsConnection * new_connection, + GError * error, + GDBusMethodInvocation *context, + NMAuthSubject * subject, + gpointer user_data) +{ + NMManager * self; + gs_unref_object NMActiveConnection *active = NULL; + gs_free_error GError *local = NULL; + gpointer async_op_type_ptr; + AsyncOpType async_op_type; + GVariant * result_floating; + + nm_utils_user_data_unpack(user_data, &self, &active, &async_op_type_ptr); + async_op_type = GPOINTER_TO_INT(async_op_type_ptr); + + if (error) + goto fail; + + nm_active_connection_set_settings_connection(active, new_connection); + + if (!_internal_activate_generic(self, active, &local)) + goto fail; + + if (async_op_type == ASYNC_OP_TYPE_AC_AUTH_ADD_AND_ACTIVATE) { + result_floating = g_variant_new("(oo)", + nm_dbus_object_get_path(NM_DBUS_OBJECT(new_connection)), + nm_dbus_object_get_path(NM_DBUS_OBJECT(active))); + } else { + result_floating = g_variant_new("(oo@a{sv})", + nm_dbus_object_get_path(NM_DBUS_OBJECT(new_connection)), + nm_dbus_object_get_path(NM_DBUS_OBJECT(active)), + g_variant_new_array(G_VARIANT_TYPE("{sv}"), NULL, 0)); + } + g_dbus_method_invocation_return_value(context, result_floating); + + nm_audit_log_connection_op(NM_AUDIT_OP_CONN_ADD_ACTIVATE, + nm_active_connection_get_settings_connection(active), + TRUE, + NULL, + nm_active_connection_get_subject(active), + NULL); + return; fail: - if (local) { - nm_assert (!error); - error = local; - } else - nm_assert (error); - - nm_active_connection_set_state_fail (active, - NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN, - error->message); - if (new_connection) - nm_settings_connection_delete (new_connection, FALSE); - g_dbus_method_invocation_return_gerror (context, error); - nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD_ACTIVATE, - NULL, - FALSE, - NULL, - nm_active_connection_get_subject (active), - error->message); + if (local) { + nm_assert(!error); + error = local; + } else + nm_assert(error); + + nm_active_connection_set_state_fail(active, + NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN, + error->message); + if (new_connection) + nm_settings_connection_delete(new_connection, FALSE); + g_dbus_method_invocation_return_gerror(context, error); + nm_audit_log_connection_op(NM_AUDIT_OP_CONN_ADD_ACTIVATE, + NULL, + FALSE, + NULL, + nm_active_connection_get_subject(active), + error->message); } static void -_add_and_activate_auth_done (NMManager *self, - AsyncOpType async_op_type, - NMActiveConnection *active, - NMConnection *connection, - GDBusMethodInvocation *invocation, - NMSettingsConnectionPersistMode persist_mode, - gboolean is_volatile, - gboolean success, - const char *error_desc) -{ - NMManagerPrivate *priv; - GError *error = NULL; - - if (!success) { - error = g_error_new_literal (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - error_desc); - nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD_ACTIVATE, - NULL, - FALSE, - NULL, - nm_active_connection_get_subject (active), - error->message); - g_dbus_method_invocation_take_error (invocation, error); - return; - } - - priv = NM_MANAGER_GET_PRIVATE (self); - - /* FIXME(shutdown): nm_settings_add_connection_dbus() cannot be cancelled. It should be made - * cancellable and tracked via AsyncOpData to be able to do a clean - * shutdown. */ - nm_settings_add_connection_dbus (priv->settings, - connection, - persist_mode, - NM_SETTINGS_CONNECTION_ADD_REASON_NONE, - ( is_volatile - ? NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE - : NM_SETTINGS_CONNECTION_INT_FLAGS_NONE), - nm_active_connection_get_subject (active), - invocation, - activation_add_done, - nm_utils_user_data_pack (self, - g_object_ref (active), - GINT_TO_POINTER (async_op_type))); +_add_and_activate_auth_done(NMManager * self, + AsyncOpType async_op_type, + NMActiveConnection * active, + NMConnection * connection, + GDBusMethodInvocation * invocation, + NMSettingsConnectionPersistMode persist_mode, + gboolean is_volatile, + gboolean success, + const char * error_desc) +{ + NMManagerPrivate *priv; + GError * error = NULL; + + if (!success) { + error = + g_error_new_literal(NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED, error_desc); + nm_audit_log_connection_op(NM_AUDIT_OP_CONN_ADD_ACTIVATE, + NULL, + FALSE, + NULL, + nm_active_connection_get_subject(active), + error->message); + g_dbus_method_invocation_take_error(invocation, error); + return; + } + + priv = NM_MANAGER_GET_PRIVATE(self); + + /* FIXME(shutdown): nm_settings_add_connection_dbus() cannot be cancelled. It should be made + * cancellable and tracked via AsyncOpData to be able to do a clean + * shutdown. */ + nm_settings_add_connection_dbus( + priv->settings, + connection, + persist_mode, + NM_SETTINGS_CONNECTION_ADD_REASON_NONE, + (is_volatile ? NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE + : NM_SETTINGS_CONNECTION_INT_FLAGS_NONE), + nm_active_connection_get_subject(active), + invocation, + activation_add_done, + nm_utils_user_data_pack(self, g_object_ref(active), GINT_TO_POINTER(async_op_type))); } static void -impl_manager_add_and_activate_connection (NMDBusObject *obj, - const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended *method_info, - GDBusConnection *dbus_connection, - const char *sender, - GDBusMethodInvocation *invocation, - GVariant *parameters) -{ - NMManager *self = NM_MANAGER (obj); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - gs_unref_object NMConnection *incompl_conn = NULL; - gs_unref_object NMActiveConnection *active = NULL; - gs_unref_object NMAuthSubject *subject = NULL; - GError *error = NULL; - NMDevice *device = NULL; - gboolean is_vpn = FALSE; - gs_unref_variant GVariant *settings = NULL; - gs_unref_variant GVariant *options = NULL; - const char *device_path; - const char *specific_object_path; - gs_free NMConnection **conns = NULL; - NMSettingsConnectionPersistMode persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_TO_DISK; - gboolean is_volatile = FALSE; - gboolean bind_dbus_client = FALSE; - AsyncOpType async_op_type; - - if (nm_streq (method_info->parent.name, "AddAndActivateConnection2")) { - async_op_type = ASYNC_OP_TYPE_AC_AUTH_ADD_AND_ACTIVATE2; - g_variant_get (parameters, "(@a{sa{sv}}&o&o@a{sv})", &settings, &device_path, &specific_object_path, &options); - } else { - nm_assert (nm_streq (method_info->parent.name, "AddAndActivateConnection")); - async_op_type = ASYNC_OP_TYPE_AC_AUTH_ADD_AND_ACTIVATE; - g_variant_get (parameters, "(@a{sa{sv}}&o&o)", &settings, &device_path, &specific_object_path); - } - - if (options) { - GVariantIter iter; - const char *option_name; - GVariant *option_value; - - g_variant_iter_init (&iter, options); - while (g_variant_iter_next (&iter, "{&sv}", &option_name, &option_value)) { - gs_unref_variant GVariant *option_value_free = NULL; - const char *s; - - option_value_free = option_value; - - if ( nm_streq (option_name, "persist") - && g_variant_is_of_type (option_value, G_VARIANT_TYPE_STRING)) { - s = g_variant_get_string (option_value, NULL); - - is_volatile = FALSE; - persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_TO_DISK; - - if (nm_streq (s, "volatile")) { - persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY; - is_volatile = TRUE; - } else if (nm_streq (s, "memory")) - persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY; - else if (nm_streq (s, "disk")) { - /* pass */ - } else { - error = g_error_new_literal (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_INVALID_ARGUMENTS, - "Option \"persist\" must be one of \"volatile\", \"memory\" or \"disk\""); - goto error; - } - } else if ( nm_streq (option_name, "bind-activation") - && g_variant_is_of_type (option_value, G_VARIANT_TYPE_STRING)) { - s = g_variant_get_string (option_value, NULL); - - if (nm_streq (s, "dbus-client")) - bind_dbus_client = TRUE; - else if (nm_streq (s, "none")) - bind_dbus_client = FALSE; - else { - error = g_error_new_literal (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_INVALID_ARGUMENTS, - "Option \"bind-activation\" must be one of \"dbus-client\" or \"none\""); - goto error; - } - } else { - error = g_error_new_literal (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_INVALID_ARGUMENTS, - "Unknown extra option passed"); - goto error; - } - } - } - - specific_object_path = nm_dbus_path_not_empty (specific_object_path); - device_path = nm_dbus_path_not_empty (device_path); - - /* Try to create a new connection with the given settings. - * We allow empty settings for AddAndActivateConnection(). In that case, - * the connection will be completed in nm_utils_complete_generic() or - * nm_device_complete_connection() below. Just make sure we don't expect - * specific data being in the connection till then (especially in - * validate_activation_request()). - */ - incompl_conn = nm_simple_connection_new (); - if (settings && g_variant_n_children (settings)) - _nm_connection_replace_settings (incompl_conn, settings, NM_SETTING_PARSE_FLAGS_STRICT, NULL); - - subject = validate_activation_request (self, - invocation, - NULL, - incompl_conn, - device_path, - &device, - &is_vpn, - &error); - if (!subject) - goto error; - - if (is_vpn) { - /* Try to fill the VPN's connection setting and name at least */ - if (!nm_connection_get_setting_vpn (incompl_conn)) { - error = g_error_new_literal (NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_SETTING, - "VPN connections require a 'vpn' setting"); - g_prefix_error (&error, "%s: ", NM_SETTING_VPN_SETTING_NAME); - goto error; - } - - conns = nm_settings_connections_array_to_connections (nm_settings_get_connections (priv->settings, NULL), -1); - - nm_utils_complete_generic (priv->platform, - incompl_conn, - NM_SETTING_VPN_SETTING_NAME, - conns, - NULL, - _("VPN connection"), - NULL, - NULL, - FALSE); /* No IPv6 by default for now */ - } else { - conns = nm_settings_connections_array_to_connections (nm_settings_get_connections (priv->settings, NULL), -1); - /* Let each device subclass complete the connection */ - if (!nm_device_complete_connection (device, - incompl_conn, - specific_object_path, - conns, - &error)) - goto error; - } - - nm_assert (_nm_connection_verify (incompl_conn, NULL) == NM_SETTING_VERIFY_SUCCESS); - - active = _new_active_connection (self, - is_vpn, - NULL, - incompl_conn, - NULL, - specific_object_path, - device, - subject, - NM_ACTIVATION_TYPE_MANAGED, - NM_ACTIVATION_REASON_USER_REQUEST, - _activation_bind_lifetime_to_profile_visibility (subject), - &error); - if (!active) - goto error; - - if (bind_dbus_client) { - NMKeepAlive *keep_alive; - - keep_alive = nm_active_connection_get_keep_alive (active); - nm_keep_alive_set_dbus_client_watch (keep_alive, dbus_connection, sender); - nm_keep_alive_arm (keep_alive); - } - - nm_active_connection_authorize (active, - incompl_conn, - _async_op_complete_ac_auth_cb, - _async_op_data_new_ac_auth_add_and_activate (self, - async_op_type, - active, - invocation, - incompl_conn, - persist_mode, - is_volatile)); - - /* we passed the pointers on to _async_op_data_new_ac_auth_add_and_activate() */ - g_steal_pointer (&incompl_conn); - g_steal_pointer (&active); - return; +impl_manager_add_and_activate_connection(NMDBusObject * obj, + const NMDBusInterfaceInfoExtended *interface_info, + const NMDBusMethodInfoExtended * method_info, + GDBusConnection * dbus_connection, + const char * sender, + GDBusMethodInvocation * invocation, + GVariant * parameters) +{ + NMManager * self = NM_MANAGER(obj); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + gs_unref_object NMConnection *incompl_conn = NULL; + gs_unref_object NMActiveConnection *active = NULL; + gs_unref_object NMAuthSubject *subject = NULL; + GError * error = NULL; + NMDevice * device = NULL; + gboolean is_vpn = FALSE; + gs_unref_variant GVariant *settings = NULL; + gs_unref_variant GVariant *options = NULL; + const char * device_path; + const char * specific_object_path; + gs_free NMConnection ** conns = NULL; + NMSettingsConnectionPersistMode persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_TO_DISK; + gboolean is_volatile = FALSE; + gboolean bind_dbus_client = FALSE; + AsyncOpType async_op_type; + + if (nm_streq(method_info->parent.name, "AddAndActivateConnection2")) { + async_op_type = ASYNC_OP_TYPE_AC_AUTH_ADD_AND_ACTIVATE2; + g_variant_get(parameters, + "(@a{sa{sv}}&o&o@a{sv})", + &settings, + &device_path, + &specific_object_path, + &options); + } else { + nm_assert(nm_streq(method_info->parent.name, "AddAndActivateConnection")); + async_op_type = ASYNC_OP_TYPE_AC_AUTH_ADD_AND_ACTIVATE; + g_variant_get(parameters, + "(@a{sa{sv}}&o&o)", + &settings, + &device_path, + &specific_object_path); + } + + if (options) { + GVariantIter iter; + const char * option_name; + GVariant * option_value; + + g_variant_iter_init(&iter, options); + while (g_variant_iter_next(&iter, "{&sv}", &option_name, &option_value)) { + gs_unref_variant GVariant *option_value_free = NULL; + const char * s; + + option_value_free = option_value; + + if (nm_streq(option_name, "persist") + && g_variant_is_of_type(option_value, G_VARIANT_TYPE_STRING)) { + s = g_variant_get_string(option_value, NULL); + + is_volatile = FALSE; + persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_TO_DISK; + + if (nm_streq(s, "volatile")) { + persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY; + is_volatile = TRUE; + } else if (nm_streq(s, "memory")) + persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY; + else if (nm_streq(s, "disk")) { + /* pass */ + } else { + error = g_error_new_literal( + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_INVALID_ARGUMENTS, + "Option \"persist\" must be one of \"volatile\", \"memory\" or \"disk\""); + goto error; + } + } else if (nm_streq(option_name, "bind-activation") + && g_variant_is_of_type(option_value, G_VARIANT_TYPE_STRING)) { + s = g_variant_get_string(option_value, NULL); + + if (nm_streq(s, "dbus-client")) + bind_dbus_client = TRUE; + else if (nm_streq(s, "none")) + bind_dbus_client = FALSE; + else { + error = g_error_new_literal( + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_INVALID_ARGUMENTS, + "Option \"bind-activation\" must be one of \"dbus-client\" or \"none\""); + goto error; + } + } else { + error = g_error_new_literal(NM_MANAGER_ERROR, + NM_MANAGER_ERROR_INVALID_ARGUMENTS, + "Unknown extra option passed"); + goto error; + } + } + } + + specific_object_path = nm_dbus_path_not_empty(specific_object_path); + device_path = nm_dbus_path_not_empty(device_path); + + /* Try to create a new connection with the given settings. + * We allow empty settings for AddAndActivateConnection(). In that case, + * the connection will be completed in nm_utils_complete_generic() or + * nm_device_complete_connection() below. Just make sure we don't expect + * specific data being in the connection till then (especially in + * validate_activation_request()). + */ + incompl_conn = nm_simple_connection_new(); + if (settings && g_variant_n_children(settings)) + _nm_connection_replace_settings(incompl_conn, + settings, + NM_SETTING_PARSE_FLAGS_STRICT, + NULL); + + subject = validate_activation_request(self, + invocation, + NULL, + incompl_conn, + device_path, + &device, + &is_vpn, + &error); + if (!subject) + goto error; + + if (is_vpn) { + /* Try to fill the VPN's connection setting and name at least */ + if (!nm_connection_get_setting_vpn(incompl_conn)) { + error = g_error_new_literal(NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING, + "VPN connections require a 'vpn' setting"); + g_prefix_error(&error, "%s: ", NM_SETTING_VPN_SETTING_NAME); + goto error; + } + + conns = nm_settings_connections_array_to_connections( + nm_settings_get_connections(priv->settings, NULL), + -1); + + nm_utils_complete_generic(priv->platform, + incompl_conn, + NM_SETTING_VPN_SETTING_NAME, + conns, + NULL, + _("VPN connection"), + NULL, + NULL, + FALSE); /* No IPv6 by default for now */ + } else { + conns = nm_settings_connections_array_to_connections( + nm_settings_get_connections(priv->settings, NULL), + -1); + /* Let each device subclass complete the connection */ + if (!nm_device_complete_connection(device, + incompl_conn, + specific_object_path, + conns, + &error)) + goto error; + } + + nm_assert(_nm_connection_verify(incompl_conn, NULL) == NM_SETTING_VERIFY_SUCCESS); + + active = _new_active_connection(self, + is_vpn, + NULL, + incompl_conn, + NULL, + specific_object_path, + device, + subject, + NM_ACTIVATION_TYPE_MANAGED, + NM_ACTIVATION_REASON_USER_REQUEST, + _activation_bind_lifetime_to_profile_visibility(subject), + &error); + if (!active) + goto error; + + if (bind_dbus_client) { + NMKeepAlive *keep_alive; + + keep_alive = nm_active_connection_get_keep_alive(active); + nm_keep_alive_set_dbus_client_watch(keep_alive, dbus_connection, sender); + nm_keep_alive_arm(keep_alive); + } + + nm_active_connection_authorize(active, + incompl_conn, + _async_op_complete_ac_auth_cb, + _async_op_data_new_ac_auth_add_and_activate(self, + async_op_type, + active, + invocation, + incompl_conn, + persist_mode, + is_volatile)); + + /* we passed the pointers on to _async_op_data_new_ac_auth_add_and_activate() */ + g_steal_pointer(&incompl_conn); + g_steal_pointer(&active); + return; error: - nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD_ACTIVATE, NULL, FALSE, NULL, subject, error->message); - g_dbus_method_invocation_take_error (invocation, error); + nm_audit_log_connection_op(NM_AUDIT_OP_CONN_ADD_ACTIVATE, + NULL, + FALSE, + NULL, + subject, + error->message); + g_dbus_method_invocation_take_error(invocation, error); } /*****************************************************************************/ gboolean -nm_manager_deactivate_connection (NMManager *manager, - NMActiveConnection *active, - NMDeviceStateReason reason, - GError **error) -{ - if (NM_IS_VPN_CONNECTION (active)) { - NMActiveConnectionStateReason vpn_reason = NM_ACTIVE_CONNECTION_STATE_REASON_USER_DISCONNECTED; - - if (nm_device_state_reason_check (reason) == NM_DEVICE_STATE_REASON_CONNECTION_REMOVED) - vpn_reason = NM_ACTIVE_CONNECTION_STATE_REASON_CONNECTION_REMOVED; - - if (!nm_vpn_connection_deactivate (NM_VPN_CONNECTION (active), vpn_reason, FALSE)) { - g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE, - "The VPN connection was not active."); - return FALSE; - } - } else { - nm_assert (NM_IS_ACT_REQUEST (active)); - nm_device_disconnect_active_connection (active, - reason, - NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN); - } - - _notify (manager, PROP_ACTIVE_CONNECTIONS); - return TRUE; +nm_manager_deactivate_connection(NMManager * manager, + NMActiveConnection *active, + NMDeviceStateReason reason, + GError ** error) +{ + if (NM_IS_VPN_CONNECTION(active)) { + NMActiveConnectionStateReason vpn_reason = + NM_ACTIVE_CONNECTION_STATE_REASON_USER_DISCONNECTED; + + if (nm_device_state_reason_check(reason) == NM_DEVICE_STATE_REASON_CONNECTION_REMOVED) + vpn_reason = NM_ACTIVE_CONNECTION_STATE_REASON_CONNECTION_REMOVED; + + if (!nm_vpn_connection_deactivate(NM_VPN_CONNECTION(active), vpn_reason, FALSE)) { + g_set_error_literal(error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE, + "The VPN connection was not active."); + return FALSE; + } + } else { + nm_assert(NM_IS_ACT_REQUEST(active)); + nm_device_disconnect_active_connection(active, + reason, + NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN); + } + + _notify(manager, PROP_ACTIVE_CONNECTIONS); + return TRUE; } static void -deactivate_net_auth_done_cb (NMAuthChain *chain, - GDBusMethodInvocation *context, - gpointer user_data) -{ - NMManager *self = NM_MANAGER (user_data); - GError *error = NULL; - NMAuthCallResult result; - NMActiveConnection *active; - char *path; - - nm_assert (G_IS_DBUS_METHOD_INVOCATION (context)); - - c_list_unlink (nm_auth_chain_parent_lst_list (chain)); - - path = nm_auth_chain_get_data (chain, "path"); - result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL); - active = active_connection_get_by_path (self, path); - - if (result != NM_AUTH_CALL_RESULT_YES) { - error = g_error_new_literal (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - "Not authorized to deactivate connections"); - } else if (!active) { - error = g_error_new_literal (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE, - "The connection was not active."); - } else { - /* success; deactivation allowed */ - if (!nm_manager_deactivate_connection (self, - active, - NM_DEVICE_STATE_REASON_USER_REQUESTED, - &error)) - nm_assert (error); - } - - if (active) { - nm_audit_log_connection_op (NM_AUDIT_OP_CONN_DEACTIVATE, - nm_active_connection_get_settings_connection (active), - !error, - NULL, - nm_auth_chain_get_subject (chain), - error ? error->message : NULL); - } - - if (error) - g_dbus_method_invocation_take_error (context, error); - else - g_dbus_method_invocation_return_value (context, NULL); +deactivate_net_auth_done_cb(NMAuthChain *chain, GDBusMethodInvocation *context, gpointer user_data) +{ + NMManager * self = NM_MANAGER(user_data); + GError * error = NULL; + NMAuthCallResult result; + NMActiveConnection *active; + char * path; + + nm_assert(G_IS_DBUS_METHOD_INVOCATION(context)); + + c_list_unlink(nm_auth_chain_parent_lst_list(chain)); + + path = nm_auth_chain_get_data(chain, "path"); + result = nm_auth_chain_get_result(chain, NM_AUTH_PERMISSION_NETWORK_CONTROL); + active = active_connection_get_by_path(self, path); + + if (result != NM_AUTH_CALL_RESULT_YES) { + error = g_error_new_literal(NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + "Not authorized to deactivate connections"); + } else if (!active) { + error = g_error_new_literal(NM_MANAGER_ERROR, + NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE, + "The connection was not active."); + } else { + /* success; deactivation allowed */ + if (!nm_manager_deactivate_connection(self, + active, + NM_DEVICE_STATE_REASON_USER_REQUESTED, + &error)) + nm_assert(error); + } + + if (active) { + nm_audit_log_connection_op(NM_AUDIT_OP_CONN_DEACTIVATE, + nm_active_connection_get_settings_connection(active), + !error, + NULL, + nm_auth_chain_get_subject(chain), + error ? error->message : NULL); + } + + if (error) + g_dbus_method_invocation_take_error(context, error); + else + g_dbus_method_invocation_return_value(context, NULL); } static void -impl_manager_deactivate_connection (NMDBusObject *obj, - const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended *method_info, - GDBusConnection *dbus_connection, - const char *sender, - GDBusMethodInvocation *invocation, - GVariant *parameters) -{ - NMManager *self = NM_MANAGER (obj); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMActiveConnection *ac; - NMSettingsConnection *sett_conn = NULL; - GError *error = NULL; - NMAuthSubject *subject = NULL; - NMAuthChain *chain; - const char *active_path; - - g_variant_get (parameters, "(&o)", &active_path); - - /* Find the connection by its object path */ - ac = active_connection_get_by_path (self, active_path); - if (ac) - sett_conn = nm_active_connection_get_settings_connection (ac); - - if (!sett_conn) { - error = g_error_new_literal (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE, - "The connection was not active."); - goto done; - } - - /* Validate the caller */ - subject = nm_dbus_manager_new_auth_subject_from_context (invocation); - if (!subject) { - error = g_error_new_literal (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - NM_UTILS_ERROR_MSG_REQ_UID_UKNOWN); - goto done; - } - - if (!nm_auth_is_subject_in_acl_set_error (nm_settings_connection_get_connection (sett_conn), - subject, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - &error)) - goto done; - - /* Validate the user request */ - chain = nm_auth_chain_new_subject (subject, invocation, deactivate_net_auth_done_cb, self); - if (!chain) { - error = g_error_new_literal (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - NM_UTILS_ERROR_MSG_REQ_AUTH_FAILED); - goto done; - } - - c_list_link_tail (&priv->auth_lst_head, nm_auth_chain_parent_lst_list (chain)); - nm_auth_chain_set_data (chain, "path", g_strdup (active_path), g_free); - nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE); +impl_manager_deactivate_connection(NMDBusObject * obj, + const NMDBusInterfaceInfoExtended *interface_info, + const NMDBusMethodInfoExtended * method_info, + GDBusConnection * dbus_connection, + const char * sender, + GDBusMethodInvocation * invocation, + GVariant * parameters) +{ + NMManager * self = NM_MANAGER(obj); + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + NMActiveConnection * ac; + NMSettingsConnection *sett_conn = NULL; + GError * error = NULL; + NMAuthSubject * subject = NULL; + NMAuthChain * chain; + const char * active_path; + + g_variant_get(parameters, "(&o)", &active_path); + + /* Find the connection by its object path */ + ac = active_connection_get_by_path(self, active_path); + if (ac) + sett_conn = nm_active_connection_get_settings_connection(ac); + + if (!sett_conn) { + error = g_error_new_literal(NM_MANAGER_ERROR, + NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE, + "The connection was not active."); + goto done; + } + + /* Validate the caller */ + subject = nm_dbus_manager_new_auth_subject_from_context(invocation); + if (!subject) { + error = g_error_new_literal(NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + NM_UTILS_ERROR_MSG_REQ_UID_UKNOWN); + goto done; + } + + if (!nm_auth_is_subject_in_acl_set_error(nm_settings_connection_get_connection(sett_conn), + subject, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + &error)) + goto done; + + /* Validate the user request */ + chain = nm_auth_chain_new_subject(subject, invocation, deactivate_net_auth_done_cb, self); + if (!chain) { + error = g_error_new_literal(NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + NM_UTILS_ERROR_MSG_REQ_AUTH_FAILED); + goto done; + } + + c_list_link_tail(&priv->auth_lst_head, nm_auth_chain_parent_lst_list(chain)); + nm_auth_chain_set_data(chain, "path", g_strdup(active_path), g_free); + nm_auth_chain_add_call(chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE); done: - if (error) { - if (sett_conn) { - nm_audit_log_connection_op (NM_AUDIT_OP_CONN_DEACTIVATE, - sett_conn, FALSE, NULL, - subject, error->message); - } - g_dbus_method_invocation_take_error (invocation, error); - } - g_clear_object (&subject); + if (error) { + if (sett_conn) { + nm_audit_log_connection_op(NM_AUDIT_OP_CONN_DEACTIVATE, + sett_conn, + FALSE, + NULL, + subject, + error->message); + } + g_dbus_method_invocation_take_error(invocation, error); + } + g_clear_object(&subject); } static gboolean -sleep_devices_add (NMManager *self, NMDevice *device, gboolean suspending) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMSleepMonitorInhibitorHandle *handle = NULL; - - if (g_hash_table_lookup_extended (priv->sleep_devices, device, NULL, (gpointer *) &handle)) { - if (suspending) { - /* if we are suspending, always insert a new handle in sleep_devices. - * Even if we had an old handle, it might be stale by now. */ - g_hash_table_insert (priv->sleep_devices, device, - nm_sleep_monitor_inhibit_take (priv->sleep_monitor)); - if (handle) - nm_sleep_monitor_inhibit_release (priv->sleep_monitor, handle); - } - return FALSE; - } - - g_hash_table_insert (priv->sleep_devices, - g_object_ref (device), - suspending - ? nm_sleep_monitor_inhibit_take (priv->sleep_monitor) - : NULL); - g_signal_connect (device, "notify::" NM_DEVICE_STATE, (GCallback) device_sleep_cb, self); - return TRUE; +sleep_devices_add(NMManager *self, NMDevice *device, gboolean suspending) +{ + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + NMSleepMonitorInhibitorHandle *handle = NULL; + + if (g_hash_table_lookup_extended(priv->sleep_devices, device, NULL, (gpointer *) &handle)) { + if (suspending) { + /* if we are suspending, always insert a new handle in sleep_devices. + * Even if we had an old handle, it might be stale by now. */ + g_hash_table_insert(priv->sleep_devices, + device, + nm_sleep_monitor_inhibit_take(priv->sleep_monitor)); + if (handle) + nm_sleep_monitor_inhibit_release(priv->sleep_monitor, handle); + } + return FALSE; + } + + g_hash_table_insert(priv->sleep_devices, + g_object_ref(device), + suspending ? nm_sleep_monitor_inhibit_take(priv->sleep_monitor) : NULL); + g_signal_connect(device, "notify::" NM_DEVICE_STATE, (GCallback) device_sleep_cb, self); + return TRUE; } static gboolean -sleep_devices_remove (NMManager *self, NMDevice *device) +sleep_devices_remove(NMManager *self, NMDevice *device) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMSleepMonitorInhibitorHandle *handle; + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + NMSleepMonitorInhibitorHandle *handle; - if (!g_hash_table_lookup_extended (priv->sleep_devices, device, NULL, (gpointer *) &handle)) - return FALSE; + if (!g_hash_table_lookup_extended(priv->sleep_devices, device, NULL, (gpointer *) &handle)) + return FALSE; - if (handle) - nm_sleep_monitor_inhibit_release (priv->sleep_monitor, handle); + if (handle) + nm_sleep_monitor_inhibit_release(priv->sleep_monitor, handle); - /* Remove device from hash */ - g_signal_handlers_disconnect_by_func (device, device_sleep_cb, self); - g_hash_table_remove (priv->sleep_devices, device); - g_object_unref (device); - return TRUE; + /* Remove device from hash */ + g_signal_handlers_disconnect_by_func(device, device_sleep_cb, self); + g_hash_table_remove(priv->sleep_devices, device); + g_object_unref(device); + return TRUE; } static void -sleep_devices_clear (NMManager *self) +sleep_devices_clear(NMManager *self) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device; - NMSleepMonitorInhibitorHandle *handle; - GHashTableIter iter; + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + NMDevice * device; + NMSleepMonitorInhibitorHandle *handle; + GHashTableIter iter; - if (!priv->sleep_devices) - return; + if (!priv->sleep_devices) + return; - g_hash_table_iter_init (&iter, priv->sleep_devices); - while (g_hash_table_iter_next (&iter, (gpointer *) &device, (gpointer *) &handle)) { - g_signal_handlers_disconnect_by_func (device, device_sleep_cb, self); - if (handle) - nm_sleep_monitor_inhibit_release (priv->sleep_monitor, handle); - g_object_unref (device); - g_hash_table_iter_remove (&iter); - } + g_hash_table_iter_init(&iter, priv->sleep_devices); + while (g_hash_table_iter_next(&iter, (gpointer *) &device, (gpointer *) &handle)) { + g_signal_handlers_disconnect_by_func(device, device_sleep_cb, self); + if (handle) + nm_sleep_monitor_inhibit_release(priv->sleep_monitor, handle); + g_object_unref(device); + g_hash_table_iter_remove(&iter); + } } static void -device_sleep_cb (NMDevice *device, - GParamSpec *pspec, - NMManager *self) -{ - switch (nm_device_get_state (device)) { - case NM_DEVICE_STATE_DISCONNECTED: - _LOGD (LOGD_SUSPEND, "sleep: unmanaging device %s", nm_device_get_ip_iface (device)); - nm_device_set_unmanaged_by_flags_queue (device, - NM_UNMANAGED_SLEEPING, - TRUE, - NM_DEVICE_STATE_REASON_SLEEPING); - break; - case NM_DEVICE_STATE_UNMANAGED: - _LOGD (LOGD_SUSPEND, "sleep: device %s is ready", nm_device_get_ip_iface (device)); - - if (!sleep_devices_remove (self, device)) - g_return_if_reached (); - - break; - default: - return; - } +device_sleep_cb(NMDevice *device, GParamSpec *pspec, NMManager *self) +{ + switch (nm_device_get_state(device)) { + case NM_DEVICE_STATE_DISCONNECTED: + _LOGD(LOGD_SUSPEND, "sleep: unmanaging device %s", nm_device_get_ip_iface(device)); + nm_device_set_unmanaged_by_flags_queue(device, + NM_UNMANAGED_SLEEPING, + TRUE, + NM_DEVICE_STATE_REASON_SLEEPING); + break; + case NM_DEVICE_STATE_UNMANAGED: + _LOGD(LOGD_SUSPEND, "sleep: device %s is ready", nm_device_get_ip_iface(device)); + + if (!sleep_devices_remove(self, device)) + g_return_if_reached(); + + break; + default: + return; + } } static void -do_sleep_wake (NMManager *self, gboolean sleeping_changed) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - gboolean suspending, waking_from_suspend; - NMDevice *device; - - suspending = sleeping_changed && priv->sleeping; - waking_from_suspend = sleeping_changed && !priv->sleeping; - - if (manager_sleeping (self)) { - _LOGD (LOGD_SUSPEND, "sleep: %s...", suspending ? "sleeping" : "disabling"); - - /* FIXME: are there still hardware devices that need to be disabled around - * suspend/resume? - */ - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { - if (nm_device_is_software (device)) { - /* If a user disables networking we consider that as an - * indication that also software devices must be disconnected. - * But we don't want to destroy them for external events as - * a system suspend. - */ - if (suspending) - continue; - } - /* Wake-on-LAN devices will be taken down post-suspend rather than pre- */ - if ( suspending - && device_is_wake_on_lan (priv->platform, device)) { - _LOGD (LOGD_SUSPEND, "sleep: device %s has wake-on-lan, skipping", - nm_device_get_ip_iface (device)); - continue; - } - - if (nm_device_is_activating (device) || - nm_device_get_state (device) == NM_DEVICE_STATE_ACTIVATED) { - _LOGD (LOGD_SUSPEND, "sleep: wait disconnection of device %s", - nm_device_get_ip_iface (device)); - - if (sleep_devices_add (self, device, suspending)) - nm_device_queue_state (device, NM_DEVICE_STATE_DEACTIVATING, NM_DEVICE_STATE_REASON_SLEEPING); - } else { - nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_SLEEPING, TRUE, NM_DEVICE_STATE_REASON_SLEEPING); - } - } - } else { - _LOGD (LOGD_SUSPEND, "sleep: %s...", waking_from_suspend ? "waking up" : "re-enabling"); - - sleep_devices_clear (self); - - if (waking_from_suspend) { - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { - if (nm_device_is_software (device)) - continue; - - /* Belatedly take down Wake-on-LAN devices; ideally we wouldn't have to do this - * but for now it's the only way to make sure we re-check their connectivity. - */ - if (device_is_wake_on_lan (priv->platform, device)) - nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_SLEEPING, TRUE, NM_DEVICE_STATE_REASON_SLEEPING); - - /* Check if the device is unmanaged but the state transition is still pending. - * If so, change state now so that later we re-manage the device forcing a - * re-check of available connections. - */ - if ( !nm_device_get_managed (device, FALSE) - && nm_device_get_state (device) != NM_DEVICE_STATE_UNMANAGED) { - nm_device_state_changed (device, NM_DEVICE_STATE_UNMANAGED, NM_DEVICE_STATE_REASON_SLEEPING); - } - } - } - - /* Ensure rfkill state is up-to-date since we don't respond to state - * changes during sleep. - */ - nm_manager_rfkill_update (self, RFKILL_TYPE_UNKNOWN); - - /* Re-manage managed devices */ - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { - guint i; - - if ( nm_device_is_software (device) - && !nm_device_get_unmanaged_flags (device, NM_UNMANAGED_SLEEPING)) { - /* DHCP leases of software devices could have gone stale - * so we need to renew them. */ - nm_device_update_dynamic_ip_setup (device); - continue; - } - - /* enable/disable wireless devices since that we don't respond - * to killswitch changes during sleep. - */ - for (i = 0; i < RFKILL_TYPE_MAX; i++) { - RadioState *rstate = &priv->radio_states[i]; - gboolean enabled = radio_enabled_for_rstate (rstate, TRUE); - - if (rstate->desc) { - _LOGD (LOGD_RFKILL, "rfkill: %s %s devices (hw_enabled %d, sw_enabled %d, user_enabled %d)", - enabled ? "enabling" : "disabling", - rstate->desc, rstate->hw_enabled, rstate->sw_enabled, rstate->user_enabled); - } - if (nm_device_get_rfkill_type (device) == rstate->rtype) - nm_device_set_enabled (device, enabled); - } - - nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_SLEEPING, FALSE, NM_DEVICE_STATE_REASON_NOW_MANAGED); - } - } - - nm_manager_update_state (self); +do_sleep_wake(NMManager *self, gboolean sleeping_changed) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + gboolean suspending, waking_from_suspend; + NMDevice * device; + + suspending = sleeping_changed && priv->sleeping; + waking_from_suspend = sleeping_changed && !priv->sleeping; + + if (manager_sleeping(self)) { + _LOGD(LOGD_SUSPEND, "sleep: %s...", suspending ? "sleeping" : "disabling"); + + /* FIXME: are there still hardware devices that need to be disabled around + * suspend/resume? + */ + c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { + if (nm_device_is_software(device)) { + /* If a user disables networking we consider that as an + * indication that also software devices must be disconnected. + * But we don't want to destroy them for external events as + * a system suspend. + */ + if (suspending) + continue; + } + /* Wake-on-LAN devices will be taken down post-suspend rather than pre- */ + if (suspending && device_is_wake_on_lan(priv->platform, device)) { + _LOGD(LOGD_SUSPEND, + "sleep: device %s has wake-on-lan, skipping", + nm_device_get_ip_iface(device)); + continue; + } + + if (nm_device_is_activating(device) + || nm_device_get_state(device) == NM_DEVICE_STATE_ACTIVATED) { + _LOGD(LOGD_SUSPEND, + "sleep: wait disconnection of device %s", + nm_device_get_ip_iface(device)); + + if (sleep_devices_add(self, device, suspending)) + nm_device_queue_state(device, + NM_DEVICE_STATE_DEACTIVATING, + NM_DEVICE_STATE_REASON_SLEEPING); + } else { + nm_device_set_unmanaged_by_flags(device, + NM_UNMANAGED_SLEEPING, + TRUE, + NM_DEVICE_STATE_REASON_SLEEPING); + } + } + } else { + _LOGD(LOGD_SUSPEND, "sleep: %s...", waking_from_suspend ? "waking up" : "re-enabling"); + + sleep_devices_clear(self); + + if (waking_from_suspend) { + c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { + if (nm_device_is_software(device)) + continue; + + /* Belatedly take down Wake-on-LAN devices; ideally we wouldn't have to do this + * but for now it's the only way to make sure we re-check their connectivity. + */ + if (device_is_wake_on_lan(priv->platform, device)) + nm_device_set_unmanaged_by_flags(device, + NM_UNMANAGED_SLEEPING, + TRUE, + NM_DEVICE_STATE_REASON_SLEEPING); + + /* Check if the device is unmanaged but the state transition is still pending. + * If so, change state now so that later we re-manage the device forcing a + * re-check of available connections. + */ + if (!nm_device_get_managed(device, FALSE) + && nm_device_get_state(device) != NM_DEVICE_STATE_UNMANAGED) { + nm_device_state_changed(device, + NM_DEVICE_STATE_UNMANAGED, + NM_DEVICE_STATE_REASON_SLEEPING); + } + } + } + + /* Ensure rfkill state is up-to-date since we don't respond to state + * changes during sleep. + */ + nm_manager_rfkill_update(self, RFKILL_TYPE_UNKNOWN); + + /* Re-manage managed devices */ + c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { + guint i; + + if (nm_device_is_software(device) + && !nm_device_get_unmanaged_flags(device, NM_UNMANAGED_SLEEPING)) { + /* DHCP leases of software devices could have gone stale + * so we need to renew them. */ + nm_device_update_dynamic_ip_setup(device); + continue; + } + + /* enable/disable wireless devices since that we don't respond + * to killswitch changes during sleep. + */ + for (i = 0; i < RFKILL_TYPE_MAX; i++) { + RadioState *rstate = &priv->radio_states[i]; + gboolean enabled = radio_enabled_for_rstate(rstate, TRUE); + + if (rstate->desc) { + _LOGD(LOGD_RFKILL, + "rfkill: %s %s devices (hw_enabled %d, sw_enabled %d, user_enabled %d)", + enabled ? "enabling" : "disabling", + rstate->desc, + rstate->hw_enabled, + rstate->sw_enabled, + rstate->user_enabled); + } + if (nm_device_get_rfkill_type(device) == rstate->rtype) + nm_device_set_enabled(device, enabled); + } + + nm_device_set_unmanaged_by_flags(device, + NM_UNMANAGED_SLEEPING, + FALSE, + NM_DEVICE_STATE_REASON_NOW_MANAGED); + } + } + + nm_manager_update_state(self); } static void -_internal_sleep (NMManager *self, gboolean do_sleep) +_internal_sleep(NMManager *self, gboolean do_sleep) { - NMManagerPrivate *priv; + NMManagerPrivate *priv; - g_return_if_fail (NM_IS_MANAGER (self)); + g_return_if_fail(NM_IS_MANAGER(self)); - priv = NM_MANAGER_GET_PRIVATE (self); + priv = NM_MANAGER_GET_PRIVATE(self); - if (priv->sleeping == do_sleep) - return; + if (priv->sleeping == do_sleep) + return; - _LOGI (LOGD_SUSPEND, "sleep: %s requested (sleeping: %s enabled: %s)", - do_sleep ? "sleep" : "wake", - priv->sleeping ? "yes" : "no", - priv->net_enabled ? "yes" : "no"); + _LOGI(LOGD_SUSPEND, + "sleep: %s requested (sleeping: %s enabled: %s)", + do_sleep ? "sleep" : "wake", + priv->sleeping ? "yes" : "no", + priv->net_enabled ? "yes" : "no"); - priv->sleeping = do_sleep; + priv->sleeping = do_sleep; - do_sleep_wake (self, TRUE); + do_sleep_wake(self, TRUE); - _notify (self, PROP_SLEEPING); + _notify(self, PROP_SLEEPING); } static void -impl_manager_sleep (NMDBusObject *obj, - const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended *method_info, - GDBusConnection *connection, - const char *sender, - GDBusMethodInvocation *invocation, - GVariant *parameters) -{ - NMManager *self = NM_MANAGER (obj); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - GError *error = NULL; - gs_unref_object NMAuthSubject *subject = NULL; - gboolean do_sleep; - - g_variant_get (parameters, "(b)", &do_sleep); - - subject = nm_dbus_manager_new_auth_subject_from_context (invocation); - - if (priv->sleeping == do_sleep) { - error = g_error_new (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_ALREADY_ASLEEP_OR_AWAKE, - "Already %s", do_sleep ? "asleep" : "awake"); - nm_audit_log_control_op (NM_AUDIT_OP_SLEEP_CONTROL, do_sleep ? "on" : "off", FALSE, subject, - error->message); - g_dbus_method_invocation_take_error (invocation, error); - return; - } - - /* Unconditionally allow the request. Previously it was polkit protected - * but unfortunately that doesn't work for short-lived processes like - * pm-utils. It uses dbus-send without --print-reply, which quits - * immediately after sending the request, and NM is unable to obtain the - * sender's UID as dbus-send has already dropped off the bus. Thus NM - * fails the request. Instead, don't validate the request, but rely on - * D-Bus permissions to restrict the call to root. - */ - _internal_sleep (self, do_sleep); - nm_audit_log_control_op (NM_AUDIT_OP_SLEEP_CONTROL, do_sleep ? "on" : "off", TRUE, subject, NULL); - g_dbus_method_invocation_return_value (invocation, NULL); - return; +impl_manager_sleep(NMDBusObject * obj, + const NMDBusInterfaceInfoExtended *interface_info, + const NMDBusMethodInfoExtended * method_info, + GDBusConnection * connection, + const char * sender, + GDBusMethodInvocation * invocation, + GVariant * parameters) +{ + NMManager * self = NM_MANAGER(obj); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + GError * error = NULL; + gs_unref_object NMAuthSubject *subject = NULL; + gboolean do_sleep; + + g_variant_get(parameters, "(b)", &do_sleep); + + subject = nm_dbus_manager_new_auth_subject_from_context(invocation); + + if (priv->sleeping == do_sleep) { + error = g_error_new(NM_MANAGER_ERROR, + NM_MANAGER_ERROR_ALREADY_ASLEEP_OR_AWAKE, + "Already %s", + do_sleep ? "asleep" : "awake"); + nm_audit_log_control_op(NM_AUDIT_OP_SLEEP_CONTROL, + do_sleep ? "on" : "off", + FALSE, + subject, + error->message); + g_dbus_method_invocation_take_error(invocation, error); + return; + } + + /* Unconditionally allow the request. Previously it was polkit protected + * but unfortunately that doesn't work for short-lived processes like + * pm-utils. It uses dbus-send without --print-reply, which quits + * immediately after sending the request, and NM is unable to obtain the + * sender's UID as dbus-send has already dropped off the bus. Thus NM + * fails the request. Instead, don't validate the request, but rely on + * D-Bus permissions to restrict the call to root. + */ + _internal_sleep(self, do_sleep); + nm_audit_log_control_op(NM_AUDIT_OP_SLEEP_CONTROL, + do_sleep ? "on" : "off", + TRUE, + subject, + NULL); + g_dbus_method_invocation_return_value(invocation, NULL); + return; } static void -sleeping_cb (NMSleepMonitor *monitor, gboolean is_about_to_suspend, gpointer user_data) +sleeping_cb(NMSleepMonitor *monitor, gboolean is_about_to_suspend, gpointer user_data) { - NMManager *self = user_data; + NMManager *self = user_data; - _LOGT (LOGD_SUSPEND, "sleep: received %s signal", is_about_to_suspend ? "sleeping" : "resuming"); - _internal_sleep (self, is_about_to_suspend); + _LOGT(LOGD_SUSPEND, "sleep: received %s signal", is_about_to_suspend ? "sleeping" : "resuming"); + _internal_sleep(self, is_about_to_suspend); } static void -_internal_enable (NMManager *self, gboolean enable) +_internal_enable(NMManager *self, gboolean enable) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); - nm_config_state_set (priv->config, TRUE, FALSE, - NM_CONFIG_STATE_PROPERTY_NETWORKING_ENABLED, enable); + nm_config_state_set(priv->config, + TRUE, + FALSE, + NM_CONFIG_STATE_PROPERTY_NETWORKING_ENABLED, + enable); - _LOGI (LOGD_SUSPEND, "%s requested (sleeping: %s enabled: %s)", - enable ? "enable" : "disable", - priv->sleeping ? "yes" : "no", - priv->net_enabled ? "yes" : "no"); + _LOGI(LOGD_SUSPEND, + "%s requested (sleeping: %s enabled: %s)", + enable ? "enable" : "disable", + priv->sleeping ? "yes" : "no", + priv->net_enabled ? "yes" : "no"); - priv->net_enabled = enable; + priv->net_enabled = enable; - do_sleep_wake (self, FALSE); + do_sleep_wake(self, FALSE); - _notify (self, PROP_NETWORKING_ENABLED); + _notify(self, PROP_NETWORKING_ENABLED); } static void -enable_net_done_cb (NMAuthChain *chain, - GDBusMethodInvocation *context, - gpointer user_data) +enable_net_done_cb(NMAuthChain *chain, GDBusMethodInvocation *context, gpointer user_data) { - NMManager *self = NM_MANAGER (user_data); - NMAuthCallResult result; - gboolean enable; - NMAuthSubject *subject; + NMManager * self = NM_MANAGER(user_data); + NMAuthCallResult result; + gboolean enable; + NMAuthSubject * subject; - nm_assert (G_IS_DBUS_METHOD_INVOCATION (context)); + nm_assert(G_IS_DBUS_METHOD_INVOCATION(context)); - c_list_unlink (nm_auth_chain_parent_lst_list (chain)); - enable = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "enable")); - subject = nm_auth_chain_get_subject (chain); + c_list_unlink(nm_auth_chain_parent_lst_list(chain)); + enable = GPOINTER_TO_UINT(nm_auth_chain_get_data(chain, "enable")); + subject = nm_auth_chain_get_subject(chain); - result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK); - if (result != NM_AUTH_CALL_RESULT_YES) { - GError *ret_error; + result = nm_auth_chain_get_result(chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK); + if (result != NM_AUTH_CALL_RESULT_YES) { + GError *ret_error; - ret_error = g_error_new_literal (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - "Not authorized to enable/disable networking"); - nm_audit_log_control_op (NM_AUDIT_OP_NET_CONTROL, enable ? "on" : "off", FALSE, - subject, ret_error->message); - g_dbus_method_invocation_take_error (context, ret_error); - return; - } + ret_error = g_error_new_literal(NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + "Not authorized to enable/disable networking"); + nm_audit_log_control_op(NM_AUDIT_OP_NET_CONTROL, + enable ? "on" : "off", + FALSE, + subject, + ret_error->message); + g_dbus_method_invocation_take_error(context, ret_error); + return; + } - _internal_enable (self, enable); - g_dbus_method_invocation_return_value (context, NULL); - nm_audit_log_control_op (NM_AUDIT_OP_NET_CONTROL, enable ? "on" : "off", TRUE, - subject, NULL); + _internal_enable(self, enable); + g_dbus_method_invocation_return_value(context, NULL); + nm_audit_log_control_op(NM_AUDIT_OP_NET_CONTROL, enable ? "on" : "off", TRUE, subject, NULL); } static void -impl_manager_enable (NMDBusObject *obj, - const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended *method_info, - GDBusConnection *connection, - const char *sender, - GDBusMethodInvocation *invocation, - GVariant *parameters) -{ - NMManager *self = NM_MANAGER (obj); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMAuthChain *chain; - GError *error = NULL; - gboolean enable; - - g_variant_get (parameters, "(b)", &enable); - - if (priv->net_enabled == enable) { - error = g_error_new (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_ALREADY_ENABLED_OR_DISABLED, - "Already %s", enable ? "enabled" : "disabled"); - goto done; - } - - chain = nm_auth_chain_new_context (invocation, enable_net_done_cb, self); - if (!chain) { - error = g_error_new_literal (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - NM_UTILS_ERROR_MSG_REQ_AUTH_FAILED); - goto done; - } - - c_list_link_tail (&priv->auth_lst_head, nm_auth_chain_parent_lst_list (chain)); - nm_auth_chain_set_data (chain, "enable", GUINT_TO_POINTER (enable), NULL); - nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK, TRUE); +impl_manager_enable(NMDBusObject * obj, + const NMDBusInterfaceInfoExtended *interface_info, + const NMDBusMethodInfoExtended * method_info, + GDBusConnection * connection, + const char * sender, + GDBusMethodInvocation * invocation, + GVariant * parameters) +{ + NMManager * self = NM_MANAGER(obj); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + NMAuthChain * chain; + GError * error = NULL; + gboolean enable; + + g_variant_get(parameters, "(b)", &enable); + + if (priv->net_enabled == enable) { + error = g_error_new(NM_MANAGER_ERROR, + NM_MANAGER_ERROR_ALREADY_ENABLED_OR_DISABLED, + "Already %s", + enable ? "enabled" : "disabled"); + goto done; + } + + chain = nm_auth_chain_new_context(invocation, enable_net_done_cb, self); + if (!chain) { + error = g_error_new_literal(NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + NM_UTILS_ERROR_MSG_REQ_AUTH_FAILED); + goto done; + } + + c_list_link_tail(&priv->auth_lst_head, nm_auth_chain_parent_lst_list(chain)); + nm_auth_chain_set_data(chain, "enable", GUINT_TO_POINTER(enable), NULL); + nm_auth_chain_add_call(chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK, TRUE); done: - if (error) - g_dbus_method_invocation_take_error (invocation, error); + if (error) + g_dbus_method_invocation_take_error(invocation, error); } /* Permissions */ static void -get_permissions_done_cb (NMAuthChain *chain, - GDBusMethodInvocation *context, - gpointer user_data) +get_permissions_done_cb(NMAuthChain *chain, GDBusMethodInvocation *context, gpointer user_data) { - GVariantBuilder results; - int i; + GVariantBuilder results; + int i; - nm_assert (G_IS_DBUS_METHOD_INVOCATION (context)); + nm_assert(G_IS_DBUS_METHOD_INVOCATION(context)); - c_list_unlink (nm_auth_chain_parent_lst_list (chain)); + c_list_unlink(nm_auth_chain_parent_lst_list(chain)); - g_variant_builder_init (&results, G_VARIANT_TYPE ("a{ss}")); + g_variant_builder_init(&results, G_VARIANT_TYPE("a{ss}")); - for (i = 0; i < (int) G_N_ELEMENTS (nm_auth_permission_sorted); i++) { - const char *permission = nm_auth_permission_names_by_idx[nm_auth_permission_sorted[i] - 1]; - NMAuthCallResult result; - const char *result_str; + for (i = 0; i < (int) G_N_ELEMENTS(nm_auth_permission_sorted); i++) { + const char *permission = nm_auth_permission_names_by_idx[nm_auth_permission_sorted[i] - 1]; + NMAuthCallResult result; + const char * result_str; - result = nm_auth_chain_get_result (chain, permission); - result_str = nm_client_permission_result_to_string (nm_auth_call_result_to_client (result)); - g_variant_builder_add (&results, "{ss}", permission, result_str); - } + result = nm_auth_chain_get_result(chain, permission); + result_str = nm_client_permission_result_to_string(nm_auth_call_result_to_client(result)); + g_variant_builder_add(&results, "{ss}", permission, result_str); + } - g_dbus_method_invocation_return_value (context, - g_variant_new ("(a{ss})", &results)); + g_dbus_method_invocation_return_value(context, g_variant_new("(a{ss})", &results)); } static void -impl_manager_get_permissions (NMDBusObject *obj, - const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended *method_info, - GDBusConnection *connection, - const char *sender, - GDBusMethodInvocation *invocation, - GVariant *parameters) +impl_manager_get_permissions(NMDBusObject * obj, + const NMDBusInterfaceInfoExtended *interface_info, + const NMDBusMethodInfoExtended * method_info, + GDBusConnection * connection, + const char * sender, + GDBusMethodInvocation * invocation, + GVariant * parameters) { - NMManager *self = NM_MANAGER (obj); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMAuthChain *chain; - int i; + NMManager * self = NM_MANAGER(obj); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + NMAuthChain * chain; + int i; - chain = nm_auth_chain_new_context (invocation, get_permissions_done_cb, self); - if (!chain) { - g_dbus_method_invocation_return_error_literal (invocation, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - NM_UTILS_ERROR_MSG_REQ_AUTH_FAILED); - return; - } + chain = nm_auth_chain_new_context(invocation, get_permissions_done_cb, self); + if (!chain) { + g_dbus_method_invocation_return_error_literal(invocation, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + NM_UTILS_ERROR_MSG_REQ_AUTH_FAILED); + return; + } - c_list_link_tail (&priv->auth_lst_head, nm_auth_chain_parent_lst_list (chain)); + c_list_link_tail(&priv->auth_lst_head, nm_auth_chain_parent_lst_list(chain)); - for (i = 0; i < (int) G_N_ELEMENTS (nm_auth_permission_sorted); i++) { - const char *permission = nm_auth_permission_names_by_idx[nm_auth_permission_sorted[i] - 1]; + for (i = 0; i < (int) G_N_ELEMENTS(nm_auth_permission_sorted); i++) { + const char *permission = nm_auth_permission_names_by_idx[nm_auth_permission_sorted[i] - 1]; - nm_auth_chain_add_call_unsafe (chain, permission, FALSE); - } + nm_auth_chain_add_call_unsafe(chain, permission, FALSE); + } } static void -impl_manager_state (NMDBusObject *obj, - const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended *method_info, - GDBusConnection *connection, - const char *sender, - GDBusMethodInvocation *invocation, - GVariant *parameters) +impl_manager_state(NMDBusObject * obj, + const NMDBusInterfaceInfoExtended *interface_info, + const NMDBusMethodInfoExtended * method_info, + GDBusConnection * connection, + const char * sender, + GDBusMethodInvocation * invocation, + GVariant * parameters) { - NMManager *self = NM_MANAGER (obj); + NMManager *self = NM_MANAGER(obj); - nm_manager_update_state (self); - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(u)", NM_MANAGER_GET_PRIVATE (self)->state)); + nm_manager_update_state(self); + g_dbus_method_invocation_return_value( + invocation, + g_variant_new("(u)", NM_MANAGER_GET_PRIVATE(self)->state)); } static void -impl_manager_set_logging (NMDBusObject *obj, - const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended *method_info, - GDBusConnection *connection, - const char *sender, - GDBusMethodInvocation *invocation, - GVariant *parameters) -{ - NMManager *self = NM_MANAGER (obj); - GError *error = NULL; - const char *level; - const char *domains; - - /* The permission is already enforced by the D-Bus daemon, but we ensure - * that the caller is still alive so that clients are forced to wait and - * we'll be able to switch to polkit without breaking behavior. - */ - if (!nm_dbus_manager_ensure_uid (nm_dbus_object_get_manager (NM_DBUS_OBJECT (self)), - invocation, - G_MAXULONG, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED)) - return; - - g_variant_get (parameters, "(&s&s)", &level, &domains); - - if (nm_logging_setup (level, domains, NULL, &error)) { - _LOGI (LOGD_CORE, "logging: level '%s' domains '%s'", - nm_logging_level_to_string (), nm_logging_domains_to_string ()); - } - - if (error) - g_dbus_method_invocation_take_error (invocation, error); - else - g_dbus_method_invocation_return_value (invocation, NULL); +impl_manager_set_logging(NMDBusObject * obj, + const NMDBusInterfaceInfoExtended *interface_info, + const NMDBusMethodInfoExtended * method_info, + GDBusConnection * connection, + const char * sender, + GDBusMethodInvocation * invocation, + GVariant * parameters) +{ + NMManager * self = NM_MANAGER(obj); + GError * error = NULL; + const char *level; + const char *domains; + + /* The permission is already enforced by the D-Bus daemon, but we ensure + * that the caller is still alive so that clients are forced to wait and + * we'll be able to switch to polkit without breaking behavior. + */ + if (!nm_dbus_manager_ensure_uid(nm_dbus_object_get_manager(NM_DBUS_OBJECT(self)), + invocation, + G_MAXULONG, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED)) + return; + + g_variant_get(parameters, "(&s&s)", &level, &domains); + + if (nm_logging_setup(level, domains, NULL, &error)) { + _LOGI(LOGD_CORE, + "logging: level '%s' domains '%s'", + nm_logging_level_to_string(), + nm_logging_domains_to_string()); + } + + if (error) + g_dbus_method_invocation_take_error(invocation, error); + else + g_dbus_method_invocation_return_value(invocation, NULL); } static void -impl_manager_get_logging (NMDBusObject *obj, - const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended *method_info, - GDBusConnection *connection, - const char *sender, - GDBusMethodInvocation *invocation, - GVariant *parameters) +impl_manager_get_logging(NMDBusObject * obj, + const NMDBusInterfaceInfoExtended *interface_info, + const NMDBusMethodInfoExtended * method_info, + GDBusConnection * connection, + const char * sender, + GDBusMethodInvocation * invocation, + GVariant * parameters) { - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(ss)", - nm_logging_level_to_string (), - nm_logging_domains_to_string ())); + g_dbus_method_invocation_return_value( + invocation, + g_variant_new("(ss)", nm_logging_level_to_string(), nm_logging_domains_to_string())); } typedef struct { - NMManager *self; - GDBusMethodInvocation *context; - guint remaining; + NMManager * self; + GDBusMethodInvocation *context; + guint remaining; } ConnectivityCheckData; static void -device_connectivity_done (NMDevice *device, - NMDeviceConnectivityHandle *handle, - NMConnectivityState state, - GError *error, - gpointer user_data) -{ - ConnectivityCheckData *data = user_data; - NMManager *self; - NMManagerPrivate *priv; - - nm_assert (data); - nm_assert (data->remaining > 0); - nm_assert (NM_IS_MANAGER (data->self)); - - data->remaining--; - - self = data->self; - priv = NM_MANAGER_GET_PRIVATE (self); - - if ( data->context - && ( data->remaining == 0 - || ( state == NM_CONNECTIVITY_FULL - && priv->connectivity_state == NM_CONNECTIVITY_FULL))) { - /* despite having a @handle and @state returned by the requests, we always - * return the current connectivity_state. That is, because the connectivity_state - * and the answer to the connectivity check shall agree. - * - * However, if one of the requests (early) returns full connectivity and agrees with - * the accumulated connectivity state, we no longer have to wait. The result is set. - * - * This also works well, because NMDevice first emits change signals to its own - * connectivity state, which is then taken into account for the accumulated global - * state. All this happens, before the callback is invoked. */ - g_dbus_method_invocation_return_value (g_steal_pointer (&data->context), - g_variant_new ("(u)", - (guint) priv->connectivity_state)); - } - - if (data->remaining == 0) { - g_object_unref (self); - g_slice_free (ConnectivityCheckData, data); - } +device_connectivity_done(NMDevice * device, + NMDeviceConnectivityHandle *handle, + NMConnectivityState state, + GError * error, + gpointer user_data) +{ + ConnectivityCheckData *data = user_data; + NMManager * self; + NMManagerPrivate * priv; + + nm_assert(data); + nm_assert(data->remaining > 0); + nm_assert(NM_IS_MANAGER(data->self)); + + data->remaining--; + + self = data->self; + priv = NM_MANAGER_GET_PRIVATE(self); + + if (data->context + && (data->remaining == 0 + || (state == NM_CONNECTIVITY_FULL + && priv->connectivity_state == NM_CONNECTIVITY_FULL))) { + /* despite having a @handle and @state returned by the requests, we always + * return the current connectivity_state. That is, because the connectivity_state + * and the answer to the connectivity check shall agree. + * + * However, if one of the requests (early) returns full connectivity and agrees with + * the accumulated connectivity state, we no longer have to wait. The result is set. + * + * This also works well, because NMDevice first emits change signals to its own + * connectivity state, which is then taken into account for the accumulated global + * state. All this happens, before the callback is invoked. */ + g_dbus_method_invocation_return_value( + g_steal_pointer(&data->context), + g_variant_new("(u)", (guint) priv->connectivity_state)); + } + + if (data->remaining == 0) { + g_object_unref(self); + g_slice_free(ConnectivityCheckData, data); + } } static void -check_connectivity_auth_done_cb (NMAuthChain *chain, - GDBusMethodInvocation *context, - gpointer user_data) -{ - NMManager *self = NM_MANAGER (user_data); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - GError *error = NULL; - NMAuthCallResult result; - ConnectivityCheckData *data; - NMDevice *device; - - c_list_unlink (nm_auth_chain_parent_lst_list (chain)); - - result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL); - - if (result != NM_AUTH_CALL_RESULT_YES) { - error = g_error_new_literal (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - "Not authorized to recheck connectivity"); - } - if (error) { - g_dbus_method_invocation_take_error (context, error); - return; - } - - data = g_slice_new (ConnectivityCheckData); - data->self = g_object_ref (self); - data->context = context; - data->remaining = 0; - - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { - if (nm_device_check_connectivity (device, - AF_INET, - device_connectivity_done, - data)) - data->remaining++; - if (nm_device_check_connectivity (device, - AF_INET6, - device_connectivity_done, - data)) - data->remaining++; - } - - if (data->remaining == 0) { - /* call the handler at least once. */ - data->remaining = 1; - device_connectivity_done (NULL, - NULL, - NM_CONNECTIVITY_UNKNOWN, - NULL, - data); - /* @data got destroyed. */ - } +check_connectivity_auth_done_cb(NMAuthChain * chain, + GDBusMethodInvocation *context, + gpointer user_data) +{ + NMManager * self = NM_MANAGER(user_data); + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + GError * error = NULL; + NMAuthCallResult result; + ConnectivityCheckData *data; + NMDevice * device; + + c_list_unlink(nm_auth_chain_parent_lst_list(chain)); + + result = nm_auth_chain_get_result(chain, NM_AUTH_PERMISSION_NETWORK_CONTROL); + + if (result != NM_AUTH_CALL_RESULT_YES) { + error = g_error_new_literal(NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + "Not authorized to recheck connectivity"); + } + if (error) { + g_dbus_method_invocation_take_error(context, error); + return; + } + + data = g_slice_new(ConnectivityCheckData); + data->self = g_object_ref(self); + data->context = context; + data->remaining = 0; + + c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { + if (nm_device_check_connectivity(device, AF_INET, device_connectivity_done, data)) + data->remaining++; + if (nm_device_check_connectivity(device, AF_INET6, device_connectivity_done, data)) + data->remaining++; + } + + if (data->remaining == 0) { + /* call the handler at least once. */ + data->remaining = 1; + device_connectivity_done(NULL, NULL, NM_CONNECTIVITY_UNKNOWN, NULL, data); + /* @data got destroyed. */ + } } static void -impl_manager_check_connectivity (NMDBusObject *obj, - const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended *method_info, - GDBusConnection *connection, - const char *sender, - GDBusMethodInvocation *invocation, - GVariant *parameters) +impl_manager_check_connectivity(NMDBusObject * obj, + const NMDBusInterfaceInfoExtended *interface_info, + const NMDBusMethodInfoExtended * method_info, + GDBusConnection * connection, + const char * sender, + GDBusMethodInvocation * invocation, + GVariant * parameters) { - NMManager *self = NM_MANAGER (obj); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMAuthChain *chain; + NMManager * self = NM_MANAGER(obj); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + NMAuthChain * chain; - chain = nm_auth_chain_new_context (invocation, check_connectivity_auth_done_cb, self); - if (!chain) { - g_dbus_method_invocation_return_error_literal(invocation, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - NM_UTILS_ERROR_MSG_REQ_AUTH_FAILED); - return; - } + chain = nm_auth_chain_new_context(invocation, check_connectivity_auth_done_cb, self); + if (!chain) { + g_dbus_method_invocation_return_error_literal(invocation, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + NM_UTILS_ERROR_MSG_REQ_AUTH_FAILED); + return; + } - c_list_link_tail (&priv->auth_lst_head, nm_auth_chain_parent_lst_list (chain)); - nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE); + c_list_link_tail(&priv->auth_lst_head, nm_auth_chain_parent_lst_list(chain)); + nm_auth_chain_add_call(chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE); } static void -start_factory (NMDeviceFactory *factory, gpointer user_data) +start_factory(NMDeviceFactory *factory, gpointer user_data) { - nm_device_factory_start (factory); + nm_device_factory_start(factory); } gboolean -nm_manager_write_device_state (NMManager *self, NMDevice *device, int *out_ifindex) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - int ifindex; - gboolean managed; - NMConfigDeviceStateManagedType managed_type; - const char *uuid = NULL; - const char *perm_hw_addr_fake = NULL; - gboolean perm_hw_addr_is_fake; - guint32 route_metric_default_aspired; - guint32 route_metric_default_effective; - NMTernary nm_owned; - NMDhcpConfig *dhcp_config; - const char *next_server = NULL; - const char *root_path = NULL; - - NM_SET_OUT (out_ifindex, 0); - - ifindex = nm_device_get_ip_ifindex (device); - if (ifindex <= 0) - return FALSE; - if (ifindex == 1) { - /* ignore loopback */ - return FALSE; - } - - if (!nm_platform_link_get (priv->platform, ifindex)) - return FALSE; - - managed = nm_device_get_managed (device, FALSE); - if (managed) { - NMSettingsConnection *sett_conn = NULL; - - if (nm_device_get_state (device) <= NM_DEVICE_STATE_ACTIVATED) - sett_conn = nm_device_get_settings_connection (device); - if (sett_conn) - uuid = nm_settings_connection_get_uuid (sett_conn); - managed_type = NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_MANAGED; - } else if (nm_device_get_unmanaged_flags (device, NM_UNMANAGED_USER_EXPLICIT)) - managed_type = NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_UNMANAGED; - else - managed_type = NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_UNKNOWN; - - perm_hw_addr_fake = nm_device_get_permanent_hw_address_full (device, FALSE, &perm_hw_addr_is_fake); - if (perm_hw_addr_fake && !perm_hw_addr_is_fake) - perm_hw_addr_fake = NULL; - - nm_owned = nm_device_is_software (device) - ? nm_device_is_nm_owned (device) - : NM_TERNARY_DEFAULT; - - route_metric_default_effective = _device_route_metric_get (self, ifindex, NM_DEVICE_TYPE_UNKNOWN, - TRUE, &route_metric_default_aspired); - - dhcp_config = nm_device_get_dhcp_config (device, AF_INET); - if (dhcp_config) { - root_path = nm_dhcp_config_get_option (dhcp_config, "root_path"); - next_server = nm_dhcp_config_get_option (dhcp_config, "next_server"); - } - - if (!nm_config_device_state_write (ifindex, - managed_type, - perm_hw_addr_fake, - uuid, - nm_owned, - route_metric_default_aspired, - route_metric_default_effective, - next_server, - root_path)) - return FALSE; - - NM_SET_OUT (out_ifindex, ifindex); - return TRUE; +nm_manager_write_device_state(NMManager *self, NMDevice *device, int *out_ifindex) +{ + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + int ifindex; + gboolean managed; + NMConfigDeviceStateManagedType managed_type; + const char * uuid = NULL; + const char * perm_hw_addr_fake = NULL; + gboolean perm_hw_addr_is_fake; + guint32 route_metric_default_aspired; + guint32 route_metric_default_effective; + NMTernary nm_owned; + NMDhcpConfig * dhcp_config; + const char * next_server = NULL; + const char * root_path = NULL; + + NM_SET_OUT(out_ifindex, 0); + + ifindex = nm_device_get_ip_ifindex(device); + if (ifindex <= 0) + return FALSE; + if (ifindex == 1) { + /* ignore loopback */ + return FALSE; + } + + if (!nm_platform_link_get(priv->platform, ifindex)) + return FALSE; + + managed = nm_device_get_managed(device, FALSE); + if (managed) { + NMSettingsConnection *sett_conn = NULL; + + if (nm_device_get_state(device) <= NM_DEVICE_STATE_ACTIVATED) + sett_conn = nm_device_get_settings_connection(device); + if (sett_conn) + uuid = nm_settings_connection_get_uuid(sett_conn); + managed_type = NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_MANAGED; + } else if (nm_device_get_unmanaged_flags(device, NM_UNMANAGED_USER_EXPLICIT)) + managed_type = NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_UNMANAGED; + else + managed_type = NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_UNKNOWN; + + perm_hw_addr_fake = + nm_device_get_permanent_hw_address_full(device, FALSE, &perm_hw_addr_is_fake); + if (perm_hw_addr_fake && !perm_hw_addr_is_fake) + perm_hw_addr_fake = NULL; + + nm_owned = nm_device_is_software(device) ? nm_device_is_nm_owned(device) : NM_TERNARY_DEFAULT; + + route_metric_default_effective = _device_route_metric_get(self, + ifindex, + NM_DEVICE_TYPE_UNKNOWN, + TRUE, + &route_metric_default_aspired); + + dhcp_config = nm_device_get_dhcp_config(device, AF_INET); + if (dhcp_config) { + root_path = nm_dhcp_config_get_option(dhcp_config, "root_path"); + next_server = nm_dhcp_config_get_option(dhcp_config, "next_server"); + } + + if (!nm_config_device_state_write(ifindex, + managed_type, + perm_hw_addr_fake, + uuid, + nm_owned, + route_metric_default_aspired, + route_metric_default_effective, + next_server, + root_path)) + return FALSE; + + NM_SET_OUT(out_ifindex, ifindex); + return TRUE; } void -nm_manager_write_device_state_all (NMManager *self) +nm_manager_write_device_state_all(NMManager *self) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - gs_unref_hashtable GHashTable *preserve_ifindexes = NULL; - NMDevice *device; + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + gs_unref_hashtable GHashTable *preserve_ifindexes = NULL; + NMDevice * device; - preserve_ifindexes = g_hash_table_new (nm_direct_hash, NULL); + preserve_ifindexes = g_hash_table_new(nm_direct_hash, NULL); - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { - int ifindex; + c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { + int ifindex; - if (nm_manager_write_device_state (self, device, &ifindex)) { - g_hash_table_add (preserve_ifindexes, - GINT_TO_POINTER (ifindex)); - } - } + if (nm_manager_write_device_state(self, device, &ifindex)) { + g_hash_table_add(preserve_ifindexes, GINT_TO_POINTER(ifindex)); + } + } - nm_config_device_state_prune_stale (preserve_ifindexes, NULL); + nm_config_device_state_prune_stale(preserve_ifindexes, NULL); } static gboolean -devices_inited_cb (gpointer user_data) +devices_inited_cb(gpointer user_data) { - NMManager *self = user_data; - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + NMManager * self = user_data; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); - priv->devices_inited_id = 0; - priv->devices_inited = TRUE; - check_if_startup_complete (self); - return G_SOURCE_REMOVE; + priv->devices_inited_id = 0; + priv->devices_inited = TRUE; + check_if_startup_complete(self); + return G_SOURCE_REMOVE; } gboolean -nm_manager_start (NMManager *self, GError **error) +nm_manager_start(NMManager *self, GError **error) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - gs_free NMSettingsConnection **connections = NULL; - guint i; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + gs_free NMSettingsConnection **connections = NULL; + guint i; - nm_device_factory_manager_load_factories (_register_device_factory, self); + nm_device_factory_manager_load_factories(_register_device_factory, self); - nm_device_factory_manager_for_each_factory (start_factory, NULL); + nm_device_factory_manager_for_each_factory(start_factory, NULL); - /* Set initial radio enabled/disabled state */ - for (i = 0; i < RFKILL_TYPE_MAX; i++) { - RadioState *rstate = &priv->radio_states[i]; - gboolean enabled; + /* Set initial radio enabled/disabled state */ + for (i = 0; i < RFKILL_TYPE_MAX; i++) { + RadioState *rstate = &priv->radio_states[i]; + gboolean enabled; - if (!rstate->desc) - continue; + if (!rstate->desc) + continue; - /* recheck kernel rfkill state */ - update_rstate_from_rfkill (priv->rfkill_mgr, rstate); + /* recheck kernel rfkill state */ + update_rstate_from_rfkill(priv->rfkill_mgr, rstate); - if (rstate->desc) { - _LOGI (LOGD_RFKILL, "rfkill: %s %s by radio killswitch; %s by state file", - rstate->desc, - (rstate->hw_enabled && rstate->sw_enabled) ? "enabled" : "disabled", - rstate->user_enabled ? "enabled" : "disabled"); - } - enabled = radio_enabled_for_rstate (rstate, TRUE); - manager_update_radio_enabled (self, rstate, enabled); - } + if (rstate->desc) { + _LOGI(LOGD_RFKILL, + "rfkill: %s %s by radio killswitch; %s by state file", + rstate->desc, + (rstate->hw_enabled && rstate->sw_enabled) ? "enabled" : "disabled", + rstate->user_enabled ? "enabled" : "disabled"); + } + enabled = radio_enabled_for_rstate(rstate, TRUE); + manager_update_radio_enabled(self, rstate, enabled); + } - _LOGI (LOGD_CORE, "Networking is %s by state file", - priv->net_enabled ? "enabled" : "disabled"); + _LOGI(LOGD_CORE, "Networking is %s by state file", priv->net_enabled ? "enabled" : "disabled"); - system_unmanaged_devices_changed_cb (priv->settings, NULL, self); + system_unmanaged_devices_changed_cb(priv->settings, NULL, self); - hostname_changed_cb (priv->hostname_manager, NULL, self); + hostname_changed_cb(priv->hostname_manager, NULL, self); - if (!nm_settings_start (priv->settings, error)) - return FALSE; + if (!nm_settings_start(priv->settings, error)) + return FALSE; - nm_platform_process_events (priv->platform); + nm_platform_process_events(priv->platform); - g_signal_connect (priv->platform, - NM_PLATFORM_SIGNAL_LINK_CHANGED, - G_CALLBACK (platform_link_cb), - self); + g_signal_connect(priv->platform, + NM_PLATFORM_SIGNAL_LINK_CHANGED, + G_CALLBACK(platform_link_cb), + self); - platform_query_devices (self); + platform_query_devices(self); - /* Load VPN plugins */ - priv->vpn_manager = g_object_ref (nm_vpn_manager_get ()); + /* Load VPN plugins */ + priv->vpn_manager = g_object_ref(nm_vpn_manager_get()); - _LOGD (LOGD_CORE, "creating virtual devices..."); - g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_ADDED, - G_CALLBACK (connection_added_cb), self); - g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED, - G_CALLBACK (connection_updated_cb), self); - connections = nm_settings_get_connections_clone (priv->settings, NULL, - NULL, NULL, - nm_settings_connection_cmp_autoconnect_priority_p_with_data, NULL); - for (i = 0; connections[i]; i++) - connection_changed (self, connections[i]); + _LOGD(LOGD_CORE, "creating virtual devices..."); + g_signal_connect(priv->settings, + NM_SETTINGS_SIGNAL_CONNECTION_ADDED, + G_CALLBACK(connection_added_cb), + self); + g_signal_connect(priv->settings, + NM_SETTINGS_SIGNAL_CONNECTION_UPDATED, + G_CALLBACK(connection_updated_cb), + self); + connections = nm_settings_get_connections_clone( + priv->settings, + NULL, + NULL, + NULL, + nm_settings_connection_cmp_autoconnect_priority_p_with_data, + NULL); + for (i = 0; connections[i]; i++) + connection_changed(self, connections[i]); - nm_clear_g_source (&priv->devices_inited_id); - priv->devices_inited_id = g_idle_add_full (G_PRIORITY_LOW + 10, devices_inited_cb, self, NULL); + nm_clear_g_source(&priv->devices_inited_id); + priv->devices_inited_id = g_idle_add_full(G_PRIORITY_LOW + 10, devices_inited_cb, self, NULL); - return TRUE; + return TRUE; } void -nm_manager_stop (NMManager *self) +nm_manager_stop(NMManager *self) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + NMDevice * device; - /* FIXME(shutdown): we don't do a proper shutdown yet: - * - need to ensure that all pending async operations are cancelled - * - e.g. operations in priv->async_op_lst_head - * - need to ensure that no more asynchronous requests are started, - * or that they complete quickly, or that they fail quickly. - * - note that cancelling some operations is not possible synchronously. - * Hence, stop() only prepares shutdown and tells everybody to not - * accept new work, and to complete in a timely manner. - * We need to still iterate the mainloop for a bit, to give everybody - * the chance to complete. - * - e.g. see comment at nm_auth_manager_force_shutdown() - */ + /* FIXME(shutdown): we don't do a proper shutdown yet: + * - need to ensure that all pending async operations are cancelled + * - e.g. operations in priv->async_op_lst_head + * - need to ensure that no more asynchronous requests are started, + * or that they complete quickly, or that they fail quickly. + * - note that cancelling some operations is not possible synchronously. + * Hence, stop() only prepares shutdown and tells everybody to not + * accept new work, and to complete in a timely manner. + * We need to still iterate the mainloop for a bit, to give everybody + * the chance to complete. + * - e.g. see comment at nm_auth_manager_force_shutdown() + */ - nm_dbus_manager_stop (nm_dbus_object_get_manager (NM_DBUS_OBJECT (self))); + nm_dbus_manager_stop(nm_dbus_object_get_manager(NM_DBUS_OBJECT(self))); - while ((device = c_list_first_entry (&priv->devices_lst_head, NMDevice, devices_lst))) - remove_device (self, device, TRUE); + while ((device = c_list_first_entry(&priv->devices_lst_head, NMDevice, devices_lst))) + remove_device(self, device, TRUE); - _active_connection_cleanup (self); + _active_connection_cleanup(self); - nm_clear_g_source (&priv->devices_inited_id); + nm_clear_g_source(&priv->devices_inited_id); } static gboolean -handle_firmware_changed (gpointer user_data) +handle_firmware_changed(gpointer user_data) { - NMManager *self = NM_MANAGER (user_data); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device; + NMManager * self = NM_MANAGER(user_data); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + NMDevice * device; - priv->fw_changed_id = 0; + priv->fw_changed_id = 0; - /* Try to re-enable devices with missing firmware */ - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { - NMDeviceState state = nm_device_get_state (device); + /* Try to re-enable devices with missing firmware */ + c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { + NMDeviceState state = nm_device_get_state(device); - if ( nm_device_get_firmware_missing (device) - && (state == NM_DEVICE_STATE_UNAVAILABLE)) { - _LOG2I (LOGD_CORE, device, "firmware may now be available"); + if (nm_device_get_firmware_missing(device) && (state == NM_DEVICE_STATE_UNAVAILABLE)) { + _LOG2I(LOGD_CORE, device, "firmware may now be available"); - /* Re-set unavailable state to try bringing the device up again */ - nm_device_state_changed (device, - NM_DEVICE_STATE_UNAVAILABLE, - NM_DEVICE_STATE_REASON_NONE); - } - } + /* Re-set unavailable state to try bringing the device up again */ + nm_device_state_changed(device, + NM_DEVICE_STATE_UNAVAILABLE, + NM_DEVICE_STATE_REASON_NONE); + } + } - return FALSE; + return FALSE; } static void -firmware_dir_changed (GFileMonitor *monitor, - GFile *file, - GFile *other_file, - GFileMonitorEvent event_type, - gpointer user_data) -{ - NMManager *self = NM_MANAGER (user_data); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - - switch (event_type) { - case G_FILE_MONITOR_EVENT_CREATED: - case G_FILE_MONITOR_EVENT_CHANGED: - case G_FILE_MONITOR_EVENT_MOVED: - case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED: - case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: - if (!priv->fw_changed_id) { - priv->fw_changed_id = g_timeout_add_seconds (4, handle_firmware_changed, self); - _LOGI (LOGD_CORE, "kernel firmware directory '%s' changed", - KERNEL_FIRMWARE_DIR); - } - break; - default: - break; - } +firmware_dir_changed(GFileMonitor * monitor, + GFile * file, + GFile * other_file, + GFileMonitorEvent event_type, + gpointer user_data) +{ + NMManager * self = NM_MANAGER(user_data); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + + switch (event_type) { + case G_FILE_MONITOR_EVENT_CREATED: + case G_FILE_MONITOR_EVENT_CHANGED: + case G_FILE_MONITOR_EVENT_MOVED: + case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED: + case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: + if (!priv->fw_changed_id) { + priv->fw_changed_id = g_timeout_add_seconds(4, handle_firmware_changed, self); + _LOGI(LOGD_CORE, "kernel firmware directory '%s' changed", KERNEL_FIRMWARE_DIR); + } + break; + default: + break; + } } static void -connection_metered_changed (GObject *object, - NMMetered metered, - gpointer user_data) +connection_metered_changed(GObject *object, NMMetered metered, gpointer user_data) { - nm_manager_update_metered (NM_MANAGER (user_data)); + nm_manager_update_metered(NM_MANAGER(user_data)); } static void -policy_default_ac_changed (GObject *object, GParamSpec *pspec, gpointer user_data) -{ - NMManager *self = NM_MANAGER (user_data); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMActiveConnection *ac; - - /* Note: this assumes that it's not possible for the IP4 default - * route to be going over the default-ip6-device. If that changes, - * we need something more complicated here. - */ - ac = nm_policy_get_default_ip4_ac (priv->policy); - if (!ac) - ac = nm_policy_get_default_ip6_ac (priv->policy); - - if (ac != priv->primary_connection) { - if (priv->primary_connection) { - g_signal_handlers_disconnect_by_func (priv->primary_connection, - G_CALLBACK (connection_metered_changed), - self); - g_clear_object (&priv->primary_connection); - } - - priv->primary_connection = ac ? g_object_ref (ac) : NULL; - - if (priv->primary_connection) { - g_signal_connect (priv->primary_connection, - NM_ACTIVE_CONNECTION_DEVICE_METERED_CHANGED, - G_CALLBACK (connection_metered_changed), self); - } - _LOGD (LOGD_CORE, "PrimaryConnection now %s", - ac ? nm_active_connection_get_settings_connection_id (ac) : "(none)"); - _notify (self, PROP_PRIMARY_CONNECTION); - _notify (self, PROP_PRIMARY_CONNECTION_TYPE); - nm_manager_update_metered (self); - } +policy_default_ac_changed(GObject *object, GParamSpec *pspec, gpointer user_data) +{ + NMManager * self = NM_MANAGER(user_data); + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + NMActiveConnection *ac; + + /* Note: this assumes that it's not possible for the IP4 default + * route to be going over the default-ip6-device. If that changes, + * we need something more complicated here. + */ + ac = nm_policy_get_default_ip4_ac(priv->policy); + if (!ac) + ac = nm_policy_get_default_ip6_ac(priv->policy); + + if (ac != priv->primary_connection) { + if (priv->primary_connection) { + g_signal_handlers_disconnect_by_func(priv->primary_connection, + G_CALLBACK(connection_metered_changed), + self); + g_clear_object(&priv->primary_connection); + } + + priv->primary_connection = ac ? g_object_ref(ac) : NULL; + + if (priv->primary_connection) { + g_signal_connect(priv->primary_connection, + NM_ACTIVE_CONNECTION_DEVICE_METERED_CHANGED, + G_CALLBACK(connection_metered_changed), + self); + } + _LOGD(LOGD_CORE, + "PrimaryConnection now %s", + ac ? nm_active_connection_get_settings_connection_id(ac) : "(none)"); + _notify(self, PROP_PRIMARY_CONNECTION); + _notify(self, PROP_PRIMARY_CONNECTION_TYPE); + nm_manager_update_metered(self); + } } static void -policy_activating_ac_changed (GObject *object, GParamSpec *pspec, gpointer user_data) -{ - NMManager *self = NM_MANAGER (user_data); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMActiveConnection *activating, *best; - - /* We only look at activating-ip6-ac if activating-ip4-ac - * AND default-ip4-ac are NULL; if default-ip4-ac is - * non-NULL, then activating-ip6-ac is irrelevant, since while - * that AC might become the new default-ip6-ac, it can't - * become primary-connection while default-ip4-ac is set to - * something else. - */ - activating = nm_policy_get_activating_ip4_ac (priv->policy); - best = nm_policy_get_default_ip4_ac (priv->policy); - if (!activating && !best) - activating = nm_policy_get_activating_ip6_ac (priv->policy); - - if (nm_g_object_ref_set (&priv->activating_connection, activating)) { - _LOGD (LOGD_CORE, "ActivatingConnection now %s", - activating - ? nm_active_connection_get_settings_connection_id (activating) - : "(none)"); - _notify (self, PROP_ACTIVATING_CONNECTION); - } +policy_activating_ac_changed(GObject *object, GParamSpec *pspec, gpointer user_data) +{ + NMManager * self = NM_MANAGER(user_data); + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + NMActiveConnection *activating, *best; + + /* We only look at activating-ip6-ac if activating-ip4-ac + * AND default-ip4-ac are NULL; if default-ip4-ac is + * non-NULL, then activating-ip6-ac is irrelevant, since while + * that AC might become the new default-ip6-ac, it can't + * become primary-connection while default-ip4-ac is set to + * something else. + */ + activating = nm_policy_get_activating_ip4_ac(priv->policy); + best = nm_policy_get_default_ip4_ac(priv->policy); + if (!activating && !best) + activating = nm_policy_get_activating_ip6_ac(priv->policy); + + if (nm_g_object_ref_set(&priv->activating_connection, activating)) { + _LOGD(LOGD_CORE, + "ActivatingConnection now %s", + activating ? nm_active_connection_get_settings_connection_id(activating) : "(none)"); + _notify(self, PROP_ACTIVATING_CONNECTION); + } } /*****************************************************************************/ typedef struct { - NMManager *self; - NMDBusObject *obj; - const NMDBusInterfaceInfoExtended *interface_info; - const NMDBusPropertyInfoExtended *property_info; - GVariant *value; - guint64 export_version_id; + NMManager * self; + NMDBusObject * obj; + const NMDBusInterfaceInfoExtended *interface_info; + const NMDBusPropertyInfoExtended * property_info; + GVariant * value; + guint64 export_version_id; } DBusSetPropertyHandle; #define NM_PERM_DENIED_ERROR "org.freedesktop.NetworkManager.PermissionDenied" static void -_dbus_set_property_auth_cb (NMAuthChain *chain, - GDBusMethodInvocation *invocation, - gpointer user_data) -{ - DBusSetPropertyHandle *handle_data = user_data; - gs_unref_object NMDBusObject *obj = handle_data->obj; - const NMDBusInterfaceInfoExtended *interface_info = handle_data->interface_info; - const NMDBusPropertyInfoExtended *property_info = handle_data->property_info; - gs_unref_variant GVariant *value = handle_data->value; - guint64 export_version_id = handle_data->export_version_id; - gs_unref_object NMManager *self = handle_data->self; - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMAuthCallResult result; - gs_free_error GError *local = NULL; - const char *error_name = NULL; - const char *error_message = NULL; - GValue gvalue; - - g_slice_free (DBusSetPropertyHandle, handle_data); - - c_list_unlink (nm_auth_chain_parent_lst_list (chain)); - result = nm_auth_chain_get_result (chain, property_info->writable.permission); - - if (result != NM_AUTH_CALL_RESULT_YES) { - error_name = NM_PERM_DENIED_ERROR; - error_message = "Not authorized to perform this operation"; - goto out; - } - - if (export_version_id != nm_dbus_object_get_export_version_id (obj)) { - error_name = "org.freedesktop.DBus.Error.UnknownObject"; - error_message = "Object was deleted while authenticating"; - goto out; - } - - /* Handle some properties specially *sigh* */ - if ( interface_info == &interface_info_manager - && nm_streq (property_info->property_name, NM_MANAGER_GLOBAL_DNS_CONFIGURATION)) { - const NMGlobalDnsConfig *global_dns; - - global_dns = nm_config_data_get_global_dns_config (nm_config_get_data (priv->config)); - if ( global_dns - && !nm_global_dns_config_is_internal (global_dns)) { - error_name = NM_PERM_DENIED_ERROR; - error_message = "Global DNS configuration already set via configuration file"; - goto out; - } - } - - g_dbus_gvariant_to_gvalue (value, &gvalue); - if (!nm_g_object_set_property (G_OBJECT (obj), property_info->property_name, &gvalue, &local)) { - error_name = "org.freedesktop.DBus.Error.InvalidArgs"; - error_message = local->message; - } - g_value_unset (&gvalue); +_dbus_set_property_auth_cb(NMAuthChain * chain, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + DBusSetPropertyHandle *handle_data = user_data; + gs_unref_object NMDBusObject * obj = handle_data->obj; + const NMDBusInterfaceInfoExtended *interface_info = handle_data->interface_info; + const NMDBusPropertyInfoExtended * property_info = handle_data->property_info; + gs_unref_variant GVariant *value = handle_data->value; + guint64 export_version_id = handle_data->export_version_id; + gs_unref_object NMManager *self = handle_data->self; + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + NMAuthCallResult result; + gs_free_error GError *local = NULL; + const char * error_name = NULL; + const char * error_message = NULL; + GValue gvalue; + + g_slice_free(DBusSetPropertyHandle, handle_data); + + c_list_unlink(nm_auth_chain_parent_lst_list(chain)); + result = nm_auth_chain_get_result(chain, property_info->writable.permission); + + if (result != NM_AUTH_CALL_RESULT_YES) { + error_name = NM_PERM_DENIED_ERROR; + error_message = "Not authorized to perform this operation"; + goto out; + } + + if (export_version_id != nm_dbus_object_get_export_version_id(obj)) { + error_name = "org.freedesktop.DBus.Error.UnknownObject"; + error_message = "Object was deleted while authenticating"; + goto out; + } + + /* Handle some properties specially *sigh* */ + if (interface_info == &interface_info_manager + && nm_streq(property_info->property_name, NM_MANAGER_GLOBAL_DNS_CONFIGURATION)) { + const NMGlobalDnsConfig *global_dns; + + global_dns = nm_config_data_get_global_dns_config(nm_config_get_data(priv->config)); + if (global_dns && !nm_global_dns_config_is_internal(global_dns)) { + error_name = NM_PERM_DENIED_ERROR; + error_message = "Global DNS configuration already set via configuration file"; + goto out; + } + } + + g_dbus_gvariant_to_gvalue(value, &gvalue); + if (!nm_g_object_set_property(G_OBJECT(obj), property_info->property_name, &gvalue, &local)) { + error_name = "org.freedesktop.DBus.Error.InvalidArgs"; + error_message = local->message; + } + g_value_unset(&gvalue); out: - nm_audit_log_control_op (property_info->writable.audit_op, - property_info->property_name, - !error_message, - nm_auth_chain_get_subject (chain), - error_message); - if (error_message) - g_dbus_method_invocation_return_dbus_error (invocation, error_name, error_message); - else - g_dbus_method_invocation_return_value (invocation, NULL); + nm_audit_log_control_op(property_info->writable.audit_op, + property_info->property_name, + !error_message, + nm_auth_chain_get_subject(chain), + error_message); + if (error_message) + g_dbus_method_invocation_return_dbus_error(invocation, error_name, error_message); + else + g_dbus_method_invocation_return_value(invocation, NULL); } void -nm_manager_dbus_set_property_handle (NMDBusObject *obj, - const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusPropertyInfoExtended *property_info, - GDBusConnection *connection, - const char *sender, - GDBusMethodInvocation *invocation, - GVariant *value, - gpointer user_data) -{ - NMManager *self = user_data; - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMAuthChain *chain; - const char *error_message = NULL; - gs_unref_object NMAuthSubject *subject = NULL; - DBusSetPropertyHandle *handle_data; - - subject = nm_dbus_manager_new_auth_subject_from_context (invocation); - if (!subject) { - error_message = NM_UTILS_ERROR_MSG_REQ_UID_UKNOWN; - goto err; - } - - handle_data = g_slice_new0 (DBusSetPropertyHandle); - handle_data->self = g_object_ref (self); - handle_data->obj = g_object_ref (obj); - handle_data->interface_info = interface_info; - handle_data->property_info = property_info; - handle_data->value = g_variant_ref (value); - handle_data->export_version_id = nm_dbus_object_get_export_version_id (obj); - - chain = nm_auth_chain_new_subject (subject, invocation, _dbus_set_property_auth_cb, handle_data); - c_list_link_tail (&priv->auth_lst_head, nm_auth_chain_parent_lst_list (chain)); - nm_auth_chain_add_call_unsafe (chain, property_info->writable.permission, TRUE); - return; +nm_manager_dbus_set_property_handle(NMDBusObject * obj, + const NMDBusInterfaceInfoExtended *interface_info, + const NMDBusPropertyInfoExtended * property_info, + GDBusConnection * connection, + const char * sender, + GDBusMethodInvocation * invocation, + GVariant * value, + gpointer user_data) +{ + NMManager * self = user_data; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + NMAuthChain * chain; + const char * error_message = NULL; + gs_unref_object NMAuthSubject *subject = NULL; + DBusSetPropertyHandle * handle_data; + + subject = nm_dbus_manager_new_auth_subject_from_context(invocation); + if (!subject) { + error_message = NM_UTILS_ERROR_MSG_REQ_UID_UKNOWN; + goto err; + } + + handle_data = g_slice_new0(DBusSetPropertyHandle); + handle_data->self = g_object_ref(self); + handle_data->obj = g_object_ref(obj); + handle_data->interface_info = interface_info; + handle_data->property_info = property_info; + handle_data->value = g_variant_ref(value); + handle_data->export_version_id = nm_dbus_object_get_export_version_id(obj); + + chain = nm_auth_chain_new_subject(subject, invocation, _dbus_set_property_auth_cb, handle_data); + c_list_link_tail(&priv->auth_lst_head, nm_auth_chain_parent_lst_list(chain)); + nm_auth_chain_add_call_unsafe(chain, property_info->writable.permission, TRUE); + return; err: - nm_audit_log_control_op (property_info->writable.audit_op, - property_info->property_name, - FALSE, - invocation, - error_message); - g_dbus_method_invocation_return_error_literal (invocation, - G_DBUS_ERROR, - G_DBUS_ERROR_AUTH_FAILED, - error_message); + nm_audit_log_control_op(property_info->writable.audit_op, + property_info->property_name, + FALSE, + invocation, + error_message); + g_dbus_method_invocation_return_error_literal(invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_AUTH_FAILED, + error_message); } /*****************************************************************************/ static NMCheckpointManager * -_checkpoint_mgr_get (NMManager *self, gboolean create_as_needed) +_checkpoint_mgr_get(NMManager *self, gboolean create_as_needed) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); - if (G_UNLIKELY (!priv->checkpoint_mgr) && create_as_needed) - priv->checkpoint_mgr = nm_checkpoint_manager_new (self, obj_properties[PROP_CHECKPOINTS]); - return priv->checkpoint_mgr; + if (G_UNLIKELY(!priv->checkpoint_mgr) && create_as_needed) + priv->checkpoint_mgr = nm_checkpoint_manager_new(self, obj_properties[PROP_CHECKPOINTS]); + return priv->checkpoint_mgr; } static void -checkpoint_auth_done_cb (NMAuthChain *chain, - GDBusMethodInvocation *context, - gpointer user_data) -{ - NMManager *self = NM_MANAGER (user_data); - char *op; - char *checkpoint_path = NULL; - char **devices; - NMCheckpoint *checkpoint; - NMAuthCallResult result; - guint32 timeout, flags; - GVariant *variant = NULL; - GError *error = NULL; - const char *arg = NULL; - guint32 add_timeout; - - op = nm_auth_chain_get_data (chain, "audit-op"); - c_list_unlink (nm_auth_chain_parent_lst_list (chain)); - result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK); - - if (NM_IN_STRSET (op, NM_AUDIT_OP_CHECKPOINT_DESTROY, - NM_AUDIT_OP_CHECKPOINT_ROLLBACK, - NM_AUDIT_OP_CHECKPOINT_ADJUST_ROLLBACK_TIMEOUT)) - arg = checkpoint_path = nm_auth_chain_get_data (chain, "checkpoint_path"); - - if (result != NM_AUTH_CALL_RESULT_YES) { - error = g_error_new_literal (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - "Not authorized to checkpoint/rollback"); - } else { - if (nm_streq0 (op, NM_AUDIT_OP_CHECKPOINT_CREATE)) { - timeout = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "timeout")); - flags = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "flags")); - devices = nm_auth_chain_get_data (chain, "devices"); - - checkpoint = nm_checkpoint_manager_create (_checkpoint_mgr_get (self, TRUE), - (const char *const *) devices, - timeout, - (NMCheckpointCreateFlags) flags, - &error); - if (checkpoint) { - arg = nm_dbus_object_get_path (NM_DBUS_OBJECT (checkpoint)); - variant = g_variant_new ("(o)", arg); - } - } else if (nm_streq0 (op, NM_AUDIT_OP_CHECKPOINT_DESTROY)) { - nm_checkpoint_manager_destroy (_checkpoint_mgr_get (self, TRUE), - checkpoint_path, &error); - } else if (nm_streq0 (op, NM_AUDIT_OP_CHECKPOINT_ROLLBACK)) { - nm_checkpoint_manager_rollback (_checkpoint_mgr_get (self, TRUE), - checkpoint_path, &variant, &error); - } else if (nm_streq0 (op, NM_AUDIT_OP_CHECKPOINT_ADJUST_ROLLBACK_TIMEOUT)) { - add_timeout = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "add_timeout")); - nm_checkpoint_manager_adjust_rollback_timeout (_checkpoint_mgr_get (self, TRUE), - checkpoint_path, add_timeout, &error); - } else - g_return_if_reached (); - } - - nm_audit_log_checkpoint_op (op, arg ?: "", !error, nm_auth_chain_get_subject (chain), - error ? error->message : NULL); - - if (error) - g_dbus_method_invocation_take_error (context, error); - else - g_dbus_method_invocation_return_value (context, variant); +checkpoint_auth_done_cb(NMAuthChain *chain, GDBusMethodInvocation *context, gpointer user_data) +{ + NMManager * self = NM_MANAGER(user_data); + char * op; + char * checkpoint_path = NULL; + char ** devices; + NMCheckpoint * checkpoint; + NMAuthCallResult result; + guint32 timeout, flags; + GVariant * variant = NULL; + GError * error = NULL; + const char * arg = NULL; + guint32 add_timeout; + + op = nm_auth_chain_get_data(chain, "audit-op"); + c_list_unlink(nm_auth_chain_parent_lst_list(chain)); + result = nm_auth_chain_get_result(chain, NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK); + + if (NM_IN_STRSET(op, + NM_AUDIT_OP_CHECKPOINT_DESTROY, + NM_AUDIT_OP_CHECKPOINT_ROLLBACK, + NM_AUDIT_OP_CHECKPOINT_ADJUST_ROLLBACK_TIMEOUT)) + arg = checkpoint_path = nm_auth_chain_get_data(chain, "checkpoint_path"); + + if (result != NM_AUTH_CALL_RESULT_YES) { + error = g_error_new_literal(NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + "Not authorized to checkpoint/rollback"); + } else { + if (nm_streq0(op, NM_AUDIT_OP_CHECKPOINT_CREATE)) { + timeout = GPOINTER_TO_UINT(nm_auth_chain_get_data(chain, "timeout")); + flags = GPOINTER_TO_UINT(nm_auth_chain_get_data(chain, "flags")); + devices = nm_auth_chain_get_data(chain, "devices"); + + checkpoint = nm_checkpoint_manager_create(_checkpoint_mgr_get(self, TRUE), + (const char *const *) devices, + timeout, + (NMCheckpointCreateFlags) flags, + &error); + if (checkpoint) { + arg = nm_dbus_object_get_path(NM_DBUS_OBJECT(checkpoint)); + variant = g_variant_new("(o)", arg); + } + } else if (nm_streq0(op, NM_AUDIT_OP_CHECKPOINT_DESTROY)) { + nm_checkpoint_manager_destroy(_checkpoint_mgr_get(self, TRUE), checkpoint_path, &error); + } else if (nm_streq0(op, NM_AUDIT_OP_CHECKPOINT_ROLLBACK)) { + nm_checkpoint_manager_rollback(_checkpoint_mgr_get(self, TRUE), + checkpoint_path, + &variant, + &error); + } else if (nm_streq0(op, NM_AUDIT_OP_CHECKPOINT_ADJUST_ROLLBACK_TIMEOUT)) { + add_timeout = GPOINTER_TO_UINT(nm_auth_chain_get_data(chain, "add_timeout")); + nm_checkpoint_manager_adjust_rollback_timeout(_checkpoint_mgr_get(self, TRUE), + checkpoint_path, + add_timeout, + &error); + } else + g_return_if_reached(); + } + + nm_audit_log_checkpoint_op(op, + arg ?: "", + !error, + nm_auth_chain_get_subject(chain), + error ? error->message : NULL); + + if (error) + g_dbus_method_invocation_take_error(context, error); + else + g_dbus_method_invocation_return_value(context, variant); } static void -impl_manager_checkpoint_create (NMDBusObject *obj, - const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended *method_info, - GDBusConnection *connection, - const char *sender, - GDBusMethodInvocation *invocation, - GVariant *parameters) -{ - NMManager *self = NM_MANAGER (obj); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMAuthChain *chain; - char **devices; - guint32 rollback_timeout; - guint32 flags; - - G_STATIC_ASSERT_EXPR (sizeof (flags) <= sizeof (NMCheckpointCreateFlags)); - - chain = nm_auth_chain_new_context (invocation, checkpoint_auth_done_cb, self); - if (!chain) { - g_dbus_method_invocation_return_error_literal (invocation, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - NM_UTILS_ERROR_MSG_REQ_AUTH_FAILED); - return; - } - - g_variant_get (parameters, "(^aouu)", &devices, &rollback_timeout, &flags); - - c_list_link_tail (&priv->auth_lst_head, nm_auth_chain_parent_lst_list (chain)); - nm_auth_chain_set_data (chain, "audit-op", NM_AUDIT_OP_CHECKPOINT_CREATE, NULL); - nm_auth_chain_set_data (chain, "devices", devices, (GDestroyNotify) g_strfreev); - nm_auth_chain_set_data (chain, "flags", GUINT_TO_POINTER (flags), NULL); - nm_auth_chain_set_data (chain, "timeout", GUINT_TO_POINTER (rollback_timeout), NULL); - nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK, TRUE); +impl_manager_checkpoint_create(NMDBusObject * obj, + const NMDBusInterfaceInfoExtended *interface_info, + const NMDBusMethodInfoExtended * method_info, + GDBusConnection * connection, + const char * sender, + GDBusMethodInvocation * invocation, + GVariant * parameters) +{ + NMManager * self = NM_MANAGER(obj); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + NMAuthChain * chain; + char ** devices; + guint32 rollback_timeout; + guint32 flags; + + G_STATIC_ASSERT_EXPR(sizeof(flags) <= sizeof(NMCheckpointCreateFlags)); + + chain = nm_auth_chain_new_context(invocation, checkpoint_auth_done_cb, self); + if (!chain) { + g_dbus_method_invocation_return_error_literal(invocation, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + NM_UTILS_ERROR_MSG_REQ_AUTH_FAILED); + return; + } + + g_variant_get(parameters, "(^aouu)", &devices, &rollback_timeout, &flags); + + c_list_link_tail(&priv->auth_lst_head, nm_auth_chain_parent_lst_list(chain)); + nm_auth_chain_set_data(chain, "audit-op", NM_AUDIT_OP_CHECKPOINT_CREATE, NULL); + nm_auth_chain_set_data(chain, "devices", devices, (GDestroyNotify) g_strfreev); + nm_auth_chain_set_data(chain, "flags", GUINT_TO_POINTER(flags), NULL); + nm_auth_chain_set_data(chain, "timeout", GUINT_TO_POINTER(rollback_timeout), NULL); + nm_auth_chain_add_call(chain, NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK, TRUE); } static void -impl_manager_checkpoint_destroy (NMDBusObject *obj, - const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended *method_info, - GDBusConnection *connection, - const char *sender, - GDBusMethodInvocation *invocation, - GVariant *parameters) -{ - NMManager *self = NM_MANAGER (obj); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMAuthChain *chain; - const char *checkpoint_path; - - chain = nm_auth_chain_new_context (invocation, checkpoint_auth_done_cb, self); - if (!chain) { - g_dbus_method_invocation_return_error_literal (invocation, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - NM_UTILS_ERROR_MSG_REQ_AUTH_FAILED); - return; - } - - g_variant_get (parameters, "(&o)", &checkpoint_path); - - c_list_link_tail (&priv->auth_lst_head, nm_auth_chain_parent_lst_list (chain)); - nm_auth_chain_set_data (chain, "audit-op", NM_AUDIT_OP_CHECKPOINT_DESTROY, NULL); - nm_auth_chain_set_data (chain, "checkpoint_path", g_strdup (checkpoint_path), g_free); - nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK, TRUE); +impl_manager_checkpoint_destroy(NMDBusObject * obj, + const NMDBusInterfaceInfoExtended *interface_info, + const NMDBusMethodInfoExtended * method_info, + GDBusConnection * connection, + const char * sender, + GDBusMethodInvocation * invocation, + GVariant * parameters) +{ + NMManager * self = NM_MANAGER(obj); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + NMAuthChain * chain; + const char * checkpoint_path; + + chain = nm_auth_chain_new_context(invocation, checkpoint_auth_done_cb, self); + if (!chain) { + g_dbus_method_invocation_return_error_literal(invocation, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + NM_UTILS_ERROR_MSG_REQ_AUTH_FAILED); + return; + } + + g_variant_get(parameters, "(&o)", &checkpoint_path); + + c_list_link_tail(&priv->auth_lst_head, nm_auth_chain_parent_lst_list(chain)); + nm_auth_chain_set_data(chain, "audit-op", NM_AUDIT_OP_CHECKPOINT_DESTROY, NULL); + nm_auth_chain_set_data(chain, "checkpoint_path", g_strdup(checkpoint_path), g_free); + nm_auth_chain_add_call(chain, NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK, TRUE); } static void -impl_manager_checkpoint_rollback (NMDBusObject *obj, - const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended *method_info, - GDBusConnection *connection, - const char *sender, - GDBusMethodInvocation *invocation, - GVariant *parameters) -{ - NMManager *self = NM_MANAGER (obj); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMAuthChain *chain; - const char *checkpoint_path; - - chain = nm_auth_chain_new_context (invocation, checkpoint_auth_done_cb, self); - if (!chain) { - g_dbus_method_invocation_return_error_literal (invocation, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - NM_UTILS_ERROR_MSG_REQ_AUTH_FAILED); - return; - } - - g_variant_get (parameters, "(&o)", &checkpoint_path); - - c_list_link_tail (&priv->auth_lst_head, nm_auth_chain_parent_lst_list (chain)); - nm_auth_chain_set_data (chain, "audit-op", NM_AUDIT_OP_CHECKPOINT_ROLLBACK, NULL); - nm_auth_chain_set_data (chain, "checkpoint_path", g_strdup (checkpoint_path), g_free); - nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK, TRUE); +impl_manager_checkpoint_rollback(NMDBusObject * obj, + const NMDBusInterfaceInfoExtended *interface_info, + const NMDBusMethodInfoExtended * method_info, + GDBusConnection * connection, + const char * sender, + GDBusMethodInvocation * invocation, + GVariant * parameters) +{ + NMManager * self = NM_MANAGER(obj); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + NMAuthChain * chain; + const char * checkpoint_path; + + chain = nm_auth_chain_new_context(invocation, checkpoint_auth_done_cb, self); + if (!chain) { + g_dbus_method_invocation_return_error_literal(invocation, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + NM_UTILS_ERROR_MSG_REQ_AUTH_FAILED); + return; + } + + g_variant_get(parameters, "(&o)", &checkpoint_path); + + c_list_link_tail(&priv->auth_lst_head, nm_auth_chain_parent_lst_list(chain)); + nm_auth_chain_set_data(chain, "audit-op", NM_AUDIT_OP_CHECKPOINT_ROLLBACK, NULL); + nm_auth_chain_set_data(chain, "checkpoint_path", g_strdup(checkpoint_path), g_free); + nm_auth_chain_add_call(chain, NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK, TRUE); } static void -impl_manager_checkpoint_adjust_rollback_timeout (NMDBusObject *obj, - const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended *method_info, - GDBusConnection *connection, - const char *sender, - GDBusMethodInvocation *invocation, - GVariant *parameters) -{ - NMManager *self = NM_MANAGER (obj); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMAuthChain *chain; - const char *checkpoint_path; - guint32 add_timeout; - - chain = nm_auth_chain_new_context (invocation, checkpoint_auth_done_cb, self); - if (!chain) { - g_dbus_method_invocation_return_error_literal (invocation, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - NM_UTILS_ERROR_MSG_REQ_AUTH_FAILED); - return; - } - - g_variant_get (parameters, "(&ou)", &checkpoint_path, &add_timeout); - - c_list_link_tail (&priv->auth_lst_head, nm_auth_chain_parent_lst_list (chain)); - nm_auth_chain_set_data (chain, "audit-op", NM_AUDIT_OP_CHECKPOINT_ADJUST_ROLLBACK_TIMEOUT, NULL); - nm_auth_chain_set_data (chain, "checkpoint_path", g_strdup (checkpoint_path), g_free); - nm_auth_chain_set_data (chain, "add_timeout", GUINT_TO_POINTER (add_timeout), NULL); - nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK, TRUE); +impl_manager_checkpoint_adjust_rollback_timeout(NMDBusObject * obj, + const NMDBusInterfaceInfoExtended *interface_info, + const NMDBusMethodInfoExtended * method_info, + GDBusConnection * connection, + const char * sender, + GDBusMethodInvocation * invocation, + GVariant * parameters) +{ + NMManager * self = NM_MANAGER(obj); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + NMAuthChain * chain; + const char * checkpoint_path; + guint32 add_timeout; + + chain = nm_auth_chain_new_context(invocation, checkpoint_auth_done_cb, self); + if (!chain) { + g_dbus_method_invocation_return_error_literal(invocation, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + NM_UTILS_ERROR_MSG_REQ_AUTH_FAILED); + return; + } + + g_variant_get(parameters, "(&ou)", &checkpoint_path, &add_timeout); + + c_list_link_tail(&priv->auth_lst_head, nm_auth_chain_parent_lst_list(chain)); + nm_auth_chain_set_data(chain, "audit-op", NM_AUDIT_OP_CHECKPOINT_ADJUST_ROLLBACK_TIMEOUT, NULL); + nm_auth_chain_set_data(chain, "checkpoint_path", g_strdup(checkpoint_path), g_free); + nm_auth_chain_set_data(chain, "add_timeout", GUINT_TO_POINTER(add_timeout), NULL); + nm_auth_chain_add_call(chain, NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK, TRUE); } /*****************************************************************************/ static void -auth_mgr_changed (NMAuthManager *auth_manager, gpointer user_data) +auth_mgr_changed(NMAuthManager *auth_manager, gpointer user_data) { - /* Let clients know they should re-check their authorization */ - nm_dbus_object_emit_signal (user_data, - &interface_info_manager, - &signal_info_check_permissions, - "()"); + /* Let clients know they should re-check their authorization */ + nm_dbus_object_emit_signal(user_data, + &interface_info_manager, + &signal_info_check_permissions, + "()"); } #define KERN_RFKILL_OP_CHANGE_ALL 3 #define KERN_RFKILL_TYPE_WLAN 1 #define KERN_RFKILL_TYPE_WWAN 5 struct rfkill_event { - __u32 idx; - __u8 type; - __u8 op; - __u8 soft, hard; + __u32 idx; + __u8 type; + __u8 op; + __u8 soft, hard; } _nm_packed; static void -rfkill_change (NMManager *self, const char *desc, RfKillType rtype, gboolean enabled) -{ - int fd; - struct rfkill_event event; - ssize_t len; - int errsv; - - g_return_if_fail (rtype == RFKILL_TYPE_WLAN || rtype == RFKILL_TYPE_WWAN); - - fd = open ("/dev/rfkill", O_RDWR | O_CLOEXEC); - if (fd < 0) { - if (errno == EACCES) - _LOGW (LOGD_RFKILL, "rfkill: (%s): failed to open killswitch device", desc); - return; - } - - if (fcntl (fd, F_SETFL, O_NONBLOCK) < 0) { - _LOGW (LOGD_RFKILL, "rfkill: (%s): failed to set killswitch device for " - "non-blocking operation", desc); - nm_close (fd); - return; - } - - memset (&event, 0, sizeof (event)); - event.op = KERN_RFKILL_OP_CHANGE_ALL; - switch (rtype) { - case RFKILL_TYPE_WLAN: - event.type = KERN_RFKILL_TYPE_WLAN; - break; - case RFKILL_TYPE_WWAN: - event.type = KERN_RFKILL_TYPE_WWAN; - break; - default: - g_assert_not_reached (); - } - event.soft = enabled ? 0 : 1; - - len = write (fd, &event, sizeof (event)); - if (len < 0) { - errsv = errno; - _LOGW (LOGD_RFKILL, "rfkill: (%s): failed to change Wi-Fi killswitch state: (%d) %s", - desc, errsv, nm_strerror_native (errsv)); - } else if (len == sizeof (event)) { - _LOGI (LOGD_RFKILL, "rfkill: %s hardware radio set %s", - desc, enabled ? "enabled" : "disabled"); - } else { - /* Failed to write full structure */ - _LOGW (LOGD_RFKILL, "rfkill: (%s): failed to change Wi-Fi killswitch state", desc); - } - - nm_close (fd); +rfkill_change(NMManager *self, const char *desc, RfKillType rtype, gboolean enabled) +{ + int fd; + struct rfkill_event event; + ssize_t len; + int errsv; + + g_return_if_fail(rtype == RFKILL_TYPE_WLAN || rtype == RFKILL_TYPE_WWAN); + + fd = open("/dev/rfkill", O_RDWR | O_CLOEXEC); + if (fd < 0) { + if (errno == EACCES) + _LOGW(LOGD_RFKILL, "rfkill: (%s): failed to open killswitch device", desc); + return; + } + + if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { + _LOGW(LOGD_RFKILL, + "rfkill: (%s): failed to set killswitch device for " + "non-blocking operation", + desc); + nm_close(fd); + return; + } + + memset(&event, 0, sizeof(event)); + event.op = KERN_RFKILL_OP_CHANGE_ALL; + switch (rtype) { + case RFKILL_TYPE_WLAN: + event.type = KERN_RFKILL_TYPE_WLAN; + break; + case RFKILL_TYPE_WWAN: + event.type = KERN_RFKILL_TYPE_WWAN; + break; + default: + g_assert_not_reached(); + } + event.soft = enabled ? 0 : 1; + + len = write(fd, &event, sizeof(event)); + if (len < 0) { + errsv = errno; + _LOGW(LOGD_RFKILL, + "rfkill: (%s): failed to change Wi-Fi killswitch state: (%d) %s", + desc, + errsv, + nm_strerror_native(errsv)); + } else if (len == sizeof(event)) { + _LOGI(LOGD_RFKILL, + "rfkill: %s hardware radio set %s", + desc, + enabled ? "enabled" : "disabled"); + } else { + /* Failed to write full structure */ + _LOGW(LOGD_RFKILL, "rfkill: (%s): failed to change Wi-Fi killswitch state", desc); + } + + nm_close(fd); } static void -manager_radio_user_toggled (NMManager *self, - RadioState *rstate, - gboolean enabled) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - gboolean old_enabled, new_enabled; - - /* Don't touch devices if asleep/networking disabled */ - if (manager_sleeping (self)) - return; - - if (rstate->desc) { - _LOGD (LOGD_RFKILL, "rfkill: (%s): setting radio %s by user", - rstate->desc, - enabled ? "enabled" : "disabled"); - } - - /* Update enabled key in state file */ - nm_config_state_set (priv->config, TRUE, FALSE, - rstate->key, enabled); - - /* When the user toggles the radio, their request should override any - * daemon (like ModemManager) enabled state that can be changed. For WWAN - * for example, we want the WwanEnabled property to reflect the daemon state - * too so that users can toggle the modem powered, but we don't want that - * daemon state to affect whether or not the user *can* turn it on, which is - * what the kernel rfkill state does. So we ignore daemon enabled state - * when determining what the new state should be since it shouldn't block - * the user's request. - */ - old_enabled = radio_enabled_for_rstate (rstate, TRUE); - rstate->user_enabled = enabled; - new_enabled = radio_enabled_for_rstate (rstate, FALSE); - if (new_enabled != old_enabled) { - /* Try to change the kernel rfkill state */ - if (rstate->rtype == RFKILL_TYPE_WLAN || rstate->rtype == RFKILL_TYPE_WWAN) - rfkill_change (self, rstate->desc, rstate->rtype, new_enabled); - - manager_update_radio_enabled (self, rstate, new_enabled); - } +manager_radio_user_toggled(NMManager *self, RadioState *rstate, gboolean enabled) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + gboolean old_enabled, new_enabled; + + /* Don't touch devices if asleep/networking disabled */ + if (manager_sleeping(self)) + return; + + if (rstate->desc) { + _LOGD(LOGD_RFKILL, + "rfkill: (%s): setting radio %s by user", + rstate->desc, + enabled ? "enabled" : "disabled"); + } + + /* Update enabled key in state file */ + nm_config_state_set(priv->config, TRUE, FALSE, rstate->key, enabled); + + /* When the user toggles the radio, their request should override any + * daemon (like ModemManager) enabled state that can be changed. For WWAN + * for example, we want the WwanEnabled property to reflect the daemon state + * too so that users can toggle the modem powered, but we don't want that + * daemon state to affect whether or not the user *can* turn it on, which is + * what the kernel rfkill state does. So we ignore daemon enabled state + * when determining what the new state should be since it shouldn't block + * the user's request. + */ + old_enabled = radio_enabled_for_rstate(rstate, TRUE); + rstate->user_enabled = enabled; + new_enabled = radio_enabled_for_rstate(rstate, FALSE); + if (new_enabled != old_enabled) { + /* Try to change the kernel rfkill state */ + if (rstate->rtype == RFKILL_TYPE_WLAN || rstate->rtype == RFKILL_TYPE_WWAN) + rfkill_change(self, rstate->desc, rstate->rtype, new_enabled); + + manager_update_radio_enabled(self, rstate, new_enabled); + } } static gboolean -periodic_update_active_connection_timestamps (gpointer user_data) +periodic_update_active_connection_timestamps(gpointer user_data) { - NMManager *manager = NM_MANAGER (user_data); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - NMActiveConnection *ac; - gboolean has_time = FALSE; - guint64 t = 0; + NMManager * manager = NM_MANAGER(user_data); + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(manager); + NMActiveConnection *ac; + gboolean has_time = FALSE; + guint64 t = 0; - c_list_for_each_entry (ac, &priv->active_connections_lst_head, active_connections_lst) { - if (nm_active_connection_get_state (ac) != NM_ACTIVE_CONNECTION_STATE_ACTIVATED) - continue; + c_list_for_each_entry (ac, &priv->active_connections_lst_head, active_connections_lst) { + if (nm_active_connection_get_state(ac) != NM_ACTIVE_CONNECTION_STATE_ACTIVATED) + continue; - if (!has_time) { - t = time (NULL); - has_time = TRUE; - } - nm_settings_connection_update_timestamp (nm_active_connection_get_settings_connection (ac), - t); - } - return G_SOURCE_CONTINUE; + if (!has_time) { + t = time(NULL); + has_time = TRUE; + } + nm_settings_connection_update_timestamp(nm_active_connection_get_settings_connection(ac), + t); + } + return G_SOURCE_CONTINUE; } /*****************************************************************************/ void -nm_manager_set_capability (NMManager *self, - NMCapability cap) +nm_manager_set_capability(NMManager *self, NMCapability cap) { - NMManagerPrivate *priv; - guint32 cap_i; - gssize idx; + NMManagerPrivate *priv; + guint32 cap_i; + gssize idx; - g_return_if_fail (NM_IS_MANAGER (self)); - if (cap < 1 || cap > _NM_CAPABILITY_MAX) - g_return_if_reached (); + g_return_if_fail(NM_IS_MANAGER(self)); + if (cap < 1 || cap > _NM_CAPABILITY_MAX) + g_return_if_reached(); - cap_i = (guint32) cap; + cap_i = (guint32) cap; - priv = NM_MANAGER_GET_PRIVATE (self); + priv = NM_MANAGER_GET_PRIVATE(self); - idx = nm_utils_array_find_binary_search (&g_array_index (priv->capabilities, guint32, 0), - sizeof (guint32), - priv->capabilities->len, - &cap_i, - nm_cmp_uint32_p_with_data, - NULL); - if (idx >= 0) - return; + idx = nm_utils_array_find_binary_search(&g_array_index(priv->capabilities, guint32, 0), + sizeof(guint32), + priv->capabilities->len, + &cap_i, + nm_cmp_uint32_p_with_data, + NULL); + if (idx >= 0) + return; - nm_assert ((~idx) <= (gssize) priv->capabilities->len); + nm_assert((~idx) <= (gssize) priv->capabilities->len); - g_array_insert_val (priv->capabilities, ~idx, cap_i); - _notify (self, PROP_CAPABILITIES); + g_array_insert_val(priv->capabilities, ~idx, cap_i); + _notify(self, PROP_CAPABILITIES); } /*****************************************************************************/ -NM_DEFINE_SINGLETON_REGISTER (NMManager); +NM_DEFINE_SINGLETON_REGISTER(NMManager); NMManager * -nm_manager_get (void) +nm_manager_get(void) { - g_return_val_if_fail (singleton_instance, NULL); - return singleton_instance; + g_return_val_if_fail(singleton_instance, NULL); + return singleton_instance; } NMSettings * -nm_settings_get (void) +nm_settings_get(void) { - g_return_val_if_fail (singleton_instance, NULL); + g_return_val_if_fail(singleton_instance, NULL); - return NM_MANAGER_GET_PRIVATE (singleton_instance)->settings; + return NM_MANAGER_GET_PRIVATE(singleton_instance)->settings; } NMManager * -nm_manager_setup (void) +nm_manager_setup(void) { - NMManager *self; + NMManager *self; - g_return_val_if_fail (!singleton_instance, singleton_instance); + g_return_val_if_fail(!singleton_instance, singleton_instance); - self = g_object_new (NM_TYPE_MANAGER, NULL); - nm_assert (NM_IS_MANAGER (self)); - singleton_instance = self; + self = g_object_new(NM_TYPE_MANAGER, NULL); + nm_assert(NM_IS_MANAGER(self)); + singleton_instance = self; - nm_singleton_instance_register (); - nm_log_dbg (LOGD_CORE, "setup %s singleton ("NM_HASH_OBFUSCATE_PTR_FMT")", - "NMManager", NM_HASH_OBFUSCATE_PTR (singleton_instance)); + nm_singleton_instance_register(); + nm_log_dbg(LOGD_CORE, + "setup %s singleton (" NM_HASH_OBFUSCATE_PTR_FMT ")", + "NMManager", + NM_HASH_OBFUSCATE_PTR(singleton_instance)); - nm_dbus_object_export (NM_DBUS_OBJECT (self)); - return self; + nm_dbus_object_export(NM_DBUS_OBJECT(self)); + return self; } static void -constructed (GObject *object) -{ - NMManager *self = NM_MANAGER (object); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - const NMConfigState *state; - - G_OBJECT_CLASS (nm_manager_parent_class)->constructed (object); - - priv->settings = nm_settings_new (self); - - nm_dbus_object_export (NM_DBUS_OBJECT (priv->settings)); - - g_signal_connect (priv->settings, "notify::" NM_SETTINGS_STARTUP_COMPLETE, - G_CALLBACK (settings_startup_complete_changed), self); - g_signal_connect (priv->settings, "notify::" NM_SETTINGS_UNMANAGED_SPECS, - G_CALLBACK (system_unmanaged_devices_changed_cb), self); - g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_FLAGS_CHANGED, G_CALLBACK (connection_flags_changed), self); - - priv->hostname_manager = g_object_ref (nm_hostname_manager_get ()); - g_signal_connect (priv->hostname_manager, "notify::" NM_HOSTNAME_MANAGER_HOSTNAME, - G_CALLBACK (hostname_changed_cb), self); - - /* - * Do not delete existing virtual devices to keep connectivity up. - * Virtual devices are reused when NetworkManager is restarted. - * Hence, don't react on NM_SETTINGS_SIGNAL_CONNECTION_REMOVED. - */ - - priv->policy = nm_policy_new (self, priv->settings); - g_signal_connect (priv->policy, "notify::" NM_POLICY_DEFAULT_IP4_AC, - G_CALLBACK (policy_default_ac_changed), self); - g_signal_connect (priv->policy, "notify::" NM_POLICY_DEFAULT_IP6_AC, - G_CALLBACK (policy_default_ac_changed), self); - g_signal_connect (priv->policy, "notify::" NM_POLICY_ACTIVATING_IP4_AC, - G_CALLBACK (policy_activating_ac_changed), self); - g_signal_connect (priv->policy, "notify::" NM_POLICY_ACTIVATING_IP6_AC, - G_CALLBACK (policy_activating_ac_changed), self); - - priv->config = g_object_ref (nm_config_get ()); - g_signal_connect (G_OBJECT (priv->config), - NM_CONFIG_SIGNAL_CONFIG_CHANGED, - G_CALLBACK (_config_changed_cb), - self); - - state = nm_config_state_get (priv->config); - - priv->net_enabled = state->net_enabled; - - priv->radio_states[RFKILL_TYPE_WLAN].user_enabled = state->wifi_enabled; - priv->radio_states[RFKILL_TYPE_WWAN].user_enabled = state->wwan_enabled; - - priv->rfkill_mgr = nm_rfkill_manager_new (); - g_signal_connect (priv->rfkill_mgr, - NM_RFKILL_MANAGER_SIGNAL_RFKILL_CHANGED, - G_CALLBACK (rfkill_manager_rfkill_changed_cb), - self); - - /* Force kernel Wi-Fi/WWAN rfkill state to follow NM saved Wi-Fi/WWAN state - * in case the BIOS doesn't save rfkill state, and to be consistent with user - * changes to the WirelessEnabled/WWANEnabled properties which toggle kernel - * rfkill. - */ - rfkill_change (self, priv->radio_states[RFKILL_TYPE_WLAN].desc, RFKILL_TYPE_WLAN, priv->radio_states[RFKILL_TYPE_WLAN].user_enabled); - rfkill_change (self, priv->radio_states[RFKILL_TYPE_WWAN].desc, RFKILL_TYPE_WWAN, priv->radio_states[RFKILL_TYPE_WWAN].user_enabled); +constructed(GObject *object) +{ + NMManager * self = NM_MANAGER(object); + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + const NMConfigState *state; + + G_OBJECT_CLASS(nm_manager_parent_class)->constructed(object); + + priv->settings = nm_settings_new(self); + + nm_dbus_object_export(NM_DBUS_OBJECT(priv->settings)); + + g_signal_connect(priv->settings, + "notify::" NM_SETTINGS_STARTUP_COMPLETE, + G_CALLBACK(settings_startup_complete_changed), + self); + g_signal_connect(priv->settings, + "notify::" NM_SETTINGS_UNMANAGED_SPECS, + G_CALLBACK(system_unmanaged_devices_changed_cb), + self); + g_signal_connect(priv->settings, + NM_SETTINGS_SIGNAL_CONNECTION_FLAGS_CHANGED, + G_CALLBACK(connection_flags_changed), + self); + + priv->hostname_manager = g_object_ref(nm_hostname_manager_get()); + g_signal_connect(priv->hostname_manager, + "notify::" NM_HOSTNAME_MANAGER_HOSTNAME, + G_CALLBACK(hostname_changed_cb), + self); + + /* + * Do not delete existing virtual devices to keep connectivity up. + * Virtual devices are reused when NetworkManager is restarted. + * Hence, don't react on NM_SETTINGS_SIGNAL_CONNECTION_REMOVED. + */ + + priv->policy = nm_policy_new(self, priv->settings); + g_signal_connect(priv->policy, + "notify::" NM_POLICY_DEFAULT_IP4_AC, + G_CALLBACK(policy_default_ac_changed), + self); + g_signal_connect(priv->policy, + "notify::" NM_POLICY_DEFAULT_IP6_AC, + G_CALLBACK(policy_default_ac_changed), + self); + g_signal_connect(priv->policy, + "notify::" NM_POLICY_ACTIVATING_IP4_AC, + G_CALLBACK(policy_activating_ac_changed), + self); + g_signal_connect(priv->policy, + "notify::" NM_POLICY_ACTIVATING_IP6_AC, + G_CALLBACK(policy_activating_ac_changed), + self); + + priv->config = g_object_ref(nm_config_get()); + g_signal_connect(G_OBJECT(priv->config), + NM_CONFIG_SIGNAL_CONFIG_CHANGED, + G_CALLBACK(_config_changed_cb), + self); + + state = nm_config_state_get(priv->config); + + priv->net_enabled = state->net_enabled; + + priv->radio_states[RFKILL_TYPE_WLAN].user_enabled = state->wifi_enabled; + priv->radio_states[RFKILL_TYPE_WWAN].user_enabled = state->wwan_enabled; + + priv->rfkill_mgr = nm_rfkill_manager_new(); + g_signal_connect(priv->rfkill_mgr, + NM_RFKILL_MANAGER_SIGNAL_RFKILL_CHANGED, + G_CALLBACK(rfkill_manager_rfkill_changed_cb), + self); + + /* Force kernel Wi-Fi/WWAN rfkill state to follow NM saved Wi-Fi/WWAN state + * in case the BIOS doesn't save rfkill state, and to be consistent with user + * changes to the WirelessEnabled/WWANEnabled properties which toggle kernel + * rfkill. + */ + rfkill_change(self, + priv->radio_states[RFKILL_TYPE_WLAN].desc, + RFKILL_TYPE_WLAN, + priv->radio_states[RFKILL_TYPE_WLAN].user_enabled); + rfkill_change(self, + priv->radio_states[RFKILL_TYPE_WWAN].desc, + RFKILL_TYPE_WWAN, + priv->radio_states[RFKILL_TYPE_WWAN].user_enabled); } static void -nm_manager_init (NMManager *self) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - guint i; - GFile *file; - - c_list_init (&priv->auth_lst_head); - c_list_init (&priv->link_cb_lst); - c_list_init (&priv->devices_lst_head); - c_list_init (&priv->active_connections_lst_head); - c_list_init (&priv->async_op_lst_head); - c_list_init (&priv->delete_volatile_connection_lst_head); - - priv->platform = g_object_ref (NM_PLATFORM_GET); - - priv->capabilities = g_array_new (FALSE, FALSE, sizeof (guint32)); - - /* Initialize rfkill structures and states */ - memset (priv->radio_states, 0, sizeof (priv->radio_states)); - - priv->radio_states[RFKILL_TYPE_WLAN].user_enabled = TRUE; - priv->radio_states[RFKILL_TYPE_WLAN].key = NM_CONFIG_STATE_PROPERTY_WIFI_ENABLED; - priv->radio_states[RFKILL_TYPE_WLAN].prop = NM_MANAGER_WIRELESS_ENABLED; - priv->radio_states[RFKILL_TYPE_WLAN].hw_prop = NM_MANAGER_WIRELESS_HARDWARE_ENABLED; - priv->radio_states[RFKILL_TYPE_WLAN].desc = "Wi-Fi"; - priv->radio_states[RFKILL_TYPE_WLAN].rtype = RFKILL_TYPE_WLAN; - - priv->radio_states[RFKILL_TYPE_WWAN].user_enabled = TRUE; - priv->radio_states[RFKILL_TYPE_WWAN].key = NM_CONFIG_STATE_PROPERTY_WWAN_ENABLED; - priv->radio_states[RFKILL_TYPE_WWAN].prop = NM_MANAGER_WWAN_ENABLED; - priv->radio_states[RFKILL_TYPE_WWAN].hw_prop = NM_MANAGER_WWAN_HARDWARE_ENABLED; - priv->radio_states[RFKILL_TYPE_WWAN].desc = "WWAN"; - priv->radio_states[RFKILL_TYPE_WWAN].rtype = RFKILL_TYPE_WWAN; - - for (i = 0; i < RFKILL_TYPE_MAX; i++) - priv->radio_states[i].hw_enabled = TRUE; - - priv->sleeping = FALSE; - priv->state = NM_STATE_DISCONNECTED; - priv->startup = TRUE; - - /* sleep/wake handling */ - priv->sleep_monitor = nm_sleep_monitor_new (); - g_signal_connect (priv->sleep_monitor, NM_SLEEP_MONITOR_SLEEPING, - G_CALLBACK (sleeping_cb), self); - - /* Listen for authorization changes */ - priv->auth_mgr = g_object_ref (nm_auth_manager_get ()); - g_signal_connect (priv->auth_mgr, - NM_AUTH_MANAGER_SIGNAL_CHANGED, - G_CALLBACK (auth_mgr_changed), - self); - - /* Monitor the firmware directory */ - if (strlen (KERNEL_FIRMWARE_DIR)) { - file = g_file_new_for_path (KERNEL_FIRMWARE_DIR "/"); - priv->fw_monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL); - g_object_unref (file); - } - - if (priv->fw_monitor) { - g_signal_connect (priv->fw_monitor, "changed", - G_CALLBACK (firmware_dir_changed), - self); - _LOGI (LOGD_CORE, "monitoring kernel firmware directory '%s'.", - KERNEL_FIRMWARE_DIR); - } else { - _LOGW (LOGD_CORE, "failed to monitor kernel firmware directory '%s'.", - KERNEL_FIRMWARE_DIR); - } - - /* Update timestamps in active connections */ - priv->timestamp_update_id = g_timeout_add_seconds (300, (GSourceFunc) periodic_update_active_connection_timestamps, self); - - priv->metered = NM_METERED_UNKNOWN; - priv->sleep_devices = g_hash_table_new (nm_direct_hash, NULL); +nm_manager_init(NMManager *self) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + guint i; + GFile * file; + + c_list_init(&priv->auth_lst_head); + c_list_init(&priv->link_cb_lst); + c_list_init(&priv->devices_lst_head); + c_list_init(&priv->active_connections_lst_head); + c_list_init(&priv->async_op_lst_head); + c_list_init(&priv->delete_volatile_connection_lst_head); + + priv->platform = g_object_ref(NM_PLATFORM_GET); + + priv->capabilities = g_array_new(FALSE, FALSE, sizeof(guint32)); + + /* Initialize rfkill structures and states */ + memset(priv->radio_states, 0, sizeof(priv->radio_states)); + + priv->radio_states[RFKILL_TYPE_WLAN].user_enabled = TRUE; + priv->radio_states[RFKILL_TYPE_WLAN].key = NM_CONFIG_STATE_PROPERTY_WIFI_ENABLED; + priv->radio_states[RFKILL_TYPE_WLAN].prop = NM_MANAGER_WIRELESS_ENABLED; + priv->radio_states[RFKILL_TYPE_WLAN].hw_prop = NM_MANAGER_WIRELESS_HARDWARE_ENABLED; + priv->radio_states[RFKILL_TYPE_WLAN].desc = "Wi-Fi"; + priv->radio_states[RFKILL_TYPE_WLAN].rtype = RFKILL_TYPE_WLAN; + + priv->radio_states[RFKILL_TYPE_WWAN].user_enabled = TRUE; + priv->radio_states[RFKILL_TYPE_WWAN].key = NM_CONFIG_STATE_PROPERTY_WWAN_ENABLED; + priv->radio_states[RFKILL_TYPE_WWAN].prop = NM_MANAGER_WWAN_ENABLED; + priv->radio_states[RFKILL_TYPE_WWAN].hw_prop = NM_MANAGER_WWAN_HARDWARE_ENABLED; + priv->radio_states[RFKILL_TYPE_WWAN].desc = "WWAN"; + priv->radio_states[RFKILL_TYPE_WWAN].rtype = RFKILL_TYPE_WWAN; + + for (i = 0; i < RFKILL_TYPE_MAX; i++) + priv->radio_states[i].hw_enabled = TRUE; + + priv->sleeping = FALSE; + priv->state = NM_STATE_DISCONNECTED; + priv->startup = TRUE; + + /* sleep/wake handling */ + priv->sleep_monitor = nm_sleep_monitor_new(); + g_signal_connect(priv->sleep_monitor, NM_SLEEP_MONITOR_SLEEPING, G_CALLBACK(sleeping_cb), self); + + /* Listen for authorization changes */ + priv->auth_mgr = g_object_ref(nm_auth_manager_get()); + g_signal_connect(priv->auth_mgr, + NM_AUTH_MANAGER_SIGNAL_CHANGED, + G_CALLBACK(auth_mgr_changed), + self); + + /* Monitor the firmware directory */ + if (strlen(KERNEL_FIRMWARE_DIR)) { + file = g_file_new_for_path(KERNEL_FIRMWARE_DIR "/"); + priv->fw_monitor = g_file_monitor_directory(file, G_FILE_MONITOR_NONE, NULL, NULL); + g_object_unref(file); + } + + if (priv->fw_monitor) { + g_signal_connect(priv->fw_monitor, "changed", G_CALLBACK(firmware_dir_changed), self); + _LOGI(LOGD_CORE, "monitoring kernel firmware directory '%s'.", KERNEL_FIRMWARE_DIR); + } else { + _LOGW(LOGD_CORE, "failed to monitor kernel firmware directory '%s'.", KERNEL_FIRMWARE_DIR); + } + + /* Update timestamps in active connections */ + priv->timestamp_update_id = + g_timeout_add_seconds(300, + (GSourceFunc) periodic_update_active_connection_timestamps, + self); + + priv->metered = NM_METERED_UNKNOWN; + priv->sleep_devices = g_hash_table_new(nm_direct_hash, NULL); } static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMManager *self = NM_MANAGER (object); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMConfigData *config_data; - const NMGlobalDnsConfig *dns_config; - const char *type; - const char *path; - NMActiveConnection *ac; - GPtrArray *ptrarr; - - switch (prop_id) { - case PROP_VERSION: - g_value_set_string (value, VERSION); - break; - case PROP_CAPABILITIES: - g_value_set_variant (value, g_variant_new_fixed_array (G_VARIANT_TYPE ("u"), - priv->capabilities->data, - priv->capabilities->len, - sizeof (guint32))); - break; - case PROP_STATE: - g_value_set_uint (value, priv->state); - break; - case PROP_STARTUP: - g_value_set_boolean (value, priv->startup); - break; - case PROP_NETWORKING_ENABLED: - g_value_set_boolean (value, priv->net_enabled); - break; - case PROP_WIRELESS_ENABLED: - g_value_set_boolean (value, radio_enabled_for_type (self, RFKILL_TYPE_WLAN, TRUE)); - break; - case PROP_WIRELESS_HARDWARE_ENABLED: - g_value_set_boolean (value, priv->radio_states[RFKILL_TYPE_WLAN].hw_enabled); - break; - case PROP_WWAN_ENABLED: - g_value_set_boolean (value, radio_enabled_for_type (self, RFKILL_TYPE_WWAN, TRUE)); - break; - case PROP_WWAN_HARDWARE_ENABLED: - g_value_set_boolean (value, priv->radio_states[RFKILL_TYPE_WWAN].hw_enabled); - break; - case PROP_WIMAX_ENABLED: - g_value_set_boolean (value, FALSE); - break; - case PROP_WIMAX_HARDWARE_ENABLED: - g_value_set_boolean (value, FALSE); - break; - case PROP_ACTIVE_CONNECTIONS: - ptrarr = g_ptr_array_new (); - c_list_for_each_entry (ac, &priv->active_connections_lst_head, active_connections_lst) { - path = nm_dbus_object_get_path (NM_DBUS_OBJECT (ac)); - if (path) - g_ptr_array_add (ptrarr, g_strdup (path)); - } - g_ptr_array_add (ptrarr, NULL); - g_value_take_boxed (value, g_ptr_array_free (ptrarr, FALSE)); - break; - case PROP_CONNECTIVITY: - g_value_set_uint (value, priv->connectivity_state); - break; - case PROP_CONNECTIVITY_CHECK_AVAILABLE: - config_data = nm_config_get_data (priv->config); - g_value_set_boolean (value, nm_config_data_get_connectivity_uri (config_data) != NULL); - break; - case PROP_CONNECTIVITY_CHECK_ENABLED: - g_value_set_boolean (value, concheck_enabled (self, NULL)); - break; - case PROP_CONNECTIVITY_CHECK_URI: - config_data = nm_config_get_data (priv->config); - g_value_set_string (value, nm_config_data_get_connectivity_uri (config_data)); - break; - case PROP_PRIMARY_CONNECTION: - nm_dbus_utils_g_value_set_object_path (value, priv->primary_connection); - break; - case PROP_PRIMARY_CONNECTION_TYPE: - type = NULL; - if (priv->primary_connection) { - NMConnection *con; - - con = nm_active_connection_get_applied_connection (priv->primary_connection); - if (con) - type = nm_connection_get_connection_type (con); - } - g_value_set_string (value, type ?: ""); - break; - case PROP_ACTIVATING_CONNECTION: - nm_dbus_utils_g_value_set_object_path (value, priv->activating_connection); - break; - case PROP_SLEEPING: - g_value_set_boolean (value, priv->sleeping); - break; - case PROP_DEVICES: - g_value_take_boxed (value, - nm_utils_strv_make_deep_copied (_get_devices_paths (self, - FALSE))); - break; - case PROP_METERED: - g_value_set_uint (value, priv->metered); - break; - case PROP_GLOBAL_DNS_CONFIGURATION: - config_data = nm_config_get_data (priv->config); - dns_config = nm_config_data_get_global_dns_config (config_data); - nm_global_dns_config_to_dbus (dns_config, value); - break; - case PROP_ALL_DEVICES: - g_value_take_boxed (value, - nm_utils_strv_make_deep_copied (_get_devices_paths (self, - TRUE))); - break; - case PROP_CHECKPOINTS: - g_value_take_boxed (value, - priv->checkpoint_mgr - ? nm_utils_strv_make_deep_copied (nm_checkpoint_manager_get_checkpoint_paths (priv->checkpoint_mgr, - NULL)) - : NULL); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMManager * self = NM_MANAGER(object); + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + NMConfigData * config_data; + const NMGlobalDnsConfig *dns_config; + const char * type; + const char * path; + NMActiveConnection * ac; + GPtrArray * ptrarr; + + switch (prop_id) { + case PROP_VERSION: + g_value_set_string(value, VERSION); + break; + case PROP_CAPABILITIES: + g_value_set_variant(value, + g_variant_new_fixed_array(G_VARIANT_TYPE("u"), + priv->capabilities->data, + priv->capabilities->len, + sizeof(guint32))); + break; + case PROP_STATE: + g_value_set_uint(value, priv->state); + break; + case PROP_STARTUP: + g_value_set_boolean(value, priv->startup); + break; + case PROP_NETWORKING_ENABLED: + g_value_set_boolean(value, priv->net_enabled); + break; + case PROP_WIRELESS_ENABLED: + g_value_set_boolean(value, radio_enabled_for_type(self, RFKILL_TYPE_WLAN, TRUE)); + break; + case PROP_WIRELESS_HARDWARE_ENABLED: + g_value_set_boolean(value, priv->radio_states[RFKILL_TYPE_WLAN].hw_enabled); + break; + case PROP_WWAN_ENABLED: + g_value_set_boolean(value, radio_enabled_for_type(self, RFKILL_TYPE_WWAN, TRUE)); + break; + case PROP_WWAN_HARDWARE_ENABLED: + g_value_set_boolean(value, priv->radio_states[RFKILL_TYPE_WWAN].hw_enabled); + break; + case PROP_WIMAX_ENABLED: + g_value_set_boolean(value, FALSE); + break; + case PROP_WIMAX_HARDWARE_ENABLED: + g_value_set_boolean(value, FALSE); + break; + case PROP_ACTIVE_CONNECTIONS: + ptrarr = g_ptr_array_new(); + c_list_for_each_entry (ac, &priv->active_connections_lst_head, active_connections_lst) { + path = nm_dbus_object_get_path(NM_DBUS_OBJECT(ac)); + if (path) + g_ptr_array_add(ptrarr, g_strdup(path)); + } + g_ptr_array_add(ptrarr, NULL); + g_value_take_boxed(value, g_ptr_array_free(ptrarr, FALSE)); + break; + case PROP_CONNECTIVITY: + g_value_set_uint(value, priv->connectivity_state); + break; + case PROP_CONNECTIVITY_CHECK_AVAILABLE: + config_data = nm_config_get_data(priv->config); + g_value_set_boolean(value, nm_config_data_get_connectivity_uri(config_data) != NULL); + break; + case PROP_CONNECTIVITY_CHECK_ENABLED: + g_value_set_boolean(value, concheck_enabled(self, NULL)); + break; + case PROP_CONNECTIVITY_CHECK_URI: + config_data = nm_config_get_data(priv->config); + g_value_set_string(value, nm_config_data_get_connectivity_uri(config_data)); + break; + case PROP_PRIMARY_CONNECTION: + nm_dbus_utils_g_value_set_object_path(value, priv->primary_connection); + break; + case PROP_PRIMARY_CONNECTION_TYPE: + type = NULL; + if (priv->primary_connection) { + NMConnection *con; + + con = nm_active_connection_get_applied_connection(priv->primary_connection); + if (con) + type = nm_connection_get_connection_type(con); + } + g_value_set_string(value, type ?: ""); + break; + case PROP_ACTIVATING_CONNECTION: + nm_dbus_utils_g_value_set_object_path(value, priv->activating_connection); + break; + case PROP_SLEEPING: + g_value_set_boolean(value, priv->sleeping); + break; + case PROP_DEVICES: + g_value_take_boxed(value, nm_utils_strv_make_deep_copied(_get_devices_paths(self, FALSE))); + break; + case PROP_METERED: + g_value_set_uint(value, priv->metered); + break; + case PROP_GLOBAL_DNS_CONFIGURATION: + config_data = nm_config_get_data(priv->config); + dns_config = nm_config_data_get_global_dns_config(config_data); + nm_global_dns_config_to_dbus(dns_config, value); + break; + case PROP_ALL_DEVICES: + g_value_take_boxed(value, nm_utils_strv_make_deep_copied(_get_devices_paths(self, TRUE))); + break; + case PROP_CHECKPOINTS: + g_value_take_boxed( + value, + priv->checkpoint_mgr ? nm_utils_strv_make_deep_copied( + nm_checkpoint_manager_get_checkpoint_paths(priv->checkpoint_mgr, NULL)) + : NULL); + 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) -{ - NMManager *self = NM_MANAGER (object); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMGlobalDnsConfig *dns_config; - GError *error = NULL; - - switch (prop_id) { - case PROP_WIRELESS_ENABLED: - manager_radio_user_toggled (NM_MANAGER (object), - &priv->radio_states[RFKILL_TYPE_WLAN], - g_value_get_boolean (value)); - break; - case PROP_WWAN_ENABLED: - manager_radio_user_toggled (NM_MANAGER (object), - &priv->radio_states[RFKILL_TYPE_WWAN], - g_value_get_boolean (value)); - break; - case PROP_WIMAX_ENABLED: - /* WIMAX is deprecated. This does nothing. */ - break; - case PROP_CONNECTIVITY_CHECK_ENABLED: - nm_config_set_connectivity_check_enabled (priv->config, - g_value_get_boolean (value)); - break; - case PROP_GLOBAL_DNS_CONFIGURATION: - dns_config = nm_global_dns_config_from_dbus (value, &error); - if (!error) - nm_config_set_global_dns (priv->config, dns_config, &error); - - nm_global_dns_config_free (dns_config); - - if (error) { - _LOGD (LOGD_CORE, "set global DNS failed with error: %s", error->message); - g_error_free (error); - } - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMManager * self = NM_MANAGER(object); + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); + NMGlobalDnsConfig *dns_config; + GError * error = NULL; + + switch (prop_id) { + case PROP_WIRELESS_ENABLED: + manager_radio_user_toggled(NM_MANAGER(object), + &priv->radio_states[RFKILL_TYPE_WLAN], + g_value_get_boolean(value)); + break; + case PROP_WWAN_ENABLED: + manager_radio_user_toggled(NM_MANAGER(object), + &priv->radio_states[RFKILL_TYPE_WWAN], + g_value_get_boolean(value)); + break; + case PROP_WIMAX_ENABLED: + /* WIMAX is deprecated. This does nothing. */ + break; + case PROP_CONNECTIVITY_CHECK_ENABLED: + nm_config_set_connectivity_check_enabled(priv->config, g_value_get_boolean(value)); + break; + case PROP_GLOBAL_DNS_CONFIGURATION: + dns_config = nm_global_dns_config_from_dbus(value, &error); + if (!error) + nm_config_set_global_dns(priv->config, dns_config, &error); + + nm_global_dns_config_free(dns_config); + + if (error) { + _LOGD(LOGD_CORE, "set global DNS failed with error: %s", error->message); + g_error_free(error); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } } static void -_deinit_device_factory (NMDeviceFactory *factory, gpointer user_data) +_deinit_device_factory(NMDeviceFactory *factory, gpointer user_data) { - g_signal_handlers_disconnect_matched (factory, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, NM_MANAGER (user_data)); + g_signal_handlers_disconnect_matched(factory, + G_SIGNAL_MATCH_DATA, + 0, + 0, + NULL, + NULL, + NM_MANAGER(user_data)); } static void -dispose (GObject *object) -{ - NMManager *self = NM_MANAGER (object); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - CList *iter; - - nm_assert (c_list_is_empty (&priv->async_op_lst_head)); - - g_signal_handlers_disconnect_by_func (priv->platform, - G_CALLBACK (platform_link_cb), - self); - while ((iter = c_list_first (&priv->link_cb_lst))) { - PlatformLinkCbData *data = c_list_entry (iter, PlatformLinkCbData, lst); +dispose(GObject *object) +{ + NMManager * self = NM_MANAGER(object); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + CList * iter; + + nm_assert(c_list_is_empty(&priv->async_op_lst_head)); + + g_signal_handlers_disconnect_by_func(priv->platform, G_CALLBACK(platform_link_cb), self); + while ((iter = c_list_first(&priv->link_cb_lst))) { + PlatformLinkCbData *data = c_list_entry(iter, PlatformLinkCbData, lst); - g_source_remove (data->idle_id); - c_list_unlink_stale (&data->lst); - g_slice_free (PlatformLinkCbData, data); - } + g_source_remove(data->idle_id); + c_list_unlink_stale(&data->lst); + g_slice_free(PlatformLinkCbData, data); + } - while ((iter = c_list_first (&priv->auth_lst_head))) - nm_auth_chain_destroy (nm_auth_chain_parent_lst_entry (iter)); + while ((iter = c_list_first(&priv->auth_lst_head))) + nm_auth_chain_destroy(nm_auth_chain_parent_lst_entry(iter)); - nm_clear_g_source (&priv->devices_inited_id); + nm_clear_g_source(&priv->devices_inited_id); - nm_clear_pointer (&priv->checkpoint_mgr, nm_checkpoint_manager_free); + nm_clear_pointer(&priv->checkpoint_mgr, nm_checkpoint_manager_free); - if (priv->concheck_mgr) { - g_signal_handlers_disconnect_by_func (priv->concheck_mgr, - G_CALLBACK (concheck_config_changed_cb), - self); - g_clear_object (&priv->concheck_mgr); - } + if (priv->concheck_mgr) { + g_signal_handlers_disconnect_by_func(priv->concheck_mgr, + G_CALLBACK(concheck_config_changed_cb), + self); + g_clear_object(&priv->concheck_mgr); + } - if (priv->auth_mgr) { - g_signal_handlers_disconnect_by_func (priv->auth_mgr, - G_CALLBACK (auth_mgr_changed), - self); - g_clear_object (&priv->auth_mgr); - } + if (priv->auth_mgr) { + g_signal_handlers_disconnect_by_func(priv->auth_mgr, G_CALLBACK(auth_mgr_changed), self); + g_clear_object(&priv->auth_mgr); + } - nm_assert (c_list_is_empty (&priv->devices_lst_head)); + nm_assert(c_list_is_empty(&priv->devices_lst_head)); - nm_clear_g_source (&priv->ac_cleanup_id); + nm_clear_g_source(&priv->ac_cleanup_id); - while ((iter = c_list_first (&priv->active_connections_lst_head))) - active_connection_remove (self, c_list_entry (iter, NMActiveConnection, active_connections_lst)); + while ((iter = c_list_first(&priv->active_connections_lst_head))) + active_connection_remove(self, + c_list_entry(iter, NMActiveConnection, active_connections_lst)); - nm_assert (c_list_is_empty (&priv->active_connections_lst_head)); - g_clear_object (&priv->primary_connection); - g_clear_object (&priv->activating_connection); + nm_assert(c_list_is_empty(&priv->active_connections_lst_head)); + g_clear_object(&priv->primary_connection); + g_clear_object(&priv->activating_connection); - if (priv->config) { - g_signal_handlers_disconnect_by_func (priv->config, _config_changed_cb, self); - g_clear_object (&priv->config); - } + if (priv->config) { + g_signal_handlers_disconnect_by_func(priv->config, _config_changed_cb, self); + g_clear_object(&priv->config); + } - if (priv->policy) { - g_signal_handlers_disconnect_by_func (priv->policy, policy_default_ac_changed, self); - g_signal_handlers_disconnect_by_func (priv->policy, policy_activating_ac_changed, self); - g_clear_object (&priv->policy); - } + if (priv->policy) { + g_signal_handlers_disconnect_by_func(priv->policy, policy_default_ac_changed, self); + g_signal_handlers_disconnect_by_func(priv->policy, policy_activating_ac_changed, self); + g_clear_object(&priv->policy); + } - if (priv->settings) { - g_signal_handlers_disconnect_by_func (priv->settings, settings_startup_complete_changed, self); - g_signal_handlers_disconnect_by_func (priv->settings, system_unmanaged_devices_changed_cb, self); - g_signal_handlers_disconnect_by_func (priv->settings, connection_added_cb, self); - g_signal_handlers_disconnect_by_func (priv->settings, connection_updated_cb, self); - g_signal_handlers_disconnect_by_func (priv->settings, connection_flags_changed, self); - g_clear_object (&priv->settings); - } + if (priv->settings) { + g_signal_handlers_disconnect_by_func(priv->settings, + settings_startup_complete_changed, + self); + g_signal_handlers_disconnect_by_func(priv->settings, + system_unmanaged_devices_changed_cb, + self); + g_signal_handlers_disconnect_by_func(priv->settings, connection_added_cb, self); + g_signal_handlers_disconnect_by_func(priv->settings, connection_updated_cb, self); + g_signal_handlers_disconnect_by_func(priv->settings, connection_flags_changed, self); + g_clear_object(&priv->settings); + } - if (priv->hostname_manager) { - g_signal_handlers_disconnect_by_func (priv->hostname_manager, hostname_changed_cb, self); - g_clear_object (&priv->hostname_manager); - } + if (priv->hostname_manager) { + g_signal_handlers_disconnect_by_func(priv->hostname_manager, hostname_changed_cb, self); + g_clear_object(&priv->hostname_manager); + } - g_clear_object (&priv->vpn_manager); + g_clear_object(&priv->vpn_manager); - sleep_devices_clear (self); - nm_clear_pointer (&priv->sleep_devices, g_hash_table_unref); + sleep_devices_clear(self); + nm_clear_pointer(&priv->sleep_devices, g_hash_table_unref); - if (priv->sleep_monitor) { - g_signal_handlers_disconnect_by_func (priv->sleep_monitor, sleeping_cb, self); - g_clear_object (&priv->sleep_monitor); - } + if (priv->sleep_monitor) { + g_signal_handlers_disconnect_by_func(priv->sleep_monitor, sleeping_cb, self); + g_clear_object(&priv->sleep_monitor); + } - if (priv->fw_monitor) { - g_signal_handlers_disconnect_by_func (priv->fw_monitor, firmware_dir_changed, self); + if (priv->fw_monitor) { + g_signal_handlers_disconnect_by_func(priv->fw_monitor, firmware_dir_changed, self); - nm_clear_g_source (&priv->fw_changed_id); + nm_clear_g_source(&priv->fw_changed_id); - g_file_monitor_cancel (priv->fw_monitor); - g_clear_object (&priv->fw_monitor); - } + g_file_monitor_cancel(priv->fw_monitor); + g_clear_object(&priv->fw_monitor); + } - if (priv->rfkill_mgr) { - g_signal_handlers_disconnect_by_func (priv->rfkill_mgr, rfkill_manager_rfkill_changed_cb, self); - g_clear_object (&priv->rfkill_mgr); - } + if (priv->rfkill_mgr) { + g_signal_handlers_disconnect_by_func(priv->rfkill_mgr, + rfkill_manager_rfkill_changed_cb, + self); + g_clear_object(&priv->rfkill_mgr); + } - nm_clear_g_source (&priv->delete_volatile_connection_idle_id); - _delete_volatile_connection_all (self, FALSE); - nm_assert (!priv->delete_volatile_connection_idle_id); - nm_assert (c_list_is_empty (&priv->delete_volatile_connection_lst_head)); + nm_clear_g_source(&priv->delete_volatile_connection_idle_id); + _delete_volatile_connection_all(self, FALSE); + nm_assert(!priv->delete_volatile_connection_idle_id); + nm_assert(c_list_is_empty(&priv->delete_volatile_connection_lst_head)); - nm_device_factory_manager_for_each_factory (_deinit_device_factory, self); + nm_device_factory_manager_for_each_factory(_deinit_device_factory, self); - nm_clear_g_source (&priv->timestamp_update_id); + nm_clear_g_source(&priv->timestamp_update_id); - nm_clear_pointer (&priv->device_route_metrics, g_hash_table_destroy); + nm_clear_pointer(&priv->device_route_metrics, g_hash_table_destroy); - G_OBJECT_CLASS (nm_manager_parent_class)->dispose (object); + G_OBJECT_CLASS(nm_manager_parent_class)->dispose(object); } static void -finalize (GObject *object) +finalize(GObject *object) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (object); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(object); - g_array_free (priv->capabilities, TRUE); + g_array_free(priv->capabilities, TRUE); - G_OBJECT_CLASS (nm_manager_parent_class)->finalize (object); + G_OBJECT_CLASS(nm_manager_parent_class)->finalize(object); - g_object_unref (priv->platform); + g_object_unref(priv->platform); } -static const GDBusSignalInfo signal_info_check_permissions = NM_DEFINE_GDBUS_SIGNAL_INFO_INIT ( - "CheckPermissions", -); +static const GDBusSignalInfo signal_info_check_permissions = + NM_DEFINE_GDBUS_SIGNAL_INFO_INIT("CheckPermissions", ); -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"), - ), -); +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"), ), ); -static const GDBusSignalInfo signal_info_device_added = NM_DEFINE_GDBUS_SIGNAL_INFO_INIT ( - "DeviceAdded", - .args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("device_path", "o"), - ), -); +static const GDBusSignalInfo signal_info_device_added = NM_DEFINE_GDBUS_SIGNAL_INFO_INIT( + "DeviceAdded", + .args = NM_DEFINE_GDBUS_ARG_INFOS(NM_DEFINE_GDBUS_ARG_INFO("device_path", "o"), ), ); -static const GDBusSignalInfo signal_info_device_removed = NM_DEFINE_GDBUS_SIGNAL_INFO_INIT ( - "DeviceRemoved", - .args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("device_path", "o"), - ), -); +static const GDBusSignalInfo signal_info_device_removed = NM_DEFINE_GDBUS_SIGNAL_INFO_INIT( + "DeviceRemoved", + .args = NM_DEFINE_GDBUS_ARG_INFOS(NM_DEFINE_GDBUS_ARG_INFO("device_path", "o"), ), ); static const NMDBusInterfaceInfoExtended interface_info_manager = { - .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( - NM_DBUS_INTERFACE, - .methods = NM_DEFINE_GDBUS_METHOD_INFOS ( - NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( - NM_DEFINE_GDBUS_METHOD_INFO_INIT ( - "Reload", - .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("flags", "u"), - ), - ), - .handle = impl_manager_reload, - ), - NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( - NM_DEFINE_GDBUS_METHOD_INFO_INIT ( - "GetDevices", - .out_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("devices", "ao"), - ), - ), - .handle = impl_manager_get_devices, - ), - NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( - NM_DEFINE_GDBUS_METHOD_INFO_INIT ( - "GetAllDevices", - .out_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("devices", "ao"), - ), - ), - .handle = impl_manager_get_all_devices, - ), - NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( - NM_DEFINE_GDBUS_METHOD_INFO_INIT ( - "GetDeviceByIpIface", - .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("iface", "s"), - ), - .out_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("device", "o"), - ), - ), - .handle = impl_manager_get_device_by_ip_iface, - ), - NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( - NM_DEFINE_GDBUS_METHOD_INFO_INIT ( - "ActivateConnection", - .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("connection", "o"), - NM_DEFINE_GDBUS_ARG_INFO ("device", "o"), - NM_DEFINE_GDBUS_ARG_INFO ("specific_object", "o"), - ), - .out_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("active_connection", "o"), - ), - ), - .handle = impl_manager_activate_connection, - ), - NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( - NM_DEFINE_GDBUS_METHOD_INFO_INIT ( - "AddAndActivateConnection", - .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("connection", "a{sa{sv}}"), - NM_DEFINE_GDBUS_ARG_INFO ("device", "o"), - NM_DEFINE_GDBUS_ARG_INFO ("specific_object", "o"), - ), - .out_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("path", "o"), - NM_DEFINE_GDBUS_ARG_INFO ("active_connection", "o"), - ), - ), - .handle = impl_manager_add_and_activate_connection, - ), - NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( - NM_DEFINE_GDBUS_METHOD_INFO_INIT ( - "AddAndActivateConnection2", - .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("connection", "a{sa{sv}}"), - NM_DEFINE_GDBUS_ARG_INFO ("device", "o"), - NM_DEFINE_GDBUS_ARG_INFO ("specific_object", "o"), - NM_DEFINE_GDBUS_ARG_INFO ("options", "a{sv}"), - ), - .out_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("path", "o"), - NM_DEFINE_GDBUS_ARG_INFO ("active_connection", "o"), - NM_DEFINE_GDBUS_ARG_INFO ("result", "a{sv}"), - ), - ), - .handle = impl_manager_add_and_activate_connection, - ), - NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( - NM_DEFINE_GDBUS_METHOD_INFO_INIT ( - "DeactivateConnection", - .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("active_connection", "o"), - ), - ), - .handle = impl_manager_deactivate_connection, - ), - NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( - NM_DEFINE_GDBUS_METHOD_INFO_INIT ( - "Sleep", - .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("sleep", "b"), - ), - ), - .handle = impl_manager_sleep, - ), - NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( - NM_DEFINE_GDBUS_METHOD_INFO_INIT ( - "Enable", - .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("enable", "b"), - ), - ), - .handle = impl_manager_enable, - ), - NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( - NM_DEFINE_GDBUS_METHOD_INFO_INIT ( - "GetPermissions", - .out_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("permissions", "a{ss}"), - ), - ), - .handle = impl_manager_get_permissions, - ), - NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( - NM_DEFINE_GDBUS_METHOD_INFO_INIT ( - "SetLogging", - .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("level", "s"), - NM_DEFINE_GDBUS_ARG_INFO ("domains", "s"), - ), - ), - .handle = impl_manager_set_logging, - ), - NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( - NM_DEFINE_GDBUS_METHOD_INFO_INIT ( - "GetLogging", - .out_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("level", "s"), - NM_DEFINE_GDBUS_ARG_INFO ("domains", "s"), - ), - ), - .handle = impl_manager_get_logging, - ), - NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( - NM_DEFINE_GDBUS_METHOD_INFO_INIT ( - "CheckConnectivity", - .out_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("connectivity", "u"), - ), - ), - .handle = impl_manager_check_connectivity, - ), - NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( - NM_DEFINE_GDBUS_METHOD_INFO_INIT ( - "state", - .out_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("state", "u"), - ), - ), - .handle = impl_manager_state, - ), - NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( - NM_DEFINE_GDBUS_METHOD_INFO_INIT ( - "CheckpointCreate", - .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("devices", "ao"), - NM_DEFINE_GDBUS_ARG_INFO ("rollback_timeout", "u"), - NM_DEFINE_GDBUS_ARG_INFO ("flags", "u"), - ), - .out_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("checkpoint", "o"), - ), - ), - .handle = impl_manager_checkpoint_create, - ), - NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( - NM_DEFINE_GDBUS_METHOD_INFO_INIT ( - "CheckpointDestroy", - .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("checkpoint", "o"), - ), - ), - .handle = impl_manager_checkpoint_destroy, - ), - NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( - NM_DEFINE_GDBUS_METHOD_INFO_INIT ( - "CheckpointRollback", - .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("checkpoint", "o"), - ), - .out_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("result", "a{su}"), - ), - ), - .handle = impl_manager_checkpoint_rollback, - ), - NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( - NM_DEFINE_GDBUS_METHOD_INFO_INIT ( - "CheckpointAdjustRollbackTimeout", - .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("checkpoint", "o"), - NM_DEFINE_GDBUS_ARG_INFO ("add_timeout", "u"), - ), - ), - .handle = impl_manager_checkpoint_adjust_rollback_timeout, - ), - ), - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( - &nm_signal_info_property_changed_legacy, - &signal_info_check_permissions, - &signal_info_state_changed, - &signal_info_device_added, - &signal_info_device_removed, - ), - .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Devices", "ao", NM_MANAGER_DEVICES), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("AllDevices", "ao", NM_MANAGER_ALL_DEVICES), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Checkpoints", "ao", NM_MANAGER_CHECKPOINTS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("NetworkingEnabled", "b", NM_MANAGER_NETWORKING_ENABLED), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE_L ("WirelessEnabled", "b", NM_MANAGER_WIRELESS_ENABLED, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI, NM_AUDIT_OP_RADIO_CONTROL), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("WirelessHardwareEnabled", "b", NM_MANAGER_WIRELESS_HARDWARE_ENABLED), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE_L ("WwanEnabled", "b", NM_MANAGER_WWAN_ENABLED, NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN, NM_AUDIT_OP_RADIO_CONTROL), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("WwanHardwareEnabled", "b", NM_MANAGER_WWAN_HARDWARE_ENABLED), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE_L ("WimaxEnabled", "b", NM_MANAGER_WIMAX_ENABLED, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX, NM_AUDIT_OP_RADIO_CONTROL), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("WimaxHardwareEnabled", "b", NM_MANAGER_WIMAX_HARDWARE_ENABLED), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("ActiveConnections", "ao", NM_MANAGER_ACTIVE_CONNECTIONS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("PrimaryConnection", "o", NM_MANAGER_PRIMARY_CONNECTION), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("PrimaryConnectionType", "s", NM_MANAGER_PRIMARY_CONNECTION_TYPE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Metered", "u", NM_MANAGER_METERED), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("ActivatingConnection", "o", NM_MANAGER_ACTIVATING_CONNECTION), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Startup", "b", NM_MANAGER_STARTUP), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Version", "s", NM_MANAGER_VERSION), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Capabilities", "u", NM_MANAGER_CAPABILITIES), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("State", "u", NM_MANAGER_STATE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Connectivity", "u", NM_MANAGER_CONNECTIVITY), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("ConnectivityCheckAvailable", "b", NM_MANAGER_CONNECTIVITY_CHECK_AVAILABLE), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE_L ("ConnectivityCheckEnabled", "b", NM_MANAGER_CONNECTIVITY_CHECK_ENABLED, NM_AUTH_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK, NM_AUDIT_OP_NET_CONTROL), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("ConnectivityCheckUri", "s", NM_MANAGER_CONNECTIVITY_CHECK_URI), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE_L ("GlobalDnsConfiguration", "a{sv}", NM_MANAGER_GLOBAL_DNS_CONFIGURATION, NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS, NM_AUDIT_OP_NET_CONTROL), - ), - ), - .legacy_property_changed = TRUE, + .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( + NM_DBUS_INTERFACE, + .methods = NM_DEFINE_GDBUS_METHOD_INFOS( + NM_DEFINE_DBUS_METHOD_INFO_EXTENDED( + NM_DEFINE_GDBUS_METHOD_INFO_INIT("Reload", + .in_args = NM_DEFINE_GDBUS_ARG_INFOS( + NM_DEFINE_GDBUS_ARG_INFO("flags", "u"), ), ), + .handle = impl_manager_reload, ), + NM_DEFINE_DBUS_METHOD_INFO_EXTENDED( + NM_DEFINE_GDBUS_METHOD_INFO_INIT( + "GetDevices", + .out_args = + NM_DEFINE_GDBUS_ARG_INFOS(NM_DEFINE_GDBUS_ARG_INFO("devices", "ao"), ), ), + .handle = impl_manager_get_devices, ), + NM_DEFINE_DBUS_METHOD_INFO_EXTENDED( + NM_DEFINE_GDBUS_METHOD_INFO_INIT( + "GetAllDevices", + .out_args = + NM_DEFINE_GDBUS_ARG_INFOS(NM_DEFINE_GDBUS_ARG_INFO("devices", "ao"), ), ), + .handle = impl_manager_get_all_devices, ), + NM_DEFINE_DBUS_METHOD_INFO_EXTENDED( + NM_DEFINE_GDBUS_METHOD_INFO_INIT( + "GetDeviceByIpIface", + .in_args = NM_DEFINE_GDBUS_ARG_INFOS(NM_DEFINE_GDBUS_ARG_INFO("iface", "s"), ), + .out_args = + NM_DEFINE_GDBUS_ARG_INFOS(NM_DEFINE_GDBUS_ARG_INFO("device", "o"), ), ), + .handle = impl_manager_get_device_by_ip_iface, ), + NM_DEFINE_DBUS_METHOD_INFO_EXTENDED( + NM_DEFINE_GDBUS_METHOD_INFO_INIT( + "ActivateConnection", + .in_args = NM_DEFINE_GDBUS_ARG_INFOS( + NM_DEFINE_GDBUS_ARG_INFO("connection", "o"), + NM_DEFINE_GDBUS_ARG_INFO("device", "o"), + NM_DEFINE_GDBUS_ARG_INFO("specific_object", "o"), ), + .out_args = NM_DEFINE_GDBUS_ARG_INFOS( + NM_DEFINE_GDBUS_ARG_INFO("active_connection", "o"), ), ), + .handle = impl_manager_activate_connection, ), + NM_DEFINE_DBUS_METHOD_INFO_EXTENDED( + NM_DEFINE_GDBUS_METHOD_INFO_INIT( + "AddAndActivateConnection", + .in_args = NM_DEFINE_GDBUS_ARG_INFOS( + NM_DEFINE_GDBUS_ARG_INFO("connection", "a{sa{sv}}"), + NM_DEFINE_GDBUS_ARG_INFO("device", "o"), + NM_DEFINE_GDBUS_ARG_INFO("specific_object", "o"), ), + .out_args = NM_DEFINE_GDBUS_ARG_INFOS( + NM_DEFINE_GDBUS_ARG_INFO("path", "o"), + NM_DEFINE_GDBUS_ARG_INFO("active_connection", "o"), ), ), + .handle = impl_manager_add_and_activate_connection, ), + NM_DEFINE_DBUS_METHOD_INFO_EXTENDED( + NM_DEFINE_GDBUS_METHOD_INFO_INIT( + "AddAndActivateConnection2", + .in_args = NM_DEFINE_GDBUS_ARG_INFOS( + NM_DEFINE_GDBUS_ARG_INFO("connection", "a{sa{sv}}"), + NM_DEFINE_GDBUS_ARG_INFO("device", "o"), + NM_DEFINE_GDBUS_ARG_INFO("specific_object", "o"), + NM_DEFINE_GDBUS_ARG_INFO("options", "a{sv}"), ), + .out_args = NM_DEFINE_GDBUS_ARG_INFOS( + NM_DEFINE_GDBUS_ARG_INFO("path", "o"), + NM_DEFINE_GDBUS_ARG_INFO("active_connection", "o"), + NM_DEFINE_GDBUS_ARG_INFO("result", "a{sv}"), ), ), + .handle = impl_manager_add_and_activate_connection, ), + NM_DEFINE_DBUS_METHOD_INFO_EXTENDED( + NM_DEFINE_GDBUS_METHOD_INFO_INIT( + "DeactivateConnection", + .in_args = NM_DEFINE_GDBUS_ARG_INFOS( + NM_DEFINE_GDBUS_ARG_INFO("active_connection", "o"), ), ), + .handle = impl_manager_deactivate_connection, ), + NM_DEFINE_DBUS_METHOD_INFO_EXTENDED( + NM_DEFINE_GDBUS_METHOD_INFO_INIT("Sleep", + .in_args = NM_DEFINE_GDBUS_ARG_INFOS( + NM_DEFINE_GDBUS_ARG_INFO("sleep", "b"), ), ), + .handle = impl_manager_sleep, ), + NM_DEFINE_DBUS_METHOD_INFO_EXTENDED( + NM_DEFINE_GDBUS_METHOD_INFO_INIT("Enable", + .in_args = NM_DEFINE_GDBUS_ARG_INFOS( + NM_DEFINE_GDBUS_ARG_INFO("enable", "b"), ), ), + .handle = impl_manager_enable, ), + NM_DEFINE_DBUS_METHOD_INFO_EXTENDED( + NM_DEFINE_GDBUS_METHOD_INFO_INIT( + "GetPermissions", + .out_args = NM_DEFINE_GDBUS_ARG_INFOS( + NM_DEFINE_GDBUS_ARG_INFO("permissions", "a{ss}"), ), ), + .handle = impl_manager_get_permissions, ), + NM_DEFINE_DBUS_METHOD_INFO_EXTENDED( + NM_DEFINE_GDBUS_METHOD_INFO_INIT("SetLogging", + .in_args = NM_DEFINE_GDBUS_ARG_INFOS( + NM_DEFINE_GDBUS_ARG_INFO("level", "s"), + NM_DEFINE_GDBUS_ARG_INFO("domains", "s"), ), ), + .handle = impl_manager_set_logging, ), + NM_DEFINE_DBUS_METHOD_INFO_EXTENDED( + NM_DEFINE_GDBUS_METHOD_INFO_INIT("GetLogging", + .out_args = NM_DEFINE_GDBUS_ARG_INFOS( + NM_DEFINE_GDBUS_ARG_INFO("level", "s"), + NM_DEFINE_GDBUS_ARG_INFO("domains", "s"), ), ), + .handle = impl_manager_get_logging, ), + NM_DEFINE_DBUS_METHOD_INFO_EXTENDED( + NM_DEFINE_GDBUS_METHOD_INFO_INIT( + "CheckConnectivity", + .out_args = NM_DEFINE_GDBUS_ARG_INFOS( + NM_DEFINE_GDBUS_ARG_INFO("connectivity", "u"), ), ), + .handle = impl_manager_check_connectivity, ), + NM_DEFINE_DBUS_METHOD_INFO_EXTENDED( + NM_DEFINE_GDBUS_METHOD_INFO_INIT("state", + .out_args = NM_DEFINE_GDBUS_ARG_INFOS( + NM_DEFINE_GDBUS_ARG_INFO("state", "u"), ), ), + .handle = impl_manager_state, ), + NM_DEFINE_DBUS_METHOD_INFO_EXTENDED( + NM_DEFINE_GDBUS_METHOD_INFO_INIT( + "CheckpointCreate", + .in_args = + NM_DEFINE_GDBUS_ARG_INFOS(NM_DEFINE_GDBUS_ARG_INFO("devices", "ao"), + NM_DEFINE_GDBUS_ARG_INFO("rollback_timeout", "u"), + NM_DEFINE_GDBUS_ARG_INFO("flags", "u"), ), + .out_args = + NM_DEFINE_GDBUS_ARG_INFOS(NM_DEFINE_GDBUS_ARG_INFO("checkpoint", "o"), ), ), + .handle = impl_manager_checkpoint_create, ), + NM_DEFINE_DBUS_METHOD_INFO_EXTENDED( + NM_DEFINE_GDBUS_METHOD_INFO_INIT( + "CheckpointDestroy", + .in_args = + NM_DEFINE_GDBUS_ARG_INFOS(NM_DEFINE_GDBUS_ARG_INFO("checkpoint", "o"), ), ), + .handle = impl_manager_checkpoint_destroy, ), + NM_DEFINE_DBUS_METHOD_INFO_EXTENDED( + NM_DEFINE_GDBUS_METHOD_INFO_INIT( + "CheckpointRollback", + .in_args = + NM_DEFINE_GDBUS_ARG_INFOS(NM_DEFINE_GDBUS_ARG_INFO("checkpoint", "o"), ), + .out_args = + NM_DEFINE_GDBUS_ARG_INFOS(NM_DEFINE_GDBUS_ARG_INFO("result", "a{su}"), ), ), + .handle = impl_manager_checkpoint_rollback, ), + NM_DEFINE_DBUS_METHOD_INFO_EXTENDED( + NM_DEFINE_GDBUS_METHOD_INFO_INIT( + "CheckpointAdjustRollbackTimeout", + .in_args = NM_DEFINE_GDBUS_ARG_INFOS( + NM_DEFINE_GDBUS_ARG_INFO("checkpoint", "o"), + NM_DEFINE_GDBUS_ARG_INFO("add_timeout", "u"), ), ), + .handle = impl_manager_checkpoint_adjust_rollback_timeout, ), ), + .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, + &signal_info_check_permissions, + &signal_info_state_changed, + &signal_info_device_added, + &signal_info_device_removed, ), + .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Devices", "ao", NM_MANAGER_DEVICES), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("AllDevices", + "ao", + NM_MANAGER_ALL_DEVICES), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Checkpoints", + "ao", + NM_MANAGER_CHECKPOINTS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("NetworkingEnabled", + "b", + NM_MANAGER_NETWORKING_ENABLED), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE_L( + "WirelessEnabled", + "b", + NM_MANAGER_WIRELESS_ENABLED, + NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI, + NM_AUDIT_OP_RADIO_CONTROL), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("WirelessHardwareEnabled", + "b", + NM_MANAGER_WIRELESS_HARDWARE_ENABLED), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE_L( + "WwanEnabled", + "b", + NM_MANAGER_WWAN_ENABLED, + NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN, + NM_AUDIT_OP_RADIO_CONTROL), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("WwanHardwareEnabled", + "b", + NM_MANAGER_WWAN_HARDWARE_ENABLED), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE_L( + "WimaxEnabled", + "b", + NM_MANAGER_WIMAX_ENABLED, + NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX, + NM_AUDIT_OP_RADIO_CONTROL), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("WimaxHardwareEnabled", + "b", + NM_MANAGER_WIMAX_HARDWARE_ENABLED), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("ActiveConnections", + "ao", + NM_MANAGER_ACTIVE_CONNECTIONS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("PrimaryConnection", + "o", + NM_MANAGER_PRIMARY_CONNECTION), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("PrimaryConnectionType", + "s", + NM_MANAGER_PRIMARY_CONNECTION_TYPE), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Metered", "u", NM_MANAGER_METERED), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("ActivatingConnection", + "o", + NM_MANAGER_ACTIVATING_CONNECTION), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Startup", "b", NM_MANAGER_STARTUP), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Version", "s", NM_MANAGER_VERSION), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Capabilities", + "au", + NM_MANAGER_CAPABILITIES), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("State", "u", NM_MANAGER_STATE), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Connectivity", + "u", + NM_MANAGER_CONNECTIVITY), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L( + "ConnectivityCheckAvailable", + "b", + NM_MANAGER_CONNECTIVITY_CHECK_AVAILABLE), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE_L( + "ConnectivityCheckEnabled", + "b", + NM_MANAGER_CONNECTIVITY_CHECK_ENABLED, + NM_AUTH_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK, + NM_AUDIT_OP_NET_CONTROL), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("ConnectivityCheckUri", + "s", + NM_MANAGER_CONNECTIVITY_CHECK_URI), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READWRITABLE_L( + "GlobalDnsConfiguration", + "a{sv}", + NM_MANAGER_GLOBAL_DNS_CONFIGURATION, + NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS, + NM_AUDIT_OP_NET_CONTROL), ), ), + .legacy_property_changed = TRUE, }; static void -nm_manager_class_init (NMManagerClass *manager_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (manager_class); - NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (manager_class); - - dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_STATIC (NM_DBUS_PATH); - dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_manager); - - object_class->constructed = constructed; - object_class->set_property = set_property; - object_class->get_property = get_property; - object_class->dispose = dispose; - object_class->finalize = finalize; - - obj_properties[PROP_VERSION] = - g_param_spec_string (NM_MANAGER_VERSION, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_CAPABILITIES] = - g_param_spec_variant (NM_MANAGER_CAPABILITIES, "", "", - G_VARIANT_TYPE ("au"), - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_STATE] = - g_param_spec_uint (NM_MANAGER_STATE, "", "", - 0, NM_STATE_DISCONNECTED, 0, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_STARTUP] = - g_param_spec_boolean (NM_MANAGER_STARTUP, "", "", - TRUE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_NETWORKING_ENABLED] = - g_param_spec_boolean (NM_MANAGER_NETWORKING_ENABLED, "", "", - TRUE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_WIRELESS_ENABLED] = - g_param_spec_boolean (NM_MANAGER_WIRELESS_ENABLED, "", "", - TRUE, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_WIRELESS_HARDWARE_ENABLED] = - g_param_spec_boolean (NM_MANAGER_WIRELESS_HARDWARE_ENABLED, "", "", - TRUE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_WWAN_ENABLED] = - g_param_spec_boolean (NM_MANAGER_WWAN_ENABLED, "", "", - TRUE, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_WWAN_HARDWARE_ENABLED] = - g_param_spec_boolean (NM_MANAGER_WWAN_HARDWARE_ENABLED, "", "", - TRUE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_WIMAX_ENABLED] = - g_param_spec_boolean (NM_MANAGER_WIMAX_ENABLED, "", "", - TRUE, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_WIMAX_HARDWARE_ENABLED] = - g_param_spec_boolean (NM_MANAGER_WIMAX_HARDWARE_ENABLED, "", "", - TRUE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_ACTIVE_CONNECTIONS] = - g_param_spec_boxed (NM_MANAGER_ACTIVE_CONNECTIONS, "", "", - G_TYPE_STRV, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_CONNECTIVITY] = - g_param_spec_uint (NM_MANAGER_CONNECTIVITY, "", "", - NM_CONNECTIVITY_UNKNOWN, NM_CONNECTIVITY_FULL, NM_CONNECTIVITY_UNKNOWN, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_CONNECTIVITY_CHECK_AVAILABLE] = - g_param_spec_boolean (NM_MANAGER_CONNECTIVITY_CHECK_AVAILABLE, "", "", - TRUE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_CONNECTIVITY_CHECK_ENABLED] = - g_param_spec_boolean (NM_MANAGER_CONNECTIVITY_CHECK_ENABLED, "", "", - TRUE, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_CONNECTIVITY_CHECK_URI] = - g_param_spec_string (NM_MANAGER_CONNECTIVITY_CHECK_URI, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_PRIMARY_CONNECTION] = - g_param_spec_string (NM_MANAGER_PRIMARY_CONNECTION, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_PRIMARY_CONNECTION_TYPE] = - g_param_spec_string (NM_MANAGER_PRIMARY_CONNECTION_TYPE, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_ACTIVATING_CONNECTION] = - g_param_spec_string (NM_MANAGER_ACTIVATING_CONNECTION, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - /* Sleeping is not exported over D-Bus */ - obj_properties[PROP_SLEEPING] = - g_param_spec_boolean (NM_MANAGER_SLEEPING, "", "", - FALSE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_DEVICES] = - g_param_spec_boxed (NM_MANAGER_DEVICES, "", "", - G_TYPE_STRV, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - /** - * NMManager:metered: - * - * Whether the connectivity is metered. - * - * Since: 1.2 - **/ - obj_properties[PROP_METERED] = - g_param_spec_uint (NM_MANAGER_METERED, "", "", - 0, G_MAXUINT32, NM_METERED_UNKNOWN, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - /** - * NMManager:global-dns-configuration: - * - * The global DNS configuration. - * - * Since: 1.2 - **/ - obj_properties[PROP_GLOBAL_DNS_CONFIGURATION] = - g_param_spec_variant (NM_MANAGER_GLOBAL_DNS_CONFIGURATION, "", "", - G_VARIANT_TYPE ("a{sv}"), - NULL, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); - - /** - * NMManager:all-devices: - * - * All devices, including those that are not realized. - * - * Since: 1.2 - **/ - obj_properties[PROP_ALL_DEVICES] = - g_param_spec_boxed (NM_MANAGER_ALL_DEVICES, "", "", - G_TYPE_STRV, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_CHECKPOINTS] = - g_param_spec_boxed (NM_MANAGER_CHECKPOINTS, "", "", - G_TYPE_STRV, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - /* signals */ - - /* emitted only for realized devices */ - signals[DEVICE_ADDED] = - g_signal_new (NM_MANAGER_DEVICE_ADDED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 1, NM_TYPE_DEVICE); - - /* Emitted for both realized devices and placeholder devices */ - signals[INTERNAL_DEVICE_ADDED] = - g_signal_new (NM_MANAGER_INTERNAL_DEVICE_ADDED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 1, G_TYPE_OBJECT); - - /* emitted only for realized devices when a device - * becomes unrealized or removed */ - signals[DEVICE_REMOVED] = - g_signal_new (NM_MANAGER_DEVICE_REMOVED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 1, NM_TYPE_DEVICE); - - /* Emitted for both realized devices and placeholder devices */ - signals[INTERNAL_DEVICE_REMOVED] = - g_signal_new (NM_MANAGER_INTERNAL_DEVICE_REMOVED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 1, G_TYPE_OBJECT); - - signals[ACTIVE_CONNECTION_ADDED] = - g_signal_new (NM_MANAGER_ACTIVE_CONNECTION_ADDED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 1, NM_TYPE_ACTIVE_CONNECTION); - - signals[ACTIVE_CONNECTION_REMOVED] = - g_signal_new (NM_MANAGER_ACTIVE_CONNECTION_REMOVED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 1, NM_TYPE_ACTIVE_CONNECTION); - - signals[CONFIGURE_QUIT] = - g_signal_new (NM_MANAGER_CONFIGURE_QUIT, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 0); +nm_manager_class_init(NMManagerClass *manager_class) +{ + GObjectClass * object_class = G_OBJECT_CLASS(manager_class); + NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(manager_class); + + dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_STATIC(NM_DBUS_PATH); + dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_manager); + + object_class->constructed = constructed; + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->dispose = dispose; + object_class->finalize = finalize; + + obj_properties[PROP_VERSION] = g_param_spec_string(NM_MANAGER_VERSION, + "", + "", + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_CAPABILITIES] = + g_param_spec_variant(NM_MANAGER_CAPABILITIES, + "", + "", + G_VARIANT_TYPE("au"), + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_STATE] = g_param_spec_uint(NM_MANAGER_STATE, + "", + "", + 0, + NM_STATE_DISCONNECTED, + 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_STARTUP] = g_param_spec_boolean(NM_MANAGER_STARTUP, + "", + "", + TRUE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_NETWORKING_ENABLED] = + g_param_spec_boolean(NM_MANAGER_NETWORKING_ENABLED, + "", + "", + TRUE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_WIRELESS_ENABLED] = + g_param_spec_boolean(NM_MANAGER_WIRELESS_ENABLED, + "", + "", + TRUE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_WIRELESS_HARDWARE_ENABLED] = + g_param_spec_boolean(NM_MANAGER_WIRELESS_HARDWARE_ENABLED, + "", + "", + TRUE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_WWAN_ENABLED] = + g_param_spec_boolean(NM_MANAGER_WWAN_ENABLED, + "", + "", + TRUE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_WWAN_HARDWARE_ENABLED] = + g_param_spec_boolean(NM_MANAGER_WWAN_HARDWARE_ENABLED, + "", + "", + TRUE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_WIMAX_ENABLED] = + g_param_spec_boolean(NM_MANAGER_WIMAX_ENABLED, + "", + "", + TRUE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_WIMAX_HARDWARE_ENABLED] = + g_param_spec_boolean(NM_MANAGER_WIMAX_HARDWARE_ENABLED, + "", + "", + TRUE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_ACTIVE_CONNECTIONS] = + g_param_spec_boxed(NM_MANAGER_ACTIVE_CONNECTIONS, + "", + "", + G_TYPE_STRV, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_CONNECTIVITY] = + g_param_spec_uint(NM_MANAGER_CONNECTIVITY, + "", + "", + NM_CONNECTIVITY_UNKNOWN, + NM_CONNECTIVITY_FULL, + NM_CONNECTIVITY_UNKNOWN, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_CONNECTIVITY_CHECK_AVAILABLE] = + g_param_spec_boolean(NM_MANAGER_CONNECTIVITY_CHECK_AVAILABLE, + "", + "", + TRUE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_CONNECTIVITY_CHECK_ENABLED] = + g_param_spec_boolean(NM_MANAGER_CONNECTIVITY_CHECK_ENABLED, + "", + "", + TRUE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_CONNECTIVITY_CHECK_URI] = + g_param_spec_string(NM_MANAGER_CONNECTIVITY_CHECK_URI, + "", + "", + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_PRIMARY_CONNECTION] = + g_param_spec_string(NM_MANAGER_PRIMARY_CONNECTION, + "", + "", + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_PRIMARY_CONNECTION_TYPE] = + g_param_spec_string(NM_MANAGER_PRIMARY_CONNECTION_TYPE, + "", + "", + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_ACTIVATING_CONNECTION] = + g_param_spec_string(NM_MANAGER_ACTIVATING_CONNECTION, + "", + "", + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + /* Sleeping is not exported over D-Bus */ + obj_properties[PROP_SLEEPING] = g_param_spec_boolean(NM_MANAGER_SLEEPING, + "", + "", + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_DEVICES] = g_param_spec_boxed(NM_MANAGER_DEVICES, + "", + "", + G_TYPE_STRV, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMManager:metered: + * + * Whether the connectivity is metered. + * + * Since: 1.2 + **/ + obj_properties[PROP_METERED] = g_param_spec_uint(NM_MANAGER_METERED, + "", + "", + 0, + G_MAXUINT32, + NM_METERED_UNKNOWN, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + /** + * NMManager:global-dns-configuration: + * + * The global DNS configuration. + * + * Since: 1.2 + **/ + obj_properties[PROP_GLOBAL_DNS_CONFIGURATION] = + g_param_spec_variant(NM_MANAGER_GLOBAL_DNS_CONFIGURATION, + "", + "", + G_VARIANT_TYPE("a{sv}"), + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * NMManager:all-devices: + * + * All devices, including those that are not realized. + * + * Since: 1.2 + **/ + obj_properties[PROP_ALL_DEVICES] = + g_param_spec_boxed(NM_MANAGER_ALL_DEVICES, + "", + "", + G_TYPE_STRV, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_CHECKPOINTS] = + g_param_spec_boxed(NM_MANAGER_CHECKPOINTS, + "", + "", + G_TYPE_STRV, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + /* signals */ + + /* emitted only for realized devices */ + signals[DEVICE_ADDED] = g_signal_new(NM_MANAGER_DEVICE_ADDED, + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 1, + NM_TYPE_DEVICE); + + /* Emitted for both realized devices and placeholder devices */ + signals[INTERNAL_DEVICE_ADDED] = g_signal_new(NM_MANAGER_INTERNAL_DEVICE_ADDED, + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 1, + G_TYPE_OBJECT); + + /* emitted only for realized devices when a device + * becomes unrealized or removed */ + signals[DEVICE_REMOVED] = g_signal_new(NM_MANAGER_DEVICE_REMOVED, + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 1, + NM_TYPE_DEVICE); + + /* Emitted for both realized devices and placeholder devices */ + signals[INTERNAL_DEVICE_REMOVED] = g_signal_new(NM_MANAGER_INTERNAL_DEVICE_REMOVED, + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 1, + G_TYPE_OBJECT); + + signals[ACTIVE_CONNECTION_ADDED] = g_signal_new(NM_MANAGER_ACTIVE_CONNECTION_ADDED, + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 1, + NM_TYPE_ACTIVE_CONNECTION); + + signals[ACTIVE_CONNECTION_REMOVED] = g_signal_new(NM_MANAGER_ACTIVE_CONNECTION_REMOVED, + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 1, + NM_TYPE_ACTIVE_CONNECTION); + + signals[CONFIGURE_QUIT] = g_signal_new(NM_MANAGER_CONFIGURE_QUIT, + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 0); } |