iwd: Be extra careful not to interrupt assumed activation

The IWD backend would originally use .Disconnect() on IWD dbus "Station"
objects to make sure IWD is out of autoconnect or that it isn't
connecting to a network that NM didn't command.  Later the default became
to let IWD run autoconnect so now most of the time the backend just
mirrors IWD's state to NMDevice's state.

Now sometimes when NMDevice still seems to have an active connection but
IWD has gone through one or more state changes (which we may see after a
delay due to D-Bus) and is now connected to or connecting to a different
network, NMDevice would first have to go through .deactivate to mirror
the fact the original connection is no longer active, and it'd use
.Disconnect() which could break the new connection, so check for this
situation.
This commit is contained in:
Andrew Zaborowski
2022-08-12 12:32:16 +02:00
committed by Thomas Haller
parent cbc2354854
commit e384ab74c2

View File

@@ -70,6 +70,7 @@ typedef struct {
bool secrets_failed : 1;
bool networks_requested : 1;
bool networks_changed : 1;
bool assuming : 1;
gint64 last_scan;
uint32_t ap_id;
guint32 rate;
@@ -581,6 +582,10 @@ deactivate(NMDevice *device)
if (!priv->dbus_obj)
return;
/* Don't cause IWD to break the connection being assumed */
if (priv->assuming)
return;
if (priv->dbus_station_proxy) {
gs_unref_variant GVariant *value =
g_dbus_proxy_get_cached_property(priv->dbus_station_proxy, "State");
@@ -2719,12 +2724,20 @@ state_changed(NMDeviceIwd *self, const char *new_state)
"IWD is connecting to the wrong AP, %s activation",
switch_ap ? "replacing" : "aborting");
cleanup_association_attempt(self, !switch_ap);
nm_device_state_changed(device,
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT);
if (switch_ap)
assume_connection(self, ap);
if (!switch_ap) {
nm_device_state_changed(device,
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT);
return;
}
priv->assuming = TRUE; /* Don't send Station.Disconnect() */
nm_device_state_changed(device,
NM_DEVICE_STATE_DISCONNECTED,
NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT);
priv->assuming = FALSE;
assume_connection(self, ap);
return;
}