After the network changed to a new channel, perform a SA Query with the AP after a random delay. This is used to confirm that we are still operating on the real operating channel of the network. Signed-off-by: Mathy Vanhoef <Mathy.Vanhoef@xxxxxxxxxxxxxx> --- src/ap/drv_callbacks.c | 2 ++ wpa_supplicant/events.c | 1 + wpa_supplicant/sme.c | 22 ++++++++++++++++++++++ wpa_supplicant/sme.h | 1 + 4 files changed, 26 insertions(+) diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index 1b15d3a69..a175c807b 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -735,6 +735,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 fb77f1dbd..428cb7368 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -4295,6 +4295,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, } #endif /* CONFIG_AP */ + sme_event_ch_switch(wpa_s); wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_CS); break; #ifdef CONFIG_AP diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index a9202e28a..e699eb5b2 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -2051,6 +2051,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) { @@ -2197,6 +2198,27 @@ 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) + return; + if (!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..ea20da78f 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); -- 2.18.0 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap