public inbox for iwd@lists.linux.dev
 help / color / mirror / Atom feed
* [PATCH v2 00/11] Refactor to unify connect failure code path
@ 2024-07-18 11:45 James Prestwood
  2024-07-18 11:45 ` [PATCH v2 01/11] station: print unknown channel number in neighbor report James Prestwood
                   ` (11 more replies)
  0 siblings, 12 replies; 13+ messages in thread
From: James Prestwood @ 2024-07-18 11:45 UTC (permalink / raw)
  To: iwd; +Cc: James Prestwood

v2:
 * Combined two earlier patch sets (autotests and netdev patch)
 * Call netdev_disconnected() rather than handle the logic manually
 * Add new NETDEV_RESULT_DISCONNECTED to cover any disconnect issued
   by the AP during the connection stage. This cover the 4-way
   handshake or key setting, or anything in between.

There are some additional unrelated patches, and more autotest fixes
that were needed as a result of some prior changes

James Prestwood (11):
  station: print unknown channel number in neighbor report
  netdev: add NETDEV_RESULT_DISCONNECTED
  station: handle NETDEV_RESULT_DISCONNECTED
  station: update logic for handshake failure
  netdev: handle disconnect event during a connection
  eapol: move HANDSHAKE_STARTED_EVENT to eapol_start()
  station: add handshake-started debug event
  auto-t: add clear_events() to IWD class
  auto-t: add reason/test arguments to hostapd deauthenticate
  auto-t: Add deauth during the 4-way handshake test
  auto-t: a few random autotest fixes

 autotests/testEncryptedProfiles/ssidCCMP.psk  |   3 +
 .../disconnect_during_handshake_test.py       | 112 ++++++++++++++++++
 autotests/testPSK-roam/failed_roam_test.py    |   3 +
 autotests/testPSK-roam/ft-psk-ccmp-1.conf     |   2 +-
 autotests/testPSK-roam/ft-psk-ccmp-2.conf     |   2 +-
 autotests/testPSK-roam/ft-psk-ccmp-3.conf     |   2 +-
 autotests/testPSK-roam/main.conf              |   3 +
 .../testPSK-roam/roam_ap_disconnect_test.py   |  12 +-
 autotests/util/hostapd.py                     |   6 +-
 autotests/util/iwd.py                         |   6 +
 src/eapol.c                                   |   4 +-
 src/netdev.c                                  |  19 +--
 src/netdev.h                                  |   2 +
 src/p2p.c                                     |   1 +
 src/station.c                                 |  39 ++++--
 15 files changed, 184 insertions(+), 32 deletions(-)
 create mode 100644 autotests/testPSK-roam/disconnect_during_handshake_test.py

-- 
2.34.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v2 01/11] station: print unknown channel number in neighbor report
  2024-07-18 11:45 [PATCH v2 00/11] Refactor to unify connect failure code path James Prestwood
@ 2024-07-18 11:45 ` James Prestwood
  2024-07-18 11:45 ` [PATCH v2 02/11] netdev: add NETDEV_RESULT_DISCONNECTED James Prestwood
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: James Prestwood @ 2024-07-18 11:45 UTC (permalink / raw)
  To: iwd; +Cc: James Prestwood

If the channel number resulted in a failure to parse the neighbor
report entry, print it for debugging.
---
 src/station.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/station.c b/src/station.c
index 509d919c..3ead4326 100644
--- a/src/station.c
+++ b/src/station.c
@@ -1835,7 +1835,7 @@ static uint32_t station_freq_from_neighbor_report(const uint8_t *country,
 			band = BAND_FREQ_5_GHZ;
 		else {
 			l_debug("Ignored: 0 oper class with an unusual "
-				"channel number");
+				"channel number %u", info->channel_num);
 
 			return 0;
 		}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 02/11] netdev: add NETDEV_RESULT_DISCONNECTED
  2024-07-18 11:45 [PATCH v2 00/11] Refactor to unify connect failure code path James Prestwood
  2024-07-18 11:45 ` [PATCH v2 01/11] station: print unknown channel number in neighbor report James Prestwood
@ 2024-07-18 11:45 ` James Prestwood
  2024-07-18 11:45 ` [PATCH v2 03/11] station: handle NETDEV_RESULT_DISCONNECTED James Prestwood
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: James Prestwood @ 2024-07-18 11:45 UTC (permalink / raw)
  To: iwd; +Cc: James Prestwood

This new result is meant to handle cases where a disconnect
event (deauth/disassoc) was received during an ongoing connection.
Whether that's during authentication, association, the 4-way
handshake, or key setting.
---
 src/netdev.h  | 2 ++
 src/p2p.c     | 1 +
 src/station.c | 1 +
 3 files changed, 4 insertions(+)

diff --git a/src/netdev.h b/src/netdev.h
index 671d0d40..db0440d0 100644
--- a/src/netdev.h
+++ b/src/netdev.h
@@ -36,6 +36,7 @@ enum netdev_result {
 	NETDEV_RESULT_HANDSHAKE_FAILED,
 	NETDEV_RESULT_KEY_SETTING_FAILED,
 	NETDEV_RESULT_ABORTED,
+	NETDEV_RESULT_DISCONNECTED,
 };
 
 enum netdev_event {
@@ -86,6 +87,7 @@ typedef void (*netdev_command_cb_t)(struct netdev *netdev, int result,
  * NETDEV_RESULT_HANDSHAKE_FAILED - MMPDU_REASON_CODE
  * NETDEV_RESULT_KEY_SETTING_FAILED - unused
  * NETDEV_RESULT_ABORTED - unused.
+ * NETDEV_RESULT_DISCONNECTED - MMPDU_REASON_CODE
  */
 typedef void (*netdev_connect_cb_t)(struct netdev *netdev,
 					enum netdev_result result,
diff --git a/src/p2p.c b/src/p2p.c
index 205d4fcb..e8c7c5de 100644
--- a/src/p2p.c
+++ b/src/p2p.c
@@ -1366,6 +1366,7 @@ static void p2p_netdev_connect_cb(struct netdev *netdev,
 	case NETDEV_RESULT_ASSOCIATION_FAILED:
 	case NETDEV_RESULT_HANDSHAKE_FAILED:
 	case NETDEV_RESULT_KEY_SETTING_FAILED:
+	case NETDEV_RESULT_DISCONNECTED:
 		/*
 		 * In the AUTHENTICATION_FAILED and ASSOCIATION_FAILED
 		 * cases there's nothing to disconnect.  In the
diff --git a/src/station.c b/src/station.c
index 3ead4326..01f6b78e 100644
--- a/src/station.c
+++ b/src/station.c
@@ -3319,6 +3319,7 @@ static void station_connect_cb(struct netdev *netdev, enum netdev_result result,
 		blacklist_remove_bss(station->connected_bss->addr);
 		station_connect_ok(station);
 		return;
+	case NETDEV_RESULT_DISCONNECTED:
 	case NETDEV_RESULT_HANDSHAKE_FAILED:
 		/* reason code in this case */
 		if (station_retry_with_reason(station, l_get_u16(event_data)))
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 03/11] station: handle NETDEV_RESULT_DISCONNECTED
  2024-07-18 11:45 [PATCH v2 00/11] Refactor to unify connect failure code path James Prestwood
  2024-07-18 11:45 ` [PATCH v2 01/11] station: print unknown channel number in neighbor report James Prestwood
  2024-07-18 11:45 ` [PATCH v2 02/11] netdev: add NETDEV_RESULT_DISCONNECTED James Prestwood
@ 2024-07-18 11:45 ` James Prestwood
  2024-07-18 11:45 ` [PATCH v2 04/11] station: update logic for handshake failure James Prestwood
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: James Prestwood @ 2024-07-18 11:45 UTC (permalink / raw)
  To: iwd; +Cc: James Prestwood

This new event is sent during a connection if netdev recieves a
disconnect event. This patch cleans up station to handle this
case and leave the existing NETDEV_EVENT_DISCONNECTED_BY_{AP,SME}
handling only for CONNECTED, NETCONFIG, and FW_ROAMING states.
---
 src/station.c | 27 ++++++++++++++++++---------
 1 file changed, 18 insertions(+), 9 deletions(-)

diff --git a/src/station.c b/src/station.c
index 01f6b78e..abbfc3dd 100644
--- a/src/station.c
+++ b/src/station.c
@@ -3311,6 +3311,7 @@ static void station_connect_cb(struct netdev *netdev, enum netdev_result result,
 {
 	struct station *station = user_data;
 	bool continue_autoconnect;
+	uint16_t reason = MMPDU_REASON_CODE_UNSPECIFIED;
 
 	l_debug("%u, result: %d", netdev_get_ifindex(station->netdev), result);
 
@@ -3320,9 +3321,22 @@ static void station_connect_cb(struct netdev *netdev, enum netdev_result result,
 		station_connect_ok(station);
 		return;
 	case NETDEV_RESULT_DISCONNECTED:
+		reason = l_get_u16(event_data);
+
+		iwd_notice(IWD_NOTICE_DISCONNECT_INFO, "reason: %u", reason);
+
+		/* Disconnected while connecting */
+		network_blacklist_add(station->connected_network,
+						station->connected_bss);
+		if (station_try_next_bss(station))
+			return;
+
+		break;
 	case NETDEV_RESULT_HANDSHAKE_FAILED:
+		reason = l_get_u16(event_data);
+
 		/* reason code in this case */
-		if (station_retry_with_reason(station, l_get_u16(event_data)))
+		if (station_retry_with_reason(station, reason))
 			return;
 
 		break;
@@ -3383,17 +3397,12 @@ static void station_disconnect_event(struct station *station, void *event_data)
 	/*
 	 * If we're connecting, AP deauthenticated us, most likely because
 	 * we provided the wrong password or otherwise failed authentication
-	 * during the handshaking phase.  Treat this as a connection failure
+	 * during the handshaking phase. Connection failures should be handled
+	 * within station_connect_cb/station_reassociate_cb apart from netconfig
+	 * and FW roams.
 	 */
 	switch (station->state) {
-	case STATION_STATE_CONNECTING:
-	case STATION_STATE_CONNECTING_AUTO:
-		station_connect_cb(station->netdev,
-					NETDEV_RESULT_HANDSHAKE_FAILED,
-					event_data, station);
-		return;
 	case STATION_STATE_CONNECTED:
-	case STATION_STATE_FT_ROAMING:
 	case STATION_STATE_FW_ROAMING:
 	case STATION_STATE_NETCONFIG:
 		iwd_notice(IWD_NOTICE_DISCONNECT_INFO, "reason: %u",
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 04/11] station: update logic for handshake failure
  2024-07-18 11:45 [PATCH v2 00/11] Refactor to unify connect failure code path James Prestwood
                   ` (2 preceding siblings ...)
  2024-07-18 11:45 ` [PATCH v2 03/11] station: handle NETDEV_RESULT_DISCONNECTED James Prestwood
@ 2024-07-18 11:45 ` James Prestwood
  2024-07-18 11:45 ` [PATCH v2 05/11] netdev: handle disconnect event during a connection James Prestwood
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: James Prestwood @ 2024-07-18 11:45 UTC (permalink / raw)
  To: iwd; +Cc: James Prestwood

After adding the NETDEV_RESULT_DISCONNECTED enum, handshake failures
initiated by the AP come in via this result so the existing logic
to call network_connect_failed() was broken. We could still get a
handshake failure generated internally, so that has been preserved
(via NETDEV_RESULT_HANDSHAKE_FAILED) but a check for a 4-way
handshake timeout reason code was also added.
---
 src/station.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/src/station.c b/src/station.c
index abbfc3dd..62b05c35 100644
--- a/src/station.c
+++ b/src/station.c
@@ -3368,7 +3368,13 @@ static void station_connect_cb(struct netdev *netdev, enum netdev_result result,
 	continue_autoconnect = station->state == STATION_STATE_CONNECTING_AUTO;
 
 	if (station->state == STATION_STATE_CONNECTING) {
-		bool during_eapol = result == NETDEV_RESULT_HANDSHAKE_FAILED;
+		/*
+		 * Either a handshake failure (generated internally) or a 4-way
+		 * handshake timeout should trigger the PSK to be asked for
+		 * again. Set during_eapol accordingly.
+		 */
+		bool during_eapol = result == NETDEV_RESULT_HANDSHAKE_FAILED ||
+			reason == MMPDU_REASON_CODE_4WAY_HANDSHAKE_TIMEOUT;
 		network_connect_failed(station->connected_network,
 								during_eapol);
 	}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 05/11] netdev: handle disconnect event during a connection
  2024-07-18 11:45 [PATCH v2 00/11] Refactor to unify connect failure code path James Prestwood
                   ` (3 preceding siblings ...)
  2024-07-18 11:45 ` [PATCH v2 04/11] station: update logic for handshake failure James Prestwood
@ 2024-07-18 11:45 ` James Prestwood
  2024-07-18 11:45 ` [PATCH v2 06/11] eapol: move HANDSHAKE_STARTED_EVENT to eapol_start() James Prestwood
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: James Prestwood @ 2024-07-18 11:45 UTC (permalink / raw)
  To: iwd; +Cc: James Prestwood

If a disconnect arrives at any point during the 4-way handshake or
key setting this would result in netdev sending a disconnect event
to station. If this is a reassociation this case is unhandled in
station and causes a hang as it expects any connection failure to
be handled via the reassociation callback, not a random disconnect
event.

To handle this case we can utilize netdev_disconnected() along with
the new NETDEV_RESULT_DISCONNECTED result to ensure the connect
callback gets called if it exists (indicating a pending connection)

Below are logs showing the "Unexpected disconnect event" which
prevents IWD from cleaning up its state and ultimately results in a
hang:

Jul 16 18:16:13: src/station.c:station_transition_reassociate()
Jul 16 18:16:13: event: state, old: connected, new: roaming
Jul 16 18:16:13: src/wiphy.c:wiphy_radio_work_done() Work item 65 done
Jul 16 18:16:13: src/wiphy.c:wiphy_radio_work_next() Starting work item 66
Jul 16 18:16:13: src/netdev.c:netdev_mlme_notify() MLME notification Del Station(20)
Jul 16 18:16:13: src/netdev.c:netdev_link_notify() event 16 on ifindex 6
Jul 16 18:16:13: src/netdev.c:netdev_mlme_notify() MLME notification Deauthenticate(39)
Jul 16 18:16:13: src/netdev.c:netdev_deauthenticate_event()
Jul 16 18:16:13: src/netdev.c:netdev_mlme_notify() MLME notification New Station(19)
Jul 16 18:16:13: src/station.c:station_netdev_event() Associating
Jul 16 18:16:13: src/netdev.c:netdev_mlme_notify() MLME notification Authenticate(37)
Jul 16 18:16:13: src/netdev.c:netdev_authenticate_event()
Jul 16 18:16:13: src/netdev.c:netdev_mlme_notify() MLME notification Associate(38)
Jul 16 18:16:13: src/netdev.c:netdev_associate_event()
Jul 16 18:16:13: src/netdev.c:netdev_link_notify() event 16 on ifindex 6
Jul 16 18:16:13: src/netdev.c:netdev_mlme_notify() MLME notification Connect(46)
Jul 16 18:16:13: src/netdev.c:netdev_connect_event()
Jul 16 18:16:13: src/netdev.c:netdev_connect_event() aborting and ignore_connect_event not set, proceed
Jul 16 18:16:13: src/netdev.c:netdev_connect_event() expect_connect_failure not set, proceed
Jul 16 18:16:13: src/netdev.c:parse_request_ies()
Jul 16 18:16:13: src/netdev.c:netdev_connect_event() Request / Response IEs parsed
Jul 16 18:16:13: src/netdev.c:netdev_get_oci()
Jul 16 18:16:13: src/netdev.c:netdev_link_notify() event 16 on ifindex 6
Jul 16 18:16:13: src/netdev.c:netdev_link_notify() event 16 on ifindex 6
Jul 16 18:16:13: src/netdev.c:netdev_link_notify() event 16 on ifindex 6
Jul 16 18:16:13: src/netdev.c:netdev_get_oci_cb() Obtained OCI: freq: 5220, width: 3, center1: 5210, center2: 0
Jul 16 18:16:13: src/eapol.c:eapol_start()
Jul 16 18:16:13: src/netdev.c:netdev_unicast_notify() Unicast notification Control Port Frame(129)
Jul 16 18:16:13: src/netdev.c:netdev_control_port_frame_event()
Jul 16 18:16:13: src/eapol.c:eapol_handle_ptk_1_of_4() ifindex=6
Jul 16 18:16:13: src/netdev.c:netdev_mlme_notify() MLME notification Control Port TX Status(139)
Jul 16 18:16:14: src/netdev.c:netdev_mlme_notify() MLME notification Notify CQM(64)
Jul 16 18:16:14: src/netdev.c:netdev_cqm_event() Signal change event (above=1 signal=-60)
Jul 16 18:16:17: src/netdev.c:netdev_link_notify() event 16 on ifindex 6
Jul 16 18:16:17: src/netdev.c:netdev_mlme_notify() MLME notification Del Station(20)
Jul 16 18:16:17: src/netdev.c:netdev_mlme_notify() MLME notification Deauthenticate(39)
Jul 16 18:16:17: src/netdev.c:netdev_deauthenticate_event()
Jul 16 18:16:17: src/netdev.c:netdev_mlme_notify() MLME notification Disconnect(48)
Jul 16 18:16:17: src/netdev.c:netdev_disconnect_event()
Jul 16 18:16:17: Received Deauthentication event, reason: 15, from_ap: true
Jul 16 18:16:17: src/wiphy.c:wiphy_radio_work_done() Work item 66 done
Jul 16 18:16:17: src/station.c:station_disconnect_event() 6
Jul 16 18:16:17: Unexpected disconnect event
Jul 16 18:16:17: src/netdev.c:netdev_link_notify() event 16 on ifindex 6
Jul 16 18:16:17: src/wiphy.c:wiphy_reg_notify() Notification of command Reg Change(36)
Jul 16 18:16:17: src/wiphy.c:wiphy_update_reg_domain() New reg domain country code for (global) is XX
---
 src/netdev.c | 19 +++++--------------
 1 file changed, 5 insertions(+), 14 deletions(-)

diff --git a/src/netdev.c b/src/netdev.c
index 153001ab..2d70fc38 100644
--- a/src/netdev.c
+++ b/src/netdev.c
@@ -1243,8 +1243,7 @@ static void netdev_disconnect_event(struct l_genl_msg *msg,
 	const void *data;
 	uint16_t reason_code = 0;
 	bool disconnect_by_ap = false;
-	netdev_event_func_t event_filter;
-	void *event_data;
+	enum netdev_event event;
 
 	l_debug("");
 
@@ -1282,19 +1281,11 @@ static void netdev_disconnect_event(struct l_genl_msg *msg,
 	l_info("Received Deauthentication event, reason: %hu, from_ap: %s",
 			reason_code, disconnect_by_ap ? "true" : "false");
 
-	event_filter = netdev->event_filter;
-	event_data = netdev->user_data;
-	netdev_connect_free(netdev);
+	event = disconnect_by_ap ? NETDEV_EVENT_DISCONNECT_BY_AP :
+				NETDEV_EVENT_DISCONNECT_BY_SME;
 
-	if (!event_filter)
-		return;
-
-	if (disconnect_by_ap)
-		event_filter(netdev, NETDEV_EVENT_DISCONNECT_BY_AP,
-						&reason_code, event_data);
-	else
-		event_filter(netdev, NETDEV_EVENT_DISCONNECT_BY_SME,
-						&reason_code, event_data);
+	netdev_disconnected(netdev, NETDEV_RESULT_DISCONNECTED,
+				event, reason_code);
 }
 
 static void netdev_cmd_disconnect_cb(struct l_genl_msg *msg, void *user_data)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 06/11] eapol: move HANDSHAKE_STARTED_EVENT to eapol_start()
  2024-07-18 11:45 [PATCH v2 00/11] Refactor to unify connect failure code path James Prestwood
                   ` (4 preceding siblings ...)
  2024-07-18 11:45 ` [PATCH v2 05/11] netdev: handle disconnect event during a connection James Prestwood
@ 2024-07-18 11:45 ` James Prestwood
  2024-07-18 11:45 ` [PATCH v2 07/11] station: add handshake-started debug event James Prestwood
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: James Prestwood @ 2024-07-18 11:45 UTC (permalink / raw)
  To: iwd; +Cc: James Prestwood

This even is not used anywhere and can be leveraged in autotesting.
Move the event to eapol_start() so it gets called unconditionally
when the 4-way handshake is started.
---
 src/eapol.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/eapol.c b/src/eapol.c
index 845ef866..6d176304 100644
--- a/src/eapol.c
+++ b/src/eapol.c
@@ -1036,8 +1036,6 @@ static void __send_eapol_start(struct eapol_sm *sm, bool noencrypt)
 	uint8_t buf[sizeof(struct eapol_frame)];
 	struct eapol_frame *frame = (struct eapol_frame *) buf;
 
-	handshake_event(sm->handshake, HANDSHAKE_EVENT_STARTED);
-
 	frame->header.protocol_version = EAPOL_PROTOCOL_VERSION_2001;
 	frame->header.packet_type = 1;
 	l_put_be16(0, &frame->header.packet_len);
@@ -2858,6 +2856,8 @@ bool eapol_start(struct eapol_sm *sm)
 		eap_set_peer_id(sm->eap, network_id);
 	}
 
+	handshake_event(sm->handshake, HANDSHAKE_EVENT_STARTED);
+
 	sm->started = true;
 
 	if (sm->require_handshake)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 07/11] station: add handshake-started debug event
  2024-07-18 11:45 [PATCH v2 00/11] Refactor to unify connect failure code path James Prestwood
                   ` (5 preceding siblings ...)
  2024-07-18 11:45 ` [PATCH v2 06/11] eapol: move HANDSHAKE_STARTED_EVENT to eapol_start() James Prestwood
@ 2024-07-18 11:45 ` James Prestwood
  2024-07-18 11:45 ` [PATCH v2 08/11] auto-t: add clear_events() to IWD class James Prestwood
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: James Prestwood @ 2024-07-18 11:45 UTC (permalink / raw)
  To: iwd; +Cc: James Prestwood

---
 src/station.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/station.c b/src/station.c
index 62b05c35..ca0e6a38 100644
--- a/src/station.c
+++ b/src/station.c
@@ -1015,6 +1015,7 @@ static void station_handshake_event(struct handshake_state *hs,
 	switch (event) {
 	case HANDSHAKE_EVENT_STARTED:
 		l_debug("Handshaking");
+		station_debug_event(station, "handshake-started");
 		break;
 	case HANDSHAKE_EVENT_SETTING_KEYS:
 		l_debug("Setting keys");
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 08/11] auto-t: add clear_events() to IWD class
  2024-07-18 11:45 [PATCH v2 00/11] Refactor to unify connect failure code path James Prestwood
                   ` (6 preceding siblings ...)
  2024-07-18 11:45 ` [PATCH v2 07/11] station: add handshake-started debug event James Prestwood
@ 2024-07-18 11:45 ` James Prestwood
  2024-07-18 11:45 ` [PATCH v2 09/11] auto-t: add reason/test arguments to hostapd deauthenticate James Prestwood
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: James Prestwood @ 2024-07-18 11:45 UTC (permalink / raw)
  To: iwd; +Cc: James Prestwood

The wait_for_event() function allows past events to cause this
function to return immediately. This behavior is known, and
relied on for some tests. But in some cases you want to only
handle _new_ events, so we need a way to clear out prior events.
---
 autotests/util/iwd.py | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/autotests/util/iwd.py b/autotests/util/iwd.py
index 511fb3a5..1d4a5472 100755
--- a/autotests/util/iwd.py
+++ b/autotests/util/iwd.py
@@ -299,6 +299,9 @@ class StationDebug(IWDDBusAbstract):
 
         return False
 
+    def clear_events(self):
+        self._events = []
+
     def wait_for_event(self, event, timeout=10):
         return ctx.non_block_wait(self._poll_event, timeout, event,
                                     exception=TimeoutError("waiting for event"))
@@ -859,6 +862,9 @@ class Device(IWDDBusAbstract):
     def wait_for_event(self, event, timeout=10):
         self._station_debug.wait_for_event(event, timeout)
 
+    def clear_events(self):
+        self._station_debug.clear_events()
+
     def event_ocurred(self, event):
         return self._station_debug.event_ocurred(event)
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 09/11] auto-t: add reason/test arguments to hostapd deauthenticate
  2024-07-18 11:45 [PATCH v2 00/11] Refactor to unify connect failure code path James Prestwood
                   ` (7 preceding siblings ...)
  2024-07-18 11:45 ` [PATCH v2 08/11] auto-t: add clear_events() to IWD class James Prestwood
@ 2024-07-18 11:45 ` James Prestwood
  2024-07-18 11:45 ` [PATCH v2 10/11] auto-t: Add deauth during the 4-way handshake test James Prestwood
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: James Prestwood @ 2024-07-18 11:45 UTC (permalink / raw)
  To: iwd; +Cc: James Prestwood

The reason code is obvious, but the test argument is actually a
toggle to send the frame encrypted or unencrypted.
---
 autotests/util/hostapd.py | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/autotests/util/hostapd.py b/autotests/util/hostapd.py
index 2f92e330..e5e35a96 100644
--- a/autotests/util/hostapd.py
+++ b/autotests/util/hostapd.py
@@ -184,8 +184,12 @@ class HostapdCLI(object):
         cmd = self.cmdline + ['wps_pin', 'any', pin]
         ctx.start_process(cmd).wait()
 
-    def deauthenticate(self, client_address):
+    def deauthenticate(self, client_address, reason=None, test=None):
         cmd = self.cmdline + ['deauthenticate', client_address]
+
+        if reason:
+            cmd.append(f"reason={reason} test={test}")
+
         ctx.start_process(cmd).wait()
 
     def eapol_reauth(self, client_address):
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 10/11] auto-t: Add deauth during the 4-way handshake test
  2024-07-18 11:45 [PATCH v2 00/11] Refactor to unify connect failure code path James Prestwood
                   ` (8 preceding siblings ...)
  2024-07-18 11:45 ` [PATCH v2 09/11] auto-t: add reason/test arguments to hostapd deauthenticate James Prestwood
@ 2024-07-18 11:45 ` James Prestwood
  2024-07-18 11:45 ` [PATCH v2 11/11] auto-t: a few random autotest fixes James Prestwood
  2024-07-18 21:11 ` [PATCH v2 00/11] Refactor to unify connect failure code path Denis Kenzior
  11 siblings, 0 replies; 13+ messages in thread
From: James Prestwood @ 2024-07-18 11:45 UTC (permalink / raw)
  To: iwd; +Cc: James Prestwood

This test will fail with current upstream as IWD hangs when the
deauthenticate event arrives. Once this is fixed the test should
pass.
---
 .../disconnect_during_handshake_test.py       | 112 ++++++++++++++++++
 autotests/testPSK-roam/ft-psk-ccmp-1.conf     |   2 +-
 autotests/testPSK-roam/ft-psk-ccmp-2.conf     |   2 +-
 autotests/testPSK-roam/ft-psk-ccmp-3.conf     |   2 +-
 autotests/testPSK-roam/main.conf              |   3 +
 5 files changed, 118 insertions(+), 3 deletions(-)
 create mode 100644 autotests/testPSK-roam/disconnect_during_handshake_test.py

diff --git a/autotests/testPSK-roam/disconnect_during_handshake_test.py b/autotests/testPSK-roam/disconnect_during_handshake_test.py
new file mode 100644
index 00000000..026081c3
--- /dev/null
+++ b/autotests/testPSK-roam/disconnect_during_handshake_test.py
@@ -0,0 +1,112 @@
+#! /usr/bin/python3
+
+import unittest
+import sys, os
+
+sys.path.append('../util')
+import iwd
+from iwd import IWD
+from iwd import PSKAgent
+from iwd import NetworkType
+from hwsim import Hwsim
+from hostapd import HostapdCLI
+import testutil
+
+class Test(unittest.TestCase):
+    def validate_connection(self, wd):
+        device = wd.list_devices(1)[0]
+
+        ordered_network = device.get_ordered_network('TestFT', full_scan=True)
+
+        self.assertEqual(ordered_network.type, NetworkType.psk)
+
+        condition = 'not obj.connected'
+        wd.wait_for_object_condition(ordered_network.network_object, condition)
+
+        self.assertFalse(self.bss_hostapd[0].list_sta())
+        self.assertFalse(self.bss_hostapd[1].list_sta())
+
+        device.connect_bssid(self.bss_hostapd[0].bssid)
+
+        condition = 'obj.state == DeviceState.connected'
+        wd.wait_for_object_condition(device, condition)
+
+        self.bss_hostapd[0].wait_for_event('AP-STA-CONNECTED %s' % device.address)
+
+        testutil.test_iface_operstate(device.name)
+        testutil.test_ifaces_connected(self.bss_hostapd[0].ifname, device.name)
+        self.assertRaises(Exception, testutil.test_ifaces_connected,
+                          (self.bss_hostapd[1].ifname, device.name, True, True))
+
+        self.rule0.enabled = True
+
+        device.roam(self.bss_hostapd[1].bssid)
+
+        device.clear_events()
+        device.wait_for_event("handshake-started")
+        self.bss_hostapd[1].deauthenticate(device.address, reason=15, test=1)
+
+        # Check that iwd is on BSS 1 once out of roaming state and doesn't
+        # go through 'disconnected', 'autoconnect', 'connecting' in between
+        from_condition = 'obj.state == DeviceState.roaming'
+        to_condition = 'obj.state == DeviceState.disconnected'
+        wd.wait_for_object_change(device, from_condition, to_condition)
+
+    def test_disconnect_during_handshake(self):
+        self.bss_hostapd[0].set_value('wpa_key_mgmt', 'WPA-PSK')
+        self.bss_hostapd[0].reload()
+        self.bss_hostapd[0].wait_for_event("AP-ENABLED")
+
+        self.bss_hostapd[1].set_value('wpa_key_mgmt', 'WPA-PSK')
+        self.bss_hostapd[1].reload()
+        self.bss_hostapd[1].wait_for_event("AP-ENABLED")
+
+        self.validate_connection(self.wd)
+
+    def tearDown(self):
+        os.system('ip link set "' + self.bss_hostapd[0].ifname + '" down')
+        os.system('ip link set "' + self.bss_hostapd[1].ifname + '" down')
+        os.system('ip link set "' + self.bss_hostapd[0].ifname + '" up')
+        os.system('ip link set "' + self.bss_hostapd[1].ifname + '" up')
+
+        for hapd in self.bss_hostapd:
+            hapd.default()
+
+        self.wd.stop()
+        self.wd = None
+
+    def setUp(self):
+        self.wd = IWD(True)
+
+    @classmethod
+    def setUpClass(cls):
+        hwsim = Hwsim()
+
+        IWD.copy_to_storage('TestFT.psk')
+
+        cls.bss_hostapd = [ HostapdCLI(config='ft-psk-ccmp-1.conf'),
+                            HostapdCLI(config='ft-psk-ccmp-2.conf') ]
+
+        unused = HostapdCLI(config='ft-psk-ccmp-3.conf')
+        unused.disable()
+
+        cls.bss_hostapd[0].set_address('12:00:00:00:00:01')
+        cls.bss_hostapd[1].set_address('12:00:00:00:00:02')
+
+        rad1 = hwsim.get_radio('rad1')
+
+        cls.rule0 = hwsim.rules.create()
+        cls.rule0.destination = rad1.addresses[0]
+        cls.rule0.prefix = '08'
+        cls.rule0.drop = True
+
+        HostapdCLI.group_neighbors(*cls.bss_hostapd)
+
+    @classmethod
+    def tearDownClass(cls):
+        IWD.clear_storage()
+        cls.bss_hostapd = None
+        cls.rule0.remove()
+
+if __name__ == '__main__':
+    unittest.main(exit=True)
diff --git a/autotests/testPSK-roam/ft-psk-ccmp-1.conf b/autotests/testPSK-roam/ft-psk-ccmp-1.conf
index b46d1f27..839eb496 100644
--- a/autotests/testPSK-roam/ft-psk-ccmp-1.conf
+++ b/autotests/testPSK-roam/ft-psk-ccmp-1.conf
@@ -13,7 +13,7 @@ wpa=2
 wpa_key_mgmt=FT-PSK
 wpa_pairwise=CCMP
 wpa_passphrase=EasilyGuessedPassword
-ieee80211w=1
+ieee80211w=0
 rsn_preauth=1
 rsn_preauth_interfaces=lo
 disable_pmksa_caching=0
diff --git a/autotests/testPSK-roam/ft-psk-ccmp-2.conf b/autotests/testPSK-roam/ft-psk-ccmp-2.conf
index 3e215457..2ffd7262 100644
--- a/autotests/testPSK-roam/ft-psk-ccmp-2.conf
+++ b/autotests/testPSK-roam/ft-psk-ccmp-2.conf
@@ -13,7 +13,7 @@ wpa=2
 wpa_key_mgmt=FT-PSK
 wpa_pairwise=CCMP
 wpa_passphrase=EasilyGuessedPassword
-ieee80211w=1
+ieee80211w=0
 rsn_preauth=1
 rsn_preauth_interfaces=lo
 disable_pmksa_caching=0
diff --git a/autotests/testPSK-roam/ft-psk-ccmp-3.conf b/autotests/testPSK-roam/ft-psk-ccmp-3.conf
index 3e215457..2ffd7262 100644
--- a/autotests/testPSK-roam/ft-psk-ccmp-3.conf
+++ b/autotests/testPSK-roam/ft-psk-ccmp-3.conf
@@ -13,7 +13,7 @@ wpa=2
 wpa_key_mgmt=FT-PSK
 wpa_pairwise=CCMP
 wpa_passphrase=EasilyGuessedPassword
-ieee80211w=1
+ieee80211w=0
 rsn_preauth=1
 rsn_preauth_interfaces=lo
 disable_pmksa_caching=0
diff --git a/autotests/testPSK-roam/main.conf b/autotests/testPSK-roam/main.conf
index 3d93ff57..a6887c9c 100644
--- a/autotests/testPSK-roam/main.conf
+++ b/autotests/testPSK-roam/main.conf
@@ -3,3 +3,6 @@ DisableMacAddressRandomization=true
 
 [General]
 RoamRetryInterval=1
+
+# For disconnect_during_handshake_test
+ManagementFrameProtection=0
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 11/11] auto-t: a few random autotest fixes
  2024-07-18 11:45 [PATCH v2 00/11] Refactor to unify connect failure code path James Prestwood
                   ` (9 preceding siblings ...)
  2024-07-18 11:45 ` [PATCH v2 10/11] auto-t: Add deauth during the 4-way handshake test James Prestwood
@ 2024-07-18 11:45 ` James Prestwood
  2024-07-18 21:11 ` [PATCH v2 00/11] Refactor to unify connect failure code path Denis Kenzior
  11 siblings, 0 replies; 13+ messages in thread
From: James Prestwood @ 2024-07-18 11:45 UTC (permalink / raw)
  To: iwd; +Cc: James Prestwood

testEncryptedProfiles:
 - This would occationally fail because the test is expecting
   to explicitly connect but after the first failed connection
   autoconnect takes over and its a race to connect.
testPSK-roam:
 - Several rules were not being cleaned up which could cause
   tests afterwards to fail
 - The AP roam test started failing randomly because of the SNR
   ranking changes. It appears that with hwsim _sometimes_ the
   SNR is able to be determined which can effect the ranking. This
   test assumed the two BSS's would be the same ranking but the
   SNR sometimes causes this to not be true.
---
 autotests/testEncryptedProfiles/ssidCCMP.psk      |  3 +++
 autotests/testPSK-roam/failed_roam_test.py        |  3 +++
 autotests/testPSK-roam/roam_ap_disconnect_test.py | 12 +++++++++++-
 3 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/autotests/testEncryptedProfiles/ssidCCMP.psk b/autotests/testEncryptedProfiles/ssidCCMP.psk
index abafdb66..a82ae05d 100644
--- a/autotests/testEncryptedProfiles/ssidCCMP.psk
+++ b/autotests/testEncryptedProfiles/ssidCCMP.psk
@@ -1,2 +1,5 @@
 [Security]
 Passphrase=secret123
+
+[General]
+AutoConnect=false
diff --git a/autotests/testPSK-roam/failed_roam_test.py b/autotests/testPSK-roam/failed_roam_test.py
index 60bcf366..e0b2f955 100644
--- a/autotests/testPSK-roam/failed_roam_test.py
+++ b/autotests/testPSK-roam/failed_roam_test.py
@@ -247,6 +247,9 @@ class Test(unittest.TestCase):
         cls.rule2.remove()
         cls.rule3.remove()
         cls.assoc_rule.remove()
+        cls.rule_bss0.remove()
+        cls.rule_bss1.remove()
+        cls.rule_bss2.remove()
 
 if __name__ == '__main__':
     unittest.main(exit=True)
diff --git a/autotests/testPSK-roam/roam_ap_disconnect_test.py b/autotests/testPSK-roam/roam_ap_disconnect_test.py
index 76c62ea0..9c660016 100644
--- a/autotests/testPSK-roam/roam_ap_disconnect_test.py
+++ b/autotests/testPSK-roam/roam_ap_disconnect_test.py
@@ -81,12 +81,21 @@ class Test(unittest.TestCase):
         cls.bss_hostapd[0].set_value('ocv', '0')
         cls.bss_hostapd[0].set_value('ieee80211w', '0')
 
+        rad0 = hwsim.get_radio('rad0')
+        rad1 = hwsim.get_radio('rad1')
+
         cls.rule0 = hwsim.rules.create()
-        cls.rule0.source = 'any'
+        cls.rule0.source = rad0.addresses[0]
         cls.rule0.bidirectional = True
         cls.rule0.signal = -8000
         cls.rule0.enabled = True
 
+        cls.rule1 = hwsim.rules.create()
+        cls.rule1.source = rad1.addresses[0]
+        cls.rule1.bidirectional = True
+        cls.rule1.signal = -8500
+        cls.rule1.enabled = True
+
         cls.bss_hostapd[0].set_address('12:00:00:00:00:01')
         cls.bss_hostapd[1].set_address('12:00:00:00:00:02')
 
@@ -95,6 +104,7 @@ class Test(unittest.TestCase):
         IWD.clear_storage()
         cls.bss_hostapd = None
         cls.rule0.remove()
+        cls.rule1.remove()
 
 if __name__ == '__main__':
     unittest.main(exit=True)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 00/11] Refactor to unify connect failure code path
  2024-07-18 11:45 [PATCH v2 00/11] Refactor to unify connect failure code path James Prestwood
                   ` (10 preceding siblings ...)
  2024-07-18 11:45 ` [PATCH v2 11/11] auto-t: a few random autotest fixes James Prestwood
@ 2024-07-18 21:11 ` Denis Kenzior
  11 siblings, 0 replies; 13+ messages in thread
From: Denis Kenzior @ 2024-07-18 21:11 UTC (permalink / raw)
  To: James Prestwood, iwd

Hi James,

On 7/18/24 6:45 AM, James Prestwood wrote:
> v2:
>   * Combined two earlier patch sets (autotests and netdev patch)
>   * Call netdev_disconnected() rather than handle the logic manually
>   * Add new NETDEV_RESULT_DISCONNECTED to cover any disconnect issued
>     by the AP during the connection stage. This cover the 4-way
>     handshake or key setting, or anything in between.
> 
> There are some additional unrelated patches, and more autotest fixes
> that were needed as a result of some prior changes
> 
> James Prestwood (11):
>    station: print unknown channel number in neighbor report
>    netdev: add NETDEV_RESULT_DISCONNECTED
>    station: handle NETDEV_RESULT_DISCONNECTED
>    station: update logic for handshake failure
>    netdev: handle disconnect event during a connection
>    eapol: move HANDSHAKE_STARTED_EVENT to eapol_start()
>    station: add handshake-started debug event
>    auto-t: add clear_events() to IWD class
>    auto-t: add reason/test arguments to hostapd deauthenticate
>    auto-t: Add deauth during the 4-way handshake test
>    auto-t: a few random autotest fixes
> 
>   autotests/testEncryptedProfiles/ssidCCMP.psk  |   3 +
>   .../disconnect_during_handshake_test.py       | 112 ++++++++++++++++++
>   autotests/testPSK-roam/failed_roam_test.py    |   3 +
>   autotests/testPSK-roam/ft-psk-ccmp-1.conf     |   2 +-
>   autotests/testPSK-roam/ft-psk-ccmp-2.conf     |   2 +-
>   autotests/testPSK-roam/ft-psk-ccmp-3.conf     |   2 +-
>   autotests/testPSK-roam/main.conf              |   3 +
>   .../testPSK-roam/roam_ap_disconnect_test.py   |  12 +-
>   autotests/util/hostapd.py                     |   6 +-
>   autotests/util/iwd.py                         |   6 +
>   src/eapol.c                                   |   4 +-
>   src/netdev.c                                  |  19 +--
>   src/netdev.h                                  |   2 +
>   src/p2p.c                                     |   1 +
>   src/station.c                                 |  39 ++++--
>   15 files changed, 184 insertions(+), 32 deletions(-)
>   create mode 100644 autotests/testPSK-roam/disconnect_during_handshake_test.py
> 

All applied, thanks.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2024-07-18 21:11 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-07-18 11:45 [PATCH v2 00/11] Refactor to unify connect failure code path James Prestwood
2024-07-18 11:45 ` [PATCH v2 01/11] station: print unknown channel number in neighbor report James Prestwood
2024-07-18 11:45 ` [PATCH v2 02/11] netdev: add NETDEV_RESULT_DISCONNECTED James Prestwood
2024-07-18 11:45 ` [PATCH v2 03/11] station: handle NETDEV_RESULT_DISCONNECTED James Prestwood
2024-07-18 11:45 ` [PATCH v2 04/11] station: update logic for handshake failure James Prestwood
2024-07-18 11:45 ` [PATCH v2 05/11] netdev: handle disconnect event during a connection James Prestwood
2024-07-18 11:45 ` [PATCH v2 06/11] eapol: move HANDSHAKE_STARTED_EVENT to eapol_start() James Prestwood
2024-07-18 11:45 ` [PATCH v2 07/11] station: add handshake-started debug event James Prestwood
2024-07-18 11:45 ` [PATCH v2 08/11] auto-t: add clear_events() to IWD class James Prestwood
2024-07-18 11:45 ` [PATCH v2 09/11] auto-t: add reason/test arguments to hostapd deauthenticate James Prestwood
2024-07-18 11:45 ` [PATCH v2 10/11] auto-t: Add deauth during the 4-way handshake test James Prestwood
2024-07-18 11:45 ` [PATCH v2 11/11] auto-t: a few random autotest fixes James Prestwood
2024-07-18 21:11 ` [PATCH v2 00/11] Refactor to unify connect failure code path Denis Kenzior

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox