From 7e9708ddbcb5f7f83c2dffab7c3ddb7a8c648fbe Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Tue, 28 Sep 2021 14:27:37 -0700 Subject: [PATCH] station: start FT-over-DS actions after roaming Once roamed IWD never sent out any FT Request frames. This prevented FT-over-DS from being used after an initial roam. --- src/station.c | 149 +++++++++++++++++++++++++------------------------- 1 file changed, 74 insertions(+), 75 deletions(-) diff --git a/src/station.c b/src/station.c index 2e7fd0f9..f12cdde5 100644 --- a/src/station.c +++ b/src/station.c @@ -1729,6 +1729,77 @@ static void station_early_neighbor_report_cb(struct netdev *netdev, int err, &station->roam_freqs); } +static bool station_can_fast_transition(struct handshake_state *hs, + struct scan_bss *bss) +{ + uint16_t mdid; + + if (!hs->mde) + return false; + + if (ie_parse_mobility_domain_from_data(hs->mde, hs->mde[1] + 2, + &mdid, NULL, NULL) < 0) + return false; + + if (!(bss->mde_present && l_get_le16(bss->mde) == mdid)) + return false; + + if (hs->supplicant_ie != NULL) { + struct ie_rsn_info rsn_info; + + if (!IE_AKM_IS_FT(hs->akm_suite)) + return false; + + if (scan_bss_get_rsn_info(bss, &rsn_info) < 0) + return false; + + if (!IE_AKM_IS_FT(rsn_info.akm_suites)) + return false; + } + + return true; +} + +static void station_ft_ds_action_start(struct station *station) +{ + struct handshake_state *hs = netdev_get_handshake(station->netdev); + uint16_t mdid; + const struct l_queue_entry *entry; + struct scan_bss *bss; + struct ie_rsn_info rsn_info; + + if (!station_can_fast_transition(hs, station->connected_bss) || + !(hs->mde[4] & 1)) + return; + + if (ie_parse_mobility_domain_from_data(hs->mde, hs->mde[1] + 2, + &mdid, NULL, NULL) < 0) + return; + + for (entry = network_bss_list_get_entries(station->connected_network); + entry; entry = entry->next) { + bss = entry->data; + + if (bss == station->connected_bss) + continue; + + if (mdid != l_get_le16(bss->mde)) + continue; + + if (scan_bss_get_rsn_info(bss, &rsn_info) < 0) + continue; + + if (!IE_AKM_IS_FT(rsn_info.akm_suites)) + continue; + + /* + * Fire and forget. Netdev will maintain a cache of responses and + * when the time comes these can be referenced for a roam + */ + netdev_fast_transition_over_ds_action(station->netdev, bss); + } +} + static void station_roamed(struct station *station) { station->roam_scan_full = false; @@ -1754,6 +1825,8 @@ static void station_roamed(struct station *station) l_warn("Could not request neighbor report"); } + station_ft_ds_action_start(station); + station_enter_state(station, STATION_STATE_CONNECTED); } @@ -1957,37 +2030,6 @@ static void station_preauthenticate_cb(struct netdev *netdev, station_transition_reassociate(station, bss, new_hs); } -static bool station_can_fast_transition(struct handshake_state *hs, - struct scan_bss *bss) -{ - uint16_t mdid; - - if (!hs->mde) - return false; - - if (ie_parse_mobility_domain_from_data(hs->mde, hs->mde[1] + 2, - &mdid, NULL, NULL) < 0) - return false; - - if (!(bss->mde_present && l_get_le16(bss->mde) == mdid)) - return false; - - if (hs->supplicant_ie != NULL) { - struct ie_rsn_info rsn_info; - - if (!IE_AKM_IS_FT(hs->akm_suite)) - return false; - - if (scan_bss_get_rsn_info(bss, &rsn_info) < 0) - return false; - - if (!IE_AKM_IS_FT(rsn_info.akm_suites)) - return false; - } - - return true; -} - static void station_transition_start(struct station *station, struct scan_bss *bss) { @@ -2624,36 +2666,6 @@ static bool station_retry_with_status(struct station *station, return station_try_next_bss(station); } -static void station_ft_ds_action_start(struct station *station, uint16_t mdid) -{ - const struct l_queue_entry *entry; - struct scan_bss *bss; - struct ie_rsn_info rsn_info; - - for (entry = network_bss_list_get_entries(station->connected_network); - entry; entry = entry->next) { - bss = entry->data; - - if (bss == station->connected_bss) - continue; - - if (mdid != l_get_le16(bss->mde)) - continue; - - if (scan_bss_get_rsn_info(bss, &rsn_info) < 0) - continue; - - if (!IE_AKM_IS_FT(rsn_info.akm_suites)) - continue; - - /* - * Fire and forget. Netdev will maintain a cache of responses and - * when the time comes these can be referenced for a roam - */ - netdev_fast_transition_over_ds_action(station->netdev, bss); - } -} - static void station_connect_ok(struct station *station) { struct handshake_state *hs = netdev_get_handshake(station->netdev); @@ -2677,20 +2689,7 @@ static void station_connect_ok(struct station *station) l_warn("Could not request neighbor report"); } - /* - * If this network supports FT-over-DS send initial action frames now - * to prepare for future roams. - */ - if (station_can_fast_transition(hs, station->connected_bss) && - (hs->mde[4] & 1)) { - uint16_t mdid; - - if (ie_parse_mobility_domain_from_data(hs->mde, hs->mde[1] + 2, - &mdid, NULL, NULL) < 0) - return; - - station_ft_ds_action_start(station, mdid); - } + station_ft_ds_action_start(station); network_connected(station->connected_network);