FST: Improve parsing of Multiband IEs

Previously, MB IEs were parsed only from association event. Try to get
MB IEs from other management frames like Probe Response frames. The MB
IEs from the association event may not be up-to-date and in some cases
may actually be missing and updating the information based on other
frames can improve robustness of FST exchanges.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Dedy Lansky 2015-11-22 14:46:54 +02:00 committed by Jouni Malinen
parent b47d05aa45
commit ea7081185e

View file

@ -1844,6 +1844,50 @@ static void interworking_process_assoc_resp(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_INTERWORKING */ #endif /* CONFIG_INTERWORKING */
#ifdef CONFIG_FST
static int wpas_fst_update_mbie(struct wpa_supplicant *wpa_s,
const u8 *ie, size_t ie_len)
{
struct mb_ies_info mb_ies;
if (!ie || !ie_len || !wpa_s->fst)
return -ENOENT;
os_memset(&mb_ies, 0, sizeof(mb_ies));
while (ie_len >= 2 && mb_ies.nof_ies < MAX_NOF_MB_IES_SUPPORTED) {
size_t len;
len = 2 + ie[1];
if (len > ie_len) {
wpa_hexdump(MSG_DEBUG, "FST: Truncated IE found",
ie, ie_len);
break;
}
if (ie[0] == WLAN_EID_MULTI_BAND) {
wpa_printf(MSG_DEBUG, "MB IE of %u bytes found",
(unsigned int) len);
mb_ies.ies[mb_ies.nof_ies].ie = ie + 2;
mb_ies.ies[mb_ies.nof_ies].ie_len = len - 2;
mb_ies.nof_ies++;
}
ie_len -= len;
ie += len;
}
if (mb_ies.nof_ies > 0) {
wpabuf_free(wpa_s->received_mb_ies);
wpa_s->received_mb_ies = mb_ies_by_info(&mb_ies);
return 0;
}
return -ENOENT;
}
#endif /* CONFIG_FST */
static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s, static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
union wpa_event_data *data) union wpa_event_data *data)
{ {
@ -2026,19 +2070,6 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
if (wpa_found || rsn_found) if (wpa_found || rsn_found)
wpa_s->ap_ies_from_associnfo = 1; wpa_s->ap_ies_from_associnfo = 1;
#ifdef CONFIG_FST
wpabuf_free(wpa_s->received_mb_ies);
wpa_s->received_mb_ies = NULL;
if (wpa_s->fst) {
struct mb_ies_info mb_ies;
wpa_printf(MSG_DEBUG, "Looking for MB IE");
if (!mb_ies_info_by_ies(&mb_ies, data->assoc_info.resp_ies,
data->assoc_info.resp_ies_len))
wpa_s->received_mb_ies = mb_ies_by_info(&mb_ies);
}
#endif /* CONFIG_FST */
if (wpa_s->assoc_freq && data->assoc_info.freq && if (wpa_s->assoc_freq && data->assoc_info.freq &&
wpa_s->assoc_freq != data->assoc_info.freq) { wpa_s->assoc_freq != data->assoc_info.freq) {
wpa_printf(MSG_DEBUG, "Operating frequency changed from " wpa_printf(MSG_DEBUG, "Operating frequency changed from "
@ -2077,6 +2108,45 @@ static int wpa_supplicant_assoc_update_ie(struct wpa_supplicant *wpa_s)
} }
static void wpas_fst_update_mb_assoc(struct wpa_supplicant *wpa_s,
union wpa_event_data *data)
{
#ifdef CONFIG_FST
struct assoc_info *ai = data ? &data->assoc_info : NULL;
struct wpa_bss *bss = wpa_s->current_bss;
const u8 *ieprb, *iebcn;
wpabuf_free(wpa_s->received_mb_ies);
wpa_s->received_mb_ies = NULL;
if (ai &&
!wpas_fst_update_mbie(wpa_s, ai->resp_ies, ai->resp_ies_len)) {
wpa_printf(MSG_DEBUG,
"FST: MB IEs updated from Association Response frame");
return;
}
if (ai &&
!wpas_fst_update_mbie(wpa_s, ai->beacon_ies, ai->beacon_ies_len)) {
wpa_printf(MSG_DEBUG,
"FST: MB IEs updated from association event Beacon IEs");
return;
}
if (!bss)
return;
ieprb = (const u8 *) (bss + 1);
iebcn = ieprb + bss->ie_len;
if (!wpas_fst_update_mbie(wpa_s, ieprb, bss->ie_len))
wpa_printf(MSG_DEBUG, "FST: MB IEs updated from bss IE");
else if (!wpas_fst_update_mbie(wpa_s, iebcn, bss->beacon_ie_len))
wpa_printf(MSG_DEBUG, "FST: MB IEs updated from bss beacon IE");
#endif /* CONFIG_FST */
}
static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
union wpa_event_data *data) union wpa_event_data *data)
{ {
@ -2137,6 +2207,8 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
"WPA/RSN IEs not updated"); "WPA/RSN IEs not updated");
} }
wpas_fst_update_mb_assoc(wpa_s, data);
#ifdef CONFIG_SME #ifdef CONFIG_SME
os_memcpy(wpa_s->sme.prev_bssid, bssid, ETH_ALEN); os_memcpy(wpa_s->sme.prev_bssid, bssid, ETH_ALEN);
wpa_s->sme.prev_bssid_set = 1; wpa_s->sme.prev_bssid_set = 1;
@ -3252,6 +3324,9 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
switch (event) { switch (event) {
case EVENT_AUTH: case EVENT_AUTH:
#ifdef CONFIG_FST
wpas_fst_update_mbie(wpa_s, data->auth.ies, data->auth.ies_len);
#endif /* CONFIG_FST */
sme_event_auth(wpa_s, data); sme_event_auth(wpa_s, data);
break; break;
case EVENT_ASSOC: case EVENT_ASSOC: