aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Prestwood <prestwoj@gmail.com>2024-01-05 06:47:49 -0800
committerDenis Kenzior <denkenz@gmail.com>2024-01-08 22:04:53 -0600
commit7080a4453e000db4e7f4566c0a0e843247d5fc6e (patch)
tree2ff414fd77cf6a4258c00caeaf55399ad70fa75a
parent8f7443b0b31b5139a7f7f23bb27f0cdaa855b2f6 (diff)
station: add handling for new NETCONFIG state
There was an unhandled corner case if netconfig was running and multiple roam conditions happened in sequence, all before netconfig had completed. A single roam before netconfig was already handled (23f0f5717c) but this did not take into account any additional roam conditions. If IWD is in this state, having started netconfig, then roamed, and again restarted netconfig it is still in a roaming state which will prevent any further roams. IWD will remain "stuck" on the current BSS until netconfig completes or gets disconnected. In addition the general state logic is wrong here. If IWD roams prior to netconfig it should stay in a connecting state (from the perspective of DBus). To fix this a new internal station state was added (no changes to the DBus API) to distinguish between a purely WiFi connecting state (STATION_STATE_CONNECTING/AUTO) and netconfig (STATION_STATE_NETCONFIG). This allows IWD roam as needed if netconfig is still running. Also, some special handling was added so the station state property remains in a "connected" state until netconfig actually completes, regardless of roams. For some background this scenario happens if the DHCP server goes down for an extended period, e.g. if its being upgraded/serviced.
-rw-r--r--src/station.c36
1 files changed, 27 insertions, 9 deletions
diff --git a/src/station.c b/src/station.c
index 68cac9454..a6442d3ec 100644
--- a/src/station.c
+++ b/src/station.c
@@ -1770,6 +1770,7 @@ static void station_reset_connection_state(struct station *station)
if (station->state == STATION_STATE_CONNECTED ||
station->state == STATION_STATE_CONNECTING ||
station->state == STATION_STATE_CONNECTING_AUTO ||
+ station->state == STATION_STATE_NETCONFIG ||
station_is_roaming(station))
network_disconnected(network);
}
@@ -2045,8 +2046,7 @@ static void station_netconfig_event_handler(enum netconfig_event event,
dbus_pending_reply(&station->connect_pending, reply);
}
- if (L_IN_SET(station->state, STATION_STATE_CONNECTING,
- STATION_STATE_CONNECTING_AUTO))
+ if (station->state == STATION_STATE_NETCONFIG)
network_connect_failed(station->connected_network,
false);
@@ -2072,9 +2072,14 @@ static bool netconfig_after_roam(struct station *station)
network_get_settings(network)))
return false;
- return netconfig_configure(station->netconfig,
+ if (!netconfig_configure(station->netconfig,
station_netconfig_event_handler,
- station);
+ station))
+ return false;
+
+ station_enter_state(station, STATION_STATE_NETCONFIG);
+
+ return true;
}
static void station_roamed(struct station *station)
@@ -3253,6 +3258,8 @@ static void station_connect_ok(struct station *station)
station_netconfig_event_handler,
station)))
return;
+
+ station_enter_state(station, STATION_STATE_NETCONFIG);
} else
station_enter_state(station, STATION_STATE_CONNECTED);
}
@@ -4064,8 +4071,10 @@ static struct l_dbus_message *station_dbus_scan(struct l_dbus *dbus,
if (station->dbus_scan_id)
return dbus_error_busy(message);
- if (station->state == STATION_STATE_CONNECTING ||
- station->state == STATION_STATE_CONNECTING_AUTO)
+ if (L_IN_SET(station->state, STATION_STATE_CONNECTING,
+ STATION_STATE_CONNECTING_AUTO,
+ STATION_STATE_NETCONFIG) ||
+ station_is_roaming(station))
return dbus_error_busy(message);
station->dbus_scan_subset_idx = 0;
@@ -4288,7 +4297,14 @@ static bool station_property_get_state(struct l_dbus *dbus,
case STATION_STATE_ROAMING:
case STATION_STATE_FT_ROAMING:
case STATION_STATE_FW_ROAMING:
- statestr = "roaming";
+ /*
+ * Stay in a connecting state if roaming before netconfig
+ * has finished
+ */
+ if (station->netconfig_after_roam)
+ statestr = "connecting";
+ else
+ statestr = "roaming";
break;
}
@@ -5022,8 +5038,10 @@ static struct l_dbus_message *station_debug_scan(struct l_dbus *dbus,
if (station->dbus_scan_id)
return dbus_error_busy(message);
- if (station->state == STATION_STATE_CONNECTING ||
- station->state == STATION_STATE_CONNECTING_AUTO)
+ if (L_IN_SET(station->state, STATION_STATE_CONNECTING,
+ STATION_STATE_CONNECTING_AUTO,
+ STATION_STATE_NETCONFIG) ||
+ station_is_roaming(station))
return dbus_error_busy(message);
if (!l_dbus_message_get_arguments(message, "aq", &iter))