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 <quic_sekar@quicinc.com>
This commit is contained in:
Manoj Sekar 2024-02-26 18:18:21 +05:30 committed by Jouni Malinen
parent 0e2ca2e4e2
commit 364cb7c943
4 changed files with 68 additions and 30 deletions

View file

@ -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, static u16 check_multi_ap(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *multi_ap_ie, size_t multi_ap_len) 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; sta->flags &= ~WLAN_STA_MULTI_AP;
if (!hapd->conf->multi_ap) if (!hapd->conf->multi_ap)
return WLAN_STATUS_SUCCESS; return WLAN_STATUS_SUCCESS;
if (multi_ap_ie) { status = check_multi_ap_ie(multi_ap_ie + 4, multi_ap_len - 4,
const u8 *multi_ap_subelem; &multi_ap);
if (status != WLAN_STATUS_SUCCESS)
return status;
multi_ap_subelem = get_ie(multi_ap_ie + 4, if (multi_ap.capability && multi_ap.capability != MULTI_AP_BACKHAUL_STA)
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)
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO, HOSTAPD_LEVEL_INFO,
"Multi-AP IE with unexpected value 0x%02x", "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) if (hapd->conf->multi_ap & FRONTHAUL_BSS)
return WLAN_STATUS_SUCCESS; return WLAN_STATUS_SUCCESS;

View file

@ -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, size_t add_multi_ap_ie(u8 *buf, size_t len,
const struct multi_ap_params *multi_ap) const struct multi_ap_params *multi_ap)
{ {

View file

@ -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); 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, size_t add_multi_ap_ie(u8 *buf, size_t len,
const struct multi_ap_params *multi_ap); const struct multi_ap_params *multi_ap);

View file

@ -2996,25 +2996,24 @@ static void multi_ap_process_assoc_resp(struct wpa_supplicant *wpa_s,
const u8 *ies, size_t ies_len) const u8 *ies, size_t ies_len)
{ {
struct ieee802_11_elems elems; struct ieee802_11_elems elems;
const u8 *map_sub_elem, *pos; struct multi_ap_params multi_ap;
size_t len; u16 status;
wpa_s->multi_ap_ie = 0; wpa_s->multi_ap_ie = 0;
if (!ies || if (!ies ||
ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed || ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed ||
!elems.multi_ap || elems.multi_ap_len < 7) !elems.multi_ap)
return; return;
pos = elems.multi_ap + 4; status = check_multi_ap_ie(elems.multi_ap + 4, elems.multi_ap_len - 4,
len = elems.multi_ap_len - 4; &multi_ap);
if (status != WLAN_STATUS_SUCCESS)
map_sub_elem = get_ie(pos, len, MULTI_AP_SUB_ELEM_TYPE);
if (!map_sub_elem || map_sub_elem[1] < 1)
return; return;
wpa_s->multi_ap_backhaul = !!(map_sub_elem[2] & MULTI_AP_BACKHAUL_BSS); wpa_s->multi_ap_backhaul = !!(multi_ap.capability &
wpa_s->multi_ap_fronthaul = !!(map_sub_elem[2] & MULTI_AP_BACKHAUL_BSS);
wpa_s->multi_ap_fronthaul = !!(multi_ap.capability &
MULTI_AP_FRONTHAUL_BSS); MULTI_AP_FRONTHAUL_BSS);
wpa_s->multi_ap_ie = 1; wpa_s->multi_ap_ie = 1;
} }