diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index f0d6a4ccb..b9443ee24 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -642,7 +642,7 @@ void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr) { struct sta_info *sta = ap_get_sta(hapd, addr); - if (!sta || !hapd->conf->disassoc_low_ack) + if (!sta || !hapd->conf->disassoc_low_ack || sta->agreed_to_steer) return; hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index 49a0dbe85..154879c06 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -361,6 +361,10 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) os_free(sta->ext_capability); +#ifdef CONFIG_WNM_AP + eloop_cancel_timeout(ap_sta_reset_steer_flag_timer, hapd, sta); +#endif /* CONFIG_WNM_AP */ + os_free(sta); } diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h index b4e7806db..255ac1fee 100644 --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h @@ -115,6 +115,7 @@ struct sta_info { unsigned int added_unassoc:1; unsigned int pending_wds_enable:1; unsigned int power_capab:1; + unsigned int agreed_to_steer:1; u16 auth_alg; diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c index f0462829f..710fe502b 100644 --- a/src/ap/wnm_ap.c +++ b/src/ap/wnm_ap.c @@ -341,6 +341,19 @@ static void ieee802_11_rx_bss_trans_mgmt_query(struct hostapd_data *hapd, } +void ap_sta_reset_steer_flag_timer(void *eloop_ctx, void *timeout_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + struct sta_info *sta = timeout_ctx; + + if (sta->agreed_to_steer) { + wpa_printf(MSG_DEBUG, "%s: Reset steering flag for STA " MACSTR, + hapd->conf->iface, MAC2STR(sta->addr)); + sta->agreed_to_steer = 0; + } +} + + static void ieee802_11_rx_bss_trans_mgmt_resp(struct hostapd_data *hapd, const u8 *addr, const u8 *frm, size_t len) @@ -348,6 +361,7 @@ static void ieee802_11_rx_bss_trans_mgmt_resp(struct hostapd_data *hapd, u8 dialog_token, status_code, bss_termination_delay; const u8 *pos, *end; int enabled = hapd->conf->bss_transition; + struct sta_info *sta; #ifdef CONFIG_MBO if (hapd->conf->mbo_enabled) @@ -379,11 +393,23 @@ static void ieee802_11_rx_bss_trans_mgmt_resp(struct hostapd_data *hapd, "bss_termination_delay=%u", MAC2STR(addr), dialog_token, status_code, bss_termination_delay); + sta = ap_get_sta(hapd, addr); + if (!sta) { + wpa_printf(MSG_DEBUG, "Station " MACSTR + " not found for received BSS TM Response", + MAC2STR(addr)); + return; + } + if (status_code == WNM_BSS_TM_ACCEPT) { if (end - pos < ETH_ALEN) { wpa_printf(MSG_DEBUG, "WNM: not enough room for Target BSSID field"); return; } + sta->agreed_to_steer = 1; + eloop_cancel_timeout(ap_sta_reset_steer_flag_timer, hapd, sta); + eloop_register_timeout(2, 0, ap_sta_reset_steer_flag_timer, + hapd, sta); wpa_printf(MSG_DEBUG, "WNM: Target BSSID: " MACSTR, MAC2STR(pos)); wpa_msg(hapd->msg_ctx, MSG_INFO, BSS_TM_RESP MACSTR @@ -393,6 +419,7 @@ static void ieee802_11_rx_bss_trans_mgmt_resp(struct hostapd_data *hapd, MAC2STR(pos)); pos += ETH_ALEN; } else { + sta->agreed_to_steer = 0; wpa_msg(hapd->msg_ctx, MSG_INFO, BSS_TM_RESP MACSTR " status_code=%u bss_termination_delay=%u", MAC2STR(addr), status_code, bss_termination_delay); diff --git a/src/ap/wnm_ap.h b/src/ap/wnm_ap.h index a44eadb85..56d0f881e 100644 --- a/src/ap/wnm_ap.h +++ b/src/ap/wnm_ap.h @@ -23,5 +23,6 @@ int wnm_send_bss_tm_req(struct hostapd_data *hapd, struct sta_info *sta, const u8 *bss_term_dur, const char *url, const u8 *nei_rep, size_t nei_rep_len, const u8 *mbo_attrs, size_t mbo_len); +void ap_sta_reset_steer_flag_timer(void *eloop_ctx, void *timeout_ctx); #endif /* WNM_AP_H */