diff options
Diffstat (limited to 'src/nm-manager.c')
| -rw-r--r-- | src/nm-manager.c | 2442 |
1 files changed, 1098 insertions, 1344 deletions
diff --git a/src/nm-manager.c b/src/nm-manager.c index 1ccfad8e..f3bbebd0 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -30,7 +30,7 @@ #include <unistd.h> #include "nm-common-macros.h" -#include "nm-dbus-manager.h" +#include "nm-bus-manager.h" #include "vpn/nm-vpn-manager.h" #include "devices/nm-device.h" #include "devices/nm-device-generic.h" @@ -56,10 +56,12 @@ #include "nm-dbus-compat.h" #include "nm-checkpoint.h" #include "nm-checkpoint-manager.h" -#include "nm-dbus-object.h" #include "nm-dispatcher.h" #include "NetworkManagerUtils.h" +#include "introspection/org.freedesktop.NetworkManager.h" +#include "introspection/org.freedesktop.NetworkManager.Device.h" + /*****************************************************************************/ typedef struct { @@ -78,6 +80,8 @@ enum { INTERNAL_DEVICE_ADDED, DEVICE_REMOVED, INTERNAL_DEVICE_REMOVED, + STATE_CHANGED, + CHECK_PERMISSIONS, ACTIVE_CONNECTION_ADDED, ACTIVE_CONNECTION_REMOVED, CONFIGURE_QUIT, @@ -110,7 +114,6 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMManager, PROP_METERED, PROP_GLOBAL_DNS_CONFIGURATION, PROP_ALL_DEVICES, - PROP_CHECKPOINTS, /* Not exported */ PROP_SLEEPING, @@ -128,14 +131,16 @@ typedef struct { NMActiveConnection *activating_connection; NMMetered metered; - CList devices_lst_head; - + GSList *devices; NMState state; NMConfig *config; - NMConnectivity *concheck_mgr; + NMConnectivityState connectivity_state; + NMPolicy *policy; + NMHostnameManager *hostname_manager; + NMBusManager *dbus_mgr; struct { GDBusConnection *connection; guint id; @@ -168,30 +173,26 @@ typedef struct { guint devices_inited_id; - NMConnectivityState connectivity_state; - bool startup:1; bool devices_inited:1; bool sleeping:1; bool net_enabled:1; - unsigned connectivity_check_enabled_last:2; - guint delete_volatile_connection_idle_id; CList delete_volatile_connection_lst_head; } NMManagerPrivate; struct _NMManager { - NMDBusObject parent; + NMExportedObject parent; NMManagerPrivate _priv; }; typedef struct { - NMDBusObjectClass parent; + NMExportedObjectClass parent; } NMManagerClass; -G_DEFINE_TYPE (NMManager, nm_manager, NM_TYPE_DBUS_OBJECT) +G_DEFINE_TYPE (NMManager, nm_manager, NM_TYPE_EXPORTED_OBJECT) #define NM_MANAGER_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMManager, NM_IS_MANAGER) @@ -268,20 +269,9 @@ NM_DEFINE_SINGLETON_INSTANCE (NMManager); /*****************************************************************************/ -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 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, NMConnection *connection, NMConnection *applied, const char *specific_object, @@ -329,8 +319,6 @@ static NMActiveConnection *active_connection_find_first (NMManager *self, const char *uuid, NMActiveConnectionState max_state); -static NMConnectivity *concheck_get_mgr (NMManager *self); - /*****************************************************************************/ static NM_CACHED_QUARK_FCN ("active-connection-add-and-activate", active_connection_add_and_activate_quark) @@ -339,73 +327,6 @@ static NM_CACHED_QUARK_FCN ("autoconnect-root", autoconnect_root_quark) /*****************************************************************************/ -static gboolean -_connection_is_vpn (NMConnection *connection) -{ - const char *type; - - 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 existance of a [vpn] section. */ - return !!nm_connection_get_setting_vpn (connection); -} - -/*****************************************************************************/ - -static gboolean -concheck_enabled (NMManager *self, gboolean *out_changed) -{ - 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; -} - -static void -concheck_config_changed_cb (NMConnectivity *connectivity, - NMManager *self) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device; - gboolean changed; - - 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); -} - -static NMConnectivity * -concheck_get_mgr (NMManager *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; -} - -/*****************************************************************************/ - typedef struct { int ifindex; guint32 aspired_metric; @@ -514,10 +435,10 @@ _device_route_metric_get (NMManager *self, * 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))) + if (!nm_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 (); } } @@ -610,7 +531,7 @@ 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)) + if (!nm_g_hash_table_add (priv->device_route_metrics, data)) nm_assert_not_reached (); out: @@ -657,7 +578,7 @@ _delete_volatile_connection_do (NMManager *self, NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); if (!NM_FLAGS_HAS (nm_settings_connection_get_flags (connection), - NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE)) + NM_SETTINGS_CONNECTION_FLAGS_VOLATILE)) return; if (active_connection_find_first (self, connection, @@ -683,7 +604,7 @@ active_connection_remove (NMManager *self, NMActiveConnection *active) 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_exported_object_is_exported (NM_EXPORTED_OBJECT (active)); c_list_unlink (&active->active_connections_lst); g_signal_emit (self, signals[ACTIVE_CONNECTION_REMOVED], 0, active); @@ -693,7 +614,7 @@ active_connection_remove (NMManager *self, NMActiveConnection *active) connection = nm_g_object_ref (nm_active_connection_get_settings_connection (active)); - nm_dbus_object_clear_and_unexport (&active); + nm_exported_object_clear_and_unexport (&active); if (connection) _delete_volatile_connection_do (self, connection); @@ -789,8 +710,8 @@ active_connection_add (NMManager *self, 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_exported_object_is_exported (NM_EXPORTED_OBJECT (active))) + nm_exported_object_export (NM_EXPORTED_OBJECT (active)); g_signal_emit (self, signals[ACTIVE_CONNECTION_ADDED], 0, active); @@ -854,7 +775,7 @@ _get_activatable_connections_filter (NMSettings *settings, gpointer user_data) { if (NM_FLAGS_HAS (nm_settings_connection_get_flags (connection), - NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE)) + NM_SETTINGS_CONNECTION_FLAGS_VOLATILE)) return FALSE; return !active_connection_find_first (user_data, connection, NULL, NM_ACTIVE_CONNECTION_STATE_DEACTIVATING); } @@ -872,20 +793,18 @@ nm_manager_get_activatable_connections (NMManager *manager, guint *out_len, gboo } static NMActiveConnection * -active_connection_get_by_path (NMManager *self, const char *path) +active_connection_get_by_path (NMManager *manager, const char *path) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); NMActiveConnection *ac; - ac = (NMActiveConnection *) 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 (path); - nm_assert (c_list_contains (&priv->active_connections_lst_head, &ac->active_connections_lst)); - return ac; + c_list_for_each_entry (ac, &priv->active_connections_lst_head, active_connections_lst) { + if (nm_streq0 (path, nm_exported_object_get_path (NM_EXPORTED_OBJECT (ac)))) + return ac; + } + return NULL; } /*****************************************************************************/ @@ -893,14 +812,8 @@ active_connection_get_by_path (NMManager *self, const char *path) static void _config_changed_cb (NMConfig *config, NMConfigData *config_data, NMConfigChangeFlags changes, NMConfigData *old_data, NMManager *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_config_data_get_connectivity_uri (config_data)) != (!nm_config_data_get_connectivity_uri (old_data))) - _notify (self, PROP_CONNECTIVITY_CHECK_AVAILABLE); - - g_object_thaw_notify (G_OBJECT (self)); } static void @@ -971,31 +884,28 @@ _reload_auth_cb (NMAuthChain *chain, g_dbus_method_invocation_return_value (context, NULL); out: - nm_auth_chain_destroy (chain); + nm_auth_chain_unref (chain); } 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); +impl_manager_reload (NMManager *self, + GDBusMethodInvocation *context, + guint32 flags) +{ + NMManagerPrivate *priv; NMAuthChain *chain; - guint32 flags; + GError *error = NULL; - g_variant_get (parameters, "(u)", &flags); + g_return_if_fail (NM_IS_MANAGER (self)); - chain = nm_auth_chain_new_context (invocation, _reload_auth_cb, self); + priv = NM_MANAGER_GET_PRIVATE (self); + + chain = nm_auth_chain_new_context (context, _reload_auth_cb, self); if (!chain) { - g_dbus_method_invocation_return_error_literal (invocation, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - "Unable to authenticate request"); + error = g_error_new_literal (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + "Unable to authenticate request"); + g_dbus_method_invocation_take_error (context, error); return; } @@ -1007,31 +917,27 @@ impl_manager_reload (NMDBusObject *obj, /*****************************************************************************/ NMDevice * -nm_manager_get_device_by_path (NMManager *self, const char *path) +nm_manager_get_device_by_path (NMManager *manager, const char *path) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device; - - g_return_val_if_fail (path, NULL); + GSList *iter; - device = (NMDevice *) 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; + g_return_val_if_fail (path != NULL, NULL); - nm_assert (c_list_contains (&priv->devices_lst_head, &device->devices_lst)); - return device; + for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) { + if (!strcmp (nm_exported_object_get_path (NM_EXPORTED_OBJECT (iter->data)), path)) + return NM_DEVICE (iter->data); + } + return NULL; } NMDevice * -nm_manager_get_device_by_ifindex (NMManager *self, int ifindex) +nm_manager_get_device_by_ifindex (NMManager *manager, int ifindex) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device; + GSList *iter; + + for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) { + NMDevice *device = NM_DEVICE (iter->data); - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { if (nm_device_get_ifindex (device) == ifindex) return device; } @@ -1040,24 +946,19 @@ nm_manager_get_device_by_ifindex (NMManager *self, int ifindex) } static NMDevice * -find_device_by_permanent_hw_addr (NMManager *self, const char *hwaddr) +find_device_by_permanent_hw_addr (NMManager *manager, const char *hwaddr) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device; + GSList *iter; const char *device_addr; - guint8 hwaddr_bin[NM_UTILS_HWADDR_LEN_MAX]; - gsize hwaddr_len; g_return_val_if_fail (hwaddr != NULL, 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; + if (nm_utils_hwaddr_valid (hwaddr, -1)) { + for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) { + device_addr = nm_device_get_permanent_hw_address (NM_DEVICE (iter->data)); + if (device_addr && nm_utils_hwaddr_matches (hwaddr, -1, device_addr, -1)) + return NM_DEVICE (iter->data); + } } return NULL; } @@ -1065,15 +966,16 @@ find_device_by_permanent_hw_addr (NMManager *self, const char *hwaddr) static NMDevice * find_device_by_ip_iface (NMManager *self, const gchar *iface) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device; + GSList *iter; + + g_return_val_if_fail (iface != NULL, NULL); - g_return_val_if_fail (iface, NULL); + for (iter = NM_MANAGER_GET_PRIVATE (self)->devices; iter; iter = g_slist_next (iter)) { + NMDevice *candidate = iter->data; - 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; + if ( nm_device_is_real (candidate) + && g_strcmp0 (nm_device_get_ip_iface (candidate), iface) == 0) + return candidate; } return NULL; } @@ -1101,11 +1003,12 @@ find_device_by_iface (NMManager *self, { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); NMDevice *fallback = NULL; - NMDevice *candidate; + GSList *iter; g_return_val_if_fail (iface != NULL, NULL); - c_list_for_each_entry (candidate, &priv->devices_lst_head, devices_lst) { + for (iter = priv->devices; iter; iter = iter->next) { + NMDevice *candidate = iter->data; if (strcmp (nm_device_get_iface (candidate), iface)) continue; @@ -1160,6 +1063,22 @@ _nm_state_to_string (NMState state) } } +static void +set_state (NMManager *self, NMState state) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + + if (priv->state == state) + return; + + priv->state = state; + + _LOGI (LOGD_CORE, "NetworkManager state is now %s", _nm_state_to_string (state)); + + _notify (self, PROP_STATE); + g_signal_emit (self, signals[STATE_CHANGED], 0, priv->state); +} + static NMState find_best_device_state (NMManager *manager) { @@ -1230,38 +1149,26 @@ nm_manager_update_metered (NMManager *self) } static void -nm_manager_update_state (NMManager *self) +nm_manager_update_state (NMManager *manager) { NMManagerPrivate *priv; NMState new_state = NM_STATE_DISCONNECTED; - g_return_if_fail (NM_IS_MANAGER (self)); + g_return_if_fail (NM_IS_MANAGER (manager)); - priv = NM_MANAGER_GET_PRIVATE (self); + priv = NM_MANAGER_GET_PRIVATE (manager); - if (manager_sleeping (self)) + if (manager_sleeping (manager)) new_state = NM_STATE_ASLEEP; else - new_state = find_best_device_state (self); + new_state = find_best_device_state (manager); 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; - - priv->state = 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); + set_state (manager, new_state); } static void @@ -1303,7 +1210,7 @@ static void check_if_startup_complete (NMManager *self) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device; + GSList *iter; if (!priv->startup) return; @@ -1316,10 +1223,12 @@ check_if_startup_complete (NMManager *self) return; } - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { - if (nm_device_has_pending_action (device)) { + for (iter = priv->devices; iter; iter = iter->next) { + NMDevice *dev = iter->data; + + if (nm_device_has_pending_action (dev)) { _LOGD (LOGD_CORE, "check_if_startup_complete returns FALSE because of %s", - nm_device_get_iface (device)); + nm_device_get_iface (dev)); return; } } @@ -1331,8 +1240,8 @@ check_if_startup_complete (NMManager *self) /* 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, + for (iter = priv->devices; iter; iter = iter->next) { + g_signal_handlers_disconnect_by_func (iter->data, G_CALLBACK (device_has_pending_action_changed), self); } @@ -1364,18 +1273,18 @@ _parent_notify_changed (NMManager *self, NMDevice *device, gboolean device_removed) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *candidate; + GSList *iter; nm_assert (NM_IS_DEVICE (device)); + nm_assert (NM_IS_MANAGER (self)); -again: - c_list_for_each_entry (candidate, &priv->devices_lst_head, devices_lst) { - if (nm_device_parent_notify_changed (candidate, device, device_removed)) { + for (iter = NM_MANAGER_GET_PRIVATE (self)->devices; iter; ) { + if (nm_device_parent_notify_changed (iter->data, 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; - } + iter = NM_MANAGER_GET_PRIVATE (self)->devices; + } else + iter = iter->next; } } @@ -1415,8 +1324,7 @@ remove_device (NMManager *self, 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); + priv->devices = g_slist_remove (priv->devices, device); _parent_notify_changed (self, device, TRUE); @@ -1434,7 +1342,8 @@ remove_device (NMManager *self, * Control that by passing @unconfigure_ip_config. */ nm_device_removed (device, unconfigure_ip_config); - _emit_device_added_removed (self, device, FALSE); + g_signal_emit (self, signals[DEVICE_REMOVED], 0, device); + _notify (self, PROP_DEVICES); } else { /* unrealize() does not release a slave device from master and * clear IP configurations, do it here */ @@ -1444,7 +1353,7 @@ remove_device (NMManager *self, g_signal_emit (self, signals[INTERNAL_DEVICE_REMOVED], 0, device); _notify (self, PROP_ALL_DEVICES); - nm_dbus_object_clear_and_unexport (&device); + nm_exported_object_clear_and_unexport (&device); check_if_startup_complete (self); } @@ -1473,7 +1382,7 @@ find_parent_device_for_connection (NMManager *self, NMConnection *connection, NM const char *parent_name = NULL; NMSettingsConnection *parent_connection; NMDevice *parent, *first_compatible = NULL; - NMDevice *candidate; + GSList *iter; g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); @@ -1506,7 +1415,9 @@ find_parent_device_for_connection (NMManager *self, NMConnection *connection, NM /* Check if the parent connection is currently activated or is comaptible * with some known device. */ - c_list_for_each_entry (candidate, &priv->devices_lst_head, devices_lst) { + for (iter = priv->devices; iter; iter = iter->next) { + NMDevice *candidate = iter->data; + /* Unmanaged devices are not compatible with any connection */ if (!nm_device_get_managed (candidate, FALSE)) continue; @@ -1622,15 +1533,18 @@ NMDevice * nm_manager_get_device (NMManager *self, const char *ifname, NMDeviceType device_type) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device; + GSList *iter; + NMDevice *d; 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; + for (iter = priv->devices; iter; iter = iter->next) { + d = iter->data; + + if ( nm_device_get_device_type (d) == device_type + && nm_streq0 (nm_device_get_iface (d), ifname)) + return d; } return NULL; @@ -1666,9 +1580,9 @@ system_create_virtual_device (NMManager *self, NMConnection *connection) NMDeviceFactory *factory; gs_free NMSettingsConnection **connections = NULL; guint i; + GSList *iter; gs_free char *iface = NULL; NMDevice *device = NULL, *parent = NULL; - NMDevice *dev_candidate; GError *error = NULL; NMLogLevel log_level; @@ -1684,15 +1598,17 @@ system_create_virtual_device (NMManager *self, NMConnection *connection) } /* 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)) { - if (nm_device_is_real (dev_candidate)) { + for (iter = priv->devices; iter; iter = g_slist_next (iter)) { + NMDevice *candidate = iter->data; + + if (nm_device_check_connection_compatible (candidate, connection)) { + if (nm_device_is_real (candidate)) { _LOG3D (LOGD_DEVICE, connection, "already created virtual interface name %s", iface); return NULL; } - device = dev_candidate; + device = candidate; break; } } @@ -1888,7 +1804,7 @@ connection_flags_changed (NMSettings *settings, DeleteVolatileConnectionData *data; if (!NM_FLAGS_HAS (nm_settings_connection_get_flags (connection), - NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE)) + NM_SETTINGS_CONNECTION_FLAGS_VOLATILE)) return; if (active_connection_find_first (self, connection, NULL, NM_ACTIVE_CONNECTION_STATE_DEACTIVATED)) { @@ -1913,10 +1829,10 @@ system_unmanaged_devices_changed_cb (NMSettings *settings, { NMManager *self = NM_MANAGER (user_data); NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device; + const GSList *iter; - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) - nm_device_set_unmanaged_by_user_settings (device); + for (iter = priv->devices; iter; iter = g_slist_next (iter)) + nm_device_set_unmanaged_by_user_settings (NM_DEVICE (iter->data)); } static void @@ -1962,7 +1878,7 @@ manager_update_radio_enabled (NMManager *self, gboolean enabled) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device; + GSList *iter; /* Do nothing for radio types not yet implemented */ if (!rstate->prop) @@ -1975,7 +1891,9 @@ manager_update_radio_enabled (NMManager *self, return; /* enable/disable wireless devices as required */ - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { + for (iter = priv->devices; iter; iter = iter->next) { + NMDevice *device = NM_DEVICE (iter->data); + 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); @@ -2118,7 +2036,7 @@ device_auth_done_cb (NMAuthChain *chain, nm_auth_chain_get_data (chain, "user-data")); g_clear_error (&error); - nm_auth_chain_destroy (chain); + nm_auth_chain_unref (chain); } static void @@ -2134,6 +2052,7 @@ device_auth_request_cb (NMDevice *device, NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); GError *error = NULL; NMAuthSubject *subject = NULL; + char *error_desc = NULL; NMAuthChain *chain; /* Validate the caller */ @@ -2146,13 +2065,15 @@ device_auth_request_cb (NMDevice *device, } /* 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)) + if (connection && !nm_auth_is_subject_in_acl (connection, + subject, + &error_desc)) { + error = g_error_new_literal (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + error_desc); + g_free (error_desc); goto done; + } /* Validate the request */ chain = nm_auth_chain_new_subject (subject, context, device_auth_done_cb, self); @@ -2349,8 +2270,8 @@ get_existing_connection (NMManager *self, } nm_settings_connection_set_flags (NM_SETTINGS_CONNECTION (added), - NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED | - NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE, + NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED | + NM_SETTINGS_CONNECTION_FLAGS_VOLATILE, TRUE); NM_SET_OUT (out_generated, TRUE); return added; @@ -2414,20 +2335,15 @@ recheck_assume_connection (NMManager *self, GError *error = NULL; subject = nm_auth_subject_new_internal (); - active = _new_active_connection (self, - FALSE, - NM_CONNECTION (connection), - NULL, - NULL, - device, - subject, + active = _new_active_connection (self, NM_CONNECTION (connection), NULL, NULL, + device, subject, generated ? NM_ACTIVATION_TYPE_EXTERNAL : NM_ACTIVATION_TYPE_ASSUME, NM_ACTIVATION_REASON_AUTOCONNECT, &error); if (!active) { _LOGW (LOGD_DEVICE, "assume: assumed connection %s failed to activate: %s", - nm_dbus_object_get_path (NM_DBUS_OBJECT (connection)), + nm_connection_get_path (NM_CONNECTION (connection)), error->message); g_error_free (error); @@ -2478,17 +2394,18 @@ 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; + GSList *iter; /* 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) { + for (iter = NM_MANAGER_GET_PRIVATE (self)->devices; iter; iter = iter->next) { + NMDevice *candidate = NM_DEVICE (iter->data); + if ( candidate != device && g_strcmp0 (nm_device_get_iface (candidate), ip_iface) == 0 && nm_device_get_device_type (candidate) == device_type @@ -2510,56 +2427,35 @@ device_iface_changed (NMDevice *device, 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); -} static void device_realized (NMDevice *device, GParamSpec *pspec, NMManager *self) { - _emit_device_added_removed (self, device, nm_device_is_real (device)); + gboolean real = nm_device_is_real (device); + + /* Emit D-Bus signals */ + g_signal_emit (self, signals[real ? DEVICE_ADDED : DEVICE_REMOVED], 0, device); + _notify (self, PROP_DEVICES); } +#if WITH_CONCHECK static void device_connectivity_changed (NMDevice *device, + GParamSpec *pspec, NMManager *self) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); NMConnectivityState best_state = NM_CONNECTIVITY_UNKNOWN; NMConnectivityState state; - NMDevice *dev; + const GSList *devices; - best_state = nm_device_get_connectivity_state (device); - if (best_state < NM_CONNECTIVITY_FULL) { - c_list_for_each_entry (dev, &priv->devices_lst_head, devices_lst) { - state = nm_device_get_connectivity_state (dev); - if (state <= best_state) - continue; + for (devices = priv->devices; devices; devices = devices->next) { + state = nm_device_get_connectivity_state (NM_DEVICE (devices->data)); + if (state > best_state) best_state = state; - if (best_state >= NM_CONNECTIVITY_FULL) { - /* it doesn't get better than this. */ - break; - } - } } - nm_assert (best_state <= NM_CONNECTIVITY_FULL); if (best_state != priv->connectivity_state) { priv->connectivity_state = best_state; @@ -2572,6 +2468,7 @@ device_connectivity_changed (NMDevice *device, nm_dispatcher_call_connectivity (priv->connectivity_state, NULL, NULL, NULL); } } +#endif static void _device_realize_finish (NMManager *self, @@ -2617,7 +2514,6 @@ add_device (NMManager *self, NMDevice *device, GError **error) GSList *iter, *remove = NULL; int ifindex; const char *dbus_path; - NMDevice *candidate; /* No duplicates */ ifindex = nm_device_get_ifindex (device); @@ -2634,20 +2530,18 @@ add_device (NMManager *self, NMDevice *device, GError **error) * 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)) + for (iter = priv->devices; iter; iter = iter->next) { + NMDevice *candidate = iter->data; + + iface = nm_device_get_ip_iface (candidate); + if (nm_device_is_real (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, 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); + priv->devices = g_slist_append (priv->devices, g_object_ref (device)); g_signal_connect (device, NM_DEVICE_STATE_CHANGED, G_CALLBACK (manager_device_state_changed), @@ -2681,9 +2575,11 @@ add_device (NMManager *self, NMDevice *device, GError **error) G_CALLBACK (device_realized), self); - g_signal_connect (device, NM_DEVICE_CONNECTIVITY_CHANGED, +#if WITH_CONCHECK + g_signal_connect (device, "notify::" NM_DEVICE_CONNECTIVITY, G_CALLBACK (device_connectivity_changed), self); +#endif if (priv->startup) { g_signal_connect (device, "notify::" NM_DEVICE_HAS_PENDING_ACTION, @@ -2712,7 +2608,7 @@ add_device (NMManager *self, NMDevice *device, GError **error) NM_UNMANAGED_SLEEPING, manager_sleeping (self)); - dbus_path = nm_dbus_object_export (NM_DBUS_OBJECT (device)); + dbus_path = nm_exported_object_export (NM_EXPORTED_OBJECT (device)); _LOG2I (LOGD_DEVICE, device, "new %s device (%s)", type_desc, dbus_path); nm_settings_device_added (priv->settings, device); @@ -2759,11 +2655,12 @@ factory_component_added_cb (NMDeviceFactory *factory, gpointer user_data) { NMManager *self = user_data; - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device; + GSList *iter; - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { - if (nm_device_notify_component_added (device, component)) + g_return_val_if_fail (self, FALSE); + + for (iter = NM_MANAGER_GET_PRIVATE (self)->devices; iter; iter = iter->next) { + if (nm_device_notify_component_added ((NMDevice *) iter->data, component)) return TRUE; } return FALSE; @@ -2793,10 +2690,9 @@ platform_link_added (NMManager *self, gboolean guess_assume, const NMConfigDeviceStateData *dev_state) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); NMDeviceFactory *factory; NMDevice *device = NULL; - NMDevice *candidate; + GSList *iter; g_return_if_fail (ifindex > 0); @@ -2804,7 +2700,8 @@ platform_link_added (NMManager *self, return; /* Let unrealized devices try to realize themselves with the link */ - c_list_for_each_entry (candidate, &priv->devices_lst_head, devices_lst) { + for (iter = NM_MANAGER_GET_PRIVATE (self)->devices; iter; iter = iter->next) { + NMDevice *candidate = iter->data; gboolean compatible = TRUE; gs_free_error GError *error = NULL; @@ -3031,12 +2928,12 @@ rfkill_manager_rfkill_changed_cb (NMRfkillManager *rfkill_mgr, nm_manager_rfkill_update (NM_MANAGER (user_data), rtype); } -const CList * +const GSList * nm_manager_get_devices (NMManager *manager) { 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; } static NMDevice * @@ -3045,10 +2942,9 @@ nm_manager_get_best_device_for_connection (NMManager *self, gboolean for_user_request, GHashTable *unavailable_devices) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + const GSList *devices, *iter; NMActiveConnection *ac; NMDevice *act_device; - NMDevice *device; NMDeviceCheckConAvailableFlags flags; ac = active_connection_find_first_by_connection (self, connection); @@ -3061,7 +2957,9 @@ nm_manager_get_best_device_for_connection (NMManager *self, flags = for_user_request ? NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST : NM_DEVICE_CHECK_CON_AVAILABLE_NONE; /* Pick the first device that's compatible with the connection. */ - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { + devices = nm_manager_get_devices (self); + for (iter = devices; iter; iter = g_slist_next (iter)) { + NMDevice *device = NM_DEVICE (iter->data); if (unavailable_devices && g_hash_table_contains (unavailable_devices, device)) continue; @@ -3074,100 +2972,67 @@ nm_manager_get_best_device_for_connection (NMManager *self, return NULL; } -static const char ** -_get_devices_paths (NMManager *self, - gboolean all_devices) +static void +_get_devices (NMManager *self, + GDBusMethodInvocation *context, + gboolean all_devices) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - const char **paths = NULL; + gs_free const char **paths = NULL; guint i; - NMDevice *device; + GSList *iter; - paths = g_new (const char *, c_list_length (&priv->devices_lst_head) + 1); + paths = g_new (const char *, g_slist_length (priv->devices) + 1); - i = 0; - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { + for (i = 0, iter = priv->devices; iter; iter = iter->next) { const char *path; - path = nm_dbus_object_get_path (NM_DBUS_OBJECT (device)); - if (!path) - continue; - - if ( !all_devices - && !nm_device_is_real (device)) - continue; - - paths[i++] = path; + path = nm_exported_object_get_path (NM_EXPORTED_OBJECT (iter->data)); + if ( path + && (all_devices || nm_device_is_real (iter->data))) + paths[i++] = path; } paths[i++] = NULL; - return paths; + g_dbus_method_invocation_return_value (context, + g_variant_new ("(^ao)", (char **) 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) -{ - 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)); +impl_manager_get_devices (NMManager *self, + GDBusMethodInvocation *context) +{ + _get_devices (self, context, FALSE); } 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) -{ - 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)); +impl_manager_get_all_devices (NMManager *self, + GDBusMethodInvocation *context) +{ + _get_devices (self, context, TRUE); } 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) -{ - NMManager *self = NM_MANAGER (obj); +impl_manager_get_device_by_ip_iface (NMManager *self, + GDBusMethodInvocation *context, + const char *iface) +{ NMDevice *device; const char *path = NULL; - const char *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)); + path = nm_exported_object_get_path (NM_EXPORTED_OBJECT (device)); - if (!path) { - g_dbus_method_invocation_return_error (invocation, + if (path == NULL) { + g_dbus_method_invocation_return_error (context, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, "No device found for the requested iface."); - return; + } else { + g_dbus_method_invocation_return_value (context, + g_variant_new ("(o)", path)); } - - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(o)", path)); } static gboolean @@ -3240,6 +3105,7 @@ find_master (NMManager *self, const char *master; NMDevice *master_device = NULL; NMSettingsConnection *master_connection = NULL; + GSList *iter; s_con = nm_connection_get_setting_connection (connection); g_assert (s_con); @@ -3268,10 +3134,10 @@ find_master (NMManager *self, /* 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) { + for (iter = priv->devices; iter; iter = g_slist_next (iter)) { + NMDevice *candidate = NM_DEVICE (iter->data); + if (candidate == device) continue; @@ -3343,6 +3209,7 @@ ensure_master_active_connection (NMManager *self, NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); NMActiveConnection *master_ac = NULL; NMDeviceState master_state; + GSList *iter; g_assert (connection); g_assert (master_connection || master_device); @@ -3419,10 +3286,12 @@ ensure_master_active_connection (NMManager *self, NM_MANAGER_ERROR_DEPENDENCY_FAILED, "Device unmanaged or not available for activation"); } else if (master_connection) { - NMDevice *candidate; + gboolean found_device = FALSE; /* Find a compatible device and activate it using this connection */ - c_list_for_each_entry (candidate, &priv->devices_lst_head, devices_lst) { + for (iter = priv->devices; iter; iter = g_slist_next (iter)) { + NMDevice *candidate = NM_DEVICE (iter->data); + if (candidate == device) { /* A device obviously can't be its own master */ continue; @@ -3431,6 +3300,7 @@ ensure_master_active_connection (NMManager *self, if (!nm_device_check_connection_available (candidate, NM_CONNECTION (master_connection), NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST, NULL)) continue; + found_device = TRUE; 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) @@ -3496,7 +3366,7 @@ find_slaves (NMManager *manager, s_con = nm_connection_get_setting_connection (NM_CONNECTION (connection)); g_return_val_if_fail (s_con, NULL); - devices = g_hash_table_new (nm_direct_hash, NULL); + devices = g_hash_table_new (g_direct_hash, g_direct_equal); /* Search through all connections, not only inactive ones, because * even if a slave was already active, it might be deactivated during @@ -3682,11 +3552,11 @@ _internal_activate_vpn (NMManager *self, NMActiveConnection *active, GError **er { nm_assert (NM_IS_VPN_CONNECTION (active)); - nm_dbus_object_export (NM_DBUS_OBJECT (active)); + nm_exported_object_export (NM_EXPORTED_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)); + nm_exported_object_unexport (NM_EXPORTED_OBJECT (active)); return FALSE; } @@ -3781,6 +3651,7 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError * NMConnection *existing_connection = NULL; NMActiveConnection *master_ac = NULL; NMAuthSubject *subject; + char *error_desc = NULL; g_return_val_if_fail (NM_IS_MANAGER (self), FALSE); g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (active), FALSE); @@ -3788,14 +3659,14 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError * g_assert (NM_IS_VPN_CONNECTION (active) == FALSE); - device = nm_active_connection_get_device (active); - g_return_val_if_fail (device != NULL, FALSE); - connection = nm_active_connection_get_settings_connection (active); - nm_assert (connection); + g_assert (connection); applied = nm_active_connection_get_applied_connection (active); + device = nm_active_connection_get_device (active); + g_return_val_if_fail (device != NULL, FALSE); + /* 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 @@ -3803,13 +3674,16 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError * */ 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: "); + if (existing_connection && + !nm_auth_is_subject_in_acl (existing_connection, + subject, + &error_desc)) { + g_set_error (error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + "Private connection already active on the device: %s", + error_desc); + g_free (error_desc); return FALSE; } @@ -3821,9 +3695,6 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError * 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); - /* Create any backing resources the device needs */ if (!nm_device_is_real (device)) { NMDevice *parent; @@ -3932,7 +3803,7 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError * _LOGD (LOGD_CORE, "Activation of '%s' depends on active connection %p %s", nm_settings_connection_get_id (connection), master_ac, - nm_dbus_object_get_path (NM_DBUS_OBJECT (master_ac)) ?: ""); + nm_exported_object_get_path (NM_EXPORTED_OBJECT (master_ac)) ?: ""); } /* Check slaves for master connection and possibly activate them */ @@ -4004,8 +3875,52 @@ _internal_activate_generic (NMManager *self, NMActiveConnection *active, GError } static NMActiveConnection * +_new_vpn_active_connection (NMManager *self, + NMSettingsConnection *settings_connection, + const char *specific_object, + NMAuthSubject *subject, + NMActivationReason activation_reason, + GError **error) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + NMActiveConnection *parent = NULL; + NMDevice *device = NULL; + + g_return_val_if_fail (!settings_connection || NM_IS_SETTINGS_CONNECTION (settings_connection), 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; + } + + device = nm_active_connection_get_device (parent); + if (!device) { + g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "Source connection had no active device."); + return NULL; + } + + return (NMActiveConnection *) nm_vpn_connection_new (settings_connection, + device, + nm_exported_object_get_path (NM_EXPORTED_OBJECT (parent)), + activation_reason, + subject); +} + +static NMActiveConnection * _new_active_connection (NMManager *self, - gboolean is_vpn, NMConnection *connection, NMConnection *applied, const char *specific_object, @@ -4015,78 +3930,45 @@ _new_active_connection (NMManager *self, NMActivationReason activation_reason, GError **error) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); NMSettingsConnection *settings_connection = NULL; - NMDevice *parent_device; + NMActiveConnection *existing_ac; + gboolean is_vpn; g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); g_return_val_if_fail (NM_IS_AUTH_SUBJECT (subject), NULL); - nm_assert (is_vpn == _connection_is_vpn (connection)); - nm_assert (is_vpn || NM_IS_DEVICE (device)); - nm_assert (!nm_streq0 (specific_object, "/")); + /* Can't create new AC for already-active connection */ + existing_ac = active_connection_find_first_by_connection (self, connection); + if (NM_IS_VPN_CONNECTION (existing_ac)) { + g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_ALREADY_ACTIVE, + "Connection '%s' is already active", + nm_connection_get_id (connection)); + return NULL; + } + + /* Normalize the specific object */ + if (specific_object && g_strcmp0 (specific_object, "/") == 0) + specific_object = NULL; + + is_vpn = nm_connection_is_type (NM_CONNECTION (connection), NM_SETTING_VPN_SETTING_NAME); if (NM_IS_SETTINGS_CONNECTION (connection)) settings_connection = (NMSettingsConnection *) connection; 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_first_by_connection (self, connection)) { - g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_ALREADY_ACTIVE, - "Connection '%s' is already active", - nm_connection_get_id (connection)); - return NULL; - } - - /* FIXME: apparently, activation here only works if @connection is - * a settings-connection. Which is not the case during AddAndActivatate. - * Probably, AddAndActivate is broken for VPN. */ if (activation_type != NM_ACTIVATION_TYPE_MANAGED) g_return_val_if_reached (NULL); - - g_return_val_if_fail (!settings_connection || NM_IS_SETTINGS_CONNECTION (settings_connection), 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 (settings_connection, - parent_device, - nm_dbus_object_get_path (NM_DBUS_OBJECT (parent)), - activation_reason, - subject); + return _new_vpn_active_connection (self, + settings_connection, + specific_object, + subject, + activation_reason, + error); } + if (device && (activation_type == NM_ACTIVATION_TYPE_MANAGED)) + nm_device_sys_iface_state_set (device, NM_DEVICE_SYS_IFACE_STATE_MANAGED); + return (NMActiveConnection *) nm_act_request_new (settings_connection, applied, specific_object, @@ -4111,16 +3993,14 @@ _internal_activation_auth_done (NMActiveConnection *active, priv->authorizing_connections = g_slist_remove (priv->authorizing_connections, active); - if (!success) - goto fail; - /* Don't continue with an internal activation if an equivalent active * connection already exists. Note that slave autoconnections always force a * reconnection. We also check this earlier, but there we may fail to * detect a duplicate if the existing active connection is undergoing * authorization in impl_manager_activate_connection(). */ - if ( nm_auth_subject_is_internal (nm_active_connection_get_subject (active)) + if ( success + && nm_auth_subject_is_internal (nm_active_connection_get_subject (active)) && nm_active_connection_get_activation_reason (active) != NM_ACTIVATION_REASON_AUTOCONNECT_SLAVES) { 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) @@ -4133,15 +4013,17 @@ _internal_activation_auth_done (NMActiveConnection *active, NM_MANAGER_ERROR_CONNECTION_ALREADY_ACTIVE, "Connection '%s' is already active", nm_active_connection_get_settings_connection_id (active)); - goto fail; + success = FALSE; + break; } } } - if (_internal_activate_generic (self, active, &error)) - return; + if (success) { + 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, @@ -4182,24 +4064,27 @@ nm_manager_activate_connection (NMManager *self, NMActivationReason activation_reason, GError **error) { - NMManagerPrivate *priv; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); NMActiveConnection *active; + char *error_desc = NULL; GSList *iter; - g_return_val_if_fail (NM_IS_MANAGER (self), NULL); - g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION (connection), NULL); - g_return_val_if_fail (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); + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (error != NULL, NULL); + g_return_val_if_fail (*error == NULL, NULL); - if (!nm_auth_is_subject_in_acl_set_error (NM_CONNECTION (connection), - subject, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - error)) + /* Ensure the subject has permissions for this connection */ + if (!nm_auth_is_subject_in_acl (NM_CONNECTION (connection), + subject, + &error_desc)) { + g_set_error_literal (error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + error_desc); + g_free (error_desc); 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 @@ -4210,7 +4095,7 @@ nm_manager_activate_connection (NMManager *self, active = iter->data; if ( connection == nm_active_connection_get_settings_connection (active) - && nm_streq0 (nm_active_connection_get_specific_object (active), specific_object) + && g_strcmp0 (nm_active_connection_get_specific_object (active), specific_object) == 0 && nm_active_connection_get_device (active) == device && nm_auth_subject_is_internal (nm_active_connection_get_subject (active)) && nm_auth_subject_is_internal (subject) @@ -4219,7 +4104,6 @@ nm_manager_activate_connection (NMManager *self, } active = _new_active_connection (self, - _connection_is_vpn (NM_CONNECTION (connection)), NM_CONNECTION (connection), applied, specific_object, @@ -4228,11 +4112,10 @@ nm_manager_activate_connection (NMManager *self, activation_type, activation_reason, error); - if (!active) - return NULL; - - priv->authorizing_connections = g_slist_prepend (priv->authorizing_connections, active); - nm_active_connection_authorize (active, NULL, _internal_activation_auth_done, self, NULL); + if (active) { + priv->authorizing_connections = g_slist_prepend (priv->authorizing_connections, active); + nm_active_connection_authorize (active, NULL, _internal_activation_auth_done, self, NULL); + } return active; } @@ -4241,12 +4124,9 @@ nm_manager_activate_connection (NMManager *self, * @self: the #NMManager * @context: the D-Bus context of the requestor * @connection: the partial or complete #NMConnection to be activated - * @device_path: the object path of the device to be activated, or NULL + * @device_path: the object path of the device to be activated, or "/" * @out_device: on successful reutrn, the #NMDevice to be activated with @connection - * The caller may pass in a device which shortcuts the lookup by path. - * In this case, the passed in device must have the matching @device_path - * already. - * @out_is_vpn: on successful return, %TRUE if @connection is a VPN connection + * @out_vpn: on successful return, %TRUE if @connection is a VPN connection * @error: location to store an error on failure * * Performs basic validation on an activation request, including ensuring that @@ -4262,16 +4142,17 @@ validate_activation_request (NMManager *self, NMConnection *connection, const char *device_path, NMDevice **out_device, - gboolean *out_is_vpn, + gboolean *out_vpn, GError **error) { NMDevice *device = NULL; - gboolean is_vpn = FALSE; - gs_unref_object NMAuthSubject *subject = NULL; + gboolean vpn = FALSE; + NMAuthSubject *subject = NULL; + char *error_desc = NULL; - nm_assert (NM_IS_CONNECTION (connection)); - nm_assert (out_device); - nm_assert (out_is_vpn); + g_assert (connection); + g_assert (out_device); + g_assert (out_vpn); /* Validate the caller */ subject = nm_auth_subject_new_unix_process_from_context (context); @@ -4283,80 +4164,76 @@ validate_activation_request (NMManager *self, return NULL; } - if (!nm_auth_is_subject_in_acl_set_error (connection, - subject, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - error)) - return NULL; + /* Ensure the subject has permissions for this connection */ + if (!nm_auth_is_subject_in_acl (connection, + subject, + &error_desc)) { + g_set_error_literal (error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + error_desc); + g_free (error_desc); + goto error; + } + + /* Check whether it's a VPN or not */ + if ( nm_connection_get_setting_vpn (connection) + || nm_connection_is_type (connection, NM_SETTING_VPN_SETTING_NAME)) + vpn = TRUE; - is_vpn = _connection_is_vpn (connection); + /* Normalize device path */ + if (device_path && g_strcmp0 (device_path, "/") == 0) + device_path = NULL; - 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) { + /* And validate it */ + 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; + goto error; } - } else if (!is_vpn) { + } else device = nm_manager_get_best_device_for_connection (self, connection, TRUE, NULL); - 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_literal (error, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_UNKNOWN_DEVICE, - "No suitable device found for this connection."); - return NULL; - } - /* Look for an existing device with the connection's interface name */ - iface = nm_manager_get_connection_iface (self, connection, NULL, error); - if (!iface) - return NULL; + if (!device && !vpn) { + gs_free char *iface = 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; - } + /* 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_literal (error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "No suitable device found for this connection."); + goto error; } + + /* Look for an existing device with the connection's interface name */ + iface = nm_manager_get_connection_iface (self, connection, NULL, error); + if (!iface) + goto error; + + device = find_device_by_iface (self, iface, connection, NULL); } - if (is_vpn && device) { - /* VPN's are treated specially. Maybe the should accept a device as well, - * however, later on during activation, we don't handle the device. - * - * Maybe we should, and maybe it makes sense to specify a device - * when activating a VPN. But for now, just error out. */ + if ((!vpn || device_path) && !device) { g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, - "Cannot specify device when activating VPN"); - return NULL; + "Failed to find a compatible device for this connection"); + goto error; } - nm_assert ( ( is_vpn && !device) - || (!is_vpn && NM_IS_DEVICE (device))); - *out_device = device; - *out_is_vpn = is_vpn; - return g_steal_pointer (&subject); + *out_vpn = vpn; + return subject; + +error: + g_object_unref (subject); + return NULL; } /*****************************************************************************/ @@ -4378,27 +4255,24 @@ _activation_auth_done (NMActiveConnection *active, subject = nm_active_connection_get_subject (active); connection = nm_active_connection_get_settings_connection (active); - if (!success) { + if (success) { + if (_internal_activate_generic (self, active, &error)) { + nm_settings_connection_autoconnect_blocked_reason_set (connection, + NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST, + FALSE); + g_dbus_method_invocation_return_value (context, + g_variant_new ("(o)", + nm_exported_object_get_path (NM_EXPORTED_OBJECT (active)))); + nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ACTIVATE, connection, TRUE, NULL, + subject, NULL); + return; + } + } else { 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 (context, - 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, @@ -4409,15 +4283,12 @@ fail: } 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); +impl_manager_activate_connection (NMManager *self, + GDBusMethodInvocation *context, + const char *connection_path, + const char *device_path, + const char *specific_object_path) +{ NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); gs_unref_object NMActiveConnection *active = NULL; gs_unref_object NMAuthSubject *subject = NULL; @@ -4425,15 +4296,14 @@ impl_manager_activate_connection (NMDBusObject *obj, 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_utils_dbus_normalize_object_path (connection_path); - specific_object_path = nm_utils_dbus_normalize_object_path (specific_object_path); - device_path = nm_utils_dbus_normalize_object_path (device_path); + /* Normalize object paths */ + if (g_strcmp0 (connection_path, "/") == 0) + connection_path = NULL; + if (g_strcmp0 (specific_object_path, "/") == 0) + specific_object_path = NULL; + if (g_strcmp0 (device_path, "/") == 0) + device_path = NULL; /* If the connection path is given and valid, that connection is activated. * Otherwise the "best" connection for the device is chosen and activated, @@ -4468,7 +4338,7 @@ impl_manager_activate_connection (NMDBusObject *obj, } subject = validate_activation_request (self, - invocation, + context, NM_CONNECTION (connection), device_path, &device, @@ -4478,7 +4348,6 @@ impl_manager_activate_connection (NMDBusObject *obj, goto error; active = _new_active_connection (self, - is_vpn, NM_CONNECTION (connection), NULL, specific_object_path, @@ -4497,7 +4366,7 @@ impl_manager_activate_connection (NMDBusObject *obj, NULL, _activation_auth_done, self, - invocation); + context); return; error: @@ -4505,7 +4374,7 @@ error: nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ACTIVATE, connection, FALSE, NULL, subject, error->message); } - g_dbus_method_invocation_take_error (invocation, error); + g_dbus_method_invocation_take_error (context, error); } /*****************************************************************************/ @@ -4526,7 +4395,7 @@ activation_add_done (NMSettings *settings, AddAndActivateInfo *info = user_data; NMManager *self; gs_unref_object NMActiveConnection *active = NULL; - gs_free_error GError *local = NULL; + GError *local = NULL; self = info->manager; active = info->active; @@ -4545,8 +4414,8 @@ activation_add_done (NMSettings *settings, g_dbus_method_invocation_return_value ( context, g_variant_new ("(oo)", - nm_dbus_object_get_path (NM_DBUS_OBJECT (new_connection)), - nm_dbus_object_get_path (NM_DBUS_OBJECT (active)))); + nm_connection_get_path (NM_CONNECTION (new_connection)), + nm_exported_object_get_path (NM_EXPORTED_OBJECT (active)))); nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD_ACTIVATE, nm_active_connection_get_settings_connection (active), TRUE, @@ -4559,7 +4428,6 @@ activation_add_done (NMSettings *settings, } nm_assert (error); - nm_active_connection_set_state_fail (active, NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN, error->message); @@ -4572,6 +4440,7 @@ activation_add_done (NMSettings *settings, NULL, nm_active_connection_get_subject (active), error->message); + g_clear_error (&local); } static void @@ -4586,12 +4455,27 @@ _add_and_activate_auth_done (NMActiveConnection *active, GDBusMethodInvocation *context = user_data2; AddAndActivateInfo *info; GError *error = NULL; - gs_unref_object NMConnection *connection = NULL; - connection = g_object_steal_qdata (G_OBJECT (active), - active_connection_add_and_activate_quark ()); + if (success) { + NMConnection *connection; + + connection = g_object_steal_qdata (G_OBJECT (active), + active_connection_add_and_activate_quark ()); + + info = g_slice_new (AddAndActivateInfo); + info->manager = self; + info->active = g_object_ref (active); - if (!success) { + /* Basic sender auth checks performed; try to add the connection */ + nm_settings_add_connection_dbus (priv->settings, + connection, + FALSE, + context, + activation_add_done, + info); + g_object_unref (connection); + } else { + g_assert (error_desc); error = g_error_new_literal (NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED, error_desc); @@ -4602,50 +4486,32 @@ _add_and_activate_auth_done (NMActiveConnection *active, nm_active_connection_get_subject (active), error->message); g_dbus_method_invocation_take_error (context, error); - g_object_unref (active); - return; } - info = g_slice_new (AddAndActivateInfo); - info->manager = self; - - /* we pass on the reference to @active. */ - info->active = active; - - /* Basic sender auth checks performed; try to add the connection */ - nm_settings_add_connection_dbus (priv->settings, - connection, - FALSE, - context, - activation_add_done, - info); + g_object_unref (active); } 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); +impl_manager_add_and_activate_connection (NMManager *self, + GDBusMethodInvocation *context, + GVariant *settings, + const char *device_path, + const char *specific_object_path) +{ NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - gs_unref_object NMConnection *connection = NULL; + NMConnection *connection = NULL; + GSList *all_connections = NULL; NMActiveConnection *active = NULL; - gs_unref_object NMAuthSubject *subject = NULL; + NMAuthSubject *subject = NULL; GError *error = NULL; NMDevice *device = NULL; - gboolean is_vpn = FALSE; - gs_unref_variant GVariant *settings = NULL; - const char *device_path; - const char *specific_object_path; + gboolean vpn = FALSE; - g_variant_get (parameters, "(@a{sa{sv}}&o&o)", &settings, &device_path, &specific_object_path); - - specific_object_path = nm_utils_dbus_normalize_object_path (specific_object_path); - device_path = nm_utils_dbus_normalize_object_path (device_path); + /* Normalize object paths */ + if (g_strcmp0 (specific_object_path, "/") == 0) + specific_object_path = NULL; + if (g_strcmp0 (device_path, "/") == 0) + device_path = NULL; /* Try to create a new connection with the given settings. * We allow empty settings for AddAndActivateConnection(). In that case, @@ -4659,16 +4525,29 @@ impl_manager_add_and_activate_connection (NMDBusObject *obj, _nm_connection_replace_settings (connection, settings, NM_SETTING_PARSE_FLAGS_STRICT, NULL); subject = validate_activation_request (self, - invocation, + context, connection, device_path, &device, - &is_vpn, + &vpn, &error); if (!subject) goto error; - if (is_vpn) { + { + gs_free NMSettingsConnection **connections = NULL; + guint i, len; + + connections = nm_settings_get_connections_clone (priv->settings, &len, + NULL, NULL, + nm_settings_connection_cmp_autoconnect_priority_p_with_data, NULL); + all_connections = NULL; + for (i = len; i > 0; ) { + i--; + all_connections = g_slist_prepend (all_connections, connections[i]); + } + } + if (vpn) { /* Try to fill the VPN's connection setting and name at least */ if (!nm_connection_get_setting_vpn (connection)) { error = g_error_new_literal (NM_CONNECTION_ERROR, @@ -4681,7 +4560,7 @@ impl_manager_add_and_activate_connection (NMDBusObject *obj, nm_utils_complete_generic (priv->platform, connection, NM_SETTING_VPN_SETTING_NAME, - (NMConnection *const*) nm_settings_get_connections (priv->settings, NULL), + all_connections, NULL, _("VPN connection"), NULL, @@ -4691,13 +4570,14 @@ impl_manager_add_and_activate_connection (NMDBusObject *obj, if (!nm_device_complete_connection (device, connection, specific_object_path, - (NMConnection *const*) nm_settings_get_connections (priv->settings, NULL), + all_connections, &error)) goto error; } + g_slist_free (all_connections); + all_connections = NULL; active = _new_active_connection (self, - is_vpn, connection, NULL, specific_object_path, @@ -4709,26 +4589,24 @@ impl_manager_add_and_activate_connection (NMDBusObject *obj, if (!active) goto error; - /* FIXME: nm_active_connection_authorize() already has two user-data pointers - * to piggyback additional data. Instead of attaching the third argument to - * @active's user-data, add a third paramter. - * Or alternatively, allocate a data structure to pass on additional data. - * Then we don't need two user-data pointers. */ g_object_set_qdata_full (G_OBJECT (active), active_connection_add_and_activate_quark (), connection, g_object_unref); - nm_active_connection_authorize (active, connection, _add_and_activate_auth_done, self, invocation); - - /* we passed the pointers on to the callback of authorize. */ - g_steal_pointer (&connection); - g_steal_pointer (&active); + nm_active_connection_authorize (active, connection, _add_and_activate_auth_done, self, context); + g_object_unref (subject); 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); + g_clear_object (&connection); + g_slist_free (all_connections); + g_clear_object (&subject); + g_clear_object (&active); + + g_assert (error); + g_dbus_method_invocation_take_error (context, error); } /*****************************************************************************/ @@ -4824,28 +4702,21 @@ deactivate_net_auth_done_cb (NMAuthChain *chain, else g_dbus_method_invocation_return_value (context, NULL); - nm_auth_chain_destroy (chain); + nm_auth_chain_unref (chain); } 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); +impl_manager_deactivate_connection (NMManager *self, + GDBusMethodInvocation *context, + const char *active_path) +{ NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); NMActiveConnection *ac; NMSettingsConnection *connection = NULL; GError *error = NULL; NMAuthSubject *subject = NULL; NMAuthChain *chain; - const char *active_path; - - g_variant_get (parameters, "(&o)", &active_path); + char *error_desc = NULL; /* Find the connection by its object path */ ac = active_connection_get_by_path (self, active_path); @@ -4860,7 +4731,7 @@ impl_manager_deactivate_connection (NMDBusObject *obj, } /* Validate the caller */ - subject = nm_auth_subject_new_unix_process_from_context (invocation); + subject = nm_auth_subject_new_unix_process_from_context (context); if (!subject) { error = g_error_new_literal (NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED, @@ -4868,15 +4739,19 @@ impl_manager_deactivate_connection (NMDBusObject *obj, goto done; } - if (!nm_auth_is_subject_in_acl_set_error (NM_CONNECTION (connection), - subject, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - &error)) + /* Ensure the subject has permissions for this connection */ + if (!nm_auth_is_subject_in_acl (NM_CONNECTION (connection), + subject, + &error_desc)) { + error = g_error_new_literal (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + error_desc); + g_free (error_desc); goto done; + } /* Validate the user request */ - chain = nm_auth_chain_new_subject (subject, invocation, deactivate_net_auth_done_cb, self); + chain = nm_auth_chain_new_subject (subject, context, deactivate_net_auth_done_cb, self); if (!chain) { error = g_error_new_literal (NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED, @@ -4894,7 +4769,7 @@ done: nm_audit_log_connection_op (NM_AUDIT_OP_CONN_DEACTIVATE, connection, FALSE, NULL, subject, error->message); } - g_dbus_method_invocation_take_error (invocation, error); + g_dbus_method_invocation_take_error (context, error); } g_clear_object (&subject); } @@ -5002,7 +4877,7 @@ do_sleep_wake (NMManager *self, gboolean sleeping_changed) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); gboolean suspending, waking_from_suspend; - NMDevice *device; + GSList *iter; suspending = sleeping_changed && priv->sleeping; waking_from_suspend = sleeping_changed && !priv->sleeping; @@ -5013,7 +4888,9 @@ do_sleep_wake (NMManager *self, gboolean sleeping_changed) /* 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) { + for (iter = priv->devices; iter; iter = iter->next) { + NMDevice *device = iter->data; + /* FIXME: shouldn't we be unmanaging software devices if !suspending? */ if (nm_device_is_software (device)) continue; @@ -5041,7 +4918,9 @@ do_sleep_wake (NMManager *self, gboolean sleeping_changed) if (waking_from_suspend) { sleep_devices_clear (self); - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { + for (iter = priv->devices; iter; iter = iter->next) { + NMDevice *device = iter->data; + if (nm_device_is_software (device)) continue; @@ -5068,7 +4947,8 @@ do_sleep_wake (NMManager *self, gboolean sleeping_changed) nm_manager_rfkill_update (self, RFKILL_TYPE_UNKNOWN); /* Re-manage managed devices */ - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { + for (iter = priv->devices; iter; iter = iter->next) { + NMDevice *device = NM_DEVICE (iter->data); guint i; if (nm_device_is_software (device)) { @@ -5161,28 +5041,27 @@ sleep_auth_done_cb (NMAuthChain *chain, g_dbus_method_invocation_return_value (context, NULL); } - nm_auth_chain_destroy (chain); + nm_auth_chain_unref (chain); } #endif 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); +impl_manager_sleep (NMManager *self, + GDBusMethodInvocation *context, + gboolean do_sleep) +{ + NMManagerPrivate *priv; GError *error = NULL; gs_unref_object NMAuthSubject *subject = NULL; - gboolean do_sleep; +#if 0 + NMAuthChain *chain; + const char *error_desc = NULL; +#endif - g_variant_get (parameters, "(b)", &do_sleep); + g_return_if_fail (NM_IS_MANAGER (self)); - subject = nm_auth_subject_new_unix_process_from_context (invocation); + priv = NM_MANAGER_GET_PRIVATE (self); + subject = nm_auth_subject_new_unix_process_from_context (context); if (priv->sleeping == do_sleep) { error = g_error_new (NM_MANAGER_ERROR, @@ -5190,7 +5069,7 @@ impl_manager_sleep (NMDBusObject *obj, "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); + g_dbus_method_invocation_take_error (context, error); return; } @@ -5204,8 +5083,22 @@ impl_manager_sleep (NMDBusObject *obj, */ _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); + g_dbus_method_invocation_return_value (context, NULL); return; + +#if 0 + chain = nm_auth_chain_new (context, sleep_auth_done_cb, self, &error_desc); + if (chain) { + priv->auth_chains = g_slist_append (priv->auth_chains, chain); + nm_auth_chain_set_data (chain, "sleep", GUINT_TO_POINTER (do_sleep), NULL); + nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SLEEP_WAKE, TRUE); + } else { + error = g_error_new_literal (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + error_desc); + g_dbus_method_invocation_take_error (context, error); + } +#endif } static void @@ -5281,25 +5174,21 @@ enable_net_done_cb (NMAuthChain *chain, g_dbus_method_invocation_take_error (context, ret_error); } - nm_auth_chain_destroy (chain); + nm_auth_chain_unref (chain); } 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); +impl_manager_enable (NMManager *self, + GDBusMethodInvocation *context, + gboolean enable) +{ + NMManagerPrivate *priv; NMAuthChain *chain; GError *error = NULL; - gboolean enable; - g_variant_get (parameters, "(b)", &enable); + g_return_if_fail (NM_IS_MANAGER (self)); + + priv = NM_MANAGER_GET_PRIVATE (self); if (priv->net_enabled == enable) { error = g_error_new (NM_MANAGER_ERROR, @@ -5308,7 +5197,7 @@ impl_manager_enable (NMDBusObject *obj, goto done; } - chain = nm_auth_chain_new_context (invocation, enable_net_done_cb, self); + chain = nm_auth_chain_new_context (context, enable_net_done_cb, self); if (!chain) { error = g_error_new_literal (NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED, @@ -5322,7 +5211,7 @@ impl_manager_enable (NMDBusObject *obj, done: if (error) - g_dbus_method_invocation_take_error (invocation, error); + g_dbus_method_invocation_take_error (context, error); } /* Permissions */ @@ -5389,28 +5278,23 @@ get_permissions_done_cb (NMAuthChain *chain, g_variant_new ("(a{ss})", &results)); } - nm_auth_chain_destroy (chain); + nm_auth_chain_unref (chain); } 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) -{ - NMManager *self = NM_MANAGER (obj); +impl_manager_get_permissions (NMManager *self, + GDBusMethodInvocation *context) +{ NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); NMAuthChain *chain; + GError *error = NULL; - chain = nm_auth_chain_new_context (invocation, get_permissions_done_cb, self); + chain = nm_auth_chain_new_context (context, get_permissions_done_cb, self); if (!chain) { - g_dbus_method_invocation_return_error_literal (invocation, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - "Unable to authenticate request."); + error = g_error_new_literal (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + "Unable to authenticate request."); + g_dbus_method_invocation_take_error (context, error); return; } @@ -5434,123 +5318,83 @@ impl_manager_get_permissions (NMDBusObject *obj, } 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_get_state (NMManager *self, + GDBusMethodInvocation *context) { - NMManager *self = NM_MANAGER (obj); - nm_manager_update_state (self); - g_dbus_method_invocation_return_value (invocation, + g_dbus_method_invocation_return_value (context, 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); +impl_manager_set_logging (NMManager *self, + GDBusMethodInvocation *context, + const char *level, + const char *domains) +{ 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)) + if (!nm_bus_manager_ensure_uid (nm_bus_manager_get (), + context, + 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); + g_dbus_method_invocation_take_error (context, error); else - g_dbus_method_invocation_return_value (invocation, NULL); + g_dbus_method_invocation_return_value (context, 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) -{ - g_dbus_method_invocation_return_value (invocation, +impl_manager_get_logging (NMManager *manager, + GDBusMethodInvocation *context) +{ + g_dbus_method_invocation_return_value (context, g_variant_new ("(ss)", nm_logging_level_to_string (), nm_logging_domains_to_string ())); } typedef struct { - NMManager *self; - GDBusMethodInvocation *context; guint remaining; + GDBusMethodInvocation *context; + NMConnectivityState state; } ConnectivityCheckData; static void -device_connectivity_done (NMDevice *device, - NMDeviceConnectivityHandle *handle, - NMConnectivityState state, - GError *error, - gpointer user_data) +device_connectivity_done (NMDevice *device, NMConnectivityState state, 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); + /* We check if the state is already FULL so that we can provide the + * response without waiting for slower devices that are not going to + * affect the overall state anyway. */ - 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->state != NM_CONNECTIVITY_FULL) { + if (state > data->state) + data->state = state; + + if (data->state == NM_CONNECTIVITY_FULL || !data->remaining) { + g_dbus_method_invocation_return_value (data->context, + g_variant_new ("(u)", data->state)); + } } - if (data->remaining == 0) { - g_object_unref (self); + if (!data->remaining) g_slice_free (ConnectivityCheckData, data); - } } static void @@ -5564,7 +5408,7 @@ check_connectivity_auth_done_cb (NMAuthChain *chain, GError *error = NULL; NMAuthCallResult result; ConnectivityCheckData *data; - NMDevice *device; + const GSList *devices; priv->auth_chains = g_slist_remove (priv->auth_chains, chain); @@ -5580,59 +5424,39 @@ check_connectivity_auth_done_cb (NMAuthChain *chain, 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); - goto out; - } - - data = g_slice_new (ConnectivityCheckData); - data->self = g_object_ref (self); - data->context = context; - data->remaining = 0; + } else { + /* it's allowed */ + data = g_slice_new0 (ConnectivityCheckData); + data->context = context; - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { - if (nm_device_check_connectivity (device, - device_connectivity_done, - data)) + for (devices = priv->devices; devices; devices = devices->next) { data->remaining++; + nm_device_check_connectivity (NM_DEVICE (devices->data), + device_connectivity_done, + data); + } } - 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. */ - } - -out: - nm_auth_chain_destroy (chain); + if (error) + g_dbus_method_invocation_take_error (context, error); + nm_auth_chain_unref (chain); } 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) -{ - NMManager *self = NM_MANAGER (obj); +impl_manager_check_connectivity (NMManager *self, + GDBusMethodInvocation *context) +{ NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); NMAuthChain *chain; + GError *error = NULL; - chain = nm_auth_chain_new_context (invocation, check_connectivity_auth_done_cb, self); + /* Validate the request */ + chain = nm_auth_chain_new_context (context, check_connectivity_auth_done_cb, self); if (!chain) { - g_dbus_method_invocation_return_error_literal(invocation, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - "Unable to authenticate request."); + error = g_error_new_literal (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + "Unable to authenticate request."); + g_dbus_method_invocation_take_error (context, error); return; } @@ -5649,14 +5473,15 @@ start_factory (NMDeviceFactory *factory, gpointer user_data) void nm_manager_write_device_state (NMManager *self) { + const GSList *devices; NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device; gs_unref_hashtable GHashTable *seen_ifindexes = NULL; gint nm_owned; - seen_ifindexes = g_hash_table_new (nm_direct_hash, NULL); + seen_ifindexes = g_hash_table_new (NULL, NULL); - c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { + for (devices = priv->devices; devices; devices = devices->next) { + NMDevice *device = NM_DEVICE (devices->data); int ifindex; gboolean managed; NMConfigDeviceStateManagedType managed_type; @@ -5797,10 +5622,10 @@ void nm_manager_stop (NMManager *self) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device; - while ((device = c_list_first_entry (&priv->devices_lst_head, NMDevice, devices_lst))) - remove_device (self, device, TRUE, TRUE); + /* Remove all devices */ + while (priv->devices) + remove_device (self, NM_DEVICE (priv->devices->data), TRUE, TRUE); _active_connection_cleanup (self); @@ -5812,20 +5637,21 @@ handle_firmware_changed (gpointer user_data) { NMManager *self = NM_MANAGER (user_data); NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMDevice *device; + GSList *iter; 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); + for (iter = priv->devices; iter; iter = iter->next) { + NMDevice *candidate = NM_DEVICE (iter->data); + NMDeviceState state = nm_device_get_state (candidate); - if ( nm_device_get_firmware_missing (device) + if ( nm_device_get_firmware_missing (candidate) && (state == NM_DEVICE_STATE_UNAVAILABLE)) { - _LOG2I (LOGD_CORE, device, "firmware may now be available"); + _LOG2I (LOGD_CORE, candidate, "firmware may now be available"); /* Re-set unavailable state to try bringing the device up again */ - nm_device_state_changed (device, + nm_device_state_changed (candidate, NM_DEVICE_STATE_UNAVAILABLE, NM_DEVICE_STATE_REASON_NONE); } @@ -5944,133 +5770,318 @@ policy_activating_device_changed (GObject *object, GParamSpec *pspec, gpointer u } } -/*****************************************************************************/ +#define NM_PERM_DENIED_ERROR "org.freedesktop.NetworkManager.PermissionDenied" typedef struct { NMManager *self; - NMDBusObject *obj; - const NMDBusInterfaceInfoExtended *interface_info; - const NMDBusPropertyInfoExtended *property_info; - GVariant *value; - guint64 export_version_id; -} DBusSetPropertyHandle; + GDBusConnection *connection; + GDBusMessage *message; + NMAuthSubject *subject; + const char *permission; + const char *audit_op; + char *audit_prop_value; + GType interface_type; + const char *glib_propname; +} PropertyFilterData; -#define NM_PERM_DENIED_ERROR "org.freedesktop.NetworkManager.PermissionDenied" +static void +free_property_filter_data (PropertyFilterData *pfd) +{ + g_object_unref (pfd->self); + g_object_unref (pfd->connection); + g_object_unref (pfd->message); + g_clear_object (&pfd->subject); + g_free (pfd->audit_prop_value); + g_slice_free (PropertyFilterData, pfd); +} static void -_dbus_set_property_auth_cb (NMAuthChain *chain, - GError *error, - GDBusMethodInvocation *invocation, - gpointer user_data) +prop_set_auth_done_cb (NMAuthChain *chain, + GError *error, + GDBusMethodInvocation *context, /* NULL */ + 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); + PropertyFilterData *pfd = user_data; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (pfd->self); NMAuthCallResult result; - const char *error_name = NULL; - const char *error_message = NULL; - GValue gvalue; - - g_slice_free (DBusSetPropertyHandle, handle_data); + GDBusMessage *reply = NULL; + const char *error_message; + gs_unref_object NMExportedObject *object = NULL; + const NMGlobalDnsConfig *global_dns; + gs_unref_variant GVariant *value = NULL; + GVariant *args; priv->auth_chains = g_slist_remove (priv->auth_chains, chain); - result = nm_auth_chain_get_result (chain, property_info->writable.permission); + result = nm_auth_chain_get_result (chain, pfd->permission); + if (error || (result != NM_AUTH_CALL_RESULT_YES)) { + reply = g_dbus_message_new_method_error_literal (pfd->message, + NM_PERM_DENIED_ERROR, + (error_message = "Not authorized to perform this operation")); + if (error) + error_message = error->message; + goto done; + } - if ( error - || result != NM_AUTH_CALL_RESULT_YES) { - error_name = NM_PERM_DENIED_ERROR; - error_message = error ? error->message : "Not authorized to perform this operation"; - goto out; + object = NM_EXPORTED_OBJECT (nm_bus_manager_get_registered_object (priv->dbus_mgr, + g_dbus_message_get_path (pfd->message))); + if (!object) { + reply = g_dbus_message_new_method_error_literal (pfd->message, + "org.freedesktop.DBus.Error.UnknownObject", + (error_message = "Object doesn't exist.")); + goto done; } - 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; + /* do some extra type checking... */ + if (!nm_exported_object_get_interface_by_type (object, pfd->interface_type)) { + reply = g_dbus_message_new_method_error_literal (pfd->message, + "org.freedesktop.DBus.Error.InvalidArgs", + (error_message = "Object is of unexpected type.")); + goto done; } - /* 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; + args = g_dbus_message_get_body (pfd->message); + g_variant_get (args, "(&s&sv)", NULL, NULL, &value); + g_assert (pfd->glib_propname); + if (!strcmp (pfd->glib_propname, NM_MANAGER_GLOBAL_DNS_CONFIGURATION)) { + g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE ("a{sv}"))); 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; + + if (global_dns && !nm_global_dns_config_is_internal (global_dns)) { + reply = g_dbus_message_new_method_error_literal (pfd->message, + NM_PERM_DENIED_ERROR, + (error_message = "Global DNS configuration already set via configuration file")); + goto done; } + /* ... but set the property on the @object itself. It would be correct to set the property + * on the skeleton interface, but as it is now, the result is the same. */ + g_object_set (object, pfd->glib_propname, value, NULL); + } else if (!strcmp (pfd->glib_propname, NM_DEVICE_STATISTICS_REFRESH_RATE_MS)) { + g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32)); + /* the same here */ + g_object_set (object, pfd->glib_propname, (guint) g_variant_get_uint32 (value), NULL); + } else { + g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN)); + /* the same here */ + g_object_set (object, pfd->glib_propname, g_variant_get_boolean (value), NULL); } - g_dbus_gvariant_to_gvalue (value, &gvalue); - g_object_set_property (G_OBJECT (obj), property_info->property_name, &gvalue); - g_value_unset (&gvalue); + reply = g_dbus_message_new_method_reply (pfd->message); + g_dbus_message_set_body (reply, g_variant_new_tuple (NULL, 0)); + error_message = NULL; +done: + nm_audit_log_control_op (pfd->audit_op, pfd->audit_prop_value, !error_message, pfd->subject, error_message); -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_auth_chain_destroy (chain); + g_dbus_connection_send_message (pfd->connection, reply, + G_DBUS_SEND_MESSAGE_FLAGS_NONE, + NULL, NULL); + g_object_unref (reply); + nm_auth_chain_unref (chain); + + free_property_filter_data (pfd); } -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) +static gboolean +do_set_property_check (gpointer user_data) { - NMManager *self = user_data; - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + PropertyFilterData *pfd = user_data; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (pfd->self); + GDBusMessage *reply = NULL; NMAuthChain *chain; const char *error_message = NULL; - gs_unref_object NMAuthSubject *subject = NULL; - DBusSetPropertyHandle *handle_data; - subject = nm_auth_subject_new_unix_process_from_context (invocation); - if (!subject) { - error_message = "Could not determine request UID"; - goto err; + pfd->subject = nm_auth_subject_new_unix_process_from_message (pfd->connection, pfd->message); + if (!pfd->subject) { + reply = g_dbus_message_new_method_error_literal (pfd->message, + NM_PERM_DENIED_ERROR, + (error_message = "Could not determine request UID.")); + goto out; } - 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); + /* Validate the user request */ + chain = nm_auth_chain_new_subject (pfd->subject, NULL, prop_set_auth_done_cb, pfd); + if (!chain) { + reply = g_dbus_message_new_method_error_literal (pfd->message, + NM_PERM_DENIED_ERROR, + (error_message = "Could not authenticate request.")); + goto out; + } - chain = nm_auth_chain_new_subject (subject, invocation, _dbus_set_property_auth_cb, handle_data); priv->auth_chains = g_slist_append (priv->auth_chains, chain); - nm_auth_chain_add_call (chain, property_info->writable.permission, TRUE); - return; + nm_auth_chain_add_call (chain, pfd->permission, TRUE); + +out: + if (reply) { + nm_audit_log_control_op (pfd->audit_op, pfd->audit_prop_value, FALSE, pfd->subject, error_message); + g_dbus_connection_send_message (pfd->connection, reply, + G_DBUS_SEND_MESSAGE_FLAGS_NONE, + NULL, NULL); + g_object_unref (reply); + free_property_filter_data (pfd); + } + + return FALSE; +} + +static GDBusMessage * +prop_filter (GDBusConnection *connection, + GDBusMessage *message, + gboolean incoming, + gpointer user_data) +{ + gs_unref_object NMManager *self = NULL; + GVariant *args; + const char *propiface = NULL; + const char *propname = NULL; + const char *glib_propname = NULL, *permission = NULL; + const char *audit_op = NULL; + GType interface_type = G_TYPE_INVALID; + PropertyFilterData *pfd; + const GVariantType *expected_type = G_VARIANT_TYPE_BOOLEAN; + gs_unref_variant GVariant *value = NULL; + + self = g_weak_ref_get (user_data); + if (!self) + return message; + + /* The sole purpose of this function is to validate property accesses on the + * NMManager object since gdbus doesn't give us this functionality. + */ + + /* Only filter org.freedesktop.DBus.Properties.Set calls */ + if ( !incoming + || g_dbus_message_get_message_type (message) != G_DBUS_MESSAGE_TYPE_METHOD_CALL + || g_strcmp0 (g_dbus_message_get_interface (message), DBUS_INTERFACE_PROPERTIES) != 0 + || g_strcmp0 (g_dbus_message_get_member (message), "Set") != 0) + return message; + + args = g_dbus_message_get_body (message); + if (!g_variant_is_of_type (args, G_VARIANT_TYPE ("(ssv)"))) + return message; + g_variant_get (args, "(&s&sv)", &propiface, &propname, &value); + + /* Only filter calls to filtered properties, on existing objects */ + if (!strcmp (propiface, NM_DBUS_INTERFACE)) { + if (!strcmp (propname, "WirelessEnabled")) { + glib_propname = NM_MANAGER_WIRELESS_ENABLED; + permission = NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI; + audit_op = NM_AUDIT_OP_RADIO_CONTROL; + } else if (!strcmp (propname, "WwanEnabled")) { + glib_propname = NM_MANAGER_WWAN_ENABLED; + permission = NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN; + audit_op = NM_AUDIT_OP_RADIO_CONTROL; + } else if (!strcmp (propname, "WimaxEnabled")) { + glib_propname = NM_MANAGER_WIMAX_ENABLED; + permission = NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX; + audit_op = NM_AUDIT_OP_RADIO_CONTROL; + } else if (!strcmp (propname, "GlobalDnsConfiguration")) { + glib_propname = NM_MANAGER_GLOBAL_DNS_CONFIGURATION; + permission = NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS; + audit_op = NM_AUDIT_OP_NET_CONTROL; + expected_type = G_VARIANT_TYPE ("a{sv}"); + } else if (!strcmp (propname, "ConnectivityCheckEnabled")) { + glib_propname = NM_MANAGER_CONNECTIVITY_CHECK_ENABLED; + permission = NM_AUTH_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK; + audit_op = NM_AUDIT_OP_NET_CONTROL; + } else + return message; + interface_type = NMDBUS_TYPE_MANAGER_SKELETON; + } else if (!strcmp (propiface, NM_DBUS_INTERFACE_DEVICE)) { + if (!strcmp (propname, "Autoconnect")) { + glib_propname = NM_DEVICE_AUTOCONNECT; + permission = NM_AUTH_PERMISSION_NETWORK_CONTROL; + audit_op = NM_AUDIT_OP_DEVICE_AUTOCONNECT; + } else if (!strcmp (propname, "Managed")) { + glib_propname = NM_DEVICE_MANAGED; + permission = NM_AUTH_PERMISSION_NETWORK_CONTROL; + audit_op = NM_AUDIT_OP_DEVICE_MANAGED; + } else + return message; + interface_type = NMDBUS_TYPE_DEVICE_SKELETON; + } else if (!strcmp (propiface, NM_DBUS_INTERFACE_DEVICE_STATISTICS)) { + if (!strcmp (propname, "RefreshRateMs")) { + glib_propname = NM_DEVICE_STATISTICS_REFRESH_RATE_MS; + permission = NM_AUTH_PERMISSION_ENABLE_DISABLE_STATISTICS; + audit_op = NM_AUDIT_OP_STATISTICS; + expected_type = G_VARIANT_TYPE ("u"); + } else + return message; + interface_type = NMDBUS_TYPE_DEVICE_SKELETON; + } else + return message; + + if (!g_variant_is_of_type (value, expected_type)) + return message; + + /* This filter function is called from a gdbus worker thread which we can't + * make other D-Bus calls from. In particular, we cannot call + * org.freedesktop.DBus.GetConnectionUnixUser to find the remote UID. + */ + pfd = g_slice_new0 (PropertyFilterData); + pfd->self = self; + self = NULL; + pfd->connection = g_object_ref (connection); + pfd->message = message; + pfd->permission = permission; + pfd->interface_type = interface_type; + pfd->glib_propname = glib_propname; + pfd->audit_op = audit_op; + if (g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN)) { + pfd->audit_prop_value = g_strdup_printf ("%s:%d", pfd->glib_propname, + g_variant_get_boolean (value)); + } else + pfd->audit_prop_value = g_strdup (pfd->glib_propname); + + g_idle_add (do_set_property_check, pfd); + + return NULL; +} + +/*****************************************************************************/ + +static int +_set_prop_filter_free2 (gpointer user_data) +{ + g_slice_free (GWeakRef, user_data); + return G_SOURCE_REMOVE; +} + +static void +_set_prop_filter_free (gpointer user_data) +{ + g_weak_ref_clear (user_data); + + /* Delay the final deletion of the user_data. There is a race when + * calling g_dbus_connection_remove_filter() that the callback and user_data + * might have been copied and being executed after the destroy function + * runs (bgo #704568). + * This doesn't really fix the race, but it should work well enough. */ + g_timeout_add_seconds (2, _set_prop_filter_free2, user_data); +} + +static void +_set_prop_filter (NMManager *self, GDBusConnection *connection) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + + nm_assert ((!priv->prop_filter.connection) == (!priv->prop_filter.id)); + + if (priv->prop_filter.connection == connection) + return; + + if (priv->prop_filter.connection) { + g_dbus_connection_remove_filter (priv->prop_filter.connection, priv->prop_filter.id); + priv->prop_filter.id = 0; + g_clear_object (&priv->prop_filter.connection); + } + if (connection) { + GWeakRef *wptr; -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); + wptr = g_slice_new (GWeakRef); + g_weak_ref_init (wptr, self); + priv->prop_filter.id = g_dbus_connection_add_filter (connection, prop_filter, wptr, _set_prop_filter_free); + priv->prop_filter.connection = g_object_ref (connection); + } } /*****************************************************************************/ @@ -6081,7 +6092,7 @@ _checkpoint_mgr_get (NMManager *self, gboolean create_as_needed) 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]); + priv->checkpoint_mgr = nm_checkpoint_manager_new (self); return priv->checkpoint_mgr; } @@ -6100,15 +6111,13 @@ checkpoint_auth_done_cb (NMAuthChain *chain, GVariant *variant = NULL; GError *error = NULL; const char *arg = NULL; - guint32 add_timeout; op = nm_auth_chain_get_data (chain, "audit-op"); priv->auth_chains = g_slist_remove (priv->auth_chains, 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)) + if ( nm_streq0 (op, NM_AUDIT_OP_CHECKPOINT_DESTROY) + || nm_streq0 (op, NM_AUDIT_OP_CHECKPOINT_ROLLBACK)) arg = checkpoint_path = nm_auth_chain_get_data (chain, "checkpoint_path"); if (auth_error) { @@ -6132,7 +6141,7 @@ checkpoint_auth_done_cb (NMAuthChain *chain, (NMCheckpointCreateFlags) flags, &error); if (checkpoint) { - arg = nm_dbus_object_get_path (NM_DBUS_OBJECT (checkpoint)); + arg = nm_exported_object_get_path (NM_EXPORTED_OBJECT (checkpoint)); variant = g_variant_new ("(o)", arg); } } else if (nm_streq0 (op, NM_AUDIT_OP_CHECKPOINT_DESTROY)) { @@ -6141,10 +6150,6 @@ checkpoint_auth_done_cb (NMAuthChain *chain, } 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 (); } @@ -6157,71 +6162,63 @@ checkpoint_auth_done_cb (NMAuthChain *chain, else g_dbus_method_invocation_return_value (context, variant); - nm_auth_chain_destroy (chain); + + nm_auth_chain_unref (chain); } 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); +impl_manager_checkpoint_create (NMManager *self, + GDBusMethodInvocation *context, + const char *const *devices, + guint32 rollback_timeout, + guint32 flags) +{ + NMManagerPrivate *priv; NMAuthChain *chain; - char **devices; - guint32 rollback_timeout; - guint32 flags; + GError *error = NULL; G_STATIC_ASSERT_EXPR (sizeof (flags) <= sizeof (NMCheckpointCreateFlags)); + g_return_if_fail (NM_IS_MANAGER (self)); + priv = NM_MANAGER_GET_PRIVATE (self); - chain = nm_auth_chain_new_context (invocation, checkpoint_auth_done_cb, self); + chain = nm_auth_chain_new_context (context, checkpoint_auth_done_cb, self); if (!chain) { - g_dbus_method_invocation_return_error_literal (invocation, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - "Unable to authenticate request."); + error = g_error_new_literal (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + "Unable to authenticate request."); + g_dbus_method_invocation_take_error (context, error); return; } - g_variant_get (parameters, "(^aouu)", &devices, &rollback_timeout, &flags); - priv->auth_chains = g_slist_append (priv->auth_chains, 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, "devices", g_strdupv ((char **) 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); +impl_manager_checkpoint_destroy (NMManager *self, + GDBusMethodInvocation *context, + const char *checkpoint_path) +{ + NMManagerPrivate *priv; + GError *error = NULL; NMAuthChain *chain; - const char *checkpoint_path; - chain = nm_auth_chain_new_context (invocation, checkpoint_auth_done_cb, self); + g_return_if_fail (NM_IS_MANAGER (self)); + priv = NM_MANAGER_GET_PRIVATE (self); + + chain = nm_auth_chain_new_context (context, checkpoint_auth_done_cb, self); if (!chain) { - g_dbus_method_invocation_return_error_literal (invocation, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - "Unable to authenticate request."); + error = g_error_new_literal (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + "Unable to authenticate request."); + g_dbus_method_invocation_take_error (context, error); return; } - g_variant_get (parameters, "(&o)", &checkpoint_path); - priv->auth_chains = g_slist_append (priv->auth_chains, 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); @@ -6229,66 +6226,29 @@ impl_manager_checkpoint_destroy (NMDBusObject *obj, } 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); +impl_manager_checkpoint_rollback (NMManager *self, + GDBusMethodInvocation *context, + const char *checkpoint_path) +{ + NMManagerPrivate *priv; + GError *error = NULL; 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, - "Unable to authenticate request."); - return; - } - - g_variant_get (parameters, "(&o)", &checkpoint_path); - - priv->auth_chains = g_slist_append (priv->auth_chains, 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; + g_return_if_fail (NM_IS_MANAGER (self)); + priv = NM_MANAGER_GET_PRIVATE (self); - chain = nm_auth_chain_new_context (invocation, checkpoint_auth_done_cb, self); + chain = nm_auth_chain_new_context (context, checkpoint_auth_done_cb, self); if (!chain) { - g_dbus_method_invocation_return_error_literal (invocation, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - "Unable to authenticate request."); + error = g_error_new_literal (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + "Unable to authenticate request."); + g_dbus_method_invocation_take_error (context, error); return; } - g_variant_get (parameters, "(&ou)", &checkpoint_path, &add_timeout); - priv->auth_chains = g_slist_append (priv->auth_chains, chain); - nm_auth_chain_set_data (chain, "audit-op", NM_AUDIT_OP_CHECKPOINT_ADJUST_ROLLBACK_TIMEOUT, NULL); + 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_set_data (chain, "add_timeout", GUINT_TO_POINTER (add_timeout), NULL); nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK, TRUE); } @@ -6298,10 +6258,7 @@ static void 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, - "()"); + g_signal_emit (NM_MANAGER (user_data), signals[CHECK_PERMISSIONS], 0); } #define KERN_RFKILL_OP_CHANGE_ALL 3 @@ -6426,6 +6383,14 @@ periodic_update_active_connection_timestamps (gpointer user_data) return G_SOURCE_CONTINUE; } +static void +dbus_connection_changed_cb (NMBusManager *dbus_mgr, + GDBusConnection *connection, + gpointer user_data) +{ + _set_prop_filter (NM_MANAGER (user_data), connection); +} + /*****************************************************************************/ void @@ -6492,7 +6457,8 @@ nm_manager_setup (void) nm_singleton_instance_register (); _LOGD (LOGD_CORE, "setup %s singleton (%p)", "NMManager", singleton_instance); - nm_dbus_object_export (NM_DBUS_OBJECT (self)); + nm_exported_object_export ((NMExportedObject *) self); + return self; } @@ -6505,9 +6471,11 @@ constructed (GObject *object) G_OBJECT_CLASS (nm_manager_parent_class)->constructed (object); + _set_prop_filter (self, nm_bus_manager_get_connection (priv->dbus_mgr)); + priv->settings = nm_settings_new (); - nm_dbus_object_export (NM_DBUS_OBJECT (priv->settings)); + nm_exported_object_export (NM_EXPORTED_OBJECT (priv->settings)); g_signal_connect (priv->settings, "notify::" NM_SETTINGS_STARTUP_COMPLETE, G_CALLBACK (settings_startup_complete_changed), self); @@ -6575,7 +6543,6 @@ nm_manager_init (NMManager *self) GFile *file; 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->delete_volatile_connection_lst_head); @@ -6607,6 +6574,12 @@ nm_manager_init (NMManager *self) priv->state = NM_STATE_DISCONNECTED; priv->startup = TRUE; + priv->dbus_mgr = g_object_ref (nm_bus_manager_get ()); + g_signal_connect (priv->dbus_mgr, + NM_BUS_MANAGER_DBUS_CONNECTION_CHANGED, + G_CALLBACK (dbus_connection_changed_cb), + self); + /* sleep/wake handling */ priv->sleep_monitor = nm_sleep_monitor_new (); g_signal_connect (priv->sleep_monitor, NM_SLEEP_MONITOR_SLEEPING, @@ -6641,7 +6614,13 @@ nm_manager_init (NMManager *self) 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); + priv->sleep_devices = g_hash_table_new (g_direct_hash, g_direct_equal); +} + +static gboolean +device_is_real (GObject *device, gpointer user_data) +{ + return nm_device_is_real (NM_DEVICE (device)); } static void @@ -6656,6 +6635,7 @@ get_property (GObject *object, guint prop_id, const char *path; NMActiveConnection *ac; GPtrArray *ptrarr; + gboolean vbool; switch (prop_id) { case PROP_VERSION: @@ -6697,7 +6677,7 @@ get_property (GObject *object, guint prop_id, 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)); + path = nm_exported_object_get_path (NM_EXPORTED_OBJECT (ac)); if (path) g_ptr_array_add (ptrarr, g_strdup (path)); } @@ -6712,10 +6692,15 @@ get_property (GObject *object, guint prop_id, 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)); +#if WITH_CONCHECK + vbool = nm_connectivity_check_enabled (nm_connectivity_get ()); +#else + vbool = FALSE; +#endif + g_value_set_boolean (value, vbool); break; case PROP_PRIMARY_CONNECTION: - nm_dbus_utils_g_value_set_object_path (value, priv->primary_connection); + nm_utils_g_value_set_object_path (value, priv->primary_connection); break; case PROP_PRIMARY_CONNECTION_TYPE: type = NULL; @@ -6729,15 +6714,13 @@ get_property (GObject *object, guint prop_id, g_value_set_string (value, type ? type : ""); break; case PROP_ACTIVATING_CONNECTION: - nm_dbus_utils_g_value_set_object_path (value, priv->activating_connection); + nm_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))); + nm_utils_g_value_set_object_path_array (value, priv->devices, device_is_real, NULL); break; case PROP_METERED: g_value_set_uint (value, priv->metered); @@ -6748,16 +6731,7 @@ get_property (GObject *object, guint prop_id, 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); + nm_utils_g_value_set_object_path_array (value, priv->devices, NULL, NULL); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -6824,6 +6798,11 @@ dispose (GObject *object) CList *iter, *iter_safe; NMActiveConnection *ac, *ac_safe; + 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)); + g_signal_handlers_disconnect_by_func (priv->platform, G_CALLBACK (platform_link_cb), self); @@ -6835,18 +6814,14 @@ dispose (GObject *object) g_slice_free (PlatformLinkCbData, data); } - g_slist_free_full (priv->auth_chains, (GDestroyNotify) nm_auth_chain_destroy); + g_slist_free_full (priv->auth_chains, (GDestroyNotify) nm_auth_chain_unref); priv->auth_chains = NULL; nm_clear_g_source (&priv->devices_inited_id); - g_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->checkpoint_mgr) { + nm_checkpoint_manager_destroy_all (priv->checkpoint_mgr, NULL); + g_clear_pointer (&priv->checkpoint_mgr, nm_checkpoint_manager_unref); } if (priv->auth_mgr) { @@ -6856,7 +6831,7 @@ dispose (GObject *object) g_clear_object (&priv->auth_mgr); } - nm_assert (c_list_is_empty (&priv->devices_lst_head)); + g_assert (priv->devices == NULL); nm_clear_g_source (&priv->ac_cleanup_id); @@ -6893,6 +6868,13 @@ dispose (GObject *object) g_clear_object (&priv->vpn_manager); + /* Unregister property filter */ + if (priv->dbus_mgr) { + g_signal_handlers_disconnect_by_func (priv->dbus_mgr, dbus_connection_changed_cb, self); + g_clear_object (&priv->dbus_mgr); + } + _set_prop_filter (self, NULL); + sleep_devices_clear (self); g_clear_pointer (&priv->sleep_devices, g_hash_table_unref); @@ -6915,11 +6897,6 @@ dispose (GObject *object) 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_device_factory_manager_for_each_factory (_deinit_device_factory, self); nm_clear_g_source (&priv->timestamp_update_id); @@ -6941,274 +6918,22 @@ finalize (GObject *object) g_object_unref (priv->platform); } -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_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 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 ( - "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 ("PrimartConnectionType", "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_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); + NMExportedObjectClass *exported_object_class = NM_EXPORTED_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); + exported_object_class->export_path = NM_DBUS_PATH; + /* virtual methods */ object_class->constructed = constructed; object_class->set_property = set_property; object_class->get_property = get_property; object_class->dispose = dispose; object_class->finalize = finalize; + /* properties */ obj_properties[PROP_VERSION] = g_param_spec_string (NM_MANAGER_VERSION, "", "", NULL, @@ -7216,11 +6941,11 @@ nm_manager_class_init (NMManagerClass *manager_class) 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); + 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, "", "", @@ -7371,17 +7096,11 @@ nm_manager_class_init (NMManagerClass *manager_class) 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 */ + /* D-Bus exported; emitted only for realized devices */ signals[DEVICE_ADDED] = g_signal_new (NM_MANAGER_DEVICE_ADDED, G_OBJECT_CLASS_TYPE (object_class), @@ -7397,7 +7116,7 @@ nm_manager_class_init (NMManagerClass *manager_class) NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_OBJECT); - /* emitted only for realized devices when a device + /* D-Bus exported; emitted only for realized devices when a device * becomes unrealized or removed */ signals[DEVICE_REMOVED] = g_signal_new (NM_MANAGER_DEVICE_REMOVED, @@ -7414,6 +7133,20 @@ nm_manager_class_init (NMManagerClass *manager_class) NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_OBJECT); + signals[STATE_CHANGED] = + g_signal_new (NM_MANAGER_STATE_CHANGED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 1, G_TYPE_UINT); + + signals[CHECK_PERMISSIONS] = + g_signal_new (NM_MANAGER_CHECK_PERMISSIONS, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 0); + signals[ACTIVE_CONNECTION_ADDED] = g_signal_new (NM_MANAGER_ACTIVE_CONNECTION_ADDED, G_OBJECT_CLASS_TYPE (object_class), @@ -7434,4 +7167,25 @@ nm_manager_class_init (NMManagerClass *manager_class) G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (manager_class), + NMDBUS_TYPE_MANAGER_SKELETON, + "Reload", impl_manager_reload, + "GetDevices", impl_manager_get_devices, + "GetAllDevices", impl_manager_get_all_devices, + "GetDeviceByIpIface", impl_manager_get_device_by_ip_iface, + "ActivateConnection", impl_manager_activate_connection, + "AddAndActivateConnection", impl_manager_add_and_activate_connection, + "DeactivateConnection", impl_manager_deactivate_connection, + "Sleep", impl_manager_sleep, + "Enable", impl_manager_enable, + "GetPermissions", impl_manager_get_permissions, + "SetLogging", impl_manager_set_logging, + "GetLogging", impl_manager_get_logging, + "CheckConnectivity", impl_manager_check_connectivity, + "state", impl_manager_get_state, + "CheckpointCreate", impl_manager_checkpoint_create, + "CheckpointDestroy", impl_manager_checkpoint_destroy, + "CheckpointRollback", impl_manager_checkpoint_rollback, + NULL); } |