@@ -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;
@@ -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
@@ -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)
{
@@ -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);
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@cs.kuleuven.be> --- 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(+)