From: Pasi Sjöholm <[email protected]>

While wifi->state is G_SUPPLICANT_STATE_COMPLETED and gets changed into
G_SUPPLICANT_STATE_4WAY_HANDSHAKE the connection is most probably roaming.

However if for some reason the wifi->state changes into
G_SUPPLICANT_STATE_DISCONNECTED after being G_SUPPLICANT_STATE_4WAY_HANDSHAKE
the handle_4way_handshake_failure() is called from interface_state() it is
required to check wifi->connected and force disconnect if true.

If not the actual disconnection will be skipped unless
retries > FAVORITE_MAXIMUM_RETRIES and wifi->connected will be set as false.
Later on this will cause state-machine deadlock between network.c and wifi.c
as network.c will still think that the network is connected and after wifi.c
thinks it's not.

In short: wifi->state will change into G_SUPPLICANT_STATE_SCANNING->
G_SUPPLICANT_STATE_ASSOCIATING and connman_network_set_associating(network, 
true);
gets called. Now the network.c is in both associating and connected. Finally 
when
wifi->state goes through  G_SUPPLICANT_STATE_4WAY_HANDSHAKE ->
G_SUPPLICANT_STATE_COMPLETED the connman_network_set_connected(network, true);
will be called but it will never call set_connected as it's already connected 
and
service state will stay as "associating" until disconnected.
---
 plugins/wifi.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/plugins/wifi.c b/plugins/wifi.c
index 42dd407..2c4c2d6 100644
--- a/plugins/wifi.c
+++ b/plugins/wifi.c
@@ -2262,6 +2262,9 @@ static bool 
handle_4way_handshake_failure(GSupplicantInterface *interface,
        if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
                return false;
 
+       if (wifi->connected)
+               return false;
+
        service = connman_service_lookup_from_network(network);
        if (!service)
                return false;
-- 
2.1.0

_______________________________________________
connman mailing list
[email protected]
https://lists.connman.net/mailman/listinfo/connman

Reply via email to