mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 11:25:21 +01:00
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:
commit
71e72c9e91
336 files changed
+89793
-24630
No files matched your search
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
@@ -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
@@ -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'",
|
||||
|
||||
+728
-255
File diff suppressed because it is too large.
Load diff
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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, ¶ms, &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, ¶ms);
|
||||
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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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, ¶ms);
|
||||
}
|
||||
#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(¶ms, 0, sizeof(params));
|
||||
params.bssid = bssid;
|
||||
params.pmkid = pmkid;
|
||||
params.pmk = pmk;
|
||||
params.pmk_len = pmk_len;
|
||||
|
||||
return hostapd_drv_add_pmkid(hapd, ¶ms);
|
||||
}
|
||||
|
||||
|
||||
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(¶ms, 0, sizeof(params));
|
||||
params.bssid = sta_addr;
|
||||
params.pmkid = pmkid;
|
||||
|
||||
return hostapd_drv_remove_pmkid(hapd, ¶ms);
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
+841
-200
File diff suppressed because it is too large.
Load diff
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
+483
-434
File diff suppressed because it is too large.
Load diff
+832
-178
File diff suppressed because it is too large.
Load diff
@@ -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 */
|
||||
@@ -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)
|
||||
|
||||
@@ -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, ¶ms);
|
||||
|
||||
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], ¶ms);
|
||||
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, ¶ms);
|
||||
|
||||
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], ¶ms);
|
||||
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;
|
||||
}
|
||||
@@ -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 */
|
||||
+3106
-664
File diff suppressed because it is too large.
Load diff
@@ -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 */
|
||||
+1629
-150
File diff suppressed because it is too large.
Load diff
@@ -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;
|
||||
|
||||
@@ -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 *
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
@@ -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
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
¢er_freq1_idx, ¢er_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,
|
||||
¢er_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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -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 */
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
+1267
-210
File diff suppressed because it is too large.
Load diff
+130
-17
@@ -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 */
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
+528
-170
File diff suppressed because it is too large.
Load diff
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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,3 +1,4 @@
|
||||
CFLAGS += -DCONFIG_IEEE80211AC
|
||||
CFLAGS += -DCONFIG_IEEE80211R
|
||||
CFLAGS += -DCONFIG_HS20
|
||||
CFLAGS += -DCONFIG_SAE
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 */
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -569,7 +569,7 @@ fail:
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf *
|
||||
static struct wpabuf *
|
||||
dpp_reconfig_build_conf(struct dpp_authentication *auth)
|
||||
{
|
||||
struct wpabuf *msg = NULL, *clear;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
@@ -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 */
|
||||
@@ -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
Reference in new issue
Block a user