netdev: add SA Query delay with OCV enabled

The way a SA Query was done following a channel switch was slightly
incorrect. One because it is only needed when OCVC is set, and two
because IWD was not waiting a random delay between 0 and 5000us as
lined out by the spec. This patch fixes both these issues.
This commit is contained in:
James Prestwood 2021-10-26 15:24:27 -07:00 committed by Denis Kenzior
parent 39ba0a9ebd
commit 3a47181a50
1 changed files with 31 additions and 1 deletions

View File

@ -142,6 +142,7 @@ struct netdev {
uint16_t last_code; /* reason or status, depending on result */
struct l_timeout *neighbor_report_timeout;
struct l_timeout *sa_query_timeout;
struct l_timeout *sa_query_delay;
struct l_timeout *group_handshake_timeout;
uint16_t sa_query_id;
uint8_t prev_snonce[32];
@ -797,6 +798,11 @@ static void netdev_connect_free(struct netdev *netdev)
netdev->sa_query_timeout = NULL;
}
if (netdev->sa_query_delay) {
l_timeout_remove(netdev->sa_query_delay);
netdev->sa_query_delay = NULL;
}
if (netdev->group_handshake_timeout) {
l_timeout_remove(netdev->group_handshake_timeout);
netdev->group_handshake_timeout = NULL;
@ -5351,6 +5357,17 @@ failed:
}
static void netdev_send_sa_query_delay(struct l_timeout *timeout,
void *user_data)
{
struct netdev *netdev = user_data;
netdev_send_sa_query_request(netdev);
l_timeout_remove(netdev->sa_query_delay);
netdev->sa_query_delay = NULL;
}
static void netdev_channel_switch_event(struct l_genl_msg *msg,
struct netdev *netdev)
{
@ -5368,7 +5385,20 @@ static void netdev_channel_switch_event(struct l_genl_msg *msg,
handshake_state_set_chandef(netdev->handshake, l_steal_ptr(chandef));
netdev_send_sa_query_request(netdev);
/*
* IEEE 802.11-2020 11.9.3.2
* "If the STA chooses to perform the specified switch and
* dot11RSNAOperatingChannelValidationActivated is true and the AP has
* indicated OCVC capability, after switching to the new channel the STA
* shall wait a random delay uniformly-distributed in the range between
* zero and 5000us, and then initiate the SA query procedure"
*/
if (netdev->handshake->supplicant_ocvc &&
netdev->handshake->authenticator_ocvc)
netdev->sa_query_delay = l_timeout_create_ms(
l_getrandom_uint32() % 5,
netdev_send_sa_query_delay,
netdev, NULL);
if (!netdev->event_filter)
return;