diff mbox series

netdev: use CMD_DEAUTHENTICATE when needed on disconnect

Message ID 20240328173745.1574384-1-prestwoj@gmail.com (mailing list archive)
State Accepted, archived
Headers show
Series netdev: use CMD_DEAUTHENTICATE when needed on disconnect | expand

Checks

Context Check Description
tedd_an/pre-ci_am success Success
prestwoj/iwd-alpine-ci-fetch success Fetch PR
prestwoj/iwd-ci-gitlint success GitLint
prestwoj/iwd-ci-fetch success Fetch PR
prestwoj/iwd-ci-incremental_build success Incremental build not run PASS
prestwoj/iwd-alpine-ci-makedistcheck success Make Distcheck
prestwoj/iwd-alpine-ci-incremental_build success Incremental build not run PASS
prestwoj/iwd-ci-build success Build - Configure
prestwoj/iwd-alpine-ci-build success Build - Configure
prestwoj/iwd-ci-clang success clang PASS
prestwoj/iwd-ci-makecheckvalgrind success Make Check w/Valgrind
prestwoj/iwd-ci-makecheck success Make Check
prestwoj/iwd-alpine-ci-makecheckvalgrind success Make Check w/Valgrind
prestwoj/iwd-alpine-ci-makecheck success Make Check
prestwoj/iwd-ci-makedistcheck success Make Distcheck
prestwoj/iwd-ci-testrunner success test-runner PASS

Commit Message

James Prestwood March 28, 2024, 5:37 p.m. UTC
netdev_disconnect() was unconditionally sending CMD_DISCONNECT which
is not the right behavior when IWD has not associated. This means
that if a connection was started then immediately canceled with
the Disconnect() method the kernel would continue to authenticate.

Instead if IWD has not yet associated it should send a deauth
command which causes the kernel to correctly cleanup its state and
stop trying to authenticate.

Below are logs showing the behavior. Autoconnect is started followed
immediately by a DBus Disconnect call, yet the kernel continues
sending authenticate events.

event: state, old: autoconnect_quick, new: connecting (auto)
src/scan.c:scan_cancel() Trying to cancel scan id 1 for wdev 7d
src/wiphy.c:wiphy_radio_work_done() Work item 1 done
src/wiphy.c:wiphy_radio_work_next() Starting work item 2
src/netdev.c:netdev_mlme_notify() MLME notification New Station(19)
src/station.c:station_dbus_disconnect()
src/station.c:station_reset_connection_state() 85
src/station.c:station_roam_state_clear() 85
event: state, old: connecting (auto), new: disconnecting
src/wiphy.c:wiphy_radio_work_done() Work item 2 done
src/station.c:station_connect_cb() 85, result: 5
src/station.c:station_disconnect_cb() 85, success: 1
event: state, old: disconnecting, new: disconnected
src/netdev.c:netdev_mlme_notify() MLME notification Authenticate(37)
src/netdev.c:netdev_authenticate_event()
Unexpected connection related event -- is another supplicant running?
src/netdev.c:netdev_mlme_notify() MLME notification Authenticate(37)
src/netdev.c:netdev_authenticate_event()
Unexpected connection related event -- is another supplicant running?
src/netdev.c:netdev_mlme_notify() MLME notification Authenticate(37)
src/netdev.c:netdev_authenticate_event()
Unexpected connection related event -- is another supplicant running?
src/netdev.c:netdev_mlme_notify() MLME notification Del Station(20)
src/netdev.c:netdev_mlme_notify() MLME notification Authenticate(37)
src/netdev.c:netdev_authenticate_event()
Unexpected connection related event -- is another supplicant running?
---
 src/netdev.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

Comments

Denis Kenzior March 28, 2024, 10:29 p.m. UTC | #1
Hi James,

On 3/28/24 12:37, James Prestwood wrote:
> netdev_disconnect() was unconditionally sending CMD_DISCONNECT which
> is not the right behavior when IWD has not associated. This means
> that if a connection was started then immediately canceled with
> the Disconnect() method the kernel would continue to authenticate.
> 
> Instead if IWD has not yet associated it should send a deauth
> command which causes the kernel to correctly cleanup its state and
> stop trying to authenticate.
> 
> Below are logs showing the behavior. Autoconnect is started followed
> immediately by a DBus Disconnect call, yet the kernel continues
> sending authenticate events.
> 
> event: state, old: autoconnect_quick, new: connecting (auto)
> src/scan.c:scan_cancel() Trying to cancel scan id 1 for wdev 7d
> src/wiphy.c:wiphy_radio_work_done() Work item 1 done
> src/wiphy.c:wiphy_radio_work_next() Starting work item 2
> src/netdev.c:netdev_mlme_notify() MLME notification New Station(19)
> src/station.c:station_dbus_disconnect()
> src/station.c:station_reset_connection_state() 85
> src/station.c:station_roam_state_clear() 85
> event: state, old: connecting (auto), new: disconnecting
> src/wiphy.c:wiphy_radio_work_done() Work item 2 done
> src/station.c:station_connect_cb() 85, result: 5
> src/station.c:station_disconnect_cb() 85, success: 1
> event: state, old: disconnecting, new: disconnected
> src/netdev.c:netdev_mlme_notify() MLME notification Authenticate(37)
> src/netdev.c:netdev_authenticate_event()
> Unexpected connection related event -- is another supplicant running?
> src/netdev.c:netdev_mlme_notify() MLME notification Authenticate(37)
> src/netdev.c:netdev_authenticate_event()
> Unexpected connection related event -- is another supplicant running?
> src/netdev.c:netdev_mlme_notify() MLME notification Authenticate(37)
> src/netdev.c:netdev_authenticate_event()
> Unexpected connection related event -- is another supplicant running?
> src/netdev.c:netdev_mlme_notify() MLME notification Del Station(20)
> src/netdev.c:netdev_mlme_notify() MLME notification Authenticate(37)
> src/netdev.c:netdev_authenticate_event()
> Unexpected connection related event -- is another supplicant running?
> ---
>   src/netdev.c | 19 ++++++++++++++++---
>   1 file changed, 16 insertions(+), 3 deletions(-)
> 

Applied, thanks.

Regards,
-Denis
diff mbox series

Patch

diff --git a/src/netdev.c b/src/netdev.c
index 09fac959..26e36081 100644
--- a/src/netdev.c
+++ b/src/netdev.c
@@ -3935,6 +3935,8 @@  int netdev_disconnect(struct netdev *netdev,
 {
 	struct l_genl_msg *disconnect;
 	bool send_disconnect = true;
+	bool deauth = false;
+	uint8_t aa[6];
 
 	if (!(netdev->ifi_flags & IFF_UP))
 		return -ENETDOWN;
@@ -3953,8 +3955,8 @@  int netdev_disconnect(struct netdev *netdev,
 		 * 1. We do not actually have a connect in progress (work.id
 		 *    is zero), then we can bail out early with an error.
 		 * 2. We have sent CMD_CONNECT but not fully connected. The
-		 *    CMD_CONNECT needs to be canceled and a disconnect should
-		 *    be sent.
+		 *    CMD_CONNECT needs to be canceled and a disconnect or
+		 *    deauth should be sent.
 		 * 3. Queued up the connect work, but haven't sent CMD_CONNECT
 		 *    to the kernel. This case we do not need to send a
 		 *    disconnect.
@@ -3969,6 +3971,11 @@  int netdev_disconnect(struct netdev *netdev,
 							netdev->work.id))
 			send_disconnect = false;
 
+		if (netdev->handshake && !netdev->associated) {
+			memcpy(aa, netdev->handshake->aa, 6);
+			deauth = true;
+		}
+
 		netdev_connect_failed(netdev, NETDEV_RESULT_ABORTED,
 					MMPDU_REASON_CODE_UNSPECIFIED);
 	} else {
@@ -3976,8 +3983,14 @@  int netdev_disconnect(struct netdev *netdev,
 	}
 
 	if (send_disconnect) {
-		disconnect = nl80211_build_disconnect(netdev->index,
+		if (deauth)
+			disconnect = nl80211_build_deauthenticate(
+					netdev->index, aa,
 					MMPDU_REASON_CODE_DEAUTH_LEAVING);
+		else
+			disconnect = nl80211_build_disconnect(netdev->index,
+					MMPDU_REASON_CODE_DEAUTH_LEAVING);
+
 		netdev->disconnect_cmd_id = l_genl_family_send(nl80211,
 					disconnect, netdev_cmd_disconnect_cb,
 					netdev, NULL);