mirror of
https://github.com/vanhoefm/fragattacks.git
synced 2025-01-31 01:04:03 -05:00
HE: Add AP mode MLME/SME handling for HE stations
Process HE information in (Re)Association Request frames and add HE elements into (Re)Association Response frames when HE is enabled in the BSS. Signed-off-by: Shashidhar Lakkavalli <slakkavalli@datto.com> Signed-off-by: John Crispin <john@phrozen.org>
This commit is contained in:
parent
8f5fc369e2
commit
78d35b16de
@ -413,6 +413,8 @@ int hostapd_sta_add(struct hostapd_data *hapd,
|
|||||||
u16 listen_interval,
|
u16 listen_interval,
|
||||||
const struct ieee80211_ht_capabilities *ht_capab,
|
const struct ieee80211_ht_capabilities *ht_capab,
|
||||||
const struct ieee80211_vht_capabilities *vht_capab,
|
const struct ieee80211_vht_capabilities *vht_capab,
|
||||||
|
const struct ieee80211_he_capabilities *he_capab,
|
||||||
|
size_t he_capab_len,
|
||||||
u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps,
|
u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps,
|
||||||
int set)
|
int set)
|
||||||
{
|
{
|
||||||
@ -432,6 +434,8 @@ int hostapd_sta_add(struct hostapd_data *hapd,
|
|||||||
params.listen_interval = listen_interval;
|
params.listen_interval = listen_interval;
|
||||||
params.ht_capabilities = ht_capab;
|
params.ht_capabilities = ht_capab;
|
||||||
params.vht_capabilities = vht_capab;
|
params.vht_capabilities = vht_capab;
|
||||||
|
params.he_capab = he_capab;
|
||||||
|
params.he_capab_len = he_capab_len;
|
||||||
params.vht_opmode_enabled = !!(flags & WLAN_STA_VHT_OPMODE_ENABLED);
|
params.vht_opmode_enabled = !!(flags & WLAN_STA_VHT_OPMODE_ENABLED);
|
||||||
params.vht_opmode = vht_opmode;
|
params.vht_opmode = vht_opmode;
|
||||||
params.flags = hostapd_sta_flags_to_drv(flags);
|
params.flags = hostapd_sta_flags_to_drv(flags);
|
||||||
|
@ -41,6 +41,8 @@ int hostapd_sta_add(struct hostapd_data *hapd,
|
|||||||
u16 listen_interval,
|
u16 listen_interval,
|
||||||
const struct ieee80211_ht_capabilities *ht_capab,
|
const struct ieee80211_ht_capabilities *ht_capab,
|
||||||
const struct ieee80211_vht_capabilities *vht_capab,
|
const struct ieee80211_vht_capabilities *vht_capab,
|
||||||
|
const struct ieee80211_he_capabilities *he_capab,
|
||||||
|
size_t he_capab_len,
|
||||||
u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps,
|
u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps,
|
||||||
int set);
|
int set);
|
||||||
int hostapd_set_privacy(struct hostapd_data *hapd, int enabled);
|
int hostapd_set_privacy(struct hostapd_data *hapd, int enabled);
|
||||||
|
@ -2325,7 +2325,8 @@ static void handle_auth(struct hostapd_data *hapd,
|
|||||||
WLAN_STA_AUTHORIZED);
|
WLAN_STA_AUTHORIZED);
|
||||||
|
|
||||||
if (hostapd_sta_add(hapd, sta->addr, 0, 0, NULL, 0, 0,
|
if (hostapd_sta_add(hapd, sta->addr, 0, 0, NULL, 0, 0,
|
||||||
NULL, NULL, sta->flags, 0, 0, 0, 0)) {
|
NULL, NULL, NULL, 0,
|
||||||
|
sta->flags, 0, 0, 0, 0)) {
|
||||||
hostapd_logger(hapd, sta->addr,
|
hostapd_logger(hapd, sta->addr,
|
||||||
HOSTAPD_MODULE_IEEE80211,
|
HOSTAPD_MODULE_IEEE80211,
|
||||||
HOSTAPD_LEVEL_NOTICE,
|
HOSTAPD_LEVEL_NOTICE,
|
||||||
@ -2866,6 +2867,14 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211AC */
|
#endif /* CONFIG_IEEE80211AC */
|
||||||
|
#ifdef CONFIG_IEEE80211AX
|
||||||
|
if (hapd->iconf->ieee80211ax) {
|
||||||
|
resp = copy_sta_he_capab(hapd, sta, elems.he_capabilities,
|
||||||
|
elems.he_capabilities_len);
|
||||||
|
if (resp != WLAN_STATUS_SUCCESS)
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_IEEE80211AX */
|
||||||
|
|
||||||
#ifdef CONFIG_P2P
|
#ifdef CONFIG_P2P
|
||||||
if (elems.p2p) {
|
if (elems.p2p) {
|
||||||
@ -3228,6 +3237,7 @@ static int add_associated_sta(struct hostapd_data *hapd,
|
|||||||
{
|
{
|
||||||
struct ieee80211_ht_capabilities ht_cap;
|
struct ieee80211_ht_capabilities ht_cap;
|
||||||
struct ieee80211_vht_capabilities vht_cap;
|
struct ieee80211_vht_capabilities vht_cap;
|
||||||
|
struct ieee80211_he_capabilities he_cap;
|
||||||
int set = 1;
|
int set = 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3280,6 +3290,12 @@ static int add_associated_sta(struct hostapd_data *hapd,
|
|||||||
if (sta->flags & WLAN_STA_VHT)
|
if (sta->flags & WLAN_STA_VHT)
|
||||||
hostapd_get_vht_capab(hapd, sta->vht_capabilities, &vht_cap);
|
hostapd_get_vht_capab(hapd, sta->vht_capabilities, &vht_cap);
|
||||||
#endif /* CONFIG_IEEE80211AC */
|
#endif /* CONFIG_IEEE80211AC */
|
||||||
|
#ifdef CONFIG_IEEE80211AX
|
||||||
|
if (sta->flags & WLAN_STA_HE) {
|
||||||
|
hostapd_get_he_capab(hapd, sta->he_capab, &he_cap,
|
||||||
|
sta->he_capab_len);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_IEEE80211AX */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add the station with forced WLAN_STA_ASSOC flag. The sta->flags
|
* Add the station with forced WLAN_STA_ASSOC flag. The sta->flags
|
||||||
@ -3291,6 +3307,8 @@ static int add_associated_sta(struct hostapd_data *hapd,
|
|||||||
sta->listen_interval,
|
sta->listen_interval,
|
||||||
sta->flags & WLAN_STA_HT ? &ht_cap : NULL,
|
sta->flags & WLAN_STA_HT ? &ht_cap : NULL,
|
||||||
sta->flags & WLAN_STA_VHT ? &vht_cap : NULL,
|
sta->flags & WLAN_STA_VHT ? &vht_cap : NULL,
|
||||||
|
sta->flags & WLAN_STA_HE ? &he_cap : NULL,
|
||||||
|
sta->flags & WLAN_STA_HE ? sta->he_capab_len : 0,
|
||||||
sta->flags | WLAN_STA_ASSOC, sta->qosinfo,
|
sta->flags | WLAN_STA_ASSOC, sta->qosinfo,
|
||||||
sta->vht_opmode, sta->p2p_ie ? 1 : 0,
|
sta->vht_opmode, sta->p2p_ie ? 1 : 0,
|
||||||
set)) {
|
set)) {
|
||||||
@ -3442,6 +3460,15 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211AC */
|
#endif /* CONFIG_IEEE80211AC */
|
||||||
|
|
||||||
|
#ifdef CONFIG_IEEE80211AX
|
||||||
|
if (hapd->iconf->ieee80211ax) {
|
||||||
|
p = hostapd_eid_he_capab(hapd, p);
|
||||||
|
p = hostapd_eid_he_operation(hapd, p);
|
||||||
|
p = hostapd_eid_spatial_reuse(hapd, p);
|
||||||
|
p = hostapd_eid_he_mu_edca_parameter_set(hapd, p);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_IEEE80211AX */
|
||||||
|
|
||||||
p = hostapd_eid_ext_capab(hapd, p);
|
p = hostapd_eid_ext_capab(hapd, p);
|
||||||
p = hostapd_eid_bss_max_idle_period(hapd, p);
|
p = hostapd_eid_bss_max_idle_period(hapd, p);
|
||||||
if (sta && sta->qos_map_enabled)
|
if (sta && sta->qos_map_enabled)
|
||||||
|
@ -71,6 +71,10 @@ void hostapd_get_ht_capab(struct hostapd_data *hapd,
|
|||||||
void hostapd_get_vht_capab(struct hostapd_data *hapd,
|
void hostapd_get_vht_capab(struct hostapd_data *hapd,
|
||||||
struct ieee80211_vht_capabilities *vht_cap,
|
struct ieee80211_vht_capabilities *vht_cap,
|
||||||
struct ieee80211_vht_capabilities *neg_vht_cap);
|
struct ieee80211_vht_capabilities *neg_vht_cap);
|
||||||
|
void hostapd_get_he_capab(struct hostapd_data *hapd,
|
||||||
|
const struct ieee80211_he_capabilities *he_cap,
|
||||||
|
struct ieee80211_he_capabilities *neg_he_cap,
|
||||||
|
size_t he_capab_len);
|
||||||
int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta);
|
int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta);
|
||||||
u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
const u8 *ht_capab);
|
const u8 *ht_capab);
|
||||||
@ -86,6 +90,8 @@ u16 copy_sta_vht_oper(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
const u8 *vht_oper);
|
const u8 *vht_oper);
|
||||||
u16 set_sta_vht_opmode(struct hostapd_data *hapd, struct sta_info *sta,
|
u16 set_sta_vht_opmode(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
const u8 *vht_opmode);
|
const u8 *vht_opmode);
|
||||||
|
u16 copy_sta_he_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
|
const u8 *he_capab, size_t he_capab_len);
|
||||||
void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
|
void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
|
||||||
const u8 *buf, size_t len, int ack);
|
const u8 *buf, size_t len, int ack);
|
||||||
void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
|
void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* hostapd / IEEE 802.11ax HE
|
* hostapd / IEEE 802.11ax HE
|
||||||
* Copyright (c) 2016-2017, Qualcomm Atheros, Inc.
|
* Copyright (c) 2016-2017, Qualcomm Atheros, Inc.
|
||||||
|
* Copyright (c) 2019 John Crispin <john@phrozen.org>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* See README for more details.
|
||||||
@ -13,6 +14,7 @@
|
|||||||
#include "hostapd.h"
|
#include "hostapd.h"
|
||||||
#include "ap_config.h"
|
#include "ap_config.h"
|
||||||
#include "beacon.h"
|
#include "beacon.h"
|
||||||
|
#include "sta_info.h"
|
||||||
#include "ieee802_11.h"
|
#include "ieee802_11.h"
|
||||||
#include "dfs.h"
|
#include "dfs.h"
|
||||||
|
|
||||||
@ -236,3 +238,104 @@ u8 * hostapd_eid_spatial_reuse(struct hostapd_data *hapd, u8 *eid)
|
|||||||
|
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void hostapd_get_he_capab(struct hostapd_data *hapd,
|
||||||
|
const struct ieee80211_he_capabilities *he_cap,
|
||||||
|
struct ieee80211_he_capabilities *neg_he_cap,
|
||||||
|
size_t he_capab_len)
|
||||||
|
{
|
||||||
|
if (!he_cap)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (he_capab_len > sizeof(*neg_he_cap))
|
||||||
|
he_capab_len = sizeof(*neg_he_cap);
|
||||||
|
/* TODO: mask out unsupported features */
|
||||||
|
|
||||||
|
os_memcpy(neg_he_cap, he_cap, he_capab_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int check_valid_he_mcs(struct hostapd_data *hapd, const u8 *sta_he_capab)
|
||||||
|
{
|
||||||
|
u16 sta_rx_mcs_set, ap_tx_mcs_set;
|
||||||
|
u8 mcs_count = 0;
|
||||||
|
const u16 *ap_mcs_set, *sta_mcs_set;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!hapd->iface->current_mode)
|
||||||
|
return 1;
|
||||||
|
ap_mcs_set = (u16 *) hapd->iface->current_mode->he_capab.mcs;
|
||||||
|
sta_mcs_set = (u16 *) ((const struct ieee80211_he_capabilities *)
|
||||||
|
sta_he_capab)->optional;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Disable HE capabilities for STAs for which there is not even a single
|
||||||
|
* allowed MCS in any supported number of streams, i.e., STA is
|
||||||
|
* advertising 3 (not supported) as HE MCS rates for all supported
|
||||||
|
* band/stream cases.
|
||||||
|
*/
|
||||||
|
switch (hapd->iface->conf->he_oper_chwidth) {
|
||||||
|
case CHANWIDTH_80P80MHZ:
|
||||||
|
mcs_count = 3;
|
||||||
|
break;
|
||||||
|
case CHANWIDTH_160MHZ:
|
||||||
|
mcs_count = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mcs_count = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < mcs_count; i++) {
|
||||||
|
int j;
|
||||||
|
|
||||||
|
/* AP Tx MCS map vs. STA Rx MCS map */
|
||||||
|
sta_rx_mcs_set = WPA_GET_LE16((const u8 *) &sta_mcs_set[i * 2]);
|
||||||
|
ap_tx_mcs_set = WPA_GET_LE16((const u8 *)
|
||||||
|
&ap_mcs_set[(i * 2) + 1]);
|
||||||
|
|
||||||
|
for (j = 0; j < HE_NSS_MAX_STREAMS; j++) {
|
||||||
|
if (((ap_tx_mcs_set >> (j * 2)) & 0x3) == 3)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (((sta_rx_mcs_set >> (j * 2)) & 0x3) == 3)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"No matching HE MCS found between AP TX and STA RX");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
u16 copy_sta_he_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
|
const u8 *he_capab, size_t he_capab_len)
|
||||||
|
{
|
||||||
|
if (!he_capab || !hapd->iconf->ieee80211ax ||
|
||||||
|
!check_valid_he_mcs(hapd, he_capab) ||
|
||||||
|
he_capab_len > sizeof(struct ieee80211_he_capabilities)) {
|
||||||
|
sta->flags &= ~WLAN_STA_HE;
|
||||||
|
os_free(sta->he_capab);
|
||||||
|
sta->he_capab = NULL;
|
||||||
|
return WLAN_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sta->he_capab) {
|
||||||
|
sta->he_capab =
|
||||||
|
os_zalloc(sizeof(struct ieee80211_he_capabilities));
|
||||||
|
if (!sta->he_capab)
|
||||||
|
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
sta->flags |= WLAN_STA_HE;
|
||||||
|
os_memset(sta->he_capab, 0, sizeof(struct ieee80211_he_capabilities));
|
||||||
|
os_memcpy(sta->he_capab, he_capab, he_capab_len);
|
||||||
|
sta->he_capab_len = he_capab_len;
|
||||||
|
|
||||||
|
return WLAN_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
@ -330,6 +330,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
|||||||
os_free(sta->ht_capabilities);
|
os_free(sta->ht_capabilities);
|
||||||
os_free(sta->vht_capabilities);
|
os_free(sta->vht_capabilities);
|
||||||
os_free(sta->vht_operation);
|
os_free(sta->vht_operation);
|
||||||
|
os_free(sta->he_capab);
|
||||||
hostapd_free_psk_list(sta->psk);
|
hostapd_free_psk_list(sta->psk);
|
||||||
os_free(sta->identity);
|
os_free(sta->identity);
|
||||||
os_free(sta->radius_cui);
|
os_free(sta->radius_cui);
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#define WLAN_STA_VENDOR_VHT BIT(21)
|
#define WLAN_STA_VENDOR_VHT BIT(21)
|
||||||
#define WLAN_STA_PENDING_FILS_ERP BIT(22)
|
#define WLAN_STA_PENDING_FILS_ERP BIT(22)
|
||||||
#define WLAN_STA_MULTI_AP BIT(23)
|
#define WLAN_STA_MULTI_AP BIT(23)
|
||||||
|
#define WLAN_STA_HE BIT(24)
|
||||||
#define WLAN_STA_PENDING_DISASSOC_CB BIT(29)
|
#define WLAN_STA_PENDING_DISASSOC_CB BIT(29)
|
||||||
#define WLAN_STA_PENDING_DEAUTH_CB BIT(30)
|
#define WLAN_STA_PENDING_DEAUTH_CB BIT(30)
|
||||||
#define WLAN_STA_NONERP BIT(31)
|
#define WLAN_STA_NONERP BIT(31)
|
||||||
@ -166,6 +167,8 @@ struct sta_info {
|
|||||||
struct ieee80211_vht_capabilities *vht_capabilities;
|
struct ieee80211_vht_capabilities *vht_capabilities;
|
||||||
struct ieee80211_vht_operation *vht_operation;
|
struct ieee80211_vht_operation *vht_operation;
|
||||||
u8 vht_opmode;
|
u8 vht_opmode;
|
||||||
|
struct ieee80211_he_capabilities *he_capab;
|
||||||
|
size_t he_capab_len;
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211W
|
#ifdef CONFIG_IEEE80211W
|
||||||
int sa_query_count; /* number of pending SA Query requests;
|
int sa_query_count; /* number of pending SA Query requests;
|
||||||
|
@ -1280,6 +1280,8 @@ struct ieee80211_ampe_ie {
|
|||||||
#define CHANWIDTH_160MHZ 2
|
#define CHANWIDTH_160MHZ 2
|
||||||
#define CHANWIDTH_80P80MHZ 3
|
#define CHANWIDTH_80P80MHZ 3
|
||||||
|
|
||||||
|
#define HE_NSS_MAX_STREAMS 8
|
||||||
|
|
||||||
#define OUI_MICROSOFT 0x0050f2 /* Microsoft (also used in Wi-Fi specs)
|
#define OUI_MICROSOFT 0x0050f2 /* Microsoft (also used in Wi-Fi specs)
|
||||||
* 00:50:F2 */
|
* 00:50:F2 */
|
||||||
#define WPA_IE_VENDOR_TYPE 0x0050f201
|
#define WPA_IE_VENDOR_TYPE 0x0050f201
|
||||||
|
Loading…
Reference in New Issue
Block a user