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;
-
- 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;
- }
- }
+ status = check_multi_ap_ie(multi_ap_ie + 4, multi_ap_len - 4,
+ &multi_ap);
+ if (status != WLAN_STATUS_SUCCESS)
+ return status;
- 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;
}
+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)
{
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);
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;
}