diff --git a/src/ap/mbo_ap.c b/src/ap/mbo_ap.c index 940f69342..287cece78 100644 --- a/src/ap/mbo_ap.c +++ b/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]; + } +} diff --git a/src/ap/mbo_ap.h b/src/ap/mbo_ap.h index 9c6aedac5..cee2300d7 100644 --- a/src/ap/mbo_ap.h +++ b/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 */ diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c index 1cf84c66c..6af460ab7 100644 --- a/src/ap/wnm_ap.c +++ b/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); } diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 9b06daddb..73ffc9998 100644 --- a/src/common/ieee802_11_defs.h +++ b/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