Commit 979b8920 authored by Dan Winship's avatar Dan Winship

core: move virtual device autoconnect tracking bits out of NMManager

Virtual devices may be created and destroyed, but we need to keep
their autoconnect state across that. Previously this was handled by
NMManager, but it really belongs with the other autoconnect tracking
in NMPolicy and NMSettingsConnection.

This also fixes a bug where NMPolicy would sometimes decide to
autoactivate a virtual device connection which NMManager would then
have to cancel.
parent 971167e2
......@@ -4610,13 +4610,6 @@ disconnect_cb (NMDevice *device,
} else {
priv->autoconnect = FALSE;
/* Software devices are removed when manually disconnected and thus
* we need to track the autoconnect flag outside the device.
*/
nm_manager_prevent_device_auto_connect (nm_manager_get (),
nm_device_get_ip_iface (device),
TRUE);
nm_device_state_changed (device,
NM_DEVICE_STATE_DEACTIVATING,
NM_DEVICE_STATE_REASON_USER_REQUESTED);
......
......@@ -249,9 +249,6 @@ typedef struct {
guint timestamp_update_id;
/* Track auto-activation for software devices */
GHashTable *noauto_sw_devices;
gboolean startup;
gboolean disposed;
} NMManagerPrivate;
......@@ -1214,21 +1211,11 @@ system_create_virtual_devices (NMManager *self)
connections = nm_settings_get_connections (priv->settings);
for (iter = connections; iter; iter = g_slist_next (iter)) {
NMConnection *connection = iter->data;
NMSettingConnection *s_con = nm_connection_get_setting_connection (connection);
g_assert (s_con);
if (connection_needs_virtual_device (connection)) {
char *iface = get_virtual_iface_name (self, connection, NULL);
/* We only create a virtual interface if the connection can autoconnect
* and the interface was not manually disconnected before.
*/
if ( nm_setting_connection_get_autoconnect (s_con)
&& iface
&& nm_manager_can_device_auto_connect (self, iface))
system_create_virtual_device (self, connection);
g_free (iface);
}
/* We only create a virtual interface if the connection can autoconnect */
if ( connection_needs_virtual_device (connection)
&& nm_settings_connection_can_autoconnect (NM_SETTINGS_CONNECTION (connection)))
system_create_virtual_device (self, connection);
}
g_slist_free (connections);
}
......@@ -2720,31 +2707,8 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError *
device = nm_active_connection_get_device (active);
if (!device) {
char *iface;
g_assert (connection_needs_virtual_device (connection));
iface = get_virtual_iface_name (self, connection, NULL);
g_assert (iface);
/* Create the software device. Only exception is when:
* - this is an auto-activation *and* the device denies auto-activation
* at this time (the device was manually disconnected/deleted before)
*/
if (!nm_manager_can_device_auto_connect (self, iface)) {
if (nm_active_connection_get_user_requested (active)) {
/* Manual activation - allow device auto-activation again */
nm_manager_prevent_device_auto_connect (self, iface, FALSE);
} else {
g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_AUTOCONNECT_NOT_ALLOWED,
"Automatic activation of '%s' not allowed for connection '%s'",
iface, nm_connection_get_id (connection));
g_free (iface);
return FALSE;
}
}
g_free (iface);
device = system_create_virtual_device (self, connection);
if (!device) {
g_set_error_literal (error,
......@@ -3617,33 +3581,6 @@ done:
g_clear_error (&error);
}
/*
* Track (software) devices that cannot auto activate.
* It is needed especially for software devices, that can be removed and added
* again. So we can't simply use a flag inside the device.
*/
void
nm_manager_prevent_device_auto_connect (NMManager *manager, const char *ifname, gboolean prevent)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
if (prevent)
g_hash_table_add (priv->noauto_sw_devices, g_strdup (ifname));
else
g_hash_table_remove (priv->noauto_sw_devices, ifname);
}
gboolean
nm_manager_can_device_auto_connect (NMManager *manager, const char *ifname)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
if (!ifname)
return FALSE;
return !g_hash_table_contains (priv->noauto_sw_devices, ifname);
}
static void
do_sleep_wake (NMManager *self)
{
......@@ -4719,8 +4656,6 @@ dispose (GObject *object)
g_object_unref (priv->fw_monitor);
}
g_hash_table_unref (priv->noauto_sw_devices);
g_slist_free (priv->factories);
if (priv->timestamp_update_id) {
......@@ -5085,9 +5020,6 @@ nm_manager_init (NMManager *manager)
KERNEL_FIRMWARE_DIR);
}
/* Hash table storing software devices that should not auto activate */
priv->noauto_sw_devices = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
load_device_factories (manager);
/* Update timestamps in active connections */
......
......@@ -128,12 +128,6 @@ gboolean nm_manager_deactivate_connection (NMManager *manager,
NMDeviceStateReason reason,
GError **error);
void nm_manager_prevent_device_auto_connect (NMManager *manager,
const char *ifname,
gboolean prevent);
gboolean nm_manager_can_device_auto_connect (NMManager *manager,
const char *ifname);
/* State handling */
NMState nm_manager_get_state (NMManager *manager);
......
......@@ -1160,6 +1160,28 @@ reset_autoconnect_for_failed_secrets (NMPolicy *policy)
g_slist_free (connections);
}
static void
block_autoconnect_for_device (NMPolicy *policy, NMDevice *device)
{
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy);
GSList *connections, *iter;
/* NMDevice keeps its own autoconnect-able-ness state; we only need to
* explicitly block connections for software devices, where the NMDevice
* might be destroyed and recreated later.
*/
if (!nm_device_is_software (device))
return;
connections = nm_settings_get_connections (priv->settings);
for (iter = connections; iter; iter = g_slist_next (iter)) {
if (nm_device_check_connection_compatible (device, iter->data, NULL)) {
nm_settings_connection_set_autoconnect_blocked_reason (NM_SETTINGS_CONNECTION (iter->data),
NM_DEVICE_STATE_REASON_USER_REQUESTED);
}
}
}
static void
sleeping_changed (NMManager *manager, GParamSpec *pspec, gpointer user_data)
{
......@@ -1432,8 +1454,15 @@ device_state_changed (NMDevice *device,
update_routing_and_dns (policy, FALSE);
break;
case NM_DEVICE_STATE_DEACTIVATING:
if (reason == NM_DEVICE_STATE_REASON_USER_REQUESTED)
nm_settings_connection_set_autoconnect_blocked_reason (connection, NM_DEVICE_STATE_REASON_USER_REQUESTED);
if (reason == NM_DEVICE_STATE_REASON_USER_REQUESTED) {
if (!nm_device_get_autoconnect (device)) {
/* The device was disconnected; block all connections on it */
block_autoconnect_for_device (policy, device);
} else {
/* The connection was deactivated, so block just this connection */
nm_settings_connection_set_autoconnect_blocked_reason (connection, NM_DEVICE_STATE_REASON_USER_REQUESTED);
}
}
break;
case NM_DEVICE_STATE_DISCONNECTED:
/* Reset retry counts for a device's connections when carrier on; if cable
......
......@@ -1955,6 +1955,7 @@ gboolean
nm_settings_connection_can_autoconnect (NMSettingsConnection *connection)
{
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (connection);
NMSettingConnection *s_con;
const char *permission;
if ( !priv->visible
......@@ -1962,6 +1963,10 @@ nm_settings_connection_can_autoconnect (NMSettingsConnection *connection)
|| priv->autoconnect_blocked_reason != NM_DEVICE_STATE_REASON_NONE)
return FALSE;
s_con = nm_connection_get_setting_connection (NM_CONNECTION (connection));
if (!nm_setting_connection_get_autoconnect (s_con))
return FALSE;
permission = nm_utils_get_shared_wifi_permission (NM_CONNECTION (connection));
if (permission) {
if (nm_settings_connection_check_permission (connection, permission) == FALSE)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment