From 364cb7c9437f3a8ef515df49cdec822d6f25798e Mon Sep 17 00:00:00 2001 From: Manoj Sekar Date: Mon, 26 Feb 2024 18:18:21 +0530 Subject: [PATCH] Multi-AP: Parse the Multi-AP element using a shared helper function This makes it more convenient to handle extensions to the element and allows code to be shared between hostapd and wpa_supplicant. Signed-off-by: Manoj Sekar --- src/ap/ieee802_11.c | 29 +++++++------------- src/common/ieee802_11_common.c | 48 ++++++++++++++++++++++++++++++++++ src/common/ieee802_11_common.h | 2 ++ wpa_supplicant/events.c | 19 +++++++------- 4 files changed, 68 insertions(+), 30 deletions(-) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 77553dc61..463d904e3 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -3416,37 +3416,26 @@ static u16 check_wmm(struct hostapd_data *hapd, struct sta_info *sta, static u16 check_multi_ap(struct hostapd_data *hapd, struct sta_info *sta, const u8 *multi_ap_ie, size_t multi_ap_len) { - u8 multi_ap_value = 0; + struct multi_ap_params multi_ap; + u16 status; sta->flags &= ~WLAN_STA_MULTI_AP; if (!hapd->conf->multi_ap) return WLAN_STATUS_SUCCESS; - if (multi_ap_ie) { - const u8 *multi_ap_subelem; + status = check_multi_ap_ie(multi_ap_ie + 4, multi_ap_len - 4, + &multi_ap); + if (status != WLAN_STATUS_SUCCESS) + return status; - multi_ap_subelem = get_ie(multi_ap_ie + 4, - multi_ap_len - 4, - MULTI_AP_SUB_ELEM_TYPE); - if (multi_ap_subelem && multi_ap_subelem[1] == 1) { - multi_ap_value = multi_ap_subelem[2]; - } else { - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, - "Multi-AP IE has missing or invalid Multi-AP subelement"); - return WLAN_STATUS_INVALID_IE; - } - } - - if (multi_ap_value && multi_ap_value != MULTI_AP_BACKHAUL_STA) + if (multi_ap.capability && multi_ap.capability != MULTI_AP_BACKHAUL_STA) hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "Multi-AP IE with unexpected value 0x%02x", - multi_ap_value); + multi_ap.capability); - if (!(multi_ap_value & MULTI_AP_BACKHAUL_STA)) { + if (!(multi_ap.capability & MULTI_AP_BACKHAUL_STA)) { if (hapd->conf->multi_ap & FRONTHAUL_BSS) return WLAN_STATUS_SUCCESS; diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index 8bde67f26..38f276446 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -2571,6 +2571,54 @@ size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len) } +u16 check_multi_ap_ie(const u8 *multi_ap_ie, size_t multi_ap_len, + struct multi_ap_params *multi_ap) +{ + const struct element *elem; + bool ext_present = false; + + os_memset(multi_ap, 0, sizeof(*multi_ap)); + + for_each_element(elem, multi_ap_ie, multi_ap_len) { + u8 id = elem->id, elen = elem->datalen; + const u8 *pos = elem->data; + + switch (id) { + case MULTI_AP_SUB_ELEM_TYPE: + if (elen >= 1) { + multi_ap->capability = *pos; + ext_present = true; + } else { + wpa_printf(MSG_DEBUG, + "Multi-AP invalid Multi-AP subelement"); + return WLAN_STATUS_INVALID_IE; + } + break; + default: + wpa_printf(MSG_DEBUG, + "Ignore unknown subelement %u in Multi-AP IE", + id); + break; + } + } + + if (!for_each_element_completed(elem, multi_ap_ie, multi_ap_len)) { + wpa_printf(MSG_DEBUG, "Multi AP IE parse failed @%d", + (int) (multi_ap_ie + multi_ap_len - + (const u8 *) elem)); + wpa_hexdump(MSG_MSGDUMP, "IEs", multi_ap_ie, multi_ap_len); + } + + if (!ext_present) { + wpa_printf(MSG_DEBUG, + "Multi-AP element without Multi-AP Extension subelement"); + return WLAN_STATUS_INVALID_IE; + } + + return WLAN_STATUS_SUCCESS; +} + + size_t add_multi_ap_ie(u8 *buf, size_t len, const struct multi_ap_params *multi_ap) { diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h index 4eba71097..d038d210b 100644 --- a/src/common/ieee802_11_common.h +++ b/src/common/ieee802_11_common.h @@ -271,6 +271,8 @@ const u8 * get_vendor_ie(const u8 *ies, size_t len, u32 vendor_type); size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len); +u16 check_multi_ap_ie(const u8 *multi_ap_ie, size_t multi_ap_len, + struct multi_ap_params *multi_ap); size_t add_multi_ap_ie(u8 *buf, size_t len, const struct multi_ap_params *multi_ap); diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 78bd2a1e4..f9ee7c0b6 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -2996,25 +2996,24 @@ static void multi_ap_process_assoc_resp(struct wpa_supplicant *wpa_s, const u8 *ies, size_t ies_len) { struct ieee802_11_elems elems; - const u8 *map_sub_elem, *pos; - size_t len; + struct multi_ap_params multi_ap; + u16 status; wpa_s->multi_ap_ie = 0; if (!ies || ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed || - !elems.multi_ap || elems.multi_ap_len < 7) + !elems.multi_ap) return; - pos = elems.multi_ap + 4; - len = elems.multi_ap_len - 4; - - map_sub_elem = get_ie(pos, len, MULTI_AP_SUB_ELEM_TYPE); - if (!map_sub_elem || map_sub_elem[1] < 1) + status = check_multi_ap_ie(elems.multi_ap + 4, elems.multi_ap_len - 4, + &multi_ap); + if (status != WLAN_STATUS_SUCCESS) return; - wpa_s->multi_ap_backhaul = !!(map_sub_elem[2] & MULTI_AP_BACKHAUL_BSS); - wpa_s->multi_ap_fronthaul = !!(map_sub_elem[2] & + wpa_s->multi_ap_backhaul = !!(multi_ap.capability & + MULTI_AP_BACKHAUL_BSS); + wpa_s->multi_ap_fronthaul = !!(multi_ap.capability & MULTI_AP_FRONTHAUL_BSS); wpa_s->multi_ap_ie = 1; }