Implement SPP (Signaling and Payload Protected) A-MSDU negotiation.
AP advertises support in the RSNXE whenever:
- The spp_amsdu configuration parameter is enabled.
- The driver supports SPP A-MSDU.
- CCMP or GCMP cipher is enabled as a pairwise cipher.
Indicate to the driver to enable SPP A-MSDU when an associating station
advertised SPP A-MSDU support in the RSNXE in (Re)Association Request
frame.
Signed-off-by: Daniel Gabay <daniel.gabay@intel.com>
res |= WPA_STA_AUTHENTICATED;
if (flags & WLAN_STA_ASSOC)
res |= WPA_STA_ASSOCIATED;
+ if (flags & WLAN_STA_SPP_AMSDU)
+ res |= WPA_STA_SPP_AMSDU;
return res;
}
else
sta->flags &= ~WLAN_STA_MFP;
+ if (wpa_auth_uses_spp_amsdu(sta->wpa_sm))
+ sta->flags |= WLAN_STA_SPP_AMSDU;
+ else
+ sta->flags &= ~WLAN_STA_SPP_AMSDU;
+
#ifdef CONFIG_IEEE80211R_AP
if (sta->auth_alg == WLAN_AUTH_FT) {
status = wpa_ft_validate_reassoc(sta->wpa_sm, req_ies,
else
sta->flags &= ~WLAN_STA_MFP;
+ if (wpa_auth_uses_spp_amsdu(sta->wpa_sm))
+ sta->flags |= WLAN_STA_SPP_AMSDU;
+ else
+ sta->flags &= ~WLAN_STA_SPP_AMSDU;
+
#ifdef CONFIG_IEEE80211R_AP
if (sta->auth_alg == WLAN_AUTH_FT) {
if (!reassoc) {
capab |= BIT(WLAN_RSNX_CAPAB_URNM_MFPR);
if (hapd->conf->ssid_protection)
capab |= BIT(WLAN_RSNX_CAPAB_SSID_PROTECTION);
+ if ((hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SPP_AMSDU) &&
+ hapd->conf->spp_amsdu)
+ capab |= BIT(WLAN_RSNX_CAPAB_SPP_A_MSDU);
if (!capab)
return eid; /* no supported extended RSN capabilities */
buf[0] = '\0';
res = os_snprintf(buf, buflen,
- "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
(flags & WLAN_STA_AUTH ? "[AUTH]" : ""),
(flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""),
(flags & WLAN_STA_AUTHORIZED ? "[AUTHORIZED]" : ""),
(flags & WLAN_STA_EHT ? "[EHT]" : ""),
(flags & WLAN_STA_6GHZ ? "[6GHZ]" : ""),
(flags & WLAN_STA_VENDOR_VHT ? "[VENDOR_VHT]" : ""),
+ (flags & WLAN_STA_SPP_AMSDU ? "[SPP-A-MSDU]" : ""),
(flags & WLAN_STA_WNM_SLEEP_MODE ?
"[WNM_SLEEP_MODE]" : ""));
if (os_snprintf_error(buflen, res))
/* STA flags */
#define WLAN_STA_AUTH BIT(0)
#define WLAN_STA_ASSOC BIT(1)
+#define WLAN_STA_SPP_AMSDU BIT(2)
#define WLAN_STA_AUTHORIZED BIT(5)
#define WLAN_STA_PENDING_POLL BIT(6) /* pending activity poll not ACKed */
#define WLAN_STA_SHORT_PREAMBLE BIT(7)
bool ssid_protection;
int rsn_override_omit_rsnxe;
+
+ bool spp_amsdu;
};
typedef enum {
struct wpa_state_machine *sm,
const u8 *osen_ie, size_t osen_ie_len);
int wpa_auth_uses_mfp(struct wpa_state_machine *sm);
+int wpa_auth_uses_spp_amsdu(struct wpa_state_machine *sm);
void wpa_auth_set_ocv(struct wpa_state_machine *sm, int ocv);
int wpa_auth_uses_ocv(struct wpa_state_machine *sm);
struct wpa_state_machine *
#include "wpa_auth_glue.h"
-static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
+static void hostapd_wpa_auth_conf(struct hostapd_iface *iface,
+ struct hostapd_bss_config *conf,
struct hostapd_config *iconf,
struct wpa_auth_config *wconf)
{
conf->no_disconnect_on_group_keyerror;
wconf->rsn_override_omit_rsnxe = conf->rsn_override_omit_rsnxe;
+ wconf->spp_amsdu = conf->spp_amsdu &&
+ (iface->drv_flags2 & WPA_DRIVER_FLAGS2_SPP_AMSDU);
}
size_t wpa_ie_len;
struct hostapd_data *tx_bss;
- hostapd_wpa_auth_conf(hapd->conf, hapd->iconf, &_conf);
+ hostapd_wpa_auth_conf(hapd->iface, hapd->conf, hapd->iconf, &_conf);
_conf.msg_ctx = hapd->msg_ctx;
tx_bss = hostapd_mbssid_get_tx_bss(hapd);
if (tx_bss != hapd)
void hostapd_reconfig_wpa(struct hostapd_data *hapd)
{
struct wpa_auth_config wpa_auth_conf;
- hostapd_wpa_auth_conf(hapd->conf, hapd->iconf, &wpa_auth_conf);
+
+ hostapd_wpa_auth_conf(hapd->iface, hapd->conf, hapd->iconf,
+ &wpa_auth_conf);
wpa_reconfig(hapd->wpa_auth, &wpa_auth_conf);
}
#endif /* CONFIG_IEEE80211R_AP */
unsigned int is_wnmsleep:1;
unsigned int pmkid_set:1;
+ unsigned int spp_amsdu:1;
unsigned int ptkstart_without_success;
capab |= BIT(WLAN_RSNX_CAPAB_URNM_MFPR);
if (conf->ssid_protection)
capab |= BIT(WLAN_RSNX_CAPAB_SSID_PROTECTION);
+ if (conf->spp_amsdu)
+ capab |= BIT(WLAN_RSNX_CAPAB_SPP_A_MSDU);
return capab;
}
return WPA_MGMT_FRAME_PROTECTION_VIOLATION;
}
+ if (wpa_auth->conf.spp_amsdu &&
+ ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SPP_A_MSDU) &&
+ (ciphers & (WPA_CIPHER_CCMP_256 | WPA_CIPHER_CCMP |
+ WPA_CIPHER_GCMP_256 | WPA_CIPHER_GCMP)))
+ sm->spp_amsdu = 1;
+ else
+ sm->spp_amsdu = 0;
+
#ifdef CONFIG_IEEE80211R_AP
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
if (mdie == NULL || mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) {
}
+int wpa_auth_uses_spp_amsdu(struct wpa_state_machine *sm)
+{
+ return sm ? sm->spp_amsdu : 0;
+}
+
#ifdef CONFIG_OCV
void wpa_auth_set_ocv(struct wpa_state_machine *sm, int ocv)