mirror of
https://github.com/opnsense/src.git
synced 2026-06-11 01:30:30 -04:00
wpa: Import wpa_supplicant/hostapd commits up to b4f7506ff
Merge vendor commits40c7ff83e7,efec822389, and2f6c3ea960. Tested by: philip MFC after: 2 months
This commit is contained in:
commit
c1d255d3ff
504 changed files with 91175 additions and 19082 deletions
|
|
@ -56,6 +56,9 @@ In general, the best way of generating a suitable formatted patch file
|
|||
is by committing the changes to a cloned git repository and using git
|
||||
format-patch. The patch can then be sent, e.g., with git send-email.
|
||||
|
||||
A list of pending patches waiting for review is available in
|
||||
Patchwork: https://patchwork.ozlabs.org/project/hostap/list/
|
||||
|
||||
|
||||
History of license and contributions terms
|
||||
------------------------------------------
|
||||
|
|
@ -140,7 +143,7 @@ The license terms used for hostap.git files
|
|||
|
||||
Modified BSD license (no advertisement clause):
|
||||
|
||||
Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi> and contributors
|
||||
Copyright (c) 2002-2021, Jouni Malinen <j@w1.fi> and contributors
|
||||
All Rights Reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
|||
1152
contrib/wpa/hostapd/Android.mk
Normal file
1152
contrib/wpa/hostapd/Android.mk
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -362,7 +362,7 @@ ChangeLog for hostapd
|
|||
* RADIUS server functionality
|
||||
- add minimal RADIUS accounting server support (hostapd-as-server);
|
||||
this is mainly to enable testing coverage with hwsim scripts
|
||||
- allow authentication log to be written into SQLite databse
|
||||
- allow authentication log to be written into SQLite database
|
||||
- added option for TLS protocol testing of an EAP peer by simulating
|
||||
various misbehaviors/known attacks
|
||||
- MAC ACL support for testing purposes
|
||||
|
|
@ -668,7 +668,7 @@ ChangeLog for hostapd
|
|||
* fixed HT Capabilities IE with nl80211 drivers
|
||||
* moved generic AP functionality code into src/ap
|
||||
* WPS: handle Selected Registrar as union of info from all Registrars
|
||||
* remove obsolte Prism54.org driver wrapper
|
||||
* remove obsolete Prism54.org driver wrapper
|
||||
* added internal debugging mechanism with backtrace support and memory
|
||||
allocation/freeing validation, etc. tests (CONFIG_WPA_TRACE=y)
|
||||
* EAP-FAST server: piggyback Phase 2 start with the end of Phase 1
|
||||
|
|
|
|||
1375
contrib/wpa/hostapd/Makefile
Normal file
1375
contrib/wpa/hostapd/Makefile
Normal file
File diff suppressed because it is too large
Load diff
214
contrib/wpa/hostapd/android.config
Normal file
214
contrib/wpa/hostapd/android.config
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
# Example hostapd build time configuration
|
||||
#
|
||||
# This file lists the configuration options that are used when building the
|
||||
# hostapd binary. All lines starting with # are ignored. Configuration option
|
||||
# lines must be commented out complete, if they are not to be included, i.e.,
|
||||
# just setting VARIABLE=n is not disabling that variable.
|
||||
#
|
||||
# This file is included in Makefile, so variables like CFLAGS and LIBS can also
|
||||
# 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
|
||||
|
||||
# Driver interface for drivers using the nl80211 kernel interface
|
||||
#CONFIG_DRIVER_NL80211=y
|
||||
# driver_nl80211.c requires a rather new libnl (version 1.1) which may not be
|
||||
# shipped with your distribution yet. If that is the case, you need to build
|
||||
# newer libnl version and point the hostapd build to use it.
|
||||
#LIBNL=/usr/src/libnl
|
||||
#CFLAGS += -I$(LIBNL)/include
|
||||
#LIBS += -L$(LIBNL)/lib
|
||||
CONFIG_LIBNL20=y
|
||||
|
||||
# QCA vendor extensions to nl80211
|
||||
CONFIG_DRIVER_NL80211_QCA=y
|
||||
|
||||
# Broadcom vendor extensions to nl80211
|
||||
#CONFIG_DRIVER_NL80211_BRCM=y
|
||||
|
||||
# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
|
||||
#CONFIG_DRIVER_BSD=y
|
||||
#CFLAGS += -I/usr/local/include
|
||||
#LIBS += -L/usr/local/lib
|
||||
#LIBS_p += -L/usr/local/lib
|
||||
#LIBS_c += -L/usr/local/lib
|
||||
|
||||
# Driver interface for no driver (e.g., RADIUS server only)
|
||||
#CONFIG_DRIVER_NONE=y
|
||||
|
||||
# WPA2/IEEE 802.11i RSN pre-authentication
|
||||
#CONFIG_RSN_PREAUTH=y
|
||||
|
||||
# Support Operating Channel Validation
|
||||
#CONFIG_OCV=y
|
||||
|
||||
# Integrated EAP server
|
||||
#CONFIG_EAP=y
|
||||
|
||||
# EAP-MD5 for the integrated EAP server
|
||||
#CONFIG_EAP_MD5=y
|
||||
|
||||
# EAP-TLS for the integrated EAP server
|
||||
#CONFIG_EAP_TLS=y
|
||||
|
||||
# EAP-MSCHAPv2 for the integrated EAP server
|
||||
#CONFIG_EAP_MSCHAPV2=y
|
||||
|
||||
# EAP-PEAP for the integrated EAP server
|
||||
#CONFIG_EAP_PEAP=y
|
||||
|
||||
# EAP-GTC for the integrated EAP server
|
||||
#CONFIG_EAP_GTC=y
|
||||
|
||||
# EAP-TTLS for the integrated EAP server
|
||||
#CONFIG_EAP_TTLS=y
|
||||
|
||||
# EAP-SIM for the integrated EAP server
|
||||
#CONFIG_EAP_SIM=y
|
||||
|
||||
# EAP-AKA for the integrated EAP server
|
||||
#CONFIG_EAP_AKA=y
|
||||
|
||||
# EAP-AKA' for the integrated EAP server
|
||||
# This requires CONFIG_EAP_AKA to be enabled, too.
|
||||
#CONFIG_EAP_AKA_PRIME=y
|
||||
|
||||
# EAP-PAX for the integrated EAP server
|
||||
#CONFIG_EAP_PAX=y
|
||||
|
||||
# EAP-PSK for the integrated EAP server (this is _not_ needed for WPA-PSK)
|
||||
#CONFIG_EAP_PSK=y
|
||||
|
||||
# EAP-SAKE for the integrated EAP server
|
||||
#CONFIG_EAP_SAKE=y
|
||||
|
||||
# EAP-GPSK for the integrated EAP server
|
||||
#CONFIG_EAP_GPSK=y
|
||||
# Include support for optional SHA256 cipher suite in EAP-GPSK
|
||||
#CONFIG_EAP_GPSK_SHA256=y
|
||||
|
||||
# EAP-FAST for the integrated EAP server
|
||||
# Note: Default OpenSSL package does not include support for all the
|
||||
# functionality needed for EAP-FAST. If EAP-FAST is enabled with OpenSSL,
|
||||
# the OpenSSL library must be patched (openssl-0.9.9-session-ticket.patch)
|
||||
# to add the needed functions.
|
||||
#CONFIG_EAP_FAST=y
|
||||
|
||||
# Wi-Fi Protected Setup (WPS)
|
||||
CONFIG_WPS=y
|
||||
# Enable UPnP support for external WPS Registrars
|
||||
#CONFIG_WPS_UPNP=y
|
||||
|
||||
# EAP-IKEv2
|
||||
#CONFIG_EAP_IKEV2=y
|
||||
|
||||
# Trusted Network Connect (EAP-TNC)
|
||||
#CONFIG_EAP_TNC=y
|
||||
|
||||
# PKCS#12 (PFX) support (used to read private key and certificate file from
|
||||
# a file that usually has extension .p12 or .pfx)
|
||||
CONFIG_PKCS12=y
|
||||
|
||||
# RADIUS authentication server. This provides access to the integrated EAP
|
||||
# server from external hosts using RADIUS.
|
||||
#CONFIG_RADIUS_SERVER=y
|
||||
|
||||
# Build IPv6 support for RADIUS operations
|
||||
CONFIG_IPV6=y
|
||||
|
||||
# IEEE Std 802.11r-2008 (Fast BSS Transition)
|
||||
#CONFIG_IEEE80211R=y
|
||||
|
||||
# Use the hostapd's IEEE 802.11 authentication (ACL), but without
|
||||
# the IEEE 802.11 Management capability (e.g., FreeBSD/net80211)
|
||||
#CONFIG_DRIVER_RADIUS_ACL=y
|
||||
|
||||
# Remove debugging code that is printing out debug messages to stdout.
|
||||
# This can be used to reduce the size of the hostapd considerably if debugging
|
||||
# code is not needed.
|
||||
#CONFIG_NO_STDOUT_DEBUG=y
|
||||
|
||||
# Add support for writing debug log to Android logcat instead of standard output
|
||||
CONFIG_ANDROID_LOG=y
|
||||
|
||||
# Remove support for RADIUS accounting
|
||||
#CONFIG_NO_ACCOUNTING=y
|
||||
|
||||
# Remove support for RADIUS
|
||||
CONFIG_NO_RADIUS=y
|
||||
|
||||
# Remove support for VLANs
|
||||
#CONFIG_NO_VLAN=y
|
||||
|
||||
# Remove support for dumping internal state through control interface commands
|
||||
# This can be used to reduce binary size at the cost of disabling a debugging
|
||||
# option.
|
||||
#CONFIG_NO_DUMP_STATE=y
|
||||
|
||||
# Select wrapper for operatins system and C library specific functions
|
||||
# unix = UNIX/POSIX like systems (default)
|
||||
# win32 = Windows systems
|
||||
# none = Empty template
|
||||
CONFIG_OS=unix
|
||||
|
||||
# Enable tracing code for developer debugging
|
||||
# This tracks use of memory allocations and other registrations and reports
|
||||
# incorrect use with a backtrace of call (or allocation) location.
|
||||
#CONFIG_WPA_TRACE=y
|
||||
# For BSD, comment out these.
|
||||
#LIBS += -lexecinfo
|
||||
#LIBS_p += -lexecinfo
|
||||
#LIBS_c += -lexecinfo
|
||||
|
||||
# Use libbfd to get more details for developer debugging
|
||||
# This enables use of libbfd to get more detailed symbols for the backtraces
|
||||
# generated by CONFIG_WPA_TRACE=y.
|
||||
#CONFIG_WPA_TRACE_BFD=y
|
||||
# For BSD, comment out these.
|
||||
#LIBS += -lbfd -liberty -lz
|
||||
#LIBS_p += -lbfd -liberty -lz
|
||||
#LIBS_c += -lbfd -liberty -lz
|
||||
|
||||
# Should we use poll instead of select? Select is used by default.
|
||||
#CONFIG_ELOOP_POLL=y
|
||||
|
||||
# Should we use epoll instead of select? Select is used by default.
|
||||
#CONFIG_ELOOP_EPOLL=y
|
||||
|
||||
# Enable AP
|
||||
CONFIG_AP=y
|
||||
|
||||
# Enable Fast Session Transfer (FST)
|
||||
#CONFIG_FST=y
|
||||
|
||||
# Multiband Operation support
|
||||
# These extensions facilitate efficient use of multiple frequency bands
|
||||
# available to the AP and the devices that may associate with it.
|
||||
#CONFIG_MBO=y
|
||||
|
||||
# Include internal line edit mode in hostapd_cli.
|
||||
CONFIG_WPA_CLI_EDIT=y
|
||||
|
||||
# Opportunistic Wireless Encryption (OWE)
|
||||
# Experimental implementation of draft-harkins-owe-07.txt
|
||||
#CONFIG_OWE=y
|
||||
|
||||
# Wpa_supplicant's random pool is not necessary on Android. Randomness is
|
||||
# already provided by the entropymixer service which ensures sufficient
|
||||
# entropy is maintained across reboots. Commit b410eb1913 'Initialize
|
||||
# /dev/urandom earlier in boot' seeds /dev/urandom with that entropy before
|
||||
# either wpa_supplicant or hostapd are run.
|
||||
CONFIG_NO_RANDOM_POOL=y
|
||||
|
||||
# Wired equivalent privacy (WEP)
|
||||
# WEP is an obsolete cryptographic data confidentiality algorithm that is not
|
||||
# considered secure. It should not be used for anything anymore. The
|
||||
# functionality needed to use WEP is available in the current hostapd
|
||||
# release under this optional build parameter. This functionality is subject to
|
||||
# be completely removed in a future release.
|
||||
CONFIG_WEP=y
|
||||
|
|
@ -14,6 +14,7 @@
|
|||
#include "utils/common.h"
|
||||
#include "utils/uuid.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/sae.h"
|
||||
#include "crypto/sha256.h"
|
||||
#include "crypto/tls.h"
|
||||
#include "drivers/driver.h"
|
||||
|
|
@ -340,7 +341,7 @@ static int hostapd_config_read_eap_user(const char *fname,
|
|||
struct hostapd_radius_attr *attr, *a;
|
||||
attr = hostapd_parse_radius_attr(buf + 19);
|
||||
if (attr == NULL) {
|
||||
wpa_printf(MSG_ERROR, "Invalid radius_auth_req_attr: %s",
|
||||
wpa_printf(MSG_ERROR, "Invalid radius_accept_attr: %s",
|
||||
buf + 19);
|
||||
user = NULL; /* already in the BSS list */
|
||||
goto failed;
|
||||
|
|
@ -711,12 +712,10 @@ static int hostapd_config_parse_key_mgmt(int line, const char *value)
|
|||
val |= WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
|
||||
#endif /* CONFIG_SHA384 */
|
||||
#endif /* CONFIG_IEEE80211R_AP */
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
else if (os_strcmp(start, "WPA-PSK-SHA256") == 0)
|
||||
val |= WPA_KEY_MGMT_PSK_SHA256;
|
||||
else if (os_strcmp(start, "WPA-EAP-SHA256") == 0)
|
||||
val |= WPA_KEY_MGMT_IEEE8021X_SHA256;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_SAE
|
||||
else if (os_strcmp(start, "SAE") == 0)
|
||||
val |= WPA_KEY_MGMT_SAE;
|
||||
|
|
@ -755,6 +754,10 @@ static int hostapd_config_parse_key_mgmt(int line, const char *value)
|
|||
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 */
|
||||
else {
|
||||
wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
|
||||
line, start);
|
||||
|
|
@ -795,6 +798,7 @@ static int hostapd_config_parse_cipher(int line, const char *value)
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_WEP
|
||||
static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx,
|
||||
char *val)
|
||||
{
|
||||
|
|
@ -845,6 +849,7 @@ static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx,
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_WEP */
|
||||
|
||||
|
||||
static int hostapd_parse_chanlist(struct hostapd_config *conf, char *val)
|
||||
|
|
@ -942,104 +947,6 @@ static int hostapd_config_bss(struct hostapd_config *conf, const char *ifname)
|
|||
}
|
||||
|
||||
|
||||
/* convert floats with one decimal place to value*10 int, i.e.,
|
||||
* "1.5" will return 15 */
|
||||
static int hostapd_config_read_int10(const char *value)
|
||||
{
|
||||
int i, d;
|
||||
char *pos;
|
||||
|
||||
i = atoi(value);
|
||||
pos = os_strchr(value, '.');
|
||||
d = 0;
|
||||
if (pos) {
|
||||
pos++;
|
||||
if (*pos >= '0' && *pos <= '9')
|
||||
d = *pos - '0';
|
||||
}
|
||||
|
||||
return i * 10 + d;
|
||||
}
|
||||
|
||||
|
||||
static int valid_cw(int cw)
|
||||
{
|
||||
return (cw == 1 || cw == 3 || cw == 7 || cw == 15 || cw == 31 ||
|
||||
cw == 63 || cw == 127 || cw == 255 || cw == 511 || cw == 1023 ||
|
||||
cw == 2047 || cw == 4095 || cw == 8191 || cw == 16383 ||
|
||||
cw == 32767);
|
||||
}
|
||||
|
||||
|
||||
enum {
|
||||
IEEE80211_TX_QUEUE_DATA0 = 0, /* used for EDCA AC_VO data */
|
||||
IEEE80211_TX_QUEUE_DATA1 = 1, /* used for EDCA AC_VI data */
|
||||
IEEE80211_TX_QUEUE_DATA2 = 2, /* used for EDCA AC_BE data */
|
||||
IEEE80211_TX_QUEUE_DATA3 = 3 /* used for EDCA AC_BK data */
|
||||
};
|
||||
|
||||
static int hostapd_config_tx_queue(struct hostapd_config *conf,
|
||||
const char *name, const char *val)
|
||||
{
|
||||
int num;
|
||||
const char *pos;
|
||||
struct hostapd_tx_queue_params *queue;
|
||||
|
||||
/* skip 'tx_queue_' prefix */
|
||||
pos = name + 9;
|
||||
if (os_strncmp(pos, "data", 4) == 0 &&
|
||||
pos[4] >= '0' && pos[4] <= '9' && pos[5] == '_') {
|
||||
num = pos[4] - '0';
|
||||
pos += 6;
|
||||
} else if (os_strncmp(pos, "after_beacon_", 13) == 0 ||
|
||||
os_strncmp(pos, "beacon_", 7) == 0) {
|
||||
wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name);
|
||||
return 0;
|
||||
} else {
|
||||
wpa_printf(MSG_ERROR, "Unknown tx_queue name '%s'", pos);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (num >= NUM_TX_QUEUES) {
|
||||
/* for backwards compatibility, do not trigger failure */
|
||||
wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
queue = &conf->tx_queue[num];
|
||||
|
||||
if (os_strcmp(pos, "aifs") == 0) {
|
||||
queue->aifs = atoi(val);
|
||||
if (queue->aifs < 0 || queue->aifs > 255) {
|
||||
wpa_printf(MSG_ERROR, "Invalid AIFS value %d",
|
||||
queue->aifs);
|
||||
return -1;
|
||||
}
|
||||
} else if (os_strcmp(pos, "cwmin") == 0) {
|
||||
queue->cwmin = atoi(val);
|
||||
if (!valid_cw(queue->cwmin)) {
|
||||
wpa_printf(MSG_ERROR, "Invalid cwMin value %d",
|
||||
queue->cwmin);
|
||||
return -1;
|
||||
}
|
||||
} else if (os_strcmp(pos, "cwmax") == 0) {
|
||||
queue->cwmax = atoi(val);
|
||||
if (!valid_cw(queue->cwmax)) {
|
||||
wpa_printf(MSG_ERROR, "Invalid cwMax value %d",
|
||||
queue->cwmax);
|
||||
return -1;
|
||||
}
|
||||
} else if (os_strcmp(pos, "burst") == 0) {
|
||||
queue->burst = hostapd_config_read_int10(val);
|
||||
} else {
|
||||
wpa_printf(MSG_ERROR, "Unknown tx_queue field '%s'", pos);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211R_AP
|
||||
|
||||
static int rkh_derive_key(const char *pos, u8 *key, size_t key_len)
|
||||
|
|
@ -1153,7 +1060,6 @@ static int add_r1kh(struct hostapd_bss_config *bss, char *value)
|
|||
#endif /* CONFIG_IEEE80211R_AP */
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
static int hostapd_config_ht_capab(struct hostapd_config *conf,
|
||||
const char *capab)
|
||||
{
|
||||
|
|
@ -1173,14 +1079,6 @@ static int hostapd_config_ht_capab(struct hostapd_config *conf,
|
|||
}
|
||||
if (!os_strstr(capab, "[HT40+]") && !os_strstr(capab, "[HT40-]"))
|
||||
conf->secondary_channel = 0;
|
||||
if (os_strstr(capab, "[SMPS-STATIC]")) {
|
||||
conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK;
|
||||
conf->ht_capab |= HT_CAP_INFO_SMPS_STATIC;
|
||||
}
|
||||
if (os_strstr(capab, "[SMPS-DYNAMIC]")) {
|
||||
conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK;
|
||||
conf->ht_capab |= HT_CAP_INFO_SMPS_DYNAMIC;
|
||||
}
|
||||
if (os_strstr(capab, "[GF]"))
|
||||
conf->ht_capab |= HT_CAP_INFO_GREEN_FIELD;
|
||||
if (os_strstr(capab, "[SHORT-GI-20]"))
|
||||
|
|
@ -1214,7 +1112,6 @@ static int hostapd_config_ht_capab(struct hostapd_config *conf,
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211AC
|
||||
|
|
@ -1323,6 +1220,32 @@ static u8 set_he_cap(int val, u8 mask)
|
|||
return (u8) (mask & (val << find_bit_offset(mask)));
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_parse_he_srg_bitmap(u8 *bitmap, char *val)
|
||||
{
|
||||
int bitpos;
|
||||
char *pos, *end;
|
||||
|
||||
os_memset(bitmap, 0, 8);
|
||||
pos = val;
|
||||
while (*pos != '\0') {
|
||||
end = os_strchr(pos, ' ');
|
||||
if (end)
|
||||
*end = '\0';
|
||||
|
||||
bitpos = atoi(pos);
|
||||
if (bitpos < 0 || bitpos > 64)
|
||||
return -1;
|
||||
|
||||
bitmap[bitpos / 8] |= BIT(bitpos % 8);
|
||||
if (!end)
|
||||
break;
|
||||
pos = end + 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
|
||||
|
||||
|
|
@ -2300,6 +2223,35 @@ static int parse_sae_password(struct hostapd_bss_config *bss, const char *val)
|
|||
pw->vlan_id = atoi(pos2);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SAE_PK
|
||||
pos2 = os_strstr(pos, "|pk=");
|
||||
if (pos2) {
|
||||
const char *epos;
|
||||
char *tmp;
|
||||
|
||||
if (!end)
|
||||
end = pos2;
|
||||
pos2 += 4;
|
||||
epos = os_strchr(pos2, '|');
|
||||
if (epos) {
|
||||
tmp = os_malloc(epos - pos2 + 1);
|
||||
if (!tmp)
|
||||
goto fail;
|
||||
os_memcpy(tmp, pos2, epos - pos2);
|
||||
tmp[epos - pos2] = '\0';
|
||||
} else {
|
||||
tmp = os_strdup(pos2);
|
||||
if (!tmp)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pw->pk = sae_parse_pk(tmp);
|
||||
str_clear_free(tmp);
|
||||
if (!pw->pk)
|
||||
goto fail;
|
||||
}
|
||||
#endif /* CONFIG_SAE_PK */
|
||||
|
||||
pos2 = os_strstr(pos, "|id=");
|
||||
if (pos2) {
|
||||
if (!end)
|
||||
|
|
@ -2322,6 +2274,18 @@ static int parse_sae_password(struct hostapd_bss_config *bss, const char *val)
|
|||
pw->password[end - val] = '\0';
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SAE_PK
|
||||
if (pw->pk &&
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
!bss->sae_pk_password_check_skip &&
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
!sae_pk_valid_password(pw->password)) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"Invalid SAE password for a SAE-PK sae_password entry");
|
||||
goto fail;
|
||||
}
|
||||
#endif /* CONFIG_SAE_PK */
|
||||
|
||||
pw->next = bss->sae_passwords;
|
||||
bss->sae_passwords = pw;
|
||||
|
||||
|
|
@ -2329,6 +2293,9 @@ static int parse_sae_password(struct hostapd_bss_config *bss, const char *val)
|
|||
fail:
|
||||
str_clear_free(pw->password);
|
||||
os_free(pw->identifier);
|
||||
#ifdef CONFIG_SAE_PK
|
||||
sae_deinit_pk(pw->pk);
|
||||
#endif /* CONFIG_SAE_PK */
|
||||
os_free(pw);
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -2365,6 +2332,22 @@ fail:
|
|||
#endif /* CONFIG_DPP2 */
|
||||
|
||||
|
||||
static int get_hex_config(u8 *buf, size_t max_len, int line,
|
||||
const char *field, const char *val)
|
||||
{
|
||||
size_t hlen = os_strlen(val), len = hlen / 2;
|
||||
u8 tmp[EXT_CAPA_MAX_LEN];
|
||||
|
||||
os_memset(tmp, 0, EXT_CAPA_MAX_LEN);
|
||||
if (hlen & 1 || len > EXT_CAPA_MAX_LEN || hexstr2bin(val, tmp, len)) {
|
||||
wpa_printf(MSG_ERROR, "Line %d: Invalid %s", line, field);
|
||||
return -1;
|
||||
}
|
||||
os_memcpy(buf, tmp, EXT_CAPA_MAX_LEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_config_fill(struct hostapd_config *conf,
|
||||
struct hostapd_bss_config *bss,
|
||||
const char *buf, char *pos, int line)
|
||||
|
|
@ -2473,6 +2456,13 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
} else if (os_strcmp(buf, "skip_inactivity_poll") == 0) {
|
||||
bss->skip_inactivity_poll = atoi(pos);
|
||||
} else if (os_strcmp(buf, "country_code") == 0) {
|
||||
if (pos[0] < 'A' || pos[0] > 'Z' ||
|
||||
pos[1] < 'A' || pos[1] > 'Z') {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Line %d: Invalid country_code '%s'",
|
||||
line, pos);
|
||||
return 1;
|
||||
}
|
||||
os_memcpy(conf->country, pos, 2);
|
||||
} else if (os_strcmp(buf, "country3") == 0) {
|
||||
conf->country[2] = strtol(pos, NULL, 16);
|
||||
|
|
@ -2484,12 +2474,13 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
bss->ieee802_1x = atoi(pos);
|
||||
} else if (os_strcmp(buf, "eapol_version") == 0) {
|
||||
int eapol_version = atoi(pos);
|
||||
|
||||
#ifdef CONFIG_MACSEC
|
||||
if (eapol_version < 1 || eapol_version > 3) {
|
||||
int max_ver = 3;
|
||||
#else /* CONFIG_MACSEC */
|
||||
if (eapol_version < 1 || eapol_version > 2) {
|
||||
int max_ver = 2;
|
||||
#endif /* CONFIG_MACSEC */
|
||||
|
||||
if (eapol_version < 1 || eapol_version > max_ver) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Line %d: invalid EAPOL version (%d): '%s'.",
|
||||
line, eapol_version, pos);
|
||||
|
|
@ -2547,6 +2538,10 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
bss->tls_session_lifetime = atoi(pos);
|
||||
} else if (os_strcmp(buf, "tls_flags") == 0) {
|
||||
bss->tls_flags = parse_tls_flags(pos);
|
||||
} else if (os_strcmp(buf, "max_auth_rounds") == 0) {
|
||||
bss->max_auth_rounds = atoi(pos);
|
||||
} else if (os_strcmp(buf, "max_auth_rounds_short") == 0) {
|
||||
bss->max_auth_rounds_short = atoi(pos);
|
||||
} else if (os_strcmp(buf, "ocsp_stapling_response") == 0) {
|
||||
os_free(bss->ocsp_stapling_response);
|
||||
bss->ocsp_stapling_response = os_strdup(pos);
|
||||
|
|
@ -2611,7 +2606,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
} else if (os_strcmp(buf, "eap_teap_auth") == 0) {
|
||||
int val = atoi(pos);
|
||||
|
||||
if (val < 0 || val > 1) {
|
||||
if (val < 0 || val > 2) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Line %d: Invalid eap_teap_auth value",
|
||||
line);
|
||||
|
|
@ -2620,6 +2615,10 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
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) {
|
||||
bss->eap_teap_id = atoi(pos);
|
||||
#endif /* EAP_SERVER_TEAP */
|
||||
#ifdef EAP_SERVER_SIM
|
||||
} else if (os_strcmp(buf, "eap_sim_db") == 0) {
|
||||
|
|
@ -2668,6 +2667,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
} else if (os_strcmp(buf, "erp_domain") == 0) {
|
||||
os_free(bss->erp_domain);
|
||||
bss->erp_domain = os_strdup(pos);
|
||||
#ifdef CONFIG_WEP
|
||||
} else if (os_strcmp(buf, "wep_key_len_broadcast") == 0) {
|
||||
int val = atoi(pos);
|
||||
|
||||
|
|
@ -2695,6 +2695,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
line, bss->wep_rekeying_period);
|
||||
return 1;
|
||||
}
|
||||
#endif /* CONFIG_WEP */
|
||||
} else if (os_strcmp(buf, "eap_reauth_period") == 0) {
|
||||
bss->eap_reauth_period = atoi(pos);
|
||||
if (bss->eap_reauth_period < 0) {
|
||||
|
|
@ -2706,8 +2707,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
bss->eapol_key_index_workaround = atoi(pos);
|
||||
#ifdef CONFIG_IAPP
|
||||
} else if (os_strcmp(buf, "iapp_interface") == 0) {
|
||||
bss->ieee802_11f = 1;
|
||||
os_strlcpy(bss->iapp_iface, pos, sizeof(bss->iapp_iface));
|
||||
wpa_printf(MSG_INFO, "DEPRECATED: iapp_interface not used");
|
||||
#endif /* CONFIG_IAPP */
|
||||
} else if (os_strcmp(buf, "own_ip_addr") == 0) {
|
||||
if (hostapd_parse_ip_addr(pos, &bss->own_ip_addr)) {
|
||||
|
|
@ -2728,6 +2728,9 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
return 1;
|
||||
}
|
||||
bss->radius->force_client_addr = 1;
|
||||
} else if (os_strcmp(buf, "radius_client_dev") == 0) {
|
||||
os_free(bss->radius->force_client_dev);
|
||||
bss->radius->force_client_dev = os_strdup(pos);
|
||||
} else if (os_strcmp(buf, "auth_server_addr") == 0) {
|
||||
if (hostapd_config_read_radius_addr(
|
||||
&bss->radius->auth_servers,
|
||||
|
|
@ -2870,6 +2873,16 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
}
|
||||
} else if (os_strcmp(buf, "wpa") == 0) {
|
||||
bss->wpa = atoi(pos);
|
||||
} else if (os_strcmp(buf, "extended_key_id") == 0) {
|
||||
int val = atoi(pos);
|
||||
|
||||
if (val < 0 || val > 2) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Line %d: Invalid extended_key_id=%d; allowed range 0..2",
|
||||
line, val);
|
||||
return 1;
|
||||
}
|
||||
bss->extended_key_id = val;
|
||||
} else if (os_strcmp(buf, "wpa_group_rekey") == 0) {
|
||||
bss->wpa_group_rekey = atoi(pos);
|
||||
bss->wpa_group_rekey_set = 1;
|
||||
|
|
@ -2879,6 +2892,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
bss->wpa_gmk_rekey = atoi(pos);
|
||||
} else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) {
|
||||
bss->wpa_ptk_rekey = atoi(pos);
|
||||
} else if (os_strcmp(buf, "wpa_deny_ptk0_rekey") == 0) {
|
||||
bss->wpa_deny_ptk0_rekey = atoi(pos);
|
||||
if (bss->wpa_deny_ptk0_rekey < 0 ||
|
||||
bss->wpa_deny_ptk0_rekey > 2) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Line %d: Invalid wpa_deny_ptk0_rekey=%d; allowed range 0..2",
|
||||
line, bss->wpa_deny_ptk0_rekey);
|
||||
return 1;
|
||||
}
|
||||
} else if (os_strcmp(buf, "wpa_group_update_count") == 0) {
|
||||
char *endp;
|
||||
unsigned long val = strtoul(pos, &endp, 0);
|
||||
|
|
@ -3131,6 +3153,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
}
|
||||
} else if (os_strcmp(buf, "acs_exclude_dfs") == 0) {
|
||||
conf->acs_exclude_dfs = atoi(pos);
|
||||
} else if (os_strcmp(buf, "op_class") == 0) {
|
||||
conf->op_class = atoi(pos);
|
||||
} else if (os_strcmp(buf, "channel") == 0) {
|
||||
if (os_strcmp(pos, "acs_survey") == 0) {
|
||||
#ifndef CONFIG_ACS
|
||||
|
|
@ -3145,12 +3169,25 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
conf->channel = atoi(pos);
|
||||
conf->acs = conf->channel == 0;
|
||||
}
|
||||
} else if (os_strcmp(buf, "edmg_channel") == 0) {
|
||||
conf->edmg_channel = atoi(pos);
|
||||
} else if (os_strcmp(buf, "enable_edmg") == 0) {
|
||||
conf->enable_edmg = atoi(pos);
|
||||
} else if (os_strcmp(buf, "chanlist") == 0) {
|
||||
if (hostapd_parse_chanlist(conf, pos)) {
|
||||
wpa_printf(MSG_ERROR, "Line %d: invalid channel list",
|
||||
line);
|
||||
return 1;
|
||||
}
|
||||
} else if (os_strcmp(buf, "freqlist") == 0) {
|
||||
if (freq_range_list_parse(&conf->acs_freq_list, pos)) {
|
||||
wpa_printf(MSG_ERROR, "Line %d: invalid frequency list",
|
||||
line);
|
||||
return 1;
|
||||
}
|
||||
conf->acs_freq_list_present = 1;
|
||||
} else if (os_strcmp(buf, "acs_exclude_6ghz_non_psc") == 0) {
|
||||
conf->acs_exclude_6ghz_non_psc = atoi(pos);
|
||||
} else if (os_strcmp(buf, "beacon_int") == 0) {
|
||||
int val = atoi(pos);
|
||||
/* MIB defines range as 1..65535, but very small values
|
||||
|
|
@ -3272,6 +3309,16 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
}
|
||||
conf->rate_type = BEACON_RATE_VHT;
|
||||
conf->beacon_rate = val;
|
||||
} else if (os_strncmp(pos, "he:", 3) == 0) {
|
||||
val = atoi(pos + 3);
|
||||
if (val < 0 || val > 11) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Line %d: invalid beacon_rate HE-MCS %d",
|
||||
line, val);
|
||||
return 1;
|
||||
}
|
||||
conf->rate_type = BEACON_RATE_HE;
|
||||
conf->beacon_rate = val;
|
||||
} else {
|
||||
val = atoi(pos);
|
||||
if (val < 10 || val > 10000) {
|
||||
|
|
@ -3292,6 +3339,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
bss->ignore_broadcast_ssid = atoi(pos);
|
||||
} else if (os_strcmp(buf, "no_probe_resp_if_max_sta") == 0) {
|
||||
bss->no_probe_resp_if_max_sta = atoi(pos);
|
||||
#ifdef CONFIG_WEP
|
||||
} else if (os_strcmp(buf, "wep_default_key") == 0) {
|
||||
bss->ssid.wep.idx = atoi(pos);
|
||||
if (bss->ssid.wep.idx > 3) {
|
||||
|
|
@ -3310,6 +3358,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
line, buf);
|
||||
return 1;
|
||||
}
|
||||
#endif /* CONFIG_WEP */
|
||||
#ifndef CONFIG_NO_VLAN
|
||||
} else if (os_strcmp(buf, "dynamic_vlan") == 0) {
|
||||
bss->ssid.dynamic_vlan = atoi(pos);
|
||||
|
|
@ -3341,7 +3390,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
} else if (os_strcmp(buf, "ap_table_expiration_time") == 0) {
|
||||
conf->ap_table_expiration_time = atoi(pos);
|
||||
} else if (os_strncmp(buf, "tx_queue_", 9) == 0) {
|
||||
if (hostapd_config_tx_queue(conf, buf, pos)) {
|
||||
if (hostapd_config_tx_queue(conf->tx_queue, buf, pos)) {
|
||||
wpa_printf(MSG_ERROR, "Line %d: invalid TX queue item",
|
||||
line);
|
||||
return 1;
|
||||
|
|
@ -3372,7 +3421,6 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
}
|
||||
} else if (os_strcmp(buf, "use_driver_iface_addr") == 0) {
|
||||
conf->use_driver_iface_addr = atoi(pos);
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
} else if (os_strcmp(buf, "ieee80211w") == 0) {
|
||||
bss->ieee80211w = atoi(pos);
|
||||
} else if (os_strcmp(buf, "group_mgmt_cipher") == 0) {
|
||||
|
|
@ -3389,6 +3437,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
line, pos);
|
||||
return 1;
|
||||
}
|
||||
} else if (os_strcmp(buf, "beacon_prot") == 0) {
|
||||
bss->beacon_prot = atoi(pos);
|
||||
} else if (os_strcmp(buf, "assoc_sa_query_max_timeout") == 0) {
|
||||
bss->assoc_sa_query_max_timeout = atoi(pos);
|
||||
if (bss->assoc_sa_query_max_timeout == 0) {
|
||||
|
|
@ -3403,14 +3453,12 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
line);
|
||||
return 1;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_OCV
|
||||
} else if (os_strcmp(buf, "ocv") == 0) {
|
||||
bss->ocv = atoi(pos);
|
||||
if (bss->ocv && !bss->ieee80211w)
|
||||
bss->ieee80211w = 1;
|
||||
#endif /* CONFIG_OCV */
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
} else if (os_strcmp(buf, "ieee80211n") == 0) {
|
||||
conf->ieee80211n = atoi(pos);
|
||||
} else if (os_strcmp(buf, "ht_capab") == 0) {
|
||||
|
|
@ -3423,7 +3471,6 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
conf->require_ht = atoi(pos);
|
||||
} else if (os_strcmp(buf, "obss_interval") == 0) {
|
||||
conf->obss_interval = atoi(pos);
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
#ifdef CONFIG_IEEE80211AC
|
||||
} else if (os_strcmp(buf, "ieee80211ac") == 0) {
|
||||
conf->ieee80211ac = atoi(pos);
|
||||
|
|
@ -3456,11 +3503,16 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
} else if (os_strcmp(buf, "he_mu_beamformer") == 0) {
|
||||
conf->he_phy_capab.he_mu_beamformer = atoi(pos);
|
||||
} else if (os_strcmp(buf, "he_bss_color") == 0) {
|
||||
conf->he_op.he_bss_color = atoi(pos);
|
||||
conf->he_op.he_bss_color = atoi(pos) & 0x3f;
|
||||
conf->he_op.he_bss_color_disabled = 0;
|
||||
} else if (os_strcmp(buf, "he_bss_color_partial") == 0) {
|
||||
conf->he_op.he_bss_color_partial = atoi(pos);
|
||||
} else if (os_strcmp(buf, "he_default_pe_duration") == 0) {
|
||||
conf->he_op.he_default_pe_duration = atoi(pos);
|
||||
} else if (os_strcmp(buf, "he_twt_required") == 0) {
|
||||
conf->he_op.he_twt_required = atoi(pos);
|
||||
} else if (os_strcmp(buf, "he_twt_responder") == 0) {
|
||||
conf->he_op.he_twt_responder = atoi(pos);
|
||||
} else if (os_strcmp(buf, "he_rts_threshold") == 0) {
|
||||
conf->he_op.he_rts_threshold = atoi(pos);
|
||||
} else if (os_strcmp(buf, "he_basic_mcs_nss_set") == 0) {
|
||||
|
|
@ -3550,19 +3602,53 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_TIMER_IDX] =
|
||||
atoi(pos) & 0xff;
|
||||
} else if (os_strcmp(buf, "he_spr_sr_control") == 0) {
|
||||
conf->spr.sr_control = atoi(pos) & 0xff;
|
||||
conf->spr.sr_control = atoi(pos) & 0x1f;
|
||||
} else if (os_strcmp(buf, "he_spr_non_srg_obss_pd_max_offset") == 0) {
|
||||
conf->spr.non_srg_obss_pd_max_offset = atoi(pos);
|
||||
} else if (os_strcmp(buf, "he_spr_srg_obss_pd_min_offset") == 0) {
|
||||
conf->spr.srg_obss_pd_min_offset = atoi(pos);
|
||||
} else if (os_strcmp(buf, "he_spr_srg_obss_pd_max_offset") == 0) {
|
||||
conf->spr.srg_obss_pd_max_offset = atoi(pos);
|
||||
} else if (os_strcmp(buf, "he_spr_srg_bss_colors") == 0) {
|
||||
if (hostapd_parse_he_srg_bitmap(
|
||||
conf->spr.srg_bss_color_bitmap, pos)) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Line %d: Invalid srg bss colors list '%s'",
|
||||
line, pos);
|
||||
return 1;
|
||||
}
|
||||
} else if (os_strcmp(buf, "he_spr_srg_partial_bssid") == 0) {
|
||||
if (hostapd_parse_he_srg_bitmap(
|
||||
conf->spr.srg_partial_bssid_bitmap, pos)) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Line %d: Invalid srg partial bssid list '%s'",
|
||||
line, pos);
|
||||
return 1;
|
||||
}
|
||||
} else if (os_strcmp(buf, "he_oper_chwidth") == 0) {
|
||||
conf->he_oper_chwidth = atoi(pos);
|
||||
} else if (os_strcmp(buf, "he_oper_centr_freq_seg0_idx") == 0) {
|
||||
conf->he_oper_centr_freq_seg0_idx = atoi(pos);
|
||||
} else if (os_strcmp(buf, "he_oper_centr_freq_seg1_idx") == 0) {
|
||||
conf->he_oper_centr_freq_seg1_idx = atoi(pos);
|
||||
} else if (os_strcmp(buf, "he_6ghz_max_mpdu") == 0) {
|
||||
conf->he_6ghz_max_mpdu = atoi(pos);
|
||||
} else if (os_strcmp(buf, "he_6ghz_max_ampdu_len_exp") == 0) {
|
||||
conf->he_6ghz_max_ampdu_len_exp = atoi(pos);
|
||||
} else if (os_strcmp(buf, "he_6ghz_rx_ant_pat") == 0) {
|
||||
conf->he_6ghz_rx_ant_pat = atoi(pos);
|
||||
} else if (os_strcmp(buf, "he_6ghz_tx_ant_pat") == 0) {
|
||||
conf->he_6ghz_tx_ant_pat = atoi(pos);
|
||||
} else if (os_strcmp(buf, "unsol_bcast_probe_resp_interval") == 0) {
|
||||
int val = atoi(pos);
|
||||
|
||||
if (val < 0 || val > 20) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Line %d: invalid unsol_bcast_probe_resp_interval value",
|
||||
line);
|
||||
return 1;
|
||||
}
|
||||
bss->unsol_bcast_probe_resp_interval = val;
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
} else if (os_strcmp(buf, "max_listen_interval") == 0) {
|
||||
bss->max_listen_interval = atoi(pos);
|
||||
|
|
@ -3744,6 +3830,9 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
} else if (os_strcmp(buf, "server_id") == 0) {
|
||||
os_free(bss->server_id);
|
||||
bss->server_id = os_strdup(pos);
|
||||
} else if (os_strcmp(buf, "wps_application_ext") == 0) {
|
||||
wpabuf_free(bss->wps_application_ext);
|
||||
bss->wps_application_ext = wpabuf_parse_bin(pos);
|
||||
#ifdef CONFIG_WPS_NFC
|
||||
} else if (os_strcmp(buf, "wps_nfc_dev_pw_id") == 0) {
|
||||
bss->wps_nfc_dev_pw_id = atoi(pos);
|
||||
|
|
@ -4144,9 +4233,53 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
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) {
|
||||
bss->sae_commit_status = atoi(pos);
|
||||
} else if (os_strcmp(buf, "sae_pk_omit") == 0) {
|
||||
bss->sae_pk_omit = atoi(pos);
|
||||
} else if (os_strcmp(buf, "sae_pk_password_check_skip") == 0) {
|
||||
bss->sae_pk_password_check_skip = atoi(pos);
|
||||
} else if (os_strcmp(buf, "sae_commit_override") == 0) {
|
||||
wpabuf_free(bss->sae_commit_override);
|
||||
bss->sae_commit_override = wpabuf_parse_bin(pos);
|
||||
} else if (os_strcmp(buf, "rsne_override_eapol") == 0) {
|
||||
wpabuf_free(bss->rsne_override_eapol);
|
||||
bss->rsne_override_eapol = wpabuf_parse_bin(pos);
|
||||
} else if (os_strcmp(buf, "rsnxe_override_eapol") == 0) {
|
||||
wpabuf_free(bss->rsnxe_override_eapol);
|
||||
bss->rsnxe_override_eapol = wpabuf_parse_bin(pos);
|
||||
} else if (os_strcmp(buf, "rsne_override_ft") == 0) {
|
||||
wpabuf_free(bss->rsne_override_ft);
|
||||
bss->rsne_override_ft = wpabuf_parse_bin(pos);
|
||||
} else if (os_strcmp(buf, "rsnxe_override_ft") == 0) {
|
||||
wpabuf_free(bss->rsnxe_override_ft);
|
||||
bss->rsnxe_override_ft = wpabuf_parse_bin(pos);
|
||||
} else if (os_strcmp(buf, "gtk_rsc_override") == 0) {
|
||||
wpabuf_free(bss->gtk_rsc_override);
|
||||
bss->gtk_rsc_override = wpabuf_parse_bin(pos);
|
||||
} else if (os_strcmp(buf, "igtk_rsc_override") == 0) {
|
||||
wpabuf_free(bss->igtk_rsc_override);
|
||||
bss->igtk_rsc_override = wpabuf_parse_bin(pos);
|
||||
} else if (os_strcmp(buf, "no_beacon_rsnxe") == 0) {
|
||||
bss->no_beacon_rsnxe = atoi(pos);
|
||||
} else if (os_strcmp(buf, "skip_prune_assoc") == 0) {
|
||||
bss->skip_prune_assoc = atoi(pos);
|
||||
} else if (os_strcmp(buf, "ft_rsnxe_used") == 0) {
|
||||
bss->ft_rsnxe_used = atoi(pos);
|
||||
} else if (os_strcmp(buf, "oci_freq_override_eapol_m3") == 0) {
|
||||
bss->oci_freq_override_eapol_m3 = atoi(pos);
|
||||
} else if (os_strcmp(buf, "oci_freq_override_eapol_g1") == 0) {
|
||||
bss->oci_freq_override_eapol_g1 = atoi(pos);
|
||||
} else if (os_strcmp(buf, "oci_freq_override_saquery_req") == 0) {
|
||||
bss->oci_freq_override_saquery_req = atoi(pos);
|
||||
} else if (os_strcmp(buf, "oci_freq_override_saquery_resp") == 0) {
|
||||
bss->oci_freq_override_saquery_resp = atoi(pos);
|
||||
} else if (os_strcmp(buf, "oci_freq_override_ft_assoc") == 0) {
|
||||
bss->oci_freq_override_ft_assoc = atoi(pos);
|
||||
} else if (os_strcmp(buf, "oci_freq_override_fils_assoc") == 0) {
|
||||
bss->oci_freq_override_fils_assoc = atoi(pos);
|
||||
} else if (os_strcmp(buf, "oci_freq_override_wnm_sleep") == 0) {
|
||||
bss->oci_freq_override_wnm_sleep = atoi(pos);
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
#ifdef CONFIG_SAE
|
||||
} else if (os_strcmp(buf, "sae_password") == 0) {
|
||||
|
|
@ -4162,8 +4295,9 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
} else if (os_strcmp(buf, "assocresp_elements") == 0) {
|
||||
if (parse_wpabuf_hex(line, buf, &bss->assocresp_elements, pos))
|
||||
return 1;
|
||||
} else if (os_strcmp(buf, "sae_anti_clogging_threshold") == 0) {
|
||||
bss->sae_anti_clogging_threshold = atoi(pos);
|
||||
} else if (os_strcmp(buf, "sae_anti_clogging_threshold") == 0 ||
|
||||
os_strcmp(buf, "anti_clogging_threshold") == 0) {
|
||||
bss->anti_clogging_threshold = atoi(pos);
|
||||
} else if (os_strcmp(buf, "sae_sync") == 0) {
|
||||
bss->sae_sync = atoi(pos);
|
||||
} else if (os_strcmp(buf, "sae_groups") == 0) {
|
||||
|
|
@ -4175,6 +4309,10 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
}
|
||||
} else if (os_strcmp(buf, "sae_require_mfp") == 0) {
|
||||
bss->sae_require_mfp = atoi(pos);
|
||||
} else if (os_strcmp(buf, "sae_confirm_immediate") == 0) {
|
||||
bss->sae_confirm_immediate = atoi(pos);
|
||||
} else if (os_strcmp(buf, "sae_pwe") == 0) {
|
||||
bss->sae_pwe = atoi(pos);
|
||||
} else if (os_strcmp(buf, "local_pwr_constraint") == 0) {
|
||||
int val = atoi(pos);
|
||||
if (val < 0 || val > 255) {
|
||||
|
|
@ -4318,12 +4456,24 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
bss->dhcp_server_port = atoi(pos);
|
||||
} else if (os_strcmp(buf, "dhcp_relay_port") == 0) {
|
||||
bss->dhcp_relay_port = atoi(pos);
|
||||
} else if (os_strcmp(buf, "fils_discovery_min_interval") == 0) {
|
||||
bss->fils_discovery_min_int = atoi(pos);
|
||||
} else if (os_strcmp(buf, "fils_discovery_max_interval") == 0) {
|
||||
bss->fils_discovery_max_int = atoi(pos);
|
||||
#endif /* CONFIG_FILS */
|
||||
} else if (os_strcmp(buf, "multicast_to_unicast") == 0) {
|
||||
bss->multicast_to_unicast = atoi(pos);
|
||||
} else if (os_strcmp(buf, "broadcast_deauth") == 0) {
|
||||
bss->broadcast_deauth = atoi(pos);
|
||||
} else if (os_strcmp(buf, "notify_mgmt_frames") == 0) {
|
||||
bss->notify_mgmt_frames = atoi(pos);
|
||||
#ifdef CONFIG_DPP
|
||||
} else if (os_strcmp(buf, "dpp_name") == 0) {
|
||||
os_free(bss->dpp_name);
|
||||
bss->dpp_name = os_strdup(pos);
|
||||
} else if (os_strcmp(buf, "dpp_mud_url") == 0) {
|
||||
os_free(bss->dpp_mud_url);
|
||||
bss->dpp_mud_url = os_strdup(pos);
|
||||
} else if (os_strcmp(buf, "dpp_connector") == 0) {
|
||||
os_free(bss->dpp_connector);
|
||||
bss->dpp_connector = os_strdup(pos);
|
||||
|
|
@ -4339,6 +4489,18 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
} else if (os_strcmp(buf, "dpp_controller") == 0) {
|
||||
if (hostapd_dpp_controller_parse(bss, pos))
|
||||
return 1;
|
||||
} else if (os_strcmp(buf, "dpp_configurator_connectivity") == 0) {
|
||||
bss->dpp_configurator_connectivity = atoi(pos);
|
||||
} else if (os_strcmp(buf, "dpp_pfs") == 0) {
|
||||
int val = atoi(pos);
|
||||
|
||||
if (val < 0 || val > 2) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Line %d: Invalid dpp_pfs value '%s'",
|
||||
line, pos);
|
||||
return -1;
|
||||
}
|
||||
bss->dpp_pfs = val;
|
||||
#endif /* CONFIG_DPP2 */
|
||||
#endif /* CONFIG_DPP */
|
||||
#ifdef CONFIG_OWE
|
||||
|
|
@ -4372,9 +4534,11 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
line, pos);
|
||||
return 1;
|
||||
}
|
||||
} else if (os_strcmp(buf, "owe_ptk_workaround") == 0) {
|
||||
bss->owe_ptk_workaround = atoi(pos);
|
||||
#endif /* CONFIG_OWE */
|
||||
} else if (os_strcmp(buf, "coloc_intf_reporting") == 0) {
|
||||
bss->coloc_intf_reporting = atoi(pos);
|
||||
#endif /* CONFIG_OWE */
|
||||
} else if (os_strcmp(buf, "multi_ap") == 0) {
|
||||
int val = atoi(pos);
|
||||
|
||||
|
|
@ -4389,8 +4553,12 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
conf->rssi_reject_assoc_rssi = atoi(pos);
|
||||
} else if (os_strcmp(buf, "rssi_reject_assoc_timeout") == 0) {
|
||||
conf->rssi_reject_assoc_timeout = atoi(pos);
|
||||
} else if (os_strcmp(buf, "rssi_ignore_probe_request") == 0) {
|
||||
conf->rssi_ignore_probe_request = atoi(pos);
|
||||
} else if (os_strcmp(buf, "pbss") == 0) {
|
||||
bss->pbss = atoi(pos);
|
||||
} else if (os_strcmp(buf, "transition_disable") == 0) {
|
||||
bss->transition_disable = strtol(pos, NULL, 16);
|
||||
#ifdef CONFIG_AIRTIME_POLICY
|
||||
} else if (os_strcmp(buf, "airtime_mode") == 0) {
|
||||
int val = atoi(pos);
|
||||
|
|
@ -4506,6 +4674,37 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
}
|
||||
bss->mka_psk_set |= MKA_PSK_SET_CKN;
|
||||
#endif /* CONFIG_MACSEC */
|
||||
} else if (os_strcmp(buf, "disable_11n") == 0) {
|
||||
bss->disable_11n = !!atoi(pos);
|
||||
} else if (os_strcmp(buf, "disable_11ac") == 0) {
|
||||
bss->disable_11ac = !!atoi(pos);
|
||||
} else if (os_strcmp(buf, "disable_11ax") == 0) {
|
||||
bss->disable_11ax = !!atoi(pos);
|
||||
#ifdef CONFIG_PASN
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
} else if (os_strcmp(buf, "force_kdk_derivation") == 0) {
|
||||
bss->force_kdk_derivation = atoi(pos);
|
||||
} else if (os_strcmp(buf, "pasn_corrupt_mic") == 0) {
|
||||
bss->pasn_corrupt_mic = atoi(pos);
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
} else if (os_strcmp(buf, "pasn_groups") == 0) {
|
||||
if (hostapd_parse_intlist(&bss->pasn_groups, pos)) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Line %d: Invalid pasn_groups value '%s'",
|
||||
line, pos);
|
||||
return 1;
|
||||
}
|
||||
} else if (os_strcmp(buf, "pasn_comeback_after") == 0) {
|
||||
bss->pasn_comeback_after = 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,
|
||||
line, "ext_capa_mask", pos))
|
||||
return 1;
|
||||
} else if (os_strcmp(buf, "ext_capa") == 0) {
|
||||
if (get_hex_config(bss->ext_capa, EXT_CAPA_MAX_LEN,
|
||||
line, "ext_capa", pos))
|
||||
return 1;
|
||||
} else {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Line %d: unknown configuration item '%s'",
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -44,15 +44,9 @@ CONFIG_LIBNL32=y
|
|||
# Driver interface for no driver (e.g., RADIUS server only)
|
||||
#CONFIG_DRIVER_NONE=y
|
||||
|
||||
# IEEE 802.11F/IAPP
|
||||
CONFIG_IAPP=y
|
||||
|
||||
# WPA2/IEEE 802.11i RSN pre-authentication
|
||||
CONFIG_RSN_PREAUTH=y
|
||||
|
||||
# IEEE 802.11w (management frame protection)
|
||||
CONFIG_IEEE80211W=y
|
||||
|
||||
# Support Operating Channel Validation
|
||||
#CONFIG_OCV=y
|
||||
|
||||
|
|
@ -154,9 +148,6 @@ CONFIG_IPV6=y
|
|||
# the IEEE 802.11 Management capability (e.g., FreeBSD/net80211)
|
||||
#CONFIG_DRIVER_RADIUS_ACL=y
|
||||
|
||||
# IEEE 802.11n (High Throughput) support
|
||||
#CONFIG_IEEE80211N=y
|
||||
|
||||
# Wireless Network Management (IEEE Std 802.11v-2011)
|
||||
# Note: This is experimental and not complete implementation.
|
||||
#CONFIG_WNM=y
|
||||
|
|
@ -355,12 +346,12 @@ CONFIG_IPV6=y
|
|||
# * ath10k
|
||||
#
|
||||
# For more details refer to:
|
||||
# http://wireless.kernel.org/en/users/Documentation/acs
|
||||
# https://wireless.wiki.kernel.org/en/users/documentation/acs
|
||||
#
|
||||
#CONFIG_ACS=y
|
||||
|
||||
# Multiband Operation support
|
||||
# These extentions facilitate efficient use of multiple frequency bands
|
||||
# These extensions facilitate efficient use of multiple frequency bands
|
||||
# available to the AP and the devices that may associate with it.
|
||||
#CONFIG_MBO=y
|
||||
|
||||
|
|
@ -389,3 +380,25 @@ CONFIG_IPV6=y
|
|||
# Override default value for the wpa_disable_eapol_key_retries configuration
|
||||
# parameter. See that parameter in hostapd.conf for more details.
|
||||
#CFLAGS += -DDEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES=1
|
||||
|
||||
# Wired equivalent privacy (WEP)
|
||||
# WEP is an obsolete cryptographic data confidentiality algorithm that is not
|
||||
# considered secure. It should not be used for anything anymore. The
|
||||
# functionality needed to use WEP is available in the current hostapd
|
||||
# release under this optional build parameter. This functionality is subject to
|
||||
# be completely removed in a future release.
|
||||
#CONFIG_WEP=y
|
||||
|
||||
# Remove all TKIP functionality
|
||||
# TKIP is an old cryptographic data confidentiality algorithm that is not
|
||||
# considered secure. It should not be used anymore. For now, the default hostapd
|
||||
# build includes this to allow mixed mode WPA+WPA2 networks to be enabled, but
|
||||
# that functionality is subject to be removed in the future.
|
||||
#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.
|
||||
# This requires CONFIG_IEEE80211W=y to be enabled, too.
|
||||
#CONFIG_PASN=y
|
||||
|
|
|
|||
19
contrib/wpa/hostapd/hostapd.android.rc
Normal file
19
contrib/wpa/hostapd/hostapd.android.rc
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# init.rc fragment for hostapd on Android
|
||||
# Copyright (c) 2002-2016, Jouni Malinen <j@w1.fi>
|
||||
#
|
||||
# This software may be distributed under the terms of the BSD license.
|
||||
# See README for more details.
|
||||
#
|
||||
|
||||
on post-fs-data
|
||||
mkdir /data/misc/wifi/hostapd 0770 wifi wifi
|
||||
|
||||
service hostapd /vendor/bin/hostapd \
|
||||
/data/misc/wifi/hostapd.conf
|
||||
class main
|
||||
user wifi
|
||||
writepid /data/misc/wifi/hostapd.pid
|
||||
group wifi
|
||||
disabled
|
||||
oneshot
|
||||
|
|
@ -41,7 +41,6 @@ interface=wlan0
|
|||
# bit 2 (4) = RADIUS
|
||||
# bit 3 (8) = WPA
|
||||
# bit 4 (16) = driver interface
|
||||
# bit 5 (32) = IAPP
|
||||
# bit 6 (64) = MLME
|
||||
#
|
||||
# Levels (minimum value for logged events):
|
||||
|
|
@ -73,7 +72,7 @@ ctrl_interface=/var/run/hostapd
|
|||
# run as non-root users. However, since the control interface can be used to
|
||||
# change the network configuration, this access needs to be protected in many
|
||||
# cases. By default, hostapd is configured to use gid 0 (root). If you
|
||||
# want to allow non-root users to use the contron interface, add a new group
|
||||
# want to allow non-root users to use the control interface, add a new group
|
||||
# and change this value to match with that group. Add users that should have
|
||||
# control interface access to this group.
|
||||
#
|
||||
|
|
@ -147,7 +146,8 @@ ssid=test
|
|||
# Operation mode (a = IEEE 802.11a (5 GHz), b = IEEE 802.11b (2.4 GHz),
|
||||
# g = IEEE 802.11g (2.4 GHz), ad = IEEE 802.11ad (60 GHz); a/g options are used
|
||||
# with IEEE 802.11n (HT), too, to specify band). For IEEE 802.11ac (VHT), this
|
||||
# needs to be set to hw_mode=a. When using ACS (see channel parameter), a
|
||||
# needs to be set to hw_mode=a. For IEEE 802.11ax (HE) on 6 GHz this needs
|
||||
# to be set to hw_mode=a. When using ACS (see channel parameter), a
|
||||
# special value "any" can be used to indicate that any support band can be used.
|
||||
# This special case is currently supported only with drivers with which
|
||||
# offloaded ACS is used.
|
||||
|
|
@ -164,8 +164,14 @@ hw_mode=g
|
|||
# which will enable the ACS survey based algorithm.
|
||||
channel=1
|
||||
|
||||
# Global operating class (IEEE 802.11, Annex E, Table E-4)
|
||||
# This option allows hostapd to specify the operating class of the channel
|
||||
# configured with the channel parameter. channel and op_class together can
|
||||
# uniquely identify channels across different bands, including the 6 GHz band.
|
||||
#op_class=131
|
||||
|
||||
# ACS tuning - Automatic Channel Selection
|
||||
# See: http://wireless.kernel.org/en/users/Documentation/acs
|
||||
# See: https://wireless.wiki.kernel.org/en/users/documentation/acs
|
||||
#
|
||||
# You can customize the ACS survey algorithm with following variables:
|
||||
#
|
||||
|
|
@ -199,11 +205,26 @@ channel=1
|
|||
#chanlist=100 104 108 112 116
|
||||
#chanlist=1 6 11-13
|
||||
|
||||
# Frequency list restriction. This option allows hostapd to select one of the
|
||||
# provided frequencies when a frequency should be automatically selected.
|
||||
# Frequency list can be provided as range using hyphen ('-') or individual
|
||||
# frequencies can be specified by comma (',') separated values
|
||||
# Default: all frequencies allowed in selected hw_mode
|
||||
#freqlist=2437,5955,5975
|
||||
#freqlist=2437,5985-6105
|
||||
|
||||
# Exclude DFS channels from ACS
|
||||
# This option can be used to exclude all DFS channels from the ACS channel list
|
||||
# in cases where the driver supports DFS channels.
|
||||
#acs_exclude_dfs=1
|
||||
|
||||
# Include only preferred scan channels from 6 GHz band for ACS
|
||||
# This option can be used to include only preferred scan channels in the 6 GHz
|
||||
# band. This can be useful in particular for devices that operate only a 6 GHz
|
||||
# BSS without a collocated 2.4/5 GHz BSS.
|
||||
# Default behavior is to include all PSC and non-PSC channels.
|
||||
#acs_exclude_6ghz_non_psc=1
|
||||
|
||||
# Beacon interval in kus (1.024 ms) (default: 100; range 15..65535)
|
||||
beacon_int=100
|
||||
|
||||
|
|
@ -258,6 +279,8 @@ fragm_threshold=-1
|
|||
# beacon_rate=ht:<HT MCS>
|
||||
# VHT:
|
||||
# beacon_rate=vht:<VHT MCS>
|
||||
# HE:
|
||||
# beacon_rate=he:<HE MCS>
|
||||
#
|
||||
# For example, beacon_rate=10 for 1 Mbps or beacon_rate=60 for 6 Mbps (OFDM).
|
||||
#beacon_rate=10
|
||||
|
|
@ -550,6 +573,10 @@ wmm_ac_vo_acm=0
|
|||
# Default: 1 (enabled)
|
||||
#broadcast_deauth=1
|
||||
|
||||
# Get notifications for received Management frames on control interface
|
||||
# Default: 0 (disabled)
|
||||
#notify_mgmt_frames=0
|
||||
|
||||
##### IEEE 802.11n related configuration ######################################
|
||||
|
||||
# ieee80211n: Whether IEEE 802.11n (HT) is enabled
|
||||
|
|
@ -559,6 +586,9 @@ wmm_ac_vo_acm=0
|
|||
# Note: hw_mode=g (2.4 GHz) and hw_mode=a (5 GHz) is used to specify the band.
|
||||
#ieee80211n=1
|
||||
|
||||
# disable_11n: Boolean (0/1) to disable HT for a specific BSS
|
||||
#disable_11n=0
|
||||
|
||||
# ht_capab: HT capabilities (list of flags)
|
||||
# LDPC coding capability: [LDPC] = supported
|
||||
# Supported channel width set: [HT40-] = both 20 MHz and 40 MHz with secondary
|
||||
|
|
@ -577,8 +607,6 @@ wmm_ac_vo_acm=0
|
|||
# channels if needed or creation of 40 MHz channel maybe rejected based
|
||||
# on overlapping BSSes. These changes are done automatically when hostapd
|
||||
# is setting up the 40 MHz channel.
|
||||
# Spatial Multiplexing (SM) Power Save: [SMPS-STATIC] or [SMPS-DYNAMIC]
|
||||
# (SMPS disabled if neither is set)
|
||||
# HT-greenfield: [GF] (disabled if not set)
|
||||
# Short GI for 20 MHz: [SHORT-GI-20] (disabled if not set)
|
||||
# Short GI for 40 MHz: [SHORT-GI-40] (disabled if not set)
|
||||
|
|
@ -613,6 +641,9 @@ wmm_ac_vo_acm=0
|
|||
# Note: hw_mode=a is used to specify that 5 GHz band is used with VHT.
|
||||
#ieee80211ac=1
|
||||
|
||||
# disable_11ac: Boolean (0/1) to disable VHT for a specific BSS
|
||||
#disable_11ac=0
|
||||
|
||||
# vht_capab: VHT capabilities (list of flags)
|
||||
#
|
||||
# vht_max_mpdu_len: [MAX-MPDU-7991] [MAX-MPDU-11454]
|
||||
|
|
@ -767,6 +798,9 @@ wmm_ac_vo_acm=0
|
|||
# 1 = enabled
|
||||
#ieee80211ax=1
|
||||
|
||||
# disable_11ax: Boolean (0/1) to disable HE for a specific BSS
|
||||
#disable_11ax=0
|
||||
|
||||
#he_su_beamformer: HE single user beamformer support
|
||||
# 0 = not supported (default)
|
||||
# 1 = supported
|
||||
|
|
@ -785,6 +819,9 @@ wmm_ac_vo_acm=0
|
|||
# he_bss_color: BSS color (1-63)
|
||||
#he_bss_color=1
|
||||
|
||||
# he_bss_color_partial: BSS color AID equation
|
||||
#he_bss_color_partial=0
|
||||
|
||||
#he_default_pe_duration: The duration of PE field in an HE PPDU in us
|
||||
# Possible values are 0 us (default), 4 us, 8 us, 12 us, and 16 us
|
||||
#he_default_pe_duration=0
|
||||
|
|
@ -794,12 +831,27 @@ wmm_ac_vo_acm=0
|
|||
# 1 = required
|
||||
#he_twt_required=0
|
||||
|
||||
#he_twt_responder: Whether TWT (HE) responder is enabled
|
||||
# 0 = disabled
|
||||
# 1 = enabled if supported by the driver (default)
|
||||
#he_twt_responder=1
|
||||
|
||||
#he_rts_threshold: Duration of STA transmission
|
||||
# 0 = not set (default)
|
||||
# unsigned integer = duration in units of 16 us
|
||||
#he_rts_threshold=0
|
||||
|
||||
# HE operating channel information; see matching vht_* parameters for details.
|
||||
# he_oper_centr_freq_seg0_idx field is used to indicate center frequency of 80
|
||||
# and 160 MHz bandwidth operation. In 80+80 MHz operation, it is the center
|
||||
# frequency of the lower frequency segment. he_oper_centr_freq_seg1_idx field
|
||||
# is used only with 80+80 MHz bandwidth operation and it is used to transmit
|
||||
# the center frequency of the second segment.
|
||||
# On the 6 GHz band the center freq calculation starts from 5.950 GHz offset.
|
||||
# For example idx=3 would result in 5965 MHz center frequency. In addition,
|
||||
# he_oper_chwidth is ignored, and the channel width is derived from the
|
||||
# configured operating class or center frequency indexes (see
|
||||
# IEEE P802.11ax/D6.1 Annex E, Table E-4).
|
||||
#he_oper_chwidth
|
||||
#he_oper_centr_freq_seg0_idx
|
||||
#he_oper_centr_freq_seg1_idx
|
||||
|
|
@ -835,10 +887,82 @@ wmm_ac_vo_acm=0
|
|||
#he_mu_edca_ac_vo_timer=255
|
||||
|
||||
# Spatial Reuse Parameter Set
|
||||
#
|
||||
# SR Control field value
|
||||
# B0 = PSR Disallowed
|
||||
# B1 = Non-SRG OBSS PD SR Disallowed
|
||||
# B2 = Non-SRG Offset Present
|
||||
# B3 = SRG Information Present
|
||||
# B4 = HESIGA_Spatial_reuse_value15_allowed
|
||||
#he_spr_sr_control
|
||||
#
|
||||
# Non-SRG OBSS PD Max Offset (included if he_spr_sr_control B2=1)
|
||||
#he_spr_non_srg_obss_pd_max_offset
|
||||
|
||||
# SRG OBSS PD Min Offset (included if he_spr_sr_control B3=1)
|
||||
#he_spr_srg_obss_pd_min_offset
|
||||
#
|
||||
# SRG OBSS PD Max Offset (included if he_spr_sr_control B3=1)
|
||||
#he_spr_srg_obss_pd_max_offset
|
||||
#
|
||||
# SPR SRG BSS Color (included if he_spr_sr_control B3=1)
|
||||
# This config represents SRG BSS Color Bitmap field of Spatial Reuse Parameter
|
||||
# Set element that indicates the BSS color values used by members of the
|
||||
# SRG of which the transmitting STA is a member. The value is in range of 0-63.
|
||||
#he_spr_srg_bss_colors=1 2 10 63
|
||||
#
|
||||
# SPR SRG Partial BSSID (included if he_spr_sr_control B3=1)
|
||||
# This config represents SRG Partial BSSID Bitmap field of Spatial Reuse
|
||||
# Parameter Set element that indicates the Partial BSSID values used by members
|
||||
# of the SRG of which the transmitting STA is a member. The value range
|
||||
# corresponds to one of the 64 possible values of BSSID[39:44], where the lowest
|
||||
# numbered bit corresponds to Partial BSSID value 0 and the highest numbered bit
|
||||
# corresponds to Partial BSSID value 63.
|
||||
#he_spr_srg_partial_bssid=0 1 3 63
|
||||
#
|
||||
#he_6ghz_max_mpdu: Maximum MPDU Length of HE 6 GHz band capabilities.
|
||||
# Indicates maximum MPDU length
|
||||
# 0 = 3895 octets
|
||||
# 1 = 7991 octets
|
||||
# 2 = 11454 octets (default)
|
||||
#he_6ghz_max_mpdu=2
|
||||
#
|
||||
#he_6ghz_max_ampdu_len_exp: Maximum A-MPDU Length Exponent of HE 6 GHz band
|
||||
# capabilities. Indicates the maximum length of A-MPDU pre-EOF padding that
|
||||
# the STA can receive. This field is an integer in the range of 0 to 7.
|
||||
# The length defined by this field is equal to
|
||||
# 2 pow(13 + Maximum A-MPDU Length Exponent) -1 octets
|
||||
# 0 = AMPDU length of 8k
|
||||
# 1 = AMPDU length of 16k
|
||||
# 2 = AMPDU length of 32k
|
||||
# 3 = AMPDU length of 65k
|
||||
# 4 = AMPDU length of 131k
|
||||
# 5 = AMPDU length of 262k
|
||||
# 6 = AMPDU length of 524k
|
||||
# 7 = AMPDU length of 1048k (default)
|
||||
#he_6ghz_max_ampdu_len_exp=7
|
||||
#
|
||||
#he_6ghz_rx_ant_pat: Rx Antenna Pattern Consistency of HE 6 GHz capability.
|
||||
# Indicates the possibility of Rx antenna pattern change
|
||||
# 0 = Rx antenna pattern might change during the lifetime of an association
|
||||
# 1 = Rx antenna pattern does not change during the lifetime of an association
|
||||
# (default)
|
||||
#he_6ghz_rx_ant_pat=1
|
||||
#
|
||||
#he_6ghz_tx_ant_pat: Tx Antenna Pattern Consistency of HE 6 GHz capability.
|
||||
# Indicates the possibility of Tx antenna pattern change
|
||||
# 0 = Tx antenna pattern might change during the lifetime of an association
|
||||
# 1 = Tx antenna pattern does not change during the lifetime of an association
|
||||
# (default)
|
||||
#he_6ghz_tx_ant_pat=1
|
||||
|
||||
# Unsolicited broadcast Probe Response transmission settings
|
||||
# This is for the 6 GHz band only. If the interval is set to a non-zero value,
|
||||
# the AP schedules unsolicited broadcast Probe Response frames to be
|
||||
# transmitted for in-band discovery. Refer to
|
||||
# IEEE P802.11ax/D8.0 26.17.2.3.2, AP behavior for fast passive scanning.
|
||||
# Valid range: 0..20 TUs; default is 0 (disabled)
|
||||
#unsol_bcast_probe_resp_interval=0
|
||||
|
||||
##### IEEE 802.1X-2004 related configuration ##################################
|
||||
|
||||
|
|
@ -877,6 +1001,8 @@ eapol_key_index_workaround=0
|
|||
|
||||
# EAP reauthentication period in seconds (default: 3600 seconds; 0 = disable
|
||||
# reauthentication).
|
||||
# Note: Reauthentications may enforce a disconnection, check the related
|
||||
# parameter wpa_deny_ptk0_rekey for details.
|
||||
#eap_reauth_period=3600
|
||||
|
||||
# Use PAE group address (01:80:c2:00:00:03) instead of individual target
|
||||
|
|
@ -1012,7 +1138,7 @@ eap_server=0
|
|||
#check_crl=1
|
||||
|
||||
# Specify whether to ignore certificate CRL validity time mismatches with
|
||||
# errors X509_V_ERR_CERT_HAS_EXPIRED and X509_V_ERR_CERT_NOT_YET_VALID.
|
||||
# errors X509_V_ERR_CRL_HAS_EXPIRED and X509_V_ERR_CRL_NOT_YET_VALID.
|
||||
#
|
||||
# 0 = ignore errors
|
||||
# 1 = do not ignore errors (default)
|
||||
|
|
@ -1081,6 +1207,12 @@ eap_server=0
|
|||
# [ENABLE-TLSv1.3] = enable TLSv1.3 (experimental - disabled by default)
|
||||
#tls_flags=[flag1][flag2]...
|
||||
|
||||
# Maximum number of EAP message rounds with data (default: 100)
|
||||
#max_auth_rounds=100
|
||||
|
||||
# Maximum number of short EAP message rounds (default: 50)
|
||||
#max_auth_rounds_short=50
|
||||
|
||||
# Cached OCSP stapling response (DER encoded)
|
||||
# If set, this file is sent as a certificate status response by the EAP server
|
||||
# if the EAP peer requests certificate status in the ClientHello message.
|
||||
|
|
@ -1167,7 +1299,7 @@ eap_server=0
|
|||
# should be unique across all issuing servers. In theory, this is a variable
|
||||
# length field, but due to some existing implementations requiring A-ID to be
|
||||
# 16 octets in length, it is strongly recommended to use that length for the
|
||||
# field to provid interoperability with deployed peer implementations. This
|
||||
# field to provide interoperability with deployed peer implementations. This
|
||||
# field is configured in hex format.
|
||||
#eap_fast_a_id=101112131415161718191a1b1c1d1e1f
|
||||
|
||||
|
|
@ -1194,6 +1326,8 @@ eap_server=0
|
|||
# EAP-TEAP authentication type
|
||||
# 0 = inner EAP (default)
|
||||
# 1 = Basic-Password-Auth
|
||||
# 2 = Do not require Phase 2 authentication if client can be authenticated
|
||||
# during Phase 1
|
||||
#eap_teap_auth=0
|
||||
|
||||
# EAP-TEAP authentication behavior when using PAC
|
||||
|
|
@ -1201,6 +1335,20 @@ eap_server=0
|
|||
# 1 = skip inner authentication (inner EAP/Basic-Password-Auth)
|
||||
#eap_teap_pac_no_inner=0
|
||||
|
||||
# EAP-TEAP behavior with Result TLV
|
||||
# 0 = include with Intermediate-Result TLV (default)
|
||||
# 1 = send in a separate message (for testing purposes)
|
||||
#eap_teap_separate_result=0
|
||||
|
||||
# EAP-TEAP identities
|
||||
# 0 = allow any identity type (default)
|
||||
# 1 = require user identity
|
||||
# 2 = require machine identity
|
||||
# 3 = request user identity; accept either user or machine identity
|
||||
# 4 = request machine identity; accept either user or machine identity
|
||||
# 5 = require both user and machine identity
|
||||
#eap_teap_id=0
|
||||
|
||||
# EAP-SIM and EAP-AKA protected success/failure indication using AT_RESULT_IND
|
||||
# (default: 0 = disabled).
|
||||
#eap_sim_aka_result_ind=1
|
||||
|
|
@ -1223,11 +1371,6 @@ eap_server=0
|
|||
# Whether to enable ERP on the EAP server.
|
||||
#eap_server_erp=1
|
||||
|
||||
##### IEEE 802.11f - Inter-Access Point Protocol (IAPP) #######################
|
||||
|
||||
# Interface to be used for IAPP broadcast packets
|
||||
#iapp_interface=eth0
|
||||
|
||||
|
||||
##### RADIUS client configuration #############################################
|
||||
# for IEEE 802.1X with external Authentication Server, IEEE 802.11
|
||||
|
|
@ -1261,6 +1404,12 @@ own_ip_addr=127.0.0.1
|
|||
# used, e.g., when the device has multiple IP addresses.
|
||||
#radius_client_addr=127.0.0.1
|
||||
|
||||
# RADIUS client forced local interface. Helps run properly with VRF
|
||||
# Default is none set which allows the network stack to pick the appropriate
|
||||
# interface automatically.
|
||||
# Example below binds to eth0
|
||||
#radius_client_dev=eth0
|
||||
|
||||
# RADIUS authentication server
|
||||
#auth_server_addr=127.0.0.1
|
||||
#auth_server_port=1812
|
||||
|
|
@ -1466,6 +1615,17 @@ own_ip_addr=127.0.0.1
|
|||
# wpa_key_mgmt=SAE for WPA3-Personal instead of wpa_key_mgmt=WPA-PSK).
|
||||
#wpa=2
|
||||
|
||||
# Extended Key ID support for Individually Addressed frames
|
||||
#
|
||||
# Extended Key ID allows to rekey PTK keys without the impacts the "normal"
|
||||
# PTK rekeying with only a single Key ID 0 has. It can only be used when the
|
||||
# driver supports it and RSN/WPA2 is used with a CCMP/GCMP pairwise cipher.
|
||||
#
|
||||
# 0 = force off, i.e., use only Key ID 0 (default)
|
||||
# 1 = enable and use Extended Key ID support when possible
|
||||
# 2 = identical to 1 but start with Key ID 1 when possible
|
||||
#extended_key_id=0
|
||||
|
||||
# WPA pre-shared keys for WPA-PSK. This can be either entered as a 256-bit
|
||||
# secret in hex format (64 hex digits), wpa_psk, or as an ASCII passphrase
|
||||
# (8..63 characters) that will be converted to PSK. This conversion uses SSID
|
||||
|
|
@ -1566,8 +1726,26 @@ own_ip_addr=127.0.0.1
|
|||
|
||||
# Maximum lifetime for PTK in seconds. This can be used to enforce rekeying of
|
||||
# PTK to mitigate some attacks against TKIP deficiencies.
|
||||
# Warning: PTK rekeying is buggy with many drivers/devices and with such
|
||||
# devices, the only secure method to rekey the PTK without Extended Key ID
|
||||
# support requires a disconnection. Check the related parameter
|
||||
# wpa_deny_ptk0_rekey for details.
|
||||
#wpa_ptk_rekey=600
|
||||
|
||||
# Workaround for PTK rekey issues
|
||||
#
|
||||
# PTK0 rekeys (rekeying the PTK without "Extended Key ID for Individually
|
||||
# Addressed Frames") can degrade the security and stability with some cards.
|
||||
# To avoid such issues hostapd can replace those PTK rekeys (including EAP
|
||||
# reauthentications) with disconnects.
|
||||
#
|
||||
# Available options:
|
||||
# 0 = always rekey when configured/instructed (default)
|
||||
# 1 = only rekey when the local driver is explicitly indicating it can perform
|
||||
# this operation without issues
|
||||
# 2 = never allow PTK0 rekeys
|
||||
#wpa_deny_ptk0_rekey=0
|
||||
|
||||
# The number of times EAPOL-Key Message 1/4 and Message 3/4 in the RSN 4-Way
|
||||
# Handshake are retried per 4-Way Handshake attempt.
|
||||
# (dot11RSNAConfigPairwiseUpdateCount)
|
||||
|
|
@ -1618,6 +1796,12 @@ own_ip_addr=127.0.0.1
|
|||
# 1 = optional
|
||||
# 2 = required
|
||||
#ieee80211w=0
|
||||
# The most common configuration options for this based on the PMF (protected
|
||||
# management frames) certification program are:
|
||||
# PMF enabled: ieee80211w=1 and wpa_key_mgmt=WPA-EAP WPA-EAP-SHA256
|
||||
# PMF required: ieee80211w=2 and wpa_key_mgmt=WPA-EAP-SHA256
|
||||
# (and similarly for WPA-PSK and WPA-PSK-SHA256 if WPA2-Personal is used)
|
||||
# WPA3-Personal-only mode: ieee80211w=2 and wpa_key_mgmt=SAE
|
||||
|
||||
# Group management cipher suite
|
||||
# Default: AES-128-CMAC (BIP)
|
||||
|
|
@ -1630,6 +1814,13 @@ own_ip_addr=127.0.0.1
|
|||
# available in deployed devices.
|
||||
#group_mgmt_cipher=AES-128-CMAC
|
||||
|
||||
# Beacon Protection (management frame protection for Beacon frames)
|
||||
# This depends on management frame protection being enabled (ieee80211w != 0)
|
||||
# and beacon protection support indication from the driver.
|
||||
# 0 = disabled (default)
|
||||
# 1 = enabled
|
||||
#beacon_prot=0
|
||||
|
||||
# Association SA Query maximum timeout (in TU = 1.024 ms; for MFP)
|
||||
# (maximum time to wait for a SA Query response)
|
||||
# dot11AssociationSAQueryMaximumTimeout, 1...4294967295
|
||||
|
|
@ -1642,9 +1833,25 @@ own_ip_addr=127.0.0.1
|
|||
|
||||
# ocv: Operating Channel Validation
|
||||
# This is a countermeasure against multi-channel man-in-the-middle attacks.
|
||||
# Enabling this depends on the driver's support for OCV when the driver SME is
|
||||
# used. If hostapd SME is used, this will be enabled just based on this
|
||||
# configuration.
|
||||
# Enabling this automatically also enables ieee80211w, if not yet enabled.
|
||||
# 0 = disabled (default)
|
||||
# 1 = enabled
|
||||
# 2 = enabled in workaround mode - Allow STA that claims OCV capability to
|
||||
# connect even if the STA doesn't send OCI or negotiate PMF. This
|
||||
# workaround is to improve interoperability with legacy STAs which are
|
||||
# wrongly copying reserved bits of RSN capabilities from the AP's
|
||||
# RSNE into (Re)Association Request frames. When this configuration is
|
||||
# enabled, the AP considers STA is OCV capable only when the STA indicates
|
||||
# MFP capability in (Re)Association Request frames and sends OCI in
|
||||
# EAPOL-Key msg 2/4/FT Reassociation Request frame/FILS (Re)Association
|
||||
# Request frame; otherwise, the AP disables OCV for the current connection
|
||||
# with the STA. Enabling this workaround mode reduced OCV protection to
|
||||
# some extend since it allows misbehavior to go through. As such, this
|
||||
# should be enabled only if interoperability with misbehaving STAs is
|
||||
# needed.
|
||||
#ocv=1
|
||||
|
||||
# disable_pmksa_caching: Disable PMKSA caching
|
||||
|
|
@ -1676,7 +1883,7 @@ own_ip_addr=127.0.0.1
|
|||
# be followed by optional peer MAC address (dot11RSNAConfigPasswordPeerMac) and
|
||||
# by optional password identifier (dot11RSNAConfigPasswordIdentifier). In
|
||||
# addition, an optional VLAN ID specification can be used to bind the station
|
||||
# to the specified VLAN whenver the specific SAE password entry is used.
|
||||
# to the specified VLAN whenever the specific SAE password entry is used.
|
||||
#
|
||||
# If the peer MAC address is not included or is set to the wildcard address
|
||||
# (ff:ff:ff:ff:ff:ff), the entry is available for any station to use. If a
|
||||
|
|
@ -1691,7 +1898,8 @@ own_ip_addr=127.0.0.1
|
|||
# special meaning of removing all previously added entries.
|
||||
#
|
||||
# sae_password uses the following encoding:
|
||||
#<password/credential>[|mac=<peer mac>][|vlanid=<VLAN ID>][|id=<identifier>]
|
||||
#<password/credential>[|mac=<peer mac>][|vlanid=<VLAN ID>]
|
||||
#[|pk=<m:ECPrivateKey-base64>][|id=<identifier>]
|
||||
# Examples:
|
||||
#sae_password=secret
|
||||
#sae_password=really secret|mac=ff:ff:ff:ff:ff:ff
|
||||
|
|
@ -1701,10 +1909,11 @@ own_ip_addr=127.0.0.1
|
|||
# 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.
|
||||
#sae_anti_clogging_threshold=5
|
||||
#sae_anti_clogging_threshold=5 (deprecated)
|
||||
#anti_clogging_threshold=5
|
||||
|
||||
# Maximum number of SAE synchronization errors (dot11RSNASAESync)
|
||||
# The offending SAe peer will be disconnected if more than this many
|
||||
# The offending SAE peer will be disconnected if more than this many
|
||||
# synchronization errors happen.
|
||||
#sae_sync=5
|
||||
|
||||
|
|
@ -1729,6 +1938,23 @@ own_ip_addr=127.0.0.1
|
|||
# MFP while SAE stations are required to negotiate MFP if sae_require_mfp=1.
|
||||
#sae_require_mfp=0
|
||||
|
||||
# SAE Confirm behavior
|
||||
# By default, AP will send out only SAE Commit message in response to a received
|
||||
# SAE Commit message. This parameter can be set to 1 to override that behavior
|
||||
# to send both SAE Commit and SAE Confirm messages without waiting for the STA
|
||||
# to send its SAE Confirm message first.
|
||||
#sae_confirm_immediate=0
|
||||
|
||||
# SAE mechanism for PWE derivation
|
||||
# 0 = hunting-and-pecking loop only (default without password identifier)
|
||||
# 1 = hash-to-element only (default with password identifier)
|
||||
# 2 = both hunting-and-pecking loop and hash-to-element enabled
|
||||
# Note: The default value is likely to change from 0 to 2 once the new
|
||||
# hash-to-element mechanism has received more interoperability testing.
|
||||
# When using SAE password identifier, the hash-to-element mechanism is used
|
||||
# regardless of the sae_pwe parameter value.
|
||||
#sae_pwe=0
|
||||
|
||||
# FILS Cache Identifier (16-bit value in hexdump format)
|
||||
#fils_cache_id=0011
|
||||
|
||||
|
|
@ -1753,6 +1979,19 @@ own_ip_addr=127.0.0.1
|
|||
# http://www.iana.org/assignments/ipsec-registry/ipsec-registry.xml#ipsec-registry-10
|
||||
#owe_groups=19 20 21
|
||||
|
||||
# OWE PTK derivation workaround
|
||||
# Initial OWE implementation used SHA256 when deriving the PTK for all OWE
|
||||
# groups. This was supposed to change to SHA384 for group 20 and SHA512 for
|
||||
# group 21. This parameter can be used to enable workaround for interoperability
|
||||
# with stations that use SHA256 with groups 20 and 21. By default (0) only the
|
||||
# appropriate hash function is accepted. When workaround is enabled (1), the
|
||||
# appropriate hash function is tried first and if that fails, SHA256-based PTK
|
||||
# derivation is attempted. This workaround can result in reduced security for
|
||||
# groups 20 and 21, but is required for interoperability with older
|
||||
# implementations. There is no impact to group 19 behavior. The workaround is
|
||||
# disabled by default and can be enabled by uncommenting the following line.
|
||||
#owe_ptk_workaround=1
|
||||
|
||||
# OWE transition mode configuration
|
||||
# Pointer to the matching open/OWE BSS
|
||||
#owe_transition_bssid=<bssid>
|
||||
|
|
@ -1790,6 +2029,45 @@ own_ip_addr=127.0.0.1
|
|||
# default: 30 TUs (= 30.72 milliseconds)
|
||||
#fils_hlp_wait_time=30
|
||||
|
||||
# FILS Discovery frame transmission minimum and maximum interval settings.
|
||||
# If fils_discovery_max_interval is non-zero, the AP enables FILS Discovery
|
||||
# frame transmission. These values use TUs as the unit and have allowed range
|
||||
# of 0-10000. fils_discovery_min_interval defaults to 20.
|
||||
#fils_discovery_min_interval=20
|
||||
#fils_discovery_max_interval=0
|
||||
|
||||
# Transition Disable indication
|
||||
# The AP can notify authenticated stations to disable transition mode in their
|
||||
# network profiles when the network has completed transition steps, i.e., once
|
||||
# sufficiently large number of APs in the ESS have been updated to support the
|
||||
# more secure alternative. When this indication is used, the stations are
|
||||
# expected to automatically disable transition mode and less secure security
|
||||
# options. This includes use of WEP, TKIP (including use of TKIP as the group
|
||||
# cipher), and connections without PMF.
|
||||
# Bitmap bits:
|
||||
# bit 0 (0x01): WPA3-Personal (i.e., disable WPA2-Personal = WPA-PSK and only
|
||||
# allow SAE to be used)
|
||||
# bit 1 (0x02): SAE-PK (disable SAE without use of SAE-PK)
|
||||
# bit 2 (0x04): WPA3-Enterprise (move to requiring PMF)
|
||||
# bit 3 (0x08): Enhanced Open (disable use of open network; require OWE)
|
||||
# (default: 0 = do not include Transition Disable KDE)
|
||||
#transition_disable=0x01
|
||||
|
||||
# PASN ECDH groups
|
||||
# PASN implementations are required to support group 19 (NIST P-256). If this
|
||||
# parameter is not set, only group 19 is supported by default. This
|
||||
# configuration parameter can be used to specify a limited set of allowed
|
||||
# groups. The group values are listed in the IANA registry:
|
||||
# http://www.iana.org/assignments/ipsec-registry/ipsec-registry.xml#ipsec-registry-10
|
||||
#pasn_groups=19 20 21
|
||||
|
||||
# PASN comeback after time in TUs
|
||||
# In case the AP is temporarily unable to handle a PASN authentication exchange
|
||||
# due to a too large number of parallel operations, this value indicates to the
|
||||
# peer after how many TUs it can try the PASN exchange again.
|
||||
# (default: 10 TUs)
|
||||
#pasn_comeback_after=10
|
||||
|
||||
##### IEEE 802.11r configuration ##############################################
|
||||
|
||||
# Mobility Domain identifier (dot11FTMobilityDomainID, MDID)
|
||||
|
|
@ -1833,7 +2111,7 @@ own_ip_addr=127.0.0.1
|
|||
# Wildcard entry:
|
||||
# Upon receiving a response from R0KH, it will be added to this list, so
|
||||
# subsequent requests won't be broadcast. If R0KH does not reply, it will be
|
||||
# blacklisted.
|
||||
# temporarily blocked (see rkh_neg_timeout).
|
||||
#r0kh=ff:ff:ff:ff:ff:ff * 00112233445566778899aabbccddeeff
|
||||
|
||||
# List of R1KHs in the same Mobility Domain
|
||||
|
|
@ -1889,7 +2167,7 @@ own_ip_addr=127.0.0.1
|
|||
#ft_psk_generate_local=0
|
||||
|
||||
##### Neighbor table ##########################################################
|
||||
# Maximum number of entries kept in AP table (either for neigbor table or for
|
||||
# Maximum number of entries kept in AP table (either for neighbor table or for
|
||||
# detecting Overlapping Legacy BSS Condition). The oldest entry will be
|
||||
# removed when adding a new entry that would make the list grow over this
|
||||
# limit. Note! WFA certification for IEEE 802.11g requires that OLBC is
|
||||
|
|
@ -2143,6 +2421,13 @@ own_ip_addr=127.0.0.1
|
|||
#wps_nfc_dh_privkey: Hexdump of DH Private Key
|
||||
#wps_nfc_dev_pw: Hexdump of Device Password
|
||||
|
||||
# Application Extension attribute for Beacon and Probe Response frames
|
||||
# This parameter can be used to add application extension into WPS IE. The
|
||||
# contents of this parameter starts with 16-octet (32 hexdump characters) of
|
||||
# UUID to identify the specific application and that is followed by the actual
|
||||
# application specific data.
|
||||
#wps_application_ext=<hexdump>
|
||||
|
||||
##### Wi-Fi Direct (P2P) ######################################################
|
||||
|
||||
# Enable P2P Device management
|
||||
|
|
@ -2151,6 +2436,31 @@ own_ip_addr=127.0.0.1
|
|||
# Allow cross connection
|
||||
#allow_cross_connection=1
|
||||
|
||||
##### Device Provisioning Protocol (DPP) ######################################
|
||||
|
||||
# Name for Enrollee's DPP Configuration Request
|
||||
#dpp_name=Test
|
||||
|
||||
# MUD URL for Enrollee's DPP Configuration Request (optional)
|
||||
#dpp_mud_url=https://example.com/mud
|
||||
|
||||
#dpp_connector
|
||||
#dpp_netaccesskey
|
||||
#dpp_netaccesskey_expiry
|
||||
#dpp_csign
|
||||
#dpp_controller
|
||||
|
||||
# Configurator Connectivity indication
|
||||
# 0: no Configurator is currently connected (default)
|
||||
# 1: advertise that a Configurator is available
|
||||
#dpp_configurator_connectivity=0
|
||||
|
||||
# DPP PFS
|
||||
# 0: allow PFS to be used or not used (default)
|
||||
# 1: require PFS to be used (note: not compatible with DPP R1)
|
||||
# 2: do not allow PFS to be used
|
||||
#dpp_pfs=0
|
||||
|
||||
#### TDLS (IEEE 802.11z-2010) #################################################
|
||||
|
||||
# Prohibit use of TDLS in this BSS
|
||||
|
|
@ -2531,7 +2841,7 @@ own_ip_addr=127.0.0.1
|
|||
# Default is 0 = OCE disabled
|
||||
#oce=0
|
||||
|
||||
# RSSI-based assocition rejection
|
||||
# RSSI-based association rejection
|
||||
#
|
||||
# Reject STA association if RSSI is below given threshold (in dBm)
|
||||
# Allowed range: -60 to -90 dBm; default = 0 (rejection disabled)
|
||||
|
|
@ -2546,6 +2856,10 @@ own_ip_addr=127.0.0.1
|
|||
# threshold (range: 0..255, default=30).
|
||||
#rssi_reject_assoc_timeout=30
|
||||
|
||||
# Ignore Probe Request frames if RSSI is below given threshold (in dBm)
|
||||
# Allowed range: -60 to -90 dBm; default = 0 (rejection disabled)
|
||||
#rssi_ignore_probe_request=-75
|
||||
|
||||
##### Fast Session Transfer (FST) support #####################################
|
||||
#
|
||||
# The options in this section are only available when the build configuration
|
||||
|
|
@ -2638,6 +2952,19 @@ own_ip_addr=127.0.0.1
|
|||
# airtime.
|
||||
#airtime_bss_limit=1
|
||||
|
||||
##### EDMG support ############################################################
|
||||
#
|
||||
# Enable EDMG capability for AP mode in the 60 GHz band. Default value is false.
|
||||
# To configure channel bonding for an EDMG AP use edmg_channel below.
|
||||
# If enable_edmg is set and edmg_channel is not set, EDMG CB1 will be
|
||||
# configured.
|
||||
#enable_edmg=1
|
||||
#
|
||||
# Configure channel bonding for AP mode in the 60 GHz band.
|
||||
# This parameter is relevant only if enable_edmg is set.
|
||||
# Default value is 0 (no channel bonding).
|
||||
#edmg_channel=9
|
||||
|
||||
##### TESTING OPTIONS #########################################################
|
||||
#
|
||||
# The options in this section are only available when the build configuration
|
||||
|
|
|
|||
|
|
@ -7,9 +7,15 @@
|
|||
# keyid=<keyid_string>
|
||||
# An optional VLAN ID can be specified by prefixing the line with
|
||||
# vlanid=<VLAN ID>.
|
||||
# An optional WPS tag can be added by prefixing the line with
|
||||
# wps=<0/1> (default: 0). Any matching entry with that tag will be used when
|
||||
# generating a PSK for a WPS Enrollee instead of generating a new random
|
||||
# per-Enrollee PSK.
|
||||
00:00:00:00:00:00 secret passphrase
|
||||
00:11:22:33:44:55 another passphrase
|
||||
00:22:33:44:55:66 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
|
||||
keyid=example_id 00:11:22:33:44:77 passphrase with keyid
|
||||
vlanid=3 00:00:00:00:00:00 passphrase with vlanid
|
||||
wps=1 00:00:00:00:00:00 passphrase for WPS
|
||||
wps=1 11:22:33:44:55:00 dev-specific passphrase for WPS
|
||||
00:00:00:00:00:00 another passphrase for all STAs
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ static void usage(void)
|
|||
fprintf(stderr, "%s\n", hostapd_cli_version);
|
||||
fprintf(stderr,
|
||||
"\n"
|
||||
"usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvB] "
|
||||
"usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvBr] "
|
||||
"[-a<path>] \\\n"
|
||||
" [-P<pid file>] [-G<ping interval>] [command..]\n"
|
||||
"\n"
|
||||
|
|
@ -68,6 +68,9 @@ static void usage(void)
|
|||
" -a<file> run in daemon mode executing the action file "
|
||||
"based on events\n"
|
||||
" from hostapd\n"
|
||||
" -r try to reconnect when client socket is "
|
||||
"disconnected.\n"
|
||||
" This is useful only when used with -a.\n"
|
||||
" -B run a daemon in the background\n"
|
||||
" -i<ifname> Interface to listen on (default: first "
|
||||
"interface found in the\n"
|
||||
|
|
@ -401,7 +404,6 @@ static int hostapd_cli_cmd_signature(struct wpa_ctrl *ctrl, int argc,
|
|||
#endif /* CONFIG_TAXONOMY */
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
|
|
@ -414,7 +416,6 @@ static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
|
|||
snprintf(buf, sizeof(buf), "SA_QUERY %s", argv[0]);
|
||||
return wpa_ctrl_command(ctrl, buf);
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
|
|
@ -974,7 +975,7 @@ static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
|
|||
dir = opendir(ctrl_iface_dir);
|
||||
if (dir == NULL) {
|
||||
printf("Control interface directory '%s' could not be "
|
||||
"openned.\n", ctrl_iface_dir);
|
||||
"opened.\n", ctrl_iface_dir);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1226,14 +1227,15 @@ static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
|||
char cmd[256];
|
||||
int res;
|
||||
|
||||
if (argc < 2 || argc > 3) {
|
||||
if (argc < 2 || argc > 4) {
|
||||
printf("Invalid vendor command\n"
|
||||
"usage: <vendor id> <command id> [<hex formatted command argument>]\n");
|
||||
"usage: <vendor id> <command id> [<hex formatted command argument>] [nested=<0|1>]\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s", argv[0], argv[1],
|
||||
argc == 3 ? argv[2] : "");
|
||||
res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s%s%s", argv[0],
|
||||
argv[1], argc >= 3 ? argv[2] : "",
|
||||
argc == 4 ? " " : "", argc == 4 ? argv[3] : "");
|
||||
if (os_snprintf_error(sizeof(cmd), res)) {
|
||||
printf("Too long VENDOR command.\n");
|
||||
return -1;
|
||||
|
|
@ -1311,24 +1313,17 @@ static int hostapd_cli_cmd_set_neighbor(struct wpa_ctrl *ctrl, int argc,
|
|||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_show_neighbor(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
return wpa_ctrl_command(ctrl, "SHOW_NEIGHBOR");
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_remove_neighbor(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
char cmd[400];
|
||||
int res;
|
||||
|
||||
if (argc != 2) {
|
||||
printf("Invalid remove_neighbor command: needs 2 arguments\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NEIGHBOR %s %s",
|
||||
argv[0], argv[1]);
|
||||
if (os_snprintf_error(sizeof(cmd), res)) {
|
||||
printf("Too long REMOVE_NEIGHBOR command.\n");
|
||||
return -1;
|
||||
}
|
||||
return wpa_ctrl_command(ctrl, cmd);
|
||||
return hostapd_cli_cmd(ctrl, "REMOVE_NEIGHBOR", 1, argc, argv);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1408,6 +1403,13 @@ static int hostapd_cli_cmd_dpp_bootstrap_info(struct wpa_ctrl *ctrl, int argc,
|
|||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_dpp_bootstrap_set(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
return hostapd_cli_cmd(ctrl, "DPP_BOOTSTRAP_SET", 1, argc, argv);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_dpp_auth_init(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
|
|
@ -1470,6 +1472,37 @@ static int hostapd_cli_cmd_dpp_pkex_remove(struct wpa_ctrl *ctrl, int argc,
|
|||
return hostapd_cli_cmd(ctrl, "DPP_PKEX_REMOVE", 1, argc, argv);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_DPP2
|
||||
|
||||
static int hostapd_cli_cmd_dpp_controller_start(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
return hostapd_cli_cmd(ctrl, "DPP_CONTROLLER_START", 1, argc, argv);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_dpp_controller_stop(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
return wpa_ctrl_command(ctrl, "DPP_CONTROLLER_STOP");
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_dpp_chirp(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
return hostapd_cli_cmd(ctrl, "DPP_CHIRP", 1, argc, argv);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_dpp_stop_chirp(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
return wpa_ctrl_command(ctrl, "DPP_STOP_CHIRP");
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DPP2 */
|
||||
#endif /* CONFIG_DPP */
|
||||
|
||||
|
||||
|
|
@ -1508,6 +1541,14 @@ static int hostapd_cli_cmd_reload_wpa_psk(struct wpa_ctrl *ctrl, int argc,
|
|||
}
|
||||
|
||||
|
||||
#ifdef ANDROID
|
||||
static int hostapd_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||
{
|
||||
return hostapd_cli_cmd(ctrl, "DRIVER", 1, argc, argv);
|
||||
}
|
||||
#endif /* ANDROID */
|
||||
|
||||
|
||||
struct hostapd_cli_cmd {
|
||||
const char *cmd;
|
||||
int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
|
||||
|
|
@ -1542,10 +1583,8 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
|
|||
{ "signature", hostapd_cli_cmd_signature, hostapd_complete_stations,
|
||||
"<addr> = get taxonomy signature for a station" },
|
||||
#endif /* CONFIG_TAXONOMY */
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
{ "sa_query", hostapd_cli_cmd_sa_query, hostapd_complete_stations,
|
||||
"<addr> = send SA Query to a station" },
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_WPS
|
||||
{ "wps_pin", hostapd_cli_cmd_wps_pin, NULL,
|
||||
"<uuid> <pin> [timeout] [addr] = add WPS Enrollee PIN" },
|
||||
|
|
@ -1637,8 +1676,10 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
|
|||
{ "set_neighbor", hostapd_cli_cmd_set_neighbor, NULL,
|
||||
"<addr> <ssid=> <nr=> [lci=] [civic=] [stat]\n"
|
||||
" = add AP to neighbor database" },
|
||||
{ "show_neighbor", hostapd_cli_cmd_show_neighbor, NULL,
|
||||
" = show neighbor database entries" },
|
||||
{ "remove_neighbor", hostapd_cli_cmd_remove_neighbor, NULL,
|
||||
"<addr> <ssid=> = remove AP from neighbor database" },
|
||||
"<addr> [ssid=<hex>] = remove AP from neighbor database" },
|
||||
{ "req_lci", hostapd_cli_cmd_req_lci, hostapd_complete_stations,
|
||||
"<addr> = send LCI request to a station"},
|
||||
{ "req_range", hostapd_cli_cmd_req_range, NULL,
|
||||
|
|
@ -1656,6 +1697,8 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
|
|||
"<id> = get DPP bootstrap URI" },
|
||||
{ "dpp_bootstrap_info", hostapd_cli_cmd_dpp_bootstrap_info, NULL,
|
||||
"<id> = show DPP bootstrap information" },
|
||||
{ "dpp_bootstrap_set", hostapd_cli_cmd_dpp_bootstrap_set, NULL,
|
||||
"<id> [conf=..] [ssid=<SSID>] [ssid_charset=#] [psk=<PSK>] [pass=<passphrase>] [configurator=<id>] [conn_status=#] [akm_use_selector=<0|1>] [group_id=..] [expiry=#] [csrattrs=..] = set DPP configurator parameters" },
|
||||
{ "dpp_auth_init", hostapd_cli_cmd_dpp_auth_init, NULL,
|
||||
"peer=<id> [own=<id>] = initiate DPP bootstrapping" },
|
||||
{ "dpp_listen", hostapd_cli_cmd_dpp_listen, NULL,
|
||||
|
|
@ -1676,6 +1719,16 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
|
|||
"add PKEX code" },
|
||||
{ "dpp_pkex_remove", hostapd_cli_cmd_dpp_pkex_remove, NULL,
|
||||
"*|<id> = remove DPP pkex information" },
|
||||
#ifdef CONFIG_DPP2
|
||||
{ "dpp_controller_start", hostapd_cli_cmd_dpp_controller_start, NULL,
|
||||
"[tcp_port=<port>] [role=..] = start DPP controller" },
|
||||
{ "dpp_controller_stop", hostapd_cli_cmd_dpp_controller_stop, NULL,
|
||||
"= stop DPP controller" },
|
||||
{ "dpp_chirp", hostapd_cli_cmd_dpp_chirp, NULL,
|
||||
"own=<BI ID> iter=<count> = start DPP chirp" },
|
||||
{ "dpp_stop_chirp", hostapd_cli_cmd_dpp_stop_chirp, NULL,
|
||||
"= stop DPP chirp" },
|
||||
#endif /* CONFIG_DPP2 */
|
||||
#endif /* CONFIG_DPP */
|
||||
{ "accept_acl", hostapd_cli_cmd_accept_macacl, NULL,
|
||||
"=Add/Delete/Show/Clear accept MAC ACL" },
|
||||
|
|
@ -1687,6 +1740,10 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
|
|||
"<addr> [req_mode=] <measurement request hexdump> = send a Beacon report request to a station" },
|
||||
{ "reload_wpa_psk", hostapd_cli_cmd_reload_wpa_psk, NULL,
|
||||
"= reload wpa_psk_file only" },
|
||||
#ifdef ANDROID
|
||||
{ "driver", hostapd_cli_cmd_driver, NULL,
|
||||
"<driver sub command> [<hex formatted data>] = send driver command data" },
|
||||
#endif /* ANDROID */
|
||||
{ NULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
|
|
@ -2011,12 +2068,13 @@ int main(int argc, char *argv[])
|
|||
int warning_displayed = 0;
|
||||
int c;
|
||||
int daemonize = 0;
|
||||
int reconnect = 0;
|
||||
|
||||
if (os_program_init())
|
||||
return -1;
|
||||
|
||||
for (;;) {
|
||||
c = getopt(argc, argv, "a:BhG:i:p:P:s:v");
|
||||
c = getopt(argc, argv, "a:BhG:i:p:P:rs:v");
|
||||
if (c < 0)
|
||||
break;
|
||||
switch (c) {
|
||||
|
|
@ -2045,6 +2103,9 @@ int main(int argc, char *argv[])
|
|||
case 'P':
|
||||
pid_file = optarg;
|
||||
break;
|
||||
case 'r':
|
||||
reconnect = 1;
|
||||
break;
|
||||
case 's':
|
||||
client_socket_dir = optarg;
|
||||
break;
|
||||
|
|
@ -2087,8 +2148,7 @@ int main(int argc, char *argv[])
|
|||
printf("Connection established.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (!interactive) {
|
||||
if (!interactive && !reconnect) {
|
||||
perror("Failed to connect to hostapd - "
|
||||
"wpa_ctrl_open");
|
||||
return -1;
|
||||
|
|
@ -2106,8 +2166,14 @@ int main(int argc, char *argv[])
|
|||
return -1;
|
||||
if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
|
||||
return -1;
|
||||
|
||||
if (interactive)
|
||||
if (reconnect && action_file && ctrl_ifname) {
|
||||
while (!hostapd_cli_quit) {
|
||||
if (ctrl_conn)
|
||||
hostapd_cli_action(ctrl_conn);
|
||||
os_sleep(1, 0);
|
||||
hostapd_cli_reconnect(ctrl_ifname);
|
||||
}
|
||||
} else if (interactive)
|
||||
hostapd_cli_interactive();
|
||||
else if (action_file)
|
||||
hostapd_cli_action(ctrl_conn);
|
||||
|
|
|
|||
|
|
@ -81,9 +81,6 @@ static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module,
|
|||
case HOSTAPD_MODULE_DRIVER:
|
||||
module_str = "DRIVER";
|
||||
break;
|
||||
case HOSTAPD_MODULE_IAPP:
|
||||
module_str = "IAPP";
|
||||
break;
|
||||
case HOSTAPD_MODULE_MLME:
|
||||
module_str = "MLME";
|
||||
break;
|
||||
|
|
@ -221,7 +218,7 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
|
|||
struct wowlan_triggers *triggs;
|
||||
|
||||
iface->drv_flags = capa.flags;
|
||||
iface->smps_modes = capa.smps_modes;
|
||||
iface->drv_flags2 = capa.flags2;
|
||||
iface->probe_resp_offloads = capa.probe_resp_offloads;
|
||||
/*
|
||||
* Use default extended capa values from per-radio information
|
||||
|
|
@ -263,7 +260,7 @@ hostapd_interface_init(struct hapd_interfaces *interfaces, const char *if_name,
|
|||
struct hostapd_iface *iface;
|
||||
int k;
|
||||
|
||||
wpa_printf(MSG_ERROR, "Configuration file: %s", config_fname);
|
||||
wpa_printf(MSG_DEBUG, "Configuration file: %s", config_fname);
|
||||
iface = hostapd_init(interfaces, config_fname);
|
||||
if (!iface)
|
||||
return NULL;
|
||||
|
|
@ -454,11 +451,12 @@ static int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize,
|
|||
static void show_version(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"hostapd v" VERSION_STR "\n"
|
||||
"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-2019, Jouni Malinen <j@w1.fi> "
|
||||
"and contributors\n");
|
||||
"and contributors\n",
|
||||
VERSION_STR);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -676,7 +674,10 @@ int main(int argc, char *argv[])
|
|||
#endif /* CONFIG_ETH_P_OUI */
|
||||
#ifdef CONFIG_DPP
|
||||
os_memset(&dpp_conf, 0, sizeof(dpp_conf));
|
||||
/* TODO: dpp_conf.msg_ctx? */
|
||||
dpp_conf.cb_ctx = &interfaces;
|
||||
#ifdef CONFIG_DPP2
|
||||
dpp_conf.remove_bi = hostapd_dpp_remove_bi;
|
||||
#endif /* CONFIG_DPP2 */
|
||||
interfaces.dpp = dpp_global_init(&dpp_conf);
|
||||
if (!interfaces.dpp)
|
||||
return -1;
|
||||
|
|
@ -771,7 +772,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
if (log_file)
|
||||
wpa_debug_open_file(log_file);
|
||||
else
|
||||
if (!log_file && !wpa_debug_syslog)
|
||||
wpa_debug_setup_stdout();
|
||||
#ifdef CONFIG_DEBUG_SYSLOG
|
||||
if (wpa_debug_syslog)
|
||||
|
|
@ -905,8 +906,11 @@ int main(int argc, char *argv[])
|
|||
!!(interfaces.iface[i]->drv_flags &
|
||||
WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
|
||||
hostapd_interface_deinit_free(interfaces.iface[i]);
|
||||
interfaces.iface[i] = NULL;
|
||||
}
|
||||
os_free(interfaces.iface);
|
||||
interfaces.iface = NULL;
|
||||
interfaces.count = 0;
|
||||
|
||||
#ifdef CONFIG_DPP
|
||||
dpp_global_deinit(interfaces.dpp);
|
||||
|
|
|
|||
196
contrib/wpa/hostapd/sae_pk_gen.c
Normal file
196
contrib/wpa/hostapd/sae_pk_gen.c
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
* SAE-PK password/modifier generator
|
||||
* Copyright (c) 2020, The Linux Foundation
|
||||
*
|
||||
* 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 "utils/base64.h"
|
||||
#include "crypto/crypto.h"
|
||||
#include "common/sae.h"
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *der = NULL;
|
||||
size_t der_len;
|
||||
struct crypto_ec_key *key = NULL;
|
||||
struct wpabuf *pub = NULL;
|
||||
u8 *data = NULL, *m;
|
||||
size_t data_len;
|
||||
char *b64 = NULL, *pw = NULL, *pos, *src;
|
||||
int sec, j;
|
||||
int ret = -1;
|
||||
u8 hash[SAE_MAX_HASH_LEN];
|
||||
char hash_hex[2 * SAE_MAX_HASH_LEN + 1];
|
||||
u8 pw_base_bin[SAE_MAX_HASH_LEN];
|
||||
u8 *dst;
|
||||
int group;
|
||||
size_t hash_len;
|
||||
unsigned long long i, expected;
|
||||
char m_hex[2 * SAE_PK_M_LEN + 1];
|
||||
u32 sec_1b, val20;
|
||||
|
||||
wpa_debug_level = MSG_INFO;
|
||||
if (os_program_init() < 0)
|
||||
goto fail;
|
||||
|
||||
if (argc != 4) {
|
||||
fprintf(stderr,
|
||||
"usage: sae_pk_gen <DER ECPrivateKey file> <Sec:3|5> <SSID>\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
sec = atoi(argv[2]);
|
||||
if (sec != 3 && sec != 5) {
|
||||
fprintf(stderr,
|
||||
"Invalid Sec value (allowed values: 3 and 5)\n");
|
||||
goto fail;
|
||||
}
|
||||
sec_1b = sec == 3;
|
||||
expected = 1;
|
||||
for (j = 0; j < sec; j++)
|
||||
expected *= 256;
|
||||
|
||||
der = os_readfile(argv[1], &der_len);
|
||||
if (!der) {
|
||||
fprintf(stderr, "Could not read %s: %s\n",
|
||||
argv[1], strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
key = crypto_ec_key_parse_priv((u8 *) der, der_len);
|
||||
if (!key) {
|
||||
fprintf(stderr, "Could not parse ECPrivateKey\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pub = crypto_ec_key_get_subject_public_key(key);
|
||||
if (!pub) {
|
||||
fprintf(stderr, "Failed to build SubjectPublicKey\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
group = crypto_ec_key_group(key);
|
||||
switch (group) {
|
||||
case 19:
|
||||
hash_len = 32;
|
||||
break;
|
||||
case 20:
|
||||
hash_len = 48;
|
||||
break;
|
||||
case 21:
|
||||
hash_len = 64;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unsupported private key group\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
data_len = os_strlen(argv[3]) + SAE_PK_M_LEN + wpabuf_len(pub);
|
||||
data = os_malloc(data_len);
|
||||
if (!data) {
|
||||
fprintf(stderr, "No memory for data buffer\n");
|
||||
goto fail;
|
||||
}
|
||||
os_memcpy(data, argv[3], os_strlen(argv[3]));
|
||||
m = data + os_strlen(argv[3]);
|
||||
if (os_get_random(m, SAE_PK_M_LEN) < 0) {
|
||||
fprintf(stderr, "Could not generate random Modifier M\n");
|
||||
goto fail;
|
||||
}
|
||||
os_memcpy(m + SAE_PK_M_LEN, wpabuf_head(pub), wpabuf_len(pub));
|
||||
|
||||
fprintf(stderr, "Searching for a suitable Modifier M value\n");
|
||||
for (i = 0;; i++) {
|
||||
if (sae_hash(hash_len, data, data_len, hash) < 0) {
|
||||
fprintf(stderr, "Hash failed\n");
|
||||
goto fail;
|
||||
}
|
||||
if (hash[0] == 0 && hash[1] == 0) {
|
||||
if ((hash[2] & 0xf0) == 0)
|
||||
fprintf(stderr, "\r%3.2f%%",
|
||||
100.0 * (double) i / (double) expected);
|
||||
for (j = 2; j < sec; j++) {
|
||||
if (hash[j])
|
||||
break;
|
||||
}
|
||||
if (j == sec)
|
||||
break;
|
||||
}
|
||||
inc_byte_array(m, SAE_PK_M_LEN);
|
||||
}
|
||||
|
||||
if (wpa_snprintf_hex(m_hex, sizeof(m_hex), m, SAE_PK_M_LEN) < 0 ||
|
||||
wpa_snprintf_hex(hash_hex, sizeof(hash_hex), hash, hash_len) < 0)
|
||||
goto fail;
|
||||
fprintf(stderr, "\nFound a valid hash in %llu iterations: %s\n",
|
||||
i + 1, hash_hex);
|
||||
|
||||
b64 = base64_encode(der, der_len, NULL);
|
||||
if (!b64)
|
||||
goto fail;
|
||||
src = pos = b64;
|
||||
while (*src) {
|
||||
if (*src != '\n')
|
||||
*pos++ = *src;
|
||||
src++;
|
||||
}
|
||||
*pos = '\0';
|
||||
|
||||
/* Skip 8*Sec bits and add Sec_1b as the every 20th bit starting with
|
||||
* one. */
|
||||
os_memset(pw_base_bin, 0, sizeof(pw_base_bin));
|
||||
dst = pw_base_bin;
|
||||
for (j = 0; j < 8 * (int) hash_len / 20; j++) {
|
||||
val20 = sae_pk_get_be19(hash + sec);
|
||||
val20 |= sec_1b << 19;
|
||||
sae_pk_buf_shift_left_19(hash + sec, hash_len - sec);
|
||||
|
||||
if (j & 1) {
|
||||
*dst |= (val20 >> 16) & 0x0f;
|
||||
dst++;
|
||||
*dst++ = (val20 >> 8) & 0xff;
|
||||
*dst++ = val20 & 0xff;
|
||||
} else {
|
||||
*dst++ = (val20 >> 12) & 0xff;
|
||||
*dst++ = (val20 >> 4) & 0xff;
|
||||
*dst = (val20 << 4) & 0xf0;
|
||||
}
|
||||
}
|
||||
if (wpa_snprintf_hex(hash_hex, sizeof(hash_hex),
|
||||
pw_base_bin, hash_len - sec) >= 0)
|
||||
fprintf(stderr, "PasswordBase binary data for base32: %s",
|
||||
hash_hex);
|
||||
|
||||
pw = sae_pk_base32_encode(pw_base_bin, 20 * 3 - 5);
|
||||
if (!pw)
|
||||
goto fail;
|
||||
|
||||
printf("# SAE-PK password/M/private key for Sec=%d.\n", sec);
|
||||
printf("sae_password=%s|pk=%s:%s\n", pw, m_hex, b64);
|
||||
printf("# Longer passwords can be used for improved security at the cost of usability:\n");
|
||||
for (j = 4; j <= ((int) hash_len * 8 + 5 - 8 * sec) / 19; j++) {
|
||||
os_free(pw);
|
||||
pw = sae_pk_base32_encode(pw_base_bin, 20 * j - 5);
|
||||
if (pw)
|
||||
printf("# %s\n", pw);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
fail:
|
||||
os_free(der);
|
||||
wpabuf_free(pub);
|
||||
crypto_ec_key_deinit(key);
|
||||
os_free(data);
|
||||
os_free(b64);
|
||||
os_free(pw);
|
||||
|
||||
os_program_deinit();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1,28 +1,6 @@
|
|||
all: hs20-osu-client
|
||||
ALL=hs20-osu-client
|
||||
|
||||
ifndef CC
|
||||
CC=gcc
|
||||
endif
|
||||
|
||||
ifndef LDO
|
||||
LDO=$(CC)
|
||||
endif
|
||||
|
||||
ifeq ($(QUIET), 1)
|
||||
Q=@
|
||||
E=true
|
||||
else
|
||||
Q=@
|
||||
E=echo
|
||||
ifeq ($(V), 1)
|
||||
Q=
|
||||
E=true
|
||||
endif
|
||||
endif
|
||||
|
||||
ifndef CFLAGS
|
||||
CFLAGS = -MMD -O2 -Wall -g
|
||||
endif
|
||||
include ../../src/build.rules
|
||||
|
||||
CFLAGS += -I../../src/utils
|
||||
CFLAGS += -I../../src/common
|
||||
|
|
@ -30,8 +8,17 @@ CFLAGS += -I../../src
|
|||
|
||||
ifndef CONFIG_NO_BROWSER
|
||||
ifndef CONFIG_BROWSER_SYSTEM
|
||||
TEST_WK := $(shell pkg-config --silence-errors --cflags webkitgtk-3.0)
|
||||
ifeq ($(TEST_WK),)
|
||||
# Try webkit2
|
||||
GTKCFLAGS := $(shell pkg-config --cflags gtk+-3.0 webkit2gtk-4.0)
|
||||
GTKLIBS := $(shell pkg-config --libs gtk+-3.0 webkit2gtk-4.0)
|
||||
CFLAGS += -DUSE_WEBKIT2
|
||||
else
|
||||
GTKCFLAGS := $(shell pkg-config --cflags gtk+-3.0 webkitgtk-3.0)
|
||||
GTKLIBS := $(shell pkg-config --libs gtk+-3.0 webkitgtk-3.0)
|
||||
endif
|
||||
|
||||
CFLAGS += $(GTKCFLAGS)
|
||||
LIBS += $(GTKLIBS)
|
||||
endif
|
||||
|
|
@ -84,23 +71,11 @@ CFLAGS += -DEAP_TLS_OPENSSL
|
|||
OBJS += ../../src/crypto/tls_openssl_ocsp.o
|
||||
LIBS += -lssl -lcrypto
|
||||
|
||||
_OBJS_VAR := OBJS
|
||||
include ../../src/objs.mk
|
||||
hs20-osu-client: $(OBJS)
|
||||
$(Q)$(LDO) $(LDFLAGS) -o hs20-osu-client $(OBJS) $(LIBS)
|
||||
@$(E) " LD " $@
|
||||
|
||||
%.o: %.c
|
||||
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
|
||||
@$(E) " CC " $<
|
||||
|
||||
clean:
|
||||
rm -f core *~ *.o *.d hs20-osu-client
|
||||
rm -f ../../src/utils/*.o
|
||||
rm -f ../../src/utils/*.d
|
||||
rm -f ../../src/common/*.o
|
||||
rm -f ../../src/common/*.d
|
||||
rm -f ../../src/crypto/*.o
|
||||
rm -f ../../src/crypto/*.d
|
||||
rm -f ../../src/wps/*.o
|
||||
rm -f ../../src/wps/*.d
|
||||
|
||||
-include $(OBJS:%.o=%.d)
|
||||
clean: common-clean
|
||||
rm -f core *~
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ int est_load_cacerts(struct hs20_osu_client *ctx, const char *url)
|
|||
return -1;
|
||||
}
|
||||
|
||||
pkcs7 = base64_decode((unsigned char *) resp, resp_len, &pkcs7_len);
|
||||
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);
|
||||
|
|
@ -639,8 +639,7 @@ int est_build_csr(struct hs20_osu_client *ctx, const char *url)
|
|||
return -1;
|
||||
}
|
||||
|
||||
attrs = base64_decode((unsigned char *) resp, resp_len,
|
||||
&attrs_len);
|
||||
attrs = base64_decode(resp, resp_len, &attrs_len);
|
||||
os_free(resp);
|
||||
|
||||
if (attrs == NULL) {
|
||||
|
|
@ -734,7 +733,7 @@ int est_simple_enroll(struct hs20_osu_client *ctx, const char *url,
|
|||
}
|
||||
wpa_printf(MSG_DEBUG, "EST simpleenroll response: %s", resp);
|
||||
|
||||
pkcs7 = base64_decode((unsigned char *) resp, resp_len, &pkcs7_len);
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -407,7 +407,7 @@ static int oma_dm_exec_browser(struct hs20_osu_client *ctx, xml_node_t *exec)
|
|||
wpa_printf(MSG_INFO, "Data: %s", data);
|
||||
wpa_printf(MSG_INFO, "Launch browser to URI '%s'", data);
|
||||
write_summary(ctx, "Launch browser to URI '%s'", data);
|
||||
res = hs20_web_browser(data);
|
||||
res = hs20_web_browser(data, 1);
|
||||
xml_node_get_text_free(ctx->xml, data);
|
||||
if (res > 0) {
|
||||
wpa_printf(MSG_INFO, "User response in browser completed successfully");
|
||||
|
|
|
|||
|
|
@ -310,7 +310,7 @@ static int download_cert(struct hs20_osu_client *ctx, xml_node_t *params,
|
|||
size_t len;
|
||||
u8 digest1[SHA256_MAC_LEN], digest2[SHA256_MAC_LEN];
|
||||
int res;
|
||||
unsigned char *b64;
|
||||
char *b64;
|
||||
FILE *f;
|
||||
|
||||
url_node = get_node(ctx->xml, params, "CertURL");
|
||||
|
|
@ -364,7 +364,7 @@ static int download_cert(struct hs20_osu_client *ctx, xml_node_t *params,
|
|||
return -1;
|
||||
}
|
||||
|
||||
b64 = base64_encode((unsigned char *) cert, len, NULL);
|
||||
b64 = base64_encode(cert, len, NULL);
|
||||
os_free(cert);
|
||||
if (b64 == NULL)
|
||||
return -1;
|
||||
|
|
@ -2233,7 +2233,7 @@ static int osu_connect(struct hs20_osu_client *ctx, const char *bssid,
|
|||
wpa_ctrl_close(mon);
|
||||
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_INFO, "Could not connect");
|
||||
wpa_printf(MSG_INFO, "Could not connect to OSU network");
|
||||
write_summary(ctx, "Could not connect to OSU network");
|
||||
wpa_printf(MSG_INFO, "Remove OSU network connection");
|
||||
snprintf(buf, sizeof(buf), "REMOVE_NETWORK %d", id);
|
||||
|
|
@ -2406,7 +2406,7 @@ static int cmd_osu_select(struct hs20_osu_client *ctx, const char *dir,
|
|||
|
||||
snprintf(fname, sizeof(fname), "file://%s/osu-providers.html", dir);
|
||||
write_summary(ctx, "Start web browser with OSU provider selection page");
|
||||
ret = hs20_web_browser(fname);
|
||||
ret = hs20_web_browser(fname, 0);
|
||||
|
||||
selected:
|
||||
if (ret > 0 && (size_t) ret <= osu_count) {
|
||||
|
|
@ -2907,7 +2907,7 @@ static char * get_hostname(const char *url)
|
|||
static int osu_cert_cb(void *_ctx, struct http_cert *cert)
|
||||
{
|
||||
struct hs20_osu_client *ctx = _ctx;
|
||||
unsigned int i, j;
|
||||
size_t i, j;
|
||||
int found;
|
||||
char *host = NULL;
|
||||
|
||||
|
|
@ -3002,7 +3002,7 @@ static int osu_cert_cb(void *_ctx, struct http_cert *cert)
|
|||
size_t name_len = os_strlen(name);
|
||||
|
||||
wpa_printf(MSG_INFO,
|
||||
"[%i] Looking for icon file name '%s' match",
|
||||
"[%zu] Looking for icon file name '%s' match",
|
||||
j, name);
|
||||
for (i = 0; i < cert->num_logo; i++) {
|
||||
struct http_logo *logo = &cert->logo[i];
|
||||
|
|
@ -3010,7 +3010,7 @@ static int osu_cert_cb(void *_ctx, struct http_cert *cert)
|
|||
char *pos;
|
||||
|
||||
wpa_printf(MSG_INFO,
|
||||
"[%i] Comparing to '%s' uri_len=%d name_len=%d",
|
||||
"[%zu] Comparing to '%s' uri_len=%d name_len=%d",
|
||||
i, logo->uri, (int) uri_len, (int) name_len);
|
||||
if (uri_len < 1 + name_len) {
|
||||
wpa_printf(MSG_INFO, "URI Length is too short");
|
||||
|
|
@ -3044,7 +3044,7 @@ static int osu_cert_cb(void *_ctx, struct http_cert *cert)
|
|||
|
||||
if (logo->hash_len != 32) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"[%i][%i] Icon hash length invalid (should be 32): %d",
|
||||
"[%zu][%zu] Icon hash length invalid (should be 32): %d",
|
||||
j, i, (int) logo->hash_len);
|
||||
continue;
|
||||
}
|
||||
|
|
@ -3054,7 +3054,7 @@ static int osu_cert_cb(void *_ctx, struct http_cert *cert)
|
|||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"[%u][%u] Icon hash did not match", j, i);
|
||||
"[%zu][%zu] Icon hash did not match", j, i);
|
||||
wpa_hexdump_ascii(MSG_DEBUG, "logo->hash",
|
||||
logo->hash, 32);
|
||||
wpa_hexdump_ascii(MSG_DEBUG, "ctx->icon_hash[j]",
|
||||
|
|
@ -3152,7 +3152,7 @@ static void check_workarounds(struct hs20_osu_client *ctx)
|
|||
|
||||
static void usage(void)
|
||||
{
|
||||
printf("usage: hs20-osu-client [-dddqqKt] [-S<station ifname>] \\\n"
|
||||
printf("usage: hs20-osu-client [-dddqqKtT] [-S<station ifname>] \\\n"
|
||||
" [-w<wpa_supplicant ctrl_iface dir>] "
|
||||
"[-r<result file>] [-f<debug file>] \\\n"
|
||||
" [-s<summary file>] \\\n"
|
||||
|
|
@ -3198,7 +3198,7 @@ int main(int argc, char *argv[])
|
|||
return -1;
|
||||
|
||||
for (;;) {
|
||||
c = getopt(argc, argv, "df:hKNo:O:qr:s:S:tw:x:");
|
||||
c = getopt(argc, argv, "df:hKNo:O:qr:s:S:tTw:x:");
|
||||
if (c < 0)
|
||||
break;
|
||||
switch (c) {
|
||||
|
|
@ -3236,6 +3236,9 @@ int main(int argc, char *argv[])
|
|||
case 't':
|
||||
wpa_debug_timestamp++;
|
||||
break;
|
||||
case 'T':
|
||||
ctx.ignore_tls = 1;
|
||||
break;
|
||||
case 'w':
|
||||
wpas_ctrl_path = optarg;
|
||||
break;
|
||||
|
|
@ -3403,7 +3406,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
wpa_printf(MSG_INFO, "Launch web browser to URL %s",
|
||||
argv[optind + 1]);
|
||||
ret = hs20_web_browser(argv[optind + 1]);
|
||||
ret = hs20_web_browser(argv[optind + 1], ctx.ignore_tls);
|
||||
wpa_printf(MSG_INFO, "Web browser result: %d", ret);
|
||||
} else if (strcmp(argv[optind], "parse_cert") == 0) {
|
||||
if (argc - optind < 2) {
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@ struct hs20_osu_client {
|
|||
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 */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -547,7 +547,7 @@ static int hs20_spp_exec(struct hs20_osu_client *ctx, xml_node_t *exec,
|
|||
}
|
||||
wpa_printf(MSG_INFO, "Launch browser to URI '%s'", uri);
|
||||
write_summary(ctx, "Launch browser to URI '%s'", uri);
|
||||
res = hs20_web_browser(uri);
|
||||
res = hs20_web_browser(uri, 1);
|
||||
xml_node_get_text_free(ctx->xml, uri);
|
||||
if (res > 0) {
|
||||
wpa_printf(MSG_INFO, "User response in browser completed successfully - sessionid='%s'",
|
||||
|
|
|
|||
42
contrib/wpa/hs20/server/Makefile
Normal file
42
contrib/wpa/hs20/server/Makefile
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
ALL=hs20_spp_server
|
||||
|
||||
include ../../src/build.rules
|
||||
|
||||
CFLAGS += -I../../src
|
||||
CFLAGS += -I../../src/utils
|
||||
CFLAGS += -I../../src/crypto
|
||||
|
||||
LIBS += -lsqlite3
|
||||
|
||||
# Using glibc < 2.17 requires -lrt for clock_gettime()
|
||||
LIBS += -lrt
|
||||
|
||||
ifndef CONFIG_NO_GITVER
|
||||
# Add VERSION_STR postfix for builds from a git repository
|
||||
ifeq ($(wildcard ../../.git),../../.git)
|
||||
GITVER := $(shell git describe --dirty=+)
|
||||
ifneq ($(GITVER),)
|
||||
CFLAGS += -DGIT_VERSION_STR_POSTFIX=\"-$(GITVER)\"
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
OBJS=spp_server.o
|
||||
OBJS += hs20_spp_server.o
|
||||
OBJS += ../../src/utils/xml-utils.o
|
||||
OBJS += ../../src/utils/base64.o
|
||||
OBJS += ../../src/utils/common.o
|
||||
OBJS += ../../src/utils/os_unix.o
|
||||
OBJS += ../../src/utils/wpa_debug.o
|
||||
OBJS += ../../src/crypto/md5-internal.o
|
||||
CFLAGS += $(shell xml2-config --cflags)
|
||||
LIBS += $(shell xml2-config --libs)
|
||||
OBJS += ../../src/utils/xml_libxml2.o
|
||||
|
||||
_OBJS_VAR := OBJS
|
||||
include ../../src/objs.mk
|
||||
hs20_spp_server: $(OBJS)
|
||||
$(LDO) $(LDFLAGS) -o hs20_spp_server $(OBJS) $(LIBS)
|
||||
|
||||
clean: common-clean
|
||||
rm -f core *~
|
||||
13
contrib/wpa/hs20/server/ca/clean.sh
Executable file
13
contrib/wpa/hs20/server/ca/clean.sh
Executable file
|
|
@ -0,0 +1,13 @@
|
|||
#!/bin/sh
|
||||
|
||||
for i in server-client server server-revoked user ocsp; do
|
||||
rm -f $i.csr $i.key $i.pem
|
||||
done
|
||||
|
||||
rm -f openssl.cnf.tmp
|
||||
if [ -d demoCA ]; then
|
||||
rm -r demoCA
|
||||
fi
|
||||
rm -f ca.pem logo.asn1 logo.der server.der ocsp-server-cache.der
|
||||
rm -f my-openssl.cnf my-openssl-root.cnf
|
||||
#rm -r rootCA
|
||||
17
contrib/wpa/hs20/server/ca/est-csrattrs.cnf
Normal file
17
contrib/wpa/hs20/server/ca/est-csrattrs.cnf
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
asn1 = SEQUENCE:attrs
|
||||
|
||||
[attrs]
|
||||
#oid1 = OID:challengePassword
|
||||
attr1 = SEQUENCE:extreq
|
||||
oid2 = OID:sha256WithRSAEncryption
|
||||
|
||||
[extreq]
|
||||
oid = OID:extensionRequest
|
||||
vals = SET:extreqvals
|
||||
|
||||
[extreqvals]
|
||||
|
||||
oid1 = OID:macAddress
|
||||
#oid2 = OID:imei
|
||||
#oid3 = OID:meid
|
||||
#oid4 = OID:DevId
|
||||
4
contrib/wpa/hs20/server/ca/est-csrattrs.sh
Executable file
4
contrib/wpa/hs20/server/ca/est-csrattrs.sh
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
|
||||
openssl asn1parse -genconf est-csrattrs.cnf -out est-csrattrs.der -oid hs20.oid
|
||||
base64 est-csrattrs.der > est-attrs.b64
|
||||
7
contrib/wpa/hs20/server/ca/hs20.oid
Normal file
7
contrib/wpa/hs20/server/ca/hs20.oid
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
1.3.6.1.1.1.1.22 macAddress
|
||||
1.2.840.113549.1.9.14 extensionRequest
|
||||
1.3.6.1.4.1.40808.1.1.1 id-wfa-hotspot-friendlyName
|
||||
1.3.6.1.4.1.40808.1.1.2 id-kp-HS2.0Auth
|
||||
1.3.6.1.4.1.40808.1.1.3 imei
|
||||
1.3.6.1.4.1.40808.1.1.4 meid
|
||||
1.3.6.1.4.1.40808.1.1.5 DevId
|
||||
11
contrib/wpa/hs20/server/ca/ocsp-req.sh
Executable file
11
contrib/wpa/hs20/server/ca/ocsp-req.sh
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/sh
|
||||
|
||||
for i in *.pem; do
|
||||
echo "===[ $i ]==================="
|
||||
openssl ocsp -text -CAfile ca.pem -verify_other demoCA/cacert.pem -trust_other -issuer demoCA/cacert.pem -cert $i -url http://localhost:8888/
|
||||
|
||||
# openssl ocsp -text -CAfile rootCA/cacert.pem -issuer demoCA/cacert.pem -cert $i -url http://localhost:8888/
|
||||
|
||||
# openssl ocsp -text -CAfile rootCA/cacert.pem -verify_other demoCA/cacert.pem -trust_other -issuer demoCA/cacert.pem -cert $i -url http://localhost:8888/
|
||||
# openssl ocsp -text -CAfile rootCA/cacert.pem -VAfile ca.pem -trust_other -issuer demoCA/cacert.pem -cert $i -url http://localhost:8888/
|
||||
done
|
||||
3
contrib/wpa/hs20/server/ca/ocsp-responder-ica.sh
Executable file
3
contrib/wpa/hs20/server/ca/ocsp-responder-ica.sh
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
openssl ocsp -index demoCA/index.txt -port 8888 -nmin 5 -rsigner demoCA/cacert.pem -rkey demoCA/private/cakey-plain.pem -CA demoCA/cacert.pem -resp_no_certs -text
|
||||
3
contrib/wpa/hs20/server/ca/ocsp-responder.sh
Executable file
3
contrib/wpa/hs20/server/ca/ocsp-responder.sh
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
openssl ocsp -index demoCA/index.txt -port 8888 -nmin 5 -rsigner ocsp.pem -rkey ocsp.key -CA demoCA/cacert.pem -text -ignore_err
|
||||
11
contrib/wpa/hs20/server/ca/ocsp-update-cache.sh
Executable file
11
contrib/wpa/hs20/server/ca/ocsp-update-cache.sh
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/sh
|
||||
|
||||
# NOTE: You may need to replace 'localhost' with your OCSP server hostname.
|
||||
openssl ocsp \
|
||||
-no_nonce \
|
||||
-CAfile ca.pem \
|
||||
-verify_other demoCA/cacert.pem \
|
||||
-issuer demoCA/cacert.pem \
|
||||
-cert server.pem \
|
||||
-url http://localhost:8888/ \
|
||||
-respout ocsp-server-cache.der
|
||||
125
contrib/wpa/hs20/server/ca/openssl-root.cnf
Normal file
125
contrib/wpa/hs20/server/ca/openssl-root.cnf
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
# OpenSSL configuration file for Hotspot 2.0 PKI (Root CA)
|
||||
|
||||
HOME = .
|
||||
RANDFILE = $ENV::HOME/.rnd
|
||||
oid_section = new_oids
|
||||
|
||||
[ new_oids ]
|
||||
|
||||
#logotypeoid=1.3.6.1.5.5.7.1.12
|
||||
|
||||
####################################################################
|
||||
[ ca ]
|
||||
default_ca = CA_default # The default ca section
|
||||
|
||||
####################################################################
|
||||
[ CA_default ]
|
||||
|
||||
dir = ./rootCA # Where everything is kept
|
||||
certs = $dir/certs # Where the issued certs are kept
|
||||
crl_dir = $dir/crl # Where the issued crl are kept
|
||||
database = $dir/index.txt # database index file.
|
||||
#unique_subject = no # Set to 'no' to allow creation of
|
||||
# several certificates with same subject
|
||||
new_certs_dir = $dir/newcerts # default place for new certs.
|
||||
|
||||
certificate = $dir/cacert.pem # The CA certificate
|
||||
serial = $dir/serial # The current serial number
|
||||
crlnumber = $dir/crlnumber # the current crl number
|
||||
# must be commented out to leave a V1 CRL
|
||||
crl = $dir/crl.pem # The current CRL
|
||||
private_key = $dir/private/cakey.pem# The private key
|
||||
RANDFILE = $dir/private/.rand # private random number file
|
||||
|
||||
x509_extensions = usr_cert # The extentions to add to the cert
|
||||
|
||||
name_opt = ca_default # Subject Name options
|
||||
cert_opt = ca_default # Certificate field options
|
||||
|
||||
default_days = 365 # how long to certify for
|
||||
default_crl_days= 30 # how long before next CRL
|
||||
default_md = default # use public key default MD
|
||||
preserve = no # keep passed DN ordering
|
||||
|
||||
policy = policy_match
|
||||
|
||||
# For the CA policy
|
||||
[ policy_match ]
|
||||
countryName = match
|
||||
stateOrProvinceName = optional
|
||||
organizationName = match
|
||||
organizationalUnitName = optional
|
||||
commonName = supplied
|
||||
emailAddress = optional
|
||||
|
||||
[ policy_anything ]
|
||||
countryName = optional
|
||||
stateOrProvinceName = optional
|
||||
localityName = optional
|
||||
organizationName = optional
|
||||
organizationalUnitName = optional
|
||||
commonName = supplied
|
||||
emailAddress = optional
|
||||
|
||||
####################################################################
|
||||
[ req ]
|
||||
default_bits = 2048
|
||||
default_keyfile = privkey.pem
|
||||
distinguished_name = req_distinguished_name
|
||||
attributes = req_attributes
|
||||
x509_extensions = v3_ca # The extentions to add to the self signed cert
|
||||
|
||||
input_password = @PASSWORD@
|
||||
output_password = @PASSWORD@
|
||||
|
||||
string_mask = utf8only
|
||||
|
||||
[ req_distinguished_name ]
|
||||
countryName = Country Name (2 letter code)
|
||||
countryName_default = US
|
||||
countryName_min = 2
|
||||
countryName_max = 2
|
||||
|
||||
localityName = Locality Name (eg, city)
|
||||
localityName_default = Tuusula
|
||||
|
||||
0.organizationName = Organization Name (eg, company)
|
||||
0.organizationName_default = WFA Hotspot 2.0
|
||||
|
||||
##organizationalUnitName = Organizational Unit Name (eg, section)
|
||||
#organizationalUnitName_default =
|
||||
#@OU@
|
||||
|
||||
commonName = Common Name (e.g. server FQDN or YOUR name)
|
||||
#@CN@
|
||||
commonName_max = 64
|
||||
|
||||
emailAddress = Email Address
|
||||
emailAddress_max = 64
|
||||
|
||||
[ req_attributes ]
|
||||
|
||||
[ v3_req ]
|
||||
|
||||
# Extensions to add to a certificate request
|
||||
basicConstraints = CA:FALSE
|
||||
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||
subjectAltName=DNS:example.com,DNS:another.example.com
|
||||
|
||||
[ v3_ca ]
|
||||
|
||||
# Hotspot 2.0 PKI requirements
|
||||
subjectKeyIdentifier=hash
|
||||
basicConstraints = critical,CA:true
|
||||
keyUsage = critical, cRLSign, keyCertSign
|
||||
|
||||
[ crl_ext ]
|
||||
|
||||
# issuerAltName=issuer:copy
|
||||
authorityKeyIdentifier=keyid:always
|
||||
|
||||
[ v3_OCSP ]
|
||||
|
||||
basicConstraints = CA:FALSE
|
||||
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||
extendedKeyUsage = OCSPSigning
|
||||
200
contrib/wpa/hs20/server/ca/openssl.cnf
Normal file
200
contrib/wpa/hs20/server/ca/openssl.cnf
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
# OpenSSL configuration file for Hotspot 2.0 PKI (Intermediate CA)
|
||||
|
||||
HOME = .
|
||||
RANDFILE = $ENV::HOME/.rnd
|
||||
oid_section = new_oids
|
||||
|
||||
[ new_oids ]
|
||||
|
||||
#logotypeoid=1.3.6.1.5.5.7.1.12
|
||||
|
||||
####################################################################
|
||||
[ ca ]
|
||||
default_ca = CA_default # The default ca section
|
||||
|
||||
####################################################################
|
||||
[ CA_default ]
|
||||
|
||||
dir = ./demoCA # Where everything is kept
|
||||
certs = $dir/certs # Where the issued certs are kept
|
||||
crl_dir = $dir/crl # Where the issued crl are kept
|
||||
database = $dir/index.txt # database index file.
|
||||
#unique_subject = no # Set to 'no' to allow creation of
|
||||
# several certificates with same subject
|
||||
new_certs_dir = $dir/newcerts # default place for new certs.
|
||||
|
||||
certificate = $dir/cacert.pem # The CA certificate
|
||||
serial = $dir/serial # The current serial number
|
||||
crlnumber = $dir/crlnumber # the current crl number
|
||||
# must be commented out to leave a V1 CRL
|
||||
crl = $dir/crl.pem # The current CRL
|
||||
private_key = $dir/private/cakey.pem# The private key
|
||||
RANDFILE = $dir/private/.rand # private random number file
|
||||
|
||||
x509_extensions = ext_client # The extentions to add to the cert
|
||||
|
||||
name_opt = ca_default # Subject Name options
|
||||
cert_opt = ca_default # Certificate field options
|
||||
|
||||
# Extension copying option: use with caution.
|
||||
copy_extensions = copy
|
||||
|
||||
default_days = 365 # how long to certify for
|
||||
default_crl_days= 30 # how long before next CRL
|
||||
default_md = default # use public key default MD
|
||||
preserve = no # keep passed DN ordering
|
||||
|
||||
policy = policy_match
|
||||
|
||||
# For the CA policy
|
||||
[ policy_match ]
|
||||
countryName = supplied
|
||||
stateOrProvinceName = optional
|
||||
organizationName = supplied
|
||||
organizationalUnitName = optional
|
||||
commonName = supplied
|
||||
emailAddress = optional
|
||||
|
||||
[ policy_osu_server ]
|
||||
countryName = match
|
||||
stateOrProvinceName = optional
|
||||
organizationName = match
|
||||
organizationalUnitName = supplied
|
||||
commonName = supplied
|
||||
emailAddress = optional
|
||||
|
||||
[ policy_anything ]
|
||||
countryName = optional
|
||||
stateOrProvinceName = optional
|
||||
localityName = optional
|
||||
organizationName = optional
|
||||
organizationalUnitName = optional
|
||||
commonName = supplied
|
||||
emailAddress = optional
|
||||
|
||||
####################################################################
|
||||
[ req ]
|
||||
default_bits = 2048
|
||||
default_keyfile = privkey.pem
|
||||
distinguished_name = req_distinguished_name
|
||||
attributes = req_attributes
|
||||
x509_extensions = v3_ca # The extentions to add to the self signed cert
|
||||
|
||||
input_password = @PASSWORD@
|
||||
output_password = @PASSWORD@
|
||||
|
||||
string_mask = utf8only
|
||||
|
||||
[ req_distinguished_name ]
|
||||
countryName = Country Name (2 letter code)
|
||||
countryName_default = FI
|
||||
countryName_min = 2
|
||||
countryName_max = 2
|
||||
|
||||
localityName = Locality Name (eg, city)
|
||||
localityName_default = Tuusula
|
||||
|
||||
0.organizationName = Organization Name (eg, company)
|
||||
0.organizationName_default = @DOMAIN@
|
||||
|
||||
##organizationalUnitName = Organizational Unit Name (eg, section)
|
||||
#organizationalUnitName_default =
|
||||
#@OU@
|
||||
|
||||
commonName = Common Name (e.g. server FQDN or YOUR name)
|
||||
#@CN@
|
||||
commonName_max = 64
|
||||
|
||||
emailAddress = Email Address
|
||||
emailAddress_max = 64
|
||||
|
||||
[ req_attributes ]
|
||||
|
||||
[ v3_ca ]
|
||||
|
||||
# Hotspot 2.0 PKI requirements
|
||||
subjectKeyIdentifier=hash
|
||||
authorityKeyIdentifier=keyid:always,issuer
|
||||
basicConstraints = critical, CA:true, pathlen:0
|
||||
keyUsage = critical, cRLSign, keyCertSign
|
||||
authorityInfoAccess = OCSP;URI:@OCSP_URI@
|
||||
# For SP intermediate CA
|
||||
#subjectAltName=critical,otherName:1.3.6.1.4.1.40808.1.1.1;UTF8String:engExample OSU
|
||||
#nameConstraints=permitted;DNS:.@DOMAIN@
|
||||
#1.3.6.1.5.5.7.1.12=ASN1:SEQUENCE:LogotypeExtn
|
||||
|
||||
[ v3_osu_server ]
|
||||
|
||||
basicConstraints = critical, CA:true, pathlen:0
|
||||
keyUsage = critical, keyEncipherment
|
||||
#@ALTNAME@
|
||||
|
||||
#logotypeoid=ASN1:SEQUENCE:LogotypeExtn
|
||||
1.3.6.1.5.5.7.1.12=ASN1:SEQUENCE:LogotypeExtn
|
||||
[LogotypeExtn]
|
||||
communityLogos=EXP:0,SEQUENCE:LogotypeInfo
|
||||
[LogotypeInfo]
|
||||
# note: implicit tag converted to explicit for CHOICE
|
||||
direct=EXP:0,SEQUENCE:LogotypeData
|
||||
[LogotypeData]
|
||||
image=SEQUENCE:LogotypeImage
|
||||
[LogotypeImage]
|
||||
imageDetails=SEQUENCE:LogotypeDetails
|
||||
imageInfo=SEQUENCE:LogotypeImageInfo
|
||||
[LogotypeDetails]
|
||||
mediaType=IA5STRING:image/png
|
||||
logotypeHash=SEQUENCE:HashAlgAndValues
|
||||
logotypeURI=SEQUENCE:URI
|
||||
[HashAlgAndValues]
|
||||
value1=SEQUENCE:HashAlgAndValueSHA256
|
||||
#value2=SEQUENCE:HashAlgAndValueSHA1
|
||||
[HashAlgAndValueSHA256]
|
||||
hashAlg=SEQUENCE:sha256_alg
|
||||
hashValue=FORMAT:HEX,OCTETSTRING:@LOGO_HASH256@
|
||||
[HashAlgAndValueSHA1]
|
||||
hashAlg=SEQUENCE:sha1_alg
|
||||
hashValue=FORMAT:HEX,OCTETSTRING:@LOGO_HASH1@
|
||||
[sha256_alg]
|
||||
algorithm=OID:sha256
|
||||
[sha1_alg]
|
||||
algorithm=OID:sha1
|
||||
[URI]
|
||||
uri=IA5STRING:@LOGO_URI@
|
||||
[LogotypeImageInfo]
|
||||
# default value color(1), component optional
|
||||
#type=IMP:0,INTEGER:1
|
||||
fileSize=INTEGER:7549
|
||||
xSize=INTEGER:128
|
||||
ySize=INTEGER:80
|
||||
language=IMP:4,IA5STRING:zxx
|
||||
|
||||
[ crl_ext ]
|
||||
|
||||
# issuerAltName=issuer:copy
|
||||
authorityKeyIdentifier=keyid:always
|
||||
|
||||
[ v3_OCSP ]
|
||||
|
||||
basicConstraints = CA:FALSE
|
||||
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||
extendedKeyUsage = OCSPSigning
|
||||
|
||||
[ ext_client ]
|
||||
|
||||
basicConstraints=CA:FALSE
|
||||
subjectKeyIdentifier=hash
|
||||
authorityKeyIdentifier=keyid,issuer
|
||||
authorityInfoAccess = OCSP;URI:@OCSP_URI@
|
||||
#@ALTNAME@
|
||||
extendedKeyUsage = clientAuth
|
||||
|
||||
[ ext_server ]
|
||||
|
||||
# Hotspot 2.0 PKI requirements
|
||||
basicConstraints=critical, CA:FALSE
|
||||
subjectKeyIdentifier=hash
|
||||
authorityKeyIdentifier=keyid,issuer
|
||||
authorityInfoAccess = OCSP;URI:@OCSP_URI@
|
||||
#@ALTNAME@
|
||||
extendedKeyUsage = critical, serverAuth
|
||||
keyUsage = critical, keyEncipherment
|
||||
209
contrib/wpa/hs20/server/ca/setup.sh
Executable file
209
contrib/wpa/hs20/server/ca/setup.sh
Executable file
|
|
@ -0,0 +1,209 @@
|
|||
#!/bin/sh
|
||||
|
||||
if [ -z "$OPENSSL" ]; then
|
||||
OPENSSL=openssl
|
||||
fi
|
||||
export OPENSSL_CONF=$PWD/openssl.cnf
|
||||
PASS=whatever
|
||||
if [ -z "$DOMAIN" ]; then
|
||||
DOMAIN=w1.fi
|
||||
fi
|
||||
COMPANY=w1.fi
|
||||
OPER_ENG="engw1.fi TESTING USE"
|
||||
OPER_FI="finw1.fi TESTIKÄYTTÖ"
|
||||
CNR="Hotspot 2.0 Trust Root CA - 99"
|
||||
CNO="ocsp.$DOMAIN"
|
||||
CNV="osu-revoked.$DOMAIN"
|
||||
CNOC="osu-client.$DOMAIN"
|
||||
OSU_SERVER_HOSTNAME="osu.$DOMAIN"
|
||||
DEBUG=0
|
||||
OCSP_URI="http://$CNO:8888/"
|
||||
LOGO_URI="http://osu.w1.fi/w1fi_logo.png"
|
||||
LOGO_HASH256="4532f7ec36424381617c03c6ce87b55a51d6e7177ffafda243cebf280a68954d"
|
||||
LOGO_HASH1="5e1d5085676eede6b02da14d31c523ec20ffba0b"
|
||||
|
||||
# Command line overrides
|
||||
USAGE=$( cat <<EOF
|
||||
Usage:\n
|
||||
# -c: Company name, used to generate Subject name CN for Intermediate CA\n
|
||||
# -C: Subject name CN of the Root CA ($CNR)\n
|
||||
# -D: Enable debugging (set -x, etc)\n
|
||||
# -g: Logo sha1 hash ($LOGO_HASH1)\n
|
||||
# -G: Logo sha256 hash ($LOGO_HASH256)\n
|
||||
# -h: Show this help message\n
|
||||
# -l: Logo URI ($LOGO_URI)\n
|
||||
# -m: Domain ($DOMAIN)\n
|
||||
# -o: Subject name CN for OSU-Client Server ($CNOC)\n
|
||||
# -O: Subject name CN for OCSP Server ($CNO)\n
|
||||
# -p: passphrase for private keys ($PASS)\n
|
||||
# -r: Operator-english ($OPER_ENG)\n
|
||||
# -R: Operator-finish ($OPER_FI)\n
|
||||
# -S: OSU Server name ($OSU_SERVER_HOSTNAME)\n
|
||||
# -u: OCSP-URI ($OCSP_URI)\n
|
||||
# -V: Subject name CN for OSU-Revoked Server ($CNV)\n
|
||||
EOF
|
||||
)
|
||||
|
||||
while getopts "c:C:Dg:G:l:m:o:O:p:r:R:S:u:V:h" flag
|
||||
do
|
||||
case $flag in
|
||||
c) COMPANY=$OPTARG;;
|
||||
C) CNR=$OPTARG;;
|
||||
D) DEBUG=1;;
|
||||
g) LOGO_HASH1=$OPTARG;;
|
||||
G) LOGO_HASH256=$OPTARG;;
|
||||
h) echo -e $USAGE; exit 0;;
|
||||
l) LOGO_URI=$OPTARG;;
|
||||
m) DOMAIN=$OPTARG;;
|
||||
o) CNOC=$OPTARG;;
|
||||
O) CNO=$OPTARG;;
|
||||
p) PASS=$OPTARG;;
|
||||
r) OPER_ENG=$OPTARG;;
|
||||
R) OPER_FI=$OPTARG;;
|
||||
S) OSU_SERVER_HOSTNAME=$OPTARG;;
|
||||
u) OCSP_URI=$OPTARG;;
|
||||
V) CNV=$OPTARG;;
|
||||
*) echo "Unknown flag: $flag"; echo -e $USAGE; exit 1;;
|
||||
esac
|
||||
done
|
||||
|
||||
fail()
|
||||
{
|
||||
echo "$*"
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo
|
||||
echo "---[ Root CA ]----------------------------------------------------------"
|
||||
echo
|
||||
|
||||
if [ $DEBUG = 1 ]
|
||||
then
|
||||
set -x
|
||||
fi
|
||||
|
||||
# Set the passphrase and some other common config accordingly.
|
||||
cat openssl-root.cnf | sed "s/@PASSWORD@/$PASS/" \
|
||||
> my-openssl-root.cnf
|
||||
|
||||
cat openssl.cnf | sed "s/@PASSWORD@/$PASS/" |
|
||||
sed "s,@OCSP_URI@,$OCSP_URI," |
|
||||
sed "s,@LOGO_URI@,$LOGO_URI," |
|
||||
sed "s,@LOGO_HASH1@,$LOGO_HASH1," |
|
||||
sed "s,@LOGO_HASH256@,$LOGO_HASH256," |
|
||||
sed "s/@DOMAIN@/$DOMAIN/" \
|
||||
> my-openssl.cnf
|
||||
|
||||
|
||||
cat my-openssl-root.cnf | sed "s/#@CN@/commonName_default = $CNR/" > openssl.cnf.tmp
|
||||
mkdir -p rootCA/certs rootCA/crl rootCA/newcerts rootCA/private
|
||||
touch rootCA/index.txt
|
||||
if [ -e rootCA/private/cakey.pem ]; then
|
||||
echo " * Use existing Root CA"
|
||||
else
|
||||
echo " * Generate Root CA private key"
|
||||
$OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:4096 -keyout rootCA/private/cakey.pem -out rootCA/careq.pem || fail "Failed to generate Root CA private key"
|
||||
echo " * Sign Root CA certificate"
|
||||
$OPENSSL ca -config openssl.cnf.tmp -md sha256 -create_serial -out rootCA/cacert.pem -days 10957 -batch -keyfile rootCA/private/cakey.pem -passin pass:$PASS -selfsign -extensions v3_ca -outdir rootCA/newcerts -infiles rootCA/careq.pem || fail "Failed to sign Root CA certificate"
|
||||
$OPENSSL x509 -in rootCA/cacert.pem -out rootCA/cacert.der -outform DER || fail "Failed to create rootCA DER"
|
||||
sha256sum rootCA/cacert.der > rootCA/cacert.fingerprint || fail "Failed to create rootCA fingerprint"
|
||||
fi
|
||||
if [ ! -e rootCA/crlnumber ]; then
|
||||
echo 00 > rootCA/crlnumber
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "---[ Intermediate CA ]--------------------------------------------------"
|
||||
echo
|
||||
|
||||
cat my-openssl.cnf | sed "s/#@CN@/commonName_default = $COMPANY Hotspot 2.0 Intermediate CA/" > openssl.cnf.tmp
|
||||
mkdir -p demoCA/certs demoCA/crl demoCA/newcerts demoCA/private
|
||||
touch demoCA/index.txt
|
||||
if [ -e demoCA/private/cakey.pem ]; then
|
||||
echo " * Use existing Intermediate CA"
|
||||
else
|
||||
echo " * Generate Intermediate CA private key"
|
||||
$OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:2048 -keyout demoCA/private/cakey.pem -out demoCA/careq.pem || fail "Failed to generate Intermediate CA private key"
|
||||
echo " * Sign Intermediate CA certificate"
|
||||
$OPENSSL ca -config openssl.cnf.tmp -md sha256 -create_serial -out demoCA/cacert.pem -days 3652 -batch -keyfile rootCA/private/cakey.pem -cert rootCA/cacert.pem -passin pass:$PASS -extensions v3_ca -infiles demoCA/careq.pem || fail "Failed to sign Intermediate CA certificate"
|
||||
# horrible from security view point, but for testing purposes since OCSP responder does not seem to support -passin
|
||||
openssl rsa -in demoCA/private/cakey.pem -out demoCA/private/cakey-plain.pem -passin pass:$PASS
|
||||
$OPENSSL x509 -in demoCA/cacert.pem -out demoCA/cacert.der -outform DER || fail "Failed to create demoCA DER."
|
||||
sha256sum demoCA/cacert.der > demoCA/cacert.fingerprint || fail "Failed to create demoCA fingerprint"
|
||||
fi
|
||||
if [ ! -e demoCA/crlnumber ]; then
|
||||
echo 00 > demoCA/crlnumber
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "OCSP responder"
|
||||
echo
|
||||
|
||||
cat my-openssl.cnf | sed "s/#@CN@/commonName_default = $CNO/" > openssl.cnf.tmp
|
||||
$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -out ocsp.csr -keyout ocsp.key -extensions v3_OCSP
|
||||
$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -keyfile demoCA/private/cakey.pem -passin pass:$PASS -in ocsp.csr -out ocsp.pem -days 730 -extensions v3_OCSP || fail "Could not generate ocsp.pem"
|
||||
|
||||
echo
|
||||
echo "---[ Server - to be revoked ] ------------------------------------------"
|
||||
echo
|
||||
|
||||
cat my-openssl.cnf | sed "s/#@CN@/commonName_default = $CNV/" > openssl.cnf.tmp
|
||||
$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -out server-revoked.csr -keyout server-revoked.key
|
||||
$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -in server-revoked.csr -out server-revoked.pem -key $PASS -days 730 -extensions ext_server
|
||||
$OPENSSL ca -revoke server-revoked.pem -key $PASS
|
||||
|
||||
echo
|
||||
echo "---[ Server - with client ext key use ] ---------------------------------"
|
||||
echo "---[ Only used for negative-testing for OSU-client implementation ] -----"
|
||||
echo
|
||||
|
||||
cat my-openssl.cnf | sed "s/#@CN@/commonName_default = $CNOC/" > openssl.cnf.tmp
|
||||
$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -out server-client.csr -keyout server-client.key || fail "Could not create server-client.key"
|
||||
$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -in server-client.csr -out server-client.pem -key $PASS -days 730 -extensions ext_client || fail "Could not create server-client.pem"
|
||||
|
||||
echo
|
||||
echo "---[ User ]-------------------------------------------------------------"
|
||||
echo
|
||||
|
||||
cat my-openssl.cnf | sed "s/#@CN@/commonName_default = User/" > openssl.cnf.tmp
|
||||
$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -out user.csr -keyout user.key || fail "Could not create user.key"
|
||||
$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -in user.csr -out user.pem -key $PASS -days 730 -extensions ext_client || fail "Could not create user.pem"
|
||||
|
||||
echo
|
||||
echo "---[ Server ]-----------------------------------------------------------"
|
||||
echo
|
||||
|
||||
ALT="DNS:$OSU_SERVER_HOSTNAME"
|
||||
ALT="$ALT,otherName:1.3.6.1.4.1.40808.1.1.1;UTF8String:$OPER_ENG"
|
||||
ALT="$ALT,otherName:1.3.6.1.4.1.40808.1.1.1;UTF8String:$OPER_FI"
|
||||
|
||||
cat my-openssl.cnf |
|
||||
sed "s/#@CN@/commonName_default = $OSU_SERVER_HOSTNAME/" |
|
||||
sed "s/^##organizationalUnitName/organizationalUnitName/" |
|
||||
sed "s/#@OU@/organizationalUnitName_default = Hotspot 2.0 Online Sign Up Server/" |
|
||||
sed "s/#@ALTNAME@/subjectAltName=critical,$ALT/" \
|
||||
> openssl.cnf.tmp
|
||||
echo $OPENSSL req -config $PWD/openssl.cnf.tmp -batch -sha256 -new -newkey rsa:2048 -nodes -out server.csr -keyout server.key -reqexts v3_osu_server
|
||||
$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -sha256 -new -newkey rsa:2048 -nodes -out server.csr -keyout server.key -reqexts v3_osu_server || fail "Failed to generate server request"
|
||||
$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -in server.csr -out server.pem -key $PASS -days 730 -extensions ext_server -policy policy_osu_server || fail "Failed to sign server certificate"
|
||||
|
||||
#dump logotype details for debugging
|
||||
$OPENSSL x509 -in server.pem -out server.der -outform DER
|
||||
openssl asn1parse -in server.der -inform DER | grep HEX | tail -1 | sed 's/.*://' | xxd -r -p > logo.der
|
||||
openssl asn1parse -in logo.der -inform DER > logo.asn1
|
||||
|
||||
|
||||
echo
|
||||
echo "---[ CRL ]---------------------------------------------------------------"
|
||||
echo
|
||||
|
||||
$OPENSSL ca -config $PWD/my-openssl.cnf -gencrl -md sha256 -out demoCA/crl/crl.pem -passin pass:$PASS
|
||||
|
||||
echo
|
||||
echo "---[ Verify ]------------------------------------------------------------"
|
||||
echo
|
||||
|
||||
$OPENSSL verify -CAfile rootCA/cacert.pem demoCA/cacert.pem
|
||||
$OPENSSL verify -CAfile rootCA/cacert.pem -untrusted demoCA/cacert.pem *.pem
|
||||
|
||||
cat rootCA/cacert.pem demoCA/cacert.pem > ca.pem
|
||||
BIN
contrib/wpa/hs20/server/ca/w1fi_logo.png
Normal file
BIN
contrib/wpa/hs20/server/ca/w1fi_logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.4 KiB |
262
contrib/wpa/hs20/server/hs20-osu-server.txt
Normal file
262
contrib/wpa/hs20/server/hs20-osu-server.txt
Normal file
|
|
@ -0,0 +1,262 @@
|
|||
Hotspot 2.0 OSU server
|
||||
======================
|
||||
|
||||
The information in this document is based on the assumption that Ubuntu
|
||||
16.04 server (64-bit) distribution is used and the web server is
|
||||
Apache2. Neither of these are requirements for the installation, but if
|
||||
other combinations are used, the package names and configuration
|
||||
parameters may need to be adjusted.
|
||||
|
||||
NOTE: This implementation and the example configuration here is meant
|
||||
only for testing purposes in a lab environment. This design is not
|
||||
secure to be installed in a publicly available Internet server without
|
||||
considerable amount of modification and review for security issues.
|
||||
|
||||
|
||||
Build dependencies
|
||||
------------------
|
||||
|
||||
Ubuntu 16.04 server
|
||||
- default installation
|
||||
- upgraded to latest package versions
|
||||
sudo apt-get update
|
||||
sudo apt-get upgrade
|
||||
|
||||
Packages needed for running the service:
|
||||
sudo apt-get install sqlite3
|
||||
sudo apt-get install apache2
|
||||
sudo apt-get install php-sqlite3 php-xml libapache2-mod-php
|
||||
|
||||
Additional packages needed for building the components:
|
||||
sudo apt-get install build-essential
|
||||
sudo apt-get install libsqlite3-dev
|
||||
sudo apt-get install libssl-dev
|
||||
sudo apt-get install libxml2-dev
|
||||
|
||||
|
||||
Installation location
|
||||
---------------------
|
||||
|
||||
Select a location for the installation root directory. The example here
|
||||
assumes /home/user/hs20-server to be used, but this can be changed by
|
||||
editing couple of files as indicated below.
|
||||
|
||||
sudo mkdir -p /home/user/hs20-server
|
||||
sudo chown $USER /home/user/hs20-server
|
||||
mkdir -p /home/user/hs20-server/spp
|
||||
mkdir -p /home/user/hs20-server/AS
|
||||
|
||||
|
||||
Build
|
||||
-----
|
||||
|
||||
# hostapd as RADIUS server
|
||||
cd hostapd
|
||||
|
||||
#example build configuration
|
||||
cat > .config <<EOF
|
||||
CONFIG_DRIVER_NONE=y
|
||||
CONFIG_PKCS12=y
|
||||
CONFIG_RADIUS_SERVER=y
|
||||
CONFIG_EAP=y
|
||||
CONFIG_EAP_TLS=y
|
||||
CONFIG_EAP_MSCHAPV2=y
|
||||
CONFIG_EAP_PEAP=y
|
||||
CONFIG_EAP_GTC=y
|
||||
CONFIG_EAP_TTLS=y
|
||||
CONFIG_EAP_SIM=y
|
||||
CONFIG_EAP_AKA=y
|
||||
CONFIG_EAP_AKA_PRIME=y
|
||||
CONFIG_SQLITE=y
|
||||
CONFIG_HS20=y
|
||||
EOF
|
||||
|
||||
make hostapd hlr_auc_gw
|
||||
cp hostapd hlr_auc_gw /home/user/hs20-server/AS
|
||||
|
||||
# build hs20_spp_server
|
||||
cd ../hs20/server
|
||||
make clean
|
||||
make
|
||||
cp hs20_spp_server /home/user/hs20-server/spp
|
||||
# prepare database (web server user/group needs to have write access)
|
||||
mkdir -p /home/user/hs20-server/AS/DB
|
||||
sudo chgrp www-data /home/user/hs20-server/AS/DB
|
||||
sudo chmod g+w /home/user/hs20-server/AS/DB
|
||||
sqlite3 /home/user/hs20-server/AS/DB/eap_user.db < sql.txt
|
||||
sudo chgrp www-data /home/user/hs20-server/AS/DB/eap_user.db
|
||||
sudo chmod g+w /home/user/hs20-server/AS/DB/eap_user.db
|
||||
# add example configuration (note: need to update URLs to match the system)
|
||||
sqlite3 /home/user/hs20-server/AS/DB/eap_user.db < sql-example.txt
|
||||
|
||||
# copy PHP scripts
|
||||
# Modify config.php if different installation directory is used.
|
||||
# Modify PHP scripts to get the desired behavior for user interaction (or use
|
||||
# the examples as-is for initial testing).
|
||||
cp -r www /home/user/hs20-server
|
||||
|
||||
# Create /home/user/hs20-server/terms-and-conditions file (HTML segment to be
|
||||
# inserted within the BODY section of the page).
|
||||
cat > /home/user/hs20-server/terms-and-conditions <<EOF
|
||||
<P>Terms and conditions..</P>
|
||||
EOF
|
||||
|
||||
# Build local keys and certs
|
||||
cd ca
|
||||
# Display help options.
|
||||
./setup.sh -h
|
||||
|
||||
# Remove old keys, fill in appropriate values, and generate your keys.
|
||||
# For instance:
|
||||
./clean.sh
|
||||
rm -fr rootCA"
|
||||
old_hostname=myserver.local
|
||||
./setup.sh -C "Hotspot 2.0 Trust Root CA - CT" \
|
||||
-o $old_hostname-osu-client \
|
||||
-O $old_hostname-oscp -p lanforge -S $old_hostname \
|
||||
-V $old_hostname-osu-revoked \
|
||||
-m local -u http://$old_hostname:8888/
|
||||
|
||||
# Configure subscription policies
|
||||
mkdir -p /home/user/hs20-server/spp/policy
|
||||
cat > /home/user/hs20-server/spp/policy/default.xml <<EOF
|
||||
<Policy>
|
||||
<PolicyUpdate>
|
||||
<UpdateInterval>30</UpdateInterval>
|
||||
<UpdateMethod>ClientInitiated</UpdateMethod>
|
||||
<Restriction>Unrestricted</Restriction>
|
||||
<URI>https://policy-server.osu.example.com/hs20/spp.php</URI>
|
||||
</PolicyUpdate>
|
||||
</Policy>
|
||||
EOF
|
||||
|
||||
|
||||
# Install Hotspot 2.0 SPP and OMA DM XML schema/DTD files
|
||||
|
||||
# XML schema for SPP
|
||||
# Copy the latest XML schema into /home/user/hs20-server/spp/spp.xsd
|
||||
|
||||
# OMA DM Device Description Framework DTD
|
||||
# Copy into /home/user/hs20-server/spp/dm_ddf-v1_2.dtd
|
||||
# http://www.openmobilealliance.org/tech/DTD/dm_ddf-v1_2.dtd
|
||||
|
||||
|
||||
# Configure RADIUS authentication service
|
||||
# Note: Change the URL to match the setup
|
||||
# Note: Install AAA server key/certificate and root CA in Key directory
|
||||
|
||||
cat > /home/user/hs20-server/AS/as-sql.conf <<EOF
|
||||
driver=none
|
||||
radius_server_clients=as.radius_clients
|
||||
eap_server=1
|
||||
eap_user_file=sqlite:DB/eap_user.db
|
||||
ca_cert=Key/ca.pem
|
||||
server_cert=Key/server.pem
|
||||
private_key=Key/server.key
|
||||
private_key_passwd=passphrase
|
||||
eap_sim_db=unix:/tmp/hlr_auc_gw.sock db=eap_sim.db
|
||||
subscr_remediation_url=https://subscription-server.osu.example.com/hs20/spp.php
|
||||
EOF
|
||||
|
||||
# Set RADIUS passphrase for the APs
|
||||
# Note: Modify to match the setup
|
||||
cat > /home/user/hs20-server/AS/as.radius_clients <<EOF
|
||||
0.0.0.0/0 radius
|
||||
EOF
|
||||
|
||||
|
||||
Start RADIUS authentication server
|
||||
----------------------------------
|
||||
|
||||
cd /home/user/hs20-server/AS
|
||||
./hostapd -B as-sql.conf
|
||||
|
||||
|
||||
OSEN RADIUS server configuration notes
|
||||
|
||||
The OSEN RADIUS server config file should have the 'ocsp_stapling_response'
|
||||
configuration in it. For example:
|
||||
|
||||
# hostapd-radius config for the radius used by the OSEN AP
|
||||
interface=eth0#0
|
||||
driver=none
|
||||
logger_syslog=-1
|
||||
logger_syslog_level=2
|
||||
logger_stdout=-1
|
||||
logger_stdout_level=2
|
||||
ctrl_interface=/var/run/hostapd
|
||||
ctrl_interface_group=0
|
||||
eap_server=1
|
||||
eap_user_file=/home/user/hs20-server/AS/hostapd-osen.eap_user
|
||||
server_id=ben-ota-2-osen
|
||||
radius_server_auth_port=1811
|
||||
radius_server_clients=/home/user/hs20-server/AS/hostap.radius_clients
|
||||
|
||||
ca_cert=/home/user/hs20-server/ca/ca.pem
|
||||
server_cert=/home/user/hs20-server/ca/server.pem
|
||||
private_key=/home/user/hs20-server/ca/server.key
|
||||
private_key_passwd=whatever
|
||||
|
||||
ocsp_stapling_response=/home/user/hs20-server/ca/ocsp-server-cache.der
|
||||
|
||||
The /home/user/hs20-server/AS/hostapd-osen.eap_user file should look
|
||||
similar to this, and should coorelate with the osu_nai entry in
|
||||
the non-OSEN VAP config file. For instance:
|
||||
|
||||
# cat hostapd-osen.eap_user
|
||||
# For OSEN authentication (Hotspot 2.0 Release 2)
|
||||
"osen@w1.fi" WFA-UNAUTH-TLS
|
||||
|
||||
|
||||
# Run OCSP server:
|
||||
cd /home/user/hs20-server/ca
|
||||
./ocsp-responder.sh&
|
||||
|
||||
# Update cache (This should be run periodically)
|
||||
./ocsp-update-cache.sh
|
||||
|
||||
|
||||
Configure web server
|
||||
--------------------
|
||||
|
||||
Edit /etc/apache2/sites-available/default-ssl
|
||||
|
||||
Add following block just before "SSL Engine Switch" line":
|
||||
|
||||
Alias /hs20/ "/home/user/hs20-server/www/"
|
||||
<Directory "/home/user/hs20-server/www/">
|
||||
Options Indexes MultiViews FollowSymLinks
|
||||
AllowOverride None
|
||||
Require all granted
|
||||
SSLOptions +StdEnvVars
|
||||
</Directory>
|
||||
|
||||
Update SSL configuration to use the OSU server certificate/key.
|
||||
They keys and certs are called 'server.key' and 'server.pem' from
|
||||
ca/setup.sh.
|
||||
|
||||
To support subscription remediation using client certificates, set
|
||||
"SSLVerifyClient optional" and configure the trust root CA(s) for the
|
||||
client certificates with SSLCACertificateFile.
|
||||
|
||||
Enable default-ssl site and restart Apache2:
|
||||
sudo a2ensite default-ssl
|
||||
sudo a2enmod ssl
|
||||
sudo service apache2 restart
|
||||
|
||||
|
||||
Management UI
|
||||
-------------
|
||||
|
||||
The sample PHP scripts include a management UI for testing
|
||||
purposes. That is available at https://<server>/hs20/users.php
|
||||
|
||||
|
||||
AP configuration
|
||||
----------------
|
||||
|
||||
APs can now be configured to use the OSU server as the RADIUS
|
||||
authentication server. In addition, the OSU Provider List ANQP element
|
||||
should be configured to use the SPP (SOAP+XML) option and with the
|
||||
following Server URL:
|
||||
https://<server>/hs20/spp.php/signup?realm=example.com
|
||||
207
contrib/wpa/hs20/server/hs20_spp_server.c
Normal file
207
contrib/wpa/hs20/server/hs20_spp_server.c
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
* Hotspot 2.0 SPP server - standalone version
|
||||
* Copyright (c) 2012-2013, Qualcomm Atheros, Inc.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include <time.h>
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "common/version.h"
|
||||
#include "xml-utils.h"
|
||||
#include "spp_server.h"
|
||||
|
||||
|
||||
static void write_timestamp(FILE *f)
|
||||
{
|
||||
time_t t;
|
||||
struct tm *tm;
|
||||
|
||||
time(&t);
|
||||
tm = localtime(&t);
|
||||
|
||||
fprintf(f, "%04u-%02u-%02u %02u:%02u:%02u ",
|
||||
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
|
||||
tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||
}
|
||||
|
||||
|
||||
void debug_print(struct hs20_svc *ctx, int print, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (ctx->debug_log == NULL)
|
||||
return;
|
||||
|
||||
write_timestamp(ctx->debug_log);
|
||||
va_start(ap, fmt);
|
||||
vfprintf(ctx->debug_log, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
fprintf(ctx->debug_log, "\n");
|
||||
}
|
||||
|
||||
|
||||
void debug_dump_node(struct hs20_svc *ctx, const char *title, xml_node_t *node)
|
||||
{
|
||||
char *str;
|
||||
|
||||
if (ctx->debug_log == NULL)
|
||||
return;
|
||||
str = xml_node_to_str(ctx->xml, node);
|
||||
if (str == NULL)
|
||||
return;
|
||||
|
||||
write_timestamp(ctx->debug_log);
|
||||
fprintf(ctx->debug_log, "%s: '%s'\n", title, str);
|
||||
os_free(str);
|
||||
}
|
||||
|
||||
|
||||
static int process(struct hs20_svc *ctx)
|
||||
{
|
||||
int dmacc = 0;
|
||||
xml_node_t *soap, *spp, *resp;
|
||||
char *user, *realm, *post, *str;
|
||||
|
||||
ctx->addr = getenv("HS20ADDR");
|
||||
if (ctx->addr)
|
||||
debug_print(ctx, 1, "Connection from %s", ctx->addr);
|
||||
ctx->test = getenv("HS20TEST");
|
||||
if (ctx->test)
|
||||
debug_print(ctx, 1, "Requested test functionality: %s",
|
||||
ctx->test);
|
||||
|
||||
user = getenv("HS20USER");
|
||||
if (user && strlen(user) == 0)
|
||||
user = NULL;
|
||||
realm = getenv("HS20REALM");
|
||||
if (realm == NULL) {
|
||||
debug_print(ctx, 1, "HS20REALM not set");
|
||||
return -1;
|
||||
}
|
||||
post = getenv("HS20POST");
|
||||
if (post == NULL) {
|
||||
debug_print(ctx, 1, "HS20POST not set");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->imsi = getenv("HS20IMSI");
|
||||
if (ctx->imsi)
|
||||
debug_print(ctx, 1, "IMSI %s", ctx->imsi);
|
||||
|
||||
ctx->eap_method = getenv("HS20EAPMETHOD");
|
||||
if (ctx->eap_method)
|
||||
debug_print(ctx, 1, "EAP method %s", ctx->eap_method);
|
||||
|
||||
ctx->id_hash = getenv("HS20IDHASH");
|
||||
if (ctx->id_hash)
|
||||
debug_print(ctx, 1, "ID-HASH %s", ctx->id_hash);
|
||||
|
||||
soap = xml_node_from_buf(ctx->xml, post);
|
||||
if (soap == NULL) {
|
||||
debug_print(ctx, 1, "Could not parse SOAP data");
|
||||
return -1;
|
||||
}
|
||||
debug_dump_node(ctx, "Received SOAP message", soap);
|
||||
spp = soap_get_body(ctx->xml, soap);
|
||||
if (spp == NULL) {
|
||||
debug_print(ctx, 1, "Could not get SPP message");
|
||||
xml_node_free(ctx->xml, soap);
|
||||
return -1;
|
||||
}
|
||||
debug_dump_node(ctx, "Received SPP message", spp);
|
||||
|
||||
resp = hs20_spp_server_process(ctx, spp, user, realm, dmacc);
|
||||
xml_node_free(ctx->xml, soap);
|
||||
if (resp == NULL && user == NULL) {
|
||||
debug_print(ctx, 1, "Request HTTP authentication");
|
||||
return 2; /* Request authentication */
|
||||
}
|
||||
if (resp == NULL) {
|
||||
debug_print(ctx, 1, "No response");
|
||||
return -1;
|
||||
}
|
||||
|
||||
soap = soap_build_envelope(ctx->xml, resp);
|
||||
if (soap == NULL) {
|
||||
debug_print(ctx, 1, "SOAP envelope building failed");
|
||||
return -1;
|
||||
}
|
||||
str = xml_node_to_str(ctx->xml, soap);
|
||||
xml_node_free(ctx->xml, soap);
|
||||
if (str == NULL) {
|
||||
debug_print(ctx, 1, "Could not get node string");
|
||||
return -1;
|
||||
}
|
||||
printf("%s", str);
|
||||
free(str);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf("usage:\n"
|
||||
"hs20_spp_server -r<root directory> [-f<debug log>]\n");
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct hs20_svc ctx;
|
||||
int ret;
|
||||
|
||||
os_memset(&ctx, 0, sizeof(ctx));
|
||||
for (;;) {
|
||||
int c = getopt(argc, argv, "f:r:v");
|
||||
if (c < 0)
|
||||
break;
|
||||
switch (c) {
|
||||
case 'f':
|
||||
if (ctx.debug_log)
|
||||
break;
|
||||
ctx.debug_log = fopen(optarg, "a");
|
||||
if (ctx.debug_log == NULL) {
|
||||
printf("Could not write to %s\n", optarg);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
ctx.root_dir = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
printf("hs20_spp_server v%s\n", VERSION_STR);
|
||||
return 0;
|
||||
default:
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (ctx.root_dir == NULL) {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
ctx.xml = xml_node_init_ctx(&ctx, NULL);
|
||||
if (ctx.xml == NULL)
|
||||
return -1;
|
||||
if (hs20_spp_server_init(&ctx) < 0) {
|
||||
xml_node_deinit_ctx(ctx.xml);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = process(&ctx);
|
||||
debug_print(&ctx, 1, "process() --> %d", ret);
|
||||
|
||||
xml_node_deinit_ctx(ctx.xml);
|
||||
hs20_spp_server_deinit(&ctx);
|
||||
if (ctx.debug_log)
|
||||
fclose(ctx.debug_log);
|
||||
|
||||
return ret;
|
||||
}
|
||||
2933
contrib/wpa/hs20/server/spp_server.c
Normal file
2933
contrib/wpa/hs20/server/spp_server.c
Normal file
File diff suppressed because it is too large
Load diff
36
contrib/wpa/hs20/server/spp_server.h
Normal file
36
contrib/wpa/hs20/server/spp_server.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Hotspot 2.0 SPP server
|
||||
* Copyright (c) 2012-2013, Qualcomm Atheros, Inc.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef SPP_SERVER_H
|
||||
#define SPP_SERVER_H
|
||||
|
||||
struct hs20_svc {
|
||||
const void *ctx;
|
||||
struct xml_node_ctx *xml;
|
||||
char *root_dir;
|
||||
FILE *debug_log;
|
||||
sqlite3 *db;
|
||||
const char *addr;
|
||||
const char *test;
|
||||
const char *imsi;
|
||||
const char *eap_method;
|
||||
const char *id_hash;
|
||||
};
|
||||
|
||||
|
||||
void debug_print(struct hs20_svc *ctx, int print, const char *fmt, ...)
|
||||
__attribute__ ((format (printf, 3, 4)));
|
||||
void debug_dump_node(struct hs20_svc *ctx, const char *title, xml_node_t *node);
|
||||
|
||||
xml_node_t * hs20_spp_server_process(struct hs20_svc *ctx, xml_node_t *node,
|
||||
const char *auth_user,
|
||||
const char *auth_realm, int dmacc);
|
||||
int hs20_spp_server_init(struct hs20_svc *ctx);
|
||||
void hs20_spp_server_deinit(struct hs20_svc *ctx);
|
||||
|
||||
#endif /* SPP_SERVER_H */
|
||||
17
contrib/wpa/hs20/server/sql-example.txt
Normal file
17
contrib/wpa/hs20/server/sql-example.txt
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
INSERT INTO osu_config(realm,field,value) VALUES('example.com','fqdn','example.com');
|
||||
INSERT INTO osu_config(realm,field,value) VALUES('example.com','friendly_name','Example Operator');
|
||||
INSERT INTO osu_config(realm,field,value) VALUES('example.com','spp_http_auth_url','https://subscription-server.osu.example.com/hs20/spp.php?realm=example.com');
|
||||
INSERT INTO osu_config(realm,field,value) VALUES('example.com','trust_root_cert_url','https://osu-server.osu.example.com/hs20/files/spp-root-ca.der');
|
||||
INSERT INTO osu_config(realm,field,value) VALUES('example.com','trust_root_cert_fingerprint','5b393a9246865569485c2605c3304e48212b449367858299beba9384c4cf4647');
|
||||
INSERT INTO osu_config(realm,field,value) VALUES('example.com','aaa_trust_root_cert_url','https://osu-server.osu.example.com/hs20/files/aaa-root-ca.der');
|
||||
INSERT INTO osu_config(realm,field,value) VALUES('example.com','aaa_trust_root_cert_fingerprint','5b393a9246865569485c2605c3304e48212b449367858299beba9384c4cf4647');
|
||||
INSERT INTO osu_config(realm,field,value) VALUES('example.com','free_account','free');
|
||||
INSERT INTO osu_config(realm,field,value) VALUES('example.com','policy_url','https://subscription-server.osu.example.com/hs20/spp.php?realm=example.com');
|
||||
INSERT INTO osu_config(realm,field,value) VALUES('example.com','remediation_url','https://subscription-server.osu.example.com/hs20/remediation.php?session_id=');
|
||||
INSERT INTO osu_config(realm,field,value) VALUES('example.com','free_remediation_url','https://subscription-server.osu.example.com/hs20/free-remediation.php?session_id=');
|
||||
INSERT INTO osu_config(realm,field,value) VALUES('example.com','signup_url','https://subscription-server.osu.example.com/hs20/signup.php?session_id=');
|
||||
|
||||
|
||||
INSERT INTO users(identity,realm,methods,password,phase2,shared) VALUES('free','example.com','TTLS-MSCHAPV2','free',1,1);
|
||||
|
||||
INSERT INTO wildcards(identity,methods) VALUES('','TTLS,TLS');
|
||||
108
contrib/wpa/hs20/server/sql.txt
Normal file
108
contrib/wpa/hs20/server/sql.txt
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
CREATE TABLE eventlog(
|
||||
user TEXT,
|
||||
realm TEXT,
|
||||
sessionid TEXT COLLATE NOCASE,
|
||||
timestamp TEXT,
|
||||
notes TEXT,
|
||||
dump TEXT,
|
||||
addr TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE sessions(
|
||||
timestamp TEXT,
|
||||
id TEXT COLLATE NOCASE,
|
||||
user TEXT,
|
||||
realm TEXT,
|
||||
password TEXT,
|
||||
machine_managed BOOLEAN,
|
||||
operation INTEGER,
|
||||
type TEXT,
|
||||
pps TEXT,
|
||||
redirect_uri TEXT,
|
||||
devinfo TEXT,
|
||||
devdetail TEXT,
|
||||
cert TEXT,
|
||||
cert_pem TEXT,
|
||||
mac_addr TEXT,
|
||||
osu_user TEXT,
|
||||
osu_password TEXT,
|
||||
eap_method TEXT,
|
||||
mobile_identifier_hash TEXT,
|
||||
test TEXT
|
||||
);
|
||||
|
||||
CREATE index sessions_id_index ON sessions(id);
|
||||
|
||||
CREATE TABLE osu_config(
|
||||
realm TEXT,
|
||||
field TEXT,
|
||||
value TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE users(
|
||||
identity TEXT PRIMARY KEY,
|
||||
methods TEXT,
|
||||
password TEXT,
|
||||
machine_managed BOOLEAN,
|
||||
remediation TEXT,
|
||||
phase2 INTEGER,
|
||||
realm TEXT,
|
||||
policy TEXT,
|
||||
devinfo TEXT,
|
||||
devdetail TEXT,
|
||||
pps TEXT,
|
||||
fetch_pps INTEGER,
|
||||
osu_user TEXT,
|
||||
osu_password TEXT,
|
||||
shared INTEGER,
|
||||
cert TEXT,
|
||||
cert_pem TEXT,
|
||||
t_c_timestamp INTEGER,
|
||||
mac_addr TEXT,
|
||||
last_msk TEXT,
|
||||
polupd_done TEXT,
|
||||
subrem TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE wildcards(
|
||||
identity TEXT PRIMARY KEY,
|
||||
methods TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE authlog(
|
||||
timestamp TEXT,
|
||||
session TEXT,
|
||||
nas_ip TEXT,
|
||||
username TEXT,
|
||||
note TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE pending_tc(
|
||||
mac_addr TEXT PRIMARY KEY,
|
||||
identity TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE current_sessions(
|
||||
mac_addr TEXT PRIMARY KEY,
|
||||
identity TEXT,
|
||||
start_time TEXT,
|
||||
nas TEXT,
|
||||
hs20_t_c_filtering BOOLEAN,
|
||||
waiting_coa_ack BOOLEAN,
|
||||
coa_ack_received BOOLEAN
|
||||
);
|
||||
|
||||
CREATE TABLE cert_enroll(
|
||||
mac_addr TEXT PRIMARY KEY,
|
||||
user TEXT,
|
||||
realm TEXT,
|
||||
serialnum TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE sim_provisioning(
|
||||
mobile_identifier_hash TEXT PRIMARY KEY,
|
||||
imsi TEXT,
|
||||
mac_addr TEXT,
|
||||
eap_method TEXT,
|
||||
timestamp TEXT
|
||||
);
|
||||
50
contrib/wpa/hs20/server/www/add-free.php
Normal file
50
contrib/wpa/hs20/server/www/add-free.php
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
require('config.php');
|
||||
|
||||
$db = new PDO($osu_db);
|
||||
if (!$db) {
|
||||
die($sqliteerror);
|
||||
}
|
||||
|
||||
if (isset($_POST["id"]))
|
||||
$id = preg_replace("/[^a-fA-F0-9]/", "", $_POST["id"]);
|
||||
else
|
||||
die("Missing session id");
|
||||
if (strlen($id) < 32)
|
||||
die("Invalid session id");
|
||||
|
||||
$row = $db->query("SELECT rowid,* FROM sessions WHERE id='$id'")->fetch();
|
||||
if ($row == false) {
|
||||
die("Session not found");
|
||||
}
|
||||
|
||||
$uri = $row['redirect_uri'];
|
||||
$rowid = $row['rowid'];
|
||||
$realm = $row['realm'];
|
||||
|
||||
$row = $db->query("SELECT value FROM osu_config WHERE realm='$realm' AND field='free_account'")->fetch();
|
||||
if (!$row || strlen($row['value']) == 0) {
|
||||
die("Free account disabled");
|
||||
}
|
||||
|
||||
$user = $row['value'];
|
||||
|
||||
$row = $db->query("SELECT password FROM users WHERE identity='$user' AND realm='$realm'")->fetch();
|
||||
if (!$row)
|
||||
die("Free account not found");
|
||||
|
||||
$pw = $row['password'];
|
||||
|
||||
if (!$db->exec("UPDATE sessions SET user='$user', password='$pw', realm='$realm', machine_managed='1' WHERE rowid=$rowid")) {
|
||||
die("Failed to update session database");
|
||||
}
|
||||
|
||||
$db->exec("INSERT INTO eventlog(user,realm,sessionid,timestamp,notes) " .
|
||||
"VALUES ('$user', '$realm', '$id', " .
|
||||
"strftime('%Y-%m-%d %H:%M:%f','now'), " .
|
||||
"'completed user input response for a new PPS MO')");
|
||||
|
||||
header("Location: $uri", true, 302);
|
||||
|
||||
?>
|
||||
56
contrib/wpa/hs20/server/www/add-mo.php
Normal file
56
contrib/wpa/hs20/server/www/add-mo.php
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
require('config.php');
|
||||
|
||||
$db = new PDO($osu_db);
|
||||
if (!$db) {
|
||||
die($sqliteerror);
|
||||
}
|
||||
|
||||
if (isset($_POST["id"]))
|
||||
$id = preg_replace("/[^a-fA-F0-9]/", "", $_POST["id"]);
|
||||
else
|
||||
die("Missing session id");
|
||||
|
||||
$user = $_POST["user"];
|
||||
$pw = $_POST["password"];
|
||||
if (strlen($id) < 32 || !isset($user) || !isset($pw)) {
|
||||
die("Invalid POST data");
|
||||
}
|
||||
|
||||
if (strlen($user) < 1 || strncasecmp($user, "cert-", 5) == 0) {
|
||||
echo "<html><body><p><red>Invalid username</red></p>\n";
|
||||
echo "<a href=\"signup.php?session_id=$id\">Try again</a>\n";
|
||||
echo "</body></html>\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
$row = $db->query("SELECT rowid,* FROM sessions WHERE id='$id'")->fetch();
|
||||
if ($row == false) {
|
||||
die("Session not found");
|
||||
}
|
||||
$realm = $row['realm'];
|
||||
|
||||
$userrow = $db->query("SELECT identity FROM users WHERE identity='$user' AND realm='$realm'")->fetch();
|
||||
if ($userrow) {
|
||||
echo "<html><body><p><red>Selected username is not available</red></p>\n";
|
||||
echo "<a href=\"signup.php?session_id=$id\">Try again</a>\n";
|
||||
echo "</body></html>\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
$uri = $row['redirect_uri'];
|
||||
$rowid = $row['rowid'];
|
||||
|
||||
if (!$db->exec("UPDATE sessions SET user='$user', password='$pw', realm='$realm', type='password' WHERE rowid=$rowid")) {
|
||||
die("Failed to update session database");
|
||||
}
|
||||
|
||||
$db->exec("INSERT INTO eventlog(user,realm,sessionid,timestamp,notes) " .
|
||||
"VALUES ('$user', '$realm', '$id', " .
|
||||
"strftime('%Y-%m-%d %H:%M:%f','now'), " .
|
||||
"'completed user input response for a new PPS MO')");
|
||||
|
||||
header("Location: $uri", true, 302);
|
||||
|
||||
?>
|
||||
39
contrib/wpa/hs20/server/www/cert-enroll.php
Normal file
39
contrib/wpa/hs20/server/www/cert-enroll.php
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
require('config.php');
|
||||
|
||||
$db = new PDO($osu_db);
|
||||
if (!$db) {
|
||||
die($sqliteerror);
|
||||
}
|
||||
|
||||
if (isset($_GET["id"]))
|
||||
$id = preg_replace("/[^a-fA-F0-9]/", "", $_GET["id"]);
|
||||
else
|
||||
die("Missing session id");
|
||||
if (strlen($id) < 32)
|
||||
die("Invalid session id");
|
||||
|
||||
$row = $db->query("SELECT rowid,* FROM sessions WHERE id='$id'")->fetch();
|
||||
if ($row == false) {
|
||||
die("Session not found");
|
||||
}
|
||||
|
||||
$uri = $row['redirect_uri'];
|
||||
$rowid = $row['rowid'];
|
||||
$realm = $row['realm'];
|
||||
|
||||
$user = sha1(mt_rand());
|
||||
|
||||
if (!$db->exec("UPDATE sessions SET user='$user', type='cert' WHERE rowid=$rowid")) {
|
||||
die("Failed to update session database");
|
||||
}
|
||||
|
||||
$db->exec("INSERT INTO eventlog(user,realm,sessionid,timestamp,notes) " .
|
||||
"VALUES ('', '$realm', '$id', " .
|
||||
"strftime('%Y-%m-%d %H:%M:%f','now'), " .
|
||||
"'completed user input response for client certificate enrollment')");
|
||||
|
||||
header("Location: $uri", true, 302);
|
||||
|
||||
?>
|
||||
7
contrib/wpa/hs20/server/www/config.php
Normal file
7
contrib/wpa/hs20/server/www/config.php
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
$osu_root = "/home/user/hs20-server";
|
||||
$osu_db = "sqlite:$osu_root/AS/DB/eap_user.db";
|
||||
$t_c_file = "$osu_root/terms-and-conditions";
|
||||
$t_c_timestamp = 123456789;
|
||||
$hostapd_ctrl = "udg:///home/user/hs20-server/AS/ctrl/as"
|
||||
?>
|
||||
232
contrib/wpa/hs20/server/www/est.php
Normal file
232
contrib/wpa/hs20/server/www/est.php
Normal file
|
|
@ -0,0 +1,232 @@
|
|||
<?php
|
||||
|
||||
require('config.php');
|
||||
|
||||
$params = explode("/", $_SERVER["PATH_INFO"], 3);
|
||||
$realm = $params[1];
|
||||
$cmd = $params[2];
|
||||
$method = $_SERVER["REQUEST_METHOD"];
|
||||
|
||||
unset($user);
|
||||
unset($rowid);
|
||||
|
||||
$db = new PDO($osu_db);
|
||||
if (!$db) {
|
||||
error_log("EST: Could not access database");
|
||||
die("Could not access database");
|
||||
}
|
||||
|
||||
if (!empty($_SERVER['PHP_AUTH_DIGEST'])) {
|
||||
$needed = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1,
|
||||
'uri'=>1, 'response'=>1);
|
||||
$data = array();
|
||||
$keys = implode('|', array_keys($needed));
|
||||
preg_match_all('@(' . $keys . ')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@',
|
||||
$_SERVER['PHP_AUTH_DIGEST'], $matches, PREG_SET_ORDER);
|
||||
foreach ($matches as $m) {
|
||||
$data[$m[1]] = $m[3] ? $m[3] : $m[4];
|
||||
unset($needed[$m[1]]);
|
||||
}
|
||||
if ($needed) {
|
||||
error_log("EST: Missing auth parameter");
|
||||
die('Authentication failed');
|
||||
}
|
||||
$user = $data['username'];
|
||||
if (strlen($user) < 1) {
|
||||
error_log("EST: Empty username");
|
||||
die('Authentication failed');
|
||||
}
|
||||
|
||||
$sql = "SELECT rowid,password,operation FROM sessions " .
|
||||
"WHERE user='$user' AND realm='$realm'";
|
||||
$q = $db->query($sql);
|
||||
if (!$q) {
|
||||
error_log("EST: Session not found for user=$user realm=$realm");
|
||||
die("Session not found");
|
||||
}
|
||||
$row = $q->fetch();
|
||||
if (!$row) {
|
||||
error_log("EST: Session fetch failed for user=$user realm=$realm");
|
||||
die('Session not found');
|
||||
}
|
||||
$rowid = $row['rowid'];
|
||||
|
||||
$oper = $row['operation'];
|
||||
if ($oper != '5') {
|
||||
error_log("EST: Unexpected operation $oper for user=$user realm=$realm");
|
||||
die("Session not found");
|
||||
}
|
||||
$pw = $row['password'];
|
||||
if (strlen($pw) < 1) {
|
||||
error_log("EST: Empty password for user=$user realm=$realm");
|
||||
die('Authentication failed');
|
||||
}
|
||||
|
||||
$A1 = md5($user . ':' . $realm . ':' . $pw);
|
||||
$A2 = md5($method . ':' . $data['uri']);
|
||||
$resp = md5($A1 . ':' . $data['nonce'] . ':' . $data['nc'] . ':' .
|
||||
$data['cnonce'] . ':' . $data['qop'] . ':' . $A2);
|
||||
if ($data['response'] != $resp) {
|
||||
error_log("EST: Incorrect authentication response for user=$user realm=$realm");
|
||||
die('Authentication failed');
|
||||
}
|
||||
} else if (isset($_SERVER["SSL_CLIENT_VERIFY"]) &&
|
||||
$_SERVER["SSL_CLIENT_VERIFY"] == "SUCCESS" &&
|
||||
isset($_SERVER["SSL_CLIENT_M_SERIAL"])) {
|
||||
$user = "cert-" . $_SERVER["SSL_CLIENT_M_SERIAL"];
|
||||
$sql = "SELECT rowid,password,operation FROM sessions " .
|
||||
"WHERE user='$user' AND realm='$realm'";
|
||||
$q = $db->query($sql);
|
||||
if (!$q) {
|
||||
error_log("EST: Session not found for user=$user realm=$realm");
|
||||
die("Session not found");
|
||||
}
|
||||
$row = $q->fetch();
|
||||
if (!$row) {
|
||||
error_log("EST: Session fetch failed for user=$user realm=$realm");
|
||||
die('Session not found');
|
||||
}
|
||||
$rowid = $row['rowid'];
|
||||
|
||||
$oper = $row['operation'];
|
||||
if ($oper != '10') {
|
||||
error_log("EST: Unexpected operation $oper for user=$user realm=$realm");
|
||||
die("Session not found");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($method == "GET" && $cmd == "cacerts") {
|
||||
$fname = "$osu_root/est/$realm-cacerts.pkcs7";
|
||||
if (!file_exists($fname)) {
|
||||
error_log("EST: cacerts - unknown realm $realm");
|
||||
die("Unknown realm");
|
||||
}
|
||||
|
||||
header("Content-Transfer-Encoding: base64");
|
||||
header("Content-Type: application/pkcs7-mime");
|
||||
|
||||
$data = file_get_contents($fname);
|
||||
echo wordwrap(base64_encode($data), 72, "\n", true);
|
||||
echo "\n";
|
||||
error_log("EST: cacerts");
|
||||
} else if ($method == "GET" && $cmd == "csrattrs") {
|
||||
header("Content-Transfer-Encoding: base64");
|
||||
header("Content-Type: application/csrattrs");
|
||||
readfile("$osu_root/est/est-attrs.b64");
|
||||
error_log("EST: csrattrs");
|
||||
} else if ($method == "POST" &&
|
||||
($cmd == "simpleenroll" || $cmd == "simplereenroll")) {
|
||||
$reenroll = $cmd == "simplereenroll";
|
||||
if (!$reenroll && (!isset($user) || strlen($user) == 0)) {
|
||||
header('HTTP/1.1 401 Unauthorized');
|
||||
header('WWW-Authenticate: Digest realm="'.$realm.
|
||||
'",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"');
|
||||
error_log("EST: simpleenroll - require authentication");
|
||||
die('Authentication required');
|
||||
}
|
||||
if ($reenroll &&
|
||||
(!isset($user) ||
|
||||
!isset($_SERVER["SSL_CLIENT_VERIFY"]) ||
|
||||
$_SERVER["SSL_CLIENT_VERIFY"] != "SUCCESS")) {
|
||||
header('HTTP/1.1 403 Forbidden');
|
||||
error_log("EST: simplereenroll - require certificate authentication");
|
||||
die('Authentication required');
|
||||
}
|
||||
if (!isset($_SERVER["CONTENT_TYPE"])) {
|
||||
error_log("EST: simpleenroll without Content-Type");
|
||||
die("Missing Content-Type");
|
||||
}
|
||||
if (!stristr($_SERVER["CONTENT_TYPE"], "application/pkcs10")) {
|
||||
error_log("EST: simpleenroll - unexpected Content-Type: " .
|
||||
$_SERVER["CONTENT_TYPE"]);
|
||||
die("Unexpected Content-Type");
|
||||
}
|
||||
|
||||
$data = file_get_contents("php://input");
|
||||
error_log("EST: simpleenroll - POST data from php://input: " . $data);
|
||||
$req = base64_decode($data);
|
||||
if ($req == FALSE) {
|
||||
error_log("EST: simpleenroll - Invalid base64-encoded PKCS#10 data");
|
||||
die("Invalid base64-encoded PKCS#10 data");
|
||||
}
|
||||
$cadir = "$osu_root/est";
|
||||
$reqfile = "$cadir/tmp/cert-req.pkcs10";
|
||||
$f = fopen($reqfile, "wb");
|
||||
fwrite($f, $req);
|
||||
fclose($f);
|
||||
|
||||
$req_pem = "$reqfile.pem";
|
||||
if (file_exists($req_pem))
|
||||
unlink($req_pem);
|
||||
exec("openssl req -in $reqfile -inform DER -out $req_pem -outform PEM");
|
||||
if (!file_exists($req_pem)) {
|
||||
error_log("EST: simpleenroll - Failed to parse certificate request");
|
||||
die("Failed to parse certificate request");
|
||||
}
|
||||
|
||||
/* FIX: validate request and add HS 2.0 extensions to cert */
|
||||
$cert_pem = "$cadir/tmp/req-signed.pem";
|
||||
if (file_exists($cert_pem))
|
||||
unlink($cert_pem);
|
||||
exec("openssl x509 -req -in $req_pem -CAkey $cadir/cakey.pem -out $cert_pem -CA $cadir/cacert.pem -CAserial $cadir/serial -days 365 -text");
|
||||
if (!file_exists($cert_pem)) {
|
||||
error_log("EST: simpleenroll - Failed to sign certificate");
|
||||
die("Failed to sign certificate");
|
||||
}
|
||||
|
||||
$cert = file_get_contents($cert_pem);
|
||||
$handle = popen("openssl x509 -in $cert_pem -serial -noout", "r");
|
||||
$serial = fread($handle, 200);
|
||||
pclose($handle);
|
||||
$pattern = "/serial=(?P<snhex>[0-9a-fA-F:]*)/m";
|
||||
preg_match($pattern, $serial, $matches);
|
||||
if (!isset($matches['snhex']) || strlen($matches['snhex']) < 1) {
|
||||
error_log("EST: simpleenroll - Could not get serial number");
|
||||
die("Could not get serial number");
|
||||
}
|
||||
$sn = str_replace(":", "", strtoupper($matches['snhex']));
|
||||
|
||||
$user = "cert-$sn";
|
||||
error_log("EST: user = $user");
|
||||
|
||||
$cert_der = "$cadir/tmp/req-signed.der";
|
||||
if (file_exists($cert_der))
|
||||
unlink($cert_der);
|
||||
exec("openssl x509 -in $cert_pem -inform PEM -out $cert_der -outform DER");
|
||||
if (!file_exists($cert_der)) {
|
||||
error_log("EST: simpleenroll - Failed to convert certificate");
|
||||
die("Failed to convert certificate");
|
||||
}
|
||||
$der = file_get_contents($cert_der);
|
||||
$fingerprint = hash("sha256", $der);
|
||||
error_log("EST: sha256(DER cert): $fingerprint");
|
||||
|
||||
$pkcs7 = "$cadir/tmp/est-client.pkcs7";
|
||||
if (file_exists($pkcs7))
|
||||
unlink($pkcs7);
|
||||
exec("openssl crl2pkcs7 -nocrl -certfile $cert_pem -out $pkcs7 -outform DER");
|
||||
if (!file_exists($pkcs7)) {
|
||||
error_log("EST: simpleenroll - Failed to prepare PKCS#7 file");
|
||||
die("Failed to prepare PKCS#7 file");
|
||||
}
|
||||
|
||||
if (!$db->exec("UPDATE sessions SET user='$user', cert='$fingerprint', cert_pem='$cert' WHERE rowid=$rowid")) {
|
||||
error_log("EST: simpleenroll - Failed to update session database");
|
||||
die("Failed to update session database");
|
||||
}
|
||||
|
||||
header("Content-Transfer-Encoding: base64");
|
||||
header("Content-Type: application/pkcs7-mime");
|
||||
|
||||
$data = file_get_contents($pkcs7);
|
||||
$resp = wordwrap(base64_encode($data), 72, "\n", true);
|
||||
echo $resp . "\n";
|
||||
error_log("EST: simpleenroll - PKCS#7 response: " . $resp);
|
||||
} else {
|
||||
header("HTTP/1.0 404 Not Found");
|
||||
error_log("EST: Unexpected method or path");
|
||||
die("Unexpected method or path");
|
||||
}
|
||||
|
||||
?>
|
||||
19
contrib/wpa/hs20/server/www/free-remediation.php
Normal file
19
contrib/wpa/hs20/server/www/free-remediation.php
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Hotspot 2.0 - public and free hotspot - remediation</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h3>Hotspot 2.0 - public and free hotspot</h3>
|
||||
|
||||
<p>Terms and conditions have changed. You need to accept the new terms
|
||||
to continue using this network.</p>
|
||||
|
||||
<p>Terms and conditions..</p>
|
||||
|
||||
<?php
|
||||
echo "<a href=\"redirect.php?id=" . $_GET["session_id"] . "\">Accept</a><br>\n";
|
||||
?>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
23
contrib/wpa/hs20/server/www/free.php
Normal file
23
contrib/wpa/hs20/server/www/free.php
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Hotspot 2.0 - public and free hotspot</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<?php
|
||||
|
||||
$id = $_GET["session_id"];
|
||||
|
||||
echo "<h3>Hotspot 2.0 - public and free hotspot</h3>\n";
|
||||
|
||||
echo "<form action=\"add-free.php\" method=\"POST\">\n";
|
||||
echo "<input type=\"hidden\" name=\"id\" value=\"$id\">\n";
|
||||
|
||||
?>
|
||||
|
||||
<p>Terms and conditions..</p>
|
||||
<input type="submit" value="Accept">
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
32
contrib/wpa/hs20/server/www/redirect.php
Normal file
32
contrib/wpa/hs20/server/www/redirect.php
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
require('config.php');
|
||||
|
||||
$db = new PDO($osu_db);
|
||||
if (!$db) {
|
||||
die($sqliteerror);
|
||||
}
|
||||
|
||||
if (isset($_GET["id"]))
|
||||
$id = preg_replace("/[^a-fA-F0-9]/", "", $_GET["id"]);
|
||||
else
|
||||
$id = 0;
|
||||
|
||||
$row = $db->query("SELECT rowid,* FROM sessions WHERE id='$id'")->fetch();
|
||||
if ($row == false) {
|
||||
die("Session not found");
|
||||
}
|
||||
|
||||
$uri = $row['redirect_uri'];
|
||||
|
||||
header("Location: $uri", true, 302);
|
||||
|
||||
$user = $row['user'];
|
||||
$realm = $row['realm'];
|
||||
|
||||
$db->exec("INSERT INTO eventlog(user,realm,sessionid,timestamp,notes) " .
|
||||
"VALUES ('$user', '$realm', '$id', " .
|
||||
"strftime('%Y-%m-%d %H:%M:%f','now'), " .
|
||||
"'redirected after user input')");
|
||||
|
||||
?>
|
||||
41
contrib/wpa/hs20/server/www/remediation-pw.php
Normal file
41
contrib/wpa/hs20/server/www/remediation-pw.php
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
require('config.php');
|
||||
|
||||
$db = new PDO($osu_db);
|
||||
if (!$db) {
|
||||
die($sqliteerror);
|
||||
}
|
||||
|
||||
if (isset($_POST["id"]))
|
||||
$id = preg_replace("/[^a-fA-F0-9]/", "", $_POST["id"]);
|
||||
else
|
||||
die("Missing session id");
|
||||
|
||||
$pw = $_POST["password"];
|
||||
if (strlen($id) < 32 || !isset($pw)) {
|
||||
die("Invalid POST data");
|
||||
}
|
||||
|
||||
$row = $db->query("SELECT rowid,* FROM sessions WHERE id='$id'")->fetch();
|
||||
if ($row == false) {
|
||||
die("Session not found");
|
||||
}
|
||||
$user = $row['user'];
|
||||
$realm = $row['realm'];
|
||||
|
||||
$uri = $row['redirect_uri'];
|
||||
$rowid = $row['rowid'];
|
||||
|
||||
if (!$db->exec("UPDATE sessions SET password='$pw' WHERE rowid=$rowid")) {
|
||||
die("Failed to update session database");
|
||||
}
|
||||
|
||||
$db->exec("INSERT INTO eventlog(user,realm,sessionid,timestamp,notes) " .
|
||||
"VALUES ('$user', '$realm', '$id', " .
|
||||
"strftime('%Y-%m-%d %H:%M:%f','now'), " .
|
||||
"'completed user input response for subscription remediation')");
|
||||
|
||||
header("Location: $uri", true, 302);
|
||||
|
||||
?>
|
||||
55
contrib/wpa/hs20/server/www/remediation.php
Normal file
55
contrib/wpa/hs20/server/www/remediation.php
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Hotspot 2.0 subscription remediation</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<?php
|
||||
|
||||
require('config.php');
|
||||
|
||||
$db = new PDO($osu_db);
|
||||
if (!$db) {
|
||||
die($sqliteerror);
|
||||
}
|
||||
|
||||
if (isset($_GET["session_id"]))
|
||||
$id = preg_replace("/[^a-fA-F0-9]/", "", $_GET["session_id"]);
|
||||
else
|
||||
$id = 0;
|
||||
echo "SessionID: " . $id . "<br>\n";
|
||||
|
||||
$row = $db->query("SELECT * FROM sessions WHERE id='$id'")->fetch();
|
||||
if ($row == false) {
|
||||
die("Session not found");
|
||||
}
|
||||
|
||||
$username = $row['user'];
|
||||
echo "User: " . $username . "@" . $row['realm'] . "<br>\n";
|
||||
|
||||
$user = $db->query("SELECT machine_managed,methods FROM users WHERE identity='$username'")->fetch();
|
||||
if ($user == false) {
|
||||
die("User not found");
|
||||
}
|
||||
|
||||
echo "<hr><br>\n";
|
||||
|
||||
$cert = $user['methods'] == "TLS" || strncmp($username, "cert-", 5) == 0;
|
||||
|
||||
if ($cert) {
|
||||
echo "<a href=\"redirect.php?id=" . $_GET["session_id"] . "\">Complete user subscription remediation</a><br>\n";
|
||||
} else if ($user['machine_managed'] == "1") {
|
||||
echo "<a href=\"redirect.php?id=" . $_GET["session_id"] . "\">Complete user subscription remediation</a><br>\n";
|
||||
echo "This will provide a new machine-generated password.<br>\n";
|
||||
} else {
|
||||
echo "<form action=\"remediation-pw.php\" method=\"POST\">\n";
|
||||
echo "<input type=\"hidden\" name=\"id\" value=\"$id\">\n";
|
||||
echo "New password: <input type=\"password\" name=\"password\"><br>\n";
|
||||
echo "<input type=\"submit\" value=\"Change password\">\n";
|
||||
echo "</form>\n";
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
59
contrib/wpa/hs20/server/www/signup.php
Normal file
59
contrib/wpa/hs20/server/www/signup.php
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Hotspot 2.0 signup</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<?php
|
||||
|
||||
$id = $_GET["session_id"];
|
||||
|
||||
require('config.php');
|
||||
|
||||
$db = new PDO($osu_db);
|
||||
if (!$db) {
|
||||
die($sqliteerror);
|
||||
}
|
||||
|
||||
$row = $db->query("SELECT realm,test FROM sessions WHERE id='$id'")->fetch();
|
||||
if ($row == false) {
|
||||
die("Session not found for id: $id");
|
||||
}
|
||||
$realm = $row['realm'];
|
||||
$test = $row['test'];
|
||||
|
||||
if (strlen($test) > 0) {
|
||||
echo "<p style=\"color:#FF0000\">Special test functionality: $test</red></big></p>\n";
|
||||
}
|
||||
|
||||
echo "<h3>Sign up for a subscription - $realm</h3>\n";
|
||||
|
||||
echo "<p>This page can be used to select between three different types of subscriptions for testing purposes.</p>\n";
|
||||
|
||||
echo "<h4>Option 1 - shared free access credential</h4>\n";
|
||||
|
||||
$row = $db->query("SELECT value FROM osu_config WHERE realm='$realm' AND field='free_account'")->fetch();
|
||||
if ($row && strlen($row['value']) > 0) {
|
||||
echo "<p><a href=\"free.php?session_id=$id\">Sign up for free access</a></p>\n";
|
||||
}
|
||||
|
||||
echo "<h4>Option 2 - username/password credential</h4>\n";
|
||||
|
||||
echo "<form action=\"add-mo.php\" method=\"POST\">\n";
|
||||
echo "<input type=\"hidden\" name=\"id\" value=\"$id\">\n";
|
||||
?>
|
||||
Select a username and password. Leave password empty to get automatically
|
||||
generated and machine managed password.<br>
|
||||
Username: <input type="text" name="user"><br>
|
||||
Password: <input type="password" name="password"><br>
|
||||
<input type="submit" value="Complete subscription registration">
|
||||
</form>
|
||||
|
||||
<?php
|
||||
echo "<h4>Option 3 - client certificate credential</h4>\n";
|
||||
|
||||
echo "<p><a href=\"cert-enroll.php?id=$id\">Enroll a client certificate</a></p>\n"
|
||||
?>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
168
contrib/wpa/hs20/server/www/spp.php
Normal file
168
contrib/wpa/hs20/server/www/spp.php
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
<?php
|
||||
|
||||
require('config.php');
|
||||
|
||||
if (!stristr($_SERVER["CONTENT_TYPE"], "application/soap+xml")) {
|
||||
error_log("spp.php - Unexpected Content-Type " . $_SERVER["CONTENT_TYPE"]);
|
||||
die("Unexpected Content-Type");
|
||||
}
|
||||
|
||||
if ($_SERVER["REQUEST_METHOD"] != "POST") {
|
||||
error_log("spp.php - Unexpected method " . $_SERVER["REQUEST_METHOD"]);
|
||||
die("Unexpected method");
|
||||
}
|
||||
|
||||
if (isset($_GET["realm"])) {
|
||||
$realm = $_GET["realm"];
|
||||
$realm = PREG_REPLACE("/[^0-9a-zA-Z\.\-]/i", '', $realm);
|
||||
} else {
|
||||
error_log("spp.php - Realm not specified");
|
||||
die("Realm not specified");
|
||||
}
|
||||
|
||||
if (isset($_GET["test"]))
|
||||
$test = PREG_REPLACE("/[^0-9a-zA-Z\_\-]/i", '', $_GET["test"]);
|
||||
else
|
||||
$test = "";
|
||||
|
||||
unset($user);
|
||||
putenv("HS20CERT");
|
||||
|
||||
if (!empty($_SERVER['PHP_AUTH_DIGEST'])) {
|
||||
$needed = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1,
|
||||
'uri'=>1, 'response'=>1);
|
||||
$data = array();
|
||||
$keys = implode('|', array_keys($needed));
|
||||
preg_match_all('@(' . $keys . ')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@',
|
||||
$_SERVER['PHP_AUTH_DIGEST'], $matches, PREG_SET_ORDER);
|
||||
foreach ($matches as $m) {
|
||||
$data[$m[1]] = $m[3] ? $m[3] : $m[4];
|
||||
unset($needed[$m[1]]);
|
||||
}
|
||||
if ($needed) {
|
||||
error_log("spp.php - Authentication failed - missing: " . print_r($needed));
|
||||
die('Authentication failed');
|
||||
}
|
||||
$user = $data['username'];
|
||||
if (strlen($user) < 1) {
|
||||
error_log("spp.php - Authentication failed - empty username");
|
||||
die('Authentication failed');
|
||||
}
|
||||
|
||||
|
||||
$db = new PDO($osu_db);
|
||||
if (!$db) {
|
||||
error_log("spp.php - Could not access database");
|
||||
die("Could not access database");
|
||||
}
|
||||
$row = $db->query("SELECT password FROM users " .
|
||||
"WHERE identity='$user' AND realm='$realm'")->fetch();
|
||||
if (!$row) {
|
||||
$row = $db->query("SELECT osu_password FROM users " .
|
||||
"WHERE osu_user='$user' AND realm='$realm'")->fetch();
|
||||
$pw = $row['osu_password'];
|
||||
} else
|
||||
$pw = $row['password'];
|
||||
if (!$row) {
|
||||
error_log("spp.php - Authentication failed - user '$user' not found");
|
||||
die('Authentication failed');
|
||||
}
|
||||
if (strlen($pw) < 1) {
|
||||
error_log("spp.php - Authentication failed - empty password");
|
||||
die('Authentication failed');
|
||||
}
|
||||
|
||||
$A1 = md5($user . ':' . $realm . ':' . $pw);
|
||||
$A2 = md5($_SERVER['REQUEST_METHOD'] . ':' . $data['uri']);
|
||||
$resp = md5($A1 . ':' . $data['nonce'] . ':' . $data['nc'] . ':' .
|
||||
$data['cnonce'] . ':' . $data['qop'] . ':' . $A2);
|
||||
if ($data['response'] != $resp) {
|
||||
error_log("Authentication failure - response mismatch");
|
||||
die('Authentication failed');
|
||||
}
|
||||
} else if (isset($_SERVER["SSL_CLIENT_VERIFY"]) &&
|
||||
$_SERVER["SSL_CLIENT_VERIFY"] == "SUCCESS" &&
|
||||
isset($_SERVER["SSL_CLIENT_M_SERIAL"])) {
|
||||
$user = "cert-" . $_SERVER["SSL_CLIENT_M_SERIAL"];
|
||||
putenv("HS20CERT=yes");
|
||||
} else if (isset($_GET["hotspot2dot0-mobile-identifier-hash"])) {
|
||||
$id_hash = $_GET["hotspot2dot0-mobile-identifier-hash"];
|
||||
$id_hash = PREG_REPLACE("/[^0-9a-h]/i", '', $id_hash);
|
||||
|
||||
$db = new PDO($osu_db);
|
||||
if (!$db) {
|
||||
error_log("spp.php - Could not access database");
|
||||
die("Could not access database");
|
||||
}
|
||||
|
||||
$row = $db->query("SELECT * FROM sim_provisioning " .
|
||||
"WHERE mobile_identifier_hash='$id_hash'")->fetch();
|
||||
if (!$row) {
|
||||
error_log("spp.php - SIM provisioning failed - mobile_identifier_hash not found");
|
||||
die('SIM provisioning failed - mobile_identifier_hash not found');
|
||||
}
|
||||
|
||||
$imsi = $row['imsi'];
|
||||
$mac_addr = $row['mac_addr'];
|
||||
$eap_method = $row['eap_method'];
|
||||
|
||||
$row = $db->query("SELECT COUNT(*) FROM osu_config " .
|
||||
"WHERE realm='$realm'")->fetch();
|
||||
if (!$row || intval($row[0]) < 1) {
|
||||
error_log("spp.php - SIM provisioning failed - realm $realm not found");
|
||||
die('SIM provisioning failed');
|
||||
}
|
||||
|
||||
error_log("spp.php - SIM provisioning for IMSI $imsi");
|
||||
putenv("HS20SIMPROV=yes");
|
||||
putenv("HS20IMSI=$imsi");
|
||||
putenv("HS20MACADDR=$mac_addr");
|
||||
putenv("HS20EAPMETHOD=$eap_method");
|
||||
putenv("HS20IDHASH=$id_hash");
|
||||
} else if (!isset($_SERVER["PATH_INFO"]) ||
|
||||
$_SERVER["PATH_INFO"] != "/signup") {
|
||||
header('HTTP/1.1 401 Unauthorized');
|
||||
header('WWW-Authenticate: Digest realm="'.$realm.
|
||||
'",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"');
|
||||
error_log("spp.php - Authentication required (not signup)");
|
||||
die('Authentication required (not signup)');
|
||||
}
|
||||
|
||||
|
||||
if (isset($user) && strlen($user) > 0)
|
||||
putenv("HS20USER=$user");
|
||||
else
|
||||
putenv("HS20USER");
|
||||
|
||||
putenv("HS20REALM=$realm");
|
||||
$postdata = file_get_contents("php://input");
|
||||
putenv("HS20POST=$postdata");
|
||||
$addr = $_SERVER["REMOTE_ADDR"];
|
||||
putenv("HS20ADDR=$addr");
|
||||
putenv("HS20TEST=$test");
|
||||
|
||||
$last = exec("$osu_root/spp/hs20_spp_server -r$osu_root -f/tmp/hs20_spp_server.log", $output, $ret);
|
||||
|
||||
if ($ret == 2) {
|
||||
if (empty($_SERVER['PHP_AUTH_DIGEST'])) {
|
||||
header('HTTP/1.1 401 Unauthorized');
|
||||
header('WWW-Authenticate: Digest realm="'.$realm.
|
||||
'",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"');
|
||||
error_log("spp.php - Authentication required (ret 2)");
|
||||
die('Authentication required');
|
||||
} else {
|
||||
error_log("spp.php - Unexpected authentication error");
|
||||
die("Unexpected authentication error");
|
||||
}
|
||||
}
|
||||
if ($ret != 0) {
|
||||
error_log("spp.php - Failed to process SPP request");
|
||||
die("Failed to process SPP request");
|
||||
}
|
||||
//error_log("spp.php: Response: " . implode($output));
|
||||
|
||||
header("Content-Type: application/soap+xml");
|
||||
|
||||
echo implode($output);
|
||||
|
||||
?>
|
||||
87
contrib/wpa/hs20/server/www/terms.php
Normal file
87
contrib/wpa/hs20/server/www/terms.php
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
<?php
|
||||
|
||||
require('config.php');
|
||||
|
||||
function print_header()
|
||||
{
|
||||
echo "<html>\n";
|
||||
echo "<head><title>HS 2.0 Terms and Conditions</title></head>\n";
|
||||
echo "<body>\n";
|
||||
}
|
||||
|
||||
$db = new PDO($osu_db);
|
||||
if (!$db) {
|
||||
die($sqliteerror);
|
||||
}
|
||||
|
||||
if (!isset($_GET["addr"])) {
|
||||
die("Missing addr parameter");
|
||||
}
|
||||
$addr = $_GET["addr"];
|
||||
|
||||
$accept = isset($_GET["accept"]) && $_GET["accept"] == "yes";
|
||||
|
||||
$res = $db->prepare("SELECT identity FROM pending_tc WHERE mac_addr=?");
|
||||
$res->execute(array($addr));
|
||||
$row = $res->fetch();
|
||||
if (!$row) {
|
||||
die("No pending session for the specified MAC address");
|
||||
}
|
||||
$identity = $row[0];
|
||||
|
||||
if (!$accept) {
|
||||
print_header();
|
||||
|
||||
echo "<p>Accept the following terms and conditions by clicking here: <a href=\"terms.php?addr=$addr&accept=yes\">Accept</a></p>\n<hr>\n";
|
||||
readfile($t_c_file);
|
||||
} else {
|
||||
$res = $db->prepare("UPDATE users SET t_c_timestamp=? WHERE identity=?");
|
||||
if (!$res->execute(array($t_c_timestamp, $identity))) {
|
||||
die("Failed to update user account.");
|
||||
}
|
||||
|
||||
$res = $db->prepare("DELETE FROM pending_tc WHERE mac_addr=?");
|
||||
$res->execute(array($addr));
|
||||
|
||||
$fp = fsockopen($hostapd_ctrl);
|
||||
if (!$fp) {
|
||||
die("Could not connect to hostapd(AS)");
|
||||
}
|
||||
|
||||
fwrite($fp, "DAC_REQUEST coa $addr t_c_clear");
|
||||
fclose($fp);
|
||||
|
||||
$waiting = true;
|
||||
$ack = false;
|
||||
for ($i = 1; $i <= 10; $i++) {
|
||||
$res = $db->prepare("SELECT waiting_coa_ack,coa_ack_received FROM current_sessions WHERE mac_addr=?");
|
||||
$res->execute(array($addr));
|
||||
$row = $res->fetch();
|
||||
if (!$row) {
|
||||
die("No current session for the specified MAC address");
|
||||
}
|
||||
if (strlen($row[0]) > 0)
|
||||
$waiting = $row[0] == 1;
|
||||
if (strlen($row[1]) > 0)
|
||||
$ack = $row[1] == 1;
|
||||
$res->closeCursor();
|
||||
if (!$waiting)
|
||||
break;
|
||||
sleep(1);
|
||||
}
|
||||
if ($ack) {
|
||||
header('X-WFA-Hotspot20-Filtering: removed');
|
||||
print_header();
|
||||
echo "<p>Terms and conditions were accepted.</p>\n";
|
||||
|
||||
echo "<P>Filtering disabled.</P>\n";
|
||||
} else {
|
||||
print_header();
|
||||
echo "<P>Failed to disable filtering.</P>\n";
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
377
contrib/wpa/hs20/server/www/users.php
Normal file
377
contrib/wpa/hs20/server/www/users.php
Normal file
|
|
@ -0,0 +1,377 @@
|
|||
<?php
|
||||
|
||||
require('config.php');
|
||||
|
||||
$db = new PDO($osu_db);
|
||||
if (!$db) {
|
||||
die($sqliteerror);
|
||||
}
|
||||
|
||||
if (isset($_GET["id"])) {
|
||||
$id = $_GET["id"];
|
||||
if (!is_numeric($id))
|
||||
$id = 0;
|
||||
} else
|
||||
$id = 0;
|
||||
if (isset($_GET["cmd"]))
|
||||
$cmd = $_GET["cmd"];
|
||||
else
|
||||
$cmd = '';
|
||||
|
||||
if ($cmd == 'eventlog' && $id > 0) {
|
||||
$row = $db->query("SELECT dump FROM eventlog WHERE rowid=$id")->fetch();
|
||||
$dump = $row['dump'];
|
||||
if ($dump[0] == '<') {
|
||||
header("Content-type: text/xml");
|
||||
echo "<?xml version=\"1.0\"?>\n";
|
||||
echo $dump;
|
||||
} else {
|
||||
header("Content-type: text/plain");
|
||||
echo $dump;
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($cmd == 'mo' && $id > 0) {
|
||||
$mo = $_GET["mo"];
|
||||
if (!isset($mo))
|
||||
exit;
|
||||
if ($mo != "devinfo" && $mo != "devdetail" && $mo != "pps")
|
||||
exit;
|
||||
$row = $db->query("SELECT $mo FROM users WHERE rowid=$id")->fetch();
|
||||
header("Content-type: text/xml");
|
||||
echo "<?xml version=\"1.0\"?>\n";
|
||||
echo $row[$mo];
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($cmd == 'cert' && $id > 0) {
|
||||
$row = $db->query("SELECT cert_pem FROM users WHERE rowid=$id")->fetch();
|
||||
header("Content-type: text/plain");
|
||||
echo $row['cert_pem'];
|
||||
exit;
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<html>
|
||||
<head><title>HS 2.0 users</title></head>
|
||||
<body>
|
||||
|
||||
<?php
|
||||
|
||||
if ($cmd == 'subrem-clear' && $id > 0) {
|
||||
$db->exec("UPDATE users SET remediation='' WHERE rowid=$id");
|
||||
}
|
||||
if ($cmd == 'subrem-add-user' && $id > 0) {
|
||||
$db->exec("UPDATE users SET remediation='user' WHERE rowid=$id");
|
||||
}
|
||||
if ($cmd == 'subrem-add-machine' && $id > 0) {
|
||||
$db->exec("UPDATE users SET remediation='machine' WHERE rowid=$id");
|
||||
}
|
||||
if ($cmd == 'subrem-add-reenroll' && $id > 0) {
|
||||
$db->exec("UPDATE users SET remediation='reenroll' WHERE rowid=$id");
|
||||
}
|
||||
if ($cmd == 'subrem-add-policy' && $id > 0) {
|
||||
$db->exec("UPDATE users SET remediation='policy' WHERE rowid=$id");
|
||||
}
|
||||
if ($cmd == 'subrem-add-free' && $id > 0) {
|
||||
$db->exec("UPDATE users SET remediation='free' WHERE rowid=$id");
|
||||
}
|
||||
if ($cmd == 'fetch-pps-on' && $id > 0) {
|
||||
$db->exec("UPDATE users SET fetch_pps=1 WHERE rowid=$id");
|
||||
}
|
||||
if ($cmd == 'fetch-pps-off' && $id > 0) {
|
||||
$db->exec("UPDATE users SET fetch_pps=0 WHERE rowid=$id");
|
||||
}
|
||||
if ($cmd == 'reset-pw' && $id > 0) {
|
||||
$db->exec("UPDATE users SET password='ChangeMe' WHERE rowid=$id");
|
||||
}
|
||||
if ($cmd == "policy" && $id > 0 && isset($_GET["policy"])) {
|
||||
$policy = $_GET["policy"];
|
||||
if ($policy == "no-policy" ||
|
||||
is_readable("$osu_root/spp/policy/$policy.xml")) {
|
||||
$db->exec("UPDATE users SET policy='$policy' WHERE rowid=$id");
|
||||
}
|
||||
}
|
||||
if ($cmd == "account-type" && $id > 0 && isset($_GET["type"])) {
|
||||
$type = $_GET["type"];
|
||||
if ($type == "shared")
|
||||
$db->exec("UPDATE users SET shared=1 WHERE rowid=$id");
|
||||
if ($type == "default")
|
||||
$db->exec("UPDATE users SET shared=0 WHERE rowid=$id");
|
||||
}
|
||||
|
||||
if ($cmd == "set-osu-cred" && $id > 0) {
|
||||
$osu_user = $_POST["osu_user"];
|
||||
$osu_password = $_POST["osu_password"];
|
||||
if (strlen($osu_user) == 0)
|
||||
$osu_password = "";
|
||||
$db->exec("UPDATE users SET osu_user='$osu_user', osu_password='$osu_password' WHERE rowid=$id");
|
||||
}
|
||||
|
||||
if ($cmd == 'clear-t-c' && $id > 0) {
|
||||
$db->exec("UPDATE users SET t_c_timestamp=NULL WHERE rowid=$id");
|
||||
}
|
||||
|
||||
$dump = 0;
|
||||
|
||||
if ($id > 0) {
|
||||
|
||||
if (isset($_GET["dump"])) {
|
||||
$dump = $_GET["dump"];
|
||||
if (!is_numeric($dump))
|
||||
$dump = 0;
|
||||
} else
|
||||
$dump = 0;
|
||||
|
||||
echo "[<a href=\"users.php\">All users</a>] ";
|
||||
if ($dump == 0)
|
||||
echo "[<a href=\"users.php?id=$id&dump=1\">Include debug dump</a>] ";
|
||||
else
|
||||
echo "[<a href=\"users.php?id=$id\">Without debug dump</a>] ";
|
||||
echo "<br>\n";
|
||||
|
||||
$row = $db->query("SELECT rowid,* FROM users WHERE rowid=$id")->fetch();
|
||||
|
||||
echo "<H3>" . $row['identity'] . "@" . $row['realm'] . "</H3>\n";
|
||||
|
||||
echo "MO: ";
|
||||
if (strlen($row['devinfo']) > 0) {
|
||||
echo "[<a href=\"users.php?cmd=mo&id=$id&mo=devinfo\">DevInfo</a>]\n";
|
||||
}
|
||||
if (strlen($row['devdetail']) > 0) {
|
||||
echo "[<a href=\"users.php?cmd=mo&id=$id&mo=devdetail\">DevDetail</a>]\n";
|
||||
}
|
||||
if (strlen($row['pps']) > 0) {
|
||||
echo "[<a href=\"users.php?cmd=mo&id=$id&mo=pps\">PPS</a>]\n";
|
||||
}
|
||||
if (strlen($row['cert_pem']) > 0) {
|
||||
echo "[<a href=\"users.php?cmd=cert&id=$id\">Certificate</a>]\n";
|
||||
}
|
||||
echo "<BR>\n";
|
||||
|
||||
echo "Fetch PPS MO: ";
|
||||
if ($row['fetch_pps'] == "1") {
|
||||
echo "On next connection " .
|
||||
"[<a href=\"users.php?cmd=fetch-pps-off&id=$id\">" .
|
||||
"do not fetch</a>]<br>\n";
|
||||
} else {
|
||||
echo "Do not fetch " .
|
||||
"[<a href=\"users.php?cmd=fetch-pps-on&id=$id\">" .
|
||||
"request fetch</a>]<br>\n";
|
||||
}
|
||||
|
||||
$cert = $row['cert'];
|
||||
if (strlen($cert) > 0) {
|
||||
echo "Certificate fingerprint: $cert<br>\n";
|
||||
}
|
||||
|
||||
echo "Remediation: ";
|
||||
$rem = $row['remediation'];
|
||||
if ($rem == "") {
|
||||
echo "Not required";
|
||||
echo " [<a href=\"users.php?cmd=subrem-add-user&id=" .
|
||||
$row['rowid'] . "\">add:user</a>]";
|
||||
echo " [<a href=\"users.php?cmd=subrem-add-machine&id=" .
|
||||
$row['rowid'] . "\">add:machine</a>]";
|
||||
if ($row['methods'] == 'TLS') {
|
||||
echo " [<a href=\"users.php?cmd=subrem-add-reenroll&id=" .
|
||||
$row['rowid'] . "\">add:reenroll</a>]";
|
||||
}
|
||||
echo " [<a href=\"users.php?cmd=subrem-add-policy&id=" .
|
||||
$row['rowid'] . "\">add:policy</a>]";
|
||||
echo " [<a href=\"users.php?cmd=subrem-add-free&id=" .
|
||||
$row['rowid'] . "\">add:free</a>]";
|
||||
} else if ($rem == "user") {
|
||||
echo "User [<a href=\"users.php?cmd=subrem-clear&id=" .
|
||||
$row['rowid'] . "\">clear</a>]";
|
||||
} else if ($rem == "policy") {
|
||||
echo "Policy [<a href=\"users.php?cmd=subrem-clear&id=" .
|
||||
$row['rowid'] . "\">clear</a>]";
|
||||
} else if ($rem == "free") {
|
||||
echo "Free [<a href=\"users.php?cmd=subrem-clear&id=" .
|
||||
$row['rowid'] . "\">clear</a>]";
|
||||
} else if ($rem == "reenroll") {
|
||||
echo "Reenroll [<a href=\"users.php?cmd=subrem-clear&id=" .
|
||||
$row['rowid'] . "\">clear</a>]";
|
||||
} else {
|
||||
echo "Machine [<a href=\"users.php?cmd=subrem-clear&id=" .
|
||||
$row['rowid'] . "\">clear</a>]";
|
||||
}
|
||||
echo "<br>\n";
|
||||
|
||||
if (strncmp($row['identity'], "cert-", 5) != 0)
|
||||
echo "Machine managed: " . ($row['machine_managed'] == "1" ? "TRUE" : "FALSE") . "<br>\n";
|
||||
|
||||
echo "<form>Policy: <select name=\"policy\" " .
|
||||
"onChange=\"window.location='users.php?cmd=policy&id=" .
|
||||
$row['rowid'] . "&policy=' + this.value;\">\n";
|
||||
echo "<option value=\"" . $row['policy'] . "\" selected>" . $row['policy'] .
|
||||
"</option>\n";
|
||||
$files = scandir("$osu_root/spp/policy");
|
||||
foreach ($files as $file) {
|
||||
if (!preg_match("/.xml$/", $file))
|
||||
continue;
|
||||
if ($file == $row['policy'] . ".xml")
|
||||
continue;
|
||||
$p = substr($file, 0, -4);
|
||||
echo "<option value=\"$p\">$p</option>\n";
|
||||
}
|
||||
echo "<option value=\"no-policy\">no policy</option>\n";
|
||||
echo "</select></form>\n";
|
||||
|
||||
echo "<form>Account type: <select name=\"type\" " .
|
||||
"onChange=\"window.location='users.php?cmd=account-type&id=" .
|
||||
$row['rowid'] . "&type=' + this.value;\">\n";
|
||||
if ($row['shared'] > 0) {
|
||||
$default_sel = "";
|
||||
$shared_sel = " selected";
|
||||
} else {
|
||||
$default_sel = " selected";
|
||||
$shared_sel = "";
|
||||
}
|
||||
echo "<option value=\"default\"$default_sel>default</option>\n";
|
||||
echo "<option value=\"shared\"$shared_sel>shared</option>\n";
|
||||
echo "</select></form>\n";
|
||||
|
||||
echo "Phase 2 method(s): " . $row['methods'] . "<br>\n";
|
||||
|
||||
echo "<br>\n";
|
||||
echo "<a href=\"users.php?cmd=reset-pw&id=" .
|
||||
$row['rowid'] . "\">Reset AAA password</a><br>\n";
|
||||
|
||||
echo "<br>\n";
|
||||
echo "<form action=\"users.php?cmd=set-osu-cred&id=" . $row['rowid'] .
|
||||
"\" method=\"POST\">\n";
|
||||
echo "OSU credentials (if username empty, AAA credentials are used):<br>\n";
|
||||
echo "username: <input type=\"text\" name=\"osu_user\" value=\"" .
|
||||
$row['osu_user'] . "\">\n";
|
||||
echo "password: <input type=\"password\" name=\"osu_password\">\n";
|
||||
echo "<input type=\"submit\" value=\"Set OSU credentials\">\n";
|
||||
echo "</form>\n";
|
||||
|
||||
if (strlen($row['t_c_timestamp']) > 0) {
|
||||
echo "<br>\n";
|
||||
echo "<a href=\"users.php?cmd=clear-t-c&id=" .
|
||||
$row['rowid'] .
|
||||
"\">Clear Terms and Conditions acceptance</a><br>\n";
|
||||
}
|
||||
|
||||
echo "<hr>\n";
|
||||
|
||||
$user = $row['identity'];
|
||||
$osu_user = $row['osu_user'];
|
||||
$realm = $row['realm'];
|
||||
}
|
||||
|
||||
if ($id > 0 || ($id == 0 && $cmd == 'eventlog')) {
|
||||
|
||||
if ($id == 0) {
|
||||
echo "[<a href=\"users.php\">All users</a>] ";
|
||||
echo "<br>\n";
|
||||
}
|
||||
|
||||
echo "<table border=1>\n";
|
||||
echo "<tr>";
|
||||
if ($id == 0) {
|
||||
echo "<th>user<th>realm";
|
||||
}
|
||||
echo "<th>time<th>address<th>sessionID<th>notes";
|
||||
if ($dump > 0)
|
||||
echo "<th>dump";
|
||||
echo "\n";
|
||||
if (isset($_GET["limit"])) {
|
||||
$limit = $_GET["limit"];
|
||||
if (!is_numeric($limit))
|
||||
$limit = 20;
|
||||
} else
|
||||
$limit = 20;
|
||||
if ($id == 0)
|
||||
$res = $db->query("SELECT rowid,* FROM eventlog ORDER BY timestamp DESC LIMIT $limit");
|
||||
else if (strlen($osu_user) > 0)
|
||||
$res = $db->query("SELECT rowid,* FROM eventlog WHERE (user='$user' OR user='$osu_user') AND realm='$realm' ORDER BY timestamp DESC LIMIT $limit");
|
||||
else
|
||||
$res = $db->query("SELECT rowid,* FROM eventlog WHERE user='$user' AND realm='$realm' ORDER BY timestamp DESC LIMIT $limit");
|
||||
foreach ($res as $row) {
|
||||
echo "<tr>";
|
||||
if ($id == 0) {
|
||||
echo "<td>" . $row['user'] . "\n";
|
||||
echo "<td>" . $row['realm'] . "\n";
|
||||
}
|
||||
echo "<td>" . $row['timestamp'] . "\n";
|
||||
echo "<td>" . $row['addr'] . "\n";
|
||||
echo "<td>" . $row['sessionid'] . "\n";
|
||||
echo "<td>" . $row['notes'] . "\n";
|
||||
$d = $row['dump'];
|
||||
if (strlen($d) > 0) {
|
||||
echo "[<a href=\"users.php?cmd=eventlog&id=" . $row['rowid'] .
|
||||
"\">";
|
||||
if ($d[0] == '<')
|
||||
echo "XML";
|
||||
else
|
||||
echo "txt";
|
||||
echo "</a>]\n";
|
||||
if ($dump > 0)
|
||||
echo "<td>" . htmlspecialchars($d) . "\n";
|
||||
}
|
||||
}
|
||||
echo "</table>\n";
|
||||
|
||||
}
|
||||
|
||||
|
||||
if ($id == 0 && $cmd != 'eventlog') {
|
||||
|
||||
echo "[<a href=\"users.php?cmd=eventlog&limit=50\">Eventlog</a>] ";
|
||||
echo "<br>\n";
|
||||
|
||||
echo "<table border=1 cellspacing=0 cellpadding=0>\n";
|
||||
echo "<tr><th>User<th>Realm<th><small>Remediation</small><th>Policy<th><small>Account type</small><th><small>Phase 2 method(s)</small><th>DevId<th>MAC Address<th>T&C\n";
|
||||
|
||||
$res = $db->query('SELECT rowid,* FROM users WHERE (phase2=1 OR methods=\'TLS\') ORDER BY identity');
|
||||
foreach ($res as $row) {
|
||||
echo "<tr><td><a href=\"users.php?id=" . $row['rowid'] . "\"> " .
|
||||
$row['identity'] . " </a>";
|
||||
echo "<td>" . $row['realm'];
|
||||
$rem = $row['remediation'];
|
||||
echo "<td>";
|
||||
if ($rem == "") {
|
||||
echo "-";
|
||||
} else if ($rem == "user") {
|
||||
echo "User";
|
||||
} else if ($rem == "policy") {
|
||||
echo "Policy";
|
||||
} else if ($rem == "free") {
|
||||
echo "Free";
|
||||
} else if ($rem == "reenroll") {
|
||||
echo "Reenroll";
|
||||
} else {
|
||||
echo "Machine";
|
||||
}
|
||||
echo "<td>" . $row['policy'];
|
||||
if ($row['shared'] > 0)
|
||||
echo "<td>shared";
|
||||
else
|
||||
echo "<td>default";
|
||||
echo "<td><small>" . $row['methods'] . "</small>";
|
||||
echo "<td>";
|
||||
$xml = xml_parser_create();
|
||||
xml_parse_into_struct($xml, $row['devinfo'], $devinfo);
|
||||
foreach($devinfo as $k) {
|
||||
if ($k['tag'] == 'DEVID') {
|
||||
echo "<small>" . $k['value'] . "</small>";
|
||||
break;
|
||||
}
|
||||
}
|
||||
echo "<td><small>" . $row['mac_addr'] . "</small>";
|
||||
echo "<td><small>" . $row['t_c_timestamp'] . "</small>";
|
||||
echo "\n";
|
||||
}
|
||||
echo "</table>\n";
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
</html>
|
||||
12
contrib/wpa/src/Makefile
Normal file
12
contrib/wpa/src/Makefile
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
SUBDIRS=ap common crypto drivers eapol_auth eapol_supp eap_common eap_peer eap_server l2_packet p2p pae radius rsn_supp tls utils wps
|
||||
SUBDIRS += fst
|
||||
|
||||
all:
|
||||
for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d; done
|
||||
|
||||
clean:
|
||||
$(Q)for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d clean; done
|
||||
$(Q)rm -f *~
|
||||
|
||||
install:
|
||||
for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d install; done
|
||||
60
contrib/wpa/src/ap/Makefile
Normal file
60
contrib/wpa/src/ap/Makefile
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
CFLAGS += -DHOSTAPD
|
||||
CFLAGS += -DNEED_AP_MLME
|
||||
CFLAGS += -DCONFIG_ETH_P_OUI
|
||||
CFLAGS += -DCONFIG_HS20
|
||||
CFLAGS += -DCONFIG_INTERWORKING
|
||||
CFLAGS += -DCONFIG_IEEE80211R
|
||||
CFLAGS += -DCONFIG_IEEE80211R_AP
|
||||
CFLAGS += -DCONFIG_WPS
|
||||
CFLAGS += -DCONFIG_PROXYARP
|
||||
CFLAGS += -DCONFIG_IPV6
|
||||
CFLAGS += -DCONFIG_AIRTIME_POLICY
|
||||
|
||||
LIB_OBJS= \
|
||||
accounting.o \
|
||||
ap_config.o \
|
||||
ap_drv_ops.o \
|
||||
ap_list.o \
|
||||
ap_mlme.o \
|
||||
airtime_policy.o \
|
||||
authsrv.o \
|
||||
beacon.o \
|
||||
bss_load.o \
|
||||
ctrl_iface_ap.o \
|
||||
dfs.o \
|
||||
dhcp_snoop.o \
|
||||
drv_callbacks.o \
|
||||
eap_user_db.o \
|
||||
eth_p_oui.o \
|
||||
gas_serv.o \
|
||||
hostapd.o \
|
||||
hs20.o \
|
||||
hw_features.o \
|
||||
ieee802_11_auth.o \
|
||||
ieee802_11.o \
|
||||
ieee802_11_ht.o \
|
||||
ieee802_11_shared.o \
|
||||
ieee802_11_vht.o \
|
||||
ieee802_1x.o \
|
||||
neighbor_db.o \
|
||||
ndisc_snoop.o \
|
||||
p2p_hostapd.o \
|
||||
pmksa_cache_auth.o \
|
||||
preauth_auth.o \
|
||||
rrm.o \
|
||||
sta_info.o \
|
||||
tkip_countermeasures.o \
|
||||
utils.o \
|
||||
vlan.o \
|
||||
vlan_ifconfig.o \
|
||||
vlan_init.o \
|
||||
wmm.o \
|
||||
wnm_ap.o \
|
||||
wpa_auth.o \
|
||||
wpa_auth_ft.o \
|
||||
wpa_auth_glue.o \
|
||||
wpa_auth_ie.o \
|
||||
wps_hostapd.o \
|
||||
x_snoop.o
|
||||
|
||||
include ../lib.rules
|
||||
|
|
@ -261,13 +261,13 @@ static void acs_clean_chan_surveys(struct hostapd_channel_data *chan)
|
|||
}
|
||||
|
||||
|
||||
void acs_cleanup(struct hostapd_iface *iface)
|
||||
static void acs_cleanup_mode(struct hostapd_hw_modes *mode)
|
||||
{
|
||||
int i;
|
||||
struct hostapd_channel_data *chan;
|
||||
|
||||
for (i = 0; i < iface->current_mode->num_channels; i++) {
|
||||
chan = &iface->current_mode->channels[i];
|
||||
for (i = 0; i < mode->num_channels; i++) {
|
||||
chan = &mode->channels[i];
|
||||
|
||||
if (chan->flag & HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED)
|
||||
acs_clean_chan_surveys(chan);
|
||||
|
|
@ -276,6 +276,15 @@ void acs_cleanup(struct hostapd_iface *iface)
|
|||
chan->flag |= HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED;
|
||||
chan->min_nf = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void acs_cleanup(struct hostapd_iface *iface)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < iface->num_hw_features; i++)
|
||||
acs_cleanup_mode(&iface->hw_features[i]);
|
||||
|
||||
iface->chans_surveyed = 0;
|
||||
iface->acs_num_completed_scans = 0;
|
||||
|
|
@ -363,40 +372,47 @@ acs_survey_chan_interference_factor(struct hostapd_iface *iface,
|
|||
}
|
||||
|
||||
|
||||
static int acs_usable_ht40_chan(const struct hostapd_channel_data *chan)
|
||||
static int acs_usable_bw40_chan(const struct hostapd_channel_data *chan)
|
||||
{
|
||||
const int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149,
|
||||
157, 184, 192 };
|
||||
const int allowed[] = { 5180, 5220, 5260, 5300, 5500, 5540, 5580, 5620,
|
||||
5660, 5745, 5785, 4920, 4960, 5955, 5995, 6035,
|
||||
6075, 6115, 6155, 6195, 6235, 6275, 6315, 6355,
|
||||
6395, 6435, 6475, 6515, 6555, 6595, 6635, 6675,
|
||||
6715, 6755, 6795, 6835, 6875, 6915, 6955, 6995,
|
||||
7035, 7075 };
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(allowed); i++)
|
||||
if (chan->chan == allowed[i])
|
||||
if (chan->freq == allowed[i])
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int acs_usable_vht80_chan(const struct hostapd_channel_data *chan)
|
||||
static int acs_usable_bw80_chan(const struct hostapd_channel_data *chan)
|
||||
{
|
||||
const int allowed[] = { 36, 52, 100, 116, 132, 149 };
|
||||
const int allowed[] = { 5180, 5260, 5550, 5580, 5660, 5745, 5955, 6035,
|
||||
6115, 6195, 6275, 6355, 6435, 6515, 6595, 6675,
|
||||
6755, 6835, 6915, 6995 };
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(allowed); i++)
|
||||
if (chan->chan == allowed[i])
|
||||
if (chan->freq == allowed[i])
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int acs_usable_vht160_chan(const struct hostapd_channel_data *chan)
|
||||
static int acs_usable_bw160_chan(const struct hostapd_channel_data *chan)
|
||||
{
|
||||
const int allowed[] = { 36, 100 };
|
||||
const int allowed[] = { 5180, 5500, 5955, 6115, 6275, 6435, 6595, 6755,
|
||||
6915 };
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(allowed); i++)
|
||||
if (chan->chan == allowed[i])
|
||||
if (chan->freq == allowed[i])
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
|
@ -453,21 +469,35 @@ static int acs_survey_list_is_sufficient(struct hostapd_channel_data *chan)
|
|||
}
|
||||
|
||||
|
||||
static int acs_surveys_are_sufficient(struct hostapd_iface *iface)
|
||||
static int acs_surveys_are_sufficient_mode(struct hostapd_hw_modes *mode)
|
||||
{
|
||||
int i;
|
||||
struct hostapd_channel_data *chan;
|
||||
int valid = 0;
|
||||
|
||||
for (i = 0; i < iface->current_mode->num_channels; i++) {
|
||||
chan = &iface->current_mode->channels[i];
|
||||
for (i = 0; i < mode->num_channels; i++) {
|
||||
chan = &mode->channels[i];
|
||||
if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
|
||||
acs_survey_list_is_sufficient(chan))
|
||||
valid++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* We need at least survey data for one channel */
|
||||
return !!valid;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int acs_surveys_are_sufficient(struct hostapd_iface *iface)
|
||||
{
|
||||
int i;
|
||||
struct hostapd_hw_modes *mode;
|
||||
|
||||
for (i = 0; i < iface->num_hw_features; i++) {
|
||||
mode = &iface->hw_features[i];
|
||||
if (!hostapd_hw_skip_mode(iface, mode) &&
|
||||
acs_surveys_are_sufficient_mode(mode))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -489,14 +519,25 @@ static int is_in_chanlist(struct hostapd_iface *iface,
|
|||
}
|
||||
|
||||
|
||||
static void acs_survey_all_chans_intereference_factor(
|
||||
struct hostapd_iface *iface)
|
||||
static int is_in_freqlist(struct hostapd_iface *iface,
|
||||
struct hostapd_channel_data *chan)
|
||||
{
|
||||
if (!iface->conf->acs_freq_list.num)
|
||||
return 1;
|
||||
|
||||
return freq_range_list_includes(&iface->conf->acs_freq_list,
|
||||
chan->freq);
|
||||
}
|
||||
|
||||
|
||||
static void acs_survey_mode_interference_factor(
|
||||
struct hostapd_iface *iface, struct hostapd_hw_modes *mode)
|
||||
{
|
||||
int i;
|
||||
struct hostapd_channel_data *chan;
|
||||
|
||||
for (i = 0; i < iface->current_mode->num_channels; i++) {
|
||||
chan = &iface->current_mode->channels[i];
|
||||
for (i = 0; i < mode->num_channels; i++) {
|
||||
chan = &mode->channels[i];
|
||||
|
||||
if (!acs_usable_chan(chan))
|
||||
continue;
|
||||
|
|
@ -504,6 +545,9 @@ static void acs_survey_all_chans_intereference_factor(
|
|||
if (!is_in_chanlist(iface, chan))
|
||||
continue;
|
||||
|
||||
if (!is_in_freqlist(iface, chan))
|
||||
continue;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "ACS: Survey analysis for channel %d (%d MHz)",
|
||||
chan->chan, chan->freq);
|
||||
|
||||
|
|
@ -515,14 +559,28 @@ static void acs_survey_all_chans_intereference_factor(
|
|||
}
|
||||
|
||||
|
||||
static struct hostapd_channel_data *acs_find_chan(struct hostapd_iface *iface,
|
||||
int freq)
|
||||
static void acs_survey_all_chans_interference_factor(
|
||||
struct hostapd_iface *iface)
|
||||
{
|
||||
int i;
|
||||
struct hostapd_hw_modes *mode;
|
||||
|
||||
for (i = 0; i < iface->num_hw_features; i++) {
|
||||
mode = &iface->hw_features[i];
|
||||
if (!hostapd_hw_skip_mode(iface, mode))
|
||||
acs_survey_mode_interference_factor(iface, mode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct hostapd_channel_data *
|
||||
acs_find_chan_mode(struct hostapd_hw_modes *mode, int freq)
|
||||
{
|
||||
struct hostapd_channel_data *chan;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < iface->current_mode->num_channels; i++) {
|
||||
chan = &iface->current_mode->channels[i];
|
||||
for (i = 0; i < mode->num_channels; i++) {
|
||||
chan = &mode->channels[i];
|
||||
|
||||
if (chan->flag & HOSTAPD_CHAN_DISABLED)
|
||||
continue;
|
||||
|
|
@ -535,6 +593,26 @@ static struct hostapd_channel_data *acs_find_chan(struct hostapd_iface *iface,
|
|||
}
|
||||
|
||||
|
||||
static struct hostapd_channel_data *
|
||||
acs_find_chan(struct hostapd_iface *iface, int freq)
|
||||
{
|
||||
int i;
|
||||
struct hostapd_hw_modes *mode;
|
||||
struct hostapd_channel_data *chan;
|
||||
|
||||
for (i = 0; i < iface->num_hw_features; i++) {
|
||||
mode = &iface->hw_features[i];
|
||||
if (!hostapd_hw_skip_mode(iface, mode)) {
|
||||
chan = acs_find_chan_mode(mode, freq);
|
||||
if (chan)
|
||||
return chan;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int is_24ghz_mode(enum hostapd_hw_mode mode)
|
||||
{
|
||||
return mode == HOSTAPD_MODE_IEEE80211B ||
|
||||
|
|
@ -565,58 +643,24 @@ static int is_common_24ghz_chan(int chan)
|
|||
#define ACS_24GHZ_PREFER_1_6_11 0.8
|
||||
#endif /* ACS_24GHZ_PREFER_1_6_11 */
|
||||
|
||||
/*
|
||||
* At this point it's assumed chan->interface_factor has been computed.
|
||||
* This function should be reusable regardless of interference computation
|
||||
* option (survey, BSS, spectral, ...). chan->interference factor must be
|
||||
* summable (i.e., must be always greater than zero).
|
||||
*/
|
||||
static struct hostapd_channel_data *
|
||||
acs_find_ideal_chan(struct hostapd_iface *iface)
|
||||
static void
|
||||
acs_find_ideal_chan_mode(struct hostapd_iface *iface,
|
||||
struct hostapd_hw_modes *mode,
|
||||
int n_chans, u32 bw,
|
||||
struct hostapd_channel_data **rand_chan,
|
||||
struct hostapd_channel_data **ideal_chan,
|
||||
long double *ideal_factor)
|
||||
{
|
||||
struct hostapd_channel_data *chan, *adj_chan, *ideal_chan = NULL,
|
||||
*rand_chan = NULL;
|
||||
long double factor, ideal_factor = 0;
|
||||
struct hostapd_channel_data *chan, *adj_chan = NULL;
|
||||
long double factor;
|
||||
int i, j;
|
||||
int n_chans = 1;
|
||||
u32 bw;
|
||||
unsigned int k;
|
||||
|
||||
/* TODO: HT40- support */
|
||||
|
||||
if (iface->conf->ieee80211n &&
|
||||
iface->conf->secondary_channel == -1) {
|
||||
wpa_printf(MSG_ERROR, "ACS: HT40- is not supported yet. Please try HT40+");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (iface->conf->ieee80211n &&
|
||||
iface->conf->secondary_channel)
|
||||
n_chans = 2;
|
||||
|
||||
if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) {
|
||||
switch (hostapd_get_oper_chwidth(iface->conf)) {
|
||||
case CHANWIDTH_80MHZ:
|
||||
n_chans = 4;
|
||||
break;
|
||||
case CHANWIDTH_160MHZ:
|
||||
n_chans = 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bw = num_chan_to_bw(n_chans);
|
||||
|
||||
/* TODO: VHT/HE80+80. Update acs_adjust_center_freq() too. */
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"ACS: Survey analysis for selected bandwidth %d MHz", bw);
|
||||
|
||||
for (i = 0; i < iface->current_mode->num_channels; i++) {
|
||||
for (i = 0; i < mode->num_channels; i++) {
|
||||
double total_weight;
|
||||
struct acs_bias *bias, tmp_bias;
|
||||
|
||||
chan = &iface->current_mode->channels[i];
|
||||
chan = &mode->channels[i];
|
||||
|
||||
/* Since in the current ACS implementation the first channel is
|
||||
* always a primary channel, skip channels not available as
|
||||
|
|
@ -628,6 +672,9 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
|
|||
if (!is_in_chanlist(iface, chan))
|
||||
continue;
|
||||
|
||||
if (!is_in_freqlist(iface, chan))
|
||||
continue;
|
||||
|
||||
if (!chan_bw_allowed(chan, bw, 1, 1)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"ACS: Channel %d: BW %u is not supported",
|
||||
|
|
@ -637,31 +684,33 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
|
|||
|
||||
/* HT40 on 5 GHz has a limited set of primary channels as per
|
||||
* 11n Annex J */
|
||||
if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
|
||||
iface->conf->ieee80211n &&
|
||||
iface->conf->secondary_channel &&
|
||||
!acs_usable_ht40_chan(chan)) {
|
||||
wpa_printf(MSG_DEBUG, "ACS: Channel %d: not allowed as primary channel for HT40",
|
||||
if (mode->mode == HOSTAPD_MODE_IEEE80211A &&
|
||||
((iface->conf->ieee80211n &&
|
||||
iface->conf->secondary_channel) ||
|
||||
is_6ghz_freq(chan->freq)) &&
|
||||
!acs_usable_bw40_chan(chan)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"ACS: Channel %d: not allowed as primary channel for 40 MHz bandwidth",
|
||||
chan->chan);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
|
||||
if (mode->mode == HOSTAPD_MODE_IEEE80211A &&
|
||||
(iface->conf->ieee80211ac || iface->conf->ieee80211ax)) {
|
||||
if (hostapd_get_oper_chwidth(iface->conf) ==
|
||||
CHANWIDTH_80MHZ &&
|
||||
!acs_usable_vht80_chan(chan)) {
|
||||
!acs_usable_bw80_chan(chan)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"ACS: Channel %d: not allowed as primary channel for VHT80",
|
||||
"ACS: Channel %d: not allowed as primary channel for 80 MHz bandwidth",
|
||||
chan->chan);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hostapd_get_oper_chwidth(iface->conf) ==
|
||||
CHANWIDTH_160MHZ &&
|
||||
!acs_usable_vht160_chan(chan)) {
|
||||
!acs_usable_bw160_chan(chan)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"ACS: Channel %d: not allowed as primary channel for VHT160",
|
||||
"ACS: Channel %d: not allowed as primary channel for 160 MHz bandwidth",
|
||||
chan->chan);
|
||||
continue;
|
||||
}
|
||||
|
|
@ -698,7 +747,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
|
|||
|
||||
/* 2.4 GHz has overlapping 20 MHz channels. Include adjacent
|
||||
* channel interference factor. */
|
||||
if (is_24ghz_mode(iface->current_mode->mode)) {
|
||||
if (is_24ghz_mode(mode->mode)) {
|
||||
for (j = 0; j < n_chans; j++) {
|
||||
adj_chan = acs_find_chan(iface, chan->freq +
|
||||
(j * 20) - 5);
|
||||
|
|
@ -744,7 +793,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
|
|||
break;
|
||||
bias = NULL;
|
||||
}
|
||||
} else if (is_24ghz_mode(iface->current_mode->mode) &&
|
||||
} else if (is_24ghz_mode(mode->mode) &&
|
||||
is_common_24ghz_chan(chan->chan)) {
|
||||
tmp_bias.channel = chan->chan;
|
||||
tmp_bias.bias = ACS_24GHZ_PREFER_1_6_11;
|
||||
|
|
@ -763,14 +812,78 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
|
|||
}
|
||||
|
||||
if (acs_usable_chan(chan) &&
|
||||
(!ideal_chan || factor < ideal_factor)) {
|
||||
ideal_factor = factor;
|
||||
ideal_chan = chan;
|
||||
(!*ideal_chan || factor < *ideal_factor)) {
|
||||
*ideal_factor = factor;
|
||||
*ideal_chan = chan;
|
||||
}
|
||||
|
||||
/* This channel would at least be usable */
|
||||
if (!rand_chan)
|
||||
rand_chan = chan;
|
||||
if (!(*rand_chan))
|
||||
*rand_chan = chan;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* At this point it's assumed chan->interference_factor has been computed.
|
||||
* This function should be reusable regardless of interference computation
|
||||
* option (survey, BSS, spectral, ...). chan->interference factor must be
|
||||
* summable (i.e., must be always greater than zero).
|
||||
*/
|
||||
static struct hostapd_channel_data *
|
||||
acs_find_ideal_chan(struct hostapd_iface *iface)
|
||||
{
|
||||
struct hostapd_channel_data *ideal_chan = NULL,
|
||||
*rand_chan = NULL;
|
||||
long double ideal_factor = 0;
|
||||
int i;
|
||||
int n_chans = 1;
|
||||
u32 bw;
|
||||
struct hostapd_hw_modes *mode;
|
||||
|
||||
if (is_6ghz_op_class(iface->conf->op_class)) {
|
||||
bw = op_class_to_bandwidth(iface->conf->op_class);
|
||||
n_chans = bw / 20;
|
||||
goto bw_selected;
|
||||
}
|
||||
|
||||
/* TODO: HT40- support */
|
||||
|
||||
if (iface->conf->ieee80211n &&
|
||||
iface->conf->secondary_channel == -1) {
|
||||
wpa_printf(MSG_ERROR, "ACS: HT40- is not supported yet. Please try HT40+");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (iface->conf->ieee80211n &&
|
||||
iface->conf->secondary_channel)
|
||||
n_chans = 2;
|
||||
|
||||
if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) {
|
||||
switch (hostapd_get_oper_chwidth(iface->conf)) {
|
||||
case CHANWIDTH_80MHZ:
|
||||
n_chans = 4;
|
||||
break;
|
||||
case CHANWIDTH_160MHZ:
|
||||
n_chans = 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bw = num_chan_to_bw(n_chans);
|
||||
|
||||
bw_selected:
|
||||
/* TODO: VHT/HE80+80. Update acs_adjust_center_freq() too. */
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"ACS: Survey analysis for selected bandwidth %d MHz", bw);
|
||||
|
||||
for (i = 0; i < iface->num_hw_features; i++) {
|
||||
mode = &iface->hw_features[i];
|
||||
if (!hostapd_hw_skip_mode(iface, mode))
|
||||
acs_find_ideal_chan_mode(iface, mode, n_chans, bw,
|
||||
&rand_chan, &ideal_chan,
|
||||
&ideal_factor);
|
||||
}
|
||||
|
||||
if (ideal_chan) {
|
||||
|
|
@ -826,7 +939,7 @@ static int acs_study_survey_based(struct hostapd_iface *iface)
|
|||
return -1;
|
||||
}
|
||||
|
||||
acs_survey_all_chans_intereference_factor(iface);
|
||||
acs_survey_all_chans_interference_factor(iface);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -862,6 +975,7 @@ static void acs_study(struct hostapd_iface *iface)
|
|||
}
|
||||
|
||||
iface->conf->channel = ideal_chan->chan;
|
||||
iface->freq = ideal_chan->freq;
|
||||
|
||||
if (iface->conf->ieee80211ac || iface->conf->ieee80211ax)
|
||||
acs_adjust_center_freq(iface);
|
||||
|
|
@ -917,31 +1031,67 @@ fail:
|
|||
}
|
||||
|
||||
|
||||
static int acs_request_scan(struct hostapd_iface *iface)
|
||||
static int * acs_request_scan_add_freqs(struct hostapd_iface *iface,
|
||||
struct hostapd_hw_modes *mode,
|
||||
int *freq)
|
||||
{
|
||||
struct wpa_driver_scan_params params;
|
||||
struct hostapd_channel_data *chan;
|
||||
int i, *freq;
|
||||
int i;
|
||||
|
||||
os_memset(¶ms, 0, sizeof(params));
|
||||
params.freqs = os_calloc(iface->current_mode->num_channels + 1,
|
||||
sizeof(params.freqs[0]));
|
||||
if (params.freqs == NULL)
|
||||
return -1;
|
||||
|
||||
freq = params.freqs;
|
||||
for (i = 0; i < iface->current_mode->num_channels; i++) {
|
||||
chan = &iface->current_mode->channels[i];
|
||||
for (i = 0; i < mode->num_channels; i++) {
|
||||
chan = &mode->channels[i];
|
||||
if (chan->flag & HOSTAPD_CHAN_DISABLED)
|
||||
continue;
|
||||
|
||||
if (!is_in_chanlist(iface, chan))
|
||||
continue;
|
||||
|
||||
if (!is_in_freqlist(iface, chan))
|
||||
continue;
|
||||
|
||||
*freq++ = chan->freq;
|
||||
}
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
|
||||
static int acs_request_scan(struct hostapd_iface *iface)
|
||||
{
|
||||
struct wpa_driver_scan_params params;
|
||||
int i, *freq;
|
||||
int num_channels;
|
||||
struct hostapd_hw_modes *mode;
|
||||
|
||||
os_memset(¶ms, 0, sizeof(params));
|
||||
|
||||
num_channels = 0;
|
||||
for (i = 0; i < iface->num_hw_features; i++) {
|
||||
mode = &iface->hw_features[i];
|
||||
if (!hostapd_hw_skip_mode(iface, mode))
|
||||
num_channels += mode->num_channels;
|
||||
}
|
||||
|
||||
params.freqs = os_calloc(num_channels + 1, sizeof(params.freqs[0]));
|
||||
if (params.freqs == NULL)
|
||||
return -1;
|
||||
|
||||
freq = params.freqs;
|
||||
|
||||
for (i = 0; i < iface->num_hw_features; i++) {
|
||||
mode = &iface->hw_features[i];
|
||||
if (!hostapd_hw_skip_mode(iface, mode))
|
||||
freq = acs_request_scan_add_freqs(iface, mode, freq);
|
||||
}
|
||||
|
||||
*freq = 0;
|
||||
|
||||
if (params.freqs == freq) {
|
||||
wpa_printf(MSG_ERROR, "ACS: No available channels found");
|
||||
os_free(params.freqs);
|
||||
return -1;
|
||||
}
|
||||
|
||||
iface->scan_cb = acs_scan_complete;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "ACS: Scanning %d / %d",
|
||||
|
|
@ -971,7 +1121,8 @@ enum hostapd_chan_status acs_init(struct hostapd_iface *iface)
|
|||
return HOSTAPD_CHAN_ACS;
|
||||
}
|
||||
|
||||
if (!iface->current_mode)
|
||||
if (!iface->current_mode &&
|
||||
iface->conf->hw_mode != HOSTAPD_MODE_IEEE80211ANY)
|
||||
return HOSTAPD_CHAN_INVALID;
|
||||
|
||||
acs_cleanup(iface);
|
||||
|
|
|
|||
|
|
@ -79,6 +79,10 @@ static void count_backlogged_sta(struct hostapd_data *hapd)
|
|||
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
||||
if (hostapd_drv_read_sta_data(hapd, &data, sta->addr))
|
||||
continue;
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
if (hapd->force_backlog_bytes)
|
||||
data.backlog_bytes = 1;
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
if (data.backlog_bytes > 0)
|
||||
set_new_backlog_time(hapd, sta, &now);
|
||||
|
|
@ -134,8 +138,8 @@ static void update_airtime_weights(void *eloop_data, void *user_data)
|
|||
unsigned int num_sta_min = 0, num_sta_prod = 1, num_sta_sum = 0,
|
||||
wt_sum = 0;
|
||||
unsigned int quantum;
|
||||
Boolean all_div_min = TRUE;
|
||||
Boolean apply_limit = iface->conf->airtime_mode == AIRTIME_MODE_DYNAMIC;
|
||||
bool all_div_min = true;
|
||||
bool apply_limit = iface->conf->airtime_mode == AIRTIME_MODE_DYNAMIC;
|
||||
int wt, num_bss = 0, max_wt = 0;
|
||||
size_t i;
|
||||
|
||||
|
|
@ -169,7 +173,7 @@ static void update_airtime_weights(void *eloop_data, void *user_data)
|
|||
* integers. */
|
||||
if (bss->num_backlogged_sta &&
|
||||
bss->num_backlogged_sta % num_sta_min > 0)
|
||||
all_div_min = FALSE;
|
||||
all_div_min = false;
|
||||
|
||||
/* If we're in LIMIT mode, we only apply the weight
|
||||
* scaling when the BSS(es) marked as limited would a
|
||||
|
|
@ -178,7 +182,7 @@ static void update_airtime_weights(void *eloop_data, void *user_data)
|
|||
if (!apply_limit && bss->conf->airtime_limit) {
|
||||
if (bss->num_backlogged_sta * wt_sum >
|
||||
bss->conf->airtime_weight * num_sta_sum)
|
||||
apply_limit = TRUE;
|
||||
apply_limit = true;
|
||||
}
|
||||
}
|
||||
if (all_div_min)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include "common/ieee802_1x_defs.h"
|
||||
#include "common/eapol_common.h"
|
||||
#include "common/dhcp.h"
|
||||
#include "common/sae.h"
|
||||
#include "eap_common/eap_wsc_common.h"
|
||||
#include "eap_server/eap.h"
|
||||
#include "wpa_auth.h"
|
||||
|
|
@ -53,23 +54,33 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
|
|||
bss->logger_syslog = (unsigned int) -1;
|
||||
bss->logger_stdout = (unsigned int) -1;
|
||||
|
||||
#ifdef CONFIG_WEP
|
||||
bss->auth_algs = WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED;
|
||||
|
||||
bss->wep_rekeying_period = 300;
|
||||
/* use key0 in individual key and key1 in broadcast key */
|
||||
bss->broadcast_key_idx_min = 1;
|
||||
bss->broadcast_key_idx_max = 2;
|
||||
#else /* CONFIG_WEP */
|
||||
bss->auth_algs = WPA_AUTH_ALG_OPEN;
|
||||
#endif /* CONFIG_WEP */
|
||||
bss->eap_reauth_period = 3600;
|
||||
|
||||
bss->wpa_group_rekey = 600;
|
||||
bss->wpa_gmk_rekey = 86400;
|
||||
bss->wpa_deny_ptk0_rekey = PTK0_REKEY_ALLOW_ALWAYS;
|
||||
bss->wpa_group_update_count = 4;
|
||||
bss->wpa_pairwise_update_count = 4;
|
||||
bss->wpa_disable_eapol_key_retries =
|
||||
DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES;
|
||||
bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
|
||||
#ifdef CONFIG_NO_TKIP
|
||||
bss->wpa_pairwise = WPA_CIPHER_CCMP;
|
||||
bss->wpa_group = WPA_CIPHER_CCMP;
|
||||
#else /* CONFIG_NO_TKIP */
|
||||
bss->wpa_pairwise = WPA_CIPHER_TKIP;
|
||||
bss->wpa_group = WPA_CIPHER_TKIP;
|
||||
#endif /* CONFIG_NO_TKIP */
|
||||
bss->rsn_pairwise = 0;
|
||||
|
||||
bss->max_num_sta = MAX_STA_COUNT;
|
||||
|
|
@ -86,11 +97,9 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
|
|||
|
||||
bss->pwd_group = 19; /* ECC: GF(p=256) */
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
bss->assoc_sa_query_max_timeout = 1000;
|
||||
bss->assoc_sa_query_retry_timeout = 201;
|
||||
bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef EAP_SERVER_FAST
|
||||
/* both anonymous and authenticated provisioning */
|
||||
bss->eap_fast_prov = 3;
|
||||
|
|
@ -112,7 +121,7 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
|
|||
|
||||
bss->radius_das_time_window = 300;
|
||||
|
||||
bss->sae_anti_clogging_threshold = 5;
|
||||
bss->anti_clogging_threshold = 5;
|
||||
bss->sae_sync = 5;
|
||||
|
||||
bss->gas_frag_limit = 1400;
|
||||
|
|
@ -122,6 +131,7 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
|
|||
bss->fils_hlp_wait_time = 30;
|
||||
bss->dhcp_server_port = DHCP_SERVER_PORT;
|
||||
bss->dhcp_relay_port = DHCP_SERVER_PORT;
|
||||
bss->fils_discovery_min_int = 20;
|
||||
#endif /* CONFIG_FILS */
|
||||
|
||||
bss->broadcast_deauth = 1;
|
||||
|
|
@ -135,6 +145,9 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
|
|||
* completed and tested with other implementations. */
|
||||
bss->tls_flags = TLS_CONN_DISABLE_TLSv1_3;
|
||||
|
||||
bss->max_auth_rounds = 100;
|
||||
bss->max_auth_rounds_short = 50;
|
||||
|
||||
bss->send_probe_response = 1;
|
||||
|
||||
#ifdef CONFIG_HS20
|
||||
|
|
@ -148,6 +161,15 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
|
|||
|
||||
/* Default to strict CRL checking. */
|
||||
bss->check_crl_strict = 1;
|
||||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
bss->sae_commit_status = -1;
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
#ifdef CONFIG_PASN
|
||||
/* comeback after 10 TUs */
|
||||
bss->pasn_comeback_after = 10;
|
||||
#endif /* CONFIG_PASN */
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -249,6 +271,14 @@ struct hostapd_config * hostapd_config_defaults(void)
|
|||
HE_OPERATION_RTS_THRESHOLD_OFFSET;
|
||||
/* Set default basic MCS/NSS set to single stream MCS 0-7 */
|
||||
conf->he_op.he_basic_mcs_nss_set = 0xfffc;
|
||||
conf->he_op.he_bss_color_disabled = 1;
|
||||
conf->he_op.he_bss_color_partial = 0;
|
||||
conf->he_op.he_bss_color = 1;
|
||||
conf->he_op.he_twt_responder = 1;
|
||||
conf->he_6ghz_max_mpdu = 2;
|
||||
conf->he_6ghz_max_ampdu_len_exp = 7;
|
||||
conf->he_6ghz_rx_ant_pat = 1;
|
||||
conf->he_6ghz_tx_ant_pat = 1;
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
|
||||
/* The third octet of the country string uses an ASCII space character
|
||||
|
|
@ -299,6 +329,7 @@ static int hostapd_config_read_wpa_psk(const char *fname,
|
|||
|
||||
while (fgets(buf, sizeof(buf), f)) {
|
||||
int vlan_id = 0;
|
||||
int wps = 0;
|
||||
|
||||
line++;
|
||||
|
||||
|
|
@ -329,6 +360,8 @@ static int hostapd_config_read_wpa_psk(const char *fname,
|
|||
value = "";
|
||||
if (!os_strcmp(name, "keyid")) {
|
||||
keyid = value;
|
||||
} else if (!os_strcmp(name, "wps")) {
|
||||
wps = atoi(value);
|
||||
} else if (!os_strcmp(name, "vlanid")) {
|
||||
vlan_id = atoi(value);
|
||||
} else {
|
||||
|
|
@ -346,8 +379,9 @@ static int hostapd_config_read_wpa_psk(const char *fname,
|
|||
if (!token)
|
||||
token = "";
|
||||
if (hwaddr_aton(token, addr)) {
|
||||
wpa_printf(MSG_ERROR, "Invalid MAC address '%s' on "
|
||||
"line %d in '%s'", token, line, fname);
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Invalid MAC address '%s' on line %d in '%s'",
|
||||
token, line, fname);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
|
@ -375,16 +409,17 @@ static int hostapd_config_read_wpa_psk(const char *fname,
|
|||
|
||||
ok = 0;
|
||||
len = os_strlen(pos);
|
||||
if (len == 64 && hexstr2bin(pos, psk->psk, PMK_LEN) == 0)
|
||||
if (len == 2 * PMK_LEN &&
|
||||
hexstr2bin(pos, psk->psk, PMK_LEN) == 0)
|
||||
ok = 1;
|
||||
else if (len >= 8 && len < 64) {
|
||||
pbkdf2_sha1(pos, ssid->ssid, ssid->ssid_len,
|
||||
4096, psk->psk, PMK_LEN);
|
||||
else if (len >= 8 && len < 64 &&
|
||||
pbkdf2_sha1(pos, ssid->ssid, ssid->ssid_len,
|
||||
4096, psk->psk, PMK_LEN) == 0)
|
||||
ok = 1;
|
||||
}
|
||||
if (!ok) {
|
||||
wpa_printf(MSG_ERROR, "Invalid PSK '%s' on line %d in "
|
||||
"'%s'", pos, line, fname);
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Invalid PSK '%s' on line %d in '%s'",
|
||||
pos, line, fname);
|
||||
os_free(psk);
|
||||
ret = -1;
|
||||
break;
|
||||
|
|
@ -402,6 +437,8 @@ static int hostapd_config_read_wpa_psk(const char *fname,
|
|||
}
|
||||
}
|
||||
|
||||
psk->wps = wps;
|
||||
|
||||
psk->next = ssid->wpa_psk;
|
||||
ssid->wpa_psk = psk;
|
||||
}
|
||||
|
|
@ -433,10 +470,53 @@ static int hostapd_derive_psk(struct hostapd_ssid *ssid)
|
|||
}
|
||||
|
||||
|
||||
int hostapd_setup_sae_pt(struct hostapd_bss_config *conf)
|
||||
{
|
||||
#ifdef CONFIG_SAE
|
||||
struct hostapd_ssid *ssid = &conf->ssid;
|
||||
struct sae_password_entry *pw;
|
||||
|
||||
if ((conf->sae_pwe == 0 && !hostapd_sae_pw_id_in_use(conf) &&
|
||||
!hostapd_sae_pk_in_use(conf)) ||
|
||||
conf->sae_pwe == 3 ||
|
||||
!wpa_key_mgmt_sae(conf->wpa_key_mgmt))
|
||||
return 0; /* PT not needed */
|
||||
|
||||
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,
|
||||
(const u8 *) ssid->wpa_passphrase,
|
||||
os_strlen(ssid->wpa_passphrase),
|
||||
NULL);
|
||||
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,
|
||||
(const u8 *) pw->password,
|
||||
os_strlen(pw->password),
|
||||
pw->identifier);
|
||||
if (!pw->pt)
|
||||
return -1;
|
||||
}
|
||||
#endif /* CONFIG_SAE */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf)
|
||||
{
|
||||
struct hostapd_ssid *ssid = &conf->ssid;
|
||||
|
||||
if (hostapd_setup_sae_pt(conf) < 0)
|
||||
return -1;
|
||||
|
||||
if (ssid->wpa_passphrase != NULL) {
|
||||
if (ssid->wpa_psk != NULL) {
|
||||
wpa_printf(MSG_DEBUG, "Using pre-configured WPA PSK "
|
||||
|
|
@ -581,6 +661,7 @@ void hostapd_config_free_eap_users(struct hostapd_eap_user *user)
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_WEP
|
||||
static void hostapd_config_free_wep(struct hostapd_wep_keys *keys)
|
||||
{
|
||||
int i;
|
||||
|
|
@ -589,6 +670,7 @@ static void hostapd_config_free_wep(struct hostapd_wep_keys *keys)
|
|||
keys->key[i] = NULL;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_WEP */
|
||||
|
||||
|
||||
void hostapd_config_clear_wpa_psk(struct hostapd_wpa_psk **l)
|
||||
|
|
@ -642,6 +724,12 @@ static void hostapd_config_free_sae_passwords(struct hostapd_bss_config *conf)
|
|||
pw = pw->next;
|
||||
str_clear_free(tmp->password);
|
||||
os_free(tmp->identifier);
|
||||
#ifdef CONFIG_SAE
|
||||
sae_deinit_pt(tmp->pt);
|
||||
#endif /* CONFIG_SAE */
|
||||
#ifdef CONFIG_SAE_PK
|
||||
sae_deinit_pk(tmp->pk);
|
||||
#endif /* CONFIG_SAE_PK */
|
||||
os_free(tmp);
|
||||
}
|
||||
}
|
||||
|
|
@ -674,10 +762,15 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
|
|||
|
||||
str_clear_free(conf->ssid.wpa_passphrase);
|
||||
os_free(conf->ssid.wpa_psk_file);
|
||||
#ifdef CONFIG_WEP
|
||||
hostapd_config_free_wep(&conf->ssid.wep);
|
||||
#endif /* CONFIG_WEP */
|
||||
#ifdef CONFIG_FULL_DYNAMIC_VLAN
|
||||
os_free(conf->ssid.vlan_tagged_interface);
|
||||
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
|
||||
#ifdef CONFIG_SAE
|
||||
sae_deinit_pt(conf->ssid.pt);
|
||||
#endif /* CONFIG_SAE */
|
||||
|
||||
hostapd_config_free_eap_users(conf->eap_user);
|
||||
os_free(conf->eap_user_sqlite);
|
||||
|
|
@ -692,6 +785,7 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
|
|||
conf->radius->num_auth_servers);
|
||||
hostapd_config_free_radius(conf->radius->acct_servers,
|
||||
conf->radius->num_acct_servers);
|
||||
os_free(conf->radius->force_client_dev);
|
||||
}
|
||||
hostapd_config_free_radius_attr(conf->radius_auth_req_attr);
|
||||
hostapd_config_free_radius_attr(conf->radius_acct_req_attr);
|
||||
|
|
@ -765,6 +859,7 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
|
|||
os_free(conf->upc);
|
||||
for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++)
|
||||
wpabuf_free(conf->wps_vendor_ext[i]);
|
||||
wpabuf_free(conf->wps_application_ext);
|
||||
wpabuf_free(conf->wps_nfc_dh_pubkey);
|
||||
wpabuf_free(conf->wps_nfc_dh_privkey);
|
||||
wpabuf_free(conf->wps_nfc_dev_pw);
|
||||
|
|
@ -832,6 +927,12 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
|
|||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
wpabuf_free(conf->own_ie_override);
|
||||
wpabuf_free(conf->sae_commit_override);
|
||||
wpabuf_free(conf->rsne_override_eapol);
|
||||
wpabuf_free(conf->rsnxe_override_eapol);
|
||||
wpabuf_free(conf->rsne_override_ft);
|
||||
wpabuf_free(conf->rsnxe_override_ft);
|
||||
wpabuf_free(conf->gtk_rsc_override);
|
||||
wpabuf_free(conf->igtk_rsc_override);
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
os_free(conf->no_probe_resp_if_seen_on);
|
||||
|
|
@ -840,6 +941,8 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
|
|||
hostapd_config_free_fils_realms(conf);
|
||||
|
||||
#ifdef CONFIG_DPP
|
||||
os_free(conf->dpp_name);
|
||||
os_free(conf->dpp_mud_url);
|
||||
os_free(conf->dpp_connector);
|
||||
wpabuf_free(conf->dpp_netaccesskey);
|
||||
wpabuf_free(conf->dpp_csign);
|
||||
|
|
@ -864,6 +967,10 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
|
|||
}
|
||||
#endif /* CONFIG_AIRTIME_POLICY */
|
||||
|
||||
#ifdef CONFIG_PASN
|
||||
os_free(conf->pasn_groups);
|
||||
#endif /* CONFIG_PASN */
|
||||
|
||||
os_free(conf);
|
||||
}
|
||||
|
||||
|
|
@ -885,6 +992,7 @@ void hostapd_config_free(struct hostapd_config *conf)
|
|||
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);
|
||||
#ifdef CONFIG_ACS
|
||||
os_free(conf->acs_chan_bias);
|
||||
|
|
@ -1027,10 +1135,85 @@ const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_SAE_PK
|
||||
static bool hostapd_sae_pk_password_without_pk(struct hostapd_bss_config *bss)
|
||||
{
|
||||
struct sae_password_entry *pw;
|
||||
bool res = false;
|
||||
|
||||
if (bss->ssid.wpa_passphrase &&
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
!bss->sae_pk_password_check_skip &&
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
sae_pk_valid_password(bss->ssid.wpa_passphrase))
|
||||
res = true;
|
||||
|
||||
for (pw = bss->sae_passwords; pw; pw = pw->next) {
|
||||
if (!pw->pk &&
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
!bss->sae_pk_password_check_skip &&
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
sae_pk_valid_password(pw->password))
|
||||
return true;
|
||||
|
||||
if (bss->ssid.wpa_passphrase && res && pw->pk &&
|
||||
os_strcmp(bss->ssid.wpa_passphrase, pw->password) == 0)
|
||||
res = false;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif /* CONFIG_SAE_PK */
|
||||
|
||||
|
||||
static bool hostapd_config_check_bss_6g(struct hostapd_bss_config *bss)
|
||||
{
|
||||
if (bss->wpa != WPA_PROTO_RSN) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Pre-RSNA security methods are not allowed in 6 GHz");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bss->ieee80211w != MGMT_FRAME_PROTECTION_REQUIRED) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Management frame protection is required in 6 GHz");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bss->wpa_key_mgmt & (WPA_KEY_MGMT_PSK |
|
||||
WPA_KEY_MGMT_FT_PSK |
|
||||
WPA_KEY_MGMT_PSK_SHA256)) {
|
||||
wpa_printf(MSG_ERROR, "Invalid AKM suite for 6 GHz");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bss->rsn_pairwise & (WPA_CIPHER_WEP40 |
|
||||
WPA_CIPHER_WEP104 |
|
||||
WPA_CIPHER_TKIP)) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Invalid pairwise cipher suite for 6 GHz");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bss->wpa_group & (WPA_CIPHER_WEP40 |
|
||||
WPA_CIPHER_WEP104 |
|
||||
WPA_CIPHER_TKIP)) {
|
||||
wpa_printf(MSG_ERROR, "Invalid group cipher suite for 6 GHz");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
|
||||
struct hostapd_config *conf,
|
||||
int full_config)
|
||||
{
|
||||
if (full_config && is_6ghz_op_class(conf->op_class) &&
|
||||
!hostapd_config_check_bss_6g(bss))
|
||||
return -1;
|
||||
|
||||
if (full_config && bss->ieee802_1x && !bss->eap_server &&
|
||||
!bss->radius->auth_servers) {
|
||||
wpa_printf(MSG_ERROR, "Invalid IEEE 802.1X configuration (no "
|
||||
|
|
@ -1038,6 +1221,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
|
|||
return -1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_WEP
|
||||
if (bss->wpa) {
|
||||
int wep, i;
|
||||
|
||||
|
|
@ -1055,6 +1239,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_WEP */
|
||||
|
||||
if (full_config && bss->wpa &&
|
||||
bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
|
||||
|
|
@ -1102,52 +1287,75 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
|
|||
}
|
||||
#endif /* CONFIG_IEEE80211R_AP */
|
||||
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
if (full_config && conf->ieee80211n &&
|
||||
conf->hw_mode == HOSTAPD_MODE_IEEE80211B) {
|
||||
bss->disable_11n = 1;
|
||||
bss->disable_11n = true;
|
||||
wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) in 11b mode is not "
|
||||
"allowed, disabling HT capabilities");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_WEP
|
||||
if (full_config && conf->ieee80211n &&
|
||||
bss->ssid.security_policy == SECURITY_STATIC_WEP) {
|
||||
bss->disable_11n = 1;
|
||||
bss->disable_11n = true;
|
||||
wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WEP is not "
|
||||
"allowed, disabling HT capabilities");
|
||||
}
|
||||
#endif /* CONFIG_WEP */
|
||||
|
||||
if (full_config && conf->ieee80211n && bss->wpa &&
|
||||
!(bss->wpa_pairwise & WPA_CIPHER_CCMP) &&
|
||||
!(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
|
||||
WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256)))
|
||||
{
|
||||
bss->disable_11n = 1;
|
||||
bss->disable_11n = true;
|
||||
wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WPA/WPA2 "
|
||||
"requires CCMP/GCMP to be enabled, disabling HT "
|
||||
"capabilities");
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
#ifdef CONFIG_IEEE80211AC
|
||||
#ifdef CONFIG_WEP
|
||||
if (full_config && conf->ieee80211ac &&
|
||||
bss->ssid.security_policy == SECURITY_STATIC_WEP) {
|
||||
bss->disable_11ac = 1;
|
||||
bss->disable_11ac = true;
|
||||
wpa_printf(MSG_ERROR,
|
||||
"VHT (IEEE 802.11ac) with WEP is not allowed, disabling VHT capabilities");
|
||||
}
|
||||
#endif /* CONFIG_WEP */
|
||||
|
||||
if (full_config && conf->ieee80211ac && bss->wpa &&
|
||||
!(bss->wpa_pairwise & WPA_CIPHER_CCMP) &&
|
||||
!(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
|
||||
WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256)))
|
||||
{
|
||||
bss->disable_11ac = 1;
|
||||
bss->disable_11ac = true;
|
||||
wpa_printf(MSG_ERROR,
|
||||
"VHT (IEEE 802.11ac) with WPA/WPA2 requires CCMP/GCMP to be enabled, disabling VHT capabilities");
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211AC */
|
||||
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
#ifdef CONFIG_WEP
|
||||
if (full_config && conf->ieee80211ax &&
|
||||
bss->ssid.security_policy == SECURITY_STATIC_WEP) {
|
||||
bss->disable_11ax = true;
|
||||
wpa_printf(MSG_ERROR,
|
||||
"HE (IEEE 802.11ax) with WEP is not allowed, disabling HE capabilities");
|
||||
}
|
||||
#endif /* CONFIG_WEP */
|
||||
|
||||
if (full_config && conf->ieee80211ax && bss->wpa &&
|
||||
!(bss->wpa_pairwise & WPA_CIPHER_CCMP) &&
|
||||
!(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
|
||||
WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256)))
|
||||
{
|
||||
bss->disable_11ax = true;
|
||||
wpa_printf(MSG_ERROR,
|
||||
"HE (IEEE 802.11ax) with WPA/WPA2 requires CCMP/GCMP to be enabled, disabling HE capabilities");
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
if (full_config && bss->wps_state && bss->ignore_broadcast_ssid) {
|
||||
wpa_printf(MSG_INFO, "WPS: ignore_broadcast_ssid "
|
||||
|
|
@ -1155,12 +1363,14 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
|
|||
bss->wps_state = 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_WEP
|
||||
if (full_config && bss->wps_state &&
|
||||
bss->ssid.wep.keys_set && bss->wpa == 0) {
|
||||
wpa_printf(MSG_INFO, "WPS: WEP configuration forced WPS to be "
|
||||
"disabled");
|
||||
bss->wps_state = 0;
|
||||
}
|
||||
#endif /* CONFIG_WEP */
|
||||
|
||||
if (full_config && bss->wps_state && bss->wpa &&
|
||||
(!(bss->wpa & 2) ||
|
||||
|
|
@ -1204,6 +1414,15 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
|
|||
}
|
||||
#endif /* CONFIG_OCV */
|
||||
|
||||
#ifdef CONFIG_SAE_PK
|
||||
if (full_config && hostapd_sae_pk_in_use(bss) &&
|
||||
hostapd_sae_pk_password_without_pk(bss)) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"SAE-PK: SAE password uses SAE-PK style, but does not have PK configured");
|
||||
return -1;
|
||||
}
|
||||
#endif /* CONFIG_SAE_PK */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1284,11 +1503,13 @@ int hostapd_config_check(struct hostapd_config *conf, int full_config)
|
|||
void hostapd_set_security_params(struct hostapd_bss_config *bss,
|
||||
int full_config)
|
||||
{
|
||||
#ifdef CONFIG_WEP
|
||||
if (bss->individual_wep_key_len == 0) {
|
||||
/* individual keys are not use; can use key idx0 for
|
||||
* broadcast keys */
|
||||
bss->broadcast_key_idx_min = 0;
|
||||
}
|
||||
#endif /* CONFIG_WEP */
|
||||
|
||||
if ((bss->wpa & 2) && bss->rsn_pairwise == 0)
|
||||
bss->rsn_pairwise = bss->wpa_pairwise;
|
||||
|
|
@ -1314,6 +1535,7 @@ void hostapd_set_security_params(struct hostapd_bss_config *bss,
|
|||
} else if (bss->ieee802_1x) {
|
||||
int cipher = WPA_CIPHER_NONE;
|
||||
bss->ssid.security_policy = SECURITY_IEEE_802_1X;
|
||||
#ifdef CONFIG_WEP
|
||||
bss->ssid.wep.default_len = bss->default_wep_key_len;
|
||||
if (full_config && bss->default_wep_key_len) {
|
||||
cipher = bss->default_wep_key_len >= 13 ?
|
||||
|
|
@ -1324,11 +1546,13 @@ void hostapd_set_security_params(struct hostapd_bss_config *bss,
|
|||
else
|
||||
cipher = WPA_CIPHER_WEP40;
|
||||
}
|
||||
#endif /* CONFIG_WEP */
|
||||
bss->wpa_group = cipher;
|
||||
bss->wpa_pairwise = cipher;
|
||||
bss->rsn_pairwise = cipher;
|
||||
if (full_config)
|
||||
bss->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
|
||||
#ifdef CONFIG_WEP
|
||||
} else if (bss->ssid.wep.keys_set) {
|
||||
int cipher = WPA_CIPHER_WEP40;
|
||||
if (bss->ssid.wep.len[0] >= 13)
|
||||
|
|
@ -1339,6 +1563,7 @@ void hostapd_set_security_params(struct hostapd_bss_config *bss,
|
|||
bss->rsn_pairwise = cipher;
|
||||
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;
|
||||
|
|
@ -1377,3 +1602,38 @@ int hostapd_sae_pw_id_in_use(struct hostapd_bss_config *conf)
|
|||
return 2;
|
||||
return with_id;
|
||||
}
|
||||
|
||||
|
||||
bool hostapd_sae_pk_in_use(struct hostapd_bss_config *conf)
|
||||
{
|
||||
#ifdef CONFIG_SAE_PK
|
||||
struct sae_password_entry *pw;
|
||||
|
||||
for (pw = conf->sae_passwords; pw; pw = pw->next) {
|
||||
if (pw->pk)
|
||||
return true;
|
||||
}
|
||||
#endif /* CONFIG_SAE_PK */
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_SAE_PK
|
||||
bool hostapd_sae_pk_exclusively(struct hostapd_bss_config *conf)
|
||||
{
|
||||
bool with_pk = false;
|
||||
struct sae_password_entry *pw;
|
||||
|
||||
if (conf->ssid.wpa_passphrase)
|
||||
return false;
|
||||
|
||||
for (pw = conf->sae_passwords; pw; pw = pw->next) {
|
||||
if (!pw->pk)
|
||||
return false;
|
||||
with_pk = true;
|
||||
}
|
||||
|
||||
return with_pk;
|
||||
}
|
||||
#endif /* CONFIG_SAE_PK */
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ struct hostapd_radius_servers;
|
|||
struct ft_remote_r0kh;
|
||||
struct ft_remote_r1kh;
|
||||
|
||||
#ifdef CONFIG_WEP
|
||||
#define NUM_WEP_KEYS 4
|
||||
struct hostapd_wep_keys {
|
||||
u8 idx;
|
||||
|
|
@ -75,10 +76,13 @@ struct hostapd_wep_keys {
|
|||
int keys_set;
|
||||
size_t default_len; /* key length used for dynamic key generation */
|
||||
};
|
||||
#endif /* CONFIG_WEP */
|
||||
|
||||
typedef enum hostap_security_policy {
|
||||
SECURITY_PLAINTEXT = 0,
|
||||
#ifdef CONFIG_WEP
|
||||
SECURITY_STATIC_WEP = 1,
|
||||
#endif /* CONFIG_WEP */
|
||||
SECURITY_IEEE_802_1X = 2,
|
||||
SECURITY_WPA_PSK = 3,
|
||||
SECURITY_WPA = 4,
|
||||
|
|
@ -88,6 +92,7 @@ typedef enum hostap_security_policy {
|
|||
struct hostapd_ssid {
|
||||
u8 ssid[SSID_MAX_LEN];
|
||||
size_t ssid_len;
|
||||
u32 short_ssid;
|
||||
unsigned int ssid_set:1;
|
||||
unsigned int utf8_ssid:1;
|
||||
unsigned int wpa_passphrase_set:1;
|
||||
|
|
@ -99,8 +104,11 @@ struct hostapd_ssid {
|
|||
struct hostapd_wpa_psk *wpa_psk;
|
||||
char *wpa_passphrase;
|
||||
char *wpa_psk_file;
|
||||
struct sae_pt *pt;
|
||||
|
||||
#ifdef CONFIG_WEP
|
||||
struct hostapd_wep_keys wep;
|
||||
#endif /* CONFIG_WEP */
|
||||
|
||||
#define DYNAMIC_VLAN_DISABLED 0
|
||||
#define DYNAMIC_VLAN_OPTIONAL 1
|
||||
|
|
@ -150,6 +158,7 @@ struct hostapd_wpa_psk {
|
|||
struct hostapd_wpa_psk *next;
|
||||
int group;
|
||||
char keyid[KEYID_LEN];
|
||||
int wps;
|
||||
u8 psk[PMK_LEN];
|
||||
u8 addr[ETH_ALEN];
|
||||
u8 p2p_dev_addr[ETH_ALEN];
|
||||
|
|
@ -188,15 +197,6 @@ struct hostapd_radius_attr {
|
|||
|
||||
|
||||
#define NUM_TX_QUEUES 4
|
||||
|
||||
struct hostapd_tx_queue_params {
|
||||
int aifs;
|
||||
int cwmin;
|
||||
int cwmax;
|
||||
int burst; /* maximum burst time in 0.1 ms, i.e., 10 = 1 ms */
|
||||
};
|
||||
|
||||
|
||||
#define MAX_ROAMING_CONSORTIUM_LEN 15
|
||||
|
||||
struct hostapd_roaming_consortium {
|
||||
|
|
@ -251,6 +251,8 @@ struct sae_password_entry {
|
|||
char *identifier;
|
||||
u8 peer_addr[ETH_ALEN];
|
||||
int vlan_id;
|
||||
struct sae_pt *pt;
|
||||
struct sae_pk *pk;
|
||||
};
|
||||
|
||||
struct dpp_controller_conf {
|
||||
|
|
@ -265,6 +267,8 @@ struct airtime_sta_weight {
|
|||
u8 addr[ETH_ALEN];
|
||||
};
|
||||
|
||||
#define EXT_CAPA_MAX_LEN 15
|
||||
|
||||
/**
|
||||
* struct hostapd_bss_config - Per-BSS configuration
|
||||
*/
|
||||
|
|
@ -317,18 +321,16 @@ struct hostapd_bss_config {
|
|||
size_t eap_req_id_text_len;
|
||||
int eapol_key_index_workaround;
|
||||
|
||||
#ifdef CONFIG_WEP
|
||||
size_t default_wep_key_len;
|
||||
int individual_wep_key_len;
|
||||
int wep_rekeying_period;
|
||||
int broadcast_key_idx_min, broadcast_key_idx_max;
|
||||
#endif /* CONFIG_WEP */
|
||||
int eap_reauth_period;
|
||||
int erp_send_reauth_start;
|
||||
char *erp_domain;
|
||||
|
||||
int ieee802_11f; /* use IEEE 802.11f (IAPP) */
|
||||
char iapp_iface[IFNAMSIZ + 1]; /* interface used with IAPP broadcast
|
||||
* frames */
|
||||
|
||||
enum macaddr_acl {
|
||||
ACCEPT_UNLESS_DENIED = 0,
|
||||
DENY_UNLESS_ACCEPTED = 1,
|
||||
|
|
@ -346,15 +348,15 @@ struct hostapd_bss_config {
|
|||
* algorithms, WPA_AUTH_ALG_{OPEN,SHARED,LEAP} */
|
||||
|
||||
int wpa; /* bitfield of WPA_PROTO_WPA, WPA_PROTO_RSN */
|
||||
int extended_key_id;
|
||||
int wpa_key_mgmt;
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
enum mfp_options ieee80211w;
|
||||
int group_mgmt_cipher;
|
||||
int beacon_prot;
|
||||
/* dot11AssociationSAQueryMaximumTimeout (in TUs) */
|
||||
unsigned int assoc_sa_query_max_timeout;
|
||||
/* dot11AssociationSAQueryRetryTimeout (in TUs) */
|
||||
int assoc_sa_query_retry_timeout;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_OCV
|
||||
int ocv; /* Operating Channel Validation */
|
||||
#endif /* CONFIG_OCV */
|
||||
|
|
@ -371,6 +373,7 @@ struct hostapd_bss_config {
|
|||
int wpa_strict_rekey;
|
||||
int wpa_gmk_rekey;
|
||||
int wpa_ptk_rekey;
|
||||
enum ptk0_rekey_handling wpa_deny_ptk0_rekey;
|
||||
u32 wpa_group_update_count;
|
||||
u32 wpa_pairwise_update_count;
|
||||
int wpa_disable_eapol_key_retries;
|
||||
|
|
@ -415,6 +418,8 @@ struct hostapd_bss_config {
|
|||
unsigned int crl_reload_interval;
|
||||
unsigned int tls_session_lifetime;
|
||||
unsigned int tls_flags;
|
||||
unsigned int max_auth_rounds;
|
||||
unsigned int max_auth_rounds_short;
|
||||
char *ocsp_stapling_response;
|
||||
char *ocsp_stapling_response_multi;
|
||||
char *dh_file;
|
||||
|
|
@ -429,6 +434,8 @@ struct hostapd_bss_config {
|
|||
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_sim_aka_result_ind;
|
||||
int eap_sim_id;
|
||||
int tnc;
|
||||
|
|
@ -497,6 +504,7 @@ struct hostapd_bss_config {
|
|||
char *model_url;
|
||||
char *upc;
|
||||
struct wpabuf *wps_vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
|
||||
struct wpabuf *wps_application_ext;
|
||||
int wps_nfc_pw_from_config;
|
||||
int wps_nfc_dev_pw_id;
|
||||
struct wpabuf *wps_nfc_dh_pubkey;
|
||||
|
|
@ -525,8 +533,9 @@ struct hostapd_bss_config {
|
|||
#define TDLS_PROHIBIT BIT(0)
|
||||
#define TDLS_PROHIBIT_CHAN_SWITCH BIT(1)
|
||||
int tdls;
|
||||
int disable_11n;
|
||||
int disable_11ac;
|
||||
bool disable_11n;
|
||||
bool disable_11ac;
|
||||
bool disable_11ax;
|
||||
|
||||
/* IEEE 802.11v */
|
||||
int time_advertisement;
|
||||
|
|
@ -648,9 +657,11 @@ struct hostapd_bss_config {
|
|||
struct wpabuf *vendor_elements;
|
||||
struct wpabuf *assocresp_elements;
|
||||
|
||||
unsigned int sae_anti_clogging_threshold;
|
||||
unsigned int anti_clogging_threshold;
|
||||
unsigned int sae_sync;
|
||||
int sae_require_mfp;
|
||||
int sae_confirm_immediate;
|
||||
int sae_pwe;
|
||||
int *sae_groups;
|
||||
struct sae_password_entry *sae_passwords;
|
||||
|
||||
|
|
@ -661,7 +672,26 @@ struct hostapd_bss_config {
|
|||
u8 bss_load_test_set;
|
||||
struct wpabuf *own_ie_override;
|
||||
int sae_reflection_attack;
|
||||
int sae_commit_status;
|
||||
int sae_pk_omit;
|
||||
int sae_pk_password_check_skip;
|
||||
struct wpabuf *sae_commit_override;
|
||||
struct wpabuf *rsne_override_eapol;
|
||||
struct wpabuf *rsnxe_override_eapol;
|
||||
struct wpabuf *rsne_override_ft;
|
||||
struct wpabuf *rsnxe_override_ft;
|
||||
struct wpabuf *gtk_rsc_override;
|
||||
struct wpabuf *igtk_rsc_override;
|
||||
int no_beacon_rsnxe;
|
||||
int skip_prune_assoc;
|
||||
int ft_rsnxe_used;
|
||||
unsigned int oci_freq_override_eapol_m3;
|
||||
unsigned int oci_freq_override_eapol_g1;
|
||||
unsigned int oci_freq_override_saquery_req;
|
||||
unsigned int oci_freq_override_saquery_resp;
|
||||
unsigned int oci_freq_override_ft_assoc;
|
||||
unsigned int oci_freq_override_fils_assoc;
|
||||
unsigned int oci_freq_override_wnm_sleep;
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
#define MESH_ENABLED BIT(0)
|
||||
|
|
@ -702,19 +732,27 @@ struct hostapd_bss_config {
|
|||
unsigned int fils_hlp_wait_time;
|
||||
u16 dhcp_server_port;
|
||||
u16 dhcp_relay_port;
|
||||
u32 fils_discovery_min_int;
|
||||
u32 fils_discovery_max_int;
|
||||
#endif /* CONFIG_FILS */
|
||||
|
||||
int multicast_to_unicast;
|
||||
|
||||
int broadcast_deauth;
|
||||
|
||||
int notify_mgmt_frames;
|
||||
|
||||
#ifdef CONFIG_DPP
|
||||
char *dpp_name;
|
||||
char *dpp_mud_url;
|
||||
char *dpp_connector;
|
||||
struct wpabuf *dpp_netaccesskey;
|
||||
unsigned int dpp_netaccesskey_expiry;
|
||||
struct wpabuf *dpp_csign;
|
||||
#ifdef CONFIG_DPP2
|
||||
struct dpp_controller_conf *dpp_controller;
|
||||
int dpp_configurator_connectivity;
|
||||
int dpp_pfs;
|
||||
#endif /* CONFIG_DPP2 */
|
||||
#endif /* CONFIG_DPP */
|
||||
|
||||
|
|
@ -724,12 +762,15 @@ struct hostapd_bss_config {
|
|||
size_t owe_transition_ssid_len;
|
||||
char owe_transition_ifname[IFNAMSIZ + 1];
|
||||
int *owe_groups;
|
||||
int owe_ptk_workaround;
|
||||
#endif /* CONFIG_OWE */
|
||||
|
||||
int coloc_intf_reporting;
|
||||
|
||||
u8 send_probe_response;
|
||||
|
||||
u8 transition_disable;
|
||||
|
||||
#define BACKHAUL_BSS 1
|
||||
#define FRONTHAUL_BSS 2
|
||||
int multi_ap; /* bitmap of BACKHAUL_BSS, FRONTHAUL_BSS */
|
||||
|
|
@ -827,15 +868,41 @@ struct hostapd_bss_config {
|
|||
*/
|
||||
u8 mka_psk_set;
|
||||
#endif /* CONFIG_MACSEC */
|
||||
|
||||
#ifdef CONFIG_PASN
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
/*
|
||||
* Normally, KDK should be derived if and only if both sides support
|
||||
* secure LTF. Allow forcing KDK derivation for testing purposes.
|
||||
*/
|
||||
int force_kdk_derivation;
|
||||
|
||||
/* If set, corrupt the MIC in the 2nd Authentication frame of PASN */
|
||||
int pasn_corrupt_mic;
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
int *pasn_groups;
|
||||
|
||||
/*
|
||||
* The time in TUs after which the non-AP STA is requested to retry the
|
||||
* PASN authentication in case there are too many parallel operations.
|
||||
*/
|
||||
u16 pasn_comeback_after;
|
||||
#endif /* CONFIG_PASN */
|
||||
|
||||
unsigned int unsol_bcast_probe_resp_interval;
|
||||
|
||||
u8 ext_capa_mask[EXT_CAPA_MAX_LEN];
|
||||
u8 ext_capa[EXT_CAPA_MAX_LEN];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct he_phy_capabilities_info - HE PHY capabilities
|
||||
*/
|
||||
struct he_phy_capabilities_info {
|
||||
Boolean he_su_beamformer;
|
||||
Boolean he_su_beamformee;
|
||||
Boolean he_mu_beamformer;
|
||||
bool he_su_beamformer;
|
||||
bool he_su_beamformee;
|
||||
bool he_mu_beamformer;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -843,8 +910,11 @@ struct he_phy_capabilities_info {
|
|||
*/
|
||||
struct he_operation {
|
||||
u8 he_bss_color;
|
||||
u8 he_bss_color_disabled;
|
||||
u8 he_bss_color_partial;
|
||||
u8 he_default_pe_duration;
|
||||
u8 he_twt_required;
|
||||
u8 he_twt_responder;
|
||||
u16 he_rts_threshold;
|
||||
u16 he_basic_mcs_nss_set;
|
||||
};
|
||||
|
|
@ -857,8 +927,8 @@ struct spatial_reuse {
|
|||
u8 non_srg_obss_pd_max_offset;
|
||||
u8 srg_obss_pd_min_offset;
|
||||
u8 srg_obss_pd_max_offset;
|
||||
u8 srg_obss_color_bitmap;
|
||||
u8 srg_obss_color_partial_bitmap;
|
||||
u8 srg_bss_color_bitmap[8];
|
||||
u8 srg_partial_bssid_bitmap[8];
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -871,11 +941,17 @@ struct hostapd_config {
|
|||
u16 beacon_int;
|
||||
int rts_threshold;
|
||||
int fragm_threshold;
|
||||
u8 op_class;
|
||||
u8 channel;
|
||||
int enable_edmg;
|
||||
u8 edmg_channel;
|
||||
u8 acs;
|
||||
struct wpa_freq_range_list acs_ch_list;
|
||||
struct wpa_freq_range_list acs_freq_list;
|
||||
u8 acs_freq_list_present;
|
||||
int acs_exclude_dfs;
|
||||
enum hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */
|
||||
int acs_exclude_6ghz_non_psc;
|
||||
enum {
|
||||
LONG_PREAMBLE = 0,
|
||||
SHORT_PREAMBLE = 1
|
||||
|
|
@ -987,6 +1063,10 @@ struct hostapd_config {
|
|||
u8 he_oper_chwidth;
|
||||
u8 he_oper_centr_freq_seg0_idx;
|
||||
u8 he_oper_centr_freq_seg1_idx;
|
||||
u8 he_6ghz_max_mpdu;
|
||||
u8 he_6ghz_max_ampdu_len_exp;
|
||||
u8 he_6ghz_rx_ant_pat;
|
||||
u8 he_6ghz_tx_ant_pat;
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
|
||||
/* VHT enable/disable config from CHAN_SWITCH */
|
||||
|
|
@ -994,8 +1074,14 @@ struct hostapd_config {
|
|||
#define CH_SWITCH_VHT_DISABLED BIT(1)
|
||||
unsigned int ch_switch_vht_config;
|
||||
|
||||
/* HE enable/disable config from CHAN_SWITCH */
|
||||
#define CH_SWITCH_HE_ENABLED BIT(0)
|
||||
#define CH_SWITCH_HE_DISABLED BIT(1)
|
||||
unsigned int ch_switch_he_config;
|
||||
|
||||
int rssi_reject_assoc_rssi;
|
||||
int rssi_reject_assoc_timeout;
|
||||
int rssi_ignore_probe_request;
|
||||
|
||||
#ifdef CONFIG_AIRTIME_POLICY
|
||||
enum {
|
||||
|
|
@ -1100,5 +1186,8 @@ int hostapd_config_check(struct hostapd_config *conf, int full_config);
|
|||
void hostapd_set_security_params(struct hostapd_bss_config *bss,
|
||||
int full_config);
|
||||
int hostapd_sae_pw_id_in_use(struct hostapd_bss_config *conf);
|
||||
bool hostapd_sae_pk_in_use(struct hostapd_bss_config *conf);
|
||||
bool hostapd_sae_pk_exclusively(struct hostapd_bss_config *conf);
|
||||
int hostapd_setup_sae_pt(struct hostapd_bss_config *conf);
|
||||
|
||||
#endif /* HOSTAPD_CONFIG_H */
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "utils/common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/ieee802_11_common.h"
|
||||
#include "common/hw_features_common.h"
|
||||
#include "wps/wps.h"
|
||||
#include "p2p/p2p.h"
|
||||
|
|
@ -107,6 +108,10 @@ 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 (add_buf(&beacon, hapd->wps_beacon_ie) < 0 ||
|
||||
add_buf(&proberesp, hapd->wps_probe_resp_ie) < 0)
|
||||
goto fail;
|
||||
|
|
@ -305,9 +310,7 @@ int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname,
|
|||
params.wpa_pairwise = hapd->conf->wpa_pairwise;
|
||||
params.wpa_key_mgmt = hapd->conf->wpa_key_mgmt;
|
||||
params.rsn_preauth = hapd->conf->rsn_preauth;
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
params.ieee80211w = hapd->conf->ieee80211w;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
}
|
||||
return hostapd_set_ieee8021x(hapd, ¶ms);
|
||||
}
|
||||
|
|
@ -348,7 +351,7 @@ int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr,
|
|||
u16 auth_alg)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->add_sta_node == NULL)
|
||||
return 0;
|
||||
return -EOPNOTSUPP;
|
||||
return hapd->driver->add_sta_node(hapd->drv_priv, addr, auth_alg);
|
||||
}
|
||||
|
||||
|
|
@ -415,6 +418,7 @@ int hostapd_sta_add(struct hostapd_data *hapd,
|
|||
const struct ieee80211_vht_capabilities *vht_capab,
|
||||
const struct ieee80211_he_capabilities *he_capab,
|
||||
size_t he_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)
|
||||
{
|
||||
|
|
@ -436,6 +440,7 @@ int hostapd_sta_add(struct hostapd_data *hapd,
|
|||
params.vht_capabilities = vht_capab;
|
||||
params.he_capab = he_capab;
|
||||
params.he_capab_len = he_capab_len;
|
||||
params.he_6ghz_capab = he_6ghz_capab;
|
||||
params.vht_opmode_enabled = !!(flags & WLAN_STA_VHT_OPMODE_ENABLED);
|
||||
params.vht_opmode = vht_opmode;
|
||||
params.flags = hostapd_sta_flags_to_drv(flags);
|
||||
|
|
@ -540,7 +545,8 @@ int hostapd_flush(struct hostapd_data *hapd)
|
|||
|
||||
|
||||
int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode,
|
||||
int freq, int channel, int ht_enabled, int vht_enabled,
|
||||
int freq, int channel, int edmg, u8 edmg_channel,
|
||||
int ht_enabled, int vht_enabled,
|
||||
int he_enabled,
|
||||
int sec_channel_offset, int oper_chwidth,
|
||||
int center_segment0, int center_segment1)
|
||||
|
|
@ -548,7 +554,8 @@ int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode,
|
|||
struct hostapd_freq_params data;
|
||||
struct hostapd_hw_modes *cmode = hapd->iface->current_mode;
|
||||
|
||||
if (hostapd_set_freq_params(&data, mode, freq, channel, ht_enabled,
|
||||
if (hostapd_set_freq_params(&data, mode, freq, channel, edmg,
|
||||
edmg_channel, ht_enabled,
|
||||
vht_enabled, he_enabled, sec_channel_offset,
|
||||
oper_chwidth,
|
||||
center_segment0, center_segment1,
|
||||
|
|
@ -583,7 +590,7 @@ int hostapd_set_frag(struct hostapd_data *hapd, int frag)
|
|||
int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
|
||||
int total_flags, int flags_or, int flags_and)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->sta_set_flags == NULL)
|
||||
if (!hapd->driver || !hapd->drv_priv || !hapd->driver->sta_set_flags)
|
||||
return 0;
|
||||
return hapd->driver->sta_set_flags(hapd->drv_priv, addr, total_flags,
|
||||
flags_or, flags_and);
|
||||
|
|
@ -645,6 +652,12 @@ int hostapd_drv_none(struct hostapd_data *hapd)
|
|||
}
|
||||
|
||||
|
||||
bool hostapd_drv_nl80211(struct hostapd_data *hapd)
|
||||
{
|
||||
return hapd->driver && os_strcmp(hapd->driver->name, "nl80211") == 0;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_driver_scan(struct hostapd_data *hapd,
|
||||
struct wpa_driver_scan_params *params)
|
||||
{
|
||||
|
|
@ -675,36 +688,41 @@ int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start,
|
|||
|
||||
int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd,
|
||||
enum wpa_alg alg, const u8 *addr,
|
||||
int key_idx, int set_tx,
|
||||
int key_idx, int vlan_id, int set_tx,
|
||||
const u8 *seq, size_t seq_len,
|
||||
const u8 *key, size_t key_len)
|
||||
const u8 *key, size_t key_len, enum key_flag key_flag)
|
||||
{
|
||||
struct wpa_driver_set_key_params params;
|
||||
|
||||
if (hapd->driver == NULL || hapd->driver->set_key == NULL)
|
||||
return 0;
|
||||
return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr,
|
||||
key_idx, set_tx, seq, seq_len, key,
|
||||
key_len);
|
||||
|
||||
os_memset(¶ms, 0, sizeof(params));
|
||||
params.ifname = ifname;
|
||||
params.alg = alg;
|
||||
params.addr = addr;
|
||||
params.key_idx = key_idx;
|
||||
params.set_tx = set_tx;
|
||||
params.seq = seq;
|
||||
params.seq_len = seq_len;
|
||||
params.key = key;
|
||||
params.key_len = key_len;
|
||||
params.vlan_id = vlan_id;
|
||||
params.key_flag = key_flag;
|
||||
|
||||
return hapd->driver->set_key(hapd->drv_priv, ¶ms);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_drv_send_mlme(struct hostapd_data *hapd,
|
||||
const void *msg, size_t len, int noack)
|
||||
const void *msg, size_t len, int noack,
|
||||
const u16 *csa_offs, size_t csa_offs_len,
|
||||
int no_encrypt)
|
||||
{
|
||||
if (!hapd->driver || !hapd->driver->send_mlme || !hapd->drv_priv)
|
||||
return 0;
|
||||
return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0,
|
||||
NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_drv_send_mlme_csa(struct hostapd_data *hapd,
|
||||
const void *msg, size_t len, int noack,
|
||||
const u16 *csa_offs, size_t csa_offs_len)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
|
||||
return 0;
|
||||
return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0,
|
||||
csa_offs, csa_offs_len);
|
||||
csa_offs, csa_offs_len, no_encrypt, 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -810,7 +828,8 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface,
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (hostapd_set_freq_params(&data, mode, freq, channel, ht_enabled,
|
||||
if (hostapd_set_freq_params(&data, mode, freq, channel, 0, 0,
|
||||
ht_enabled,
|
||||
vht_enabled, he_enabled, sec_channel_offset,
|
||||
oper_chwidth, center_segment0,
|
||||
center_segment1,
|
||||
|
|
@ -850,10 +869,24 @@ static void hostapd_get_hw_mode_any_channels(struct hostapd_data *hapd,
|
|||
for (i = 0; i < mode->num_channels; i++) {
|
||||
struct hostapd_channel_data *chan = &mode->channels[i];
|
||||
|
||||
if ((acs_ch_list_all ||
|
||||
freq_range_list_includes(&hapd->iface->conf->acs_ch_list,
|
||||
chan->chan)) &&
|
||||
!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
|
||||
if (!acs_ch_list_all &&
|
||||
(hapd->iface->conf->acs_freq_list.num &&
|
||||
!freq_range_list_includes(
|
||||
&hapd->iface->conf->acs_freq_list,
|
||||
chan->freq)))
|
||||
continue;
|
||||
if (!acs_ch_list_all &&
|
||||
(!hapd->iface->conf->acs_freq_list_present &&
|
||||
hapd->iface->conf->acs_ch_list.num &&
|
||||
!freq_range_list_includes(
|
||||
&hapd->iface->conf->acs_ch_list,
|
||||
chan->chan)))
|
||||
continue;
|
||||
if (is_6ghz_freq(chan->freq) &&
|
||||
hapd->iface->conf->acs_exclude_6ghz_non_psc &&
|
||||
!is_6ghz_psc_frequency(chan->freq))
|
||||
continue;
|
||||
if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
|
||||
!(hapd->iface->conf->acs_exclude_dfs &&
|
||||
(chan->flag & HOSTAPD_CHAN_RADAR)))
|
||||
int_array_add_unique(freq_list, chan->freq);
|
||||
|
|
@ -879,10 +912,9 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd)
|
|||
{
|
||||
struct drv_acs_params params;
|
||||
int ret, i, acs_ch_list_all = 0;
|
||||
u8 *channels = NULL;
|
||||
unsigned int num_channels = 0;
|
||||
struct hostapd_hw_modes *mode;
|
||||
int *freq_list = NULL;
|
||||
enum hostapd_hw_mode selected_mode;
|
||||
|
||||
if (hapd->driver == NULL || hapd->driver->do_acs == NULL)
|
||||
return 0;
|
||||
|
|
@ -894,42 +926,27 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd)
|
|||
* If no chanlist config parameter is provided, include all enabled
|
||||
* channels of the selected hw_mode.
|
||||
*/
|
||||
if (!hapd->iface->conf->acs_ch_list.num)
|
||||
acs_ch_list_all = 1;
|
||||
if (hapd->iface->conf->acs_freq_list_present)
|
||||
acs_ch_list_all = !hapd->iface->conf->acs_freq_list.num;
|
||||
else
|
||||
acs_ch_list_all = !hapd->iface->conf->acs_ch_list.num;
|
||||
|
||||
mode = hapd->iface->current_mode;
|
||||
if (mode) {
|
||||
channels = os_malloc(mode->num_channels);
|
||||
if (channels == NULL)
|
||||
return -1;
|
||||
if (hapd->iface->current_mode)
|
||||
selected_mode = hapd->iface->current_mode->mode;
|
||||
else
|
||||
selected_mode = HOSTAPD_MODE_IEEE80211ANY;
|
||||
|
||||
for (i = 0; i < mode->num_channels; i++) {
|
||||
struct hostapd_channel_data *chan = &mode->channels[i];
|
||||
if (!acs_ch_list_all &&
|
||||
!freq_range_list_includes(
|
||||
&hapd->iface->conf->acs_ch_list,
|
||||
chan->chan))
|
||||
continue;
|
||||
if (hapd->iface->conf->acs_exclude_dfs &&
|
||||
(chan->flag & HOSTAPD_CHAN_RADAR))
|
||||
continue;
|
||||
if (!(chan->flag & HOSTAPD_CHAN_DISABLED)) {
|
||||
channels[num_channels++] = chan->chan;
|
||||
int_array_add_unique(&freq_list, chan->freq);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < hapd->iface->num_hw_features; i++) {
|
||||
mode = &hapd->iface->hw_features[i];
|
||||
hostapd_get_hw_mode_any_channels(hapd, mode,
|
||||
acs_ch_list_all,
|
||||
&freq_list);
|
||||
}
|
||||
for (i = 0; i < hapd->iface->num_hw_features; i++) {
|
||||
mode = &hapd->iface->hw_features[i];
|
||||
if (selected_mode != HOSTAPD_MODE_IEEE80211ANY &&
|
||||
selected_mode != mode->mode)
|
||||
continue;
|
||||
hostapd_get_hw_mode_any_channels(hapd, mode, acs_ch_list_all,
|
||||
&freq_list);
|
||||
}
|
||||
|
||||
params.ch_list = channels;
|
||||
params.ch_list_len = num_channels;
|
||||
params.freq_list = freq_list;
|
||||
params.edmg_enabled = hapd->iface->conf->enable_edmg;
|
||||
|
||||
params.ht_enabled = !!(hapd->iface->conf->ieee80211n);
|
||||
params.ht40_enabled = !!(hapd->iface->conf->ht_capab &
|
||||
|
|
@ -953,8 +970,11 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd)
|
|||
params.ch_width = 160;
|
||||
}
|
||||
|
||||
if (hapd->iface->conf->op_class)
|
||||
params.ch_width = op_class_to_bandwidth(
|
||||
hapd->iface->conf->op_class);
|
||||
ret = hapd->driver->do_acs(hapd->drv_priv, ¶ms);
|
||||
os_free(channels);
|
||||
os_free(freq_list);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -968,3 +988,11 @@ int hostapd_drv_update_dh_ie(struct hostapd_data *hapd, const u8 *peer,
|
|||
return hapd->driver->update_dh_ie(hapd->drv_priv, peer, reason_code,
|
||||
ie, ielen);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_drv_dpp_listen(struct hostapd_data *hapd, bool enable)
|
||||
{
|
||||
if (!hapd->driver || !hapd->driver->dpp_listen || !hapd->drv_priv)
|
||||
return 0;
|
||||
return hapd->driver->dpp_listen(hapd->drv_priv, enable);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ int hostapd_sta_add(struct hostapd_data *hapd,
|
|||
const struct ieee80211_vht_capabilities *vht_capab,
|
||||
const struct ieee80211_he_capabilities *he_capab,
|
||||
size_t he_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);
|
||||
int hostapd_set_privacy(struct hostapd_data *hapd, int enabled);
|
||||
|
|
@ -62,7 +63,8 @@ int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd,
|
|||
const u8 *addr, int idx, u8 *seq);
|
||||
int hostapd_flush(struct hostapd_data *hapd);
|
||||
int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode,
|
||||
int freq, int channel, int ht_enabled, int vht_enabled,
|
||||
int freq, int channel, int edmg, u8 edmg_channel,
|
||||
int ht_enabled, int vht_enabled,
|
||||
int he_enabled, int sec_channel_offset, int oper_chwidth,
|
||||
int center_segment0, int center_segment1);
|
||||
int hostapd_set_rts(struct hostapd_data *hapd, int rts);
|
||||
|
|
@ -79,6 +81,7 @@ 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,
|
||||
struct wpa_driver_scan_params *params);
|
||||
struct wpa_scan_results * hostapd_driver_get_scan_results(
|
||||
|
|
@ -88,14 +91,13 @@ int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start,
|
|||
int hostapd_drv_set_key(const char *ifname,
|
||||
struct hostapd_data *hapd,
|
||||
enum wpa_alg alg, const u8 *addr,
|
||||
int key_idx, int set_tx,
|
||||
int key_idx, int vlan_id, int set_tx,
|
||||
const u8 *seq, size_t seq_len,
|
||||
const u8 *key, size_t key_len);
|
||||
const u8 *key, size_t key_len, enum key_flag key_flag);
|
||||
int hostapd_drv_send_mlme(struct hostapd_data *hapd,
|
||||
const void *msg, size_t len, int noack);
|
||||
int hostapd_drv_send_mlme_csa(struct hostapd_data *hapd,
|
||||
const void *msg, size_t len, int noack,
|
||||
const u16 *csa_offs, size_t csa_offs_len);
|
||||
const void *msg, size_t len, int noack,
|
||||
const u16 *csa_offs, size_t csa_offs_len,
|
||||
int no_encrypt);
|
||||
int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
|
||||
const u8 *addr, int reason);
|
||||
int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
|
||||
|
|
@ -132,6 +134,7 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface,
|
|||
int hostapd_drv_do_acs(struct hostapd_data *hapd);
|
||||
int hostapd_drv_update_dh_ie(struct hostapd_data *hapd, const u8 *peer,
|
||||
u16 reason_code, const u8 *ie, size_t ielen);
|
||||
int hostapd_drv_dpp_listen(struct hostapd_data *hapd, bool enable);
|
||||
|
||||
|
||||
#include "drivers/driver.h"
|
||||
|
|
@ -348,12 +351,13 @@ static inline int hostapd_drv_br_set_net_param(struct hostapd_data *hapd,
|
|||
static inline int hostapd_drv_vendor_cmd(struct hostapd_data *hapd,
|
||||
int vendor_id, int subcmd,
|
||||
const u8 *data, size_t data_len,
|
||||
enum nested_attr nested_attr_flag,
|
||||
struct wpabuf *buf)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->vendor_cmd == NULL)
|
||||
return -1;
|
||||
return hapd->driver->vendor_cmd(hapd->drv_priv, vendor_id, subcmd, data,
|
||||
data_len, buf);
|
||||
data_len, nested_attr_flag, buf);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_stop_ap(struct hostapd_data *hapd)
|
||||
|
|
@ -381,4 +385,35 @@ hostapd_drv_send_external_auth_status(struct hostapd_data *hapd,
|
|||
return hapd->driver->send_external_auth_status(hapd->drv_priv, params);
|
||||
}
|
||||
|
||||
static inline int
|
||||
hostapd_drv_set_band(struct hostapd_data *hapd, u32 band_mask)
|
||||
{
|
||||
if (!hapd->driver || !hapd->drv_priv || !hapd->driver->set_band)
|
||||
return -1;
|
||||
return hapd->driver->set_band(hapd->drv_priv, band_mask);
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
static inline int hostapd_drv_driver_cmd(struct hostapd_data *hapd,
|
||||
char *cmd, char *buf, size_t buf_len)
|
||||
{
|
||||
if (!hapd->driver->driver_cmd)
|
||||
return -1;
|
||||
return hapd->driver->driver_cmd(hapd->drv_priv, cmd, buf, buf_len);
|
||||
}
|
||||
#endif /* ANDROID */
|
||||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
static inline int
|
||||
hostapd_drv_register_frame(struct hostapd_data *hapd, u16 type,
|
||||
const u8 *match, size_t match_len,
|
||||
bool multicast)
|
||||
{
|
||||
if (!hapd->driver || !hapd->drv_priv || !hapd->driver->register_frame)
|
||||
return -1;
|
||||
return hapd->driver->register_frame(hapd->drv_priv, type, match,
|
||||
match_len, multicast);
|
||||
}
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
#endif /* AP_DRV_OPS */
|
||||
|
|
|
|||
|
|
@ -228,7 +228,6 @@ void ap_list_process_beacon(struct hostapd_iface *iface,
|
|||
set_beacon++;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
if (!iface->olbc_ht && !ap->ht_support &&
|
||||
(ap->channel == 0 ||
|
||||
ap->channel == iface->conf->channel ||
|
||||
|
|
@ -241,7 +240,6 @@ void ap_list_process_beacon(struct hostapd_iface *iface,
|
|||
MAC2STR(ap->addr), ap->channel);
|
||||
set_beacon++;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
if (set_beacon)
|
||||
ieee802_11_update_beacons(iface);
|
||||
|
|
@ -285,14 +283,12 @@ void ap_list_timer(struct hostapd_iface *iface)
|
|||
iface->olbc = 0;
|
||||
set_beacon++;
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
if (!olbc_ht && iface->olbc_ht) {
|
||||
wpa_printf(MSG_DEBUG, "OLBC HT not detected anymore");
|
||||
iface->olbc_ht = 0;
|
||||
hostapd_ht_operation_update(iface);
|
||||
set_beacon++;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
}
|
||||
|
||||
if (set_beacon)
|
||||
|
|
|
|||
|
|
@ -110,28 +110,10 @@ static int hostapd_setup_radius_srv(struct hostapd_data *hapd)
|
|||
srv.auth_port = conf->radius_server_auth_port;
|
||||
srv.acct_port = conf->radius_server_acct_port;
|
||||
srv.conf_ctx = hapd;
|
||||
srv.eap_sim_db_priv = hapd->eap_sim_db_priv;
|
||||
srv.ssl_ctx = hapd->ssl_ctx;
|
||||
srv.msg_ctx = hapd->msg_ctx;
|
||||
srv.pac_opaque_encr_key = conf->pac_opaque_encr_key;
|
||||
srv.eap_fast_a_id = conf->eap_fast_a_id;
|
||||
srv.eap_fast_a_id_len = conf->eap_fast_a_id_len;
|
||||
srv.eap_fast_a_id_info = conf->eap_fast_a_id_info;
|
||||
srv.eap_fast_prov = conf->eap_fast_prov;
|
||||
srv.pac_key_lifetime = conf->pac_key_lifetime;
|
||||
srv.pac_key_refresh_time = conf->pac_key_refresh_time;
|
||||
srv.eap_teap_auth = conf->eap_teap_auth;
|
||||
srv.eap_teap_pac_no_inner = conf->eap_teap_pac_no_inner;
|
||||
srv.eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
|
||||
srv.eap_sim_id = conf->eap_sim_id;
|
||||
srv.tnc = conf->tnc;
|
||||
srv.wps = hapd->wps;
|
||||
srv.ipv6 = conf->radius_server_ipv6;
|
||||
srv.get_eap_user = hostapd_radius_get_eap_user;
|
||||
srv.eap_req_id_text = conf->eap_req_id_text;
|
||||
srv.eap_req_id_text_len = conf->eap_req_id_text_len;
|
||||
srv.pwd_group = conf->pwd_group;
|
||||
srv.server_id = conf->server_id ? conf->server_id : "hostapd";
|
||||
srv.sqlite_file = conf->eap_user_sqlite;
|
||||
#ifdef CONFIG_RADIUS_TEST
|
||||
srv.dump_msk_file = conf->dump_msk_file;
|
||||
|
|
@ -142,10 +124,8 @@ static int hostapd_setup_radius_srv(struct hostapd_data *hapd)
|
|||
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 = conf->eap_server_erp;
|
||||
srv.erp_domain = conf->erp_domain;
|
||||
srv.tls_session_lifetime = conf->tls_session_lifetime;
|
||||
srv.tls_flags = conf->tls_flags;
|
||||
srv.eap_cfg = hapd->eap_cfg;
|
||||
|
||||
hapd->radius_srv = radius_server_init(&srv);
|
||||
if (hapd->radius_srv == NULL) {
|
||||
|
|
@ -193,6 +173,60 @@ static void authsrv_tls_event(void *ctx, enum tls_event ev,
|
|||
#endif /* EAP_TLS_FUNCS */
|
||||
|
||||
|
||||
static struct eap_config * authsrv_eap_config(struct hostapd_data *hapd)
|
||||
{
|
||||
struct eap_config *cfg;
|
||||
|
||||
cfg = os_zalloc(sizeof(*cfg));
|
||||
if (!cfg)
|
||||
return NULL;
|
||||
|
||||
cfg->eap_server = hapd->conf->eap_server;
|
||||
cfg->ssl_ctx = hapd->ssl_ctx;
|
||||
cfg->msg_ctx = hapd->msg_ctx;
|
||||
cfg->eap_sim_db_priv = hapd->eap_sim_db_priv;
|
||||
cfg->tls_session_lifetime = hapd->conf->tls_session_lifetime;
|
||||
cfg->tls_flags = hapd->conf->tls_flags;
|
||||
cfg->max_auth_rounds = hapd->conf->max_auth_rounds;
|
||||
cfg->max_auth_rounds_short = hapd->conf->max_auth_rounds_short;
|
||||
if (hapd->conf->pac_opaque_encr_key)
|
||||
cfg->pac_opaque_encr_key =
|
||||
os_memdup(hapd->conf->pac_opaque_encr_key, 16);
|
||||
if (hapd->conf->eap_fast_a_id) {
|
||||
cfg->eap_fast_a_id = os_memdup(hapd->conf->eap_fast_a_id,
|
||||
hapd->conf->eap_fast_a_id_len);
|
||||
cfg->eap_fast_a_id_len = hapd->conf->eap_fast_a_id_len;
|
||||
}
|
||||
if (hapd->conf->eap_fast_a_id_info)
|
||||
cfg->eap_fast_a_id_info =
|
||||
os_strdup(hapd->conf->eap_fast_a_id_info);
|
||||
cfg->eap_fast_prov = hapd->conf->eap_fast_prov;
|
||||
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_sim_aka_result_ind = hapd->conf->eap_sim_aka_result_ind;
|
||||
cfg->eap_sim_id = hapd->conf->eap_sim_id;
|
||||
cfg->tnc = hapd->conf->tnc;
|
||||
cfg->wps = hapd->wps;
|
||||
cfg->fragment_size = hapd->conf->fragment_size;
|
||||
cfg->pwd_group = hapd->conf->pwd_group;
|
||||
cfg->pbc_in_m1 = hapd->conf->pbc_in_m1;
|
||||
if (hapd->conf->server_id) {
|
||||
cfg->server_id = (u8 *) os_strdup(hapd->conf->server_id);
|
||||
cfg->server_id_len = os_strlen(hapd->conf->server_id);
|
||||
} else {
|
||||
cfg->server_id = (u8 *) os_strdup("hostapd");
|
||||
cfg->server_id_len = 7;
|
||||
}
|
||||
cfg->erp = hapd->conf->eap_server_erp;
|
||||
|
||||
return cfg;
|
||||
}
|
||||
|
||||
|
||||
int authsrv_init(struct hostapd_data *hapd)
|
||||
{
|
||||
#ifdef EAP_TLS_FUNCS
|
||||
|
|
@ -273,6 +307,14 @@ int authsrv_init(struct hostapd_data *hapd)
|
|||
}
|
||||
#endif /* EAP_SIM_DB */
|
||||
|
||||
hapd->eap_cfg = authsrv_eap_config(hapd);
|
||||
if (!hapd->eap_cfg) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Failed to build EAP server configuration");
|
||||
authsrv_deinit(hapd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef RADIUS_SERVER
|
||||
if (hapd->conf->radius_server_clients &&
|
||||
hostapd_setup_radius_srv(hapd))
|
||||
|
|
@ -303,4 +345,7 @@ void authsrv_deinit(struct hostapd_data *hapd)
|
|||
hapd->eap_sim_db_priv = NULL;
|
||||
}
|
||||
#endif /* EAP_SIM_DB */
|
||||
|
||||
eap_server_config_free(hapd->eap_cfg);
|
||||
hapd->eap_cfg = NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,27 +36,6 @@
|
|||
|
||||
#ifdef NEED_AP_MLME
|
||||
|
||||
static u8 * hostapd_eid_rm_enabled_capab(struct hostapd_data *hapd, u8 *eid,
|
||||
size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < RRM_CAPABILITIES_IE_LEN; i++) {
|
||||
if (hapd->conf->radio_measurements[i])
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == RRM_CAPABILITIES_IE_LEN || len < 2 + RRM_CAPABILITIES_IE_LEN)
|
||||
return eid;
|
||||
|
||||
*eid++ = WLAN_EID_RRM_ENABLED_CAPABILITIES;
|
||||
*eid++ = RRM_CAPABILITIES_IE_LEN;
|
||||
os_memcpy(eid, hapd->conf->radio_measurements, RRM_CAPABILITIES_IE_LEN);
|
||||
|
||||
return eid + RRM_CAPABILITIES_IE_LEN;
|
||||
}
|
||||
|
||||
|
||||
static u8 * hostapd_eid_bss_load(struct hostapd_data *hapd, u8 *eid, size_t len)
|
||||
{
|
||||
if (len < 2 + 5)
|
||||
|
|
@ -287,17 +266,101 @@ static u8 * hostapd_eid_country(struct hostapd_data *hapd, u8 *eid,
|
|||
}
|
||||
|
||||
|
||||
static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len)
|
||||
const u8 * hostapd_wpa_ie(struct hostapd_data *hapd, u8 eid)
|
||||
{
|
||||
const u8 *ies;
|
||||
size_t ies_len;
|
||||
|
||||
ies = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ies_len);
|
||||
if (!ies)
|
||||
return NULL;
|
||||
|
||||
return get_ie(ies, ies_len, eid);
|
||||
}
|
||||
|
||||
|
||||
static const u8 * hostapd_vendor_wpa_ie(struct hostapd_data *hapd,
|
||||
u32 vendor_type)
|
||||
{
|
||||
const u8 *ies;
|
||||
size_t ies_len;
|
||||
|
||||
ies = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ies_len);
|
||||
if (!ies)
|
||||
return NULL;
|
||||
|
||||
return get_vendor_ie(ies, ies_len, vendor_type);
|
||||
}
|
||||
|
||||
|
||||
static u8 * hostapd_get_rsne(struct hostapd_data *hapd, u8 *pos, size_t len)
|
||||
{
|
||||
const u8 *ie;
|
||||
size_t ielen;
|
||||
|
||||
ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ielen);
|
||||
if (ie == NULL || ielen > len)
|
||||
return eid;
|
||||
ie = hostapd_wpa_ie(hapd, WLAN_EID_RSN);
|
||||
if (!ie || 2U + ie[1] > len)
|
||||
return pos;
|
||||
|
||||
os_memcpy(eid, ie, ielen);
|
||||
return eid + ielen;
|
||||
os_memcpy(pos, ie, 2 + ie[1]);
|
||||
return pos + 2 + ie[1];
|
||||
}
|
||||
|
||||
|
||||
static u8 * hostapd_get_mde(struct hostapd_data *hapd, u8 *pos, size_t len)
|
||||
{
|
||||
const u8 *ie;
|
||||
|
||||
ie = hostapd_wpa_ie(hapd, WLAN_EID_MOBILITY_DOMAIN);
|
||||
if (!ie || 2U + ie[1] > len)
|
||||
return pos;
|
||||
|
||||
os_memcpy(pos, ie, 2 + ie[1]);
|
||||
return pos + 2 + ie[1];
|
||||
}
|
||||
|
||||
|
||||
static u8 * hostapd_get_rsnxe(struct hostapd_data *hapd, u8 *pos, size_t len)
|
||||
{
|
||||
const u8 *ie;
|
||||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
if (hapd->conf->no_beacon_rsnxe) {
|
||||
wpa_printf(MSG_INFO, "TESTING: Do not add RSNXE into Beacon");
|
||||
return pos;
|
||||
}
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
ie = hostapd_wpa_ie(hapd, WLAN_EID_RSNX);
|
||||
if (!ie || 2U + ie[1] > len)
|
||||
return pos;
|
||||
|
||||
os_memcpy(pos, ie, 2 + ie[1]);
|
||||
return pos + 2 + ie[1];
|
||||
}
|
||||
|
||||
|
||||
static u8 * hostapd_get_wpa_ie(struct hostapd_data *hapd, u8 *pos, size_t len)
|
||||
{
|
||||
const u8 *ie;
|
||||
|
||||
ie = hostapd_vendor_wpa_ie(hapd, WPA_IE_VENDOR_TYPE);
|
||||
if (!ie || 2U + ie[1] > len)
|
||||
return pos;
|
||||
|
||||
os_memcpy(pos, ie, 2 + ie[1]);
|
||||
return pos + 2 + ie[1];
|
||||
}
|
||||
|
||||
|
||||
static u8 * hostapd_get_osen_ie(struct hostapd_data *hapd, u8 *pos, size_t len)
|
||||
{
|
||||
const u8 *ie;
|
||||
|
||||
ie = hostapd_vendor_wpa_ie(hapd, OSEN_IE_VENDOR_TYPE);
|
||||
if (!ie || 2U + ie[1] > len)
|
||||
return pos;
|
||||
|
||||
os_memcpy(pos, ie, 2 + ie[1]);
|
||||
return pos + 2 + ie[1];
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -395,16 +458,20 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
|
|||
}
|
||||
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
if (hapd->iconf->ieee80211ax) {
|
||||
if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) {
|
||||
buflen += 3 + sizeof(struct ieee80211_he_capabilities) +
|
||||
3 + sizeof(struct ieee80211_he_operation) +
|
||||
3 + sizeof(struct ieee80211_he_mu_edca_parameter_set) +
|
||||
3 + sizeof(struct ieee80211_spatial_reuse);
|
||||
if (is_6ghz_op_class(hapd->iconf->op_class))
|
||||
buflen += sizeof(struct ieee80211_he_6ghz_oper_info) +
|
||||
3 + sizeof(struct ieee80211_he_6ghz_band_cap);
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
|
||||
buflen += hostapd_mbo_ie_len(hapd);
|
||||
buflen += hostapd_eid_owe_trans_len(hapd);
|
||||
buflen += hostapd_eid_dpp_cc_len(hapd);
|
||||
|
||||
resp = os_zalloc(buflen);
|
||||
if (resp == NULL)
|
||||
|
|
@ -455,13 +522,10 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
|
|||
/* Extended supported rates */
|
||||
pos = hostapd_eid_ext_supp_rates(hapd, pos);
|
||||
|
||||
/* RSN, MDIE */
|
||||
if (hapd->conf->wpa != WPA_PROTO_WPA)
|
||||
pos = hostapd_eid_wpa(hapd, pos, epos - pos);
|
||||
|
||||
pos = hostapd_get_rsne(hapd, pos, epos - pos);
|
||||
pos = hostapd_eid_bss_load(hapd, pos, epos - pos);
|
||||
|
||||
pos = hostapd_eid_rm_enabled_capab(hapd, pos, epos - pos);
|
||||
pos = hostapd_get_mde(hapd, pos, epos - pos);
|
||||
|
||||
/* eCSA IE */
|
||||
csa_pos = hostapd_eid_ecsa(hapd, pos);
|
||||
|
|
@ -470,15 +534,8 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
|
|||
pos = csa_pos;
|
||||
|
||||
pos = hostapd_eid_supported_op_classes(hapd, pos);
|
||||
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
/* Secondary Channel Offset element */
|
||||
/* TODO: The standard doesn't specify a position for this element. */
|
||||
pos = hostapd_eid_secondary_channel(hapd, pos);
|
||||
|
||||
pos = hostapd_eid_ht_capabilities(hapd, pos);
|
||||
pos = hostapd_eid_ht_operation(hapd, pos);
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
pos = hostapd_eid_ext_capab(hapd, pos);
|
||||
|
||||
|
|
@ -498,22 +555,34 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
|
|||
#endif /* CONFIG_FST */
|
||||
|
||||
#ifdef CONFIG_IEEE80211AC
|
||||
if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) {
|
||||
if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac &&
|
||||
!is_6ghz_op_class(hapd->iconf->op_class)) {
|
||||
pos = hostapd_eid_vht_capabilities(hapd, pos, 0);
|
||||
pos = hostapd_eid_vht_operation(hapd, pos);
|
||||
pos = hostapd_eid_txpower_envelope(hapd, pos);
|
||||
pos = hostapd_eid_wb_chsw_wrapper(hapd, pos);
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211AC */
|
||||
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax &&
|
||||
is_6ghz_op_class(hapd->iconf->op_class))
|
||||
pos = hostapd_eid_txpower_envelope(hapd, pos);
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
|
||||
if ((hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) ||
|
||||
(hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax))
|
||||
pos = hostapd_eid_wb_chsw_wrapper(hapd, pos);
|
||||
|
||||
pos = hostapd_eid_fils_indic(hapd, pos, 0);
|
||||
pos = hostapd_get_rsnxe(hapd, pos, epos - pos);
|
||||
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
if (hapd->iconf->ieee80211ax) {
|
||||
if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) {
|
||||
pos = hostapd_eid_he_capab(hapd, pos, IEEE80211_MODE_AP);
|
||||
pos = hostapd_eid_he_operation(hapd, pos);
|
||||
pos = hostapd_eid_he_mu_edca_parameter_set(hapd, pos);
|
||||
pos = hostapd_eid_spatial_reuse(hapd, pos);
|
||||
pos = hostapd_eid_he_mu_edca_parameter_set(hapd, pos);
|
||||
pos = hostapd_eid_he_6ghz_band_cap(hapd, pos);
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
|
||||
|
|
@ -522,9 +591,9 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
|
|||
pos = hostapd_eid_vendor_vht(hapd, pos);
|
||||
#endif /* CONFIG_IEEE80211AC */
|
||||
|
||||
/* WPA */
|
||||
if (hapd->conf->wpa == WPA_PROTO_WPA)
|
||||
pos = hostapd_eid_wpa(hapd, pos, epos - pos);
|
||||
/* WPA / OSEN */
|
||||
pos = hostapd_get_wpa_ie(hapd, pos, epos - pos);
|
||||
pos = hostapd_get_osen_ie(hapd, pos, epos - pos);
|
||||
|
||||
/* Wi-Fi Alliance WMM */
|
||||
pos = hostapd_eid_wmm(hapd, pos);
|
||||
|
|
@ -553,11 +622,11 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
|
|||
|
||||
#ifdef CONFIG_HS20
|
||||
pos = hostapd_eid_hs20_indication(hapd, pos);
|
||||
pos = hostapd_eid_osen(hapd, pos);
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
||||
pos = hostapd_eid_mbo(hapd, pos, (u8 *) resp + buflen - pos);
|
||||
pos = hostapd_eid_owe_trans(hapd, pos, (u8 *) resp + buflen - pos);
|
||||
pos = hostapd_eid_dpp_cc(hapd, pos, (u8 *) resp + buflen - pos);
|
||||
|
||||
if (hapd->conf->vendor_elements) {
|
||||
os_memcpy(pos, wpabuf_head(hapd->conf->vendor_elements),
|
||||
|
|
@ -579,7 +648,9 @@ enum ssid_match_result {
|
|||
static enum ssid_match_result ssid_match(struct hostapd_data *hapd,
|
||||
const u8 *ssid, size_t ssid_len,
|
||||
const u8 *ssid_list,
|
||||
size_t ssid_list_len)
|
||||
size_t ssid_list_len,
|
||||
const u8 *short_ssid_list,
|
||||
size_t short_ssid_list_len)
|
||||
{
|
||||
const u8 *pos, *end;
|
||||
int wildcard = 0;
|
||||
|
|
@ -590,20 +661,30 @@ static enum ssid_match_result ssid_match(struct hostapd_data *hapd,
|
|||
os_memcmp(ssid, hapd->conf->ssid.ssid, ssid_len) == 0)
|
||||
return EXACT_SSID_MATCH;
|
||||
|
||||
if (ssid_list == NULL)
|
||||
return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH;
|
||||
if (ssid_list) {
|
||||
pos = ssid_list;
|
||||
end = ssid_list + ssid_list_len;
|
||||
while (end - pos >= 2) {
|
||||
if (2 + pos[1] > end - pos)
|
||||
break;
|
||||
if (pos[1] == 0)
|
||||
wildcard = 1;
|
||||
if (pos[1] == hapd->conf->ssid.ssid_len &&
|
||||
os_memcmp(pos + 2, hapd->conf->ssid.ssid,
|
||||
pos[1]) == 0)
|
||||
return EXACT_SSID_MATCH;
|
||||
pos += 2 + pos[1];
|
||||
}
|
||||
}
|
||||
|
||||
pos = ssid_list;
|
||||
end = ssid_list + ssid_list_len;
|
||||
while (end - pos >= 2) {
|
||||
if (2 + pos[1] > end - pos)
|
||||
break;
|
||||
if (pos[1] == 0)
|
||||
wildcard = 1;
|
||||
if (pos[1] == hapd->conf->ssid.ssid_len &&
|
||||
os_memcmp(pos + 2, hapd->conf->ssid.ssid, pos[1]) == 0)
|
||||
return EXACT_SSID_MATCH;
|
||||
pos += 2 + pos[1];
|
||||
if (short_ssid_list) {
|
||||
pos = short_ssid_list;
|
||||
end = short_ssid_list + short_ssid_list_len;
|
||||
while (end - pos >= 4) {
|
||||
if (hapd->conf->ssid.short_ssid == WPA_GET_LE32(pos))
|
||||
return EXACT_SSID_MATCH;
|
||||
pos += 4;
|
||||
}
|
||||
}
|
||||
|
||||
return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH;
|
||||
|
|
@ -741,11 +822,11 @@ void handle_probe_req(struct hostapd_data *hapd,
|
|||
int ret;
|
||||
u16 csa_offs[2];
|
||||
size_t csa_offs_len;
|
||||
u32 session_timeout, acct_interim_interval;
|
||||
struct vlan_description vlan_id;
|
||||
struct hostapd_sta_wpa_psk_short *psk = NULL;
|
||||
char *identity = NULL;
|
||||
char *radius_cui = NULL;
|
||||
struct radius_sta rad_info;
|
||||
|
||||
if (hapd->iconf->rssi_ignore_probe_request && ssi_signal &&
|
||||
ssi_signal < hapd->iconf->rssi_ignore_probe_request)
|
||||
return;
|
||||
|
||||
if (len < IEEE80211_HDRLEN)
|
||||
return;
|
||||
|
|
@ -754,10 +835,8 @@ void handle_probe_req(struct hostapd_data *hapd,
|
|||
sta_track_add(hapd->iface, mgmt->sa, ssi_signal);
|
||||
ie_len = len - IEEE80211_HDRLEN;
|
||||
|
||||
ret = ieee802_11_allowed_address(hapd, mgmt->sa, (const u8 *) mgmt, len,
|
||||
&session_timeout,
|
||||
&acct_interim_interval, &vlan_id,
|
||||
&psk, &identity, &radius_cui, 1);
|
||||
ret = hostapd_allowed_address(hapd, mgmt->sa, (const u8 *) mgmt, len,
|
||||
&rad_info, 1);
|
||||
if (ret == HOSTAPD_ACL_REJECT) {
|
||||
wpa_msg(hapd->msg_ctx, MSG_DEBUG,
|
||||
"Ignore Probe Request frame from " MACSTR
|
||||
|
|
@ -836,7 +915,7 @@ void handle_probe_req(struct hostapd_data *hapd,
|
|||
#endif /* CONFIG_P2P */
|
||||
|
||||
if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0 &&
|
||||
elems.ssid_list_len == 0) {
|
||||
elems.ssid_list_len == 0 && elems.short_ssid_list_len == 0) {
|
||||
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for "
|
||||
"broadcast SSID ignored", MAC2STR(mgmt->sa));
|
||||
return;
|
||||
|
|
@ -868,7 +947,8 @@ void handle_probe_req(struct hostapd_data *hapd,
|
|||
#endif /* CONFIG_TAXONOMY */
|
||||
|
||||
res = ssid_match(hapd, elems.ssid, elems.ssid_len,
|
||||
elems.ssid_list, elems.ssid_list_len);
|
||||
elems.ssid_list, elems.ssid_list_len,
|
||||
elems.short_ssid_list, elems.short_ssid_list_len);
|
||||
if (res == NO_SSID_MATCH) {
|
||||
if (!(mgmt->da[0] & 0x01)) {
|
||||
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
|
||||
|
|
@ -881,6 +961,12 @@ void handle_probe_req(struct hostapd_data *hapd,
|
|||
return;
|
||||
}
|
||||
|
||||
if (hapd->conf->ignore_broadcast_ssid && res == WILDCARD_SSID_MATCH) {
|
||||
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for "
|
||||
"broadcast SSID ignored", MAC2STR(mgmt->sa));
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
if (hapd->conf->interworking &&
|
||||
elems.interworking && elems.interworking_len >= 1) {
|
||||
|
|
@ -985,9 +1071,9 @@ void handle_probe_req(struct hostapd_data *hapd,
|
|||
hapd->cs_c_off_ecsa_proberesp;
|
||||
}
|
||||
|
||||
ret = hostapd_drv_send_mlme_csa(hapd, resp, resp_len, noack,
|
||||
csa_offs_len ? csa_offs : NULL,
|
||||
csa_offs_len);
|
||||
ret = hostapd_drv_send_mlme(hapd, resp, resp_len, noack,
|
||||
csa_offs_len ? csa_offs : NULL,
|
||||
csa_offs_len, 0);
|
||||
|
||||
if (ret < 0)
|
||||
wpa_printf(MSG_INFO, "handle_probe_req: send failed");
|
||||
|
|
@ -1038,6 +1124,23 @@ static u8 * hostapd_probe_resp_offloads(struct hostapd_data *hapd,
|
|||
#endif /* NEED_AP_MLME */
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
/* Unsolicited broadcast Probe Response transmission, 6 GHz only */
|
||||
static u8 * hostapd_unsol_bcast_probe_resp(struct hostapd_data *hapd,
|
||||
struct wpa_driver_ap_params *params)
|
||||
{
|
||||
if (!is_6ghz_op_class(hapd->iconf->op_class))
|
||||
return NULL;
|
||||
|
||||
params->unsol_bcast_probe_resp_interval =
|
||||
hapd->conf->unsol_bcast_probe_resp_interval;
|
||||
|
||||
return hostapd_gen_probe_resp(hapd, NULL, 0,
|
||||
¶ms->unsol_bcast_probe_resp_tmpl_len);
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
|
||||
|
||||
void sta_track_del(struct hostapd_sta_info *info)
|
||||
{
|
||||
#ifdef CONFIG_TAXONOMY
|
||||
|
|
@ -1048,6 +1151,243 @@ void sta_track_del(struct hostapd_sta_info *info)
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_FILS
|
||||
|
||||
static u16 hostapd_fils_discovery_cap(struct hostapd_data *hapd)
|
||||
{
|
||||
u16 cap_info, phy_index = 0;
|
||||
u8 chwidth = FD_CAP_BSS_CHWIDTH_20, mcs_nss_size = 4;
|
||||
struct hostapd_hw_modes *mode = hapd->iface->current_mode;
|
||||
|
||||
cap_info = FD_CAP_ESS;
|
||||
if (hapd->conf->wpa)
|
||||
cap_info |= FD_CAP_PRIVACY;
|
||||
|
||||
if (is_6ghz_op_class(hapd->iconf->op_class)) {
|
||||
phy_index = FD_CAP_PHY_INDEX_HE;
|
||||
|
||||
switch (hapd->iconf->op_class) {
|
||||
case 135:
|
||||
mcs_nss_size += 4;
|
||||
/* fallthrough */
|
||||
case 134:
|
||||
mcs_nss_size += 4;
|
||||
chwidth = FD_CAP_BSS_CHWIDTH_160_80_80;
|
||||
break;
|
||||
case 133:
|
||||
chwidth = FD_CAP_BSS_CHWIDTH_80;
|
||||
break;
|
||||
case 132:
|
||||
chwidth = FD_CAP_BSS_CHWIDTH_40;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (hostapd_get_oper_chwidth(hapd->iconf)) {
|
||||
case CHANWIDTH_80P80MHZ:
|
||||
mcs_nss_size += 4;
|
||||
/* fallthrough */
|
||||
case CHANWIDTH_160MHZ:
|
||||
mcs_nss_size += 4;
|
||||
chwidth = FD_CAP_BSS_CHWIDTH_160_80_80;
|
||||
break;
|
||||
case CHANWIDTH_80MHZ:
|
||||
chwidth = FD_CAP_BSS_CHWIDTH_80;
|
||||
break;
|
||||
case CHANWIDTH_USE_HT:
|
||||
if (hapd->iconf->secondary_channel)
|
||||
chwidth = FD_CAP_BSS_CHWIDTH_40;
|
||||
else
|
||||
chwidth = FD_CAP_BSS_CHWIDTH_20;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax)
|
||||
phy_index = FD_CAP_PHY_INDEX_HE;
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
#ifdef CONFIG_IEEE80211AC
|
||||
if (!phy_index &&
|
||||
hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac)
|
||||
phy_index = FD_CAP_PHY_INDEX_VHT;
|
||||
#endif /* CONFIG_IEEE80211AC */
|
||||
if (!phy_index &&
|
||||
hapd->iconf->ieee80211n && !hapd->conf->disable_11n)
|
||||
phy_index = FD_CAP_PHY_INDEX_HT;
|
||||
}
|
||||
|
||||
cap_info |= phy_index << FD_CAP_PHY_INDEX_SHIFT;
|
||||
cap_info |= chwidth << FD_CAP_BSS_CHWIDTH_SHIFT;
|
||||
|
||||
if (mode) {
|
||||
u16 *mcs = (u16 *) mode->he_capab[IEEE80211_MODE_AP].mcs;
|
||||
int i;
|
||||
u16 nss = 0;
|
||||
|
||||
for (i = 0; i < HE_NSS_MAX_STREAMS; i++) {
|
||||
u16 nss_mask = 0x3 << (i * 2);
|
||||
|
||||
if (mcs_nss_size == 4 &&
|
||||
(((mcs[0] & nss_mask) == nss_mask) ||
|
||||
((mcs[1] & nss_mask) == nss_mask)))
|
||||
continue;
|
||||
|
||||
if (mcs_nss_size == 8 &&
|
||||
(((mcs[2] & nss_mask) == nss_mask) ||
|
||||
((mcs[3] & nss_mask) == nss_mask)))
|
||||
continue;
|
||||
|
||||
if (mcs_nss_size == 12 &&
|
||||
(((mcs[4] & nss_mask) == nss_mask) ||
|
||||
((mcs[5] & nss_mask) == nss_mask)))
|
||||
continue;
|
||||
|
||||
nss++;
|
||||
}
|
||||
|
||||
if (nss > 4)
|
||||
cap_info |= FD_CAP_NSS_5_8 << FD_CAP_NSS_SHIFT;
|
||||
else if (nss)
|
||||
cap_info |= (nss - 1) << FD_CAP_NSS_SHIFT;
|
||||
}
|
||||
|
||||
return cap_info;
|
||||
}
|
||||
|
||||
|
||||
static u8 * hostapd_gen_fils_discovery(struct hostapd_data *hapd, size_t *len)
|
||||
{
|
||||
struct ieee80211_mgmt *head;
|
||||
const u8 *mobility_domain;
|
||||
u8 *pos, *length_pos, buf[200];
|
||||
u16 ctl = 0;
|
||||
u8 fd_rsn_info[5];
|
||||
size_t total_len, buf_len;
|
||||
|
||||
total_len = 24 + 2 + 12;
|
||||
|
||||
/* FILS Discovery Frame Control */
|
||||
ctl = (sizeof(hapd->conf->ssid.short_ssid) - 1) |
|
||||
FD_FRAME_CTL_SHORT_SSID_PRESENT |
|
||||
FD_FRAME_CTL_LENGTH_PRESENT |
|
||||
FD_FRAME_CTL_CAP_PRESENT;
|
||||
total_len += 4 + 1 + 2;
|
||||
|
||||
/* Check for optional subfields and calculate length */
|
||||
if (wpa_auth_write_fd_rsn_info(hapd->wpa_auth, fd_rsn_info)) {
|
||||
ctl |= FD_FRAME_CTL_RSN_INFO_PRESENT;
|
||||
total_len += sizeof(fd_rsn_info);
|
||||
}
|
||||
|
||||
mobility_domain = hostapd_wpa_ie(hapd, WLAN_EID_MOBILITY_DOMAIN);
|
||||
if (mobility_domain) {
|
||||
ctl |= FD_FRAME_CTL_MD_PRESENT;
|
||||
total_len += 3;
|
||||
}
|
||||
|
||||
pos = hostapd_eid_fils_indic(hapd, buf, 0);
|
||||
buf_len = pos - buf;
|
||||
total_len += buf_len;
|
||||
|
||||
head = os_zalloc(total_len);
|
||||
if (!head)
|
||||
return NULL;
|
||||
|
||||
head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
||||
WLAN_FC_STYPE_ACTION);
|
||||
os_memset(head->da, 0xff, ETH_ALEN);
|
||||
os_memcpy(head->sa, hapd->own_addr, ETH_ALEN);
|
||||
os_memcpy(head->bssid, hapd->own_addr, ETH_ALEN);
|
||||
|
||||
head->u.action.category = WLAN_ACTION_PUBLIC;
|
||||
head->u.action.u.public_action.action = WLAN_PA_FILS_DISCOVERY;
|
||||
|
||||
pos = &head->u.action.u.public_action.variable[0];
|
||||
|
||||
/* FILS Discovery Information field */
|
||||
|
||||
/* FILS Discovery Frame Control */
|
||||
WPA_PUT_LE16(pos, ctl);
|
||||
pos += 2;
|
||||
|
||||
/* Hardware or low-level driver will fill in the Timestamp value */
|
||||
pos += 8;
|
||||
|
||||
/* Beacon Interval */
|
||||
WPA_PUT_LE16(pos, hapd->iconf->beacon_int);
|
||||
pos += 2;
|
||||
|
||||
/* Short SSID */
|
||||
WPA_PUT_LE32(pos, hapd->conf->ssid.short_ssid);
|
||||
pos += sizeof(hapd->conf->ssid.short_ssid);
|
||||
|
||||
/* Store position of FILS discovery information element Length field */
|
||||
length_pos = pos++;
|
||||
|
||||
/* FD Capability */
|
||||
WPA_PUT_LE16(pos, hostapd_fils_discovery_cap(hapd));
|
||||
pos += 2;
|
||||
|
||||
/* Operating Class - not present */
|
||||
|
||||
/* Primary Channel - not present */
|
||||
|
||||
/* AP Configuration Sequence Number - not present */
|
||||
|
||||
/* Access Network Options - not present */
|
||||
|
||||
/* FD RSN Information */
|
||||
if (ctl & FD_FRAME_CTL_RSN_INFO_PRESENT) {
|
||||
os_memcpy(pos, fd_rsn_info, sizeof(fd_rsn_info));
|
||||
pos += sizeof(fd_rsn_info);
|
||||
}
|
||||
|
||||
/* Channel Center Frequency Segment 1 - not present */
|
||||
|
||||
/* Mobility Domain */
|
||||
if (ctl & FD_FRAME_CTL_MD_PRESENT) {
|
||||
os_memcpy(pos, &mobility_domain[2], 3);
|
||||
pos += 3;
|
||||
}
|
||||
|
||||
/* Fill in the Length field value */
|
||||
*length_pos = pos - (length_pos + 1);
|
||||
|
||||
/* FILS Indication element */
|
||||
if (buf_len) {
|
||||
os_memcpy(pos, buf, buf_len);
|
||||
pos += buf_len;
|
||||
}
|
||||
|
||||
*len = pos - (u8 *) head;
|
||||
wpa_hexdump(MSG_DEBUG, "FILS Discovery frame template",
|
||||
head, pos - (u8 *) head);
|
||||
return (u8 *) head;
|
||||
}
|
||||
|
||||
|
||||
/* Configure FILS Discovery frame transmission parameters */
|
||||
static u8 * hostapd_fils_discovery(struct hostapd_data *hapd,
|
||||
struct wpa_driver_ap_params *params)
|
||||
{
|
||||
params->fd_max_int = hapd->conf->fils_discovery_max_int;
|
||||
if (is_6ghz_op_class(hapd->iconf->op_class) &&
|
||||
params->fd_max_int > FD_MAX_INTERVAL_6GHZ)
|
||||
params->fd_max_int = FD_MAX_INTERVAL_6GHZ;
|
||||
|
||||
params->fd_min_int = hapd->conf->fils_discovery_min_int;
|
||||
if (params->fd_min_int > params->fd_max_int)
|
||||
params->fd_min_int = params->fd_max_int;
|
||||
|
||||
if (params->fd_max_int)
|
||||
return hostapd_gen_fils_discovery(hapd,
|
||||
¶ms->fd_frame_tmpl_len);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_FILS */
|
||||
|
||||
|
||||
int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
||||
struct wpa_driver_ap_params *params)
|
||||
{
|
||||
|
|
@ -1058,7 +1398,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
|||
size_t resp_len = 0;
|
||||
#ifdef NEED_AP_MLME
|
||||
u16 capab_info;
|
||||
u8 *pos, *tailpos, *csa_pos;
|
||||
u8 *pos, *tailpos, *tailend, *csa_pos;
|
||||
|
||||
#define BEACON_HEAD_BUF_SIZE 256
|
||||
#define BEACON_TAIL_BUF_SIZE 512
|
||||
|
|
@ -1087,16 +1427,20 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
|||
#endif /* CONFIG_IEEE80211AC */
|
||||
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
if (hapd->iconf->ieee80211ax) {
|
||||
if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) {
|
||||
tail_len += 3 + sizeof(struct ieee80211_he_capabilities) +
|
||||
3 + sizeof(struct ieee80211_he_operation) +
|
||||
3 + sizeof(struct ieee80211_he_mu_edca_parameter_set) +
|
||||
3 + sizeof(struct ieee80211_spatial_reuse);
|
||||
if (is_6ghz_op_class(hapd->iconf->op_class))
|
||||
tail_len += sizeof(struct ieee80211_he_6ghz_oper_info) +
|
||||
3 + sizeof(struct ieee80211_he_6ghz_band_cap);
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
|
||||
tail_len += hostapd_mbo_ie_len(hapd);
|
||||
tail_len += hostapd_eid_owe_trans_len(hapd);
|
||||
tail_len += hostapd_eid_dpp_cc_len(hapd);
|
||||
|
||||
tailpos = tail = os_malloc(tail_len);
|
||||
if (head == NULL || tail == NULL) {
|
||||
|
|
@ -1105,6 +1449,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
|||
os_free(tail);
|
||||
return -1;
|
||||
}
|
||||
tailend = tail + tail_len;
|
||||
|
||||
head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
||||
WLAN_FC_STYPE_BEACON);
|
||||
|
|
@ -1145,8 +1490,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
|||
|
||||
head_len = pos - (u8 *) head;
|
||||
|
||||
tailpos = hostapd_eid_country(hapd, tailpos,
|
||||
tail + BEACON_TAIL_BUF_SIZE - tailpos);
|
||||
tailpos = hostapd_eid_country(hapd, tailpos, tailend - tailpos);
|
||||
|
||||
/* Power Constraint element */
|
||||
tailpos = hostapd_eid_pwr_constraint(hapd, tailpos);
|
||||
|
|
@ -1163,18 +1507,11 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
|||
/* Extended supported rates */
|
||||
tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos);
|
||||
|
||||
/* RSN, MDIE */
|
||||
if (hapd->conf->wpa != WPA_PROTO_WPA)
|
||||
tailpos = hostapd_eid_wpa(hapd, tailpos,
|
||||
tail + BEACON_TAIL_BUF_SIZE -
|
||||
tailpos);
|
||||
|
||||
tailpos = hostapd_get_rsne(hapd, tailpos, tailend - tailpos);
|
||||
tailpos = hostapd_eid_bss_load(hapd, tailpos, tailend - tailpos);
|
||||
tailpos = hostapd_eid_rm_enabled_capab(hapd, tailpos,
|
||||
tail + BEACON_TAIL_BUF_SIZE -
|
||||
tailpos);
|
||||
|
||||
tailpos = hostapd_eid_bss_load(hapd, tailpos,
|
||||
tail + BEACON_TAIL_BUF_SIZE - tailpos);
|
||||
tailend - tailpos);
|
||||
tailpos = hostapd_get_mde(hapd, tailpos, tailend - tailpos);
|
||||
|
||||
/* eCSA IE */
|
||||
csa_pos = hostapd_eid_ecsa(hapd, tailpos);
|
||||
|
|
@ -1183,15 +1520,8 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
|||
tailpos = csa_pos;
|
||||
|
||||
tailpos = hostapd_eid_supported_op_classes(hapd, tailpos);
|
||||
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
/* Secondary Channel Offset element */
|
||||
/* TODO: The standard doesn't specify a position for this element. */
|
||||
tailpos = hostapd_eid_secondary_channel(hapd, tailpos);
|
||||
|
||||
tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
|
||||
tailpos = hostapd_eid_ht_operation(hapd, tailpos);
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
tailpos = hostapd_eid_ext_capab(hapd, tailpos);
|
||||
|
||||
|
|
@ -1214,23 +1544,35 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
|||
#endif /* CONFIG_FST */
|
||||
|
||||
#ifdef CONFIG_IEEE80211AC
|
||||
if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) {
|
||||
if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac &&
|
||||
!is_6ghz_op_class(hapd->iconf->op_class)) {
|
||||
tailpos = hostapd_eid_vht_capabilities(hapd, tailpos, 0);
|
||||
tailpos = hostapd_eid_vht_operation(hapd, tailpos);
|
||||
tailpos = hostapd_eid_txpower_envelope(hapd, tailpos);
|
||||
tailpos = hostapd_eid_wb_chsw_wrapper(hapd, tailpos);
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211AC */
|
||||
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax &&
|
||||
is_6ghz_op_class(hapd->iconf->op_class))
|
||||
tailpos = hostapd_eid_txpower_envelope(hapd, tailpos);
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
|
||||
if ((hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) ||
|
||||
(hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax))
|
||||
tailpos = hostapd_eid_wb_chsw_wrapper(hapd, tailpos);
|
||||
|
||||
tailpos = hostapd_eid_fils_indic(hapd, tailpos, 0);
|
||||
tailpos = hostapd_get_rsnxe(hapd, tailpos, tailend - tailpos);
|
||||
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
if (hapd->iconf->ieee80211ax) {
|
||||
if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) {
|
||||
tailpos = hostapd_eid_he_capab(hapd, tailpos,
|
||||
IEEE80211_MODE_AP);
|
||||
tailpos = hostapd_eid_he_operation(hapd, tailpos);
|
||||
tailpos = hostapd_eid_he_mu_edca_parameter_set(hapd, tailpos);
|
||||
tailpos = hostapd_eid_spatial_reuse(hapd, tailpos);
|
||||
tailpos = hostapd_eid_he_mu_edca_parameter_set(hapd, tailpos);
|
||||
tailpos = hostapd_eid_he_6ghz_band_cap(hapd, tailpos);
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
|
||||
|
|
@ -1239,11 +1581,9 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
|||
tailpos = hostapd_eid_vendor_vht(hapd, tailpos);
|
||||
#endif /* CONFIG_IEEE80211AC */
|
||||
|
||||
/* WPA */
|
||||
if (hapd->conf->wpa == WPA_PROTO_WPA)
|
||||
tailpos = hostapd_eid_wpa(hapd, tailpos,
|
||||
tail + BEACON_TAIL_BUF_SIZE -
|
||||
tailpos);
|
||||
/* WPA / OSEN */
|
||||
tailpos = hostapd_get_wpa_ie(hapd, tailpos, tailend - tailpos);
|
||||
tailpos = hostapd_get_osen_ie(hapd, tailpos, tailend - tailpos);
|
||||
|
||||
/* Wi-Fi Alliance WMM */
|
||||
tailpos = hostapd_eid_wmm(hapd, tailpos);
|
||||
|
|
@ -1271,12 +1611,12 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
|||
|
||||
#ifdef CONFIG_HS20
|
||||
tailpos = hostapd_eid_hs20_indication(hapd, tailpos);
|
||||
tailpos = hostapd_eid_osen(hapd, tailpos);
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
||||
tailpos = hostapd_eid_mbo(hapd, tailpos, tail + tail_len - tailpos);
|
||||
tailpos = hostapd_eid_owe_trans(hapd, tailpos,
|
||||
tail + tail_len - tailpos);
|
||||
tailpos = hostapd_eid_dpp_cc(hapd, tailpos, tail + tail_len - tailpos);
|
||||
|
||||
if (hapd->conf->vendor_elements) {
|
||||
os_memcpy(tailpos, wpabuf_head(hapd->conf->vendor_elements),
|
||||
|
|
@ -1315,10 +1655,13 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
|||
params->key_mgmt_suites = hapd->conf->wpa_key_mgmt;
|
||||
params->auth_algs = hapd->conf->auth_algs;
|
||||
params->wpa_version = hapd->conf->wpa;
|
||||
params->privacy = hapd->conf->ssid.wep.keys_set || hapd->conf->wpa ||
|
||||
params->privacy = hapd->conf->wpa;
|
||||
#ifdef CONFIG_WEP
|
||||
params->privacy |= hapd->conf->ssid.wep.keys_set ||
|
||||
(hapd->conf->ieee802_1x &&
|
||||
(hapd->conf->default_wep_key_len ||
|
||||
hapd->conf->individual_wep_key_len));
|
||||
#endif /* CONFIG_WEP */
|
||||
switch (hapd->conf->ignore_broadcast_ssid) {
|
||||
case 0:
|
||||
params->hide_ssid = NO_SSID_HIDING;
|
||||
|
|
@ -1331,7 +1674,6 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
|||
break;
|
||||
}
|
||||
params->isolate = hapd->conf->isolate;
|
||||
params->smps_mode = hapd->iconf->ht_capab & HT_CAP_INFO_SMPS_MASK;
|
||||
#ifdef NEED_AP_MLME
|
||||
params->cts_protect = !!(ieee802_11_erp_info(hapd) &
|
||||
ERP_INFO_USE_PROTECTION);
|
||||
|
|
@ -1390,6 +1732,14 @@ void ieee802_11_free_ap_params(struct wpa_driver_ap_params *params)
|
|||
params->head = NULL;
|
||||
os_free(params->proberesp);
|
||||
params->proberesp = NULL;
|
||||
#ifdef CONFIG_FILS
|
||||
os_free(params->fd_frame_tmpl);
|
||||
params->fd_frame_tmpl = NULL;
|
||||
#endif /* CONFIG_FILS */
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
os_free(params->unsol_bcast_probe_resp_tmpl);
|
||||
params->unsol_bcast_probe_resp_tmpl = NULL;
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1403,6 +1753,11 @@ int ieee802_11_set_beacon(struct hostapd_data *hapd)
|
|||
struct wpabuf *beacon, *proberesp, *assocresp;
|
||||
int res, ret = -1;
|
||||
|
||||
if (!hapd->drv_priv) {
|
||||
wpa_printf(MSG_ERROR, "Interface is disabled");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hapd->csa_in_progress) {
|
||||
wpa_printf(MSG_ERROR, "Cannot set beacons during CSA period");
|
||||
return -1;
|
||||
|
|
@ -1421,11 +1776,41 @@ int ieee802_11_set_beacon(struct hostapd_data *hapd)
|
|||
params.proberesp_ies = proberesp;
|
||||
params.assocresp_ies = assocresp;
|
||||
params.reenable = hapd->reenable_beacon;
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
params.he_spr_ctrl = hapd->iface->conf->spr.sr_control;
|
||||
params.he_spr_non_srg_obss_pd_max_offset =
|
||||
hapd->iface->conf->spr.non_srg_obss_pd_max_offset;
|
||||
params.he_spr_srg_obss_pd_min_offset =
|
||||
hapd->iface->conf->spr.srg_obss_pd_min_offset;
|
||||
params.he_spr_srg_obss_pd_max_offset =
|
||||
hapd->iface->conf->spr.srg_obss_pd_max_offset;
|
||||
os_memcpy(params.he_spr_bss_color_bitmap,
|
||||
hapd->iface->conf->spr.srg_bss_color_bitmap, 8);
|
||||
os_memcpy(params.he_spr_partial_bssid_bitmap,
|
||||
hapd->iface->conf->spr.srg_partial_bssid_bitmap, 8);
|
||||
params.he_bss_color_disabled =
|
||||
hapd->iface->conf->he_op.he_bss_color_disabled;
|
||||
params.he_bss_color_partial =
|
||||
hapd->iface->conf->he_op.he_bss_color_partial;
|
||||
params.he_bss_color = hapd->iface->conf->he_op.he_bss_color;
|
||||
params.twt_responder = hostapd_get_he_twt_responder(hapd,
|
||||
IEEE80211_MODE_AP);
|
||||
params.unsol_bcast_probe_resp_tmpl =
|
||||
hostapd_unsol_bcast_probe_resp(hapd, ¶ms);
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
hapd->reenable_beacon = 0;
|
||||
#ifdef CONFIG_SAE
|
||||
params.sae_pwe = hapd->conf->sae_pwe;
|
||||
#endif /* CONFIG_SAE */
|
||||
|
||||
#ifdef CONFIG_FILS
|
||||
params.fd_frame_tmpl = hostapd_fils_discovery(hapd, ¶ms);
|
||||
#endif /* CONFIG_FILS */
|
||||
|
||||
if (cmode &&
|
||||
hostapd_set_freq_params(&freq, iconf->hw_mode, iface->freq,
|
||||
iconf->channel, iconf->ieee80211n,
|
||||
iconf->channel, iconf->enable_edmg,
|
||||
iconf->edmg_channel, iconf->ieee80211n,
|
||||
iconf->ieee80211ac, iconf->ieee80211ax,
|
||||
iconf->secondary_channel,
|
||||
hostapd_get_oper_chwidth(iconf),
|
||||
|
|
|
|||
|
|
@ -30,4 +30,6 @@ sta_track_seen_on(struct hostapd_iface *iface, const u8 *addr,
|
|||
void sta_track_claim_taxonomy_info(struct hostapd_iface *iface, const u8 *addr,
|
||||
struct wpabuf **probe_ie_taxonomy);
|
||||
|
||||
const u8 * hostapd_wpa_ie(struct hostapd_data *hapd, u8 eid);
|
||||
|
||||
#endif /* BEACON_H */
|
||||
|
|
|
|||
|
|
@ -273,6 +273,36 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
|
|||
if (!os_snprintf_error(buflen - len, res))
|
||||
len += res;
|
||||
}
|
||||
|
||||
if (sta->sae && sta->sae->tmp) {
|
||||
const u8 *pos;
|
||||
unsigned int j, count;
|
||||
struct wpabuf *groups = sta->sae->tmp->peer_rejected_groups;
|
||||
|
||||
res = os_snprintf(buf + len, buflen - len,
|
||||
"sae_rejected_groups=");
|
||||
if (!os_snprintf_error(buflen - len, res))
|
||||
len += res;
|
||||
|
||||
if (groups) {
|
||||
pos = wpabuf_head(groups);
|
||||
count = wpabuf_len(groups) / 2;
|
||||
} else {
|
||||
pos = NULL;
|
||||
count = 0;
|
||||
}
|
||||
for (j = 0; pos && j < count; j++) {
|
||||
res = os_snprintf(buf + len, buflen - len, "%s%d",
|
||||
j == 0 ? "" : " ", WPA_GET_LE16(pos));
|
||||
if (!os_snprintf_error(buflen - len, res))
|
||||
len += res;
|
||||
pos += 2;
|
||||
}
|
||||
|
||||
res = os_snprintf(buf + len, buflen - len, "\n");
|
||||
if (!os_snprintf_error(buflen - len, res))
|
||||
len += res;
|
||||
}
|
||||
#endif /* CONFIG_SAE */
|
||||
|
||||
if (sta->vlan_id > 0) {
|
||||
|
|
@ -315,7 +345,6 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
|
|||
}
|
||||
#endif /* CONFIG_IEEE80211AC */
|
||||
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
if ((sta->flags & WLAN_STA_HT) && sta->ht_capabilities) {
|
||||
res = os_snprintf(buf + len, buflen - len,
|
||||
"ht_caps_info=0x%04x\n",
|
||||
|
|
@ -324,7 +353,6 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
|
|||
if (!os_snprintf_error(buflen - len, res))
|
||||
len += res;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
if (sta->ext_capability &&
|
||||
buflen - len > (unsigned) (11 + 2 * sta->ext_capability[0])) {
|
||||
|
|
@ -432,9 +460,6 @@ static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype,
|
|||
int ret;
|
||||
u8 *pos;
|
||||
|
||||
if (!hapd->drv_priv || !hapd->driver->send_frame)
|
||||
return -1;
|
||||
|
||||
mgmt = os_zalloc(sizeof(*mgmt) + 100);
|
||||
if (mgmt == NULL)
|
||||
return -1;
|
||||
|
|
@ -468,8 +493,8 @@ static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype,
|
|||
pos += 2;
|
||||
*pos++ = minor_reason_code;
|
||||
|
||||
ret = hapd->driver->send_frame(hapd->drv_priv, (u8 *) mgmt,
|
||||
pos - (u8 *) mgmt, 1);
|
||||
ret = hostapd_drv_send_mlme(hapd, mgmt, pos - (u8 *) mgmt, 0, NULL, 0,
|
||||
0);
|
||||
os_free(mgmt);
|
||||
|
||||
return ret < 0 ? -1 : 0;
|
||||
|
|
@ -499,8 +524,7 @@ int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd,
|
|||
if (pos) {
|
||||
struct ieee80211_mgmt mgmt;
|
||||
int encrypt;
|
||||
if (!hapd->drv_priv || !hapd->driver->send_frame)
|
||||
return -1;
|
||||
|
||||
pos += 6;
|
||||
encrypt = atoi(pos);
|
||||
os_memset(&mgmt, 0, sizeof(mgmt));
|
||||
|
|
@ -510,10 +534,10 @@ int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd,
|
|||
os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
|
||||
os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
|
||||
mgmt.u.deauth.reason_code = host_to_le16(reason);
|
||||
if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
|
||||
IEEE80211_HDRLEN +
|
||||
sizeof(mgmt.u.deauth),
|
||||
encrypt) < 0)
|
||||
if (hostapd_drv_send_mlme(hapd, (u8 *) &mgmt,
|
||||
IEEE80211_HDRLEN +
|
||||
sizeof(mgmt.u.deauth),
|
||||
0, NULL, 0, !encrypt) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -562,8 +586,7 @@ int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd,
|
|||
if (pos) {
|
||||
struct ieee80211_mgmt mgmt;
|
||||
int encrypt;
|
||||
if (!hapd->drv_priv || !hapd->driver->send_frame)
|
||||
return -1;
|
||||
|
||||
pos += 6;
|
||||
encrypt = atoi(pos);
|
||||
os_memset(&mgmt, 0, sizeof(mgmt));
|
||||
|
|
@ -573,10 +596,10 @@ int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd,
|
|||
os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
|
||||
os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
|
||||
mgmt.u.disassoc.reason_code = host_to_le16(reason);
|
||||
if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
|
||||
IEEE80211_HDRLEN +
|
||||
sizeof(mgmt.u.deauth),
|
||||
encrypt) < 0)
|
||||
if (hostapd_drv_send_mlme(hapd, (u8 *) &mgmt,
|
||||
IEEE80211_HDRLEN +
|
||||
sizeof(mgmt.u.deauth),
|
||||
0, NULL, 0, !encrypt) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -709,6 +732,8 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
|
|||
|
||||
ret = os_snprintf(buf + len, buflen - len,
|
||||
"channel=%u\n"
|
||||
"edmg_enable=%d\n"
|
||||
"edmg_channel=%d\n"
|
||||
"secondary_channel=%d\n"
|
||||
"ieee80211n=%d\n"
|
||||
"ieee80211ac=%d\n"
|
||||
|
|
@ -716,17 +741,36 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
|
|||
"beacon_int=%u\n"
|
||||
"dtim_period=%d\n",
|
||||
iface->conf->channel,
|
||||
iface->conf->enable_edmg,
|
||||
iface->conf->edmg_channel,
|
||||
iface->conf->ieee80211n && !hapd->conf->disable_11n ?
|
||||
iface->conf->secondary_channel : 0,
|
||||
iface->conf->ieee80211n && !hapd->conf->disable_11n,
|
||||
iface->conf->ieee80211ac &&
|
||||
!hapd->conf->disable_11ac,
|
||||
iface->conf->ieee80211ax,
|
||||
iface->conf->ieee80211ax &&
|
||||
!hapd->conf->disable_11ax,
|
||||
iface->conf->beacon_int,
|
||||
hapd->conf->dtim_period);
|
||||
if (os_snprintf_error(buflen - len, ret))
|
||||
return len;
|
||||
len += ret;
|
||||
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
if (iface->conf->ieee80211ax && !hapd->conf->disable_11ax) {
|
||||
ret = os_snprintf(buf + len, buflen - len,
|
||||
"he_oper_chwidth=%d\n"
|
||||
"he_oper_centr_freq_seg0_idx=%d\n"
|
||||
"he_oper_centr_freq_seg1_idx=%d\n",
|
||||
iface->conf->he_oper_chwidth,
|
||||
iface->conf->he_oper_centr_freq_seg0_idx,
|
||||
iface->conf->he_oper_centr_freq_seg1_idx);
|
||||
if (os_snprintf_error(buflen - len, ret))
|
||||
return len;
|
||||
len += ret;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
|
||||
if (iface->conf->ieee80211ac && !hapd->conf->disable_11ac) {
|
||||
ret = os_snprintf(buf + len, buflen - len,
|
||||
"vht_oper_chwidth=%d\n"
|
||||
|
|
@ -865,6 +909,7 @@ int hostapd_parse_csa_settings(const char *pos,
|
|||
SET_CSA_SETTING(sec_channel_offset);
|
||||
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->block_tx = !!os_strstr(pos, " blocktx");
|
||||
#undef SET_CSA_SETTING
|
||||
|
||||
|
|
|
|||
|
|
@ -81,17 +81,17 @@ static int dfs_is_chan_allowed(struct hostapd_channel_data *chan, int n_chans)
|
|||
* We will also choose this first channel as the control one.
|
||||
*/
|
||||
int allowed_40[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
|
||||
184, 192 };
|
||||
165, 173, 184, 192 };
|
||||
/*
|
||||
* VHT80, valid channels based on center frequency:
|
||||
* 42, 58, 106, 122, 138, 155
|
||||
* 42, 58, 106, 122, 138, 155, 171
|
||||
*/
|
||||
int allowed_80[] = { 36, 52, 100, 116, 132, 149 };
|
||||
int allowed_80[] = { 36, 52, 100, 116, 132, 149, 165 };
|
||||
/*
|
||||
* VHT160 valid channels based on center frequency:
|
||||
* 50, 114
|
||||
* 50, 114, 163
|
||||
*/
|
||||
int allowed_160[] = { 36, 100 };
|
||||
int allowed_160[] = { 36, 100, 149 };
|
||||
int *allowed = allowed_40;
|
||||
unsigned int i, allowed_no = 0;
|
||||
|
||||
|
|
@ -144,30 +144,44 @@ static int dfs_chan_range_available(struct hostapd_hw_modes *mode,
|
|||
int i;
|
||||
u32 bw = num_chan_to_bw(num_chans);
|
||||
|
||||
if (first_chan_idx + num_chans > mode->num_channels)
|
||||
if (first_chan_idx + num_chans > mode->num_channels) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DFS: some channels in range not defined");
|
||||
return 0;
|
||||
}
|
||||
|
||||
first_chan = &mode->channels[first_chan_idx];
|
||||
|
||||
/* hostapd DFS implementation assumes the first channel as primary.
|
||||
* If it's not allowed to use the first channel as primary, decline the
|
||||
* whole channel range. */
|
||||
if (!chan_pri_allowed(first_chan))
|
||||
if (!chan_pri_allowed(first_chan)) {
|
||||
wpa_printf(MSG_DEBUG, "DFS: primary chanenl not allowed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_chans; i++) {
|
||||
chan = dfs_get_chan_data(mode, first_chan->freq + i * 20,
|
||||
first_chan_idx);
|
||||
if (!chan)
|
||||
if (!chan) {
|
||||
wpa_printf(MSG_DEBUG, "DFS: no channel data for %d",
|
||||
first_chan->freq + i * 20);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* HT 40 MHz secondary channel availability checked only for
|
||||
* primary channel */
|
||||
if (!chan_bw_allowed(chan, bw, 1, !i))
|
||||
if (!chan_bw_allowed(chan, bw, 1, !i)) {
|
||||
wpa_printf(MSG_DEBUG, "DFS: bw now allowed for %d",
|
||||
first_chan->freq + i * 20);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dfs_channel_available(chan, skip_radar))
|
||||
if (!dfs_channel_available(chan, skip_radar)) {
|
||||
wpa_printf(MSG_DEBUG, "DFS: channel not available %d",
|
||||
first_chan->freq + i * 20);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
|
@ -210,22 +224,36 @@ static int dfs_find_channel(struct hostapd_iface *iface,
|
|||
if (iface->conf->ieee80211n &&
|
||||
iface->conf->secondary_channel &&
|
||||
(!dfs_is_chan_allowed(chan, n_chans) ||
|
||||
!(chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P)))
|
||||
!(chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P))) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DFS: channel %d (%d) is incompatible",
|
||||
chan->freq, chan->chan);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Skip incompatible chandefs */
|
||||
if (!dfs_chan_range_available(mode, i, n_chans, skip_radar))
|
||||
if (!dfs_chan_range_available(mode, i, n_chans, skip_radar)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DFS: range not available for %d (%d)",
|
||||
chan->freq, chan->chan);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!is_in_chanlist(iface, chan))
|
||||
if (!is_in_chanlist(iface, chan)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DFS: channel %d (%d) not in chanlist",
|
||||
chan->freq, chan->chan);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ret_chan && idx == channel_idx) {
|
||||
wpa_printf(MSG_DEBUG, "Selected ch. #%d", chan->chan);
|
||||
wpa_printf(MSG_DEBUG, "Selected channel %d (%d)",
|
||||
chan->freq, chan->chan);
|
||||
*ret_chan = chan;
|
||||
return idx;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "Adding channel: %d", chan->chan);
|
||||
wpa_printf(MSG_DEBUG, "Adding channel %d (%d)",
|
||||
chan->freq, chan->chan);
|
||||
channel_idx++;
|
||||
}
|
||||
return channel_idx;
|
||||
|
|
@ -235,6 +263,7 @@ static int dfs_find_channel(struct hostapd_iface *iface,
|
|||
static void dfs_adjust_center_freq(struct hostapd_iface *iface,
|
||||
struct hostapd_channel_data *chan,
|
||||
int secondary_channel,
|
||||
int sec_chan_idx_80p80,
|
||||
u8 *oper_centr_freq_seg0_idx,
|
||||
u8 *oper_centr_freq_seg1_idx)
|
||||
{
|
||||
|
|
@ -261,8 +290,14 @@ static void dfs_adjust_center_freq(struct hostapd_iface *iface,
|
|||
case CHANWIDTH_160MHZ:
|
||||
*oper_centr_freq_seg0_idx = chan->chan + 14;
|
||||
break;
|
||||
case CHANWIDTH_80P80MHZ:
|
||||
*oper_centr_freq_seg0_idx = chan->chan + 6;
|
||||
*oper_centr_freq_seg1_idx = sec_chan_idx_80p80 + 6;
|
||||
break;
|
||||
|
||||
default:
|
||||
wpa_printf(MSG_INFO, "DFS only VHT20/40/80/160 is supported now");
|
||||
wpa_printf(MSG_INFO,
|
||||
"DFS: Unsupported channel width configuration");
|
||||
*oper_centr_freq_seg0_idx = 0;
|
||||
break;
|
||||
}
|
||||
|
|
@ -441,8 +476,11 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
|
|||
{
|
||||
struct hostapd_hw_modes *mode;
|
||||
struct hostapd_channel_data *chan = NULL;
|
||||
struct hostapd_channel_data *chan2 = NULL;
|
||||
int num_available_chandefs;
|
||||
int chan_idx;
|
||||
int chan_idx, chan_idx2;
|
||||
int sec_chan_idx_80p80 = -1;
|
||||
int i;
|
||||
u32 _rand;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "DFS: Selecting random channel");
|
||||
|
|
@ -459,6 +497,8 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
|
|||
|
||||
/* Get the count first */
|
||||
num_available_chandefs = dfs_find_channel(iface, NULL, 0, skip_radar);
|
||||
wpa_printf(MSG_DEBUG, "DFS: num_available_chandefs=%d",
|
||||
num_available_chandefs);
|
||||
if (num_available_chandefs == 0)
|
||||
return NULL;
|
||||
|
||||
|
|
@ -466,6 +506,12 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
|
|||
return NULL;
|
||||
chan_idx = _rand % num_available_chandefs;
|
||||
dfs_find_channel(iface, &chan, chan_idx, skip_radar);
|
||||
if (!chan) {
|
||||
wpa_printf(MSG_DEBUG, "DFS: no random channel found");
|
||||
return NULL;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "DFS: got random channel %d (%d)",
|
||||
chan->freq, chan->chan);
|
||||
|
||||
/* dfs_find_channel() calculations assume HT40+ */
|
||||
if (iface->conf->secondary_channel)
|
||||
|
|
@ -473,8 +519,45 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
|
|||
else
|
||||
*secondary_channel = 0;
|
||||
|
||||
/* Get secondary channel for HT80P80 */
|
||||
if (hostapd_get_oper_chwidth(iface->conf) == CHANWIDTH_80P80MHZ) {
|
||||
if (num_available_chandefs <= 1) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"only 1 valid chan, can't support 80+80");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Loop all channels except channel1 to find a valid channel2
|
||||
* that is not adjacent to channel1.
|
||||
*/
|
||||
for (i = 0; i < num_available_chandefs - 1; i++) {
|
||||
/* start from chan_idx + 1, end when chan_idx - 1 */
|
||||
chan_idx2 = (chan_idx + 1 + i) % num_available_chandefs;
|
||||
dfs_find_channel(iface, &chan2, chan_idx2, skip_radar);
|
||||
if (chan2 && abs(chan2->chan - chan->chan) > 12) {
|
||||
/* two channels are not adjacent */
|
||||
sec_chan_idx_80p80 = chan2->chan;
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DFS: got second chan: %d (%d)",
|
||||
chan2->freq, chan2->chan);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we got a valid secondary channel which is not
|
||||
* adjacent to the first channel.
|
||||
*/
|
||||
if (sec_chan_idx_80p80 == -1) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"DFS: failed to get chan2 for 80+80");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
dfs_adjust_center_freq(iface, chan,
|
||||
*secondary_channel,
|
||||
sec_chan_idx_80p80,
|
||||
oper_centr_freq_seg0_idx,
|
||||
oper_centr_freq_seg1_idx);
|
||||
|
||||
|
|
@ -515,6 +598,7 @@ static int set_dfs_state(struct hostapd_iface *iface, int freq, int ht_enabled,
|
|||
int n_chans = 1, i;
|
||||
struct hostapd_hw_modes *mode;
|
||||
int frequency = freq;
|
||||
int frequency2 = 0;
|
||||
int ret = 0;
|
||||
|
||||
mode = iface->current_mode;
|
||||
|
|
@ -542,6 +626,11 @@ static int set_dfs_state(struct hostapd_iface *iface, int freq, int ht_enabled,
|
|||
n_chans = 4;
|
||||
frequency = cf1 - 30;
|
||||
break;
|
||||
case CHAN_WIDTH_80P80:
|
||||
n_chans = 4;
|
||||
frequency = cf1 - 30;
|
||||
frequency2 = cf2 - 30;
|
||||
break;
|
||||
case CHAN_WIDTH_160:
|
||||
n_chans = 8;
|
||||
frequency = cf1 - 70;
|
||||
|
|
@ -557,6 +646,11 @@ static int set_dfs_state(struct hostapd_iface *iface, int freq, int ht_enabled,
|
|||
for (i = 0; i < n_chans; i++) {
|
||||
ret += set_dfs_state_freq(iface, frequency, state);
|
||||
frequency = frequency + 20;
|
||||
|
||||
if (chan_width == CHAN_WIDTH_80P80) {
|
||||
ret += set_dfs_state_freq(iface, frequency2, state);
|
||||
frequency2 = frequency2 + 20;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -662,6 +756,9 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
|
|||
int res, n_chans, n_chans1, start_chan_idx, start_chan_idx1;
|
||||
int skip_radar = 0;
|
||||
|
||||
if (is_6ghz_freq(iface->freq))
|
||||
return 1;
|
||||
|
||||
if (!iface->current_mode) {
|
||||
/*
|
||||
* This can happen with drivers that do not provide mode
|
||||
|
|
@ -759,7 +856,7 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
|
|||
}
|
||||
|
||||
|
||||
static int hostapd_config_dfs_chan_available(struct hostapd_iface *iface)
|
||||
int hostapd_is_dfs_chan_available(struct hostapd_iface *iface)
|
||||
{
|
||||
int n_chans, n_chans1, start_chan_idx, start_chan_idx1;
|
||||
|
||||
|
|
@ -807,7 +904,7 @@ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
|
|||
* another radio.
|
||||
*/
|
||||
if (iface->state != HAPD_IFACE_ENABLED &&
|
||||
hostapd_config_dfs_chan_available(iface)) {
|
||||
hostapd_is_dfs_chan_available(iface)) {
|
||||
hostapd_setup_interface_complete(iface, 0);
|
||||
iface->cac_started = 0;
|
||||
}
|
||||
|
|
@ -837,6 +934,44 @@ int hostapd_dfs_pre_cac_expired(struct hostapd_iface *iface, int freq,
|
|||
}
|
||||
|
||||
|
||||
static struct hostapd_channel_data *
|
||||
dfs_downgrade_bandwidth(struct hostapd_iface *iface, int *secondary_channel,
|
||||
u8 *oper_centr_freq_seg0_idx,
|
||||
u8 *oper_centr_freq_seg1_idx, int *skip_radar)
|
||||
{
|
||||
struct hostapd_channel_data *channel;
|
||||
|
||||
for (;;) {
|
||||
channel = dfs_get_valid_channel(iface, secondary_channel,
|
||||
oper_centr_freq_seg0_idx,
|
||||
oper_centr_freq_seg1_idx,
|
||||
*skip_radar);
|
||||
if (channel) {
|
||||
wpa_printf(MSG_DEBUG, "DFS: Selected channel: %d",
|
||||
channel->chan);
|
||||
return channel;
|
||||
}
|
||||
|
||||
if (*skip_radar) {
|
||||
*skip_radar = 0;
|
||||
} else {
|
||||
int oper_chwidth;
|
||||
|
||||
oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
|
||||
if (oper_chwidth == CHANWIDTH_USE_HT)
|
||||
break;
|
||||
*skip_radar = 1;
|
||||
hostapd_set_oper_chwidth(iface->conf, oper_chwidth - 1);
|
||||
}
|
||||
}
|
||||
|
||||
wpa_printf(MSG_INFO,
|
||||
"%s: no DFS channels left, waiting for NOP to finish",
|
||||
__func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface)
|
||||
{
|
||||
struct hostapd_channel_data *channel;
|
||||
|
|
@ -854,8 +989,14 @@ static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface)
|
|||
skip_radar);
|
||||
|
||||
if (!channel) {
|
||||
wpa_printf(MSG_ERROR, "No valid channel available");
|
||||
return err;
|
||||
channel = dfs_downgrade_bandwidth(iface, &secondary_channel,
|
||||
&oper_centr_freq_seg0_idx,
|
||||
&oper_centr_freq_seg1_idx,
|
||||
&skip_radar);
|
||||
if (!channel) {
|
||||
wpa_printf(MSG_ERROR, "No valid channel available");
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d",
|
||||
|
|
@ -884,11 +1025,14 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
|
|||
int secondary_channel;
|
||||
u8 oper_centr_freq_seg0_idx;
|
||||
u8 oper_centr_freq_seg1_idx;
|
||||
u8 new_vht_oper_chwidth;
|
||||
int skip_radar = 1;
|
||||
struct csa_settings csa_settings;
|
||||
unsigned int i;
|
||||
int err = 1;
|
||||
struct hostapd_hw_modes *cmode = iface->current_mode;
|
||||
u8 current_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
|
||||
int ieee80211_mode = IEEE80211_MODE_AP;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s called (CAC active: %s, CSA active: %s)",
|
||||
__func__, iface->cac_started ? "yes" : "no",
|
||||
|
|
@ -922,28 +1066,33 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
|
|||
* requires to perform a CAC first.
|
||||
*/
|
||||
skip_radar = 0;
|
||||
channel = dfs_get_valid_channel(iface, &secondary_channel,
|
||||
&oper_centr_freq_seg0_idx,
|
||||
&oper_centr_freq_seg1_idx,
|
||||
skip_radar);
|
||||
channel = dfs_downgrade_bandwidth(iface, &secondary_channel,
|
||||
&oper_centr_freq_seg0_idx,
|
||||
&oper_centr_freq_seg1_idx,
|
||||
&skip_radar);
|
||||
if (!channel) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"%s: no DFS channels left, waiting for NOP to finish",
|
||||
__func__);
|
||||
return err;
|
||||
/*
|
||||
* Toggle interface state to enter DFS state
|
||||
* until NOP is finished.
|
||||
*/
|
||||
hostapd_disable_iface(iface);
|
||||
hostapd_enable_iface(iface);
|
||||
return 0;
|
||||
}
|
||||
|
||||
iface->freq = channel->freq;
|
||||
iface->conf->channel = channel->chan;
|
||||
iface->conf->secondary_channel = secondary_channel;
|
||||
hostapd_set_oper_centr_freq_seg0_idx(iface->conf,
|
||||
oper_centr_freq_seg0_idx);
|
||||
hostapd_set_oper_centr_freq_seg1_idx(iface->conf,
|
||||
oper_centr_freq_seg1_idx);
|
||||
if (!skip_radar) {
|
||||
iface->freq = channel->freq;
|
||||
iface->conf->channel = channel->chan;
|
||||
iface->conf->secondary_channel = secondary_channel;
|
||||
hostapd_set_oper_centr_freq_seg0_idx(
|
||||
iface->conf, oper_centr_freq_seg0_idx);
|
||||
hostapd_set_oper_centr_freq_seg1_idx(
|
||||
iface->conf, oper_centr_freq_seg1_idx);
|
||||
|
||||
hostapd_disable_iface(iface);
|
||||
hostapd_enable_iface(iface);
|
||||
return 0;
|
||||
hostapd_disable_iface(iface);
|
||||
hostapd_enable_iface(iface);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d",
|
||||
|
|
@ -952,23 +1101,32 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
|
|||
"freq=%d chan=%d sec_chan=%d", channel->freq,
|
||||
channel->chan, secondary_channel);
|
||||
|
||||
new_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
|
||||
hostapd_set_oper_chwidth(iface->conf, current_vht_oper_chwidth);
|
||||
|
||||
/* Setup CSA request */
|
||||
os_memset(&csa_settings, 0, sizeof(csa_settings));
|
||||
csa_settings.cs_count = 5;
|
||||
csa_settings.block_tx = 1;
|
||||
#ifdef CONFIG_MESH
|
||||
if (iface->mconf)
|
||||
ieee80211_mode = IEEE80211_MODE_MESH;
|
||||
#endif /* CONFIG_MESH */
|
||||
err = hostapd_set_freq_params(&csa_settings.freq_params,
|
||||
iface->conf->hw_mode,
|
||||
channel->freq,
|
||||
channel->chan,
|
||||
iface->conf->enable_edmg,
|
||||
iface->conf->edmg_channel,
|
||||
iface->conf->ieee80211n,
|
||||
iface->conf->ieee80211ac,
|
||||
iface->conf->ieee80211ax,
|
||||
secondary_channel,
|
||||
hostapd_get_oper_chwidth(iface->conf),
|
||||
new_vht_oper_chwidth,
|
||||
oper_centr_freq_seg0_idx,
|
||||
oper_centr_freq_seg1_idx,
|
||||
cmode->vht_capab,
|
||||
&cmode->he_capab[IEEE80211_MODE_AP]);
|
||||
&cmode->he_capab[ieee80211_mode]);
|
||||
|
||||
if (err) {
|
||||
wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params");
|
||||
|
|
@ -988,6 +1146,7 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
|
|||
iface->freq = channel->freq;
|
||||
iface->conf->channel = channel->chan;
|
||||
iface->conf->secondary_channel = secondary_channel;
|
||||
hostapd_set_oper_chwidth(iface->conf, new_vht_oper_chwidth);
|
||||
hostapd_set_oper_centr_freq_seg0_idx(iface->conf,
|
||||
oper_centr_freq_seg0_idx);
|
||||
hostapd_set_oper_centr_freq_seg1_idx(iface->conf,
|
||||
|
|
@ -1024,8 +1183,10 @@ int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq,
|
|||
return 0;
|
||||
|
||||
/* mark radar frequency as invalid */
|
||||
set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width,
|
||||
cf1, cf2, HOSTAPD_CHAN_DFS_UNAVAILABLE);
|
||||
res = set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width,
|
||||
cf1, cf2, HOSTAPD_CHAN_DFS_UNAVAILABLE);
|
||||
if (!res)
|
||||
return 0;
|
||||
|
||||
/* Skip if reported radar event not overlapped our channels */
|
||||
res = dfs_are_channels_overlapped(iface, freq, chan_width, cf1, cf2);
|
||||
|
|
@ -1067,7 +1228,9 @@ int hostapd_is_dfs_required(struct hostapd_iface *iface)
|
|||
{
|
||||
int n_chans, n_chans1, start_chan_idx, start_chan_idx1, res;
|
||||
|
||||
if (!iface->conf->ieee80211h || !iface->current_mode ||
|
||||
if ((!(iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
|
||||
!iface->conf->ieee80211h) ||
|
||||
!iface->current_mode ||
|
||||
iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A)
|
||||
return 0;
|
||||
|
||||
|
|
@ -1093,11 +1256,18 @@ int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
|
|||
int ht_enabled, int chan_offset, int chan_width,
|
||||
int cf1, int cf2)
|
||||
{
|
||||
/* This is called when the driver indicates that an offloaded DFS has
|
||||
* started CAC. */
|
||||
hostapd_set_state(iface, HAPD_IFACE_DFS);
|
||||
/* 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
|
||||
"freq=%d chan=%d chan_offset=%d width=%d seg0=%d "
|
||||
"seg1=%d cac_time=%ds",
|
||||
freq, (freq - 5000) / 5, chan_offset, chan_width, cf1, cf2, 60);
|
||||
freq, (freq - 5000) / 5, chan_offset, chan_width, cf1, cf2,
|
||||
iface->dfs_cac_ms / 1000);
|
||||
iface->cac_started = 1;
|
||||
os_get_reltime(&iface->dfs_cac_start);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1111,6 +1281,8 @@ int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
|
|||
*/
|
||||
int hostapd_handle_dfs_offload(struct hostapd_iface *iface)
|
||||
{
|
||||
int dfs_res;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s: iface->cac_started: %d",
|
||||
__func__, iface->cac_started);
|
||||
|
||||
|
|
@ -1126,10 +1298,11 @@ int hostapd_handle_dfs_offload(struct hostapd_iface *iface)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (ieee80211_is_dfs(iface->freq, iface->hw_features,
|
||||
iface->num_hw_features)) {
|
||||
wpa_printf(MSG_DEBUG, "%s: freq %d MHz requires DFS",
|
||||
__func__, iface->freq);
|
||||
dfs_res = hostapd_is_dfs_required(iface);
|
||||
if (dfs_res > 0) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"%s: freq %d MHz requires DFS for %d chans",
|
||||
__func__, iface->freq, dfs_res);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1138,3 +1311,60 @@ int hostapd_handle_dfs_offload(struct hostapd_iface *iface)
|
|||
__func__, iface->freq);
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_is_dfs_overlap(struct hostapd_iface *iface, enum chan_width width,
|
||||
int center_freq)
|
||||
{
|
||||
struct hostapd_channel_data *chan;
|
||||
struct hostapd_hw_modes *mode = iface->current_mode;
|
||||
int half_width;
|
||||
int res = 0;
|
||||
int i;
|
||||
|
||||
if (!iface->conf->ieee80211h || !mode ||
|
||||
mode->mode != HOSTAPD_MODE_IEEE80211A)
|
||||
return 0;
|
||||
|
||||
switch (width) {
|
||||
case CHAN_WIDTH_20_NOHT:
|
||||
case CHAN_WIDTH_20:
|
||||
half_width = 10;
|
||||
break;
|
||||
case CHAN_WIDTH_40:
|
||||
half_width = 20;
|
||||
break;
|
||||
case CHAN_WIDTH_80:
|
||||
case CHAN_WIDTH_80P80:
|
||||
half_width = 40;
|
||||
break;
|
||||
case CHAN_WIDTH_160:
|
||||
half_width = 80;
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_WARNING, "DFS chanwidth %d not supported",
|
||||
width);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < mode->num_channels; i++) {
|
||||
chan = &mode->channels[i];
|
||||
|
||||
if (!(chan->flag & HOSTAPD_CHAN_RADAR))
|
||||
continue;
|
||||
|
||||
if ((chan->flag & HOSTAPD_CHAN_DFS_MASK) ==
|
||||
HOSTAPD_CHAN_DFS_AVAILABLE)
|
||||
continue;
|
||||
|
||||
if (center_freq - chan->freq < half_width &&
|
||||
chan->freq - center_freq < half_width)
|
||||
res++;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "DFS CAC required: (%d, %d): in range: %s",
|
||||
center_freq - half_width, center_freq + half_width,
|
||||
res ? "yes" : "no");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,9 +25,12 @@ int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq,
|
|||
int ht_enabled,
|
||||
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 ht_enabled, int chan_offset, int chan_width,
|
||||
int cf1, int cf2);
|
||||
int hostapd_handle_dfs_offload(struct hostapd_iface *iface);
|
||||
int hostapd_is_dfs_overlap(struct hostapd_iface *iface, enum chan_width width,
|
||||
int center_freq);
|
||||
|
||||
#endif /* DFS_H */
|
||||
|
|
|
|||
|
|
@ -39,22 +39,22 @@ static void handle_dhcp(void *ctx, const u8 *src_addr, const u8 *buf,
|
|||
const u8 *end, *pos;
|
||||
int res, msgtype = 0, prefixlen = 32;
|
||||
u32 subnet_mask = 0;
|
||||
u16 tot_len;
|
||||
u16 ip_len;
|
||||
|
||||
exten_len = len - ETH_HLEN - (sizeof(*b) - sizeof(b->exten));
|
||||
if (exten_len < 4)
|
||||
return;
|
||||
|
||||
b = (const struct bootp_pkt *) &buf[ETH_HLEN];
|
||||
tot_len = ntohs(b->iph.tot_len);
|
||||
if (tot_len > (unsigned int) (len - ETH_HLEN))
|
||||
ip_len = ntohs(b->iph.ip_len);
|
||||
if (ip_len > (unsigned int) (len - ETH_HLEN))
|
||||
return;
|
||||
|
||||
if (WPA_GET_BE32(b->exten) != DHCP_MAGIC)
|
||||
return;
|
||||
|
||||
/* Parse DHCP options */
|
||||
end = (const u8 *) b + tot_len;
|
||||
end = (const u8 *) b + ip_len;
|
||||
pos = &b->exten[4];
|
||||
while (pos < end && *pos != DHCP_OPT_END) {
|
||||
const u8 *opt = pos++;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* hostapd / DPP integration
|
||||
* Copyright (c) 2017, Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018-2020, The Linux Foundation
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
|
|
@ -9,7 +10,12 @@
|
|||
#ifndef DPP_HOSTAPD_H
|
||||
#define DPP_HOSTAPD_H
|
||||
|
||||
struct dpp_bootstrap_info;
|
||||
|
||||
int hostapd_dpp_qr_code(struct hostapd_data *hapd, const char *cmd);
|
||||
int hostapd_dpp_nfc_uri(struct hostapd_data *hapd, const char *cmd);
|
||||
int hostapd_dpp_nfc_handover_req(struct hostapd_data *hapd, const char *cmd);
|
||||
int hostapd_dpp_nfc_handover_sel(struct hostapd_data *hapd, const char *cmd);
|
||||
int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd);
|
||||
int hostapd_dpp_listen(struct hostapd_data *hapd, const char *cmd);
|
||||
void hostapd_dpp_listen_stop(struct hostapd_data *hapd);
|
||||
|
|
@ -35,4 +41,9 @@ void hostapd_dpp_deinit(struct hostapd_data *hapd);
|
|||
void hostapd_dpp_init_global(struct hapd_interfaces *ifaces);
|
||||
void hostapd_dpp_deinit_global(struct hapd_interfaces *ifaces);
|
||||
|
||||
int hostapd_dpp_controller_start(struct hostapd_data *hapd, const char *cmd);
|
||||
int hostapd_dpp_chirp(struct hostapd_data *hapd, const char *cmd);
|
||||
void hostapd_dpp_chirp_stop(struct hostapd_data *hapd);
|
||||
void hostapd_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi);
|
||||
|
||||
#endif /* DPP_HOSTAPD_H */
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
#include "common/ieee802_11_common.h"
|
||||
#include "common/wpa_ctrl.h"
|
||||
#include "common/dpp.h"
|
||||
#include "common/sae.h"
|
||||
#include "common/hw_features_common.h"
|
||||
#include "crypto/random.h"
|
||||
#include "p2p/p2p.h"
|
||||
#include "wps/wps.h"
|
||||
|
|
@ -103,20 +105,45 @@ void hostapd_notify_assoc_fils_finish(struct hostapd_data *hapd,
|
|||
#endif /* CONFIG_FILS */
|
||||
|
||||
|
||||
static bool check_sa_query_need(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
if ((sta->flags &
|
||||
(WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED)) !=
|
||||
(WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED))
|
||||
return false;
|
||||
|
||||
if (!sta->sa_query_timed_out && sta->sa_query_count > 0)
|
||||
ap_check_sa_query_timeout(hapd, sta);
|
||||
|
||||
if (!sta->sa_query_timed_out && (sta->auth_alg != WLAN_AUTH_FT)) {
|
||||
/*
|
||||
* STA has already been associated with MFP and SA Query timeout
|
||||
* has not been reached. Reject the association attempt
|
||||
* temporarily and start SA Query, if one is not pending.
|
||||
*/
|
||||
if (sta->sa_query_count == 0)
|
||||
ap_sta_start_sa_query(hapd, sta);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *req_ies, size_t req_ies_len, int reassoc)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
int new_assoc, res;
|
||||
int new_assoc;
|
||||
enum wpa_validate_result res;
|
||||
struct ieee802_11_elems elems;
|
||||
const u8 *ie;
|
||||
size_t ielen;
|
||||
#if defined(CONFIG_IEEE80211R_AP) || defined(CONFIG_IEEE80211W) || defined(CONFIG_FILS) || defined(CONFIG_OWE)
|
||||
u8 buf[sizeof(struct ieee80211_mgmt) + 1024];
|
||||
u8 *p = buf;
|
||||
#endif /* CONFIG_IEEE80211R_AP || CONFIG_IEEE80211W || CONFIG_FILS || CONFIG_OWE */
|
||||
u16 reason = WLAN_REASON_UNSPECIFIED;
|
||||
u16 status = WLAN_STATUS_SUCCESS;
|
||||
int status = WLAN_STATUS_SUCCESS;
|
||||
const u8 *p2p_dev_addr = NULL;
|
||||
|
||||
if (addr == NULL) {
|
||||
|
|
@ -131,6 +158,19 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
|||
"hostapd_notif_assoc: Skip event with no address");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (is_multicast_ether_addr(addr) ||
|
||||
is_zero_ether_addr(addr) ||
|
||||
os_memcmp(addr, hapd->own_addr, ETH_ALEN) == 0) {
|
||||
/* Do not process any frames with unexpected/invalid SA so that
|
||||
* we do not add any state for unexpected STA addresses or end
|
||||
* up sending out frames to unexpected destination. */
|
||||
wpa_printf(MSG_DEBUG, "%s: Invalid SA=" MACSTR
|
||||
" in received indication - ignore this indication silently",
|
||||
__func__, MAC2STR(addr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
random_add_randomness(addr, ETH_ALEN);
|
||||
|
||||
hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
|
||||
|
|
@ -207,7 +247,6 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
|||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
#ifdef NEED_AP_MLME
|
||||
if (elems.ht_capabilities &&
|
||||
(hapd->iface->conf->ht_capab &
|
||||
|
|
@ -221,7 +260,6 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
|||
ht40_intolerant_add(hapd->iface, sta);
|
||||
}
|
||||
#endif /* NEED_AP_MLME */
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
if (elems.ext_capab && elems.ext_capab_len > 4) {
|
||||
|
|
@ -281,6 +319,17 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
|||
os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
|
||||
struct wpabuf *wps;
|
||||
|
||||
if (check_sa_query_need(hapd, sta)) {
|
||||
status = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
|
||||
|
||||
p = hostapd_eid_assoc_comeback_time(hapd, sta,
|
||||
p);
|
||||
|
||||
hostapd_sta_assoc(hapd, addr, reassoc, status,
|
||||
buf, p - buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sta->flags |= WLAN_STA_WPS;
|
||||
wps = ieee802_11_vendor_ie_concat(ie, ielen,
|
||||
WPS_IE_VENDOR_TYPE);
|
||||
|
|
@ -308,58 +357,75 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
|||
res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
|
||||
hapd->iface->freq,
|
||||
ie, ielen,
|
||||
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);
|
||||
if (res != WPA_IE_OK) {
|
||||
reason = WLAN_REASON_INVALID_IE;
|
||||
status = WLAN_STATUS_INVALID_IE;
|
||||
switch (res) {
|
||||
case WPA_IE_OK:
|
||||
reason = WLAN_REASON_UNSPECIFIED;
|
||||
status = WLAN_STATUS_SUCCESS;
|
||||
break;
|
||||
case WPA_INVALID_IE:
|
||||
reason = WLAN_REASON_INVALID_IE;
|
||||
status = WLAN_STATUS_INVALID_IE;
|
||||
break;
|
||||
case WPA_INVALID_GROUP:
|
||||
reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
|
||||
status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
|
||||
break;
|
||||
case WPA_INVALID_PAIRWISE:
|
||||
reason = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
|
||||
status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
|
||||
break;
|
||||
case WPA_INVALID_AKMP:
|
||||
reason = WLAN_REASON_AKMP_NOT_VALID;
|
||||
status = WLAN_STATUS_AKMP_NOT_VALID;
|
||||
break;
|
||||
case WPA_NOT_ENABLED:
|
||||
reason = WLAN_REASON_INVALID_IE;
|
||||
status = WLAN_STATUS_INVALID_IE;
|
||||
break;
|
||||
case WPA_ALLOC_FAIL:
|
||||
reason = WLAN_REASON_UNSPECIFIED;
|
||||
status = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
break;
|
||||
case WPA_MGMT_FRAME_PROTECTION_VIOLATION:
|
||||
reason = WLAN_REASON_INVALID_IE;
|
||||
status = WLAN_STATUS_INVALID_IE;
|
||||
break;
|
||||
case WPA_INVALID_MGMT_GROUP_CIPHER:
|
||||
reason = WLAN_REASON_CIPHER_SUITE_REJECTED;
|
||||
status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
|
||||
break;
|
||||
case WPA_INVALID_MDIE:
|
||||
reason = WLAN_REASON_INVALID_MDE;
|
||||
status = WLAN_STATUS_INVALID_MDIE;
|
||||
break;
|
||||
case WPA_INVALID_PROTO:
|
||||
reason = WLAN_REASON_INVALID_IE;
|
||||
status = WLAN_STATUS_INVALID_IE;
|
||||
break;
|
||||
case WPA_INVALID_PMKID:
|
||||
reason = WLAN_REASON_INVALID_PMKID;
|
||||
status = WLAN_STATUS_INVALID_PMKID;
|
||||
break;
|
||||
case WPA_DENIED_OTHER_REASON:
|
||||
reason = WLAN_REASON_UNSPECIFIED;
|
||||
status = WLAN_STATUS_ASSOC_DENIED_UNSPEC;
|
||||
break;
|
||||
}
|
||||
if (status != WLAN_STATUS_SUCCESS) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"WPA/RSN information element rejected? (res %u)",
|
||||
res);
|
||||
wpa_hexdump(MSG_DEBUG, "IE", ie, ielen);
|
||||
if (res == WPA_INVALID_GROUP) {
|
||||
reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
|
||||
status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
|
||||
} else if (res == WPA_INVALID_PAIRWISE) {
|
||||
reason = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
|
||||
status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
|
||||
} else if (res == WPA_INVALID_AKMP) {
|
||||
reason = WLAN_REASON_AKMP_NOT_VALID;
|
||||
status = WLAN_STATUS_AKMP_NOT_VALID;
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) {
|
||||
reason = WLAN_REASON_INVALID_IE;
|
||||
status = WLAN_STATUS_INVALID_IE;
|
||||
} else if (res == WPA_INVALID_MGMT_GROUP_CIPHER) {
|
||||
reason = WLAN_REASON_CIPHER_SUITE_REJECTED;
|
||||
status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
else {
|
||||
reason = WLAN_REASON_INVALID_IE;
|
||||
status = WLAN_STATUS_INVALID_IE;
|
||||
}
|
||||
goto fail;
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) ==
|
||||
(WLAN_STA_ASSOC | WLAN_STA_MFP) &&
|
||||
!sta->sa_query_timed_out &&
|
||||
sta->sa_query_count > 0)
|
||||
ap_check_sa_query_timeout(hapd, sta);
|
||||
if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) ==
|
||||
(WLAN_STA_ASSOC | WLAN_STA_MFP) &&
|
||||
!sta->sa_query_timed_out &&
|
||||
(sta->auth_alg != WLAN_AUTH_FT)) {
|
||||
/*
|
||||
* STA has already been associated with MFP and SA
|
||||
* Query timeout has not been reached. Reject the
|
||||
* association attempt temporarily and start SA Query,
|
||||
* if one is not pending.
|
||||
*/
|
||||
|
||||
if (sta->sa_query_count == 0)
|
||||
ap_sta_start_sa_query(hapd, sta);
|
||||
|
||||
if (check_sa_query_need(hapd, sta)) {
|
||||
status = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
|
||||
|
||||
p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
|
||||
|
|
@ -373,7 +439,6 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
|||
sta->flags |= WLAN_STA_MFP;
|
||||
else
|
||||
sta->flags &= ~WLAN_STA_MFP;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
#ifdef CONFIG_IEEE80211R_AP
|
||||
if (sta->auth_alg == WLAN_AUTH_FT) {
|
||||
|
|
@ -390,6 +455,20 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
|||
}
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R_AP */
|
||||
#ifdef CONFIG_SAE
|
||||
if (hapd->conf->sae_pwe == 2 &&
|
||||
sta->auth_alg == WLAN_AUTH_SAE &&
|
||||
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;
|
||||
}
|
||||
#endif /* CONFIG_SAE */
|
||||
} else if (hapd->conf->wps_state) {
|
||||
#ifdef CONFIG_WPS
|
||||
struct wpabuf *wps;
|
||||
|
|
@ -442,6 +521,9 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
|||
return WLAN_STATUS_INVALID_IE;
|
||||
#endif /* CONFIG_HS20 */
|
||||
}
|
||||
#ifdef CONFIG_WPS
|
||||
skip_wpa_check:
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
#ifdef CONFIG_MBO
|
||||
if (hapd->conf->mbo_enabled && (hapd->conf->wpa & 2) &&
|
||||
|
|
@ -453,13 +535,10 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
|||
}
|
||||
#endif /* CONFIG_MBO */
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
skip_wpa_check:
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
#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);
|
||||
sta->auth_alg, req_ies, req_ies_len,
|
||||
!elems.rsnxe);
|
||||
if (!p) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Failed to write AssocResp IEs");
|
||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
|
|
@ -546,22 +625,24 @@ skip_wpa_check:
|
|||
wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_OWE &&
|
||||
elems.owe_dh) {
|
||||
u8 *npos;
|
||||
u16 ret_status;
|
||||
|
||||
npos = owe_assoc_req_process(hapd, sta,
|
||||
elems.owe_dh, elems.owe_dh_len,
|
||||
p, sizeof(buf) - (p - buf),
|
||||
&reason);
|
||||
&ret_status);
|
||||
status = ret_status;
|
||||
if (npos)
|
||||
p = npos;
|
||||
|
||||
if (!npos &&
|
||||
reason == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
|
||||
status = WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
|
||||
hostapd_sta_assoc(hapd, addr, reassoc, status, buf,
|
||||
status == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
|
||||
hostapd_sta_assoc(hapd, addr, reassoc, ret_status, buf,
|
||||
p - buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!npos || reason != WLAN_STATUS_SUCCESS)
|
||||
if (!npos || status != WLAN_STATUS_SUCCESS)
|
||||
goto fail;
|
||||
}
|
||||
#endif /* CONFIG_OWE */
|
||||
|
|
@ -598,6 +679,11 @@ skip_wpa_check:
|
|||
pfs_fail:
|
||||
#endif /* CONFIG_DPP2 */
|
||||
|
||||
if (elems.rrm_enabled &&
|
||||
elems.rrm_enabled_len >= sizeof(sta->rrm_enabled_capa))
|
||||
os_memcpy(sta->rrm_enabled_capa, elems.rrm_enabled,
|
||||
sizeof(sta->rrm_enabled_capa));
|
||||
|
||||
#if defined(CONFIG_IEEE80211R_AP) || defined(CONFIG_FILS) || defined(CONFIG_OWE)
|
||||
hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
|
||||
|
||||
|
|
@ -644,7 +730,8 @@ skip_wpa_check:
|
|||
|
||||
fail:
|
||||
#ifdef CONFIG_IEEE80211R_AP
|
||||
hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
|
||||
if (status >= 0)
|
||||
hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
|
||||
#endif /* CONFIG_IEEE80211R_AP */
|
||||
hostapd_drv_sta_disassoc(hapd, sta->addr, reason);
|
||||
ap_free_sta(hapd, sta);
|
||||
|
|
@ -682,6 +769,7 @@ void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
|
|||
|
||||
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_DISASSOC);
|
||||
sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
|
||||
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
|
||||
|
|
@ -775,8 +863,6 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
|
|||
int offset, int width, int cf1, int cf2,
|
||||
int finished)
|
||||
{
|
||||
/* TODO: If OCV is enabled deauth STAs that don't perform a SA Query */
|
||||
|
||||
#ifdef NEED_AP_MLME
|
||||
int channel, chwidth, is_dfs;
|
||||
u8 seg0_idx = 0, seg1_idx = 0;
|
||||
|
|
@ -784,9 +870,10 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
|
|||
|
||||
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO,
|
||||
"driver %s channel switch: freq=%d, ht=%d, vht_ch=0x%x, offset=%d, width=%d (%s), cf1=%d, cf2=%d",
|
||||
"driver %s channel switch: freq=%d, ht=%d, vht_ch=0x%x, he_ch=0x%x, offset=%d, width=%d (%s), cf1=%d, cf2=%d",
|
||||
finished ? "had" : "starting",
|
||||
freq, ht, hapd->iconf->ch_switch_vht_config, offset,
|
||||
freq, ht, hapd->iconf->ch_switch_vht_config,
|
||||
hapd->iconf->ch_switch_he_config, offset,
|
||||
width, channel_width_to_string(width), cf1, cf2);
|
||||
|
||||
if (!hapd->iface->current_mode) {
|
||||
|
|
@ -826,9 +913,18 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
|
|||
|
||||
switch (hapd->iface->current_mode->mode) {
|
||||
case HOSTAPD_MODE_IEEE80211A:
|
||||
if (cf1 > 5000)
|
||||
if (cf1 == 5935)
|
||||
seg0_idx = (cf1 - 5925) / 5;
|
||||
else if (cf1 > 5950)
|
||||
seg0_idx = (cf1 - 5950) / 5;
|
||||
else if (cf1 > 5000)
|
||||
seg0_idx = (cf1 - 5000) / 5;
|
||||
if (cf2 > 5000)
|
||||
|
||||
if (cf2 == 5935)
|
||||
seg1_idx = (cf2 - 5925) / 5;
|
||||
else if (cf2 > 5950)
|
||||
seg1_idx = (cf2 - 5950) / 5;
|
||||
else if (cf2 > 5000)
|
||||
seg1_idx = (cf2 - 5000) / 5;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -849,13 +945,31 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
|
|||
else if (hapd->iconf->ch_switch_vht_config &
|
||||
CH_SWITCH_VHT_DISABLED)
|
||||
hapd->iconf->ieee80211ac = 0;
|
||||
} else if (hapd->iconf->ch_switch_he_config) {
|
||||
/* CHAN_SWITCH HE config */
|
||||
if (hapd->iconf->ch_switch_he_config &
|
||||
CH_SWITCH_HE_ENABLED)
|
||||
hapd->iconf->ieee80211ax = 1;
|
||||
else if (hapd->iconf->ch_switch_he_config &
|
||||
CH_SWITCH_HE_DISABLED)
|
||||
hapd->iconf->ieee80211ax = 0;
|
||||
}
|
||||
hapd->iconf->ch_switch_vht_config = 0;
|
||||
hapd->iconf->ch_switch_he_config = 0;
|
||||
|
||||
hapd->iconf->secondary_channel = offset;
|
||||
hostapd_set_oper_chwidth(hapd->iconf, chwidth);
|
||||
hostapd_set_oper_centr_freq_seg0_idx(hapd->iconf, seg0_idx);
|
||||
hostapd_set_oper_centr_freq_seg1_idx(hapd->iconf, seg1_idx);
|
||||
if (hapd->iconf->ieee80211ac) {
|
||||
hapd->iconf->vht_capab &= ~VHT_CAP_SUPP_CHAN_WIDTH_MASK;
|
||||
if (chwidth == CHANWIDTH_160MHZ)
|
||||
hapd->iconf->vht_capab |=
|
||||
VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
|
||||
else if (chwidth == CHANWIDTH_80P80MHZ)
|
||||
hapd->iconf->vht_capab |=
|
||||
VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
|
||||
}
|
||||
|
||||
is_dfs = ieee80211_is_dfs(freq, hapd->iface->hw_features,
|
||||
hapd->iface->num_hw_features);
|
||||
|
|
@ -879,10 +993,39 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
|
|||
} else if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) {
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED
|
||||
"freq=%d dfs=%d", freq, is_dfs);
|
||||
} else if (is_dfs &&
|
||||
hostapd_is_dfs_required(hapd->iface) &&
|
||||
!hostapd_is_dfs_chan_available(hapd->iface) &&
|
||||
!hapd->iface->cac_started) {
|
||||
hostapd_disable_iface(hapd->iface);
|
||||
hostapd_enable_iface(hapd->iface);
|
||||
}
|
||||
|
||||
for (i = 0; i < hapd->iface->num_bss; i++)
|
||||
hostapd_neighbor_set_own_report(hapd->iface->bss[i]);
|
||||
|
||||
#ifdef CONFIG_OCV
|
||||
if (hapd->conf->ocv) {
|
||||
struct sta_info *sta;
|
||||
bool check_sa_query = false;
|
||||
|
||||
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
||||
if (wpa_auth_uses_ocv(sta->wpa_sm) &&
|
||||
!(sta->flags & WLAN_STA_WNM_SLEEP_MODE)) {
|
||||
sta->post_csa_sa_query = 1;
|
||||
check_sa_query = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (check_sa_query) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"OCV: Check post-CSA SA Query initiation in 15 seconds");
|
||||
eloop_register_timeout(15, 0,
|
||||
hostapd_ocv_check_csa_sa_query,
|
||||
hapd, NULL);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_OCV */
|
||||
#endif /* NEED_AP_MLME */
|
||||
}
|
||||
|
||||
|
|
@ -909,6 +1052,7 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd,
|
|||
{
|
||||
int ret, i;
|
||||
int err = 0;
|
||||
struct hostapd_channel_data *pri_chan;
|
||||
|
||||
if (hapd->iconf->channel) {
|
||||
wpa_printf(MSG_INFO, "ACS: Channel was already set to %d",
|
||||
|
|
@ -916,12 +1060,20 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd,
|
|||
return;
|
||||
}
|
||||
|
||||
hapd->iface->freq = acs_res->pri_freq;
|
||||
|
||||
if (!hapd->iface->current_mode) {
|
||||
for (i = 0; i < hapd->iface->num_hw_features; i++) {
|
||||
struct hostapd_hw_modes *mode =
|
||||
&hapd->iface->hw_features[i];
|
||||
|
||||
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))
|
||||
continue;
|
||||
hapd->iface->current_mode = mode;
|
||||
break;
|
||||
}
|
||||
|
|
@ -935,24 +1087,33 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd,
|
|||
}
|
||||
}
|
||||
|
||||
hapd->iface->freq = hostapd_hw_get_freq(hapd, acs_res->pri_channel);
|
||||
|
||||
if (!acs_res->pri_channel) {
|
||||
if (!acs_res->pri_freq) {
|
||||
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_WARNING,
|
||||
"driver switched to bad channel");
|
||||
err = 1;
|
||||
goto out;
|
||||
}
|
||||
pri_chan = hw_get_channel_freq(hapd->iface->current_mode->mode,
|
||||
acs_res->pri_freq, NULL,
|
||||
hapd->iface->hw_features,
|
||||
hapd->iface->num_hw_features);
|
||||
if (!pri_chan) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"ACS: Could not determine primary channel number from pri_freq %u",
|
||||
acs_res->pri_freq);
|
||||
err = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
hapd->iconf->channel = acs_res->pri_channel;
|
||||
hapd->iconf->channel = pri_chan->chan;
|
||||
hapd->iconf->acs = 1;
|
||||
|
||||
if (acs_res->sec_channel == 0)
|
||||
if (acs_res->sec_freq == 0)
|
||||
hapd->iconf->secondary_channel = 0;
|
||||
else if (acs_res->sec_channel < acs_res->pri_channel)
|
||||
else if (acs_res->sec_freq < acs_res->pri_freq)
|
||||
hapd->iconf->secondary_channel = -1;
|
||||
else if (acs_res->sec_channel > acs_res->pri_channel)
|
||||
else if (acs_res->sec_freq > acs_res->pri_freq)
|
||||
hapd->iconf->secondary_channel = 1;
|
||||
else {
|
||||
wpa_printf(MSG_ERROR, "Invalid secondary channel!");
|
||||
|
|
@ -960,32 +1121,35 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd,
|
|||
goto out;
|
||||
}
|
||||
|
||||
hapd->iconf->edmg_channel = acs_res->edmg_channel;
|
||||
|
||||
if (hapd->iface->conf->ieee80211ac || hapd->iface->conf->ieee80211ax) {
|
||||
/* set defaults for backwards compatibility */
|
||||
hostapd_set_oper_centr_freq_seg1_idx(hapd->iconf, 0);
|
||||
hostapd_set_oper_centr_freq_seg0_idx(hapd->iconf, 0);
|
||||
hostapd_set_oper_chwidth(hapd->iconf, CHANWIDTH_USE_HT);
|
||||
if (acs_res->ch_width == 80) {
|
||||
if (acs_res->ch_width == 40) {
|
||||
if (is_6ghz_freq(acs_res->pri_freq))
|
||||
hostapd_set_oper_centr_freq_seg0_idx(
|
||||
hapd->iconf,
|
||||
acs_res->vht_seg0_center_ch);
|
||||
} else if (acs_res->ch_width == 80) {
|
||||
hostapd_set_oper_centr_freq_seg0_idx(
|
||||
hapd->iconf, acs_res->vht_seg0_center_ch);
|
||||
hostapd_set_oper_chwidth(hapd->iconf, CHANWIDTH_80MHZ);
|
||||
} else if (acs_res->ch_width == 160) {
|
||||
if (acs_res->vht_seg1_center_ch == 0) {
|
||||
hostapd_set_oper_centr_freq_seg0_idx(
|
||||
hapd->iconf,
|
||||
acs_res->vht_seg0_center_ch);
|
||||
hostapd_set_oper_chwidth(hapd->iconf,
|
||||
CHANWIDTH_160MHZ);
|
||||
CHANWIDTH_80MHZ);
|
||||
} else {
|
||||
hostapd_set_oper_centr_freq_seg0_idx(
|
||||
hapd->iconf,
|
||||
acs_res->vht_seg0_center_ch);
|
||||
hostapd_set_oper_chwidth(hapd->iconf,
|
||||
CHANWIDTH_80P80MHZ);
|
||||
hostapd_set_oper_centr_freq_seg1_idx(
|
||||
hapd->iconf,
|
||||
acs_res->vht_seg1_center_ch);
|
||||
hostapd_set_oper_chwidth(hapd->iconf,
|
||||
CHANWIDTH_80P80MHZ);
|
||||
}
|
||||
} else if (acs_res->ch_width == 160) {
|
||||
hostapd_set_oper_chwidth(hapd->iconf, CHANWIDTH_160MHZ);
|
||||
hostapd_set_oper_centr_freq_seg0_idx(
|
||||
hapd->iconf, acs_res->vht_seg1_center_ch);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1164,12 +1328,10 @@ static void hostapd_action_rx(struct hostapd_data *hapd,
|
|||
return;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R_AP */
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (mgmt->u.action.category == WLAN_ACTION_SA_QUERY) {
|
||||
ieee802_11_sa_query_action(hapd, mgmt, drv_mgmt->frame_len);
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_WNM_AP
|
||||
if (mgmt->u.action.category == WLAN_ACTION_WNM) {
|
||||
ieee802_11_rx_wnm_action_ap(hapd, mgmt, drv_mgmt->frame_len);
|
||||
|
|
@ -1383,15 +1545,33 @@ static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src,
|
|||
#endif /* HOSTAPD */
|
||||
|
||||
|
||||
static struct hostapd_channel_data *
|
||||
hostapd_get_mode_chan(struct hostapd_hw_modes *mode, unsigned int freq)
|
||||
{
|
||||
int i;
|
||||
struct hostapd_channel_data *chan;
|
||||
|
||||
for (i = 0; i < mode->num_channels; i++) {
|
||||
chan = &mode->channels[i];
|
||||
if ((unsigned int) chan->freq == freq)
|
||||
return chan;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static struct hostapd_channel_data * hostapd_get_mode_channel(
|
||||
struct hostapd_iface *iface, unsigned int freq)
|
||||
{
|
||||
int i;
|
||||
struct hostapd_channel_data *chan;
|
||||
|
||||
for (i = 0; i < iface->current_mode->num_channels; i++) {
|
||||
chan = &iface->current_mode->channels[i];
|
||||
if ((unsigned int) chan->freq == freq)
|
||||
for (i = 0; i < iface->num_hw_features; i++) {
|
||||
if (hostapd_hw_skip_mode(iface, &iface->hw_features[i]))
|
||||
continue;
|
||||
chan = hostapd_get_mode_chan(&iface->hw_features[i], freq);
|
||||
if (chan)
|
||||
return chan;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ static void fils_dhcp_handler(int sd, void *eloop_ctx, void *sock_ctx)
|
|||
ssize_t res;
|
||||
u8 msgtype = 0;
|
||||
int rapid_commit = 0;
|
||||
struct iphdr *iph;
|
||||
struct ip *iph;
|
||||
struct udphdr *udph;
|
||||
struct wpabuf *resp;
|
||||
const u8 *rpos;
|
||||
|
|
@ -259,14 +259,14 @@ static void fils_dhcp_handler(int sd, void *eloop_ctx, void *sock_ctx)
|
|||
wpabuf_put_data(resp, "\xaa\xaa\x03\x00\x00\x00", 6);
|
||||
wpabuf_put_be16(resp, ETH_P_IP);
|
||||
iph = wpabuf_put(resp, sizeof(*iph));
|
||||
iph->version = 4;
|
||||
iph->ihl = sizeof(*iph) / 4;
|
||||
iph->tot_len = htons(sizeof(*iph) + sizeof(*udph) + (end - pos));
|
||||
iph->ttl = 1;
|
||||
iph->protocol = 17; /* UDP */
|
||||
iph->saddr = hapd->conf->dhcp_server.u.v4.s_addr;
|
||||
iph->daddr = dhcp->client_ip;
|
||||
iph->check = ip_checksum(iph, sizeof(*iph));
|
||||
iph->ip_v = 4;
|
||||
iph->ip_hl = sizeof(*iph) / 4;
|
||||
iph->ip_len = htons(sizeof(*iph) + sizeof(*udph) + (end - pos));
|
||||
iph->ip_ttl = 1;
|
||||
iph->ip_p = 17; /* UDP */
|
||||
iph->ip_src.s_addr = hapd->conf->dhcp_server.u.v4.s_addr;
|
||||
iph->ip_dst.s_addr = dhcp->client_ip;
|
||||
iph->ip_sum = ip_checksum(iph, sizeof(*iph));
|
||||
udph = wpabuf_put(resp, sizeof(*udph));
|
||||
udph->uh_sport = htons(DHCP_SERVER_PORT);
|
||||
udph->uh_dport = htons(DHCP_CLIENT_PORT);
|
||||
|
|
@ -479,13 +479,13 @@ static int fils_process_hlp_udp(struct hostapd_data *hapd,
|
|||
struct sta_info *sta, const u8 *dst,
|
||||
const u8 *pos, size_t len)
|
||||
{
|
||||
const struct iphdr *iph;
|
||||
const struct ip *iph;
|
||||
const struct udphdr *udph;
|
||||
u16 sport, dport, ulen;
|
||||
|
||||
if (len < sizeof(*iph) + sizeof(*udph))
|
||||
return 0;
|
||||
iph = (const struct iphdr *) pos;
|
||||
iph = (const struct ip *) pos;
|
||||
udph = (const struct udphdr *) (iph + 1);
|
||||
sport = ntohs(udph->uh_sport);
|
||||
dport = ntohs(udph->uh_dport);
|
||||
|
|
@ -510,24 +510,24 @@ static int fils_process_hlp_ip(struct hostapd_data *hapd,
|
|||
struct sta_info *sta, const u8 *dst,
|
||||
const u8 *pos, size_t len)
|
||||
{
|
||||
const struct iphdr *iph;
|
||||
u16 tot_len;
|
||||
const struct ip *iph;
|
||||
uint16_t ip_len;
|
||||
|
||||
if (len < sizeof(*iph))
|
||||
return 0;
|
||||
iph = (const struct iphdr *) pos;
|
||||
iph = (const struct ip *) pos;
|
||||
if (ip_checksum(iph, sizeof(*iph)) != 0) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"FILS: HLP request IPv4 packet had invalid header checksum - dropped");
|
||||
return 0;
|
||||
}
|
||||
tot_len = ntohs(iph->tot_len);
|
||||
if (tot_len > len)
|
||||
ip_len = ntohs(iph->ip_len);
|
||||
if (ip_len > len)
|
||||
return 0;
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"FILS: HLP request IPv4: saddr=%08x daddr=%08x protocol=%u",
|
||||
iph->saddr, iph->daddr, iph->protocol);
|
||||
switch (iph->protocol) {
|
||||
iph->ip_src.s_addr, iph->ip_dst.s_addr, iph->ip_p);
|
||||
switch (iph->ip_p) {
|
||||
case 17:
|
||||
return fils_process_hlp_udp(hapd, sta, dst, pos, len);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1555,11 +1555,14 @@ void gas_serv_req_dpp_processing(struct hostapd_data *hapd,
|
|||
di->prot = prot;
|
||||
di->sd_resp = buf;
|
||||
di->sd_resp_pos = 0;
|
||||
di->dpp = 1;
|
||||
tx_buf = gas_build_initial_resp(
|
||||
dialog_token, WLAN_STATUS_SUCCESS,
|
||||
comeback_delay, 10);
|
||||
if (tx_buf)
|
||||
comeback_delay, 10 + 2);
|
||||
if (tx_buf) {
|
||||
gas_serv_write_dpp_adv_proto(tx_buf);
|
||||
wpabuf_put_le16(tx_buf, 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
|
|
@ -1782,9 +1785,10 @@ static void gas_serv_rx_gas_comeback_req(struct hostapd_data *hapd,
|
|||
tx_buf = gas_build_comeback_resp(dialog_token,
|
||||
WLAN_STATUS_SUCCESS,
|
||||
dialog->sd_frag_id, more, 0,
|
||||
10 + frag_len);
|
||||
10 + 2 + frag_len);
|
||||
if (tx_buf) {
|
||||
gas_serv_write_dpp_adv_proto(tx_buf);
|
||||
wpabuf_put_le16(tx_buf, frag_len);
|
||||
wpabuf_put_buf(tx_buf, buf);
|
||||
}
|
||||
} else
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* hostapd / Initialization and configuration
|
||||
* Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2021, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "utils/crc32.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/wpa_ctrl.h"
|
||||
#include "common/hw_features_common.h"
|
||||
|
|
@ -28,7 +29,6 @@
|
|||
#include "accounting.h"
|
||||
#include "ap_list.h"
|
||||
#include "beacon.h"
|
||||
#include "iapp.h"
|
||||
#include "ieee802_1x.h"
|
||||
#include "ieee802_11_auth.h"
|
||||
#include "vlan_init.h"
|
||||
|
|
@ -58,8 +58,10 @@
|
|||
|
||||
|
||||
static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason);
|
||||
#ifdef CONFIG_WEP
|
||||
static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd);
|
||||
static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd);
|
||||
#endif /* CONFIG_WEP */
|
||||
static int setup_interface2(struct hostapd_iface *iface);
|
||||
static void channel_list_update_timeout(void *eloop_ctx, void *timeout_ctx);
|
||||
static void hostapd_interface_setup_failure_handler(void *eloop_ctx,
|
||||
|
|
@ -74,6 +76,8 @@ int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
|
|||
int ret;
|
||||
|
||||
for (i = 0; i < interfaces->count; i++) {
|
||||
if (!interfaces->iface[i])
|
||||
continue;
|
||||
ret = cb(interfaces->iface[i], ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -89,7 +93,9 @@ void hostapd_reconfig_encryption(struct hostapd_data *hapd)
|
|||
return;
|
||||
|
||||
hostapd_set_privacy(hapd, 0);
|
||||
#ifdef CONFIG_WEP
|
||||
hostapd_setup_encryption(hapd->conf->iface, hapd);
|
||||
#endif /* CONFIG_WEP */
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -101,7 +107,8 @@ static void hostapd_reload_bss(struct hostapd_data *hapd)
|
|||
return;
|
||||
|
||||
if (hapd->conf->wmm_enabled < 0)
|
||||
hapd->conf->wmm_enabled = hapd->iconf->ieee80211n;
|
||||
hapd->conf->wmm_enabled = hapd->iconf->ieee80211n |
|
||||
hapd->iconf->ieee80211ax;
|
||||
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
radius_client_reconfig(hapd->radius, hapd->conf->radius);
|
||||
|
|
@ -142,7 +149,9 @@ static void hostapd_reload_bss(struct hostapd_data *hapd)
|
|||
wpa_deinit(hapd->wpa_auth);
|
||||
hapd->wpa_auth = NULL;
|
||||
hostapd_set_privacy(hapd, 0);
|
||||
#ifdef CONFIG_WEP
|
||||
hostapd_setup_encryption(hapd->conf->iface, hapd);
|
||||
#endif /* CONFIG_WEP */
|
||||
hostapd_set_generic_elem(hapd, (u8 *) "", 0);
|
||||
}
|
||||
|
||||
|
|
@ -170,7 +179,9 @@ static void hostapd_clear_old(struct hostapd_iface *iface)
|
|||
for (j = 0; j < iface->num_bss; j++) {
|
||||
hostapd_flush_old_stations(iface->bss[j],
|
||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
#ifdef CONFIG_WEP
|
||||
hostapd_broadcast_wep_clear(iface->bss[j]);
|
||||
#endif /* CONFIG_WEP */
|
||||
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
/* TODO: update dynamic data based on changed configuration
|
||||
|
|
@ -284,6 +295,8 @@ int hostapd_reload_config(struct hostapd_iface *iface)
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_WEP
|
||||
|
||||
static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd,
|
||||
const char *ifname)
|
||||
{
|
||||
|
|
@ -292,26 +305,24 @@ static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd,
|
|||
if (!ifname || !hapd->drv_priv)
|
||||
return;
|
||||
for (i = 0; i < NUM_WEP_KEYS; i++) {
|
||||
if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE, NULL, i,
|
||||
0, NULL, 0, NULL, 0)) {
|
||||
if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE, NULL, i, 0,
|
||||
0, NULL, 0, NULL, 0, KEY_FLAG_GROUP)) {
|
||||
wpa_printf(MSG_DEBUG, "Failed to clear default "
|
||||
"encryption keys (ifname=%s keyidx=%d)",
|
||||
ifname, i);
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (hapd->conf->ieee80211w) {
|
||||
for (i = NUM_WEP_KEYS; i < NUM_WEP_KEYS + 2; i++) {
|
||||
if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE,
|
||||
NULL, i, 0, NULL,
|
||||
0, NULL, 0)) {
|
||||
NULL, i, 0, 0, NULL,
|
||||
0, NULL, 0, KEY_FLAG_GROUP)) {
|
||||
wpa_printf(MSG_DEBUG, "Failed to clear "
|
||||
"default mgmt encryption keys "
|
||||
"(ifname=%s keyidx=%d)", ifname, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -328,11 +339,12 @@ static int hostapd_broadcast_wep_set(struct hostapd_data *hapd)
|
|||
struct hostapd_ssid *ssid = &hapd->conf->ssid;
|
||||
|
||||
idx = ssid->wep.idx;
|
||||
if (ssid->wep.default_len &&
|
||||
if (ssid->wep.default_len && ssid->wep.key[idx] &&
|
||||
hostapd_drv_set_key(hapd->conf->iface,
|
||||
hapd, WPA_ALG_WEP, broadcast_ether_addr, idx,
|
||||
hapd, WPA_ALG_WEP, broadcast_ether_addr, idx, 0,
|
||||
1, NULL, 0, ssid->wep.key[idx],
|
||||
ssid->wep.len[idx])) {
|
||||
ssid->wep.len[idx],
|
||||
KEY_FLAG_GROUP_RX_TX_DEFAULT)) {
|
||||
wpa_printf(MSG_WARNING, "Could not set WEP encryption.");
|
||||
errors++;
|
||||
}
|
||||
|
|
@ -340,8 +352,10 @@ static int hostapd_broadcast_wep_set(struct hostapd_data *hapd)
|
|||
return errors;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_WEP */
|
||||
|
||||
static void hostapd_free_hapd_data(struct hostapd_data *hapd)
|
||||
|
||||
void hostapd_free_hapd_data(struct hostapd_data *hapd)
|
||||
{
|
||||
os_free(hapd->probereq_cb);
|
||||
hapd->probereq_cb = NULL;
|
||||
|
|
@ -363,8 +377,6 @@ static void hostapd_free_hapd_data(struct hostapd_data *hapd)
|
|||
hapd->beacon_set_done = 0;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface);
|
||||
iapp_deinit(hapd->iapp);
|
||||
hapd->iapp = NULL;
|
||||
accounting_deinit(hapd);
|
||||
hostapd_deinit_wpa(hapd);
|
||||
vlan_deinit(hapd);
|
||||
|
|
@ -381,6 +393,7 @@ static void hostapd_free_hapd_data(struct hostapd_data *hapd)
|
|||
#ifdef CONFIG_DPP
|
||||
hostapd_dpp_deinit(hapd);
|
||||
gas_query_ap_deinit(hapd->gas);
|
||||
hapd->gas = NULL;
|
||||
#endif /* CONFIG_DPP */
|
||||
|
||||
authsrv_deinit(hapd);
|
||||
|
|
@ -403,6 +416,7 @@ static void hostapd_free_hapd_data(struct hostapd_data *hapd)
|
|||
}
|
||||
|
||||
wpabuf_free(hapd->time_adv);
|
||||
hapd->time_adv = NULL;
|
||||
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
gas_serv_deinit(hapd);
|
||||
|
|
@ -418,16 +432,23 @@ static void hostapd_free_hapd_data(struct hostapd_data *hapd)
|
|||
hapd->tmp_eap_user.identity_len);
|
||||
bin_clear_free(hapd->tmp_eap_user.password,
|
||||
hapd->tmp_eap_user.password_len);
|
||||
os_memset(&hapd->tmp_eap_user, 0, sizeof(hapd->tmp_eap_user));
|
||||
#endif /* CONFIG_SQLITE */
|
||||
|
||||
#ifdef CONFIG_MESH
|
||||
wpabuf_free(hapd->mesh_pending_auth);
|
||||
hapd->mesh_pending_auth = NULL;
|
||||
/* handling setup failure is already done */
|
||||
hapd->setup_complete_cb = NULL;
|
||||
#endif /* CONFIG_MESH */
|
||||
|
||||
hostapd_clean_rrm(hapd);
|
||||
fils_hlp_deinit(hapd);
|
||||
|
||||
#ifdef CONFIG_OCV
|
||||
eloop_cancel_timeout(hostapd_ocv_check_csa_sa_query, hapd, NULL);
|
||||
#endif /* CONFIG_OCV */
|
||||
|
||||
#ifdef CONFIG_SAE
|
||||
{
|
||||
struct hostapd_sae_commit_queue *q;
|
||||
|
|
@ -481,14 +502,12 @@ static void sta_track_deinit(struct hostapd_iface *iface)
|
|||
}
|
||||
|
||||
|
||||
static void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
|
||||
void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
#ifdef NEED_AP_MLME
|
||||
hostapd_stop_setup_timers(iface);
|
||||
#endif /* NEED_AP_MLME */
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
if (iface->current_mode)
|
||||
acs_cleanup(iface);
|
||||
hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
|
||||
|
|
@ -529,6 +548,8 @@ static void hostapd_cleanup_iface(struct hostapd_iface *iface)
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_WEP
|
||||
|
||||
static void hostapd_clear_wep(struct hostapd_data *hapd)
|
||||
{
|
||||
if (hapd->drv_priv && !hapd->iface->driver_ap_teardown && hapd->conf) {
|
||||
|
|
@ -557,10 +578,13 @@ static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd)
|
|||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (hapd->conf->ssid.wep.key[i] &&
|
||||
hostapd_drv_set_key(iface, hapd, WPA_ALG_WEP, NULL, i,
|
||||
hostapd_drv_set_key(iface, hapd, WPA_ALG_WEP, NULL, i, 0,
|
||||
i == hapd->conf->ssid.wep.idx, NULL, 0,
|
||||
hapd->conf->ssid.wep.key[i],
|
||||
hapd->conf->ssid.wep.len[i])) {
|
||||
hapd->conf->ssid.wep.len[i],
|
||||
i == hapd->conf->ssid.wep.idx ?
|
||||
KEY_FLAG_GROUP_RX_TX_DEFAULT :
|
||||
KEY_FLAG_GROUP_RX_TX)) {
|
||||
wpa_printf(MSG_WARNING, "Could not set WEP "
|
||||
"encryption.");
|
||||
return -1;
|
||||
|
|
@ -573,6 +597,8 @@ static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_WEP */
|
||||
|
||||
|
||||
static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason)
|
||||
{
|
||||
|
|
@ -604,11 +630,13 @@ static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason)
|
|||
}
|
||||
|
||||
|
||||
static void hostapd_bss_deinit_no_free(struct hostapd_data *hapd)
|
||||
void hostapd_bss_deinit_no_free(struct hostapd_data *hapd)
|
||||
{
|
||||
hostapd_free_stas(hapd);
|
||||
hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING);
|
||||
#ifdef CONFIG_WEP
|
||||
hostapd_clear_wep(hapd);
|
||||
#endif /* CONFIG_WEP */
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1146,7 +1174,8 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
|
|||
}
|
||||
|
||||
if (conf->wmm_enabled < 0)
|
||||
conf->wmm_enabled = hapd->iconf->ieee80211n;
|
||||
conf->wmm_enabled = hapd->iconf->ieee80211n |
|
||||
hapd->iconf->ieee80211ax;
|
||||
|
||||
#ifdef CONFIG_IEEE80211R_AP
|
||||
if (is_zero_ether_addr(conf->r1_key_holder))
|
||||
|
|
@ -1159,13 +1188,15 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
|
|||
#endif /* CONFIG_MESH */
|
||||
|
||||
if (flush_old_stations)
|
||||
hostapd_flush_old_stations(hapd,
|
||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
hostapd_flush(hapd);
|
||||
hostapd_set_privacy(hapd, 0);
|
||||
|
||||
hostapd_broadcast_wep_clear(hapd);
|
||||
#ifdef CONFIG_WEP
|
||||
if (!hostapd_drv_nl80211(hapd))
|
||||
hostapd_broadcast_wep_clear(hapd);
|
||||
if (hostapd_setup_encryption(conf->iface, hapd))
|
||||
return -1;
|
||||
#endif /* CONFIG_WEP */
|
||||
|
||||
/*
|
||||
* Fetch the SSID from the system and use it or,
|
||||
|
|
@ -1195,8 +1226,14 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
|
|||
os_memcpy(conf->ssid.ssid, ssid, conf->ssid.ssid_len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Short SSID calculation is identical to FCS and it is defined in
|
||||
* IEEE P802.11-REVmd/D3.0, 9.4.2.170.3 (Calculating the Short-SSID).
|
||||
*/
|
||||
conf->ssid.short_ssid = crc32(conf->ssid.ssid, conf->ssid.ssid_len);
|
||||
|
||||
if (!hostapd_drv_none(hapd)) {
|
||||
wpa_printf(MSG_ERROR, "Using interface %s with hwaddr " MACSTR
|
||||
wpa_printf(MSG_DEBUG, "Using interface %s with hwaddr " MACSTR
|
||||
" and ssid \"%s\"",
|
||||
conf->iface, MAC2STR(hapd->own_addr),
|
||||
wpa_ssid_txt(conf->ssid.ssid, conf->ssid.ssid_len));
|
||||
|
|
@ -1298,13 +1335,6 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (conf->ieee802_11f &&
|
||||
(hapd->iapp = iapp_init(hapd, conf->iapp_iface)) == NULL) {
|
||||
wpa_printf(MSG_ERROR, "IEEE 802.11F (IAPP) initialization "
|
||||
"failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
if (gas_serv_init(hapd)) {
|
||||
wpa_printf(MSG_ERROR, "GAS server initialization failed");
|
||||
|
|
@ -1352,6 +1382,21 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
|
|||
if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
|
||||
return -1;
|
||||
|
||||
if (flush_old_stations && !conf->start_disabled &&
|
||||
conf->broadcast_deauth) {
|
||||
u8 addr[ETH_ALEN];
|
||||
|
||||
/* Should any previously associated STA not have noticed that
|
||||
* the AP had stopped and restarted, send one more
|
||||
* deauthentication notification now that the AP is ready to
|
||||
* operate. */
|
||||
wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
|
||||
"Deauthenticate all stations at BSS start");
|
||||
os_memset(addr, 0xff, ETH_ALEN);
|
||||
hostapd_drv_sta_deauth(hapd, addr,
|
||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
}
|
||||
|
||||
if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0)
|
||||
return -1;
|
||||
|
||||
|
|
@ -1584,6 +1629,71 @@ static int setup_interface(struct hostapd_iface *iface)
|
|||
}
|
||||
|
||||
|
||||
static int configured_fixed_chan_to_freq(struct hostapd_iface *iface)
|
||||
{
|
||||
int freq, i, j;
|
||||
|
||||
if (!iface->conf->channel)
|
||||
return 0;
|
||||
if (iface->conf->op_class) {
|
||||
freq = ieee80211_chan_to_freq(NULL, iface->conf->op_class,
|
||||
iface->conf->channel);
|
||||
if (freq < 0) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"Could not convert op_class %u channel %u to operating frequency",
|
||||
iface->conf->op_class, iface->conf->channel);
|
||||
return -1;
|
||||
}
|
||||
iface->freq = freq;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Old configurations using only 2.4/5/60 GHz bands may not specify the
|
||||
* op_class parameter. Select a matching channel from the configured
|
||||
* mode using the channel parameter for these cases.
|
||||
*/
|
||||
for (j = 0; j < iface->num_hw_features; j++) {
|
||||
struct hostapd_hw_modes *mode = &iface->hw_features[j];
|
||||
|
||||
if (iface->conf->hw_mode != HOSTAPD_MODE_IEEE80211ANY &&
|
||||
iface->conf->hw_mode != mode->mode)
|
||||
continue;
|
||||
for (i = 0; i < mode->num_channels; i++) {
|
||||
struct hostapd_channel_data *chan = &mode->channels[i];
|
||||
|
||||
if (chan->chan == iface->conf->channel &&
|
||||
!is_6ghz_freq(chan->freq)) {
|
||||
iface->freq = chan->freq;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wpa_printf(MSG_INFO, "Could not determine operating frequency");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_set_6ghz_sec_chan(struct hostapd_iface *iface)
|
||||
{
|
||||
int bw, seg0;
|
||||
|
||||
if (!is_6ghz_op_class(iface->conf->op_class))
|
||||
return;
|
||||
|
||||
seg0 = hostapd_get_oper_centr_freq_seg0_idx(iface->conf);
|
||||
bw = center_idx_to_bw_6ghz(seg0);
|
||||
/* Assign the secondary channel if absent in config for
|
||||
* bandwidths > 20 MHz */
|
||||
if (bw > 20 && !iface->conf->secondary_channel) {
|
||||
if (((iface->conf->channel - 1) / 4) % 2)
|
||||
iface->conf->secondary_channel = -1;
|
||||
else
|
||||
iface->conf->secondary_channel = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int setup_interface2(struct hostapd_iface *iface)
|
||||
{
|
||||
iface->wait_channel_update = 0;
|
||||
|
|
@ -1592,7 +1702,21 @@ static int setup_interface2(struct hostapd_iface *iface)
|
|||
/* Not all drivers support this yet, so continue without hw
|
||||
* feature data. */
|
||||
} else {
|
||||
int ret = hostapd_select_hw_mode(iface);
|
||||
int ret;
|
||||
|
||||
ret = configured_fixed_chan_to_freq(iface);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
if (iface->conf->op_class) {
|
||||
int ch_width;
|
||||
|
||||
ch_width = op_class_to_ch_width(iface->conf->op_class);
|
||||
hostapd_set_oper_chwidth(iface->conf, ch_width);
|
||||
hostapd_set_6ghz_sec_chan(iface);
|
||||
}
|
||||
|
||||
ret = hostapd_select_hw_mode(iface);
|
||||
if (ret < 0) {
|
||||
wpa_printf(MSG_ERROR, "Could not select hw_mode and "
|
||||
"channel. (%d)", ret);
|
||||
|
|
@ -1602,6 +1726,12 @@ static int setup_interface2(struct hostapd_iface *iface)
|
|||
wpa_printf(MSG_DEBUG, "Interface initialization will be completed in a callback (ACS)");
|
||||
return 0;
|
||||
}
|
||||
ret = hostapd_check_edmg_capab(iface);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
ret = hostapd_check_he_6ghz_capab(iface);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
ret = hostapd_check_ht_capab(iface);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
|
@ -1694,7 +1824,7 @@ static void fst_hostapd_update_mb_ie_cb(void *ctx, const u8 *addr,
|
|||
|
||||
|
||||
static const u8 * fst_hostapd_get_sta(struct fst_get_peer_ctx **get_ctx,
|
||||
Boolean mb_only)
|
||||
bool mb_only)
|
||||
{
|
||||
struct sta_info *s = (struct sta_info *) *get_ctx;
|
||||
|
||||
|
|
@ -1716,7 +1846,7 @@ static const u8 * fst_hostapd_get_sta(struct fst_get_peer_ctx **get_ctx,
|
|||
|
||||
static const u8 * fst_hostapd_get_peer_first(void *ctx,
|
||||
struct fst_get_peer_ctx **get_ctx,
|
||||
Boolean mb_only)
|
||||
bool mb_only)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
|
||||
|
|
@ -1728,7 +1858,7 @@ static const u8 * fst_hostapd_get_peer_first(void *ctx,
|
|||
|
||||
static const u8 * fst_hostapd_get_peer_next(void *ctx,
|
||||
struct fst_get_peer_ctx **get_ctx,
|
||||
Boolean mb_only)
|
||||
bool mb_only)
|
||||
{
|
||||
return fst_hostapd_get_sta(get_ctx, mb_only);
|
||||
}
|
||||
|
|
@ -1816,6 +1946,13 @@ static int hostapd_owe_iface_iter2(struct hostapd_iface *iface, void *ctx)
|
|||
|
||||
if (!bss->conf->owe_transition_ifname[0])
|
||||
continue;
|
||||
if (bss->iface->state != HAPD_IFACE_ENABLED) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"OWE: Interface %s state %s - defer beacon update",
|
||||
bss->conf->iface,
|
||||
hostapd_state_text(bss->iface->state));
|
||||
continue;
|
||||
}
|
||||
res = hostapd_owe_trans_get_info(bss);
|
||||
if (res == 0)
|
||||
continue;
|
||||
|
|
@ -1873,12 +2010,11 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
|
|||
goto fail;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Completing interface initialization");
|
||||
if (iface->conf->channel) {
|
||||
if (iface->freq) {
|
||||
#ifdef NEED_AP_MLME
|
||||
int res;
|
||||
#endif /* NEED_AP_MLME */
|
||||
|
||||
iface->freq = hostapd_hw_get_freq(hapd, iface->conf->channel);
|
||||
wpa_printf(MSG_DEBUG, "Mode: %s Channel: %d "
|
||||
"Frequency: %d MHz",
|
||||
hostapd_hw_mode_txt(iface->conf->hw_mode),
|
||||
|
|
@ -1926,6 +2062,8 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
|
|||
if (!delay_apply_cfg &&
|
||||
hostapd_set_freq(hapd, hapd->iconf->hw_mode, iface->freq,
|
||||
hapd->iconf->channel,
|
||||
hapd->iconf->enable_edmg,
|
||||
hapd->iconf->edmg_channel,
|
||||
hapd->iconf->ieee80211n,
|
||||
hapd->iconf->ieee80211ac,
|
||||
hapd->iconf->ieee80211ax,
|
||||
|
|
@ -2049,6 +2187,13 @@ dfs_offload:
|
|||
if (hapd->setup_complete_cb)
|
||||
hapd->setup_complete_cb(hapd->setup_complete_cb_ctx);
|
||||
|
||||
#ifdef CONFIG_MESH
|
||||
if (delay_apply_cfg && !iface->mconf) {
|
||||
wpa_printf(MSG_ERROR, "Error while completing mesh init");
|
||||
goto fail;
|
||||
}
|
||||
#endif /* CONFIG_MESH */
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s: Setup of interface done.",
|
||||
iface->bss[0]->conf->iface);
|
||||
if (iface->interfaces && iface->interfaces->terminate_on_error > 0)
|
||||
|
|
@ -2189,10 +2334,12 @@ int hostapd_setup_interface(struct hostapd_iface *iface)
|
|||
{
|
||||
int ret;
|
||||
|
||||
if (!iface->conf)
|
||||
return -1;
|
||||
ret = setup_interface(iface);
|
||||
if (ret) {
|
||||
wpa_printf(MSG_ERROR, "%s: Unable to setup interface.",
|
||||
iface->bss[0]->conf->iface);
|
||||
iface->conf->bss[0]->iface);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -2288,12 +2435,10 @@ void hostapd_interface_deinit(struct hostapd_iface *iface)
|
|||
hostapd_bss_deinit(iface->bss[j]);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
#ifdef NEED_AP_MLME
|
||||
hostapd_stop_setup_timers(iface);
|
||||
eloop_cancel_timeout(ap_ht2040_timeout, iface, NULL);
|
||||
#endif /* NEED_AP_MLME */
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2576,6 +2721,12 @@ int hostapd_enable_iface(struct hostapd_iface *hapd_iface)
|
|||
{
|
||||
size_t j;
|
||||
|
||||
if (!hapd_iface)
|
||||
return -1;
|
||||
|
||||
if (hapd_iface->enable_iface_cb)
|
||||
return hapd_iface->enable_iface_cb(hapd_iface);
|
||||
|
||||
if (hapd_iface->bss[0]->drv_priv != NULL) {
|
||||
wpa_printf(MSG_ERROR, "Interface %s already enabled",
|
||||
hapd_iface->conf->bss[0]->iface);
|
||||
|
|
@ -2637,6 +2788,9 @@ int hostapd_disable_iface(struct hostapd_iface *hapd_iface)
|
|||
if (hapd_iface == NULL)
|
||||
return -1;
|
||||
|
||||
if (hapd_iface->disable_iface_cb)
|
||||
return hapd_iface->disable_iface_cb(hapd_iface);
|
||||
|
||||
if (hapd_iface->bss[0]->drv_priv == NULL) {
|
||||
wpa_printf(MSG_INFO, "Interface %s already disabled",
|
||||
hapd_iface->conf->bss[0]->iface);
|
||||
|
|
@ -3057,10 +3211,7 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
|
||||
hostapd_prune_associations(hapd, sta->addr);
|
||||
ap_sta_clear_disconnect_timeouts(hapd, sta);
|
||||
|
||||
/* IEEE 802.11F (IAPP) */
|
||||
if (hapd->conf->ieee802_11f)
|
||||
iapp_new_station(hapd->iapp, sta);
|
||||
sta->post_csa_sa_query = 0;
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (sta->p2p_ie == NULL && !sta->no_p2p_set) {
|
||||
|
|
@ -3298,7 +3449,8 @@ static int hostapd_change_config_freq(struct hostapd_data *hapd,
|
|||
if (old_params &&
|
||||
hostapd_set_freq_params(old_params, conf->hw_mode,
|
||||
hostapd_hw_get_freq(hapd, conf->channel),
|
||||
conf->channel, conf->ieee80211n,
|
||||
conf->channel, conf->enable_edmg,
|
||||
conf->edmg_channel, conf->ieee80211n,
|
||||
conf->ieee80211ac, conf->ieee80211ax,
|
||||
conf->secondary_channel,
|
||||
hostapd_get_oper_chwidth(conf),
|
||||
|
|
@ -3436,15 +3588,23 @@ void hostapd_cleanup_cs_params(struct hostapd_data *hapd)
|
|||
}
|
||||
|
||||
|
||||
void hostapd_chan_switch_vht_config(struct hostapd_data *hapd, int vht_enabled)
|
||||
void hostapd_chan_switch_config(struct hostapd_data *hapd,
|
||||
struct hostapd_freq_params *freq_params)
|
||||
{
|
||||
if (vht_enabled)
|
||||
if (freq_params->he_enabled)
|
||||
hapd->iconf->ch_switch_he_config |= CH_SWITCH_HE_ENABLED;
|
||||
else
|
||||
hapd->iconf->ch_switch_he_config |= CH_SWITCH_HE_DISABLED;
|
||||
|
||||
if (freq_params->vht_enabled)
|
||||
hapd->iconf->ch_switch_vht_config |= CH_SWITCH_VHT_ENABLED;
|
||||
else
|
||||
hapd->iconf->ch_switch_vht_config |= CH_SWITCH_VHT_DISABLED;
|
||||
|
||||
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO, "CHAN_SWITCH VHT CONFIG 0x%x",
|
||||
HOSTAPD_LEVEL_INFO,
|
||||
"CHAN_SWITCH HE config 0x%x VHT config 0x%x",
|
||||
hapd->iconf->ch_switch_he_config,
|
||||
hapd->iconf->ch_switch_vht_config);
|
||||
}
|
||||
|
||||
|
|
@ -3571,3 +3731,25 @@ void hostapd_periodic_iface(struct hostapd_iface *iface)
|
|||
#endif /* CONFIG_NO_RADIUS */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_OCV
|
||||
void hostapd_ocv_check_csa_sa_query(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct hostapd_data *hapd = eloop_ctx;
|
||||
struct sta_info *sta;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "OCV: Post-CSA SA Query initiation check");
|
||||
|
||||
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
||||
if (!sta->post_csa_sa_query)
|
||||
continue;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "OCV: OCVC STA " MACSTR
|
||||
" did not start SA Query after CSA - disconnect",
|
||||
MAC2STR(sta->addr));
|
||||
ap_sta_disconnect(hapd, sta, sta->addr,
|
||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_OCV */
|
||||
|
|
|
|||
|
|
@ -38,6 +38,10 @@ union wps_event_data;
|
|||
struct mesh_conf;
|
||||
#endif /* CONFIG_MESH */
|
||||
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP
|
||||
#define CTRL_IFACE_COOKIE_LEN 8
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP */
|
||||
|
||||
struct hostapd_iface;
|
||||
|
||||
struct hapd_interfaces {
|
||||
|
|
@ -72,6 +76,11 @@ struct hapd_interfaces {
|
|||
#ifdef CONFIG_DPP
|
||||
struct dpp_global *dpp;
|
||||
#endif /* CONFIG_DPP */
|
||||
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP
|
||||
unsigned char ctrl_iface_cookie[CTRL_IFACE_COOKIE_LEN];
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP */
|
||||
|
||||
};
|
||||
|
||||
enum hostapd_chan_status {
|
||||
|
|
@ -179,13 +188,12 @@ struct hostapd_data {
|
|||
u64 acct_session_id;
|
||||
struct radius_das_data *radius_das;
|
||||
|
||||
struct iapp_data *iapp;
|
||||
|
||||
struct hostapd_cached_radius_acl *acl_cache;
|
||||
struct hostapd_acl_query_data *acl_queries;
|
||||
|
||||
struct wpa_authenticator *wpa_auth;
|
||||
struct eapol_authenticator *eapol_auth;
|
||||
struct eap_config *eap_cfg;
|
||||
|
||||
struct rsn_preauth_interface *preauth_iface;
|
||||
struct os_reltime michael_mic_failure;
|
||||
|
|
@ -318,10 +326,10 @@ struct hostapd_data {
|
|||
|
||||
#ifdef CONFIG_SAE
|
||||
/** Key used for generating SAE anti-clogging tokens */
|
||||
u8 sae_token_key[8];
|
||||
struct os_reltime last_sae_token_key_update;
|
||||
u16 sae_token_idx;
|
||||
u16 sae_pending_token_idx[256];
|
||||
u8 comeback_key[8];
|
||||
struct os_reltime last_comeback_key_update;
|
||||
u16 comeback_idx;
|
||||
u16 comeback_pending_idx[256];
|
||||
int dot11RSNASAERetransPeriod; /* msec */
|
||||
struct dl_list sae_commit_queue; /* struct hostapd_sae_commit_queue */
|
||||
#endif /* CONFIG_SAE */
|
||||
|
|
@ -337,12 +345,17 @@ struct hostapd_data {
|
|||
u8 last_gtk[WPA_GTK_MAX_LEN];
|
||||
size_t last_gtk_len;
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
enum wpa_alg last_igtk_alg;
|
||||
int last_igtk_key_idx;
|
||||
u8 last_igtk[WPA_IGTK_MAX_LEN];
|
||||
size_t last_igtk_len;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
enum wpa_alg last_bigtk_alg;
|
||||
int last_bigtk_key_idx;
|
||||
u8 last_bigtk[WPA_BIGTK_MAX_LEN];
|
||||
size_t last_bigtk_len;
|
||||
|
||||
bool force_backlog_bytes;
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
#ifdef CONFIG_MBO
|
||||
|
|
@ -359,6 +372,8 @@ struct hostapd_data {
|
|||
|
||||
int dhcp_sock; /* UDP socket used with the DHCP server */
|
||||
|
||||
struct ptksa_cache *ptksa;
|
||||
|
||||
#ifdef CONFIG_DPP
|
||||
int dpp_init_done;
|
||||
struct dpp_authentication *dpp_auth;
|
||||
|
|
@ -380,6 +395,16 @@ struct hostapd_data {
|
|||
unsigned int dpp_resp_wait_time;
|
||||
unsigned int dpp_resp_max_tries;
|
||||
unsigned int dpp_resp_retry_time;
|
||||
#ifdef CONFIG_DPP2
|
||||
struct wpabuf *dpp_presence_announcement;
|
||||
struct dpp_bootstrap_info *dpp_chirp_bi;
|
||||
int dpp_chirp_freq;
|
||||
int *dpp_chirp_freqs;
|
||||
int dpp_chirp_iter;
|
||||
int dpp_chirp_round;
|
||||
int dpp_chirp_scan_done;
|
||||
int dpp_chirp_listen;
|
||||
#endif /* CONFIG_DPP2 */
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
char *dpp_config_obj_override;
|
||||
char *dpp_discovery_override;
|
||||
|
|
@ -398,6 +423,10 @@ struct hostapd_data {
|
|||
#ifdef CONFIG_SQLITE
|
||||
sqlite3 *rad_attr_db;
|
||||
#endif /* CONFIG_SQLITE */
|
||||
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP
|
||||
unsigned char ctrl_iface_cookie[CTRL_IFACE_COOKIE_LEN];
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP */
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -465,9 +494,7 @@ struct hostapd_iface {
|
|||
struct ap_info *ap_hash[STA_HASH_SIZE];
|
||||
|
||||
u64 drv_flags;
|
||||
|
||||
/* SMPS modes supported by the driver (WPA_DRIVER_SMPS_MODE_*) */
|
||||
unsigned int smps_modes;
|
||||
u64 drv_flags2;
|
||||
|
||||
/*
|
||||
* A bitmap of supported protocols for probe response offload. See
|
||||
|
|
@ -566,6 +593,9 @@ struct hostapd_iface {
|
|||
|
||||
/* Previous WMM element information */
|
||||
struct hostapd_wmm_ac_params prev_wmm[WMM_AC_NUM];
|
||||
|
||||
int (*enable_iface_cb)(struct hostapd_iface *iface);
|
||||
int (*disable_iface_cb)(struct hostapd_iface *iface);
|
||||
};
|
||||
|
||||
/* hostapd.c */
|
||||
|
|
@ -594,13 +624,17 @@ void hostapd_interface_deinit_free(struct hostapd_iface *iface);
|
|||
int hostapd_enable_iface(struct hostapd_iface *hapd_iface);
|
||||
int hostapd_reload_iface(struct hostapd_iface *hapd_iface);
|
||||
int hostapd_disable_iface(struct hostapd_iface *hapd_iface);
|
||||
void hostapd_bss_deinit_no_free(struct hostapd_data *hapd);
|
||||
void hostapd_free_hapd_data(struct hostapd_data *hapd);
|
||||
void hostapd_cleanup_iface_partial(struct hostapd_iface *iface);
|
||||
int hostapd_add_iface(struct hapd_interfaces *ifaces, char *buf);
|
||||
int hostapd_remove_iface(struct hapd_interfaces *ifaces, char *buf);
|
||||
void hostapd_channel_list_updated(struct hostapd_iface *iface, int initiator);
|
||||
void hostapd_set_state(struct hostapd_iface *iface, enum hostapd_iface_state s);
|
||||
const char * hostapd_state_text(enum hostapd_iface_state s);
|
||||
int hostapd_csa_in_progress(struct hostapd_iface *iface);
|
||||
void hostapd_chan_switch_vht_config(struct hostapd_data *hapd, int vht_enabled);
|
||||
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);
|
||||
void
|
||||
|
|
@ -609,6 +643,7 @@ hostapd_switch_channel_fallback(struct hostapd_iface *iface,
|
|||
void hostapd_cleanup_cs_params(struct hostapd_data *hapd);
|
||||
void hostapd_periodic_iface(struct hostapd_iface *iface);
|
||||
int hostapd_owe_trans_get_info(struct hostapd_data *hapd);
|
||||
void hostapd_ocv_check_csa_sa_query(void *eloop_ctx, void *timeout_ctx);
|
||||
|
||||
/* utils.c */
|
||||
int hostapd_register_probereq_cb(struct hostapd_data *hapd,
|
||||
|
|
|
|||
|
|
@ -80,15 +80,15 @@ u8 * hostapd_eid_osen(struct hostapd_data *hapd, u8 *eid)
|
|||
/* 4 PTKSA replay counters when using WMM */
|
||||
capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
|
||||
capab |= WPA_CAPABILITY_MFPC;
|
||||
if (hapd->conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED)
|
||||
capab |= WPA_CAPABILITY_MFPR;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_OCV
|
||||
if (hapd->conf->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);
|
||||
|
|
|
|||
|
|
@ -224,16 +224,27 @@ int hostapd_prepare_rates(struct hostapd_iface *iface,
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface)
|
||||
{
|
||||
int pri_chan, sec_chan;
|
||||
int pri_freq, sec_freq;
|
||||
struct hostapd_channel_data *p_chan, *s_chan;
|
||||
|
||||
pri_chan = iface->conf->channel;
|
||||
sec_chan = pri_chan + iface->conf->secondary_channel * 4;
|
||||
pri_freq = iface->freq;
|
||||
sec_freq = pri_freq + iface->conf->secondary_channel * 20;
|
||||
|
||||
return allowed_ht40_channel_pair(iface->current_mode, pri_chan,
|
||||
sec_chan);
|
||||
if (!iface->current_mode)
|
||||
return 0;
|
||||
|
||||
p_chan = hw_get_channel_freq(iface->current_mode->mode, pri_freq, NULL,
|
||||
iface->hw_features,
|
||||
iface->num_hw_features);
|
||||
|
||||
s_chan = hw_get_channel_freq(iface->current_mode->mode, sec_freq, NULL,
|
||||
iface->hw_features,
|
||||
iface->num_hw_features);
|
||||
|
||||
return allowed_ht40_channel_pair(iface->current_mode->mode,
|
||||
p_chan, s_chan);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -241,9 +252,11 @@ static void ieee80211n_switch_pri_sec(struct hostapd_iface *iface)
|
|||
{
|
||||
if (iface->conf->secondary_channel > 0) {
|
||||
iface->conf->channel += 4;
|
||||
iface->freq += 20;
|
||||
iface->conf->secondary_channel = -1;
|
||||
} else {
|
||||
iface->conf->channel -= 4;
|
||||
iface->freq -= 20;
|
||||
iface->conf->secondary_channel = 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -252,13 +265,23 @@ static void ieee80211n_switch_pri_sec(struct hostapd_iface *iface)
|
|||
static int ieee80211n_check_40mhz_5g(struct hostapd_iface *iface,
|
||||
struct wpa_scan_results *scan_res)
|
||||
{
|
||||
int pri_chan, sec_chan;
|
||||
unsigned int pri_freq, sec_freq;
|
||||
int res;
|
||||
struct hostapd_channel_data *pri_chan, *sec_chan;
|
||||
|
||||
pri_chan = iface->conf->channel;
|
||||
sec_chan = pri_chan + iface->conf->secondary_channel * 4;
|
||||
pri_freq = iface->freq;
|
||||
sec_freq = pri_freq + iface->conf->secondary_channel * 20;
|
||||
|
||||
res = check_40mhz_5g(iface->current_mode, scan_res, pri_chan, sec_chan);
|
||||
if (!iface->current_mode)
|
||||
return 0;
|
||||
pri_chan = hw_get_channel_freq(iface->current_mode->mode, pri_freq,
|
||||
NULL, iface->hw_features,
|
||||
iface->num_hw_features);
|
||||
sec_chan = hw_get_channel_freq(iface->current_mode->mode, sec_freq,
|
||||
NULL, iface->hw_features,
|
||||
iface->num_hw_features);
|
||||
|
||||
res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
|
||||
|
||||
if (res == 2) {
|
||||
if (iface->conf->no_pri_sec_switch) {
|
||||
|
|
@ -290,7 +313,7 @@ static void ieee80211n_check_scan(struct hostapd_iface *iface)
|
|||
{
|
||||
struct wpa_scan_results *scan_res;
|
||||
int oper40;
|
||||
int res;
|
||||
int res = 0;
|
||||
|
||||
/* Check list of neighboring BSSes (from scan) to see whether 40 MHz is
|
||||
* allowed per IEEE Std 802.11-2012, 10.15.3.2 */
|
||||
|
|
@ -326,7 +349,24 @@ static void ieee80211n_check_scan(struct hostapd_iface *iface)
|
|||
}
|
||||
}
|
||||
|
||||
res = ieee80211n_allowed_ht40_channel_pair(iface);
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
if (iface->conf->secondary_channel &&
|
||||
iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G &&
|
||||
iface->conf->ieee80211ax) {
|
||||
struct he_capabilities *he_cap;
|
||||
|
||||
he_cap = &iface->current_mode->he_capab[IEEE80211_MODE_AP];
|
||||
if (!(he_cap->phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
|
||||
HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"HE: 40 MHz channel width is not supported in 2.4 GHz; clear secondary channel configuration");
|
||||
iface->conf->secondary_channel = 0;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
|
||||
if (iface->conf->secondary_channel)
|
||||
res = ieee80211n_allowed_ht40_channel_pair(iface);
|
||||
if (!res) {
|
||||
iface->conf->secondary_channel = 0;
|
||||
hostapd_set_oper_centr_freq_seg0_idx(iface->conf, 0);
|
||||
|
|
@ -352,7 +392,7 @@ static void ieee80211n_scan_channels_2g4(struct hostapd_iface *iface,
|
|||
if (iface->current_mode == NULL)
|
||||
return;
|
||||
|
||||
pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel);
|
||||
pri_freq = iface->freq;
|
||||
if (iface->conf->secondary_channel > 0)
|
||||
sec_freq = pri_freq + 20;
|
||||
else
|
||||
|
|
@ -397,7 +437,7 @@ static void ieee80211n_scan_channels_5g(struct hostapd_iface *iface,
|
|||
if (iface->current_mode == NULL)
|
||||
return;
|
||||
|
||||
pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel);
|
||||
pri_freq = iface->freq;
|
||||
if (iface->conf->secondary_channel > 0) {
|
||||
affected_start = pri_freq - 10;
|
||||
affected_end = pri_freq + 30;
|
||||
|
|
@ -537,26 +577,6 @@ static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface)
|
|||
return 0;
|
||||
}
|
||||
|
||||
switch (conf & HT_CAP_INFO_SMPS_MASK) {
|
||||
case HT_CAP_INFO_SMPS_STATIC:
|
||||
if (!(iface->smps_modes & WPA_DRIVER_SMPS_MODE_STATIC)) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Driver does not support configured HT capability [SMPS-STATIC]");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case HT_CAP_INFO_SMPS_DYNAMIC:
|
||||
if (!(iface->smps_modes & WPA_DRIVER_SMPS_MODE_DYNAMIC)) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Driver does not support configured HT capability [SMPS-DYNAMIC]");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case HT_CAP_INFO_SMPS_DISABLED:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ((conf & HT_CAP_INFO_GREEN_FIELD) &&
|
||||
!(hw & HT_CAP_INFO_GREEN_FIELD)) {
|
||||
wpa_printf(MSG_ERROR, "Driver does not support configured "
|
||||
|
|
@ -663,13 +683,13 @@ static int ieee80211ax_supported_he_capab(struct hostapd_iface *iface)
|
|||
}
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
|
||||
int hostapd_check_ht_capab(struct hostapd_iface *iface)
|
||||
{
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
int ret;
|
||||
|
||||
if (is_6ghz_freq(iface->freq))
|
||||
return 0;
|
||||
if (!iface->conf->ieee80211n)
|
||||
return 0;
|
||||
|
||||
|
|
@ -698,21 +718,92 @@ int hostapd_check_ht_capab(struct hostapd_iface *iface)
|
|||
return ret;
|
||||
if (!ieee80211n_allowed_ht40_channel_pair(iface))
|
||||
return -1;
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_check_edmg_capab(struct hostapd_iface *iface)
|
||||
{
|
||||
struct hostapd_hw_modes *mode = iface->hw_features;
|
||||
struct ieee80211_edmg_config edmg;
|
||||
|
||||
if (!iface->conf->enable_edmg)
|
||||
return 0;
|
||||
|
||||
hostapd_encode_edmg_chan(iface->conf->enable_edmg,
|
||||
iface->conf->edmg_channel,
|
||||
iface->conf->channel,
|
||||
&edmg);
|
||||
|
||||
if (mode->edmg.channels && ieee802_edmg_is_allowed(mode->edmg, edmg))
|
||||
return 0;
|
||||
|
||||
wpa_printf(MSG_WARNING, "Requested EDMG configuration is not valid");
|
||||
wpa_printf(MSG_INFO, "EDMG capab: channels 0x%x, bw_config %d",
|
||||
mode->edmg.channels, mode->edmg.bw_config);
|
||||
wpa_printf(MSG_INFO,
|
||||
"Requested EDMG configuration: channels 0x%x, bw_config %d",
|
||||
edmg.channels, edmg.bw_config);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_check_he_6ghz_capab(struct hostapd_iface *iface)
|
||||
{
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
struct he_capabilities *he_cap;
|
||||
u16 hw;
|
||||
|
||||
if (!iface->current_mode || !is_6ghz_freq(iface->freq))
|
||||
return 0;
|
||||
|
||||
he_cap = &iface->current_mode->he_capab[IEEE80211_MODE_AP];
|
||||
hw = he_cap->he_6ghz_capa;
|
||||
if (iface->conf->he_6ghz_max_mpdu >
|
||||
((hw & HE_6GHZ_BAND_CAP_MAX_MPDU_LEN_MASK) >>
|
||||
HE_6GHZ_BAND_CAP_MAX_MPDU_LEN_SHIFT)) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"The driver does not support the configured HE 6 GHz Max MPDU length");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (iface->conf->he_6ghz_max_ampdu_len_exp >
|
||||
((hw & HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_MASK) >>
|
||||
HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_SHIFT)) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"The driver does not support the configured HE 6 GHz Max AMPDU Length Exponent");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (iface->conf->he_6ghz_rx_ant_pat &&
|
||||
!(hw & HE_6GHZ_BAND_CAP_RX_ANTPAT_CONS)) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"The driver does not support the configured HE 6 GHz Rx Antenna Pattern");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (iface->conf->he_6ghz_tx_ant_pat &&
|
||||
!(hw & HE_6GHZ_BAND_CAP_TX_ANTPAT_CONS)) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"The driver does not support the configured HE 6 GHz Tx Antenna Pattern");
|
||||
return -1;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_is_usable_chan(struct hostapd_iface *iface,
|
||||
int channel, int primary)
|
||||
int frequency, int primary)
|
||||
{
|
||||
struct hostapd_channel_data *chan;
|
||||
|
||||
if (!iface->current_mode)
|
||||
return 0;
|
||||
|
||||
chan = hw_get_channel_chan(iface->current_mode, channel, NULL);
|
||||
chan = hw_get_channel_freq(iface->current_mode->mode, frequency, NULL,
|
||||
iface->hw_features, iface->num_hw_features);
|
||||
if (!chan)
|
||||
return 0;
|
||||
|
||||
|
|
@ -721,8 +812,8 @@ static int hostapd_is_usable_chan(struct hostapd_iface *iface,
|
|||
return 1;
|
||||
|
||||
wpa_printf(MSG_INFO,
|
||||
"Channel %d (%s) not allowed for AP mode, flags: 0x%x%s%s",
|
||||
channel, primary ? "primary" : "secondary",
|
||||
"Frequency %d (%s) not allowed for AP mode, flags: 0x%x%s%s",
|
||||
frequency, primary ? "primary" : "secondary",
|
||||
chan->flag,
|
||||
chan->flag & HOSTAPD_CHAN_NO_IR ? " NO-IR" : "",
|
||||
chan->flag & HOSTAPD_CHAN_RADAR ? " RADAR" : "");
|
||||
|
|
@ -730,37 +821,123 @@ static int hostapd_is_usable_chan(struct hostapd_iface *iface,
|
|||
}
|
||||
|
||||
|
||||
static int hostapd_is_usable_chans(struct hostapd_iface *iface)
|
||||
static int hostapd_is_usable_edmg(struct hostapd_iface *iface)
|
||||
{
|
||||
int secondary_chan;
|
||||
int i, contiguous = 0;
|
||||
int num_of_enabled = 0;
|
||||
int max_contiguous = 0;
|
||||
struct ieee80211_edmg_config edmg;
|
||||
struct hostapd_channel_data *pri_chan;
|
||||
|
||||
pri_chan = hw_get_channel_chan(iface->current_mode,
|
||||
iface->conf->channel, NULL);
|
||||
if (!pri_chan)
|
||||
if (!iface->conf->enable_edmg)
|
||||
return 1;
|
||||
|
||||
if (!iface->current_mode)
|
||||
return 0;
|
||||
pri_chan = hw_get_channel_freq(iface->current_mode->mode,
|
||||
iface->freq, NULL,
|
||||
iface->hw_features,
|
||||
iface->num_hw_features);
|
||||
hostapd_encode_edmg_chan(iface->conf->enable_edmg,
|
||||
iface->conf->edmg_channel,
|
||||
pri_chan->chan,
|
||||
&edmg);
|
||||
if (!(edmg.channels & BIT(pri_chan->chan - 1)))
|
||||
return 0;
|
||||
|
||||
if (!hostapd_is_usable_chan(iface, iface->conf->channel, 1))
|
||||
/* 60 GHz channels 1..6 */
|
||||
for (i = 0; i < 6; i++) {
|
||||
int freq = 56160 + 2160 * (i + 1);
|
||||
|
||||
if (edmg.channels & BIT(i)) {
|
||||
contiguous++;
|
||||
num_of_enabled++;
|
||||
} else {
|
||||
contiguous = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* P802.11ay defines that the total number of subfields
|
||||
* set to one does not exceed 4.
|
||||
*/
|
||||
if (num_of_enabled > 4)
|
||||
return 0;
|
||||
|
||||
if (!hostapd_is_usable_chan(iface, freq, 1))
|
||||
return 0;
|
||||
|
||||
if (contiguous > max_contiguous)
|
||||
max_contiguous = contiguous;
|
||||
}
|
||||
|
||||
/* Check if the EDMG configuration is valid under the limitations
|
||||
* of P802.11ay.
|
||||
*/
|
||||
/* check bw_config against contiguous EDMG channels */
|
||||
switch (edmg.bw_config) {
|
||||
case EDMG_BW_CONFIG_4:
|
||||
if (!max_contiguous)
|
||||
return 0;
|
||||
break;
|
||||
case EDMG_BW_CONFIG_5:
|
||||
if (max_contiguous < 2)
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_is_usable_chans(struct hostapd_iface *iface)
|
||||
{
|
||||
int secondary_freq;
|
||||
struct hostapd_channel_data *pri_chan;
|
||||
|
||||
if (!iface->current_mode)
|
||||
return 0;
|
||||
pri_chan = hw_get_channel_freq(iface->current_mode->mode,
|
||||
iface->freq, NULL,
|
||||
iface->hw_features,
|
||||
iface->num_hw_features);
|
||||
if (!pri_chan) {
|
||||
wpa_printf(MSG_ERROR, "Primary frequency not present");
|
||||
return 0;
|
||||
}
|
||||
if (!hostapd_is_usable_chan(iface, pri_chan->freq, 1)) {
|
||||
wpa_printf(MSG_ERROR, "Primary frequency not allowed");
|
||||
return 0;
|
||||
}
|
||||
if (!hostapd_is_usable_edmg(iface))
|
||||
return 0;
|
||||
|
||||
if (!iface->conf->secondary_channel)
|
||||
return 1;
|
||||
|
||||
if (hostapd_is_usable_chan(iface, iface->freq +
|
||||
iface->conf->secondary_channel * 20, 0)) {
|
||||
if (iface->conf->secondary_channel == 1 &&
|
||||
(pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P))
|
||||
return 1;
|
||||
if (iface->conf->secondary_channel == -1 &&
|
||||
(pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40M))
|
||||
return 1;
|
||||
}
|
||||
if (!iface->conf->ht40_plus_minus_allowed)
|
||||
return hostapd_is_usable_chan(
|
||||
iface, iface->conf->channel +
|
||||
iface->conf->secondary_channel * 4, 0);
|
||||
return 0;
|
||||
|
||||
/* Both HT40+ and HT40- are set, pick a valid secondary channel */
|
||||
secondary_chan = iface->conf->channel + 4;
|
||||
if (hostapd_is_usable_chan(iface, secondary_chan, 0) &&
|
||||
secondary_freq = iface->freq + 20;
|
||||
if (hostapd_is_usable_chan(iface, secondary_freq, 0) &&
|
||||
(pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P)) {
|
||||
iface->conf->secondary_channel = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
secondary_chan = iface->conf->channel - 4;
|
||||
if (hostapd_is_usable_chan(iface, secondary_chan, 0) &&
|
||||
secondary_freq = iface->freq - 20;
|
||||
if (hostapd_is_usable_chan(iface, secondary_freq, 0) &&
|
||||
(pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40M)) {
|
||||
iface->conf->secondary_channel = -1;
|
||||
return 1;
|
||||
|
|
@ -770,10 +947,43 @@ static int hostapd_is_usable_chans(struct hostapd_iface *iface)
|
|||
}
|
||||
|
||||
|
||||
static void hostapd_determine_mode(struct hostapd_iface *iface)
|
||||
{
|
||||
int i;
|
||||
enum hostapd_hw_mode target_mode;
|
||||
|
||||
if (iface->current_mode ||
|
||||
iface->conf->hw_mode != HOSTAPD_MODE_IEEE80211ANY)
|
||||
return;
|
||||
|
||||
if (iface->freq < 4000)
|
||||
target_mode = HOSTAPD_MODE_IEEE80211G;
|
||||
else if (iface->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) {
|
||||
iface->current_mode = mode;
|
||||
iface->conf->hw_mode = mode->mode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!iface->current_mode)
|
||||
wpa_printf(MSG_ERROR, "ACS: Cannot decide mode");
|
||||
}
|
||||
|
||||
|
||||
static enum hostapd_chan_status
|
||||
hostapd_check_chans(struct hostapd_iface *iface)
|
||||
{
|
||||
if (iface->conf->channel) {
|
||||
if (iface->freq) {
|
||||
hostapd_determine_mode(iface);
|
||||
if (hostapd_is_usable_chans(iface))
|
||||
return HOSTAPD_CHAN_VALID;
|
||||
else
|
||||
|
|
@ -807,9 +1017,9 @@ static void hostapd_notify_bad_chans(struct hostapd_iface *iface)
|
|||
hostapd_logger(iface->bss[0], NULL,
|
||||
HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_WARNING,
|
||||
"Configured channel (%d) not found from the "
|
||||
"channel list of current mode (%d) %s",
|
||||
"Configured channel (%d) or frequency (%d) (secondary_channel=%d) not found from the channel list of the current mode (%d) %s",
|
||||
iface->conf->channel,
|
||||
iface->freq, iface->conf->secondary_channel,
|
||||
iface->current_mode->mode,
|
||||
hostapd_hw_mode_txt(iface->current_mode->mode));
|
||||
hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
|
||||
|
|
@ -829,9 +1039,7 @@ int hostapd_acs_completed(struct hostapd_iface *iface, int err)
|
|||
case HOSTAPD_CHAN_VALID:
|
||||
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO,
|
||||
ACS_EVENT_COMPLETED "freq=%d channel=%d",
|
||||
hostapd_hw_get_freq(iface->bss[0],
|
||||
iface->conf->channel),
|
||||
iface->conf->channel);
|
||||
iface->freq, iface->conf->channel);
|
||||
break;
|
||||
case HOSTAPD_CHAN_ACS:
|
||||
wpa_printf(MSG_ERROR, "ACS error - reported complete, but no result available");
|
||||
|
|
@ -889,16 +1097,28 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface)
|
|||
iface->current_mode = NULL;
|
||||
for (i = 0; i < iface->num_hw_features; i++) {
|
||||
struct hostapd_hw_modes *mode = &iface->hw_features[i];
|
||||
int chan;
|
||||
|
||||
if (mode->mode == iface->conf->hw_mode) {
|
||||
if (iface->freq > 0 &&
|
||||
!hw_mode_get_channel(mode, iface->freq, &chan))
|
||||
continue;
|
||||
|
||||
iface->current_mode = mode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (iface->current_mode == NULL) {
|
||||
if (!(iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) ||
|
||||
!(iface->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY))
|
||||
{
|
||||
if ((iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) &&
|
||||
(iface->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"Using offloaded hw_mode=any ACS");
|
||||
} else if (!(iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) &&
|
||||
iface->conf->hw_mode == HOSTAPD_MODE_IEEE80211ANY) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"Using internal ACS for hw_mode=any");
|
||||
} else {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Hardware does not support configured mode");
|
||||
hostapd_logger(iface->bss[0], NULL,
|
||||
|
|
@ -952,7 +1172,9 @@ int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq)
|
|||
struct hostapd_hw_modes *mode;
|
||||
|
||||
if (hapd->iface->current_mode) {
|
||||
channel = hw_get_chan(hapd->iface->current_mode, freq);
|
||||
channel = hw_get_chan(hapd->iface->current_mode->mode, freq,
|
||||
hapd->iface->hw_features,
|
||||
hapd->iface->num_hw_features);
|
||||
if (channel)
|
||||
return channel;
|
||||
}
|
||||
|
|
@ -963,9 +1185,28 @@ int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq)
|
|||
return 0;
|
||||
for (i = 0; i < hapd->iface->num_hw_features; i++) {
|
||||
mode = &hapd->iface->hw_features[i];
|
||||
channel = hw_get_chan(mode, freq);
|
||||
channel = hw_get_chan(mode->mode, freq,
|
||||
hapd->iface->hw_features,
|
||||
hapd->iface->num_hw_features);
|
||||
if (channel)
|
||||
return channel;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_hw_skip_mode(struct hostapd_iface *iface,
|
||||
struct hostapd_hw_modes *mode)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (iface->current_mode)
|
||||
return mode != iface->current_mode;
|
||||
if (mode->mode != HOSTAPD_MODE_IEEE80211B)
|
||||
return 0;
|
||||
for (i = 0; i < iface->num_hw_features; i++) {
|
||||
if (iface->hw_features[i].mode == HOSTAPD_MODE_IEEE80211G)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,9 +21,13 @@ const char * hostapd_hw_mode_txt(int mode);
|
|||
int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan);
|
||||
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,
|
||||
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);
|
||||
#else /* NEED_AP_MLME */
|
||||
static inline void
|
||||
hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
|
||||
|
|
@ -48,7 +52,7 @@ static inline int hostapd_select_hw_mode(struct hostapd_iface *iface)
|
|||
|
||||
static inline const char * hostapd_hw_mode_txt(int mode)
|
||||
{
|
||||
return NULL;
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
static inline int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan)
|
||||
|
|
@ -61,6 +65,11 @@ static inline int hostapd_check_ht_capab(struct hostapd_iface *iface)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int hostapd_check_edmg_capab(struct hostapd_iface *iface)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int hostapd_prepare_rates(struct hostapd_iface *iface,
|
||||
struct hostapd_hw_modes *mode)
|
||||
{
|
||||
|
|
@ -71,6 +80,17 @@ static inline void hostapd_stop_setup_timers(struct hostapd_iface *iface)
|
|||
{
|
||||
}
|
||||
|
||||
static inline int hostapd_hw_skip_mode(struct hostapd_iface *iface,
|
||||
struct hostapd_hw_modes *mode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int hostapd_check_he_6ghz_capab(struct hostapd_iface *iface)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* NEED_AP_MLME */
|
||||
|
||||
#endif /* HW_FEATURES_H */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -16,8 +16,7 @@ struct hostapd_frame_info;
|
|||
struct ieee80211_ht_capabilities;
|
||||
struct ieee80211_vht_capabilities;
|
||||
struct ieee80211_mgmt;
|
||||
struct vlan_description;
|
||||
struct hostapd_sta_wpa_psk_short;
|
||||
struct radius_sta;
|
||||
enum ieee80211_op_mode;
|
||||
|
||||
int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
|
||||
|
|
@ -50,9 +49,10 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid);
|
|||
u8 * hostapd_eid_qos_map_set(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_rm_enabled_capab(struct hostapd_data *hapd, u8 *eid,
|
||||
size_t len);
|
||||
u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_secondary_channel(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);
|
||||
|
|
@ -63,6 +63,7 @@ u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
|
|||
u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_he_mu_edca_parameter_set(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_spatial_reuse(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_he_6ghz_band_cap(struct hostapd_data *hapd, u8 *eid);
|
||||
|
||||
int hostapd_ht_operation_update(struct hostapd_iface *iface);
|
||||
void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
|
||||
|
|
@ -95,6 +96,10 @@ u16 set_sta_vht_opmode(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
u16 copy_sta_he_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
enum ieee80211_op_mode opmode, const u8 *he_capab,
|
||||
size_t he_capab_len);
|
||||
u16 copy_sta_he_6ghz_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *he_6ghz_capab);
|
||||
int hostapd_get_he_twt_responder(struct hostapd_data *hapd,
|
||||
enum ieee80211_op_mode mode);
|
||||
void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *buf, size_t len, int ack);
|
||||
void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
|
||||
|
|
@ -162,7 +167,7 @@ void ieee802_11_finish_fils_auth(struct hostapd_data *hapd,
|
|||
const u8 *msk, size_t msk_len);
|
||||
u8 * owe_assoc_req_process(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *owe_dh, u8 owe_dh_len,
|
||||
u8 *owe_buf, size_t owe_buf_len, u16 *reason);
|
||||
u8 *owe_buf, size_t owe_buf_len, u16 *status);
|
||||
u16 owe_process_rsn_ie(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *rsn_ie, size_t rsn_ie_len,
|
||||
const u8 *owe_dh, size_t owe_dh_len);
|
||||
|
|
@ -180,17 +185,14 @@ void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
|
||||
size_t hostapd_eid_owe_trans_len(struct hostapd_data *hapd);
|
||||
u8 * hostapd_eid_owe_trans(struct hostapd_data *hapd, u8 *eid, size_t len);
|
||||
int ieee802_11_allowed_address(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *msg, size_t len, u32 *session_timeout,
|
||||
u32 *acct_interim_interval,
|
||||
struct vlan_description *vlan_id,
|
||||
struct hostapd_sta_wpa_psk_short **psk,
|
||||
char **identity, char **radius_cui,
|
||||
int is_probe_req);
|
||||
|
||||
size_t hostapd_eid_dpp_cc_len(struct hostapd_data *hapd);
|
||||
u8 * hostapd_eid_dpp_cc(struct hostapd_data *hapd, u8 *eid, size_t len);
|
||||
|
||||
int get_tx_parameters(struct sta_info *sta, int ap_max_chanwidth,
|
||||
int ap_seg1_idx, int *bandwidth, int *seg1_idx);
|
||||
|
||||
void auth_sae_process_commit(void *eloop_ctx, void *user_ctx);
|
||||
u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len);
|
||||
|
||||
#endif /* IEEE802_11_H */
|
||||
|
|
|
|||
|
|
@ -32,12 +32,7 @@ struct hostapd_cached_radius_acl {
|
|||
macaddr addr;
|
||||
int accepted; /* HOSTAPD_ACL_* */
|
||||
struct hostapd_cached_radius_acl *next;
|
||||
u32 session_timeout;
|
||||
u32 acct_interim_interval;
|
||||
struct vlan_description vlan_id;
|
||||
struct hostapd_sta_wpa_psk_short *psk;
|
||||
char *identity;
|
||||
char *radius_cui;
|
||||
struct radius_sta info;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -54,9 +49,9 @@ struct hostapd_acl_query_data {
|
|||
#ifndef CONFIG_NO_RADIUS
|
||||
static void hostapd_acl_cache_free_entry(struct hostapd_cached_radius_acl *e)
|
||||
{
|
||||
os_free(e->identity);
|
||||
os_free(e->radius_cui);
|
||||
hostapd_free_psk_list(e->psk);
|
||||
os_free(e->info.identity);
|
||||
os_free(e->info.radius_cui);
|
||||
hostapd_free_psk_list(e->info.psk);
|
||||
os_free(e);
|
||||
}
|
||||
|
||||
|
|
@ -73,25 +68,8 @@ static void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache)
|
|||
}
|
||||
|
||||
|
||||
static void copy_psk_list(struct hostapd_sta_wpa_psk_short **psk,
|
||||
struct hostapd_sta_wpa_psk_short *src)
|
||||
{
|
||||
if (!psk)
|
||||
return;
|
||||
|
||||
if (src)
|
||||
src->ref++;
|
||||
|
||||
*psk = src;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr,
|
||||
u32 *session_timeout,
|
||||
u32 *acct_interim_interval,
|
||||
struct vlan_description *vlan_id,
|
||||
struct hostapd_sta_wpa_psk_short **psk,
|
||||
char **identity, char **radius_cui)
|
||||
struct radius_sta *out)
|
||||
{
|
||||
struct hostapd_cached_radius_acl *entry;
|
||||
struct os_reltime now;
|
||||
|
|
@ -105,27 +83,8 @@ static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr,
|
|||
if (os_reltime_expired(&now, &entry->timestamp,
|
||||
RADIUS_ACL_TIMEOUT))
|
||||
return -1; /* entry has expired */
|
||||
if (entry->accepted == HOSTAPD_ACL_ACCEPT_TIMEOUT)
|
||||
if (session_timeout)
|
||||
*session_timeout = entry->session_timeout;
|
||||
if (acct_interim_interval)
|
||||
*acct_interim_interval =
|
||||
entry->acct_interim_interval;
|
||||
if (vlan_id)
|
||||
*vlan_id = entry->vlan_id;
|
||||
copy_psk_list(psk, entry->psk);
|
||||
if (identity) {
|
||||
if (entry->identity)
|
||||
*identity = os_strdup(entry->identity);
|
||||
else
|
||||
*identity = NULL;
|
||||
}
|
||||
if (radius_cui) {
|
||||
if (entry->radius_cui)
|
||||
*radius_cui = os_strdup(entry->radius_cui);
|
||||
else
|
||||
*radius_cui = NULL;
|
||||
}
|
||||
*out = entry->info;
|
||||
|
||||
return entry->accepted;
|
||||
}
|
||||
|
||||
|
|
@ -238,42 +197,28 @@ int hostapd_check_acl(struct hostapd_data *hapd, const u8 *addr,
|
|||
* @addr: MAC address of the STA
|
||||
* @msg: Authentication message
|
||||
* @len: Length of msg in octets
|
||||
* @session_timeout: Buffer for returning session timeout (from RADIUS)
|
||||
* @acct_interim_interval: Buffer for returning account interval (from RADIUS)
|
||||
* @vlan_id: Buffer for returning VLAN ID
|
||||
* @psk: Linked list buffer for returning WPA PSK
|
||||
* @identity: Buffer for returning identity (from RADIUS)
|
||||
* @radius_cui: Buffer for returning CUI (from RADIUS)
|
||||
* @out.session_timeout: Buffer for returning session timeout (from RADIUS)
|
||||
* @out.acct_interim_interval: Buffer for returning account interval (from
|
||||
* RADIUS)
|
||||
* @out.vlan_id: Buffer for returning VLAN ID
|
||||
* @out.psk: Linked list buffer for returning WPA PSK
|
||||
* @out.identity: Buffer for returning identity (from RADIUS)
|
||||
* @out.radius_cui: Buffer for returning CUI (from RADIUS)
|
||||
* @is_probe_req: Whether this query for a Probe Request frame
|
||||
* Returns: HOSTAPD_ACL_ACCEPT, HOSTAPD_ACL_REJECT, or HOSTAPD_ACL_PENDING
|
||||
*
|
||||
* The caller is responsible for freeing the returned *identity and *radius_cui
|
||||
* values with os_free().
|
||||
* The caller is responsible for properly cloning the returned out->identity and
|
||||
* out->radius_cui and out->psk values.
|
||||
*/
|
||||
int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *msg, size_t len, u32 *session_timeout,
|
||||
u32 *acct_interim_interval,
|
||||
struct vlan_description *vlan_id,
|
||||
struct hostapd_sta_wpa_psk_short **psk,
|
||||
char **identity, char **radius_cui,
|
||||
const u8 *msg, size_t len, struct radius_sta *out,
|
||||
int is_probe_req)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (session_timeout)
|
||||
*session_timeout = 0;
|
||||
if (acct_interim_interval)
|
||||
*acct_interim_interval = 0;
|
||||
if (vlan_id)
|
||||
os_memset(vlan_id, 0, sizeof(*vlan_id));
|
||||
if (psk)
|
||||
*psk = NULL;
|
||||
if (identity)
|
||||
*identity = NULL;
|
||||
if (radius_cui)
|
||||
*radius_cui = NULL;
|
||||
os_memset(out, 0, sizeof(*out));
|
||||
|
||||
res = hostapd_check_acl(hapd, addr, vlan_id);
|
||||
res = hostapd_check_acl(hapd, addr, &out->vlan_id);
|
||||
if (res != HOSTAPD_ACL_PENDING)
|
||||
return res;
|
||||
|
||||
|
|
@ -290,12 +235,10 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
|
|||
};
|
||||
|
||||
if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_DISABLED)
|
||||
vlan_id = NULL;
|
||||
os_memset(&out->vlan_id, 0, sizeof(out->vlan_id));
|
||||
|
||||
/* Check whether ACL cache has an entry for this station */
|
||||
res = hostapd_acl_cache_get(hapd, addr, session_timeout,
|
||||
acct_interim_interval, vlan_id, psk,
|
||||
identity, radius_cui);
|
||||
res = hostapd_acl_cache_get(hapd, addr, out);
|
||||
if (res == HOSTAPD_ACL_ACCEPT ||
|
||||
res == HOSTAPD_ACL_ACCEPT_TIMEOUT)
|
||||
return res;
|
||||
|
|
@ -307,14 +250,6 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
|
|||
if (os_memcmp(query->addr, addr, ETH_ALEN) == 0) {
|
||||
/* pending query in RADIUS retransmit queue;
|
||||
* do not generate a new one */
|
||||
if (identity) {
|
||||
os_free(*identity);
|
||||
*identity = NULL;
|
||||
}
|
||||
if (radius_cui) {
|
||||
os_free(*radius_cui);
|
||||
*radius_cui = NULL;
|
||||
}
|
||||
return HOSTAPD_ACL_PENDING;
|
||||
}
|
||||
query = query->next;
|
||||
|
|
@ -488,8 +423,8 @@ static void decode_tunnel_passwords(struct hostapd_data *hapd,
|
|||
passphraselen);
|
||||
psk->is_passphrase = 1;
|
||||
}
|
||||
psk->next = cache->psk;
|
||||
cache->psk = psk;
|
||||
psk->next = cache->info.psk;
|
||||
cache->info.psk = psk;
|
||||
psk = NULL;
|
||||
}
|
||||
skip:
|
||||
|
|
@ -518,6 +453,7 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
|
|||
struct hostapd_data *hapd = data;
|
||||
struct hostapd_acl_query_data *query, *prev;
|
||||
struct hostapd_cached_radius_acl *cache;
|
||||
struct radius_sta *info;
|
||||
struct radius_hdr *hdr = radius_msg_get_hdr(msg);
|
||||
|
||||
query = hapd->acl_queries;
|
||||
|
|
@ -555,65 +491,66 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
|
|||
}
|
||||
os_get_reltime(&cache->timestamp);
|
||||
os_memcpy(cache->addr, query->addr, sizeof(cache->addr));
|
||||
info = &cache->info;
|
||||
if (hdr->code == RADIUS_CODE_ACCESS_ACCEPT) {
|
||||
u8 *buf;
|
||||
size_t len;
|
||||
|
||||
if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT,
|
||||
&cache->session_timeout) == 0)
|
||||
&info->session_timeout) == 0)
|
||||
cache->accepted = HOSTAPD_ACL_ACCEPT_TIMEOUT;
|
||||
else
|
||||
cache->accepted = HOSTAPD_ACL_ACCEPT;
|
||||
|
||||
if (radius_msg_get_attr_int32(
|
||||
msg, RADIUS_ATTR_ACCT_INTERIM_INTERVAL,
|
||||
&cache->acct_interim_interval) == 0 &&
|
||||
cache->acct_interim_interval < 60) {
|
||||
&info->acct_interim_interval) == 0 &&
|
||||
info->acct_interim_interval < 60) {
|
||||
wpa_printf(MSG_DEBUG, "Ignored too small "
|
||||
"Acct-Interim-Interval %d for STA " MACSTR,
|
||||
cache->acct_interim_interval,
|
||||
info->acct_interim_interval,
|
||||
MAC2STR(query->addr));
|
||||
cache->acct_interim_interval = 0;
|
||||
info->acct_interim_interval = 0;
|
||||
}
|
||||
|
||||
if (hapd->conf->ssid.dynamic_vlan != DYNAMIC_VLAN_DISABLED)
|
||||
cache->vlan_id.notempty = !!radius_msg_get_vlanid(
|
||||
msg, &cache->vlan_id.untagged,
|
||||
MAX_NUM_TAGGED_VLAN, cache->vlan_id.tagged);
|
||||
info->vlan_id.notempty = !!radius_msg_get_vlanid(
|
||||
msg, &info->vlan_id.untagged,
|
||||
MAX_NUM_TAGGED_VLAN, info->vlan_id.tagged);
|
||||
|
||||
decode_tunnel_passwords(hapd, shared_secret, shared_secret_len,
|
||||
msg, req, cache);
|
||||
|
||||
if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME,
|
||||
&buf, &len, NULL) == 0) {
|
||||
cache->identity = os_zalloc(len + 1);
|
||||
if (cache->identity)
|
||||
os_memcpy(cache->identity, buf, len);
|
||||
info->identity = os_zalloc(len + 1);
|
||||
if (info->identity)
|
||||
os_memcpy(info->identity, buf, len);
|
||||
}
|
||||
if (radius_msg_get_attr_ptr(
|
||||
msg, RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
|
||||
&buf, &len, NULL) == 0) {
|
||||
cache->radius_cui = os_zalloc(len + 1);
|
||||
if (cache->radius_cui)
|
||||
os_memcpy(cache->radius_cui, buf, len);
|
||||
info->radius_cui = os_zalloc(len + 1);
|
||||
if (info->radius_cui)
|
||||
os_memcpy(info->radius_cui, buf, len);
|
||||
}
|
||||
|
||||
if (hapd->conf->wpa_psk_radius == PSK_RADIUS_REQUIRED &&
|
||||
!cache->psk)
|
||||
!info->psk)
|
||||
cache->accepted = HOSTAPD_ACL_REJECT;
|
||||
|
||||
if (cache->vlan_id.notempty &&
|
||||
!hostapd_vlan_valid(hapd->conf->vlan, &cache->vlan_id)) {
|
||||
if (info->vlan_id.notempty &&
|
||||
!hostapd_vlan_valid(hapd->conf->vlan, &info->vlan_id)) {
|
||||
hostapd_logger(hapd, query->addr,
|
||||
HOSTAPD_MODULE_RADIUS,
|
||||
HOSTAPD_LEVEL_INFO,
|
||||
"Invalid VLAN %d%s received from RADIUS server",
|
||||
cache->vlan_id.untagged,
|
||||
cache->vlan_id.tagged[0] ? "+" : "");
|
||||
os_memset(&cache->vlan_id, 0, sizeof(cache->vlan_id));
|
||||
info->vlan_id.untagged,
|
||||
info->vlan_id.tagged[0] ? "+" : "");
|
||||
os_memset(&info->vlan_id, 0, sizeof(info->vlan_id));
|
||||
}
|
||||
if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_REQUIRED &&
|
||||
!cache->vlan_id.notempty)
|
||||
!info->vlan_id.notempty)
|
||||
cache->accepted = HOSTAPD_ACL_REJECT;
|
||||
} else
|
||||
cache->accepted = HOSTAPD_ACL_REJECT;
|
||||
|
|
@ -622,7 +559,7 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
|
|||
|
||||
#ifdef CONFIG_DRIVER_RADIUS_ACL
|
||||
hostapd_drv_set_radius_acl_auth(hapd, query->addr, cache->accepted,
|
||||
cache->session_timeout);
|
||||
info->session_timeout);
|
||||
#else /* CONFIG_DRIVER_RADIUS_ACL */
|
||||
#ifdef NEED_AP_MLME
|
||||
/* Re-send original authentication frame for 802.11 processing */
|
||||
|
|
@ -685,6 +622,19 @@ void hostapd_acl_deinit(struct hostapd_data *hapd)
|
|||
}
|
||||
|
||||
|
||||
void hostapd_copy_psk_list(struct hostapd_sta_wpa_psk_short **psk,
|
||||
struct hostapd_sta_wpa_psk_short *src)
|
||||
{
|
||||
if (!psk)
|
||||
return;
|
||||
|
||||
if (src)
|
||||
src->ref++;
|
||||
|
||||
*psk = src;
|
||||
}
|
||||
|
||||
|
||||
void hostapd_free_psk_list(struct hostapd_sta_wpa_psk_short *psk)
|
||||
{
|
||||
if (psk && psk->ref) {
|
||||
|
|
|
|||
|
|
@ -16,18 +16,25 @@ enum {
|
|||
HOSTAPD_ACL_ACCEPT_TIMEOUT = 3
|
||||
};
|
||||
|
||||
struct radius_sta {
|
||||
u32 session_timeout;
|
||||
u32 acct_interim_interval;
|
||||
struct vlan_description vlan_id;
|
||||
struct hostapd_sta_wpa_psk_short *psk;
|
||||
char *identity;
|
||||
char *radius_cui;
|
||||
};
|
||||
|
||||
int hostapd_check_acl(struct hostapd_data *hapd, const u8 *addr,
|
||||
struct vlan_description *vlan_id);
|
||||
int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *msg, size_t len, u32 *session_timeout,
|
||||
u32 *acct_interim_interval,
|
||||
struct vlan_description *vlan_id,
|
||||
struct hostapd_sta_wpa_psk_short **psk,
|
||||
char **identity, char **radius_cui,
|
||||
const u8 *msg, size_t len, struct radius_sta *out,
|
||||
int is_probe_req);
|
||||
int hostapd_acl_init(struct hostapd_data *hapd);
|
||||
void hostapd_acl_deinit(struct hostapd_data *hapd);
|
||||
void hostapd_free_psk_list(struct hostapd_sta_wpa_psk_short *psk);
|
||||
void hostapd_acl_expire(struct hostapd_data *hapd);
|
||||
void hostapd_copy_psk_list(struct hostapd_sta_wpa_psk_short **psk,
|
||||
struct hostapd_sta_wpa_psk_short *src);
|
||||
|
||||
#endif /* IEEE802_11_AUTH_H */
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "utils/common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/ieee802_11_common.h"
|
||||
#include "hostapd.h"
|
||||
#include "ap_config.h"
|
||||
#include "beacon.h"
|
||||
|
|
@ -44,6 +45,41 @@ static u8 ieee80211_he_ppet_size(u8 ppe_thres_hdr, const u8 *phy_cap_info)
|
|||
}
|
||||
|
||||
|
||||
static u8 ieee80211_he_mcs_set_size(const u8 *phy_cap_info)
|
||||
{
|
||||
u8 sz = 4;
|
||||
|
||||
if (phy_cap_info[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
|
||||
HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G)
|
||||
sz += 4;
|
||||
if (phy_cap_info[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
|
||||
HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
|
||||
sz += 4;
|
||||
|
||||
return sz;
|
||||
}
|
||||
|
||||
|
||||
static int ieee80211_invalid_he_cap_size(const u8 *buf, size_t len)
|
||||
{
|
||||
struct ieee80211_he_capabilities *cap;
|
||||
size_t cap_len;
|
||||
|
||||
cap = (struct ieee80211_he_capabilities *) buf;
|
||||
cap_len = sizeof(*cap) - sizeof(cap->optional);
|
||||
if (len < cap_len)
|
||||
return 1;
|
||||
|
||||
cap_len += ieee80211_he_mcs_set_size(cap->he_phy_capab_info);
|
||||
if (len < cap_len)
|
||||
return 1;
|
||||
|
||||
cap_len += ieee80211_he_ppet_size(buf[cap_len], cap->he_phy_capab_info);
|
||||
|
||||
return len != cap_len;
|
||||
}
|
||||
|
||||
|
||||
u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
|
||||
enum ieee80211_op_mode opmode)
|
||||
{
|
||||
|
|
@ -51,12 +87,12 @@ u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
|
|||
struct hostapd_hw_modes *mode = hapd->iface->current_mode;
|
||||
u8 he_oper_chwidth = ~HE_PHYCAP_CHANNEL_WIDTH_MASK;
|
||||
u8 *pos = eid;
|
||||
u8 ie_size = 0, mcs_nss_size = 0, ppet_size = 0;
|
||||
u8 ie_size = 0, mcs_nss_size = 4, ppet_size = 0;
|
||||
|
||||
if (!mode)
|
||||
return eid;
|
||||
|
||||
ie_size = sizeof(struct ieee80211_he_capabilities);
|
||||
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);
|
||||
|
||||
|
|
@ -74,7 +110,6 @@ u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
|
|||
case CHANWIDTH_USE_HT:
|
||||
he_oper_chwidth |= HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
|
||||
HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G;
|
||||
mcs_nss_size += 4;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -136,6 +171,9 @@ u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid)
|
|||
if (!hapd->iface->current_mode)
|
||||
return eid;
|
||||
|
||||
if (is_6ghz_op_class(hapd->iconf->op_class))
|
||||
oper_size += 5;
|
||||
|
||||
*pos++ = WLAN_EID_EXTENSION;
|
||||
*pos++ = 1 + oper_size;
|
||||
*pos++ = WLAN_EID_EXT_HE_OPERATION;
|
||||
|
|
@ -154,9 +192,12 @@ u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid)
|
|||
params |= (hapd->iface->conf->he_op.he_rts_threshold <<
|
||||
HE_OPERATION_RTS_THRESHOLD_OFFSET);
|
||||
|
||||
if (hapd->iface->conf->he_op.he_bss_color)
|
||||
params |= (hapd->iface->conf->he_op.he_bss_color <<
|
||||
HE_OPERATION_BSS_COLOR_OFFSET);
|
||||
if (hapd->iface->conf->he_op.he_bss_color_disabled)
|
||||
params |= HE_OPERATION_BSS_COLOR_DISABLED;
|
||||
if (hapd->iface->conf->he_op.he_bss_color_partial)
|
||||
params |= HE_OPERATION_BSS_COLOR_PARTIAL;
|
||||
params |= hapd->iface->conf->he_op.he_bss_color <<
|
||||
HE_OPERATION_BSS_COLOR_OFFSET;
|
||||
|
||||
/* HE minimum required basic MCS and NSS for STAs */
|
||||
oper->he_mcs_nss_set =
|
||||
|
|
@ -164,9 +205,49 @@ u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid)
|
|||
|
||||
/* TODO: conditional MaxBSSID Indicator subfield */
|
||||
|
||||
oper->he_oper_params = host_to_le32(params);
|
||||
pos += 6; /* skip the fixed part */
|
||||
|
||||
pos += oper_size;
|
||||
if (is_6ghz_op_class(hapd->iconf->op_class)) {
|
||||
u8 seg0 = hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf);
|
||||
u8 seg1 = hostapd_get_oper_centr_freq_seg1_idx(hapd->iconf);
|
||||
|
||||
if (!seg0)
|
||||
seg0 = hapd->iconf->channel;
|
||||
|
||||
params |= HE_OPERATION_6GHZ_OPER_INFO;
|
||||
|
||||
/* 6 GHz Operation Information field
|
||||
* IEEE P802.11ax/D8.0, 9.4.2.249 HE Operation element,
|
||||
* Figure 9-788k
|
||||
*/
|
||||
*pos++ = hapd->iconf->channel; /* Primary Channel */
|
||||
|
||||
/* Control: Channel Width */
|
||||
if (seg1)
|
||||
*pos++ = 3;
|
||||
else
|
||||
*pos++ = center_idx_to_bw_6ghz(seg0);
|
||||
|
||||
/* Channel Center Freq Seg0/Seg1 */
|
||||
if (hapd->iconf->he_oper_chwidth == 2) {
|
||||
/*
|
||||
* Seg 0 indicates the channel center frequency index of
|
||||
* the 160 MHz channel.
|
||||
*/
|
||||
seg1 = seg0;
|
||||
if (hapd->iconf->channel < seg0)
|
||||
seg0 -= 8;
|
||||
else
|
||||
seg0 += 8;
|
||||
}
|
||||
|
||||
*pos++ = seg0;
|
||||
*pos++ = seg1;
|
||||
/* Minimum Rate */
|
||||
*pos++ = 6; /* TODO: what should be set here? */
|
||||
}
|
||||
|
||||
oper->he_oper_params = host_to_le32(params);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
|
@ -238,6 +319,11 @@ u8 * hostapd_eid_spatial_reuse(struct hostapd_data *hapd, u8 *eid)
|
|||
if (spr->sr_ctrl & SPATIAL_REUSE_SRG_INFORMATION_PRESENT) {
|
||||
*spr_param++ = hapd->iface->conf->spr.srg_obss_pd_min_offset;
|
||||
*spr_param++ = hapd->iface->conf->spr.srg_obss_pd_max_offset;
|
||||
os_memcpy(spr_param,
|
||||
hapd->iface->conf->spr.srg_bss_color_bitmap, 8);
|
||||
spr_param += 8;
|
||||
os_memcpy(spr_param,
|
||||
hapd->iface->conf->spr.srg_partial_bssid_bitmap, 8);
|
||||
pos += 18;
|
||||
}
|
||||
|
||||
|
|
@ -245,6 +331,46 @@ u8 * hostapd_eid_spatial_reuse(struct hostapd_data *hapd, u8 *eid)
|
|||
}
|
||||
|
||||
|
||||
u8 * hostapd_eid_he_6ghz_band_cap(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
struct hostapd_config *conf = hapd->iface->conf;
|
||||
struct hostapd_hw_modes *mode = hapd->iface->current_mode;
|
||||
struct he_capabilities *he_cap;
|
||||
struct ieee80211_he_6ghz_band_cap *cap;
|
||||
u16 capab;
|
||||
u8 *pos;
|
||||
|
||||
if (!mode || !is_6ghz_op_class(hapd->iconf->op_class) ||
|
||||
!is_6ghz_freq(hapd->iface->freq))
|
||||
return eid;
|
||||
|
||||
he_cap = &mode->he_capab[IEEE80211_MODE_AP];
|
||||
capab = he_cap->he_6ghz_capa & HE_6GHZ_BAND_CAP_MIN_MPDU_START;
|
||||
capab |= (conf->he_6ghz_max_ampdu_len_exp <<
|
||||
HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_SHIFT) &
|
||||
HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_MASK;
|
||||
capab |= (conf->he_6ghz_max_mpdu <<
|
||||
HE_6GHZ_BAND_CAP_MAX_MPDU_LEN_SHIFT) &
|
||||
HE_6GHZ_BAND_CAP_MAX_MPDU_LEN_MASK;
|
||||
capab |= HE_6GHZ_BAND_CAP_SMPS_DISABLED;
|
||||
if (conf->he_6ghz_rx_ant_pat)
|
||||
capab |= HE_6GHZ_BAND_CAP_RX_ANTPAT_CONS;
|
||||
if (conf->he_6ghz_tx_ant_pat)
|
||||
capab |= HE_6GHZ_BAND_CAP_TX_ANTPAT_CONS;
|
||||
|
||||
pos = eid;
|
||||
*pos++ = WLAN_EID_EXTENSION;
|
||||
*pos++ = 1 + sizeof(*cap);
|
||||
*pos++ = WLAN_EID_EXT_HE_6GHZ_BAND_CAP;
|
||||
|
||||
cap = (struct ieee80211_he_6ghz_band_cap *) pos;
|
||||
cap->capab = host_to_le16(capab);
|
||||
pos += sizeof(*cap);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
void hostapd_get_he_capab(struct hostapd_data *hapd,
|
||||
const struct ieee80211_he_capabilities *he_cap,
|
||||
struct ieee80211_he_capabilities *neg_he_cap,
|
||||
|
|
@ -323,8 +449,10 @@ u16 copy_sta_he_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
enum ieee80211_op_mode opmode, const u8 *he_capab,
|
||||
size_t he_capab_len)
|
||||
{
|
||||
if (!he_capab || !hapd->iconf->ieee80211ax ||
|
||||
if (!he_capab || !(sta->flags & WLAN_STA_WMM) ||
|
||||
!hapd->iconf->ieee80211ax || hapd->conf->disable_11ax ||
|
||||
!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)) {
|
||||
sta->flags &= ~WLAN_STA_HE;
|
||||
os_free(sta->he_capab);
|
||||
|
|
@ -346,3 +474,46 @@ u16 copy_sta_he_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
|
||||
return WLAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
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)) {
|
||||
sta->flags &= ~WLAN_STA_6GHZ;
|
||||
os_free(sta->he_6ghz_capab);
|
||||
sta->he_6ghz_capab = NULL;
|
||||
return WLAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!sta->he_6ghz_capab) {
|
||||
sta->he_6ghz_capab =
|
||||
os_zalloc(sizeof(struct ieee80211_he_6ghz_band_cap));
|
||||
if (!sta->he_6ghz_capab)
|
||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
}
|
||||
|
||||
sta->flags |= WLAN_STA_6GHZ;
|
||||
os_memcpy(sta->he_6ghz_capab, he_6ghz_capab,
|
||||
sizeof(struct ieee80211_he_6ghz_band_cap));
|
||||
|
||||
return WLAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_get_he_twt_responder(struct hostapd_data *hapd,
|
||||
enum ieee80211_op_mode mode)
|
||||
{
|
||||
u8 *mac_cap;
|
||||
|
||||
if (!hapd->iface->current_mode ||
|
||||
!hapd->iface->current_mode->he_capab[mode].he_supported)
|
||||
return 0;
|
||||
|
||||
mac_cap = hapd->iface->current_mode->he_capab[mode].mac_cap;
|
||||
|
||||
return !!(mac_cap[HE_MAC_CAPAB_0] & HE_MACCAP_TWT_RESPONDER) &&
|
||||
hapd->iface->conf->he_op.he_twt_responder;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid)
|
|||
u8 *pos = eid;
|
||||
|
||||
if (!hapd->iconf->ieee80211n || !hapd->iface->current_mode ||
|
||||
hapd->conf->disable_11n)
|
||||
hapd->conf->disable_11n || is_6ghz_op_class(hapd->iconf->op_class))
|
||||
return eid;
|
||||
|
||||
*pos++ = WLAN_EID_HT_CAP;
|
||||
|
|
@ -84,7 +84,8 @@ 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 (!hapd->iconf->ieee80211n || hapd->conf->disable_11n ||
|
||||
is_6ghz_op_class(hapd->iconf->op_class))
|
||||
return eid;
|
||||
|
||||
*pos++ = WLAN_EID_HT_OPERATION;
|
||||
|
|
@ -108,32 +109,9 @@ u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid)
|
|||
}
|
||||
|
||||
|
||||
u8 * hostapd_eid_secondary_channel(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
u8 sec_ch;
|
||||
|
||||
if (!hapd->cs_freq_params.channel ||
|
||||
!hapd->cs_freq_params.sec_channel_offset)
|
||||
return eid;
|
||||
|
||||
if (hapd->cs_freq_params.sec_channel_offset == -1)
|
||||
sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW;
|
||||
else if (hapd->cs_freq_params.sec_channel_offset == 1)
|
||||
sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE;
|
||||
else
|
||||
return eid;
|
||||
|
||||
*eid++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET;
|
||||
*eid++ = 1;
|
||||
*eid++ = sec_ch;
|
||||
|
||||
return eid;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
op_mode
|
||||
Set to 0 (HT pure) under the followign conditions
|
||||
Set to 0 (HT pure) under the following conditions
|
||||
- all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
|
||||
- all STAs in the BSS are 20 MHz HT in 20 MHz BSS
|
||||
Set to 1 (HT non-member protection) if there may be non-HT STAs
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include "utils/common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/ocv.h"
|
||||
#include "common/wpa_ctrl.h"
|
||||
#include "hostapd.h"
|
||||
#include "sta_info.h"
|
||||
#include "ap_config.h"
|
||||
|
|
@ -19,8 +20,6 @@
|
|||
#include "ieee802_11.h"
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
|
||||
u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, u8 *eid)
|
||||
{
|
||||
|
|
@ -74,6 +73,16 @@ void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
|
|||
"Failed to get channel info for OCI element in SA Query Request");
|
||||
return;
|
||||
}
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
if (hapd->conf->oci_freq_override_saquery_req) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"TEST: Override OCI frequency %d -> %u MHz",
|
||||
ci.frequency,
|
||||
hapd->conf->oci_freq_override_saquery_req);
|
||||
ci.frequency =
|
||||
hapd->conf->oci_freq_override_saquery_req;
|
||||
}
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
oci_ie_len = OCV_OCI_EXTENDED_LEN;
|
||||
oci_ie = os_zalloc(oci_ie_len);
|
||||
|
|
@ -114,7 +123,8 @@ void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
|
|||
end += oci_ie_len;
|
||||
}
|
||||
#endif /* CONFIG_OCV */
|
||||
if (hostapd_drv_send_mlme(hapd, mgmt, end - (u8 *) mgmt, 0) < 0)
|
||||
if (hostapd_drv_send_mlme(hapd, mgmt, end - (u8 *) mgmt, 0, NULL, 0, 0)
|
||||
< 0)
|
||||
wpa_printf(MSG_INFO, "ieee802_11_send_sa_query_req: send failed");
|
||||
|
||||
os_free(mgmt);
|
||||
|
|
@ -152,6 +162,16 @@ static void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd,
|
|||
"Failed to get channel info for OCI element in SA Query Response");
|
||||
return;
|
||||
}
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
if (hapd->conf->oci_freq_override_saquery_resp) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"TEST: Override OCI frequency %d -> %u MHz",
|
||||
ci.frequency,
|
||||
hapd->conf->oci_freq_override_saquery_resp);
|
||||
ci.frequency =
|
||||
hapd->conf->oci_freq_override_saquery_resp;
|
||||
}
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
oci_ie_len = OCV_OCI_EXTENDED_LEN;
|
||||
oci_ie = os_zalloc(oci_ie_len);
|
||||
|
|
@ -195,7 +215,8 @@ static void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd,
|
|||
end += oci_ie_len;
|
||||
}
|
||||
#endif /* CONFIG_OCV */
|
||||
if (hostapd_drv_send_mlme(hapd, resp, end - (u8 *) resp, 0) < 0)
|
||||
if (hostapd_drv_send_mlme(hapd, resp, end - (u8 *) resp, 0, NULL, 0, 0)
|
||||
< 0)
|
||||
wpa_printf(MSG_INFO, "ieee80211_mgmt_sa_query_request: send failed");
|
||||
|
||||
os_free(resp);
|
||||
|
|
@ -220,6 +241,12 @@ void ieee802_11_sa_query_action(struct hostapd_data *hapd,
|
|||
(unsigned long) len);
|
||||
return;
|
||||
}
|
||||
if (is_multicast_ether_addr(mgmt->da)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"IEEE 802.11: Ignore group-addressed SA Query frame (A1=" MACSTR " A2=" MACSTR ")",
|
||||
MAC2STR(mgmt->da), MAC2STR(mgmt->sa));
|
||||
return;
|
||||
}
|
||||
|
||||
sta = ap_get_sta(hapd, sa);
|
||||
|
||||
|
|
@ -254,14 +281,21 @@ void ieee802_11_sa_query_action(struct hostapd_data *hapd,
|
|||
return;
|
||||
|
||||
if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
|
||||
tx_chanwidth, tx_seg1_idx) != 0) {
|
||||
wpa_printf(MSG_WARNING, "%s", ocv_errorstr);
|
||||
tx_chanwidth, tx_seg1_idx) !=
|
||||
OCI_SUCCESS) {
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, OCV_FAILURE "addr="
|
||||
MACSTR " frame=saquery%s error=%s",
|
||||
MAC2STR(sa),
|
||||
action_type == WLAN_SA_QUERY_REQUEST ?
|
||||
"req" : "resp", ocv_errorstr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_OCV */
|
||||
|
||||
if (action_type == WLAN_SA_QUERY_REQUEST) {
|
||||
if (sta)
|
||||
sta->post_csa_sa_query = 0;
|
||||
ieee802_11_send_sa_query_resp(hapd, sa, trans_id);
|
||||
return;
|
||||
}
|
||||
|
|
@ -304,8 +338,6 @@ void ieee802_11_sa_query_action(struct hostapd_data *hapd,
|
|||
ap_sta_stop_sa_query(hapd, sta);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
|
||||
static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
|
||||
{
|
||||
|
|
@ -379,6 +411,11 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
|
|||
wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt))
|
||||
*pos |= 0x01;
|
||||
#endif /* CONFIG_FILS */
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
if (hapd->iconf->ieee80211ax &&
|
||||
hostapd_get_he_twt_responder(hapd, IEEE80211_MODE_AP))
|
||||
*pos |= 0x40; /* Bit 78 - TWT responder */
|
||||
#endif /* CONFIG_IEEE80211AX */
|
||||
break;
|
||||
case 10: /* Bits 80-87 */
|
||||
#ifdef CONFIG_SAE
|
||||
|
|
@ -394,6 +431,18 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
|
|||
* Identifiers Used Exclusively */
|
||||
}
|
||||
#endif /* CONFIG_SAE */
|
||||
if (hapd->conf->beacon_prot &&
|
||||
(hapd->iface->drv_flags &
|
||||
WPA_DRIVER_FLAGS_BEACON_PROTECTION))
|
||||
*pos |= 0x10; /* Bit 84 - Beacon Protection Enabled */
|
||||
break;
|
||||
case 11: /* Bits 88-95 */
|
||||
#ifdef CONFIG_SAE_PK
|
||||
if (hapd->conf->wpa &&
|
||||
wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
|
||||
hostapd_sae_pk_exclusively(hapd->conf))
|
||||
*pos |= 0x01; /* Bit 88 - SAE PK Exclusively */
|
||||
#endif /* CONFIG_SAE_PK */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -402,48 +451,10 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
|
|||
u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
u8 *pos = eid;
|
||||
u8 len = 0, i;
|
||||
u8 len = EXT_CAPA_MAX_LEN, i;
|
||||
|
||||
if (hapd->conf->tdls & (TDLS_PROHIBIT | TDLS_PROHIBIT_CHAN_SWITCH))
|
||||
len = 5;
|
||||
if (len < 4 && hapd->conf->interworking)
|
||||
len = 4;
|
||||
if (len < 3 && hapd->conf->wnm_sleep_mode)
|
||||
len = 3;
|
||||
if (len < 1 && hapd->iconf->obss_interval)
|
||||
len = 1;
|
||||
if (len < 7 && hapd->conf->ssid.utf8_ssid)
|
||||
len = 7;
|
||||
if (len < 9 &&
|
||||
(hapd->conf->ftm_initiator || hapd->conf->ftm_responder))
|
||||
len = 9;
|
||||
#ifdef CONFIG_WNM_AP
|
||||
if (len < 4)
|
||||
len = 4;
|
||||
#endif /* CONFIG_WNM_AP */
|
||||
#ifdef CONFIG_HS20
|
||||
if (hapd->conf->hs20 && len < 6)
|
||||
len = 6;
|
||||
#endif /* CONFIG_HS20 */
|
||||
#ifdef CONFIG_MBO
|
||||
if (hapd->conf->mbo_enabled && len < 6)
|
||||
len = 6;
|
||||
#endif /* CONFIG_MBO */
|
||||
#ifdef CONFIG_FILS
|
||||
if ((!(hapd->conf->wpa & WPA_PROTO_RSN) ||
|
||||
!wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) && len < 10)
|
||||
len = 10;
|
||||
#endif /* CONFIG_FILS */
|
||||
#ifdef CONFIG_SAE
|
||||
if (len < 11 && hapd->conf->wpa &&
|
||||
wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
|
||||
hostapd_sae_pw_id_in_use(hapd->conf))
|
||||
len = 11;
|
||||
#endif /* CONFIG_SAE */
|
||||
if (len < hapd->iface->extended_capa_len)
|
||||
len = hapd->iface->extended_capa_len;
|
||||
if (len == 0)
|
||||
return eid;
|
||||
|
||||
*pos++ = WLAN_EID_EXT_CAPAB;
|
||||
*pos++ = len;
|
||||
|
|
@ -454,6 +465,11 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
|
|||
*pos &= ~hapd->iface->extended_capa_mask[i];
|
||||
*pos |= hapd->iface->extended_capa[i];
|
||||
}
|
||||
|
||||
if (i < EXT_CAPA_MAX_LEN) {
|
||||
*pos &= ~hapd->conf->ext_capa_mask[i];
|
||||
*pos |= hapd->conf->ext_capa[i];
|
||||
}
|
||||
}
|
||||
|
||||
while (len > 0 && eid[1 + len] == 0) {
|
||||
|
|
@ -854,6 +870,35 @@ u8 * hostapd_eid_owe_trans(struct hostapd_data *hapd, u8 *eid,
|
|||
}
|
||||
|
||||
|
||||
size_t hostapd_eid_dpp_cc_len(struct hostapd_data *hapd)
|
||||
{
|
||||
#ifdef CONFIG_DPP2
|
||||
if (hapd->conf->dpp_configurator_connectivity)
|
||||
return 6;
|
||||
#endif /* CONFIG_DPP2 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
u8 * hostapd_eid_dpp_cc(struct hostapd_data *hapd, u8 *eid, size_t len)
|
||||
{
|
||||
u8 *pos = eid;
|
||||
|
||||
#ifdef CONFIG_DPP2
|
||||
if (!hapd->conf->dpp_configurator_connectivity || len < 6)
|
||||
return pos;
|
||||
|
||||
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||
*pos++ = 4;
|
||||
WPA_PUT_BE24(pos, OUI_WFA);
|
||||
pos += 3;
|
||||
*pos++ = DPP_CC_OUI_TYPE;
|
||||
#endif /* CONFIG_DPP2 */
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
void ap_copy_sta_supp_op_classes(struct sta_info *sta,
|
||||
const u8 *supp_op_classes,
|
||||
size_t supp_op_classes_len)
|
||||
|
|
@ -1000,3 +1045,51 @@ int get_tx_parameters(struct sta_info *sta, int ap_max_chanwidth,
|
|||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_OCV */
|
||||
|
||||
|
||||
u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len)
|
||||
{
|
||||
u8 *pos = eid;
|
||||
bool sae_pk = false;
|
||||
u16 capab = 0;
|
||||
size_t flen;
|
||||
|
||||
if (!(hapd->conf->wpa & WPA_PROTO_RSN))
|
||||
return eid;
|
||||
|
||||
#ifdef CONFIG_SAE_PK
|
||||
sae_pk = hostapd_sae_pk_in_use(hapd->conf);
|
||||
#endif /* CONFIG_SAE_PK */
|
||||
|
||||
if (wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
|
||||
(hapd->conf->sae_pwe == 1 || hapd->conf->sae_pwe == 2 ||
|
||||
hostapd_sae_pw_id_in_use(hapd->conf) || sae_pk) &&
|
||||
hapd->conf->sae_pwe != 3) {
|
||||
capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
|
||||
#ifdef CONFIG_SAE_PK
|
||||
if (sae_pk)
|
||||
capab |= BIT(WLAN_RSNX_CAPAB_SAE_PK);
|
||||
#endif /* CONFIG_SAE_PK */
|
||||
}
|
||||
|
||||
if (hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF)
|
||||
capab |= BIT(WLAN_RSNX_CAPAB_SECURE_LTF);
|
||||
if (hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_RTT)
|
||||
capab |= BIT(WLAN_RSNX_CAPAB_SECURE_RTT);
|
||||
if (hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_PROT_RANGE_NEG)
|
||||
capab |= BIT(WLAN_RSNX_CAPAB_PROT_RANGE_NEG);
|
||||
|
||||
flen = (capab & 0xff00) ? 2 : 1;
|
||||
if (len < 2 + flen || !capab)
|
||||
return eid; /* no supported extended RSN capabilities */
|
||||
capab |= flen - 1; /* bit 0-3 = Field length (n - 1) */
|
||||
|
||||
*pos++ = WLAN_EID_RSNX;
|
||||
*pos++ = flen;
|
||||
*pos++ = capab & 0x00ff;
|
||||
capab >>= 8;
|
||||
if (capab)
|
||||
*pos++ = capab;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid, u32 nsts)
|
|||
struct hostapd_hw_modes *mode = hapd->iface->current_mode;
|
||||
u8 *pos = eid;
|
||||
|
||||
if (!mode)
|
||||
if (!mode || is_6ghz_op_class(hapd->iconf->op_class))
|
||||
return eid;
|
||||
|
||||
if (mode->mode == HOSTAPD_MODE_IEEE80211G && hapd->conf->vendor_vht &&
|
||||
|
|
@ -76,6 +76,9 @@ u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid)
|
|||
struct ieee80211_vht_operation *oper;
|
||||
u8 *pos = eid;
|
||||
|
||||
if (is_6ghz_op_class(hapd->iconf->op_class))
|
||||
return eid;
|
||||
|
||||
*pos++ = WLAN_EID_VHT_OPERATION;
|
||||
*pos++ = sizeof(*oper);
|
||||
|
||||
|
|
@ -164,176 +167,11 @@ static int check_valid_vht_mcs(struct hostapd_hw_modes *mode,
|
|||
}
|
||||
|
||||
|
||||
u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
u8 bw, chan1, chan2 = 0;
|
||||
int freq1;
|
||||
|
||||
if (!hapd->cs_freq_params.channel ||
|
||||
!hapd->cs_freq_params.vht_enabled)
|
||||
return eid;
|
||||
|
||||
/* bandwidth: 0: 40, 1: 80, 2: 160, 3: 80+80 */
|
||||
switch (hapd->cs_freq_params.bandwidth) {
|
||||
case 40:
|
||||
bw = 0;
|
||||
break;
|
||||
case 80:
|
||||
/* check if it's 80+80 */
|
||||
if (!hapd->cs_freq_params.center_freq2)
|
||||
bw = 1;
|
||||
else
|
||||
bw = 3;
|
||||
break;
|
||||
case 160:
|
||||
bw = 2;
|
||||
break;
|
||||
default:
|
||||
/* not valid VHT bandwidth or not in CSA */
|
||||
return eid;
|
||||
}
|
||||
|
||||
freq1 = hapd->cs_freq_params.center_freq1 ?
|
||||
hapd->cs_freq_params.center_freq1 :
|
||||
hapd->cs_freq_params.freq;
|
||||
if (ieee80211_freq_to_chan(freq1, &chan1) !=
|
||||
HOSTAPD_MODE_IEEE80211A)
|
||||
return eid;
|
||||
|
||||
if (hapd->cs_freq_params.center_freq2 &&
|
||||
ieee80211_freq_to_chan(hapd->cs_freq_params.center_freq2,
|
||||
&chan2) != HOSTAPD_MODE_IEEE80211A)
|
||||
return eid;
|
||||
|
||||
*eid++ = WLAN_EID_VHT_CHANNEL_SWITCH_WRAPPER;
|
||||
*eid++ = 5; /* Length of Channel Switch Wrapper */
|
||||
*eid++ = WLAN_EID_VHT_WIDE_BW_CHSWITCH;
|
||||
*eid++ = 3; /* Length of Wide Bandwidth Channel Switch element */
|
||||
*eid++ = bw; /* New Channel Width */
|
||||
*eid++ = chan1; /* New Channel Center Frequency Segment 0 */
|
||||
*eid++ = chan2; /* New Channel Center Frequency Segment 1 */
|
||||
|
||||
return eid;
|
||||
}
|
||||
|
||||
|
||||
u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
struct hostapd_iface *iface = hapd->iface;
|
||||
struct hostapd_config *iconf = iface->conf;
|
||||
struct hostapd_hw_modes *mode = iface->current_mode;
|
||||
struct hostapd_channel_data *chan;
|
||||
int dfs, i;
|
||||
u8 channel, tx_pwr_count, local_pwr_constraint;
|
||||
int max_tx_power;
|
||||
u8 tx_pwr;
|
||||
|
||||
if (!mode)
|
||||
return eid;
|
||||
|
||||
if (ieee80211_freq_to_chan(iface->freq, &channel) == NUM_HOSTAPD_MODES)
|
||||
return eid;
|
||||
|
||||
for (i = 0; i < mode->num_channels; i++) {
|
||||
if (mode->channels[i].freq == iface->freq)
|
||||
break;
|
||||
}
|
||||
if (i == mode->num_channels)
|
||||
return eid;
|
||||
|
||||
switch (iface->conf->vht_oper_chwidth) {
|
||||
case CHANWIDTH_USE_HT:
|
||||
if (iconf->secondary_channel == 0) {
|
||||
/* Max Transmit Power count = 0 (20 MHz) */
|
||||
tx_pwr_count = 0;
|
||||
} else {
|
||||
/* Max Transmit Power count = 1 (20, 40 MHz) */
|
||||
tx_pwr_count = 1;
|
||||
}
|
||||
break;
|
||||
case CHANWIDTH_80MHZ:
|
||||
/* Max Transmit Power count = 2 (20, 40, and 80 MHz) */
|
||||
tx_pwr_count = 2;
|
||||
break;
|
||||
case CHANWIDTH_80P80MHZ:
|
||||
case CHANWIDTH_160MHZ:
|
||||
/* Max Transmit Power count = 3 (20, 40, 80, 160/80+80 MHz) */
|
||||
tx_pwr_count = 3;
|
||||
break;
|
||||
default:
|
||||
return eid;
|
||||
}
|
||||
|
||||
/*
|
||||
* Below local_pwr_constraint logic is referred from
|
||||
* hostapd_eid_pwr_constraint.
|
||||
*
|
||||
* Check if DFS is required by regulatory.
|
||||
*/
|
||||
dfs = hostapd_is_dfs_required(hapd->iface);
|
||||
if (dfs < 0)
|
||||
dfs = 0;
|
||||
|
||||
/*
|
||||
* In order to meet regulations when TPC is not implemented using
|
||||
* a transmit power that is below the legal maximum (including any
|
||||
* mitigation factor) should help. In this case, indicate 3 dB below
|
||||
* maximum allowed transmit power.
|
||||
*/
|
||||
if (hapd->iconf->local_pwr_constraint == -1)
|
||||
local_pwr_constraint = (dfs == 0) ? 0 : 3;
|
||||
else
|
||||
local_pwr_constraint = hapd->iconf->local_pwr_constraint;
|
||||
|
||||
/*
|
||||
* A STA that is not an AP shall use a transmit power less than or
|
||||
* equal to the local maximum transmit power level for the channel.
|
||||
* The local maximum transmit power can be calculated from the formula:
|
||||
* local max TX pwr = max TX pwr - local pwr constraint
|
||||
* Where max TX pwr is maximum transmit power level specified for
|
||||
* channel in Country element and local pwr constraint is specified
|
||||
* for channel in this Power Constraint element.
|
||||
*/
|
||||
chan = &mode->channels[i];
|
||||
max_tx_power = chan->max_tx_power - local_pwr_constraint;
|
||||
|
||||
/*
|
||||
* Local Maximum Transmit power is encoded as two's complement
|
||||
* with a 0.5 dB step.
|
||||
*/
|
||||
max_tx_power *= 2; /* in 0.5 dB steps */
|
||||
if (max_tx_power > 127) {
|
||||
/* 63.5 has special meaning of 63.5 dBm or higher */
|
||||
max_tx_power = 127;
|
||||
}
|
||||
if (max_tx_power < -128)
|
||||
max_tx_power = -128;
|
||||
if (max_tx_power < 0)
|
||||
tx_pwr = 0x80 + max_tx_power + 128;
|
||||
else
|
||||
tx_pwr = max_tx_power;
|
||||
|
||||
*eid++ = WLAN_EID_VHT_TRANSMIT_POWER_ENVELOPE;
|
||||
*eid++ = 2 + tx_pwr_count;
|
||||
|
||||
/*
|
||||
* Max Transmit Power count and
|
||||
* Max Transmit Power units = 0 (EIRP)
|
||||
*/
|
||||
*eid++ = tx_pwr_count;
|
||||
|
||||
for (i = 0; i <= tx_pwr_count; i++)
|
||||
*eid++ = tx_pwr;
|
||||
|
||||
return eid;
|
||||
}
|
||||
|
||||
|
||||
u16 copy_sta_vht_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *vht_capab)
|
||||
{
|
||||
/* Disable VHT caps for STAs associated to no-VHT BSSes. */
|
||||
if (!vht_capab ||
|
||||
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)) {
|
||||
sta->flags &= ~WLAN_STA_VHT;
|
||||
|
|
@ -422,7 +260,9 @@ u8 * hostapd_eid_vendor_vht(struct hostapd_data *hapd, u8 *eid)
|
|||
{
|
||||
u8 *pos = eid;
|
||||
|
||||
if (!hapd->iface->current_mode)
|
||||
/* Vendor VHT is applicable only to 2.4 GHz */
|
||||
if (!hapd->iface->current_mode ||
|
||||
hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G)
|
||||
return eid;
|
||||
|
||||
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -42,10 +42,9 @@ const u8 * ieee802_1x_get_key(struct eapol_state_machine *sm, size_t *len);
|
|||
const u8 * ieee802_1x_get_session_id(struct eapol_state_machine *sm,
|
||||
size_t *len);
|
||||
void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm,
|
||||
int enabled);
|
||||
void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm,
|
||||
int valid);
|
||||
void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth);
|
||||
bool enabled);
|
||||
void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm, bool valid);
|
||||
void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, bool pre_auth);
|
||||
int ieee802_1x_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen);
|
||||
int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
char *buf, size_t buflen);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,60 @@ hostapd_neighbor_get(struct hostapd_data *hapd, const u8 *bssid,
|
|||
}
|
||||
|
||||
|
||||
int hostapd_neighbor_show(struct hostapd_data *hapd, char *buf, size_t buflen)
|
||||
{
|
||||
struct hostapd_neighbor_entry *nr;
|
||||
char *pos, *end;
|
||||
|
||||
pos = buf;
|
||||
end = buf + buflen;
|
||||
|
||||
dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry,
|
||||
list) {
|
||||
int ret;
|
||||
char nrie[2 * 255 + 1];
|
||||
char lci[2 * 255 + 1];
|
||||
char civic[2 * 255 + 1];
|
||||
char ssid[SSID_MAX_LEN * 2 + 1];
|
||||
|
||||
ssid[0] = '\0';
|
||||
wpa_snprintf_hex(ssid, sizeof(ssid), nr->ssid.ssid,
|
||||
nr->ssid.ssid_len);
|
||||
|
||||
nrie[0] = '\0';
|
||||
if (nr->nr)
|
||||
wpa_snprintf_hex(nrie, sizeof(nrie),
|
||||
wpabuf_head(nr->nr),
|
||||
wpabuf_len(nr->nr));
|
||||
|
||||
lci[0] = '\0';
|
||||
if (nr->lci)
|
||||
wpa_snprintf_hex(lci, sizeof(lci),
|
||||
wpabuf_head(nr->lci),
|
||||
wpabuf_len(nr->lci));
|
||||
|
||||
civic[0] = '\0';
|
||||
if (nr->civic)
|
||||
wpa_snprintf_hex(civic, sizeof(civic),
|
||||
wpabuf_head(nr->civic),
|
||||
wpabuf_len(nr->civic));
|
||||
|
||||
ret = os_snprintf(pos, end - pos, MACSTR
|
||||
" ssid=%s%s%s%s%s%s%s%s\n",
|
||||
MAC2STR(nr->bssid), ssid,
|
||||
nr->nr ? " nr=" : "", nrie,
|
||||
nr->lci ? " lci=" : "", lci,
|
||||
nr->civic ? " civic=" : "", civic,
|
||||
nr->stationary ? " stat" : "");
|
||||
if (os_snprintf_error(end - pos, ret))
|
||||
break;
|
||||
pos += ret;
|
||||
}
|
||||
|
||||
return pos - buf;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_neighbor_clear_entry(struct hostapd_neighbor_entry *nr)
|
||||
{
|
||||
wpabuf_free(nr->nr);
|
||||
|
|
@ -166,7 +220,7 @@ void hostapd_neighbor_set_own_report(struct hostapd_data *hapd)
|
|||
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;
|
||||
int he = hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax;
|
||||
struct wpa_ssid_value ssid;
|
||||
u8 channel, op_class;
|
||||
u8 center_freq1_idx = 0, center_freq2_idx = 0;
|
||||
|
|
@ -202,6 +256,8 @@ void hostapd_neighbor_set_own_report(struct hostapd_data *hapd)
|
|||
/* VHT bit added in IEEE P802.11-REVmc/D4.3 */
|
||||
if (vht)
|
||||
bssid_info |= NEI_REP_BSSID_INFO_VHT;
|
||||
if (he)
|
||||
bssid_info |= NEI_REP_BSSID_INFO_HE;
|
||||
}
|
||||
|
||||
/* TODO: Set NEI_REP_BSSID_INFO_MOBILITY_DOMAIN if MDE is set */
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
struct hostapd_neighbor_entry *
|
||||
hostapd_neighbor_get(struct hostapd_data *hapd, const u8 *bssid,
|
||||
const struct wpa_ssid_value *ssid);
|
||||
int hostapd_neighbor_show(struct hostapd_data *hapd, char *buf, size_t buflen);
|
||||
int hostapd_neighbor_set(struct hostapd_data *hapd, const u8 *bssid,
|
||||
const struct wpa_ssid_value *ssid,
|
||||
const struct wpabuf *nr, const struct wpabuf *lci,
|
||||
|
|
|
|||
|
|
@ -516,6 +516,12 @@ struct rsn_pmksa_cache_entry * pmksa_cache_get_okc(
|
|||
for (entry = pmksa->pmksa; entry; entry = entry->next) {
|
||||
if (os_memcmp(entry->spa, spa, ETH_ALEN) != 0)
|
||||
continue;
|
||||
if (wpa_key_mgmt_sae(entry->akmp) ||
|
||||
wpa_key_mgmt_fils(entry->akmp)) {
|
||||
if (os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0)
|
||||
return entry;
|
||||
continue;
|
||||
}
|
||||
rsn_pmkid(entry->pmk, entry->pmk_len, aa, spa, new_pmkid,
|
||||
entry->akmp);
|
||||
if (os_memcmp(new_pmkid, pmkid, PMKID_LEN) == 0)
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ static void rsn_preauth_receive(void *ctx, const u8 *src_addr,
|
|||
sta = NULL;
|
||||
} else {
|
||||
sta->eapol_sm->radius_identifier = -1;
|
||||
sta->eapol_sm->portValid = TRUE;
|
||||
sta->eapol_sm->portValid = true;
|
||||
sta->eapol_sm->flags |= EAPOL_SM_PREAUTH;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,9 +46,7 @@ static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx);
|
|||
static void ap_handle_session_warning_timer(void *eloop_ctx, void *timeout_ctx);
|
||||
static void ap_sta_deauth_cb_timeout(void *eloop_ctx, void *timeout_ctx);
|
||||
static void ap_sta_disassoc_cb_timeout(void *eloop_ctx, void *timeout_ctx);
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx);
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
static void ap_sta_delayed_1x_auth_fail_cb(void *eloop_ctx, void *timeout_ctx);
|
||||
|
||||
|
|
@ -158,6 +156,37 @@ void ap_sta_ip6addr_del(struct hostapd_data *hapd, struct sta_info *sta)
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_PASN
|
||||
|
||||
void ap_free_sta_pasn(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
if (sta->pasn) {
|
||||
wpa_printf(MSG_DEBUG, "PASN: Free PASN context: " MACSTR,
|
||||
MAC2STR(sta->addr));
|
||||
|
||||
if (sta->pasn->ecdh)
|
||||
crypto_ecdh_deinit(sta->pasn->ecdh);
|
||||
|
||||
wpabuf_free(sta->pasn->secret);
|
||||
sta->pasn->secret = NULL;
|
||||
|
||||
#ifdef CONFIG_SAE
|
||||
sae_clear_data(&sta->pasn->sae);
|
||||
#endif /* CONFIG_SAE */
|
||||
|
||||
#ifdef CONFIG_FILS
|
||||
/* In practice this pointer should be NULL */
|
||||
wpabuf_free(sta->pasn->fils.erp_resp);
|
||||
sta->pasn->fils.erp_resp = NULL;
|
||||
#endif /* CONFIG_FILS */
|
||||
|
||||
bin_clear_free(sta->pasn, sizeof(*sta->pasn));
|
||||
sta->pasn = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PASN */
|
||||
|
||||
void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
int set_beacon = 0;
|
||||
|
|
@ -166,6 +195,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
|||
|
||||
/* just in case */
|
||||
ap_sta_set_authorized(hapd, sta, 0);
|
||||
hostapd_set_sta_flags(hapd, sta);
|
||||
|
||||
if (sta->flags & (WLAN_STA_WDS | WLAN_STA_MULTI_AP))
|
||||
hostapd_set_wds_sta(hapd, NULL, sta->addr, sta->aid, 0);
|
||||
|
|
@ -235,9 +265,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
|||
sta->assoc_ie_taxonomy = NULL;
|
||||
#endif /* CONFIG_TAXONOMY */
|
||||
|
||||
#ifdef CONFIG_IEEE80211N
|
||||
ht40_intolerant_remove(hapd->iface, sta);
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (sta->no_p2p_set) {
|
||||
|
|
@ -248,10 +276,10 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
|||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
#if defined(NEED_AP_MLME) && defined(CONFIG_IEEE80211N)
|
||||
#ifdef NEED_AP_MLME
|
||||
if (hostapd_ht_operation_update(hapd->iface) > 0)
|
||||
set_beacon++;
|
||||
#endif /* NEED_AP_MLME && CONFIG_IEEE80211N */
|
||||
#endif /* NEED_AP_MLME */
|
||||
|
||||
#ifdef CONFIG_MESH
|
||||
if (hapd->mesh_sta_free_cb)
|
||||
|
|
@ -301,10 +329,8 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
|||
|
||||
os_free(sta->challenge);
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
os_free(sta->sa_query_trans_id);
|
||||
eloop_cancel_timeout(ap_sa_query_timer, hapd, sta);
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
p2p_group_notif_disassoc(hapd->p2p_group, sta->addr);
|
||||
|
|
@ -331,6 +357,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
|||
os_free(sta->vht_capabilities);
|
||||
os_free(sta->vht_operation);
|
||||
os_free(sta->he_capab);
|
||||
os_free(sta->he_6ghz_capab);
|
||||
hostapd_free_psk_list(sta->psk);
|
||||
os_free(sta->identity);
|
||||
os_free(sta->radius_cui);
|
||||
|
|
@ -375,8 +402,16 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
|||
eloop_cancel_timeout(ap_sta_reset_steer_flag_timer, hapd, sta);
|
||||
#endif /* CONFIG_WNM_AP */
|
||||
|
||||
#ifdef CONFIG_PASN
|
||||
ap_free_sta_pasn(hapd, sta);
|
||||
#endif /* CONFIG_PASN */
|
||||
|
||||
os_free(sta->ifname_wds);
|
||||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
os_free(sta->sae_postponed_commit);
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
os_free(sta);
|
||||
}
|
||||
|
||||
|
|
@ -546,6 +581,7 @@ skip_poll:
|
|||
case STA_DISASSOC_FROM_CLI:
|
||||
ap_sta_set_authorized(hapd, sta, 0);
|
||||
sta->flags &= ~WLAN_STA_ASSOC;
|
||||
hostapd_set_sta_flags(hapd, sta);
|
||||
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
|
||||
if (!sta->acct_terminate_cause)
|
||||
sta->acct_terminate_cause =
|
||||
|
|
@ -590,7 +626,8 @@ static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx)
|
|||
|
||||
wpa_printf(MSG_DEBUG, "%s: Session timer for STA " MACSTR,
|
||||
hapd->conf->iface, MAC2STR(sta->addr));
|
||||
if (!(sta->flags & WLAN_STA_AUTH)) {
|
||||
if (!(sta->flags & (WLAN_STA_AUTH | WLAN_STA_ASSOC |
|
||||
WLAN_STA_AUTHORIZED))) {
|
||||
if (sta->flags & WLAN_STA_GAS) {
|
||||
wpa_printf(MSG_DEBUG, "GAS: Remove temporary STA "
|
||||
"entry " MACSTR, MAC2STR(sta->addr));
|
||||
|
|
@ -813,6 +850,7 @@ void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
sta->timeout_next = STA_DEAUTH;
|
||||
}
|
||||
ap_sta_set_authorized(hapd, sta, 0);
|
||||
hostapd_set_sta_flags(hapd, sta);
|
||||
wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
|
||||
"for " MACSTR " (%d seconds - "
|
||||
"AP_MAX_INACTIVITY_AFTER_DISASSOC)",
|
||||
|
|
@ -863,6 +901,7 @@ void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
|
||||
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
|
||||
ap_sta_set_authorized(hapd, sta, 0);
|
||||
hostapd_set_sta_flags(hapd, sta);
|
||||
sta->timeout_next = STA_REMOVE;
|
||||
wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
|
||||
"for " MACSTR " (%d seconds - "
|
||||
|
|
@ -1028,6 +1067,13 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta)
|
|||
int ret;
|
||||
int old_vlanid = sta->vlan_id_bound;
|
||||
|
||||
if ((sta->flags & WLAN_STA_WDS) && sta->vlan_id == 0) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"Do not override WDS VLAN assignment for STA "
|
||||
MACSTR, MAC2STR(sta->addr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
iface = hapd->conf->iface;
|
||||
if (hapd->conf->ssid.vlan[0])
|
||||
iface = hapd->conf->ssid.vlan;
|
||||
|
|
@ -1049,7 +1095,8 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta)
|
|||
if (sta->vlan_id == old_vlanid)
|
||||
goto skip_counting;
|
||||
|
||||
if (sta->vlan_id > 0 && vlan == NULL) {
|
||||
if (sta->vlan_id > 0 && !vlan &&
|
||||
!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_VLAN_OFFLOAD)) {
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_DEBUG, "could not find VLAN for "
|
||||
"binding station to (vlan_id=%d)",
|
||||
|
|
@ -1095,8 +1142,6 @@ done:
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
|
||||
int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
u32 tu;
|
||||
|
|
@ -1135,6 +1180,8 @@ static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
|
|||
if (sta->sa_query_count > 0 &&
|
||||
ap_check_sa_query_timeout(hapd, sta))
|
||||
return;
|
||||
if (sta->sa_query_count >= 1000)
|
||||
return;
|
||||
|
||||
nbuf = os_realloc_array(sta->sa_query_trans_id,
|
||||
sta->sa_query_count + 1,
|
||||
|
|
@ -1186,8 +1233,6 @@ void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta)
|
|||
sta->sa_query_count = 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
|
||||
const char * ap_sta_wpa_get_keyid(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
|
|
@ -1324,9 +1369,10 @@ 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);
|
||||
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
|
||||
wpa_printf(MSG_DEBUG, "%s: %s: reschedule ap_handle_timer timeout "
|
||||
"for " MACSTR " (%d seconds - "
|
||||
"AP_MAX_INACTIVITY_AFTER_DEAUTH)",
|
||||
|
|
@ -1414,7 +1460,8 @@ 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",
|
||||
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",
|
||||
(flags & WLAN_STA_AUTH ? "[AUTH]" : ""),
|
||||
(flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""),
|
||||
(flags & WLAN_STA_AUTHORIZED ? "[AUTHORIZED]" : ""),
|
||||
|
|
@ -1433,6 +1480,8 @@ int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen)
|
|||
(flags & WLAN_STA_GAS ? "[GAS]" : ""),
|
||||
(flags & WLAN_STA_HT ? "[HT]" : ""),
|
||||
(flags & WLAN_STA_VHT ? "[VHT]" : ""),
|
||||
(flags & WLAN_STA_HE ? "[HE]" : ""),
|
||||
(flags & WLAN_STA_6GHZ ? "[6GHZ]" : ""),
|
||||
(flags & WLAN_STA_VENDOR_VHT ? "[VENDOR_VHT]" : ""),
|
||||
(flags & WLAN_STA_WNM_SLEEP_MODE ?
|
||||
"[WNM_SLEEP_MODE]" : ""));
|
||||
|
|
@ -1486,3 +1535,33 @@ int ap_sta_pending_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
|
|||
return eloop_is_timeout_registered(ap_sta_delayed_1x_auth_fail_cb,
|
||||
hapd, sta);
|
||||
}
|
||||
|
||||
|
||||
int ap_sta_re_add(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
/*
|
||||
* 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
|
||||
* STA PS state gets cleared and configuration gets updated. To handle
|
||||
* this, station's added_unassoc flag is cleared once the station has
|
||||
* completed association.
|
||||
*/
|
||||
ap_sta_set_authorized(hapd, sta, 0);
|
||||
hostapd_drv_sta_remove(hapd, sta->addr);
|
||||
sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_AUTH | WLAN_STA_AUTHORIZED);
|
||||
|
||||
if (hostapd_sta_add(hapd, sta->addr, 0, 0,
|
||||
sta->supported_rates,
|
||||
sta->supported_rates_len,
|
||||
0, NULL, NULL, NULL, 0, NULL,
|
||||
sta->flags, 0, 0, 0, 0)) {
|
||||
hostapd_logger(hapd, sta->addr,
|
||||
HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_NOTICE,
|
||||
"Could not add STA to kernel driver");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sta->added_unassoc = 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@
|
|||
#include "vlan.h"
|
||||
#include "common/wpa_common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/sae.h"
|
||||
#include "crypto/sha384.h"
|
||||
|
||||
/* STA flags */
|
||||
#define WLAN_STA_AUTH BIT(0)
|
||||
|
|
@ -38,6 +40,8 @@
|
|||
#define WLAN_STA_PENDING_FILS_ERP BIT(22)
|
||||
#define WLAN_STA_MULTI_AP BIT(23)
|
||||
#define WLAN_STA_HE BIT(24)
|
||||
#define WLAN_STA_6GHZ BIT(25)
|
||||
#define WLAN_STA_PENDING_PASN_FILS_ERP BIT(26)
|
||||
#define WLAN_STA_PENDING_DISASSOC_CB BIT(29)
|
||||
#define WLAN_STA_PENDING_DEAUTH_CB BIT(30)
|
||||
#define WLAN_STA_NONERP BIT(31)
|
||||
|
|
@ -62,6 +66,43 @@ struct pending_eapol_rx {
|
|||
struct os_reltime rx_time;
|
||||
};
|
||||
|
||||
enum pasn_fils_state {
|
||||
PASN_FILS_STATE_NONE = 0,
|
||||
PASN_FILS_STATE_PENDING_AS,
|
||||
PASN_FILS_STATE_COMPLETE
|
||||
};
|
||||
|
||||
struct pasn_fils_data {
|
||||
u8 state;
|
||||
u8 nonce[FILS_NONCE_LEN];
|
||||
u8 anonce[FILS_NONCE_LEN];
|
||||
u8 session[FILS_SESSION_LEN];
|
||||
u8 erp_pmkid[PMKID_LEN];
|
||||
|
||||
struct wpabuf *erp_resp;
|
||||
};
|
||||
|
||||
struct pasn_data {
|
||||
int akmp;
|
||||
int cipher;
|
||||
u16 group;
|
||||
u8 trans_seq;
|
||||
u8 wrapped_data_format;
|
||||
size_t kdk_len;
|
||||
|
||||
u8 hash[SHA384_MAC_LEN];
|
||||
struct wpa_ptk ptk;
|
||||
struct crypto_ecdh *ecdh;
|
||||
|
||||
struct wpabuf *secret;
|
||||
#ifdef CONFIG_SAE
|
||||
struct sae_data sae;
|
||||
#endif /* CONFIG_SAE */
|
||||
#ifdef CONFIG_FILS
|
||||
struct pasn_fils_data fils;
|
||||
#endif /* CONFIG_FILS */
|
||||
};
|
||||
|
||||
struct sta_info {
|
||||
struct sta_info *next; /* next entry in sta list */
|
||||
struct sta_info *hnext; /* next entry in hash table list */
|
||||
|
|
@ -121,6 +162,7 @@ struct sta_info {
|
|||
unsigned int hs20_t_c_filtering:1;
|
||||
unsigned int ft_over_ds:1;
|
||||
unsigned int external_dh_updated:1;
|
||||
unsigned int post_csa_sa_query:1;
|
||||
|
||||
u16 auth_alg;
|
||||
|
||||
|
|
@ -170,8 +212,8 @@ struct sta_info {
|
|||
u8 vht_opmode;
|
||||
struct ieee80211_he_capabilities *he_capab;
|
||||
size_t he_capab_len;
|
||||
struct ieee80211_he_6ghz_band_cap *he_6ghz_capab;
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
int sa_query_count; /* number of pending SA Query requests;
|
||||
* 0 = no SA Query in progress */
|
||||
int sa_query_timed_out;
|
||||
|
|
@ -179,7 +221,6 @@ struct sta_info {
|
|||
* sa_query_count octets of pending SA Query
|
||||
* transaction identifiers */
|
||||
struct os_reltime sa_query_start;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
#if defined(CONFIG_INTERWORKING) || defined(CONFIG_DPP)
|
||||
#define GAS_DIALOG_MAX 8 /* Max concurrent dialog number */
|
||||
|
|
@ -278,11 +319,17 @@ struct sta_info {
|
|||
int last_tk_key_idx;
|
||||
u8 last_tk[WPA_TK_MAX_LEN];
|
||||
size_t last_tk_len;
|
||||
u8 *sae_postponed_commit;
|
||||
size_t sae_postponed_commit_len;
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
#ifdef CONFIG_AIRTIME_POLICY
|
||||
unsigned int airtime_weight;
|
||||
struct os_reltime backlogged_until;
|
||||
#endif /* CONFIG_AIRTIME_POLICY */
|
||||
|
||||
#ifdef CONFIG_PASN
|
||||
struct pasn_data *pasn;
|
||||
#endif /* CONFIG_PASN */
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -358,5 +405,8 @@ void ap_sta_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
|
|||
struct sta_info *sta);
|
||||
int ap_sta_pending_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
|
||||
struct sta_info *sta);
|
||||
int ap_sta_re_add(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
|
||||
void ap_free_sta_pasn(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
|
||||
#endif /* STA_INFO_H */
|
||||
|
|
|
|||
|
|
@ -56,6 +56,10 @@ static int prune_associations(struct hostapd_iface *iface, void *ctx)
|
|||
ohapd = iface->bss[j];
|
||||
if (ohapd == data->hapd)
|
||||
continue;
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
if (ohapd->conf->skip_prune_assoc)
|
||||
continue;
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
#ifdef CONFIG_FST
|
||||
/* Don't prune STAs belong to same FST */
|
||||
if (ohapd->iface->fst &&
|
||||
|
|
|
|||
|
|
@ -22,7 +22,9 @@
|
|||
static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
|
||||
int existsok)
|
||||
{
|
||||
int ret, i;
|
||||
int ret;
|
||||
#ifdef CONFIG_WEP
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_WEP_KEYS; i++) {
|
||||
if (!hapd->conf->ssid.wep.key[i])
|
||||
|
|
@ -32,6 +34,7 @@ static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
|
|||
vlan->ifname);
|
||||
return -1;
|
||||
}
|
||||
#endif /* CONFIG_WEP */
|
||||
|
||||
if (!iface_exists(vlan->ifname))
|
||||
ret = hostapd_vlan_if_add(hapd, vlan->ifname);
|
||||
|
|
|
|||
|
|
@ -111,9 +111,11 @@ u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid)
|
|||
u8 *pos = eid;
|
||||
struct wmm_parameter_element *wmm =
|
||||
(struct wmm_parameter_element *) (pos + 2);
|
||||
struct hostapd_wmm_ac_params wmmp[WMM_AC_NUM] = { 0 };
|
||||
struct hostapd_wmm_ac_params wmmp[WMM_AC_NUM];
|
||||
int e;
|
||||
|
||||
os_memset(wmmp, 0, sizeof(wmmp));
|
||||
|
||||
if (!hapd->conf->wmm_enabled)
|
||||
return eid;
|
||||
wmm_calc_regulatory_limit(hapd, wmmp);
|
||||
|
|
@ -209,7 +211,7 @@ static void wmm_send_action(struct hostapd_data *hapd, const u8 *addr,
|
|||
os_memcpy(t, tspec, sizeof(struct wmm_tspec_element));
|
||||
len = ((u8 *) (t + 1)) - buf;
|
||||
|
||||
if (hostapd_drv_send_mlme(hapd, m, len, 0) < 0)
|
||||
if (hostapd_drv_send_mlme(hapd, m, len, 0, NULL, 0, 0) < 0)
|
||||
wpa_printf(MSG_INFO, "wmm_send_action: send failed");
|
||||
}
|
||||
|
||||
|
|
@ -291,10 +293,11 @@ int wmm_process_tspec(struct wmm_tspec_element *tspec)
|
|||
|
||||
static void wmm_addts_req(struct hostapd_data *hapd,
|
||||
const struct ieee80211_mgmt *mgmt,
|
||||
struct wmm_tspec_element *tspec, size_t len)
|
||||
const struct wmm_tspec_element *tspec, size_t len)
|
||||
{
|
||||
const u8 *end = ((const u8 *) mgmt) + len;
|
||||
int res;
|
||||
struct wmm_tspec_element tspec_resp;
|
||||
|
||||
if ((const u8 *) (tspec + 1) > end) {
|
||||
wpa_printf(MSG_DEBUG, "WMM: TSPEC overflow in ADDTS Request");
|
||||
|
|
@ -306,10 +309,11 @@ static void wmm_addts_req(struct hostapd_data *hapd,
|
|||
mgmt->u.action.u.wmm_action.dialog_token,
|
||||
MAC2STR(mgmt->sa));
|
||||
|
||||
res = wmm_process_tspec(tspec);
|
||||
os_memcpy(&tspec_resp, tspec, sizeof(struct wmm_tspec_element));
|
||||
res = wmm_process_tspec(&tspec_resp);
|
||||
wpa_printf(MSG_DEBUG, "WMM: ADDTS processing result: %d", res);
|
||||
|
||||
wmm_send_action(hapd, mgmt->sa, tspec, WMM_ACTION_CODE_ADDTS_RESP,
|
||||
wmm_send_action(hapd, mgmt->sa, &tspec_resp, WMM_ACTION_CODE_ADDTS_RESP,
|
||||
mgmt->u.action.u.wmm_action.dialog_token, res);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
|
|||
size_t len;
|
||||
size_t gtk_elem_len = 0;
|
||||
size_t igtk_elem_len = 0;
|
||||
size_t bigtk_elem_len = 0;
|
||||
struct wnm_sleep_element wnmsleep_ie;
|
||||
u8 *wnmtfs_ie, *oci_ie;
|
||||
u8 wnmsleep_ie_len, oci_ie_len;
|
||||
|
|
@ -102,6 +103,15 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
|
|||
os_free(wnmtfs_ie);
|
||||
return -1;
|
||||
}
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
if (hapd->conf->oci_freq_override_wnm_sleep) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"TEST: Override OCI frequency %d -> %u MHz",
|
||||
ci.frequency,
|
||||
hapd->conf->oci_freq_override_wnm_sleep);
|
||||
ci.frequency = hapd->conf->oci_freq_override_wnm_sleep;
|
||||
}
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
oci_ie_len = OCV_OCI_EXTENDED_LEN;
|
||||
oci_ie = os_zalloc(oci_ie_len);
|
||||
|
|
@ -122,8 +132,10 @@ 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 +
|
||||
MAX_GTK_SUBELEM_LEN + MAX_IGTK_SUBELEM_LEN +
|
||||
MAX_BIGTK_SUBELEM_LEN +
|
||||
oci_ie_len);
|
||||
if (mgmt == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "MLME: Failed to allocate buffer for "
|
||||
|
|
@ -150,7 +162,6 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
|
|||
pos += gtk_elem_len;
|
||||
wpa_printf(MSG_DEBUG, "Pass 4, gtk_len = %d",
|
||||
(int) gtk_elem_len);
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
res = wpa_wnmsleep_igtk_subelem(sta->wpa_sm, pos);
|
||||
if (res < 0)
|
||||
goto fail;
|
||||
|
|
@ -158,11 +169,21 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
|
|||
pos += igtk_elem_len;
|
||||
wpa_printf(MSG_DEBUG, "Pass 4 igtk_len = %d",
|
||||
(int) igtk_elem_len);
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
if (hapd->conf->beacon_prot &&
|
||||
(hapd->iface->drv_flags &
|
||||
WPA_DRIVER_FLAGS_BEACON_PROTECTION)) {
|
||||
res = wpa_wnmsleep_bigtk_subelem(sta->wpa_sm, pos);
|
||||
if (res < 0)
|
||||
goto fail;
|
||||
bigtk_elem_len = res;
|
||||
pos += bigtk_elem_len;
|
||||
wpa_printf(MSG_DEBUG, "Pass 4 bigtk_len = %d",
|
||||
(int) bigtk_elem_len);
|
||||
}
|
||||
|
||||
WPA_PUT_LE16((u8 *)
|
||||
&mgmt->u.action.u.wnm_sleep_resp.keydata_len,
|
||||
gtk_elem_len + igtk_elem_len);
|
||||
gtk_elem_len + igtk_elem_len + bigtk_elem_len);
|
||||
}
|
||||
os_memcpy(pos, &wnmsleep_ie, wnmsleep_ie_len);
|
||||
/* copy TFS IE here */
|
||||
|
|
@ -178,7 +199,8 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
|
|||
#endif /* CONFIG_OCV */
|
||||
|
||||
len = 1 + sizeof(mgmt->u.action.u.wnm_sleep_resp) + gtk_elem_len +
|
||||
igtk_elem_len + wnmsleep_ie_len + wnmtfs_ie_len + oci_ie_len;
|
||||
igtk_elem_len + bigtk_elem_len +
|
||||
wnmsleep_ie_len + wnmtfs_ie_len + oci_ie_len;
|
||||
|
||||
/* In driver, response frame should be forced to sent when STA is in
|
||||
* PS mode */
|
||||
|
|
@ -191,8 +213,8 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
|
|||
|
||||
/* when entering wnmsleep
|
||||
* 1. pause the node in driver
|
||||
* 2. mark the node so that AP won't update GTK/IGTK during
|
||||
* WNM Sleep
|
||||
* 2. mark the node so that AP won't update GTK/IGTK/BIGTK
|
||||
* during WNM Sleep
|
||||
*/
|
||||
if (wnmsleep_ie.status == WNM_STATUS_SLEEP_ACCEPT &&
|
||||
wnmsleep_ie.action_type == WNM_SLEEP_MODE_ENTER) {
|
||||
|
|
@ -203,7 +225,7 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
|
|||
}
|
||||
/* when exiting wnmsleep
|
||||
* 1. unmark the node
|
||||
* 2. start GTK/IGTK update if MFP is not used
|
||||
* 2. start GTK/IGTK/BIGTK update if MFP is not used
|
||||
* 3. unpause the node in driver
|
||||
*/
|
||||
if ((wnmsleep_ie.status == WNM_STATUS_SLEEP_ACCEPT ||
|
||||
|
|
@ -223,6 +245,7 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
|
|||
|
||||
#undef MAX_GTK_SUBELEM_LEN
|
||||
#undef MAX_IGTK_SUBELEM_LEN
|
||||
#undef MAX_BIGTK_SUBELEM_LEN
|
||||
fail:
|
||||
os_free(wnmtfs_ie);
|
||||
os_free(oci_ie);
|
||||
|
|
@ -305,8 +328,9 @@ static void ieee802_11_rx_wnmsleep_req(struct hostapd_data *hapd,
|
|||
|
||||
if (ocv_verify_tx_params(oci_ie, oci_ie_len, &ci,
|
||||
channel_width_to_int(ci.chanwidth),
|
||||
ci.seg1_idx) != 0) {
|
||||
wpa_msg(hapd, MSG_WARNING, "WNM: %s", ocv_errorstr);
|
||||
ci.seg1_idx) != OCI_SUCCESS) {
|
||||
wpa_msg(hapd, MSG_WARNING, "WNM: OCV failed: %s",
|
||||
ocv_errorstr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -510,6 +534,31 @@ static void ieee802_11_rx_bss_trans_mgmt_resp(struct hostapd_data *hapd,
|
|||
}
|
||||
|
||||
|
||||
static void wnm_beacon_protection_failure(struct hostapd_data *hapd,
|
||||
const u8 *addr)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
|
||||
if (!hapd->conf->beacon_prot ||
|
||||
!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_BEACON_PROTECTION))
|
||||
return;
|
||||
|
||||
sta = ap_get_sta(hapd, addr);
|
||||
if (!sta || !(sta->flags & WLAN_STA_AUTHORIZED)) {
|
||||
wpa_printf(MSG_DEBUG, "Station " MACSTR
|
||||
" not found for received WNM-Notification Request",
|
||||
MAC2STR(addr));
|
||||
return;
|
||||
}
|
||||
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO,
|
||||
"Beacon protection failure reported");
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, WPA_EVENT_UNPROT_BEACON "reporter="
|
||||
MACSTR, MAC2STR(addr));
|
||||
}
|
||||
|
||||
|
||||
static void ieee802_11_rx_wnm_notification_req(struct hostapd_data *hapd,
|
||||
const u8 *addr, const u8 *buf,
|
||||
size_t len)
|
||||
|
|
@ -528,8 +577,14 @@ static void ieee802_11_rx_wnm_notification_req(struct hostapd_data *hapd,
|
|||
MAC2STR(addr), dialog_token, type);
|
||||
wpa_hexdump(MSG_MSGDUMP, "WNM: Notification Request subelements",
|
||||
buf, len);
|
||||
if (type == WLAN_EID_VENDOR_SPECIFIC)
|
||||
switch (type) {
|
||||
case WNM_NOTIF_TYPE_BEACON_PROTECTION_FAILURE:
|
||||
wnm_beacon_protection_failure(hapd, addr);
|
||||
break;
|
||||
case WNM_NOTIF_TYPE_VENDOR_SPECIFIC:
|
||||
mbo_ap_wnm_notification_req(hapd, addr, buf, len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -643,7 +698,7 @@ int wnm_send_disassoc_imminent(struct hostapd_data *hapd,
|
|||
|
||||
wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request frame to indicate imminent disassociation (disassoc_timer=%d) to "
|
||||
MACSTR, disassoc_timer, MAC2STR(sta->addr));
|
||||
if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
|
||||
if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0, NULL, 0, 0) < 0) {
|
||||
wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
|
||||
"Management Request frame");
|
||||
return -1;
|
||||
|
|
@ -716,7 +771,7 @@ int wnm_send_ess_disassoc_imminent(struct hostapd_data *hapd,
|
|||
os_memcpy(pos, url, url_len);
|
||||
pos += url_len;
|
||||
|
||||
if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
|
||||
if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0, NULL, 0, 0) < 0) {
|
||||
wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
|
||||
"Management Request frame");
|
||||
return -1;
|
||||
|
|
@ -792,7 +847,7 @@ int wnm_send_bss_tm_req(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
mbo_len);
|
||||
}
|
||||
|
||||
if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
|
||||
if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0, NULL, 0, 0) < 0) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"Failed to send BSS Transition Management Request frame");
|
||||
os_free(buf);
|
||||
|
|
@ -836,7 +891,7 @@ int wnm_send_coloc_intf_req(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
wpa_printf(MSG_DEBUG, "WNM: Sending Collocated Interference Request to "
|
||||
MACSTR " (dialog_token=%u auto_report=%u timeout=%u)",
|
||||
MAC2STR(sta->addr), dialog_token, auto_report, timeout);
|
||||
if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
|
||||
if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0, NULL, 0, 0) < 0) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"WNM: Failed to send Collocated Interference Request frame");
|
||||
return -1;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue