From ccd702f7da4be5544f5facb21f29044c1dcd1d32 Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Thu, 28 Mar 2024 10:37:45 -0700 Subject: [PATCH] netdev: use CMD_DEAUTHENTICATE when needed on disconnect 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(-) 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);