Browse Source

AP: Store STA supported operating classes information

This makes hostapd track Supported Operating Classes information from
the associated STAs. The stored information is available through the STA
control interface command (supp_op_classes row) as a hexdump of the
Supported Operating Classes element starting from the Length field. This
information can be used as input to BSS transition management and
channel switching decisions.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
Jouni Malinen 9 years ago
parent
commit
adf0478e8e

+ 9 - 0
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;
 }
 

+ 3 - 0
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

+ 3 - 0
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;
 }
 

+ 4 - 0
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 */

+ 17 - 0
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);
+}

+ 1 - 0
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);
 }

+ 3 - 0
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 */
 };
 
 

+ 4 - 0
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)

+ 3 - 0
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;
 };