diff mbox series

[v3,1/3] ft: track FT auth/action response status

Message ID 20230831123924.531560-1-prestwoj@gmail.com (mailing list archive)
State Accepted, archived
Headers show
Series [v3,1/3] ft: track FT auth/action response status | expand

Checks

Context Check Description
tedd_an/pre-ci_am fail error: patch failed: src/ft.c:58 error: src/ft.c: patch does not apply hint: Use 'git am --show-current-patch' to see the failed patch

Commit Message

James Prestwood Aug. 31, 2023, 12:39 p.m. UTC
Certain return codes, though failures, can indicate that the AP is
just confused or booting up and treating it as a full failure may
not be the best route.

For example in some production deployments if an AP is rebooted it
may take some time for neighboring APs to exchange keys for
current associations. If a client roams during that time it will
reject saying the PMKID is invalid.

Use the ft_associate call return to communicate the status (if any)
that was in the auth/action response. If there was a parsing error
or no response -ENOENT is still returned.
---
 src/ft.c | 37 ++++++++++++++++++++++++++-----------
 1 file changed, 26 insertions(+), 11 deletions(-)

v3:
 * Reordered action parsing to not set IEs unless status == 0
diff mbox series

Patch

diff --git a/src/ft.c b/src/ft.c
index c51a1288..2cc611b8 100644
--- a/src/ft.c
+++ b/src/ft.c
@@ -58,13 +58,14 @@  struct ft_info {
 	uint32_t frequency;
 	uint32_t ds_frequency;
 	uint32_t offchannel_id;
+	/* Status of Authenticate/Action frame response, or error (< 0) */
+	int status;
 
 	struct l_timeout *timeout;
 	struct wiphy_radio_work_item work;
 
 	struct ie_ft_info ft_info;
 
-	bool parsed : 1;
 	bool onchannel : 1;
 };
 
@@ -526,22 +527,23 @@  static int ft_over_ds_parse_action_response(const uint8_t *frame,
 	if (memcmp(spa, hdr->address_1, 6))
 		return -EINVAL;
 
-	status = l_get_le16(frame + 14);
-	if (status != 0)
-		return (int)status;
-
 	if (spa_out)
 		*spa_out = spa;
 
 	if (aa_out)
 		*aa_out = aa;
 
+	status = l_get_le16(frame + 14);
+	if (status != 0)
+		goto done;
+
 	if (ies_out && ies_len) {
 		*ies_out = frame + 16;
 		*ies_len = frame_len - 16;
 	}
 
-	return 0;
+done:
+	return (int)status;
 }
 
 int __ft_rx_associate(uint32_t ifindex, const uint8_t *frame, size_t frame_len)
@@ -825,7 +827,7 @@  void __ft_rx_action(uint32_t ifindex, const uint8_t *frame, size_t frame_len)
 
 	ret = ft_over_ds_parse_action_response(frame, frame_len, &spa, &aa,
 						&ies, &ies_len);
-	if (ret != 0) {
+	if (ret < 0) {
 		l_debug("Could not parse action response");
 		return;
 	}
@@ -836,13 +838,22 @@  void __ft_rx_action(uint32_t ifindex, const uint8_t *frame, size_t frame_len)
 		return;
 	}
 
+
+	if (ret != 0) {
+		l_debug("BSS "MAC" rejected FT action with status=%u",
+				MAC_STR(info->aa), ret);
+		info->status = ret;
+		goto done;
+	}
+
 	if (!ft_parse_ies(info, hs, ies, ies_len)) {
 		l_debug("Could not parse action response IEs");
 		goto ft_error;
 	}
 
-	info->parsed = true;
+	info->status = ret;
 
+done:
 	l_timeout_remove(info->timeout);
 	info->timeout = NULL;
 
@@ -872,6 +883,7 @@  static struct ft_info *ft_info_new(struct handshake_state *hs,
 						target_bss->rsne[1] + 2);
 
 	l_getrandom(info->snonce, 32);
+	info->status = -ENOENT;
 
 	return info;
 }
@@ -1016,6 +1028,7 @@  void __ft_rx_authenticate(uint32_t ifindex, const uint8_t *frame,
 	if (status != 0) {
 		l_debug("BSS "MAC" rejected FT auth with status=%u",
 				MAC_STR(info->aa), status);
+		info->status = status;
 		goto cancel;
 	}
 
@@ -1024,7 +1037,7 @@  void __ft_rx_authenticate(uint32_t ifindex, const uint8_t *frame,
 		goto cancel;
 	}
 
-	info->parsed = true;
+	info->status = status;
 
 cancel:
 	/*
@@ -1164,11 +1177,13 @@  int ft_associate(uint32_t ifindex, const uint8_t *addr)
 	 * Either failed or no response. This may have been an FT-over-DS
 	 * attempt so clear out the entry so FT-over-Air can try again.
 	 */
-	if (!info->parsed) {
+	if (info->status != 0) {
+		int status = info->status;
+
 		l_queue_remove(info_list, info);
 		ft_info_destroy(info);
 
-		return -ENOENT;
+		return status;
 	}
 
 	ft_prepare_handshake(info, hs);