diff mbox series

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

Message ID 20230822152931.276136-2-prestwoj@gmail.com (mailing list archive)
State New
Headers show
Series Support fallback if FT fails | 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. 22, 2023, 3:29 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 to relay this information to station to
handle it rather than acting like there was no response. For now
this is being hard coded to status=53, but more could be added,
or the status itself could be returned if there are other specific
status codes that need to be handled.
---
 src/ft.c | 37 ++++++++++++++++++++++++++++---------
 1 file changed, 28 insertions(+), 9 deletions(-)

Comments

James Prestwood Aug. 22, 2023, 3:34 p.m. UTC | #1
On 8/22/23 8:29 AM, James Prestwood wrote:
> 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 to relay this information to station to
> handle it rather than acting like there was no response. For now
> this is being hard coded to status=53, but more could be added,
> or the status itself could be returned if there are other specific
> status codes that need to be handled.

This part is wrong, I instead made ft_associate return the status 
directly, and station can sort out how it wants to proceed.

> ---
>   src/ft.c | 37 ++++++++++++++++++++++++++++---------
>   1 file changed, 28 insertions(+), 9 deletions(-)
> 
> diff --git a/src/ft.c b/src/ft.c
> index c51a1288..8dfc1cb7 100644
> --- a/src/ft.c
> +++ b/src/ft.c
> @@ -58,6 +58,7 @@ struct ft_info {
>   	uint32_t frequency;
>   	uint32_t ds_frequency;
>   	uint32_t offchannel_id;
> +	uint16_t status;
>   
>   	struct l_timeout *timeout;
>   	struct wiphy_radio_work_item work;
> @@ -155,6 +156,7 @@ static bool ft_parse_authentication_resp_frame(const uint8_t *data, size_t len,
>   	if (memcmp(data + 16, addr3, 6))
>   		return false;
>   
> +
>   	/* Check Authentication algorithm number is FT (2) */
>   	if (l_get_le16(data + 24) != 2)
>   		return false;
> @@ -527,8 +529,6 @@ static int ft_over_ds_parse_action_response(const uint8_t *frame,
>   		return -EINVAL;
>   
>   	status = l_get_le16(frame + 14);
> -	if (status != 0)
> -		return (int)status;
>   
>   	if (spa_out)
>   		*spa_out = spa;
> @@ -541,7 +541,7 @@ static int ft_over_ds_parse_action_response(const uint8_t *frame,
>   		*ies_len = frame_len - 16;
>   	}
>   
> -	return 0;
> +	return (int)status;
>   }
>   
>   int __ft_rx_associate(uint32_t ifindex, const uint8_t *frame, size_t frame_len)
> @@ -825,7 +825,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,6 +836,14 @@ void __ft_rx_action(uint32_t ifindex, const uint8_t *frame, size_t frame_len)
>   		return;
>   	}
>   
> +	info->status = ret;
> +
> +	if (info->status != 0) {
> +		l_debug("BSS "MAC" rejected FT action with status=%u",
> +				MAC_STR(info->aa), info->status);
> +		goto done;
> +	}
> +
>   	if (!ft_parse_ies(info, hs, ies, ies_len)) {
>   		l_debug("Could not parse action response IEs");
>   		goto ft_error;
> @@ -843,6 +851,7 @@ void __ft_rx_action(uint32_t ifindex, const uint8_t *frame, size_t frame_len)
>   
>   	info->parsed = true;
>   
> +done:
>   	l_timeout_remove(info->timeout);
>   	info->timeout = NULL;
>   
> @@ -872,6 +881,7 @@ static struct ft_info *ft_info_new(struct handshake_state *hs,
>   						target_bss->rsne[1] + 2);
>   
>   	l_getrandom(info->snonce, 32);
> +	info->status = 0xffff;
>   
>   	return info;
>   }
> @@ -998,7 +1008,6 @@ void __ft_rx_authenticate(uint32_t ifindex, const uint8_t *frame,
>   	struct netdev *netdev = netdev_find(ifindex);
>   	struct handshake_state *hs = netdev_get_handshake(netdev);
>   	struct ft_info *info;
> -	uint16_t status;
>   	const uint8_t *ies;
>   	size_t ies_len;
>   
> @@ -1008,14 +1017,14 @@ void __ft_rx_authenticate(uint32_t ifindex, const uint8_t *frame,
>   
>   	if (!ft_parse_authentication_resp_frame(frame, frame_len,
>   					info->spa, info->aa, info->aa, 2,
> -					&status, &ies, &ies_len)) {
> +					&info->status, &ies, &ies_len)) {
>   		l_debug("Could not parse auth response");
>   		return;
>   	}
>   
> -	if (status != 0) {
> +	if (info->status != 0) {
>   		l_debug("BSS "MAC" rejected FT auth with status=%u",
> -				MAC_STR(info->aa), status);
> +				MAC_STR(info->aa), info->status);
>   		goto cancel;
>   	}
>   
> @@ -1165,10 +1174,20 @@ int ft_associate(uint32_t ifindex, const uint8_t *addr)
>   	 * attempt so clear out the entry so FT-over-Air can try again.
>   	 */
>   	if (!info->parsed) {
> +		uint16_t status = info->status;
> +
>   		l_queue_remove(info_list, info);
>   		ft_info_destroy(info);
>   
> -		return -ENOENT;
> +		/*
> +		 * The status may have been successful but the IEs were invalid,
> +		 * treat this the same as no response.
> +		 */
> +		if (status == 0xffff || status == 0)
> +			return -ENOENT;
> +
> +		/* If the AP rejected for some reason, relay this to station */
> +		return (int)status;
>   	}
>   
>   	ft_prepare_handshake(info, hs);
Denis Kenzior Aug. 27, 2023, 7 p.m. UTC | #2
Hi James,

On 8/22/23 10:29, James Prestwood wrote:
> 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 to relay this information to station to
> handle it rather than acting like there was no response. For now
> this is being hard coded to status=53, but more could be added,
> or the status itself could be returned if there are other specific
> status codes that need to be handled.

Please update the description per reply to this thread.

> ---
>   src/ft.c | 37 ++++++++++++++++++++++++++++---------
>   1 file changed, 28 insertions(+), 9 deletions(-)
> 
> diff --git a/src/ft.c b/src/ft.c
> index c51a1288..8dfc1cb7 100644
> --- a/src/ft.c
> +++ b/src/ft.c
> @@ -58,6 +58,7 @@ struct ft_info {
>   	uint32_t frequency;
>   	uint32_t ds_frequency;
>   	uint32_t offchannel_id;
> +	uint16_t status;

Might want to indicate that this status is for the first step (authenticate/action)

>   
>   	struct l_timeout *timeout;
>   	struct wiphy_radio_work_item work;
> @@ -155,6 +156,7 @@ static bool ft_parse_authentication_resp_frame(const uint8_t *data, size_t len,
>   	if (memcmp(data + 16, addr3, 6))
>   		return false;
>   
> +

This is spurious?

>   	/* Check Authentication algorithm number is FT (2) */
>   	if (l_get_le16(data + 24) != 2)
>   		return false;

<snip>

> @@ -836,6 +836,14 @@ void __ft_rx_action(uint32_t ifindex, const uint8_t *frame, size_t frame_len)
>   		return;
>   	}
>   
> +	info->status = ret;
> +
> +	if (info->status != 0) {
> +		l_debug("BSS "MAC" rejected FT action with status=%u",
> +				MAC_STR(info->aa), info->status);
> +		goto done;
> +	}
> +
>   	if (!ft_parse_ies(info, hs, ies, ies_len)) {
>   		l_debug("Could not parse action response IEs");
>   		goto ft_error;

Should the status be set only once ft_parse_ies succeeded?

> @@ -843,6 +851,7 @@ void __ft_rx_action(uint32_t ifindex, const uint8_t *frame, size_t frame_len)
>   
>   	info->parsed = true;
>   
> +done:
>   	l_timeout_remove(info->timeout);
>   	info->timeout = NULL;
>   
> @@ -872,6 +881,7 @@ static struct ft_info *ft_info_new(struct handshake_state *hs,
>   						target_bss->rsne[1] + 2);
>   
>   	l_getrandom(info->snonce, 32);
> +	info->status = 0xffff;

Why is this needed?

>   
>   	return info;
>   }

<snip>

> @@ -1165,10 +1174,20 @@ int ft_associate(uint32_t ifindex, const uint8_t *addr)
>   	 * attempt so clear out the entry so FT-over-Air can try again.
>   	 */
>   	if (!info->parsed) {
> +		uint16_t status = info->status;
> +
>   		l_queue_remove(info_list, info);
>   		ft_info_destroy(info);
>   
> -		return -ENOENT;
> +		/*
> +		 * The status may have been successful but the IEs were invalid,
> +		 * treat this the same as no response.
> +		 */
> +		if (status == 0xffff || status == 0)
> +			return -ENOENT;
> +
> +		/* If the AP rejected for some reason, relay this to station */
> +		return (int)status;

I think this entire step can be dropped if you make sure status == 0 is set only 
if parsing succeeded.

>   	}
>   
>   	ft_prepare_handshake(info, hs);

Regards,
-Denis
diff mbox series

Patch

diff --git a/src/ft.c b/src/ft.c
index c51a1288..8dfc1cb7 100644
--- a/src/ft.c
+++ b/src/ft.c
@@ -58,6 +58,7 @@  struct ft_info {
 	uint32_t frequency;
 	uint32_t ds_frequency;
 	uint32_t offchannel_id;
+	uint16_t status;
 
 	struct l_timeout *timeout;
 	struct wiphy_radio_work_item work;
@@ -155,6 +156,7 @@  static bool ft_parse_authentication_resp_frame(const uint8_t *data, size_t len,
 	if (memcmp(data + 16, addr3, 6))
 		return false;
 
+
 	/* Check Authentication algorithm number is FT (2) */
 	if (l_get_le16(data + 24) != 2)
 		return false;
@@ -527,8 +529,6 @@  static int ft_over_ds_parse_action_response(const uint8_t *frame,
 		return -EINVAL;
 
 	status = l_get_le16(frame + 14);
-	if (status != 0)
-		return (int)status;
 
 	if (spa_out)
 		*spa_out = spa;
@@ -541,7 +541,7 @@  static int ft_over_ds_parse_action_response(const uint8_t *frame,
 		*ies_len = frame_len - 16;
 	}
 
-	return 0;
+	return (int)status;
 }
 
 int __ft_rx_associate(uint32_t ifindex, const uint8_t *frame, size_t frame_len)
@@ -825,7 +825,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,6 +836,14 @@  void __ft_rx_action(uint32_t ifindex, const uint8_t *frame, size_t frame_len)
 		return;
 	}
 
+	info->status = ret;
+
+	if (info->status != 0) {
+		l_debug("BSS "MAC" rejected FT action with status=%u",
+				MAC_STR(info->aa), info->status);
+		goto done;
+	}
+
 	if (!ft_parse_ies(info, hs, ies, ies_len)) {
 		l_debug("Could not parse action response IEs");
 		goto ft_error;
@@ -843,6 +851,7 @@  void __ft_rx_action(uint32_t ifindex, const uint8_t *frame, size_t frame_len)
 
 	info->parsed = true;
 
+done:
 	l_timeout_remove(info->timeout);
 	info->timeout = NULL;
 
@@ -872,6 +881,7 @@  static struct ft_info *ft_info_new(struct handshake_state *hs,
 						target_bss->rsne[1] + 2);
 
 	l_getrandom(info->snonce, 32);
+	info->status = 0xffff;
 
 	return info;
 }
@@ -998,7 +1008,6 @@  void __ft_rx_authenticate(uint32_t ifindex, const uint8_t *frame,
 	struct netdev *netdev = netdev_find(ifindex);
 	struct handshake_state *hs = netdev_get_handshake(netdev);
 	struct ft_info *info;
-	uint16_t status;
 	const uint8_t *ies;
 	size_t ies_len;
 
@@ -1008,14 +1017,14 @@  void __ft_rx_authenticate(uint32_t ifindex, const uint8_t *frame,
 
 	if (!ft_parse_authentication_resp_frame(frame, frame_len,
 					info->spa, info->aa, info->aa, 2,
-					&status, &ies, &ies_len)) {
+					&info->status, &ies, &ies_len)) {
 		l_debug("Could not parse auth response");
 		return;
 	}
 
-	if (status != 0) {
+	if (info->status != 0) {
 		l_debug("BSS "MAC" rejected FT auth with status=%u",
-				MAC_STR(info->aa), status);
+				MAC_STR(info->aa), info->status);
 		goto cancel;
 	}
 
@@ -1165,10 +1174,20 @@  int ft_associate(uint32_t ifindex, const uint8_t *addr)
 	 * attempt so clear out the entry so FT-over-Air can try again.
 	 */
 	if (!info->parsed) {
+		uint16_t status = info->status;
+
 		l_queue_remove(info_list, info);
 		ft_info_destroy(info);
 
-		return -ENOENT;
+		/*
+		 * The status may have been successful but the IEs were invalid,
+		 * treat this the same as no response.
+		 */
+		if (status == 0xffff || status == 0)
+			return -ENOENT;
+
+		/* If the AP rejected for some reason, relay this to station */
+		return (int)status;
 	}
 
 	ft_prepare_handshake(info, hs);