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>
This commit is contained in:
Jouni Malinen 2016-02-22 13:24:21 +02:00 committed by Jouni Malinen
parent 6332aaf3b2
commit 8dd49f0cff
4 changed files with 82 additions and 0 deletions

View file

@ -47,3 +47,68 @@ int mbo_ap_get_info(struct sta_info *sta, char *buf, size_t buflen)
return 0; return 0;
return ret; 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];
}
}

View file

@ -18,6 +18,8 @@ struct ieee802_11_elems;
void mbo_ap_check_sta_assoc(struct hostapd_data *hapd, struct sta_info *sta, void mbo_ap_check_sta_assoc(struct hostapd_data *hapd, struct sta_info *sta,
struct ieee802_11_elems *elems); struct ieee802_11_elems *elems);
int mbo_ap_get_info(struct sta_info *sta, char *buf, size_t buflen); 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 */ #else /* CONFIG_MBO */
@ -33,6 +35,12 @@ static inline int mbo_ap_get_info(struct sta_info *sta, char *buf,
return 0; 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 /* CONFIG_MBO */
#endif /* MBO_AP_H */ #endif /* MBO_AP_H */

View file

@ -17,6 +17,7 @@
#include "ap/ap_config.h" #include "ap/ap_config.h"
#include "ap/ap_drv_ops.h" #include "ap/ap_drv_ops.h"
#include "ap/wpa_auth.h" #include "ap/wpa_auth.h"
#include "mbo_ap.h"
#include "wnm_ap.h" #include "wnm_ap.h"
#define MAX_TFS_IE_LEN 1024 #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); MAC2STR(addr), dialog_token, type);
wpa_hexdump(MSG_MSGDUMP, "WNM: Notification Request subelements", wpa_hexdump(MSG_MSGDUMP, "WNM: Notification Request subelements",
buf, len); buf, len);
if (type == WLAN_EID_VENDOR_SPECIFIC)
mbo_ap_wnm_notification_req(hapd, addr, buf, len);
} }

View file

@ -1113,6 +1113,12 @@ enum mbo_transition_reject_reason {
MBO_TRANSITION_REJECT_REASON_SERVICES = 6, 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) */ /* Wi-Fi Direct (P2P) */
#define P2P_OUI_TYPE 9 #define P2P_OUI_TYPE 9