diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c index a95230e06..9f249d741 100644 --- a/src/ap/ctrl_iface_ap.c +++ b/src/ap/ctrl_iface_ap.c @@ -166,6 +166,15 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd, if (res >= 0) len += res; + if (sta->supp_op_classes && + buflen - len > (unsigned) (17 + 2 * sta->supp_op_classes[0])) { + len += os_snprintf(buf + len, buflen - len, "supp_op_classes="); + len += wpa_snprintf_hex(buf + len, buflen - len, + sta->supp_op_classes + 1, + sta->supp_op_classes[0]); + len += os_snprintf(buf + len, buflen - len, "\n"); + } + return len; } diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index 702ee6479..803ca8ec6 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -176,6 +176,9 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, mbo_ap_check_sta_assoc(hapd, sta, &elems); + ap_copy_sta_supp_op_classes(sta, elems.supp_op_classes, + elems.supp_op_classes_len); + if (hapd->conf->wpa) { if (ie == NULL || ielen == 0) { #ifdef CONFIG_WPS diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 84e6e15ad..b36e68dd6 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -1726,6 +1726,9 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, } #endif /* CONFIG_MBO */ + ap_copy_sta_supp_op_classes(sta, elems.supp_op_classes, + elems.supp_op_classes_len); + return WLAN_STATUS_SUCCESS; } diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h index 78db20445..1a96b3317 100644 --- a/src/ap/ieee802_11.h +++ b/src/ap/ieee802_11.h @@ -130,4 +130,8 @@ static inline u8 hostapd_mbo_ie_len(struct hostapd_data *hapd) #endif /* CONFIG_MBO */ +void ap_copy_sta_supp_op_classes(struct sta_info *sta, + const u8 *supp_op_classes, + size_t supp_op_classes_len); + #endif /* IEEE802_11_H */ diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c index 10776353c..af858f09e 100644 --- a/src/ap/ieee802_11_shared.c +++ b/src/ap/ieee802_11_shared.c @@ -558,3 +558,20 @@ u8 hostapd_mbo_ie_len(struct hostapd_data *hapd) } #endif /* CONFIG_MBO */ + + +void ap_copy_sta_supp_op_classes(struct sta_info *sta, + const u8 *supp_op_classes, + size_t supp_op_classes_len) +{ + if (!supp_op_classes) + return; + os_free(sta->supp_op_classes); + sta->supp_op_classes = os_malloc(1 + supp_op_classes_len); + if (!sta->supp_op_classes) + return; + + sta->supp_op_classes[0] = supp_op_classes_len; + os_memcpy(sta->supp_op_classes + 1, supp_op_classes, + supp_op_classes_len); +} diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index 60058e45c..c36842b39 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -328,6 +328,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) #endif /* CONFIG_SAE */ mbo_ap_sta_free(sta); + os_free(sta->supp_op_classes); os_free(sta); } diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h index 08e795e1c..e22334149 100644 --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h @@ -190,6 +190,9 @@ struct sta_info { * enum mbo_cellular_capa values */ struct mbo_non_pref_chan_info *non_pref_chan; #endif /* CONFIG_MBO */ + + u8 *supp_op_classes; /* Supported Operating Classes element, if + * received, starting from the Length field */ }; diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index 2e503b953..5b05b68f1 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -371,6 +371,10 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, elems->mb_ies.ies[elems->mb_ies.nof_ies].ie_len = elen; elems->mb_ies.nof_ies++; break; + case WLAN_EID_SUPPORTED_OPERATING_CLASSES: + elems->supp_op_classes = pos; + elems->supp_op_classes_len = elen; + break; default: unknown++; if (!show_errors) diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h index 3a3dd4d10..d9fecd6c4 100644 --- a/src/common/ieee802_11_common.h +++ b/src/common/ieee802_11_common.h @@ -62,6 +62,7 @@ struct ieee802_11_elems { const u8 *ampe; const u8 *mic; const u8 *pref_freq_list; + const u8 *supp_op_classes; u8 ssid_len; u8 supp_rates_len; @@ -92,6 +93,8 @@ struct ieee802_11_elems { u8 ampe_len; u8 mic_len; u8 pref_freq_list_len; + u8 supp_op_classes_len; + struct mb_ies_info mb_ies; };