summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2018-04-13 09:24:59 +0200
committerThomas Haller <thaller@redhat.com>2018-04-13 09:24:59 +0200
commitf69dbd71fe1f714250cc865b4c2e50fcc95579d2 (patch)
treec773636a70ab4c3406683d3e1f59ebe69612c434
parent786adf969c297fc2e830b43cc9e9b1a154d43216 (diff)
parent04a42e2748478a6f6c204f94c7c83fa2c9b8dbd9 (diff)
downloadNetworkManager-f69dbd71fe1f714250cc865b4c2e50fcc95579d2.tar.gz
core: merge branch 'th/settings-cleanup'
https://github.com/NetworkManager/NetworkManager/pull/85
-rw-r--r--config.h.meson3
-rw-r--r--configure.ac26
-rw-r--r--libnm-core/nm-simple-connection.c7
-rw-r--r--meson.build1
-rw-r--r--src/devices/nm-device.c161
-rw-r--r--src/nm-active-connection.c270
-rw-r--r--src/nm-auth-manager.c616
-rw-r--r--src/nm-auth-manager.h62
-rw-r--r--src/nm-auth-utils.c168
-rw-r--r--src/nm-auth-utils.h11
-rw-r--r--src/nm-core-utils.c22
-rw-r--r--src/nm-core-utils.h7
-rw-r--r--src/nm-dbus-object.c73
-rw-r--r--src/nm-dbus-object.h15
-rw-r--r--src/nm-dbus-utils.c153
-rw-r--r--src/nm-dbus-utils.h39
-rw-r--r--src/nm-dispatcher.c2
-rw-r--r--src/nm-manager.c24
-rw-r--r--src/nm-policy.c3
-rw-r--r--src/nm-types.h1
-rw-r--r--src/settings/nm-agent-manager.c12
-rw-r--r--src/settings/nm-settings-connection.c153
-rw-r--r--src/settings/nm-settings-connection.h1
-rw-r--r--src/settings/nm-settings.c344
-rw-r--r--src/settings/nm-settings.h8
-rw-r--r--src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c14
-rw-r--r--src/tests/config/nm-test-device.c2
-rw-r--r--src/tests/test-general.c18
28 files changed, 1247 insertions, 969 deletions
diff --git a/config.h.meson b/config.h.meson
index 12b35a66b9..06190aae11 100644
--- a/config.h.meson
+++ b/config.h.meson
@@ -214,9 +214,6 @@
/* Define if you have oFono support (experimental) */
#mesondefine WITH_OFONO
-/* whether to compile polkit support */
-#mesondefine WITH_POLKIT
-
/* Define if you have polkit agent */
#mesondefine WITH_POLKIT_AGENT
diff --git a/configure.ac b/configure.ac
index a0600e1ca7..c703890e1c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -629,26 +629,20 @@ AM_CONDITIONAL(WITH_JSON_VALIDATION, test "${enable_json_validation}" != "no")
# we usually compile with polkit support. --enable-polkit=yes|no only sets the
# default configuration for main.auth-polkit. User can always enable/disable polkit
-# autorization via config. Only when specifying --enable-polkit=disabled, we do
-# not compile support. In this case, the user cannot enable polkit authorization via
-# configuration.
+# autorization via config.
AC_ARG_ENABLE(polkit,
- AS_HELP_STRING([--enable-polkit=yes|no|disabled],
- [set default value for auth-polkit configuration option. This value can be overwritten by NM configuration. 'disabled' compiles NM without any support]),
+ AS_HELP_STRING([--enable-polkit=yes|no],
+ [set default value for auth-polkit configuration option. This value can be overwritten by NM configuration. 'disabled' is an alias for 'no']),
[enable_polkit=${enableval}], [enable_polkit=yes])
if (test "${enable_polkit}" != "no" -a "${enable_polkit}" != "disabled"); then
- enable_polkit=yes
+ enable_polkit=true
AC_DEFINE(NM_CONFIG_DEFAULT_MAIN_AUTH_POLKIT, "true", [The default value of the auth-polkit configuration option])
AC_SUBST(NM_CONFIG_DEFAULT_MAIN_AUTH_POLKIT_TEXT, true)
else
+ enable_polkit=false
AC_DEFINE(NM_CONFIG_DEFAULT_MAIN_AUTH_POLKIT, "false", [The default value of the auth-polkit configuration option])
AC_SUBST(NM_CONFIG_DEFAULT_MAIN_AUTH_POLKIT_TEXT, false)
fi
-if (test "${enable_polkit}" != "disabled"); then
- AC_DEFINE(WITH_POLKIT, 1, [whether to compile polkit support])
-else
- AC_DEFINE(WITH_POLKIT, 0, [whether to compile polkit support])
-fi
PKG_CHECK_MODULES(POLKIT, [polkit-agent-1 >= 0.97], [have_pk_agent=yes],[have_pk_agent=no])
AC_ARG_ENABLE(polkit-agent,
@@ -1341,14 +1335,10 @@ echo
echo "Platform:"
echo " session tracking: $session_tracking"
echo " suspend/resume: $with_suspend_resume"
-if test "${enable_polkit}" = "yes"; then
- if test "${enable_modify_system}" = "yes"; then
- echo " policykit: yes (permissive modify.system) (default: main.auth-polkit=${enable_polkit})"
- else
- echo " policykit: yes (restrictive modify.system) (default: main.auth-polkit=${enable_polkit})"
- fi
+if test "${enable_modify_system}" = "yes"; then
+ echo " policykit: main.auth-polkit=${enable_polkit} (permissive modify.system)"
else
- echo " policykit: no"
+ echo " policykit: main.auth-polkit=${enable_polkit} (restrictive modify.system)"
fi
echo " polkit agent: ${enable_polkit_agent}"
echo " selinux: $have_selinux"
diff --git a/libnm-core/nm-simple-connection.c b/libnm-core/nm-simple-connection.c
index 11700666f5..f06e1aed4b 100644
--- a/libnm-core/nm-simple-connection.c
+++ b/libnm-core/nm-simple-connection.c
@@ -113,11 +113,16 @@ NMConnection *
nm_simple_connection_new_clone (NMConnection *connection)
{
NMConnection *clone;
+ const char *path;
g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
clone = nm_simple_connection_new ();
- nm_connection_set_path (clone, nm_connection_get_path (connection));
+
+ path = nm_connection_get_path (connection);
+ if (path)
+ nm_connection_set_path (clone, path);
+
nm_connection_replace_settings_from_connection (clone, connection);
return clone;
diff --git a/meson.build b/meson.build
index 5f29c16a69..17ddbc4a57 100644
--- a/meson.build
+++ b/meson.build
@@ -448,7 +448,6 @@ endif
config_default_main_auth_polkit = (polkit == 'yes').to_string()
config_h.set_quoted('NM_CONFIG_DEFAULT_MAIN_AUTH_POLKIT', config_default_main_auth_polkit)
-config_h.set10('WITH_POLKIT', enable_polkit)
enable_modify_system = get_option('modify_system')
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index c0540534e0..882e9a86d1 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -256,7 +256,7 @@ typedef struct _NMDevicePrivate {
GSList *pending_actions;
GSList *dad6_failed_addrs;
- NMDevice *parent_device;
+ NMDBusTrackObjPath parent_device;
char * udi;
char * iface; /* may change, could be renamed by user */
@@ -321,9 +321,7 @@ typedef struct _NMDevicePrivate {
NMActRequest * queued_act_request;
bool queued_act_request_is_waiting_for_carrier:1;
- bool act_request_public:1;
- NMActRequest *act_request;
- gulong act_request_id;
+ NMDBusTrackObjPath act_request;
ActivationHandleData act_handle4; /* for layer2 and IPv4. */
ActivationHandleData act_handle6;
guint recheck_assume_id;
@@ -1514,12 +1512,9 @@ nm_device_parent_get_ifindex (NMDevice *self)
NMDevice *
nm_device_parent_get_device (NMDevice *self)
{
- NMDevicePrivate *priv;
-
g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
- priv = NM_DEVICE_GET_PRIVATE (self);
- return priv->parent_device;
+ return NM_DEVICE_GET_PRIVATE (self)->parent_device.obj;
}
static void
@@ -1541,7 +1536,7 @@ _parent_set_ifindex (NMDevice *self,
NMDevice *parent_device;
gboolean changed = FALSE;
int old_ifindex;
- NMDevice *old_device;
+ gs_unref_object NMDevice *old_device = NULL;
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
@@ -1551,16 +1546,15 @@ _parent_set_ifindex (NMDevice *self,
parent_ifindex = 0;
old_ifindex = priv->parent_ifindex;
- old_device = priv->parent_device;
if (priv->parent_ifindex == parent_ifindex) {
if (parent_ifindex > 0) {
if ( !force_check
- && priv->parent_device
- && nm_device_get_ifindex (priv->parent_device) == parent_ifindex)
+ && priv->parent_device.obj
+ && nm_device_get_ifindex (priv->parent_device.obj) == parent_ifindex)
return FALSE;
} else {
- if (!priv->parent_device)
+ if (!priv->parent_device.obj)
return FALSE;
}
} else {
@@ -1575,24 +1569,23 @@ _parent_set_ifindex (NMDevice *self,
} else
parent_device = NULL;
- if (parent_device != priv->parent_device) {
- priv->parent_device = parent_device;
+ if (parent_device != priv->parent_device.obj) {
+ old_device = nm_g_object_ref (priv->parent_device.obj);
+ nm_dbus_track_obj_path_set (&priv->parent_device, parent_device, TRUE);
changed = TRUE;
}
if (changed) {
if (priv->parent_ifindex <= 0)
_LOGD (LOGD_DEVICE, "parent: clear");
- else if (!priv->parent_device)
+ else if (!priv->parent_device.obj)
_LOGD (LOGD_DEVICE, "parent: ifindex %d, no device", priv->parent_ifindex);
else {
_LOGD (LOGD_DEVICE, "parent: ifindex %d, device %p, %s", priv->parent_ifindex,
- priv->parent_device, nm_device_get_iface (priv->parent_device));
+ priv->parent_device.obj, nm_device_get_iface (priv->parent_device.obj));
}
- NM_DEVICE_GET_CLASS (self)->parent_changed_notify (self, old_ifindex, old_device, priv->parent_ifindex, priv->parent_device);
-
- _notify (self, PROP_PARENT);
+ NM_DEVICE_GET_CLASS (self)->parent_changed_notify (self, old_ifindex, old_device, priv->parent_ifindex, priv->parent_device.obj);
}
return changed;
}
@@ -1617,7 +1610,7 @@ nm_device_parent_notify_changed (NMDevice *self,
priv = NM_DEVICE_GET_PRIVATE (self);
if (priv->parent_ifindex > 0) {
- if ( priv->parent_device == change_candidate
+ if ( priv->parent_device.obj == change_candidate
|| priv->parent_ifindex == nm_device_get_ifindex (change_candidate))
return _parent_set_ifindex (self, priv->parent_ifindex, device_removed);
}
@@ -2164,7 +2157,7 @@ nm_device_get_act_request (NMDevice *self)
{
g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
- return NM_DEVICE_GET_PRIVATE (self)->act_request;
+ return NM_DEVICE_GET_PRIVATE (self)->act_request.obj;
}
NMSettingsConnection *
@@ -2172,7 +2165,7 @@ nm_device_get_settings_connection (NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
- return priv->act_request ? nm_act_request_get_settings_connection (priv->act_request) : NULL;
+ return priv->act_request.obj ? nm_act_request_get_settings_connection (priv->act_request.obj) : NULL;
}
NMConnection *
@@ -2184,7 +2177,7 @@ nm_device_get_applied_connection (NMDevice *self)
priv = NM_DEVICE_GET_PRIVATE (self);
- return priv->act_request ? nm_act_request_get_applied_connection (priv->act_request) : NULL;
+ return priv->act_request.obj ? nm_act_request_get_applied_connection (priv->act_request.obj) : NULL;
}
gboolean
@@ -2192,10 +2185,10 @@ nm_device_has_unmodified_applied_connection (NMDevice *self, NMSettingCompareFla
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
- if (!priv->act_request)
+ if (!priv->act_request.obj)
return FALSE;
- return nm_active_connection_has_unmodified_applied_connection ((NMActiveConnection *) priv->act_request, compare_flags);
+ return nm_active_connection_has_unmodified_applied_connection ((NMActiveConnection *) priv->act_request.obj, compare_flags);
}
NMSetting *
@@ -4533,7 +4526,7 @@ check_ip_state (NMDevice *self, gboolean may_fail, gboolean full_state_update)
/* Don't progress into IP_CHECK or SECONDARIES if we're waiting for the
* master to enslave us. */
- if ( nm_active_connection_get_master (NM_ACTIVE_CONNECTION (priv->act_request))
+ if ( nm_active_connection_get_master (NM_ACTIVE_CONNECTION (priv->act_request.obj))
&& !priv->is_enslaved)
return;
@@ -5726,8 +5719,9 @@ activate_stage1_device_prepare (NMDevice *self)
_set_ip_state (self, AF_INET6, IP_NONE);
/* Notify the new ActiveConnection along with the state change */
- priv->act_request_public = TRUE;
- _notify (self, PROP_ACTIVE_CONNECTION);
+ nm_dbus_track_obj_path_set (&priv->act_request,
+ priv->act_request.obj,
+ TRUE);
nm_device_state_changed (self, NM_DEVICE_STATE_PREPARE, NM_DEVICE_STATE_REASON_NONE);
@@ -5763,7 +5757,7 @@ nm_device_activate_schedule_stage1_device_prepare (NMDevice *self)
g_return_if_fail (NM_IS_DEVICE (self));
priv = NM_DEVICE_GET_PRIVATE (self);
- g_return_if_fail (priv->act_request);
+ g_return_if_fail (priv->act_request.obj);
activation_source_schedule (self, activate_stage1_device_prepare, AF_INET);
}
@@ -5940,7 +5934,7 @@ activate_stage2_device_config (NMDevice *self)
if (slave_state == NM_DEVICE_STATE_IP_CONFIG)
nm_device_master_enslave_slave (self, info->slave, nm_device_get_applied_connection (info->slave));
- else if ( priv->act_request
+ else if ( priv->act_request.obj
&& nm_device_sys_iface_state_is_external (self)
&& slave_state <= NM_DEVICE_STATE_DISCONNECTED)
nm_device_queue_recheck_assume (info->slave);
@@ -5965,10 +5959,10 @@ nm_device_activate_schedule_stage2_device_config (NMDevice *self)
g_return_if_fail (NM_IS_DEVICE (self));
priv = NM_DEVICE_GET_PRIVATE (self);
- g_return_if_fail (priv->act_request);
+ g_return_if_fail (priv->act_request.obj);
if (!priv->master_ready_handled) {
- NMActiveConnection *active = NM_ACTIVE_CONNECTION (priv->act_request);
+ NMActiveConnection *active = NM_ACTIVE_CONNECTION (priv->act_request.obj);
NMActiveConnection *master;
master = nm_active_connection_get_master (active);
@@ -6256,10 +6250,10 @@ nm_device_handle_ipv4ll_event (sd_ipv4ll *ll, int event, void *data)
NMIP4Config *config;
int r;
- if (priv->act_request == NULL)
+ if (priv->act_request.obj == NULL)
return;
- connection = nm_act_request_get_applied_connection (priv->act_request);
+ connection = nm_act_request_get_applied_connection (priv->act_request.obj);
g_assert (connection);
/* Ignore if the connection isn't an AutoIP connection */
@@ -8179,7 +8173,7 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
guint i;
- g_return_if_fail (priv->act_request);
+ g_return_if_fail (priv->act_request.obj);
if (!applied_config_get_current (&priv->ac_ip6_config))
applied_config_init_new (&priv->ac_ip6_config, self, AF_INET6);
@@ -8991,7 +8985,7 @@ nm_device_activate_schedule_stage3_ip_config_start (NMDevice *self)
g_return_if_fail (NM_IS_DEVICE (self));
priv = NM_DEVICE_GET_PRIVATE (self);
- g_return_if_fail (priv->act_request);
+ g_return_if_fail (priv->act_request.obj);
/* Add the interface to the specified firewall zone */
if (priv->fw_state == FIREWALL_STATE_UNMANAGED) {
@@ -9063,7 +9057,7 @@ nm_device_activate_schedule_ip4_config_timeout (NMDevice *self)
g_return_if_fail (NM_IS_DEVICE (self));
priv = NM_DEVICE_GET_PRIVATE (self);
- g_return_if_fail (priv->act_request);
+ g_return_if_fail (priv->act_request.obj);
activation_source_schedule (self, activate_stage4_ip4_config_timeout, AF_INET);
}
@@ -9119,7 +9113,7 @@ nm_device_activate_schedule_ip6_config_timeout (NMDevice *self)
g_return_if_fail (NM_IS_DEVICE (self));
priv = NM_DEVICE_GET_PRIVATE (self);
- g_return_if_fail (priv->act_request);
+ g_return_if_fail (priv->act_request.obj);
activation_source_schedule (self, activate_stage4_ip6_config_timeout, AF_INET6);
}
@@ -9577,43 +9571,26 @@ nm_device_activate_ip6_state_done (NMDevice *self)
/*****************************************************************************/
static void
-act_request_set_cb (NMActRequest *act_request,
- GParamSpec *pspec,
- NMDevice *self)
-{
- _notify (self, PROP_ACTIVE_CONNECTION);
-}
-
-static void
act_request_set (NMDevice *self, NMActRequest *act_request)
{
NMDevicePrivate *priv;
- gs_unref_object NMActRequest *old_act_requst = NULL;
nm_assert (NM_IS_DEVICE (self));
nm_assert (!act_request || NM_IS_ACT_REQUEST (act_request));
priv = NM_DEVICE_GET_PRIVATE (self);
- if ( !priv->act_request_public
- && priv->act_request == act_request)
+ if ( !priv->act_request.visible
+ && priv->act_request.obj == act_request)
return;
/* always clear the public flag. The few callers that set a new @act_request
* don't want that the property is public yet. */
- priv->act_request_public = FALSE;
-
- nm_clear_g_signal_handler (priv->act_request, &priv->act_request_id);
-
- old_act_requst = priv->act_request;
- priv->act_request = nm_g_object_ref (act_request);
+ nm_dbus_track_obj_path_set (&priv->act_request,
+ act_request,
+ FALSE);
if (act_request) {
- priv->act_request_id = g_signal_connect (act_request,
- "notify::"NM_DBUS_OBJECT_PATH,
- G_CALLBACK (act_request_set_cb),
- self);
-
switch (nm_active_connection_get_activation_type (NM_ACTIVE_CONNECTION (act_request))) {
case NM_ACTIVATION_TYPE_EXTERNAL:
break;
@@ -9630,8 +9607,6 @@ act_request_set (NMDevice *self, NMActRequest *act_request)
break;
}
}
-
- _notify (self, PROP_ACTIVE_CONNECTION);
}
static void
@@ -10096,7 +10071,7 @@ check_and_reapply_connection (NMDevice *self,
}
if ( version_id != 0
- && version_id != nm_active_connection_version_id_get ((NMActiveConnection *) priv->act_request)) {
+ && version_id != nm_active_connection_version_id_get ((NMActiveConnection *) priv->act_request.obj)) {
g_set_error_literal (error,
NM_DEVICE_ERROR,
NM_DEVICE_ERROR_VERSION_ID_MISMATCH,
@@ -10109,10 +10084,10 @@ check_and_reapply_connection (NMDevice *self,
*************************************************************************/
if (diffs)
- nm_active_connection_version_id_bump ((NMActiveConnection *) priv->act_request);
+ nm_active_connection_version_id_bump ((NMActiveConnection *) priv->act_request.obj);
_LOGD (LOGD_DEVICE, "reapply (version-id %llu%s)",
- (unsigned long long) nm_active_connection_version_id_get (((NMActiveConnection *) priv->act_request)),
+ (unsigned long long) nm_active_connection_version_id_get (((NMActiveConnection *) priv->act_request.obj)),
diffs ? "" : " (unmodified)");
if (diffs) {
@@ -10362,7 +10337,7 @@ get_applied_connection_cb (NMDevice *self,
g_dbus_method_invocation_return_value (context,
g_variant_new ("(@a{sa{sv}}t)",
settings,
- nm_active_connection_version_id_get ((NMActiveConnection *) priv->act_request)));
+ nm_active_connection_version_id_get ((NMActiveConnection *) priv->act_request.obj)));
}
static void
@@ -10560,7 +10535,7 @@ impl_device_disconnect (NMDBusObject *obj,
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
NMConnection *connection;
- if (!priv->act_request) {
+ if (!priv->act_request.obj) {
g_dbus_method_invocation_return_error_literal (invocation,
NM_DEVICE_ERROR,
NM_DEVICE_ERROR_NOT_ACTIVE,
@@ -10748,8 +10723,8 @@ nm_device_steal_connection (NMDevice *self, NMSettingsConnection *connection)
&& connection == nm_active_connection_get_settings_connection (NM_ACTIVE_CONNECTION (priv->queued_act_request)))
_clear_queued_act_request (priv);
- if ( priv->act_request
- && connection == nm_active_connection_get_settings_connection (NM_ACTIVE_CONNECTION (priv->act_request))
+ if ( priv->act_request.obj
+ && connection == nm_active_connection_get_settings_connection (NM_ACTIVE_CONNECTION (priv->act_request.obj))
&& priv->state < NM_DEVICE_STATE_DEACTIVATING) {
nm_device_state_changed (self,
NM_DEVICE_STATE_DEACTIVATING,
@@ -10765,7 +10740,7 @@ nm_device_queue_activation (NMDevice *self, NMActRequest *req)
must_queue = _carrier_wait_check_act_request_must_queue (self, req);
- if ( !priv->act_request
+ if ( !priv->act_request.obj
&& !must_queue
&& nm_device_is_real (self)) {
_device_activate (self, req);
@@ -10780,7 +10755,7 @@ nm_device_queue_activation (NMDevice *self, NMActRequest *req)
_LOGD (LOGD_DEVICE, "queue activation request waiting for %s", must_queue ? "carrier" : "currently active connection to disconnect");
/* Deactivate existing activation request first */
- if (priv->act_request) {
+ if (priv->act_request.obj) {
_LOGI (LOGD_DEVICE, "disconnecting for new activation request.");
nm_device_state_changed (self,
NM_DEVICE_STATE_DEACTIVATING,
@@ -10995,7 +10970,7 @@ nm_device_set_ip_config (NMDevice *self,
&& (settings_connection = nm_device_get_settings_connection (self))
&& NM_FLAGS_HAS (nm_settings_connection_get_flags (settings_connection),
NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED)
- && nm_active_connection_get_activation_type (NM_ACTIVE_CONNECTION (priv->act_request)) == NM_ACTIVATION_TYPE_EXTERNAL) {
+ && nm_active_connection_get_activation_type (NM_ACTIVE_CONNECTION (priv->act_request.obj)) == NM_ACTIVATION_TYPE_EXTERNAL) {
g_object_freeze_notify (G_OBJECT (settings_connection));
nm_connection_add_setting (NM_CONNECTION (settings_connection),
IS_IPv4
@@ -12470,7 +12445,7 @@ nm_device_reapply_settings_immediately (NMDevice *self)
if (g_strcmp0 ((zone = nm_setting_connection_get_zone (s_con_settings)),
nm_setting_connection_get_zone (s_con_applied)) != 0) {
- version_id = nm_active_connection_version_id_bump ((NMActiveConnection *) self->_priv->act_request);
+ version_id = nm_active_connection_version_id_bump ((NMActiveConnection *) self->_priv->act_request.obj);
_LOGD (LOGD_DEVICE, "reapply setting: zone = %s%s%s (version-id %llu)", NM_PRINT_FMT_QUOTE_STRING (zone), (unsigned long long) version_id);
g_object_set (G_OBJECT (s_con_applied),
@@ -12482,7 +12457,7 @@ nm_device_reapply_settings_immediately (NMDevice *self)
if ((metered = nm_setting_connection_get_metered (s_con_settings)) != nm_setting_connection_get_metered (s_con_applied)) {
- version_id = nm_active_connection_version_id_bump ((NMActiveConnection *) self->_priv->act_request);
+ version_id = nm_active_connection_version_id_bump ((NMActiveConnection *) self->_priv->act_request.obj);
_LOGD (LOGD_DEVICE, "reapply setting: metered = %d (version-id %llu)", (int) metered, (unsigned long long) version_id);
g_object_set (G_OBJECT (s_con_applied),
@@ -12841,19 +12816,19 @@ cp_connection_added_or_updated (NMDevice *self, NMConnection *connection)
}
static void
-cp_connection_added (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data)
+cp_connection_added (NMSettings *settings, NMConnection *connection, gpointer user_data)
{
cp_connection_added_or_updated (user_data, connection);
}
static void
-cp_connection_updated (NMConnectionProvider *cp, NMConnection *connection, gboolean by_user, gpointer user_data)
+cp_connection_updated (NMSettings *settings, NMConnection *connection, gboolean by_user, gpointer user_data)
{
cp_connection_added_or_updated (user_data, connection);
}
static void
-cp_connection_removed (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data)
+cp_connection_removed (NMSettings *settings, NMConnection *connection, gpointer user_data)
{
NMDevice *self = user_data;
@@ -13088,11 +13063,11 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type)
* above disables them. */
nm_assert (priv->needs_ip6_subnet == FALSE);
- if (priv->act_request) {
- nm_active_connection_set_default (NM_ACTIVE_CONNECTION (priv->act_request), AF_INET, FALSE);
+ if (priv->act_request.obj) {
+ nm_active_connection_set_default (NM_ACTIVE_CONNECTION (priv->act_request.obj), AF_INET, FALSE);
priv->master_ready_handled = FALSE;
- nm_clear_g_signal_handler (priv->act_request, &priv->master_ready_id);
+ nm_clear_g_signal_handler (priv->act_request.obj, &priv->master_ready_id);
act_request_set (self, NULL);
}
@@ -13544,7 +13519,7 @@ _set_state_full (NMDevice *self,
g_cancellable_cancel (priv->deactivating_cancellable);
/* Cache the activation request for the dispatcher */
- req = nm_g_object_ref (priv->act_request);
+ req = nm_g_object_ref (priv->act_request.obj);
if ( state > NM_DEVICE_STATE_UNMANAGED
&& state <= NM_DEVICE_STATE_ACTIVATED
@@ -14792,6 +14767,9 @@ nm_device_init (NMDevice *self)
priv->connectivity_state = NM_CONNECTIVITY_UNKNOWN;
+ nm_dbus_track_obj_path_init (&priv->parent_device, G_OBJECT (self), obj_properties[PROP_PARENT]);
+ nm_dbus_track_obj_path_init (&priv->act_request, G_OBJECT (self), obj_properties[PROP_ACTIVE_CONNECTION]);
+
priv->netns = g_object_ref (NM_NETNS_GET);
priv->autoconnect_blocked_flags = DEFAULT_AUTOCONNECT
@@ -15030,6 +15008,9 @@ finalize (GObject *object)
g_hash_table_unref (priv->ip6_saved_properties);
g_hash_table_unref (priv->available_connections);
+ nm_dbus_track_obj_path_deinit (&priv->parent_device);
+ nm_dbus_track_obj_path_deinit (&priv->act_request);
+
G_OBJECT_CLASS (nm_device_parent_class)->finalize (object);
/* for testing, NMDeviceTest does not invoke NMDevice::constructed,
@@ -15146,9 +15127,6 @@ get_property (GObject *object, guint prop_id,
{
NMDevice *self = NM_DEVICE (object);
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
- GPtrArray *array;
- GHashTableIter iter;
- NMConnection *connection;
GVariantBuilder array_builder;
switch (prop_id) {
@@ -15223,7 +15201,7 @@ get_property (GObject *object, guint prop_id,
g_variant_new ("(uu)", priv->state, priv->state_reason));
break;
case PROP_ACTIVE_CONNECTION:
- nm_dbus_utils_g_value_set_object_path (value, priv->act_request_public ? priv->act_request : NULL);
+ g_value_set_string (value, nm_dbus_track_obj_path_get (&priv->act_request));
break;
case PROP_DEVICE_TYPE:
g_value_set_uint (value, priv->type);
@@ -15254,12 +15232,9 @@ get_property (GObject *object, guint prop_id,
g_value_set_uint (value, priv->rfkill_type);
break;
case PROP_AVAILABLE_CONNECTIONS:
- array = g_ptr_array_sized_new (g_hash_table_size (priv->available_connections));
- g_hash_table_iter_init (&iter, priv->available_connections);
- while (g_hash_table_iter_next (&iter, (gpointer) &connection, NULL))
- g_ptr_array_add (array, g_strdup (nm_connection_get_path (connection)));
- g_ptr_array_add (array, NULL);
- g_value_take_boxed (value, (char **) g_ptr_array_free (array, FALSE));
+ nm_dbus_utils_g_value_set_object_path_from_hash (value,
+ priv->available_connections,
+ TRUE);
break;
case PROP_PHYSICAL_PORT_ID:
g_value_set_string (value, priv->physical_port_id);
@@ -15268,7 +15243,7 @@ get_property (GObject *object, guint prop_id,
g_value_set_object (value, nm_device_get_master (self));
break;
case PROP_PARENT:
- nm_dbus_utils_g_value_set_object_path (value, priv->parent_device);
+ g_value_set_string (value, nm_dbus_track_obj_path_get (&priv->parent_device));
break;
case PROP_HW_ADDRESS:
g_value_set_string (value, priv->hw_addr);
diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c
index 88074e2302..4f6033893b 100644
--- a/src/nm-active-connection.c
+++ b/src/nm-active-connection.c
@@ -28,12 +28,15 @@
#include "settings/nm-settings-connection.h"
#include "nm-simple-connection.h"
#include "nm-auth-utils.h"
+#include "nm-auth-manager.h"
#include "nm-auth-subject.h"
#include "NetworkManagerUtils.h"
#include "nm-core-internal.h"
+#define AUTH_CALL_ID_SHARED_WIFI_PERMISSION_FAILED ((NMAuthManagerCallId *) GINT_TO_POINTER (1))
+
typedef struct _NMActiveConnectionPrivate {
- NMSettingsConnection *settings_connection;
+ NMDBusTrackObjPath settings_connection;
NMConnection *applied_connection;
char *specific_object;
NMDevice *device;
@@ -59,11 +62,15 @@ typedef struct _NMActiveConnectionPrivate {
NMActiveConnection *parent;
- NMAuthChain *chain;
- const char *wifi_shared_permission;
- NMActiveConnectionAuthResultFunc result_func;
- gpointer user_data1;
- gpointer user_data2;
+ struct {
+ NMAuthManagerCallId *call_id_network_control;
+ NMAuthManagerCallId *call_id_wifi_shared_permission;
+
+ NMActiveConnectionAuthResultFunc result_func;
+ gpointer user_data1;
+ gpointer user_data2;
+ } auth;
+
} NMActiveConnectionPrivate;
NM_GOBJECT_PROPERTIES_DEFINE (NMActiveConnection,
@@ -184,40 +191,24 @@ _settings_connection_updated (NMSettingsConnection *connection,
}
static void
-_settings_connection_removed (NMSettingsConnection *connection,
- gpointer user_data)
-{
- NMActiveConnection *self = user_data;
-
- /* Our settings connection is about to drop off. The next active connection
- * cleanup is going to tear us down (at least until we grow the capability to
- * re-link; in that case we'd just clean the references to the old connection here).
- * Let's remove ourselves from the bus so that we're not exposed with a dangling
- * reference to the setting connection once it's gone. */
- if (nm_dbus_object_is_exported (NM_DBUS_OBJECT (self)))
- nm_dbus_object_unexport (NM_DBUS_OBJECT (self));
-}
-
-static void
_set_settings_connection (NMActiveConnection *self, NMSettingsConnection *connection)
{
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
- if (priv->settings_connection == connection)
+ if (priv->settings_connection.obj == connection)
return;
- if (priv->settings_connection) {
- g_signal_handlers_disconnect_by_func (priv->settings_connection, _settings_connection_updated, self);
- g_signal_handlers_disconnect_by_func (priv->settings_connection, _settings_connection_removed, self);
- g_signal_handlers_disconnect_by_func (priv->settings_connection, _settings_connection_notify_flags, self);
- g_clear_object (&priv->settings_connection);
+
+ if (priv->settings_connection.obj) {
+ g_signal_handlers_disconnect_by_func (priv->settings_connection.obj, _settings_connection_updated, self);
+ g_signal_handlers_disconnect_by_func (priv->settings_connection.obj, _settings_connection_notify_flags, self);
}
if (connection) {
- priv->settings_connection = g_object_ref (connection);
g_signal_connect (connection, NM_SETTINGS_CONNECTION_UPDATED_INTERNAL, (GCallback) _settings_connection_updated, self);
- g_signal_connect (connection, NM_SETTINGS_CONNECTION_REMOVED, (GCallback) _settings_connection_removed, self);
if (nm_active_connection_get_activation_type (self) == NM_ACTIVATION_TYPE_EXTERNAL)
g_signal_connect (connection, "notify::"NM_SETTINGS_CONNECTION_FLAGS, (GCallback) _settings_connection_notify_flags, self);
}
+
+ nm_dbus_track_obj_path_set (&priv->settings_connection, connection, TRUE);
}
NMActiveConnectionState
@@ -275,7 +266,7 @@ nm_active_connection_set_state (NMActiveConnection *self,
if ( new_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED
|| old_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
- nm_settings_connection_update_timestamp (priv->settings_connection,
+ nm_settings_connection_update_timestamp (priv->settings_connection.obj,
(guint64) time (NULL), TRUE);
}
@@ -371,7 +362,7 @@ nm_active_connection_get_settings_connection_id (NMActiveConnection *self)
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), NULL);
- con = NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->settings_connection;
+ con = NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->settings_connection.obj;
return con
? nm_connection_get_id (NM_CONNECTION (con))
: NULL;
@@ -382,7 +373,7 @@ _nm_active_connection_get_settings_connection (NMActiveConnection *self)
{
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), NULL);
- return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->settings_connection;
+ return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->settings_connection.obj;
}
NMSettingsConnection *
@@ -456,7 +447,7 @@ nm_active_connection_set_settings_connection (NMActiveConnection *self,
priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
g_return_if_fail (NM_IS_SETTINGS_CONNECTION (connection));
- g_return_if_fail (!priv->settings_connection);
+ g_return_if_fail (!priv->settings_connection.obj);
g_return_if_fail (!priv->applied_connection);
/* Can't change connection after the ActiveConnection is exported over D-Bus.
@@ -471,7 +462,7 @@ nm_active_connection_set_settings_connection (NMActiveConnection *self,
_set_settings_connection (self, connection);
_set_applied_connection_take (self,
- nm_simple_connection_new_clone (NM_CONNECTION (priv->settings_connection)));
+ nm_simple_connection_new_clone (NM_CONNECTION (priv->settings_connection.obj)));
}
gboolean
@@ -483,9 +474,9 @@ nm_active_connection_has_unmodified_applied_connection (NMActiveConnection *self
priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
- g_return_val_if_fail (priv->settings_connection, FALSE);
+ g_return_val_if_fail (priv->settings_connection.obj, FALSE);
- return nm_settings_connection_has_unmodified_applied_connection (priv->settings_connection,
+ return nm_settings_connection_has_unmodified_applied_connection (priv->settings_connection.obj,
priv->applied_connection,
compare_flags);
}
@@ -501,10 +492,10 @@ nm_active_connection_clear_secrets (NMActiveConnection *self)
priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
- if (nm_settings_connection_has_unmodified_applied_connection (priv->settings_connection,
+ if (nm_settings_connection_has_unmodified_applied_connection (priv->settings_connection.obj,
priv->applied_connection,
NM_SETTING_COMPARE_FLAG_NONE))
- nm_connection_clear_secrets ((NMConnection *) priv->settings_connection);
+ nm_connection_clear_secrets ((NMConnection *) priv->settings_connection.obj);
nm_connection_clear_secrets (priv->applied_connection);
}
@@ -864,11 +855,11 @@ _set_activation_type (NMActiveConnection *self,
priv->activation_type = activation_type;
- if (priv->settings_connection) {
+ if (priv->settings_connection.obj) {
if (activation_type == NM_ACTIVATION_TYPE_EXTERNAL)
- g_signal_connect (priv->settings_connection, "notify::"NM_SETTINGS_CONNECTION_FLAGS, (GCallback) _settings_connection_notify_flags, self);
+ g_signal_connect (priv->settings_connection.obj, "notify::"NM_SETTINGS_CONNECTION_FLAGS, (GCallback) _settings_connection_notify_flags, self);
else
- g_signal_handlers_disconnect_by_func (priv->settings_connection, _settings_connection_notify_flags, self);
+ g_signal_handlers_disconnect_by_func (priv->settings_connection.obj, _settings_connection_notify_flags, self);
}
}
@@ -914,7 +905,7 @@ _settings_connection_notify_flags (NMSettingsConnection *settings_connection,
nm_assert (NM_IS_ACTIVE_CONNECTION (self));
nm_assert (NM_IS_SETTINGS_CONNECTION (settings_connection));
nm_assert (nm_active_connection_get_activation_type (self) == NM_ACTIVATION_TYPE_EXTERNAL);
- nm_assert (NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->settings_connection == settings_connection);
+ nm_assert (NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->settings_connection.obj == settings_connection);
if (NM_FLAGS_HAS (nm_settings_connection_get_flags (settings_connection),
NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED))
@@ -997,62 +988,93 @@ nm_active_connection_set_parent (NMActiveConnection *self, NMActiveConnection *p
/*****************************************************************************/
static void
-auth_done (NMAuthChain *chain,
+auth_cancel (NMActiveConnection *self)
+{
+ NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
+
+ if (priv->auth.call_id_network_control)
+ nm_auth_manager_check_authorization_cancel (priv->auth.call_id_network_control);
+ if (priv->auth.call_id_wifi_shared_permission) {
+ if (priv->auth.call_id_wifi_shared_permission == AUTH_CALL_ID_SHARED_WIFI_PERMISSION_FAILED)
+ priv->auth.call_id_wifi_shared_permission = NULL;
+ else
+ nm_auth_manager_check_authorization_cancel (priv->auth.call_id_wifi_shared_permission);
+ }
+ priv->auth.result_func = NULL;
+ priv->auth.user_data1 = NULL;
+ priv->auth.user_data2 = NULL;
+}
+
+static void
+auth_complete (NMActiveConnection *self, gboolean result, const char *message)
+{
+ _nm_unused gs_unref_object NMActiveConnection *self_keep_alive = g_object_ref (self);
+ NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
+
+ priv->auth.result_func (self,
+ result,
+ message,
+ priv->auth.user_data1,
+ priv->auth.user_data2);
+ auth_cancel (self);
+}
+
+static void
+auth_done (NMAuthManager *auth_mgr,
+ NMAuthManagerCallId *auth_call_id,
+ gboolean is_authorized,
+ gboolean is_challenge,
GError *error,
- GDBusMethodInvocation *unused,
gpointer user_data)
+
{
NMActiveConnection *self = NM_ACTIVE_CONNECTION (user_data);
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
NMAuthCallResult result;
- g_assert (priv->chain == chain);
- g_assert (priv->result_func != NULL);
-
- /* Must stay alive over the callback */
- g_object_ref (self);
+ nm_assert (auth_call_id);
+ nm_assert (priv->auth.result_func);
- if (error) {
- priv->result_func (self, FALSE, error->message, priv->user_data1, priv->user_data2);
- goto done;
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ if (auth_call_id == priv->auth.call_id_network_control)
+ priv->auth.call_id_network_control = NULL;
+ else {
+ nm_assert (auth_call_id == priv->auth.call_id_wifi_shared_permission);
+ priv->auth.call_id_wifi_shared_permission = NULL;
+ }
+ return;
}
- /* Caller has had a chance to obtain authorization, so we only need to
- * check for 'yes' here.
- */
- result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL);
- if (result != NM_AUTH_CALL_RESULT_YES) {
- priv->result_func (self,
- FALSE,
- "Not authorized to control networking.",
- priv->user_data1,
- priv->user_data2);
- goto done;
- }
+ result = nm_auth_call_result_eval (is_authorized, is_challenge, error);
- if (priv->wifi_shared_permission) {
- result = nm_auth_chain_get_result (chain, priv->wifi_shared_permission);
+ if (auth_call_id == priv->auth.call_id_network_control) {
+ priv->auth.call_id_network_control = NULL;
if (result != NM_AUTH_CALL_RESULT_YES) {
- priv->result_func (self,
- FALSE,
- "Not authorized to share connections via wifi.",
- priv->user_data1,
- priv->user_data2);
- goto done;
+ auth_complete (self, FALSE, "Not authorized to control networking.");
+ return;
}
+ } else {
+ nm_assert (auth_call_id == priv->auth.call_id_wifi_shared_permission);
+ if (result != NM_AUTH_CALL_RESULT_YES) {
+ /* we don't fail right away. Instead, we mark that wifi-shared-permissions
+ * are missing. We prefer to report the failure about network-control.
+ * Below, we will wait longer for call_id_network_control (if it's still
+ * pending). */
+ priv->auth.call_id_wifi_shared_permission = AUTH_CALL_ID_SHARED_WIFI_PERMISSION_FAILED;
+ } else
+ priv->auth.call_id_wifi_shared_permission = NULL;
}
- /* Otherwise authorized and available to activate */
- priv->result_func (self, TRUE, NULL, priv->user_data1, priv->user_data2);
+ if (priv->auth.call_id_network_control)
+ return;
-done:
- nm_auth_chain_unref (chain);
- priv->chain = NULL;
- priv->result_func = NULL;
- priv->user_data1 = NULL;
- priv->user_data2 = NULL;
+ if (priv->auth.call_id_wifi_shared_permission) {
+ if (priv->auth.call_id_wifi_shared_permission == AUTH_CALL_ID_SHARED_WIFI_PERMISSION_FAILED)
+ auth_complete (self, FALSE, "Not authorized to share connections via wifi.");
+ return;
+ }
- g_object_unref (self);
+ auth_complete (self, TRUE, NULL);
}
/**
@@ -1080,37 +1102,43 @@ nm_active_connection_authorize (NMActiveConnection *self,
const char *wifi_permission = NULL;
NMConnection *con;
- g_return_if_fail (result_func != NULL);
- g_return_if_fail (priv->chain == NULL);
+ g_return_if_fail (result_func);
+ g_return_if_fail (!priv->auth.call_id_network_control);
+ nm_assert (!priv->auth.call_id_wifi_shared_permission);
if (initial_connection) {
g_return_if_fail (NM_IS_CONNECTION (initial_connection));
- g_return_if_fail (!priv->settings_connection);
+ g_return_if_fail (!priv->settings_connection.obj);
g_return_if_fail (!priv->applied_connection);
con = initial_connection;
} else {
- g_return_if_fail (NM_IS_SETTINGS_CONNECTION (priv->settings_connection));
+ g_return_if_fail (NM_IS_SETTINGS_CONNECTION (priv->settings_connection.obj));
g_return_if_fail (NM_IS_CONNECTION (priv->applied_connection));
con = priv->applied_connection;
}
- priv->chain = nm_auth_chain_new_subject (priv->subject, NULL, auth_done, self);
- g_assert (priv->chain);
-
- /* Check that the subject is allowed to use networking at all */
- nm_auth_chain_add_call (priv->chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE);
+ priv->auth.call_id_network_control = nm_auth_manager_check_authorization (nm_auth_manager_get (),
+ priv->subject,
+ NM_AUTH_PERMISSION_NETWORK_CONTROL,
+ TRUE,
+ auth_done,
+ self);
/* Shared wifi connections require special permissions too */
wifi_permission = nm_utils_get_shared_wifi_permission (con);
if (wifi_permission) {
- priv->wifi_shared_permission = wifi_permission;
- nm_auth_chain_add_call (priv->chain, wifi_permission, TRUE);
+ priv->auth.call_id_wifi_shared_permission = nm_auth_manager_check_authorization (nm_auth_manager_get (),
+ priv->subject,
+ wifi_permission,
+ TRUE,
+ auth_done,
+ self);
}
/* Wait for authorization */
- priv->result_func = result_func;
- priv->user_data1 = user_data1;
- priv->user_data2 = user_data2;
+ priv->auth.result_func = result_func;
+ priv->auth.user_data1 = user_data1;
+ priv->auth.user_data2 = user_data2;
}
/*****************************************************************************/
@@ -1172,31 +1200,40 @@ get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE ((NMActiveConnection *) object);
- GPtrArray *devices;
+ char **strv;
NMDevice *master_device = NULL;
switch (prop_id) {
+
+ /* note that while priv->settings_connection.obj might not be set initially,
+ * it will be set before the object is exported on D-Bus. Hence,
+ * nobody is calling these property getters before the object is
+ * exported, at which point we will have a valid settings-connection.
+ *
+ * Therefore, intentionally not check whether priv->settings_connection.obj
+ * is set, to get an assertion failure if somebody tries to access the
+ * getters at the wrong time. */
case PROP_CONNECTION:
- g_value_set_string (value, nm_connection_get_path (NM_CONNECTION (priv->settings_connection)));
+ g_value_set_string (value, nm_dbus_track_obj_path_get (&priv->settings_connection));
break;
case PROP_ID:
- g_value_set_string (value, nm_connection_get_id (NM_CONNECTION (priv->settings_connection)));
+ g_value_set_string (value, nm_connection_get_id (NM_CONNECTION (priv->settings_connection.obj)));
break;
case PROP_UUID:
- g_value_set_string (value, nm_connection_get_uuid (NM_CONNECTION (priv->settings_connection)));
+ g_value_set_string (value, nm_connection_get_uuid (NM_CONNECTION (priv->settings_connection.obj)));
break;
case PROP_TYPE:
- g_value_set_string (value, nm_connection_get_connection_type (NM_CONNECTION (priv->settings_connection)));
+ g_value_set_string (value, nm_connection_get_connection_type (NM_CONNECTION (priv->settings_connection.obj)));
break;
+
case PROP_SPECIFIC_OBJECT:
g_value_set_string (value, priv->specific_object ? priv->specific_object : "/");
break;
case PROP_DEVICES:
- devices = g_ptr_array_sized_new (2);
+ strv = g_new0 (char *, 2);
if (priv->device && priv->state < NM_ACTIVE_CONNECTION_STATE_DEACTIVATED)
- g_ptr_array_add (devices, g_strdup (nm_dbus_object_get_path (NM_DBUS_OBJECT (priv->device))));
- g_ptr_array_add (devices, NULL);
- g_value_take_boxed (value, (char **) g_ptr_array_free (devices, FALSE));
+ strv[0] = g_strdup (nm_dbus_object_get_path (NM_DBUS_OBJECT (priv->device)));
+ g_value_take_boxed (value, strv);
break;
case PROP_STATE:
if (priv->state_set)
@@ -1342,6 +1379,10 @@ nm_active_connection_init (NMActiveConnection *self)
priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_ACTIVE_CONNECTION, NMActiveConnectionPrivate);
self->_priv = priv;
+ nm_dbus_track_obj_path_init (&priv->settings_connection,
+ G_OBJECT (self),
+ obj_properties[PROP_CONNECTION]);
+
c_list_init (&self->active_connections_lst);
_LOGT ("creating");
@@ -1359,8 +1400,8 @@ constructed (GObject *object)
G_OBJECT_CLASS (nm_active_connection_parent_class)->constructed (object);
if ( !priv->applied_connection
- && priv->settings_connection)
- priv->applied_connection = nm_simple_connection_new_clone (NM_CONNECTION (priv->settings_connection));
+ && priv->settings_connection.obj)
+ priv->applied_connection = nm_simple_connection_new_clone (NM_CONNECTION (priv->settings_connection.obj));
_LOGD ("constructed (%s, version-id %llu, type %s)",
G_OBJECT_TYPE_NAME (self),
@@ -1390,10 +1431,7 @@ dispose (GObject *object)
_LOGD ("disposing");
- if (priv->chain) {
- nm_auth_chain_unref (priv->chain);
- priv->chain = NULL;
- }
+ auth_cancel (self);
g_free (priv->specific_object);
priv->specific_object = NULL;
@@ -1418,6 +1456,17 @@ dispose (GObject *object)
G_OBJECT_CLASS (nm_active_connection_parent_class)->dispose (object);
}
+static void
+finalize (GObject *object)
+{
+ NMActiveConnection *self = NM_ACTIVE_CONNECTION (object);
+ NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
+
+ nm_dbus_track_obj_path_set (&priv->settings_connection, NULL, FALSE);
+
+ G_OBJECT_CLASS (nm_active_connection_parent_class)->finalize (object);
+}
+
static const GDBusSignalInfo signal_info_state_changed = NM_DEFINE_GDBUS_SIGNAL_INFO_INIT (
"StateChanged",
.args = NM_DEFINE_GDBUS_ARG_INFOS (
@@ -1470,6 +1519,7 @@ nm_active_connection_class_init (NMActiveConnectionClass *ac_class)
object_class->set_property = set_property;
object_class->constructed = constructed;
object_class->dispose = dispose;
+ object_class->finalize = finalize;
obj_properties[PROP_CONNECTION] =
g_param_spec_string (NM_ACTIVE_CONNECTION_CONNECTION, "", "",
diff --git a/src/nm-auth-manager.c b/src/nm-auth-manager.c
index 003d997505..6a8214c824 100644
--- a/src/nm-auth-manager.c
+++ b/src/nm-auth-manager.c
@@ -22,6 +22,7 @@
#include "nm-auth-manager.h"
+#include "nm-utils/c-list.h"
#include "nm-errors.h"
#include "nm-core-internal.h"
#include "NetworkManagerUtils.h"
@@ -30,6 +31,9 @@
#define POLKIT_OBJECT_PATH "/org/freedesktop/PolicyKit1/Authority"
#define POLKIT_INTERFACE "org.freedesktop.PolicyKit1.Authority"
+#define CANCELLATION_ID_PREFIX "cancellation-id-"
+#define CANCELLATION_TIMEOUT_MS 5000
+
/*****************************************************************************/
NM_GOBJECT_PROPERTIES_DEFINE_BASE (
@@ -44,13 +48,14 @@ enum {
static guint signals[LAST_SIGNAL] = {0};
typedef struct {
- gboolean polkit_enabled;
-#if WITH_POLKIT
- guint call_id_counter;
- GCancellable *new_proxy_cancellable;
- GSList *queued_calls;
+ CList calls_lst_head;
GDBusProxy *proxy;
-#endif
+ GCancellable *new_proxy_cancellable;
+ GCancellable *cancel_cancellable;
+ guint64 call_numid_counter;
+ bool polkit_enabled:1;
+ bool disposing:1;
+ bool shutting_down:1;
} NMAuthManagerPrivate;
struct _NMAuthManager {
@@ -85,6 +90,22 @@ NM_DEFINE_SINGLETON_REGISTER (NMAuthManager);
} \
} G_STMT_END
+#define _NMLOG2(level, call_id, ...) \
+ G_STMT_START { \
+ if (nm_logging_enabled ((level), (_NMLOG_DOMAIN))) { \
+ NMAuthManagerCallId *_call_id = (call_id); \
+ char __prefix[30] = _NMLOG_PREFIX_NAME; \
+ \
+ if (_call_id->self != singleton_instance) \
+ g_snprintf (__prefix, sizeof (__prefix), ""_NMLOG_PREFIX_NAME"[%p]", _call_id->self); \
+ _nm_log ((level), (_NMLOG_DOMAIN), 0, NULL, NULL, \
+ "%s: call[%"G_GUINT64_FORMAT"]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
+ __prefix, \
+ _call_id->call_numid \
+ _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
+ } \
+ } G_STMT_END
+
/*****************************************************************************/
gboolean
@@ -97,251 +118,323 @@ nm_auth_manager_get_polkit_enabled (NMAuthManager *self)
/*****************************************************************************/
-#if WITH_POLKIT
-
typedef enum {
POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE = 0,
POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION = (1<<0),
} PolkitCheckAuthorizationFlags;
-typedef struct {
- guint call_id;
+typedef enum {
+ IDLE_REASON_AUTHORIZED,
+ IDLE_REASON_NO_DBUS,
+} IdleReason;
+
+struct _NMAuthManagerCallId {
+ CList calls_lst;
NMAuthManager *self;
- GSimpleAsyncResult *simple;
- gchar *cancellation_id;
GVariant *dbus_parameters;
- GCancellable *cancellable;
-} CheckAuthData;
+ GCancellable *dbus_cancellable;
+ NMAuthManagerCheckAuthorizationCallback callback;
+ gpointer user_data;
+ guint64 call_numid;
+ guint idle_id;
+ IdleReason idle_reason:8;
+};
+
+#define cancellation_id_to_str_a(call_numid) \
+ nm_sprintf_bufa (NM_STRLEN (CANCELLATION_ID_PREFIX) + 20, \
+ CANCELLATION_ID_PREFIX"%"G_GUINT64_FORMAT, \
+ (call_numid))
static void
-_check_auth_data_free (CheckAuthData *data)
+_call_id_free (NMAuthManagerCallId *call_id)
{
- if (data->dbus_parameters)
- g_variant_unref (data->dbus_parameters);
- g_object_unref (data->self);
- g_object_unref (data->simple);
- g_clear_object (&data->cancellable);
- g_free (data->cancellation_id);
- g_free (data);
+ c_list_unlink (&call_id->calls_lst);
+ nm_clear_g_source (&call_id->idle_id);
+ if (call_id->dbus_parameters)
+ g_variant_unref (g_steal_pointer (&call_id->dbus_parameters));
+
+ if (call_id->dbus_cancellable) {
+ /* we have a pending D-Bus call. We keep the call-id instance alive
+ * for _call_check_authorize_cb() */
+ g_cancellable_cancel (call_id->dbus_cancellable);
+ return;
+ }
+
+ g_object_unref (call_id->self);
+ g_slice_free (NMAuthManagerCallId, call_id);
}
static void
-_call_check_authorization_complete_with_error (CheckAuthData *data,
- const char *error_message)
+_call_id_invoke_callback (NMAuthManagerCallId *call_id,
+ gboolean is_authorized,
+ gboolean is_challenge,
+ GError *error)
{
- NMAuthManager *self = data->self;
-
- _LOGD ("call[%u]: CheckAuthorization failed due to internal error: %s", data->call_id, error_message);
- g_simple_async_result_set_error (data->simple,
- NM_MANAGER_ERROR,
- NM_MANAGER_ERROR_FAILED,
- "Authorization check failed: %s",
- error_message);
-
- g_simple_async_result_complete_in_idle (data->simple);
-
- _check_auth_data_free (data);
+ c_list_unlink (&call_id->calls_lst);
+
+ call_id->callback (call_id->self,
+ call_id,
+ is_authorized,
+ is_challenge,
+ error,
+ call_id->user_data);
+ _call_id_free (call_id);
}
static void
-cancel_check_authorization_cb (GDBusProxy *proxy,
+cancel_check_authorization_cb (GObject *proxy,
GAsyncResult *res,
gpointer user_data)
{
- NMAuthManager *self = user_data;
- GVariant *value;
- GError *error= NULL;
-
- value = g_dbus_proxy_call_finish (proxy, res, &error);
- if (value == NULL) {
- g_dbus_error_strip_remote_error (error);
- _LOGD ("Error cancelling authorization check: %s", error->message);
- g_error_free (error);
- } else
- g_variant_unref (value);
+ NMAuthManagerCallId *call_id = user_data;
+ gs_unref_variant GVariant *value = NULL;
+ gs_free_error GError *error= NULL;
+
+ value = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, &error);
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ _LOG2T (call_id, "cancel request was cancelled");
+ else if (error)
+ _LOG2T (call_id, "cancel request failed: %s", error->message);
+ else
+ _LOG2T (call_id, "cancel request succeeded");
- g_object_unref (self);
+ _call_id_free (call_id);
}
-typedef struct {
- gboolean is_authorized;
- gboolean is_challenge;
-} CheckAuthorizationResult;
-
static void
-check_authorization_cb (GDBusProxy *proxy,
- GAsyncResult *res,
- gpointer user_data)
+_call_check_authorize_cb (GObject *proxy,
+ GAsyncResult *res,
+ gpointer user_data)
{
- CheckAuthData *data = user_data;
- NMAuthManager *self = data->self;
- NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
- GVariant *value;
- GError *error = NULL;
-
- value = _nm_dbus_proxy_call_finish (proxy, res, G_VARIANT_TYPE ("((bba{ss}))"), &error);
- if (value == NULL) {
- if (data->cancellation_id != NULL &&
- ( g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)
- && !g_dbus_error_is_remote_error (error))) {
- _LOGD ("call[%u]: CheckAuthorization cancelled", data->call_id);
- g_dbus_proxy_call (priv->proxy,
- "CancelCheckAuthorization",
- g_variant_new ("(s)", data->cancellation_id),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL, /* GCancellable */
- (GAsyncReadyCallback) cancel_check_authorization_cb,
- g_object_ref (self));
- } else
- _LOGD ("call[%u]: CheckAuthorization failed: %s", data->call_id, error->message);
- g_dbus_error_strip_remote_error (error);
- g_simple_async_result_set_error (data->simple,
- NM_MANAGER_ERROR,
- NM_MANAGER_ERROR_FAILED,
- "Authorization check failed: %s",
- error->message);
- g_error_free (error);
- } else {
- CheckAuthorizationResult *result;
+ NMAuthManagerCallId *call_id = user_data;
+ NMAuthManager *self;
+ NMAuthManagerPrivate *priv;
+ gs_unref_variant GVariant *value = NULL;
+ gs_free_error GError *error = NULL;
+ gboolean is_authorized = FALSE;
+ gboolean is_challenge = FALSE;
- result = g_new0 (CheckAuthorizationResult, 1);
+ /* we need to clear the cancelable, to signal for _call_id_free() that we
+ * are not in a pending call.
+ *
+ * Note how _call_id_free() kept call-id alive, even if the request was
+ * already cancelled. */
+ g_clear_object (&call_id->dbus_cancellable);
- g_variant_get (value,
- "((bb@a{ss}))",
- &result->is_authorized,
- &result->is_challenge,
- NULL);
- g_variant_unref (value);
+ self = call_id->self;
+ priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
- _LOGD ("call[%u]: CheckAuthorization succeeded: (is_authorized=%d, is_challenge=%d)", data->call_id, result->is_authorized, result->is_challenge);
- g_simple_async_result_set_op_res_gpointer (data->simple, result, g_free);
+ value = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, G_VARIANT_TYPE ("((bba{ss}))"), &error);
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ /* call_id was cancelled externally, but _call_id_free() kept call_id
+ * alive (and it has still the reference on @self. */
+
+ if (!priv->cancel_cancellable) {
+ /* we do a forced shutdown. There is no more time for cancelling... */
+ _call_id_free (call_id);
+
+ /* this shouldn't really happen, because:
+ * _call_check_authorize() only scheduled the D-Bus request at a time when
+ * cancel_cancellable was still set. It means, somebody called force-shutdown
+ * after call-id was schedule.
+ * force-shutdown should only be called after:
+ * - cancel all pending requests
+ * - give enough time to cancel the request and schedule a D-Bus call
+ * to CancelCheckAuthorization (below), before issuing force-shutdown. */
+ g_return_if_reached ();
+ }
+
+ g_dbus_proxy_call (priv->proxy,
+ "CancelCheckAuthorization",
+ g_variant_new ("(s)",
+ cancellation_id_to_str_a (call_id->call_numid)),
+ G_DBUS_CALL_FLAGS_NONE,
+ CANCELLATION_TIMEOUT_MS,
+ priv->cancel_cancellable,
+ cancel_check_authorization_cb,
+ call_id);
+ return;
}
- g_simple_async_result_complete (data->simple);
+ if (!error) {
+ g_variant_get (value,
+ "((bb@a{ss}))",
+ &is_authorized,
+ &is_challenge,
+ NULL);
+ _LOG2T (call_id, "completed: authorized=%d, challenge=%d",
+ is_authorized, is_challenge);
+ } else
+ _LOG2T (call_id, "completed: failed: %s", error->message);
- _check_auth_data_free (data);
+ _call_id_invoke_callback (call_id, is_authorized, is_challenge, error);
}
static void
-_call_check_authorization (CheckAuthData *data)
+_call_check_authorize (NMAuthManagerCallId *call_id)
{
- NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (data->self);
+ NMAuthManager *self = call_id->self;
+ NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
+
+ nm_assert (call_id->dbus_parameters);
+ nm_assert (g_variant_is_floating (call_id->dbus_parameters));
+ nm_assert (!call_id->dbus_cancellable);
+
+ call_id->dbus_cancellable = g_cancellable_new ();
+
+ nm_assert (priv->cancel_cancellable);
g_dbus_proxy_call (priv->proxy,
"CheckAuthorization",
- data->dbus_parameters,
+ g_steal_pointer (&call_id->dbus_parameters),
G_DBUS_CALL_FLAGS_NONE,
G_MAXINT, /* no timeout */
- data->cancellable,
- (GAsyncReadyCallback) check_authorization_cb,
- data);
- g_clear_object (&data->cancellable);
- data->dbus_parameters = NULL;
+ call_id->dbus_cancellable,
+ _call_check_authorize_cb,
+ call_id);
}
-void
-nm_auth_manager_polkit_authority_check_authorization (NMAuthManager *self,
- NMAuthSubject *subject,
- const char *action_id,
- gboolean allow_user_interaction,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
+static gboolean
+_call_on_idle (gpointer user_data)
+{
+ NMAuthManagerCallId *call_id = user_data;
+ gs_free_error GError *error = NULL;
+ gboolean is_authorized = FALSE;
+ gboolean is_challenge = FALSE;
+ const char *error_msg = NULL;
+
+ call_id->idle_id = 0;
+ if (call_id->idle_reason == IDLE_REASON_AUTHORIZED) {
+ is_authorized = TRUE;
+ _LOG2T (call_id, "completed: authorized=%d, challenge=%d (simulated)",
+ is_authorized, is_challenge);
+ } else {
+ nm_assert (call_id->idle_reason == IDLE_REASON_NO_DBUS);
+ error_msg = "failure creating GDBusProxy for authorization request";
+ _LOG2T (call_id, "completed: failed due to no D-Bus proxy");
+ }
+
+ if (error_msg)
+ g_set_error_literal (&error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, error_msg);
+ _call_id_invoke_callback (call_id, is_authorized, is_challenge, error);
+ return G_SOURCE_REMOVE;
+}
+
+/*
+ * @callback must never be invoked synchronously.
+ *
+ * @callback is always invoked exactly once, and never synchronously.
+ * You may cancel the invocation with nm_auth_manager_check_authorization_cancel(),
+ * but: you may only do so exactly once, and only before @callback is
+ * invoked. Even if you cancel the request, @callback will still be invoked
+ * (synchronously, during the _cancel() callback).
+ *
+ * The request keeps @self alive (it needs to do so, because when cancelling a
+ * request we might need to do an additional CancelCheckAuthorization call, for
+ * which @self must be live long enough).
+ */
+NMAuthManagerCallId *
+nm_auth_manager_check_authorization (NMAuthManager *self,
+ NMAuthSubject *subject,
+ const char *action_id,
+ gboolean allow_user_interaction,
+ NMAuthManagerCheckAuthorizationCallback callback,
+ gpointer user_data)
{
NMAuthManagerPrivate *priv;
+ PolkitCheckAuthorizationFlags flags;
char subject_buf[64];
GVariantBuilder builder;
- PolkitCheckAuthorizationFlags flags;
GVariant *subject_value;
GVariant *details_value;
- CheckAuthData *data;
+ NMAuthManagerCallId *call_id;
- g_return_if_fail (NM_IS_AUTH_MANAGER (self));
- g_return_if_fail (NM_IS_AUTH_SUBJECT (subject));
- g_return_if_fail (nm_auth_subject_is_unix_process (subject));
- g_return_if_fail (action_id != NULL);
- g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_val_if_fail (NM_IS_AUTH_MANAGER (self), NULL);
+ g_return_val_if_fail (NM_IN_SET (nm_auth_subject_get_subject_type (subject),
+ NM_AUTH_SUBJECT_TYPE_INTERNAL,
+ NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS),
+ NULL);
+ g_return_val_if_fail (action_id, NULL);
priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
- g_return_if_fail (priv->polkit_enabled);
+ g_return_val_if_fail (!priv->disposing, NULL);
+ g_return_val_if_fail (!priv->shutting_down, NULL);
flags = allow_user_interaction
? POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION
: POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE;
- subject_value = nm_auth_subject_unix_process_to_polkit_gvariant (subject);
- nm_assert (g_variant_is_floating (subject_value));
-
- /* ((PolkitDetails *)NULL) */
- g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}"));
- details_value = g_variant_builder_end (&builder);
-
- data = g_new0 (CheckAuthData, 1);
- data->call_id = ++priv->call_id_counter;
- data->self = g_object_ref (self);
- data->simple = g_simple_async_result_new (G_OBJECT (self),
- callback,
- user_data,
- nm_auth_manager_polkit_authority_check_authorization);
- if (cancellable != NULL) {
- data->cancellation_id = g_strdup_printf ("cancellation-id-%u", data->call_id);
- data->cancellable = g_object_ref (cancellable);
- }
-
- data->dbus_parameters = g_variant_new ("(@(sa{sv})s@a{ss}us)",
- subject_value,
- action_id,
- details_value,
- (guint32) flags,
- data->cancellation_id != NULL ? data->cancellation_id : "");
-
- if (priv->new_proxy_cancellable) {
- _LOGD ("call[%u]: CheckAuthorization(%s), subject=%s (wait for proxy)", data->call_id, action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf)));
-
- priv->queued_calls = g_slist_prepend (priv->queued_calls, data);
- } else if (!priv->proxy) {
- _LOGD ("call[%u]: CheckAuthorization(%s), subject=%s (fails due to invalid DBUS proxy)", data->call_id, action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf)));
-
- _call_check_authorization_complete_with_error (data, "invalid DBUS proxy");
+ call_id = g_slice_new0 (NMAuthManagerCallId);
+ call_id->self = g_object_ref (self);
+ call_id->callback = callback;
+ call_id->user_data = user_data;
+ call_id->call_numid = ++priv->call_numid_counter;
+ c_list_link_tail (&priv->calls_lst_head, &call_id->calls_lst);
+
+ if (!priv->polkit_enabled) {
+ _LOG2T (call_id, "CheckAuthorization(%s), subject=%s (succeeding due to polkit authorization disabled)", action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf)));
+ call_id->idle_reason = IDLE_REASON_AUTHORIZED;
+ call_id->idle_id = g_idle_add (_call_on_idle, call_id);
+ } else if (nm_auth_subject_is_internal (subject)) {
+ _LOG2T (call_id, "CheckAuthorization(%s), subject=%s (succeeding for internal request)", action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf)));
+ call_id->idle_reason = IDLE_REASON_AUTHORIZED;
+ call_id->idle_id = g_idle_add (_call_on_idle, call_id);
+ } else if (nm_auth_subject_get_unix_process_uid (subject) == 0) {
+ _LOG2T (call_id, "CheckAuthorization(%s), subject=%s (succeeding for root)", action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf)));
+ call_id->idle_reason = IDLE_REASON_AUTHORIZED;
+ call_id->idle_id = g_idle_add (_call_on_idle, call_id);
+ } else if ( !priv->proxy
+ && !priv->new_proxy_cancellable) {
+ _LOG2T (call_id, "CheckAuthorization(%s), subject=%s (failing due to invalid DBUS proxy)", action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf)));
+ call_id->idle_reason = IDLE_REASON_NO_DBUS;
+ call_id->idle_id = g_idle_add (_call_on_idle, call_id);
} else {
- _LOGD ("call[%u]: CheckAuthorization(%s), subject=%s", data->call_id, action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf)));
-
- _call_check_authorization (data);
+ subject_value = nm_auth_subject_unix_process_to_polkit_gvariant (subject);
+ nm_assert (g_variant_is_floating (subject_value));
+
+ /* ((PolkitDetails *)NULL) */
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}"));
+ details_value = g_variant_builder_end (&builder);
+
+ call_id->dbus_parameters = g_variant_new ("(@(sa{sv})s@a{ss}us)",
+ subject_value,
+ action_id,
+ details_value,
+ (guint32) flags,
+ cancellation_id_to_str_a (call_id->call_numid));
+ if (!priv->proxy) {
+ _LOG2T (call_id, "CheckAuthorization(%s), subject=%s (wait for proxy)", action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf)));
+ } else {
+ _LOG2T (call_id, "CheckAuthorization(%s), subject=%s", action_id, nm_auth_subject_to_string (subject, subject_buf, sizeof (subject_buf)));
+ _call_check_authorize (call_id);
+ }
}
+
+ return call_id;
}
-gboolean
-nm_auth_manager_polkit_authority_check_authorization_finish (NMAuthManager *self,
- GAsyncResult *res,
- gboolean *out_is_authorized,
- gboolean *out_is_challenge,
- GError **error)
+void
+nm_auth_manager_check_authorization_cancel (NMAuthManagerCallId *call_id)
{
- gboolean success = FALSE;
- gboolean is_authorized = FALSE;
- gboolean is_challenge = FALSE;
+ NMAuthManager *self;
+ gs_free_error GError *error = NULL;
- g_return_val_if_fail (NM_IS_AUTH_MANAGER (self), FALSE);
- g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (res), FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ g_return_if_fail (call_id);
- if (!g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) {
- CheckAuthorizationResult *result;
+ self = call_id->self;
- result = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res));
- is_authorized = !!result->is_authorized;
- is_challenge = !!result->is_challenge;
- success = TRUE;
- }
- g_assert ((success && !error) || (!success || error));
+ g_return_if_fail (NM_IS_AUTH_MANAGER (self));
+ g_return_if_fail (!c_list_is_empty (&call_id->calls_lst));
- if (out_is_authorized)
- *out_is_authorized = is_authorized;
- if (out_is_challenge)
- *out_is_challenge = is_challenge;
- return success;
+ nm_assert (c_list_contains (&NM_AUTH_MANAGER_GET_PRIVATE (self)->calls_lst_head, &call_id->calls_lst));
+
+ nm_utils_error_set_cancelled (&error, FALSE, "NMAuthManager");
+ _LOG2T (call_id, "completed: failed due to call cancelled");
+ _call_id_invoke_callback (call_id,
+ FALSE,
+ FALSE,
+ error);
}
/*****************************************************************************/
@@ -350,14 +443,14 @@ static void
_emit_changed_signal (NMAuthManager *self)
{
_LOGD ("emit changed signal");
- g_signal_emit_by_name (self, NM_AUTH_MANAGER_SIGNAL_CHANGED);
+ g_signal_emit (self, signals[CHANGED_SIGNAL], 0);
}
static void
_log_name_owner (NMAuthManager *self, char **out_name_owner)
{
NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
- char *name_owner;
+ gs_free char *name_owner = NULL;
name_owner = g_dbus_proxy_get_name_owner (priv->proxy);
if (name_owner)
@@ -365,10 +458,7 @@ _log_name_owner (NMAuthManager *self, char **out_name_owner)
else
_LOGD ("dbus name owner: none");
- if (out_name_owner)
- *out_name_owner = name_owner;
- else
- g_free (name_owner);
+ NM_SET_OUT (out_name_owner, g_steal_pointer (&name_owner));
}
static void
@@ -377,20 +467,16 @@ _dbus_on_name_owner_notify_cb (GObject *object,
gpointer user_data)
{
NMAuthManager *self = user_data;
- NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
- char *name_owner;
+ gs_free char *name_owner = NULL;
- g_return_if_fail (priv->proxy == (void *) object);
+ nm_assert (NM_AUTH_MANAGER_GET_PRIVATE (self)->proxy == (GDBusProxy *) object);
_log_name_owner (self, &name_owner);
-
if (!name_owner) {
/* when the name disappears, we also want to raise a emit signal.
* When it appears, we raise one already. */
_emit_changed_signal (self);
}
-
- g_free (name_owner);
}
static void
@@ -398,9 +484,8 @@ _dbus_on_changed_signal_cb (GDBusProxy *proxy,
gpointer user_data)
{
NMAuthManager *self = user_data;
- NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
- g_return_if_fail (priv->proxy == proxy);
+ nm_assert (NM_AUTH_MANAGER_GET_PRIVATE (self)->proxy == proxy);
_LOGD ("dbus signal: \"Changed\"");
_emit_changed_signal (self);
@@ -411,49 +496,35 @@ _dbus_new_proxy_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
- NMAuthManager **p_self = user_data;
- NMAuthManager *self = NULL;
+ NMAuthManager *self;
NMAuthManagerPrivate *priv;
- GError *error = NULL;
+ gs_free GError *error = NULL;
GDBusProxy *proxy;
- CheckAuthData *data;
+ NMAuthManagerCallId *call_id;
proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
- if (!*p_self) {
- _LOGD ("_dbus_new_proxy_cb(): manager destroyed before callback finished. Abort");
- g_clear_object (&proxy);
- g_clear_error (&error);
- g_free (p_self);
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
- }
- self = *p_self;
- g_object_remove_weak_pointer (G_OBJECT (self), (void **)p_self);
- g_free (p_self);
+ self = user_data;
priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
- g_return_if_fail (priv->new_proxy_cancellable);
- g_return_if_fail (!priv->proxy);
-
+ priv->proxy = proxy;
g_clear_object (&priv->new_proxy_cancellable);
- priv->queued_calls = g_slist_reverse (priv->queued_calls);
-
- priv->proxy = proxy;
if (!priv->proxy) {
- _LOGE ("could not get polkit proxy: %s", error->message);
- g_clear_error (&error);
-
- while (priv->queued_calls) {
- data = priv->queued_calls->data;
- priv->queued_calls = g_slist_remove (priv->queued_calls, data);
+ _LOGE ("could not create polkit proxy: %s", error->message);
- _call_check_authorization_complete_with_error (data, "error creating DBUS proxy");
+ while ((call_id = c_list_first_entry (&priv->calls_lst_head, NMAuthManagerCallId, calls_lst))) {
+ _LOG2T (call_id, "completed: failed due to no D-Bus proxy after startup");
+ _call_id_invoke_callback (call_id, FALSE, FALSE, error);
}
return;
}
+ priv->cancel_cancellable = g_cancellable_new ();
+
g_signal_connect (priv->proxy,
"notify::g-name-owner",
G_CALLBACK (_dbus_on_name_owner_notify_cb),
@@ -464,17 +535,14 @@ _dbus_new_proxy_cb (GObject *source_object,
_log_name_owner (self, NULL);
- while (priv->queued_calls) {
- data = priv->queued_calls->data;
- priv->queued_calls = g_slist_remove (priv->queued_calls, data);
- _LOGD ("call[%u]: CheckAuthorization invoke now", data->call_id);
- _call_check_authorization (data);
+ while ((call_id = c_list_first_entry (&priv->calls_lst_head, NMAuthManagerCallId, calls_lst))) {
+ _LOG2T (call_id, "CheckAuthorization invoke now");
+ _call_check_authorize (call_id);
}
+
_emit_changed_signal (self);
}
-#endif
-
/*****************************************************************************/
NMAuthManager *
@@ -485,23 +553,42 @@ nm_auth_manager_get ()
return singleton_instance;
}
-/*****************************************************************************/
-
-static void
-get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+void
+nm_auth_manager_force_shutdown (NMAuthManager *self)
{
- NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE ((NMAuthManager *) object);
+ NMAuthManagerPrivate *priv;
- switch (prop_id) {
- case PROP_POLKIT_ENABLED:
- g_value_set_boolean (value, priv->polkit_enabled);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
+ g_return_if_fail (NM_IS_AUTH_MANAGER (self));
+
+ priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
+
+ /* while we have pending requests (NMAuthManagerCallId), the instance
+ * is kept alive.
+ *
+ * Even if the caller cancells all pending call-ids, we still need to keep
+ * a reference to self, in order to handle pending CancelCheckAuthorization
+ * requests.
+ *
+ * To do a corrdinated shutdown, do the following:
+ * - cancel all pending NMAuthManagerCallId requests.
+ * - ensure everybody unrefs the NMAuthManager instance. If by that, the instance
+ * gets destroyed, the shutdown already completed successfully.
+ * - Otherwise, the object is kept alive by pending CancelCheckAuthorization requests.
+ * wait a certain timeout (1 second) for all requests to complete (by watching
+ * for destruction of NMAuthManager).
+ * - if that doesn't happen within timeout, issue nm_auth_manager_force_shutdown() and
+ * wait longer. After that, soon the instance should be destroyed and you
+ * did a successful shutdown.
+ * - if the instance was still not destroyed within a short timeout, you leaked
+ * resources. You cannot properly shutdown.
+ */
+
+ priv->shutting_down = TRUE;
+ nm_clear_g_cancellable (&priv->cancel_cancellable);
}
+/*****************************************************************************/
+
static void
set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
@@ -523,6 +610,9 @@ set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *p
static void
nm_auth_manager_init (NMAuthManager *self)
{
+ NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
+
+ c_list_init (&priv->calls_lst_head);
}
static void
@@ -533,16 +623,10 @@ constructed (GObject *object)
G_OBJECT_CLASS (nm_auth_manager_parent_class)->constructed (object);
-#if WITH_POLKIT
_LOGD ("create auth-manager: polkit %s", priv->polkit_enabled ? "enabled" : "disabled");
if (priv->polkit_enabled) {
- NMAuthManager **p_self;
-
priv->new_proxy_cancellable = g_cancellable_new ();
- p_self = g_new (NMAuthManager *, 1);
- *p_self = self;
- g_object_add_weak_pointer (G_OBJECT (self), (void **) p_self);
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
NULL,
@@ -551,14 +635,8 @@ constructed (GObject *object)
POLKIT_INTERFACE,
priv->new_proxy_cancellable,
_dbus_new_proxy_cb,
- p_self);
+ self);
}
-#else
- if (priv->polkit_enabled)
- _LOGW ("create auth-manager: polkit disabled at compile time. All authentication requests will fail");
- else
- _LOGD ("create auth-manager: polkit disabled at compile time");
-#endif
}
NMAuthManager *
@@ -585,23 +663,22 @@ static void
dispose (GObject *object)
{
NMAuthManager* self = NM_AUTH_MANAGER (object);
-#if WITH_POLKIT
NMAuthManagerPrivate *priv = NM_AUTH_MANAGER_GET_PRIVATE (self);
-#endif
+ gs_free_error GError *error_disposing = NULL;
_LOGD ("dispose");
-#if WITH_POLKIT
- /* since we take a reference for each queued call, we don't expect to have any queued calls in dispose() */
- g_assert (!priv->queued_calls);
+ nm_assert (!c_list_is_empty (&priv->calls_lst_head));
+
+ priv->disposing = TRUE;
nm_clear_g_cancellable (&priv->new_proxy_cancellable);
+ nm_clear_g_cancellable (&priv->cancel_cancellable);
if (priv->proxy) {
g_signal_handlers_disconnect_by_data (priv->proxy, self);
g_clear_object (&priv->proxy);
}
-#endif
G_OBJECT_CLASS (nm_auth_manager_parent_class)->dispose (object);
}
@@ -611,7 +688,6 @@ nm_auth_manager_class_init (NMAuthManagerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
- object_class->get_property = get_property;
object_class->set_property = set_property;
object_class->constructed = constructed;
object_class->dispose = dispose;
@@ -619,7 +695,7 @@ nm_auth_manager_class_init (NMAuthManagerClass *klass)
obj_properties[PROP_POLKIT_ENABLED] =
g_param_spec_boolean (NM_AUTH_MANAGER_POLKIT_ENABLED, "", "",
FALSE,
- G_PARAM_READWRITE |
+ G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
@@ -628,11 +704,7 @@ nm_auth_manager_class_init (NMAuthManagerClass *klass)
signals[CHANGED_SIGNAL] = g_signal_new (NM_AUTH_MANAGER_SIGNAL_CHANGED,
NM_TYPE_AUTH_MANAGER,
G_SIGNAL_RUN_LAST,
- 0, /* class offset */
- NULL, /* accumulator */
- NULL, /* accumulator data */
+ 0, NULL, NULL,
g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE,
- 0);
+ G_TYPE_NONE, 0);
}
-
diff --git a/src/nm-auth-manager.h b/src/nm-auth-manager.h
index e66ef78c1b..fe7ee787dc 100644
--- a/src/nm-auth-manager.h
+++ b/src/nm-auth-manager.h
@@ -23,6 +23,31 @@
#include "nm-auth-subject.h"
+/*****************************************************************************/
+
+typedef enum {
+ NM_AUTH_CALL_RESULT_UNKNOWN,
+ NM_AUTH_CALL_RESULT_YES,
+ NM_AUTH_CALL_RESULT_AUTH,
+ NM_AUTH_CALL_RESULT_NO,
+} NMAuthCallResult;
+
+static inline NMAuthCallResult
+nm_auth_call_result_eval (gboolean is_authorized,
+ gboolean is_challenge,
+ GError *error)
+{
+ if (error)
+ return NM_AUTH_CALL_RESULT_UNKNOWN;
+ if (is_authorized)
+ return NM_AUTH_CALL_RESULT_YES;
+ if (is_challenge)
+ return NM_AUTH_CALL_RESULT_AUTH;
+ return NM_AUTH_CALL_RESULT_NO;
+}
+
+/*****************************************************************************/
+
#define NM_TYPE_AUTH_MANAGER (nm_auth_manager_get_type ())
#define NM_AUTH_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_AUTH_MANAGER, NMAuthManager))
#define NM_AUTH_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_AUTH_MANAGER, NMAuthManagerClass))
@@ -42,23 +67,28 @@ GType nm_auth_manager_get_type (void);
NMAuthManager *nm_auth_manager_setup (gboolean polkit_enabled);
NMAuthManager *nm_auth_manager_get (void);
+void nm_auth_manager_force_shutdown (NMAuthManager *self);
+
gboolean nm_auth_manager_get_polkit_enabled (NMAuthManager *self);
-#if WITH_POLKIT
-
-void nm_auth_manager_polkit_authority_check_authorization (NMAuthManager *self,
- NMAuthSubject *subject,
- const char *action_id,
- gboolean allow_user_interaction,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-gboolean nm_auth_manager_polkit_authority_check_authorization_finish (NMAuthManager *self,
- GAsyncResult *res,
- gboolean *out_is_authorized,
- gboolean *out_is_challenge,
- GError **error);
-
-#endif
+/*****************************************************************************/
+
+typedef struct _NMAuthManagerCallId NMAuthManagerCallId;
+
+typedef void (*NMAuthManagerCheckAuthorizationCallback) (NMAuthManager *self,
+ NMAuthManagerCallId *call_id,
+ gboolean is_authorized,
+ gboolean is_challenge,
+ GError *error,
+ gpointer user_data);
+
+NMAuthManagerCallId *nm_auth_manager_check_authorization (NMAuthManager *self,
+ NMAuthSubject *subject,
+ const char *action_id,
+ gboolean allow_user_interaction,
+ NMAuthManagerCheckAuthorizationCallback callback,
+ gpointer user_data);
+
+void nm_auth_manager_check_authorization_cancel (NMAuthManagerCallId *call_id);
#endif /* NM_AUTH_MANAGER_H */
diff --git a/src/nm-auth-utils.c b/src/nm-auth-utils.c
index 5d92f36d6a..cba118250f 100644
--- a/src/nm-auth-utils.c
+++ b/src/nm-auth-utils.c
@@ -34,19 +34,16 @@
/*****************************************************************************/
struct NMAuthChain {
- GHashTable *data;
+ GHashTable *data_hash;
CList auth_call_lst_head;
GDBusMethodInvocation *context;
NMAuthSubject *subject;
- GError *error;
NMAuthChainResultFunc done_func;
gpointer user_data;
- guint idle_id;
-
guint32 refcount;
bool done:1;
@@ -55,9 +52,8 @@ struct NMAuthChain {
typedef struct {
CList auth_call_lst;
NMAuthChain *chain;
- GCancellable *cancellable;
+ NMAuthManagerCallId *call_id;
char *permission;
- guint call_idle_id;
} AuthCall;
/*****************************************************************************/
@@ -75,8 +71,8 @@ _ASSERT_call (AuthCall *call)
static void
auth_call_free (AuthCall *call)
{
- nm_clear_g_source (&call->call_idle_id);
- nm_clear_g_cancellable (&call->cancellable);
+ if (call->call_id)
+ nm_auth_manager_check_authorization_cancel (call->call_id);
c_list_unlink_stale (&call->auth_call_lst);
g_free (call->permission);
g_slice_free (AuthCall, call);
@@ -123,7 +119,9 @@ _get_data (NMAuthChain *self, const char *tag)
{
ChainData *tmp;
- tmp = g_hash_table_lookup (self->data, &tag);
+ if (!self->data_hash)
+ return NULL;
+ tmp = g_hash_table_lookup (self->data_hash, &tag);
return tmp ? tmp->data : NULL;
}
@@ -156,7 +154,10 @@ nm_auth_chain_steal_data (NMAuthChain *self, const char *tag)
g_return_val_if_fail (self, NULL);
g_return_val_if_fail (tag, NULL);
- tmp = g_hash_table_lookup (self->data, &tag);
+ if (!self->data_hash)
+ return NULL;
+
+ tmp = g_hash_table_lookup (self->data_hash, &tag);
if (!tmp)
return NULL;
@@ -164,7 +165,7 @@ nm_auth_chain_steal_data (NMAuthChain *self, const char *tag)
/* Make sure the destroy handler isn't called when freeing */
tmp->destroy = NULL;
- g_hash_table_remove (self->data, tmp);
+ g_hash_table_remove (self->data_hash, tmp);
return value;
}
@@ -177,10 +178,15 @@ nm_auth_chain_set_data (NMAuthChain *self,
g_return_if_fail (self);
g_return_if_fail (tag);
- if (data == NULL)
- g_hash_table_remove (self->data, &tag);
- else {
- g_hash_table_add (self->data,
+ if (data == NULL) {
+ if (self->data_hash)
+ g_hash_table_remove (self->data_hash, &tag);
+ } else {
+ if (!self->data_hash) {
+ self->data_hash = g_hash_table_new_full (nm_pstr_hash, nm_pstr_equal,
+ NULL, chain_data_free);
+ }
+ g_hash_table_add (self->data_hash,
chain_data_new (tag, data, data_destroy));
}
}
@@ -210,17 +216,16 @@ nm_auth_chain_get_subject (NMAuthChain *self)
/*****************************************************************************/
static gboolean
-auth_chain_finish (gpointer user_data)
+auth_chain_finish (NMAuthChain *self)
{
- NMAuthChain *self = user_data;
-
- self->idle_id = 0;
self->done = TRUE;
/* Ensure we stay alive across the callback */
+ nm_assert (self->refcount == 1);
self->refcount++;
- self->done_func (self, self->error, self->context, self->user_data);
- nm_auth_chain_unref (self);
+ self->done_func (self, NULL, self->context, self->user_data);
+ nm_assert (NM_IN_SET (self->refcount, 1, 2));
+ nm_auth_chain_destroy (self);
return FALSE;
}
@@ -233,71 +238,42 @@ auth_call_complete (AuthCall *call)
self = call->chain;
- c_list_unlink (&call->auth_call_lst);
-
- if (c_list_is_empty (&self->auth_call_lst_head)) {
- nm_assert (!self->idle_id && !self->done);
- self->idle_id = g_idle_add (auth_chain_finish, self);
- }
+ nm_assert (!self->done);
auth_call_free (call);
-}
-
-static gboolean
-auth_call_complete_idle_cb (gpointer user_data)
-{
- AuthCall *call = user_data;
-
- _ASSERT_call (call);
- call->call_idle_id = 0;
- auth_call_complete (call);
- return G_SOURCE_REMOVE;
+ if (c_list_is_empty (&self->auth_call_lst_head)) {
+ /* we are on an idle-handler or a clean call-stack (non-reentrant). */
+ auth_chain_finish (self);
+ }
}
-#if WITH_POLKIT
static void
-pk_call_cb (GObject *object, GAsyncResult *result, gpointer user_data)
+pk_call_cb (NMAuthManager *auth_manager,
+ NMAuthManagerCallId *call_id,
+ gboolean is_authorized,
+ gboolean is_challenge,
+ GError *error,
+ gpointer user_data)
{
AuthCall *call;
- gs_free_error GError *error = NULL;
- gboolean is_authorized = FALSE, is_challenge = FALSE;
- guint call_result = NM_AUTH_CALL_RESULT_UNKNOWN;
-
- nm_auth_manager_polkit_authority_check_authorization_finish (NM_AUTH_MANAGER (object),
- result,
- &is_authorized,
- &is_challenge,
- &error);
- if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
- nm_log_dbg (LOGD_CORE, "callback already cancelled");
+ NMAuthCallResult call_result;
+
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
- }
call = user_data;
- g_clear_object (&call->cancellable);
+ nm_assert (call->call_id == call_id);
- if (error) {
- /* Don't ruin the chain. Just leave the result unknown. */
- nm_log_warn (LOGD_CORE, "error requesting auth for %s: %s",
- call->permission, error->message);
- } else {
- if (is_authorized) {
- /* Caller has the permission */
- call_result = NM_AUTH_CALL_RESULT_YES;
- } else if (is_challenge) {
- /* Caller could authenticate to get the permission */
- call_result = NM_AUTH_CALL_RESULT_AUTH;
- } else
- call_result = NM_AUTH_CALL_RESULT_NO;
- }
+ call->call_id = NULL;
+
+ call_result = nm_auth_call_result_eval (is_authorized, is_challenge, error);
nm_auth_chain_set_data (call->chain, call->permission, GUINT_TO_POINTER (call_result), NULL);
auth_call_complete (call);
}
-#endif
void
nm_auth_chain_add_call (NMAuthChain *self,
@@ -308,42 +284,21 @@ nm_auth_chain_add_call (NMAuthChain *self,
NMAuthManager *auth_manager = nm_auth_manager_get ();
g_return_if_fail (self);
- g_return_if_fail (permission && *permission);
g_return_if_fail (self->subject);
+ g_return_if_fail (!self->done);
+ g_return_if_fail (permission && *permission);
g_return_if_fail (nm_auth_subject_is_unix_process (self->subject) || nm_auth_subject_is_internal (self->subject));
- g_return_if_fail (!self->idle_id && !self->done);
call = g_slice_new0 (AuthCall);
call->chain = self;
call->permission = g_strdup (permission);
c_list_link_tail (&self->auth_call_lst_head, &call->auth_call_lst);
-
- if ( nm_auth_subject_is_internal (self->subject)
- || nm_auth_subject_get_unix_process_uid (self->subject) == 0
- || !nm_auth_manager_get_polkit_enabled (auth_manager)) {
- /* Root user or non-polkit always gets the permission */
- nm_auth_chain_set_data (self, permission, GUINT_TO_POINTER (NM_AUTH_CALL_RESULT_YES), NULL);
- call->call_idle_id = g_idle_add (auth_call_complete_idle_cb, call);
- } else {
- /* Non-root always gets authenticated when using polkit */
-#if WITH_POLKIT
- call->cancellable = g_cancellable_new ();
- nm_auth_manager_polkit_authority_check_authorization (auth_manager,
- self->subject,
- permission,
- allow_interaction,
- call->cancellable,
- pk_call_cb,
- call);
-#else
- if (!call->chain->error) {
- call->chain->error = g_error_new_literal (NM_MANAGER_ERROR,
- NM_MANAGER_ERROR_FAILED,
- "Polkit support is disabled at compile time");
- }
- call->call_idle_id = g_idle_add (auth_call_complete_idle_cb, call);
-#endif
- }
+ call->call_id = nm_auth_manager_check_authorization (auth_manager,
+ self->subject,
+ permission,
+ allow_interaction,
+ pk_call_cb,
+ call);
}
/*****************************************************************************/
@@ -386,7 +341,6 @@ nm_auth_chain_new_subject (NMAuthSubject *subject,
self = g_slice_new0 (NMAuthChain);
c_list_init (&self->auth_call_lst_head);
self->refcount = 1;
- self->data = g_hash_table_new_full (nm_pstr_hash, nm_pstr_equal, NULL, chain_data_free);
self->done_func = done_func;
self->user_data = user_data;
self->context = context ? g_object_ref (context) : NULL;
@@ -395,36 +349,36 @@ nm_auth_chain_new_subject (NMAuthSubject *subject,
}
/**
- * nm_auth_chain_unref:
+ * nm_auth_chain_destroy:
* @self: the auth-chain
*
- * Unrefs the auth-chain. By unrefing the auth-chain, you also cancel
+ * Destroys the auth-chain. By destroying the auth-chain, you also cancel
* the receipt of the done-callback. IOW, the callback will not be invoked.
*
- * The only exception is, if you call nm_auth_chain_unref() from inside
+ * The only exception is, if may call nm_auth_chain_destroy() from inside
* the callback. In this case, @self stays alive until the callback returns.
+ *
+ * Note that you might only destroy an auth-chain exactly once, and never
+ * after the callback was handled.
*/
void
-nm_auth_chain_unref (NMAuthChain *self)
+nm_auth_chain_destroy (NMAuthChain *self)
{
AuthCall *call;
g_return_if_fail (self);
- g_return_if_fail (self->refcount > 0);
+ g_return_if_fail (NM_IN_SET (self->refcount, 1, 2));
if (--self->refcount > 0)
return;
- nm_clear_g_source (&self->idle_id);
-
nm_clear_g_object (&self->subject);
nm_clear_g_object (&self->context);
while ((call = c_list_first_entry (&self->auth_call_lst_head, AuthCall, auth_call_lst)))
auth_call_free (call);
- g_clear_error (&self->error);
- nm_clear_pointer (&self->data, g_hash_table_destroy);
+ nm_clear_pointer (&self->data_hash, g_hash_table_destroy);
g_slice_free (NMAuthChain, self);
}
diff --git a/src/nm-auth-utils.h b/src/nm-auth-utils.h
index 335edb5b36..a641c49dfe 100644
--- a/src/nm-auth-utils.h
+++ b/src/nm-auth-utils.h
@@ -23,14 +23,9 @@
#include "nm-connection.h"
-typedef struct NMAuthChain NMAuthChain;
+#include "nm-auth-manager.h"
-typedef enum {
- NM_AUTH_CALL_RESULT_UNKNOWN,
- NM_AUTH_CALL_RESULT_YES,
- NM_AUTH_CALL_RESULT_AUTH,
- NM_AUTH_CALL_RESULT_NO,
-} NMAuthCallResult;
+typedef struct NMAuthChain NMAuthChain;
typedef void (*NMAuthChainResultFunc) (NMAuthChain *chain,
GError *error,
@@ -62,7 +57,7 @@ void nm_auth_chain_add_call (NMAuthChain *chain,
const char *permission,
gboolean allow_interaction);
-void nm_auth_chain_unref (NMAuthChain *chain);
+void nm_auth_chain_destroy (NMAuthChain *chain);
/* Caller must free returned error description */
gboolean nm_auth_is_subject_in_acl (NMConnection *connection,
diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c
index a9f9255be4..2a50f8f816 100644
--- a/src/nm-core-utils.c
+++ b/src/nm-core-utils.c
@@ -2234,7 +2234,13 @@ _log_connection_sort_names (LogConnectionSettingData *setting_data, GArray *sort
}
void
-nm_utils_log_connection_diff (NMConnection *connection, NMConnection *diff_base, guint32 level, guint64 domain, const char *name, const char *prefix)
+nm_utils_log_connection_diff (NMConnection *connection,
+ NMConnection *diff_base,
+ guint32 level,
+ guint64 domain,
+ const char *name,
+ const char *prefix,
+ const char *dbus_path)
{
GHashTable *connection_diff = NULL;
GArray *sorted_hashes;
@@ -2310,7 +2316,6 @@ nm_utils_log_connection_diff (NMConnection *connection, NMConnection *diff_base,
if (print_header) {
GError *err_verify = NULL;
- const char *path = nm_connection_get_path (connection);
const char *t1, *t2;
t1 = nm_connection_get_connection_type (connection);
@@ -2320,12 +2325,12 @@ nm_utils_log_connection_diff (NMConnection *connection, NMConnection *diff_base,
prefix, name,
connection, G_OBJECT_TYPE_NAME (connection), NM_PRINT_FMT_QUOTE_STRING (t1),
diff_base, G_OBJECT_TYPE_NAME (diff_base), NM_PRINT_FMT_QUOTE_STRING (t2),
- NM_PRINT_FMT_QUOTED (path, " [", path, "]", ""));
+ NM_PRINT_FMT_QUOTED (dbus_path, " [", dbus_path, "]", ""));
} else {
nm_log (level, domain, NULL, NULL, "%sconnection '%s' (%p/%s/%s%s%s):%s%s%s",
prefix, name,
connection, G_OBJECT_TYPE_NAME (connection), NM_PRINT_FMT_QUOTE_STRING (t1),
- NM_PRINT_FMT_QUOTED (path, " [", path, "]", ""));
+ NM_PRINT_FMT_QUOTED (dbus_path, " [", dbus_path, "]", ""));
}
print_header = FALSE;
@@ -3645,7 +3650,8 @@ nm_utils_setpgid (gpointer unused G_GNUC_UNUSED)
/**
* nm_utils_g_value_set_strv:
* @value: a #GValue, initialized to store a #G_TYPE_STRV
- * @strings: a #GPtrArray of strings
+ * @strings: a #GPtrArray of strings. %NULL values are not
+ * allowed.
*
* Converts @strings to a #GStrv and stores it in @value.
*/
@@ -3653,11 +3659,13 @@ void
nm_utils_g_value_set_strv (GValue *value, GPtrArray *strings)
{
char **strv;
- int i;
+ guint i;
strv = g_new (char *, strings->len + 1);
- for (i = 0; i < strings->len; i++)
+ for (i = 0; i < strings->len; i++) {
+ nm_assert (strings->pdata[i]);
strv[i] = g_strdup (strings->pdata[i]);
+ }
strv[i] = NULL;
g_value_take_boxed (value, strv);
diff --git a/src/nm-core-utils.h b/src/nm-core-utils.h
index 33773ab679..6b3682aa8f 100644
--- a/src/nm-core-utils.h
+++ b/src/nm-core-utils.h
@@ -231,7 +231,12 @@ const char *nm_utils_new_infiniband_name (char *name, const char *parent_name, i
int nm_utils_cmp_connection_by_autoconnect_priority (NMConnection *a, NMConnection *b);
-void nm_utils_log_connection_diff (NMConnection *connection, NMConnection *diff_base, guint32 level, guint64 domain, const char *name, const char *prefix);
+void nm_utils_log_connection_diff (NMConnection *connection,
+ NMConnection *diff_base,
+ guint32 level, guint64 domain,
+ const char *name,
+ const char *prefix,
+ const char *dbus_path);
gint64 nm_utils_get_monotonic_timestamp_ns (void);
gint64 nm_utils_get_monotonic_timestamp_us (void);
diff --git a/src/nm-dbus-object.c b/src/nm-dbus-object.c
index cd3a23509e..014f30f40c 100644
--- a/src/nm-dbus-object.c
+++ b/src/nm-dbus-object.c
@@ -37,9 +37,13 @@ nm_dbus_object_set_quitting (void)
/*****************************************************************************/
-NM_GOBJECT_PROPERTIES_DEFINE (NMDBusObject,
- PROP_PATH,
-);
+enum {
+ EXPORTED_CHANGED,
+
+ LAST_SIGNAL,
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
G_DEFINE_ABSTRACT_TYPE (NMDBusObject, nm_dbus_object, G_TYPE_OBJECT);
@@ -53,6 +57,12 @@ G_DEFINE_ABSTRACT_TYPE (NMDBusObject, nm_dbus_object, G_TYPE_OBJECT);
/*****************************************************************************/
+static void
+_emit_exported_changed (NMDBusObject *self)
+{
+ g_signal_emit (self, signals[EXPORTED_CHANGED], 0);
+}
+
static char *
_create_export_path (NMDBusObjectClass *klass)
{
@@ -107,6 +117,8 @@ nm_dbus_object_export (NMDBusObject *self)
g_return_val_if_fail (!self->internal.path, self->internal.path);
+ nm_assert (!self->internal.is_unexporting);
+
self->internal.path = _create_export_path (NM_DBUS_OBJECT_GET_CLASS (self));
self->internal.export_version_id = ++id_counter;
@@ -115,7 +127,7 @@ nm_dbus_object_export (NMDBusObject *self)
_nm_dbus_manager_obj_export (self);
- _notify (self, PROP_PATH);
+ _emit_exported_changed (self);
return self->internal.path;
}
@@ -135,12 +147,27 @@ nm_dbus_object_unexport (NMDBusObject *self)
_LOGT ("unexport: \"%s\"", self->internal.path);
+ /* note that we emit the signal *before* actually unexporting the object.
+ * The reason is, that listeners want to use this signal to know that
+ * the object goes away, and clear their D-Bus path to this object.
+ *
+ * But this must happen before we actually unregister the object, so
+ * that we first emit a D-Bus signal that other objects no longer
+ * reference this object, before finally unregistering the object itself.
+ *
+ * The inconvenient part is, that at this point nm_dbus_object_get_path()
+ * still returns the path. So, the callee needs to handle that. Possibly
+ * by using "nm_dbus_object_get_path_still_exported()". */
+ self->internal.is_unexporting = TRUE;
+
+ _emit_exported_changed (self);
+
_nm_dbus_manager_obj_unexport (self);
g_clear_pointer (&self->internal.path, g_free);
self->internal.export_version_id = 0;
- _notify (self, PROP_PATH);
+ self->internal.is_unexporting = FALSE;
}
/*****************************************************************************/
@@ -205,22 +232,6 @@ nm_dbus_object_emit_signal (NMDBusObject *self,
/*****************************************************************************/
static void
-get_property (GObject *object, guint prop_id,
- GValue *value, GParamSpec *pspec)
-{
- NMDBusObject *self = NM_DBUS_OBJECT (object);
-
- switch (prop_id) {
- case PROP_PATH:
- g_value_set_string (value, self->internal.path);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
dispatch_properties_changed (GObject *object,
guint n_pspecs,
GParamSpec **pspecs)
@@ -284,10 +295,11 @@ dispose (GObject *object)
g_warn_if_reached ();
nm_dbus_object_unexport (self);
}
- } else if (nm_clear_g_free (&self->internal.path)) {
+ } else if (self->internal.path) {
/* FIXME: do a proper, coordinate shutdown, so that no objects stay
* alive nor exported. */
- _notify (self, PROP_PATH);
+ _emit_exported_changed (self);
+ nm_clear_g_free (&self->internal.path);
}
G_OBJECT_CLASS (nm_dbus_object_parent_class)->dispose (object);
@@ -302,14 +314,13 @@ nm_dbus_object_class_init (NMDBusObjectClass *klass)
object_class->constructed = constructed;
object_class->dispose = dispose;
- object_class->get_property = get_property;
object_class->dispatch_properties_changed = dispatch_properties_changed;
- obj_properties[PROP_PATH] =
- g_param_spec_string (NM_DBUS_OBJECT_PATH, "", "",
- NULL,
- G_PARAM_READABLE |
- G_PARAM_STATIC_STRINGS);
-
- g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
+ signals[EXPORTED_CHANGED] =
+ g_signal_new (NM_DBUS_OBJECT_EXPORTED_CHANGED,
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
}
diff --git a/src/nm-dbus-object.h b/src/nm-dbus-object.h
index f6629289a5..947ea6c7dd 100644
--- a/src/nm-dbus-object.h
+++ b/src/nm-dbus-object.h
@@ -82,7 +82,7 @@ extern const NMDBusInterfaceInfoExtended nm_interface_info_device_statistics;
#define NM_IS_DBUS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DBUS_OBJECT))
#define NM_DBUS_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DBUS_OBJECT, NMDBusObjectClass))
-#define NM_DBUS_OBJECT_PATH "path"
+#define NM_DBUS_OBJECT_EXPORTED_CHANGED "exported-changed"
/* NMDBusObject and NMDBusManager cooperate strongly. Hence, there is an
* internal data structure attached to the NMDBusObject accessible to both of them. */
@@ -99,6 +99,7 @@ struct _NMDBusObjectInternal {
* unexported, or even re-exported afterwards. If that happens, we want
* to fail the request. For that, we keep track of a version id. */
guint64 export_version_id;
+ bool is_unexporting:1;
};
struct _NMDBusObject {
@@ -169,6 +170,18 @@ nm_dbus_object_is_exported (NMDBusObject *self)
return !!nm_dbus_object_get_path (self);
}
+static inline const char *
+nm_dbus_object_get_path_still_exported (NMDBusObject *self)
+{
+ g_return_val_if_fail (NM_IS_DBUS_OBJECT (self), NULL);
+
+ /* like nm_dbus_object_get_path(), however, while unexporting
+ * (exported-changed signal), returns %NULL instead of the path. */
+ return self->internal.is_unexporting
+ ? NULL
+ : self->internal.path;
+}
+
const char *nm_dbus_object_export (NMDBusObject *self);
void nm_dbus_object_unexport (NMDBusObject *self);
diff --git a/src/nm-dbus-utils.c b/src/nm-dbus-utils.c
index 2464ff79f7..5a57206c76 100644
--- a/src/nm-dbus-utils.c
+++ b/src/nm-dbus-utils.c
@@ -121,6 +121,20 @@ nm_dbus_utils_g_value_set_object_path (GValue *value, gpointer object)
}
void
+nm_dbus_utils_g_value_set_object_path_still_exported (GValue *value, gpointer object)
+{
+ const char *path;
+
+ g_return_if_fail (!object || NM_IS_DBUS_OBJECT (object));
+
+ if ( object
+ && (path = nm_dbus_object_get_path_still_exported (object)))
+ g_value_set_string (value, path);
+ else
+ g_value_set_string (value, "/");
+}
+
+void
nm_dbus_utils_g_value_set_object_path_from_hash (GValue *value,
GHashTable *hash /* has keys of NMDBusObject type. */,
gboolean expect_all_exported)
@@ -152,4 +166,143 @@ nm_dbus_utils_g_value_set_object_path_from_hash (GValue *value,
g_value_take_boxed (value, strv);
}
+const char **
+nm_dbus_utils_get_paths_for_clist (const CList *lst_head,
+ gssize lst_len,
+ guint member_offset,
+ gboolean expect_all_exported)
+{
+ const CList *iter;
+ const char **strv;
+ const char *path;
+ gsize i, n;
+
+ nm_assert (lst_head);
+
+ if (lst_len < 0)
+ n = c_list_length (lst_head);
+ else {
+ n = lst_len;
+ nm_assert (n == c_list_length (lst_head));
+ }
+
+ i = 0;
+ strv = g_new (const char *, n + 1);
+ c_list_for_each (iter, lst_head) {
+ NMDBusObject *obj = (NMDBusObject *) (((const char *) iter) - member_offset);
+
+ path = nm_dbus_object_get_path (obj);
+ if (!path) {
+ nm_assert (expect_all_exported);
+ continue;
+ }
+
+ nm_assert (i < n);
+ strv[i++] = path;
+ }
+ nm_assert (i <= n);
+ strv[i] = NULL;
+
+ return strv;
+}
+
/*****************************************************************************/
+
+void
+nm_dbus_track_obj_path_init (NMDBusTrackObjPath *track,
+ GObject *target,
+ const GParamSpec *pspec)
+{
+ nm_assert (track);
+ nm_assert (G_IS_OBJECT (target));
+ nm_assert (G_IS_PARAM_SPEC (pspec));
+
+ track->_obj = NULL;
+ track->_notify_target = target;
+ track->_notify_pspec = pspec;
+ track->_notify_signal_id = 0;
+ track->_visible = FALSE;
+}
+
+void
+nm_dbus_track_obj_path_deinit (NMDBusTrackObjPath *track)
+{
+ /* we allow deinit() to be called multiple times (e.g. from
+ * dispose(), which must be re-entrant). */
+ nm_assert (track);
+ nm_assert (!track->_notify_target || G_IS_OBJECT (track->_notify_target));
+
+ nm_clear_g_signal_handler (track->obj, &track->_notify_signal_id);
+ track->_notify_target = NULL;
+ track->_notify_pspec = NULL;
+ track->_visible = FALSE;
+ nm_clear_g_object (&track->_obj);
+}
+
+void
+nm_dbus_track_obj_path_notify (const NMDBusTrackObjPath *track)
+{
+ nm_assert (track);
+ nm_assert (G_IS_OBJECT (track->_notify_target));
+ nm_assert (G_IS_PARAM_SPEC (track->_notify_pspec));
+
+ g_object_notify_by_pspec (track->_notify_target,
+ (GParamSpec *) track->_notify_pspec);
+}
+
+const char *
+nm_dbus_track_obj_path_get (const NMDBusTrackObjPath *track)
+{
+ nm_assert (track);
+ nm_assert (G_IS_OBJECT (track->_notify_target));
+
+ return track->obj && track->visible
+ ? nm_dbus_object_get_path_still_exported (track->obj)
+ : NULL;
+}
+
+static void
+_track_obj_exported_changed (NMDBusObject *obj,
+ NMDBusTrackObjPath *track)
+{
+ nm_dbus_track_obj_path_notify (track);
+}
+
+void
+nm_dbus_track_obj_path_set (NMDBusTrackObjPath *track,
+ gpointer obj,
+ gboolean visible)
+{
+ gs_unref_object NMDBusObject *old_obj = NULL;
+ const char *old_path;
+
+ nm_assert (track);
+ nm_assert (G_IS_OBJECT (track->_notify_target));
+
+ g_return_if_fail (!obj || NM_IS_DBUS_OBJECT (obj));
+
+ if ( track->obj == obj
+ && track->visible == !!visible)
+ return;
+
+ old_path = nm_dbus_track_obj_path_get (track);
+
+ track->_visible = visible;
+
+ if (track->obj != obj) {
+ nm_clear_g_signal_handler (track->obj, &track->_notify_signal_id);
+
+ old_obj = track->obj;
+ track->_obj = nm_g_object_ref (obj);
+
+ if (obj) {
+ track->_notify_signal_id = g_signal_connect (obj,
+ NM_DBUS_OBJECT_EXPORTED_CHANGED,
+ G_CALLBACK (_track_obj_exported_changed),
+ track);
+ }
+ }
+
+ if (!nm_streq0 (old_path, nm_dbus_track_obj_path_get (track)))
+ nm_dbus_track_obj_path_notify (track);
+}
diff --git a/src/nm-dbus-utils.h b/src/nm-dbus-utils.h
index 1d9c92ec36..e7e930e938 100644
--- a/src/nm-dbus-utils.h
+++ b/src/nm-dbus-utils.h
@@ -164,10 +164,49 @@ GVariant *nm_dbus_utils_get_property (GObject *obj,
/*****************************************************************************/
+struct CList;
+
+const char **nm_dbus_utils_get_paths_for_clist (const struct CList *lst_head,
+ gssize lst_len,
+ guint member_offset,
+ gboolean expect_all_exported);
+
void nm_dbus_utils_g_value_set_object_path (GValue *value, gpointer object);
+void nm_dbus_utils_g_value_set_object_path_still_exported (GValue *value, gpointer object);
+
void nm_dbus_utils_g_value_set_object_path_from_hash (GValue *value,
GHashTable *hash,
gboolean expect_all_exported);
+/*****************************************************************************/
+
+typedef struct {
+ union {
+ gpointer const obj;
+ gpointer _obj;
+ };
+ GObject *_notify_target;
+ const GParamSpec *_notify_pspec;
+ gulong _notify_signal_id;
+ union {
+ const bool visible;
+ bool _visible;
+ };
+} NMDBusTrackObjPath;
+
+void nm_dbus_track_obj_path_init (NMDBusTrackObjPath *track,
+ GObject *target,
+ const GParamSpec *pspec);
+
+void nm_dbus_track_obj_path_deinit (NMDBusTrackObjPath *track);
+
+void nm_dbus_track_obj_path_notify (const NMDBusTrackObjPath *track);
+
+const char *nm_dbus_track_obj_path_get (const NMDBusTrackObjPath *track);
+
+void nm_dbus_track_obj_path_set (NMDBusTrackObjPath *track,
+ gpointer obj,
+ gboolean visible);
+
#endif /* __NM_DBUS_UTILS_H__ */
diff --git a/src/nm-dispatcher.c b/src/nm-dispatcher.c
index 2f88d468eb..235134c872 100644
--- a/src/nm-dispatcher.c
+++ b/src/nm-dispatcher.c
@@ -579,7 +579,7 @@ _dispatcher_call (NMDispatcherAction action,
const char *connection_path;
const char *filename;
- connection_path = nm_connection_get_path (NM_CONNECTION (settings_connection));
+ connection_path = nm_dbus_object_get_path (NM_DBUS_OBJECT (settings_connection));
if (connection_path) {
g_variant_builder_add (&connection_props, "{sv}",
NMD_CONNECTION_PROPS_PATH,
diff --git a/src/nm-manager.c b/src/nm-manager.c
index c8fad9dbb7..612f41562c 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -953,7 +953,7 @@ _reload_auth_cb (NMAuthChain *chain,
g_dbus_method_invocation_return_value (context, NULL);
out:
- nm_auth_chain_unref (chain);
+ nm_auth_chain_destroy (chain);
}
static void
@@ -2100,7 +2100,7 @@ device_auth_done_cb (NMAuthChain *chain,
nm_auth_chain_get_data (chain, "user-data"));
g_clear_error (&error);
- nm_auth_chain_unref (chain);
+ nm_auth_chain_destroy (chain);
}
static void
@@ -2392,7 +2392,7 @@ recheck_assume_connection (NMManager *self,
if (!active) {
_LOGW (LOGD_DEVICE, "assume: assumed connection %s failed to activate: %s",
- nm_connection_get_path (NM_CONNECTION (connection)),
+ nm_dbus_object_get_path (NM_DBUS_OBJECT (connection)),
error->message);
g_error_free (error);
@@ -4517,7 +4517,7 @@ activation_add_done (NMSettings *settings,
g_dbus_method_invocation_return_value (
context,
g_variant_new ("(oo)",
- nm_connection_get_path (NM_CONNECTION (new_connection)),
+ nm_dbus_object_get_path (NM_DBUS_OBJECT (new_connection)),
nm_dbus_object_get_path (NM_DBUS_OBJECT (active))));
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD_ACTIVATE,
nm_active_connection_get_settings_connection (active),
@@ -4796,7 +4796,7 @@ deactivate_net_auth_done_cb (NMAuthChain *chain,
else
g_dbus_method_invocation_return_value (context, NULL);
- nm_auth_chain_unref (chain);
+ nm_auth_chain_destroy (chain);
}
static void
@@ -5138,7 +5138,7 @@ sleep_auth_done_cb (NMAuthChain *chain,
g_dbus_method_invocation_return_value (context, NULL);
}
- nm_auth_chain_unref (chain);
+ nm_auth_chain_destroy (chain);
}
#endif
@@ -5276,7 +5276,7 @@ enable_net_done_cb (NMAuthChain *chain,
g_dbus_method_invocation_take_error (context, ret_error);
}
- nm_auth_chain_unref (chain);
+ nm_auth_chain_destroy (chain);
}
static void
@@ -5384,7 +5384,7 @@ get_permissions_done_cb (NMAuthChain *chain,
g_variant_new ("(a{ss})", &results));
}
- nm_auth_chain_unref (chain);
+ nm_auth_chain_destroy (chain);
}
static void
@@ -5606,7 +5606,7 @@ check_connectivity_auth_done_cb (NMAuthChain *chain,
}
out:
- nm_auth_chain_unref (chain);
+ nm_auth_chain_destroy (chain);
}
static void
@@ -6017,7 +6017,7 @@ out:
g_dbus_method_invocation_return_dbus_error (invocation, error_name, error_message);
else
g_dbus_method_invocation_return_value (invocation, NULL);
- nm_auth_chain_unref (chain);
+ nm_auth_chain_destroy (chain);
}
void
@@ -6152,7 +6152,7 @@ checkpoint_auth_done_cb (NMAuthChain *chain,
else
g_dbus_method_invocation_return_value (context, variant);
- nm_auth_chain_unref (chain);
+ nm_auth_chain_destroy (chain);
}
static void
@@ -6830,7 +6830,7 @@ dispose (GObject *object)
g_slice_free (PlatformLinkCbData, data);
}
- g_slist_free_full (priv->auth_chains, (GDestroyNotify) nm_auth_chain_unref);
+ g_slist_free_full (priv->auth_chains, (GDestroyNotify) nm_auth_chain_destroy);
priv->auth_chains = NULL;
nm_clear_g_source (&priv->devices_inited_id);
diff --git a/src/nm-policy.c b/src/nm-policy.c
index 61efee556b..9f845c1b0e 100644
--- a/src/nm-policy.c
+++ b/src/nm-policy.c
@@ -2321,10 +2321,9 @@ _deactivate_if_active (NMPolicy *self, NMSettingsConnection *connection)
nm_assert (NM_IS_SETTINGS_CONNECTION (connection));
nm_manager_for_each_active_connection (priv->manager, ac, tmp_list) {
- NMActiveConnectionState state = nm_active_connection_get_state (ac);
if ( nm_active_connection_get_settings_connection (ac) == connection
- && (state <= NM_ACTIVE_CONNECTION_STATE_ACTIVATED)) {
+ && (nm_active_connection_get_state (ac) <= NM_ACTIVE_CONNECTION_STATE_ACTIVATED)) {
if (!nm_manager_deactivate_connection (priv->manager,
ac,
NM_DEVICE_STATE_REASON_CONNECTION_REMOVED,
diff --git a/src/nm-types.h b/src/nm-types.h
index 0d5277e3af..e48a6e2a18 100644
--- a/src/nm-types.h
+++ b/src/nm-types.h
@@ -38,7 +38,6 @@ typedef struct _NMDBusManager NMDBusManager;
typedef struct _NMConfig NMConfig;
typedef struct _NMConfigData NMConfigData;
typedef struct _NMArpingManager NMArpingManager;
-typedef struct _NMConnectionProvider NMConnectionProvider;
typedef struct _NMConnectivity NMConnectivity;
typedef struct _NMDevice NMDevice;
typedef struct _NMDhcp4Config NMDhcp4Config;
diff --git a/src/settings/nm-agent-manager.c b/src/settings/nm-agent-manager.c
index b2cdc7d922..00aa3a0865 100644
--- a/src/settings/nm-agent-manager.c
+++ b/src/settings/nm-agent-manager.c
@@ -360,7 +360,7 @@ agent_register_permissions_done (NMAuthChain *chain,
request_add_agent (c_list_entry (iter, Request, lst_request), agent);
}
- nm_auth_chain_unref (chain);
+ nm_auth_chain_destroy (chain);
}
static NMSecretAgent *
@@ -539,7 +539,7 @@ request_free (Request *req)
g_object_unref (req->con.connection);
g_free (req->con.path);
if (req->con.chain)
- nm_auth_chain_unref (req->con.chain);
+ nm_auth_chain_destroy (req->con.chain);
if (req->request_type == REQUEST_TYPE_CON_GET) {
g_free (req->con.get.setting_name);
g_strfreev (req->con.get.hints);
@@ -810,7 +810,7 @@ request_remove_agent (Request *req, NMSecretAgent *agent)
case REQUEST_TYPE_CON_DEL:
if (req->con.chain) {
/* This cancels the pending authorization requests. */
- nm_auth_chain_unref (req->con.chain);
+ nm_auth_chain_destroy (req->con.chain);
req->con.chain = NULL;
}
break;
@@ -1047,7 +1047,7 @@ _con_get_request_start_validated (NMAuthChain *chain,
_con_get_request_start_proceed (req, req->con.current_has_modify);
}
- nm_auth_chain_unref (chain);
+ nm_auth_chain_destroy (chain);
}
static void
@@ -1541,7 +1541,7 @@ agent_permissions_changed_done (NMAuthChain *chain,
nm_secret_agent_add_permission (agent, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED, share_protected);
nm_secret_agent_add_permission (agent, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN, share_open);
- nm_auth_chain_unref (chain);
+ nm_auth_chain_destroy (chain);
}
static void
@@ -1616,7 +1616,7 @@ cancel_more:
goto cancel_more;
}
- g_slist_free_full (priv->chains, (GDestroyNotify) nm_auth_chain_unref);
+ g_slist_free_full (priv->chains, (GDestroyNotify) nm_auth_chain_destroy);
priv->chains = NULL;
if (priv->agents) {
diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c
index 713395420e..9e87a35ba3 100644
--- a/src/settings/nm-settings-connection.c
+++ b/src/settings/nm-settings-connection.c
@@ -32,6 +32,7 @@
#include "nm-config-data.h"
#include "nm-dbus-interface.h"
#include "nm-session-monitor.h"
+#include "nm-auth-manager.h"
#include "nm-auth-utils.h"
#include "nm-auth-subject.h"
#include "nm-agent-manager.h"
@@ -80,7 +81,8 @@ typedef struct _NMSettingsConnectionPrivate {
NMSettingsAutoconnectBlockedReason autoconnect_blocked_reason:4;
- GSList *pending_auths; /* List of pending authentication requests */
+ /* List of pending authentication requests */
+ CList auth_lst_head;
CList call_ids_lst_head; /* in-progress secrets requests */
@@ -581,7 +583,7 @@ _update_prepare (NMSettingsConnection *self,
if (!nm_connection_normalize (new_connection, NULL, NULL, error))
return FALSE;
- if ( nm_connection_get_path (NM_CONNECTION (self))
+ if ( nm_dbus_object_get_path (NM_DBUS_OBJECT (self))
&& g_strcmp0 (nm_settings_connection_get_uuid (self), nm_connection_get_uuid (new_connection)) != 0) {
/* Updating the UUID is not allowed once the path is exported. */
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
@@ -661,8 +663,10 @@ nm_settings_connection_update (NMSettingsConnection *self,
NM_SETTING_COMPARE_FLAG_EXACT)) {
gs_unref_object NMConnection *simple = NULL;
- if (log_diff_name)
- nm_utils_log_connection_diff (replace_connection, NM_CONNECTION (self), LOGL_DEBUG, LOGD_CORE, log_diff_name, "++ ");
+ if (log_diff_name) {
+ nm_utils_log_connection_diff (replace_connection, NM_CONNECTION (self), LOGL_DEBUG, LOGD_CORE, log_diff_name, "++ ",
+ nm_dbus_object_get_path (NM_DBUS_OBJECT (self)));
+ }
/* Make a copy of agent-owned secrets because they won't be present in
* the connection returned by plugins, as plugins return only what was
@@ -798,7 +802,7 @@ nm_settings_connection_delete (NMSettingsConnection *self,
for_agents = nm_simple_connection_new_clone (NM_CONNECTION (self));
nm_connection_clear_secrets (for_agents);
nm_agent_manager_delete_secrets (priv->agent_mgr,
- nm_connection_get_path (NM_CONNECTION (self)),
+ nm_dbus_object_get_path (NM_DBUS_OBJECT (self)),
for_agents);
g_object_unref (for_agents);
@@ -1295,7 +1299,7 @@ nm_settings_connection_get_secrets (NMSettingsConnection *self,
priv->last_secret_agent_version_id = nm_agent_manager_get_agent_version_id (priv->agent_mgr);
call_id_a = nm_agent_manager_get_secrets (priv->agent_mgr,
- nm_connection_get_path (NM_CONNECTION (self)),
+ nm_dbus_object_get_path (NM_DBUS_OBJECT (self)),
NM_CONNECTION (self),
subject,
existing_secrets,
@@ -1359,7 +1363,7 @@ nm_settings_connection_cancel_secrets (NMSettingsConnection *self,
_get_secrets_cancel (self, call_id, FALSE);
}
-/**** User authorization **************************************/
+/*****************************************************************************/
typedef void (*AuthCallback) (NMSettingsConnection *self,
GDBusMethodInvocation *context,
@@ -1367,46 +1371,61 @@ typedef void (*AuthCallback) (NMSettingsConnection *self,
GError *error,
gpointer data);
-static void
-pk_auth_cb (NMAuthChain *chain,
- GError *chain_error,
- GDBusMethodInvocation *context,
- gpointer user_data)
-{
- NMSettingsConnection *self = NM_SETTINGS_CONNECTION (user_data);
- NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
- GError *error = NULL;
- NMAuthCallResult result;
- const char *perm;
+typedef struct {
+ CList auth_lst;
+ NMAuthManagerCallId *call_id;
+ NMSettingsConnection *self;
AuthCallback callback;
gpointer callback_data;
+ GDBusMethodInvocation *invocation;
NMAuthSubject *subject;
+} AuthData;
+
+static void
+pk_auth_cb (NMAuthManager *auth_manager,
+ NMAuthManagerCallId *auth_call_id,
+ gboolean is_authorized,
+ gboolean is_challenge,
+ GError *auth_error,
+ gpointer user_data)
+{
+ AuthData *auth_data = user_data;
+ NMSettingsConnection *self;
+ gs_free_error GError *error = NULL;
+
+ nm_assert (auth_data);
+ nm_assert (NM_IS_SETTINGS_CONNECTION (auth_data->self));
+
+ self = auth_data->self;
- priv->pending_auths = g_slist_remove (priv->pending_auths, chain);
+ auth_data->call_id = NULL;
- perm = nm_auth_chain_get_data (chain, "perm");
- g_assert (perm);
- result = nm_auth_chain_get_result (chain, perm);
+ c_list_unlink (&auth_data->auth_lst);
- /* If our NMSettingsConnection is already gone, do nothing */
- if (chain_error) {
+ if (g_error_matches (auth_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ error = g_error_new (NM_SETTINGS_ERROR,
+ NM_SETTINGS_ERROR_FAILED,
+ "Error checking authorization: connection was deleted");
+ } else if (auth_error) {
error = g_error_new (NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_FAILED,
"Error checking authorization: %s",
- chain_error->message ? chain_error->message : "(unknown)");
- } else if (result != NM_AUTH_CALL_RESULT_YES) {
+ auth_error->message);
+ } else if (nm_auth_call_result_eval (is_authorized, is_challenge, auth_error) != NM_AUTH_CALL_RESULT_YES) {
error = g_error_new_literal (NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_PERMISSION_DENIED,
- "Insufficient privileges.");
+ "Insufficient privileges");
}
- callback = nm_auth_chain_get_data (chain, "callback");
- callback_data = nm_auth_chain_get_data (chain, "callback-data");
- subject = nm_auth_chain_get_data (chain, "subject");
- callback (self, context, subject, error, callback_data);
+ auth_data->callback (self,
+ auth_data->invocation,
+ auth_data->subject,
+ error,
+ auth_data->callback_data);
- g_clear_error (&error);
- nm_auth_chain_unref (chain);
+ g_object_unref (auth_data->invocation);
+ g_object_unref (auth_data->subject);
+ g_slice_free (AuthData, auth_data);
}
/**
@@ -1434,59 +1453,57 @@ _new_auth_subject (GDBusMethodInvocation *context, GError **error)
return subject;
}
+/* may either invoke callback synchronously or asynchronously. */
static void
auth_start (NMSettingsConnection *self,
- GDBusMethodInvocation *context,
+ GDBusMethodInvocation *invocation,
NMAuthSubject *subject,
const char *check_permission,
AuthCallback callback,
gpointer callback_data)
{
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
- NMAuthChain *chain;
- GError *error = NULL;
+ AuthData *auth_data;
char *error_desc = NULL;
- g_return_if_fail (context != NULL);
- g_return_if_fail (NM_IS_AUTH_SUBJECT (subject));
+ nm_assert (nm_dbus_object_is_exported (NM_DBUS_OBJECT (self)));
+ nm_assert (G_IS_DBUS_METHOD_INVOCATION (invocation));
+ nm_assert (NM_IS_AUTH_SUBJECT (subject));
/* Ensure the caller can view this connection */
if (!nm_auth_is_subject_in_acl (NM_CONNECTION (self),
subject,
&error_desc)) {
+ gs_free_error GError *error = NULL;
+
error = g_error_new_literal (NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_PERMISSION_DENIED,
error_desc);
g_free (error_desc);
- callback (self, context, subject, error, callback_data);
- g_clear_error (&error);
+ callback (self, invocation, subject, error, callback_data);
return;
}
if (!check_permission) {
/* Don't need polkit auth, automatic success */
- callback (self, context, subject, NULL, callback_data);
- return;
- }
-
- chain = nm_auth_chain_new_subject (subject, context, pk_auth_cb, self);
- if (!chain) {
- g_set_error_literal (&error,
- NM_SETTINGS_ERROR,
- NM_SETTINGS_ERROR_PERMISSION_DENIED,
- "Unable to authenticate the request.");
- callback (self, context, subject, error, callback_data);
- g_clear_error (&error);
+ callback (self, invocation, subject, NULL, callback_data);
return;
}
- priv->pending_auths = g_slist_append (priv->pending_auths, chain);
- nm_auth_chain_set_data (chain, "perm", (gpointer) check_permission, NULL);
- nm_auth_chain_set_data (chain, "callback", callback, NULL);
- nm_auth_chain_set_data (chain, "callback-data", callback_data, NULL);
- nm_auth_chain_set_data (chain, "subject", g_object_ref (subject), g_object_unref);
- nm_auth_chain_add_call (chain, check_permission, TRUE);
+ auth_data = g_slice_new (AuthData);
+ auth_data->self = self;
+ auth_data->callback = callback;
+ auth_data->callback_data = callback_data;
+ auth_data->invocation = g_object_ref (invocation);
+ auth_data->subject = g_object_ref (subject);
+ c_list_link_tail (&priv->auth_lst_head, &auth_data->auth_lst);
+ auth_data->call_id = nm_auth_manager_check_authorization (nm_auth_manager_get (),
+ subject,
+ check_permission,
+ TRUE,
+ pk_auth_cb,
+ auth_data);
}
/**** DBus method handlers ************************************/
@@ -1789,7 +1806,7 @@ update_auth_cb (NMSettingsConnection *self,
secrets_filter_cb,
GUINT_TO_POINTER (NM_SETTING_SECRET_FLAG_AGENT_OWNED));
nm_agent_manager_save_secrets (info->agent_mgr,
- nm_connection_get_path (NM_CONNECTION (self)),
+ nm_dbus_object_get_path (NM_DBUS_OBJECT (self)),
for_agent,
info->subject);
}
@@ -2065,7 +2082,7 @@ get_modify_permission_basic (NMSettingsConnection *self)
* request affects more than just the caller, require 'modify.system'.
*/
s_con = nm_connection_get_setting_connection (NM_CONNECTION (self));
- g_assert (s_con);
+ nm_assert (s_con);
if (nm_setting_connection_get_num_permissions (s_con) == 1)
return NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN;
@@ -2210,7 +2227,7 @@ dbus_clear_secrets_auth_cb (NMSettingsConnection *self,
/* Tell agents to remove secrets for this connection */
nm_agent_manager_delete_secrets (priv->agent_mgr,
- nm_connection_get_path (NM_CONNECTION (self)),
+ nm_dbus_object_get_path (NM_DBUS_OBJECT (self)),
NM_CONNECTION (self));
nm_settings_connection_update (self,
@@ -2274,11 +2291,15 @@ void
nm_settings_connection_signal_remove (NMSettingsConnection *self)
{
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
+ AuthData *auth_data;
if (priv->removed)
return;
priv->removed = TRUE;
+ while ((auth_data = c_list_first_entry (&priv->auth_lst_head, AuthData, auth_lst)))
+ nm_auth_manager_check_authorization_cancel (auth_data->call_id);
+
nm_dbus_object_emit_signal (NM_DBUS_OBJECT (self),
&interface_info_settings_connection,
&signal_info_removed,
@@ -2963,8 +2984,11 @@ nm_settings_connection_init (NMSettingsConnection *self)
priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_SETTINGS_CONNECTION, NMSettingsConnectionPrivate);
self->_priv = priv;
+ c_list_init (&self->_connections_lst);
+
priv->ready = TRUE;
c_list_init (&priv->call_ids_lst_head);
+ c_list_init (&priv->auth_lst_head);
priv->session_monitor = g_object_ref (nm_session_monitor_get ());
priv->session_changed_id = g_signal_connect (priv->session_monitor,
@@ -3000,6 +3024,9 @@ dispose (GObject *object)
_LOGD ("disposing");
+ nm_assert (c_list_is_empty (&self->_connections_lst));
+ nm_assert (c_list_is_empty (&priv->auth_lst_head));
+
/* Cancel in-progress secrets requests */
if (priv->agent_mgr) {
c_list_for_each_entry_safe (call_id, call_id_safe, &priv->call_ids_lst_head, call_ids_lst)
@@ -3017,10 +3044,6 @@ dispose (GObject *object)
g_clear_object (&priv->system_secrets);
g_clear_object (&priv->agent_secrets);
- /* Cancel PolicyKit requests */
- g_slist_free_full (priv->pending_auths, (GDestroyNotify) nm_auth_chain_unref);
- priv->pending_auths = NULL;
-
g_clear_pointer (&priv->seen_bssids, g_hash_table_destroy);
set_visible (self, FALSE);
diff --git a/src/settings/nm-settings-connection.h b/src/settings/nm-settings-connection.h
index f5b3179312..555a1d1285 100644
--- a/src/settings/nm-settings-connection.h
+++ b/src/settings/nm-settings-connection.h
@@ -104,6 +104,7 @@ struct _NMSettingsConnectionPrivate;
struct _NMSettingsConnection {
NMDBusObject parent;
struct _NMSettingsConnectionPrivate *_priv;
+ CList _connections_lst;
};
struct _NMSettingsConnectionClass {
diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c
index ade117de5d..20346929d6 100644
--- a/src/settings/nm-settings.c
+++ b/src/settings/nm-settings.c
@@ -62,6 +62,7 @@
#include "nm-utils.h"
#include "nm-core-internal.h"
+#include "nm-utils/nm-c-list.h"
#include "nm-dbus-object.h"
#include "devices/nm-device-ethernet.h"
#include "nm-settings-connection.h"
@@ -119,17 +120,21 @@ typedef struct {
GSList *auths;
GSList *plugins;
- gboolean connections_loaded;
- GHashTable *connections;
+
+ CList connections_lst_head;
+
NMSettingsConnection **connections_cached_list;
GSList *unmanaged_specs;
GSList *unrecognized_specs;
- gboolean started;
- gboolean startup_complete;
-
NMHostnameManager *hostname_manager;
+ guint connections_len;
+
+ bool started:1;
+ bool startup_complete:1;
+ bool connections_loaded:1;
+
} NMSettingsPrivate;
struct _NMSettings {
@@ -166,27 +171,29 @@ static void connection_ready_changed (NMSettingsConnection *conn,
GParamSpec *pspec,
gpointer user_data);
+static void default_wired_clear_tag (NMSettings *self,
+ NMDevice *device,
+ NMSettingsConnection *connection,
+ gboolean add_to_no_auto_default);
+
/*****************************************************************************/
static void
check_startup_complete (NMSettings *self)
{
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
- GHashTableIter iter;
NMSettingsConnection *conn;
if (priv->startup_complete)
return;
- g_hash_table_iter_init (&iter, priv->connections);
- while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &conn)) {
+ c_list_for_each_entry (conn, &priv->connections_lst_head, _connections_lst) {
if (!nm_settings_connection_get_ready (conn))
return;
}
/* the connection_ready_changed signal handler is no longer needed. */
- g_hash_table_iter_init (&iter, priv->connections);
- while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &conn))
+ c_list_for_each_entry (conn, &priv->connections_lst_head, _connections_lst)
g_signal_handlers_disconnect_by_func (conn, G_CALLBACK (connection_ready_changed), self);
priv->startup_complete = TRUE;
@@ -249,48 +256,25 @@ load_connections (NMSettings *self)
unrecognized_specs_changed (NULL, self);
}
-void
-nm_settings_for_each_connection (NMSettings *self,
- NMSettingsForEachFunc for_each_func,
- gpointer user_data)
-{
- NMSettingsPrivate *priv;
- GHashTableIter iter;
- gpointer data;
-
- g_return_if_fail (NM_IS_SETTINGS (self));
- g_return_if_fail (for_each_func != NULL);
-
- priv = NM_SETTINGS_GET_PRIVATE (self);
-
- g_hash_table_iter_init (&iter, priv->connections);
- while (g_hash_table_iter_next (&iter, NULL, &data))
- for_each_func (self, NM_SETTINGS_CONNECTION (data), user_data);
-}
-
static void
impl_settings_list_connections (NMDBusObject *obj,
const NMDBusInterfaceInfoExtended *interface_info,
const NMDBusMethodInfoExtended *method_info,
- GDBusConnection *connection,
+ GDBusConnection *dbus_connection,
const char *sender,
GDBusMethodInvocation *invocation,
GVariant *parameters)
{
NMSettings *self = NM_SETTINGS (obj);
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
- gs_unref_ptrarray GPtrArray *connections = NULL;
- GHashTableIter iter;
- gpointer key;
-
- connections = g_ptr_array_sized_new (g_hash_table_size (priv->connections) + 1);
- g_hash_table_iter_init (&iter, priv->connections);
- while (g_hash_table_iter_next (&iter, &key, NULL))
- g_ptr_array_add (connections, key);
- g_ptr_array_add (connections, NULL);
+ gs_free const char **strv = NULL;
+ strv = nm_dbus_utils_get_paths_for_clist (&priv->connections_lst_head,
+ priv->connections_len,
+ G_STRUCT_OFFSET (NMSettingsConnection, _connections_lst),
+ TRUE);
g_dbus_method_invocation_return_value (invocation,
- g_variant_new ("(^ao)", connections->pdata));
+ g_variant_new ("(^ao)", strv));
}
NMSettingsConnection *
@@ -298,16 +282,14 @@ nm_settings_get_connection_by_uuid (NMSettings *self, const char *uuid)
{
NMSettingsPrivate *priv;
NMSettingsConnection *candidate;
- GHashTableIter iter;
g_return_val_if_fail (NM_IS_SETTINGS (self), NULL);
g_return_val_if_fail (uuid != NULL, NULL);
priv = NM_SETTINGS_GET_PRIVATE (self);
- g_hash_table_iter_init (&iter, priv->connections);
- while (g_hash_table_iter_next (&iter, NULL, (gpointer) &candidate)) {
- if (g_strcmp0 (uuid, nm_settings_connection_get_uuid (candidate)) == 0)
+ c_list_for_each_entry (candidate, &priv->connections_lst_head, _connections_lst) {
+ if (nm_streq (uuid, nm_settings_connection_get_uuid (candidate)))
return candidate;
}
@@ -360,7 +342,7 @@ impl_settings_get_connection_by_uuid (NMDBusObject *obj,
g_dbus_method_invocation_return_value (invocation,
g_variant_new ("(o)",
- nm_connection_get_path (NM_CONNECTION (connection))));
+ nm_dbus_object_get_path (NM_DBUS_OBJECT (connection))));
return;
error:
@@ -368,19 +350,23 @@ error:
}
static void
-_clear_connections_cached_list (NMSettingsConnection ***p_connections_cached_list)
+_clear_connections_cached_list (NMSettingsPrivate *priv)
{
+ if (!priv->connections_cached_list)
+ return;
+
+ nm_assert (priv->connections_len == NM_PTRARRAY_LEN (priv->connections_cached_list));
+
#if NM_MORE_ASSERTS
/* set the pointer to a bogus value. This makes it more apparent
* if somebody has a reference to the cached list and still uses
* it. That is a bug, this code just tries to make it blow up
* more eagerly. */
- if (*p_connections_cached_list) {
- NMSettingsConnection **p = *p_connections_cached_list;
- memset (p, 0xdeaddead, sizeof (NMSettingsConnection *) * (NM_PTRARRAY_LEN (p) + 1));
- }
+ memset (priv->connections_cached_list,
+ 0xdeaddead,
+ sizeof (NMSettingsConnection *) * (priv->connections_len + 1));
#endif
- g_clear_pointer (p_connections_cached_list, g_free);
+ nm_clear_g_free (&priv->connections_cached_list);
}
/**
@@ -398,37 +384,33 @@ _clear_connections_cached_list (NMSettingsConnection ***p_connections_cached_lis
NMSettingsConnection *const*
nm_settings_get_connections (NMSettings *self, guint *out_len)
{
- GHashTableIter iter;
NMSettingsPrivate *priv;
- guint l, i;
NMSettingsConnection **v;
NMSettingsConnection *con;
+ guint i;
g_return_val_if_fail (NM_IS_SETTINGS (self), NULL);
priv = NM_SETTINGS_GET_PRIVATE (self);
- if (G_LIKELY (priv->connections_cached_list)) {
- NM_SET_OUT (out_len, g_hash_table_size (priv->connections));
- return priv->connections_cached_list;
- }
+ nm_assert (priv->connections_len == c_list_length (&priv->connections_lst_head));
- l = g_hash_table_size (priv->connections);
+ if (G_UNLIKELY (!priv->connections_cached_list)) {
+ v = g_new (NMSettingsConnection *, priv->connections_len + 1);
- v = g_new (NMSettingsConnection *, (gsize) l + 1);
+ i = 0;
+ c_list_for_each_entry (con, &priv->connections_lst_head, _connections_lst) {
+ nm_assert (i < priv->connections_len);
+ v[i++] = con;
+ }
+ nm_assert (i == priv->connections_len);
+ v[i] = NULL;
- i = 0;
- g_hash_table_iter_init (&iter, priv->connections);
- while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &con)) {
- nm_assert (i < l);
- v[i++] = con;
+ priv->connections_cached_list = v;
}
- nm_assert (i == l);
- v[i] = NULL;
- NM_SET_OUT (out_len, l);
- priv->connections_cached_list = v;
- return v;
+ NM_SET_OUT (out_len, priv->connections_len);
+ return priv->connections_cached_list;
}
/**
@@ -495,28 +477,41 @@ NMSettingsConnection *
nm_settings_get_connection_by_path (NMSettings *self, const char *path)
{
NMSettingsPrivate *priv;
+ NMSettingsConnection *connection;
g_return_val_if_fail (NM_IS_SETTINGS (self), NULL);
- g_return_val_if_fail (path != NULL, NULL);
+ g_return_val_if_fail (path, NULL);
priv = NM_SETTINGS_GET_PRIVATE (self);
- return (NMSettingsConnection *) g_hash_table_lookup (priv->connections, path);
+ connection = (NMSettingsConnection *) nm_dbus_manager_lookup_object (nm_dbus_object_get_manager (NM_DBUS_OBJECT (self)),
+ path);
+ if ( !connection
+ || !NM_IS_SETTINGS_CONNECTION (connection))
+ return NULL;
+
+ nm_assert (c_list_contains (&priv->connections_lst_head, &connection->_connections_lst));
+ return connection;
}
gboolean
nm_settings_has_connection (NMSettings *self, NMSettingsConnection *connection)
{
- NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
- GHashTableIter iter;
- gpointer data;
+ NMSettingsConnection *candidate = NULL;
+ const char *path;
- g_hash_table_iter_init (&iter, priv->connections);
- while (g_hash_table_iter_next (&iter, NULL, &data))
- if (data == connection)
- return TRUE;
+ g_return_val_if_fail (NM_IS_SETTINGS (self), FALSE);
+ g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION (connection), FALSE);
- return FALSE;
+ path = nm_dbus_object_get_path (NM_DBUS_OBJECT (connection));
+ if (path)
+ candidate = nm_settings_get_connection_by_path (self, path);
+
+ nm_assert (!candidate || candidate == connection);
+ nm_assert (!!candidate == nm_c_list_contains_entry (&NM_SETTINGS_GET_PRIVATE (self)->connections_lst_head,
+ connection,
+ _connections_lst));
+ return !!candidate;
}
const GSList *
@@ -844,28 +839,24 @@ connection_flags_changed (NMSettingsConnection *connection,
}
static void
-_emit_connection_removed (NMSettings *self,
- NMSettingsConnection *connection)
-{
- nm_dbus_object_emit_signal (NM_DBUS_OBJECT (self),
- &interface_info_settings,
- &signal_info_connection_removed,
- "(o)",
- nm_connection_get_path (NM_CONNECTION (connection)));
-
- g_signal_emit (self, signals[CONNECTION_REMOVED], 0, connection);
-}
-
-static void
connection_removed (NMSettingsConnection *connection, gpointer user_data)
{
NMSettings *self = NM_SETTINGS (user_data);
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
- const char *cpath = nm_connection_get_path (NM_CONNECTION (connection));
+ NMDevice *device;
- if (!g_hash_table_lookup (priv->connections, cpath))
- g_return_if_reached ();
- g_object_ref (connection);
+ g_return_if_fail (NM_IS_SETTINGS_CONNECTION (connection));
+ g_return_if_fail (!c_list_is_empty (&connection->_connections_lst));
+ nm_assert (c_list_contains (&priv->connections_lst_head, &connection->_connections_lst));
+
+ /* When the default wired connection is removed (either deleted or saved to
+ * a new persistent connection by a plugin), write the MAC address of the
+ * wired device to the config file and don't create a new default wired
+ * connection for that device again.
+ */
+ device = g_object_get_qdata (G_OBJECT (connection), _default_wired_device_quark ());
+ if (device)
+ default_wired_clear_tag (self, device, connection, TRUE);
/* Disconnect signal handlers, as plugins might still keep references
* to the connection (and thus the signal handlers would still be live)
@@ -877,22 +868,30 @@ connection_removed (NMSettingsConnection *connection, gpointer user_data)
g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (connection_flags_changed), self);
if (!priv->startup_complete)
g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (connection_ready_changed), self);
- g_object_unref (self);
/* Forget about the connection internally */
- g_hash_table_remove (priv->connections, (gpointer) cpath);
- _clear_connections_cached_list (&priv->connections_cached_list);
+ _clear_connections_cached_list (priv);
+ priv->connections_len--;
+ c_list_unlink (&connection->_connections_lst);
- _emit_connection_removed (self, connection);
+ if (priv->connections_loaded) {
+ _notify (self, PROP_CONNECTIONS);
- /* Re-emit for listeners like NMPolicy */
- _notify (self, PROP_CONNECTIONS);
- if (nm_dbus_object_is_exported (NM_DBUS_OBJECT (connection)))
- nm_dbus_object_unexport (NM_DBUS_OBJECT (connection));
+ nm_dbus_object_emit_signal (NM_DBUS_OBJECT (self),
+ &interface_info_settings,
+ &signal_info_connection_removed,
+ "(o)",
+ nm_dbus_object_get_path (NM_DBUS_OBJECT (connection)));
+ }
- check_startup_complete (self);
+ nm_dbus_object_unexport (NM_DBUS_OBJECT (connection));
- g_object_unref (connection);
+ if (priv->connections_loaded)
+ g_signal_emit (self, signals[CONNECTION_REMOVED], 0, connection);
+
+ g_object_ref (connection);
+
+ check_startup_complete (self);
}
#define NM_DBUS_SERVICE_OPENCONNECT "org.freedesktop.NetworkManager.openconnect"
@@ -940,19 +939,16 @@ claim_connection (NMSettings *self, NMSettingsConnection *connection)
{
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
GError *error = NULL;
- GHashTableIter iter;
- gpointer data;
const char *path;
NMSettingsConnection *existing;
g_return_if_fail (NM_IS_SETTINGS_CONNECTION (connection));
- g_return_if_fail (nm_connection_get_path (NM_CONNECTION (connection)) == NULL);
+ g_return_if_fail (!nm_dbus_object_is_exported (NM_DBUS_OBJECT (connection)));
- g_hash_table_iter_init (&iter, priv->connections);
- while (g_hash_table_iter_next (&iter, NULL, &data)) {
- /* prevent duplicates */
- if (data == connection)
- return;
+ /* prevent duplicates */
+ if (!c_list_is_empty (&connection->_connections_lst)) {
+ nm_assert (c_list_contains (&priv->connections_lst_head, &connection->_connections_lst));
+ return;
}
if (!nm_connection_normalize (NM_CONNECTION (connection), NULL, NULL, &error)) {
@@ -990,7 +986,6 @@ claim_connection (NMSettings *self, NMSettingsConnection *connection)
/* Evil openconnect migration hack */
openconnect_migrate_hack (NM_CONNECTION (connection));
- g_object_ref (self);
/* This one unexports the connection, it needs to run late to give the active
* connection a chance to deal with its reference to this settings connection. */
g_signal_connect_after (connection, NM_SETTINGS_CONNECTION_REMOVED,
@@ -1006,17 +1001,15 @@ claim_connection (NMSettings *self, NMSettingsConnection *connection)
self);
}
- /* Export the connection over D-Bus */
- g_warn_if_fail (nm_connection_get_path (NM_CONNECTION (connection)) == NULL);
- path = nm_dbus_object_export (NM_DBUS_OBJECT (connection));
- nm_connection_set_path (NM_CONNECTION (connection), path);
+ _clear_connections_cached_list (priv);
- g_hash_table_insert (priv->connections,
- (gpointer) nm_connection_get_path (NM_CONNECTION (connection)),
- g_object_ref (connection));
- _clear_connections_cached_list (&priv->connections_cached_list);
+ priv->connections_len++;
+ c_list_link_tail (&priv->connections_lst_head, &connection->_connections_lst);
- nm_utils_log_connection_diff (NM_CONNECTION (connection), NULL, LOGL_DEBUG, LOGD_CORE, "new connection", "++ ");
+ path = nm_dbus_object_export (NM_DBUS_OBJECT (connection));
+
+ nm_utils_log_connection_diff (NM_CONNECTION (connection), NULL, LOGL_DEBUG, LOGD_CORE, "new connection", "++ ",
+ path);
/* Only emit the individual connection-added signal after connections
* have been initially loaded.
@@ -1026,7 +1019,7 @@ claim_connection (NMSettings *self, NMSettingsConnection *connection)
&interface_info_settings,
&signal_info_new_connection,
"(o)",
- nm_connection_get_path (NM_CONNECTION (connection)));
+ nm_dbus_object_get_path (NM_DBUS_OBJECT (connection)));
g_signal_emit (self, signals[CONNECTION_ADDED], 0, connection);
_notify (self, PROP_CONNECTIONS);
@@ -1077,14 +1070,14 @@ nm_settings_add_connection (NMSettings *self,
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
GSList *iter;
NMSettingsConnection *added = NULL;
- GHashTableIter citer;
- NMConnection *candidate = NULL;
+ NMSettingsConnection *candidate = NULL;
+ const char *uuid;
+
+ uuid = nm_connection_get_uuid (connection);
/* Make sure a connection with this UUID doesn't already exist */
- g_hash_table_iter_init (&citer, priv->connections);
- while (g_hash_table_iter_next (&citer, NULL, (gpointer *) &candidate)) {
- if (g_strcmp0 (nm_connection_get_uuid (connection),
- nm_connection_get_uuid (candidate)) == 0) {
+ c_list_for_each_entry (candidate, &priv->connections_lst_head, _connections_lst) {
+ if (nm_streq0 (uuid, nm_connection_get_uuid (NM_CONNECTION (candidate)))) {
g_set_error_literal (error,
NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_UUID_EXISTS,
@@ -1152,7 +1145,7 @@ send_agent_owned_secrets (NMSettings *self,
secrets_filter_cb,
GUINT_TO_POINTER (NM_SETTING_SECRET_FLAG_AGENT_OWNED));
nm_agent_manager_save_secrets (priv->agent_mgr,
- nm_connection_get_path (NM_CONNECTION (connection)),
+ nm_dbus_object_get_path (NM_DBUS_OBJECT (connection)),
for_agent,
subject);
g_object_unref (for_agent);
@@ -1212,7 +1205,7 @@ pk_add_cb (NMAuthChain *chain,
send_agent_owned_secrets (self, added, subject);
g_clear_error (&error);
- nm_auth_chain_unref (chain);
+ nm_auth_chain_destroy (chain);
}
/* FIXME: remove if/when kernel supports adhoc wpa */
@@ -1365,9 +1358,9 @@ settings_add_connection_add_cb (NMSettings *self,
g_dbus_method_invocation_return_gerror (context, error);
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD, NULL, FALSE, NULL, subject, error->message);
} else {
- g_dbus_method_invocation_return_value (
- context,
- g_variant_new ("(o)", nm_connection_get_path (NM_CONNECTION (connection))));
+ g_dbus_method_invocation_return_value (context,
+ g_variant_new ("(o)",
+ nm_dbus_object_get_path (NM_DBUS_OBJECT (connection))));
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD, connection, TRUE, NULL,
subject, NULL);
}
@@ -1570,7 +1563,7 @@ pk_hostname_cb (NMAuthChain *chain,
else
g_dbus_method_invocation_return_value (context, NULL);
- nm_auth_chain_unref (chain);
+ nm_auth_chain_destroy (chain);
}
static void
@@ -1618,27 +1611,24 @@ static gboolean
have_connection_for_device (NMSettings *self, NMDevice *device)
{
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
- GHashTableIter iter;
- gpointer data;
NMSettingConnection *s_con;
NMSettingWired *s_wired;
const char *setting_hwaddr;
const char *perm_hw_addr;
+ NMSettingsConnection *connection;
g_return_val_if_fail (NM_IS_SETTINGS (self), FALSE);
perm_hw_addr = nm_device_get_permanent_hw_address (device);
/* Find a wired connection locked to the given MAC address, if any */
- g_hash_table_iter_init (&iter, priv->connections);
- while (g_hash_table_iter_next (&iter, NULL, &data)) {
- NMConnection *connection = NM_CONNECTION (data);
+ c_list_for_each_entry (connection, &priv->connections_lst_head, _connections_lst) {
const char *ctype, *iface;
- if (!nm_device_check_connection_compatible (device, connection))
+ if (!nm_device_check_connection_compatible (device, NM_CONNECTION (connection)))
continue;
- s_con = nm_connection_get_setting_connection (connection);
+ s_con = nm_connection_get_setting_connection (NM_CONNECTION (connection));
iface = nm_setting_connection_get_interface_name (s_con);
if (iface && strcmp (iface, nm_device_get_iface (device)) != 0)
@@ -1649,7 +1639,7 @@ have_connection_for_device (NMSettings *self, NMDevice *device)
&& strcmp (ctype, NM_SETTING_PPPOE_SETTING_NAME))
continue;
- s_wired = nm_connection_get_setting_wired (connection);
+ s_wired = nm_connection_get_setting_wired (NM_CONNECTION (connection));
if (!s_wired && !strcmp (ctype, NM_SETTING_PPPOE_SETTING_NAME)) {
/* No wired setting; therefore the PPPoE connection applies to any device */
@@ -1677,26 +1667,6 @@ have_connection_for_device (NMSettings *self, NMDevice *device)
return FALSE;
}
-static void default_wired_clear_tag (NMSettings *self,
- NMDevice *device,
- NMSettingsConnection *connection,
- gboolean add_to_no_auto_default);
-
-static void
-default_wired_connection_removed_cb (NMSettingsConnection *connection, NMSettings *self)
-{
- NMDevice *device;
-
- /* When the default wired connection is removed (either deleted or saved to
- * a new persistent connection by a plugin), write the MAC address of the
- * wired device to the config file and don't create a new default wired
- * connection for that device again.
- */
- device = g_object_get_qdata (G_OBJECT (connection), _default_wired_device_quark ());
- if (device)
- default_wired_clear_tag (self, device, connection, TRUE);
-}
-
static void
default_wired_connection_updated_by_user_cb (NMSettingsConnection *connection, gboolean by_user, NMSettings *self)
{
@@ -1729,7 +1699,6 @@ default_wired_clear_tag (NMSettings *self,
g_object_set_qdata (G_OBJECT (connection), _default_wired_device_quark (), NULL);
g_object_set_qdata (G_OBJECT (device), _default_wired_connection_quark (), NULL);
- g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (default_wired_connection_removed_cb), self);
g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (default_wired_connection_updated_by_user_cb), self);
if (add_to_no_auto_default)
@@ -1781,8 +1750,6 @@ device_realized (NMDevice *device, GParamSpec *pspec, NMSettings *self)
g_signal_connect (added, NM_SETTINGS_CONNECTION_UPDATED_INTERNAL,
G_CALLBACK (default_wired_connection_updated_by_user_cb), self);
- g_signal_connect (added, NM_SETTINGS_CONNECTION_REMOVED,
- G_CALLBACK (default_wired_connection_removed_cb), self);
_LOGI ("(%s): created default wired connection '%s'",
nm_device_get_iface (device),
@@ -1855,10 +1822,8 @@ nm_settings_start (NMSettings *self, GError **error)
/* Load the plugins; fail if a plugin is not found. */
plugins = nm_config_data_get_plugins (nm_config_get_data_orig (priv->config), TRUE);
- if (!load_plugins (self, (const char **) plugins, error)) {
- g_object_unref (self);
+ if (!load_plugins (self, (const char **) plugins, error))
return FALSE;
- }
load_connections (self);
check_startup_complete (self);
@@ -1883,18 +1848,19 @@ get_property (GObject *object, guint prop_id,
NMSettings *self = NM_SETTINGS (object);
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
const GSList *specs, *iter;
- GHashTableIter citer;
- GPtrArray *array;
- const char *path;
+ guint i;
+ char **strvs;
+ const char **strv;
switch (prop_id) {
case PROP_UNMANAGED_SPECS:
- array = g_ptr_array_new ();
specs = nm_settings_get_unmanaged_specs (self);
- for (iter = specs; iter; iter = g_slist_next (iter))
- g_ptr_array_add (array, g_strdup (iter->data));
- g_ptr_array_add (array, NULL);
- g_value_take_boxed (value, (char **) g_ptr_array_free (array, FALSE));
+ strvs = g_new (char *, g_slist_length ((GSList *) specs) + 1);
+ i = 0;
+ for (iter = specs; iter; iter = iter->next)
+ strvs[i++] = g_strdup (iter->data);
+ strvs[i] = NULL;
+ g_value_take_boxed (value, strvs);
break;
case PROP_HOSTNAME:
g_value_set_string (value,
@@ -1906,12 +1872,11 @@ get_property (GObject *object, guint prop_id,
g_value_set_boolean (value, !!get_plugin (self, NM_SETTINGS_PLUGIN_CAP_MODIFY_CONNECTIONS));
break;
case PROP_CONNECTIONS:
- array = g_ptr_array_sized_new (g_hash_table_size (priv->connections) + 1);
- g_hash_table_iter_init (&citer, priv->connections);
- while (g_hash_table_iter_next (&citer, (gpointer) &path, NULL))
- g_ptr_array_add (array, g_strdup (path));
- g_ptr_array_add (array, NULL);
- g_value_take_boxed (value, (char **) g_ptr_array_free (array, FALSE));
+ strv = nm_dbus_utils_get_paths_for_clist (&priv->connections_lst_head,
+ priv->connections_len,
+ G_STRUCT_OFFSET (NMSettingsConnection, _connections_lst),
+ TRUE);
+ g_value_take_boxed (value, nm_utils_strv_make_deep_copied (strv));
break;
case PROP_STARTUP_COMPLETE:
g_value_set_boolean (value, nm_settings_get_startup_complete (self));
@@ -1929,7 +1894,7 @@ nm_settings_init (NMSettings *self)
{
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
- priv->connections = g_hash_table_new_full (nm_str_hash, g_str_equal, NULL, g_object_unref);
+ c_list_init (&priv->connections_lst_head);
priv->agent_mgr = g_object_ref (nm_agent_manager_get ());
priv->config = g_object_ref (nm_config_get ());
@@ -1947,7 +1912,7 @@ dispose (GObject *object)
NMSettings *self = NM_SETTINGS (object);
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
- g_slist_free_full (priv->auths, (GDestroyNotify) nm_auth_chain_unref);
+ g_slist_free_full (priv->auths, (GDestroyNotify) nm_auth_chain_destroy);
priv->auths = NULL;
g_object_unref (priv->agent_mgr);
@@ -1968,8 +1933,9 @@ finalize (GObject *object)
NMSettings *self = NM_SETTINGS (object);
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
- g_hash_table_destroy (priv->connections);
- _clear_connections_cached_list (&priv->connections_cached_list);
+ _clear_connections_cached_list (priv);
+
+ nm_assert (c_list_is_empty (&priv->connections_lst_head));
g_slist_free_full (priv->unmanaged_specs, g_free);
g_slist_free_full (priv->unrecognized_specs, g_free);
diff --git a/src/settings/nm-settings.h b/src/settings/nm-settings.h
index 2a5a5053c5..7d56f7b43f 100644
--- a/src/settings/nm-settings.h
+++ b/src/settings/nm-settings.h
@@ -70,14 +70,6 @@ NMSettings *nm_settings_get (void);
NMSettings *nm_settings_new (void);
gboolean nm_settings_start (NMSettings *self, GError **error);
-typedef void (*NMSettingsForEachFunc) (NMSettings *settings,
- NMSettingsConnection *connection,
- gpointer user_data);
-
-void nm_settings_for_each_connection (NMSettings *settings,
- NMSettingsForEachFunc for_each_func,
- gpointer user_data);
-
typedef void (*NMSettingsAddCallback) (NMSettings *settings,
NMSettingsConnection *connection,
GError *error,
diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c
index e66ecfdccc..2d95b535a2 100644
--- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c
+++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c
@@ -326,21 +326,21 @@ update_connection (SettingsPluginIfcfg *self,
if (new_unmanaged || new_unrecognized) {
if (!old_unmanaged && !old_unrecognized) {
+ /* ref connection first, because we put it into priv->connections below.
+ * Emitting signal-removed might otherwise delete it. */
g_object_ref (connection_by_uuid);
+
/* Unexport the connection by telling the settings service it's
* been removed.
*/
nm_settings_connection_signal_remove (NM_SETTINGS_CONNECTION (connection_by_uuid));
- /* Remove the path so that claim_connection() doesn't complain later when
- * interface gets managed and connection is re-added. */
- nm_connection_set_path (NM_CONNECTION (connection_by_uuid), NULL);
/* signal_remove() will end up removing the connection from our hash,
* so add it back now.
*/
g_hash_table_insert (priv->connections,
g_strdup (nm_connection_get_uuid (NM_CONNECTION (connection_by_uuid))),
- connection_by_uuid);
+ connection_by_uuid/*<< took reference above*/);
}
} else {
if (old_unmanaged /* && !new_unmanaged */) {
@@ -372,7 +372,9 @@ update_connection (SettingsPluginIfcfg *self,
_LOGI ("add connection "NM_IFCFG_CONNECTION_LOG_FMT, NM_IFCFG_CONNECTION_LOG_ARG (connection_new));
else
_LOGI ("new connection "NM_IFCFG_CONNECTION_LOG_FMT, NM_IFCFG_CONNECTION_LOG_ARG (connection_new));
- g_hash_table_insert (priv->connections, g_strdup (uuid), connection_new);
+ g_hash_table_insert (priv->connections,
+ g_strdup (uuid),
+ connection_new /* take reference */);
g_signal_connect (connection_new, NM_SETTINGS_CONNECTION_REMOVED,
G_CALLBACK (connection_removed_cb),
@@ -748,7 +750,7 @@ impl_ifcfgrh_get_ifcfg_details (SettingsPluginIfcfg *plugin,
return;
}
- path = nm_connection_get_path (NM_CONNECTION (connection));
+ path = nm_dbus_object_get_path (NM_DBUS_OBJECT (connection));
if (!path) {
g_dbus_method_invocation_return_error (context,
NM_SETTINGS_ERROR,
diff --git a/src/tests/config/nm-test-device.c b/src/tests/config/nm-test-device.c
index 3ec866f5e5..4963158340 100644
--- a/src/tests/config/nm-test-device.c
+++ b/src/tests/config/nm-test-device.c
@@ -57,7 +57,7 @@ nm_test_device_init (NMTestDevice *self)
}
/* We jump over NMDevice's construct/destruct methods, which require NMPlatform
- * and NMConnectionProvider to be initialized.
+ * and NMSettings to be initialized.
*/
static void
constructed (GObject *object)
diff --git a/src/tests/test-general.c b/src/tests/test-general.c
index 632f2c33cc..38eaf25e91 100644
--- a/src/tests/test-general.c
+++ b/src/tests/test-general.c
@@ -232,13 +232,13 @@ test_nm_utils_log_connection_diff (void)
connection = nm_simple_connection_new ();
nm_connection_add_setting (connection, nm_setting_connection_new ());
- nm_utils_log_connection_diff (connection, NULL, LOGL_DEBUG, LOGD_CORE, "test1", ">>> ");
+ nm_utils_log_connection_diff (connection, NULL, LOGL_DEBUG, LOGD_CORE, "test1", ">>> ", NULL);
nm_connection_add_setting (connection, nm_setting_wired_new ());
- nm_utils_log_connection_diff (connection, NULL, LOGL_DEBUG, LOGD_CORE, "test2", ">>> ");
+ nm_utils_log_connection_diff (connection, NULL, LOGL_DEBUG, LOGD_CORE, "test2", ">>> ", NULL);
connection2 = nm_simple_connection_new_clone (connection);
- nm_utils_log_connection_diff (connection, connection2, LOGL_DEBUG, LOGD_CORE, "test3", ">>> ");
+ nm_utils_log_connection_diff (connection, connection2, LOGL_DEBUG, LOGD_CORE, "test3", ">>> ", NULL);
g_object_set (nm_connection_get_setting_connection (connection),
NM_SETTING_CONNECTION_ID, "id",
@@ -248,24 +248,24 @@ test_nm_utils_log_connection_diff (void)
NM_SETTING_CONNECTION_ID, "id2",
NM_SETTING_CONNECTION_MASTER, "master2",
NULL);
- nm_utils_log_connection_diff (connection, connection2, LOGL_DEBUG, LOGD_CORE, "test4", ">>> ");
+ nm_utils_log_connection_diff (connection, connection2, LOGL_DEBUG, LOGD_CORE, "test4", ">>> ", NULL);
nm_connection_add_setting (connection, nm_setting_802_1x_new ());
- nm_utils_log_connection_diff (connection, connection2, LOGL_DEBUG, LOGD_CORE, "test5", ">>> ");
+ nm_utils_log_connection_diff (connection, connection2, LOGL_DEBUG, LOGD_CORE, "test5", ">>> ", NULL);
g_object_set (nm_connection_get_setting_802_1x (connection),
NM_SETTING_802_1X_PASSWORD, "id2",
NM_SETTING_802_1X_PASSWORD_FLAGS, NM_SETTING_SECRET_FLAG_NOT_SAVED,
NULL);
- nm_utils_log_connection_diff (connection, NULL, LOGL_DEBUG, LOGD_CORE, "test6", ">>> ");
- nm_utils_log_connection_diff (connection, connection2, LOGL_DEBUG, LOGD_CORE, "test7", ">>> ");
- nm_utils_log_connection_diff (connection2, connection, LOGL_DEBUG, LOGD_CORE, "test8", ">>> ");
+ nm_utils_log_connection_diff (connection, NULL, LOGL_DEBUG, LOGD_CORE, "test6", ">>> ", NULL);
+ nm_utils_log_connection_diff (connection, connection2, LOGL_DEBUG, LOGD_CORE, "test7", ">>> ", NULL);
+ nm_utils_log_connection_diff (connection2, connection, LOGL_DEBUG, LOGD_CORE, "test8", ">>> ", NULL);
g_clear_object (&connection);
g_clear_object (&connection2);
connection = nmtst_create_minimal_connection ("id-vpn-1", NULL, NM_SETTING_VPN_SETTING_NAME, NULL);
- nm_utils_log_connection_diff (connection, NULL, LOGL_DEBUG, LOGD_CORE, "test-vpn-1", ">>> ");
+ nm_utils_log_connection_diff (connection, NULL, LOGL_DEBUG, LOGD_CORE, "test-vpn-1", ">>> ", NULL);
g_clear_object (&connection);
}