wpa: Update to 2.12

Fixes and new features include:

hostapd:
* support RSN overriding (e.g., WPA3-Personal Compatibility Mode)
* EHT/IEEE 802.11be/Wi-Fi 7
  - more complete support
  - fix message validation issues that could enable DoS attacks
  - fix group key rekeying
* enable SAE group 20 by default if SAE-EXT-KEY is enabled
* reject unexpected SAE password identifier to avoid DoS attack against
  a specific STA
* mandate use of SAE H2E when using password identifiers
* assign VLAN when using SAE with PMKSA caching
* support SPP A-MSDU negotiation
* support IEEE 802.11bi functionality
  - changing SAE password identifiers
  - EPPKE
  - IEEE 802.1X/EAP in Authentication frames
  - Association frame encryption
  - PMKID privacy
* remove the driver interface for now obsolete Host AP driver
* remove the driver interface for now obsolete Atheros WEXT interface
* move supported, basic, and Beacon TX rate configuration to be at BSS
  level instead of per-radio for all BSSs
* fix various issues in Multiple-BSSID functionality
* support OpenSSL 3.0 API changes
* EAP-TEAP: protocol changes based on RFC 9930; this is not compatible
  with previous versions
* support Automated Frequency Coordination (AFC) on the 6 GHz band
* improve GAS/ANQP processing to support larger ANQP responses
* a large number of other fixes, cleanup, and extensions

wpa_supplicant:
* support RSN overriding (e.g., WPA3-Personal Compatibility Mode)
* improve BSS transition management support
* EHT/IEEE 802.11be/Wi-Fi 7
  - more complete support
  - fix message validation issues that could enable DoS attacks
* support Wi-Fi Direct R2
* support Wi-Fi Aware (add synchronized NAN; extend USD support)
* support Proximity Ranging
* support SPP A-MSDU negotiation
* support IEEE 802.11bi functionality
  - changing SAE password identifiers
  - EPPKE
  - IEEE 802.1X/EAP in Authentication frames
  - Association frame encryption
  - PMKID privacy
* enable layer 2/Wi-Fi multicast filtering for all networks (not
  just some Passpoint networks which enabled this before)
* wpa_gui: port to Qt6
* support OpenSSL 3.0 API changes
* EAP-TEAP: protocol changes based on RFC 9930; this is not compatible
  with previous versions
* maintain configuration file permissions when writing updated
  configuration
* add option to validate PKCS#11/OpenSC engine and module paths
* fix PMKSA caching to enforce network context to avoid misuse of
  unexpected PMKSA cache entries
* fix a potential DoS attack in SAE processing of an unexpected element
* fix incomplete bounds checking of mesh AMPE messages that could have
  resulted in DoS attacks and memory corruption
* a large number of other fixes, cleanup, and extensions

MFC after:	2 months

Merge commit '513264698a892550ba20aeb9da7f360417fdc63b'
This commit is contained in:
Cy Schubert committed 2026-08-10 20:54:02 -07:00
commit 71e72c9e91
336 files changed
+89793 -24630

No files matched your search

+10
View File
@@ -0,0 +1,10 @@
SUBDIRS=$(wildcard hostapd) $(wildcard wpa_supplicant)
all:
for dir in $(SUBDIRS); do $(MAKE) -C $$dir; done
clean distclean:
for dir in $(SUBDIRS); do $(MAKE) -C $$dir clean; done
install:
for dir in $(SUBDIRS); do $(MAKE) -C $$dir install; done
+1 -1
View File
@@ -1,7 +1,7 @@
wpa_supplicant and hostapd
--------------------------
Copyright (c) 2002-2024, Jouni Malinen <[email protected]> and contributors
Copyright (c) 2002-2026, Jouni Malinen <[email protected]> and contributors
All Rights Reserved.
These programs are licensed under the BSD license (the one with
+38 -2
View File
@@ -127,7 +127,7 @@ HOBJS += src/utils/trace.c
LDFLAGS += -rdynamic
L_CFLAGS += -funwind-tables
ifdef CONFIG_WPA_TRACE_BFD
L_CFLAGS += -DWPA_TRACE_BFD
L_CFLAGS += -DWPA_TRACE_BFD -fno-inline -fno-optimize-sibling-calls
LIBS += -lbfd
LIBS_c += -lbfd
LIBS_h += -lbfd
@@ -259,9 +259,10 @@ L_CFLAGS += -DCONFIG_SAE
OBJS += src/common/sae.c
ifdef CONFIG_SAE_PK
L_CFLAGS += -DCONFIG_SAE_PK
NEED_AES_SIV=y
NEED_BASE64=y
OBJS += src/common/sae_pk.c
endif
NEED_AES_SIV=y
NEED_ECC=y
NEED_DH_GROUPS=y
NEED_HMAC_SHA256_KDF=y
@@ -588,6 +589,21 @@ OBJS += src/ap/nan_usd_ap.c
L_CFLAGS += -DCONFIG_NAN_USD
endif
ifdef CONFIG_PMKSA_PRIVACY
CONFIG_ENC_ASSOC=y
L_CFLAGS += -DCONFIG_PMKSA_PRIVACY
endif
ifdef CONFIG_IEEE8021X_AUTH
CONFIG_ENC_ASSOC=y
L_CFLAGS += -DCONFIG_IEEE8021X_AUTH
endif
ifdef CONFIG_ENC_ASSOC
CONFIG_PASN=y
L_CFLAGS += -DCONFIG_ENC_ASSOC
endif
ifdef CONFIG_PASN
L_CFLAGS += -DCONFIG_PASN
L_CFLAGS += -DCONFIG_PTKSA_CACHE
@@ -936,6 +952,20 @@ endif
endif
endif
ifdef CONFIG_SAE
ifdef CONFIG_IEEE80211BE
NEED_SHA384=y
endif
ifdef NEED_SHA384
# Need to add HMAC-SHA384 KDF as well, if SHA384 was enabled.
NEED_HMAC_SHA384_KDF=y
endif
ifdef NEED_SHA512
# Need to add HMAC-SHA512 KDF as well, if SHA512 was enabled.
NEED_HMAC_SHA512_KDF=y
endif
endif
L_CFLAGS += -DCONFIG_SHA256
ifneq ($(CONFIG_TLS), openssl)
ifneq ($(CONFIG_TLS), gnutls)
@@ -1055,6 +1085,7 @@ OBJS += src/pasn/pasn_common.c
OBJS += src/ap/ieee802_11.c
OBJS += src/ap/hw_features.c
OBJS += src/ap/dfs.c
OBJS += src/ap/interference.c
L_CFLAGS += -DNEED_AP_MLME
endif
OBJS += src/ap/ieee802_11_ht.c
@@ -1125,6 +1156,11 @@ ifdef CONFIG_ANDROID_LOG
L_CFLAGS += -DCONFIG_ANDROID_LOG
endif
ifdef CONFIG_PROCESS_COORDINATION
L_CFLAGS += -DCONFIG_PROCESS_COORDINATION
OBJS += src/common/proc_coord.c
endif
OBJS_c = hostapd_cli.c
OBJS_c += src/common/wpa_ctrl.c
OBJS_c += src/utils/os_$(CONFIG_OS).c
+30
View File
@@ -1,5 +1,35 @@
ChangeLog for hostapd
2026-08-07 - v2.12
* support RSN overriding (e.g., WPA3-Personal Compatibility Mode)
* EHT/IEEE 802.11be/Wi-Fi 7
- more complete support
- fix message validation issues that could enable DoS attacks
- fix group key rekeying
* enable SAE group 20 by default if SAE-EXT-KEY is enabled
* reject unexpected SAE password identifier to avoid DoS attack against
a specific STA
* mandate use of SAE H2E when using password identifiers
* assign VLAN when using SAE with PMKSA caching
* support SPP A-MSDU negotiation
* support IEEE 802.11bi functionality
- changing SAE password identifiers
- EPPKE
- IEEE 802.1X/EAP in Authentication frames
- Association frame encryption
- PMKID privacy
* remove the driver interface for now obsolete Host AP driver
* remove the driver interface for now obsolete Atheros WEXT interface
* move supported, basic, and Beacon TX rate configuration to be at BSS
level instead of per-radio for all BSSs
* fix various issues in Multiple-BSSID functionality
* support OpenSSL 3.0 API changes
* EAP-TEAP: protocol changes based on RFC 9930; this is not compatible
with previous versions
* support Automated Frequency Coordination (AFC) on the 6 GHz band
* improve GAS/ANQP processing to support larger ANQP responses
* a large number of other fixes, cleanup, and extensions
2024-07-20 - v2.11
* Wi-Fi Easy Connect
- add support for DPP release 3
+65 -2
View File
@@ -116,7 +116,7 @@ HOBJS += ../src/utils/trace.o
LDFLAGS += -rdynamic
CFLAGS += -funwind-tables
ifdef CONFIG_WPA_TRACE_BFD
CFLAGS += -DPACKAGE="hostapd" -DWPA_TRACE_BFD
CFLAGS += -DPACKAGE="hostapd" -DWPA_TRACE_BFD -fno-inline -fno-optimize-sibling-calls
LIBS += -lbfd -ldl -liberty -lz
LIBS_c += -lbfd -ldl -liberty -lz
LIBS_h += -lbfd -ldl -liberty -lz
@@ -298,9 +298,10 @@ CFLAGS += -DCONFIG_SAE
OBJS += ../src/common/sae.o
ifdef CONFIG_SAE_PK
CFLAGS += -DCONFIG_SAE_PK
NEED_AES_SIV=y
NEED_BASE64=y
OBJS += ../src/common/sae_pk.o
endif
NEED_AES_SIV=y
NEED_ECC=y
NEED_DH_GROUPS=y
NEED_HMAC_SHA256_KDF=y
@@ -354,6 +355,14 @@ CFLAGS += -DCONFIG_IEEE80211AX
OBJS += ../src/ap/ieee802_11_he.o
endif
ifdef CONFIG_IEEE80211AX
ifdef CONFIG_AFC
CFLAGS += -DCONFIG_AFC
OBJS += ../src/ap/afc.o
NEED_JSON=y
endif
endif
ifdef CONFIG_MBO
CFLAGS += -DCONFIG_MBO
OBJS += ../src/ap/mbo_ap.o
@@ -614,6 +623,21 @@ OBJS += ../src/ap/nan_usd_ap.o
CFLAGS += -DCONFIG_NAN_USD
endif
ifdef CONFIG_PMKSA_PRIVACY
CONFIG_ENC_ASSOC=y
CFLAGS += -DCONFIG_PMKSA_PRIVACY
endif
ifdef CONFIG_IEEE8021X_AUTH
CONFIG_ENC_ASSOC=y
CFLAGS += -DCONFIG_IEEE8021X_AUTH
endif
ifdef CONFIG_ENC_ASSOC
CONFIG_PASN=y
CFLAGS += -DCONFIG_ENC_ASSOC
endif
ifdef CONFIG_PASN
CFLAGS += -DCONFIG_PASN
CFLAGS += -DCONFIG_PTKSA_CACHE
@@ -708,6 +732,7 @@ CFLAGS += -DCONFIG_TLSV12
endif
ifeq ($(CONFIG_TLS), wolfssl)
CFLAGS += -DCRYPTO_RSA_OAEP_SHA256
CONFIG_CRYPTO=wolfssl
ifdef TLS_FUNCS
OBJS += ../src/crypto/tls_wolfssl.o
@@ -1065,6 +1090,20 @@ endif
endif
endif
ifdef CONFIG_SAE
ifdef CONFIG_IEEE80211BE
NEED_SHA384=y
endif
ifdef NEED_SHA384
# Need to add HMAC-SHA384 KDF as well, if SHA384 was enabled.
NEED_HMAC_SHA384_KDF=y
endif
ifdef NEED_SHA512
# Need to add HMAC-SHA512 KDF as well, if SHA512 was enabled.
NEED_HMAC_SHA512_KDF=y
endif
endif
CFLAGS += -DCONFIG_SHA256
ifneq ($(CONFIG_TLS), openssl)
ifneq ($(CONFIG_TLS), linux)
@@ -1201,6 +1240,7 @@ OBJS += ../src/pasn/pasn_common.o
OBJS += ../src/ap/ieee802_11.o
OBJS += ../src/ap/hw_features.o
OBJS += ../src/ap/dfs.o
OBJS += ../src/ap/interference.o
CFLAGS += -DNEED_AP_MLME
endif
OBJS += ../src/ap/ieee802_11_ht.o
@@ -1298,6 +1338,11 @@ ifdef CONFIG_NO_TKIP
CFLAGS += -DCONFIG_NO_TKIP
endif
ifdef CONFIG_PROCESS_COORDINATION
CFLAGS += -DCONFIG_PROCESS_COORDINATION
OBJS += ../src/common/proc_coord.o
endif
$(DESTDIR)$(BINDIR)/%: %
install -D $(<) $(@)
@@ -1365,6 +1410,16 @@ SOBJS += ../src/common/sae.o
SOBJS += ../src/common/sae_pk.o
SOBJS += ../src/common/dragonfly.o
SOBJS += $(AESOBJS)
ifneq ($(CONFIG_TLS), openssl)
ifneq ($(CONFIG_TLS), linux)
ifneq ($(CONFIG_TLS), gnutls)
ifneq ($(CONFIG_TLS), wolfssl)
SOBJS += ../src/crypto/sha384.o
SOBJS += ../src/crypto/sha512.o
endif
endif
endif
endif
SOBJS += ../src/crypto/sha256-prf.o
SOBJS += ../src/crypto/sha384-prf.o
SOBJS += ../src/crypto/sha512-prf.o
@@ -1372,6 +1427,14 @@ SOBJS += ../src/crypto/dh_groups.o
SOBJS += ../src/crypto/sha256-kdf.o
SOBJS += ../src/crypto/sha384-kdf.o
SOBJS += ../src/crypto/sha512-kdf.o
SOBJS += ../src/common/wpa_common.o
ifdef CONFIG_NO_RANDOM_POOL
CFLAGS += -DCONFIG_NO_RANDOM_POOL
else
SOBJS += ../src/crypto/random.o
endif
SOBJS += ../src/crypto/sha1-prf.o
SOBJS += ../src/utils/eloop.o
_OBJS_VAR := NOBJS
include ../src/objs.mk
+3 -8
View File
@@ -2,7 +2,7 @@ hostapd - user space IEEE 802.11 AP and IEEE 802.1X/WPA/WPA2/EAP
Authenticator and RADIUS authentication server
================================================================
Copyright (c) 2002-2024, Jouni Malinen <[email protected]> and contributors
Copyright (c) 2002-2026, Jouni Malinen <[email protected]> and contributors
All Rights Reserved.
This program is licensed under the BSD license (the one with
@@ -69,11 +69,6 @@ Requirements
Current hardware/software requirements:
- drivers:
Host AP driver for Prism2/2.5/3.
(http://w1.fi/hostap-driver.html)
Please note that station firmware version needs to be 1.7.0 or newer
to work in WPA mode.
mac80211-based drivers that support AP mode (with driver=nl80211).
This includes drivers for Atheros (ath9k) and Broadcom (b43)
chipsets.
@@ -125,7 +120,7 @@ use an external Authentication Server and encapsulate EAP frame in the
frames used by that server. RADIUS is suitable for this, but IEEE
802.1X would also allow other mechanisms.
Host AP driver includes PAE functionality in the kernel driver. It
Drivers include PAE functionality in the kernel driver. It
is a relatively simple mechanism for denying normal frames going to
or coming from an unauthorized port. PAE allows IEEE 802.1X related
frames to be passed between the Supplicant and the Authenticator even
@@ -156,7 +151,7 @@ with the Authentication Server. After this is completed successfully,
the virtual port is set to Authorized state and frames from and to the
station are accepted.
Host AP configuration for IEEE 802.1X
hostapd configuration for IEEE 802.1X
-------------------------------------
The user space daemon has its own configuration file that can be used to
+1 -1
View File
@@ -155,6 +155,6 @@ References
----------
[1] https://www.wi-fi.org/discover-wi-fi/wi-fi-easymesh
[2] https://github.com/prplfoundation/prplMesh
[2] https://gitlab.com/prpl-foundation/prplmesh/prplMesh
[3] https://www.wi-fi.org/file/multi-ap-specification-v10
(requires registration)
-3
View File
@@ -9,9 +9,6 @@
# be modified from here. In most cass, these lines should use += in order not
# to override previous values of the variables.
# Driver interface for Host AP driver
#CONFIG_DRIVER_HOSTAP=y
# Driver interface for wired authenticator
#CONFIG_DRIVER_WIRED=y
+431 -303
View File
@@ -713,14 +713,14 @@ static int hostapd_config_parse_key_mgmt(int line, const char *value)
else if (os_strcmp(start, "DPP") == 0)
val |= WPA_KEY_MGMT_DPP;
#endif /* CONFIG_DPP */
#ifdef CONFIG_HS20
else if (os_strcmp(start, "OSEN") == 0)
val |= WPA_KEY_MGMT_OSEN;
#endif /* CONFIG_HS20 */
#ifdef CONFIG_PASN
else if (os_strcmp(start, "PASN") == 0)
val |= WPA_KEY_MGMT_PASN;
#endif /* CONFIG_PASN */
#ifdef CONFIG_ENC_ASSOC
else if (os_strcmp(start, "EPPKE") == 0)
val |= WPA_KEY_MGMT_EPPKE;
#endif /* CONFIG_ENC_ASSOC */
else {
wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
line, start);
@@ -865,7 +865,7 @@ static int hostapd_parse_intlist(int **int_list, char *val)
break;
pos = end + 1;
}
list[count] = -1;
list[count] = 0;
*int_list = list;
return 0;
@@ -1269,7 +1269,7 @@ static int hostapd_parse_he_srg_bitmap(u8 *bitmap, char *val)
*end = '\0';
bitpos = atoi(pos);
if (bitpos < 0 || bitpos > 64)
if (bitpos < 0 || bitpos > 63)
return -1;
bitmap[bitpos / 8] |= BIT(bitpos % 8);
@@ -1281,6 +1281,140 @@ static int hostapd_parse_he_srg_bitmap(u8 *bitmap, char *val)
return 0;
}
#ifdef CONFIG_AFC
static int hostapd_afc_parse_cert_ids(struct hostapd_config *conf, char *pos)
{
struct afc_cert_id *c = NULL, *tmp;
unsigned int i, count = 0;
while (pos && pos[0]) {
char *p;
tmp = os_realloc_array(c, count + 1, sizeof(*c));
if (!tmp)
goto error;
c = tmp;
i = count;
count++;
os_memset(&c[i], 0, sizeof(struct afc_cert_id));
p = os_strchr(pos, ':');
if (!p)
goto error;
*p++ = '\0';
if (!p || !p[0])
goto error;
c[i].ruleset = os_strdup(pos);
if (!c[i].ruleset)
goto error;
pos = p;
p = os_strchr(pos, ',');
if (p)
*p++ = '\0';
c[i].id = os_strdup(pos);
if (!c[i].id)
goto error;
pos = p;
}
hostapd_config_free_afc_cert_ids(conf);
conf->afc.n_cert_ids = count;
conf->afc.cert_ids = c;
return 0;
error:
for (i = 0; i < count; i++) {
os_free(c[i].ruleset);
os_free(c[i].id);
}
os_free(c);
return -ENOMEM;
}
static int hostapd_afc_parse_position_data(struct afc_linear_polygon **data,
unsigned int *n_linear_polygon_data,
char *pos)
{
struct afc_linear_polygon *d = NULL, *tmp;
unsigned int count = 0;
while (pos && pos[0]) {
char *p, *end;
tmp = os_realloc_array(d, count + 1, sizeof(*d));
if (!tmp)
goto error;
d = tmp;
p = os_strchr(pos, ':');
if (!p)
goto error;
*p++ = '\0';
if (!p || !p[0])
goto error;
d[count].longitude = strtod(pos, &end);
if (*end)
goto error;
pos = p;
p = os_strchr(pos, ',');
if (p)
*p++ = '\0';
d[count].latitude = strtod(pos, &end);
if (*end)
goto error;
pos = p;
count++;
}
os_free(*data);
*n_linear_polygon_data = count;
*data = d;
return 0;
error:
os_free(d);
return -ENOMEM;
}
static int hostapd_afc_parse_op_class(struct hostapd_config *conf, char *pos)
{
os_free(conf->afc.op_class);
conf->afc.op_class = NULL;
while (pos && pos[0]) {
char *p;
p = os_strchr(pos, ',');
if (p)
*p++ = '\0';
int_array_add_unique(&conf->afc.op_class, atoi(pos));
pos = p;
}
return 0;
}
#endif /* CONFIG_AFC */
#endif /* CONFIG_IEEE80211AX */
@@ -1834,233 +1968,6 @@ static int hs20_parse_oper_friendly_name(struct hostapd_bss_config *bss,
return 0;
}
static int hs20_parse_icon(struct hostapd_bss_config *bss, char *pos)
{
struct hs20_icon *icon;
char *end;
icon = os_realloc_array(bss->hs20_icons, bss->hs20_icons_count + 1,
sizeof(struct hs20_icon));
if (icon == NULL)
return -1;
bss->hs20_icons = icon;
icon = &bss->hs20_icons[bss->hs20_icons_count];
os_memset(icon, 0, sizeof(*icon));
icon->width = atoi(pos);
pos = os_strchr(pos, ':');
if (pos == NULL)
return -1;
pos++;
icon->height = atoi(pos);
pos = os_strchr(pos, ':');
if (pos == NULL)
return -1;
pos++;
end = os_strchr(pos, ':');
if (end == NULL || end - pos > 3)
return -1;
os_memcpy(icon->language, pos, end - pos);
pos = end + 1;
end = os_strchr(pos, ':');
if (end == NULL || end - pos > 255)
return -1;
os_memcpy(icon->type, pos, end - pos);
pos = end + 1;
end = os_strchr(pos, ':');
if (end == NULL || end - pos > 255)
return -1;
os_memcpy(icon->name, pos, end - pos);
pos = end + 1;
if (os_strlen(pos) > 255)
return -1;
os_memcpy(icon->file, pos, os_strlen(pos));
bss->hs20_icons_count++;
return 0;
}
static int hs20_parse_osu_ssid(struct hostapd_bss_config *bss,
char *pos, int line)
{
size_t slen;
char *str;
str = wpa_config_parse_string(pos, &slen);
if (str == NULL || slen < 1 || slen > SSID_MAX_LEN) {
wpa_printf(MSG_ERROR, "Line %d: Invalid SSID '%s'", line, pos);
os_free(str);
return -1;
}
os_memcpy(bss->osu_ssid, str, slen);
bss->osu_ssid_len = slen;
os_free(str);
return 0;
}
static int hs20_parse_osu_server_uri(struct hostapd_bss_config *bss,
char *pos, int line)
{
struct hs20_osu_provider *p;
p = os_realloc_array(bss->hs20_osu_providers,
bss->hs20_osu_providers_count + 1, sizeof(*p));
if (p == NULL)
return -1;
bss->hs20_osu_providers = p;
bss->last_osu = &bss->hs20_osu_providers[bss->hs20_osu_providers_count];
bss->hs20_osu_providers_count++;
os_memset(bss->last_osu, 0, sizeof(*p));
bss->last_osu->server_uri = os_strdup(pos);
return 0;
}
static int hs20_parse_osu_friendly_name(struct hostapd_bss_config *bss,
char *pos, int line)
{
if (bss->last_osu == NULL) {
wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
return -1;
}
if (parse_lang_string(&bss->last_osu->friendly_name,
&bss->last_osu->friendly_name_count, pos)) {
wpa_printf(MSG_ERROR, "Line %d: Invalid osu_friendly_name '%s'",
line, pos);
return -1;
}
return 0;
}
static int hs20_parse_osu_nai(struct hostapd_bss_config *bss,
char *pos, int line)
{
if (bss->last_osu == NULL) {
wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
return -1;
}
os_free(bss->last_osu->osu_nai);
bss->last_osu->osu_nai = os_strdup(pos);
if (bss->last_osu->osu_nai == NULL)
return -1;
return 0;
}
static int hs20_parse_osu_nai2(struct hostapd_bss_config *bss,
char *pos, int line)
{
if (bss->last_osu == NULL) {
wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
return -1;
}
os_free(bss->last_osu->osu_nai2);
bss->last_osu->osu_nai2 = os_strdup(pos);
if (bss->last_osu->osu_nai2 == NULL)
return -1;
bss->hs20_osu_providers_nai_count++;
return 0;
}
static int hs20_parse_osu_method_list(struct hostapd_bss_config *bss, char *pos,
int line)
{
if (bss->last_osu == NULL) {
wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
return -1;
}
if (hostapd_parse_intlist(&bss->last_osu->method_list, pos)) {
wpa_printf(MSG_ERROR, "Line %d: Invalid osu_method_list", line);
return -1;
}
return 0;
}
static int hs20_parse_osu_icon(struct hostapd_bss_config *bss, char *pos,
int line)
{
char **n;
struct hs20_osu_provider *p = bss->last_osu;
if (p == NULL) {
wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
return -1;
}
n = os_realloc_array(p->icons, p->icons_count + 1, sizeof(char *));
if (n == NULL)
return -1;
p->icons = n;
p->icons[p->icons_count] = os_strdup(pos);
if (p->icons[p->icons_count] == NULL)
return -1;
p->icons_count++;
return 0;
}
static int hs20_parse_osu_service_desc(struct hostapd_bss_config *bss,
char *pos, int line)
{
if (bss->last_osu == NULL) {
wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
return -1;
}
if (parse_lang_string(&bss->last_osu->service_desc,
&bss->last_osu->service_desc_count, pos)) {
wpa_printf(MSG_ERROR, "Line %d: Invalid osu_service_desc '%s'",
line, pos);
return -1;
}
return 0;
}
static int hs20_parse_operator_icon(struct hostapd_bss_config *bss, char *pos,
int line)
{
char **n;
n = os_realloc_array(bss->hs20_operator_icon,
bss->hs20_operator_icon_count + 1, sizeof(char *));
if (!n)
return -1;
bss->hs20_operator_icon = n;
bss->hs20_operator_icon[bss->hs20_operator_icon_count] = os_strdup(pos);
if (!bss->hs20_operator_icon[bss->hs20_operator_icon_count])
return -1;
bss->hs20_operator_icon_count++;
return 0;
}
#endif /* CONFIG_HS20 */
@@ -2436,6 +2343,31 @@ static int get_u16(const char *pos, int line, u16 *ret_val)
#endif /* CONFIG_IEEE80211BE */
#ifdef CONFIG_TESTING_OPTIONS
static bool get_hexstream(const char *val, struct wpabuf **var,
const char *name, int line)
{
struct wpabuf *tmp;
size_t len = os_strlen(val) / 2;
tmp = wpabuf_alloc(len);
if (!tmp)
return false;
if (hexstr2bin(val, wpabuf_put(tmp, len), len)) {
wpabuf_free(tmp);
wpa_printf(MSG_ERROR, "Line %d: Invalid %s '%s'",
line, name, val);
return false;
}
wpabuf_free(*var);
*var = tmp;
return true;
}
#endif /* CONFIG_TESTING_OPTIONS */
static int hostapd_config_fill(struct hostapd_config *conf,
struct hostapd_bss_config *bss,
const char *buf, char *pos, int line)
@@ -2731,8 +2663,6 @@ static int hostapd_config_fill(struct hostapd_config *conf,
return 1;
}
bss->eap_teap_auth = val;
} else if (os_strcmp(buf, "eap_teap_pac_no_inner") == 0) {
bss->eap_teap_pac_no_inner = atoi(pos);
} else if (os_strcmp(buf, "eap_teap_separate_result") == 0) {
bss->eap_teap_separate_result = atoi(pos);
} else if (os_strcmp(buf, "eap_teap_id") == 0) {
@@ -3073,6 +3003,14 @@ static int hostapd_config_fill(struct hostapd_config *conf,
return 1;
}
bss->extended_key_id = val;
#ifdef CONFIG_ENC_ASSOC
} else if (os_strcmp(buf, "assoc_frame_encryption") == 0) {
bss->assoc_frame_encryption = atoi(pos);
} else if (os_strcmp(buf, "pmksa_caching_privacy") == 0) {
bss->pmksa_caching_privacy = atoi(pos);
} else if (os_strcmp(buf, "eap_using_authentication_frames") == 0) {
bss->eap_using_authentication_frames = atoi(pos);
#endif /* CONFIG_ENC_ASSOC */
} else if (os_strcmp(buf, "wpa_group_rekey") == 0) {
bss->wpa_group_rekey = atoi(pos);
bss->wpa_group_rekey_set = 1;
@@ -3156,6 +3094,16 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->wpa_key_mgmt = hostapd_config_parse_key_mgmt(line, pos);
if (bss->wpa_key_mgmt == -1)
return 1;
} else if (os_strcmp(buf, "rsn_override_key_mgmt") == 0) {
bss->rsn_override_key_mgmt =
hostapd_config_parse_key_mgmt(line, pos);
if (bss->rsn_override_key_mgmt == -1)
return 1;
} else if (os_strcmp(buf, "rsn_override_key_mgmt_2") == 0) {
bss->rsn_override_key_mgmt_2 =
hostapd_config_parse_key_mgmt(line, pos);
if (bss->rsn_override_key_mgmt_2 == -1)
return 1;
} else if (os_strcmp(buf, "wpa_psk_radius") == 0) {
bss->wpa_psk_radius = atoi(pos);
if (bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
@@ -3187,6 +3135,32 @@ static int hostapd_config_fill(struct hostapd_config *conf,
line, pos);
return 1;
}
} else if (os_strcmp(buf, "rsn_override_pairwise") == 0) {
bss->rsn_override_pairwise =
hostapd_config_parse_cipher(line, pos);
if (bss->rsn_override_pairwise == -1 ||
bss->rsn_override_pairwise == 0)
return 1;
if (bss->rsn_override_pairwise &
(WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) {
wpa_printf(MSG_ERROR,
"Line %d: unsupported pairwise cipher suite '%s'",
line, pos);
return 1;
}
} else if (os_strcmp(buf, "rsn_override_pairwise_2") == 0) {
bss->rsn_override_pairwise_2 =
hostapd_config_parse_cipher(line, pos);
if (bss->rsn_override_pairwise_2 == -1 ||
bss->rsn_override_pairwise_2 == 0)
return 1;
if (bss->rsn_override_pairwise_2 &
(WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) {
wpa_printf(MSG_ERROR,
"Line %d: unsupported pairwise cipher suite '%s'",
line, pos);
return 1;
}
} else if (os_strcmp(buf, "group_cipher") == 0) {
bss->group_cipher = hostapd_config_parse_cipher(line, pos);
if (bss->group_cipher == -1 || bss->group_cipher == 0)
@@ -3208,6 +3182,10 @@ static int hostapd_config_fill(struct hostapd_config *conf,
os_free(bss->rsn_preauth_interfaces);
bss->rsn_preauth_interfaces = os_strdup(pos);
#endif /* CONFIG_RSN_PREAUTH */
} else if (os_strcmp(buf, "rsn_override_omit_rsnxe") == 0) {
bss->rsn_override_omit_rsnxe = atoi(pos);
} else if (os_strcmp(buf, "rsn_override_mlo_compat") == 0) {
bss->rsn_override_mlo_compat = atoi(pos);
} else if (os_strcmp(buf, "peerkey") == 0) {
wpa_printf(MSG_INFO,
"Line %d: Obsolete peerkey parameter ignored", line);
@@ -3319,6 +3297,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->radius_server_auth_port = atoi(pos);
} else if (os_strcmp(buf, "radius_server_acct_port") == 0) {
bss->radius_server_acct_port = atoi(pos);
} else if (os_strcmp(buf, "radius_server_acct_log") == 0) {
bss->radius_server_acct_log = atoi(pos);
} else if (os_strcmp(buf, "radius_server_ipv6") == 0) {
bss->radius_server_ipv6 = atoi(pos);
#endif /* RADIUS_SERVER */
@@ -3494,18 +3474,19 @@ static int hostapd_config_fill(struct hostapd_config *conf,
}
bss->send_probe_response = val;
} else if (os_strcmp(buf, "supported_rates") == 0) {
if (hostapd_parse_intlist(&conf->supported_rates, pos)) {
if (hostapd_parse_intlist(&bss->supported_rates, pos)) {
wpa_printf(MSG_ERROR, "Line %d: invalid rate list",
line);
return 1;
}
} else if (os_strcmp(buf, "basic_rates") == 0) {
if (hostapd_parse_intlist(&conf->basic_rates, pos)) {
if (hostapd_parse_intlist(&bss->basic_rates, pos)) {
wpa_printf(MSG_ERROR, "Line %d: invalid rate list",
line);
return 1;
}
} else if (os_strcmp(buf, "beacon_rate") == 0) {
enum beacon_rate_type rate_type;
int val;
if (os_strncmp(pos, "ht:", 3) == 0) {
@@ -3516,8 +3497,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
line, val);
return 1;
}
conf->rate_type = BEACON_RATE_HT;
conf->beacon_rate = val;
rate_type = BEACON_RATE_HT;
} else if (os_strncmp(pos, "vht:", 4) == 0) {
val = atoi(pos + 4);
if (val < 0 || val > 9) {
@@ -3526,8 +3506,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
line, val);
return 1;
}
conf->rate_type = BEACON_RATE_VHT;
conf->beacon_rate = val;
rate_type = BEACON_RATE_VHT;
} else if (os_strncmp(pos, "he:", 3) == 0) {
val = atoi(pos + 3);
if (val < 0 || val > 11) {
@@ -3536,8 +3515,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
line, val);
return 1;
}
conf->rate_type = BEACON_RATE_HE;
conf->beacon_rate = val;
rate_type = BEACON_RATE_HE;
} else {
val = atoi(pos);
if (val < 10 || val > 10000) {
@@ -3546,9 +3524,11 @@ static int hostapd_config_fill(struct hostapd_config *conf,
line, val);
return 1;
}
conf->rate_type = BEACON_RATE_LEGACY;
conf->beacon_rate = val;
rate_type = BEACON_RATE_LEGACY;
}
bss->rate_type = rate_type;
bss->beacon_rate = val;
} else if (os_strcmp(buf, "preamble") == 0) {
if (atoi(pos))
conf->preamble = SHORT_PREAMBLE;
@@ -3642,6 +3622,12 @@ static int hostapd_config_fill(struct hostapd_config *conf,
conf->use_driver_iface_addr = atoi(pos);
} else if (os_strcmp(buf, "ieee80211w") == 0) {
bss->ieee80211w = atoi(pos);
} else if (os_strcmp(buf, "rsn_override_mfp") == 0) {
bss->rsn_override_mfp = atoi(pos);
} else if (os_strcmp(buf, "rsn_override_mfp_2") == 0) {
bss->rsn_override_mfp_2 = atoi(pos);
} else if (os_strcmp(buf, "spp_amsdu") == 0) {
bss->spp_amsdu = !!atoi(pos);
} else if (os_strcmp(buf, "group_mgmt_cipher") == 0) {
if (os_strcmp(pos, "AES-128-CMAC") == 0) {
bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC;
@@ -3888,6 +3874,89 @@ static int hostapd_config_fill(struct hostapd_config *conf,
return 1;
}
bss->unsol_bcast_probe_resp_interval = val;
#ifdef CONFIG_AFC
} else if (os_strcmp(buf, "afcd_sock") == 0) {
os_free(conf->afc.socket);
conf->afc.socket = os_strdup(pos);
} else if (os_strcmp(buf, "afc_request_version") == 0) {
os_free(conf->afc.request.version);
conf->afc.request.version = os_strdup((pos));
} else if (os_strcmp(buf, "afc_serial_number") == 0) {
os_free(conf->afc.request.sn);
conf->afc.request.sn = os_strdup((pos));
} else if (os_strcmp(buf, "afc_cert_ids") == 0) {
if (hostapd_afc_parse_cert_ids(conf, pos)) {
wpa_printf(MSG_ERROR, "Line %d: invalid afc_cert_ids",
line);
return 1;
}
} else if (os_strcmp(buf, "afc_location_type") == 0) {
conf->afc.location.type = atoi(pos);
if (conf->afc.location.type != AFC_ELLIPSE &&
conf->afc.location.type != AFC_LINEAR_POLYGON &&
conf->afc.location.type != AFC_RADIAL_POLYGON) {
wpa_printf(MSG_ERROR,
"Line %d: invalid afc_location_type value",
line);
return 1;
}
} else if (os_strcmp(buf, "afc_linear_polygon") == 0) {
if (hostapd_afc_parse_position_data(
&conf->afc.location.linear_polygon_data,
&conf->afc.location.n_linear_polygon_data,
pos)) {
wpa_printf(MSG_ERROR,
"Line %d: invalid afc_linear_polygon",
line);
return 1;
}
} else if (os_strcmp(buf, "afc_radial_polygon") == 0) {
if (hostapd_afc_parse_position_data(
(struct afc_linear_polygon **)
&conf->afc.location.radial_polygon_data,
&conf->afc.location.n_radial_polygon_data,
pos)) {
wpa_printf(MSG_ERROR,
"Line %d: invalid afc_radial_polygon",
line);
return 1;
}
} else if (os_strcmp(buf, "afc_major_axis") == 0) {
conf->afc.location.major_axis = atoi(pos);
} else if (os_strcmp(buf, "afc_minor_axis") == 0) {
conf->afc.location.minor_axis = atoi(pos);
} else if (os_strcmp(buf, "afc_orientation") == 0) {
conf->afc.location.orientation = atoi(pos);
} else if (os_strcmp(buf, "afc_height") == 0) {
char *end;
conf->afc.location.height = strtod(pos, &end);
if (*end) {
wpa_printf(MSG_ERROR,
"Line %d: invalid afc_height value",
line);
return 1;
}
} else if (os_strcmp(buf, "afc_height_type") == 0) {
os_free(conf->afc.location.height_type);
conf->afc.location.height_type = os_strdup(pos);
} else if (os_strcmp(buf, "afc_vertical_tolerance") == 0) {
conf->afc.location.vertical_tolerance = atoi(pos);
} else if (os_strcmp(buf, "afc_min_power") == 0) {
conf->afc.min_power = atoi(pos);
} else if (os_strcmp(buf, "afc_freq_range") == 0) {
if (freq_range_list_parse(&conf->afc.freqs, pos)) {
wpa_printf(MSG_ERROR, "Line %d: invalid afc_freq_range",
line);
return 1;
}
} else if (os_strcmp(buf, "afc_op_class") == 0) {
if (hostapd_afc_parse_op_class(conf, pos)) {
wpa_printf(MSG_ERROR, "Line %d: invalid afc_op_class",
line);
return 1;
}
#endif /* CONFIG_AFC */
} else if (os_strcmp(buf, "mbssid") == 0) {
int mbssid = atoi(pos);
if (mbssid < 0 || mbssid > ENHANCED_MBSSID_ENABLED) {
@@ -3897,6 +3966,10 @@ static int hostapd_config_fill(struct hostapd_config *conf,
return 1;
}
conf->mbssid = mbssid;
} else if (os_strcmp(buf, "mbssid_index") == 0) {
bss->mbssid_index = atoi(pos);
} else if (os_strcmp(buf, "mbssid_max") == 0) {
conf->mbssid_max = atoi(pos);
#endif /* CONFIG_IEEE80211AX */
} else if (os_strcmp(buf, "max_listen_interval") == 0) {
bss->max_listen_interval = atoi(pos);
@@ -4248,12 +4321,24 @@ static int hostapd_config_fill(struct hostapd_config *conf,
tok_start = os_strchr(tok_prev, ',');
if (tok_start) {
domain_len = tok_start - tok_prev;
if (domain_len > 255) {
wpa_printf(MSG_ERROR,
"Line %d: domain_name is too long (max 255)", line);
os_free(domain_list);
return 1;
}
*domain_ptr = domain_len;
os_memcpy(domain_ptr + 1, tok_prev, domain_len);
domain_ptr += domain_len + 1;
tok_prev = ++tok_start;
} else {
domain_len = os_strlen(tok_prev);
if (domain_len > 255) {
wpa_printf(MSG_ERROR,
"Line %d: domain_name is too long (max 255)", line);
os_free(domain_list);
return 1;
}
*domain_ptr = domain_len;
os_memcpy(domain_ptr + 1, tok_prev, domain_len);
domain_ptr += domain_len + 1;
@@ -4314,8 +4399,6 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->disable_dgaf = atoi(pos);
} else if (os_strcmp(buf, "na_mcast_to_ucast") == 0) {
bss->na_mcast_to_ucast = atoi(pos);
} else if (os_strcmp(buf, "osen") == 0) {
bss->osen = atoi(pos);
} else if (os_strcmp(buf, "anqp_domain_id") == 0) {
bss->anqp_domain_id = atoi(pos);
} else if (os_strcmp(buf, "hs20_deauth_req_timeout") == 0) {
@@ -4354,44 +4437,6 @@ static int hostapd_config_fill(struct hostapd_config *conf,
os_free(bss->hs20_operating_class);
bss->hs20_operating_class = oper_class;
bss->hs20_operating_class_len = oper_class_len;
} else if (os_strcmp(buf, "hs20_icon") == 0) {
if (hs20_parse_icon(bss, pos) < 0) {
wpa_printf(MSG_ERROR, "Line %d: Invalid hs20_icon '%s'",
line, pos);
return 1;
}
} else if (os_strcmp(buf, "osu_ssid") == 0) {
if (hs20_parse_osu_ssid(bss, pos, line) < 0)
return 1;
} else if (os_strcmp(buf, "osu_server_uri") == 0) {
if (hs20_parse_osu_server_uri(bss, pos, line) < 0)
return 1;
} else if (os_strcmp(buf, "osu_friendly_name") == 0) {
if (hs20_parse_osu_friendly_name(bss, pos, line) < 0)
return 1;
} else if (os_strcmp(buf, "osu_nai") == 0) {
if (hs20_parse_osu_nai(bss, pos, line) < 0)
return 1;
} else if (os_strcmp(buf, "osu_nai2") == 0) {
if (hs20_parse_osu_nai2(bss, pos, line) < 0)
return 1;
} else if (os_strcmp(buf, "osu_method_list") == 0) {
if (hs20_parse_osu_method_list(bss, pos, line) < 0)
return 1;
} else if (os_strcmp(buf, "osu_icon") == 0) {
if (hs20_parse_osu_icon(bss, pos, line) < 0)
return 1;
} else if (os_strcmp(buf, "osu_service_desc") == 0) {
if (hs20_parse_osu_service_desc(bss, pos, line) < 0)
return 1;
} else if (os_strcmp(buf, "operator_icon") == 0) {
if (hs20_parse_operator_icon(bss, pos, line) < 0)
return 1;
} else if (os_strcmp(buf, "subscr_remediation_url") == 0) {
os_free(bss->subscr_remediation_url);
bss->subscr_remediation_url = os_strdup(pos);
} else if (os_strcmp(buf, "subscr_remediation_method") == 0) {
bss->subscr_remediation_method = atoi(pos);
} else if (os_strcmp(buf, "hs20_t_c_filename") == 0) {
os_free(bss->t_c_filename);
bss->t_c_filename = os_strdup(pos);
@@ -4400,9 +4445,6 @@ static int hostapd_config_fill(struct hostapd_config *conf,
} else if (os_strcmp(buf, "hs20_t_c_server_url") == 0) {
os_free(bss->t_c_server_url);
bss->t_c_server_url = os_strdup(pos);
} else if (os_strcmp(buf, "hs20_sim_provisioning_url") == 0) {
os_free(bss->hs20_sim_provisioning_url);
bss->hs20_sim_provisioning_url = os_strdup(pos);
#endif /* CONFIG_HS20 */
#ifdef CONFIG_MBO
} else if (os_strcmp(buf, "mbo") == 0) {
@@ -4432,6 +4474,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
PARSE_TEST_PROBABILITY(corrupt_gtk_rekey_mic_probability)
} else if (os_strcmp(buf, "ecsa_ie_only") == 0) {
conf->ecsa_ie_only = atoi(pos);
} else if (os_strcmp(buf, "csa_ie_only") == 0) {
conf->csa_ie_only = atoi(pos);
} else if (os_strcmp(buf, "bss_load_test") == 0) {
WPA_PUT_LE16(bss->bss_load_test, atoi(pos));
pos = os_strchr(pos, ':');
@@ -4462,23 +4506,29 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->radio_measurements[0] |=
WLAN_RRM_CAPS_NEIGHBOR_REPORT;
} else if (os_strcmp(buf, "own_ie_override") == 0) {
struct wpabuf *tmp;
size_t len = os_strlen(pos) / 2;
tmp = wpabuf_alloc(len);
if (!tmp)
if (!get_hexstream(pos, &bss->own_ie_override,
"own_ie_override", line))
return 1;
if (hexstr2bin(pos, wpabuf_put(tmp, len), len)) {
wpabuf_free(tmp);
wpa_printf(MSG_ERROR,
"Line %d: Invalid own_ie_override '%s'",
line, pos);
} else if (os_strcmp(buf, "rsne_override") == 0) {
if (!get_hexstream(pos, &bss->rsne_override,
"rsne_override", line))
return 1;
} else if (os_strcmp(buf, "rsnoe_override") == 0) {
if (!get_hexstream(pos, &bss->rsnoe_override,
"rsnoe_override", line))
return 1;
} else if (os_strcmp(buf, "rsno2e_override") == 0) {
if (!get_hexstream(pos, &bss->rsno2e_override,
"rsno2e_override", line))
return 1;
} else if (os_strcmp(buf, "rsnxe_override") == 0) {
if (!get_hexstream(pos, &bss->rsnxe_override,
"rsnxe_override", line))
return 1;
} else if (os_strcmp(buf, "rsnxoe_override") == 0) {
if (!get_hexstream(pos, &bss->rsnxoe_override,
"rsnxoe_override", line))
return 1;
}
wpabuf_free(bss->own_ie_override);
bss->own_ie_override = tmp;
} else if (os_strcmp(buf, "sae_reflection_attack") == 0) {
bss->sae_reflection_attack = atoi(pos);
} else if (os_strcmp(buf, "sae_commit_status") == 0) {
@@ -4540,6 +4590,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
return 1;
} else if (os_strcmp(buf, "eapol_m3_no_encrypt") == 0) {
bss->eapol_m3_no_encrypt = atoi(pos);
} else if (os_strcmp(buf, "eapol_key_reserved_random") == 0) {
bss->eapol_key_reserved_random = atoi(pos);
} else if (os_strcmp(buf, "test_assoc_comeback_type") == 0) {
bss->test_assoc_comeback_type = atoi(pos);
} else if (os_strcmp(buf, "presp_elements") == 0) {
@@ -4560,6 +4612,10 @@ static int hostapd_config_fill(struct hostapd_config *conf,
line);
return 1;
}
} else if (os_strcmp(buf, "sae_password_psk") == 0) {
bss->sae_password_psk = atoi(pos);
} else if (os_strcmp(buf, "sae_track_password") == 0) {
bss->sae_track_password = atoi(pos);
#endif /* CONFIG_SAE */
} else if (os_strcmp(buf, "vendor_elements") == 0) {
if (parse_wpabuf_hex(line, buf, &bss->vendor_elements, pos))
@@ -4585,6 +4641,13 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->sae_confirm_immediate = atoi(pos);
} else if (os_strcmp(buf, "sae_pwe") == 0) {
bss->sae_pwe = atoi(pos);
} else if (os_strcmp(buf, "sae_accept_h2e_without_use") == 0) {
bss->sae_accept_h2e_without_use = atoi(pos);
} else if (os_strcmp(buf, "sae_pw_id_num") == 0) {
bss->sae_pw_id_num = atoi(pos);
} else if (os_strcmp(buf, "sae_pw_id_key") == 0) {
if (parse_wpabuf_hex(line, buf, &bss->sae_pw_id_key, pos))
return 1;
} else if (os_strcmp(buf, "local_pwr_constraint") == 0) {
int val = atoi(pos);
if (val < 0 || val > 255) {
@@ -4674,6 +4737,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
wpabuf_free(conf->lci);
conf->lci = NULL;
}
if (conf->lci) {
/* Enable LCI capability in RM Enabled Capabilities
* element */
bss->radio_measurements[1] |=
WLAN_RRM_CAPS_LCI_MEASUREMENT;
} else {
bss->radio_measurements[1] &=
~WLAN_RRM_CAPS_LCI_MEASUREMENT;
}
} else if (os_strcmp(buf, "civic") == 0) {
wpabuf_free(conf->civic);
conf->civic = wpabuf_parse_bin(pos);
@@ -4681,6 +4753,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
wpabuf_free(conf->civic);
conf->civic = NULL;
}
if (conf->civic) {
/* Enable civic location capability in RM Enabled
* Capabilities element */
bss->radio_measurements[4] |=
WLAN_RRM_CAPS_CIVIC_LOCATION_MEASUREMENT;
} else {
bss->radio_measurements[4] &=
~WLAN_RRM_CAPS_CIVIC_LOCATION_MEASUREMENT;
}
} else if (os_strcmp(buf, "rrm_neighbor_report") == 0) {
if (atoi(pos))
bss->radio_measurements[0] |=
@@ -4980,6 +5061,16 @@ static int hostapd_config_fill(struct hostapd_config *conf,
return 1;
}
bss->macsec_csindex = macsec_csindex;
} else if (os_strcmp(buf, "macsec_icv_indicator") == 0) {
int macsec_icv_indicator = atoi(pos);
if (macsec_icv_indicator < 0 || macsec_icv_indicator > 1) {
wpa_printf(MSG_ERROR,
"Line %d: invalid macsec_icv_indicator (%d): '%s'.",
line, macsec_icv_indicator, pos);
return 1;
}
bss->macsec_icv_indicator = macsec_icv_indicator;
} else if (os_strcmp(buf, "mka_cak") == 0) {
size_t len = os_strlen(pos);
@@ -5024,6 +5115,17 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->force_kdk_derivation = atoi(pos);
} else if (os_strcmp(buf, "pasn_corrupt_mic") == 0) {
bss->pasn_corrupt_mic = atoi(pos);
} else if (os_strcmp(buf, "pasn_test_groups") == 0) {
int *groups = NULL;
if (hostapd_parse_intlist(&groups, pos) < 0) {
wpa_printf(MSG_ERROR,
"Line %d: Invalid pasn_test_groups value '%s'",
line, pos);
return 1;
}
os_free(bss->pasn_test_groups);
bss->pasn_test_groups = groups;
#endif /* CONFIG_TESTING_OPTIONS */
} else if (os_strcmp(buf, "pasn_groups") == 0) {
if (hostapd_parse_intlist(&bss->pasn_groups, pos)) {
@@ -5036,6 +5138,14 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->pasn_comeback_after = atoi(pos);
} else if (os_strcmp(buf, "pasn_noauth") == 0) {
bss->pasn_noauth = atoi(pos);
#ifdef CONFIG_ENC_ASSOC
} else if (os_strcmp(buf, "eppke_unauth") == 0) {
bss->eppke_unauth = atoi(pos);
#endif /* CONFIG_ENC_ASSOC */
} else if (os_strcmp(buf, "urnm_mfpr") == 0) {
bss->urnm_mfpr = !!atoi(pos);
} else if (os_strcmp(buf, "urnm_mfpr_x20") == 0) {
bss->urnm_mfpr_x20 = !!atoi(pos);
#endif /* CONFIG_PASN */
} else if (os_strcmp(buf, "ext_capa_mask") == 0) {
if (get_hex_config(bss->ext_capa_mask, EXT_CAPA_MAX_LEN,
@@ -5053,9 +5163,23 @@ static int hostapd_config_fill(struct hostapd_config *conf,
if (val < 0 || val > 1)
return 1;
bss->ssid_protection = val;
} else if (os_strcmp(buf, "known_sta_identification") == 0) {
int val = atoi(pos);
if (val < 0 || val > 1)
return 1;
bss->known_sta_identification = val;
} else if (os_strcmp(buf, "channel_usage") == 0) {
conf->channel_usage = atoi(pos);
} else if (os_strcmp(buf, "peer_to_peer_twt") == 0) {
conf->peer_to_peer_twt = atoi(pos);
#ifdef CONFIG_IEEE80211BE
} else if (os_strcmp(buf, "ieee80211be") == 0) {
conf->ieee80211be = atoi(pos);
} else if (os_strcmp(buf, "require_eht") == 0) {
conf->require_eht = atoi(pos);
} else if (os_strcmp(buf, "bss_require_eht") == 0) {
bss->bss_require_eht = atoi(pos);
} else if (os_strcmp(buf, "eht_oper_chwidth") == 0) {
conf->eht_oper_chwidth = atoi(pos);
} else if (os_strcmp(buf, "eht_oper_centr_freq_seg0_idx") == 0) {
@@ -5097,8 +5221,12 @@ static int hostapd_config_fill(struct hostapd_config *conf,
return 1;
} else if (os_strcmp(buf, "mld_indicate_disabled") == 0) {
bss->mld_indicate_disabled = atoi(pos);
} else if (os_strcmp(buf, "disable_mcs15_rx") == 0) {
conf->disable_mcs15_rx = atoi(pos);
#endif /* CONFIG_TESTING_OPTIONS */
#endif /* CONFIG_IEEE80211BE */
} else if (os_strcmp(buf, "i2r_lmr_policy") == 0) {
conf->i2r_lmr_policy = atoi(pos);
} else {
wpa_printf(MSG_ERROR,
"Line %d: unknown configuration item '%s'",
File diff suppressed because it is too large. Load diff
+2
View File
@@ -14,6 +14,8 @@ int hostapd_ctrl_iface_init(struct hostapd_data *hapd);
void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd);
int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface);
void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interface);
int hostapd_mld_ctrl_iface_init(struct hostapd_mld *mld);
void hostapd_mld_ctrl_iface_deinit(struct hostapd_mld *mld);
#else /* CONFIG_NO_CTRL_IFACE */
static inline int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
{
+20 -14
View File
@@ -9,9 +9,6 @@
# be modified from here. In most cass, these lines should use += in order not
# to override previous values of the variables.
# Driver interface for Host AP driver
CONFIG_DRIVER_HOSTAP=y
# Driver interface for wired authenticator
#CONFIG_DRIVER_WIRED=y
@@ -152,7 +149,6 @@ CONFIG_IPV6=y
#CONFIG_DRIVER_RADIUS_ACL=y
# Wireless Network Management (IEEE Std 802.11v-2011)
# Note: This is experimental and not complete implementation.
#CONFIG_WNM=y
# IEEE 802.11ac (Very High Throughput) support
@@ -163,9 +159,6 @@ CONFIG_IPV6=y
# IEEE 802.11be EHT support
# CONFIG_IEEE80211AX is mandatory for setting CONFIG_IEEE80211BE.
# Note: This is experimental and work in progress. The definitions are still
# subject to change and this should not be expected to interoperate with the
# final IEEE 802.11be version.
#CONFIG_IEEE80211BE=y
# Simultaneous Authentication of Equals (SAE), WPA3-Personal
@@ -384,8 +377,7 @@ CONFIG_IPV6=y
#CONFIG_WPA_CLI_EDIT=y
# Opportunistic Wireless Encryption (OWE)
# Experimental implementation of draft-harkins-owe-07.txt
#CONFIG_OWE=y
CONFIG_OWE=y
# Airtime policy support
#CONFIG_AIRTIME_POLICY=y
@@ -410,18 +402,32 @@ CONFIG_IPV6=y
#CONFIG_NO_TKIP=y
# Pre-Association Security Negotiation (PASN)
# Experimental implementation based on IEEE P802.11z/D2.6 and the protocol
# design is still subject to change. As such, this should not yet be enabled in
# production use.
#CONFIG_PASN=y
# Device Provisioning Protocol (DPP) (also known as Wi-Fi Easy Connect)
CONFIG_DPP=y
# DPP version 2 support
CONFIG_DPP2=y
# DPP version 3 support (experimental and still changing; do not enable for
# production use)
# DPP version 3 support
#CONFIG_DPP3=y
# Wi-Fi Aware unsynchronized service discovery (NAN USD)
#CONFIG_NAN_USD=y
# Enhanced Privacy Protection (IEEE P802.11bi)
# Note: These features are experimental and still changing; do not enable for
# production use.
# Encrypted association frame support (needed for EPPKE and EAP in
# Authentication frames)
#CONFIG_ENC_ASSOC=y
#
# PMKSA caching privacy support
#CONFIG_PMKSA_PRIVACY=y
#
# IEEE 802.1X (EAP) authentication in Authentication frames
# IEEE P802.11bi/D4.0, 12.16.5 (IEEE 802.1X authentication utilizing
# Authentication frames)
#CONFIG_IEEE8021X_AUTH=y
# Automated Frequency Coordination for 6 GHz outdoor
#CONFIG_AFC=y
-7
View File
@@ -44,13 +44,6 @@ int eap_server_register_methods(void)
ret = eap_server_unauth_tls_register();
#endif /* EAP_SERVER_TLS */
#ifdef EAP_SERVER_TLS
#ifdef CONFIG_HS20
if (ret == 0)
ret = eap_server_wfa_unauth_tls_register();
#endif /* CONFIG_HS20 */
#endif /* EAP_SERVER_TLS */
#ifdef EAP_SERVER_MSCHAPV2
if (ret == 0)
ret = eap_server_mschapv2_register();
+23 -6
View File
@@ -1,6 +1,6 @@
/*
* HLR/AuC testing gateway for hostapd EAP-SIM/AKA database/authenticator
* Copyright (c) 2005-2007, 2012-2017, Jouni Malinen <j@w1.fi>
* Copyright (c) 2005-2007, 2012-2024, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -66,6 +66,7 @@ static int update_milenage = 0;
static int sqn_changes = 0;
static int ind_len = 5;
static int stdout_debug = 1;
static bool stop = false;
/* GSM triplets */
struct gsm_triplet {
@@ -877,6 +878,12 @@ static int process_cmd(char *cmd, char *resp, size_t resp_len)
if (os_strncmp(cmd, "AKA-AUTS ", 9) == 0)
return aka_auts(cmd + 9, resp, resp_len);
if (strncmp(cmd, "TERMINATE", 9) == 0) {
stop = true;
resp[0] = '\0';
return 0;
}
printf("Unknown request: %s\n", cmd);
return -1;
}
@@ -931,10 +938,13 @@ static void cleanup(void)
struct gsm_triplet *g, *gprev;
struct milenage_parameters *m, *prev;
if (update_milenage && milenage_file && sqn_changes)
if (update_milenage && milenage_file && sqn_changes) {
sqn_changes = 0;
update_milenage_file(milenage_file);
}
g = gsm_db;
gsm_db = NULL;
while (g) {
gprev = g;
g = g->next;
@@ -942,16 +952,21 @@ static void cleanup(void)
}
m = milenage_db;
milenage_db = NULL;
while (m) {
prev = m;
m = m->next;
os_free(prev);
}
if (serv_sock >= 0)
if (serv_sock >= 0) {
close(serv_sock);
if (socket_path)
serv_sock = -1;
}
if (socket_path) {
unlink(socket_path);
socket_path = NULL;
}
#ifdef CONFIG_SQLITE
if (sqlite_db) {
@@ -965,6 +980,7 @@ static void cleanup(void)
static void handle_term(int sig)
{
printf("Signal %d - terminate\n", sig);
cleanup();
exit(0);
}
@@ -973,7 +989,7 @@ static void usage(void)
{
printf("HLR/AuC testing gateway for hostapd EAP-SIM/AKA "
"database/authenticator\n"
"Copyright (c) 2005-2017, Jouni Malinen <[email protected]>\n"
"Copyright (c) 2005-2024, Jouni Malinen <[email protected]>\n"
"\n"
"usage:\n"
"hlr_auc_gw [-hu] [-s<socket path>] [-g<triplet file>] "
@@ -1081,8 +1097,9 @@ int main(int argc, char *argv[])
signal(SIGTERM, handle_term);
signal(SIGINT, handle_term);
for (;;)
while (!stop)
process(serv_sock);
cleanup();
} else {
char buf[1000];
socket_path = NULL;
+325 -45
View File
@@ -20,11 +20,11 @@ interface=wlan0
# interface is also created.
#bridge=br0
# Driver interface type (hostap/wired/none/nl80211/bsd);
# default: hostap). nl80211 is used with all Linux mac80211 drivers.
# Driver interface type (wired/none/nl80211/bsd);
# default: nl80211). nl80211 is used with all Linux mac80211 drivers.
# Use driver=none if building hostapd as a standalone RADIUS server that does
# not control any wireless/wired driver.
# driver=hostap
# driver=nl80211
# Driver interface parameters (mainly for development testing use)
# driver_params=<params>
@@ -313,7 +313,15 @@ fragm_threshold=-1
# Station MAC address -based authentication
# Please note that this kind of access control requires a driver that uses
# hostapd to take care of management frame processing and as such, this can be
# used with driver=hostap or driver=nl80211, but not with driver=atheros.
# used with driver=nl80211, but not with driver=bsd.
#
# Especially in cases where not all STAs with authentication credentials are
# fully trusted, unexpected MAC addresses should be marked to be rejected, e.g.,
# by including them in the deny list (deny_mac_file). This should cover MAC
# addresses that are known to be used in the LAN, e.g., the MAC address of the
# default gateway and any server like RADIUS server or proxy. BSSIDs and MLD
# MAC addresses of other APs in the same network should also be disallowed.
#
# 0 = accept unless in deny list
# 1 = deny unless in accept list
# 2 = use external RADIUS server (accept/deny lists are searched first)
@@ -1030,6 +1038,62 @@ wmm_ac_vo_acm=0
# Valid range: 0..20 TUs; default is 0 (disabled)
#unsol_bcast_probe_resp_interval=0
#channel_usage: Whether Channel Usage procedures is supported by AP.
# 0 = Channel Usage support is disabled (default)
# 1 = Channel Usage support is enabled
#channel_usage=0
#peer_to_peer_twt: Indicates an HE AP supports negotiating a peer-to-peer
# TWT schedule that is requested by a non-AP STA to establish a
# channel-usage-aidable BSS or an off-channel TDLS direct link.
# 0 = Does not support Peer-to-peer TWT (default)
# 1 = Supports Peer-to-peer TWT
#peer_to_peer_twt=0
##### Automated Frequency Coordination for 6 GHz UNII-5 and UNII-7 bands ######
# AFC daemon connection socket
#afcd_sock=/var/run/afcd.sock
# AFC request identification parameters
#afc_request_version=1.1
#afc_serial_number=abcdefg
# Comma separated list of certification IDs in <rule set>:<ID> format
#afc_cert_ids=US_47_CFR_PART_15_SUBPART_E:CID000
# AFC location type:
# 0 = ellipse
# 1 = linear polygon
# 2 = radial polygon
#afc_location_type=0
# AFC ellipse or linear polygon coordinations
#afc_linear_polygon=-122.984157:37.425056
# AFC radial polygon coordinations
#afc_radial_polygon=118.8:92.76,76.44:87.456,98.56:123.33
# AFC ellipse major/minor axis and orientation
#afc_major_axis=100
#afc_minor_axis=50
#afc_orientation=70
# AFC device elevation parameters
#afc_height=3.0
#afc_height_type=AGL
#afc_vertical_tolerance=7
# AFC minimum desired TX power (dBm)
#afc_min_power=24
# AFC request frequency ranges
# Frequency list can be provided as range using hyphen ('-') or individual
# frequencies can be specified by comma (',') separated values
#afc_freq_range=5925-6425,6525-6875
# AFC request operation classes
#afc_op_class=131,132,133,134,136,137
##### IEEE 802.11be related configuration #####################################
#ieee80211be: Whether IEEE 802.11be (EHT) is enabled
@@ -1037,6 +1101,14 @@ wmm_ac_vo_acm=0
# 1 = enabled
#ieee80211be=1
# Require stations to support EHT PHY (reject association if they do not).
# This is a radio-level parameter and applies to all BSSs in the radio.
#require_eht=1
# Require stations to support EHT PHY for a specific BSS only.
# This is a per-BSS parameter.
#bss_require_eht=1
#disable_11be: Boolean (0/1) to disable EHT for a specific BSS
#disable_11be=0
@@ -1102,6 +1174,13 @@ wmm_ac_vo_acm=0
# will be used as the AP MLD MAC address.
#mld_addr=02:03:04:05:06:07
# Disable EHT-MCS 15 RX
# If set to 1, the MCS15 Disable subfield in the EHT Operation element is set
# to 1, disabling EHT-MCS 15. If set to 0, the subfield is set to 0, enabling
# EHT-MCS 15. The default value is 1, indicating EHT-MCS 15 reception capability
# is disabled.
#disable_mcs15_rx=1
##### IEEE 802.1X-2004 related configuration ##################################
# Require IEEE 802.1X authorization
@@ -1207,6 +1286,10 @@ eapol_key_index_workaround=0
# mka_priority (Priority of MKA Actor)
# Range: 0..255 (default: 255)
#
# macsec_icv_indicator: Always include ICV indicator
# 0 = ICV Indicator is not included when ICV has default length (default)
# 1 = ICV Indicator is always included (compatibility mode)
#
# macsec_csindex: IEEE 802.1X/MACsec cipher suite
# 0 = GCM-AES-128 (default)
# 1 = GCM-AES-256 (default)
@@ -1786,6 +1869,9 @@ own_ip_addr=127.0.0.1
# accounting while still enabling RADIUS authentication.
#radius_server_acct_port=1813
# Log received RADIUS accounting data
#radius_server_acct_log=1
# Use IPv6 with RADIUS server (IPv4 will also be supported using IPv6 API)
#radius_server_ipv6=1
@@ -1869,8 +1955,8 @@ own_ip_addr=127.0.0.1
# FT-FILS-SHA384 = FT and Fast Initial Link Setup with SHA384
# OWE = Opportunistic Wireless Encryption (a.k.a. Enhanced Open)
# DPP = Device Provisioning Protocol
# OSEN = Hotspot 2.0 online signup with encryption
# (dot11RSNAConfigAuthenticationSuitesTable)
# EPPKE = Enhanced Privacy Protection Key Exchange
#wpa_key_mgmt=WPA-PSK WPA-EAP
# Set of accepted cipher suites (encryption algorithms) for pairwise keys
@@ -2021,6 +2107,12 @@ own_ip_addr=127.0.0.1
# 1 = enabled
#beacon_prot=0
# SPP (Signaling and Payload Protected) A-MSDU.
# This depends on driver support and CCMP/GCMP cipher suite being used.
# 0 = disabled (default)
# 1 = enabled if driver indicates support for this
#spp_amsdu=1
# Association SA Query maximum timeout (in TU = 1.024 ms; for MFP)
# (maximum time to wait for a SA Query response)
# dot11AssociationSAQueryMaximumTimeout, 1...4294967295
@@ -2110,6 +2202,29 @@ own_ip_addr=127.0.0.1
# contains and entry in the same format as sae_password uses.
#sae_password_file=/tc/hostapd.sae_passwords
# Whether to use wpa_passphrase as an SAE password
# 0 = enabled if no matching sae_password is set (default)
# 1 = disabled in all cases
#sae_password_psk=0
# Tracking of SAE password use
# While SAE design does not allow the AP to determine the used password robustly
# if multiple password are configured without use of password identifiers, a
# small number of such passwords might be usable with minimal impact to STAs.
# This parameter can be used to enable such mechanism by tracking which password
# STAs have tried and either succeeded or failed to complete authentication
# with. Configured passwords are then tried one by one until success. This shows
# up as a potential attack to the STA, though, and as such, may result in the AP
# getting rejected after a couple of attempts. Only one password can be tested
# per attempt, so this limits this mechanism to only a small number (e.g., 2-3)
# passwords without showing significant usability issues with some STAs. This
# is meant as a workaround until SAE with password identifiers is deployed on
# STAs.
# This parameter sets the maximum number of STA MAC addresses to track per
# SAE password. This should be set sufficiently high to cover the expected
# number of active STAs.
#sae_track_password=0
# SAE threshold for anti-clogging mechanism (dot11RSNASAEAntiCloggingThreshold)
# This parameter defines how many open SAE instances can be in progress at the
# same time before the anti-clogging mechanism is taken into use.
@@ -2159,6 +2274,32 @@ own_ip_addr=127.0.0.1
# regardless of the sae_pwe parameter value.
#sae_pwe=0
# Accept SAE association when the STA advertises SAE H2E support in the RSNXE
# but authenticated using the hunting-and-pecking loop (i.e., did not use H2E).
# By default (0), hostapd rejects such an association as a potential downgrade
# when sae_pwe=2. This option is a workaround for WPA3-Personal Compatibility
# Mode and RSNXE-override interoperability with certain stations (e.g., some MLO
# STAs that add only the RSNXE Override element and do not use H2E on 2.4/5
# GHz).
#
# Enabling this weakens SAE downgrade protection and should only be used when
# RSN overriding is enabled in the hostapd configuration and such
# interoperability is required.
#sae_accept_h2e_without_use=0
# Changing SAE password identifiers
# AP can send a set of unique SAE password identifiers to allow the long term
# password identifier to be changed for over the air exchanges to avoid tracking
# of devices using password identifiers.
#
# Key for generating and interpreting encrypted password identifiers. This must
# be same for each AP in the network. 32 octets as a hexdump
#sae_pw_id_key=000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
#
# How many over the air password identifier values to provide to a STA each time
# SAE is used.
#sae_pw_id_num=2
# FILS Cache Identifier (16-bit value in hexdump format)
#fils_cache_id=0011
@@ -2279,6 +2420,17 @@ own_ip_addr=127.0.0.1
# (default: 1 = activated)
#pasn_noauth=1
# Unauthenticated EPPKE activated
# This indicates whether EPPKE without a base AKM (i.e., using
# WPA_KEY_MGMT_EPPKE as the selected AKMP in the RSNE without mutual
# authentication) is allowed.
#
# When enabled, the AP advertises support for unauthenticated EPPKE via the
# Unauthenticated EPPKE bit in the RSNXE (WLAN_RSNX_CAPAB_UNAUTH_EPPKE).
# See IEEE P802.11bi/D4.0, 12.16.9.1 for details.
# (default: 0 = disabled)
#eppke_unauth=0
# SSID protection in 4-way handshake
# The IEEE 802.11i-2004 RSN design did not provide means for protecting the
# SSID in the general case. IEEE P802.11REVme/D6.0 added support for this in
@@ -2298,6 +2450,129 @@ own_ip_addr=127.0.0.1
#
#ssid_protection=0
# Known STA Identification
# IEEE Std 802.11-2024 adds a mechanism that allows the SA Query procedure on
# (re)association to the previously used AP to be skipped when that AP still
# has a valid security association. This can speed up cases where a STA needs to
# reassociate back to the same AP to update some association parameters.
#
# 0 = Do not process Known STA Identification (default)
# 1 = Allow Known STA Identification to be used to skip SA Query procedure
#known_sta_identification=0
# RSNE/RSNXE override
#
# These parameters can be used to configure RSN parameters for STAs that support
# the override elements. The RSN parameters for STAs that do not support these
# mechanisms are configured in the referenced configuration parameters. The AP
# allows STAs to use either of the configured sets for negotiating RSN
# parameters.
#
# The main purpose of this mechanism is to make the AP look like it is using an
# older security mechanism (e.g., WPA2-Personal) to older STAs while allowing
# new stations use newer security mechanisms (e.g., WPA3-Personal) based on the
# override values. This might be needed to work around issues with deployed
# STAs that do not implement RSNE extensibility correctly and may fail to
# connect when the AP is using a transition mode like WPA3-Personal transition
# mode.
#
# Key management; see wpa_key_mgmt for RSNE configuration
#rsn_override_key_mgmt=<accepted key management algorithms>
#
# Pairwise cipher suites; see rsn_pairwise for RSNE configuration
#rsn_override_pairwise=<accepted cipher suites)
#
# Management frame protection (MFP/PMF); see ieee80211w for RSNE configuration
# 0 = disabled
# 1 = optional
# 2 = required
#rsn_override_mfp=<0/1/2>
#
# Second set of similar parameters. These are required to be used for
# Wi-Fi 7 (EHT/MLO) associations with RSN overriding and can optionally be used
# in cases that do not use Wi-Fi 7.
#rsn_override_key_mgmt_2
#rsn_override_pairwise_2
#rsn_override_mfp_2
#
# The RSNXE is normally included if any of the extended RSN capabilities is
# enabled/supported. When using RSN overriding, a separate RSNXOE is included
# and it may be more interoperable to omit the RSNXE completely. This
# configuration parameter can be used to do that.
# 0 = Include the RSNXE if any extended RSN capability is enabled/supported
# (default).
# 1 = Do not include the RSNXE.
#rsn_override_omit_rsnxe=0
# Allow MLO partner link association from a non-RSNO-capable STA that
# negotiates an AKM from the override set (e.g., SAE on the 6 GHz primary
# link) but whose partner link per-STA profile RSNE would not match the base
# wpa_key_mgmt of that link (e.g., WPA-PSK on 2.4 GHz in WPA3-Personal
# Compatibility Mode). When enabled, the AP MLD falls back to
# rsn_override_key_mgmt for the partner link key_mgmt validation to allow the
# stronger AKM to be used for ML associations even if when RSNE does not
# advertise support for this on all links.
# 0 = Disabled (default)
# 1 = Enabled
#rsn_override_mlo_compat=0
#
# Example configuration for WPA2-Personal/PMF-optional in RSNE and
# WPA3-Personal/PMF-required/MLO in override elements
#wpa_key_mgmt=WPA-PSK
#rsn_pairwise=CCMP
#ieee80211w=1
#rsn_override_key_mgmt=SAE
#rsn_override_pairwise=GCMP-256
#rsn_override_mfp=2
#rsn_override_key_mgmt_2=SAE-EXT-KEY
#rsn_override_pairwise_2=GCMP-256
#rsn_override_mfp_2=2
#beacon_prot=1
#sae_groups=19 20
#sae_require_mfp=1
#sae_pwe=2
##### IEEE 802.11az configuration #############################################
#
# urnm_mfpr:
# urnm_mfpr mandates use of management frame protection and establishment of
# PTKSA across all supported bandwidths, regardless of the urnm_mfpr_x20
# setting for unassociated negotiation and measurement operations.
#
# urnm_mfpr_x20:
# urnm_mfpr_x20 allows unassociated negotiation and measurement
# operations using 20 MHz bandwidth without requiring management frame
# protection and a PTKSA while mandating the security for higher bandwidth
# cases. This is only valid if urnm_mfpr is false.
#
# Behavior Summary:
# - urnm_mfpr = 1:
# - PTKSA is required for all supported bandwidths.
# - urnm_mfpr_x20 is ignored.
#
# - urnm_mfpr = 0 and urnm_mfpr_x20 = 1:
# - PTKSA is required only for bandwidths greater than 20 MHz.
#
# - urnm_mfpr = 0 and urnm_mfpr_x20 = 0:
# - PTKSA is not required for any bandwidths.
#urnm_mfpr=0
#urnm_mfpr_x20=0
#i2r_lmr_policy: Policy for I2R LMR feedback
# This indicates whether initiating stations are required to support the
# capability to generate and transmit Initiator-to-Responder Location
# Measurement Reports (I2R LMRs).
# This parameter matches the dot11I2RLMRFeedbackPolicy MIB variable.
#
# When set to 1:
# Do not require initiating stations to support I2R LMR generation and
# transmission.
#
# When set to 0:
# Request initiating stations to negotiate and support the transmission of
# I2R LMRs during location measurement operations.
#i2r_lmr_policy=1
##### IEEE 802.11r configuration ##############################################
# Mobility Domain identifier (dot11FTMobilityDomainID, MDID)
@@ -2402,6 +2677,34 @@ own_ip_addr=127.0.0.1
# 1 = enabled
#ft_psk_generate_local=0
##### IEEE 802.11bi related configuration #####################################
# IEEE Std 802.11bi introduces following Enhanced Privacy Protection (EPP)
# features.
#
# (Re)Association Request/Response frame encryption: Indicates if the AP
# supports encryption of (Re)Association Request and Response frames
# 0 = disabled (default)
# 1 = enabled
#assoc_frame_encryption=0
# PMKSA caching privacy: Indicates if the AP supports recomputation of the PMKID
# after the indicated PMKID in the RSNE identifies a cached PMKSA and a PTKSA
# was established using the identified PMKSA. The recomputed PMKID will be
# delivered to the non-AP STA in the Key Delivery element added in the encrypted
# (Re)Association Response frame.
# 0 = disabled (default)
# 1 = enabled
#pmksa_caching_privacy=0
# IEEE 802.1X (EAP) Authentication utilizing Authentication frames: Indicates
# if the AP supports encapsulation of EAP PDUs within Authentication frames
# in addition to the older design of EAPOL frames (Data frames after
# association).
# 0 = disabled (default)
# 1 = enabled
#eap_using_authentication_frames=0
##### Neighbor table ##########################################################
# Maximum number of entries kept in AP table (either for neighbor table or for
# detecting Overlapping Legacy BSS Condition). The oldest entry will be
@@ -2573,7 +2876,7 @@ own_ip_addr=127.0.0.1
# message when acting as a Registrar. If skip_cred_build=1, this data will also
# be able to override the Credential attribute that would have otherwise been
# automatically generated based on network configuration. This configuration
# option points to an external file that much contain the WPS Credential
# option points to an external file that contains the WPS Credential
# attribute(s) as binary data.
#extra_cred=hostapd.cred
@@ -2970,9 +3273,6 @@ own_ip_addr=127.0.0.1
# forging such frames to other stations in the BSS.
#disable_dgaf=1
# OSU Server-Only Authenticated L2 Encryption Network
#osen=1
# ANQP Domain ID (0..65535)
# An identifier for a set of APs in an ESS that share the same common ANQP
# information. 0 = Some of the ANQP information is unique to this AP (default).
@@ -3053,42 +3353,6 @@ own_ip_addr=127.0.0.1
# @1@ = MAC address of the STA (colon separated hex octets)
#hs20_t_c_server_url=https://example.com/t_and_c?addr=@1@&ap=123
# OSU and Operator icons
# <Icon Width>:<Icon Height>:<Language code>:<Icon Type>:<Name>:<file path>
#hs20_icon=32:32:eng:image/png:icon32:/tmp/icon32.png
#hs20_icon=64:64:eng:image/png:icon64:/tmp/icon64.png
# OSU SSID (see ssid2 for format description)
# This is the SSID used for all OSU connections to all the listed OSU Providers.
#osu_ssid="example"
# OSU Providers
# One or more sets of following parameter. Each OSU provider is started by the
# mandatory osu_server_uri item. The other parameters add information for the
# last added OSU provider. osu_nai specifies the OSU_NAI value for OSEN
# authentication when using a standalone OSU BSS. osu_nai2 specifies the OSU_NAI
# value for OSEN authentication when using a shared BSS (Single SSID) for OSU.
#
#osu_server_uri=https://example.com/osu/
#osu_friendly_name=eng:Example operator
#osu_friendly_name=fin:Esimerkkipalveluntarjoaja
#[email protected]
#[email protected]
#osu_method_list=1 0
#osu_icon=icon32
#osu_icon=icon64
#osu_service_desc=eng:Example services
#osu_service_desc=fin:Esimerkkipalveluja
#
#osu_server_uri=...
# Operator Icons
# Operator icons are specified using references to the hs20_icon entries
# (Name subfield). This information, if present, is advertsised in the
# Operator Icon Metadata ANQO-element.
#operator_icon=icon32
#operator_icon=icon64
##### Multiband Operation (MBO) ###############################################
#
# MBO enabled
@@ -3267,6 +3531,10 @@ own_ip_addr=127.0.0.1
# (channel switch operating class is needed)
#ecsa_ie_only=0
#
# Include only CSA IE without ECSA IE
# (the operating class is not mentioned)
#csa_ie_only=0
# Delay EAPOL-Key messages 1/4 and 3/4 by not sending the frame until the last
# attempt (wpa_pairwise_update_count). This will trigger a timeout on all
# previous attempts and thus delays the frame. (testing only)
@@ -3350,6 +3618,18 @@ own_ip_addr=127.0.0.1
# 2 = Enhanced multiple BSSID advertisement enabled.
#mbssid=0
#
# Maximum number of BSSs that can be added into a Multiple BSSID set
# This is a radio level parameter. If not set (or 0), the maximum is determined
# automatically based on the configured BSSs which may limit dynamic addition
# of new BSSs.
#mbssid_max=0
#
# Multiple BSSID Index override
# This is a BSS level parameter. If not set (or 0), the BSSID index is
# determined automatically based on the configured BSSs which may limit dynamic
# addition of new BSSs.
#mbssid_index=0
#
# The transmitting interface should be added with the 'interface' option while
# the non-transmitting interfaces should be added using the 'bss' option.
# Security configuration should be added separately per interface, if required.
+122 -8
View File
@@ -21,7 +21,7 @@
static const char *const hostapd_cli_version =
"hostapd_cli v" VERSION_STR "\n"
"Copyright (c) 2004-2024, Jouni Malinen <[email protected]> and contributors";
"Copyright (c) 2004-2026, Jouni Malinen <[email protected]> and contributors";
static struct wpa_ctrl *ctrl_conn;
static int hostapd_cli_quit = 0;
@@ -54,7 +54,11 @@ static void usage(void)
fprintf(stderr, "%s\n", hostapd_cli_version);
fprintf(stderr,
"\n"
"usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvBr] "
"usage: hostapd_cli [-p<path>] [-i<ifname>] "
#ifdef CONFIG_IEEE80211BE
"[-l<link_id>] "
#endif /* CONFIG_IEEE80211BE */
"[-hvBr] "
"[-a<path>] \\\n"
" [-P<pid file>] [-G<ping interval>] [command..]\n"
"\n"
@@ -74,7 +78,11 @@ static void usage(void)
" -B run a daemon in the background\n"
" -i<ifname> Interface to listen on (default: first "
"interface found in the\n"
" socket path)\n\n");
" socket path)\n"
#ifdef CONFIG_IEEE80211BE
" -l<link_id> Link ID of the interface in case of Multi-Link Operation\n"
#endif /* CONFIG_IEEE80211BE */
"\n");
print_help(stderr, NULL);
}
@@ -192,7 +200,7 @@ static void hostapd_cli_msg_cb(char *msg, size_t len)
static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd, int print)
{
char buf[4096];
char buf[8192];
size_t len;
int ret;
@@ -213,6 +221,8 @@ static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd, int print)
if (print) {
buf[len] = '\0';
printf("%s", buf);
if (interactive && len > 0 && buf[len - 1] != '\n')
printf("\n");
}
return 0;
}
@@ -1223,6 +1233,13 @@ static int hostapd_cli_cmd_notify_cw_change(struct wpa_ctrl *ctrl,
}
static int hostapd_cli_cmd_set_bw(struct wpa_ctrl *ctrl,
int argc, char *argv[])
{
return hostapd_cli_cmd(ctrl, "SET_BW", 0, argc, argv);
}
static int hostapd_cli_cmd_enable(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
@@ -1265,6 +1282,29 @@ static int hostapd_cli_cmd_enable_mld(struct wpa_ctrl *ctrl, int argc,
}
#ifdef CONFIG_TESTING_OPTIONS
static int hostapd_cli_cmd_remove_link(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
unsigned int count = (argc && atoi(argv[0]) > 0) ? atoi(argv[0]) : 1;
char buf[64];
snprintf(buf, sizeof(buf), "LINK_REMOVE %u", count);
return wpa_ctrl_command(ctrl, buf);
}
static int hostapd_cli_cmd_link_enable(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
return hostapd_cli_cmd(ctrl, "LINK_ENABLE", 1, argc, argv);
}
#endif /* CONFIG_TESTING_OPTIONS */
static int hostapd_cli_cmd_disable_mld(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
@@ -1654,6 +1694,31 @@ static int hostapd_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
#endif /* ANDROID */
#ifdef CONFIG_AFC
static int hostapd_cli_cmd_afc_get_request(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
return hostapd_cli_cmd(ctrl, "AFC_GET_REQUEST", 0, 0, NULL);
}
static int hostapd_cli_cmd_afc_get_response(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
return hostapd_cli_cmd(ctrl, "AFC_GET_RESPONSE", 0, 0, NULL);
}
static int hostapd_cli_cmd_afc_send_request(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
return hostapd_cli_cmd(ctrl, "AFC_SEND_REQUEST", 0, 0, NULL);
}
#endif /* CONFIG_AFC */
struct hostapd_cli_cmd {
const char *cmd;
int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
@@ -1762,6 +1827,10 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
#endif /* CONFIG_IEEE80211AX */
{ "notify_cw_change", hostapd_cli_cmd_notify_cw_change, NULL,
"<channel_width> = 0 - 20 MHz, 1 - 40 MHz, 2 - 80 MHz, 3 - 160 MHz" },
{ "set_bw", hostapd_cli_cmd_set_bw, NULL,
"[sec_channel_offset=] [center_freq1=]\n"
" [center_freq2=] [bandwidth=] [ht|vht]\n"
" = change channel bandwidth" },
{ "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif, NULL,
"<addr> <url>\n"
" = send WNM-Notification Subscription Remediation Request" },
@@ -1783,6 +1852,13 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
"= disable hostapd on current interface" },
{ "enable_mld", hostapd_cli_cmd_enable_mld, NULL,
"= enable AP MLD to which the interface is affiliated" },
#ifdef CONFIG_TESTING_OPTIONS
{ "remove_link", hostapd_cli_cmd_remove_link, NULL,
"<count> = remove MLO link and send Reconfiguration MLE" },
{ "link_enable", hostapd_cli_cmd_link_enable, NULL,
" bss_config=<phy>:<config file>\n"
" = Enable a link previously removed from the MLD AP" },
#endif /* CONFIG_TESTING_OPTIONS */
{ "disable_mld", hostapd_cli_cmd_disable_mld, NULL,
"= disable AP MLD to which the interface is affiliated" },
{ "update_beacon", hostapd_cli_cmd_update_beacon, NULL,
@@ -1882,6 +1958,14 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
{ "driver", hostapd_cli_cmd_driver, NULL,
"<driver sub command> [<hex formatted data>] = send driver command data" },
#endif /* ANDROID */
#ifdef CONFIG_AFC
{ "afc_get_request", hostapd_cli_cmd_afc_get_request, NULL,
" = Show latest AFC request data"},
{ "afc_get_response", hostapd_cli_cmd_afc_get_response, NULL,
" = Show latest AFC response data"},
{ "afc_send_request", hostapd_cli_cmd_afc_send_request, NULL,
" = Send another AFC request and upadte the timeout"},
#endif /* CONFIG_AFC */
{ NULL, NULL, NULL, NULL }
};
@@ -2174,9 +2258,13 @@ static void hostapd_cli_action_ping(void *eloop_ctx, void *timeout_ctx)
if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
hostapd_cli_action_cb) < 0 ||
len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
printf("hostapd did not reply to PING command - exiting\n");
eloop_terminate();
return;
printf("hostapd did not reply to PING command - open a new connection\n");
hostapd_cli_close_connection();
if (hostapd_cli_reconnect(ctrl_ifname)) {
printf("Failed to establish new connection - exit\n");
eloop_terminate();
return;
}
}
eloop_register_timeout(ping_interval, 0, hostapd_cli_action_ping,
ctrl, NULL);
@@ -2212,12 +2300,15 @@ int main(int argc, char *argv[])
int c;
int daemonize = 0;
int reconnect = 0;
#ifdef CONFIG_IEEE80211BE
int link_id = -1;
#endif /* CONFIG_IEEE80211BE */
if (os_program_init())
return -1;
for (;;) {
c = getopt(argc, argv, "a:BhG:i:p:P:rs:v");
c = getopt(argc, argv, "a:BhG:i:l:p:P:rs:v");
if (c < 0)
break;
switch (c) {
@@ -2252,6 +2343,11 @@ int main(int argc, char *argv[])
case 's':
client_socket_dir = optarg;
break;
#ifdef CONFIG_IEEE80211BE
case 'l':
link_id = atoi(optarg);
break;
#endif /* CONFIG_IEEE80211BE */
default:
usage();
return -1;
@@ -2285,6 +2381,24 @@ int main(int argc, char *argv[])
closedir(dir);
}
}
#ifdef CONFIG_IEEE80211BE
if (link_id >= 0 && ctrl_ifname) {
int ret;
char buf[300];
ret = os_snprintf(buf, sizeof(buf), "%s_%s%d",
ctrl_ifname, WPA_CTRL_IFACE_LINK_NAME,
link_id);
if (os_snprintf_error(sizeof(buf), ret))
return -1;
os_free(ctrl_ifname);
ctrl_ifname = os_strdup(buf);
link_id = -1;
}
#endif /* CONFIG_IEEE80211BE */
hostapd_cli_reconnect(ctrl_ifname);
if (ctrl_conn) {
if (warning_displayed)
+89 -7
View File
@@ -20,6 +20,7 @@
#include "crypto/tls.h"
#include "common/version.h"
#include "common/dpp.h"
#include "common/proc_coord.h"
#include "drivers/driver.h"
#include "eap_server/eap.h"
#include "eap_server/tncs.h"
@@ -160,6 +161,7 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
struct wpa_driver_capa capa;
#ifdef CONFIG_IEEE80211BE
struct hostapd_data *h_hapd = NULL;
void *shared_hapd = NULL;
#endif /* CONFIG_IEEE80211BE */
if (hapd->driver == NULL || hapd->driver->hapd_init == NULL) {
@@ -168,8 +170,16 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
}
#ifdef CONFIG_IEEE80211BE
if (conf->mld_ap)
if (conf->mld_ap) {
hostapd_bss_setup_multi_link(hapd, iface->interfaces);
if (!hapd->mld) {
wpa_printf(MSG_ERROR,
"MLD: Failed to initialize context for %s",
conf->iface);
return -1;
}
h_hapd = hostapd_mld_get_first_bss(hapd);
}
if (h_hapd) {
hapd->drv_priv = h_hapd->drv_priv;
@@ -191,7 +201,6 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
os_memcpy(hapd->own_addr, b, ETH_ALEN);
}
hostapd_mld_add_link(hapd);
wpa_printf(MSG_DEBUG,
"Setup of non first link (%d) BSS of MLD %s",
hapd->mld_link_id, hapd->conf->iface);
@@ -254,6 +263,42 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
params.own_addr = hapd->own_addr;
#ifdef CONFIG_IEEE80211BE
if (hapd->driver->can_share_drv &&
hapd->driver->can_share_drv(hapd, &params, &shared_hapd)) {
char force_ifname[IFNAMSIZ];
const u8 *addr = params.bssid;
u8 if_addr[ETH_ALEN];
if (!shared_hapd) {
wpa_printf(MSG_ERROR, "Failed to get the shared drv");
os_free(params.bridge);
return -1;
}
/* Share an already initialized driver interface instance
* using an AP mode BSS in it instead of adding a new driver
* interface instance for the same driver. */
if (hostapd_if_add(shared_hapd, WPA_IF_AP_BSS,
params.ifname, addr, hapd,
&hapd->drv_priv, force_ifname, if_addr,
params.num_bridge && params.bridge[0] ?
params.bridge[0] : NULL,
1)) {
wpa_printf(MSG_ERROR, "Failed to add BSS (BSSID="
MACSTR ")", MAC2STR(hapd->own_addr));
os_free(params.bridge);
return -1;
}
os_free(params.bridge);
hapd->interface_added = 1;
os_memcpy(params.own_addr, addr ? addr : if_addr, ETH_ALEN);
goto pre_setup_mld;
}
#endif /* CONFIG_IEEE80211BE */
hapd->drv_priv = hapd->driver->hapd_init(hapd, &params);
os_free(params.bridge);
if (hapd->drv_priv == NULL) {
@@ -264,6 +309,7 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
}
#ifdef CONFIG_IEEE80211BE
pre_setup_mld:
/*
* This is the first interface added to the AP MLD, so have the
* interface hardware address be the MLD address, while the link address
@@ -278,7 +324,6 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
else
os_memcpy(hapd->own_addr, b, ETH_ALEN);
hostapd_mld_add_link(hapd);
wpa_printf(MSG_DEBUG, "Setup of first link (%d) BSS of MLD %s",
hapd->mld_link_id, hapd->conf->iface);
}
@@ -338,8 +383,14 @@ setup_mld:
hapd->mld_link_id, MAC2STR(hapd->mld->mld_addr),
MAC2STR(hapd->own_addr));
hostapd_drv_link_add(hapd, hapd->mld_link_id,
hapd->own_addr);
if (hostapd_drv_link_add(hapd, hapd->mld_link_id,
hapd->own_addr)) {
wpa_printf(MSG_ERROR,
"MLD: Failed to add link %d in MLD %s",
hapd->mld_link_id, hapd->conf->iface);
return -1;
}
hostapd_mld_add_link(hapd);
}
#endif /* CONFIG_IEEE80211BE */
@@ -555,7 +606,7 @@ static void show_version(void)
"hostapd v%s\n"
"User space daemon for IEEE 802.11 AP management,\n"
"IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
"Copyright (c) 2002-2024, Jouni Malinen <[email protected]> "
"Copyright (c) 2002-2026, Jouni Malinen <[email protected]> "
"and contributors\n",
VERSION_STR);
}
@@ -570,6 +621,9 @@ static void usage(void)
"\\\n"
" [-g <global ctrl_iface>] [-G <group>]\\\n"
" [-i <comma-separated list of interface names>]\\\n"
#ifdef CONFIG_PROCESS_COORDINATION
" [-z<process coordination directory>] \\\n"
#endif /* CONFIG_PROCESS_COORDINATION */
" <configuration file(s)>\n"
"\n"
"options:\n"
@@ -595,6 +649,9 @@ static void usage(void)
" -S start all the interfaces synchronously\n"
" -t include timestamps in some debug messages\n"
" -v show hostapd version\n"
#ifdef CONFIG_PROCESS_COORDINATION
" -z process coordination directory\n"
#endif /* CONFIG_PROCESS_COORDINATION */
" -q show less debug messages (-qq for even less)\n");
exit(1);
@@ -748,6 +805,7 @@ static void hostapd_global_cleanup_mld(struct hapd_interfaces *interfaces)
if (!interfaces->mld[i])
continue;
interfaces->mld_ctrl_iface_deinit(interfaces->mld[i]);
os_free(interfaces->mld[i]);
interfaces->mld[i] = NULL;
}
@@ -779,6 +837,9 @@ int main(int argc, char *argv[])
#ifdef CONFIG_DPP
struct dpp_global_config dpp_conf;
#endif /* CONFIG_DPP */
#ifdef CONFIG_PROCESS_COORDINATION
const char *proc_coord_dir = NULL;
#endif /* CONFIG_PROCESS_COORDINATION */
if (os_program_init())
return -1;
@@ -793,6 +854,10 @@ int main(int argc, char *argv[])
interfaces.global_iface_path = NULL;
interfaces.global_iface_name = NULL;
interfaces.global_ctrl_sock = -1;
#ifdef CONFIG_IEEE80211BE
interfaces.mld_ctrl_iface_init = hostapd_mld_ctrl_iface_init;
interfaces.mld_ctrl_iface_deinit = hostapd_mld_ctrl_iface_deinit;
#endif /* CONFIG_IEEE80211BE */
dl_list_init(&interfaces.global_ctrl_dst);
#ifdef CONFIG_ETH_P_OUI
dl_list_init(&interfaces.eth_p_oui);
@@ -809,7 +874,7 @@ int main(int argc, char *argv[])
#endif /* CONFIG_DPP */
for (;;) {
c = getopt(argc, argv, "b:Bde:f:hi:KP:sSTtu:vg:G:q");
c = getopt(argc, argv, "b:Bde:f:hi:KP:sSTtu:vg:G:qz:");
if (c < 0)
break;
switch (c) {
@@ -885,6 +950,11 @@ int main(int argc, char *argv[])
case 'q':
wpa_debug_level++;
break;
#ifdef CONFIG_PROCESS_COORDINATION
case 'z':
proc_coord_dir = optarg;
break;
#endif /* CONFIG_PROCESS_COORDINATION */
default:
usage();
break;
@@ -933,6 +1003,14 @@ int main(int argc, char *argv[])
eloop_register_timeout(HOSTAPD_CLEANUP_INTERVAL, 0,
hostapd_periodic, &interfaces, NULL);
#ifdef CONFIG_PROCESS_COORDINATION
if (proc_coord_dir) {
interfaces.pc = proc_coord_init(proc_coord_dir);
if (!interfaces.pc)
goto out;
}
#endif /* CONFIG_PROCESS_COORDINATION */
if (fst_global_init()) {
wpa_printf(MSG_ERROR,
"Failed to initialize global FST context");
@@ -1045,6 +1123,10 @@ int main(int argc, char *argv[])
dpp_global_deinit(interfaces.dpp);
#endif /* CONFIG_DPP */
#ifdef CONFIG_PROCESS_COORDINATION
proc_coord_deinit(interfaces.pc);
#endif /* CONFIG_PROCESS_COORDINATION */
if (interfaces.eloop_initialized)
eloop_cancel_timeout(hostapd_periodic, &interfaces, NULL);
hostapd_global_deinit(pid_file, interfaces.eloop_initialized);
+1 -4
View File
@@ -30,10 +30,7 @@ L_CFLAGS += -DCONFIG_CTRL_IFACE
L_CFLAGS += -DCONFIG_CTRL_IFACE_UNIX
L_CFLAGS += -DCONFIG_CTRL_IFACE_CLIENT_DIR=\"/data/misc/wifi/sockets\"
OBJS = spp_client.c
OBJS += oma_dm_client.c
OBJS += osu_client.c
OBJS += est.c
OBJS = osu_client.c
OBJS += ../../src/common/wpa_ctrl.c
OBJS += ../../src/common/wpa_helpers.c
OBJS += ../../src/utils/xml-utils.c
+1 -4
View File
@@ -24,10 +24,7 @@ LIBS += $(GTKLIBS)
endif
endif
OBJS=spp_client.o
OBJS += oma_dm_client.o
OBJS += osu_client.o
OBJS += est.o
OBJS = osu_client.o
OBJS += ../../src/utils/xml-utils.o
CFLAGS += -DCONFIG_CTRL_IFACE
CFLAGS += -DCONFIG_CTRL_IFACE_UNIX
-47
View File
@@ -1,47 +0,0 @@
<DevDetail xmlns="urn:oma:mo:oma-dm-devdetail:1.0">
<Ext>
<org.wi-fi>
<Wi-Fi>
<EAPMethodList>
<EAPMethod1>
<EAPType>13</EAPType>
</EAPMethod1>
<EAPMethod2>
<EAPType>21</EAPType>
<InnerMethod>MS-CHAP-V2</InnerMethod>
</EAPMethod2>
<EAPMethod3>
<EAPType>18</EAPType>
</EAPMethod3>
<EAPMethod4>
<EAPType>23</EAPType>
</EAPMethod4>
<EAPMethod5>
<EAPType>50</EAPType>
</EAPMethod5>
</EAPMethodList>
<ManufacturingCertificate>false</ManufacturingCertificate>
<Wi-FiMACAddress>020102030405</Wi-FiMACAddress>
<IMSI>310026000000000</IMSI>
<IMEI_MEID>imei:490123456789012</IMEI_MEID>
<ClientTriggerRedirectURI>http://localhost:12345/</ClientTriggerRedirectURI>
<Ops>
<launchBrowserToURI></launchBrowserToURI>
<negotiateClientCertTLS></negotiateClientCertTLS>
<getCertificate></getCertificate>
</Ops>
</Wi-Fi>
</org.wi-fi>
</Ext>
<URI>
<MaxDepth>0</MaxDepth>
<MaxTotLen>0</MaxTotLen>
<MaxSegLen>0</MaxSegLen>
</URI>
<DevType>MobilePhone</DevType>
<OEM>Manufacturer</OEM>
<FwV>1.0</FwV>
<SwV>1.0</SwV>
<HwV>1.0</HwV>
<LrgObj>false</LrgObj>
</DevDetail>
-7
View File
@@ -1,7 +0,0 @@
<DevInfo xmlns="urn:oma:mo:oma-dm-devinfo:1.0">
<DevId>urn:Example:HS20-station:123456</DevId>
<Man>Manufacturer</Man>
<Mod>HS20-station</Mod>
<DmV>1.2</DmV>
<Lang>en</Lang>
</DevInfo>
-742
View File
@@ -1,742 +0,0 @@
/*
* Hotspot 2.0 OSU client - EST client
* Copyright (c) 2012-2014, Qualcomm Atheros, Inc.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/pkcs7.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/opensslv.h>
#include <openssl/buffer.h>
#include "common.h"
#include "utils/base64.h"
#include "utils/xml-utils.h"
#include "utils/http-utils.h"
#include "osu_client.h"
static int pkcs7_to_cert(struct hs20_osu_client *ctx, const u8 *pkcs7,
size_t len, char *pem_file, char *der_file)
{
#ifdef OPENSSL_IS_BORINGSSL
CBS pkcs7_cbs;
#else /* OPENSSL_IS_BORINGSSL */
PKCS7 *p7 = NULL;
const unsigned char *p = pkcs7;
#endif /* OPENSSL_IS_BORINGSSL */
STACK_OF(X509) *certs;
int i, num, ret = -1;
BIO *out = NULL;
#ifdef OPENSSL_IS_BORINGSSL
certs = sk_X509_new_null();
if (!certs)
goto fail;
CBS_init(&pkcs7_cbs, pkcs7, len);
if (!PKCS7_get_certificates(certs, &pkcs7_cbs)) {
wpa_printf(MSG_INFO, "Could not parse PKCS#7 object: %s",
ERR_error_string(ERR_get_error(), NULL));
write_result(ctx, "Could not parse PKCS#7 object from EST");
goto fail;
}
#else /* OPENSSL_IS_BORINGSSL */
p7 = d2i_PKCS7(NULL, &p, len);
if (p7 == NULL) {
wpa_printf(MSG_INFO, "Could not parse PKCS#7 object: %s",
ERR_error_string(ERR_get_error(), NULL));
write_result(ctx, "Could not parse PKCS#7 object from EST");
goto fail;
}
switch (OBJ_obj2nid(p7->type)) {
case NID_pkcs7_signed:
certs = p7->d.sign->cert;
break;
case NID_pkcs7_signedAndEnveloped:
certs = p7->d.signed_and_enveloped->cert;
break;
default:
certs = NULL;
break;
}
#endif /* OPENSSL_IS_BORINGSSL */
if (!certs || ((num = sk_X509_num(certs)) == 0)) {
wpa_printf(MSG_INFO, "No certificates found in PKCS#7 object");
write_result(ctx, "No certificates found in PKCS#7 object");
goto fail;
}
if (der_file) {
FILE *f = fopen(der_file, "wb");
if (f == NULL)
goto fail;
i2d_X509_fp(f, sk_X509_value(certs, 0));
fclose(f);
}
if (pem_file) {
out = BIO_new(BIO_s_file());
if (out == NULL ||
BIO_write_filename(out, pem_file) <= 0)
goto fail;
for (i = 0; i < num; i++) {
X509 *cert = sk_X509_value(certs, i);
X509_print(out, cert);
PEM_write_bio_X509(out, cert);
BIO_puts(out, "\n");
}
}
ret = 0;
fail:
#ifdef OPENSSL_IS_BORINGSSL
if (certs)
sk_X509_pop_free(certs, X509_free);
#else /* OPENSSL_IS_BORINGSSL */
PKCS7_free(p7);
#endif /* OPENSSL_IS_BORINGSSL */
if (out)
BIO_free_all(out);
return ret;
}
int est_load_cacerts(struct hs20_osu_client *ctx, const char *url)
{
char *buf, *resp;
size_t buflen;
unsigned char *pkcs7;
size_t pkcs7_len, resp_len;
int res;
buflen = os_strlen(url) + 100;
buf = os_malloc(buflen);
if (buf == NULL)
return -1;
os_snprintf(buf, buflen, "%s/cacerts", url);
wpa_printf(MSG_INFO, "Download EST cacerts from %s", buf);
write_summary(ctx, "Download EST cacerts from %s", buf);
ctx->no_osu_cert_validation = 1;
http_ocsp_set(ctx->http, 1);
res = http_download_file(ctx->http, buf, "Cert/est-cacerts.txt",
ctx->ca_fname);
http_ocsp_set(ctx->http,
(ctx->workarounds & WORKAROUND_OCSP_OPTIONAL) ? 1 : 2);
ctx->no_osu_cert_validation = 0;
if (res < 0) {
wpa_printf(MSG_INFO, "Failed to download EST cacerts from %s",
buf);
write_result(ctx, "Failed to download EST cacerts from %s",
buf);
os_free(buf);
return -1;
}
os_free(buf);
resp = os_readfile("Cert/est-cacerts.txt", &resp_len);
if (resp == NULL) {
wpa_printf(MSG_INFO, "Could not read Cert/est-cacerts.txt");
write_result(ctx, "Could not read EST cacerts");
return -1;
}
pkcs7 = base64_decode(resp, resp_len, &pkcs7_len);
if (pkcs7 && pkcs7_len < resp_len / 2) {
wpa_printf(MSG_INFO, "Too short base64 decode (%u bytes; downloaded %u bytes) - assume this was binary",
(unsigned int) pkcs7_len, (unsigned int) resp_len);
os_free(pkcs7);
pkcs7 = NULL;
}
if (pkcs7 == NULL) {
wpa_printf(MSG_INFO, "EST workaround - Could not decode base64, assume this is DER encoded PKCS7");
pkcs7 = os_malloc(resp_len);
if (pkcs7) {
os_memcpy(pkcs7, resp, resp_len);
pkcs7_len = resp_len;
}
}
os_free(resp);
if (pkcs7 == NULL) {
wpa_printf(MSG_INFO, "Could not fetch PKCS7 cacerts");
write_result(ctx, "Could not fetch EST PKCS#7 cacerts");
return -1;
}
res = pkcs7_to_cert(ctx, pkcs7, pkcs7_len, "Cert/est-cacerts.pem",
NULL);
os_free(pkcs7);
if (res < 0) {
wpa_printf(MSG_INFO, "Could not parse CA certs from PKCS#7 cacerts response");
write_result(ctx, "Could not parse CA certs from EST PKCS#7 cacerts response");
return -1;
}
unlink("Cert/est-cacerts.txt");
return 0;
}
/*
* CsrAttrs ::= SEQUENCE SIZE (0..MAX) OF AttrOrOID
*
* AttrOrOID ::= CHOICE {
* oid OBJECT IDENTIFIER,
* attribute Attribute }
*
* Attribute ::= SEQUENCE {
* type OBJECT IDENTIFIER,
* values SET SIZE(1..MAX) OF OBJECT IDENTIFIER }
*/
typedef struct {
ASN1_OBJECT *type;
STACK_OF(ASN1_OBJECT) *values;
} Attribute;
typedef struct {
int type;
union {
ASN1_OBJECT *oid;
Attribute *attribute;
} d;
} AttrOrOID;
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
DEFINE_STACK_OF(AttrOrOID)
#endif
typedef struct {
int type;
STACK_OF(AttrOrOID) *attrs;
} CsrAttrs;
ASN1_SEQUENCE(Attribute) = {
ASN1_SIMPLE(Attribute, type, ASN1_OBJECT),
ASN1_SET_OF(Attribute, values, ASN1_OBJECT)
} ASN1_SEQUENCE_END(Attribute);
ASN1_CHOICE(AttrOrOID) = {
ASN1_SIMPLE(AttrOrOID, d.oid, ASN1_OBJECT),
ASN1_SIMPLE(AttrOrOID, d.attribute, Attribute)
} ASN1_CHOICE_END(AttrOrOID);
ASN1_CHOICE(CsrAttrs) = {
ASN1_SEQUENCE_OF(CsrAttrs, attrs, AttrOrOID)
} ASN1_CHOICE_END(CsrAttrs);
IMPLEMENT_ASN1_FUNCTIONS(CsrAttrs);
static void add_csrattrs_oid(struct hs20_osu_client *ctx, ASN1_OBJECT *oid,
STACK_OF(X509_EXTENSION) *exts)
{
char txt[100];
int res;
if (!oid)
return;
res = OBJ_obj2txt(txt, sizeof(txt), oid, 1);
if (res < 0 || res >= (int) sizeof(txt))
return;
if (os_strcmp(txt, "1.2.840.113549.1.9.7") == 0) {
wpa_printf(MSG_INFO, "TODO: csrattr challengePassword");
} else if (os_strcmp(txt, "1.2.840.113549.1.1.11") == 0) {
wpa_printf(MSG_INFO, "csrattr sha256WithRSAEncryption");
} else {
wpa_printf(MSG_INFO, "Ignore unsupported csrattr oid %s", txt);
}
}
static void add_csrattrs_ext_req(struct hs20_osu_client *ctx,
STACK_OF(ASN1_OBJECT) *values,
STACK_OF(X509_EXTENSION) *exts)
{
char txt[100];
int i, num, res;
num = sk_ASN1_OBJECT_num(values);
for (i = 0; i < num; i++) {
ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(values, i);
res = OBJ_obj2txt(txt, sizeof(txt), oid, 1);
if (res < 0 || res >= (int) sizeof(txt))
continue;
if (os_strcmp(txt, "1.3.6.1.1.1.1.22") == 0) {
wpa_printf(MSG_INFO, "TODO: extReq macAddress");
} else if (os_strcmp(txt, "1.3.6.1.4.1.40808.1.1.3") == 0) {
wpa_printf(MSG_INFO, "TODO: extReq imei");
} else if (os_strcmp(txt, "1.3.6.1.4.1.40808.1.1.4") == 0) {
wpa_printf(MSG_INFO, "TODO: extReq meid");
} else if (os_strcmp(txt, "1.3.6.1.4.1.40808.1.1.5") == 0) {
wpa_printf(MSG_INFO, "TODO: extReq DevId");
} else {
wpa_printf(MSG_INFO, "Ignore unsupported cstattr extensionsRequest %s",
txt);
}
}
}
static void add_csrattrs_attr(struct hs20_osu_client *ctx, Attribute *attr,
STACK_OF(X509_EXTENSION) *exts)
{
char txt[100], txt2[100];
int i, num, res;
if (!attr || !attr->type || !attr->values)
return;
res = OBJ_obj2txt(txt, sizeof(txt), attr->type, 1);
if (res < 0 || res >= (int) sizeof(txt))
return;
if (os_strcmp(txt, "1.2.840.113549.1.9.14") == 0) {
add_csrattrs_ext_req(ctx, attr->values, exts);
return;
}
num = sk_ASN1_OBJECT_num(attr->values);
for (i = 0; i < num; i++) {
ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(attr->values, i);
res = OBJ_obj2txt(txt2, sizeof(txt2), oid, 1);
if (res < 0 || res >= (int) sizeof(txt2))
continue;
wpa_printf(MSG_INFO, "Ignore unsupported cstattr::attr %s oid %s",
txt, txt2);
}
}
static void add_csrattrs(struct hs20_osu_client *ctx, CsrAttrs *csrattrs,
STACK_OF(X509_EXTENSION) *exts)
{
int i, num;
if (!csrattrs || ! csrattrs->attrs)
return;
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
num = sk_AttrOrOID_num(csrattrs->attrs);
#else
num = SKM_sk_num(AttrOrOID, csrattrs->attrs);
#endif
for (i = 0; i < num; i++) {
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
AttrOrOID *ao = sk_AttrOrOID_value(csrattrs->attrs, i);
#else
AttrOrOID *ao = SKM_sk_value(AttrOrOID, csrattrs->attrs, i);
#endif
switch (ao->type) {
case 0:
add_csrattrs_oid(ctx, ao->d.oid, exts);
break;
case 1:
add_csrattrs_attr(ctx, ao->d.attribute, exts);
break;
}
}
}
static int generate_csr(struct hs20_osu_client *ctx, char *key_pem,
char *csr_pem, char *est_req, char *old_cert,
CsrAttrs *csrattrs)
{
EVP_PKEY_CTX *pctx = NULL;
EVP_PKEY *pkey = NULL;
X509_REQ *req = NULL;
int ret = -1;
unsigned int val;
X509_NAME *subj = NULL;
char name[100];
STACK_OF(X509_EXTENSION) *exts = NULL;
X509_EXTENSION *ex;
BIO *out;
CONF *ctmp = NULL;
wpa_printf(MSG_INFO, "Generate RSA private key");
write_summary(ctx, "Generate RSA private key");
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
if (!pctx)
return -1;
if (EVP_PKEY_keygen_init(pctx) <= 0)
goto fail;
if (EVP_PKEY_CTX_set_rsa_keygen_bits(pctx, 2048) <= 0)
goto fail;
if (EVP_PKEY_keygen(pctx, &pkey) <= 0)
goto fail;
EVP_PKEY_CTX_free(pctx);
pctx = NULL;
if (key_pem) {
FILE *f = fopen(key_pem, "wb");
if (f == NULL)
goto fail;
if (!PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL)) {
wpa_printf(MSG_INFO, "Could not write private key: %s",
ERR_error_string(ERR_get_error(), NULL));
fclose(f);
goto fail;
}
fclose(f);
}
wpa_printf(MSG_INFO, "Generate CSR");
write_summary(ctx, "Generate CSR");
req = X509_REQ_new();
if (req == NULL)
goto fail;
if (old_cert) {
FILE *f;
X509 *cert;
int res;
f = fopen(old_cert, "r");
if (f == NULL)
goto fail;
cert = PEM_read_X509(f, NULL, NULL, NULL);
fclose(f);
if (cert == NULL)
goto fail;
res = X509_REQ_set_subject_name(req,
X509_get_subject_name(cert));
X509_free(cert);
if (!res)
goto fail;
} else {
os_get_random((u8 *) &val, sizeof(val));
os_snprintf(name, sizeof(name), "cert-user-%u", val);
subj = X509_NAME_new();
if (subj == NULL ||
!X509_NAME_add_entry_by_txt(subj, "CN", MBSTRING_ASC,
(unsigned char *) name,
-1, -1, 0) ||
!X509_REQ_set_subject_name(req, subj))
goto fail;
X509_NAME_free(subj);
subj = NULL;
}
if (!X509_REQ_set_pubkey(req, pkey))
goto fail;
exts = sk_X509_EXTENSION_new_null();
if (!exts)
goto fail;
ex = X509V3_EXT_nconf_nid(ctmp, NULL, NID_basic_constraints,
"CA:FALSE");
if (ex == NULL ||
!sk_X509_EXTENSION_push(exts, ex))
goto fail;
ex = X509V3_EXT_nconf_nid(ctmp, NULL, NID_key_usage,
"nonRepudiation,digitalSignature,keyEncipherment");
if (ex == NULL ||
!sk_X509_EXTENSION_push(exts, ex))
goto fail;
ex = X509V3_EXT_nconf_nid(ctmp, NULL, NID_ext_key_usage,
"1.3.6.1.4.1.40808.1.1.2");
if (ex == NULL ||
!sk_X509_EXTENSION_push(exts, ex))
goto fail;
add_csrattrs(ctx, csrattrs, exts);
if (!X509_REQ_add_extensions(req, exts))
goto fail;
sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
exts = NULL;
if (!X509_REQ_sign(req, pkey, EVP_sha256()))
goto fail;
out = BIO_new(BIO_s_mem());
if (out) {
char *txt;
size_t rlen;
#if !defined(ANDROID) || !defined(OPENSSL_IS_BORINGSSL)
X509_REQ_print(out, req);
#endif
rlen = BIO_ctrl_pending(out);
txt = os_malloc(rlen + 1);
if (txt) {
int res = BIO_read(out, txt, rlen);
if (res > 0) {
txt[res] = '\0';
wpa_printf(MSG_MSGDUMP, "OpenSSL: Certificate request:\n%s",
txt);
}
os_free(txt);
}
BIO_free(out);
}
if (csr_pem) {
FILE *f = fopen(csr_pem, "w");
if (f == NULL)
goto fail;
#if !defined(ANDROID) || !defined(OPENSSL_IS_BORINGSSL)
X509_REQ_print_fp(f, req);
#endif
if (!PEM_write_X509_REQ(f, req)) {
fclose(f);
goto fail;
}
fclose(f);
}
if (est_req) {
BIO *mem = BIO_new(BIO_s_mem());
BUF_MEM *ptr;
char *pos, *end, *buf_end;
FILE *f;
if (mem == NULL)
goto fail;
if (!PEM_write_bio_X509_REQ(mem, req)) {
BIO_free(mem);
goto fail;
}
BIO_get_mem_ptr(mem, &ptr);
pos = ptr->data;
buf_end = pos + ptr->length;
/* Remove START/END lines */
while (pos < buf_end && *pos != '\n')
pos++;
if (pos == buf_end) {
BIO_free(mem);
goto fail;
}
pos++;
end = pos;
while (end < buf_end && *end != '-')
end++;
f = fopen(est_req, "w");
if (f == NULL) {
BIO_free(mem);
goto fail;
}
fwrite(pos, end - pos, 1, f);
fclose(f);
BIO_free(mem);
}
ret = 0;
fail:
if (exts)
sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
if (subj)
X509_NAME_free(subj);
if (req)
X509_REQ_free(req);
if (pkey)
EVP_PKEY_free(pkey);
if (pctx)
EVP_PKEY_CTX_free(pctx);
return ret;
}
int est_build_csr(struct hs20_osu_client *ctx, const char *url)
{
char *buf;
size_t buflen;
int res;
char old_cert_buf[200];
char *old_cert = NULL;
CsrAttrs *csrattrs = NULL;
buflen = os_strlen(url) + 100;
buf = os_malloc(buflen);
if (buf == NULL)
return -1;
os_snprintf(buf, buflen, "%s/csrattrs", url);
wpa_printf(MSG_INFO, "Download csrattrs from %s", buf);
write_summary(ctx, "Download EST csrattrs from %s", buf);
ctx->no_osu_cert_validation = 1;
http_ocsp_set(ctx->http, 1);
res = http_download_file(ctx->http, buf, "Cert/est-csrattrs.txt",
ctx->ca_fname);
http_ocsp_set(ctx->http,
(ctx->workarounds & WORKAROUND_OCSP_OPTIONAL) ? 1 : 2);
ctx->no_osu_cert_validation = 0;
os_free(buf);
if (res < 0) {
wpa_printf(MSG_INFO, "Failed to download EST csrattrs - assume no extra attributes are needed");
} else {
size_t resp_len;
char *resp;
unsigned char *attrs;
const unsigned char *pos;
size_t attrs_len;
resp = os_readfile("Cert/est-csrattrs.txt", &resp_len);
if (resp == NULL) {
wpa_printf(MSG_INFO, "Could not read csrattrs");
return -1;
}
attrs = base64_decode(resp, resp_len, &attrs_len);
os_free(resp);
if (attrs == NULL) {
wpa_printf(MSG_INFO, "Could not base64 decode csrattrs");
return -1;
}
unlink("Cert/est-csrattrs.txt");
pos = attrs;
csrattrs = d2i_CsrAttrs(NULL, &pos, attrs_len);
os_free(attrs);
if (csrattrs == NULL) {
wpa_printf(MSG_INFO, "Failed to parse csrattrs ASN.1");
/* Continue assuming no additional requirements */
}
}
if (ctx->client_cert_present) {
os_snprintf(old_cert_buf, sizeof(old_cert_buf),
"SP/%s/client-cert.pem", ctx->fqdn);
old_cert = old_cert_buf;
}
res = generate_csr(ctx, "Cert/privkey-plain.pem", "Cert/est-req.pem",
"Cert/est-req.b64", old_cert, csrattrs);
if (csrattrs)
CsrAttrs_free(csrattrs);
return res;
}
int est_simple_enroll(struct hs20_osu_client *ctx, const char *url,
const char *user, const char *pw)
{
char *buf, *resp, *req, *req2;
size_t buflen, resp_len, len, pkcs7_len;
unsigned char *pkcs7;
char client_cert_buf[200];
char client_key_buf[200];
const char *client_cert = NULL, *client_key = NULL;
int res;
req = os_readfile("Cert/est-req.b64", &len);
if (req == NULL) {
wpa_printf(MSG_INFO, "Could not read Cert/req.b64");
return -1;
}
req2 = os_realloc(req, len + 1);
if (req2 == NULL) {
os_free(req);
return -1;
}
req2[len] = '\0';
req = req2;
wpa_printf(MSG_DEBUG, "EST simpleenroll request: %s", req);
buflen = os_strlen(url) + 100;
buf = os_malloc(buflen);
if (buf == NULL) {
os_free(req);
return -1;
}
if (ctx->client_cert_present) {
os_snprintf(buf, buflen, "%s/simplereenroll", url);
os_snprintf(client_cert_buf, sizeof(client_cert_buf),
"SP/%s/client-cert.pem", ctx->fqdn);
client_cert = client_cert_buf;
os_snprintf(client_key_buf, sizeof(client_key_buf),
"SP/%s/client-key.pem", ctx->fqdn);
client_key = client_key_buf;
} else
os_snprintf(buf, buflen, "%s/simpleenroll", url);
wpa_printf(MSG_INFO, "EST simpleenroll URL: %s", buf);
write_summary(ctx, "EST simpleenroll URL: %s", buf);
ctx->no_osu_cert_validation = 1;
http_ocsp_set(ctx->http, 1);
resp = http_post(ctx->http, buf, req, "application/pkcs10",
"Content-Transfer-Encoding: base64",
ctx->ca_fname, user, pw, client_cert, client_key,
&resp_len);
http_ocsp_set(ctx->http,
(ctx->workarounds & WORKAROUND_OCSP_OPTIONAL) ? 1 : 2);
ctx->no_osu_cert_validation = 0;
os_free(buf);
if (resp == NULL) {
wpa_printf(MSG_INFO, "EST certificate enrollment failed");
write_result(ctx, "EST certificate enrollment failed");
return -1;
}
wpa_printf(MSG_DEBUG, "EST simpleenroll response: %s", resp);
pkcs7 = base64_decode(resp, resp_len, &pkcs7_len);
if (pkcs7 == NULL) {
wpa_printf(MSG_INFO, "EST workaround - Could not decode base64, assume this is DER encoded PKCS7");
pkcs7 = os_malloc(resp_len);
if (pkcs7) {
os_memcpy(pkcs7, resp, resp_len);
pkcs7_len = resp_len;
}
}
os_free(resp);
if (pkcs7 == NULL) {
wpa_printf(MSG_INFO, "Failed to parse simpleenroll base64 response");
write_result(ctx, "Failed to parse EST simpleenroll base64 response");
return -1;
}
res = pkcs7_to_cert(ctx, pkcs7, pkcs7_len, "Cert/est_cert.pem",
"Cert/est_cert.der");
os_free(pkcs7);
if (res < 0) {
wpa_printf(MSG_INFO, "EST: Failed to extract certificate from PKCS7 file");
write_result(ctx, "EST: Failed to extract certificate from EST PKCS7 file");
return -1;
}
wpa_printf(MSG_INFO, "EST simple%senroll completed successfully",
ctx->client_cert_present ? "re" : "");
write_summary(ctx, "EST simple%senroll completed successfully",
ctx->client_cert_present ? "re" : "");
return 0;
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
-97
View File
@@ -9,113 +9,16 @@
#ifndef OSU_CLIENT_H
#define OSU_CLIENT_H
#define SPP_NS_URI "http://www.wi-fi.org/specifications/hotspot2dot0/v1.0/spp"
#define URN_OMA_DM_DEVINFO "urn:oma:mo:oma-dm-devinfo:1.0"
#define URN_OMA_DM_DEVDETAIL "urn:oma:mo:oma-dm-devdetail:1.0"
#define URN_HS20_DEVDETAIL_EXT "urn:wfa:mo-ext:hotspot2dot0-devdetail-ext:1.0"
#define URN_HS20_PPS "urn:wfa:mo:hotspot2dot0-perprovidersubscription:1.0"
#define MAX_OSU_VALS 10
struct osu_lang_text {
char lang[4];
char text[253];
};
struct hs20_osu_client {
struct xml_node_ctx *xml;
struct http_ctx *http;
int no_reconnect;
char pps_fname[300];
char *devid;
const char *result_file;
const char *summary_file;
const char *ifname;
const char *ca_fname;
int no_osu_cert_validation; /* for EST operations */
char *fqdn;
char *server_url;
struct osu_lang_text friendly_name[MAX_OSU_VALS];
size_t friendly_name_count;
size_t icon_count;
char icon_filename[MAX_OSU_VALS][256];
u8 icon_hash[MAX_OSU_VALS][32];
int pps_cred_set;
int pps_updated;
int client_cert_present;
char **server_dnsname;
size_t server_dnsname_count;
const char *osu_ssid; /* Enforced OSU_SSID for testing purposes */
#define WORKAROUND_OCSP_OPTIONAL 0x00000001
unsigned long int workarounds;
int ignore_tls; /* whether to ignore TLS validation issues with HTTPS
* server certificate */
};
/* osu_client.c */
void write_result(struct hs20_osu_client *ctx, const char *fmt, ...)
__attribute__ ((format (printf, 2, 3)));
void write_summary(struct hs20_osu_client *ctx, const char *fmt, ...)
__attribute__ ((format (printf, 2, 3)));
void debug_dump_node(struct hs20_osu_client *ctx, const char *title,
xml_node_t *node);
int osu_get_certificate(struct hs20_osu_client *ctx, xml_node_t *getcert);
int hs20_add_pps_mo(struct hs20_osu_client *ctx, const char *uri,
xml_node_t *add_mo, char *fname, size_t fname_len);
void get_user_pw(struct hs20_osu_client *ctx, xml_node_t *pps,
const char *alt_loc, char **user, char **pw);
int update_pps_file(struct hs20_osu_client *ctx, const char *pps_fname,
xml_node_t *pps);
void cmd_set_pps(struct hs20_osu_client *ctx, const char *pps_fname);
/* spp_client.c */
void spp_sub_rem(struct hs20_osu_client *ctx, const char *address,
const char *pps_fname,
const char *client_cert, const char *client_key,
const char *cred_username, const char *cred_password,
xml_node_t *pps);
void spp_pol_upd(struct hs20_osu_client *ctx, const char *address,
const char *pps_fname,
const char *client_cert, const char *client_key,
const char *cred_username, const char *cred_password,
xml_node_t *pps);
int cmd_prov(struct hs20_osu_client *ctx, const char *url);
int cmd_sim_prov(struct hs20_osu_client *ctx, const char *url);
/* oma_dm_client.c */
int cmd_oma_dm_prov(struct hs20_osu_client *ctx, const char *url);
int cmd_oma_dm_sim_prov(struct hs20_osu_client *ctx, const char *url);
void oma_dm_sub_rem(struct hs20_osu_client *ctx, const char *address,
const char *pps_fname,
const char *client_cert, const char *client_key,
const char *cred_username, const char *cred_password,
xml_node_t *pps);
void oma_dm_pol_upd(struct hs20_osu_client *ctx, const char *address,
const char *pps_fname,
const char *client_cert, const char *client_key,
const char *cred_username, const char *cred_password,
xml_node_t *pps);
void cmd_oma_dm_sub_rem(struct hs20_osu_client *ctx, const char *address,
const char *pps_fname);
void cmd_oma_dm_add(struct hs20_osu_client *ctx, const char *pps_fname,
const char *add_fname);
void cmd_oma_dm_replace(struct hs20_osu_client *ctx, const char *pps_fname,
const char *replace_fname);
/* est.c */
int est_load_cacerts(struct hs20_osu_client *ctx, const char *url);
int est_build_csr(struct hs20_osu_client *ctx, const char *url);
int est_simple_enroll(struct hs20_osu_client *ctx, const char *url,
const char *user, const char *pw);
#endif /* OSU_CLIENT_H */
File diff suppressed because it is too large. Load diff
+6
View File
@@ -3,6 +3,9 @@ CFLAGS += -DNEED_AP_MLME
CFLAGS += -DCONFIG_ETH_P_OUI
CFLAGS += -DCONFIG_HS20
CFLAGS += -DCONFIG_INTERWORKING
CFLAGS += -DCONFIG_IEEE80211AC
CFLAGS += -DCONFIG_IEEE80211AX
CFLAGS += -DCONFIG_IEEE80211BE
CFLAGS += -DCONFIG_IEEE80211R
CFLAGS += -DCONFIG_IEEE80211R_AP
CFLAGS += -DCONFIG_WPS
@@ -32,10 +35,13 @@ LIB_OBJS= \
hw_features.o \
ieee802_11_auth.o \
ieee802_11.o \
ieee802_11_eht.o \
ieee802_11_he.o \
ieee802_11_ht.o \
ieee802_11_shared.o \
ieee802_11_vht.o \
ieee802_1x.o \
interference.o \
neighbor_db.o \
ndisc_snoop.o \
p2p_hostapd.o \
+106 -72
View File
@@ -2,6 +2,7 @@
* ACS - Automatic Channel Selection module
* Copyright (c) 2011, Atheros Communications
* Copyright (c) 2013, Qualcomm Atheros, Inc.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -54,7 +55,7 @@
* Todo / Ideas
* ------------
* - implement other interference computation methods
* - BSS/RSSI based
* - RSSI based
* - spectral scan based
* (should be possibly to hook this up with current ACS scans)
* - add wpa_supplicant support (for P2P)
@@ -557,6 +558,9 @@ static int acs_surveys_are_sufficient(struct hostapd_iface *iface)
static int acs_usable_chan(struct hostapd_channel_data *chan)
{
if (chan->interference_bss_based)
return 1;
return !dl_list_empty(&chan->survey_list) &&
!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
acs_survey_list_is_sufficient(chan);
@@ -828,7 +832,8 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
struct hostapd_channel_data **ideal_chan,
long double *ideal_factor)
{
struct hostapd_channel_data *chan, *adj_chan = NULL, *best;
struct hostapd_channel_data *chan, *adj_chan = NULL,
*chan2 = NULL, *best;
long double factor;
int i, j;
int bw320_offset = 0, ideal_bw320_offset = 0;
@@ -847,49 +852,11 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
chan = &mode->channels[i];
/* Since in the current ACS implementation the first channel is
* always a primary channel, skip channels not available as
* primary until more sophisticated channel selection is
* implemented.
*
* If this implementation is changed to allow any channel in
* the bandwidth to be the primary one, the last parameter to
* acs_update_puncturing_bitmap() should be changed to the index
* of the primary channel
*/
if (!chan_pri_allowed(chan))
continue;
if ((chan->flag & HOSTAPD_CHAN_RADAR) &&
iface->conf->acs_exclude_dfs)
continue;
if (!is_in_chanlist(iface, chan))
continue;
if (!is_in_freqlist(iface, chan))
continue;
if (chan->max_tx_power < iface->conf->min_tx_power)
continue;
if ((chan->flag & HOSTAPD_CHAN_INDOOR_ONLY) &&
iface->conf->country[2] == 0x4f)
continue;
if (!chan_bw_allowed(chan, bw, secondary_channel != -1, 1)) {
wpa_printf(MSG_DEBUG,
"ACS: Channel %d: BW %u is not supported",
chan->chan, bw);
continue;
}
/* HT40 on 5 GHz has a limited set of primary channels as per
* 11n Annex J */
if (mode->mode == HOSTAPD_MODE_IEEE80211A &&
((iface->conf->ieee80211n &&
iface->conf->secondary_channel) ||
is_6ghz_freq(chan->freq)) &&
if (bw == 40 &&
mode->mode == HOSTAPD_MODE_IEEE80211A &&
iface->conf->ieee80211n &&
!acs_usable_bw_chan(chan, ACS_BW40)) {
wpa_printf(MSG_DEBUG,
"ACS: Channel %d: not allowed as primary channel for 40 MHz bandwidth",
@@ -900,18 +867,14 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
if (mode->mode == HOSTAPD_MODE_IEEE80211A &&
(iface->conf->ieee80211ac || iface->conf->ieee80211ax ||
iface->conf->ieee80211be)) {
if (hostapd_get_oper_chwidth(iface->conf) ==
CONF_OPER_CHWIDTH_80MHZ &&
!acs_usable_bw_chan(chan, ACS_BW80)) {
if (bw == 80 && !acs_usable_bw_chan(chan, ACS_BW80)) {
wpa_printf(MSG_DEBUG,
"ACS: Channel %d: not allowed as primary channel for 80 MHz bandwidth",
chan->chan);
continue;
}
if (hostapd_get_oper_chwidth(iface->conf) ==
CONF_OPER_CHWIDTH_160MHZ &&
!acs_usable_bw_chan(chan, ACS_BW160)) {
if (bw == 160 && !acs_usable_bw_chan(chan, ACS_BW160)) {
wpa_printf(MSG_DEBUG,
"ACS: Channel %d: not allowed as primary channel for 160 MHz bandwidth",
chan->chan);
@@ -921,43 +884,67 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
if (mode->mode == HOSTAPD_MODE_IEEE80211A &&
iface->conf->ieee80211be) {
if (hostapd_get_oper_chwidth(iface->conf) ==
CONF_OPER_CHWIDTH_320MHZ &&
!acs_usable_bw320_chan(iface, chan, &bw320_offset))
if (bw == 320 &&
!acs_usable_bw320_chan(iface, chan,
&bw320_offset)) {
wpa_printf(MSG_DEBUG,
"ACS: Channel %d: not allowed as primary channel for 320 MHz bandwidth",
chan->chan);
continue;
}
}
factor = 0;
best = NULL;
if (acs_usable_chan(chan)) {
factor = chan->interference_factor;
total_weight = 1;
best = chan;
}
for (j = 1; j < n_chans; j++) {
adj_chan = acs_find_chan(iface, chan->freq +
j * secondary_channel * 20);
if (!adj_chan)
for (j = 0; j < n_chans; j++) {
chan2 = acs_find_chan(iface, chan->freq +
j * secondary_channel * 20);
if (!chan2)
break;
if (!chan_bw_allowed(adj_chan, bw, 1, 0)) {
if (!chan_bw_allowed(chan2, bw, secondary_channel != -1,
j == 0)) {
wpa_printf(MSG_DEBUG,
"ACS: PRI Channel %d: secondary channel %d BW %u is not supported",
chan->chan, adj_chan->chan, bw);
"ACS: Channel %d: BW %u is not supported",
chan2->chan, bw);
break;
}
if (!acs_usable_chan(adj_chan))
if ((chan2->flag & HOSTAPD_CHAN_RADAR) &&
iface->conf->acs_exclude_dfs)
break;
if (chan2->max_tx_power < iface->conf->min_tx_power)
break;
if ((chan2->flag & HOSTAPD_CHAN_INDOOR_ONLY) &&
iface->conf->country[2] == 0x4f)
break;
if (!acs_usable_chan(chan2))
continue;
factor += adj_chan->interference_factor;
factor += chan2->interference_factor;
total_weight += 1;
if (!chan_pri_allowed(chan2))
continue;
if (!is_in_chanlist(iface, chan2))
continue;
if (!is_in_freqlist(iface, chan2))
continue;
if (iface->conf->acs_exclude_6ghz_non_psc &&
!is_6ghz_psc_frequency(chan2->freq))
continue;
/* find the best channel in this segment */
if (!best || adj_chan->interference_factor <
if (!best || chan2->interference_factor <
best->interference_factor)
best = adj_chan;
best = chan2;
}
if (j != n_chans) {
@@ -966,18 +953,25 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
continue;
}
if (!best) {
wpa_printf(MSG_DEBUG,
"ACS: No valid channel found in the segment starting with channel %d",
chan->chan);
continue;
}
/* If the AP is in the 5 GHz or 6 GHz band, lets prefer a less
* crowded primary channel if one was found in the segment */
if (iface->current_mode &&
iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
best && chan != best) {
chan != best) {
wpa_printf(MSG_DEBUG,
"ACS: promoting channel %d over %d (less interference %Lg/%Lg)",
best->chan, chan->chan,
chan->interference_factor,
best->interference_factor);
#ifdef CONFIG_IEEE80211BE
index_primary = (chan->freq - best->freq) / 20;
index_primary = (best->freq - chan->freq) / 20;
#endif /* CONFIG_IEEE80211BE */
chan = best;
}
@@ -1254,13 +1248,53 @@ static int acs_study_survey_based(struct hostapd_iface *iface)
}
static int acs_study_bss_based(struct hostapd_iface *iface)
{
struct wpa_scan_results *scan_res;
int j;
wpa_printf(MSG_DEBUG, "ACS: Trying BSS-based ACS");
scan_res = hostapd_driver_get_scan_results(iface->bss[0]);
if (!scan_res) {
wpa_printf(MSG_INFO, "ACS: Scan request failed");
hostapd_setup_interface_complete(iface, 1);
return -1;
}
for (j = 0; j < iface->current_mode->num_channels; j++) {
struct hostapd_channel_data *chan;
unsigned int bss_on_ch = 0;
size_t i;
chan = &iface->current_mode->channels[j];
for (i = 0; i < scan_res->num; i++) {
struct wpa_scan_res *bss = scan_res->res[i];
if (bss->freq == chan->freq)
bss_on_ch++;
}
wpa_printf(MSG_MSGDUMP,
"ACS: Interference on ch %d (%d MHz): %d",
chan->chan, chan->freq, bss_on_ch);
chan->interference_factor = bss_on_ch;
chan->interference_bss_based = true;
}
wpa_scan_results_free(scan_res);
return 0;
}
static int acs_study_options(struct hostapd_iface *iface)
{
if (acs_study_survey_based(iface) == 0)
return 0;
/* TODO: If no surveys are available/sufficient this is a good
* place to fallback to BSS-based ACS */
wpa_printf(MSG_INFO, "ACS: Survey based ACS failed");
if (acs_study_bss_based(iface) == 0)
return 0;
return -1;
}
File diff suppressed because it is too large. Load diff
+6 -1
View File
@@ -119,7 +119,12 @@ static void set_sta_weights(struct hostapd_data *hapd, unsigned int weight)
static unsigned int get_airtime_quantum(unsigned int max_wt)
{
unsigned int quantum = AIRTIME_QUANTUM_TARGET / max_wt;
unsigned int quantum;
if (max_wt == 0)
return AIRTIME_QUANTUM_MAX;
quantum = AIRTIME_QUANTUM_TARGET / max_wt;
if (quantum < AIRTIME_QUANTUM_MIN)
quantum = AIRTIME_QUANTUM_MIN;
+120 -56
View File
@@ -170,6 +170,7 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
#ifdef CONFIG_TESTING_OPTIONS
bss->sae_commit_status = -1;
bss->test_assoc_comeback_type = -1;
bss->association_response_status_code = -1;
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_PASN
@@ -177,6 +178,13 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
bss->pasn_comeback_after = 10;
bss->pasn_noauth = 1;
#endif /* CONFIG_PASN */
bss->urnm_mfpr_x20 = -1;
bss->urnm_mfpr = -1;
#ifdef CONFIG_ENC_ASSOC
bss->assoc_frame_encryption = 0;
bss->pmksa_caching_privacy = 0;
bss->eap_using_authentication_frames = 0;
#endif /* CONFIG_ENC_ASSOC */
}
@@ -306,6 +314,8 @@ struct hostapd_config * hostapd_config_defaults(void)
hostapd_set_and_check_bw320_offset(conf, 0);
conf->disable_mcs15_rx = true;
return conf;
}
@@ -491,34 +501,48 @@ int hostapd_setup_sae_pt(struct hostapd_bss_config *conf)
#ifdef CONFIG_SAE
struct hostapd_ssid *ssid = &conf->ssid;
struct sae_password_entry *pw;
int *groups = conf->sae_groups;
int default_groups[] = { 19, 0, 0 };
if ((conf->sae_pwe == SAE_PWE_HUNT_AND_PECK &&
!hostapd_sae_pw_id_in_use(conf) &&
!wpa_key_mgmt_sae_ext_key(conf->wpa_key_mgmt) &&
!wpa_key_mgmt_sae_ext_key(conf->wpa_key_mgmt |
conf->rsn_override_key_mgmt |
conf->rsn_override_key_mgmt_2) &&
!hostapd_sae_pk_in_use(conf)) ||
conf->sae_pwe == SAE_PWE_FORCE_HUNT_AND_PECK ||
!wpa_key_mgmt_sae(conf->wpa_key_mgmt))
!wpa_key_mgmt_sae(conf->wpa_key_mgmt |
conf->rsn_override_key_mgmt |
conf->rsn_override_key_mgmt_2))
return 0; /* PT not needed */
if (!groups) {
groups = default_groups;
if (wpa_key_mgmt_sae_ext_key(conf->wpa_key_mgmt |
conf->rsn_override_key_mgmt |
conf->rsn_override_key_mgmt_2))
default_groups[1] = 20;
}
sae_deinit_pt(ssid->pt);
ssid->pt = NULL;
if (ssid->wpa_passphrase) {
ssid->pt = sae_derive_pt(conf->sae_groups, ssid->ssid,
ssid->ssid_len,
ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
(const u8 *) ssid->wpa_passphrase,
os_strlen(ssid->wpa_passphrase),
NULL);
NULL, 0);
if (!ssid->pt)
return -1;
}
for (pw = conf->sae_passwords; pw; pw = pw->next) {
sae_deinit_pt(pw->pt);
pw->pt = sae_derive_pt(conf->sae_groups, ssid->ssid,
ssid->ssid_len,
pw->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
(const u8 *) pw->password,
os_strlen(pw->password),
pw->identifier);
(const u8 *) pw->identifier,
pw->identifier ?
os_strlen(pw->identifier) : 0);
if (!pw->pt)
return -1;
}
@@ -779,6 +803,8 @@ static void hostapd_config_free_sae_passwords(struct hostapd_bss_config *conf)
#ifdef CONFIG_SAE_PK
sae_deinit_pk(tmp->pk);
#endif /* CONFIG_SAE_PK */
os_free(tmp->success_mac);
os_free(tmp->fail_mac);
os_free(tmp);
}
}
@@ -865,6 +891,8 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
os_free(conf->radius_das_shared_secret);
hostapd_config_free_vlan(conf);
os_free(conf->time_zone);
os_free(conf->supported_rates);
os_free(conf->basic_rates);
#ifdef CONFIG_IEEE80211R_AP
hostapd_config_clear_rxkhs(conf);
@@ -917,31 +945,6 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
os_free(conf->hs20_wan_metrics);
os_free(conf->hs20_connection_capability);
os_free(conf->hs20_operating_class);
os_free(conf->hs20_icons);
if (conf->hs20_osu_providers) {
for (i = 0; i < conf->hs20_osu_providers_count; i++) {
struct hs20_osu_provider *p;
size_t j;
p = &conf->hs20_osu_providers[i];
os_free(p->friendly_name);
os_free(p->server_uri);
os_free(p->method_list);
for (j = 0; j < p->icons_count; j++)
os_free(p->icons[j]);
os_free(p->icons);
os_free(p->osu_nai);
os_free(p->osu_nai2);
os_free(p->service_desc);
}
os_free(conf->hs20_osu_providers);
}
if (conf->hs20_operator_icon) {
for (i = 0; i < conf->hs20_operator_icon_count; i++)
os_free(conf->hs20_operator_icon[i]);
os_free(conf->hs20_operator_icon);
}
os_free(conf->subscr_remediation_url);
os_free(conf->hs20_sim_provisioning_url);
os_free(conf->t_c_filename);
os_free(conf->t_c_server_url);
#endif /* CONFIG_HS20 */
@@ -960,6 +963,11 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
#ifdef CONFIG_TESTING_OPTIONS
wpabuf_free(conf->own_ie_override);
wpabuf_free(conf->rsne_override);
wpabuf_free(conf->rsnoe_override);
wpabuf_free(conf->rsno2e_override);
wpabuf_free(conf->rsnxe_override);
wpabuf_free(conf->rsnxoe_override);
wpabuf_free(conf->sae_commit_override);
wpabuf_free(conf->rsne_override_eapol);
wpabuf_free(conf->rsnxe_override_eapol);
@@ -1008,12 +1016,33 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
#ifdef CONFIG_PASN
os_free(conf->pasn_groups);
#ifdef CONFIG_TESTING_OPTIONS
os_free(conf->pasn_test_groups);
#endif /* CONFIG_TESTING_OPTIONS */
#endif /* CONFIG_PASN */
wpabuf_clear_free(conf->sae_pw_id_key);
os_free(conf);
}
#ifdef CONFIG_AFC
void hostapd_config_free_afc_cert_ids(struct hostapd_config *conf)
{
unsigned int i;
for (i = 0; i < conf->afc.n_cert_ids; i++) {
os_free(conf->afc.cert_ids[i].ruleset);
os_free(conf->afc.cert_ids[i].id);
}
os_free(conf->afc.cert_ids);
conf->afc.cert_ids = NULL;
conf->afc.n_cert_ids = 0;
}
#endif /* CONFIG_AFC */
/**
* hostapd_config_free - Free hostapd configuration
* @conf: Configuration data from hostapd_config_read().
@@ -1028,8 +1057,6 @@ void hostapd_config_free(struct hostapd_config *conf)
for (i = 0; i < conf->num_bss; i++)
hostapd_config_free_bss(conf->bss[i]);
os_free(conf->bss);
os_free(conf->supported_rates);
os_free(conf->basic_rates);
os_free(conf->acs_ch_list.range);
os_free(conf->acs_freq_list.range);
os_free(conf->driver_params);
@@ -1038,6 +1065,18 @@ void hostapd_config_free(struct hostapd_config *conf)
#endif /* CONFIG_ACS */
wpabuf_free(conf->lci);
wpabuf_free(conf->civic);
#ifdef CONFIG_AFC
os_free(conf->afc.socket);
os_free(conf->afc.request.version);
os_free(conf->afc.request.sn);
hostapd_config_free_afc_cert_ids(conf);
os_free(conf->afc.cert_ids);
os_free(conf->afc.location.height_type);
os_free(conf->afc.location.linear_polygon_data);
os_free(conf->afc.location.radial_polygon_data);
os_free(conf->afc.freqs.range);
os_free(conf->afc.op_class);
#endif /* CONFIG_AFC */
os_free(conf);
}
@@ -1079,21 +1118,6 @@ int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
}
int hostapd_rate_found(int *list, int rate)
{
int i;
if (list == NULL)
return 0;
for (i = 0; list[i] >= 0; i++)
if (list[i] == rate)
return 1;
return 0;
}
int hostapd_vlan_valid(struct hostapd_vlan *vlan,
struct vlan_description *vlan_desc)
{
@@ -1204,7 +1228,7 @@ static bool hostapd_sae_pk_password_without_pk(struct hostapd_bss_config *bss)
#endif /* CONFIG_SAE_PK */
static bool hostapd_config_check_bss_6g(struct hostapd_bss_config *bss)
bool hostapd_config_check_bss_6g(struct hostapd_bss_config *bss)
{
if (bss->wpa != WPA_PROTO_RSN) {
wpa_printf(MSG_ERROR,
@@ -1324,6 +1348,22 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
}
}
if (full_config) {
size_t i;
for (i = 0; i < conf->num_bss; i++) {
if (conf->bss[i] != bss &&
os_strcmp(conf->bss[i]->iface, bss->iface) == 0) {
wpa_printf(MSG_ERROR,
"Duplicate interface '%s' for BSSID "
MACSTR " and " MACSTR, bss->iface,
MAC2STR(conf->bss[i]->bssid),
MAC2STR(bss->bssid));
return -1;
}
}
}
#ifdef CONFIG_IEEE80211R_AP
if (full_config && wpa_key_mgmt_ft(bss->wpa_key_mgmt) &&
(bss->nas_identifier == NULL ||
@@ -1491,9 +1531,31 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
#ifdef CONFIG_IEEE80211BE
if (full_config && !bss->disable_11be && bss->disable_11ax) {
bss->disable_11be = true;
bss->mld_ap = 0;
wpa_printf(MSG_INFO,
"Disabling IEEE 802.11be as IEEE 802.11ax is disabled for this BSS");
}
if (full_config && conf->ieee80211be && !bss->disable_11be &&
!bss->beacon_prot && ap_pmf_enabled(bss)) {
bss->beacon_prot = 1;
wpa_printf(MSG_INFO,
"Enabling beacon protection as IEEE 802.11be is enabled for this BSS");
}
if (full_config && (!conf->ieee80211be || bss->disable_11be) &&
bss->mld_ap) {
wpa_printf(MSG_INFO,
"Cannot enable mld_ap when IEEE 802.11be is disabled");
return -1;
}
if (full_config && (!conf->ieee80211be || bss->disable_11be) &&
bss->bss_require_eht) {
bss->bss_require_eht = false;
wpa_printf(MSG_INFO,
"Disabling bss_require_eht as IEEE 802.11be is disabled for this BSS");
}
#endif /* CONFIG_IEEE80211BE */
if (full_config && bss->ignore_broadcast_ssid && conf->mbssid) {
@@ -1502,6 +1564,13 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
return -1;
}
/* Do not advertise SPP A-MSDU support if not using CCMP/GCMP */
if (full_config && bss->spp_amsdu &&
!(bss->wpa &&
bss->rsn_pairwise & (WPA_CIPHER_CCMP_256 | WPA_CIPHER_CCMP |
WPA_CIPHER_GCMP_256 | WPA_CIPHER_GCMP)))
bss->spp_amsdu = false;
return 0;
}
@@ -1668,11 +1737,6 @@ void hostapd_set_security_params(struct hostapd_bss_config *bss,
if (full_config)
bss->wpa_key_mgmt = WPA_KEY_MGMT_NONE;
#endif /* CONFIG_WEP */
} else if (bss->osen) {
bss->ssid.security_policy = SECURITY_OSEN;
bss->wpa_group = WPA_CIPHER_CCMP;
bss->wpa_pairwise = 0;
bss->rsn_pairwise = WPA_CIPHER_CCMP;
} else {
bss->ssid.security_policy = SECURITY_PLAINTEXT;
if (full_config) {
+127 -41
View File
@@ -93,7 +93,6 @@ typedef enum hostap_security_policy {
SECURITY_IEEE_802_1X = 2,
SECURITY_WPA_PSK = 3,
SECURITY_WPA = 4,
SECURITY_OSEN = 5
} secpolicy;
struct hostapd_ssid {
@@ -189,7 +188,6 @@ struct hostapd_eap_user {
unsigned int wildcard_prefix:1;
unsigned int password_hash:1; /* whether password is hashed with
* nt_password_hash() */
unsigned int remediation:1;
unsigned int macacl:1;
int ttls_auth; /* EAP_TTLS_AUTH_* bitfield */
struct hostapd_radius_attr *accept_attr;
@@ -260,6 +258,10 @@ struct sae_password_entry {
int vlan_id;
struct sae_pt *pt;
struct sae_pk *pk;
u8 *success_mac;
unsigned int num_success_mac, next_success_mac;
u8 *fail_mac;
unsigned int num_fail_mac, next_fail_mac;
};
struct dpp_controller_conf {
@@ -293,6 +295,9 @@ struct hostapd_bss_config {
int max_num_sta; /* maximum number of STAs in station table */
enum beacon_rate_type rate_type;
unsigned int beacon_rate;
int dtim_period;
unsigned int bss_load_update_period;
unsigned int chan_util_avg_period;
@@ -325,6 +330,9 @@ struct hostapd_bss_config {
struct hostapd_ssid ssid;
int *supported_rates;
int *basic_rates;
char *eap_req_id_text; /* optional displayable message sent with
* EAP Request-Identity */
size_t eap_req_id_text_len;
@@ -358,7 +366,11 @@ struct hostapd_bss_config {
int wpa; /* bitfield of WPA_PROTO_WPA, WPA_PROTO_RSN */
int extended_key_id;
int wpa_key_mgmt;
int rsn_override_key_mgmt;
int rsn_override_key_mgmt_2;
enum mfp_options ieee80211w;
enum mfp_options rsn_override_mfp;
enum mfp_options rsn_override_mfp_2;
int group_mgmt_cipher;
int beacon_prot;
/* dot11AssociationSAQueryMaximumTimeout (in TUs) */
@@ -387,9 +399,14 @@ struct hostapd_bss_config {
u32 wpa_pairwise_update_count;
int wpa_disable_eapol_key_retries;
int rsn_pairwise;
int rsn_override_pairwise;
int rsn_override_pairwise_2;
int rsn_preauth;
char *rsn_preauth_interfaces;
int rsn_override_omit_rsnxe;
int rsn_override_mlo_compat;
#ifdef CONFIG_IEEE80211R_AP
/* IEEE 802.11r - Fast BSS Transition */
u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN];
@@ -443,7 +460,6 @@ struct hostapd_bss_config {
int pac_key_lifetime;
int pac_key_refresh_time;
int eap_teap_auth;
int eap_teap_pac_no_inner;
int eap_teap_separate_result;
int eap_teap_id;
int eap_teap_method_sequence;
@@ -458,6 +474,7 @@ struct hostapd_bss_config {
char *radius_server_clients;
int radius_server_auth_port;
int radius_server_acct_port;
int radius_server_acct_log;
int radius_server_ipv6;
int use_pae_group_addr; /* Whether to send EAPOL frames to PAE group
@@ -554,6 +571,10 @@ struct hostapd_bss_config {
bool disable_11ax;
bool disable_11be;
#ifdef CONFIG_IEEE80211BE
bool bss_require_eht;
#endif /* CONFIG_IEEE80211BE */
/* IEEE 802.11v */
int time_advertisement;
char *time_zone;
@@ -613,7 +634,6 @@ struct hostapd_bss_config {
u8 qos_map_set[16 + 2 * 21];
unsigned int qos_map_set_len;
int osen;
int proxy_arp;
int na_mcast_to_ucast;
@@ -629,37 +649,7 @@ struct hostapd_bss_config {
size_t hs20_connection_capability_len;
u8 *hs20_operating_class;
u8 hs20_operating_class_len;
struct hs20_icon {
u16 width;
u16 height;
char language[3];
char type[256];
char name[256];
char file[256];
} *hs20_icons;
size_t hs20_icons_count;
u8 osu_ssid[SSID_MAX_LEN];
size_t osu_ssid_len;
struct hs20_osu_provider {
unsigned int friendly_name_count;
struct hostapd_lang_string *friendly_name;
char *server_uri;
int *method_list;
char **icons;
size_t icons_count;
char *osu_nai;
char *osu_nai2;
unsigned int service_desc_count;
struct hostapd_lang_string *service_desc;
} *hs20_osu_providers, *last_osu;
size_t hs20_osu_providers_count;
size_t hs20_osu_providers_nai_count;
char **hs20_operator_icon;
size_t hs20_operator_icon_count;
unsigned int hs20_deauth_req_timeout;
char *subscr_remediation_url;
u8 subscr_remediation_method;
char *hs20_sim_provisioning_url;
char *t_c_filename;
u32 t_c_timestamp;
char *t_c_server_url;
@@ -679,8 +669,18 @@ struct hostapd_bss_config {
int sae_require_mfp;
int sae_confirm_immediate;
enum sae_pwe sae_pwe;
/* Accept an SAE association even when the STA advertises SAE H2E
* support in the RSNXE but authenticated using hunting-and-pecking.
* This is a workaround for WPA3-Personal Compatibility Mode and
* RSNXE-override interoperability (e.g., some MLO STAs that add only
* the RSNXE Override element and do not use H2E on 2.4/5 GHz) */
bool sae_accept_h2e_without_use;
int *sae_groups;
struct sae_password_entry *sae_passwords;
int sae_password_psk;
int sae_track_password;
struct wpabuf *sae_pw_id_key;
unsigned int sae_pw_id_num;
char *wowlan_triggers; /* Wake-on-WLAN triggers */
@@ -688,6 +688,11 @@ struct hostapd_bss_config {
u8 bss_load_test[5];
u8 bss_load_test_set;
struct wpabuf *own_ie_override;
struct wpabuf *rsne_override;
struct wpabuf *rsnoe_override;
struct wpabuf *rsno2e_override;
struct wpabuf *rsnxe_override;
struct wpabuf *rsnxoe_override;
int sae_reflection_attack;
int sae_commit_status;
int sae_pk_omit;
@@ -712,8 +717,10 @@ struct hostapd_bss_config {
struct wpabuf *eapol_m1_elements;
struct wpabuf *eapol_m3_elements;
bool eapol_m3_no_encrypt;
bool eapol_key_reserved_random;
int test_assoc_comeback_type;
struct wpabuf *presp_elements;
int association_response_status_code;
#ifdef CONFIG_IEEE80211BE
u16 eht_oper_puncturing_override;
@@ -905,6 +912,14 @@ struct hostapd_bss_config {
*/
int macsec_csindex;
/**
* macsec_icv_indicator - Always include ICV Indicator
* (for compatibility with older MACsec switches)
*
* Range: 0-1 (default: 0)
*/
int macsec_icv_indicator;
/**
* mka_ckn - MKA pre-shared CKN
*/
@@ -932,6 +947,11 @@ struct hostapd_bss_config {
/* Whether to allow PASN-UNAUTH */
int pasn_noauth;
#ifdef CONFIG_ENC_ASSOC
/* Whether to allow unauthenticated EPPKE (EPPKE without base AKM) */
bool eppke_unauth;
#endif /* CONFIG_ENC_ASSOC */
#ifdef CONFIG_TESTING_OPTIONS
/*
* Normally, KDK should be derived if and only if both sides support
@@ -941,6 +961,12 @@ struct hostapd_bss_config {
/* If set, corrupt the MIC in the 2nd Authentication frame of PASN */
int pasn_corrupt_mic;
/*
* If set, override Supported Groups element in the 2nd Authentication
* frame of PASN for group negotiation testing.
*/
int *pasn_test_groups;
#endif /* CONFIG_TESTING_OPTIONS */
int *pasn_groups;
@@ -952,6 +978,9 @@ struct hostapd_bss_config {
u16 pasn_comeback_after;
#endif /* CONFIG_PASN */
int urnm_mfpr_x20;
int urnm_mfpr;
unsigned int unsol_bcast_probe_resp_interval;
u8 ext_capa_mask[EXT_CAPA_MAX_LEN];
@@ -959,9 +988,9 @@ struct hostapd_bss_config {
u8 rnr;
char *config_id;
bool xrates_supported;
bool ssid_protection;
bool known_sta_identification;
#ifdef CONFIG_IEEE80211BE
/* The AP is part of an AP MLD */
@@ -981,6 +1010,14 @@ struct hostapd_bss_config {
bool mld_indicate_disabled;
#endif /* CONFIG_TESTING_OPTIONS */
#endif /* CONFIG_IEEE80211BE */
int mbssid_index;
bool spp_amsdu;
#ifdef CONFIG_ENC_ASSOC
unsigned int assoc_frame_encryption:1;
unsigned int pmksa_caching_privacy:1;
unsigned int eap_using_authentication_frames:1;
#endif /* CONFIG_ENC_ASSOC */
};
/**
@@ -1057,11 +1094,6 @@ struct hostapd_config {
SHORT_PREAMBLE = 1
} preamble;
int *supported_rates;
int *basic_rates;
unsigned int beacon_rate;
enum beacon_rate_type rate_type;
const struct wpa_driver_ops *driver;
char *driver_params;
@@ -1139,6 +1171,7 @@ struct hostapd_config {
double ignore_reassoc_probability;
double corrupt_gtk_rekey_mic_probability;
int ecsa_ie_only;
int csa_ie_only;
bool delay_eapol_tx;
#endif /* CONFIG_TESTING_OPTIONS */
@@ -1220,6 +1253,7 @@ struct hostapd_config {
u8 punct_acs_threshold;
u8 eht_default_pe_duration;
u8 eht_bw320_offset;
bool require_eht;
#endif /* CONFIG_IEEE80211BE */
/* EHT enable/disable config from CHAN_SWITCH */
@@ -1232,9 +1266,60 @@ struct hostapd_config {
MBSSID_ENABLED = 1,
ENHANCED_MBSSID_ENABLED = 2,
} mbssid;
unsigned int mbssid_max;
/* Whether to enable TWT responder in HT and VHT modes */
bool ht_vht_twt_responder;
bool channel_usage;
bool peer_to_peer_twt;
/* Set I2R LMR policy to allow LMR response from ISTA */
bool i2r_lmr_policy;
/* Disable MCS15 Subfield in EHT operation element */
bool disable_mcs15_rx;
#ifdef CONFIG_AFC
struct {
char *socket;
struct {
char *version;
char *sn;
} request;
unsigned int n_cert_ids;
struct afc_cert_id {
char *ruleset;
char *id;
} *cert_ids;
struct {
enum afc_location_type {
AFC_ELLIPSE,
AFC_LINEAR_POLYGON,
AFC_RADIAL_POLYGON,
} type;
unsigned int n_linear_polygon_data;
struct afc_linear_polygon {
double longitude;
double latitude;
} *linear_polygon_data;
unsigned int n_radial_polygon_data;
struct afc_radial_polygon {
double length;
double angle;
} *radial_polygon_data;
int major_axis;
int minor_axis;
int orientation;
double height;
char *height_type;
int vertical_tolerance;
} location;
struct wpa_freq_range_list freqs;
int *op_class; /* int array */
int min_power;
} afc;
#endif /* CONFIG_AFC */
};
@@ -1373,7 +1458,6 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf);
void hostapd_config_free(struct hostapd_config *conf);
int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
const u8 *addr, struct vlan_description *vlan_id);
int hostapd_rate_found(int *list, int rate);
const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
const u8 *addr, const u8 *p2p_dev_addr,
const u8 *prev_psk, int *vlan_id);
@@ -1397,5 +1481,7 @@ int hostapd_add_acl_maclist(struct mac_acl_entry **acl, int *num,
int vlan_id, const u8 *addr);
void hostapd_remove_acl_mac(struct mac_acl_entry **acl, int *num,
const u8 *addr);
bool hostapd_config_check_bss_6g(struct hostapd_bss_config *bss);
void hostapd_config_free_afc_cert_ids(struct hostapd_config *conf);
#endif /* HOSTAPD_CONFIG_H */
+197 -41
View File
@@ -21,6 +21,7 @@
#include "p2p_hostapd.h"
#include "hs20.h"
#include "wpa_auth.h"
#include "hw_features.h"
#include "ap_drv_ops.h"
@@ -39,6 +40,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;
}
@@ -116,9 +119,11 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
goto fail;
#endif /* CONFIG_FILS */
pos = hostapd_eid_rsnxe(hapd, buf, sizeof(buf));
if (add_buf_data(&assocresp, buf, pos - buf) < 0)
goto fail;
if (!hapd->conf->rsn_override_omit_rsnxe) {
pos = hostapd_eid_rsnxe(hapd, buf, sizeof(buf));
if (add_buf_data(&assocresp, buf, pos - buf) < 0)
goto fail;
}
if (add_buf(&beacon, hapd->wps_beacon_ie) < 0 ||
add_buf(&proberesp, hapd->wps_probe_resp_ie) < 0)
@@ -181,11 +186,6 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
if (add_buf_data(&beacon, buf, pos - buf) < 0 ||
add_buf_data(&proberesp, buf, pos - buf) < 0)
goto fail;
pos = hostapd_eid_osen(hapd, buf);
if (add_buf_data(&beacon, buf, pos - buf) < 0 ||
add_buf_data(&proberesp, buf, pos - buf) < 0)
goto fail;
#endif /* CONFIG_HS20 */
#ifdef CONFIG_MBO
@@ -370,7 +370,14 @@ int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname)
{
char force_ifname[IFNAMSIZ];
u8 if_addr[ETH_ALEN];
return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, hapd->own_addr,
const u8 *addr = hapd->own_addr;
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap)
addr = hapd->mld->mld_addr;
#endif /* CONFIG_IEEE80211BE */
return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, addr,
NULL, NULL, force_ifname, if_addr, NULL, 0);
}
@@ -472,7 +479,8 @@ int hostapd_sta_add(struct hostapd_data *hapd,
size_t eht_capab_len,
const struct ieee80211_he_6ghz_band_cap *he_6ghz_capab,
u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps,
int set, const u8 *link_addr, bool mld_link_sta)
int set, const u8 *link_addr, bool mld_link_sta,
u16 eml_cap, bool epp_sta)
{
struct hostapd_sta_add_params params;
@@ -502,6 +510,9 @@ int hostapd_sta_add(struct hostapd_data *hapd,
params.support_p2p_ps = supp_p2p_ps;
params.set = set;
params.mld_link_id = -1;
#ifdef CONFIG_ENC_ASSOC
params.epp_sta = epp_sta;
#endif /* CONFIG_ENC_ASSOC */
#ifdef CONFIG_IEEE80211BE
/*
@@ -512,6 +523,9 @@ int hostapd_sta_add(struct hostapd_data *hapd,
params.mld_link_id = hapd->mld_link_id;
params.mld_link_addr = link_addr;
params.mld_link_sta = mld_link_sta;
/* Copy EML capabilities of ML STA */
if (link_addr)
params.eml_cap = eml_cap;
}
#endif /* CONFIG_IEEE80211BE */
@@ -519,16 +533,6 @@ int hostapd_sta_add(struct hostapd_data *hapd,
}
int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr,
u8 *tspec_ie, size_t tspec_ielen)
{
if (hapd->driver == NULL || hapd->driver->add_tspec == NULL)
return 0;
return hapd->driver->add_tspec(hapd->drv_priv, addr, tspec_ie,
tspec_ielen);
}
int hostapd_set_privacy(struct hostapd_data *hapd, int enabled)
{
if (hapd->driver == NULL || hapd->driver->set_privacy == NULL)
@@ -754,15 +758,7 @@ hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
!hapd->drv_priv)
return NULL;
return hapd->driver->get_hw_feature_data(hapd->drv_priv, num_modes,
flags, dfs_domain);
}
int hostapd_driver_commit(struct hostapd_data *hapd)
{
if (hapd->driver == NULL || hapd->driver->commit == NULL)
return 0;
return hapd->driver->commit(hapd->drv_priv);
flags, dfs_domain, NULL, 0);
}
@@ -781,6 +777,37 @@ bool hostapd_drv_nl80211(struct hostapd_data *hapd)
int hostapd_driver_scan(struct hostapd_data *hapd,
struct wpa_driver_scan_params *params)
{
params->link_id = -1;
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap)
params->link_id = hapd->mld_link_id;
if (!hapd->iface->scan_cb && hapd->conf->mld_ap &&
hapd->iface->interfaces) {
/* Other links may be waiting for scan results */
unsigned int i;
for (i = 0; i < hapd->iface->interfaces->count; i++) {
struct hostapd_iface *h_iface =
hapd->iface->interfaces->iface[i];
struct hostapd_data *h_hapd;
if (!h_iface || h_iface == hapd->iface ||
h_iface->num_bss == 0)
continue;
h_hapd = h_iface->bss[0];
if (hostapd_is_ml_partner(hapd, h_hapd) &&
h_hapd->iface->state == HAPD_IFACE_ACS) {
wpa_printf(MSG_INFO,
"ACS in progress in a partner link - try to scan later");
return -EBUSY;
}
}
}
#endif /* CONFIG_IEEE80211BE */
if (hapd->driver && hapd->driver->scan2)
return hapd->driver->scan2(hapd->drv_priv, params);
return -1;
@@ -889,20 +916,23 @@ int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
const u8 *addr, int reason)
{
const u8 *own_addr = hapd->own_addr;
int link_id = -1;
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap) {
struct sta_info *sta = ap_get_sta(hapd, addr);
if (ap_sta_is_mld(hapd, sta))
if (ap_sta_is_mld(hapd, sta)) {
own_addr = hapd->mld->mld_addr;
link_id = hapd->mld_link_id;
}
}
#endif /* CONFIG_IEEE80211BE */
if (!hapd->driver || !hapd->driver->sta_disassoc || !hapd->drv_priv)
return 0;
return hapd->driver->sta_disassoc(hapd->drv_priv, own_addr, addr,
reason);
reason, link_id);
}
@@ -916,9 +946,50 @@ int hostapd_drv_wnm_oper(struct hostapd_data *hapd, enum wnm_oper oper,
}
#ifdef CONFIG_IEEE80211BE
static bool hostapd_is_action_frame_link_agnostic(u8 category, u8 sub_category)
{
/* As per IEEE Std 802.11be-2024, 35.3.14 (MLD individually addressed
* Management frame delivery), between an AP MLD and a non-AP MLD, the
* following individually addressed MMPDUs shall be intended for an MLD.
*/
switch (category) {
case WLAN_ACTION_BLOCK_ACK:
case WLAN_ACTION_FT:
case WLAN_ACTION_SA_QUERY:
case WLAN_ACTION_WNM:
switch (sub_category) {
case WNM_BSS_TRANS_MGMT_REQ:
case WNM_BSS_TRANS_MGMT_RESP:
case WNM_SLEEP_MODE_REQ:
case WNM_SLEEP_MODE_RESP:
return true;
default:
return false;
}
case WLAN_ACTION_ROBUST_AV_STREAMING:
switch (sub_category) {
case ROBUST_AV_SCS_REQ:
case ROBUST_AV_SCS_RESP:
case ROBUST_AV_MSCS_REQ:
case ROBUST_AV_MSCS_RESP:
return true;
default:
return false;
}
/* TODO: Handle EHT/EPCS related action frames once the support is
* added. */
default:
return false;
}
}
#endif /* CONFIG_IEEE80211BE */
static int hapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
unsigned int wait, const u8 *dst,
const u8 *data, size_t len, bool addr3_ap)
const u8 *data, size_t len, bool addr3_ap,
const u8 *forced_a3)
{
const u8 *own_addr = hapd->own_addr;
const u8 *bssid;
@@ -926,12 +997,15 @@ static int hapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
struct sta_info *sta;
int link_id = -1;
if (!hapd->driver || !hapd->driver->send_action || !hapd->drv_priv)
return 0;
bssid = hapd->own_addr;
if (!addr3_ap && !is_multicast_ether_addr(dst) &&
len > 0 && data[0] == WLAN_ACTION_PUBLIC) {
if (forced_a3) {
bssid = forced_a3;
} else if (!addr3_ap && !is_multicast_ether_addr(dst) &&
len > 0 && data[0] == WLAN_ACTION_PUBLIC) {
/*
* Public Action frames to a STA that is not a member of the BSS
* shall use wildcard BSSID value.
@@ -956,11 +1030,15 @@ static int hapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
own_addr = hapd->mld->mld_addr;
bssid = own_addr;
}
if (!hostapd_is_action_frame_link_agnostic(data[0], data[1]))
link_id = hapd->mld_link_id;
#endif /* CONFIG_IEEE80211BE */
}
return hapd->driver->send_action(hapd->drv_priv, freq, wait, dst,
own_addr, bssid, data, len, 0);
own_addr, bssid, data, len, 0,
link_id);
}
@@ -968,7 +1046,8 @@ int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
unsigned int wait, const u8 *dst, const u8 *data,
size_t len)
{
return hapd_drv_send_action(hapd, freq, wait, dst, data, len, false);
return hapd_drv_send_action(hapd, freq, wait, dst, data, len, false,
NULL);
}
@@ -977,7 +1056,19 @@ int hostapd_drv_send_action_addr3_ap(struct hostapd_data *hapd,
unsigned int wait, const u8 *dst,
const u8 *data, size_t len)
{
return hapd_drv_send_action(hapd, freq, wait, dst, data, len, true);
return hapd_drv_send_action(hapd, freq, wait, dst, data, len, true,
NULL);
}
int hostapd_drv_send_action_forced_addr3(struct hostapd_data *hapd,
unsigned int freq,
unsigned int wait, const u8 *dst,
const u8 *a3,
const u8 *data, size_t len)
{
return hapd_drv_send_action(hapd, freq, wait, dst, data, len, false,
a3);
}
@@ -1018,6 +1109,12 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface,
}
data.radar_background = radar_background;
data.link_id = -1;
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap)
data.link_id = hapd->mld_link_id;
#endif /* CONFIG_IEEE80211BE */
res = hapd->driver->start_dfs_cac(hapd->drv_priv, &data);
if (!res) {
if (radar_background)
@@ -1049,6 +1146,10 @@ void hostapd_get_hw_mode_any_channels(struct hostapd_data *hapd,
{
int i;
bool is_no_ir = false;
bool allow_6g_acs = is_6ghz_op_class(hapd->iconf->op_class) &&
hostapd_config_check_bss_6g(hapd->conf) &&
(hapd->iface->conf->ieee80211ax ||
hapd->iface->conf->ieee80211be);
for (i = 0; i < mode->num_channels; i++) {
struct hostapd_channel_data *chan = &mode->channels[i];
@@ -1069,8 +1170,7 @@ void hostapd_get_hw_mode_any_channels(struct hostapd_data *hapd,
if (is_6ghz_freq(chan->freq) &&
((hapd->iface->conf->acs_exclude_6ghz_non_psc &&
!is_6ghz_psc_frequency(chan->freq)) ||
(!hapd->iface->conf->ieee80211ax &&
!hapd->iface->conf->ieee80211be)))
!allow_6g_acs))
continue;
if ((!(chan->flag & HOSTAPD_CHAN_DISABLED) || allow_disabled) &&
!(hapd->iface->conf->acs_exclude_dfs &&
@@ -1133,8 +1233,7 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd)
params.hw_mode = hapd->iface->conf->hw_mode;
params.link_id = -1;
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap && hapd->iconf->ieee80211be &&
!hapd->conf->disable_11be)
if (hapd->conf->mld_ap)
params.link_id = hapd->mld_link_id;
#endif /* CONFIG_IEEE80211BE */
@@ -1250,3 +1349,60 @@ int hostapd_drv_set_secure_ranging_ctx(struct hostapd_data *hapd,
return hapd->driver->set_secure_ranging_ctx(hapd->drv_priv, &params);
}
#endif /* CONFIG_PASN */
struct hostapd_multi_hw_info *
hostapd_get_multi_hw_info(struct hostapd_data *hapd,
unsigned int *num_multi_hws)
{
if (!hapd->driver || !hapd->driver->get_multi_hw_info)
return NULL;
return hapd->driver->get_multi_hw_info(hapd->drv_priv, num_multi_hws);
}
int hostapd_drv_add_pmkid(struct hostapd_data *hapd,
struct wpa_pmkid_params *params)
{
if (!hapd->driver || !hapd->driver->add_pmkid || !hapd->drv_priv)
return 0;
return hapd->driver->add_pmkid(hapd->drv_priv, params);
}
int hostapd_add_pmkid(struct hostapd_data *hapd, const u8 *bssid, const u8 *pmk,
size_t pmk_len, const u8 *pmkid, int akmp)
{
struct wpa_pmkid_params params;
os_memset(&params, 0, sizeof(params));
params.bssid = bssid;
params.pmkid = pmkid;
params.pmk = pmk;
params.pmk_len = pmk_len;
return hostapd_drv_add_pmkid(hapd, &params);
}
static int hostapd_drv_remove_pmkid(struct hostapd_data *hapd,
struct wpa_pmkid_params *params)
{
if (!hapd->driver || !hapd->driver->remove_pmkid || !hapd->drv_priv)
return 0;
return hapd->driver->remove_pmkid(hapd->drv_priv, params);
}
int hostapd_remove_pmkid(struct hostapd_data *hapd, const u8 *sta_addr,
const u8 *pmkid)
{
struct wpa_pmkid_params params;
os_memset(&params, 0, sizeof(params));
params.bssid = sta_addr;
params.pmkid = pmkid;
return hostapd_drv_remove_pmkid(hapd, &params);
}
+26 -14
View File
@@ -49,7 +49,8 @@ int hostapd_sta_add(struct hostapd_data *hapd,
size_t eht_capab_len,
const struct ieee80211_he_6ghz_band_cap *he_6ghz_capab,
u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps,
int set, const u8 *link_addr, bool mld_link_sta);
int set, const u8 *link_addr, bool mld_link_sta,
u16 eml_cap, bool epp_sta);
int hostapd_set_privacy(struct hostapd_data *hapd, int enabled);
int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem,
size_t elem_len);
@@ -86,7 +87,6 @@ int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
struct hostapd_hw_modes *
hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
u16 *flags, u8 *dfs_domain);
int hostapd_driver_commit(struct hostapd_data *hapd);
int hostapd_drv_none(struct hostapd_data *hapd);
bool hostapd_drv_nl80211(struct hostapd_data *hapd);
int hostapd_driver_scan(struct hostapd_data *hapd,
@@ -116,6 +116,11 @@ int hostapd_drv_send_action_addr3_ap(struct hostapd_data *hapd,
unsigned int freq,
unsigned int wait, const u8 *dst,
const u8 *data, size_t len);
int hostapd_drv_send_action_forced_addr3(struct hostapd_data *hapd,
unsigned int freq,
unsigned int wait, const u8 *dst,
const u8 *a3,
const u8 *data, size_t len);
static inline void
hostapd_drv_send_action_cancel_wait(struct hostapd_data *hapd)
{
@@ -130,8 +135,6 @@ int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr,
u16 seq, u16 status, const u8 *ie, size_t len);
int hostapd_sta_assoc(struct hostapd_data *hapd, const u8 *addr,
int reassoc, u16 status, const u8 *ie, size_t len);
int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr,
u8 *tspec_ie, size_t tspec_ielen);
int hostapd_start_dfs_cac(struct hostapd_iface *iface,
enum hostapd_hw_mode mode, int freq,
int channel, int ht_enabled, int vht_enabled,
@@ -267,14 +270,6 @@ static inline int hostapd_drv_set_radius_acl_expire(struct hostapd_data *hapd,
return hapd->driver->set_radius_acl_expire(hapd->drv_priv, mac);
}
static inline int hostapd_drv_set_authmode(struct hostapd_data *hapd,
int auth_algs)
{
if (hapd->driver == NULL || hapd->driver->set_authmode == NULL)
return 0;
return hapd->driver->set_authmode(hapd->drv_priv, auth_algs);
}
static inline void hostapd_drv_poll_client(struct hostapd_data *hapd,
const u8 *own_addr, const u8 *addr,
int qos)
@@ -393,7 +388,7 @@ static inline int hostapd_drv_vendor_cmd(struct hostapd_data *hapd,
static inline int hostapd_drv_stop_ap(struct hostapd_data *hapd)
{
int link_id = -1;
int link_id = -1, ret;
if (!hapd->driver || !hapd->driver->stop_ap || !hapd->drv_priv)
return 0;
@@ -401,7 +396,13 @@ static inline int hostapd_drv_stop_ap(struct hostapd_data *hapd)
if (hapd->conf->mld_ap)
link_id = hapd->mld_link_id;
#endif /* CONFIG_IEEE80211BE */
return hapd->driver->stop_ap(hapd->drv_priv, link_id);
ret = hapd->driver->stop_ap(hapd->drv_priv, link_id);
if (ret)
return ret;
hapd->beacon_set_done = 0;
return 0;
}
static inline int hostapd_drv_channel_info(struct hostapd_data *hapd,
@@ -478,4 +479,15 @@ static inline int hostapd_drv_link_sta_remove(struct hostapd_data *hapd,
#endif /* CONFIG_IEEE80211BE */
struct hostapd_multi_hw_info *
hostapd_get_multi_hw_info(struct hostapd_data *hapd,
unsigned int *num_multi_hws);
int hostapd_drv_add_pmkid(struct hostapd_data *hapd,
struct wpa_pmkid_params *params);
int hostapd_add_pmkid(struct hostapd_data *hapd, const u8 *bssid, const u8 *pmk,
size_t pmk_len, const u8 *pmkid, int akmp);
int hostapd_remove_pmkid(struct hostapd_data *hapd, const u8 *sta_addr,
const u8 *pmkid);
#endif /* AP_DRV_OPS */
+6 -2
View File
@@ -112,7 +112,9 @@ void mlme_associate_indication(struct hostapd_data *hapd, struct sta_info *sta)
if (sta->auth_alg != WLAN_AUTH_FT &&
sta->auth_alg != WLAN_AUTH_FILS_SK &&
sta->auth_alg != WLAN_AUTH_FILS_SK_PFS &&
sta->auth_alg != WLAN_AUTH_FILS_PK)
sta->auth_alg != WLAN_AUTH_FILS_PK &&
sta->auth_alg != WLAN_AUTH_EPPKE &&
sta->auth_alg != WLAN_AUTH_802_1X)
mlme_deletekeys_request(hapd, sta);
ap_sta_clear_disconnect_timeouts(hapd, sta);
}
@@ -140,7 +142,9 @@ void mlme_reassociate_indication(struct hostapd_data *hapd,
if (sta->auth_alg != WLAN_AUTH_FT &&
sta->auth_alg != WLAN_AUTH_FILS_SK &&
sta->auth_alg != WLAN_AUTH_FILS_SK_PFS &&
sta->auth_alg != WLAN_AUTH_FILS_PK)
sta->auth_alg != WLAN_AUTH_FILS_PK &&
sta->auth_alg != WLAN_AUTH_EPPKE &&
sta->auth_alg != WLAN_AUTH_802_1X)
mlme_deletekeys_request(hapd, sta);
ap_sta_clear_disconnect_timeouts(hapd, sta);
}
+111 -5
View File
@@ -14,6 +14,7 @@
#include "eap_server/eap.h"
#include "eap_server/eap_sim_db.h"
#include "eapol_auth/eapol_auth_sm.h"
#include "radius/radius.h"
#include "radius/radius_server.h"
#include "hostapd.h"
#include "ap_config.h"
@@ -89,7 +90,6 @@ static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity,
user->force_version = eap_user->force_version;
user->macacl = eap_user->macacl;
user->ttls_auth = eap_user->ttls_auth;
user->remediation = eap_user->remediation;
user->accept_attr = eap_user->accept_attr;
user->t_c_timestamp = eap_user->t_c_timestamp;
rv = 0;
@@ -102,6 +102,114 @@ out:
}
/**
* hostapd_radius_log_acct_req - Callback for logging received RADIUS
* accounting requests
* @ctx: Context (struct hostapd_data)
* @msg: Received RADIUS accounting request
* @status_type: Status type from the message (parsed Acct-Status-Type
* attribute)
* Returns: 0 on success, -1 on failure
*/
static int hostapd_radius_log_acct_req(void *ctx, struct radius_msg *msg,
u32 status_type)
{
char nas_id[RADIUS_MAX_ATTR_LEN + 1] = "";
char session_id[RADIUS_MAX_ATTR_LEN + 1] = "";
char username[RADIUS_MAX_ATTR_LEN + 1] = "";
char calling_station_id[3 * ETH_ALEN] = "";
u32 session_time = 0, terminate_cause = 0,
bytes_in = 0, bytes_out = 0,
packets_in = 0, packets_out = 0,
gigawords_in = 0, gigawords_out = 0;
unsigned long long total_bytes_in = 0, total_bytes_out = 0;
/* Parse NAS identification (required by RFC 2866, section 4.1) */
if (radius_msg_get_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER, (u8 *) nas_id,
sizeof(nas_id) - 1))
nas_id[0] = '\0';
/* Process Accounting-On and Accounting-Off messages separately */
if (status_type == RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_ON ||
status_type == RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_OFF) {
wpa_printf(MSG_INFO, "RADIUS ACCT: NAS='%s' status='%s'",
nas_id,
status_type == RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_ON
? "Accounting-On" : "Accounting-Off");
return 0;
}
/* Parse session ID (required by RFC 2866, section 5.5) */
if (radius_msg_get_attr(msg, RADIUS_ATTR_ACCT_SESSION_ID,
(u8 *) session_id,
sizeof(session_id) - 1) == 0) {
wpa_printf(MSG_DEBUG,
"RADIUS ACCT: request doesn't include session ID");
return -1;
}
/* Parse user name */
radius_msg_get_attr(msg, RADIUS_ATTR_USER_NAME, (u8 *) username,
sizeof(username) - 1);
/* Parse device identifier */
radius_msg_get_attr(msg, RADIUS_ATTR_CALLING_STATION_ID,
(u8 *) calling_station_id,
sizeof(calling_station_id) - 1);
switch (status_type) {
case RADIUS_ACCT_STATUS_TYPE_START:
wpa_printf(MSG_INFO,
"RADIUS ACCT: NAS='%s' session='%s' status='Accounting-Start' station='%s' username='%s'",
nas_id, session_id, calling_station_id, username);
break;
case RADIUS_ACCT_STATUS_TYPE_STOP:
case RADIUS_ACCT_STATUS_TYPE_INTERIM_UPDATE:
/* Parse counters */
radius_msg_get_attr_int32(msg, RADIUS_ATTR_ACCT_SESSION_TIME,
&session_time);
radius_msg_get_attr_int32(msg,
RADIUS_ATTR_ACCT_TERMINATE_CAUSE,
&terminate_cause);
radius_msg_get_attr_int32(msg, RADIUS_ATTR_ACCT_INPUT_OCTETS,
&bytes_in);
radius_msg_get_attr_int32(msg, RADIUS_ATTR_ACCT_OUTPUT_OCTETS,
&bytes_out);
radius_msg_get_attr_int32(msg, RADIUS_ATTR_ACCT_INPUT_PACKETS,
&packets_in);
radius_msg_get_attr_int32(msg, RADIUS_ATTR_ACCT_OUTPUT_PACKETS,
&packets_out);
radius_msg_get_attr_int32(msg,
RADIUS_ATTR_ACCT_INPUT_GIGAWORDS,
&gigawords_in);
radius_msg_get_attr_int32(msg,
RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS,
&gigawords_out);
/* RFC 2869, section 5.1 and 5.2 */
total_bytes_in = ((u64) gigawords_in << 32) + bytes_in;
total_bytes_out = ((u64) gigawords_out << 32) + bytes_out;
wpa_printf(MSG_INFO,
"RADIUS ACCT: NAS='%s' session='%s' status='%s' station='%s' username='%s' session_time=%u term_cause=%u pck_in=%u pck_out=%u bytes_in=%llu bytes_out=%llu",
nas_id, session_id,
status_type == RADIUS_ACCT_STATUS_TYPE_STOP ?
"Accounting-Stop" : "Accounting-Interim-Update",
calling_station_id, username, session_time,
terminate_cause, packets_in, packets_out,
total_bytes_in, total_bytes_out);
break;
default:
wpa_printf(MSG_DEBUG,
"RADIUS ACCT: Unknown request status type %u",
status_type);
return -1;
}
return 0;
}
static int hostapd_setup_radius_srv(struct hostapd_data *hapd)
{
struct radius_server_conf srv;
@@ -129,6 +237,8 @@ static int hostapd_setup_radius_srv(struct hostapd_data *hapd)
srv.conf_ctx = hapd;
srv.ipv6 = conf->radius_server_ipv6;
srv.get_eap_user = hostapd_radius_get_eap_user;
if (conf->radius_server_acct_log)
srv.acct_req_cb = hostapd_radius_log_acct_req;
srv.eap_req_id_text = conf->eap_req_id_text;
srv.eap_req_id_text_len = conf->eap_req_id_text_len;
srv.sqlite_file = conf->eap_user_sqlite;
@@ -136,9 +246,6 @@ static int hostapd_setup_radius_srv(struct hostapd_data *hapd)
srv.dump_msk_file = conf->dump_msk_file;
#endif /* CONFIG_RADIUS_TEST */
#ifdef CONFIG_HS20
srv.subscr_remediation_url = conf->subscr_remediation_url;
srv.subscr_remediation_method = conf->subscr_remediation_method;
srv.hs20_sim_provisioning_url = conf->hs20_sim_provisioning_url;
srv.t_c_server_url = conf->t_c_server_url;
#endif /* CONFIG_HS20 */
srv.erp_domain = conf->erp_domain;
@@ -224,7 +331,6 @@ static struct eap_config * authsrv_eap_config(struct hostapd_data *hapd)
cfg->pac_key_lifetime = hapd->conf->pac_key_lifetime;
cfg->pac_key_refresh_time = hapd->conf->pac_key_refresh_time;
cfg->eap_teap_auth = hapd->conf->eap_teap_auth;
cfg->eap_teap_pac_no_inner = hapd->conf->eap_teap_pac_no_inner;
cfg->eap_teap_separate_result = hapd->conf->eap_teap_separate_result;
cfg->eap_teap_id = hapd->conf->eap_teap_id;
cfg->eap_teap_method_sequence = hapd->conf->eap_teap_method_sequence;
File diff suppressed because it is too large. Load diff
+431 -68
View File
@@ -11,6 +11,7 @@
#include "utils/common.h"
#include "common/ieee802_11_defs.h"
#include "common/sae.h"
#include "common/hw_features_common.h"
#include "eapol_auth/eapol_auth_sm.h"
#include "fst/fst_ctrl_iface.h"
#include "hostapd.h"
@@ -475,6 +476,10 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
#ifdef CONFIG_IEEE80211BE
if (sta->mld_info.mld_sta) {
u16 mld_sta_capa = sta->mld_info.common_info.mld_capa;
u8 max_simul_links = mld_sta_capa &
EHT_ML_MLD_CAPA_MAX_NUM_SIM_LINKS_MASK;
for (i = 0; i < MAX_NUM_MLD_LINKS; ++i) {
if (!sta->mld_info.links[i].valid)
continue;
@@ -485,6 +490,11 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
if (!os_snprintf_error(buflen - len, ret))
len += ret;
}
ret = os_snprintf(buf + len, buflen - len,
"max_simul_links=%d\n", max_simul_links);
if (!os_snprintf_error(buflen - len, ret))
len += ret;
}
#endif /* CONFIG_IEEE80211BE */
@@ -661,15 +671,18 @@ int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd,
}
#endif /* CONFIG_P2P_MANAGER */
if (os_strstr(txtaddr, " tx=0"))
hostapd_drv_sta_remove(hapd, addr);
else
hostapd_drv_sta_deauth(hapd, addr, reason);
sta = ap_get_sta(hapd, addr);
if (sta)
ap_sta_deauthenticate(hapd, sta, reason);
else if (addr[0] == 0xff)
hostapd_free_stas(hapd);
if (os_strstr(txtaddr, " tx=0")) {
hostapd_drv_sta_remove(hapd, addr);
if (sta)
ap_free_sta(hapd, sta);
} else {
hostapd_drv_sta_deauth(hapd, addr, reason);
if (sta)
ap_sta_deauthenticate(hapd, sta, reason);
else if (addr[0] == 0xff)
hostapd_free_stas(hapd);
}
return 0;
}
@@ -723,15 +736,18 @@ int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd,
}
#endif /* CONFIG_P2P_MANAGER */
if (os_strstr(txtaddr, " tx=0"))
hostapd_drv_sta_remove(hapd, addr);
else
hostapd_drv_sta_disassoc(hapd, addr, reason);
sta = ap_get_sta(hapd, addr);
if (sta)
ap_sta_disassociate(hapd, sta, reason);
else if (addr[0] == 0xff)
hostapd_free_stas(hapd);
if (os_strstr(txtaddr, " tx=0")) {
hostapd_drv_sta_remove(hapd, addr);
if (sta)
ap_free_sta(hapd, sta);
} else {
hostapd_drv_sta_disassoc(hapd, addr, reason);
if (sta)
ap_sta_disassociate(hapd, sta, reason);
else if (addr[0] == 0xff)
hostapd_free_stas(hapd);
}
return 0;
}
@@ -874,15 +890,12 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
iface->conf->channel,
iface->conf->enable_edmg,
iface->conf->edmg_channel,
iface->conf->ieee80211n && !hapd->conf->disable_11n ?
hostapd_is_ht_enabled(hapd) ?
iface->conf->secondary_channel : 0,
iface->conf->ieee80211n && !hapd->conf->disable_11n,
iface->conf->ieee80211ac &&
!hapd->conf->disable_11ac,
iface->conf->ieee80211ax &&
!hapd->conf->disable_11ax,
iface->conf->ieee80211be &&
!hapd->conf->disable_11be,
hostapd_is_ht_enabled(hapd),
hostapd_is_vht_enabled(hapd),
hostapd_is_he_enabled(hapd),
hostapd_is_eht_enabled(hapd),
iface->conf->beacon_int,
hapd->conf->dtim_period);
if (os_snprintf_error(buflen - len, ret))
@@ -890,7 +903,7 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
len += ret;
#ifdef CONFIG_IEEE80211BE
if (iface->conf->ieee80211be && !hapd->conf->disable_11be) {
if (hostapd_is_eht_enabled(hapd)) {
ret = os_snprintf(buf + len, buflen - len,
"eht_oper_chwidth=%d\n"
"eht_oper_centr_freq_seg0_idx=%d\n",
@@ -911,6 +924,15 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
len += ret;
}
if (hapd->iconf->punct_bitmap) {
ret = os_snprintf(buf + len, buflen - len,
"punct_bitmap=0x%x\n",
hapd->iconf->punct_bitmap);
if (os_snprintf_error(buflen - len, ret))
return len;
len += ret;
}
if (hapd->conf->mld_ap) {
struct hostapd_data *link_bss;
@@ -945,12 +967,21 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
return len;
len += ret;
}
ret = os_snprintf(buf + len, buflen - len,
"ap_mld_type=%s\n",
(hapd->iface->mld_mld_capa &
EHT_ML_MLD_CAPA_AP_MLD_TYPE_IND_MASK)
? "NSTR" : "STR");
if (os_snprintf_error(buflen - len, ret))
return len;
len += ret;
}
}
#endif /* CONFIG_IEEE80211BE */
#ifdef CONFIG_IEEE80211AX
if (iface->conf->ieee80211ax && !hapd->conf->disable_11ax) {
if (hostapd_is_he_enabled(hapd)) {
ret = os_snprintf(buf + len, buflen - len,
"he_oper_chwidth=%d\n"
"he_oper_centr_freq_seg0_idx=%d\n"
@@ -974,7 +1005,7 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
}
#endif /* CONFIG_IEEE80211AX */
if (iface->conf->ieee80211ac && !hapd->conf->disable_11ac) {
if (hostapd_is_vht_enabled(hapd)) {
ret = os_snprintf(buf + len, buflen - len,
"vht_oper_chwidth=%d\n"
"vht_oper_centr_freq_seg0_idx=%d\n"
@@ -989,7 +1020,7 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
len += ret;
}
if (iface->conf->ieee80211ac && !hapd->conf->disable_11ac && mode) {
if (hostapd_is_vht_enabled(hapd) && mode) {
u16 rxmap = WPA_GET_LE16(&mode->vht_mcs_set[0]);
u16 txmap = WPA_GET_LE16(&mode->vht_mcs_set[4]);
@@ -1002,7 +1033,7 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
len += ret;
}
if (iface->conf->ieee80211n && !hapd->conf->disable_11n) {
if (hostapd_is_ht_enabled(hapd)) {
ret = os_snprintf(buf + len, buflen - len,
"ht_caps_info=%04x\n",
hapd->iconf->ht_capab);
@@ -1011,21 +1042,21 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
len += ret;
}
if (iface->conf->ieee80211n && !hapd->conf->disable_11n && mode) {
if (hostapd_is_ht_enabled(hapd) && mode) {
len = hostapd_write_ht_mcs_bitmask(buf, buflen, len,
mode->mcs_set);
}
if (iface->current_rates && iface->num_rates) {
if (hapd->current_rates && hapd->num_rates) {
ret = os_snprintf(buf + len, buflen - len, "supported_rates=");
if (os_snprintf_error(buflen - len, ret))
return len;
len += ret;
for (j = 0; j < iface->num_rates; j++) {
for (j = 0; j < hapd->num_rates; j++) {
ret = os_snprintf(buf + len, buflen - len, "%s%02x",
j > 0 ? " " : "",
iface->current_rates[j].rate / 5);
hapd->current_rates[j].rate / 5);
if (os_snprintf_error(buflen - len, ret))
return len;
len += ret;
@@ -1094,10 +1125,313 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
}
int hostapd_parse_csa_settings(const char *pos,
int hostapd_parse_freq_params(const char *pos,
struct hostapd_freq_params *params,
unsigned int freq)
{
os_memset(params, 0, sizeof(*params));
if (freq)
params->freq = freq;
else
params->freq = atoi(pos);
if (params->freq == 0) {
wpa_printf(MSG_ERROR, "freq_params: invalid freq provided");
return -1;
}
#define SET_FREQ_PARAM(str) \
do { \
const char *pos2 = os_strstr(pos, " " #str "="); \
if (pos2) { \
pos2 += sizeof(" " #str "=") - 1; \
params->str = atoi(pos2); \
} \
} while (0)
SET_FREQ_PARAM(center_freq1);
SET_FREQ_PARAM(center_freq2);
SET_FREQ_PARAM(bandwidth);
SET_FREQ_PARAM(sec_channel_offset);
SET_FREQ_PARAM(punct_bitmap);
params->ht_enabled = !!os_strstr(pos, " ht");
params->vht_enabled = !!os_strstr(pos, " vht");
params->eht_enabled = !!os_strstr(pos, " eht");
params->he_enabled = !!os_strstr(pos, " he") ||
params->eht_enabled;
#undef SET_FREQ_PARAM
return 0;
}
static struct hostapd_hw_modes * get_target_hw_mode(struct hostapd_iface *iface,
int freq)
{
int i;
enum hostapd_hw_mode target_mode;
bool is_6ghz = is_6ghz_freq(freq);
if (freq < 4000)
target_mode = HOSTAPD_MODE_IEEE80211G;
else if (freq > 50000)
target_mode = HOSTAPD_MODE_IEEE80211AD;
else
target_mode = HOSTAPD_MODE_IEEE80211A;
for (i = 0; i < iface->num_hw_features; i++) {
struct hostapd_hw_modes *mode;
mode = &iface->hw_features[i];
if (mode->mode == target_mode && mode->is_6ghz == is_6ghz)
return mode;
}
return NULL;
}
static bool
hostapd_ctrl_is_freq_in_mode(struct hostapd_hw_modes *mode,
struct hostapd_multi_hw_info *current_hw_info,
int freq)
{
struct hostapd_channel_data *chan;
int i;
for (i = 0; i < mode->num_channels; i++) {
chan = &mode->channels[i];
if (chan->flag & HOSTAPD_CHAN_DISABLED)
continue;
if (!chan_in_current_hw_info(current_hw_info, chan))
continue;
if (chan->freq == freq)
return true;
}
return false;
}
static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params,
u16 punct_bitmap)
{
u32 start_freq;
bool is_6g = is_6ghz_freq(params->freq);
if (is_6g) {
const int bw_idx[] = { 20, 40, 80, 160, 320 };
int idx, bw;
/* The 6 GHz band requires HE to be enabled. */
params->he_enabled = 1;
if (params->center_freq1) {
if (params->freq == 5935)
idx = (params->center_freq1 - 5925) / 5;
else
idx = (params->center_freq1 - 5950) / 5;
bw = center_idx_to_bw_6ghz(idx);
if (bw < 0 || bw >= (int) ARRAY_SIZE(bw_idx) ||
bw_idx[bw] != params->bandwidth)
return -1;
}
} else { /* Non-6 GHz channel */
/* An EHT STA is also an HE STA as defined in
* IEEE Std 802.11be-2024, 4.3.16a (Extremely high throughput
* (EHT) STA). */
if (params->he_enabled || params->eht_enabled) {
params->he_enabled = 1;
/* An HE STA is also a VHT STA if operating in the 5 GHz
* band and an HE STA is also an HT STA in the 2.4 GHz
* band as defined in IEEE Std 802.11ax-2021, 4.3.15a.
* A VHT STA is an HT STA as defined in IEEE
* Std 802.11, 4.3.15. */
if (IS_5GHZ(params->freq))
params->vht_enabled = 1;
params->ht_enabled = 1;
}
}
switch (params->bandwidth) {
case 0:
/* bandwidth not specified: use 20 MHz by default */
/* fall-through */
case 20:
if (params->center_freq1 &&
params->center_freq1 != params->freq)
return -1;
if (params->center_freq2 || params->sec_channel_offset)
return -1;
if (punct_bitmap)
return -1;
break;
case 40:
if (params->center_freq2 ||
(!is_6g && !params->sec_channel_offset))
return -1;
if (punct_bitmap)
return -1;
if (!params->center_freq1)
break;
switch (params->sec_channel_offset) {
case 1:
if (params->freq + 10 != params->center_freq1)
return -1;
break;
case -1:
if (params->freq - 10 != params->center_freq1)
return -1;
break;
case 0:
if (!is_6g)
return -1;
break;
default:
return -1;
}
break;
case 80:
if (!params->center_freq1 ||
(!is_6g && !params->sec_channel_offset))
return 1;
switch (params->sec_channel_offset) {
case 1:
if (params->freq - 10 != params->center_freq1 &&
params->freq + 30 != params->center_freq1)
return 1;
break;
case -1:
if (params->freq + 10 != params->center_freq1 &&
params->freq - 30 != params->center_freq1)
return -1;
break;
case 0:
if (!is_6g)
return -1;
break;
default:
return -1;
}
if (params->center_freq2 && punct_bitmap)
return -1;
/* Adjacent and overlapped are not allowed for 80+80 */
if (params->center_freq2 &&
params->center_freq1 - params->center_freq2 <= 80 &&
params->center_freq2 - params->center_freq1 <= 80)
return 1;
break;
case 160:
if (!params->center_freq1 || params->center_freq2 ||
(!is_6g && !params->sec_channel_offset))
return -1;
switch (params->sec_channel_offset) {
case 1:
if (params->freq + 70 != params->center_freq1 &&
params->freq + 30 != params->center_freq1 &&
params->freq - 10 != params->center_freq1 &&
params->freq - 50 != params->center_freq1)
return -1;
break;
case -1:
if (params->freq + 50 != params->center_freq1 &&
params->freq + 10 != params->center_freq1 &&
params->freq - 30 != params->center_freq1 &&
params->freq - 70 != params->center_freq1)
return -1;
break;
case 0:
if (!is_6g)
return -1;
break;
default:
return -1;
}
break;
case 320:
if (!params->center_freq1 || params->center_freq2)
return -1;
switch (params->sec_channel_offset) {
case 1:
if (params->freq + 150 != params->center_freq1 &&
params->freq + 110 != params->center_freq1 &&
params->freq + 70 != params->center_freq1 &&
params->freq + 30 != params->center_freq1 &&
params->freq - 10 != params->center_freq1 &&
params->freq - 50 != params->center_freq1 &&
params->freq - 90 != params->center_freq1 &&
params->freq - 130 != params->center_freq1)
return -1;
break;
case -1:
if (params->freq + 130 != params->center_freq1 &&
params->freq + 90 != params->center_freq1 &&
params->freq + 50 != params->center_freq1 &&
params->freq + 10 != params->center_freq1 &&
params->freq - 30 != params->center_freq1 &&
params->freq - 70 != params->center_freq1 &&
params->freq - 110 != params->center_freq1 &&
params->freq - 150 != params->center_freq1)
return -1;
break;
case 0:
break;
default:
return -1;
}
break;
default:
return -1;
}
if (!punct_bitmap)
return 0;
if (!params->eht_enabled) {
wpa_printf(MSG_ERROR,
"Preamble puncturing supported only in EHT");
return -1;
}
if (params->freq >= 2412 && params->freq <= 2484) {
wpa_printf(MSG_ERROR,
"Preamble puncturing is not supported in 2.4 GHz");
return -1;
}
start_freq = params->center_freq1 - (params->bandwidth / 2);
if (!is_punct_bitmap_valid(params->bandwidth,
(params->freq - start_freq) / 20,
punct_bitmap)) {
wpa_printf(MSG_ERROR, "Invalid preamble puncturing bitmap");
return -1;
}
return 0;
}
int hostapd_parse_csa_settings(struct hostapd_iface *iface,
const char *pos,
struct csa_settings *settings)
{
struct hostapd_hw_modes *target_mode;
char *end;
int ret;
os_memset(settings, 0, sizeof(*settings));
settings->cs_count = strtol(pos, &end, 10);
@@ -1106,42 +1440,37 @@ int hostapd_parse_csa_settings(const char *pos,
return -1;
}
settings->freq_params.freq = atoi(end);
if (settings->freq_params.freq == 0) {
wpa_printf(MSG_ERROR, "chanswitch: invalid freq provided");
settings->block_tx = !!os_strstr(pos, " blocktx");
ret = hostapd_parse_freq_params(end, &settings->freq_params, 0);
if (ret < 0) {
wpa_printf(MSG_INFO,
"chanswitch: failed to parse frequency parameters");
return ret;
}
target_mode = get_target_hw_mode(iface, settings->freq_params.freq);
if (!target_mode) {
wpa_printf(MSG_DEBUG,
"chanswitch: Invalid frequency settings provided for hw mode");
return -1;
}
#define SET_CSA_SETTING(str) \
do { \
const char *pos2 = os_strstr(pos, " " #str "="); \
if (pos2) { \
pos2 += sizeof(" " #str "=") - 1; \
settings->freq_params.str = atoi(pos2); \
} \
} while (0)
if (iface->num_hw_features > 1 &&
!hostapd_ctrl_is_freq_in_mode(target_mode, iface->current_hw_info,
settings->freq_params.freq)) {
wpa_printf(MSG_INFO,
"chanswitch: Invalid frequency settings provided for multi band phy");
return -1;
}
#define SET_CSA_SETTING_EXT(str) \
do { \
const char *pos2 = os_strstr(pos, " " #str "="); \
if (pos2) { \
pos2 += sizeof(" " #str "=") - 1; \
settings->str = atoi(pos2); \
} \
} while (0)
SET_CSA_SETTING(center_freq1);
SET_CSA_SETTING(center_freq2);
SET_CSA_SETTING(bandwidth);
SET_CSA_SETTING(sec_channel_offset);
SET_CSA_SETTING_EXT(punct_bitmap);
settings->freq_params.ht_enabled = !!os_strstr(pos, " ht");
settings->freq_params.vht_enabled = !!os_strstr(pos, " vht");
settings->freq_params.he_enabled = !!os_strstr(pos, " he");
settings->freq_params.eht_enabled = !!os_strstr(pos, " eht");
settings->block_tx = !!os_strstr(pos, " blocktx");
#undef SET_CSA_SETTING
#undef SET_CSA_SETTING_EXT
ret = hostapd_ctrl_check_freq_params(&settings->freq_params,
settings->freq_params.punct_bitmap);
if (ret) {
wpa_printf(MSG_INFO,
"chanswitch: invalid frequency settings provided");
return ret;
}
return 0;
}
@@ -1174,6 +1503,7 @@ int hostapd_ctrl_iface_pmksa_add(struct hostapd_data *hapd, char *cmd)
size_t pmk_len;
char *pos, *pos2;
int akmp = 0, expiration = 0;
int ret;
/*
* Entry format:
@@ -1209,8 +1539,18 @@ int hostapd_ctrl_iface_pmksa_add(struct hostapd_data *hapd, char *cmd)
if (sscanf(pos, "%d %d", &expiration, &akmp) != 2)
return -1;
return wpa_auth_pmksa_add2(hapd->wpa_auth, spa, pmk, pmk_len,
pmkid, expiration, akmp, NULL);
ret = wpa_auth_pmksa_add2(hapd->wpa_auth, spa, pmk, pmk_len,
pmkid, expiration, akmp, NULL, false);
if (ret)
return ret;
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap)
ret = wpa_auth_pmksa_add2(hapd->wpa_auth, spa, pmk, pmk_len,
pmkid, expiration, akmp, NULL, true);
#endif /* CONFIG_IEEE80211BE */
return ret;
}
@@ -1609,6 +1949,11 @@ int hostapd_disassoc_deny_mac(struct hostapd_data *hapd)
struct vlan_description vlan_id;
for (sta = hapd->sta_list; sta; sta = sta->next) {
#ifdef CONFIG_IEEE80211BE
int link_id;
struct mld_link_info *info;
#endif /* CONFIG_IEEE80211BE */
if (hostapd_maclist_found(hapd->conf->deny_mac,
hapd->conf->num_deny_mac, sta->addr,
&vlan_id) &&
@@ -1616,6 +1961,24 @@ int hostapd_disassoc_deny_mac(struct hostapd_data *hapd)
!vlan_compare(&vlan_id, sta->vlan_desc)))
ap_sta_disconnect(hapd, sta, sta->addr,
WLAN_REASON_UNSPECIFIED);
#ifdef CONFIG_IEEE80211BE
for (link_id = 0; hapd->conf->mld_ap &&
link_id < MAX_NUM_MLD_LINKS &&
sta->mld_info.mld_sta; link_id++) {
info = &sta->mld_info.links[link_id];
if (!info->valid || link_id != hapd->mld_link_id)
continue;
if (hostapd_maclist_found(hapd->conf->deny_mac,
hapd->conf->num_deny_mac,
info->peer_addr,
&vlan_id) &&
(!vlan_id.notempty ||
!vlan_compare(&vlan_id, sta->vlan_desc)))
ap_sta_disconnect(hapd, sta, sta->addr,
WLAN_REASON_UNSPECIFIED);
}
#endif /* CONFIG_IEEE80211BE */
}
return 0;
+5 -1
View File
@@ -26,7 +26,11 @@ int hostapd_ctrl_iface_poll_sta(struct hostapd_data *hapd,
const char *txtaddr);
int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
size_t buflen);
int hostapd_parse_csa_settings(const char *pos,
int hostapd_parse_freq_params(const char *pos,
struct hostapd_freq_params *params,
unsigned int freq);
int hostapd_parse_csa_settings(struct hostapd_iface *iface,
const char *pos,
struct csa_settings *settings);
int hostapd_ctrl_iface_stop_ap(struct hostapd_data *hapd);
int hostapd_ctrl_iface_pmksa_list(struct hostapd_data *hapd, char *buf,
+95 -2
View File
@@ -2,6 +2,7 @@
* DFS - Dynamic Frequency Selection
* Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
* Copyright (c) 2013-2017, Qualcomm Atheros, Inc.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -253,6 +254,13 @@ static int dfs_find_channel(struct hostapd_iface *iface,
for (i = 0; i < mode->num_channels; i++) {
chan = &mode->channels[i];
if (!chan_in_current_hw_info(iface->current_hw_info, chan)) {
wpa_printf(MSG_DEBUG,
"DFS: channel %d (%d) is not under current hardware index",
chan->freq, chan->chan);
continue;
}
/* Skip HT40/VHT incompatible channels */
if (iface->conf->ieee80211n &&
iface->conf->secondary_channel &&
@@ -974,6 +982,7 @@ static int hostapd_dfs_request_channel_switch(struct hostapd_iface *iface,
u8 new_vht_oper_chwidth;
unsigned int i;
unsigned int num_err = 0;
u8 op_class, chan;
wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d", channel);
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL
@@ -982,6 +991,13 @@ static int hostapd_dfs_request_channel_switch(struct hostapd_iface *iface,
new_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
hostapd_set_oper_chwidth(iface->conf, current_vht_oper_chwidth);
if (ieee80211_freq_to_channel_ext(freq, secondary_channel,
new_vht_oper_chwidth, &op_class,
&chan) != NUM_HOSTAPD_MODES) {
wpa_printf(MSG_DEBUG, "Update op_class %d->%d",
iface->conf->op_class, op_class);
iface->conf->op_class = op_class;
}
/* Setup CSA request */
os_memset(&csa_settings, 0, sizeof(csa_settings));
@@ -1039,6 +1055,14 @@ static int hostapd_dfs_request_channel_switch(struct hostapd_iface *iface,
oper_centr_freq_seg0_idx);
hostapd_set_oper_centr_freq_seg1_idx(iface->conf,
oper_centr_freq_seg1_idx);
if (ieee80211_freq_to_channel_ext(freq, secondary_channel,
new_vht_oper_chwidth,
&op_class, &chan) !=
NUM_HOSTAPD_MODES) {
wpa_printf(MSG_DEBUG, "Update op_class %d->%d",
iface->conf->op_class, op_class);
iface->conf->op_class = op_class;
}
hostapd_disable_iface(iface);
hostapd_enable_iface(iface);
@@ -1106,6 +1130,25 @@ static void hostapd_dfs_update_background_chain(struct hostapd_iface *iface)
}
static bool
hostapd_is_freq_in_current_hw_info(struct hostapd_iface *iface, int freq)
{
struct hostapd_channel_data *chan;
if (!iface->current_mode)
return false;
chan = hw_mode_get_channel(iface->current_mode, freq, NULL);
/* If channel data is not found for the given frequency, consider it is
* out of the current hardware info. */
if (!chan)
return false;
return chan_in_current_hw_info(iface->current_hw_info, chan);
}
static bool
hostapd_dfs_is_background_event(struct hostapd_iface *iface, int freq)
{
@@ -1143,6 +1186,14 @@ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
int ht_enabled, int chan_offset, int chan_width,
int cf1, int cf2)
{
if (!hostapd_is_freq_in_current_hw_info(iface, freq)) {
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO,
DFS_EVENT_CAC_COMPLETED
"Ignoring since freq=%d info is out of own range",
freq);
return 0;
}
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_COMPLETED
"success=%d freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d radar_detected=%d",
success, freq, ht_enabled, chan_offset, chan_width, cf1, cf2,
@@ -1214,6 +1265,14 @@ int hostapd_dfs_pre_cac_expired(struct hostapd_iface *iface, int freq,
int ht_enabled, int chan_offset, int chan_width,
int cf1, int cf2)
{
if (!hostapd_is_freq_in_current_hw_info(iface, freq)) {
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO,
DFS_EVENT_PRE_CAC_EXPIRED
"Ignoring since freq=%d info is out of own range",
freq);
return 0;
}
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_PRE_CAC_EXPIRED
"freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d",
freq, ht_enabled, chan_offset, chan_width, cf1, cf2);
@@ -1276,6 +1335,7 @@ static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface)
u8 oper_centr_freq_seg1_idx = 0;
enum dfs_channel_type channel_type = DFS_ANY_CHANNEL;
int err = 1;
u8 op_class, chan;
/* Radar detected during active CAC */
iface->cac_started = 0;
@@ -1308,6 +1368,14 @@ static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface)
oper_centr_freq_seg0_idx);
hostapd_set_oper_centr_freq_seg1_idx(iface->conf,
oper_centr_freq_seg1_idx);
if (ieee80211_freq_to_channel_ext(channel->freq, secondary_channel,
hostapd_get_oper_chwidth(iface->conf),
&op_class, &chan) !=
NUM_HOSTAPD_MODES) {
wpa_printf(MSG_DEBUG, "Update op_class %d->%d",
iface->conf->op_class, op_class);
iface->conf->op_class = op_class;
}
err = 0;
hostapd_setup_interface_complete(iface, err);
@@ -1445,6 +1513,14 @@ int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq,
int ht_enabled, int chan_offset, int chan_width,
int cf1, int cf2)
{
if (!hostapd_is_freq_in_current_hw_info(iface, freq)) {
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO,
DFS_EVENT_RADAR_DETECTED
"Ignoring since freq=%d info is out of own range",
freq);
return 0;
}
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_RADAR_DETECTED
"freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d",
freq, ht_enabled, chan_offset, chan_width, cf1, cf2);
@@ -1483,6 +1559,14 @@ int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq,
int ht_enabled, int chan_offset, int chan_width,
int cf1, int cf2)
{
if (!hostapd_is_freq_in_current_hw_info(iface, freq)) {
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO,
DFS_EVENT_NOP_FINISHED
"Ignoring since freq=%d info is out of own range",
freq);
return 0;
}
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NOP_FINISHED
"freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d",
freq, ht_enabled, chan_offset, chan_width, cf1, cf2);
@@ -1536,10 +1620,19 @@ int hostapd_is_dfs_required(struct hostapd_iface *iface)
}
int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
int hostapd_dfs_start_cac(struct hostapd_data *hapd, int freq,
int ht_enabled, int chan_offset, int chan_width,
int cf1, int cf2)
{
struct hostapd_iface *iface = hapd->iface;
if (!hostapd_is_freq_in_current_hw_info(iface, freq)) {
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START
"Ignoring since freq=%d info is out of own range",
freq);
return 0;
}
if (hostapd_dfs_is_background_event(iface, freq)) {
iface->radar_background.cac_started = 1;
} else {
@@ -1558,7 +1651,7 @@ int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
}
/* TODO: How to check CAC time for ETSI weather channels? */
iface->dfs_cac_ms = 60000;
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START
wpa_msg(hapd->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START
"freq=%d chan=%d chan_offset=%d width=%d seg0=%d "
"seg1=%d cac_time=%ds%s",
freq, (freq - 5000) / 5, chan_offset, chan_width, cf1, cf2,
+1 -1
View File
@@ -26,7 +26,7 @@ int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq,
int chan_offset, int chan_width, int cf1, int cf2);
int hostapd_is_dfs_required(struct hostapd_iface *iface);
int hostapd_is_dfs_chan_available(struct hostapd_iface *iface);
int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
int hostapd_dfs_start_cac(struct hostapd_data *hapd, int freq,
int ht_enabled, int chan_offset, int chan_width,
int cf1, int cf2);
int hostapd_handle_dfs_offload(struct hostapd_iface *iface);
+53 -3
View File
@@ -2,7 +2,7 @@
* hostapd / DPP integration
* Copyright (c) 2017, Qualcomm Atheros, Inc.
* Copyright (c) 2018-2020, The Linux Foundation
* Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -934,6 +934,7 @@ int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd)
#endif /* CONFIG_DPP2 */
hostapd_drv_send_action_cancel_wait(hapd);
dpp_auth_deinit(hapd->dpp_auth);
hapd->dpp_auth = NULL;
}
auth = dpp_auth_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
@@ -1382,6 +1383,21 @@ static void hostapd_dpp_start_gas_client(struct hostapd_data *hapd)
}
static void hostapd_gas_req_wait(void *eloop_ctx, void *timeout_ctx)
{
struct hostapd_data *hapd = eloop_ctx;
struct dpp_authentication *auth = hapd->dpp_auth;
if (!auth)
return;
wpa_printf(MSG_DEBUG, "DPP: Timeout while waiting for Config Request");
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
dpp_auth_deinit(auth);
hapd->dpp_auth = NULL;
}
static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator)
{
wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
@@ -1400,6 +1416,9 @@ static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator)
if (!hapd->dpp_auth->configurator)
hostapd_dpp_start_gas_client(hapd);
else
eloop_register_timeout(10, 0, hostapd_gas_req_wait,
hapd, NULL);
}
@@ -2142,11 +2161,22 @@ static void hostapd_dpp_rx_peer_disc_req(struct hostapd_data *hapd,
if (wpa_auth_pmksa_add2(hapd->wpa_auth, src, intro.pmk, intro.pmk_len,
intro.pmkid, expiration,
WPA_KEY_MGMT_DPP, pkhash) < 0) {
WPA_KEY_MGMT_DPP, pkhash, false) < 0) {
wpa_printf(MSG_ERROR, "DPP: Failed to add PMKSA cache entry");
goto done;
}
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap &&
wpa_auth_pmksa_add2(hapd->wpa_auth, src, intro.pmk, intro.pmk_len,
intro.pmkid, expiration,
WPA_KEY_MGMT_DPP, pkhash, true) < 0) {
wpa_printf(MSG_ERROR,
"DPP: Failed to add PMKSA cache entry (MLD)");
goto done;
}
#endif /* CONFIG_IEEE80211BE */
hostapd_dpp_send_peer_disc_resp(hapd, src, freq, trans_id[0],
DPP_STATUS_OK);
done:
@@ -2916,11 +2946,22 @@ hostapd_dpp_rx_priv_peer_intro_update(struct hostapd_data *hapd, const u8 *src,
if (wpa_auth_pmksa_add2(hapd->wpa_auth, src, intro.pmk, intro.pmk_len,
intro.pmkid, expiration,
WPA_KEY_MGMT_DPP, pkhash) < 0) {
WPA_KEY_MGMT_DPP, pkhash, false) < 0) {
wpa_printf(MSG_ERROR, "DPP: Failed to add PMKSA cache entry");
goto done;
}
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap &&
wpa_auth_pmksa_add2(hapd->wpa_auth, src, intro.pmk, intro.pmk_len,
intro.pmkid, expiration,
WPA_KEY_MGMT_DPP, pkhash, true) < 0) {
wpa_printf(MSG_ERROR,
"DPP: Failed to add PMKSA cache entry (MLD)");
goto done;
}
#endif /* CONFIG_IEEE80211BE */
wpa_printf(MSG_DEBUG, "DPP: Private Peer Introduction completed with "
MACSTR, MAC2STR(src));
@@ -2940,6 +2981,10 @@ void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src,
const u8 *hdr;
unsigned int pkex_t;
/* Discard DPP Action frames if there is no global DPP context */
if (!hapd->iface->interfaces || !hapd->iface->interfaces->dpp)
return;
if (len < DPP_HDR_LEN)
return;
if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
@@ -3079,6 +3124,7 @@ hostapd_dpp_gas_req_handler(struct hostapd_data *hapd, const u8 *sa,
struct wpabuf *resp;
wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR, MAC2STR(sa));
eloop_cancel_timeout(hostapd_gas_req_wait, hapd, NULL);
if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
!ether_addr_equal(sa, auth->peer_mac_addr)) {
#ifdef CONFIG_DPP2
@@ -3359,6 +3405,7 @@ void hostapd_dpp_stop(struct hostapd_data *hapd)
#ifdef CONFIG_DPP3
hostapd_dpp_push_button_stop(hapd);
#endif /* CONFIG_DPP3 */
eloop_cancel_timeout(hostapd_gas_req_wait, hapd, NULL);
}
@@ -3512,6 +3559,7 @@ void hostapd_dpp_deinit(struct hostapd_data *hapd)
eloop_cancel_timeout(hostapd_dpp_auth_conf_wait_timeout, hapd, NULL);
eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
eloop_cancel_timeout(hostapd_gas_req_wait, hapd, NULL);
#ifdef CONFIG_DPP2
eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
hapd, NULL);
@@ -3940,6 +3988,7 @@ int hostapd_dpp_push_button(struct hostapd_data *hapd, const char *cmd)
}
eloop_register_timeout(100, 0, hostapd_dpp_push_button_expire,
hapd, NULL);
hostapd_drv_dpp_listen(hapd, true);
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PB_STATUS "started");
return 0;
@@ -3955,6 +4004,7 @@ void hostapd_dpp_push_button_stop(struct hostapd_data *hapd)
eloop_cancel_timeout(hostapd_dpp_push_button_expire, hapd, NULL);
if (hostapd_dpp_pb_active(hapd)) {
wpa_printf(MSG_DEBUG, "DPP: Stop active push button mode");
hostapd_drv_dpp_listen(hapd, false);
if (!ifaces->dpp_pb_result_indicated)
wpa_msg(hapd->msg_ctx, MSG_INFO,
DPP_EVENT_PB_RESULT "failed");
+377 -165
View File
@@ -1,6 +1,7 @@
/*
* hostapd / Callback functions for driver wrappers
* Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -18,6 +19,7 @@
#include "common/dpp.h"
#include "common/sae.h"
#include "common/hw_features_common.h"
#include "common/nan_de.h"
#include "crypto/random.h"
#include "p2p/p2p.h"
#include "wps/wps.h"
@@ -43,6 +45,7 @@
#include "fils_hlp.h"
#include "neighbor_db.h"
#include "nan_usd_ap.h"
#include "interference.h"
#ifdef CONFIG_FILS
@@ -73,6 +76,8 @@ void hostapd_notify_assoc_fils_finish(struct hostapd_data *hapd,
p = hostapd_eid_assoc_fils_session(sta->wpa_sm, p,
elems.fils_session,
sta->fils_hlp_resp);
if (!p)
return;
reply_res = hostapd_sta_assoc(hapd, sta->addr,
sta->fils_pending_assoc_is_reassoc,
@@ -186,7 +191,22 @@ static int hostapd_update_sta_links_status(struct hostapd_data *hapd,
/* Parse Subelements */
while (rem_len > 2) {
size_t ie_len = 2 + pos[1];
size_t ie_len, subelem_defrag_len;
int num_frag_subelems;
num_frag_subelems =
ieee802_11_defrag_mle_subelem(mlebuf, pos,
&subelem_defrag_len);
if (num_frag_subelems < 0) {
wpa_printf(MSG_DEBUG,
"MLD: Failed to parse MLE subelem");
break;
}
ie_len = 2 + subelem_defrag_len;
if ((size_t) num_frag_subelems * 2 > rem_len)
break;
rem_len -= num_frag_subelems * 2;
if (rem_len < ie_len)
break;
@@ -197,13 +217,13 @@ static int hostapd_update_sta_links_status(struct hostapd_data *hapd,
size_t sta_profile_len;
u16 sta_ctrl;
if (pos[1] < BASIC_MLE_STA_CTRL_LEN + 1) {
if (subelem_defrag_len < BASIC_MLE_STA_CTRL_LEN + 1) {
wpa_printf(MSG_DEBUG,
"MLO: Invalid per-STA profile IE");
goto next_subelem;
}
sta_profile_len = pos[1];
sta_profile_len = subelem_defrag_len;
sta_profile = &pos[2];
sta_ctrl = WPA_GET_LE16(sta_profile);
link_id = sta_ctrl & BASIC_MLE_STA_CTRL_LINK_ID_MASK;
@@ -248,6 +268,52 @@ out:
#endif /* CONFIG_IEEE80211BE */
#if defined(HOSTAPD) || defined(CONFIG_IEEE80211BE)
static struct hostapd_data * hostapd_find_by_sta(struct hostapd_iface *iface,
const u8 *src, bool rsn,
struct sta_info **sta_ret)
{
struct hostapd_data *hapd;
struct sta_info *sta;
unsigned int j;
if (sta_ret)
*sta_ret = NULL;
for (j = 0; j < iface->num_bss; j++) {
hapd = iface->bss[j];
sta = ap_get_sta(hapd, src);
if (sta && (sta->flags & WLAN_STA_ASSOC) &&
(!rsn || sta->wpa_sm)) {
if (sta_ret)
*sta_ret = sta;
return hapd;
}
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap) {
struct hostapd_data *p_hapd;
for_each_mld_link(p_hapd, hapd) {
if (p_hapd == hapd)
continue;
sta = ap_get_sta(p_hapd, src);
if (sta && (sta->flags & WLAN_STA_ASSOC) &&
(!rsn || sta->wpa_sm)) {
if (sta_ret)
*sta_ret = sta;
return p_hapd;
}
}
}
#endif /* CONFIG_IEEE80211BE */
}
return NULL;
}
#endif /* HOSTAPD || CONFIG_IEEE80211BE */
int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
const u8 *req_ies, size_t req_ies_len,
const u8 *resp_ies, size_t resp_ies_len,
@@ -268,6 +334,15 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
struct hostapd_iface *iface = hapd->iface;
#endif /* CONFIG_OWE */
bool updated = false;
bool driver_acl;
#ifdef CONFIG_P2P
if (hapd->p2p_group && (!hapd->started || hapd->disabled)) {
wpa_printf(MSG_DEBUG,
"hostapd_notif_assoc: Ignore assoc event - P2P GO not started or disabled");
return 0;
}
#endif /* CONFIG_P2P */
if (addr == NULL) {
/*
@@ -317,12 +392,6 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
ie = elems.wpa_ie - 2;
ielen = elems.wpa_ie_len + 2;
wpa_printf(MSG_DEBUG, "STA included WPA IE in (Re)AssocReq");
#ifdef CONFIG_HS20
} else if (elems.osen) {
ie = elems.osen - 2;
ielen = elems.osen_len + 2;
wpa_printf(MSG_DEBUG, "STA included OSEN IE in (Re)AssocReq");
#endif /* CONFIG_HS20 */
} else {
ie = NULL;
ielen = 0;
@@ -340,6 +409,11 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
* will not remove the STA immediately.
*/
sta->timeout_next = STA_NULLFUNC;
} else if (!hostapd_acceptable_sta_addr(hapd, addr, addr, false)) {
wpa_printf(MSG_INFO, "STA " MACSTR " not allowed to connect",
MAC2STR(addr));
hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_UNSPECIFIED);
return -1;
} else {
sta = ap_sta_add(hapd, addr);
if (sta == NULL) {
@@ -404,13 +478,57 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
* ACL if the driver supports ACL offload to avoid potentially
* conflicting ACL rules.
*/
if (hapd->iface->drv_max_acl_mac_addrs == 0 &&
driver_acl = hapd->iface->drv_max_acl_mac_addrs > 0;
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap)
driver_acl = false;
#endif /* CONFIG_IEEE80211BE */
if (!driver_acl &&
hostapd_check_acl(hapd, addr, NULL) != HOSTAPD_ACL_ACCEPT) {
wpa_printf(MSG_INFO, "STA " MACSTR " not allowed to connect",
MAC2STR(addr));
reason = WLAN_REASON_UNSPECIFIED;
goto fail;
}
#ifdef CONFIG_IEEE80211BE
/*
* The idea is that ACL is per link. For MLO associations, check
* whether peer MLD MAC address is acceptable in all requested links.
* For each peer link address, check the corresponding association
* local link's ACL configuration whether it is acceptable.
*/
if (!driver_acl && hapd->conf->mld_ap && link_addr) {
int link_id;
struct mld_link_info *info;
struct hostapd_data *bss;
for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
info = &sta->mld_info.links[link_id];
if (!info->valid)
continue;
bss = hostapd_mld_get_link_bss(hapd, link_id);
if (bss && bss != hapd &&
hostapd_check_acl(bss, addr, NULL) !=
HOSTAPD_ACL_ACCEPT) {
wpa_printf(MSG_INFO, "STA " MACSTR
" not allowed to connect",
MAC2STR(addr));
reason = WLAN_REASON_UNSPECIFIED;
goto fail;
}
if (bss &&
hostapd_check_acl(bss, info->peer_addr, NULL) !=
HOSTAPD_ACL_ACCEPT) {
wpa_printf(MSG_INFO, "link addr " MACSTR
" not allowed to connect",
MAC2STR(info->peer_addr));
reason = WLAN_REASON_UNSPECIFIED;
goto fail;
}
}
}
#endif /* CONFIG_IEEE80211BE */
#ifdef CONFIG_P2P
if (elems.p2p) {
@@ -481,7 +599,7 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA");
reason = WLAN_REASON_INVALID_IE;
status = WLAN_STATUS_INVALID_IE;
status = WLAN_STATUS_INVALID_ELEMENT;
goto fail;
}
#ifdef CONFIG_WPS
@@ -513,6 +631,9 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
"Failed to initialize WPA state machine");
return -1;
}
wpa_auth_set_rsn_selection(sta->wpa_sm, elems.rsn_selection,
elems.rsn_selection_len);
wpa_auth_set_auth_alg(sta->wpa_sm, sta->auth_alg);
#ifdef CONFIG_IEEE80211BE
if (ap_sta_is_mld(hapd, sta)) {
wpa_printf(MSG_DEBUG,
@@ -528,9 +649,10 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
elems.rsnxe ? elems.rsnxe - 2 : NULL,
elems.rsnxe ? elems.rsnxe_len + 2 : 0,
elems.mdie, elems.mdie_len,
elems.owe_dh, elems.owe_dh_len, NULL);
elems.owe_dh, elems.owe_dh_len, NULL,
ap_sta_is_mld(hapd, sta));
reason = WLAN_REASON_INVALID_IE;
status = WLAN_STATUS_INVALID_IE;
status = WLAN_STATUS_INVALID_ELEMENT;
switch (res) {
case WPA_IE_OK:
reason = WLAN_REASON_UNSPECIFIED;
@@ -538,23 +660,23 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
break;
case WPA_INVALID_IE:
reason = WLAN_REASON_INVALID_IE;
status = WLAN_STATUS_INVALID_IE;
status = WLAN_STATUS_INVALID_ELEMENT;
break;
case WPA_INVALID_GROUP:
reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
status = WLAN_STATUS_INVALID_GROUP_CIPHER;
break;
case WPA_INVALID_PAIRWISE:
reason = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER;
break;
case WPA_INVALID_AKMP:
reason = WLAN_REASON_AKMP_NOT_VALID;
status = WLAN_STATUS_AKMP_NOT_VALID;
status = WLAN_STATUS_INVALID_AKMP;
break;
case WPA_NOT_ENABLED:
reason = WLAN_REASON_INVALID_IE;
status = WLAN_STATUS_INVALID_IE;
status = WLAN_STATUS_INVALID_ELEMENT;
break;
case WPA_ALLOC_FAIL:
reason = WLAN_REASON_UNSPECIFIED;
@@ -562,19 +684,19 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
break;
case WPA_MGMT_FRAME_PROTECTION_VIOLATION:
reason = WLAN_REASON_INVALID_IE;
status = WLAN_STATUS_INVALID_IE;
status = WLAN_STATUS_INVALID_ELEMENT;
break;
case WPA_INVALID_MGMT_GROUP_CIPHER:
reason = WLAN_REASON_CIPHER_SUITE_REJECTED;
status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
status = WLAN_STATUS_CIPHER_OUT_OF_POLICY;
break;
case WPA_INVALID_MDIE:
reason = WLAN_REASON_INVALID_MDE;
status = WLAN_STATUS_INVALID_MDIE;
status = WLAN_STATUS_INVALID_MDE;
break;
case WPA_INVALID_PROTO:
reason = WLAN_REASON_INVALID_IE;
status = WLAN_STATUS_INVALID_IE;
status = WLAN_STATUS_INVALID_ELEMENT;
break;
case WPA_INVALID_PMKID:
reason = WLAN_REASON_INVALID_PMKID;
@@ -598,6 +720,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,
@@ -605,9 +732,9 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
if (status != WLAN_STATUS_SUCCESS) {
if (status == WLAN_STATUS_INVALID_PMKID)
reason = WLAN_REASON_INVALID_IE;
if (status == WLAN_STATUS_INVALID_MDIE)
if (status == WLAN_STATUS_INVALID_MDE)
reason = WLAN_REASON_INVALID_IE;
if (status == WLAN_STATUS_INVALID_FTIE)
if (status == WLAN_STATUS_INVALID_FTE)
reason = WLAN_REASON_INVALID_IE;
goto fail;
}
@@ -619,14 +746,27 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
sta->sae && !sta->sae->h2e &&
ieee802_11_rsnx_capab_len(elems.rsnxe, elems.rsnxe_len,
WLAN_RSNX_CAPAB_SAE_H2E)) {
wpa_printf(MSG_INFO, "SAE: " MACSTR
" indicates support for SAE H2E, but did not use it",
MAC2STR(sta->addr));
status = WLAN_STATUS_UNSPECIFIED_FAILURE;
reason = WLAN_REASON_UNSPECIFIED;
goto fail;
if (hapd->conf->sae_accept_h2e_without_use) {
wpa_printf(MSG_INFO, "SAE: " MACSTR
" indicates support for SAE H2E, but did not use it - accepting due to sae_accept_h2e_without_use",
MAC2STR(sta->addr));
} else {
wpa_printf(MSG_INFO, "SAE: " MACSTR
" indicates support for SAE H2E, but did not use it",
MAC2STR(sta->addr));
status = WLAN_STATUS_UNSPECIFIED_FAILURE;
reason = WLAN_REASON_UNSPECIFIED;
goto fail;
}
}
#endif /* CONFIG_SAE */
wpa_auth_set_ssid_protection(
sta->wpa_sm,
hapd->conf->ssid_protection &&
ieee802_11_rsnx_capab_len(
elems.rsnxe, elems.rsnxe_len,
WLAN_RSNX_CAPAB_SSID_PROTECTION));
} else if (hapd->conf->wps_state) {
#ifdef CONFIG_WPS
struct wpabuf *wps;
@@ -639,7 +779,7 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
#ifdef CONFIG_WPS_STRICT
if (wps && wps_validate_assoc_req(wps) < 0) {
reason = WLAN_REASON_INVALID_IE;
status = WLAN_STATUS_INVALID_IE;
status = WLAN_STATUS_INVALID_ELEMENT;
wpabuf_free(wps);
goto fail;
}
@@ -655,29 +795,6 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
sta->flags |= WLAN_STA_MAYBE_WPS;
wpabuf_free(wps);
#endif /* CONFIG_WPS */
#ifdef CONFIG_HS20
} else if (hapd->conf->osen) {
if (elems.osen == NULL) {
hostapd_logger(
hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO,
"No HS 2.0 OSEN element in association request");
return WLAN_STATUS_INVALID_IE;
}
wpa_printf(MSG_DEBUG, "HS 2.0: OSEN association");
if (sta->wpa_sm == NULL)
sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
sta->addr, NULL);
if (sta->wpa_sm == NULL) {
wpa_printf(MSG_WARNING,
"Failed to initialize WPA state machine");
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
if (wpa_validate_osen(hapd->wpa_auth, sta->wpa_sm,
elems.osen - 2, elems.osen_len + 2) < 0)
return WLAN_STATUS_INVALID_IE;
#endif /* CONFIG_HS20 */
}
#ifdef CONFIG_WPS
skip_wpa_check:
@@ -696,7 +813,7 @@ skip_wpa_check:
#ifdef CONFIG_IEEE80211R_AP
p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, buf, sizeof(buf),
sta->auth_alg, req_ies, req_ies_len,
!elems.rsnxe);
!elems.rsnxe, reassoc, sta->vlan_id);
if (!p) {
wpa_printf(MSG_DEBUG, "FT: Failed to write AssocResp IEs");
return WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -773,6 +890,9 @@ skip_wpa_check:
p = hostapd_eid_assoc_fils_session(sta->wpa_sm, p,
elems.fils_session,
sta->fils_hlp_resp);
if (!p)
goto fail;
wpa_hexdump(MSG_DEBUG, "FILS Assoc Resp BUF (IEs)",
buf, p - buf);
}
@@ -857,21 +977,22 @@ skip_wpa_check:
}
#endif /* CONFIG_IEEE80211R_AP || CONFIG_FILS */
new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE;
hostapd_set_sta_flags(hapd, sta);
#ifdef CONFIG_IEEE80211BE
if (hostapd_process_assoc_ml_info(hapd, sta, req_ies, req_ies_len,
!!reassoc, WLAN_STATUS_SUCCESS,
true)) {
true, NULL)) {
status = WLAN_STATUS_UNSPECIFIED_FAILURE;
reason = WLAN_REASON_UNSPECIFIED;
goto fail;
}
#endif /* CONFIG_IEEE80211BE */
new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE;
hostapd_set_sta_flags(hapd, sta);
if (updated)
ap_sta_set_authorized_event(hapd, sta, 1);
@@ -897,6 +1018,10 @@ skip_wpa_check:
}
#endif /* CONFIG_P2P */
if (elems.wfa_capab)
hostapd_wfa_capab(hapd, sta, elems.wfa_capab,
elems.wfa_capab + elems.wfa_capab_len);
return 0;
fail:
@@ -923,33 +1048,27 @@ static void hostapd_remove_sta(struct hostapd_data *hapd, struct sta_info *sta)
#ifdef CONFIG_IEEE80211BE
static void hostapd_notif_disassoc_mld(struct hostapd_data *assoc_hapd,
struct sta_info *sta,
const u8 *addr)
void hostapd_notif_disassoc_mld(struct hostapd_data *assoc_hapd,
struct sta_info *sta, const u8 *addr)
{
unsigned int link_id, i;
unsigned int i;
struct hostapd_data *tmp_hapd;
struct hapd_interfaces *interfaces = assoc_hapd->iface->interfaces;
/* Remove STA entry in non-assoc links */
for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
if (!sta->mld_info.links[link_id].valid)
for (i = 0; i < interfaces->count; i++) {
struct sta_info *tmp_sta;
tmp_hapd = interfaces->iface[i]->bss[0];
if (!tmp_hapd->conf->mld_ap ||
assoc_hapd == tmp_hapd ||
!hostapd_is_ml_partner(assoc_hapd, tmp_hapd))
continue;
for (i = 0; i < interfaces->count; i++) {
struct sta_info *tmp_sta;
tmp_hapd = interfaces->iface[i]->bss[0];
if (!tmp_hapd->conf->mld_ap ||
assoc_hapd == tmp_hapd ||
assoc_hapd->conf->mld_id != tmp_hapd->conf->mld_id)
continue;
tmp_sta = ap_get_sta(tmp_hapd, addr);
if (tmp_sta)
ap_free_sta(tmp_hapd, tmp_sta);
}
tmp_sta = ap_get_sta(tmp_hapd, addr);
if (tmp_sta)
ap_free_sta(tmp_hapd, tmp_sta);
}
/* Remove STA in assoc link */
@@ -980,7 +1099,7 @@ void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
sta = ap_get_sta(hapd, addr);
#ifdef CONFIG_IEEE80211BE
if (hostapd_is_mld_ap(hapd)) {
if (hostapd_is_multiple_link_mld(hapd)) {
struct hostapd_data *assoc_hapd;
unsigned int i;
@@ -994,7 +1113,7 @@ void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
struct hostapd_bss_config *hconf = h_hapd->conf;
if (!hconf->mld_ap ||
hconf->mld_id != hapd->conf->mld_id)
!hostapd_is_ml_partner(hapd, h_hapd))
continue;
sta = ap_get_sta(h_hapd, addr);
@@ -1037,6 +1156,20 @@ legacy:
void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr)
{
struct sta_info *sta = ap_get_sta(hapd, addr);
#ifdef CONFIG_IEEE80211BE
struct hostapd_data *orig_hapd = hapd;
if (!sta && hapd->conf->mld_ap) {
hapd = hostapd_find_by_sta(hapd->iface, addr, true, &sta);
if (!hapd) {
wpa_printf(MSG_DEBUG,
"No partner link BSS found for STA " MACSTR
" - fallback to received context",
MAC2STR(addr));
hapd = orig_hapd;
}
}
#endif /* CONFIG_IEEE80211BE */
if (!sta || !hapd->conf->disassoc_low_ack || sta->agreed_to_steer)
return;
@@ -1402,10 +1535,9 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd,
if (mode->mode == acs_res->hw_mode) {
if (hapd->iface->freq > 0 &&
!hw_get_chan(mode->mode,
hapd->iface->freq,
hapd->iface->hw_features,
hapd->iface->num_hw_features))
!hw_mode_get_channel(mode,
hapd->iface->freq,
NULL))
continue;
hapd->iface->current_mode = mode;
break;
@@ -1587,8 +1719,6 @@ static void hostapd_notif_auth(struct hostapd_data *hapd,
{
struct sta_info *sta;
u16 status = WLAN_STATUS_SUCCESS;
u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
size_t resp_ies_len = 0;
sta = ap_get_sta(hapd, rx_auth->peer);
if (!sta) {
@@ -1633,7 +1763,7 @@ static void hostapd_notif_auth(struct hostapd_data *hapd,
fail:
hostapd_sta_auth(hapd, rx_auth->peer, rx_auth->auth_transaction + 1,
status, resp_ies, resp_ies_len);
status, NULL, 0);
}
@@ -1714,14 +1844,14 @@ static void hostapd_action_rx(struct hostapd_data *hapd,
WLAN_PA_VENDOR_SPECIFIC &&
WPA_GET_BE24(mgmt->u.action.u.vs_public_action.oui) ==
OUI_WFA &&
mgmt->u.action.u.vs_public_action.variable[0] == NAN_OUI_TYPE) {
mgmt->u.action.u.vs_public_action.variable[0] == NAN_SDF_OUI_TYPE) {
const u8 *pos, *end;
pos = mgmt->u.action.u.vs_public_action.variable;
end = drv_mgmt->frame + drv_mgmt->frame_len;
pos++;
hostapd_nan_usd_rx_sdf(hapd, mgmt->sa, drv_mgmt->freq,
pos, end - pos);
hostapd_nan_usd_rx_sdf(hapd, mgmt->sa, mgmt->bssid,
drv_mgmt->freq, pos, end - pos);
return;
}
#endif /* CONFIG_NAN_USD */
@@ -1788,6 +1918,11 @@ static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface,
if (bssid[0] == 0xff && bssid[1] == 0xff && bssid[2] == 0xff &&
bssid[3] == 0xff && bssid[4] == 0xff && bssid[5] == 0xff)
return HAPD_BROADCAST;
#ifdef CONFIG_NAN_USD
if (nan_de_is_nan_network_id(bssid))
return HAPD_BROADCAST; /* Process NAN Network ID like broadcast
*/
#endif /* CONFIG_NAN_USD */
for (i = 0; i < iface->num_bss; i++) {
struct hostapd_data *hapd;
@@ -1921,18 +2056,19 @@ static void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf,
{
struct ieee80211_hdr *hdr;
struct hostapd_data *orig_hapd, *tmp_hapd;
const u8 *bssid;
orig_hapd = hapd;
hdr = (struct ieee80211_hdr *) buf;
hapd = switch_link_hapd(hapd, link_id);
tmp_hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len), link_id);
bssid = get_hdr_bssid(hdr, len);
tmp_hapd = get_hapd_bssid(hapd->iface, bssid, link_id);
if (tmp_hapd) {
hapd = tmp_hapd;
#ifdef CONFIG_IEEE80211BE
} else if (hapd->conf->mld_ap &&
ether_addr_equal(hapd->mld->mld_addr,
get_hdr_bssid(hdr, len))) {
} else if (hapd->conf->mld_ap && bssid &&
ether_addr_equal(hapd->mld->mld_addr, bssid)) {
/* AP MLD address match - use hapd pointer as-is */
#endif /* CONFIG_IEEE80211BE */
} else {
@@ -1979,50 +2115,6 @@ static int hostapd_event_new_sta(struct hostapd_data *hapd, const u8 *addr)
}
static struct hostapd_data * hostapd_find_by_sta(struct hostapd_iface *iface,
const u8 *src, bool rsn,
struct sta_info **sta_ret)
{
struct hostapd_data *hapd;
struct sta_info *sta;
unsigned int j;
if (sta_ret)
*sta_ret = NULL;
for (j = 0; j < iface->num_bss; j++) {
hapd = iface->bss[j];
sta = ap_get_sta(hapd, src);
if (sta && (sta->flags & WLAN_STA_ASSOC) &&
(!rsn || sta->wpa_sm)) {
if (sta_ret)
*sta_ret = sta;
return hapd;
}
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap) {
struct hostapd_data *p_hapd;
for_each_mld_link(p_hapd, hapd) {
if (p_hapd == hapd)
continue;
sta = ap_get_sta(p_hapd, src);
if (sta && (sta->flags & WLAN_STA_ASSOC) &&
(!rsn || sta->wpa_sm)) {
if (sta_ret)
*sta_ret = sta;
return p_hapd;
}
}
}
#endif /* CONFIG_IEEE80211BE */
}
return NULL;
}
static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src,
const u8 *data, size_t data_len,
enum frame_encryption encrypted,
@@ -2166,6 +2258,8 @@ void hostapd_event_get_survey(struct hostapd_iface *iface,
continue;
if (chan->flag & HOSTAPD_CHAN_DISABLED)
continue;
if (!(chan->flag & HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED))
continue;
dl_list_del(&survey->list);
dl_list_add_tail(&chan->survey_list, &survey->list);
@@ -2191,6 +2285,10 @@ static void hostapd_event_iface_unavailable(struct hostapd_data *hapd)
hostapd_switch_channel_fallback(hapd->iface,
&hapd->cs_freq_params);
}
/* Clear beacon_set_done so that the RNR and other beacon parameters
* are properly updated. */
hapd->beacon_set_done = 0;
}
@@ -2248,11 +2346,26 @@ static void hostapd_event_dfs_cac_started(struct hostapd_data *hapd,
struct dfs_event *radar)
{
wpa_printf(MSG_DEBUG, "DFS offload CAC started on %d MHz", radar->freq);
hostapd_dfs_start_cac(hapd->iface, radar->freq, radar->ht_enabled,
hostapd_dfs_start_cac(hapd, radar->freq, radar->ht_enabled,
radar->chan_offset, radar->chan_width,
radar->cf1, radar->cf2);
}
static void hostapd_event_incumbt_sig_intf_detected(
struct hostapd_data *hapd, struct incumbt_sig_intf_event *intf_info)
{
wpa_printf(MSG_DEBUG, "Interference due to incumbent signal detected on %d MHz with intf bitmap 0x%x on link_id %d",
intf_info->freq, intf_info->chan_bw_interference_bitmap,
intf_info->link_id);
if (hostapd_incumbt_sig_intf_detected(
hapd->iface, intf_info->freq, intf_info->chan_width,
intf_info->cf1, intf_info->cf2,
intf_info->chan_bw_interference_bitmap))
wpa_printf(MSG_INFO,
"Failed to handle incumbent signal interference");
}
#endif /* NEED_AP_MLME */
@@ -2297,7 +2410,7 @@ static int hostapd_notif_update_dh_ie(struct hostapd_data *hapd,
}
if (!(hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE)) {
wpa_printf(MSG_DEBUG, "OWE: No OWE AKM configured");
status = WLAN_STATUS_AKMP_NOT_VALID;
status = WLAN_STATUS_INVALID_AKMP;
goto err;
}
if (ieee802_11_parse_elems(ie, ie_len, &elems, 1) == ParseFailed) {
@@ -2394,8 +2507,14 @@ static void hostapd_event_color_change(struct hostapd_data *hapd, bool success)
if (bss->cca_color == 0)
continue;
if (success)
if (success) {
hapd->iface->conf->he_op.he_bss_color = bss->cca_color;
/* Clear the disabled flag set during CCA so that
* subsequent beacon rebuilds advertise the new color
* as enabled.
*/
hapd->iface->conf->he_op.he_bss_color_disabled = 0;
}
bss->cca_in_progress = 0;
if (ieee802_11_set_beacon(bss)) {
@@ -2409,6 +2528,88 @@ static void hostapd_event_color_change(struct hostapd_data *hapd, bool success)
#endif /* CONFIG_IEEE80211AX */
static void hostapd_iface_enable(struct hostapd_data *hapd)
{
wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_ENABLED);
if (hapd->disabled && hapd->started) {
hapd->disabled = 0;
/*
* Try to re-enable interface if the driver stopped it
* when the interface got disabled.
*/
if (hapd->wpa_auth)
wpa_auth_reconfig_group_keys(hapd->wpa_auth);
else
hostapd_reconfig_encryption(hapd);
hapd->reenable_beacon = 1;
ieee802_11_set_beacon(hapd);
#ifdef NEED_AP_MLME
} else if (hapd->disabled && hapd->iface->cac_started) {
wpa_printf(MSG_DEBUG, "DFS: restarting pending CAC");
hostapd_handle_dfs(hapd->iface);
#endif /* NEED_AP_MLME */
}
}
static void hostapd_iface_disable(struct hostapd_data *hapd)
{
hostapd_free_stas(hapd);
wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_DISABLED);
hapd->disabled = 1;
}
#ifdef CONFIG_IEEE80211BE
static void hostapd_mld_iface_enable(struct hostapd_data *hapd)
{
struct hostapd_data *first_link, *link_bss;
first_link = hostapd_mld_is_first_bss(hapd) ? hapd :
hostapd_mld_get_first_bss(hapd);
/* Links have been removed. Re-add all links and enable them, but
* enable the first link BSS before doing that. */
if (hostapd_drv_link_add(first_link, first_link->mld_link_id,
first_link->own_addr)) {
wpa_printf(MSG_ERROR, "MLD: Failed to re-add link %d in MLD %s",
first_link->mld_link_id, first_link->conf->iface);
return;
}
hostapd_iface_enable(first_link);
/* Add other affiliated links */
for_each_mld_link(link_bss, first_link) {
if (link_bss == first_link)
continue;
if (hostapd_drv_link_add(link_bss, link_bss->mld_link_id,
link_bss->own_addr)) {
wpa_printf(MSG_ERROR,
"MLD: Failed to re-add link %d in MLD %s",
link_bss->mld_link_id,
link_bss->conf->iface);
continue;
}
hostapd_iface_enable(link_bss);
}
}
static void hostapd_mld_iface_disable(struct hostapd_data *hapd)
{
struct hostapd_data *link_bss;
for_each_mld_link(link_bss, hapd)
hostapd_iface_disable(link_bss);
}
#endif /* CONFIG_IEEE80211BE */
void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
union wpa_event_data *data)
{
@@ -2497,6 +2698,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
hostapd_client_poll_ok(hapd, data->client_poll.addr);
break;
case EVENT_RX_FROM_UNKNOWN:
hapd = switch_link_hapd(hapd, data->rx_from_unknown.link_id);
hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.bssid,
data->rx_from_unknown.addr,
data->rx_from_unknown.wds);
@@ -2639,6 +2841,9 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
#ifdef NEED_AP_MLME
case EVENT_INTERFACE_UNAVAILABLE:
hostapd_event_iface_unavailable(hapd);
/* Update beacon information in all other interfaces to cover
* removal/disabling of this BSS. */
hostapd_refresh_all_iface_beacons(hapd->iface);
break;
case EVENT_DFS_RADAR_DETECTED:
if (!data)
@@ -2684,32 +2889,32 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
hapd = switch_link_hapd(hapd, data->dfs_event.link_id);
hostapd_event_dfs_cac_started(hapd, &data->dfs_event);
break;
case EVENT_INCUMBT_SIG_INTF_DETECTED:
if (!data)
break;
hapd = switch_link_hapd(hapd,
data->incumbt_sig_intf_event.link_id);
hostapd_event_incumbt_sig_intf_detected(
hapd, &data->incumbt_sig_intf_event);
break;
#endif /* NEED_AP_MLME */
case EVENT_INTERFACE_ENABLED:
wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_ENABLED);
if (hapd->disabled && hapd->started) {
hapd->disabled = 0;
/*
* Try to re-enable interface if the driver stopped it
* when the interface got disabled.
*/
if (hapd->wpa_auth)
wpa_auth_reconfig_group_keys(hapd->wpa_auth);
else
hostapd_reconfig_encryption(hapd);
hapd->reenable_beacon = 1;
ieee802_11_set_beacon(hapd);
#ifdef NEED_AP_MLME
} else if (hapd->disabled && hapd->iface->cac_started) {
wpa_printf(MSG_DEBUG, "DFS: restarting pending CAC");
hostapd_handle_dfs(hapd->iface);
#endif /* NEED_AP_MLME */
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap) {
hostapd_mld_iface_enable(hapd);
break;
}
#endif /* CONFIG_IEEE80211BE */
hostapd_iface_enable(hapd);
break;
case EVENT_INTERFACE_DISABLED:
hostapd_free_stas(hapd);
wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_DISABLED);
hapd->disabled = 1;
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap) {
hostapd_mld_iface_disable(hapd);
break;
}
#endif /* CONFIG_IEEE80211BE */
hostapd_iface_disable(hapd);
break;
#ifdef CONFIG_ACS
case EVENT_ACS_CHANNEL_SELECTED:
@@ -2762,6 +2967,13 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
hostapd_event_color_change(hapd, true);
break;
#endif /* CONFIG_IEEE80211AX */
#ifdef CONFIG_IEEE80211BE
case EVENT_MLD_INTERFACE_FREED:
wpa_printf(MSG_DEBUG, "MLD: Interface %s freed",
hapd->conf->iface);
hostapd_mld_interface_freed(hapd);
break;
#endif /* CONFIG_IEEE80211BE */
default:
wpa_printf(MSG_DEBUG, "Unknown event %d", event);
break;
-2
View File
@@ -89,8 +89,6 @@ static int get_user_cb(void *ctx, int argc, char *argv[], char *col[])
user->next = (void *) 1;
} else if (os_strcmp(col[i], "methods") == 0 && argv[i]) {
set_user_methods(user, argv[i]);
} else if (os_strcmp(col[i], "remediation") == 0 && argv[i]) {
user->remediation = strlen(argv[i]) > 0;
} else if (os_strcmp(col[i], "t_c_timestamp") == 0 && argv[i]) {
user->t_c_timestamp = strtol(argv[i], NULL, 10);
}
+10 -2
View File
@@ -536,16 +536,24 @@ int gas_query_ap_rx(struct gas_query_ap *gas, const u8 *sa, u8 categ,
}
if (action == WLAN_PA_GAS_COMEBACK_RESP) {
if (pos + 1 > data + len)
if (pos + 1 > data + len) {
wpa_printf(MSG_DEBUG,
"GAS: No room for frag_id in the response from "
MACSTR, MAC2STR(sa));
return 0;
}
frag_id = *pos & 0x7f;
more_frags = (*pos & 0x80) >> 7;
pos++;
}
/* Comeback Delay */
if (pos + 2 > data + len)
if (pos + 2 > data + len) {
wpa_printf(MSG_DEBUG,
"GAS: No room for Comeback Delay in the response from "
MACSTR, MAC2STR(sa));
return 0;
}
comeback_delay = WPA_GET_LE16(pos);
if (comeback_delay > GAS_QUERY_MAX_COMEBACK_DELAY)
comeback_delay = GAS_QUERY_MAX_COMEBACK_DELAY;
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+182 -5
View File
@@ -35,6 +35,7 @@ struct ieee80211_ht_capabilities;
struct full_dynamic_vlan;
enum wps_event;
union wps_event_data;
struct rsn_pmksa_cache_entry;
#ifdef CONFIG_MESH
struct mesh_conf;
#endif /* CONFIG_MESH */
@@ -97,7 +98,13 @@ struct hapd_interfaces {
#ifdef CONFIG_IEEE80211BE
struct hostapd_mld **mld;
size_t mld_count;
int (*mld_ctrl_iface_init)(struct hostapd_mld *mld);
void (*mld_ctrl_iface_deinit)(struct hostapd_mld *mld);
#endif /* CONFIG_IEEE80211BE */
#ifdef CONFIG_PROCESS_COORDINATION
struct proc_coord *pc;
#endif /* CONFIG_PROCESS_COORDINATION */
};
enum hostapd_chan_status {
@@ -167,6 +174,21 @@ struct hostapd_sae_commit_queue {
u8 msg[];
};
struct mld_link_info {
u8 valid:1;
u8 nstr_bitmap_len:2;
u8 local_addr[ETH_ALEN];
u8 peer_addr[ETH_ALEN];
u8 nstr_bitmap[2];
u16 capability;
u16 status;
u16 resp_sta_profile_len;
u8 *resp_sta_profile;
};
/**
* struct hostapd_data - hostapd per-BSS data structure
*/
@@ -204,6 +226,10 @@ struct hostapd_data {
void *msg_ctx; /* ctx for wpa_msg() calls */
void *msg_ctx_parent; /* parent interface ctx for wpa_msg() calls */
int num_rates;
struct hostapd_rate_data *current_rates;
int *basic_rates;
struct radius_client_data *radius;
u64 acct_session_id;
struct radius_das_data *radius_das;
@@ -304,6 +330,13 @@ struct hostapd_data {
size_t psk_len);
void *new_psk_cb_ctx;
#ifdef CONFIG_IEEE8021X_AUTH
void (*send_eap_req)(struct hostapd_data *hapd, struct sta_info *sta,
u8 type, u16 auth_transaction, u16 status,
struct rsn_pmksa_cache_entry *cached_pmk,
const u8 *eap_req, size_t eap_req_len);
#endif /* CONFIG_IEEE8021X_AUTH */
/* channel switch parameters */
struct hostapd_freq_params cs_freq_params;
u8 cs_count;
@@ -476,6 +509,14 @@ struct hostapd_data {
struct hostapd_mld *mld;
struct dl_list link;
u8 mld_link_id;
/* Cached partner info for ML probe response */
struct mld_link_info partner_links[MAX_NUM_MLD_LINKS];
/* 5 characters for "_link", up to 2 characters for <link ID>, so in
* total, additional 7 characters required. */
char ctrl_sock_iface[IFNAMSIZ + 7 + 1];
#ifdef CONFIG_TESTING_OPTIONS
u8 eht_mld_link_removal_count;
#endif /* CONFIG_TESTING_OPTIONS */
@@ -483,6 +524,8 @@ struct hostapd_data {
#ifdef CONFIG_NAN_USD
struct nan_de *nan_de;
/* Whether nan_de should be freed on deinit */
bool nan_de_is_owned;
#endif /* CONFIG_NAN_USD */
u64 scan_cookie; /* Scan instance identifier for the ongoing HT40 scan
@@ -518,6 +561,10 @@ struct hostapd_mld {
struct hostapd_data *fbss;
struct dl_list links; /* List head of all affiliated links */
int ctrl_sock;
struct dl_list ctrl_dst;
char *ctrl_interface; /* Directory for UNIX domain sockets */
};
#define HOSTAPD_MLD_MAX_REF_COUNT 0xFF
@@ -598,11 +645,6 @@ struct hostapd_iface {
struct hostapd_hw_modes *hw_features;
int num_hw_features;
struct hostapd_hw_modes *current_mode;
/* Rates that are currently used (i.e., filtered copy of
* current_mode->channels */
int num_rates;
struct hostapd_rate_data *current_rates;
int *basic_rates;
int freq;
bool radar_detected;
@@ -711,6 +753,43 @@ struct hostapd_iface {
bool is_no_ir;
bool is_ch_switch_dfs; /* Channel switch from ACS to DFS */
struct hostapd_multi_hw_info *multi_hw_info;
unsigned int num_multi_hws;
struct hostapd_multi_hw_info *current_hw_info;
/* Use assisted DFS functionality from the driver. This is used only
* in wpa_supplicant builds for P2P GO functionality. */
bool assisted_dfs;
#ifdef CONFIG_AFC
struct wpabuf *afc_request;
char *afc_response;
struct {
unsigned int request_id;
int timeout;
unsigned int num_freq_range;
struct afc_freq_range_elem {
int low_freq;
int high_freq;
/**
* Maximum EIRP power spectral density received from
* the AFC coordinator for this band
*/
double max_psd;
} *freq_range;
unsigned int num_chan_info;
struct afc_chan_info_elem {
int chan;
/**
* Maximum EIRP power received from the AFC coordinator
* for this channel for each op_class
*/
double power[5];
} *chan_info_list;
bool data_valid;
} afc;
#endif /* CONFIG_AFC */
};
/* hostapd.c */
@@ -733,6 +812,8 @@ struct hostapd_iface * hostapd_init(struct hapd_interfaces *interfaces,
struct hostapd_iface *
hostapd_interface_init_bss(struct hapd_interfaces *interfaces, const char *phy,
const char *config_fname, int debug);
void hostapd_bss_setup_multi_link(struct hostapd_data *hapd,
struct hapd_interfaces *interfaces);
void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
int reassoc);
void hostapd_interface_deinit_free(struct hostapd_iface *iface);
@@ -753,6 +834,8 @@ void hostapd_chan_switch_config(struct hostapd_data *hapd,
struct hostapd_freq_params *freq_params);
int hostapd_switch_channel(struct hostapd_data *hapd,
struct csa_settings *settings);
int hostapd_force_channel_switch(struct hostapd_iface *iface,
struct csa_settings *settings);
void
hostapd_switch_channel_fallback(struct hostapd_iface *iface,
const struct hostapd_freq_params *freq_params);
@@ -763,6 +846,38 @@ void hostapd_ocv_check_csa_sa_query(void *eloop_ctx, void *timeout_ctx);
void hostapd_switch_color(struct hostapd_data *hapd, u64 bitmap);
void hostapd_cleanup_cca_params(struct hostapd_data *hapd);
#ifdef CONFIG_AFC
int hostap_afc_get_chan_max_eirp_power(struct hostapd_iface *iface, bool psd,
int *power);
int hostapd_afc_handle_request(struct hostapd_iface *iface);
void hostapd_afc_send_request(struct hostapd_iface *iface);
void hostapd_afc_stop(struct hostapd_iface *iface);
void hostap_afc_disable_channels(struct hostapd_iface *iface);
#else /* CONFIG_AFC */
static inline int
hostap_afc_get_chan_max_eirp_power(struct hostapd_iface *iface, bool psd,
int *power)
{
return -EINVAL;
}
static inline int hostapd_afc_handle_request(struct hostapd_iface *iface)
{
return 1;
}
static inline void hostapd_afc_send_request(struct hostapd_iface *iface)
{
}
static inline void hostapd_afc_stop(struct hostapd_iface *iface)
{
}
static inline void hostap_afc_disable_channels(struct hostapd_iface *iface)
{
}
#endif /* CONFIG_AFC */
/* utils.c */
int hostapd_register_probereq_cb(struct hostapd_data *hapd,
@@ -781,6 +896,8 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
const u8 *req_ie, size_t req_ielen, const u8 *resp_ie,
size_t resp_ielen, const u8 *link_addr, int reassoc);
void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr);
void hostapd_notif_disassoc_mld(struct hostapd_data *assoc_hapd,
struct sta_info *sta, const u8 *addr);
void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr);
void hostapd_event_connect_failed_reason(struct hostapd_data *hapd,
const u8 *addr, int reason_code);
@@ -806,6 +923,10 @@ void hostapd_event_sta_opmode_changed(struct hostapd_data *hapd, const u8 *addr,
enum smps_mode smps_mode,
enum chan_width chan_width, u8 rx_nss);
int hostapd_change_config_freq(struct hostapd_data *hapd,
struct hostapd_config *conf,
struct hostapd_freq_params *params,
struct hostapd_freq_params *old_params);
#ifdef CONFIG_FST
void fst_hostapd_fill_iface_obj(struct hostapd_data *hapd,
struct fst_wpa_obj *iface_obj);
@@ -822,15 +943,22 @@ bool hostapd_is_ml_partner(struct hostapd_data *hapd1,
u8 hostapd_get_mld_id(struct hostapd_data *hapd);
int hostapd_mld_add_link(struct hostapd_data *hapd);
int hostapd_mld_remove_link(struct hostapd_data *hapd);
u8 hostapd_get_active_links(struct hostapd_data *hapd);
struct hostapd_data * hostapd_mld_get_first_bss(struct hostapd_data *hapd);
int hostapd_build_beacon_data(struct hostapd_data *hapd,
struct beacon_data *beacon);
void free_beacon_data(struct beacon_data *beacon);
int hostapd_fill_cca_settings(struct hostapd_data *hapd,
struct cca_settings *settings);
void hostapd_switch_color_timeout_handler(void *eloop_data, void *user_ctx);
bool hostapd_is_cca_in_progress(struct hostapd_iface *iface);
void hostapd_refresh_all_iface_beacons(struct hostapd_iface *hapd_iface);
#ifdef CONFIG_IEEE80211BE
bool hostapd_mld_is_first_bss(struct hostapd_data *hapd);
void hostapd_mld_interface_freed(struct hostapd_data *hapd);
#define for_each_mld_link(partner, self) \
dl_list_for_each(partner, &self->mld->links, struct hostapd_data, link)
@@ -849,4 +977,53 @@ static inline bool hostapd_mld_is_first_bss(struct hostapd_data *hapd)
u16 hostapd_get_punct_bitmap(struct hostapd_data *hapd);
void hostapd_get_oper_chan_info_of_bss(struct hostapd_data *hapd,
enum oper_chan_width *width,
u8 *seg0, u8 *seg1);
u8 hostapd_get_oper_class_of_bss(struct hostapd_data *hapd);
enum oper_chan_width
hostapd_get_oper_chan_width_of_bss(struct hostapd_data *hapd);
static inline bool ap_pmf_enabled(struct hostapd_bss_config *conf)
{
return conf->ieee80211w != NO_MGMT_FRAME_PROTECTION ||
conf->rsn_override_mfp != NO_MGMT_FRAME_PROTECTION ||
conf->rsn_override_mfp_2 != NO_MGMT_FRAME_PROTECTION;
}
enum oper_chan_width
hostapd_chan_width_from_freq_params(struct hostapd_freq_params *freq_params);
struct hostapd_data *
hostapd_get_mbssid_bss_by_idx(struct hostapd_data *hapd, size_t idx);
bool hostapd_acceptable_sta_addr(struct hostapd_data *hapd, const u8 *addr,
const u8 *addr_ml, bool mld);
static inline bool
hostapd_is_ht_enabled(struct hostapd_data *hapd)
{
return hapd->iconf->ieee80211n && !hapd->conf->disable_11n;
}
static inline bool
hostapd_is_vht_enabled(struct hostapd_data *hapd)
{
return hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac;
}
static inline bool
hostapd_is_he_enabled(struct hostapd_data *hapd)
{
return hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax;
}
static inline bool
hostapd_is_eht_enabled(struct hostapd_data *hapd)
{
return hapd->iconf->ieee80211be && !hapd->conf->disable_11be;
}
#endif /* HOSTAPD_H */
-107
View File
@@ -44,113 +44,6 @@ u8 * hostapd_eid_hs20_indication(struct hostapd_data *hapd, u8 *eid)
}
u8 * hostapd_eid_osen(struct hostapd_data *hapd, u8 *eid)
{
u8 *len;
u16 capab;
if (!hapd->conf->osen)
return eid;
*eid++ = WLAN_EID_VENDOR_SPECIFIC;
len = eid++; /* to be filled */
WPA_PUT_BE24(eid, OUI_WFA);
eid += 3;
*eid++ = HS20_OSEN_OUI_TYPE;
/* Group Data Cipher Suite */
RSN_SELECTOR_PUT(eid, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED);
eid += RSN_SELECTOR_LEN;
/* Pairwise Cipher Suite Count and List */
WPA_PUT_LE16(eid, 1);
eid += 2;
RSN_SELECTOR_PUT(eid, RSN_CIPHER_SUITE_CCMP);
eid += RSN_SELECTOR_LEN;
/* AKM Suite Count and List */
WPA_PUT_LE16(eid, 1);
eid += 2;
RSN_SELECTOR_PUT(eid, RSN_AUTH_KEY_MGMT_OSEN);
eid += RSN_SELECTOR_LEN;
/* RSN Capabilities */
capab = 0;
if (hapd->conf->wmm_enabled) {
/* 4 PTKSA replay counters when using WMM */
capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
}
if (hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
capab |= WPA_CAPABILITY_MFPC;
if (hapd->conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED)
capab |= WPA_CAPABILITY_MFPR;
}
#ifdef CONFIG_OCV
if (hapd->conf->ocv &&
(hapd->iface->drv_flags2 &
(WPA_DRIVER_FLAGS2_AP_SME | WPA_DRIVER_FLAGS2_OCV)))
capab |= WPA_CAPABILITY_OCVC;
#endif /* CONFIG_OCV */
WPA_PUT_LE16(eid, capab);
eid += 2;
*len = eid - len - 1;
return eid;
}
int hs20_send_wnm_notification(struct hostapd_data *hapd, const u8 *addr,
u8 osu_method, const char *url)
{
struct wpabuf *buf;
size_t len = 0;
int ret;
/* TODO: should refuse to send notification if the STA is not associated
* or if the STA did not indicate support for WNM-Notification */
if (url) {
len = 1 + os_strlen(url);
if (5 + len > 255) {
wpa_printf(MSG_INFO, "HS 2.0: Too long URL for "
"WNM-Notification: '%s'", url);
return -1;
}
}
buf = wpabuf_alloc(4 + 7 + len);
if (buf == NULL)
return -1;
wpabuf_put_u8(buf, WLAN_ACTION_WNM);
wpabuf_put_u8(buf, WNM_NOTIFICATION_REQ);
wpabuf_put_u8(buf, 1); /* Dialog token */
wpabuf_put_u8(buf, 1); /* Type - 1 reserved for WFA */
/* Subscription Remediation subelement */
wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
wpabuf_put_u8(buf, 5 + len);
wpabuf_put_be24(buf, OUI_WFA);
wpabuf_put_u8(buf, HS20_WNM_SUB_REM_NEEDED);
if (url) {
wpabuf_put_u8(buf, len - 1);
wpabuf_put_data(buf, url, len - 1);
wpabuf_put_u8(buf, osu_method);
} else {
/* Server URL and Server Method fields not included */
wpabuf_put_u8(buf, 0);
}
ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
wpabuf_head(buf), wpabuf_len(buf));
wpabuf_free(buf);
return ret;
}
int hs20_send_wnm_notification_deauth_req(struct hostapd_data *hapd,
const u8 *addr,
const struct wpabuf *payload)
+263 -65
View File
@@ -72,16 +72,62 @@ static char * dfs_info(struct hostapd_channel_data *chan)
#endif /* CONFIG_NO_STDOUT_DEBUG */
static void move_survey_data(struct hostapd_channel_data *new_chan,
struct hostapd_channel_data *old_chan)
{
struct freq_survey *survey, *tmp;
/* Copy the survey list from the old to new channel */
if (old_chan->flag & HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED) {
dl_list_init(&new_chan->survey_list);
dl_list_for_each_safe(survey, tmp, &old_chan->survey_list,
struct freq_survey, list) {
dl_list_del(&survey->list);
dl_list_add(&new_chan->survey_list,
&survey->list);
}
new_chan->flag |= HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED;
}
}
static void move_hw_mode_data(struct hostapd_hw_modes *new_feature,
struct hostapd_hw_modes *old_feature)
{
int i, j;
for (i = 0; i < new_feature->num_channels; i++) {
struct hostapd_channel_data *new_chan;
struct hostapd_channel_data *old_chan;
new_chan = &new_feature->channels[i];
for (j = 0; j < old_feature->num_channels; j++) {
old_chan = &old_feature->channels[j];
if (new_chan->freq != old_chan->freq)
continue;
move_survey_data(new_chan, old_chan);
break;
}
}
}
int hostapd_get_hw_features(struct hostapd_iface *iface)
{
struct hostapd_data *hapd = iface->bss[0];
int i, j;
unsigned int k;
u16 num_modes, flags;
struct hostapd_hw_modes *modes;
u8 dfs_domain;
enum hostapd_hw_mode mode = HOSTAPD_MODE_IEEE80211ANY;
bool is_6ghz = false;
bool orig_mode_valid = false;
struct hostapd_multi_hw_info *multi_hw_info;
unsigned int num_multi_hws;
if (hostapd_drv_none(hapd))
return -1;
@@ -110,9 +156,6 @@ int hostapd_get_hw_features(struct hostapd_iface *iface)
is_6ghz = iface->current_mode->is_6ghz;
iface->current_mode = NULL;
}
hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
iface->hw_features = modes;
iface->num_hw_features = num_modes;
for (i = 0; i < num_modes; i++) {
struct hostapd_hw_modes *feature = &modes[i];
@@ -142,7 +185,8 @@ int hostapd_get_hw_features(struct hostapd_iface *iface)
} else if (((feature->channels[j].flag &
HOSTAPD_CHAN_RADAR) &&
!(iface->drv_flags &
WPA_DRIVER_FLAGS_DFS_OFFLOAD)) ||
WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
!iface->assisted_dfs) ||
(feature->channels[j].flag &
HOSTAPD_CHAN_NO_IR)) {
feature->channels[j].flag |=
@@ -160,29 +204,66 @@ int hostapd_get_hw_features(struct hostapd_iface *iface)
feature->channels[j].max_tx_power,
dfs ? dfs_info(&feature->channels[j]) : "");
}
/* Move any old data that should be kept */
for (j = 0; j < iface->num_hw_features; j++) {
struct hostapd_hw_modes *old_feature =
&iface->hw_features[j];
if (feature->mode != old_feature->mode)
continue;
move_hw_mode_data(feature, old_feature);
}
}
hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
iface->hw_features = modes;
iface->num_hw_features = num_modes;
hostap_afc_disable_channels(iface);
if (orig_mode_valid && !iface->current_mode) {
wpa_printf(MSG_ERROR,
"%s: Could not update iface->current_mode",
__func__);
}
multi_hw_info = hostapd_get_multi_hw_info(hapd, &num_multi_hws);
if (!multi_hw_info)
return 0;
hostapd_free_multi_hw_info(iface->multi_hw_info);
iface->multi_hw_info = multi_hw_info;
iface->num_multi_hws = num_multi_hws;
wpa_printf(MSG_DEBUG, "Multiple underlying hardwares info:");
for (k = 0; k < num_multi_hws; k++) {
struct hostapd_multi_hw_info *hw_info = &multi_hw_info[k];
wpa_printf(MSG_DEBUG,
" %d. hw_idx=%u, frequency range: %d-%d MHz",
k + 1, hw_info->hw_idx, hw_info->start_freq,
hw_info->end_freq);
}
return 0;
}
int hostapd_prepare_rates(struct hostapd_iface *iface,
int hostapd_prepare_rates(struct hostapd_data *hapd,
struct hostapd_hw_modes *mode)
{
struct hostapd_bss_config *conf = hapd->conf;
int i, num_basic_rates = 0;
int basic_rates_a[] = { 60, 120, 240, -1 };
int basic_rates_b[] = { 10, 20, -1 };
int basic_rates_g[] = { 10, 20, 55, 110, -1 };
int *basic_rates;
int basic_rates_a[] = { 60, 120, 240, 0 };
int basic_rates_b[] = { 10, 20, 0 };
int basic_rates_g[] = { 10, 20, 55, 110, 0 };
const int *basic_rates;
if (iface->conf->basic_rates)
basic_rates = iface->conf->basic_rates;
if (conf->basic_rates)
basic_rates = conf->basic_rates;
else switch (mode->mode) {
case HOSTAPD_MODE_IEEE80211A:
basic_rates = basic_rates_a;
@@ -199,22 +280,15 @@ int hostapd_prepare_rates(struct hostapd_iface *iface,
return -1;
}
i = 0;
while (basic_rates[i] >= 0)
i++;
if (i)
i++; /* -1 termination */
os_free(iface->basic_rates);
iface->basic_rates = os_malloc(i * sizeof(int));
if (iface->basic_rates)
os_memcpy(iface->basic_rates, basic_rates, i * sizeof(int));
os_free(hapd->basic_rates);
hapd->basic_rates = int_array_dup(basic_rates);
os_free(iface->current_rates);
iface->num_rates = 0;
os_free(hapd->current_rates);
hapd->num_rates = 0;
iface->current_rates =
hapd->current_rates =
os_calloc(mode->num_rates, sizeof(struct hostapd_rate_data));
if (!iface->current_rates) {
if (!hapd->current_rates) {
wpa_printf(MSG_ERROR, "Failed to allocate memory for rate "
"table.");
return -1;
@@ -223,27 +297,26 @@ int hostapd_prepare_rates(struct hostapd_iface *iface,
for (i = 0; i < mode->num_rates; i++) {
struct hostapd_rate_data *rate;
if (iface->conf->supported_rates &&
!hostapd_rate_found(iface->conf->supported_rates,
mode->rates[i]))
if (conf->supported_rates &&
!int_array_includes(conf->supported_rates, mode->rates[i]))
continue;
rate = &iface->current_rates[iface->num_rates];
rate = &hapd->current_rates[hapd->num_rates];
rate->rate = mode->rates[i];
if (hostapd_rate_found(basic_rates, rate->rate)) {
if (int_array_includes(basic_rates, rate->rate)) {
rate->flags |= HOSTAPD_RATE_BASIC;
num_basic_rates++;
}
wpa_printf(MSG_DEBUG, "RATE[%d] rate=%d flags=0x%x",
iface->num_rates, rate->rate, rate->flags);
iface->num_rates++;
hapd->num_rates, rate->rate, rate->flags);
hapd->num_rates++;
}
if ((iface->num_rates == 0 || num_basic_rates == 0) &&
(!iface->conf->ieee80211n || !iface->conf->require_ht)) {
if ((hapd->num_rates == 0 || num_basic_rates == 0) &&
(!hapd->iconf->ieee80211n || !hapd->iconf->require_ht)) {
wpa_printf(MSG_ERROR, "No rates remaining in supported/basic "
"rate sets (%d,%d).",
iface->num_rates, num_basic_rates);
hapd->num_rates, num_basic_rates);
return -1;
}
@@ -506,12 +579,6 @@ static void ap_ht40_scan_retry(void *eloop_data, void *user_data)
else
ieee80211n_scan_channels_5g(iface, &params);
params.link_id = -1;
#ifdef CONFIG_IEEE80211BE
if (iface->bss[0]->conf->mld_ap)
params.link_id = iface->bss[0]->mld_link_id;
#endif /* CONFIG_IEEE80211BE */
ret = hostapd_driver_scan(iface->bss[0], &params);
iface->num_ht40_scan_tries++;
os_free(params.freqs);
@@ -533,6 +600,9 @@ static void ap_ht40_scan_retry(void *eloop_data, void *user_data)
wpa_printf(MSG_DEBUG,
"Failed to request a scan in device, bringing up in HT20 mode");
hostapd_set_oper_centr_freq_seg0_idx(iface->conf, 0);
hostapd_set_oper_centr_freq_seg1_idx(iface->conf, 0);
hostapd_set_oper_chwidth(iface->conf, CONF_OPER_CHWIDTH_USE_HT);
iface->conf->secondary_channel = 0;
iface->conf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
hostapd_setup_interface_complete(iface, 0);
@@ -563,11 +633,6 @@ static int ieee80211n_check_40mhz(struct hostapd_iface *iface)
else
ieee80211n_scan_channels_5g(iface, &params);
params.link_id = -1;
#ifdef CONFIG_IEEE80211BE
if (iface->bss[0]->conf->mld_ap)
params.link_id = iface->bss[0]->mld_link_id;
#endif /* CONFIG_IEEE80211BE */
ret = hostapd_driver_scan(iface->bss[0], &params);
os_free(params.freqs);
@@ -716,10 +781,18 @@ static int ieee80211ac_supported_vht_capab(struct hostapd_iface *iface)
#endif /* CONFIG_IEEE80211AC */
#ifdef CONFIG_IEEE80211BE
static int ieee80211be_supported_eht_capab(struct hostapd_iface *iface)
{
return iface->current_mode->eht_capab[IEEE80211_MODE_AP].eht_supported;
}
#endif /* CONFIG_IEEE80211BE */
#ifdef CONFIG_IEEE80211AX
static int ieee80211ax_supported_he_capab(struct hostapd_iface *iface)
{
return 1;
return iface->current_mode->he_capab[IEEE80211_MODE_AP].he_supported;
}
#endif /* CONFIG_IEEE80211AX */
@@ -743,10 +816,19 @@ int hostapd_check_ht_capab(struct hostapd_iface *iface)
if (!ieee80211n_supported_ht_capab(iface))
return -1;
#ifdef CONFIG_IEEE80211BE
if (iface->conf->ieee80211be &&
!ieee80211be_supported_eht_capab(iface)) {
wpa_printf(MSG_ERROR, "Driver does not support EHT");
return -1;
}
#endif /* CONFIG_IEEE80211BE */
#ifdef CONFIG_IEEE80211AX
if (iface->conf->ieee80211ax &&
!ieee80211ax_supported_he_capab(iface))
!ieee80211ax_supported_he_capab(iface)) {
wpa_printf(MSG_ERROR, "Driver does not support HE");
return -1;
}
#endif /* CONFIG_IEEE80211AX */
#ifdef CONFIG_IEEE80211AC
if (iface->conf->ieee80211ac &&
@@ -1003,16 +1085,87 @@ static bool hostapd_is_usable_punct_bitmap(struct hostapd_iface *iface)
}
static int hostapd_is_usable_chan_seg(struct hostapd_iface *iface)
{
int central, oper_chwidth, err;
int start_chan, start_freq, chan_num, i;
oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
central = hostapd_get_oper_centr_freq_seg0_idx(iface->conf);
switch (oper_chwidth) {
case CONF_OPER_CHWIDTH_80MHZ:
case CONF_OPER_CHWIDTH_80P80MHZ:
chan_num = 4;
break;
case CONF_OPER_CHWIDTH_160MHZ:
chan_num = 8;
break;
case CONF_OPER_CHWIDTH_320MHZ:
chan_num = 16;
break;
default:
return 0;
}
start_chan = central - chan_num * 2 + 2;
start_freq = hw_get_freq(iface->current_mode, start_chan);
if (!start_freq) {
wpa_printf(MSG_ERROR, "Frequency not present (seg0)");
return 0;
}
for (i = 0; i < chan_num; i++) {
int freq = start_freq + i * 20;
err = hostapd_is_usable_chan(iface, freq, freq == iface->freq);
if (err <= 0) {
wpa_printf(MSG_ERROR,
"Frequency %d is not allowed (seg0)",
freq);
return err;
}
}
if (oper_chwidth != CONF_OPER_CHWIDTH_80P80MHZ)
return 1;
central = hostapd_get_oper_centr_freq_seg1_idx(iface->conf);
start_chan = central - chan_num * 2 + 2;
start_freq = hw_get_freq(iface->current_mode, start_chan);
if (!start_freq) {
wpa_printf(MSG_ERROR, "Frequency not present (seg1)");
return 0;
}
for (i = 0; i < chan_num; i++) {
int freq = start_freq + i * 20;
err = hostapd_is_usable_chan(iface, freq, freq == iface->freq);
if (err <= 0) {
wpa_printf(MSG_ERROR,
"Frequency %d is not allowed (seg1)",
freq);
return err;
}
}
return 1;
}
/* Returns:
* 1 = usable
* 0 = not usable
* -1 = not currently usable due to 6 GHz NO-IR
*/
static int hostapd_is_usable_chans(struct hostapd_iface *iface)
int hostapd_is_usable_chans(struct hostapd_iface *iface)
{
int secondary_freq;
int secondary_freq, new_sec;
enum hostapd_chan_width_attr bw_flag;
struct hostapd_channel_data *pri_chan;
int err, err2;
int err, err2, central, oper_chwidth;
if (!iface->current_mode)
return 0;
@@ -1025,11 +1178,6 @@ static int hostapd_is_usable_chans(struct hostapd_iface *iface)
return 0;
}
err = hostapd_is_usable_chan(iface, pri_chan->freq, 1);
if (err <= 0) {
wpa_printf(MSG_ERROR, "Primary frequency not allowed");
return err;
}
err = hostapd_is_usable_edmg(iface);
if (err <= 0)
return err;
@@ -1037,6 +1185,24 @@ static int hostapd_is_usable_chans(struct hostapd_iface *iface)
if (!hostapd_is_usable_punct_bitmap(iface))
return 0;
oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
/*
* The central channel is not filled in acs_adjust_center_freq() after
* ACS of 80+80 MHz. In that case we only check the primary 40 MHz.
*/
central = hostapd_get_oper_centr_freq_seg0_idx(iface->conf);
if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
oper_chwidth != CONF_OPER_CHWIDTH_USE_HT && central)
return hostapd_is_usable_chan_seg(iface);
err = hostapd_is_usable_chan(iface, pri_chan->freq, 1);
if (err <= 0) {
wpa_printf(MSG_ERROR, "Primary frequency not allowed");
return err;
}
if (!iface->conf->secondary_channel)
return 1;
@@ -1053,18 +1219,19 @@ static int hostapd_is_usable_chans(struct hostapd_iface *iface)
if (!iface->conf->ht40_plus_minus_allowed)
return err;
/* Both HT40+ and HT40- are set, pick a valid secondary channel */
secondary_freq = iface->freq + 20;
err2 = hostapd_is_usable_chan(iface, secondary_freq, 0);
if (err2 > 0 && (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P)) {
iface->conf->secondary_channel = 1;
return 1;
}
/* Both HT40+ and HT40- are set, check the swapped pri/sec channel
* option for a 40 MHz channel */
new_sec = -iface->conf->secondary_channel;
bw_flag = new_sec == 1 ?
HOSTAPD_CHAN_WIDTH_40P : HOSTAPD_CHAN_WIDTH_40M;
secondary_freq = iface->freq - 20;
secondary_freq = iface->freq + new_sec * 20;
err2 = hostapd_is_usable_chan(iface, secondary_freq, 0);
if (err2 > 0 && (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40M)) {
iface->conf->secondary_channel = -1;
if (err2 <= 0)
return err;
if (pri_chan->allowed_bw & bw_flag) {
iface->conf->secondary_channel = new_sec;
return 1;
}
@@ -1391,3 +1558,34 @@ int hostapd_hw_skip_mode(struct hostapd_iface *iface,
}
return 0;
}
void hostapd_free_multi_hw_info(struct hostapd_multi_hw_info *multi_hw_info)
{
os_free(multi_hw_info);
}
int hostapd_set_current_hw_info(struct hostapd_iface *iface, int oper_freq)
{
struct hostapd_multi_hw_info *hw_info;
unsigned int i;
if (!iface->num_multi_hws)
return 0;
for (i = 0; i < iface->num_multi_hws; i++) {
hw_info = &iface->multi_hw_info[i];
if (hw_info->start_freq <= oper_freq &&
hw_info->end_freq >= oper_freq) {
iface->current_hw_info = hw_info;
wpa_printf(MSG_DEBUG,
"Mode: Selected underlying hardware: hw_idx=%u",
iface->current_hw_info->hw_idx);
return 0;
}
}
return -1;
}
+20 -2
View File
@@ -24,12 +24,15 @@ int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq);
int hostapd_check_ht_capab(struct hostapd_iface *iface);
int hostapd_check_edmg_capab(struct hostapd_iface *iface);
int hostapd_check_he_6ghz_capab(struct hostapd_iface *iface);
int hostapd_prepare_rates(struct hostapd_iface *iface,
int hostapd_prepare_rates(struct hostapd_data *hapd,
struct hostapd_hw_modes *mode);
void hostapd_stop_setup_timers(struct hostapd_iface *iface);
int hostapd_hw_skip_mode(struct hostapd_iface *iface,
struct hostapd_hw_modes *mode);
int hostapd_determine_mode(struct hostapd_iface *iface);
void hostapd_free_multi_hw_info(struct hostapd_multi_hw_info *multi_hw_info);
int hostapd_set_current_hw_info(struct hostapd_iface *iface, int oper_freq);
int hostapd_is_usable_chans(struct hostapd_iface *iface);
#else /* NEED_AP_MLME */
static inline void
hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
@@ -77,7 +80,7 @@ static inline int hostapd_check_edmg_capab(struct hostapd_iface *iface)
return 0;
}
static inline int hostapd_prepare_rates(struct hostapd_iface *iface,
static inline int hostapd_prepare_rates(struct hostapd_data *hapd,
struct hostapd_hw_modes *mode)
{
return 0;
@@ -103,6 +106,21 @@ static inline int hostapd_determine_mode(struct hostapd_iface *iface)
return 0;
}
static inline
void hostapd_free_multi_hw_info(struct hostapd_multi_hw_info *multi_hw_info)
{
}
static inline int hostapd_set_current_hw_info(struct hostapd_iface *iface,
u32 oper_freq)
{
return 0;
}
static inline int hostapd_is_usable_chans(struct hostapd_iface *iface)
{
return 1;
}
#endif /* NEED_AP_MLME */
#endif /* HW_FEATURES_H */
File diff suppressed because it is too large. Load diff
+74 -4
View File
@@ -9,6 +9,8 @@
#ifndef IEEE802_11_H
#define IEEE802_11_H
#include "utils/list.h"
struct hostapd_iface;
struct hostapd_data;
struct sta_info;
@@ -24,6 +26,36 @@ struct sae_pk;
struct sae_pt;
struct sae_password_entry;
struct mld_info;
struct mld_link_info;
struct rsn_pmksa_cache_entry;
enum link_parse_type {
LINK_PARSE_ASSOC,
LINK_PARSE_REASSOC,
LINK_PARSE_RECONF,
};
#define LINK_RECONF_GROUP_KDE_MAX_LEN 255
struct link_reconf_req_info {
struct dl_list list;
u16 status;
u8 link_id;
u8 local_addr[ETH_ALEN];
u8 peer_addr[ETH_ALEN];
size_t sta_prof_len;
u8 sta_prof[];
};
struct link_reconf_req_list {
u8 sta_mld_addr[ETH_ALEN];
u8 dialog_token;
u16 links_add_ok;
u16 links_del_ok;
u16 new_valid_links;
struct dl_list del_req; /* list of struct link_reconf_req_info */
struct dl_list add_req; /* list of struct link_reconf_req_info */
};
int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
struct hostapd_frame_info *fi);
@@ -63,7 +95,7 @@ u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid, u32 nsts);
u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_vendor_vht(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_chsw_wrapper(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
enum ieee80211_op_mode opmode);
@@ -94,6 +126,12 @@ u8 * hostapd_eid_eht_ml_beacon(struct hostapd_data *hapd,
u8 *eid, bool include_mld_id);
u8 * hostapd_eid_eht_ml_assoc(struct hostapd_data *hapd, struct sta_info *info,
u8 *eid);
u8 * hostapd_eid_eht_basic_ml_common(struct hostapd_data *hapd,
u8 *eid, struct mld_info *mld_info,
bool include_mld_id, bool include_bpcc);
size_t hostapd_eid_eht_basic_ml_len(struct hostapd_data *hapd,
struct sta_info *info,
bool include_mld_id, bool include_pbcc);
size_t hostapd_eid_eht_ml_beacon_len(struct hostapd_data *hapd,
struct mld_info *info,
bool include_mld_id);
@@ -130,6 +168,8 @@ u16 copy_sta_he_6ghz_capab(struct hostapd_data *hapd, struct sta_info *sta,
int hostapd_get_he_twt_responder(struct hostapd_data *hapd,
enum ieee80211_op_mode mode);
bool hostapd_get_ht_vht_twt_responder(struct hostapd_data *hapd);
void hostapd_wfa_capab(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *pos, const u8 *end);
u8 * hostapd_eid_cca(struct hostapd_data *hapd, u8 *eid);
void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
const u8 *buf, size_t len, int ack);
@@ -250,9 +290,12 @@ u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
u8 **elem_offset,
const u8 *known_bss, size_t known_bss_len, u8 *rnr_eid,
u8 *rnr_count, u8 **rnr_offset, size_t rnr_len);
bool hostapd_is_mld_ap(struct hostapd_data *hapd);
bool hostapd_is_multiple_link_mld(struct hostapd_data *hapd);
int sae_password_bind(struct hostapd_data *hapd, const u8 *addr,
const char *password);
const char * sae_get_password(struct hostapd_data *hapd,
struct sta_info *sta, const char *rx_id,
struct sta_info *sta, const u8 *rx_id,
size_t rx_id_len,
struct sae_password_entry **pw_entry,
struct sae_pt **s_pt, const struct sae_pk **s_pk);
struct sta_info * hostapd_ml_get_assoc_sta(struct hostapd_data *hapd,
@@ -262,6 +305,33 @@ int hostapd_process_assoc_ml_info(struct hostapd_data *hapd,
struct sta_info *sta,
const u8 *ies, size_t ies_len,
bool reassoc, int tx_link_status,
bool offload);
bool offload,
bool *set_beacon);
void ml_deinit_link_reconf_req(struct link_reconf_req_list **req_list_ptr);
int ieee80211_ml_process_link(struct hostapd_data *hapd,
struct sta_info *origin_sta,
struct mld_link_info *link,
const u8 *ies, size_t ies_len,
enum link_parse_type type, bool offload,
bool *set_beacon);
void ieee80211_ml_build_assoc_resp(struct hostapd_data *hapd,
struct mld_link_info *link);
void ieee802_11_rx_protected_eht_action(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt,
size_t len);
void hostapd_link_reconf_resp_tx_status(struct hostapd_data *hapd,
struct sta_info *sta,
const struct ieee80211_mgmt *mgmt,
size_t len, int ok);
size_t hostapd_eid_eht_ml_tid_to_link_map_len(struct hostapd_data *hapd);
u8 * hostapd_eid_eht_ml_tid_to_link_map(struct hostapd_data *hapd, u8 *eid);
void ieee80211_send_eap_req(struct hostapd_data *hapd, struct sta_info *sta,
u8 type, u16 auth_transaction, u16 status,
struct rsn_pmksa_cache_entry *cached_pmk,
const u8 *eap_req, size_t eap_req_len);
#endif /* IEEE802_11_H */
File diff suppressed because it is too large. Load diff
+32 -43
View File
@@ -2,6 +2,7 @@
* hostapd / IEEE 802.11ax HE
* Copyright (c) 2016-2017, Qualcomm Atheros, Inc.
* Copyright (c) 2019 John Crispin <john@phrozen.org>
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -70,7 +71,8 @@ static int ieee80211_invalid_he_cap_size(const u8 *buf, size_t len)
u8 ppe_thres_hdr;
cap = (struct ieee80211_he_capabilities *) buf;
cap_len = sizeof(*cap) - sizeof(cap->optional);
cap_len = sizeof(cap->he_mac_capab_info) +
sizeof(cap->he_phy_capab_info);
if (len < cap_len)
return 1;
@@ -91,37 +93,21 @@ u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
{
struct ieee80211_he_capabilities *cap;
struct hostapd_hw_modes *mode = hapd->iface->current_mode;
u8 he_oper_chwidth = ~HE_PHYCAP_CHANNEL_WIDTH_MASK;
const struct he_capabilities *he_capab;
u8 *pos = eid;
u8 ie_size = 0, mcs_nss_size = 4, ppet_size = 0;
u8 ie_size = 0, mcs_nss_size, ppet_size;
u8 *epos;
if (!mode)
return eid;
ie_size = sizeof(*cap) - sizeof(cap->optional);
ppet_size = ieee80211_he_ppet_size(mode->he_capab[opmode].ppet[0],
mode->he_capab[opmode].phy_cap);
he_capab = &mode->he_capab[opmode];
switch (hapd->iface->conf->he_oper_chwidth) {
case CONF_OPER_CHWIDTH_80P80MHZ:
he_oper_chwidth |=
HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G;
mcs_nss_size += 4;
/* fall through */
case CONF_OPER_CHWIDTH_160MHZ:
he_oper_chwidth |= HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
mcs_nss_size += 4;
/* fall through */
case CONF_OPER_CHWIDTH_80MHZ:
case CONF_OPER_CHWIDTH_USE_HT:
he_oper_chwidth |= HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G;
break;
default:
break;
}
mcs_nss_size = ieee80211_he_mcs_set_size(he_capab->phy_cap);
ppet_size = ieee80211_he_ppet_size(he_capab->ppet[0],
he_capab->phy_cap);
ie_size += mcs_nss_size + ppet_size;
ie_size = IEEE80211_HE_CAPAB_MIN_LEN + mcs_nss_size + ppet_size;
*pos++ = WLAN_EID_EXTENSION;
*pos++ = 1 + ie_size;
@@ -130,14 +116,16 @@ u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
cap = (struct ieee80211_he_capabilities *) pos;
os_memset(cap, 0, sizeof(*cap));
os_memcpy(cap->he_mac_capab_info, mode->he_capab[opmode].mac_cap,
os_memcpy(cap->he_mac_capab_info, he_capab->mac_cap,
HE_MAX_MAC_CAPAB_SIZE);
os_memcpy(cap->he_phy_capab_info, mode->he_capab[opmode].phy_cap,
os_memcpy(cap->he_phy_capab_info, he_capab->phy_cap,
HE_MAX_PHY_CAPAB_SIZE);
os_memcpy(cap->optional, mode->he_capab[opmode].mcs, mcs_nss_size);
epos = (u8 *) &cap->he_basic_supported_mcs_set;
os_memcpy(epos, he_capab->mcs, mcs_nss_size);
epos += mcs_nss_size;
if (ppet_size)
os_memcpy(&cap->optional[mcs_nss_size],
mode->he_capab[opmode].ppet, ppet_size);
os_memcpy(epos, he_capab->ppet, ppet_size);
if (hapd->iface->conf->he_phy_capab.he_su_beamformer)
cap->he_phy_capab_info[HE_PHYCAP_SU_BEAMFORMER_CAPAB_IDX] |=
@@ -160,9 +148,6 @@ u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
cap->he_phy_capab_info[HE_PHYCAP_MU_BEAMFORMER_CAPAB_IDX] &=
~HE_PHYCAP_MU_BEAMFORMER_CAPAB;
cap->he_phy_capab_info[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &=
he_oper_chwidth;
pos += ie_size;
return pos;
@@ -221,7 +206,7 @@ u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid)
if (is_6ghz_op_class(hapd->iconf->op_class)) {
enum oper_chan_width oper_chwidth =
hostapd_get_oper_chwidth(hapd->iconf);
hapd->iconf->he_oper_chwidth;
u8 seg0 = hapd->iconf->he_oper_centr_freq_seg0_idx;
u8 seg1 = hostapd_get_oper_centr_freq_seg1_idx(hapd->iconf);
u8 control;
@@ -229,6 +214,9 @@ u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid)
u16 punct_bitmap = hostapd_get_punct_bitmap(hapd);
if (punct_bitmap) {
oper_chwidth = hostapd_get_oper_chwidth(hapd->iconf);
seg0 = hostapd_get_oper_centr_freq_seg0_idx(
hapd->iconf);
punct_update_legacy_bw(punct_bitmap,
hapd->iconf->channel,
&oper_chwidth, &seg0, &seg1);
@@ -427,14 +415,15 @@ 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;
const u16 *ap_mcs_set;
const u8 *sta_mcs_set;
int i;
if (!hapd->iface->current_mode)
return 1;
ap_mcs_set = (u16 *) hapd->iface->current_mode->he_capab[opmode].mcs;
sta_mcs_set = (u16 *) ((const struct ieee80211_he_capabilities *)
sta_he_capab)->optional;
sta_mcs_set = (const u8 *) &((const struct ieee80211_he_capabilities *)
sta_he_capab)->he_basic_supported_mcs_set;
/*
* Disable HE capabilities for STAs for which there is not even a single
@@ -458,7 +447,7 @@ static int check_valid_he_mcs(struct hostapd_data *hapd, const u8 *sta_he_capab,
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]);
sta_rx_mcs_set = WPA_GET_LE16(&sta_mcs_set[i * 4]);
ap_tx_mcs_set = WPA_GET_LE16((const u8 *)
&ap_mcs_set[(i * 2) + 1]);
@@ -485,7 +474,7 @@ u16 copy_sta_he_capab(struct hostapd_data *hapd, struct sta_info *sta,
size_t he_capab_len)
{
if (!he_capab || !(sta->flags & WLAN_STA_WMM) ||
!hapd->iconf->ieee80211ax || hapd->conf->disable_11ax ||
!hostapd_is_he_enabled(hapd) ||
!check_valid_he_mcs(hapd, he_capab, opmode) ||
ieee80211_invalid_he_cap_size(he_capab, he_capab_len) ||
he_capab_len > sizeof(struct ieee80211_he_capabilities)) {
@@ -514,9 +503,9 @@ u16 copy_sta_he_capab(struct hostapd_data *hapd, struct sta_info *sta,
u16 copy_sta_he_6ghz_capab(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *he_6ghz_capab)
{
if (!he_6ghz_capab || !hapd->iconf->ieee80211ax ||
hapd->conf->disable_11ax ||
!is_6ghz_op_class(hapd->iconf->op_class)) {
if (!he_6ghz_capab || !hostapd_is_he_enabled(hapd) ||
!is_6ghz_op_class(hapd->iconf->op_class) ||
!(sta->flags & WLAN_STA_HE)) {
sta->flags &= ~WLAN_STA_6GHZ;
os_free(sta->he_6ghz_capab);
sta->he_6ghz_capab = NULL;
@@ -545,7 +534,7 @@ int hostapd_get_he_twt_responder(struct hostapd_data *hapd,
if (!hapd->iface->current_mode ||
!hapd->iface->current_mode->he_capab[mode].he_supported ||
!hapd->iconf->ieee80211ax || hapd->conf->disable_11ax)
!hostapd_is_he_enabled(hapd))
return 0;
mac_cap = hapd->iface->current_mode->he_capab[mode].mac_cap;
+51 -10
View File
@@ -26,8 +26,8 @@ u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid)
struct ieee80211_ht_capabilities *cap;
u8 *pos = eid;
if (!hapd->iconf->ieee80211n || !hapd->iface->current_mode ||
hapd->conf->disable_11n || is_6ghz_op_class(hapd->iconf->op_class))
if (!hostapd_is_ht_enabled(hapd) || !hapd->iface->current_mode ||
is_6ghz_op_class(hapd->iconf->op_class))
return eid;
*pos++ = WLAN_EID_HT_CAP;
@@ -79,12 +79,57 @@ u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid)
}
static void set_ht_param(struct hostapd_data *hapd,
struct ieee80211_ht_operation *oper)
{
int secondary_channel = hapd->iconf->secondary_channel;
#ifdef CONFIG_IEEE80211BE
enum oper_chan_width chwidth = hostapd_get_oper_chwidth(hapd->iconf);
u16 bw = 0, punct_bitmap = hostapd_get_punct_bitmap(hapd);
u8 offset, chan_bit_pos;
switch (chwidth) {
case CONF_OPER_CHWIDTH_80MHZ:
bw = 80;
offset = 6;
break;
case CONF_OPER_CHWIDTH_160MHZ:
bw = 160;
offset = 14;
break;
case CONF_OPER_CHWIDTH_320MHZ:
bw = 320;
offset = 30;
break;
default:
goto no_update;
}
chan_bit_pos = (hapd->iconf->channel -
hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf) +
offset) / 4;
/* Check if secondary channel is punctured */
if (bw >= 80 && punct_bitmap && secondary_channel &&
(punct_bitmap & BIT(chan_bit_pos + secondary_channel)))
return; /* Do not indicate punctured secondary channel for HT */
no_update:
#endif /* CONFIG_IEEE80211BE */
if (secondary_channel == 1)
oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE |
HT_INFO_HT_PARAM_STA_CHNL_WIDTH;
if (secondary_channel == -1)
oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW |
HT_INFO_HT_PARAM_STA_CHNL_WIDTH;
}
u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid)
{
struct ieee80211_ht_operation *oper;
u8 *pos = eid;
if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n ||
if (!hostapd_is_ht_enabled(hapd) ||
is_6ghz_op_class(hapd->iconf->op_class))
return eid;
@@ -96,12 +141,7 @@ u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid)
oper->primary_chan = hapd->iconf->channel;
oper->operation_mode = host_to_le16(hapd->iface->ht_op_mode);
if (hapd->iconf->secondary_channel == 1)
oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE |
HT_INFO_HT_PARAM_STA_CHNL_WIDTH;
if (hapd->iconf->secondary_channel == -1)
oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW |
HT_INFO_HT_PARAM_STA_CHNL_WIDTH;
set_ht_param(hapd, oper);
pos += sizeof(*oper);
@@ -363,7 +403,7 @@ u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
* frame.
*/
if (!ht_capab || !(sta->flags & WLAN_STA_WMM) ||
!hapd->iconf->ieee80211n || hapd->conf->disable_11n) {
!hostapd_is_ht_enabled(hapd)) {
sta->flags &= ~WLAN_STA_HT;
os_free(sta->ht_capabilities);
sta->ht_capabilities = NULL;
@@ -417,6 +457,7 @@ void ht40_intolerant_remove(struct hostapd_iface *iface, struct sta_info *sta)
iface->num_sta_ht40_intolerant--;
if (iface->num_sta_ht40_intolerant == 0 &&
iface->conf->obss_interval &&
(iface->conf->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) &&
(iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX)) {
unsigned int delay_time = OVERLAPPING_BSS_TRANS_DELAY_FACTOR *
+97 -8
View File
@@ -381,6 +381,10 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx,
/* Bit 13 - Collocated Interference Reporting */
*pos |= 0x20;
}
if (hapd->iface->conf->civic)
*pos |= 0x40; /* Bit 14 - Civic Location */
if (hapd->iface->conf->lci)
*pos |= 0x80; /* Bit 15 - Geospatial Location */
break;
case 2: /* Bits 16-23 */
if (hapd->conf->wnm_sleep_mode)
@@ -476,6 +480,19 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx,
*pos |= 0x01; /* Bit 88 - SAE PK Exclusively */
#endif /* CONFIG_SAE_PK */
break;
case 12: /* Bits 96-103 */
if (hapd->iconf->i2r_lmr_policy)
*pos |= 0x02; /* Bit 97 - I2R LMR Feedback Policy */
if (hapd->iconf->peer_to_peer_twt)
*pos |= 0x10; /* Bit 100 - Peer to Peer TWT */
if (hapd->conf->known_sta_identification)
*pos |= 0x40; /* Bit 102 - Known STA Identification
* Enabled */
break;
case 13: /* Bits 104-111 */
if (hapd->iconf->channel_usage)
*pos |= 0x01; /* Bit 104 - Channel Usage support */
break;
}
}
@@ -1034,7 +1051,8 @@ int get_tx_parameters(struct sta_info *sta, int ap_max_chanwidth,
int requested_bw;
if (sta->ht_capabilities)
ht_40mhz = !!(sta->ht_capabilities->ht_capabilities_info &
ht_40mhz = !!(le_to_host16(sta->ht_capabilities->
ht_capabilities_info) &
HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET);
if (sta->vht_operation) {
@@ -1070,9 +1088,9 @@ int get_tx_parameters(struct sta_info *sta, int ap_max_chanwidth,
* normal clients), use it to determine the supported channel
* bandwidth.
*/
vht_chanwidth = capab->vht_capabilities_info &
vht_chanwidth = le_to_host32(capab->vht_capabilities_info) &
VHT_CAP_SUPP_CHAN_WIDTH_MASK;
vht_80p80 = capab->vht_capabilities_info &
vht_80p80 = le_to_host32(capab->vht_capabilities_info) &
VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
/* TODO: Also take into account Extended NSS BW Support field */
@@ -1097,7 +1115,7 @@ u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len)
{
u8 *pos = eid;
bool sae_pk = false;
u32 capab = 0, tmp;
u64 capab = 0, tmp;
size_t flen;
if (!(hapd->conf->wpa & WPA_PROTO_RSN))
@@ -1124,10 +1142,37 @@ u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len)
capab |= BIT(WLAN_RSNX_CAPAB_SECURE_LTF);
if (hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_RTT_AP)
capab |= BIT(WLAN_RSNX_CAPAB_SECURE_RTT);
if (hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_PROT_RANGE_NEG_AP)
capab |= BIT(WLAN_RSNX_CAPAB_URNM_MFPR);
if (hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_PROT_RANGE_NEG_AP) {
if (hapd->conf->urnm_mfpr != 0)
capab |= BIT(WLAN_RSNX_CAPAB_URNM_MFPR);
if (hapd->conf->urnm_mfpr_x20 == 1)
capab |= BIT(WLAN_RSNX_CAPAB_URNM_MFPR_X20);
}
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);
#ifdef CONFIG_ENC_ASSOC
/* Per IEEE 802.11bi/D4.0, 12.16.7 (PMKSA caching privacy)
* a STA that sets the PMKSA Caching Privacy Support
* field in the RSNXE to 1 shall set the (Re)Association
* Frame Encryption Support field in the RSNXE to 1.
*/
if ((hapd->iface->drv_flags2 &
WPA_DRIVER_FLAGS2_ASSOCIATION_FRAME_ENCRYPTION) &&
(hapd->conf->assoc_frame_encryption ||
hapd->conf->pmksa_caching_privacy))
capab |= BIT(WLAN_RSNX_CAPAB_ASSOC_FRAME_ENCRYPTION);
if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_EPPKE)
capab |= BIT(WLAN_RSNX_CAPAB_KEK_IN_PASN);
if (hapd->conf->pmksa_caching_privacy)
capab |= BIT(WLAN_RSNX_CAPAB_PMKSA_CACHING_PRIVACY);
if (hapd->conf->eap_using_authentication_frames)
capab |= BIT(WLAN_RSNX_CAPAB_802_1X_IN_AUTH_FRAMES);
if (hapd->conf->eppke_unauth)
capab |= BIT_ULL(WLAN_RSNX_CAPAB_UNAUTH_EPPKE);
#endif /* CONFIG_ENC_ASSOC */
if (!capab)
return eid; /* no supported extended RSN capabilities */
@@ -1221,8 +1266,52 @@ struct sta_info * hostapd_ml_get_assoc_sta(struct hostapd_data *hapd,
bool hostapd_get_ht_vht_twt_responder(struct hostapd_data *hapd)
{
return hapd->iconf->ht_vht_twt_responder &&
((hapd->iconf->ieee80211n && !hapd->conf->disable_11n) ||
(hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac)) &&
(hostapd_is_ht_enabled(hapd) ||
hostapd_is_vht_enabled(hapd)) &&
(hapd->iface->drv_flags2 &
WPA_DRIVER_FLAGS2_HT_VHT_TWT_RESPONDER);
}
static void hostapd_wfa_gen_capab(struct hostapd_data *hapd,
struct sta_info *sta,
const u8 *capab, size_t len)
{
char *hex;
size_t buflen;
wpa_printf(MSG_DEBUG,
"WFA: Received indication of generational capabilities from "
MACSTR, MAC2STR(sta->addr));
wpa_hexdump(MSG_DEBUG, "WFA: Generational Capabilities", capab, len);
buflen = 2 * len + 1;
hex = os_zalloc(buflen);
if (!hex)
return;
wpa_snprintf_hex(hex, buflen, capab, len);
wpa_msg(hapd->msg_ctx, MSG_INFO, WFA_GEN_CAPAB_RX MACSTR " %s",
MAC2STR(sta->addr), hex);
os_free(hex);
}
void hostapd_wfa_capab(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *pos, const u8 *end)
{
u8 capab_len;
const u8 *gen_capa;
if (end - pos < 1)
return;
capab_len = *pos++;
if (capab_len > end - pos)
return;
pos += capab_len; /* skip the Capabilities field */
/* Wi-Fi Alliance Capabilities attributes use a header that is similar
* to the one used in Information Elements. */
gen_capa = get_ie(pos, end - pos, WFA_CAPA_ATTR_GENERATIONAL_CAPAB);
if (gen_capa)
hostapd_wfa_gen_capab(hapd, sta, gen_capa + 2, gen_capa[1]);
}
+31 -18
View File
@@ -21,6 +21,24 @@
#include "dfs.h"
static struct hostapd_hw_modes *
mode_for_vht_capab(struct hostapd_data *hapd, struct hostapd_hw_modes *mode)
{
if (mode->mode == HOSTAPD_MODE_IEEE80211G && hapd->conf->vendor_vht &&
mode->vht_capab == 0 && hapd->iface->hw_features) {
int i;
for (i = 0; i < hapd->iface->num_hw_features; i++) {
if (hapd->iface->hw_features[i].mode ==
HOSTAPD_MODE_IEEE80211A)
return &hapd->iface->hw_features[i];
}
}
return mode;
}
u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid, u32 nsts)
{
struct ieee80211_vht_capabilities *cap;
@@ -30,18 +48,7 @@ u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid, u32 nsts)
if (!mode || is_6ghz_op_class(hapd->iconf->op_class))
return eid;
if (mode->mode == HOSTAPD_MODE_IEEE80211G && hapd->conf->vendor_vht &&
mode->vht_capab == 0 && hapd->iface->hw_features) {
int i;
for (i = 0; i < hapd->iface->num_hw_features; i++) {
if (hapd->iface->hw_features[i].mode ==
HOSTAPD_MODE_IEEE80211A) {
mode = &hapd->iface->hw_features[i];
break;
}
}
}
mode = mode_for_vht_capab(hapd, mode);
*pos++ = WLAN_EID_VHT_CAP;
*pos++ = sizeof(*cap);
@@ -95,6 +102,9 @@ u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid)
#ifdef CONFIG_IEEE80211BE
if (punct_bitmap) {
oper_chwidth = hostapd_get_oper_chwidth(hapd->iconf);
seg0 = hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf);
seg1 = hostapd_get_oper_centr_freq_seg1_idx(hapd->iconf);
punct_update_legacy_bw(punct_bitmap,
hapd->iconf->channel,
&oper_chwidth, &seg0, &seg1);
@@ -140,9 +150,10 @@ u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid)
}
static int check_valid_vht_mcs(struct hostapd_hw_modes *mode,
static int check_valid_vht_mcs(struct hostapd_data *hapd,
const u8 *sta_vht_capab)
{
struct hostapd_hw_modes *mode = hapd->iface->current_mode;
const struct ieee80211_vht_capabilities *vht_cap;
struct ieee80211_vht_capabilities ap_vht_cap;
u16 sta_rx_mcs_set, ap_tx_mcs_set;
@@ -150,6 +161,7 @@ static int check_valid_vht_mcs(struct hostapd_hw_modes *mode,
if (!mode)
return 1;
mode = mode_for_vht_capab(hapd, mode);
/*
* Disable VHT caps for STAs for which there is not even a single
@@ -166,10 +178,10 @@ static int check_valid_vht_mcs(struct hostapd_hw_modes *mode,
ap_tx_mcs_set = le_to_host16(ap_vht_cap.vht_supported_mcs_set.tx_map);
for (i = 0; i < VHT_RX_NSS_MAX_STREAMS; i++) {
if ((ap_tx_mcs_set & (0x3 << (i * 2))) == 3)
if (((ap_tx_mcs_set >> (i * 2)) & 0x3) == 3)
continue;
if ((sta_rx_mcs_set & (0x3 << (i * 2))) == 3)
if (((sta_rx_mcs_set >> (i * 2)) & 0x3) == 3)
continue;
return 1;
@@ -186,8 +198,9 @@ u16 copy_sta_vht_capab(struct hostapd_data *hapd, struct sta_info *sta,
{
/* Disable VHT caps for STAs associated to no-VHT BSSes. */
if (!vht_capab || !(sta->flags & WLAN_STA_WMM) ||
!hapd->iconf->ieee80211ac || hapd->conf->disable_11ac ||
!check_valid_vht_mcs(hapd->iface->current_mode, vht_capab)) {
!hostapd_is_vht_enabled(hapd) ||
!check_valid_vht_mcs(hapd, vht_capab) ||
!(sta->flags & WLAN_STA_HT)) {
sta->flags &= ~WLAN_STA_VHT;
os_free(sta->vht_capabilities);
sta->vht_capabilities = NULL;
@@ -212,7 +225,7 @@ u16 copy_sta_vht_capab(struct hostapd_data *hapd, struct sta_info *sta,
u16 copy_sta_vht_oper(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *vht_oper)
{
if (!vht_oper) {
if (!vht_oper || !(sta->flags & WLAN_STA_VHT)) {
os_free(sta->vht_operation);
sta->vht_operation = NULL;
return WLAN_STATUS_SUCCESS;
+102 -94
View File
@@ -45,7 +45,7 @@ static void ieee802_1x_wnm_notif_send(void *eloop_ctx, void *timeout_ctx);
#endif /* CONFIG_HS20 */
static bool ieee802_1x_finished(struct hostapd_data *hapd,
struct sta_info *sta, int success,
int remediation, bool logoff);
bool logoff);
static void ieee802_1x_send(struct hostapd_data *hapd, struct sta_info *sta,
@@ -149,9 +149,9 @@ static void ieee802_1x_ml_set_sta_authorized(struct hostapd_data *hapd,
bool authorized)
{
#ifdef CONFIG_IEEE80211BE
unsigned int i, link_id;
unsigned int i;
if (!hostapd_is_mld_ap(hapd))
if (!hostapd_is_multiple_link_mld(hapd))
return;
/*
@@ -161,32 +161,35 @@ static void ieee802_1x_ml_set_sta_authorized(struct hostapd_data *hapd,
if (authorized && hapd->mld_link_id != sta->mld_assoc_link_id)
return;
for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
struct mld_link_info *link = &sta->mld_info.links[link_id];
for (i = 0; i < hapd->iface->interfaces->count; i++) {
struct sta_info *tmp_sta;
struct mld_link_info *link;
struct hostapd_data *tmp_hapd =
hapd->iface->interfaces->iface[i]->bss[0];
if (!hostapd_is_ml_partner(hapd, tmp_hapd))
continue;
link = &sta->mld_info.links[tmp_hapd->mld_link_id];
if (!link->valid)
continue;
for (i = 0; i < hapd->iface->interfaces->count; i++) {
struct sta_info *tmp_sta;
struct hostapd_data *tmp_hapd =
hapd->iface->interfaces->iface[i]->bss[0];
if (!hostapd_is_ml_partner(hapd, tmp_hapd))
for (tmp_sta = tmp_hapd->sta_list; tmp_sta;
tmp_sta = tmp_sta->next) {
if (tmp_sta == sta ||
tmp_sta->mld_assoc_link_id !=
sta->mld_assoc_link_id ||
tmp_sta->aid != sta->aid)
continue;
for (tmp_sta = tmp_hapd->sta_list; tmp_sta;
tmp_sta = tmp_sta->next) {
if (tmp_sta == sta ||
tmp_sta->mld_assoc_link_id !=
sta->mld_assoc_link_id ||
tmp_sta->aid != sta->aid)
continue;
if (!ether_addr_equal(
tmp_sta->mld_info.common_info.mld_addr,
sta->mld_info.common_info.mld_addr))
continue;
ieee802_1x_set_authorized(tmp_hapd, tmp_sta,
authorized, true);
break;
}
ieee802_1x_set_authorized(tmp_hapd, tmp_sta,
authorized, true);
break;
}
}
#endif /* CONFIG_IEEE80211BE */
@@ -453,8 +456,7 @@ static int add_common_radius_sta_attr_rsn(struct hostapd_data *hapd,
return -1;
}
suite = wpa_cipher_to_suite(((hapd->conf->wpa & 0x2) ||
hapd->conf->osen) ?
suite = wpa_cipher_to_suite(((hapd->conf->wpa & 0x2)) ?
WPA_PROTO_RSN : WPA_PROTO_WPA,
hapd->conf->wpa_group);
if (!hostapd_config_get_radius_attr(req_attr,
@@ -583,7 +585,7 @@ static int add_common_radius_sta_attr(struct hostapd_data *hapd,
}
#endif /* CONFIG_IEEE80211R_AP */
if ((hapd->conf->wpa || hapd->conf->osen) && sta->wpa_sm &&
if (hapd->conf->wpa && sta->wpa_sm &&
add_common_radius_sta_attr_rsn(hapd, req_attr, sta, msg) < 0)
return -1;
@@ -1125,7 +1127,7 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
struct rsn_pmksa_cache_entry *pmksa;
int key_mgmt;
if (!hapd->conf->ieee802_1x && !hapd->conf->wpa && !hapd->conf->osen &&
if (!hapd->conf->ieee802_1x && !hapd->conf->wpa &&
!hapd->conf->wps_state)
return;
@@ -1134,6 +1136,9 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
(unsigned long) len, MAC2STR(sa), encrypted);
sta = ap_get_sta(hapd, sa);
if (!sta || (!(sta->flags & (WLAN_STA_ASSOC | WLAN_STA_PREAUTH)) &&
#ifdef CONFIG_IEEE8021X_AUTH
!sta->epp_sta &&
#endif /* CONFIG_IEEE8021X_AUTH */
!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_WIRED))) {
wpa_printf(MSG_DEBUG,
"IEEE 802.1X data frame from not associated/Pre-authenticating STA");
@@ -1185,7 +1190,7 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
return;
}
if (!hapd->conf->ieee802_1x && !hapd->conf->osen &&
if (!hapd->conf->ieee802_1x &&
!(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) {
wpa_printf(MSG_DEBUG,
"IEEE 802.1X: Ignore EAPOL message - 802.1X not enabled and WPS not used");
@@ -1252,6 +1257,29 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
HOSTAPD_LEVEL_DEBUG,
"received EAPOL-Start from STA");
#ifdef CONFIG_IEEE80211R_AP
if (hapd->conf->wpa &&
wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt) && sta->wpa_sm &&
((wpa_key_mgmt_ft(wpa_auth_sta_key_mgmt(sta->wpa_sm)) &&
(sta->flags & WLAN_STA_AUTHORIZED)) ||
sta->auth_alg == WLAN_AUTH_FT)) {
/* When FT is used, reauthentication to generate a new
* PMK-R0 would be complicated since the current AP
* might not be the one with which the currently used
* PMK-R0 was generated. IEEE Std 802.11-2020, 13.4.2
* (FT initial mobility domain association in an RSN)
* mandates STA to perform a new FT initial mobility
* domain association whenever its Supplicant would
* trigger sending of an EAPOL-Start frame. As such,
* this EAPOL-Start frame should not have been sent.
* Discard it to avoid unexpected behavior. */
hostapd_logger(hapd, sta->addr,
HOSTAPD_MODULE_IEEE8021X,
HOSTAPD_LEVEL_DEBUG,
"discard unexpected EAPOL-Start from STA that uses FT");
break;
}
#endif /* CONFIG_IEEE80211R_AP */
sta->eapol_sm->flags &= ~EAPOL_SM_WAIT_START;
pmksa = wpa_auth_sta_get_pmksa(sta->wpa_sm);
if (pmksa) {
@@ -1337,7 +1365,7 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
}
#endif /* CONFIG_WPS */
if (!force_1x && !hapd->conf->ieee802_1x && !hapd->conf->osen) {
if (!force_1x && !hapd->conf->ieee802_1x) {
wpa_printf(MSG_DEBUG,
"IEEE 802.1X: Ignore STA - 802.1X not enabled or forced for WPS");
/*
@@ -1348,6 +1376,19 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
return;
}
#ifdef CONFIG_IEEE8021X_AUTH
if (sta->auth_alg == WLAN_AUTH_802_1X) {
wpa_printf(MSG_DEBUG,
"IEEE 802.1X: Ignore STA - EAP in Authentication frames");
/*
* Clear any possible EAPOL authenticator state to support
* reassociation change from WPA-EAP to PSK.
*/
ieee802_1x_free_station(hapd, sta);
return;
}
#endif /* CONFIG_IEEE8021X_AUTH */
key_mgmt = wpa_auth_sta_key_mgmt(sta->wpa_sm);
if (key_mgmt != -1 &&
(wpa_key_mgmt_wpa_psk(key_mgmt) || key_mgmt == WPA_KEY_MGMT_OWE ||
@@ -1471,10 +1512,6 @@ void ieee802_1x_free_station(struct hostapd_data *hapd, struct sta_info *sta)
{
struct eapol_state_machine *sm = sta->eapol_sm;
#ifdef CONFIG_HS20
eloop_cancel_timeout(ieee802_1x_wnm_notif_send, hapd, sta);
#endif /* CONFIG_HS20 */
if (sta->pending_eapol_rx) {
wpabuf_free(sta->pending_eapol_rx->buf);
os_free(sta->pending_eapol_rx);
@@ -1750,32 +1787,6 @@ static void ieee802_1x_update_sta_cui(struct hostapd_data *hapd,
#ifdef CONFIG_HS20
static void ieee802_1x_hs20_sub_rem(struct sta_info *sta, u8 *pos, size_t len)
{
sta->remediation = 1;
os_free(sta->remediation_url);
if (len > 2) {
sta->remediation_url = os_malloc(len);
if (!sta->remediation_url)
return;
sta->remediation_method = pos[0];
os_memcpy(sta->remediation_url, pos + 1, len - 1);
sta->remediation_url[len - 1] = '\0';
wpa_printf(MSG_DEBUG,
"HS 2.0: Subscription remediation needed for "
MACSTR " - server method %u URL %s",
MAC2STR(sta->addr), sta->remediation_method,
sta->remediation_url);
} else {
sta->remediation_url = NULL;
wpa_printf(MSG_DEBUG,
"HS 2.0: Subscription remediation needed for "
MACSTR, MAC2STR(sta->addr));
}
/* TODO: assign the STA into remediation VLAN or add filtering */
}
static void ieee802_1x_hs20_deauth_req(struct hostapd_data *hapd,
struct sta_info *sta, const u8 *pos,
size_t len)
@@ -1891,7 +1902,6 @@ static void ieee802_1x_check_hs20(struct hostapd_data *hapd,
size_t len;
buf = NULL;
sta->remediation = 0;
sta->hs20_deauth_requested = 0;
sta->hs20_deauth_on_ack = 0;
@@ -1916,9 +1926,6 @@ static void ieee802_1x_check_hs20(struct hostapd_data *hapd,
continue; /* invalid WFA VSA */
switch (type) {
case RADIUS_VENDOR_ATTR_WFA_HS20_SUBSCR_REMEDIATION:
ieee802_1x_hs20_sub_rem(sta, pos, sublen);
break;
case RADIUS_VENDOR_ATTR_WFA_HS20_DEAUTH_REQ:
ieee802_1x_hs20_deauth_req(hapd, sta, pos, sublen);
break;
@@ -2306,9 +2313,11 @@ static void ieee802_1x_rekey(void *eloop_ctx, void *timeout_ctx)
static void ieee802_1x_eapol_send(void *ctx, void *sta_ctx, u8 type,
const u8 *data, size_t datalen)
{
#ifdef CONFIG_WPS
struct hostapd_data *hapd = ctx;
struct sta_info *sta = sta_ctx;
#ifdef CONFIG_WPS
if ((sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) ==
WLAN_STA_MAYBE_WPS) {
const u8 *identity;
@@ -2330,7 +2339,16 @@ static void ieee802_1x_eapol_send(void *ctx, void *sta_ctx, u8 type,
}
#endif /* CONFIG_WPS */
ieee802_1x_send(ctx, sta_ctx, type, data, datalen);
#ifdef CONFIG_IEEE8021X_AUTH
if (sta->epp_sta && hapd->send_eap_req) {
hapd->send_eap_req(hapd, sta, type,
sta->eap_auth_data.auth_transaction + 1,
WLAN_STATUS_SUCCESS, NULL, data, datalen);
return;
}
#endif /* CONFIG_IEEE8021X_AUTH */
ieee802_1x_send(hapd, sta, type, data, datalen);
}
@@ -2347,7 +2365,7 @@ static void ieee802_1x_aaa_send(void *ctx, void *sta_ctx,
static bool _ieee802_1x_finished(void *ctx, void *sta_ctx, int success,
int preauth, int remediation, bool logoff)
int preauth, bool logoff)
{
struct hostapd_data *hapd = ctx;
struct sta_info *sta = sta_ctx;
@@ -2357,7 +2375,7 @@ static bool _ieee802_1x_finished(void *ctx, void *sta_ctx, int success,
return false;
}
return ieee802_1x_finished(hapd, sta, success, remediation, logoff);
return ieee802_1x_finished(hapd, sta, success, logoff);
}
@@ -2399,7 +2417,6 @@ static int ieee802_1x_get_eap_user(void *ctx, const u8 *identity,
user->force_version = eap_user->force_version;
user->macacl = eap_user->macacl;
user->ttls_auth = eap_user->ttls_auth;
user->remediation = eap_user->remediation;
rv = 0;
out:
@@ -2557,8 +2574,6 @@ int ieee802_1x_init(struct hostapd_data *hapd)
}
#endif /* CONFIG_IEEE80211BE */
dl_list_init(&hapd->erp_keys);
os_memset(&conf, 0, sizeof(conf));
conf.eap_cfg = hapd->eap_cfg;
conf.ctx = hapd;
@@ -2987,7 +3002,11 @@ int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
id = eap_get_identity(sm->eap, &id_len);
if (id)
identity_buf = dup_binstr(id, id_len);
} else if (sm->eap && sm->identity) {
identity_buf = dup_binstr(sm->identity,
sm->identity_len);
}
ret = os_snprintf(buf + len, buflen - len,
/* TODO: dot1xAuthSessionOctetsRx */
/* TODO: dot1xAuthSessionOctetsTx */
@@ -3003,8 +3022,7 @@ int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
wpa_auth_sta_key_mgmt(sta->wpa_sm))) ?
1 : 2,
(unsigned int) diff.sec,
sm->identity ? (char *) sm->identity :
(identity_buf ? identity_buf : "N/A"));
identity_buf ? identity_buf : "N/A");
os_free(identity_buf);
if (os_snprintf_error(buflen - len, ret))
return len;
@@ -3041,17 +3059,6 @@ static void ieee802_1x_wnm_notif_send(void *eloop_ctx, void *timeout_ctx)
struct hostapd_data *hapd = eloop_ctx;
struct sta_info *sta = timeout_ctx;
if (sta->remediation) {
wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to "
MACSTR " to indicate Subscription Remediation",
MAC2STR(sta->addr));
hs20_send_wnm_notification(hapd, sta->addr,
sta->remediation_method,
sta->remediation_url);
os_free(sta->remediation_url);
sta->remediation_url = NULL;
}
if (sta->hs20_deauth_req) {
wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to "
MACSTR " to indicate imminent deauthentication",
@@ -3074,7 +3081,7 @@ static void ieee802_1x_wnm_notif_send(void *eloop_ctx, void *timeout_ctx)
static bool ieee802_1x_finished(struct hostapd_data *hapd,
struct sta_info *sta, int success,
int remediation, bool logoff)
bool logoff)
{
const u8 *key;
size_t len;
@@ -3084,16 +3091,7 @@ static bool ieee802_1x_finished(struct hostapd_data *hapd,
struct os_reltime now, remaining;
#ifdef CONFIG_HS20
if (remediation && !sta->remediation) {
sta->remediation = 1;
os_free(sta->remediation_url);
sta->remediation_url =
os_strdup(hapd->conf->subscr_remediation_url);
sta->remediation_method = 1; /* SOAP-XML SPP */
}
if (success && (sta->remediation || sta->hs20_deauth_req ||
sta->hs20_t_c_filtering)) {
if (success && (sta->hs20_deauth_req || sta->hs20_t_c_filtering)) {
wpa_printf(MSG_DEBUG, "HS 2.0: Schedule WNM-Notification to "
MACSTR " in 100 ms", MAC2STR(sta->addr));
eloop_cancel_timeout(ieee802_1x_wnm_notif_send, hapd, sta);
@@ -3114,7 +3112,7 @@ static bool ieee802_1x_finished(struct hostapd_data *hapd,
} else {
session_timeout = dot11RSNAConfigPMKLifetime;
}
if (success && key && len >= PMK_LEN && !sta->remediation &&
if (success && key && len >= PMK_LEN &&
!sta->hs20_deauth_requested &&
wpa_auth_pmksa_add(sta->wpa_sm, key, len, session_timeout,
sta->eapol_sm) == 0) {
@@ -3142,3 +3140,13 @@ static bool ieee802_1x_finished(struct hostapd_data *hapd,
return false;
}
#ifdef CONFIG_IEEE8021X_AUTH
void ieee802_1x_eapol_sm_set_port_enabled(struct eapol_state_machine *sm,
bool value)
{
if (sm && sm->eap_if)
sm->eap_if->portEnabled = value;
}
#endif /* CONFIG_IEEE8021X_AUTH */
+2
View File
@@ -66,4 +66,6 @@ void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd,
struct eapol_state_machine *
ieee802_1x_alloc_eapol_sm(struct hostapd_data *hapd, struct sta_info *sta);
void ieee802_1x_eapol_sm_set_port_enabled(struct eapol_state_machine *sm,
bool value);
#endif /* IEEE802_1X_H */
+592
View File
@@ -0,0 +1,592 @@
/*
* Management of interference due to incumbent signals in 6 GHz band
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
#include "utils/common.h"
#include "common/hw_features_common.h"
#include "common/ieee802_11_common.h"
#include "hostapd.h"
#include "ap_drv_ops.h"
#include "beacon.h"
#include "interference.h"
#define BASE_6GHZ_FREQ 5950
/* Channel 2 (op class 136) has a center frequency of 5935 MHz. */
#define BASE_6GHZ_CH2_FREQ 5935
enum chan_seg {
SEG_PRI20 = 0x1,
SEG_SEC20 = 0x2,
SEG_SEC40_LOW = 0x4,
SEG_SEC40_UP = 0x8,
SEG_SEC40 = 0xC,
SEG_SEC80_LOW = 0x10,
SEG_SEC80_LOW_UP = 0x20,
SEG_SEC80_UP_LOW = 0x40,
SEG_SEC80_UP = 0x80,
SEG_SEC80 = 0xF0,
SEG_SEC160_LOW = 0x0100,
SEG_SEC160_LOW_UP = 0x0200,
SEG_SEC160_LOW_UP_UP = 0x0400,
SEG_SEC160_LOW_UP_UP_UP = 0x0800,
SEG_SEC160_UP_LOW_LOW_LOW = 0x1000,
SEG_SEC160_UP_LOW_LOW = 0x2000,
SEG_SEC160_UP_LOW = 0x4000,
SEG_SEC160_UP = 0x8000,
SEG_SEC160 = 0xFF00,
};
static bool is_chan_disabled(struct hostapd_hw_modes *mode, int chan_num)
{
struct hostapd_channel_data *chan;
int i;
for (i = 0; i < mode->num_channels; i++) {
chan = &mode->channels[i];
if (chan->chan == chan_num)
return !!(chan->flag & HOSTAPD_CHAN_DISABLED);
}
return true;
}
/*
* chan_range_available - Check whether the channel can operate in the given
* bandwidth in 6 GHz
* @first_chan_idx - Channel index of the first 20 MHz channel in a segment
* @num_chans - Number of 20 MHz channels needed for the operating bandwidth
* @allowed_arr - Range of channels allowed in the given bandwidth
* @allowed_arr_size - Number of channels allowed in the given bandwidth
* Returns: Whether the channel can operation in the given bandwidth
*/
static bool chan_range_available(struct hostapd_hw_modes *mode,
unsigned int first_chan_idx,
unsigned int num_chans,
const int *allowed_arr,
unsigned int allowed_arr_size)
{
struct hostapd_channel_data *first_chan;
unsigned int i;
first_chan = &mode->channels[first_chan_idx];
if (!chan_pri_allowed(first_chan)) {
wpa_printf(MSG_DEBUG, "Intf: Primary channel %d not allowed",
first_chan->chan);
return false;
}
/* 20 MHz channel, so no need to check the range */
if (num_chans == 1)
return true;
if (allowed_arr) {
for (i = 0; i < allowed_arr_size; i++) {
if (first_chan->chan == allowed_arr[i])
break;
}
if (i == allowed_arr_size)
return false;
}
/*
* Check whether all the 20 MHz channels in the given operating range
* are enabled.
*/
for (i = 1; i < num_chans; i++) {
if (is_chan_disabled(mode, first_chan->chan + i * 4))
return false;
}
return true;
}
static bool is_in_chanlist(struct hostapd_iface *iface,
struct hostapd_channel_data *chan)
{
if (!iface->conf->acs_ch_list.num)
return true;
return freq_range_list_includes(&iface->conf->acs_ch_list, chan->chan);
}
static int get_center_freq_6g(int chan_idx, enum chan_width chan_width,
int *center_freq)
{
if (!center_freq)
return -1;
*center_freq = 0;
switch (chan_width) {
case CHAN_WIDTH_20:
if (chan_idx == 2) {
*center_freq = BASE_6GHZ_CH2_FREQ;
break;
}
if (chan_idx >= 1 && chan_idx <= 233)
*center_freq = ((chan_idx / 4) * 4 + 1) * 5 +
BASE_6GHZ_FREQ;
break;
case CHAN_WIDTH_40:
if (chan_idx >= 1 && chan_idx <= 229)
*center_freq = ((chan_idx / 8) * 8 + 3) * 5 +
BASE_6GHZ_FREQ;
break;
case CHAN_WIDTH_80:
if (chan_idx >= 1 && chan_idx <= 221)
*center_freq = ((chan_idx / 16) * 16 + 7) * 5 +
BASE_6GHZ_FREQ;
break;
case CHAN_WIDTH_160:
if (chan_idx >= 1 && chan_idx <= 221)
*center_freq = ((chan_idx / 32) * 32 + 15) * 5 +
BASE_6GHZ_FREQ;
break;
case CHAN_WIDTH_320:
if (chan_idx >= 1 && chan_idx <= 221)
*center_freq = ((chan_idx / 32) * 32 + 31) * 5 +
BASE_6GHZ_FREQ;
break;
default:
break;
}
if (*center_freq == 0)
return -1;
return 0;
}
static bool is_interference_in_chanlist(int freq_start, int freq_end,
const int *interference_freqs)
{
int i;
for (i = freq_start; i <= freq_end; i += 20) {
if (int_array_includes(interference_freqs, i))
return true;
}
return false;
}
static const int * get_allowed_channel_array(int num_chans, unsigned int *size)
{
static const int allowed_40_6g[] = { 1, 9, 17, 25, 33, 41, 49, 57, 65,
73, 81, 89, 97, 105, 113, 121, 129,
137, 145, 153, 161, 169, 177, 185,
193, 201, 209, 217, 225, 233 };
static const int allowed_80_6g[] = { 1, 17, 33, 49, 65, 81, 97, 113,
129, 145, 161, 177,
193, 209 };
static const int allowed_160_6g[] = { 1, 33, 65, 97, 129, 161, 193 };
static const int allowed_320_6g[] = { 1, 65, 129, 33, 97, 161 };
switch (num_chans) {
case 2:
*size = ARRAY_SIZE(allowed_40_6g);
return allowed_40_6g;
case 4:
*size = ARRAY_SIZE(allowed_80_6g);
return allowed_80_6g;
case 8:
*size = ARRAY_SIZE(allowed_160_6g);
return allowed_160_6g;
case 16:
*size = ARRAY_SIZE(allowed_320_6g);
return allowed_320_6g;
default:
*size = 0;
return NULL;
}
}
/**
* intf_find_channel_list - Find the list of channels that can operate with
* channel width chan_width and not present within the range of current
* operating range.
* @chan_width - Channel width to be checked
* @chandef_list - Pointer array to hold the list of valid available chandef
* Returns: The total number of available chandefs that support the provided
* bandwidth
*/
static int intf_find_channel_list(struct hostapd_iface *iface, int chan_width,
struct hostapd_channel_data **chandef_list,
const int *interference_freqs)
{
struct hostapd_hw_modes *mode = iface->current_mode;
int new_center_freq, new_start_freq, new_end_freq;
const int *allowed_arr = NULL;
unsigned int allowed_arr_size = 0;
struct hostapd_channel_data *chan;
int i;
unsigned int channel_idx = 0, n_chans;
int ret;
switch (chan_width) {
case CHAN_WIDTH_20_NOHT:
case CHAN_WIDTH_20:
n_chans = 1;
break;
case CHAN_WIDTH_40:
n_chans = 2;
break;
case CHAN_WIDTH_80:
n_chans = 4;
break;
case CHAN_WIDTH_80P80:
case CHAN_WIDTH_160:
n_chans = 8;
break;
case CHAN_WIDTH_320:
n_chans = 16;
break;
default:
n_chans = 1;
break;
}
allowed_arr = get_allowed_channel_array(n_chans, &allowed_arr_size);
for (i = 0; i < mode->num_channels; i++) {
chan = &mode->channels[i];
if (!chan_in_current_hw_info(iface->current_hw_info, chan)) {
wpa_printf(MSG_DEBUG,
"Intf: Channel %d (%d) is not under current hardware index",
chan->freq, chan->chan);
continue;
}
/* Skip incompatible chandefs */
if (!chan_range_available(mode, i, n_chans,
allowed_arr, allowed_arr_size)) {
wpa_printf(MSG_DEBUG,
"Intf: Range not available for chan %d (%d)",
chan->freq, chan->chan);
continue;
}
if (!is_in_chanlist(iface, chan)) {
wpa_printf(MSG_DEBUG,
"Intf: Channel %d (%d) not in chanlist",
chan->freq, chan->chan);
continue;
}
ret = get_center_freq_6g(chan->chan, chan_width,
&new_center_freq);
if (ret) {
wpa_printf(MSG_INFO,
"Intf: Couldn't find center freq for chan %d chan_width %d",
chan->chan, chan_width);
return 0;
}
new_start_freq = (new_center_freq -
channel_width_to_int(chan_width) / 2) + 10;
new_end_freq = (new_center_freq +
channel_width_to_int(chan_width) / 2) - 10;
if (is_interference_in_chanlist(new_start_freq, new_end_freq,
interference_freqs)) {
wpa_printf(MSG_DEBUG,
"Intf: Found frequency which has interference in channel (%d)",
chan->chan);
continue;
}
wpa_printf(MSG_DEBUG,
"Intf: Adding channel %d (%d) to valid chandef list",
chan->freq, chan->chan);
chandef_list[channel_idx] = chan;
channel_idx++;
}
return channel_idx;
}
static enum chan_width downgrade_bandwidth(enum chan_width chan_width)
{
switch (chan_width) {
case CHAN_WIDTH_320:
return CHAN_WIDTH_160;
case CHAN_WIDTH_160:
return CHAN_WIDTH_80;
case CHAN_WIDTH_80:
return CHAN_WIDTH_40;
case CHAN_WIDTH_40:
return CHAN_WIDTH_20;
default:
return CHAN_WIDTH_20_NOHT;
}
}
/*
* hostapd_incumbt_sig_intf_detected - Incumbent signal interference is detected
* in the operating channel. The interference channel information is available
* as a bitmap(chan_bw_interference_bitmap). If interference has occurred in
* the primary channel, do a complete channel switch to a different channel;
* otherwise, reduce the operating bandwidth and continue AP operation using
* the same primary channel.
*/
int hostapd_incumbt_sig_intf_detected(struct hostapd_iface *iface, int freq,
int chan_width, int cf1, int cf2,
u32 chan_bw_interference_bitmap)
{
struct csa_settings settings;
struct hostapd_channel_data *chan_data = NULL;
struct hostapd_channel_data *chan_temp;
struct hostapd_channel_data **available_chandef_list = NULL;
int ret = 0;
unsigned int i;
u32 _rand;
u32 chan_idx;
int num_available_chandefs = 0;
enum chan_width new_chan_width;
int new_center_freq;
int current_start_freq;
int temp_width;
struct hostapd_hw_modes *mode = iface->current_mode;
int *interference_freqs = NULL;
int primary_chan_bit = -1;
int segment_freq;
int start_freq = (cf1 - channel_width_to_int(chan_width) / 2) + 10;
u8 channel_no;
unsigned int num_segments;
int new_bw;
wpa_printf(MSG_DEBUG,
"Intf: input freq=%d, chan_width=%d, cf1=%d, cf2=%d, chan_bw_interference_bitmap=0x%x",
freq, chan_width, cf1, cf2, chan_bw_interference_bitmap);
num_segments = channel_width_to_int(chan_width) / 20;
if (!num_segments) {
wpa_printf(MSG_INFO, "Intf: Invalid channel width %d",
chan_width);
return -1;
}
/* Determine which 20 MHz segment contains the primary channel */
for (i = 0; i < num_segments; i++) {
segment_freq = start_freq + i * 20;
if (segment_freq == freq) {
primary_chan_bit = i;
break;
}
}
/* Check whether interference has occurred in primary 20 MHz channel */
if (primary_chan_bit >= 0 &&
(chan_bw_interference_bitmap & BIT(primary_chan_bit))) {
available_chandef_list = os_calloc(
mode->num_channels,
sizeof(struct hostapd_channel_data *));
if (!available_chandef_list) {
wpa_printf(MSG_ERROR,
"Intf: Failed to allocate available_chandef_list");
return -1;
}
/* Store frequencies with interference in interference_freqs */
current_start_freq =
(cf1 - channel_width_to_int(chan_width) / 2) + 10;
for (i = 0; i < num_segments; i++) {
if (chan_bw_interference_bitmap & BIT(i)) {
wpa_printf(MSG_DEBUG,
"Intf: Found incumbent signal interference in frequency %d",
current_start_freq + 20 * i);
int_array_add_unique(&interference_freqs,
current_start_freq +
20 * i);
if (!interference_freqs) {
wpa_printf(MSG_ERROR,
"Intf: Failed to store interference frequencies");
ret = -1;
goto exit;
}
}
}
/* Find a random channel to be switched */
temp_width = chan_width;
while (temp_width > CHAN_WIDTH_20_NOHT) {
num_available_chandefs =
intf_find_channel_list(iface, temp_width,
available_chandef_list,
interference_freqs);
if (num_available_chandefs > 0)
break;
wpa_printf(MSG_DEBUG, "Intf: Downgrading bandwidth");
temp_width = downgrade_bandwidth(temp_width);
}
if (num_available_chandefs == 0) {
wpa_printf(MSG_INFO, "Intf: No available_chandefs");
goto exit;
}
if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0)
_rand = os_random();
chan_idx = _rand % num_available_chandefs;
chan_data = available_chandef_list[chan_idx];
new_chan_width = temp_width;
wpa_printf(MSG_DEBUG, "Intf: Got random channel %d (%d)",
chan_data->freq, chan_data->chan);
} else {
/*
* Interference is not present in the primary 20 MHz, so
* reduce bandwidth.
*/
u8 seg0 = hostapd_get_oper_centr_freq_seg0_idx(iface->conf);
u8 seg1 = hostapd_get_oper_centr_freq_seg1_idx(iface->conf);
enum oper_chan_width oper_chwidth;
int j;
for (j = 0; j < mode->num_channels; j++) {
chan_temp = &mode->channels[j];
if (chan_temp->freq == freq)
chan_data = chan_temp;
}
if (!chan_data) {
wpa_printf(MSG_INFO, "Intf: No channel found");
goto exit;
}
oper_chwidth = chan_width_to_oper_chwidth(chan_width);
if (chan_width > CHAN_WIDTH_40) {
punct_update_legacy_bw(chan_bw_interference_bitmap,
iface->conf->channel,
&oper_chwidth, &seg0, &seg1);
if (oper_chwidth == CONF_OPER_CHWIDTH_160MHZ)
new_chan_width = CHAN_WIDTH_160;
else if (oper_chwidth == CONF_OPER_CHWIDTH_80MHZ)
new_chan_width = CHAN_WIDTH_80;
else if (seg0 == 0)
new_chan_width = CHAN_WIDTH_20;
else
new_chan_width = CHAN_WIDTH_40;
} else {
new_chan_width = CHAN_WIDTH_20;
}
}
if (new_chan_width > CHAN_WIDTH_20) {
ret = get_center_freq_6g(chan_data->chan, new_chan_width,
&new_center_freq);
if (ret) {
wpa_printf(MSG_ERROR,
"Intf: Couldn't find center freq for chan : %d chan_width : %d",
chan_data->chan, new_chan_width);
goto exit;
}
} else {
new_center_freq = chan_data->freq;
}
ieee80211_freq_to_chan(chan_data->freq, &channel_no);
os_memset(&settings, 0, sizeof(settings));
settings.cs_count = 5;
settings.freq_params.freq = chan_data->freq;
switch (new_chan_width) {
case CHAN_WIDTH_40:
new_bw = 40;
break;
case CHAN_WIDTH_80P80:
case CHAN_WIDTH_80:
new_bw = 80;
break;
case CHAN_WIDTH_160:
new_bw = 160;
break;
case CHAN_WIDTH_320:
new_bw = 320;
break;
default:
new_bw = 20;
break;
}
settings.freq_params.bandwidth = new_bw;
settings.freq_params.channel = channel_no;
settings.freq_params.center_freq1 = new_center_freq;
settings.freq_params.ht_enabled = iface->conf->ieee80211n;
settings.freq_params.vht_enabled = iface->conf->ieee80211ac;
settings.freq_params.he_enabled = iface->conf->ieee80211ax;
settings.freq_params.eht_enabled = iface->conf->ieee80211be;
wpa_printf(MSG_DEBUG,
"Intf: channel=%u, freq=%d, bw=%d, center_freq1=%d",
settings.freq_params.channel,
settings.freq_params.freq,
settings.freq_params.bandwidth,
settings.freq_params.center_freq1);
if (chan_data->freq == iface->freq) {
if (hostapd_change_config_freq(iface->bss[0], iface->conf,
&settings.freq_params, NULL)) {
wpa_printf(MSG_INFO,
"Intf: Failed to update bandwidth");
ret = -1;
goto exit;
}
if (hostapd_set_freq(
iface->bss[0], iface->conf->hw_mode, iface->freq,
iface->conf->channel, iface->conf->enable_edmg,
iface->conf->edmg_channel, iface->conf->ieee80211n,
iface->conf->ieee80211ac,
iface->conf->ieee80211ax,
iface->conf->ieee80211be,
iface->conf->secondary_channel,
hostapd_get_oper_chwidth(iface->conf),
hostapd_get_oper_centr_freq_seg0_idx(iface->conf),
hostapd_get_oper_centr_freq_seg1_idx(iface->conf))) {
wpa_printf(MSG_ERROR,
"Intf: Failed to apply bandwidth update");
ret = -1;
goto exit;
}
ieee802_11_set_beacons(iface);
goto exit;
}
/* Channel and bandwidth have been decided, triggering channel switch */
for (i = 0; i < iface->num_bss; i++) {
/* Save CHAN_SWITCH VHT and HE config */
hostapd_chan_switch_config(iface->bss[i],
&settings.freq_params);
ret = hostapd_switch_channel(iface->bss[i], &settings);
if (ret) {
wpa_printf(MSG_ERROR,
"Intf: Channel switch failed");
break;
}
}
exit:
os_free(available_chandef_list);
os_free(interference_freqs);
return ret;
}
+18
View File
@@ -0,0 +1,18 @@
/*
* Management of interference due to incumbent signals in 6 GHz band
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef INTERFERENCE_H
#define INTERFERENCE_H
struct hostapd_iface;
int hostapd_incumbt_sig_intf_detected(struct hostapd_iface *iface, int freq,
int chan_width,
int cf1, int cf2,
u32 chan_bw_interference_bitmap);
#endif /* INTERFERENCE_H */
+39 -25
View File
@@ -1,6 +1,6 @@
/*
* NAN unsynchronized service discovery (USD)
* Copyright (c) 2024, Qualcomm Innovation Center, Inc.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -29,38 +29,38 @@ static int hostapd_nan_de_tx(void *ctx, unsigned int freq,
wpabuf_len(buf));
/* TODO: Force use of OFDM */
return hostapd_drv_send_action(hapd, hapd->iface->freq, 0, dst,
wpabuf_head(buf), wpabuf_len(buf));
return hostapd_drv_send_action_forced_addr3(hapd, hapd->iface->freq, 0,
dst, bssid,
wpabuf_head(buf),
wpabuf_len(buf));
}
static int hostapd_nan_de_listen(void *ctx, unsigned int freq,
unsigned int duration)
unsigned int duration, const u8 *forced_addr)
{
return 0;
}
static void
hostapd_nan_de_discovery_result(void *ctx, int subscribe_id,
enum nan_service_protocol_type srv_proto_type,
const u8 *ssi, size_t ssi_len,
int peer_publish_id, const u8 *peer_addr,
bool fsd, bool fsd_gas)
hostapd_nan_de_discovery_result(void *ctx, struct nan_discovery_result *res)
{
struct hostapd_data *hapd = ctx;
char *ssi_hex;
ssi_hex = os_zalloc(2 * ssi_len + 1);
ssi_hex = os_zalloc(2 * res->ssi_len + 1);
if (!ssi_hex)
return;
if (ssi)
wpa_snprintf_hex(ssi_hex, 2 * ssi_len + 1, ssi, ssi_len);
if (res->ssi)
wpa_snprintf_hex(ssi_hex, 2 * res->ssi_len + 1,
res->ssi, res->ssi_len);
wpa_msg(hapd->msg_ctx, MSG_INFO, NAN_DISCOVERY_RESULT
"subscribe_id=%d publish_id=%d address=" MACSTR
" fsd=%d fsd_gas=%d srv_proto_type=%u ssi=%s",
subscribe_id, peer_publish_id, MAC2STR(peer_addr),
fsd, fsd_gas, srv_proto_type, ssi_hex);
res->subscribe_id, res->peer_publish_id,
MAC2STR(res->peer_addr), res->fsd, res->fsd_gas,
res->srv_proto_type, ssi_hex);
os_free(ssi_hex);
}
@@ -127,7 +127,8 @@ static void hostapd_nan_de_subscribe_terminated(void *ctx, int subscribe_id,
static void hostapd_nan_de_receive(void *ctx, int id, int peer_instance_id,
const u8 *ssi, size_t ssi_len,
const u8 *peer_addr)
const u8 *peer_addr,
const u8 *buf, size_t len)
{
struct hostapd_data *hapd = ctx;
char *ssi_hex;
@@ -148,6 +149,10 @@ int hostapd_nan_usd_init(struct hostapd_data *hapd)
{
struct nan_callbacks cb;
/* If nan_de is already initialized, do not create a new instance. */
if (hapd->nan_de)
return 0;
os_memset(&cb, 0, sizeof(cb));
cb.ctx = hapd;
cb.tx = hostapd_nan_de_tx;
@@ -158,26 +163,33 @@ int hostapd_nan_usd_init(struct hostapd_data *hapd)
cb.subscribe_terminated = hostapd_nan_de_subscribe_terminated;
cb.receive = hostapd_nan_de_receive;
hapd->nan_de = nan_de_init(hapd->own_addr, true, &cb);
hapd->nan_de = nan_de_init(hapd->own_addr, false, true, 0, &cb);
if (!hapd->nan_de)
return -1;
hapd->nan_de_is_owned = true;
return 0;
}
void hostapd_nan_usd_deinit(struct hostapd_data *hapd)
{
nan_de_deinit(hapd->nan_de);
if (hapd->nan_de_is_owned) {
nan_de_deinit(hapd->nan_de);
hapd->nan_de_is_owned = false;
}
hapd->nan_de = NULL;
}
void hostapd_nan_usd_rx_sdf(struct hostapd_data *hapd, const u8 *src,
unsigned int freq, const u8 *buf, size_t len)
const u8 *a3, unsigned int freq,
const u8 *buf, size_t len)
{
if (!hapd->nan_de)
return;
nan_de_rx_sdf(hapd->nan_de, src, freq, buf, len);
nan_de_rx_sdf(hapd->nan_de, src, a3, freq, buf, len, 0);
}
@@ -192,7 +204,7 @@ void hostapd_nan_usd_flush(struct hostapd_data *hapd)
int hostapd_nan_usd_publish(struct hostapd_data *hapd, const char *service_name,
enum nan_service_protocol_type srv_proto_type,
const struct wpabuf *ssi,
struct nan_publish_params *params)
struct nan_publish_params *params, bool p2p)
{
int publish_id;
struct wpabuf *elems = NULL;
@@ -201,7 +213,7 @@ int hostapd_nan_usd_publish(struct hostapd_data *hapd, const char *service_name,
return -1;
publish_id = nan_de_publish(hapd->nan_de, service_name, srv_proto_type,
ssi, elems, params);
ssi, elems, params, p2p, NULL);
wpabuf_free(elems);
return publish_id;
}
@@ -231,7 +243,7 @@ int hostapd_nan_usd_subscribe(struct hostapd_data *hapd,
const char *service_name,
enum nan_service_protocol_type srv_proto_type,
const struct wpabuf *ssi,
struct nan_subscribe_params *params)
struct nan_subscribe_params *params, bool p2p)
{
int subscribe_id;
struct wpabuf *elems = NULL;
@@ -240,7 +252,8 @@ int hostapd_nan_usd_subscribe(struct hostapd_data *hapd,
return -1;
subscribe_id = nan_de_subscribe(hapd->nan_de, service_name,
srv_proto_type, ssi, elems, params);
srv_proto_type, ssi, elems, params, p2p,
NULL);
wpabuf_free(elems);
return subscribe_id;
}
@@ -258,10 +271,11 @@ void hostapd_nan_usd_cancel_subscribe(struct hostapd_data *hapd,
int hostapd_nan_usd_transmit(struct hostapd_data *hapd, int handle,
const struct wpabuf *ssi,
const struct wpabuf *elems,
const u8 *peer_addr, u8 req_instance_id)
const u8 *peer_addr,
u8 req_instance_id)
{
if (!hapd->nan_de)
return -1;
return nan_de_transmit(hapd->nan_de, handle, ssi, elems, peer_addr,
req_instance_id);
req_instance_id, NULL, NULL);
}
+4 -3
View File
@@ -1,6 +1,6 @@
/*
* NAN unsynchronized service discovery (USD)
* Copyright (c) 2024, Qualcomm Innovation Center, Inc.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -16,12 +16,13 @@ enum nan_service_protocol_type;
int hostapd_nan_usd_init(struct hostapd_data *hapd);
void hostapd_nan_usd_deinit(struct hostapd_data *hapd);
void hostapd_nan_usd_rx_sdf(struct hostapd_data *hapd, const u8 *src,
const u8 *a3,
unsigned int freq, const u8 *buf, size_t len);
void hostapd_nan_usd_flush(struct hostapd_data *hapd);
int hostapd_nan_usd_publish(struct hostapd_data *hapd, const char *service_name,
enum nan_service_protocol_type srv_proto_type,
const struct wpabuf *ssi,
struct nan_publish_params *params);
struct nan_publish_params *params, bool p2p);
void hostapd_nan_usd_cancel_publish(struct hostapd_data *hapd, int publish_id);
int hostapd_nan_usd_update_publish(struct hostapd_data *hapd, int publish_id,
const struct wpabuf *ssi);
@@ -29,7 +30,7 @@ int hostapd_nan_usd_subscribe(struct hostapd_data *hapd,
const char *service_name,
enum nan_service_protocol_type srv_proto_type,
const struct wpabuf *ssi,
struct nan_subscribe_params *params);
struct nan_subscribe_params *params, bool p2p);
void hostapd_nan_usd_cancel_subscribe(struct hostapd_data *hapd,
int subscribe_id);
int hostapd_nan_usd_transmit(struct hostapd_data *hapd, int handle,
+36 -30
View File
@@ -203,16 +203,15 @@ void hostapd_free_neighbor_db(struct hostapd_data *hapd)
#ifdef NEED_AP_MLME
static enum nr_chan_width hostapd_get_nr_chan_width(struct hostapd_data *hapd,
int ht, int vht, int he)
static enum nr_chan_width
hostapd_get_nr_chan_width(struct hostapd_data *hapd,
int ht, int vht, int he,
enum oper_chan_width oper_chwidth,
int secondary_channel)
{
enum oper_chan_width oper_chwidth;
oper_chwidth = hostapd_get_oper_chwidth(hapd->iconf);
if (!ht && !vht && !he)
return NR_CHAN_WIDTH_20;
if (!hapd->iconf->secondary_channel)
if (!secondary_channel)
return NR_CHAN_WIDTH_20;
if ((!vht && !he) || oper_chwidth == CONF_OPER_CHWIDTH_USE_HT)
return NR_CHAN_WIDTH_40;
@@ -231,14 +230,16 @@ void hostapd_neighbor_set_own_report(struct hostapd_data *hapd)
{
#ifdef NEED_AP_MLME
u16 capab = hostapd_own_capab_info(hapd);
int ht = hapd->iconf->ieee80211n && !hapd->conf->disable_11n;
int vht = hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac;
int he = hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax;
bool eht = he && hapd->iconf->ieee80211be && !hapd->conf->disable_11be;
int ht = hostapd_is_ht_enabled(hapd);
int vht = hostapd_is_vht_enabled(hapd);
int he = hostapd_is_he_enabled(hapd);
bool eht = he && hostapd_is_eht_enabled(hapd);
struct wpa_ssid_value ssid;
u8 channel, op_class;
u8 center_freq1_idx = 0, center_freq2_idx = 0;
enum oper_chan_width oper_chwidth;
enum nr_chan_width width;
int secondary_channel;
u32 bssid_info;
struct wpabuf *nr;
@@ -264,10 +265,7 @@ void hostapd_neighbor_set_own_report(struct hostapd_data *hapd)
}
if (ht) {
bssid_info |= NEI_REP_BSSID_INFO_HT |
NEI_REP_BSSID_INFO_DELAYED_BA;
/* VHT bit added in IEEE P802.11-REVmc/D4.3 */
bssid_info |= NEI_REP_BSSID_INFO_HT;
if (vht)
bssid_info |= NEI_REP_BSSID_INFO_VHT;
}
@@ -278,23 +276,30 @@ void hostapd_neighbor_set_own_report(struct hostapd_data *hapd)
bssid_info |= NEI_REP_BSSID_INFO_EHT;
/* TODO: Set NEI_REP_BSSID_INFO_MOBILITY_DOMAIN if MDE is set */
hostapd_get_oper_chan_info_of_bss(hapd, &oper_chwidth,
&center_freq1_idx, &center_freq2_idx);
secondary_channel = hapd->iconf->secondary_channel;
if (center_freq1_idx == hapd->iconf->channel &&
oper_chwidth == CONF_OPER_CHWIDTH_USE_HT)
secondary_channel = 0;
if (ieee80211_freq_to_channel_ext(hapd->iface->freq,
hapd->iconf->secondary_channel,
hostapd_get_oper_chwidth(hapd->iconf),
secondary_channel,
oper_chwidth,
&op_class, &channel) ==
NUM_HOSTAPD_MODES)
return;
width = hostapd_get_nr_chan_width(hapd, ht, vht, he);
if (vht) {
center_freq1_idx = hostapd_get_oper_centr_freq_seg0_idx(
hapd->iconf);
if (width == NR_CHAN_WIDTH_80P80)
center_freq2_idx =
hostapd_get_oper_centr_freq_seg1_idx(
hapd->iconf);
} else if (ht) {
width = hostapd_get_nr_chan_width(hapd, ht, vht, he, oper_chwidth,
secondary_channel);
if (width != NR_CHAN_WIDTH_80P80)
center_freq2_idx = 0;
if (!vht && ht) {
center_freq1_idx = 0;
ieee80211_freq_to_chan(hapd->iface->freq +
10 * hapd->iconf->secondary_channel,
10 * secondary_channel,
&center_freq1_idx);
}
@@ -313,12 +318,13 @@ void hostapd_neighbor_set_own_report(struct hostapd_data *hapd)
wpabuf_put_le32(nr, bssid_info);
wpabuf_put_u8(nr, op_class);
wpabuf_put_u8(nr, channel);
wpabuf_put_u8(nr, ieee80211_get_phy_type(hapd->iface->freq, ht, vht));
wpabuf_put_u8(nr, ieee80211_get_phy_type(hapd->iface->freq, ht, vht,
he));
/*
* Wide Bandwidth Channel subelement may be needed to allow the
* receiving STA to send packets to the AP. See IEEE P802.11-REVmc/D5.0
* Figure 9-301.
* receiving STA to send packets to the AP. See IEEE Std 802.11-2024,
* Figure 9-423 (Wide Bandwidth Channel subelement format).
*/
wpabuf_put_u8(nr, WNM_NEIGHBOR_WIDE_BW_CHAN);
wpabuf_put_u8(nr, 3);
+19 -11
View File
@@ -141,8 +141,8 @@ static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa)
}
static void pmksa_cache_from_eapol_data(struct rsn_pmksa_cache_entry *entry,
struct eapol_state_machine *eapol)
void pmksa_cache_from_eapol_data(struct rsn_pmksa_cache_entry *entry,
struct eapol_state_machine *eapol)
{
struct vlan_description *vlan_desc;
@@ -470,6 +470,17 @@ void pmksa_cache_auth_deinit(struct rsn_pmksa_cache *pmksa)
}
/**
* pmksa_cache_auth_set_ctx - Set the context for PMKSA cache
* @cache: Pointer to the PMKSA cache structure
* @ctx: Context pointer to be stored in the cache
*/
void pmksa_cache_auth_set_ctx(struct rsn_pmksa_cache *cache, void *ctx)
{
cache->ctx = ctx;
}
/**
* pmksa_cache_auth_get - Fetch a PMKSA cache entry
* @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init()
@@ -644,29 +655,25 @@ int pmksa_cache_auth_radius_das_disconnect(struct rsn_pmksa_cache *pmksa,
* @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init()
* @buf: Buffer for the list
* @len: Length of the buffer
* @index: Externally stored index counter
* Returns: Number of bytes written to buffer
*
* This function is used to generate a text format representation of the
* current PMKSA cache contents for the ctrl_iface PMKSA command.
*/
int pmksa_cache_auth_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len)
int pmksa_cache_auth_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len,
int *index)
{
int i, ret;
int ret;
char *pos = buf;
struct rsn_pmksa_cache_entry *entry;
struct os_reltime now;
os_get_reltime(&now);
ret = os_snprintf(pos, buf + len - pos,
"Index / SPA / PMKID / expiration (in seconds) / opportunistic\n");
if (os_snprintf_error(buf + len - pos, ret))
return pos - buf;
pos += ret;
i = 0;
entry = pmksa->pmksa;
while (entry) {
ret = os_snprintf(pos, buf + len - pos, "%d " MACSTR " ",
i, MAC2STR(entry->spa));
*index, MAC2STR(entry->spa));
if (os_snprintf_error(buf + len - pos, ret))
return pos - buf;
pos += ret;
@@ -679,6 +686,7 @@ int pmksa_cache_auth_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len)
return pos - buf;
pos += ret;
entry = entry->next;
(*index)++;
}
return pos - buf;
}
+13 -1
View File
@@ -33,9 +33,17 @@ struct rsn_pmksa_cache_entry {
struct radius_class_data radius_class;
u8 eap_type_authsrv;
struct vlan_description *vlan_desc;
int sae_vlan_id;
int opportunistic;
u64 acct_multi_session_id;
#ifdef CONFIG_IEEE80211BE
/**
* This field is used to identify whether the entry is from ml_pmksa or
* pmksa.
*/
bool is_ml;
#endif /* CONFIG_IEEE80211BE */
};
struct rsn_pmksa_cache;
@@ -45,6 +53,7 @@ struct rsn_pmksa_cache *
pmksa_cache_auth_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
void *ctx), void *ctx);
void pmksa_cache_auth_deinit(struct rsn_pmksa_cache *pmksa);
void pmksa_cache_auth_set_ctx(struct rsn_pmksa_cache *cache, void *ctx);
struct rsn_pmksa_cache_entry *
pmksa_cache_auth_get(struct rsn_pmksa_cache *pmksa,
const u8 *spa, const u8 *pmkid);
@@ -75,9 +84,12 @@ void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa,
struct rsn_pmksa_cache_entry *entry);
int pmksa_cache_auth_radius_das_disconnect(struct rsn_pmksa_cache *pmksa,
struct radius_das_attrs *attr);
int pmksa_cache_auth_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len);
int pmksa_cache_auth_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len,
int *index);
void pmksa_cache_auth_flush(struct rsn_pmksa_cache *pmksa);
int pmksa_cache_auth_list_mesh(struct rsn_pmksa_cache *pmksa, const u8 *addr,
char *buf, size_t len);
void pmksa_cache_from_eapol_data(struct rsn_pmksa_cache_entry *entry,
struct eapol_state_machine *eapol);
#endif /* PMKSA_CACHE_H */
+4 -3
View File
@@ -536,13 +536,14 @@ int hostapd_send_range_req(struct hostapd_data *hapd, const u8 *addr,
if (!hapd->range_req_token) /* For wraparounds */
hapd->range_req_token++;
/* IEEE P802.11-REVmc/D5.0, 9.6.7.2 */
/* IEEE Std 802.11-2024, 9.6.6.2 (Radio Measurement Request frame
* format) */
wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
wpabuf_put_u8(buf, WLAN_RRM_RADIO_MEASUREMENT_REQUEST);
wpabuf_put_u8(buf, hapd->range_req_token); /* Dialog Token */
wpabuf_put_le16(buf, 0); /* Number of Repetitions */
/* IEEE P802.11-REVmc/D5.0, 9.4.2.21 */
/* IEEE Std 802.11-2024, 9.4.2.19 (Measurement Request element) */
wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
len = wpabuf_put(buf, 1); /* Length will be set later */
@@ -554,7 +555,7 @@ int hostapd_send_range_req(struct hostapd_data *hapd, const u8 *addr,
wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
wpabuf_put_u8(buf, MEASURE_TYPE_FTM_RANGE); /* Measurement Type */
/* IEEE P802.11-REVmc/D5.0, 9.4.2.21.19 */
/* IEEE Std 802.11-2024, 9.4.2.19.19 (FTM Range request) */
wpabuf_put_le16(buf, random_interval); /* Randomization Interval */
wpabuf_put_u8(buf, min_ap); /* Minimum AP Count */
+392 -119
View File
@@ -77,6 +77,24 @@ struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta)
}
#ifdef CONFIG_IEEE80211BE
struct sta_info * ap_get_link_sta(struct hostapd_data *hapd,
const u8 *link_addr)
{
struct sta_info *link_sta;
for (link_sta = hapd->sta_list; link_sta; link_sta = link_sta->next) {
if (link_sta->mld_info.mld_sta &&
ether_addr_equal(link_sta->mld_info.links[hapd->mld_link_id].peer_addr,
link_addr))
return link_sta;
}
return NULL;
}
#endif /* CONFIG_IEEE80211BE */
#ifdef CONFIG_P2P
struct sta_info * ap_get_sta_p2p(struct hostapd_data *hapd, const u8 *addr)
{
@@ -191,9 +209,10 @@ void ap_free_sta_pasn(struct hostapd_data *hapd, struct sta_info *sta)
static void __ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
{
#ifdef CONFIG_IEEE80211BE
if (hostapd_sta_is_link_sta(hapd, sta) &&
!hostapd_drv_link_sta_remove(hapd, sta->addr))
if (hostapd_sta_is_link_sta(hapd, sta)) {
hostapd_drv_link_sta_remove(hapd, sta->addr);
return;
}
#endif /* CONFIG_IEEE80211BE */
hostapd_drv_sta_remove(hapd, sta->addr);
@@ -201,8 +220,9 @@ static void __ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
#ifdef CONFIG_IEEE80211BE
static void clear_wpa_sm_for_each_partner_link(struct hostapd_data *hapd,
struct sta_info *psta)
void set_wpa_sm_for_each_partner_link(struct hostapd_data *hapd,
struct sta_info *psta, void *wpa_sm)
{
struct sta_info *lsta;
struct hostapd_data *lhapd;
@@ -215,15 +235,54 @@ static void clear_wpa_sm_for_each_partner_link(struct hostapd_data *hapd,
continue;
lsta = ap_get_sta(lhapd, psta->addr);
if (lsta)
lsta->wpa_sm = NULL;
if (lsta) {
if (lsta->wpa_sm && lsta->wpa_sm != wpa_sm)
wpa_printf(MSG_DEBUG,
"AP MLD: Replacing lsta->wpa_sm %p with %p for a partner link",
lsta->wpa_sm, wpa_sm);
lsta->wpa_sm = wpa_sm;
}
}
}
void clear_wpa_sm_for_each_partner_link(struct hostapd_data *hapd,
struct sta_info *psta)
{
set_wpa_sm_for_each_partner_link(hapd, psta, NULL);
}
void clear_wpa_sm_for_all_sta(struct hostapd_data *hapd,
struct wpa_state_machine *wpa_sm)
{
struct hostapd_data *lhapd;
if (!hapd->mld)
return;
for_each_mld_link(lhapd, hapd) {
struct sta_info *sta;
for (sta = lhapd->sta_list; sta; sta = sta->next) {
if (sta->wpa_sm == wpa_sm) {
wpa_printf(MSG_DEBUG,
"AP MLD: Clearing to be freed wpa_sm=%p pointer from sta=%p",
sta->wpa_sm, sta);
sta->wpa_sm = NULL;
}
}
}
}
#endif /* CONFIG_IEEE80211BE */
void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
{
#ifndef CONFIG_NO_VLAN
struct hostapd_data *vlan_bss = hapd;
#endif /* CONFIG_NO_VLAN */
int set_beacon = 0;
accounting_sta_stop(hapd, sta);
@@ -334,22 +393,27 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
eloop_cancel_timeout(ap_handle_session_timer, hapd, sta);
eloop_cancel_timeout(ap_handle_session_warning_timer, hapd, sta);
ap_sta_clear_disconnect_timeouts(hapd, sta);
ap_sta_clear_assoc_timeout(hapd, sta);
sae_clear_retransmit_timer(hapd, sta);
ieee802_1x_free_station(hapd, sta);
#ifdef CONFIG_IEEE80211BE
if (!ap_sta_is_mld(hapd, sta) ||
hapd->mld_link_id == sta->mld_assoc_link_id) {
wpa_auth_sta_deinit(sta->wpa_sm);
/* Remove references from partner links. */
clear_wpa_sm_for_each_partner_link(hapd, sta);
}
/* Release group references in case non-association link STA is removed
* before association link STA */
if (hostapd_sta_is_link_sta(hapd, sta))
wpa_release_link_auth_ref(sta->wpa_sm, hapd->mld_link_id);
wpa_release_link_auth_ref(sta->wpa_sm, hapd->mld_link_id,
false);
if (!ap_sta_is_mld(hapd, sta) ||
hapd->mld_link_id == sta->mld_assoc_link_id) {
struct wpa_state_machine *sm = sta->wpa_sm;
/* Remove references from partner links. */
clear_wpa_sm_for_each_partner_link(hapd, sta);
clear_wpa_sm_for_all_sta(hapd, sm);
wpa_auth_sta_deinit(sm);
}
#else /* CONFIG_IEEE80211BE */
wpa_auth_sta_deinit(sta->wpa_sm);
#endif /* CONFIG_IEEE80211BE */
@@ -361,13 +425,20 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
#endif /* CONFIG_NO_RADIUS */
#ifndef CONFIG_NO_VLAN
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap) {
vlan_bss = hostapd_mld_get_first_bss(hapd);
if (!vlan_bss)
vlan_bss = hapd;
}
#endif /* CONFIG_IEEE80211BE */
/*
* sta->wpa_sm->group needs to be released before so that
* vlan_remove_dynamic() can check that no stations are left on the
* AP_VLAN netdev.
*/
if (sta->vlan_id)
vlan_remove_dynamic(hapd, sta->vlan_id);
vlan_remove_dynamic(vlan_bss, sta->vlan_id);
if (sta->vlan_id_bound) {
/*
* Need to remove the STA entry before potentially removing the
@@ -378,7 +449,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
hostapd_drv_sta_remove(hapd, sta->addr);
sta->added_unassoc = 0;
}
vlan_remove_dynamic(hapd, sta->vlan_id_bound);
vlan_remove_dynamic(vlan_bss, sta->vlan_id_bound);
}
#endif /* CONFIG_NO_VLAN */
@@ -391,7 +462,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
p2p_group_notif_disassoc(hapd->p2p_group, sta->addr);
#endif /* CONFIG_P2P */
#ifdef CONFIG_INTERWORKING
#if defined(CONFIG_INTERWORKING) || defined(CONFIG_DPP)
if (sta->gas_dialog) {
int i;
@@ -399,7 +470,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
gas_serv_dialog_clear(&sta->gas_dialog[i]);
os_free(sta->gas_dialog);
}
#endif /* CONFIG_INTERWORKING */
#endif /* CONFIG_INTERWORKING || CONFIG_DPP */
wpabuf_free(sta->wps_ie);
wpabuf_free(sta->p2p_ie);
@@ -418,7 +489,6 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
hostapd_free_psk_list(sta->psk);
os_free(sta->identity);
os_free(sta->radius_cui);
os_free(sta->remediation_url);
os_free(sta->t_c_url);
wpabuf_free(sta->hs20_deauth_req);
os_free(sta->hs20_session_info_url);
@@ -467,6 +537,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
#ifdef CONFIG_IEEE80211BE
ap_sta_free_sta_profile(&sta->mld_info);
ml_deinit_link_reconf_req(&sta->reconf_req);
#endif /* CONFIG_IEEE80211BE */
#ifdef CONFIG_TESTING_OPTIONS
@@ -474,6 +545,14 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
forced_memzero(sta->last_tk, WPA_TK_MAX_LEN);
#endif /* CONFIG_TESTING_OPTIONS */
wpabuf_free(sta->sae_pw_id);
#ifdef CONFIG_IEEE8021X_AUTH
crypto_ecdh_deinit(sta->eap_auth_data.ecdh);
wpabuf_clear_free(sta->eap_auth_data.dhss);
os_free(sta->eap_auth_data.rsnxe);
#endif /* CONFIG_IEEE8021X_AUTH */
os_free(sta);
}
@@ -580,6 +659,17 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
sta->timeout_next = STA_DISASSOC;
goto skip_poll;
} else if (inactive_sec < max_inactivity) {
#ifdef CONFIG_TESTING_OPTIONS
if (hapd->conf->skip_inactivity_poll == -1) {
wpa_msg(hapd->msg_ctx, MSG_DEBUG,
"Force inactivity timeout for station "
MACSTR
" even though it has been active %is ago",
MAC2STR(sta->addr), inactive_sec);
sta->timeout_next = STA_DISASSOC;
goto skip_poll;
}
#endif /* CONFIG_TESTING_OPTIONS */
/* station activity detected; reset timeout state */
wpa_msg(hapd->msg_ctx, MSG_DEBUG,
"Station " MACSTR " has been active %is ago",
@@ -791,6 +881,25 @@ void ap_sta_session_warning_timeout(struct hostapd_data *hapd,
}
static void ap_sta_assoc_timeout(void *eloop_ctx, void *timeout_ctx)
{
struct hostapd_data *hapd = eloop_ctx;
struct sta_info *sta = timeout_ctx;
if (sta->flags & WLAN_STA_ASSOC)
return;
wpa_printf(MSG_DEBUG, "STA " MACSTR
" did not complete association in time - remove it",
MAC2STR(sta->addr));
if (sta->flags & WLAN_STA_AUTH)
ap_sta_deauthenticate(hapd, sta,
WLAN_REASON_PREV_AUTH_NOT_VALID);
else
ap_free_sta(hapd, sta);
}
struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
{
struct sta_info *sta;
@@ -821,11 +930,11 @@ struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
}
for (i = 0; i < WLAN_SUPP_RATES_MAX; i++) {
if (!hapd->iface->basic_rates)
if (!hapd->basic_rates)
break;
if (hapd->iface->basic_rates[i] < 0)
if (hapd->basic_rates[i] <= 0)
break;
sta->supported_rates[i] = hapd->iface->basic_rates[i] / 5;
sta->supported_rates[i] = hapd->basic_rates[i] / 5;
}
sta->supported_rates_len = i;
@@ -856,6 +965,9 @@ struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
&sta->probe_ie_taxonomy);
#endif /* CONFIG_TAXONOMY */
if (!(hapd->conf->mesh & MESH_ENABLED))
eloop_register_timeout(60, 0, ap_sta_assoc_timeout, hapd, sta);
return sta;
}
@@ -924,7 +1036,8 @@ static void ap_sta_disassoc_cb_timeout(void *eloop_ctx, void *timeout_ctx)
static void ap_sta_disconnect_common(struct hostapd_data *hapd,
struct sta_info *sta, unsigned int timeout)
struct sta_info *sta, unsigned int timeout,
bool free_1x)
{
sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
@@ -933,17 +1046,21 @@ static void ap_sta_disconnect_common(struct hostapd_data *hapd,
wpa_printf(MSG_DEBUG,
"reschedule ap_handle_timer timeout (%u sec) for " MACSTR,
MAC2STR(sta->addr), timeout);
timeout, MAC2STR(sta->addr));
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
eloop_register_timeout(timeout, 0, ap_handle_timer, hapd, sta);
accounting_sta_stop(hapd, sta);
ieee802_1x_free_station(hapd, sta);
if (free_1x)
ieee802_1x_free_station(hapd, sta);
#ifdef CONFIG_IEEE80211BE
if (!hapd->conf->mld_ap ||
if (!ap_sta_is_mld(hapd, sta) ||
hapd->mld_link_id == sta->mld_assoc_link_id) {
wpa_auth_sta_deinit(sta->wpa_sm);
struct wpa_state_machine *sm = sta->wpa_sm;
clear_wpa_sm_for_each_partner_link(hapd, sta);
clear_wpa_sm_for_all_sta(hapd, sm);
wpa_auth_sta_deinit(sm);
}
#else /* CONFIG_IEEE80211BE */
wpa_auth_sta_deinit(sta->wpa_sm);
@@ -953,6 +1070,18 @@ static void ap_sta_disconnect_common(struct hostapd_data *hapd,
}
static void ap_sta_disassociate_common(struct hostapd_data *hapd,
struct sta_info *sta, u16 reason)
{
sta->disassoc_reason = reason;
sta->flags |= WLAN_STA_PENDING_DISASSOC_CB;
eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta);
eloop_register_timeout(hapd->iface->drv_flags &
WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0,
ap_sta_disassoc_cb_timeout, hapd, sta);
}
static void ap_sta_handle_disassociate(struct hostapd_data *hapd,
struct sta_info *sta, u16 reason)
{
@@ -970,14 +1099,9 @@ static void ap_sta_handle_disassociate(struct hostapd_data *hapd,
sta->timeout_next = STA_DEAUTH;
}
ap_sta_disconnect_common(hapd, sta, AP_MAX_INACTIVITY_AFTER_DISASSOC);
sta->disassoc_reason = reason;
sta->flags |= WLAN_STA_PENDING_DISASSOC_CB;
eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta);
eloop_register_timeout(hapd->iface->drv_flags &
WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0,
ap_sta_disassoc_cb_timeout, hapd, sta);
ap_sta_disconnect_common(hapd, sta, AP_MAX_INACTIVITY_AFTER_DISASSOC,
true);
ap_sta_disassociate_common(hapd, sta, reason);
}
@@ -993,25 +1117,9 @@ static void ap_sta_deauth_cb_timeout(void *eloop_ctx, void *timeout_ctx)
}
static void ap_sta_handle_deauthenticate(struct hostapd_data *hapd,
static void ap_sta_deauthenticate_common(struct hostapd_data *hapd,
struct sta_info *sta, u16 reason)
{
if (hapd->iface->current_mode &&
hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211AD) {
/* Deauthentication is not used in DMG/IEEE 802.11ad;
* disassociate the STA instead. */
ap_sta_disassociate(hapd, sta, reason);
return;
}
wpa_printf(MSG_DEBUG, "%s: deauthenticate STA " MACSTR,
hapd->conf->iface, MAC2STR(sta->addr));
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
sta->timeout_next = STA_REMOVE;
ap_sta_disconnect_common(hapd, sta, AP_MAX_INACTIVITY_AFTER_DEAUTH);
sta->deauth_reason = reason;
sta->flags |= WLAN_STA_PENDING_DEAUTH_CB;
eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
@@ -1021,9 +1129,47 @@ static void ap_sta_handle_deauthenticate(struct hostapd_data *hapd,
}
static void ap_sta_handle_deauthenticate(struct hostapd_data *hapd,
struct sta_info *sta, u16 reason)
{
wpa_printf(MSG_DEBUG, "%s: deauthenticate STA " MACSTR,
hapd->conf->iface, MAC2STR(sta->addr));
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
sta->timeout_next = STA_REMOVE;
ap_sta_disconnect_common(hapd, sta, AP_MAX_INACTIVITY_AFTER_DEAUTH,
true);
ap_sta_deauthenticate_common(hapd, sta, reason);
}
static void ap_sta_handle_disconnect(struct hostapd_data *hapd,
struct sta_info *sta, u16 reason)
{
wpa_printf(MSG_DEBUG, "%s: disconnect STA " MACSTR,
hapd->conf->iface, MAC2STR(sta->addr));
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
sta->timeout_next = STA_REMOVE;
ap_sta_disconnect_common(hapd, sta, AP_MAX_INACTIVITY_AFTER_DEAUTH,
false);
ap_sta_deauthenticate_common(hapd, sta, reason);
}
enum ap_sta_disconnect_op {
AP_STA_DEAUTHENTICATE,
AP_STA_DISASSOCIATE,
AP_STA_DISCONNECT
};
static bool ap_sta_ml_disconnect(struct hostapd_data *hapd,
struct sta_info *sta, u16 reason,
bool disassoc)
enum ap_sta_disconnect_op op)
{
#ifdef CONFIG_IEEE80211BE
struct hostapd_data *assoc_hapd, *tmp_hapd;
@@ -1031,7 +1177,7 @@ static bool ap_sta_ml_disconnect(struct hostapd_data *hapd,
unsigned int i, link_id;
struct hapd_interfaces *interfaces;
if (!hostapd_is_mld_ap(hapd))
if (!hostapd_is_multiple_link_mld(hapd))
return false;
/*
@@ -1072,25 +1218,30 @@ static bool ap_sta_ml_disconnect(struct hostapd_data *hapd,
tmp_sta->aid != assoc_sta->aid)
continue;
if (disassoc)
if (op == AP_STA_DISASSOCIATE)
ap_sta_handle_disassociate(tmp_hapd,
tmp_sta,
reason);
else
else if (op == AP_STA_DEAUTHENTICATE)
ap_sta_handle_deauthenticate(tmp_hapd,
tmp_sta,
reason);
else
ap_sta_handle_disconnect(tmp_hapd,
tmp_sta,
reason);
break;
}
}
}
/* Disconnect the station on which the association was performed. */
if (disassoc)
if (op == AP_STA_DISASSOCIATE)
ap_sta_handle_disassociate(assoc_hapd, assoc_sta, reason);
else
else if (op == AP_STA_DEAUTHENTICATE)
ap_sta_handle_deauthenticate(assoc_hapd, assoc_sta, reason);
else
ap_sta_handle_disconnect(assoc_hapd, assoc_sta, reason);
return true;
#else /* CONFIG_IEEE80211BE */
@@ -1102,7 +1253,7 @@ static bool ap_sta_ml_disconnect(struct hostapd_data *hapd,
void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
u16 reason)
{
if (ap_sta_ml_disconnect(hapd, sta, reason, true))
if (ap_sta_ml_disconnect(hapd, sta, reason, AP_STA_DISASSOCIATE))
return;
ap_sta_handle_disassociate(hapd, sta, reason);
@@ -1112,7 +1263,15 @@ void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
u16 reason)
{
if (ap_sta_ml_disconnect(hapd, sta, reason, false))
if (hapd->iface->current_mode &&
hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211AD) {
/* Deauthentication is not used in DMG/IEEE 802.11ad;
* disassociate the STA instead. */
ap_sta_disassociate(hapd, sta, reason);
return;
}
if (ap_sta_ml_disconnect(hapd, sta, reason, AP_STA_DEAUTHENTICATE))
return;
ap_sta_handle_deauthenticate(hapd, sta, reason);
@@ -1139,10 +1298,19 @@ int ap_sta_wps_cancel(struct hostapd_data *hapd,
static int ap_sta_get_free_vlan_id(struct hostapd_data *hapd)
{
struct hostapd_vlan *vlan;
struct hostapd_data *vlan_bss = hapd;
int vlan_id = MAX_VLAN_ID + 2;
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap) {
vlan_bss = hostapd_mld_get_first_bss(hapd);
if (!vlan_bss)
vlan_bss = hapd;
}
#endif /* CONFIG_IEEE80211BE */
retry:
for (vlan = hapd->conf->vlan; vlan; vlan = vlan->next) {
for (vlan = vlan_bss->conf->vlan; vlan; vlan = vlan->next) {
if (vlan->vlan_id == vlan_id) {
vlan_id++;
goto retry;
@@ -1152,12 +1320,22 @@ retry:
}
int ap_sta_set_vlan(struct hostapd_data *hapd, struct sta_info *sta,
struct vlan_description *vlan_desc)
static int ap_sta_set_vlan_helper(struct hostapd_data *hapd,
struct sta_info *sta,
struct vlan_description *vlan_desc)
{
struct hostapd_vlan *vlan = NULL, *wildcard_vlan = NULL;
struct hostapd_data *vlan_bss = hapd;
int old_vlan_id, vlan_id = 0, ret = 0;
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap) {
vlan_bss = hostapd_mld_get_first_bss(hapd);
if (!vlan_bss)
vlan_bss = hapd;
}
#endif /* CONFIG_IEEE80211BE */
/* Check if there is something to do */
if (hapd->conf->ssid.per_sta_vif && !sta->vlan_id) {
/* This sta is lacking its own vif */
@@ -1174,7 +1352,7 @@ int ap_sta_set_vlan(struct hostapd_data *hapd, struct sta_info *sta,
/* find a free vlan_id sufficiently big */
vlan_id = ap_sta_get_free_vlan_id(hapd);
/* Get wildcard VLAN */
for (vlan = hapd->conf->vlan; vlan; vlan = vlan->next) {
for (vlan = vlan_bss->conf->vlan; vlan; vlan = vlan->next) {
if (vlan->vlan_id == VLAN_ID_WILDCARD)
break;
}
@@ -1188,7 +1366,7 @@ int ap_sta_set_vlan(struct hostapd_data *hapd, struct sta_info *sta,
goto done;
}
} else if (vlan_desc && vlan_desc->notempty) {
for (vlan = hapd->conf->vlan; vlan; vlan = vlan->next) {
for (vlan = vlan_bss->conf->vlan; vlan; vlan = vlan->next) {
if (!vlan_compare(&vlan->vlan_desc, vlan_desc))
break;
if (vlan->vlan_id == VLAN_ID_WILDCARD)
@@ -1201,10 +1379,10 @@ int ap_sta_set_vlan(struct hostapd_data *hapd, struct sta_info *sta,
vlan_id = vlan_desc->untagged;
if (vlan_desc->tagged[0]) {
/* Tagged VLAN configuration */
vlan_id = ap_sta_get_free_vlan_id(hapd);
vlan_id = ap_sta_get_free_vlan_id(vlan_bss);
}
} else {
hostapd_logger(hapd, sta->addr,
hostapd_logger(vlan_bss, sta->addr,
HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"missing vlan and wildcard for vlan=%d%s",
@@ -1217,9 +1395,9 @@ int ap_sta_set_vlan(struct hostapd_data *hapd, struct sta_info *sta,
}
if (vlan && vlan->vlan_id == VLAN_ID_WILDCARD) {
vlan = vlan_add_dynamic(hapd, vlan, vlan_id, vlan_desc);
vlan = vlan_add_dynamic(vlan_bss, vlan, vlan_id, vlan_desc);
if (vlan == NULL) {
hostapd_logger(hapd, sta->addr,
hostapd_logger(vlan_bss, sta->addr,
HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"could not add dynamic VLAN interface for vlan=%d%s",
@@ -1231,13 +1409,13 @@ int ap_sta_set_vlan(struct hostapd_data *hapd, struct sta_info *sta,
goto done;
}
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
hostapd_logger(vlan_bss, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"added new dynamic VLAN interface '%s'",
vlan->ifname);
} else if (vlan && vlan->dynamic_vlan > 0) {
vlan->dynamic_vlan++;
hostapd_logger(hapd, sta->addr,
hostapd_logger(vlan_bss, sta->addr,
HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"updated existing dynamic VLAN interface '%s'",
@@ -1249,24 +1427,63 @@ done:
sta->vlan_desc = vlan ? &vlan->vlan_desc : NULL;
if (vlan_id != old_vlan_id && old_vlan_id)
vlan_remove_dynamic(hapd, old_vlan_id);
vlan_remove_dynamic(vlan_bss, old_vlan_id);
return ret;
}
int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta)
int ap_sta_set_vlan(struct hostapd_data *hapd, struct sta_info *sta,
struct vlan_description *vlan_desc)
{
int ret;
#ifdef CONFIG_IEEE80211BE
size_t i;
struct hapd_interfaces *interfaces = hapd->iface->interfaces;
#endif /* CONFIG_IEEE80211BE */
ret = ap_sta_set_vlan_helper(hapd, sta, vlan_desc);
if (ret)
return ret;
#ifdef CONFIG_IEEE80211BE
for (i = 0; interfaces && i < interfaces->count; i++) {
struct sta_info *tmp_sta;
struct hostapd_data *tmp_hapd = interfaces->iface[i]->bss[0];
if (!tmp_hapd->conf->mld_ap ||
hapd == tmp_hapd ||
!hostapd_is_ml_partner(hapd, tmp_hapd))
continue;
tmp_sta = ap_get_sta(tmp_hapd, sta->addr);
if (tmp_sta)
ap_sta_set_vlan_helper(tmp_hapd, tmp_sta, vlan_desc);
}
#endif /* CONFIG_IEEE80211BE */
return 0;
}
static int ap_sta_bind_vlan_helper(struct hostapd_data *hapd,
struct sta_info *sta)
{
#ifndef CONFIG_NO_VLAN
const char *iface;
struct hostapd_vlan *vlan = NULL;
struct hostapd_data *vlan_bss = hapd;
int ret;
int old_vlanid = sta->vlan_id_bound;
int mld_link_id = -1;
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap)
if (hapd->conf->mld_ap) {
mld_link_id = hapd->mld_link_id;
vlan_bss = hostapd_mld_get_first_bss(hapd);
if (!vlan_bss)
vlan_bss = hapd;
}
#endif /* CONFIG_IEEE80211BE */
if ((sta->flags & WLAN_STA_WDS) && sta->vlan_id == 0) {
@@ -1281,7 +1498,7 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta)
iface = hapd->conf->ssid.vlan;
if (sta->vlan_id > 0) {
for (vlan = hapd->conf->vlan; vlan; vlan = vlan->next) {
for (vlan = vlan_bss->conf->vlan; vlan; vlan = vlan->next) {
if (vlan->vlan_id == sta->vlan_id)
break;
}
@@ -1299,7 +1516,7 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta)
if (sta->vlan_id > 0 && !vlan &&
!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_VLAN_OFFLOAD)) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
hostapd_logger(vlan_bss, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG, "could not find VLAN for "
"binding station to (vlan_id=%d)",
sta->vlan_id);
@@ -1307,7 +1524,7 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta)
goto done;
} else if (vlan && vlan->dynamic_vlan > 0) {
vlan->dynamic_vlan++;
hostapd_logger(hapd, sta->addr,
hostapd_logger(vlan_bss, sta->addr,
HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"updated existing dynamic VLAN interface '%s'",
@@ -1318,24 +1535,25 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta)
sta->vlan_id_bound = sta->vlan_id;
skip_counting:
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
hostapd_logger(vlan_bss, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG, "binding station to interface "
"'%s'", iface);
if (wpa_auth_sta_set_vlan(sta->wpa_sm, sta->vlan_id) < 0)
if (wpa_auth_sta_set_vlan(sta->wpa_sm, hapd->wpa_auth,
sta->vlan_id) < 0)
wpa_printf(MSG_INFO, "Failed to update VLAN-ID for WPA");
ret = hostapd_drv_set_sta_vlan(iface, hapd, sta->addr, sta->vlan_id,
mld_link_id);
if (ret < 0) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
hostapd_logger(vlan_bss, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG, "could not bind the STA "
"entry to vlan_id=%d", sta->vlan_id);
}
/* During 1x reauth, if the vlan id changes, then remove the old id. */
if (old_vlanid > 0 && old_vlanid != sta->vlan_id)
vlan_remove_dynamic(hapd, old_vlanid);
vlan_remove_dynamic(vlan_bss, old_vlanid);
done:
return ret;
@@ -1345,6 +1563,60 @@ done:
}
int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta)
{
int ret;
#ifdef CONFIG_IEEE80211BE
size_t i;
struct hapd_interfaces *interfaces = hapd->iface->interfaces;
#endif /* CONFIG_IEEE80211BE */
ret = ap_sta_bind_vlan_helper(hapd, sta);
if (ret)
return ret;
#ifdef CONFIG_IEEE80211BE
for (i = 0; interfaces && i < interfaces->count; i++) {
struct sta_info *tmp_sta;
struct hostapd_data *tmp_hapd = interfaces->iface[i]->bss[0];
if (!tmp_hapd->conf->mld_ap ||
hapd == tmp_hapd ||
!hostapd_is_ml_partner(hapd, tmp_hapd))
continue;
tmp_sta = ap_get_sta(tmp_hapd, sta->addr);
if (tmp_sta)
ap_sta_bind_vlan_helper(tmp_hapd, tmp_sta);
}
#endif /* CONFIG_IEEE80211BE */
return 0;
}
void ap_sta_set_sa_query_timeout(struct hostapd_data *hapd,
struct sta_info *sta, int value)
{
sta->sa_query_timed_out = value;
#ifdef CONFIG_IEEE80211BE
if (ap_sta_is_mld(hapd, sta)) {
struct hostapd_data *lhapd;
for_each_mld_link(lhapd, hapd) {
struct sta_info *lsta;
if (lhapd == hapd)
continue;
lsta = ap_get_sta(lhapd, sta->addr);
if (lsta)
lsta->sa_query_timed_out = value;
}
}
#endif /* CONFIG_IEEE80211BE */
}
int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta)
{
u32 tu;
@@ -1357,7 +1629,7 @@ int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta)
HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"association SA Query timed out");
sta->sa_query_timed_out = 1;
ap_sta_set_sa_query_timeout(hapd, sta, 1);
os_free(sta->sa_query_trans_id);
sta->sa_query_trans_id = NULL;
sta->sa_query_count = 0;
@@ -1529,10 +1801,13 @@ void ap_sta_set_authorized_event(struct hostapd_data *hapd,
char dpp_pkhash_buf[100];
char keyid_buf[100];
char ip_addr[100];
char vlanid_buf[20];
dpp_pkhash_buf[0] = '\0';
keyid_buf[0] = '\0';
ip_addr[0] = '\0';
vlanid_buf[0] = '\0';
#ifdef CONFIG_P2P
if (wpa_auth_get_ip_addr(sta->wpa_sm, ip_addr_buf) == 0) {
os_snprintf(ip_addr, sizeof(ip_addr),
@@ -1561,15 +1836,21 @@ void ap_sta_set_authorized_event(struct hostapd_data *hapd,
dpp_pkhash, SHA256_MAC_LEN);
}
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s%s%s",
buf, ip_addr, keyid_buf, dpp_pkhash_buf);
#ifndef CONFIG_NO_VLAN
if (sta->vlan_id)
os_snprintf(vlanid_buf, sizeof(vlanid_buf),
" vlanid=%u", sta->vlan_id);
#endif /* CONFIG_NO_VLAN */
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s%s%s%s",
buf, ip_addr, keyid_buf, dpp_pkhash_buf, vlanid_buf);
if (hapd->msg_ctx_parent &&
hapd->msg_ctx_parent != hapd->msg_ctx)
wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO,
AP_STA_CONNECTED "%s%s%s%s",
AP_STA_CONNECTED "%s%s%s%s%s",
buf, ip_addr, keyid_buf,
dpp_pkhash_buf);
dpp_pkhash_buf, vlanid_buf);
} else {
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf);
@@ -1596,12 +1877,13 @@ void ap_sta_set_authorized_event(struct hostapd_data *hapd,
}
void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta,
bool ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta,
int authorized)
{
if (!ap_sta_set_authorized_flag(hapd, sta, authorized))
return;
return false;
ap_sta_set_authorized_event(hapd, sta, authorized);
return true;
}
@@ -1625,41 +1907,19 @@ void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
if (sta == NULL)
return;
ap_sta_set_authorized(hapd, sta, 0);
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
hostapd_set_sta_flags(hapd, sta);
wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
wpa_printf(MSG_DEBUG, "%s: %s: reschedule ap_handle_timer timeout "
"for " MACSTR " (%d seconds - "
"AP_MAX_INACTIVITY_AFTER_DEAUTH)",
hapd->conf->iface, __func__, MAC2STR(sta->addr),
AP_MAX_INACTIVITY_AFTER_DEAUTH);
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0,
ap_handle_timer, hapd, sta);
sta->timeout_next = STA_REMOVE;
if (hapd->iface->current_mode &&
hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211AD) {
/* Deauthentication is not used in DMG/IEEE 802.11ad;
* disassociate the STA instead. */
sta->disassoc_reason = reason;
sta->flags |= WLAN_STA_PENDING_DISASSOC_CB;
eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta);
eloop_register_timeout(hapd->iface->drv_flags &
WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ?
2 : 0, 0, ap_sta_disassoc_cb_timeout,
hapd, sta);
ap_sta_disassociate_common(hapd, sta, reason);
return;
}
sta->deauth_reason = reason;
sta->flags |= WLAN_STA_PENDING_DEAUTH_CB;
eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
eloop_register_timeout(hapd->iface->drv_flags &
WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0,
ap_sta_deauth_cb_timeout, hapd, sta);
if (ap_sta_ml_disconnect(hapd, sta, reason, AP_STA_DISCONNECT))
return;
ap_sta_handle_disconnect(hapd, sta, reason);
}
@@ -1712,13 +1972,20 @@ void ap_sta_clear_disconnect_timeouts(struct hostapd_data *hapd,
}
void ap_sta_clear_assoc_timeout(struct hostapd_data *hapd,
struct sta_info *sta)
{
eloop_cancel_timeout(ap_sta_assoc_timeout, hapd, sta);
}
int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen)
{
int res;
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]" : ""),
@@ -1741,6 +2008,7 @@ int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen)
(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))
@@ -1825,8 +2093,12 @@ static void ap_sta_remove_link_sta(struct hostapd_data *hapd,
int ap_sta_re_add(struct hostapd_data *hapd, struct sta_info *sta)
{
const u8 *mld_link_addr = NULL;
bool mld_link_sta = false;
bool mld_link_sta = false, epp_sta = false;
u16 eml_cap = 0;
#ifdef CONFIG_ENC_ASSOC
epp_sta = sta->epp_sta;
#endif /* CONFIG_ENC_ASSOC */
/*
* If a station that is already associated to the AP, is trying to
* authenticate again, remove the STA entry, in order to make sure the
@@ -1841,6 +2113,7 @@ int ap_sta_re_add(struct hostapd_data *hapd, struct sta_info *sta)
mld_link_sta = sta->mld_assoc_link_id != mld_link_id;
mld_link_addr = sta->mld_info.links[mld_link_id].peer_addr;
eml_cap = sta->mld_info.common_info.eml_capa;
/*
* In case the AP is affiliated with an AP MLD, we need to
@@ -1859,7 +2132,7 @@ int ap_sta_re_add(struct hostapd_data *hapd, struct sta_info *sta)
sta->supported_rates_len,
0, NULL, NULL, NULL, 0, NULL, 0, NULL,
sta->flags, 0, 0, 0, 0,
mld_link_addr, mld_link_sta)) {
mld_link_addr, mld_link_sta, eml_cap, epp_sta)) {
hostapd_logger(hapd, sta->addr,
HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_NOTICE,
+76 -19
View File
@@ -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)
@@ -70,6 +71,25 @@ struct pending_eapol_rx {
enum frame_encryption encrypted;
};
struct eap_over_auth_data {
int akm;
int cipher;
u16 group;
u16 auth_transaction;
u8 snonce[WPA_NONCE_LEN];
u8 anonce[WPA_NONCE_LEN];
u8 *rsnxe;
u8 pmk[PMK_LEN_MAX];
size_t pmk_len;
struct wpa_ptk ptk;
size_t rsnxe_len;
struct crypto_ecdh *ecdh;
struct wpabuf *dhss;
bool add_mic;
u8 epp_pmkid_cur[PMKID_LEN];
u8 epp_pmkid_next[PMKID_LEN];
};
#define EHT_ML_MAX_STA_PROF_LEN 1024
struct mld_info {
bool mld_sta;
@@ -81,20 +101,7 @@ struct mld_info {
u16 mld_capa;
} common_info;
struct mld_link_info {
u8 valid:1;
u8 nstr_bitmap_len:2;
u8 local_addr[ETH_ALEN];
u8 peer_addr[ETH_ALEN];
u8 nstr_bitmap[2];
u16 capability;
u16 status;
u16 resp_sta_profile_len;
u8 *resp_sta_profile;
} links[MAX_NUM_MLD_LINKS];
struct mld_link_info links[MAX_NUM_MLD_LINKS];
};
struct sta_info {
@@ -111,6 +118,16 @@ struct sta_info {
u8 supported_rates[WLAN_SUPP_RATES_MAX];
int supported_rates_len;
u8 qosinfo; /* Valid when WLAN_STA_WMM is set */
#ifdef CONFIG_ENC_ASSOC
bool epp_sta; /* Indicates if the station is an EPP peer */
#endif /* CONFIG_ENC_ASSOC */
#ifdef CONFIG_PMKSA_PRIVACY
u8 snonce[NONCE_LEN]; /* SNonce to compute next PMKID if
* PMKID caching privacy is on */
u8 anonce[NONCE_LEN]; /* ANonce to compute next PMKID if
* PMKID caching privacy is on */
u8 epp_pmkid_next[PMKID_LEN];
#endif /* CONFIG_PMKSA_PRIVACY */
#ifdef CONFIG_MESH
enum mesh_plink_state plink_state;
@@ -144,7 +161,6 @@ struct sta_info {
unsigned int ht_20mhz_set:1;
unsigned int no_p2p_set:1;
unsigned int qos_map_enabled:1;
unsigned int remediation:1;
unsigned int hs20_deauth_requested:1;
unsigned int hs20_deauth_on_ack:1;
unsigned int session_timeout_set:1;
@@ -230,8 +246,6 @@ struct sta_info {
struct wpabuf *hs20_ie; /* HS 2.0 IE from (Re)Association Request */
/* Hotspot 2.0 Roaming Consortium from (Re)Association Request */
struct wpabuf *roaming_consortium;
u8 remediation_method;
char *remediation_url; /* HS 2.0 Subscription Remediation Server URL */
char *t_c_url; /* HS 2.0 Terms and Conditions Server URL */
struct wpabuf *hs20_deauth_req;
char *hs20_session_info_url;
@@ -277,7 +291,7 @@ struct sta_info {
#endif /* CONFIG_TAXONOMY */
#ifdef CONFIG_FILS
u8 fils_snonce[FILS_NONCE_LEN];
u8 fils_snonce[NONCE_LEN];
u8 fils_session[FILS_SESSION_LEN];
u8 fils_erp_pmkid[PMKID_LEN];
u8 *fils_pending_assoc_req;
@@ -331,10 +345,20 @@ struct sta_info {
#ifdef CONFIG_IEEE80211BE
struct mld_info mld_info;
u8 mld_assoc_link_id;
struct link_reconf_req_list *reconf_req;
#endif /* CONFIG_IEEE80211BE */
u16 max_idle_period; /* if nonzero, the granted BSS max idle period in
* units of 1000 TUs */
u64 last_known_sta_id_timestamp;
struct wpabuf *sae_pw_id;
unsigned int sae_pw_id_counter;
#ifdef CONFIG_IEEE8021X_AUTH
struct eap_over_auth_data eap_auth_data;
#endif /* CONFIG_IEEE8021X_AUTH */
};
@@ -359,6 +383,8 @@ int ap_for_each_sta(struct hostapd_data *hapd,
void *ctx),
void *ctx);
struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta);
struct sta_info * ap_get_link_sta(struct hostapd_data *hapd,
const u8 *link_addr);
struct sta_info * ap_get_sta_p2p(struct hostapd_data *hapd, const u8 *addr);
void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta);
void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta);
@@ -387,6 +413,8 @@ int ap_sta_set_vlan(struct hostapd_data *hapd, struct sta_info *sta,
struct vlan_description *vlan_desc);
void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta);
void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta);
void ap_sta_set_sa_query_timeout(struct hostapd_data *hapd,
struct sta_info *sta, int value);
int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta);
const char * ap_sta_wpa_get_keyid(struct hostapd_data *hapd,
struct sta_info *sta);
@@ -399,7 +427,7 @@ bool ap_sta_set_authorized_flag(struct hostapd_data *hapd, struct sta_info *sta,
int authorized);
void ap_sta_set_authorized_event(struct hostapd_data *hapd,
struct sta_info *sta, int authorized);
void ap_sta_set_authorized(struct hostapd_data *hapd,
bool ap_sta_set_authorized(struct hostapd_data *hapd,
struct sta_info *sta, int authorized);
static inline int ap_sta_is_authorized(struct sta_info *sta)
{
@@ -410,6 +438,8 @@ void ap_sta_deauth_cb(struct hostapd_data *hapd, struct sta_info *sta);
void ap_sta_disassoc_cb(struct hostapd_data *hapd, struct sta_info *sta);
void ap_sta_clear_disconnect_timeouts(struct hostapd_data *hapd,
struct sta_info *sta);
void ap_sta_clear_assoc_timeout(struct hostapd_data *hapd,
struct sta_info *sta);
int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen);
void ap_sta_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
@@ -442,5 +472,32 @@ static inline void ap_sta_set_mld(struct sta_info *sta, bool mld)
void ap_sta_free_sta_profile(struct mld_info *info);
void hostapd_free_link_stas(struct hostapd_data *hapd);
void set_wpa_sm_for_each_partner_link(struct hostapd_data *hapd,
struct sta_info *psta, void *wpa_sm);
void clear_wpa_sm_for_each_partner_link(struct hostapd_data *hapd,
struct sta_info *psta);
void clear_wpa_sm_for_all_sta(struct hostapd_data *hapd,
struct wpa_state_machine *wpa_sm);
static inline bool ap_sta_is_epp(const struct sta_info *sta)
{
#ifdef CONFIG_ENC_ASSOC
return sta && sta->epp_sta;
#else /* CONFIG_ENC_ASSOC */
return false;
#endif /* CONFIG_ENC_ASSOC */
}
static inline bool ap_sta_support_enc_assoc(struct hostapd_data *hapd,
const u8 *rsnxe, size_t rsnxe_len)
{
#ifdef CONFIG_ENC_ASSOC
return (hapd->conf->assoc_frame_encryption &&
ieee802_11_rsnx_capab_len(rsnxe,
rsnxe_len,
WLAN_RSNX_CAPAB_ASSOC_FRAME_ENCRYPTION));
#else /* CONFIG_ENC_ASSOC */
return false;
#endif /* CONFIG_ENC_ASSOC */
}
#endif /* STA_INFO_H */
+20 -2
View File
@@ -462,11 +462,19 @@ void vlan_newlink(const char *ifname, struct hostapd_data *hapd)
{
char br_name[IFNAMSIZ];
struct hostapd_vlan *vlan;
struct hostapd_data *vlan_bss = hapd;
int untagged, *tagged, i, notempty;
wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname);
for (vlan = hapd->conf->vlan; vlan; vlan = vlan->next) {
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap) {
vlan_bss = hostapd_mld_get_first_bss(hapd);
if (vlan_bss == NULL)
vlan_bss = hapd;
}
#endif /* CONFIG_IEEE80211BE */
for (vlan = vlan_bss->conf->vlan; vlan; vlan = vlan->next) {
if (vlan->configured ||
os_strcmp(ifname, vlan->ifname) != 0)
continue;
@@ -563,10 +571,20 @@ static void vlan_put_bridge(const char *br_name, struct hostapd_data *hapd,
void vlan_dellink(const char *ifname, struct hostapd_data *hapd)
{
struct hostapd_vlan *first, *prev, *vlan = hapd->conf->vlan;
struct hostapd_vlan *first, *prev, *vlan;
struct hostapd_data *vlan_bss = hapd;
wpa_printf(MSG_DEBUG, "VLAN: vlan_dellink(%s)", ifname);
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap) {
vlan_bss = hostapd_mld_get_first_bss(hapd);
if (!vlan_bss)
vlan_bss = hapd;
}
#endif /* CONFIG_IEEE80211BE */
vlan = vlan_bss->conf->vlan;
first = prev = vlan;
while (vlan) {
+10 -4
View File
@@ -148,7 +148,7 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
#define MAX_GTK_SUBELEM_LEN 45
#define MAX_IGTK_SUBELEM_LEN 26
#define MAX_BIGTK_SUBELEM_LEN 26
mgmt = os_zalloc(sizeof(*mgmt) + wnmsleep_ie_len +
mgmt = os_zalloc(sizeof(*mgmt) + wnmsleep_ie_len + wnmtfs_ie_len +
MAX_GTK_SUBELEM_LEN + MAX_IGTK_SUBELEM_LEN +
MAX_BIGTK_SUBELEM_LEN +
oci_ie_len);
@@ -740,7 +740,7 @@ static void ieee802_11_rx_wnm_event_report(struct hostapd_data *hapd,
switch (report_ie->type) {
#ifdef CONFIG_IEEE80211AX
case WNM_EVENT_TYPE_BSS_COLOR_COLLISION:
if (!hapd->iconf->ieee80211ax || hapd->conf->disable_11ax)
if (!hostapd_is_he_enabled(hapd))
return;
if (report_ie->len <
fixed_field_len + tsf_len + 8) {
@@ -756,7 +756,7 @@ static void ieee802_11_rx_wnm_event_report(struct hostapd_data *hapd,
hostapd_switch_color(hapd->iface->bss[0], bitmap);
break;
case WNM_EVENT_TYPE_BSS_COLOR_IN_USE:
if (!hapd->iconf->ieee80211ax || hapd->conf->disable_11ax)
if (!hostapd_is_he_enabled(hapd))
return;
if (report_ie->len < fixed_field_len + tsf_len + 1) {
wpa_printf(MSG_DEBUG,
@@ -1030,7 +1030,13 @@ int wnm_send_bss_tm_req(struct hostapd_data *hapd, struct sta_info *sta,
if (disassoc_timer) {
#ifdef CONFIG_IEEE80211BE
if (ap_sta_is_mld(hapd, sta)) {
/* Link removal is scheduled only when the Link Removal Imminent
* field is set to 1 in BTM as per IEEE Std 802.11be-2024,
* 9.6.13.9 (BSS Transition Management Request frame format);
* else schedule full disconnection.
*/
if (ap_sta_is_mld(hapd, sta) &&
(req_mode & WNM_BSS_TM_REQ_LINK_REMOVAL_IMMINENT)) {
int i;
unsigned int links = 0;
File diff suppressed because it is too large. Load diff
+130 -17
View File
@@ -17,7 +17,7 @@
struct vlan_description;
struct mld_info;
#define MAX_OWN_IE_OVERRIDE 256
#define MAX_OWN_IE_OVERRIDE 257
#ifdef _MSC_VER
#pragma pack(push, 1)
@@ -173,6 +173,8 @@ struct wpa_auth_config {
int wpa;
int extended_key_id;
int wpa_key_mgmt;
int rsn_override_key_mgmt;
int rsn_override_key_mgmt_2;
int wpa_pairwise;
int wpa_group;
int wpa_group_rekey;
@@ -184,6 +186,8 @@ struct wpa_auth_config {
u32 wpa_pairwise_update_count;
int wpa_disable_eapol_key_retries;
int rsn_pairwise;
int rsn_override_pairwise;
int rsn_override_pairwise_2;
int rsn_preauth;
int eapol_version;
int wmm_enabled;
@@ -192,6 +196,8 @@ struct wpa_auth_config {
int okc;
int tx_status;
enum mfp_options ieee80211w;
enum mfp_options rsn_override_mfp;
enum mfp_options rsn_override_mfp_2;
int beacon_prot;
int group_mgmt_cipher;
int sae_require_mfp;
@@ -224,6 +230,21 @@ struct wpa_auth_config {
double corrupt_gtk_rekey_mic_probability;
u8 own_ie_override[MAX_OWN_IE_OVERRIDE];
size_t own_ie_override_len;
bool rsne_override_set;
u8 rsne_override[MAX_OWN_IE_OVERRIDE];
size_t rsne_override_len;
bool rsnoe_override_set;
u8 rsnoe_override[MAX_OWN_IE_OVERRIDE];
size_t rsnoe_override_len;
bool rsno2e_override_set;
u8 rsno2e_override[MAX_OWN_IE_OVERRIDE];
size_t rsno2e_override_len;
bool rsnxe_override_set;
u8 rsnxe_override[MAX_OWN_IE_OVERRIDE];
size_t rsnxe_override_len;
bool rsnxoe_override_set;
u8 rsnxoe_override[MAX_OWN_IE_OVERRIDE];
size_t rsnxoe_override_len;
u8 rsne_override_eapol[MAX_OWN_IE_OVERRIDE];
size_t rsne_override_eapol_len;
u8 rsnxe_override_eapol[MAX_OWN_IE_OVERRIDE];
@@ -245,6 +266,7 @@ struct wpa_auth_config {
struct wpabuf *eapol_m1_elements;
struct wpabuf *eapol_m3_elements;
bool eapol_m3_no_encrypt;
bool eapol_key_reserved_random;
#endif /* CONFIG_TESTING_OPTIONS */
unsigned int oci_freq_override_eapol_m3;
unsigned int oci_freq_override_eapol_g1;
@@ -262,10 +284,21 @@ struct wpa_auth_config {
#endif /* CONFIG_FILS */
enum sae_pwe sae_pwe;
bool sae_pk;
bool urnm_mfpr_x20;
bool urnm_mfpr;
unsigned int secure_ltf:1;
unsigned int secure_rtt:1;
unsigned int prot_range_neg:1;
#ifdef CONFIG_ENC_ASSOC
unsigned int assoc_frame_encryption:1;
unsigned int pmksa_caching_privacy:1;
unsigned int eap_using_authentication_frames:1;
#ifdef CONFIG_PASN
/* Whether to allow unauthenticated EPPKE (EPPKE without base AKM) */
bool eppke_unauth;
#endif /* CONFIG_PASN */
#endif /* CONFIG_ENC_ASSOC */
int owe_ptk_workaround;
u8 transition_disable;
@@ -295,6 +328,14 @@ struct wpa_auth_config {
#endif /* CONFIG_IEEE80211BE */
bool ssid_protection;
int rsn_override_omit_rsnxe;
int rsn_override_mlo_compat;
bool spp_amsdu;
unsigned int sae_pw_id_num;
u8 sae_pw_id_key[32];
};
typedef enum {
@@ -355,6 +396,12 @@ struct wpa_auth_callbacks {
void *ctx), void *cb_ctx);
int (*for_each_auth)(void *ctx, int (*cb)(struct wpa_authenticator *a,
void *ctx), void *cb_ctx);
#ifdef CONFIG_IEEE80211BE
int (*for_each_partner_auth)(void *ctx,
int (*cb)(struct wpa_authenticator *a,
void *ctx),
void *cb_ctx);
#endif /* CONFIG_IEEE80211BE */
int (*send_ether)(void *ctx, const u8 *dst, u16 proto, const u8 *data,
size_t data_len);
int (*send_oui)(void *ctx, const u8 *dst, u8 oui_suffix, const u8 *data,
@@ -389,8 +436,6 @@ struct wpa_auth_callbacks {
int (*send_ft_action)(void *ctx, const u8 *dst,
const u8 *data, size_t data_len);
int (*add_tspec)(void *ctx, const u8 *sta_addr, u8 *tspec_ie,
size_t tspec_ielen);
#endif /* CONFIG_IEEE80211R_AP */
#ifdef CONFIG_MESH
int (*start_ampe)(void *ctx, const u8 *sta_addr);
@@ -400,9 +445,13 @@ struct wpa_auth_callbacks {
size_t ltf_keyseed_len);
#endif /* CONFIG_PASN */
#ifdef CONFIG_IEEE80211BE
int (*get_ml_key_info)(void *ctx, struct wpa_auth_ml_key_info *info);
int (*get_ml_key_info)(void *ctx, struct wpa_auth_ml_key_info *info,
bool rekey, int vlan_id);
struct wpa_authenticator * (*next_primary_auth)(void *ctx);
#endif /* CONFIG_IEEE80211BE */
int (*get_drv_flags)(void *ctx, u64 *drv_flags, u64 *drv_flags2);
int (*remove_pmkid)(void *ctx, const u8 *sta_addr, const u8 *pmkid);
bool (*first_sta_seen_mbssid)(void *ctx, int vlan_id);
};
struct wpa_authenticator * wpa_init(const u8 *addr,
@@ -429,11 +478,13 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
const u8 *rsnxe, size_t rsnxe_len,
const u8 *mdie, size_t mdie_len,
const u8 *owe_dh, size_t owe_dh_len,
struct wpa_state_machine *assoc_sm);
struct wpa_state_machine *assoc_sm,
bool is_ml);
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 *
@@ -462,6 +513,8 @@ int wpa_auth_get_pairwise(struct wpa_state_machine *sm);
const u8 * wpa_auth_get_pmk(struct wpa_state_machine *sm, int *len);
const u8 * wpa_auth_get_dpp_pkhash(struct wpa_state_machine *sm);
int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm);
bool wpa_auth_get_first_sta_seen(struct wpa_authenticator *wpa_auth,
int vlan_id);
int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm);
int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm);
int wpa_auth_sta_fils_tk_already_set(struct wpa_state_machine *sm);
@@ -481,11 +534,12 @@ int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
struct eapol_state_machine *eapol);
int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr,
const u8 *pmk, size_t pmk_len, const u8 *pmkid,
int akmp);
int akmp, bool is_ml, int vlan_id);
void wpa_auth_add_sae_pmkid(struct wpa_state_machine *sm, const u8 *pmkid);
int wpa_auth_pmksa_add2(struct wpa_authenticator *wpa_auth, const u8 *addr,
const u8 *pmk, size_t pmk_len, const u8 *pmkid,
int session_timeout, int akmp, const u8 *dpp_pkhash);
int session_timeout, int akmp, const u8 *dpp_pkhash,
bool is_ml);
void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth,
const u8 *sta_addr);
int wpa_auth_pmksa_list(struct wpa_authenticator *wpa_auth, char *buf,
@@ -500,10 +554,13 @@ wpa_auth_pmksa_create_entry(const u8 *aa, const u8 *spa, const u8 *pmk,
int wpa_auth_pmksa_add_entry(struct wpa_authenticator *wpa_auth,
struct rsn_pmksa_cache_entry *entry);
struct rsn_pmksa_cache *
wpa_auth_get_pmksa_cache(struct wpa_authenticator *wpa_auth);
wpa_auth_get_pmksa_cache(struct wpa_authenticator *wpa_auth, bool is_ml);
struct rsn_pmksa_cache_entry *
wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr,
const u8 *pmkid);
int wpa_auth_pmksa_get_pmk(struct wpa_authenticator *wpa_auth,
const u8 *sta_addr, const u8 **pmk, size_t *pmk_len,
const u8 **pmkid);
struct rsn_pmksa_cache_entry *
wpa_auth_pmksa_get_fils_cache_id(struct wpa_authenticator *wpa_auth,
const u8 *sta_addr, const u8 *pmkid);
@@ -511,15 +568,17 @@ void wpa_auth_pmksa_set_to_sm(struct rsn_pmksa_cache_entry *pmksa,
struct wpa_state_machine *sm,
struct wpa_authenticator *wpa_auth,
u8 *pmkid, u8 *pmk, size_t *pmk_len);
int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id);
int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm,
struct wpa_authenticator *wpa_auth, int vlan_id);
void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth,
struct wpa_state_machine *sm, int ack);
bool wpa_auth_ap_sta_support_pmkid_privacy(struct wpa_state_machine *sm);
#ifdef CONFIG_IEEE80211R_AP
u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
size_t max_len, int auth_alg,
const u8 *req_ies, size_t req_ies_len,
int omit_rsnxe);
int omit_rsnxe, bool reassoc, int vlan_id);
void wpa_ft_process_auth(struct wpa_state_machine *sm,
u16 auth_transaction, const u8 *ies, size_t ies_len,
void (*cb)(void *ctx, const u8 *dst,
@@ -597,19 +656,34 @@ void wpa_auth_get_fils_aead_params(struct wpa_state_machine *sm,
void wpa_auth_add_fils_pmk_pmkid(struct wpa_state_machine *sm, const u8 *pmk,
size_t pmk_len, const u8 *pmkid);
u8 * wpa_auth_write_assoc_resp_owe(struct wpa_state_machine *sm,
u8 *pos, size_t max_len,
const u8 *req_ies, size_t req_ies_len);
u8 *pos, size_t max_len);
u8 * wpa_auth_write_assoc_resp_fils(struct wpa_state_machine *sm,
u8 *pos, size_t max_len,
const u8 *req_ies, size_t req_ies_len);
u8 *pos, size_t max_len);
bool wpa_auth_write_fd_rsn_info(struct wpa_authenticator *wpa_auth,
u8 *fd_rsn_info);
void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg);
void wpa_auth_set_hash_alg_sae_ext_key(struct wpa_state_machine *sm,
size_t pmk_len);
void wpa_auth_set_rsn_selection(struct wpa_state_machine *sm, const u8 *ie,
size_t len);
void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z);
void wpa_auth_set_ssid_protection(struct wpa_state_machine *sm, bool val);
void wpa_auth_set_transition_disable(struct wpa_authenticator *wpa_auth,
u8 val);
u8 * wpa_auth_eid_key_delivery(u8 *eid, size_t max_len,
struct wpa_state_machine *sm,
bool is_ml);
u8 * wpa_auth_write_assoc_resp_eppke(struct wpa_state_machine *sm,
u8 *pos, size_t max_len, bool is_ml);
void wpa_store_eppke_pmk_ptk_sm(struct wpa_state_machine *sm,
const struct wpa_ptk *ptk, const u8 *pmk,
size_t pmk_len);
int wpa_auth_epp_derive_new_pmkid(const u8 *anonce, const u8 *snonce,
int akmp, size_t pmk_len, u8 *pmkid);
bool wpa_auth_ap_sta_support_assoc_enc(struct wpa_state_machine *sm);
void wpa_auth_ensure_group_init(struct wpa_state_machine *sm);
int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce,
void (*cb)(void *ctx1, void *ctx2),
void *ctx1, void *ctx2);
@@ -644,10 +718,18 @@ void wpa_auth_set_ml_info(struct wpa_state_machine *sm,
u8 mld_assoc_link_id, struct mld_info *info);
void wpa_auth_ml_get_key_info(struct wpa_authenticator *a,
struct wpa_auth_ml_link_key_info *info,
bool mgmt_frame_prot, bool beacon_prot);
bool mgmt_frame_prot, bool beacon_prot,
bool rekey, int vlan_id);
void wpa_release_link_auth_ref(struct wpa_state_machine *sm,
int release_link_id);
void wpa_release_link_auth_ref(struct wpa_state_machine *sm, u8 link_id,
bool rejected);
size_t wpa_auth_ml_group_kdes_len(struct wpa_state_machine *sm, u16 req_links);
u8 * wpa_auth_ml_group_kdes(struct wpa_state_machine *sm, u8 *pos,
u16 req_links);
void wpa_reset_assoc_sm_info(struct wpa_state_machine *assoc_sm,
struct wpa_authenticator *wpa_auth,
u8 mld_assoc_link_id);
#define for_each_sm_auth(sm, link_id) \
for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) \
@@ -655,4 +737,35 @@ void wpa_release_link_auth_ref(struct wpa_state_machine *sm,
sm->mld_links[link_id].wpa_auth && \
sm->wpa_auth != sm->mld_links[link_id].wpa_auth)
static inline bool wpa_auth_pmf_enabled(struct wpa_auth_config *conf)
{
return conf->ieee80211w != NO_MGMT_FRAME_PROTECTION ||
conf->rsn_override_mfp != NO_MGMT_FRAME_PROTECTION ||
conf->rsn_override_mfp_2 != NO_MGMT_FRAME_PROTECTION;
}
bool wpa_auth_sm_known_sta_identification(struct wpa_state_machine *sm,
const u8 *timestamp,
const u8 *mic, size_t mic_len);
struct wpa_group * wpa_select_vlan_wpa_group(struct wpa_group *gsm,
int vlan_id);
void wpa_auth_set_sae_pw_id(struct wpa_state_machine *sm,
const struct wpabuf *pw_id,
unsigned int counter);
int wpa_auth_802_1x_get_msk(struct wpa_authenticator *wpa_auth,
const u8 *addr, u8 *msk, size_t *len);
int wpa_auth_802_1x_set_key(struct wpa_authenticator *wpa_auth,
enum wpa_alg alg, const u8 *addr,
u8 *key, size_t key_len);
bool wpa_auth_ap_support_secure_ltf(struct wpa_authenticator *wpa_auth);
int wpa_write_802_1x_rsne(struct wpa_authenticator *wpa_auth, u8 *buf,
size_t len, const u8 *pmkid, int akmp,
int pairwise_cipher, int group_cipher,
int group_mgmt_cipher, enum mfp_options mfp);
int wpa_write_eppke_rsne(const u8 *wpa_ie, size_t wpa_ie_len,
u8 *buf, size_t len,
const u8 *pmkid, int akmp,
int pairwise_cipher, enum mfp_options mfp);
#endif /* WPA_AUTH_H */
+49 -67
View File
@@ -765,19 +765,6 @@ wpa_ft_get_session_timeout(struct wpa_authenticator *wpa_auth,
}
static int wpa_ft_add_tspec(struct wpa_authenticator *wpa_auth,
const u8 *sta_addr,
u8 *tspec_ie, size_t tspec_ielen)
{
if (wpa_auth->cb->add_tspec == NULL) {
wpa_printf(MSG_DEBUG, "FT: add_tspec is not initialized");
return -1;
}
return wpa_auth->cb->add_tspec(wpa_auth->cb_ctx, sta_addr, tspec_ie,
tspec_ielen);
}
#ifdef CONFIG_OCV
static int wpa_channel_info(struct wpa_authenticator *wpa_auth,
struct wpa_channel_info *ci)
@@ -2212,7 +2199,8 @@ static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth,
}
static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len)
static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len,
bool reassoc, int vlan_id)
{
u8 *subelem;
struct wpa_auth_config *conf = &sm->wpa_auth->conf;
@@ -2224,6 +2212,11 @@ static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len)
const u8 *kek;
size_t kek_len;
#ifdef CONFIG_IEEE80211BE
if (reassoc && vlan_id)
gsm = wpa_select_vlan_wpa_group(gsm, vlan_id);
#endif /* CONFIG_IEEE80211BE */
if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
kek = sm->PTK.kek2;
kek_len = sm->PTK.kek2_len;
@@ -2247,8 +2240,7 @@ static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len)
pad_len += 8;
if (pad_len && key_len < sizeof(keybuf)) {
os_memcpy(keybuf, gsm->GTK[gsm->GN - 1], key_len);
if (conf->disable_gtk ||
sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
if (conf->disable_gtk) {
/*
* Provide unique random GTK to each STA to prevent use
* of GTK in the BSS.
@@ -2260,7 +2252,7 @@ static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len)
keybuf[key_len] = 0xdd;
key_len += pad_len;
key = keybuf;
} else if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
} else if (conf->disable_gtk) {
/*
* Provide unique random GTK to each STA to prevent use of GTK
* in the BSS.
@@ -2339,7 +2331,7 @@ static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len)
pos += 6;
*pos++ = igtk_len;
igtk = gsm->IGTK[gsm->GN_igtk - 4];
if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
if (conf->disable_gtk) {
/*
* Provide unique random IGTK to each STA to prevent use of
* IGTK in the BSS.
@@ -2372,7 +2364,6 @@ static u8 * wpa_ft_bigtk_subelem(struct wpa_state_machine *sm, size_t *len)
const u8 *kek, *bigtk;
size_t kek_len;
size_t bigtk_len;
u8 stub_bigtk[WPA_IGTK_MAX_LEN];
if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
kek = sm->PTK.kek2;
@@ -2400,17 +2391,6 @@ static u8 * wpa_ft_bigtk_subelem(struct wpa_state_machine *sm, size_t *len)
pos += 6;
*pos++ = bigtk_len;
bigtk = gsm->BIGTK[gsm->GN_bigtk - 6];
if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
/*
* Provide unique random BIGTK to each OSEN STA to prevent use
* of BIGTK in the BSS.
*/
if (random_get_bytes(stub_bigtk, bigtk_len / 8) < 0) {
os_free(subelem);
return NULL;
}
bigtk = stub_bigtk;
}
if (aes_wrap(kek, kek_len, bigtk_len / 8, bigtk, pos)) {
wpa_printf(MSG_DEBUG,
"FT: BIGTK subelem encryption failed: kek_len=%d",
@@ -2499,24 +2479,6 @@ static u8 * wpa_ft_process_rdie(struct wpa_state_machine *sm,
}
#endif /* NEED_AP_MLME */
if (parse.wmm_tspec && !sm->wpa_auth->conf.ap_mlme) {
int res;
res = wpa_ft_add_tspec(sm->wpa_auth, sm->addr, pos,
sizeof(struct wmm_tspec_element));
if (res >= 0) {
if (res)
rdie->status_code = host_to_le16(res);
else {
/* TSPEC accepted; include updated TSPEC in
* response */
rdie->descr_count = 1;
pos += sizeof(struct wmm_tspec_element);
}
return pos;
}
}
wpa_printf(MSG_DEBUG, "FT: No supported resource requested");
rdie->status_code = host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE);
return pos;
@@ -2558,7 +2520,7 @@ static u8 * wpa_ft_process_ric(struct wpa_state_machine *sm, u8 *pos, u8 *end,
u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
size_t max_len, int auth_alg,
const u8 *req_ies, size_t req_ies_len,
int omit_rsnxe)
int omit_rsnxe, bool reassoc, int vlan_id)
{
u8 *end, *mdie, *ftie, *rsnie = NULL, *r0kh_id, *subelem = NULL;
u8 *fte_mic, *elem_count;
@@ -2648,7 +2610,8 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
/* Fast BSS Transition Information */
if (auth_alg == WLAN_AUTH_FT) {
subelem = wpa_ft_gtk_subelem(sm, &subelem_len);
subelem = wpa_ft_gtk_subelem(sm, &subelem_len, reassoc,
vlan_id);
if (!subelem) {
wpa_printf(MSG_DEBUG,
"FT: Failed to add GTK subelement");
@@ -3204,19 +3167,19 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm,
sm->wpa_auth->conf.mobility_domain,
MOBILITY_DOMAIN_ID_LEN) != 0) {
wpa_printf(MSG_DEBUG, "FT: Invalid MDIE");
retval = WLAN_STATUS_INVALID_MDIE;
retval = WLAN_STATUS_INVALID_MDE;
goto out;
}
if (!parse.ftie || parse.ftie_len < sizeof(struct rsn_ftie)) {
wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
retval = WLAN_STATUS_INVALID_FTIE;
retval = WLAN_STATUS_INVALID_FTE;
goto out;
}
if (parse.r0kh_id == NULL) {
wpa_printf(MSG_DEBUG, "FT: Invalid FTIE - no R0KH-ID");
retval = WLAN_STATUS_INVALID_FTIE;
retval = WLAN_STATUS_INVALID_FTE;
goto out;
}
@@ -3314,6 +3277,25 @@ pmk_r1_derived:
os_memcpy(sm->pmk_r1, pmk_r1, pmk_r1_len);
sm->pmk_r1_len = pmk_r1_len;
/*
* Make sure the pairwise suite indicate by the STA matches the one that
* was used during initial mobility domain association.
*/
if (!(parse.pairwise_cipher & pairwise)) {
wpa_printf(MSG_ERROR,
"FT: Pairwise cipher from PMK-R1 cache (0x%x) not used in the RSNE (0x%x) - reject",
pairwise, parse.pairwise_cipher);
retval = WLAN_STATUS_INVALID_PAIRWISE_CIPHER;
goto out;
}
if (sm->pmk_r1_len == SHA512_MAC_LEN)
sm->hash_alg = RSN_HASH_SHA512;
else if (sm->pmk_r1_len == SHA384_MAC_LEN)
sm->hash_alg = RSN_HASH_SHA384;
else
sm->hash_alg = RSN_HASH_SHA256;
if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
wpa_printf(MSG_DEBUG, "FT: Failed to get random data for "
"ANonce");
@@ -3328,7 +3310,7 @@ pmk_r1_derived:
ftie = (const struct rsn_ftie_sha512 *) parse.ftie;
if (!ftie || parse.ftie_len < sizeof(*ftie)) {
wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
retval = WLAN_STATUS_INVALID_FTIE;
retval = WLAN_STATUS_INVALID_FTE;
goto out;
}
@@ -3339,7 +3321,7 @@ pmk_r1_derived:
ftie = (const struct rsn_ftie_sha384 *) parse.ftie;
if (!ftie || parse.ftie_len < sizeof(*ftie)) {
wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
retval = WLAN_STATUS_INVALID_FTIE;
retval = WLAN_STATUS_INVALID_FTE;
goto out;
}
@@ -3350,7 +3332,7 @@ pmk_r1_derived:
ftie = (const struct rsn_ftie *) parse.ftie;
if (!ftie || parse.ftie_len < sizeof(*ftie)) {
wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
retval = WLAN_STATUS_INVALID_FTIE;
retval = WLAN_STATUS_INVALID_FTE;
goto out;
}
@@ -3536,7 +3518,7 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
os_memcmp(mdie->mobility_domain, conf->mobility_domain,
MOBILITY_DOMAIN_ID_LEN) != 0) {
wpa_printf(MSG_DEBUG, "FT: Invalid MDIE");
retval = WLAN_STATUS_INVALID_MDIE;
retval = WLAN_STATUS_INVALID_MDE;
goto out;
}
@@ -3555,7 +3537,7 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
wpa_printf(MSG_DEBUG,
"FT: Invalid FTE (fte_mic_len=%zu mic_len=%zu)",
parse.fte_mic_len, mic_len);
retval = WLAN_STATUS_INVALID_FTIE;
retval = WLAN_STATUS_INVALID_FTE;
goto out;
}
@@ -3565,7 +3547,7 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
parse.fte_snonce, WPA_NONCE_LEN);
wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce",
sm->SNonce, WPA_NONCE_LEN);
retval = WLAN_STATUS_INVALID_FTIE;
retval = WLAN_STATUS_INVALID_FTE;
goto out;
}
@@ -3575,13 +3557,13 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
parse.fte_anonce, WPA_NONCE_LEN);
wpa_hexdump(MSG_DEBUG, "FT: Expected ANonce",
sm->ANonce, WPA_NONCE_LEN);
retval = WLAN_STATUS_INVALID_FTIE;
retval = WLAN_STATUS_INVALID_FTE;
goto out;
}
if (parse.r0kh_id == NULL) {
wpa_printf(MSG_DEBUG, "FT: No R0KH-ID subelem in FTIE");
retval = WLAN_STATUS_INVALID_FTIE;
retval = WLAN_STATUS_INVALID_FTE;
goto out;
}
@@ -3594,13 +3576,13 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
parse.r0kh_id, parse.r0kh_id_len);
wpa_hexdump(MSG_DEBUG, "FT: The current R0KH-ID",
sm->r0kh_id, sm->r0kh_id_len);
retval = WLAN_STATUS_INVALID_FTIE;
retval = WLAN_STATUS_INVALID_FTE;
goto out;
}
if (parse.r1kh_id == NULL) {
wpa_printf(MSG_DEBUG, "FT: No R1KH-ID subelem in FTIE");
retval = WLAN_STATUS_INVALID_FTIE;
retval = WLAN_STATUS_INVALID_FTE;
goto out;
}
@@ -3612,7 +3594,7 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
parse.r1kh_id, FT_R1KH_ID_LEN);
wpa_hexdump(MSG_DEBUG, "FT: Expected R1KH-ID",
conf->r1_key_holder, FT_R1KH_ID_LEN);
retval = WLAN_STATUS_INVALID_FTIE;
retval = WLAN_STATUS_INVALID_FTE;
goto out;
}
@@ -3674,7 +3656,7 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
wpa_hexdump(MSG_MSGDUMP, "FT: RSNXE",
parse.rsnxe ? parse.rsnxe - 2 : NULL,
parse.rsnxe ? parse.rsnxe_len + 2 : 0);
retval = WLAN_STATUS_INVALID_FTIE;
retval = WLAN_STATUS_INVALID_FTE;
goto out;
}
@@ -3721,7 +3703,7 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
OCV_FAILURE "addr=" MACSTR
" frame=ft-reassoc-req error=%s",
MAC2STR(sm->addr), ocv_errorstr);
retval = WLAN_STATUS_INVALID_FTIE;
retval = WLAN_STATUS_INVALID_FTE;
goto out;
}
}
@@ -3818,7 +3800,7 @@ static void wpa_ft_rrb_rx_request_cb(void *ctx, const u8 *dst,
wpa_printf(MSG_DEBUG, "FT: Over-the-DS RX request cb for " MACSTR,
MAC2STR(sm->addr));
wpa_ft_send_rrb_auth_resp(sm, sm->ft_pending_current_ap, sm->addr,
WLAN_STATUS_SUCCESS, ies, ies_len);
resp, ies, ies_len);
}
+254 -95
View File
@@ -35,7 +35,82 @@
#include "wpa_auth_glue.h"
static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
static void hostapd_wpa_auth_config_update(struct hostapd_data *hapd,
struct wpa_auth_config *_conf)
{
struct hostapd_data *tx_bss;
_conf->msg_ctx = hapd->msg_ctx;
tx_bss = hostapd_mbssid_get_tx_bss(hapd);
if (tx_bss != hapd)
_conf->tx_bss_auth = tx_bss->wpa_auth;
if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EAPOL_TX_STATUS)
_conf->tx_status = 1;
if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_MLME)
_conf->ap_mlme = 1;
if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
(hapd->conf->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
(hapd->conf->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
wpa_msg(hapd->msg_ctx, MSG_INFO,
"Disable PTK0 rekey support - replaced with disconnect");
_conf->wpa_deny_ptk0_rekey = 1;
}
if (_conf->extended_key_id &&
(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID))
wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Extended Key ID supported");
else
_conf->extended_key_id = 0;
if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_BEACON_PROTECTION))
_conf->beacon_prot = 0;
#ifdef CONFIG_OCV
if (!(hapd->iface->drv_flags2 &
(WPA_DRIVER_FLAGS2_AP_SME | WPA_DRIVER_FLAGS2_OCV)))
_conf->ocv = 0;
#endif /* CONFIG_OCV */
_conf->secure_ltf =
!!(hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF_AP);
_conf->secure_rtt =
!!(hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_RTT_AP);
_conf->prot_range_neg =
!!(hapd->iface->drv_flags2 &
WPA_DRIVER_FLAGS2_PROT_RANGE_NEG_AP);
#ifdef CONFIG_ENC_ASSOC
if (!(hapd->iface->drv_flags2 &
WPA_DRIVER_FLAGS2_ASSOCIATION_FRAME_ENCRYPTION))
_conf->assoc_frame_encryption = 0;
#endif /* CONFIG_ENC_ASSOC */
#ifdef CONFIG_IEEE80211BE
_conf->mld_addr = NULL;
_conf->link_id = -1;
_conf->first_link_auth = NULL;
if (hapd->conf->mld_ap) {
struct hostapd_data *lhapd;
_conf->mld_addr = hapd->mld->mld_addr;
_conf->link_id = hapd->mld_link_id;
for_each_mld_link(lhapd, hapd) {
if (lhapd == hapd)
continue;
if (lhapd->wpa_auth)
_conf->first_link_auth = lhapd->wpa_auth;
}
}
#endif /* CONFIG_IEEE80211BE */
}
static void hostapd_wpa_auth_conf(struct hostapd_iface *iface,
struct hostapd_bss_config *conf,
struct hostapd_config *iconf,
struct wpa_auth_config *wconf)
{
@@ -43,8 +118,16 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
os_memset(wconf, 0, sizeof(*wconf));
wconf->wpa = conf->wpa;
#ifdef CONFIG_ENC_ASSOC
wconf->assoc_frame_encryption = conf->assoc_frame_encryption;
wconf->pmksa_caching_privacy = conf->pmksa_caching_privacy;
wconf->eap_using_authentication_frames =
conf->eap_using_authentication_frames;
#endif /* CONFIG_ENC_ASSOC */
wconf->extended_key_id = conf->extended_key_id;
wconf->wpa_key_mgmt = conf->wpa_key_mgmt;
wconf->rsn_override_key_mgmt = conf->rsn_override_key_mgmt;
wconf->rsn_override_key_mgmt_2 = conf->rsn_override_key_mgmt_2;
wconf->wpa_pairwise = conf->wpa_pairwise;
wconf->wpa_group = conf->wpa_group;
wconf->wpa_group_rekey = conf->wpa_group_rekey;
@@ -56,6 +139,8 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
conf->wpa_disable_eapol_key_retries;
wconf->wpa_pairwise_update_count = conf->wpa_pairwise_update_count;
wconf->rsn_pairwise = conf->rsn_pairwise;
wconf->rsn_override_pairwise = conf->rsn_override_pairwise;
wconf->rsn_override_pairwise_2 = conf->rsn_override_pairwise_2;
wconf->rsn_preauth = conf->rsn_preauth;
wconf->eapol_version = conf->eapol_version;
#ifdef CONFIG_MACSEC
@@ -70,6 +155,8 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
#endif /* CONFIG_OCV */
wconf->okc = conf->okc;
wconf->ieee80211w = conf->ieee80211w;
wconf->rsn_override_mfp = conf->rsn_override_mfp;
wconf->rsn_override_mfp_2 = conf->rsn_override_mfp_2;
wconf->beacon_prot = conf->beacon_prot;
wconf->group_mgmt_cipher = conf->group_mgmt_cipher;
wconf->sae_require_mfp = conf->sae_require_mfp;
@@ -103,17 +190,6 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
#endif /* CONFIG_IEEE80211R_AP */
#ifdef CONFIG_HS20
wconf->disable_gtk = conf->disable_dgaf;
if (conf->osen) {
wconf->disable_gtk = 1;
wconf->wpa = WPA_PROTO_OSEN;
wconf->wpa_key_mgmt = WPA_KEY_MGMT_OSEN;
wconf->wpa_pairwise = 0;
wconf->wpa_group = WPA_CIPHER_CCMP;
wconf->rsn_pairwise = WPA_CIPHER_CCMP;
wconf->rsn_preauth = 0;
wconf->disable_pmksa_caching = 1;
wconf->ieee80211w = 1;
}
#endif /* CONFIG_HS20 */
#ifdef CONFIG_TESTING_OPTIONS
wconf->corrupt_gtk_rekey_mic_probability =
@@ -126,6 +202,46 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
wpabuf_head(conf->own_ie_override),
wconf->own_ie_override_len);
}
if (conf->rsne_override &&
wpabuf_len(conf->rsne_override) <= MAX_OWN_IE_OVERRIDE) {
wconf->rsne_override_len = wpabuf_len(conf->rsne_override);
os_memcpy(wconf->rsne_override,
wpabuf_head(conf->rsne_override),
wconf->rsne_override_len);
wconf->rsne_override_set = true;
}
if (conf->rsnoe_override &&
wpabuf_len(conf->rsnoe_override) <= MAX_OWN_IE_OVERRIDE) {
wconf->rsnoe_override_len = wpabuf_len(conf->rsnoe_override);
os_memcpy(wconf->rsnoe_override,
wpabuf_head(conf->rsnoe_override),
wconf->rsnoe_override_len);
wconf->rsnoe_override_set = true;
}
if (conf->rsno2e_override &&
wpabuf_len(conf->rsno2e_override) <= MAX_OWN_IE_OVERRIDE) {
wconf->rsno2e_override_len = wpabuf_len(conf->rsno2e_override);
os_memcpy(wconf->rsno2e_override,
wpabuf_head(conf->rsno2e_override),
wconf->rsno2e_override_len);
wconf->rsno2e_override_set = true;
}
if (conf->rsnxe_override &&
wpabuf_len(conf->rsnxe_override) <= MAX_OWN_IE_OVERRIDE) {
wconf->rsnxe_override_len = wpabuf_len(conf->rsnxe_override);
os_memcpy(wconf->rsnxe_override,
wpabuf_head(conf->rsnxe_override),
wconf->rsnxe_override_len);
wconf->rsnxe_override_set = true;
}
if (conf->rsnxoe_override &&
wpabuf_len(conf->rsnxoe_override) <= MAX_OWN_IE_OVERRIDE) {
wconf->rsnxoe_override_len = wpabuf_len(conf->rsnxoe_override);
os_memcpy(wconf->rsnxoe_override,
wpabuf_head(conf->rsnxoe_override),
wconf->rsnxoe_override_len);
wconf->rsnxoe_override_set = true;
}
if (conf->rsne_override_eapol &&
wpabuf_len(conf->rsne_override_eapol) <= MAX_OWN_IE_OVERRIDE) {
wconf->rsne_override_eapol_set = 1;
@@ -190,6 +306,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
if (conf->eapol_m3_elements)
wconf->eapol_m3_elements = wpabuf_dup(conf->eapol_m3_elements);
wconf->eapol_m3_no_encrypt = conf->eapol_m3_no_encrypt;
wconf->eapol_key_reserved_random = conf->eapol_key_reserved_random;
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_P2P
os_memcpy(wconf->ip_addr_go, conf->ip_addr_go, 4);
@@ -219,15 +336,35 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
wconf->dpp_pfs = conf->dpp_pfs;
#endif /* CONFIG_DPP2 */
#ifdef CONFIG_PASN
#ifdef CONFIG_ENC_ASSOC
wconf->eppke_unauth = conf->eppke_unauth;
#endif /* CONFIG_ENC_ASSOC */
#ifdef CONFIG_TESTING_OPTIONS
wconf->force_kdk_derivation = conf->force_kdk_derivation;
#endif /* CONFIG_TESTING_OPTIONS */
#endif /* CONFIG_PASN */
if (conf->urnm_mfpr_x20 == 1)
wconf->urnm_mfpr_x20 = true;
if (conf->urnm_mfpr != 0)
wconf->urnm_mfpr = true;
wconf->radius_psk = conf->wpa_psk_radius == PSK_RADIUS_DURING_4WAY_HS;
wconf->no_disconnect_on_group_keyerror =
conf->bss_max_idle && conf->ap_max_inactivity &&
conf->no_disconnect_on_group_keyerror;
wconf->rsn_override_omit_rsnxe = conf->rsn_override_omit_rsnxe;
wconf->rsn_override_mlo_compat = conf->rsn_override_mlo_compat;
wconf->spp_amsdu = conf->spp_amsdu &&
(iface->drv_flags2 & WPA_DRIVER_FLAGS2_SPP_AMSDU);
if (conf->sae_pw_id_num && conf->sae_pw_id_key &&
wpabuf_len(conf->sae_pw_id_key) == sizeof(wconf->sae_pw_id_key)) {
wconf->sae_pw_id_num = conf->sae_pw_id_num;
os_memcpy(wconf->sae_pw_id_key,
wpabuf_head(conf->sae_pw_id_key),
wpabuf_len(conf->sae_pw_id_key));
}
}
@@ -371,13 +508,17 @@ static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr,
#endif /* CONFIG_SAE */
#ifdef CONFIG_OWE
if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) &&
if (((hapd->conf->wpa_key_mgmt | hapd->conf->rsn_override_key_mgmt |
hapd->conf->rsn_override_key_mgmt_2) &
WPA_KEY_MGMT_OWE) &&
sta && sta->owe_pmk) {
if (psk_len)
*psk_len = sta->owe_pmk_len;
return sta->owe_pmk;
}
if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) && sta) {
if (((hapd->conf->wpa_key_mgmt | hapd->conf->rsn_override_key_mgmt |
hapd->conf->rsn_override_key_mgmt_2) &
WPA_KEY_MGMT_OWE) && sta) {
struct rsn_pmksa_cache_entry *sa;
sa = wpa_auth_sta_get_pmksa(sta->wpa_sm);
@@ -459,10 +600,20 @@ static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg,
size_t key_len, enum key_flag key_flag)
{
struct hostapd_data *hapd = ctx;
struct hostapd_data *link_bss = hapd;
const char *ifname = hapd->conf->iface;
int set_tx = !(key_flag & KEY_FLAG_NEXT);
#ifdef CONFIG_IEEE80211BE
if (hapd->conf->mld_ap) {
link_bss = hostapd_mld_get_first_bss(hapd);
if (!link_bss)
link_bss = hapd;
}
#endif /* CONFIG_IEEE80211BE */
if (vlan_id > 0) {
ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan, vlan_id);
ifname = hostapd_get_vlan_id_ifname(link_bss->conf->vlan,
vlan_id);
if (!ifname) {
if (!(hapd->iface->drv_flags &
WPA_DRIVER_FLAGS_VLAN_OFFLOAD))
@@ -512,8 +663,8 @@ static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg,
hapd->last_gtk_len = key_len;
}
#endif /* CONFIG_TESTING_OPTIONS */
return hostapd_drv_set_key(ifname, hapd, alg, addr, idx, vlan_id, 1,
NULL, 0, key, key_len, key_flag);
return hostapd_drv_set_key(ifname, hapd, alg, addr, idx, vlan_id,
set_tx, NULL, 0, key, key_len, key_flag);
}
@@ -632,6 +783,29 @@ static int hostapd_wpa_auth_for_each_auth(
}
#ifdef CONFIG_IEEE80211BE
static int hostapd_wpa_auth_for_each_partner_auth(
void *ctx, int (*cb)(struct wpa_authenticator *sm, void *ctx),
void *cb_ctx)
{
struct hostapd_data *hapd = ctx;
struct hostapd_data *bss;
if (cb(hapd->wpa_auth, cb_ctx))
return 1;
if (!hapd->mld)
return 0;
for_each_mld_link(bss, hapd) {
if (bss != hapd && bss->wpa_auth && cb(bss->wpa_auth, cb_ctx))
return 1;
}
return 0;
}
#endif /* CONFIG_IEEE80211BE */
#ifdef CONFIG_IEEE80211R_AP
struct wpa_ft_rrb_rx_later_data {
@@ -972,7 +1146,7 @@ static void hostapd_store_ptksa(void *ctx, const u8 *addr,int cipher,
struct hostapd_data *hapd = ctx;
ptksa_cache_add(hapd->ptksa, hapd->own_addr, addr, cipher, life_time,
ptk, NULL, NULL, 0);
ptk, NULL, NULL, 0, 0);
}
@@ -1441,15 +1615,6 @@ static void hostapd_rrb_oui_receive(void *ctx, const u8 *src_addr,
}
static int hostapd_wpa_auth_add_tspec(void *ctx, const u8 *sta_addr,
u8 *tspec_ie, size_t tspec_ielen)
{
struct hostapd_data *hapd = ctx;
return hostapd_add_tspec(hapd, sta_addr, tspec_ie, tspec_ielen);
}
static int hostapd_wpa_register_ft_oui(struct hostapd_data *hapd,
const char *ft_iface)
{
@@ -1535,10 +1700,31 @@ static int hostapd_set_ltf_keyseed(void *ctx, const u8 *peer_addr,
#endif /* CONFIG_PASN */
static bool hostapd_first_sta_seen_mbssid(void *ctx, int vlan_id)
{
struct hostapd_data *hapd = ctx;
if (hapd->iconf->mbssid) {
size_t i;
for (i = 0; i < hapd->iface->num_bss; i++) {
struct hostapd_data *tmp_hapd = hapd->iface->bss[i];
if (wpa_auth_get_first_sta_seen(tmp_hapd->wpa_auth,
vlan_id))
return true;
}
}
return false;
}
#ifdef CONFIG_IEEE80211BE
static int hostapd_wpa_auth_get_ml_key_info(void *ctx,
struct wpa_auth_ml_key_info *info)
struct wpa_auth_ml_key_info *info,
bool rekey, int vlan_id)
{
struct hostapd_data *hapd = ctx;
unsigned int i;
@@ -1562,7 +1748,8 @@ static int hostapd_wpa_auth_get_ml_key_info(void *ctx,
wpa_auth_ml_get_key_info(hapd->wpa_auth,
&info->links[i],
info->mgmt_frame_prot,
info->beacon_prot);
info->beacon_prot,
rekey, vlan_id);
continue;
}
@@ -1573,7 +1760,8 @@ static int hostapd_wpa_auth_get_ml_key_info(void *ctx,
wpa_auth_ml_get_key_info(bss->wpa_auth,
&info->links[i],
info->mgmt_frame_prot,
info->beacon_prot);
info->beacon_prot,
rekey, vlan_id);
link_bss_found = true;
break;
}
@@ -1586,6 +1774,21 @@ static int hostapd_wpa_auth_get_ml_key_info(void *ctx,
return 0;
}
static struct wpa_authenticator * hostapd_next_primary_auth(void *cb_ctx)
{
struct hostapd_data *hapd = cb_ctx, *bss;
for_each_mld_link(bss, hapd) {
if (bss == hapd)
continue;
if (bss->wpa_auth)
return bss->wpa_auth;
}
return NULL;
}
#endif /* CONFIG_IEEE80211BE */
@@ -1603,6 +1806,15 @@ static int hostapd_wpa_auth_get_drv_flags(void *ctx,
}
static int hostapd_wpa_auth_remove_pmkid(void *ctx, const u8 *sta_addr,
const u8 *pmkid)
{
struct hostapd_data *hapd = ctx;
return hostapd_remove_pmkid(hapd, sta_addr, pmkid);
}
int hostapd_setup_wpa(struct hostapd_data *hapd)
{
struct wpa_auth_config _conf;
@@ -1621,6 +1833,9 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
.get_sta_count = hostapd_wpa_auth_get_sta_count,
.for_each_sta = hostapd_wpa_auth_for_each_sta,
.for_each_auth = hostapd_wpa_auth_for_each_auth,
#ifdef CONFIG_IEEE80211BE
.for_each_partner_auth = hostapd_wpa_auth_for_each_partner_auth,
#endif /* CONFIG_IEEE80211BE */
.send_ether = hostapd_wpa_auth_send_ether,
.send_oui = hostapd_wpa_auth_send_oui,
.channel_info = hostapd_channel_info,
@@ -1637,7 +1852,6 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
.send_ft_action = hostapd_wpa_auth_send_ft_action,
.add_sta = hostapd_wpa_auth_add_sta,
.add_sta_ft = hostapd_wpa_auth_add_sta_ft,
.add_tspec = hostapd_wpa_auth_add_tspec,
.set_vlan = hostapd_wpa_auth_set_vlan,
.get_vlan = hostapd_wpa_auth_get_vlan,
.set_identity = hostapd_wpa_auth_set_identity,
@@ -1655,75 +1869,17 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
#endif /* CONFIG_PASN */
#ifdef CONFIG_IEEE80211BE
.get_ml_key_info = hostapd_wpa_auth_get_ml_key_info,
.next_primary_auth = hostapd_next_primary_auth,
#endif /* CONFIG_IEEE80211BE */
.get_drv_flags = hostapd_wpa_auth_get_drv_flags,
.remove_pmkid = hostapd_wpa_auth_remove_pmkid,
.first_sta_seen_mbssid = hostapd_first_sta_seen_mbssid,
};
const u8 *wpa_ie;
size_t wpa_ie_len;
struct hostapd_data *tx_bss;
hostapd_wpa_auth_conf(hapd->conf, hapd->iconf, &_conf);
_conf.msg_ctx = hapd->msg_ctx;
tx_bss = hostapd_mbssid_get_tx_bss(hapd);
if (tx_bss != hapd)
_conf.tx_bss_auth = tx_bss->wpa_auth;
if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EAPOL_TX_STATUS)
_conf.tx_status = 1;
if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_MLME)
_conf.ap_mlme = 1;
if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
(hapd->conf->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
(hapd->conf->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
wpa_msg(hapd->msg_ctx, MSG_INFO,
"Disable PTK0 rekey support - replaced with disconnect");
_conf.wpa_deny_ptk0_rekey = 1;
}
if (_conf.extended_key_id &&
(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID))
wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Extended Key ID supported");
else
_conf.extended_key_id = 0;
if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_BEACON_PROTECTION))
_conf.beacon_prot = 0;
#ifdef CONFIG_OCV
if (!(hapd->iface->drv_flags2 &
(WPA_DRIVER_FLAGS2_AP_SME | WPA_DRIVER_FLAGS2_OCV)))
_conf.ocv = 0;
#endif /* CONFIG_OCV */
_conf.secure_ltf =
!!(hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF_AP);
_conf.secure_rtt =
!!(hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_RTT_AP);
_conf.prot_range_neg =
!!(hapd->iface->drv_flags2 &
WPA_DRIVER_FLAGS2_PROT_RANGE_NEG_AP);
#ifdef CONFIG_IEEE80211BE
_conf.mld_addr = NULL;
_conf.link_id = -1;
_conf.first_link_auth = NULL;
if (hapd->conf->mld_ap) {
struct hostapd_data *lhapd;
_conf.mld_addr = hapd->mld->mld_addr;
_conf.link_id = hapd->mld_link_id;
for_each_mld_link(lhapd, hapd) {
if (lhapd == hapd)
continue;
if (lhapd->wpa_auth)
_conf.first_link_auth = lhapd->wpa_auth;
}
}
#endif /* CONFIG_IEEE80211BE */
hostapd_wpa_auth_conf(hapd->iface, hapd->conf, hapd->iconf, &_conf);
hostapd_wpa_auth_config_update(hapd, &_conf);
hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb, hapd);
if (hapd->wpa_auth == NULL) {
@@ -1788,7 +1944,10 @@ int hostapd_setup_wpa(struct hostapd_data *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);
hostapd_wpa_auth_config_update(hapd, &wpa_auth_conf);
wpa_reconfig(hapd->wpa_auth, &wpa_auth_conf);
}
+13
View File
@@ -61,6 +61,7 @@ struct wpa_state_machine {
unsigned int pmk_len;
u8 pmkid[PMKID_LEN]; /* valid if pmkid_set == 1 */
struct wpa_ptk PTK;
enum rsn_hash_alg hash_alg;
u8 keyidx_active;
bool use_ext_key_id;
bool PTK_valid;
@@ -97,6 +98,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;
@@ -111,6 +113,8 @@ struct wpa_state_machine {
size_t wpa_ie_len;
u8 *rsnxe;
size_t rsnxe_len;
u8 *rsn_selection;
size_t rsn_selection_len;
enum {
WPA_VERSION_NO_WPA = 0 /* WPA not used */,
@@ -124,6 +128,9 @@ struct wpa_state_machine {
u32 dot11RSNAStatsTKIPLocalMICFailures;
u32 dot11RSNAStatsTKIPRemoteMICFailures;
bool rsn_override;
bool rsn_override_2;
#ifdef CONFIG_IEEE80211R_AP
u8 xxkey[PMK_LEN_MAX]; /* PSK or the second 256 bits of MSK, or the
* first 384 bits of MSK */
@@ -178,6 +185,7 @@ struct wpa_state_machine {
struct mld_link {
bool valid;
bool rejected;
u8 peer_addr[ETH_ALEN];
struct wpa_authenticator *wpa_auth;
@@ -185,6 +193,9 @@ struct wpa_state_machine {
#endif /* CONFIG_IEEE80211BE */
bool ssid_protection;
struct wpabuf *sae_pw_id;
unsigned int sae_pw_id_counter;
};
@@ -261,6 +272,8 @@ struct wpa_authenticator {
#endif /* CONFIG_P2P */
#ifdef CONFIG_IEEE80211BE
/* MLD-level PMKSA cache for non-AP MLD entries only. */
struct rsn_pmksa_cache *ml_pmksa;
bool is_ml;
u8 mld_addr[ETH_ALEN];
u8 link_id;
File diff suppressed because it is too large. Load diff
+2 -1
View File
@@ -331,6 +331,7 @@ int ieee802_1x_alloc_kay_sm_hapd(struct hostapd_data *hapd,
hapd->conf->macsec_port,
hapd->conf->mka_priority,
hapd->conf->macsec_csindex,
hapd->conf->macsec_icv_indicator,
hapd->conf->iface,
hapd->own_addr);
/* ieee802_1x_kay_init() frees kay_ctx on failure */
@@ -477,7 +478,7 @@ void * ieee802_1x_create_preshared_mka_hapd(struct hostapd_data *hapd,
cak->len = hapd->conf->mka_cak_len;
os_memcpy(cak->key, hapd->conf->mka_cak, cak->len);
ckn->len = hapd->conf->mka_ckn_len;;
ckn->len = hapd->conf->mka_ckn_len;
os_memcpy(ckn->name, hapd->conf->mka_ckn, ckn->len);
res = ieee802_1x_kay_create_mka(hapd->kay, ckn, cak, 0, PSK, true);
+2
View File
@@ -20,6 +20,7 @@
#include "wps/wps_defs.h"
#include "wps/wps_dev_attr.h"
#include "wps/wps_attr_parse.h"
#include "crypto/dh_group5.h"
#include "hostapd.h"
#include "ap_config.h"
#include "ap_drv_ops.h"
@@ -1071,6 +1072,7 @@ static void hostapd_free_wps(struct wps_context *wps)
wps_device_data_free(&wps->dev);
bin_clear_free(wps->network_key, wps->network_key_len);
hostapd_wps_nfc_clear(wps);
dh5_free(wps->dh_ctx);
wpabuf_free(wps->dh_pubkey);
wpabuf_free(wps->dh_privkey);
forced_memzero(wps->psk, sizeof(wps->psk));
+3
View File
@@ -83,13 +83,16 @@ _make_dirs:
@mkdir -p $(sort $(_DIRS))
$(BUILDDIR)/$(PROJ)/src/%.o: $(ROOTDIR)src/%.c $(CONFIG_FILE) | _make_dirs
@echo $(CURDIR): '$(CC) -c -o $@ $(CFLAGS) $<' >[email protected]
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
@$(E) " CC " $<
$(BUILDDIR)/$(PROJ)/%.o: %.c $(CONFIG_FILE) | _make_dirs
@echo $(CURDIR): '$(CC) -c -o $@ $(CFLAGS) $<' >[email protected]
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
@$(E) " CC " $<
# for the fuzzing tests
$(BUILDDIR)/$(PROJ)/wpa_supplicant/%.o: $(ROOTDIR)wpa_supplicant/%.c $(CONFIG_FILE) | _make_dirs
@echo $(CURDIR): '$(CC) -c -o $@ $(CFLAGS) $<' >[email protected]
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
@$(E) " CC " $<
+1
View File
@@ -1,3 +1,4 @@
CFLAGS += -DCONFIG_IEEE80211AC
CFLAGS += -DCONFIG_IEEE80211R
CFLAGS += -DCONFIG_HS20
CFLAGS += -DCONFIG_SAE
+10 -5
View File
@@ -416,7 +416,7 @@ static int sae_tests(void)
goto fail;
/* Check that output matches the test vector */
if (sae_write_commit(&sae, buf, NULL, NULL) < 0)
if (sae_write_commit(&sae, buf, NULL, NULL, 0) < 0)
goto fail;
wpa_hexdump_buf(MSG_DEBUG, "SAE: Commit message", buf);
@@ -449,7 +449,9 @@ static int sae_tests(void)
pt_info = sae_derive_pt(pt_groups,
(const u8 *) ssid, os_strlen(ssid),
(const u8 *) pw, os_strlen(pw), pwid);
(const u8 *) pw, os_strlen(pw),
(const u8 *) pwid,
os_strlen(pwid));
if (!pt_info)
goto fail;
@@ -608,7 +610,8 @@ static int sae_pk_tests(void)
static int pasn_test_pasn_auth(void)
{
/* Test vector taken from IEEE P802.11az/D2.6, J.12 */
/* Test vector taken from IEEE Std 802.11-2024,
* J.12 (PASN Test Vectors) */
const u8 pmk[] = {
0xde, 0xf4, 0x3e, 0x55, 0x67, 0xe0, 0x1c, 0xa6,
0x64, 0x92, 0x65, 0xf1, 0x9a, 0x29, 0x0e, 0xef,
@@ -646,12 +649,13 @@ static int pasn_test_pasn_auth(void)
};
struct wpa_ptk ptk;
int ret;
enum rsn_hash_alg hash_alg;
ret = pasn_pmk_to_ptk(pmk, sizeof(pmk),
spa_addr, bssid,
dhss, sizeof(dhss),
&ptk, WPA_KEY_MGMT_PASN, WPA_CIPHER_CCMP,
WPA_KDK_MAX_LEN);
WPA_KDK_MAX_LEN, 0, &hash_alg, false);
if (ret)
return ret;
@@ -680,7 +684,8 @@ static int pasn_test_pasn_auth(void)
static int pasn_test_no_pasn_auth(void)
{
/* Test vector taken from IEEE P802.11az/D2.6, J.13 */
/* Test vector taken from IEEE Std 802.11-2024,
* J.13 (KDK Test Vectors when PASN authentication is not used) */
const u8 pmk[] = {
0xde, 0xf4, 0x3e, 0x55, 0x67, 0xe0, 0x1c, 0xa6,
0x64, 0x92, 0x65, 0xf1, 0x9a, 0x29, 0x0e, 0xef,
+59 -6
View File
@@ -39,7 +39,6 @@
#define WPA_KEY_MGMT_WAPI_PSK BIT(12)
#define WPA_KEY_MGMT_WAPI_CERT BIT(13)
#define WPA_KEY_MGMT_CCKM BIT(14)
#define WPA_KEY_MGMT_OSEN BIT(15)
#define WPA_KEY_MGMT_IEEE8021X_SUITE_B BIT(16)
#define WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 BIT(17)
#define WPA_KEY_MGMT_FILS_SHA256 BIT(18)
@@ -53,6 +52,7 @@
#define WPA_KEY_MGMT_SAE_EXT_KEY BIT(26)
#define WPA_KEY_MGMT_FT_SAE_EXT_KEY BIT(27)
#define WPA_KEY_MGMT_IEEE8021X_SHA384 BIT(28)
#define WPA_KEY_MGMT_EPPKE BIT(29)
#define WPA_KEY_MGMT_FT (WPA_KEY_MGMT_FT_PSK | \
@@ -69,7 +69,6 @@ static inline int wpa_key_mgmt_wpa_ieee8021x(int akm)
WPA_KEY_MGMT_FT_IEEE8021X |
WPA_KEY_MGMT_FT_IEEE8021X_SHA384 |
WPA_KEY_MGMT_CCKM |
WPA_KEY_MGMT_OSEN |
WPA_KEY_MGMT_IEEE8021X_SHA256 |
WPA_KEY_MGMT_IEEE8021X_SUITE_B |
WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 |
@@ -129,6 +128,22 @@ static inline int wpa_key_mgmt_sae_ext_key(int akm)
WPA_KEY_MGMT_FT_SAE_EXT_KEY));
}
static inline int wpa_key_mgmt_only_sae(int akm)
{
return wpa_key_mgmt_sae(akm) &&
!(akm & ~(WPA_KEY_MGMT_SAE |
WPA_KEY_MGMT_SAE_EXT_KEY |
WPA_KEY_MGMT_FT_SAE |
WPA_KEY_MGMT_FT_SAE_EXT_KEY));
}
static inline int wpa_key_mgmt_only_sae_ext_key(int akm)
{
return wpa_key_mgmt_sae_ext_key(akm) &&
!(akm & ~(WPA_KEY_MGMT_SAE_EXT_KEY |
WPA_KEY_MGMT_FT_SAE_EXT_KEY));
}
static inline int wpa_key_mgmt_fils(int akm)
{
return !!(akm & (WPA_KEY_MGMT_FILS_SHA256 |
@@ -144,7 +159,6 @@ static inline int wpa_key_mgmt_sha256(int akm)
WPA_KEY_MGMT_IEEE8021X_SHA256 |
WPA_KEY_MGMT_SAE |
WPA_KEY_MGMT_FT_SAE |
WPA_KEY_MGMT_OSEN |
WPA_KEY_MGMT_IEEE8021X_SUITE_B |
WPA_KEY_MGMT_FILS_SHA256 |
WPA_KEY_MGMT_FT_FILS_SHA256));
@@ -172,7 +186,8 @@ static inline int wpa_key_mgmt_wpa(int akm)
wpa_key_mgmt_fils(akm) ||
wpa_key_mgmt_sae(akm) ||
akm == WPA_KEY_MGMT_OWE ||
akm == WPA_KEY_MGMT_DPP;
akm == WPA_KEY_MGMT_DPP ||
akm == WPA_KEY_MGMT_EPPKE;
}
static inline int wpa_key_mgmt_wpa_any(int akm)
@@ -193,10 +208,27 @@ static inline int wpa_key_mgmt_cross_akm(int akm)
WPA_KEY_MGMT_SAE_EXT_KEY));
}
static inline bool wpa_key_mgmt_eppke(int akm)
{
return !!(akm & WPA_KEY_MGMT_EPPKE);
}
static inline int wpa_key_mgmt_enhanced_open(int akm)
{
return !!(akm & (WPA_KEY_MGMT_OWE |
WPA_KEY_MGMT_EPPKE));
}
static inline int wpa_key_mgmt_only_enhanced_open(int akm)
{
return wpa_key_mgmt_enhanced_open(akm) &&
!(akm & ~(WPA_KEY_MGMT_OWE |
WPA_KEY_MGMT_EPPKE));
}
#define WPA_PROTO_WPA BIT(0)
#define WPA_PROTO_RSN BIT(1)
#define WPA_PROTO_WAPI BIT(2)
#define WPA_PROTO_OSEN BIT(3)
#define WPA_AUTH_ALG_OPEN BIT(0)
#define WPA_AUTH_ALG_SHARED BIT(1)
@@ -205,12 +237,19 @@ static inline int wpa_key_mgmt_cross_akm(int akm)
#define WPA_AUTH_ALG_SAE BIT(4)
#define WPA_AUTH_ALG_FILS BIT(5)
#define WPA_AUTH_ALG_FILS_SK_PFS BIT(6)
#define WPA_AUTH_ALG_EPPKE BIT(7)
#define WPA_AUTH_ALG_802_1X BIT(8)
static inline int wpa_auth_alg_fils(int alg)
{
return !!(alg & (WPA_AUTH_ALG_FILS | WPA_AUTH_ALG_FILS_SK_PFS));
}
static inline bool wpa_auth_alg_eppke(int alg)
{
return !!(alg & WPA_AUTH_ALG_EPPKE);
}
enum wpa_alg {
WPA_ALG_NONE,
WPA_ALG_WEP,
@@ -481,6 +520,7 @@ enum key_flag {
KEY_FLAG_GROUP = BIT(4),
KEY_FLAG_PAIRWISE = BIT(5),
KEY_FLAG_PMK = BIT(6),
KEY_FLAG_NEXT = BIT(7),
/* Used flag combinations */
KEY_FLAG_RX_TX = KEY_FLAG_RX | KEY_FLAG_TX,
KEY_FLAG_GROUP_RX_TX = KEY_FLAG_GROUP | KEY_FLAG_RX_TX,
@@ -493,8 +533,10 @@ enum key_flag {
KEY_FLAG_PAIRWISE_RX = KEY_FLAG_PAIRWISE | KEY_FLAG_RX,
KEY_FLAG_PAIRWISE_RX_TX_MODIFY = KEY_FLAG_PAIRWISE_RX_TX |
KEY_FLAG_MODIFY,
KEY_FLAG_PAIRWISE_NEXT = KEY_FLAG_PAIRWISE_RX | KEY_FLAG_NEXT,
/* Max allowed flags for each key type */
KEY_FLAG_PAIRWISE_MASK = KEY_FLAG_PAIRWISE_RX_TX_MODIFY,
KEY_FLAG_PAIRWISE_MASK = KEY_FLAG_PAIRWISE_RX_TX_MODIFY |
KEY_FLAG_NEXT,
KEY_FLAG_GROUP_MASK = KEY_FLAG_GROUP_RX_TX_DEFAULT,
KEY_FLAG_PMK_MASK = KEY_FLAG_PMK,
};
@@ -532,4 +574,15 @@ enum sae_pwe {
SAE_PWE_NOT_SET = 4,
};
enum wpa_p2p_mode {
WPA_P2P_MODE_WFD_R1 = 0,
WPA_P2P_MODE_WFD_R2 = 1,
WPA_P2P_MODE_WFD_PCC = 2,
};
#define USEC_80211_TU 1024
#define USEC_TO_TU(m) ((m) / USEC_80211_TU)
#define TU_TO_USEC(m) ((m) * USEC_80211_TU)
#endif /* DEFS_H */
+78 -5
View File
@@ -2,7 +2,7 @@
* DPP functionality shared between hostapd and wpa_supplicant
* Copyright (c) 2017, Qualcomm Atheros, Inc.
* Copyright (c) 2018-2020, The Linux Foundation
* Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -299,7 +299,8 @@ int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info)
}
int dpp_parse_uri_version(struct dpp_bootstrap_info *bi, const char *version)
static int dpp_parse_uri_version(struct dpp_bootstrap_info *bi,
const char *version)
{
#ifdef CONFIG_DPP2
if (!version || DPP_VERSION < 2)
@@ -1035,6 +1036,10 @@ struct wpabuf * dpp_build_conf_req_helper(struct dpp_authentication *auth,
json_value_sep(json);
json_add_string(json, "pkcs10", csr);
}
#ifdef CONFIG_DPP3
json_value_sep(json);
json_add_int(json, "capabilities", DPP_ENROLLEE_CAPAB_SAE_PW_ID);
#endif /* CONFIG_DPP3 */
if (extra_name && extra_value && extra_name[0] && extra_value[0]) {
json_value_sep(json);
wpabuf_printf(json, "\"%s\":%s", extra_name, extra_value);
@@ -1139,8 +1144,18 @@ int dpp_configuration_valid(const struct dpp_configuration *conf)
return 0;
if (dpp_akm_psk(conf->akm) && !conf->passphrase && !conf->psk_set)
return 0;
if (dpp_akm_psk(conf->akm) && conf->passphrase) {
size_t len = os_strlen(conf->passphrase);
if (len > 63 || len < 8)
return 0;
}
if (dpp_akm_sae(conf->akm) && !conf->passphrase)
return 0;
#ifdef CONFIG_DPP3
if (conf->idpass && (!conf->passphrase || !dpp_akm_sae(conf->akm)))
return 0;
#endif /* CONFIG_DPP3 */
return 1;
}
@@ -1150,6 +1165,9 @@ void dpp_configuration_free(struct dpp_configuration *conf)
if (!conf)
return;
str_clear_free(conf->passphrase);
#ifdef CONFIG_DPP3
os_free(conf->idpass);
#endif /* CONFIG_DPP3 */
os_free(conf->group_id);
os_free(conf->csrattrs);
os_free(conf->extra_name);
@@ -1228,14 +1246,28 @@ static int dpp_configuration_parse_helper(struct dpp_authentication *auth,
end = os_strchr(pos, ' ');
pass_len = end ? (size_t) (end - pos) : os_strlen(pos);
pass_len /= 2;
if (pass_len > 63 || pass_len < 8)
goto fail;
conf->passphrase = os_zalloc(pass_len + 1);
if (!conf->passphrase ||
hexstr2bin(pos, (u8 *) conf->passphrase, pass_len) < 0)
goto fail;
}
#ifdef CONFIG_DPP3
pos = os_strstr(cmd, " idpass=");
if (pos) {
size_t idpass_len;
pos += 8;
end = os_strchr(pos, ' ');
idpass_len = end ? (size_t) (end - pos) : os_strlen(pos);
idpass_len /= 2;
conf->idpass = os_zalloc(idpass_len + 1);
if (!conf->idpass ||
hexstr2bin(pos, (u8 *) conf->idpass, idpass_len) < 0)
goto fail;
}
#endif /* CONFIG_DPP3 */
pos = os_strstr(cmd, " psk=");
if (pos) {
pos += 5;
@@ -1595,6 +1627,13 @@ static void dpp_build_legacy_cred_params(struct wpabuf *buf,
if (conf->passphrase && os_strlen(conf->passphrase) < 64) {
json_add_string_escape(buf, "pass", conf->passphrase,
os_strlen(conf->passphrase));
#ifdef CONFIG_DPP3
if (conf->idpass) {
json_value_sep(buf);
json_add_string_escape(buf, "idpass", conf->idpass,
os_strlen(conf->idpass));
}
#endif /* CONFIG_DPP3 */
} else if (conf->psk_set) {
char psk[2 * sizeof(conf->psk) + 1];
@@ -1917,6 +1956,16 @@ dpp_build_conf_obj_legacy(struct dpp_authentication *auth,
const char *akm_str;
size_t len = 1000;
#ifdef CONFIG_DPP3
if (conf->idpass &&
!(auth->enrollee_capabilities & DPP_ENROLLEE_CAPAB_SAE_PW_ID)) {
wpa_printf(MSG_DEBUG,
"DPP: Enrollee does not support SAE Password Identifier - cannot generate config object");
return NULL;
}
#endif /* CONFIG_DPP3 */
if (conf->extra_name && conf->extra_value)
len += 10 + os_strlen(conf->extra_name) +
os_strlen(conf->extra_value);
@@ -2535,6 +2584,18 @@ dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start,
cont:
#endif /* CONFIG_DPP2 */
#ifdef CONFIG_DPP3
token = json_get_member(root, "capabilities");
if (token && token->type == JSON_NUMBER) {
wpa_printf(MSG_DEBUG, "DPP: capabilities = 0x%x",
token->number);
wpa_msg(auth->msg_ctx, MSG_INFO,
DPP_EVENT_ENROLLEE_CAPABILITY "%d",
token->number);
auth->enrollee_capabilities = token->number;
}
#endif /* CONFIG_DPP3 */
resp = dpp_build_conf_resp(auth, e_nonce, e_nonce_len, netrole,
cert_req);
@@ -2558,13 +2619,25 @@ static int dpp_parse_cred_legacy(struct dpp_config_obj *conf,
if (pass && pass->type == JSON_STRING) {
size_t len = os_strlen(pass->string);
#ifdef CONFIG_DPP3
struct json_token *saepi = json_get_member(cred, "idpass");
#endif /* CONFIG_DPP3 */
wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Legacy passphrase",
pass->string, len);
if (len < 8 || len > 63)
if (dpp_akm_psk(conf->akm) && (len < 8 || len > 63)) {
wpa_printf(MSG_DEBUG,
"DPP: Unexpected pass length %zu for a config object that includes PSK",
len);
return -1;
}
os_strlcpy(conf->passphrase, pass->string,
sizeof(conf->passphrase));
#ifdef CONFIG_DPP3
if (saepi && saepi->type == JSON_STRING)
os_strlcpy(conf->password_id, saepi->string,
sizeof(conf->password_id));
#endif /* CONFIG_DPP3 */
} else if (psk_hex && psk_hex->type == JSON_STRING) {
if (dpp_akm_sae(conf->akm) && !dpp_akm_psk(conf->akm)) {
wpa_printf(MSG_DEBUG,
+9 -1
View File
@@ -2,7 +2,7 @@
* DPP functionality shared between hostapd and wpa_supplicant
* Copyright (c) 2017, Qualcomm Atheros, Inc.
* Copyright (c) 2018-2020, The Linux Foundation
* Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -134,6 +134,9 @@ enum dpp_connector_key {
#define DPP_MAX_SHARED_SECRET_LEN 66
#define DPP_CP_LEN 64
/* DPP Configuration Request - Enrollee Capabilities */
#define DPP_ENROLLEE_CAPAB_SAE_PW_ID BIT(0)
struct dpp_curve_params {
const char *name;
size_t hash_len;
@@ -260,6 +263,7 @@ struct dpp_configuration {
/* For legacy configuration */
char *passphrase;
char *idpass;
u8 psk[32];
int psk_set;
@@ -356,6 +360,9 @@ struct dpp_authentication {
u8 ssid_len;
int ssid_charset;
char passphrase[64];
#ifdef CONFIG_DPP3
char password_id[64];
#endif /* CONFIG_DPP3 */
u8 psk[PMK_LEN];
int psk_set;
enum dpp_akm akm;
@@ -393,6 +400,7 @@ struct dpp_authentication {
char *e_name;
char *e_mud_url;
int *e_band_support;
unsigned int enrollee_capabilities;
#ifdef CONFIG_TESTING_OPTIONS
char *config_obj_override;
char *discovery_override;
+1 -1
View File
@@ -1869,7 +1869,7 @@ int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr,
SHA256_MAC_LEN) != 0) {
wpa_hexdump(MSG_DEBUG,
"DPP: Expected Responder Bootstrapping Key Hash",
auth->peer_bi->pubkey_hash, SHA256_MAC_LEN);
auth->own_bi->pubkey_hash, SHA256_MAC_LEN);
dpp_auth_fail(auth,
"Responder Bootstrapping Key Hash mismatch");
return -1;
+2 -1
View File
@@ -161,7 +161,7 @@ static struct wpabuf * dpp_build_key_pkg(struct dpp_authentication *auth)
/* Attributes ::= SET OF Attribute { { OneAsymmetricKeyAttributes } } */
attr = dpp_build_attribute(auth->conf);
attr = asn1_encaps(attr, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SET);
if (!priv_key || !attr || !alg)
if (!attr || !alg)
goto fail;
/*
@@ -515,6 +515,7 @@ out:
wpabuf_free(enc_cont_info);
return env;
fail:
wpa_printf(MSG_INFO, "DPP: Failed to build DPPEnvelopedData");
wpabuf_free(env);
env = NULL;
goto out;
+1
View File
@@ -2371,6 +2371,7 @@ struct crypto_ec_point * dpp_decrypt_e_id(struct crypto_ec_key *ppkey,
crypto_ec_point_invert(ec, e_id) ||
crypto_ec_point_add(ec, e_id, e_prime_id_point, e_id)) {
crypto_ec_point_deinit(e_id, 1);
e_id = NULL;
goto fail;
}
+1 -1
View File
@@ -2,7 +2,7 @@
* DPP module internal definitions
* Copyright (c) 2017, Qualcomm Atheros, Inc.
* Copyright (c) 2018-2020, The Linux Foundation
* Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
+1 -1
View File
@@ -569,7 +569,7 @@ fail:
}
struct wpabuf *
static struct wpabuf *
dpp_reconfig_build_conf(struct dpp_authentication *auth)
{
struct wpabuf *msg = NULL, *clear;
+2 -2
View File
@@ -1,7 +1,7 @@
/*
* DPP over TCP
* Copyright (c) 2019-2020, The Linux Foundation
* Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -2291,7 +2291,7 @@ void dpp_controller_new_qr_code(struct dpp_global *dpp,
dl_list_for_each(conn, &ctrl->conn, struct dpp_connection, list) {
struct dpp_authentication *auth = conn->auth;
if (!auth->response_pending ||
if (!auth || !auth->response_pending ||
dpp_notify_new_qr_code(auth, bi) != 1)
continue;
wpa_printf(MSG_DEBUG,
+6
View File
@@ -79,6 +79,12 @@ struct wpabuf *
gas_build_comeback_resp(u8 dialog_token, u16 status_code, u8 frag_id, u8 more,
u16 comeback_delay, size_t size)
{
if (frag_id > 127) {
wpa_printf(MSG_INFO,
"GAS: Invalid frag_id=%u - cannot build comeback response",
frag_id);
return NULL;
}
return gas_build_resp(WLAN_PA_GAS_COMEBACK_RESP, dialog_token,
status_code, frag_id, more, comeback_delay,
size);
+13 -1
View File
@@ -2,7 +2,7 @@
* Generic advertisement service (GAS) server
* Copyright (c) 2017, Qualcomm Atheros, Inc.
* Copyright (c) 2020, The Linux Foundation
* Copyright (c) 2022, Qualcomm Innovation Center, Inc.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -44,6 +44,7 @@ struct gas_server_response {
struct gas_server_handler *handler;
u16 comeback_delay;
bool initial_resp_sent;
bool timeout_extended;
};
struct gas_server {
@@ -61,6 +62,17 @@ static void gas_server_response_timeout(void *eloop_ctx, void *user_ctx)
{
struct gas_server_response *response = eloop_ctx;
if (!response->resp && response->comeback_delay &&
!response->timeout_extended) {
wpa_printf(MSG_DEBUG,
"GAS: Extend timeout while waiting for response");
response->timeout_extended = true;
eloop_register_timeout(GAS_QUERY_TIMEOUT, 0,
gas_server_response_timeout,
response, user_ctx);
return;
}
wpa_printf(MSG_DEBUG, "GAS: Response @%p timeout for " MACSTR
" (dialog_token=%u freq=%d frag_id=%u sent=%lu/%lu) - drop pending data",
response, MAC2STR(response->dst), response->dialog_token,
+1 -1
View File
@@ -2,7 +2,7 @@
* Generic advertisement service (GAS) server
* Copyright (c) 2017, Qualcomm Atheros, Inc.
* Copyright (c) 2020, The Linux Foundation
* Copyright (c) 2022, Qualcomm Innovation Center, Inc.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
+45 -3
View File
@@ -387,6 +387,7 @@ static void punct_update_legacy_bw_80(u8 bitmap, u8 pri_chan, u8 *seg0)
switch (bitmap) {
case 0x6:
case 0x9:
*seg0 = 0;
return;
case 0x8:
@@ -432,6 +433,27 @@ static void punct_update_legacy_bw_160(u8 bitmap, u8 pri,
}
static void punct_update_legacy_bw_320(u16 bitmap, u8 pri,
enum oper_chan_width *width, u8 *seg0)
{
if (pri < *seg0) {
*seg0 -= 16;
if (bitmap & 0x00FF) {
*width = 1;
punct_update_legacy_bw_160(bitmap & 0xFF, pri, width,
seg0);
}
} else {
*seg0 += 16;
if (bitmap & 0xFF00) {
*width = 1;
punct_update_legacy_bw_160((bitmap & 0xFF00) >> 8,
pri, width, seg0);
}
}
}
void punct_update_legacy_bw(u16 bitmap, u8 pri, enum oper_chan_width *width,
u8 *seg0, u8 *seg1)
{
@@ -446,7 +468,10 @@ void punct_update_legacy_bw(u16 bitmap, u8 pri, enum oper_chan_width *width,
punct_update_legacy_bw_160(bitmap & 0xFF, pri, width, seg0);
}
/* TODO: 320 MHz */
if (*width == CONF_OPER_CHWIDTH_320MHZ && (bitmap & 0xFFFF)) {
*width = CONF_OPER_CHWIDTH_160MHZ;
punct_update_legacy_bw_320(bitmap & 0xFFFF, pri, width, seg0);
}
}
@@ -481,6 +506,7 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
data->sec_channel_offset = sec_channel_offset;
data->center_freq1 = freq + sec_channel_offset * 10;
data->center_freq2 = 0;
data->punct_bitmap = punct_bitmap;
if (oper_chwidth == CONF_OPER_CHWIDTH_80MHZ)
data->bandwidth = 80;
else if (oper_chwidth == CONF_OPER_CHWIDTH_160MHZ ||
@@ -569,7 +595,8 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
if (data->eht_enabled) switch (oper_chwidth) {
case CONF_OPER_CHWIDTH_320MHZ:
if (!(eht_cap->phy_cap[EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_IDX] &
if (eht_cap &&
!(eht_cap->phy_cap[EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_IDX] &
EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_MASK)) {
wpa_printf(MSG_ERROR,
"320 MHz channel width is not supported in 5 or 6 GHz");
@@ -968,7 +995,7 @@ int chan_pri_allowed(const struct hostapd_channel_data *chan)
}
/* IEEE P802.11be/D3.0, Table 36-30 - Definition of the Punctured Channel
/* IEEE Std 802.11be-2024, Table 36-30 - Definition of the Punctured Channel
* Information field in the U-SIG for an EHT MU PPDU using non-OFDMA
* transmissions */
static const u16 punct_bitmap_80[] = { 0xF, 0xE, 0xD, 0xB, 0x7 };
@@ -1033,3 +1060,18 @@ bool is_punct_bitmap_valid(u16 bw, u16 pri_ch_bit_pos, u16 punct_bitmap)
return false;
}
bool chan_in_current_hw_info(struct hostapd_multi_hw_info *current_hw_info,
struct hostapd_channel_data *chan)
{
/* Assuming that if current_hw_info is not set full
* iface->current_mode->channels[] can be used to scan for channels,
* hence we return true.
*/
if (!current_hw_info)
return true;
return current_hw_info->start_freq <= chan->freq &&
current_hw_info->end_freq >= chan->freq;
}
@@ -58,5 +58,7 @@ int chan_bw_allowed(const struct hostapd_channel_data *chan, u32 bw,
int ht40_plus, int pri);
int chan_pri_allowed(const struct hostapd_channel_data *chan);
bool is_punct_bitmap_valid(u16 bw, u16 pri_ch_bit_pos, u16 punct_bitmap);
bool chan_in_current_hw_info(struct hostapd_multi_hw_info *current_hw_info,
struct hostapd_channel_data *chan);
#endif /* HW_FEATURES_COMMON_H */
File diff suppressed because it is too large. Load diff
+68 -7
View File
@@ -38,6 +38,11 @@ struct multi_ap_params {
/* Parsed Information Elements */
struct ieee802_11_elems {
/* Control of parsing operations */
bool show_errors;
bool stop_at_mic; /* Whether to stop parsing after MIC element */
/* Parsed data */
const u8 *ssid;
const u8 *supp_rates;
const u8 *ds_params;
@@ -65,6 +70,8 @@ struct ieee802_11_elems {
const u8 *vendor_ht_cap;
const u8 *vendor_vht;
const u8 *p2p;
const u8 *p2p2_ie;
const u8 *pasn_encrypted_data;
const u8 *wfd;
const u8 *link_id;
const u8 *interworking;
@@ -73,7 +80,6 @@ struct ieee802_11_elems {
const u8 *ext_capab;
const u8 *bss_max_idle_period;
const u8 *ssid_list;
const u8 *osen;
const u8 *mbo;
const u8 *ampe;
const u8 *mic;
@@ -93,7 +99,7 @@ struct ieee802_11_elems {
const u8 *key_delivery;
const u8 *wrapped_data;
const u8 *fils_pk;
const u8 *fils_nonce;
const u8 *nonce;
const u8 *owe_dh;
const u8 *power_capab;
const u8 *roaming_cons_sel;
@@ -116,6 +122,15 @@ struct ieee802_11_elems {
const u8 *prior_access_mle;
const u8 *mbssid_known_bss;
const u8 *mbssid;
const u8 *rsne_override;
const u8 *rsne_override_2;
const u8 *rsnxe_override;
const u8 *rsn_selection;
const u8 *wfa_capab;
const u8 *proximity_ranging;
const u8 *akm_suite_selector;
const u8 *supported_groups;
const u8 *nan_ie;
u8 ssid_len;
u8 supp_rates_len;
@@ -136,13 +151,14 @@ struct ieee802_11_elems {
u8 vendor_ht_cap_len;
u8 vendor_vht_len;
u8 p2p_len;
u8 p2p2_ie_len;
u8 pasn_encrypted_data_len;
u8 wfd_len;
u8 interworking_len;
u8 qos_map_set_len;
u8 hs20_len;
u8 ext_capab_len;
u8 ssid_list_len;
u8 osen_len;
u8 mbo_len;
u8 ampe_len;
u8 mic_len;
@@ -156,9 +172,10 @@ struct ieee802_11_elems {
u8 fils_key_confirm_len;
size_t fils_hlp_len;
u8 fils_ip_addr_assign_len;
u8 key_delivery_len;
size_t key_delivery_len;
size_t wrapped_data_len;
u8 fils_pk_len;
u8 nonce_len;
u8 owe_dh_len;
u8 power_capab_len;
u8 roaming_cons_sel_len;
@@ -179,6 +196,15 @@ struct ieee802_11_elems {
size_t prior_access_mle_len;
u8 mbssid_known_bss_len;
u8 mbssid_len;
size_t rsne_override_len;
size_t rsne_override_2_len;
size_t rsnxe_override_len;
size_t rsn_selection_len;
u8 wfa_capab_len;
size_t proximity_ranging_len;
u8 akm_suite_selector_len;
u8 supported_groups_len;
size_t nan_len;
struct mb_ies_info mb_ies;
@@ -196,14 +222,18 @@ typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes;
ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
struct ieee802_11_elems *elems,
int show_errors);
ParseRes ieee802_11_parse_elems_ctrl(const u8 *start, size_t len,
struct ieee802_11_elems *elems);
void ieee802_11_elems_clear_ids(struct ieee802_11_elems *elems,
const u8 *ids, size_t num);
void ieee802_11_elems_clear_ext_ids(struct ieee802_11_elems *elems,
const u8 *ids, size_t num);
ParseRes ieee802_11_parse_link_assoc_req(const u8 *start, size_t len,
struct ieee802_11_elems *elems,
ParseRes ieee802_11_parse_link_assoc_req(struct ieee802_11_elems *elems,
struct wpabuf *mlbuf,
u8 link_id, bool show_errors);
ParseRes ieee802_11_parse_link_assoc_resp(struct ieee802_11_elems *elems,
struct wpabuf *mlbuf,
u8 link_id, bool show_errors);
int ieee802_11_ie_count(const u8 *ies, size_t ies_len);
struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
u32 oui_type);
@@ -244,7 +274,7 @@ int ieee80211_is_dfs(int freq, const struct hostapd_hw_modes *modes,
u16 num_modes);
int is_dfs_global_op_class(u8 op_class);
bool is_80plus_op_class(u8 op_class);
enum phy_type ieee80211_get_phy_type(int freq, int ht, int vht);
enum phy_type ieee80211_get_phy_type(int freq, bool ht, bool vht, bool he);
int supp_rates_11b_only(struct ieee802_11_elems *elems);
int mb_ies_info_by_ies(struct mb_ies_info *info, const u8 *ies_buf,
@@ -289,6 +319,8 @@ u8 country_to_global_op_class(const char *country, u8 op_class);
const struct oper_class_map * get_oper_class(const char *country, u8 op_class);
int oper_class_bw_to_int(const struct oper_class_map *map);
bool is_24ghz_freq(int freq);
bool is_5ghz_freq(int freq);
int center_idx_to_bw_6ghz(u8 idx);
bool is_6ghz_freq(int freq);
bool is_6ghz_op_class(u8 op_class);
@@ -299,6 +331,10 @@ bool is_same_band(int freq1, int freq2);
#define IS_2P4GHZ(n) (n >= 2412 && n <= 2484)
#define IS_5GHZ(n) (n > 4000 && n < 5895)
u8 op_class_idx_to_chan(const struct oper_class_map *op, u8 idx);
int op_class_chan_to_idx(const struct oper_class_map *op, u8 chan);
int ieee80211_get_center_freq(int ctrl_freq, u32 bw);
int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
size_t nei_rep_len);
@@ -309,6 +345,7 @@ bool ieee802_11_rsnx_capab(const u8 *rsnxe, unsigned int capab);
int op_class_to_bandwidth(u8 op_class);
enum oper_chan_width op_class_to_ch_width(u8 op_class);
int chwidth_freq2_to_ch_width(int chwidth, int freq2);
enum oper_chan_width chan_width_to_oper_chwidth(enum chan_width chan_width);
/* element iteration helpers */
#define for_each_element(_elem, _data, _datalen) \
@@ -367,7 +404,31 @@ int ieee802_edmg_is_allowed(struct ieee80211_edmg_config allowed,
struct ieee80211_edmg_config requested);
struct wpabuf * ieee802_11_defrag(const u8 *data, size_t len, bool ext_elem);
ssize_t ieee802_11_defrag_mle_subelem(struct wpabuf *mlbuf,
const u8 *parent_subelem,
size_t *defrag_len);
const u8 * get_ml_ie(const u8 *ies, size_t len, u8 type);
const u8 * get_basic_mle_mld_addr(const u8 *buf, size_t len);
const u8 * get_basic_mle_eml_capa(const u8 *buf, size_t len);
int get_basic_mle_link_id(const u8 *buf, size_t len);
unsigned int get_max_nss_capability(struct ieee802_11_elems *elems,
bool parse_for_rx, enum chan_width bw);
struct supported_chan_width {
bool is_40_supported;
bool is_160_supported;
bool is_80p80_supported;
bool is_320_supported;
};
struct supported_chan_width
get_supported_channel_width(struct ieee802_11_elems *elems, int freq);
enum chan_width get_operation_channel_width(struct ieee802_11_elems *elems);
enum chan_width get_sta_operation_chan_width(
enum chan_width ap_operation_chan_width,
struct supported_chan_width sta_supported_width);
#endif /* IEEE802_11_COMMON_H */
+331 -98
View File
@@ -21,7 +21,7 @@
#define WLAN_FC_RETRY 0x0800
#define WLAN_FC_PWRMGT 0x1000
#define WLAN_FC_MOREDATA 0x2000
#define WLAN_FC_ISWEP 0x4000
#define WLAN_FC_PROTECTED 0x4000
#define WLAN_FC_HTC 0x8000
#define WLAN_FC_S1G_BEACON_NEXT_TBTT 0x0100
@@ -98,28 +98,39 @@
#define WLAN_AUTH_FILS_SK_PFS 5
#define WLAN_AUTH_FILS_PK 6
#define WLAN_AUTH_PASN 7
#define WLAN_AUTH_802_1X 8
#define WLAN_AUTH_EPPKE 9
#define WLAN_AUTH_LEAP 128
/* Authentication transaction sequence number */
#define WLAN_AUTH_TR_SEQ_SAE_COMMIT 1
#define WLAN_AUTH_TR_SEQ_SAE_CONFIRM 2
#define WLAN_AUTH_TR_SEQ_PASN_AUTH1 1
#define WLAN_AUTH_TR_SEQ_PASN_AUTH2 2
#define WLAN_AUTH_TR_SEQ_PASN_AUTH3 3
#define WLAN_AUTH_CHALLENGE_LEN 128
/* IEEE Std 802.11-2024, 9.4.1.4 (Capability Information field) */
#define WLAN_CAPABILITY_ESS BIT(0)
#define WLAN_CAPABILITY_IBSS BIT(1)
#define WLAN_CAPABILITY_CF_POLLABLE BIT(2)
#define WLAN_CAPABILITY_CF_POLL_REQUEST BIT(3)
/* bit 2 is reserved (was WLAN_CAPABILITY_CF_POLLABLE) */
/* bit 3 is reserved (was WLAN_CAPABILITY_CF_POLL_REQUEST) */
#define WLAN_CAPABILITY_PRIVACY BIT(4)
#define WLAN_CAPABILITY_SHORT_PREAMBLE BIT(5)
#define WLAN_CAPABILITY_PBCC BIT(6)
#define WLAN_CAPABILITY_CHANNEL_AGILITY BIT(7)
/* bit 6 is reserved (was WLAN_CAPABILITY_PBCC) */
/* bit 7 is reserved (was WLAN_CAPABILITY_CHANNEL_AGILITY) */
#define WLAN_CAPABILITY_SPECTRUM_MGMT BIT(8)
#define WLAN_CAPABILITY_QOS BIT(9)
#define WLAN_CAPABILITY_SHORT_SLOT_TIME BIT(10)
#define WLAN_CAPABILITY_APSD BIT(11)
#define WLAN_CAPABILITY_RADIO_MEASUREMENT BIT(12)
#define WLAN_CAPABILITY_DSSS_OFDM BIT(13)
#define WLAN_CAPABILITY_DELAYED_BLOCK_ACK BIT(14)
#define WLAN_CAPABILITY_IMM_BLOCK_ACK BIT(15)
#define WLAN_CAPABILITY_EPD BIT(13)
/* bit 14 is reserved (was WLAN_CAPABILITY_DELAYED_BLOCK_ACK) */
/* bit 15 is reserved (was WLAN_CAPABILITY_IMM_BLOCK_ACK) */
/* Status codes (IEEE Std 802.11-2020, 9.4.1.9, Table 9-50) */
/* Status codes (IEEE Std 802.11-2024, 9.4.1.9, Table 9-80) */
#define WLAN_STATUS_SUCCESS 0
#define WLAN_STATUS_UNSPECIFIED_FAILURE 1
#define WLAN_STATUS_TDLS_WAKEUP_ALTERNATE 2
@@ -153,13 +164,13 @@
#define WLAN_STATUS_REQUEST_DECLINED 37
#define WLAN_STATUS_INVALID_PARAMETERS 38
#define WLAN_STATUS_REJECTED_WITH_SUGGESTED_CHANGES 39
#define WLAN_STATUS_INVALID_IE 40
#define WLAN_STATUS_GROUP_CIPHER_NOT_VALID 41
#define WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID 42
#define WLAN_STATUS_AKMP_NOT_VALID 43
#define WLAN_STATUS_UNSUPPORTED_RSN_IE_VERSION 44
#define WLAN_STATUS_INVALID_RSN_IE_CAPAB 45
#define WLAN_STATUS_CIPHER_REJECTED_PER_POLICY 46
#define WLAN_STATUS_INVALID_ELEMENT 40
#define WLAN_STATUS_INVALID_GROUP_CIPHER 41
#define WLAN_STATUS_INVALID_PAIRWISE_CIPHER 42
#define WLAN_STATUS_INVALID_AKMP 43
#define WLAN_STATUS_UNSUPPORTED_RSNE_VERSION 44
#define WLAN_STATUS_INVALID_RSNE_CAPABILITIES 45
#define WLAN_STATUS_CIPHER_OUT_OF_POLICY 46
#define WLAN_STATUS_TS_NOT_CREATED 47
#define WLAN_STATUS_DIRECT_LINK_NOT_ALLOWED 48
#define WLAN_STATUS_DEST_STA_NOT_PRESENT 49
@@ -167,8 +178,8 @@
#define WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE 51
#define WLAN_STATUS_INVALID_FT_ACTION_FRAME_COUNT 52
#define WLAN_STATUS_INVALID_PMKID 53
#define WLAN_STATUS_INVALID_MDIE 54
#define WLAN_STATUS_INVALID_FTIE 55
#define WLAN_STATUS_INVALID_MDE 54
#define WLAN_STATUS_INVALID_FTE 55
#define WLAN_STATUS_REQUESTED_TCLAS_NOT_SUPPORTED 56
#define WLAN_STATUS_INSUFFICIENT_TCLAS_PROCESSING_RESOURCES 57
#define WLAN_STATUS_TRY_ANOTHER_BSS 58
@@ -181,7 +192,7 @@
#define WLAN_STATUS_ADV_SRV_UNREACHABLE 65
#define WLAN_STATUS_REQ_REFUSED_SSPN 67
#define WLAN_STATUS_REQ_REFUSED_UNAUTH_ACCESS 68
#define WLAN_STATUS_INVALID_RSNIE 72
#define WLAN_STATUS_INVALID_RSNE 72
#define WLAN_STATUS_U_APSD_COEX_NOT_SUPPORTED 73
#define WLAN_STATUS_U_APSD_COEX_MODE_NOT_SUPPORTED 74
#define WLAN_STATUS_BAD_INTERVAL_WITH_U_APSD_COEX 75
@@ -233,6 +244,8 @@
#define WLAN_STATUS_DENIED_TX_LINK_NOT_ACCEPTED 139
#define WLAN_STATUS_EPCS_DENIED_VERIFICATION_FAILURE 140
#define WLAN_STATUS_DENIED_OPERATION_PARAMETER_UPDATE 141
#define WLAN_STATUS_802_1_X_AUTH_FAILED 152
#define WLAN_STATUS_802_1_X_AUTH_SUCCESS 153
/* Reason codes (IEEE Std 802.11-2020, 9.4.1.7, Table 9-90) */
#define WLAN_REASON_UNSPECIFIED 1
@@ -495,7 +508,7 @@
#define WLAN_EID_EXT_EXTENDED_REQUEST 10
#define WLAN_EID_EXT_ESTIMATED_SERVICE_PARAMS 11
#define WLAN_EID_EXT_FILS_PUBLIC_KEY 12
#define WLAN_EID_EXT_FILS_NONCE 13
#define WLAN_EID_EXT_NONCE 13
#define WLAN_EID_EXT_FUTURE_CHANNEL_GUIDANCE 14
#define WLAN_EID_EXT_OWE_DH_PARAM 32
#define WLAN_EID_EXT_PASSWORD_IDENTIFIER 33
@@ -504,6 +517,7 @@
#define WLAN_EID_EXT_HE_MU_EDCA_PARAMS 38
#define WLAN_EID_EXT_SPATIAL_REUSE 39
#define WLAN_EID_EXT_COLOR_CHANGE_ANNOUNCEMENT 42
#define WLAN_EID_EXT_MAX_CHANNEL_SWITCH_TIME 52
#define WLAN_EID_EXT_OCV_OCI 54
#define WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION 55
#define WLAN_EID_EXT_NON_INHERITANCE 56
@@ -524,6 +538,10 @@
#define WLAN_EID_EXT_MULTI_LINK_TRAFFIC_INDICATION 110
#define WLAN_EID_EXT_QOS_CHARACTERISTICS 113
#define WLAN_EID_EXT_AKM_SUITE_SELECTOR 114
#define WLAN_EID_EXT_BANDWIDTH_INDICATION 135
#define WLAN_EID_EXT_KNOWN_STA_IDENTIFICATION 136
#define WLAN_EID_EXT_PASN_ENCRYPTED_DATA 140
#define WLAN_EID_EXT_SUPPORTED_GROUPS 161
/* Extended Capabilities field */
#define WLAN_EXT_CAPAB_20_40_COEX 0
@@ -606,6 +624,7 @@
#define WLAN_EXT_CAPAB_BEACON_PROTECTION 84
#define WLAN_EXT_CAPAB_MSCS 85
#define WLAN_EXT_CAPAB_SAE_PK_EXCLUSIVELY 88
#define WLAN_EXT_CAPAB_KNOWN_STA_IDENTIFICATION 102
/* Extended RSN Capabilities */
/* bits 0-3: Field length (n-1) */
@@ -615,8 +634,15 @@
#define WLAN_RSNX_CAPAB_SECURE_LTF 8
#define WLAN_RSNX_CAPAB_SECURE_RTT 9
#define WLAN_RSNX_CAPAB_URNM_MFPR_X20 10
#define WLAN_RSNX_CAPAB_SPP_A_MSDU 14
#define WLAN_RSNX_CAPAB_URNM_MFPR 15
#define WLAN_RSNX_CAPAB_KEK_IN_PASN 18
#define WLAN_RSNX_CAPAB_SSID_PROTECTION 21
#define WLAN_RSNX_CAPAB_ASSOC_FRAME_ENCRYPTION 27
#define WLAN_RSNX_CAPAB_802_1X_IN_AUTH_FRAMES 28
#define WLAN_RSNX_CAPAB_PMKSA_CACHING_PRIVACY 29
#define WLAN_RSNX_CAPAB_SAE_PW_ID_CHANGE 34
#define WLAN_RSNX_CAPAB_UNAUTH_EPPKE 36
/* Multiple BSSID element subelements */
#define WLAN_MBSSID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE 0
@@ -700,7 +726,7 @@
#define WLAN_PA_FILS_DISCOVERY 34
#define WLAN_PA_LOCATION_MEASUREMENT_REPORT 47
/* HT Action field values (IEEE P802.11-REVme/D4.0, 9.6.11.1, Table 9-491) */
/* HT Action field values (IEEE Std 802.11-2024, 9.6.11.1, Table 9-517) */
#define WLAN_HT_ACTION_NOTIFY_CHANWIDTH 0
#define WLAN_HT_ACTION_SMPS 1
#define WLAN_HT_ACTION_CSI 4
@@ -708,7 +734,7 @@
#define WLAN_HT_ACTION_COMPRESSED_BF 6
#define WLAN_HT_ACTION_ASEL_IDX_FEEDBACK 7
/* VHT Action field values (IEEE P802.11-REVme/D4.0, 9.6.22.1, Table 9-579) */
/* VHT Action field values (IEEE Std 802.11-2024, 9.6.22.1, Table 9-605) */
#define WLAN_VHT_ACTION_COMPRESSED_BF 0
#define WLAN_VHT_ACTION_GROUP_ID_MGMT 1
#define WLAN_VHT_ACTION_OPMODE_NOTIF 2
@@ -774,6 +800,21 @@
#define WLAN_PROT_FTM 2
#define WLAN_PROT_FTM_REPORT 3
/* Protected EHT Action field values (IEEE Std 802.11be-2024, Table 9-658d) */
#define WLAN_PROT_EHT_T2L_MAPPING_REQUEST 0
#define WLAN_PROT_EHT_T2L_MAPPING_RESPONSE 1
#define WLAN_PROT_EHT_T2L_MAPPING_TEARDOWN 2
#define WLAN_PROT_EHT_EPCS_ENABLE_REQUEST 3
#define WLAN_PROT_EHT_EPCS_ENABLE_RESPONSE 4
#define WLAN_PROT_EHT_EPCS_ENABLE_TEARDOWN 5
#define WLAN_PROT_EHT_EML_OPMODE_NOTIF 6
#define WLAN_PROT_EHT_LINK_RECOMMENDATION 7
#define WLAN_PROT_EHT_MLO_UPDATE_REQUEST 8
#define WLAN_PROT_EHT_MLO_UPDATE_RESPONSE 9
#define WLAN_PROT_EHT_LINK_RECONFIG_NOTIFY 10
#define WLAN_PROT_EHT_LINK_RECONFIG_REQUEST 11
#define WLAN_PROT_EHT_LINK_RECONFIG_RESPONSE 12
/* Radio Measurement capabilities (from RM Enabled Capabilities element)
* IEEE Std 802.11-2020, 9.4.2.44, Table 9-179 */
/* byte 1 (out of 5) */
@@ -786,6 +827,7 @@
#define WLAN_RRM_CAPS_LCI_MEASUREMENT BIT(4)
/* byte 5 (out of 5) */
#define WLAN_RRM_CAPS_FTM_RANGE_REPORT BIT(2)
#define WLAN_RRM_CAPS_CIVIC_LOCATION_MEASUREMENT BIT(3)
/*
* IEEE Std 802.11-2020, 9.4.2.20.19 (Fine Timing Measurement Range
@@ -941,7 +983,7 @@ enum lci_req_subelem {
LCI_REQ_SUBELEM_MAX_AGE = 4,
};
#define FILS_NONCE_LEN 16
#define NONCE_LEN 16
#define FILS_SESSION_LEN 8
#define FILS_CACHE_ID_LEN 2
#define FILS_MAX_KEY_AUTH_LEN 48
@@ -1160,12 +1202,40 @@ struct ieee80211_mgmt {
u8 dialog_token;
u8 variable[];
} STRUCT_PACKED rrm;
struct {
u8 action; /* Protected EHT - 11 */
u8 dialog_token;
/* Reconfiguration Multi-Link element,
* OCI element (optional) */
u8 variable[];
} STRUCT_PACKED link_reconf_req;
struct {
u8 action; /* Protected EHT - 12 */
u8 dialog_token;
u8 count;
/* Reconfiguration status list,
* Group Key Data (optional),
* OCI element (optional),
* Basic Multi-Link element (optional) */
u8 variable[];
} STRUCT_PACKED link_reconf_resp;
struct {
u8 action;
u8 oui[3];
u8 oui_type;
u8 subtype;
u8 variable[0];
} STRUCT_PACKED naf;
} u;
} STRUCT_PACKED action;
} u;
} STRUCT_PACKED;
#define IEEE80211_MIN_ACTION_LEN(type) \
(offsetof(struct ieee80211_mgmt, u.action.u.type) + \
sizeof(((struct ieee80211_mgmt *) 0)->u.action.u.type))
#define IEEE80211_MAX_MMPDU_SIZE 2304
/* Rx MCS bitmask is in the first 77 bits of supported_mcs_set */
@@ -1343,6 +1413,7 @@ struct ieee80211_ampe_ie {
#define HT_OPER_PARAM_PCO_PHASE ((u16) BIT(11))
/* B36..B39 - Reserved */
#define BSS_MEMBERSHIP_SELECTOR_EHT_PHY 121
#define BSS_MEMBERSHIP_SELECTOR_HE_PHY 122
#define BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY 123
#define BSS_MEMBERSHIP_SELECTOR_EPD 124
@@ -1425,15 +1496,16 @@ struct ieee80211_ampe_ie {
#define WPS_IE_VENDOR_TYPE 0x0050f204
#define OUI_WFA 0x506f9a
#define P2P_IE_VENDOR_TYPE 0x506f9a09
#define P2P2_IE_VENDOR_TYPE 0x506f9a28
#define WFD_IE_VENDOR_TYPE 0x506f9a0a
#define WFD_OUI_TYPE 10
#define HS20_IE_VENDOR_TYPE 0x506f9a10
#define OSEN_IE_VENDOR_TYPE 0x506f9a12
#define NAN_IE_VENDOR_TYPE 0x506f9a13
#define NAN_SDF_VENDOR_TYPE 0x506f9a13
#define NAN_OUI_TYPE 0x13
#define NAN_SDF_OUI_TYPE 0x13
#define MBO_IE_VENDOR_TYPE 0x506f9a16
#define NAN_NAF_VENDOR_TYPE 0x506f9a18
#define NAN_NAF_OUI_TYPE 0x18
#define MBO_OUI_TYPE 22
#define OWE_IE_VENDOR_TYPE 0x506f9a1c
#define OWE_OUI_TYPE 28
@@ -1446,6 +1518,17 @@ struct ieee80211_ampe_ie {
#define QM_IE_OUI_TYPE 0x22
#define WFA_CAPA_IE_VENDOR_TYPE 0x506f9a23
#define WFA_CAPA_OUI_TYPE 0x23
#define WFA_RSNE_OVERRIDE_OUI_TYPE 0x29
#define WFA_RSNE_OVERRIDE_2_OUI_TYPE 0x2a
#define WFA_RSNXE_OVERRIDE_OUI_TYPE 0x2b
#define WFA_RSN_SELECTION_OUI_TYPE 0x2c
#define RSNE_OVERRIDE_IE_VENDOR_TYPE 0x506f9a29
#define RSNE_OVERRIDE_2_IE_VENDOR_TYPE 0x506f9a2a
#define RSNXE_OVERRIDE_IE_VENDOR_TYPE 0x506f9a2b
#define RSN_SELECTION_IE_VENDOR_TYPE 0x506f9a2c
/* Proximity Ranging (PR) */
#define PR_IE_VENDOR_TYPE 0x506f9a2e
#define PR_OUI_TYPE 0x2e
#define MULTI_AP_SUB_ELEM_TYPE 0x06
#define MULTI_AP_PROFILE_SUB_ELEM_TYPE 0x07
@@ -1579,7 +1662,6 @@ enum wmm_ac {
#define HS20_INDICATION_OUI_TYPE 16
#define HS20_ANQP_OUI_TYPE 17
#define HS20_OSEN_OUI_TYPE 18
#define HS20_ROAMING_CONS_SEL_OUI_TYPE 29
#define HS20_STYPE_QUERY_LIST 1
#define HS20_STYPE_CAPABILITY_LIST 2
@@ -1588,11 +1670,6 @@ enum wmm_ac {
#define HS20_STYPE_CONNECTION_CAPABILITY 5
#define HS20_STYPE_NAI_HOME_REALM_QUERY 6
#define HS20_STYPE_OPERATING_CLASS 7
#define HS20_STYPE_OSU_PROVIDERS_LIST 8
#define HS20_STYPE_ICON_REQUEST 10
#define HS20_STYPE_ICON_BINARY_FILE 11
#define HS20_STYPE_OPERATOR_ICON_METADATA 12
#define HS20_STYPE_OSU_PROVIDERS_NAI_LIST 13
#define HS20_DGAF_DISABLED 0x01
#define HS20_PPS_MO_ID_PRESENT 0x02
@@ -1602,7 +1679,6 @@ enum wmm_ac {
#endif /* HS20_VERSION */
/* WNM-Notification WFA vendors specific subtypes */
#define HS20_WNM_SUB_REM_NEEDED 0
#define HS20_WNM_DEAUTH_IMMINENT_NOTICE 1
#define WFA_WNM_NOTIF_SUBELEM_NON_PREF_CHAN_REPORT 2
#define WFA_WNM_NOTIF_SUBELEM_CELL_DATA_CAPA 3
@@ -1710,6 +1786,7 @@ enum mbo_transition_reject_reason {
/* Wi-Fi Direct (P2P) */
#define P2P_OUI_TYPE 9
#define P2P2_OUI_TYPE 0x28
enum p2p_attr_id {
P2P_ATTR_STATUS = 0,
@@ -1740,6 +1817,13 @@ enum p2p_attr_id {
P2P_ATTR_SESSION_ID = 26,
P2P_ATTR_FEATURE_CAPABILITY = 27,
P2P_ATTR_PERSISTENT_GROUP = 28,
P2P_ATTR_CAPABILITY_EXTENSION = 29,
P2P_ATTR_WLAN_AP_INFORMATION = 30,
P2P_ATTR_DEVICE_IDENTITY_KEY = 31,
P2P_ATTR_DEVICE_IDENTITY_RESOLUTION = 32,
P2P_ATTR_PAIRING_AND_BOOTSTRAPPING = 33,
P2P_ATTR_PASSWORD = 34,
P2P_ATTR_ACTION_FRAME_WRAPPER = 35,
P2P_ATTR_VENDOR_SPECIFIC = 221
};
@@ -1764,6 +1848,31 @@ enum p2p_attr_id {
#define P2P_GROUP_CAPAB_GROUP_FORMATION BIT(6)
#define P2P_GROUP_CAPAB_IP_ADDR_ALLOCATION BIT(7)
/* P2P Capability Extension attribute - Capability info */
#define P2P_PCEA_LEN_MASK (BIT(0) | BIT(1) | BIT(2) | BIT(3))
#define P2P_PCEA_6GHZ BIT(4)
#define P2P_PCEA_REG_INFO BIT(5)
#define P2P_PCEA_DFS_OWNER BIT(6)
#define P2P_PCEA_CLI_REQ_CS BIT(7)
#define P2P_PCEA_PAIRING_CAPABLE BIT(8)
#define P2P_PCEA_PAIRING_SETUP_ENABLED BIT(9)
#define P2P_PCEA_PMK_CACHING BIT(10)
#define P2P_PCEA_PASN_TYPE BIT(11)
#define P2P_PCEA_TWT_POWER_MGMT BIT(12)
/* P2P Pairing Bootstrapping Method attribute - Bootstrapping Method */
#define P2P_PBMA_OPPORTUNISTIC BIT(0)
#define P2P_PBMA_PIN_CODE_DISPLAY BIT(1)
#define P2P_PBMA_PASSPHRASE_DISPLAY BIT(2)
#define P2P_PBMA_QR_DISPLAY BIT(3)
#define P2P_PBMA_NFC_TAG BIT(4)
#define P2P_PBMA_PIN_CODE_KEYPAD BIT(5)
#define P2P_PBMA_PASSPHRASE_KEYPAD BIT(6)
#define P2P_PBMA_QR_SCAN BIT(7)
#define P2P_PBMA_NFC_READER BIT(8)
#define P2P_PBMA_SERVICE_MANAGED BIT(14)
#define P2P_PBMA_HANDSHAKE_SKIP BIT(15)
/* P2PS Coordination Protocol Transport Bitmap */
#define P2PS_FEATURE_CAPAB_UDP_TRANSPORT BIT(0)
#define P2PS_FEATURE_CAPAB_MAC_TRANSPORT BIT(1)
@@ -1795,6 +1904,7 @@ enum p2p_status_code {
P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD = 10,
P2P_SC_FAIL_REJECTED_BY_USER = 11,
P2P_SC_SUCCESS_DEFERRED = 12,
P2P_SC_COMEBACK = 13,
};
enum p2p_role_indication {
@@ -1989,6 +2099,7 @@ enum bss_trans_mgmt_reason {
#define WNM_NEIGHBOR_MULTIPLE_BSSID 71
#define WNM_NEIGHBOR_VHT_CAPAB 191
#define WNM_NEIGHBOR_VHT_OPER 192
#define WNM_NEIGHBOR_MULTI_LINK 201
/* QoS action */
enum qos_action {
@@ -2322,9 +2433,10 @@ enum phy_type {
PHY_TYPE_S1G = 11,
PHY_TYPE_CDMG = 12,
PHY_TYPE_CMMG = 13,
PHY_TYPE_HE = 14,
};
/* IEEE Std 802.11-2020, 9.4.2.36 - Neighbor Report element */
/* IEEE Std 802.11-2024, 9.4.2.35 - Neighbor Report element */
/* BSSID Information Field */
#define NEI_REP_BSSID_INFO_AP_NOT_REACH BIT(0)
#define NEI_REP_BSSID_INFO_AP_UNKNOWN_REACH BIT(1)
@@ -2335,14 +2447,21 @@ enum phy_type {
#define NEI_REP_BSSID_INFO_QOS BIT(5)
#define NEI_REP_BSSID_INFO_APSD BIT(6)
#define NEI_REP_BSSID_INFO_RM BIT(7)
#define NEI_REP_BSSID_INFO_DELAYED_BA BIT(8)
#define NEI_REP_BSSID_INFO_IMM_BA BIT(9)
/* bit 8 is reserved (was NEI_REP_BSSID_INFO_DELAYED_BA) */
/* bit 9 is reserved (was NEI_REP_BSSID_INFO_IMM_BA) */
#define NEI_REP_BSSID_INFO_MOBILITY_DOMAIN BIT(10)
#define NEI_REP_BSSID_INFO_HT BIT(11)
#define NEI_REP_BSSID_INFO_VHT BIT(12)
#define NEI_REP_BSSID_INFO_FTM BIT(13)
#define NEI_REP_BSSID_INFO_HE BIT(14)
#define NEI_REP_BSSID_INFO_ER_BSS BIT(15)
#define NEI_REP_BSSID_INFO_COLOCATED_AP BIT(16)
#define NEI_REP_BSSID_INFO_UNSOLIC_PROBE_RESP BIT(17)
#define NEI_REP_BSSID_INFO_MEMBER_OF_ESS_WITH_COLOC_AP BIT(18)
#define NEI_REP_BSSID_INFO_OCT_WITH_REPORTING_AP BIT(19)
#define NEI_REP_BSSID_INFO_COLOCATED_WITH_6GHZ BIT(20)
#define NEI_REP_BSSID_INFO_EHT BIT(21)
#define NEI_REP_BSSID_INFO_DMG_POSITIONING BIT(22)
/*
* IEEE Std 802.11-2020, Table 9-175 - HT/VHT Operation Information
@@ -2360,9 +2479,16 @@ enum nr_chan_width {
struct ieee80211_he_capabilities {
u8 he_mac_capab_info[6];
u8 he_phy_capab_info[11];
/* Followed by 4, 8, or 12 octets of Supported HE-MCS And NSS Set field
* and optional variable length PPE Thresholds field. */
u8 optional[37];
/* Supported HE-MCS And NSS Set field */
struct {
le16 rx_map; /* Rx HE-MCS Map <= 80 MHz */
le16 tx_map; /* Tx HE-MCS Map <= 80 MHz */
/* Followed by 0, 4, or 8 octets of optional Rx/Tx HE-MCS maps
* for 160 MHz and 80+80 MHz. These are included in the
* optional[] below. */
} he_basic_supported_mcs_set;
/* Followed by optional variable length PPE Thresholds field. */
u8 optional[33];
} STRUCT_PACKED;
#define IEEE80211_HE_CAPAB_MIN_LEN (6 + 11)
@@ -2439,6 +2565,8 @@ struct ieee80211_spatial_reuse {
u8 params[19];
} STRUCT_PACKED;
#define HE_CAPABILITIES_ELEM_MIN_LEN 21
/* HE Capabilities Information defines */
#define HE_MACCAP_TWT_RESPONDER ((u8) BIT(2))
@@ -2490,10 +2618,17 @@ struct ieee80211_spatial_reuse {
#define HE_OPERATION_BSS_COLOR_OFFSET 24
#define HE_OPERATION_BSS_COLOR_MAX 64
/* HE operation fields length */
#define HE_OPERATION_ELEM_MIN_LEN 6
#define HE_OPERATION_VHT_OPER_INFO_LEN 3
#define HE_OPERATION_COHOSTED_BSSID_INDICATOR_LEN 1
#define HE_OPERATION_6GHZ_OPER_INFO_LEN 5
/**
* enum he_reg_info_6ghz_ap_type - Allowed Access Point types for 6 GHz Band
*
* IEEE P802.11-REVme/D4.0, Table E-12 (Regulatory Info subfield encoding)
* IEEE Std 802.11-2024, Table E-12 (Regulatory Info subfield interpretation by
* non-AP STAs with dot11ExtendedRegInfoSupport not set to true)
*/
enum he_reg_info_6ghz_ap_type {
HE_REG_INFO_6GHZ_AP_TYPE_INDOOR = 0,
@@ -2583,7 +2718,7 @@ struct ieee80211_he_mu_edca_parameter_set {
* transmit power is specified for the corresponding 20 MHz channel. */
#define RNR_20_MHZ_PSD_MAX_TXPOWER 127
/* IEEE P802.11be/D5.0, Figure 9-704c - MLD Parameters subfield format */
/* IEEE Std 802.11be-2024, Figure 9-734c - MLD Parameters subfield format */
/* B0..B7: AP MLD ID */
/* B8..B11: Link ID */
/* B12..B19: BSS Parameters Change Count */
@@ -2592,24 +2727,30 @@ struct ieee80211_he_mu_edca_parameter_set {
/* B21: Disabled Link Indication */
#define RNR_TBTT_INFO_MLD_PARAM2_LINK_DISABLED 0x20
/* IEEE P802.11be/D2.3, 9.4.2.311 - EHT Operation element */
/* IEEE Std 802.11be-2024, 9.4.2.321 - EHT Operation element */
#define EHT_OPERATION_ELEM_MIN_LEN 5
/* Figure 9-1002b: EHT Operation Parameters field subfields */
/* Figure 9-1074j: EHT Operation Parameters field format */
#define EHT_OPER_INFO_PRESENT BIT(0)
#define EHT_OPER_DISABLED_SUBCHAN_BITMAP_PRESENT BIT(1)
#define EHT_OPER_DEFAULT_PE_DURATION BIT(2)
#define EHT_OPER_GROUP_ADDR_BU_INDICATION_LIMIT BIT(3)
#define EHT_OPER_GROUP_ADDR_BU_INDICATION_EXPONENT (BIT(4) | BIT(5))
#define EHT_OPER_MCS15_DISABLE BIT(6)
#define EHT_OPER_DISABLED_SUBCHAN_BITMAP_SIZE 2
/* Control subfield: Channel Width subfield; see Table 9-401b */
/* Control subfield: Channel Width subfield; see Table 9-417e (Channel width,
* CCFS0, and CCFS1 subfields) */
#define EHT_OPER_CHANNEL_WIDTH_MASK 0x7
#define EHT_OPER_CHANNEL_WIDTH_20MHZ 0
#define EHT_OPER_CHANNEL_WIDTH_40MHZ 1
#define EHT_OPER_CHANNEL_WIDTH_80MHZ 2
#define EHT_OPER_CHANNEL_WIDTH_160MHZ 3
#define EHT_OPER_CHANNEL_WIDTH_320MHZ 4
/* Figure 9-1002c: EHT Operation Information field format */
/* Figure 9-1074k: EHT Operation Information field format */
#define EHT_OPER_INFO_MIN_LEN 3
struct ieee80211_eht_oper_info {
u8 control; /* B0..B2: Channel Width */
u8 ccfs0;
@@ -2617,16 +2758,17 @@ struct ieee80211_eht_oper_info {
le16 disabled_chan_bitmap; /* 0 or 2 octets */
} STRUCT_PACKED;
/* Figure 9-1002a: EHT Operation element format */
/* Figure 9-1074i: EHT Operation element format */
struct ieee80211_eht_operation {
u8 oper_params; /* EHT Operation Parameters: EHT_OPER_* bits */
u8 basic_eht_mcs_nss_set[4];
struct ieee80211_eht_oper_info oper_info; /* 0 or 3 or 5 octets */
} STRUCT_PACKED;
/* IEEE P802.11be/D1.5, 9.4.2.313 - EHT Capabilities element */
/* IEEE Std 802.11be-2024, 9.4.2.323 - EHT Capabilities element */
#define EHT_CAPABILITIES_ELEM_MIN_LEN 11
/* Figure 9-1002af: EHT MAC Capabilities Information field */
/* Figure 9-1074ap: EHT MAC Capabilities Information field format */
#define EHT_MACCAP_EPCS_PRIO BIT(0)
#define EHT_MACCAP_OM_CONTROL BIT(1)
#define EHT_MACCAP_TRIGGERED_TXOP_MODE1 BIT(2)
@@ -2639,7 +2781,7 @@ struct ieee80211_eht_operation {
#define EHT_MACCAP_MAX_MPDU_LEN_11454 BIT(7)
#define EHT_MACCAP_MAX_AMPDU_LEN_EXP_EXT BIT(8)
/* Figure 9-1002ag: EHT PHY Capabilities Information field format
/* Figure 9-1074aq: EHT PHY Capabilities Information field format
* _IDX indicates the octet index within the field */
#define EHT_PHY_CAPAB_LEN 9
@@ -2662,20 +2804,20 @@ struct ieee80211_eht_operation {
EHT_PHYCAP_MU_BEAMFORMER_160MHZ | \
EHT_PHYCAP_MU_BEAMFORMER_320MHZ)
/* Figure 9-1002ah: Supported EHT-MCS and NSS Set field format */
/* Figure 9-1074ar: Supported EHT-MCS and NSS Set field format */
#define EHT_PHYCAP_MCS_NSS_LEN_20MHZ_ONLY 4
#define EHT_PHYCAP_MCS_NSS_LEN_20MHZ_PLUS 3
#define EHT_MCS_NSS_CAPAB_LEN 9
/*
* Figure 9-1002ak: EHT PPE Thresholds field format
* Figure 9-1074au: EHT PPE Thresholds field format
* Maximum PPE threshold length: 62 octets
* NSS: 4 bits (maximum NSS: 16), RU index: 5 bits, each pair: 6 bits
* 4 + 5 + 5 * 16 * 6 = 489 bits, Padding: 7 bits
*/
#define EHT_PPE_THRESH_CAPAB_LEN 62
/* 9.4.2.313.5: EHT PPE Thresholds field */
/* 9.4.2.323.5: EHT PPE Thresholds field */
#define EHT_PPE_THRES_NSS_SHIFT 0
#define EHT_PPE_THRES_NSS_MASK ((u8) (BIT(0) | BIT(1) | \
BIT(2) | BIT(3)))
@@ -2686,7 +2828,7 @@ struct ieee80211_eht_operation {
#define EHT_NSS_MAX_STREAMS 8
/* Figure 9-1002ae: EHT Capabilities element format */
/* Figure 9-1074ao: EHT Capabilities element format */
struct ieee80211_eht_capabilities {
/* EHT MAC Capabilities Information */
le16 mac_cap;
@@ -2698,13 +2840,13 @@ struct ieee80211_eht_capabilities {
#define IEEE80211_EHT_CAPAB_MIN_LEN (2 + 9)
/* IEEE P802.11be/D2.1, 9.4.2.312 - Multi-Link element */
/* IEEE Std P802.11be-2024, 9.4.2.322 - Multi-Link element */
/* Figure 9-1002f: Multi-Link Control field */
/* Figure 9-1074n: Multi-Link Control field */
#define MULTI_LINK_CONTROL_TYPE_MASK 0x07
#define MULTI_LINK_CONTROL_LEN 2
/* Table 9-401c: Mult-Link element Type subfield encoding */
/* Table 9-417f: [Multi-Link element] Type subfield encoding */
#define MULTI_LINK_CONTROL_TYPE_BASIC 0
#define MULTI_LINK_CONTROL_TYPE_PROBE_REQ 1
#define MULTI_LINK_CONTROL_TYPE_RECONF 2
@@ -2712,26 +2854,28 @@ struct ieee80211_eht_capabilities {
#define MULTI_LINK_CONTROL_TYPE_PRIOR_ACCESS 4
/*
* IEEE P802.11be/D2.2, Table 9-401c: Optional subelement IDs for Link Info
* field of the Multi-Link element
* Table 9-417g: Optional subelement IDs for Link Info field of the Multi-Link
* element
*/
#define MULTI_LINK_SUB_ELEM_ID_PER_STA_PROFILE 0
#define MULTI_LINK_SUB_ELEM_ID_VENDOR 221
#define MULTI_LINK_SUB_ELEM_ID_FRAGMENT 254
/* IEEE P802.11be/D2.2, 9.4.2.312.2 - Basic Multi-Link element */
/* IEEE Std 802.11be-2024, 9.4.2.322.2 - Basic Multi-Link element */
/* Figure 9-1002g: Presence Bitmap subfield of the Basic Multi-Link element */
/* Figure 9-1074o: Presence Bitmap subfield of the Basic Multi-Link element */
#define BASIC_MULTI_LINK_CTRL_PRES_LINK_ID 0x0010
#define BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT 0x0020
#define BASIC_MULTI_LINK_CTRL_PRES_MSD_INFO 0x0040
#define BASIC_MULTI_LINK_CTRL_PRES_EML_CAPA 0x0080
#define BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA 0x0100
#define BASIC_MULTI_LINK_CTRL_PRES_AP_MLD_ID 0x0200
#define BASIC_MULTI_LINK_CTRL_PRES_EXT_MLD_CAP 0x0400
/*
* STA Control field definitions of Per-STA Profile subelement in Basic
* Multi-Link element as described in Figure 9-1002n: STA Control field format.
* Multi-Link element as described in Figure 9-1074v: STA Control field format
* of the Basic Multi-Link element.
*/
#define BASIC_MLE_STA_CTRL_LEN 2
#define BASIC_MLE_STA_CTRL_LINK_ID_MASK 0x000F
@@ -2746,7 +2890,7 @@ struct ieee80211_eht_capabilities {
#define BASIC_MLE_STA_PROF_STA_MAC_IDX 3
/* IEEE P802.11be/D2.2, 9.4.2.312.2.3 - Common Info field of the Basic
/* IEEE Std 802.11be-2024, 9.4.2.322.2.3 - Common Info field of the Basic
* Multi-Link element */
struct eht_ml_basic_common_info {
u8 len;
@@ -2762,10 +2906,17 @@ struct eht_ml_basic_common_info {
* EML Capabilities: 2 octets
* MLD Capabilities and Operations: 2 octets
* AP MLD ID: 1 octet
* Extended MLD Capabilities And Operations: 2 octets
*/
u8 variable[];
} STRUCT_PACKED;
/* Length of the EML Capabilities field in the Common Info field (in octets) */
#define EHT_ML_EML_CAPA_LEN 2
/* Length of the Link ID Info field in the Common Info field (in octets) */
#define EHT_ML_LINK_ID_LEN 1
#define EHT_ML_LINK_ID_MSK 0x0f
#define EHT_ML_MEDIUM_SYNC_DELAY_DURATION 0x00ff
@@ -2776,39 +2927,29 @@ struct eht_ml_basic_common_info {
#define EHT_ML_EML_CAPA_EMLSR_PADDING_DELAY_MASK 0x000e
#define EHT_ML_EML_CAPA_EMLSR_TRANS_DELAY_MASK 0x0070
#define EHT_ML_EML_CAPA_EMLMR_SUPP 0x0080
#define EHT_ML_EML_CAPA_EMLMR_DELAY_MASK 0x0700
#define EHT_ML_EML_CAPA_TRANSITION_TIMEOUT_MASK 0x7800
#define EHT_ML_EML_CAPA_RESERVED 0x8700
#define EHT_ML_MLD_CAPA_MAX_NUM_SIM_LINKS_MASK 0x000f
#define EHT_ML_MLD_CAPA_SRS_SUPP 0x0010
#define EHT_ML_MLD_CAPA_TID_TO_LINK_MAP_ALL_TO_ALL 0x0020
#define EHT_ML_MLD_CAPA_TID_TO_LINK_MAP_ALL_TO_ONE 0x0040
#define EHT_ML_MLD_CAPA_TID_TO_LINK_MAP_NEG_SUPP_MSK 0x0060
#define EHT_ML_MLD_CAPA_AP_MLD_TYPE_IND_MASK 0x0080
#define EHT_ML_MLD_CAPA_FREQ_SEP_FOR_STR_MASK 0x0f80
#define EHT_ML_MLD_CAPA_AAR_SUPP 0x1000
#define EHT_ML_MLD_CAPA_LINK_RECONF_OP_SUPPORT 0x2000
#define EHT_ML_MLD_CAPA_ALIGNED_TWT_SUPPORT 0x4000
#define EHT_ML_MLD_CAPA_RESERVED 0x8000
#define EHT_PER_STA_CTRL_LINK_ID_MSK 0x000f
#define EHT_PER_STA_CTRL_COMPLETE_PROFILE_MSK 0x0010
#define EHT_PER_STA_CTRL_MAC_ADDR_PRESENT_MSK 0x0020
#define EHT_PER_STA_CTRL_BEACON_INTERVAL_PRESENT_MSK 0x0040
#define EHT_PER_STA_CTRL_TSF_OFFSET_PRESENT_MSK 0x0080
#define EHT_PER_STA_CTRL_DTIM_INFO_PRESENT_MSK 0x0100
#define EHT_PER_STA_CTRL_NSTR_LINK_PAIR_PRESENT_MSK 0x0200
#define EHT_PER_STA_CTRL_NSTR_BM_SIZE_MSK 0x0400
#define EHT_PER_STA_CTRL_BSS_PARAM_CNT_PRESENT_MSK 0x0800
#define EHT_ML_EXT_MLD_CAPA_OP_PARAM_UPDATE 0x0001
#define EHT_ML_EXT_MLD_CAPA_OP_RECO_MAX_LINKS_MASK 0x001e
#define EHT_ML_EXT_MLD_CAPA_NSTR_UPDATE 0x0020
#define EHT_ML_EXT_MLD_CAPA_EMLSR_ENA_ONE_LINK 0x0040
#define EHT_ML_EXT_MLD_CAPA_BTM_MLD_RECO_MULTI_AP 0x0080
/* IEEE P802.11be/D4.1, Figure 9-1001x - STA Control field format for the
* Reconfiguration Multi-Link element */
#define EHT_PER_STA_RECONF_CTRL_LINK_ID_MSK 0x000f
#define EHT_PER_STA_RECONF_CTRL_COMPLETE_PROFILE 0x0010
#define EHT_PER_STA_RECONF_CTRL_MAC_ADDR 0x0020
#define EHT_PER_STA_RECONF_CTRL_AP_REMOVAL_TIMER 0x0040
#define EHT_PER_STA_RECONF_CTRL_OP_UPDATE_TYPE_MSK 0x0780
#define EHT_PER_STA_RECONF_CTRL_OP_PARAMS 0x0800
#define EHT_PER_STA_RECONF_CTRL_NSTR_BITMAP_SIZE 0x1000
#define EHT_PER_STA_RECONF_CTRL_NSTR_INDIC_BITMAP 0x2000
/* IEEE P802.11be/D2.0, 9.4.2.312.2.4 - Per-STA Profile subelement format */
/* IEEE Std 802.11be-2024, Figure 9-1074u - Per-STA Profile subelement format
* of the Basic Multi-Link element*/
struct ieee80211_eht_per_sta_profile {
le16 sta_control;
@@ -2816,11 +2957,14 @@ struct ieee80211_eht_per_sta_profile {
u8 variable[];
} STRUCT_PACKED;
/* IEEE P802.11be/D4.0, 9.4.2.312.3 - Probe Request Multi-Link element
/* IEEE Std 802.11be-2024, 9.4.2.322.3 - Probe Request Multi-Link element
* Figure 9-1074y - Presence Bitmap field format of the Probe Request
* Multi-Link element
* Presence Bitmap field is B4..B15 of the Multi-Link Control field, i.e.,
* B0 in the presence bitmap is B4 in the control field. */
#define EHT_ML_PRES_BM_PROBE_REQ_AP_MLD_ID 0x0010
#define EHT_ML_PRES_BM_PROBE_REQ_MLD_MAC_ADDR 0x0020
struct eht_ml_probe_req_common_info {
u8 len;
@@ -2830,13 +2974,17 @@ struct eht_ml_probe_req_common_info {
* bitmap
*
* AP MLD ID: 1 octet
* MLD MAC Address: 6 cotets
*/
u8 variable[];
} STRUCT_PACKED;
/* IEEE P802.11be/D4.0, 9.4.2.312.4 - Reconfiguration Multi-Link element */
/* IEEE Std 802.11be-2024, 9.4.2.322.4 - Reconfiguration Multi-Link element */
#define RECONF_MULTI_LINK_CTRL_PRES_MLD_MAC_ADDR 0x0001
#define RECONF_MULTI_LINK_CTRL_PRES_EML_CAPA 0x0002
#define RECONF_MULTI_LINK_CTRL_PRES_MLD_CAPA 0x0004
#define RECONF_MULTI_LINK_CTRL_PRES_EXT_MLD_CAP 0x0008
#define EHT_PER_STA_RECONF_CTRL_LINK_ID_MSK 0x000f
#define EHT_PER_STA_RECONF_CTRL_COMPLETE_PROFILE 0x0010
@@ -2845,8 +2993,54 @@ struct eht_ml_probe_req_common_info {
#define EHT_PER_STA_RECONF_CTRL_OP_UPDATE_TYPE_MSK 0x0780
#define EHT_PER_STA_RECONF_CTRL_OP_PARAMS 0x0800
#define EHT_PER_STA_RECONF_CTRL_NSTR_BITMAP_SIZE 0x1000
#define EHT_PER_STA_RECONF_CTRL_NSTR_INDICATION 0x2000
/* IEEE P802.11be/D2.0, 9.4.2.312.1 - Multi-Link element / General */
#define EHT_PER_STA_RECONF_CTRL_OP_UPDATE_TYPE_VAL(x) ((x) >> 7)
/* IEEE Std 802.11be-2024, Figure 9-1074ad - Common Info field format of the
* Reconfiguration Multi-Link element */
struct eht_ml_reconf_common_info {
u8 len;
/*
* Followed by optional fields based on the multi link reconf presence
* bitmap
*
* MLD MAC Address: 6 octets
* EML Capabilities: 2 octets
* MLD Capabilities and Operations: 2 octets
* Extended MLD Capabilities and Operations: 2 octets
*/
u8 variable[];
} STRUCT_PACKED;
/* IEEE Std 802.11be-2024, Table 9-417p - Reconfiguration Operation Type
* subfield encoding */
enum ieee80211_eht_reconf_mle_op_type {
EHT_RECONF_TYPE_AP_REMOVAL = 0,
EHT_RECONF_TYPE_OP_PARAM_UPDATE = 1,
EHT_RECONF_TYPE_ADD_LINK = 2,
EHT_RECONF_TYPE_DELETE_LINK = 3,
EHT_RECONF_TYPE_NSTR_STATUS_UPDATE = 4,
};
/* IEEE Std 802.11be-2024, Figure 9-1074ag — STA Info field format for the
* Reconfiguration Multi-Link element */
struct eht_ml_reconf_sta_info {
u8 len;
/* Followed by optional fields based on STA control presence bitmap.
*
* STA MAC Address: 6 octets
* AP Removal Timer: 2 octets
* Operation Parameters: 3 octets
* NSTR Indication Bitmap: 1 or 2 octets
*/
u8 variable[];
} STRUCT_PACKED;
/* IEEE Std 802.11be-2024, 9.4.2.322.1 - Multi-Link element / General */
struct ieee80211_eht_ml {
le16 ml_control;
@@ -2855,13 +3049,32 @@ struct ieee80211_eht_ml {
u8 variable[];
} STRUCT_PACKED;
/* Table 9-401c - Optional subelement IDs for Link Info field of the
* Multi-Link element */
enum ieee80211_eht_ml_sub_elem {
EHT_ML_SUB_ELEM_PER_STA_PROFILE = 0,
EHT_ML_SUB_ELEM_VENDOR = 221,
EHT_ML_SUB_ELEM_FRAGMENT = 254,
};
/* IEEE Std 802.11be-2024, 9.4.2.329 (Bandwidth Indication element) defines the
* Bandwidth Indication Information field to have the same definition as the
* EHT Operation Information field in the EHT Operation element.
*/
struct ieee80211_bw_ind_info {
u8 control; /* B0..B2: Channel Width */
u8 ccfs0;
u8 ccfs1;
le16 disabled_chan_bitmap; /* 0 or 2 octets */
} STRUCT_PACKED;
/* Control subfield: Channel Width subfield; see Table 9-417e (Channel width,
* CCFS0, and CCFS1 subfields) in IEEE Std 802.11be-2024. */
#define BW_IND_CHANNEL_WIDTH_20MHZ EHT_OPER_CHANNEL_WIDTH_20MHZ
#define BW_IND_CHANNEL_WIDTH_40MHZ EHT_OPER_CHANNEL_WIDTH_40MHZ
#define BW_IND_CHANNEL_WIDTH_80MHZ EHT_OPER_CHANNEL_WIDTH_80MHZ
#define BW_IND_CHANNEL_WIDTH_160MHZ EHT_OPER_CHANNEL_WIDTH_160MHZ
#define BW_IND_CHANNEL_WIDTH_320MHZ EHT_OPER_CHANNEL_WIDTH_320MHZ
/* IEEE Std 802.11be-2024, 9.4.2.329 (Bandwidth Indication element) */
struct ieee80211_bw_ind_element {
u8 bw_ind_params; /* Bandwidth Indication Parameters */
struct ieee80211_bw_ind_info bw_ind_info; /* 3 or 5 octets */
} STRUCT_PACKED;
#define BW_IND_PARAMETER_DISABLED_SUBCHAN_BITMAP_PRESENT BIT(1)
/* IEEE P802.11ay/D4.0, 9.4.2.251 - EDMG Operation element */
#define EDMG_BSS_OPERATING_CHANNELS_OFFSET 6
@@ -2915,9 +3128,20 @@ enum scs_request_type {
SCS_REQ_CHANGE = 2,
};
/* IEEE Std 802.11be-2024, 9.4.2.324 (TID-To-Link Mapping element)
* Figure 9-1074ax (TID-TO-Link Mapping Control field format) */
#define EHT_TID_TO_LINK_MAP_DIRECTION_DOWN 0
#define EHT_TID_TO_LINK_MAP_DIRECTION_UP 1
#define EHT_TID_TO_LINK_MAP_DIRECTION_BOTH 2
#define EHT_TID_TO_LINK_MAP_DIRECTION_MSK 0x03
#define EHT_TID_TO_LINK_MAP_DEFAULT 0x04
#define EHT_TID_TO_LINK_MAP_SWITCH_TIME_PRESENT 0x08
#define EHT_TID_TO_LINK_MAP_EXPECT_DUR_PRESENT 0x10
#define EHT_TID_TO_LINK_MAP_LINK_MAPPING_SIZE 0x20
/*
* IEEE P802.11be/D4.0, 9.4.2.316 QoS Characteristics element,
* Table 9-404s (Direction subfield encoding)
* IEEE Std 802.11be-2024, 9.4.2.326 QoS Characteristics element,
* Table 9-417w (Direction subfield encoding)
*/
enum scs_direction {
SCS_DIRECTION_UP = 0,
@@ -2926,8 +3150,8 @@ enum scs_direction {
};
/*
* IEEE P802.11be/D4.0, 9.4.2.316 QoS Characteristics element,
* Figure 9-1001av (Control Info field format)
* IEEE Std 802.11be-2024, 9.4.2.326 QoS Characteristics element,
* Figure 9-1074bd (Control Info field format)
*/
#define EHT_QOS_CONTROL_INFO_DIRECTION_OFFSET 0
#define EHT_QOS_CONTROL_INFO_TID_OFFSET 2
@@ -2936,7 +3160,7 @@ enum scs_direction {
#define EHT_QOS_CONTROL_INFO_LINK_ID_OFFSET 25
/*
* IEEE P802.11be/D4.0, 9.4.2.316 QoS Characteristics element,
* IEEE Std 802.11be-2024, 9.4.2.326 QoS Characteristics element,
* Presence Bitmap Of Additional Parameters
*/
#define SCS_QOS_BIT_MAX_MSDU_SIZE ((u16) BIT(0))
@@ -3040,6 +3264,15 @@ enum dscp_policy_request_type {
#define WFA_CAPA_QM_UNSOLIC_DSCP BIT(1)
#define WFA_CAPA_QM_NON_EHT_SCS_TRAFFIC_DESC BIT(2)
/* Wi-Fi Alliance Capabilities attributes */
enum wfa_capa_attr_id {
WFA_CAPA_ATTR_GENERATIONAL_CAPAB = 1,
WFA_CAPA_ATTR_VENDOR_SPECIFIC = 221,
};
/* Wi-Fi Alliance Capabilities frame */
#define WFA_CAPAB_VENDOR_TYPE 0x506f9a1b
struct ieee80211_neighbor_ap_info {
u8 tbtt_info_hdr;
u8 tbtt_info_len;
Loaded 100 of 336 files, more files were not shown because too many files have changed in this diff. Show more