From f91e68e903ade9739fba99729940983cae9faccb Mon Sep 17 00:00:00 2001 From: Mathy Vanhoef Date: Mon, 6 Aug 2018 15:46:35 -0400 Subject: [PATCH] OCV: Perform an SA Query after a channel switch After the network changed to a new channel, perform an SA Query with the AP after a random delay if OCV was negotiated for the association. This is used to confirm that we are still operating on the real operating channel of the network. This commit is adding only the station side functionality for this, i.e., the AP behavior is not changed to disconnect stations with OCV that do not go through SA Query. Signed-off-by: Mathy Vanhoef --- src/ap/drv_callbacks.c | 2 ++ wpa_supplicant/events.c | 3 +++ wpa_supplicant/sme.c | 21 +++++++++++++++++++++ wpa_supplicant/sme.h | 5 +++++ 4 files changed, 31 insertions(+) diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index 7e71e6f8c..fa81da9f8 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -739,6 +739,8 @@ void hostapd_event_sta_opmode_changed(struct hostapd_data *hapd, const u8 *addr, void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, int offset, int width, int cf1, int cf2) { + /* 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; diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 37d429d33..8eac4be0f 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -4339,6 +4339,9 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, } #endif /* CONFIG_AP */ +#ifdef CONFIG_IEEE80211W + sme_event_ch_switch(wpa_s); +#endif /* CONFIG_IEEE80211W */ wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_CS); wnm_clear_coloc_intf_reporting(wpa_s); break; diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index c4abff6eb..779c79b43 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -2220,6 +2220,7 @@ void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable) static const unsigned int sa_query_max_timeout = 1000; static const unsigned int sa_query_retry_timeout = 201; +static const unsigned int sa_query_ch_switch_max_delay = 5000; /* in usec */ static int sme_check_sa_query_timeout(struct wpa_supplicant *wpa_s) { @@ -2368,6 +2369,26 @@ void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa, } +void sme_event_ch_switch(struct wpa_supplicant *wpa_s) +{ + unsigned int usec; + u32 _rand; + + if (wpa_s->wpa_state != WPA_COMPLETED || + !wpa_sm_ocv_enabled(wpa_s->wpa)) + return; + + wpa_dbg(wpa_s, MSG_DEBUG, + "SME: Channel switch completed - trigger new SA Query to verify new operating channel"); + sme_stop_sa_query(wpa_s); + + if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0) + _rand = os_random(); + usec = _rand % (sa_query_ch_switch_max_delay + 1); + eloop_register_timeout(0, usec, sme_sa_query_timer, wpa_s, NULL); +} + + static void sme_process_sa_query_request(struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *data, size_t len) diff --git a/wpa_supplicant/sme.h b/wpa_supplicant/sme.h index f3c822025..1a7f9e832 100644 --- a/wpa_supplicant/sme.h +++ b/wpa_supplicant/sme.h @@ -28,6 +28,7 @@ void sme_event_disassoc(struct wpa_supplicant *wpa_s, struct disassoc_info *info); void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *da, u16 reason_code); +void sme_event_ch_switch(struct wpa_supplicant *wpa_s); void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *data, size_t len); void sme_state_changed(struct wpa_supplicant *wpa_s); @@ -89,6 +90,10 @@ static inline void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, { } +static inline void sme_event_ch_switch(struct wpa_supplicant *wpa_s) +{ +} + static inline void sme_state_changed(struct wpa_supplicant *wpa_s) { }