diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index 524a15132..173549e7b 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -844,8 +844,6 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, int offset, int width, int cf1, int cf2, int finished) { - /* TODO: If OCV is enabled deauth STAs that don't perform a SA Query */ - #ifdef NEED_AP_MLME int channel, chwidth, is_dfs; u8 seg0_idx = 0, seg1_idx = 0; @@ -958,6 +956,29 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, for (i = 0; i < hapd->iface->num_bss; i++) hostapd_neighbor_set_own_report(hapd->iface->bss[i]); + +#ifdef CONFIG_OCV + if (hapd->conf->ocv) { + struct sta_info *sta; + bool check_sa_query = false; + + for (sta = hapd->sta_list; sta; sta = sta->next) { + if (wpa_auth_uses_ocv(sta->wpa_sm) && + !(sta->flags & WLAN_STA_WNM_SLEEP_MODE)) { + sta->post_csa_sa_query = 1; + check_sa_query = true; + } + } + + if (check_sa_query) { + wpa_printf(MSG_DEBUG, + "OCV: Check post-CSA SA Query initiation in 15 seconds"); + eloop_register_timeout(15, 0, + hostapd_ocv_check_csa_sa_query, + hapd, NULL); + } + } +#endif /* CONFIG_OCV */ #endif /* NEED_AP_MLME */ } diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index f9af038be..f0af4b87c 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -439,6 +439,10 @@ static void hostapd_free_hapd_data(struct hostapd_data *hapd) hostapd_clean_rrm(hapd); fils_hlp_deinit(hapd); +#ifdef CONFIG_OCV + eloop_cancel_timeout(hostapd_ocv_check_csa_sa_query, hapd, NULL); +#endif /* CONFIG_OCV */ + #ifdef CONFIG_SAE { struct hostapd_sae_commit_queue *q; @@ -3151,6 +3155,7 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta, hostapd_prune_associations(hapd, sta->addr); ap_sta_clear_disconnect_timeouts(hapd, sta); + sta->post_csa_sa_query = 0; #ifdef CONFIG_P2P if (sta->p2p_ie == NULL && !sta->no_p2p_set) { @@ -3662,3 +3667,25 @@ void hostapd_periodic_iface(struct hostapd_iface *iface) #endif /* CONFIG_NO_RADIUS */ } } + + +#ifdef CONFIG_OCV +void hostapd_ocv_check_csa_sa_query(void *eloop_ctx, void *timeout_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + struct sta_info *sta; + + wpa_printf(MSG_DEBUG, "OCV: Post-CSA SA Query initiation check"); + + for (sta = hapd->sta_list; sta; sta = sta->next) { + if (!sta->post_csa_sa_query) + continue; + + wpa_printf(MSG_DEBUG, "OCV: OCVC STA " MACSTR + " did not start SA Query after CSA - disconnect", + MAC2STR(sta->addr)); + ap_sta_disconnect(hapd, sta, sta->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + } +} +#endif /* CONFIG_OCV */ diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h index 609c84b22..b70d13fba 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -632,6 +632,7 @@ hostapd_switch_channel_fallback(struct hostapd_iface *iface, void hostapd_cleanup_cs_params(struct hostapd_data *hapd); void hostapd_periodic_iface(struct hostapd_iface *iface); int hostapd_owe_trans_get_info(struct hostapd_data *hapd); +void hostapd_ocv_check_csa_sa_query(void *eloop_ctx, void *timeout_ctx); /* utils.c */ int hostapd_register_probereq_cb(struct hostapd_data *hapd, diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c index ba8f2cf98..45a07085f 100644 --- a/src/ap/ieee802_11_shared.c +++ b/src/ap/ieee802_11_shared.c @@ -267,6 +267,8 @@ void ieee802_11_sa_query_action(struct hostapd_data *hapd, #endif /* CONFIG_OCV */ if (action_type == WLAN_SA_QUERY_REQUEST) { + if (sta) + sta->post_csa_sa_query = 0; ieee802_11_send_sa_query_resp(hapd, sa, trans_id); return; } diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h index 940d31590..ef485618a 100644 --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h @@ -122,6 +122,7 @@ struct sta_info { unsigned int hs20_t_c_filtering:1; unsigned int ft_over_ds:1; unsigned int external_dh_updated:1; + unsigned int post_csa_sa_query:1; u16 auth_alg;