Browse Source

MBO: Update STA cellular data capability based on WNM Notification

This makes hostapd parse a received WNM Notification Request frame
subelements and if a WFA MBO cellular data capability subelement is
seen, update the cellular data capability for the STA.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
Jouni Malinen 9 years ago
parent
commit
8dd49f0cff
4 changed files with 82 additions and 0 deletions
  1. 65 0
      src/ap/mbo_ap.c
  2. 8 0
      src/ap/mbo_ap.h
  3. 3 0
      src/ap/wnm_ap.c
  4. 6 0
      src/common/ieee802_11_defs.h

+ 65 - 0
src/ap/mbo_ap.c

@@ -47,3 +47,68 @@ int mbo_ap_get_info(struct sta_info *sta, char *buf, size_t buflen)
 		return 0;
 	return ret;
 }
+
+
+static void mbo_ap_wnm_notif_req_cell_capa(struct sta_info *sta,
+					   const u8 *buf, size_t len)
+{
+	if (len < 1)
+		return;
+	wpa_printf(MSG_DEBUG, "MBO: STA " MACSTR
+		   " updated cellular data capability: %u",
+		   MAC2STR(sta->addr), buf[0]);
+	sta->cell_capa = buf[0];
+}
+
+
+static void mbo_ap_wnm_notif_req_elem(struct sta_info *sta, u8 type,
+				      const u8 *buf, size_t len)
+{
+	switch (type) {
+	case WFA_WNM_NOTIF_SUBELEM_CELL_DATA_CAPA:
+		mbo_ap_wnm_notif_req_cell_capa(sta, buf, len);
+		break;
+	default:
+		wpa_printf(MSG_DEBUG,
+			   "MBO: Ignore unknown WNM Notification WFA subelement %u",
+			   type);
+		break;
+	}
+}
+
+
+void mbo_ap_wnm_notification_req(struct hostapd_data *hapd, const u8 *addr,
+				 const u8 *buf, size_t len)
+{
+	const u8 *pos, *end;
+	u8 ie_len;
+	struct sta_info *sta;
+
+	if (!hapd->conf->mbo_enabled)
+		return;
+
+	sta = ap_get_sta(hapd, addr);
+	if (!sta)
+		return;
+
+	pos = buf;
+	end = buf + len;
+
+	while (end - pos > 1) {
+		ie_len = pos[1];
+
+		if (2 + ie_len > end - pos)
+			break;
+
+		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC &&
+		    ie_len >= 4 && WPA_GET_BE24(pos + 2) == OUI_WFA)
+			mbo_ap_wnm_notif_req_elem(sta, pos[5],
+						  pos + 6, ie_len - 4);
+		else
+			wpa_printf(MSG_DEBUG,
+				   "MBO: Ignore unknown WNM Notification element %u (len=%u)",
+				   pos[0], pos[1]);
+
+		pos += 2 + pos[1];
+	}
+}

+ 8 - 0
src/ap/mbo_ap.h

@@ -18,6 +18,8 @@ struct ieee802_11_elems;
 void mbo_ap_check_sta_assoc(struct hostapd_data *hapd, struct sta_info *sta,
 			    struct ieee802_11_elems *elems);
 int mbo_ap_get_info(struct sta_info *sta, char *buf, size_t buflen);
+void mbo_ap_wnm_notification_req(struct hostapd_data *hapd, const u8 *addr,
+				 const u8 *buf, size_t len);
 
 #else /* CONFIG_MBO */
 
@@ -33,6 +35,12 @@ static inline int mbo_ap_get_info(struct sta_info *sta, char *buf,
 	return 0;
 }
 
+static inline void mbo_ap_wnm_notification_req(struct hostapd_data *hapd,
+					       const u8 *addr,
+					       const u8 *buf, size_t len)
+{
+}
+
 #endif /* CONFIG_MBO */
 
 #endif /* MBO_AP_H */

+ 3 - 0
src/ap/wnm_ap.c

@@ -17,6 +17,7 @@
 #include "ap/ap_config.h"
 #include "ap/ap_drv_ops.h"
 #include "ap/wpa_auth.h"
+#include "mbo_ap.h"
 #include "wnm_ap.h"
 
 #define MAX_TFS_IE_LEN  1024
@@ -394,6 +395,8 @@ static void ieee802_11_rx_wnm_notification_req(struct hostapd_data *hapd,
 		   MAC2STR(addr), dialog_token, type);
 	wpa_hexdump(MSG_MSGDUMP, "WNM: Notification Request subelements",
 		    buf, len);
+	if (type == WLAN_EID_VENDOR_SPECIFIC)
+		mbo_ap_wnm_notification_req(hapd, addr, buf, len);
 }
 
 

+ 6 - 0
src/common/ieee802_11_defs.h

@@ -1113,6 +1113,12 @@ enum mbo_transition_reject_reason {
 	MBO_TRANSITION_REJECT_REASON_SERVICES = 6,
 };
 
+/* MBO v0.0_r19, 4.4: WNM-Notification vendor subelements */
+enum wfa_wnm_notif_subelem_id {
+	WFA_WNM_NOTIF_SUBELEM_NON_PREF_CHAN_REPORT = 2,
+	WFA_WNM_NOTIF_SUBELEM_CELL_DATA_CAPA = 3,
+};
+
 /* Wi-Fi Direct (P2P) */
 
 #define P2P_OUI_TYPE 9