From: Daniel Gabay <daniel.gabay@xxxxxxxxx> Implement SPP (Signaling and Payload Protected) A-MSDU negotiation. AP advertise support in beacon/probe response RSNXE whenever: - The driver supports SPP A-MSDU. - Advertising CCMP/GCMP ciphers in RSN element. - The spp_amsdu conf option is not explicitly disabled (if the above is true, it is enabled by default). Indicate to the driver to enable SPP A-MSDU when associating station advertised SPP A-MSDU support in association request RSNXE. Signed-off-by: Daniel Gabay <daniel.gabay@xxxxxxxxx> --- src/ap/ap_drv_ops.c | 2 ++ src/ap/drv_callbacks.c | 5 +++++ src/ap/ieee802_11.c | 5 +++++ src/ap/ieee802_11_shared.c | 3 +++ src/ap/sta_info.c | 5 +++-- src/ap/sta_info.h | 1 + src/ap/wpa_auth.h | 3 +++ src/ap/wpa_auth_glue.c | 3 +++ src/ap/wpa_auth_i.h | 1 + src/ap/wpa_auth_ie.c | 15 +++++++++++++++ 10 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index 65e83f468b..8e9c41e41d 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -39,6 +39,8 @@ u32 hostapd_sta_flags_to_drv(u32 flags) 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; } diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index d660beefcf..7234a3b478 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -649,6 +649,11 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, 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, diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index a9ed6eb0fa..73e92e408c 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -4222,6 +4222,11 @@ static int __check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, 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) { diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c index 5e67216de6..32bdd49742 100644 --- a/src/ap/ieee802_11_shared.c +++ b/src/ap/ieee802_11_shared.c @@ -1136,6 +1136,9 @@ u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len) 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 */ diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index 5a7677905d..4023b75708 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -1766,7 +1766,7 @@ int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen) 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]" : ""), @@ -1790,7 +1790,8 @@ int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen) (flags & WLAN_STA_6GHZ ? "[6GHZ]" : ""), (flags & WLAN_STA_VENDOR_VHT ? "[VENDOR_VHT]" : ""), (flags & WLAN_STA_WNM_SLEEP_MODE ? - "[WNM_SLEEP_MODE]" : "")); + "[WNM_SLEEP_MODE]" : ""), + (flags & WLAN_STA_SPP_AMSDU ? "[SPP-A-MSDU]" : "")); if (os_snprintf_error(buflen, res)) res = -1; diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h index d22e86d451..0bcb1d17f9 100644 --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h @@ -22,6 +22,7 @@ /* 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) diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 9514e55b7f..7354314b81 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -319,6 +319,8 @@ struct wpa_auth_config { bool ssid_protection; int rsn_override_omit_rsnxe; + + bool spp_amsdu; }; typedef enum { @@ -459,6 +461,7 @@ int wpa_validate_osen(struct wpa_authenticator *wpa_auth, 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 * diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index 9fa9f19b7b..6b66f38188 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -277,6 +277,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, conf->no_disconnect_on_group_keyerror; wconf->rsn_override_omit_rsnxe = conf->rsn_override_omit_rsnxe; + wconf->spp_amsdu = conf->spp_amsdu; } @@ -1755,6 +1756,8 @@ int hostapd_setup_wpa(struct hostapd_data *hapd) _conf.prot_range_neg = !!(hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_PROT_RANGE_NEG_AP); + _conf.spp_amsdu = hapd->conf->spp_amsdu && + hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SPP_AMSDU; #ifdef CONFIG_IEEE80211BE _conf.mld_addr = NULL; diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h index cb902e42b9..188f51eb84 100644 --- a/src/ap/wpa_auth_i.h +++ b/src/ap/wpa_auth_i.h @@ -97,6 +97,7 @@ struct wpa_state_machine { #endif /* CONFIG_IEEE80211R_AP */ unsigned int is_wnmsleep:1; unsigned int pmkid_set:1; + unsigned int spp_amsdu:1; unsigned int ptkstart_without_success; diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c index ce7f90aff2..3e7a08421a 100644 --- a/src/ap/wpa_auth_ie.c +++ b/src/ap/wpa_auth_ie.c @@ -507,6 +507,8 @@ static u32 rsnxe_capab(struct wpa_auth_config *conf, int key_mgmt) 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; } @@ -1169,6 +1171,14 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, 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) { @@ -1412,6 +1422,11 @@ int wpa_auth_uses_mfp(struct wpa_state_machine *sm) } +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) -- 2.43.0 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap