mirror of
https://github.com/vanhoefm/fragattacks.git
synced 2024-11-28 18:28:23 -05:00
pull in new hostap code
This commit is contained in:
commit
f988e85c95
31
.gitignore
vendored
31
.gitignore
vendored
@ -1,35 +1,8 @@
|
|||||||
*.a
|
|
||||||
*.o
|
|
||||||
*.d
|
|
||||||
*.gcno
|
|
||||||
*.gcda
|
|
||||||
*.gcov
|
|
||||||
*.pyc
|
*.pyc
|
||||||
*~
|
*~
|
||||||
.config
|
|
||||||
tests/hwsim/logs
|
tests/hwsim/logs
|
||||||
tests/remote/logs
|
tests/remote/logs
|
||||||
wpaspy/build
|
wpaspy/build
|
||||||
wpa_supplicant/eapol_test
|
|
||||||
wpa_supplicant/nfc_pw_token
|
|
||||||
wpa_supplicant/preauth_test
|
|
||||||
wpa_supplicant/wpa_cli
|
|
||||||
wpa_supplicant/wpa_passphrase
|
|
||||||
wpa_supplicant/wpa_supplicant
|
|
||||||
wpa_supplicant/wpa_priv
|
|
||||||
wpa_supplicant/wpa_gui/Makefile
|
|
||||||
wpa_supplicant/wpa_gui/wpa_gui
|
|
||||||
wpa_supplicant/wpa_gui-qt4/Makefile
|
|
||||||
wpa_supplicant/wpa_gui-qt4/wpa_gui
|
|
||||||
wpa_supplicant/libwpa_test1
|
|
||||||
wpa_supplicant/libwpa_test2
|
|
||||||
hostapd/hostapd
|
|
||||||
hostapd/hostapd_cli
|
|
||||||
hostapd/hlr_auc_gw
|
|
||||||
hostapd/nt_password_hash
|
|
||||||
mac80211_hwsim/tools/hwsim_test
|
|
||||||
wlantest/libwlantest.a
|
|
||||||
wlantest/test_vectors
|
|
||||||
wlantest/wlantest
|
|
||||||
wlantest/wlantest_cli
|
|
||||||
**/parallel-vm.log
|
**/parallel-vm.log
|
||||||
|
tags
|
||||||
|
build/
|
||||||
|
@ -322,6 +322,24 @@ fi.w1.wpa_supplicant1.CreateInterface.
|
|||||||
</dl>
|
</dl>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<h3>Roam ( s : addr ) --> nothing</h3>
|
||||||
|
<p>Initiate a roam to another BSS within the current ESS.</p>
|
||||||
|
<h4>Possible errors</h4>
|
||||||
|
<dl>
|
||||||
|
<dt>fi.w1.wpa_supplicant1.InvalidArgs</dt>
|
||||||
|
<dd>Missing address argument.</dd>
|
||||||
|
<dt>fi.w1.wpa_supplicant1.InvalidArgs</dt>
|
||||||
|
<dd>Invalid hardware address format.</dd>
|
||||||
|
<dt>fi.w1.wpa_supplicant1.InvalidArgs</dt>
|
||||||
|
<dd>Target BSS not found.</dd>
|
||||||
|
<dt>fi.w1.wpa_supplicant1.NotConnected</dt>
|
||||||
|
<dd>Interface is not connected to any network.</dd>
|
||||||
|
<dt>fi.w1.wpa_supplicant1.UnknownError</dt>
|
||||||
|
<dd>Scan processing was not included in the build.</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<h3>AddBlob ( s : name, ay : data ) --> nothing</h3>
|
<h3>AddBlob ( s : name, ay : data ) --> nothing</h3>
|
||||||
<p>Adds a blob to the interface.</p>
|
<p>Adds a blob to the interface.</p>
|
||||||
@ -651,7 +669,7 @@ fi.w1.wpa_supplicant1.CreateInterface.
|
|||||||
<tr><td>Pairwise</td><td>as</td><td>Possible array elements: "ccmp-256", "gcmp-256", "ccmp", "gcmp", "tkip", "none"</td>
|
<tr><td>Pairwise</td><td>as</td><td>Possible array elements: "ccmp-256", "gcmp-256", "ccmp", "gcmp", "tkip", "none"</td>
|
||||||
<tr><td>Group</td><td>as</td><td>Possible array elements: "ccmp-256", "gcmp-256", "ccmp", "gcmp", "tkip", "wep104", "wep40"</td>
|
<tr><td>Group</td><td>as</td><td>Possible array elements: "ccmp-256", "gcmp-256", "ccmp", "gcmp", "tkip", "wep104", "wep40"</td>
|
||||||
<tr><td>GroupMgmt</td><td>as</td><td>Possible array elements: "aes-128-cmac", "bip-gmac-128", "bip-gmac-256", "bip-cmac-256"</td>
|
<tr><td>GroupMgmt</td><td>as</td><td>Possible array elements: "aes-128-cmac", "bip-gmac-128", "bip-gmac-256", "bip-cmac-256"</td>
|
||||||
<tr><td>KeyMgmt</td><td>as</td><td>Possible array elements: "wpa-psk", "wpa-ft-psk", "wpa-psk-sha256", "wpa-eap", "wpa-ft-eap", "wpa-eap-sha256", "ieee8021x", "wpa-none", "wps", "none"</td>
|
<tr><td>KeyMgmt</td><td>as</td><td>Possible array elements: "wpa-psk", "wpa-ft-psk", "wpa-psk-sha256", "wpa-eap", "wpa-ft-eap", "wpa-eap-sha256", "sae", "ieee8021x", "wpa-none", "wps", "none"</td>
|
||||||
<tr><td>Protocol</td><td>as</td><td>Possible array elements: "rsn", "wpa"</td>
|
<tr><td>Protocol</td><td>as</td><td>Possible array elements: "rsn", "wpa"</td>
|
||||||
<tr><td>AuthAlg</td><td>as</td><td>Possible array elements: "open", "shared", "leap"</td>
|
<tr><td>AuthAlg</td><td>as</td><td>Possible array elements: "open", "shared", "leap"</td>
|
||||||
<tr><td>Scan</td><td>as</td><td>Possible array elements: "active", "passive", "ssid"</td>
|
<tr><td>Scan</td><td>as</td><td>Possible array elements: "active", "passive", "ssid"</td>
|
||||||
@ -891,7 +909,7 @@ fi.w1.wpa_supplicant1.CreateInterface.
|
|||||||
|
|
||||||
<li>
|
<li>
|
||||||
<h3>Hessid - s - (read/write)</h3>
|
<h3>Hessid - s - (read/write)</h3>
|
||||||
<p>Homogenous ESS identifier</p>
|
<p>Homogeneous ESS identifier</p>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
@ -2037,7 +2055,7 @@ scan results.
|
|||||||
<tr><td>KeyMgmt</td><td>as</td><td>Key management suite. Possible array elements: "wpa-psk", "wpa-ft-psk", "wpa-psk-sha256", "wpa-eap", "wpa-ft-eap", "wpa-eap-sha256", "wpa-eap-suite-b", "wpa-eap-suite-b-192", "wpa-fils-sha256", "wpa-fils-sha384", "wpa-ft-fils-sha256", "wpa-ft-fils-sha384", "sae", "ft-sae", "wpa-none"</td>
|
<tr><td>KeyMgmt</td><td>as</td><td>Key management suite. Possible array elements: "wpa-psk", "wpa-ft-psk", "wpa-psk-sha256", "wpa-eap", "wpa-ft-eap", "wpa-eap-sha256", "wpa-eap-suite-b", "wpa-eap-suite-b-192", "wpa-fils-sha256", "wpa-fils-sha384", "wpa-ft-fils-sha256", "wpa-ft-fils-sha384", "sae", "ft-sae", "wpa-none"</td>
|
||||||
<tr><td>Pairwise</td><td>as</td><td>Pairwise cipher suites. Possible array elements: "ccmp", "tkip"</td>
|
<tr><td>Pairwise</td><td>as</td><td>Pairwise cipher suites. Possible array elements: "ccmp", "tkip"</td>
|
||||||
<tr><td>Group</td><td>s</td><td>Group cipher suite. Possible values are: "ccmp", "tkip", "wep104", "wep40"</td>
|
<tr><td>Group</td><td>s</td><td>Group cipher suite. Possible values are: "ccmp", "tkip", "wep104", "wep40"</td>
|
||||||
<tr><td>MgmtGroup</td><td>s</td><td>Mangement frames cipher suite. Possible values are: "aes128cmac"</td>
|
<tr><td>MgmtGroup</td><td>s</td><td>Management frames cipher suite. Possible values are: "aes128cmac"</td>
|
||||||
</table>
|
</table>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
@ -278,7 +278,7 @@ TYPEDEF_HIDES_STRUCT = NO
|
|||||||
# For small to medium size projects (<1000 input files) the default value is
|
# For small to medium size projects (<1000 input files) the default value is
|
||||||
# probably good enough. For larger projects a too small cache size can cause
|
# probably good enough. For larger projects a too small cache size can cause
|
||||||
# doxygen to be busy swapping symbols to and from disk most of the time
|
# doxygen to be busy swapping symbols to and from disk most of the time
|
||||||
# causing a significant performance penality.
|
# causing a significant performance penalty.
|
||||||
# If the system has enough physical memory increasing the cache will improve the
|
# If the system has enough physical memory increasing the cache will improve the
|
||||||
# performance by keeping more symbols in memory. Note that the value works on
|
# performance by keeping more symbols in memory. Note that the value works on
|
||||||
# a logarithmic scale so increasing the size by one will roughly double the
|
# a logarithmic scale so increasing the size by one will roughly double the
|
||||||
|
@ -156,7 +156,7 @@ ap_scan=1:
|
|||||||
- wpa_supplicant requests scan with SIOCSIWSCAN
|
- wpa_supplicant requests scan with SIOCSIWSCAN
|
||||||
- driver reports scan complete with wireless event SIOCGIWSCAN
|
- driver reports scan complete with wireless event SIOCGIWSCAN
|
||||||
- wpa_supplicant reads scan results with SIOCGIWSCAN (multiple call if
|
- wpa_supplicant reads scan results with SIOCGIWSCAN (multiple call if
|
||||||
a larget buffer is needed)
|
a larger buffer is needed)
|
||||||
- wpa_supplicant decides which AP to use based on scan results
|
- wpa_supplicant decides which AP to use based on scan results
|
||||||
- wpa_supplicant configures driver to associate with the selected BSS
|
- wpa_supplicant configures driver to associate with the selected BSS
|
||||||
(SIOCSIWMODE, SIOCSIWGENIE, SIOCSIWAUTH, SIOCSIWFREQ,
|
(SIOCSIWMODE, SIOCSIWGENIE, SIOCSIWAUTH, SIOCSIWFREQ,
|
||||||
|
@ -283,7 +283,7 @@ service discovery. The user of the P2P module is responsible for
|
|||||||
providing P2P specific Service Request TLV(s) for queries and Service
|
providing P2P specific Service Request TLV(s) for queries and Service
|
||||||
Response TLV(s) for responses.
|
Response TLV(s) for responses.
|
||||||
|
|
||||||
\subsection p2p_sd_query Quering services of peers
|
\subsection p2p_sd_query Querying services of peers
|
||||||
|
|
||||||
Service discovery is implemented by processing pending queries as a
|
Service discovery is implemented by processing pending queries as a
|
||||||
part of the device discovery phase. \ref p2p_sd_request() function is used
|
part of the device discovery phase. \ref p2p_sd_request() function is used
|
||||||
|
@ -1,28 +1,15 @@
|
|||||||
ALL=eap_example
|
ALL=eap_example
|
||||||
|
|
||||||
all: $(ALL)
|
include ../src/build.rules
|
||||||
|
|
||||||
ifndef CC
|
|
||||||
CC=gcc
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifndef RANLIB
|
|
||||||
RANLIB=ranlib
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifndef CFLAGS
|
|
||||||
CFLAGS = -MMD -O2 -Wall -g
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
CFLAGS += -I.
|
CFLAGS += -I.
|
||||||
CFLAGS += -I../src
|
CFLAGS += -I../src
|
||||||
CFLAGS += -I../src/utils
|
CFLAGS += -I../src/utils
|
||||||
|
|
||||||
|
|
||||||
OBJS_both += ../src/utils/libutils.a
|
EAP_LIBS += ../src/utils/libutils.a
|
||||||
OBJS_both += ../src/crypto/libcrypto.a
|
EAP_LIBS += ../src/crypto/libcrypto.a
|
||||||
OBJS_both += ../src/tls/libtls.a
|
EAP_LIBS += ../src/tls/libtls.a
|
||||||
|
|
||||||
OBJS_both += ../src/eap_common/eap_peap_common.o
|
OBJS_both += ../src/eap_common/eap_peap_common.o
|
||||||
OBJS_both += ../src/eap_common/eap_psk_common.o
|
OBJS_both += ../src/eap_common/eap_psk_common.o
|
||||||
@ -95,41 +82,22 @@ OBJS_server += ../src/eap_server/eap_server_tls_common.o
|
|||||||
CFLAGS += -DEAP_SERVER
|
CFLAGS += -DEAP_SERVER
|
||||||
|
|
||||||
|
|
||||||
ifndef LDO
|
|
||||||
LDO=$(CC)
|
|
||||||
endif
|
|
||||||
|
|
||||||
Q=@
|
|
||||||
E=echo
|
|
||||||
ifeq ($(V), 1)
|
|
||||||
Q=
|
|
||||||
E=true
|
|
||||||
endif
|
|
||||||
|
|
||||||
%.o: %.c
|
|
||||||
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
|
|
||||||
@$(E) " CC " $<
|
|
||||||
|
|
||||||
|
|
||||||
OBJS_lib=$(OBJS_both) $(OBJS_peer) $(OBJS_server)
|
OBJS_lib=$(OBJS_both) $(OBJS_peer) $(OBJS_server)
|
||||||
|
_OBJS_VAR := OBJS_lib
|
||||||
|
include ../src/objs.mk
|
||||||
|
|
||||||
OBJS_ex = eap_example.o eap_example_peer.o eap_example_server.o
|
OBJS_ex = eap_example.o eap_example_peer.o eap_example_server.o
|
||||||
|
_OBJS_VAR := OBJS_ex
|
||||||
|
include ../src/objs.mk
|
||||||
|
|
||||||
|
_OBJS_VAR := EAP_LIBS
|
||||||
../src/utils/libutils.a:
|
include ../src/objs.mk
|
||||||
$(MAKE) -C ../src/utils
|
|
||||||
|
|
||||||
../src/crypto/libcrypto.a:
|
|
||||||
$(MAKE) -C ../src/crypto
|
|
||||||
|
|
||||||
../src/tls/libtls.a:
|
|
||||||
$(MAKE) -C ../src/tls
|
|
||||||
|
|
||||||
|
|
||||||
ifneq ($(CONFIG_SOLIB), yes)
|
ifneq ($(CONFIG_SOLIB), yes)
|
||||||
LIBEAP = libeap.a
|
LIBEAP = libeap.a
|
||||||
libeap.a: $(OBJS_lib)
|
libeap.a: $(EAP_LIBS) $(OBJS_lib)
|
||||||
$(AR) crT libeap.a $(OBJS_lib)
|
$(AR) crT libeap.a $^
|
||||||
$(RANLIB) libeap.a
|
$(RANLIB) libeap.a
|
||||||
|
|
||||||
else
|
else
|
||||||
@ -137,16 +105,15 @@ CFLAGS += -fPIC -DPIC
|
|||||||
LDFLAGS += -shared
|
LDFLAGS += -shared
|
||||||
|
|
||||||
LIBEAP = libeap.so
|
LIBEAP = libeap.so
|
||||||
libeap.so: $(OBJS_lib)
|
libeap.so: $(EAP_LIBS) $(OBJS_lib)
|
||||||
$(LDO) $(LDFLAGS) $(OBJS_lib) -o $(LIBEAP)
|
$(LDO) $(LDFLAGS) $^ -o $(LIBEAP)
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
eap_example: $(OBJS_ex) $(LIBEAP)
|
eap_example: $(OBJS_ex) $(LIBEAP)
|
||||||
$(LDO) $(LDFLAGS) -o eap_example $(OBJS_ex) -L. -leap $(LIBS)
|
$(LDO) $(LDFLAGS) -o eap_example $(OBJS_ex) -L. -leap $(LIBS)
|
||||||
|
|
||||||
clean:
|
clean: common-clean
|
||||||
$(MAKE) -C ../src clean
|
rm -f core *~ *.o *.d libeap.a libeap.so
|
||||||
rm -f core *~ *.o *.d libeap.a libeap.so $(ALL)
|
|
||||||
|
|
||||||
-include $(OBJS:%.o=%.d)
|
-include $(OBJS:%.o=%.d)
|
||||||
|
@ -18,16 +18,16 @@ void eap_example_server_rx(const u8 *data, size_t data_len);
|
|||||||
|
|
||||||
|
|
||||||
struct eap_peer_ctx {
|
struct eap_peer_ctx {
|
||||||
Boolean eapSuccess;
|
bool eapSuccess;
|
||||||
Boolean eapRestart;
|
bool eapRestart;
|
||||||
Boolean eapFail;
|
bool eapFail;
|
||||||
Boolean eapResp;
|
bool eapResp;
|
||||||
Boolean eapNoResp;
|
bool eapNoResp;
|
||||||
Boolean eapReq;
|
bool eapReq;
|
||||||
Boolean portEnabled;
|
bool portEnabled;
|
||||||
Boolean altAccept; /* for EAP */
|
bool altAccept; /* for EAP */
|
||||||
Boolean altReject; /* for EAP */
|
bool altReject; /* for EAP */
|
||||||
Boolean eapTriggerStart;
|
bool eapTriggerStart;
|
||||||
|
|
||||||
struct wpabuf *eapReqData; /* for EAP */
|
struct wpabuf *eapReqData; /* for EAP */
|
||||||
|
|
||||||
@ -48,11 +48,11 @@ static struct eap_peer_config * peer_get_config(void *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static Boolean peer_get_bool(void *ctx, enum eapol_bool_var variable)
|
static bool peer_get_bool(void *ctx, enum eapol_bool_var variable)
|
||||||
{
|
{
|
||||||
struct eap_peer_ctx *peer = ctx;
|
struct eap_peer_ctx *peer = ctx;
|
||||||
if (peer == NULL)
|
if (peer == NULL)
|
||||||
return FALSE;
|
return false;
|
||||||
switch (variable) {
|
switch (variable) {
|
||||||
case EAPOL_eapSuccess:
|
case EAPOL_eapSuccess:
|
||||||
return peer->eapSuccess;
|
return peer->eapSuccess;
|
||||||
@ -75,12 +75,11 @@ static Boolean peer_get_bool(void *ctx, enum eapol_bool_var variable)
|
|||||||
case EAPOL_eapTriggerStart:
|
case EAPOL_eapTriggerStart:
|
||||||
return peer->eapTriggerStart;
|
return peer->eapTriggerStart;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void peer_set_bool(void *ctx, enum eapol_bool_var variable,
|
static void peer_set_bool(void *ctx, enum eapol_bool_var variable, bool value)
|
||||||
Boolean value)
|
|
||||||
{
|
{
|
||||||
struct eap_peer_ctx *peer = ctx;
|
struct eap_peer_ctx *peer = ctx;
|
||||||
if (peer == NULL)
|
if (peer == NULL)
|
||||||
@ -319,7 +318,7 @@ int eap_example_peer_init(void)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Enable "port" to allow authentication */
|
/* Enable "port" to allow authentication */
|
||||||
eap_ctx.portEnabled = TRUE;
|
eap_ctx.portEnabled = true;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -344,7 +343,7 @@ int eap_example_peer_step(void)
|
|||||||
if (eap_ctx.eapResp) {
|
if (eap_ctx.eapResp) {
|
||||||
struct wpabuf *resp;
|
struct wpabuf *resp;
|
||||||
printf("==> Response\n");
|
printf("==> Response\n");
|
||||||
eap_ctx.eapResp = FALSE;
|
eap_ctx.eapResp = false;
|
||||||
resp = eap_get_eapRespData(eap_ctx.eap);
|
resp = eap_get_eapRespData(eap_ctx.eap);
|
||||||
if (resp) {
|
if (resp) {
|
||||||
/* Send EAP response to the server */
|
/* Send EAP response to the server */
|
||||||
@ -372,7 +371,7 @@ int eap_example_peer_step(void)
|
|||||||
void eap_example_peer_rx(const u8 *data, size_t data_len)
|
void eap_example_peer_rx(const u8 *data, size_t data_len)
|
||||||
{
|
{
|
||||||
/* Make received EAP message available to the EAP library */
|
/* Make received EAP message available to the EAP library */
|
||||||
eap_ctx.eapReq = TRUE;
|
eap_ctx.eapReq = true;
|
||||||
wpabuf_free(eap_ctx.eapReqData);
|
wpabuf_free(eap_ctx.eapReqData);
|
||||||
eap_ctx.eapReqData = wpabuf_alloc_copy(data, data_len);
|
eap_ctx.eapReqData = wpabuf_alloc_copy(data, data_len);
|
||||||
}
|
}
|
||||||
|
@ -234,8 +234,8 @@ int eap_example_server_init(void)
|
|||||||
eap_ctx.eap_if = eap_get_interface(eap_ctx.eap);
|
eap_ctx.eap_if = eap_get_interface(eap_ctx.eap);
|
||||||
|
|
||||||
/* Enable "port" and request EAP to start authentication. */
|
/* Enable "port" and request EAP to start authentication. */
|
||||||
eap_ctx.eap_if->portEnabled = TRUE;
|
eap_ctx.eap_if->portEnabled = true;
|
||||||
eap_ctx.eap_if->eapRestart = TRUE;
|
eap_ctx.eap_if->eapRestart = true;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -296,5 +296,5 @@ void eap_example_server_rx(const u8 *data, size_t data_len)
|
|||||||
wpabuf_free(eap_ctx.eap_if->eapRespData);
|
wpabuf_free(eap_ctx.eap_if->eapRespData);
|
||||||
eap_ctx.eap_if->eapRespData = wpabuf_alloc_copy(data, data_len);
|
eap_ctx.eap_if->eapRespData = wpabuf_alloc_copy(data, data_len);
|
||||||
if (eap_ctx.eap_if->eapRespData)
|
if (eap_ctx.eap_if->eapRespData)
|
||||||
eap_ctx.eap_if->eapResp = TRUE;
|
eap_ctx.eap_if->eapResp = true;
|
||||||
}
|
}
|
||||||
|
5
hostapd/.gitignore
vendored
Normal file
5
hostapd/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
.config
|
||||||
|
hostapd
|
||||||
|
hostapd_cli
|
||||||
|
hlr_auc_gw
|
||||||
|
nt_password_hash
|
@ -250,8 +250,13 @@ endif
|
|||||||
ifdef CONFIG_SAE
|
ifdef CONFIG_SAE
|
||||||
L_CFLAGS += -DCONFIG_SAE
|
L_CFLAGS += -DCONFIG_SAE
|
||||||
OBJS += src/common/sae.c
|
OBJS += src/common/sae.c
|
||||||
|
ifdef CONFIG_SAE_PK
|
||||||
|
L_CFLAGS += -DCONFIG_SAE_PK
|
||||||
|
OBJS += src/common/sae_pk.c
|
||||||
|
endif
|
||||||
NEED_ECC=y
|
NEED_ECC=y
|
||||||
NEED_DH_GROUPS=y
|
NEED_DH_GROUPS=y
|
||||||
|
NEED_HMAC_SHA256_KDF=y
|
||||||
NEED_DRAGONFLY=y
|
NEED_DRAGONFLY=y
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -281,10 +286,6 @@ L_CFLAGS += -DCONFIG_WNM -DCONFIG_WNM_AP
|
|||||||
OBJS += src/ap/wnm_ap.c
|
OBJS += src/ap/wnm_ap.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_IEEE80211N
|
|
||||||
L_CFLAGS += -DCONFIG_IEEE80211N
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifdef CONFIG_IEEE80211AC
|
ifdef CONFIG_IEEE80211AC
|
||||||
L_CFLAGS += -DCONFIG_IEEE80211AC
|
L_CFLAGS += -DCONFIG_IEEE80211AC
|
||||||
endif
|
endif
|
||||||
@ -313,6 +314,14 @@ OBJS += src/fst/fst_ctrl_iface.c
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifdef CONFIG_WEP
|
||||||
|
L_CFLAGS += -DCONFIG_WEP
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifdef CONFIG_NO_TKIP
|
||||||
|
L_CFLAGS += -DCONFIG_NO_TKIP
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
include $(LOCAL_PATH)/src/drivers/drivers.mk
|
include $(LOCAL_PATH)/src/drivers/drivers.mk
|
||||||
|
|
||||||
@ -405,7 +414,7 @@ endif
|
|||||||
ifdef CONFIG_EAP_SIM_COMMON
|
ifdef CONFIG_EAP_SIM_COMMON
|
||||||
OBJS += src/eap_common/eap_sim_common.c
|
OBJS += src/eap_common/eap_sim_common.c
|
||||||
# Example EAP-SIM/AKA interface for GSM/UMTS authentication. This can be
|
# Example EAP-SIM/AKA interface for GSM/UMTS authentication. This can be
|
||||||
# replaced with another file implementating the interface specified in
|
# replaced with another file implementing the interface specified in
|
||||||
# eap_sim_db.h.
|
# eap_sim_db.h.
|
||||||
OBJS += src/eap_server/eap_sim_db.c
|
OBJS += src/eap_server/eap_sim_db.c
|
||||||
NEED_FIPS186_2_PRF=y
|
NEED_FIPS186_2_PRF=y
|
||||||
@ -532,6 +541,12 @@ endif
|
|||||||
ifdef CONFIG_DPP
|
ifdef CONFIG_DPP
|
||||||
L_CFLAGS += -DCONFIG_DPP
|
L_CFLAGS += -DCONFIG_DPP
|
||||||
OBJS += src/common/dpp.c
|
OBJS += src/common/dpp.c
|
||||||
|
OBJS += src/common/dpp_auth.c
|
||||||
|
OBJS += src/common/dpp_backup.c
|
||||||
|
OBJS += src/common/dpp_crypto.c
|
||||||
|
OBJS += src/common/dpp_pkex.c
|
||||||
|
OBJS += src/common/dpp_reconfig.c
|
||||||
|
OBJS += src/common/dpp_tcp.c
|
||||||
OBJS += src/ap/dpp_hostapd.c
|
OBJS += src/ap/dpp_hostapd.c
|
||||||
OBJS += src/ap/gas_query_ap.c
|
OBJS += src/ap/gas_query_ap.c
|
||||||
NEED_AES_SIV=y
|
NEED_AES_SIV=y
|
||||||
@ -999,9 +1014,7 @@ OBJS += src/ap/hw_features.c
|
|||||||
OBJS += src/ap/dfs.c
|
OBJS += src/ap/dfs.c
|
||||||
L_CFLAGS += -DNEED_AP_MLME
|
L_CFLAGS += -DNEED_AP_MLME
|
||||||
endif
|
endif
|
||||||
ifdef CONFIG_IEEE80211N
|
|
||||||
OBJS += src/ap/ieee802_11_ht.c
|
OBJS += src/ap/ieee802_11_ht.c
|
||||||
endif
|
|
||||||
|
|
||||||
ifdef CONFIG_IEEE80211AC
|
ifdef CONFIG_IEEE80211AC
|
||||||
OBJS += src/ap/ieee802_11_vht.c
|
OBJS += src/ap/ieee802_11_vht.c
|
||||||
|
@ -362,7 +362,7 @@ ChangeLog for hostapd
|
|||||||
* RADIUS server functionality
|
* RADIUS server functionality
|
||||||
- add minimal RADIUS accounting server support (hostapd-as-server);
|
- add minimal RADIUS accounting server support (hostapd-as-server);
|
||||||
this is mainly to enable testing coverage with hwsim scripts
|
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
|
- added option for TLS protocol testing of an EAP peer by simulating
|
||||||
various misbehaviors/known attacks
|
various misbehaviors/known attacks
|
||||||
- MAC ACL support for testing purposes
|
- MAC ACL support for testing purposes
|
||||||
@ -668,7 +668,7 @@ ChangeLog for hostapd
|
|||||||
* fixed HT Capabilities IE with nl80211 drivers
|
* fixed HT Capabilities IE with nl80211 drivers
|
||||||
* moved generic AP functionality code into src/ap
|
* moved generic AP functionality code into src/ap
|
||||||
* WPS: handle Selected Registrar as union of info from all Registrars
|
* 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
|
* added internal debugging mechanism with backtrace support and memory
|
||||||
allocation/freeing validation, etc. tests (CONFIG_WPA_TRACE=y)
|
allocation/freeing validation, etc. tests (CONFIG_WPA_TRACE=y)
|
||||||
* EAP-FAST server: piggyback Phase 2 start with the end of Phase 1
|
* EAP-FAST server: piggyback Phase 2 start with the end of Phase 1
|
||||||
|
131
hostapd/Makefile
131
hostapd/Makefile
@ -1,10 +1,7 @@
|
|||||||
ifndef CC
|
ALL=hostapd hostapd_cli
|
||||||
CC=gcc
|
CONFIG_FILE = .config
|
||||||
endif
|
|
||||||
|
|
||||||
ifndef CFLAGS
|
include ../src/build.rules
|
||||||
CFLAGS = -MMD -O2 -Wall -g
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifdef LIBS
|
ifdef LIBS
|
||||||
# If LIBS is set with some global build system defaults, clone those for
|
# If LIBS is set with some global build system defaults, clone those for
|
||||||
@ -19,6 +16,9 @@ endif
|
|||||||
ifndef LIBS_n
|
ifndef LIBS_n
|
||||||
LIBS_n := $(LIBS)
|
LIBS_n := $(LIBS)
|
||||||
endif
|
endif
|
||||||
|
ifndef LIBS_s
|
||||||
|
LIBS_s := $(LIBS)
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CFLAGS += $(EXTRA_CFLAGS)
|
CFLAGS += $(EXTRA_CFLAGS)
|
||||||
@ -27,8 +27,6 @@ CFLAGS += -I$(abspath ../src/utils)
|
|||||||
|
|
||||||
export BINDIR ?= /usr/local/bin/
|
export BINDIR ?= /usr/local/bin/
|
||||||
|
|
||||||
-include .config
|
|
||||||
|
|
||||||
ifndef CONFIG_NO_GITVER
|
ifndef CONFIG_NO_GITVER
|
||||||
# Add VERSION_STR postfix for builds from a git repository
|
# Add VERSION_STR postfix for builds from a git repository
|
||||||
ifeq ($(wildcard ../.git),../.git)
|
ifeq ($(wildcard ../.git),../.git)
|
||||||
@ -122,6 +120,7 @@ LIBS += -lbfd -ldl -liberty -lz
|
|||||||
LIBS_c += -lbfd -ldl -liberty -lz
|
LIBS_c += -lbfd -ldl -liberty -lz
|
||||||
LIBS_h += -lbfd -ldl -liberty -lz
|
LIBS_h += -lbfd -ldl -liberty -lz
|
||||||
LIBS_n += -lbfd -ldl -liberty -lz
|
LIBS_n += -lbfd -ldl -liberty -lz
|
||||||
|
LIBS_s += -lbfd -ldl -liberty -lz
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -294,8 +293,13 @@ endif
|
|||||||
ifdef CONFIG_SAE
|
ifdef CONFIG_SAE
|
||||||
CFLAGS += -DCONFIG_SAE
|
CFLAGS += -DCONFIG_SAE
|
||||||
OBJS += ../src/common/sae.o
|
OBJS += ../src/common/sae.o
|
||||||
|
ifdef CONFIG_SAE_PK
|
||||||
|
CFLAGS += -DCONFIG_SAE_PK
|
||||||
|
OBJS += ../src/common/sae_pk.o
|
||||||
|
endif
|
||||||
NEED_ECC=y
|
NEED_ECC=y
|
||||||
NEED_DH_GROUPS=y
|
NEED_DH_GROUPS=y
|
||||||
|
NEED_HMAC_SHA256_KDF=y
|
||||||
NEED_AP_MLME=y
|
NEED_AP_MLME=y
|
||||||
NEED_DRAGONFLY=y
|
NEED_DRAGONFLY=y
|
||||||
endif
|
endif
|
||||||
@ -331,10 +335,6 @@ CFLAGS += -DCONFIG_WNM -DCONFIG_WNM_AP
|
|||||||
OBJS += ../src/ap/wnm_ap.o
|
OBJS += ../src/ap/wnm_ap.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_IEEE80211N
|
|
||||||
CFLAGS += -DCONFIG_IEEE80211N
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifdef CONFIG_IEEE80211AC
|
ifdef CONFIG_IEEE80211AC
|
||||||
CFLAGS += -DCONFIG_IEEE80211AC
|
CFLAGS += -DCONFIG_IEEE80211AC
|
||||||
endif
|
endif
|
||||||
@ -444,7 +444,7 @@ endif
|
|||||||
ifdef CONFIG_EAP_SIM_COMMON
|
ifdef CONFIG_EAP_SIM_COMMON
|
||||||
OBJS += ../src/eap_common/eap_sim_common.o
|
OBJS += ../src/eap_common/eap_sim_common.o
|
||||||
# Example EAP-SIM/AKA interface for GSM/UMTS authentication. This can be
|
# Example EAP-SIM/AKA interface for GSM/UMTS authentication. This can be
|
||||||
# replaced with another file implementating the interface specified in
|
# replaced with another file implementing the interface specified in
|
||||||
# eap_sim_db.h.
|
# eap_sim_db.h.
|
||||||
OBJS += ../src/eap_server/eap_sim_db.o
|
OBJS += ../src/eap_server/eap_sim_db.o
|
||||||
NEED_FIPS186_2_PRF=y
|
NEED_FIPS186_2_PRF=y
|
||||||
@ -571,6 +571,12 @@ endif
|
|||||||
ifdef CONFIG_DPP
|
ifdef CONFIG_DPP
|
||||||
CFLAGS += -DCONFIG_DPP
|
CFLAGS += -DCONFIG_DPP
|
||||||
OBJS += ../src/common/dpp.o
|
OBJS += ../src/common/dpp.o
|
||||||
|
OBJS += ../src/common/dpp_auth.o
|
||||||
|
OBJS += ../src/common/dpp_backup.o
|
||||||
|
OBJS += ../src/common/dpp_crypto.o
|
||||||
|
OBJS += ../src/common/dpp_pkex.o
|
||||||
|
OBJS += ../src/common/dpp_reconfig.o
|
||||||
|
OBJS += ../src/common/dpp_tcp.o
|
||||||
OBJS += ../src/ap/dpp_hostapd.o
|
OBJS += ../src/ap/dpp_hostapd.o
|
||||||
OBJS += ../src/ap/gas_query_ap.o
|
OBJS += ../src/ap/gas_query_ap.o
|
||||||
NEED_AES_SIV=y
|
NEED_AES_SIV=y
|
||||||
@ -697,6 +703,7 @@ LIBS += -lssl
|
|||||||
endif
|
endif
|
||||||
OBJS += ../src/crypto/crypto_openssl.o
|
OBJS += ../src/crypto/crypto_openssl.o
|
||||||
HOBJS += ../src/crypto/crypto_openssl.o
|
HOBJS += ../src/crypto/crypto_openssl.o
|
||||||
|
SOBJS += ../src/crypto/crypto_openssl.o
|
||||||
ifdef NEED_FIPS186_2_PRF
|
ifdef NEED_FIPS186_2_PRF
|
||||||
OBJS += ../src/crypto/fips_prf_openssl.o
|
OBJS += ../src/crypto/fips_prf_openssl.o
|
||||||
endif
|
endif
|
||||||
@ -704,9 +711,11 @@ NEED_TLS_PRF_SHA256=y
|
|||||||
LIBS += -lcrypto
|
LIBS += -lcrypto
|
||||||
LIBS_h += -lcrypto
|
LIBS_h += -lcrypto
|
||||||
LIBS_n += -lcrypto
|
LIBS_n += -lcrypto
|
||||||
|
LIBS_s += -lcrypto
|
||||||
ifdef CONFIG_TLS_ADD_DL
|
ifdef CONFIG_TLS_ADD_DL
|
||||||
LIBS += -ldl
|
LIBS += -ldl
|
||||||
LIBS_h += -ldl
|
LIBS_h += -ldl
|
||||||
|
LIBS_s += -ldl
|
||||||
endif
|
endif
|
||||||
ifndef CONFIG_TLS_DEFAULT_CIPHERS
|
ifndef CONFIG_TLS_DEFAULT_CIPHERS
|
||||||
CONFIG_TLS_DEFAULT_CIPHERS = "DEFAULT:!EXP:!LOW"
|
CONFIG_TLS_DEFAULT_CIPHERS = "DEFAULT:!EXP:!LOW"
|
||||||
@ -1155,9 +1164,7 @@ OBJS += ../src/ap/hw_features.o
|
|||||||
OBJS += ../src/ap/dfs.o
|
OBJS += ../src/ap/dfs.o
|
||||||
CFLAGS += -DNEED_AP_MLME
|
CFLAGS += -DNEED_AP_MLME
|
||||||
endif
|
endif
|
||||||
ifdef CONFIG_IEEE80211N
|
|
||||||
OBJS += ../src/ap/ieee802_11_ht.o
|
OBJS += ../src/ap/ieee802_11_ht.o
|
||||||
endif
|
|
||||||
|
|
||||||
ifdef CONFIG_IEEE80211AC
|
ifdef CONFIG_IEEE80211AC
|
||||||
OBJS += ../src/ap/ieee802_11_vht.o
|
OBJS += ../src/ap/ieee802_11_vht.o
|
||||||
@ -1244,60 +1251,33 @@ OBJS += ../src/fst/fst_ctrl_iface.o
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ALL=hostapd hostapd_cli
|
ifdef CONFIG_WEP
|
||||||
|
CFLAGS += -DCONFIG_WEP
|
||||||
all: verify_config $(ALL)
|
|
||||||
|
|
||||||
Q=@
|
|
||||||
E=echo
|
|
||||||
ifeq ($(V), 1)
|
|
||||||
Q=
|
|
||||||
E=true
|
|
||||||
endif
|
|
||||||
ifeq ($(QUIET), 1)
|
|
||||||
Q=@
|
|
||||||
E=true
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_CODE_COVERAGE
|
ifdef CONFIG_NO_TKIP
|
||||||
%.o: %.c
|
CFLAGS += -DCONFIG_NO_TKIP
|
||||||
@$(E) " CC " $<
|
|
||||||
$(Q)cd $(dir $@); $(CC) -c -o $(notdir $@) $(CFLAGS) $(notdir $<)
|
|
||||||
else
|
|
||||||
%.o: %.c
|
|
||||||
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
|
|
||||||
@$(E) " CC " $<
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
verify_config:
|
|
||||||
@if [ ! -r .config ]; then \
|
|
||||||
echo 'Building hostapd requires a configuration file'; \
|
|
||||||
echo '(.config). See README for more instructions. You can'; \
|
|
||||||
echo 'run "cp defconfig .config" to create an example'; \
|
|
||||||
echo 'configuration.'; \
|
|
||||||
exit 1; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
$(DESTDIR)$(BINDIR)/%: %
|
$(DESTDIR)$(BINDIR)/%: %
|
||||||
install -D $(<) $(@)
|
install -D $(<) $(@)
|
||||||
|
|
||||||
install: $(addprefix $(DESTDIR)$(BINDIR)/,$(ALL))
|
install: $(addprefix $(DESTDIR)$(BINDIR)/,$(ALL))
|
||||||
|
|
||||||
../src/drivers/build.hostapd:
|
_OBJS_VAR := OBJS
|
||||||
@if [ -f ../src/drivers/build.wpa_supplicant ]; then \
|
include ../src/objs.mk
|
||||||
$(MAKE) -C ../src/drivers clean; \
|
|
||||||
fi
|
|
||||||
@touch ../src/drivers/build.hostapd
|
|
||||||
|
|
||||||
BCHECK=../src/drivers/build.hostapd
|
hostapd: $(OBJS)
|
||||||
|
|
||||||
hostapd: $(BCHECK) $(OBJS)
|
|
||||||
$(Q)$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS)
|
$(Q)$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS)
|
||||||
@$(E) " LD " $@
|
@$(E) " LD " $@
|
||||||
|
|
||||||
ifdef CONFIG_WPA_TRACE
|
ifdef CONFIG_WPA_TRACE
|
||||||
OBJS_c += ../src/utils/trace.o
|
OBJS_c += ../src/utils/trace.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
_OBJS_VAR := OBJS_c
|
||||||
|
include ../src/objs.mk
|
||||||
|
|
||||||
hostapd_cli: $(OBJS_c)
|
hostapd_cli: $(OBJS_c)
|
||||||
$(Q)$(CC) $(LDFLAGS) -o hostapd_cli $(OBJS_c) $(LIBS_c)
|
$(Q)$(CC) $(LDFLAGS) -o hostapd_cli $(OBJS_c) $(LIBS_c)
|
||||||
@$(E) " LD " $@
|
@$(E) " LD " $@
|
||||||
@ -1332,6 +1312,35 @@ ifeq ($(CONFIG_TLS), linux)
|
|||||||
HOBJS += ../src/crypto/crypto_linux.o
|
HOBJS += ../src/crypto/crypto_linux.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
SOBJS += sae_pk_gen.o
|
||||||
|
SOBJS += ../src/utils/common.o
|
||||||
|
SOBJS += ../src/utils/os_$(CONFIG_OS).o
|
||||||
|
SOBJS += ../src/utils/base64.o
|
||||||
|
SOBJS += ../src/utils/wpa_debug.o
|
||||||
|
SOBJS += ../src/utils/wpabuf.o
|
||||||
|
ifdef CONFIG_WPA_TRACE
|
||||||
|
SOBJS += ../src/utils/trace.o
|
||||||
|
endif
|
||||||
|
SOBJS += ../src/common/ieee802_11_common.o
|
||||||
|
SOBJS += ../src/common/sae.o
|
||||||
|
SOBJS += ../src/common/sae_pk.o
|
||||||
|
SOBJS += ../src/common/dragonfly.o
|
||||||
|
SOBJS += $(AESOBJS)
|
||||||
|
SOBJS += ../src/crypto/sha256-prf.o
|
||||||
|
SOBJS += ../src/crypto/sha384-prf.o
|
||||||
|
SOBJS += ../src/crypto/sha512-prf.o
|
||||||
|
SOBJS += ../src/crypto/dh_groups.o
|
||||||
|
SOBJS += ../src/crypto/sha256-kdf.o
|
||||||
|
SOBJS += ../src/crypto/sha384-kdf.o
|
||||||
|
SOBJS += ../src/crypto/sha512-kdf.o
|
||||||
|
|
||||||
|
_OBJS_VAR := NOBJS
|
||||||
|
include ../src/objs.mk
|
||||||
|
_OBJS_VAR := HOBJS
|
||||||
|
include ../src/objs.mk
|
||||||
|
_OBJS_VAR := SOBJS
|
||||||
|
include ../src/objs.mk
|
||||||
|
|
||||||
nt_password_hash: $(NOBJS)
|
nt_password_hash: $(NOBJS)
|
||||||
$(Q)$(CC) $(LDFLAGS) -o nt_password_hash $(NOBJS) $(LIBS_n)
|
$(Q)$(CC) $(LDFLAGS) -o nt_password_hash $(NOBJS) $(LIBS_n)
|
||||||
@$(E) " LD " $@
|
@$(E) " LD " $@
|
||||||
@ -1340,15 +1349,17 @@ hlr_auc_gw: $(HOBJS)
|
|||||||
$(Q)$(CC) $(LDFLAGS) -o hlr_auc_gw $(HOBJS) $(LIBS_h)
|
$(Q)$(CC) $(LDFLAGS) -o hlr_auc_gw $(HOBJS) $(LIBS_h)
|
||||||
@$(E) " LD " $@
|
@$(E) " LD " $@
|
||||||
|
|
||||||
|
sae_pk_gen: $(SOBJS)
|
||||||
|
$(Q)$(CC) $(LDFLAGS) -o sae_pk_gen $(SOBJS) $(LIBS_s)
|
||||||
|
@$(E) " LD " $@
|
||||||
|
|
||||||
|
.PHONY: lcov-html
|
||||||
lcov-html:
|
lcov-html:
|
||||||
lcov -c -d .. > lcov.info
|
lcov -c -d $(BUILDDIR) > lcov.info
|
||||||
genhtml lcov.info --output-directory lcov-html
|
genhtml lcov.info --output-directory lcov-html
|
||||||
|
|
||||||
clean:
|
clean: common-clean
|
||||||
$(MAKE) -C ../src clean
|
rm -f core *~ nt_password_hash hlr_auc_gw
|
||||||
rm -f core *~ *.o hostapd hostapd_cli nt_password_hash hlr_auc_gw
|
rm -f sae_pk_gen
|
||||||
rm -f *.d *.gcno *.gcda *.gcov
|
|
||||||
rm -f lcov.info
|
rm -f lcov.info
|
||||||
rm -rf lcov-html
|
rm -rf lcov-html
|
||||||
|
|
||||||
-include $(OBJS:%.o=%.d)
|
|
||||||
|
@ -125,9 +125,6 @@ CONFIG_IPV6=y
|
|||||||
# the IEEE 802.11 Management capability (e.g., FreeBSD/net80211)
|
# the IEEE 802.11 Management capability (e.g., FreeBSD/net80211)
|
||||||
#CONFIG_DRIVER_RADIUS_ACL=y
|
#CONFIG_DRIVER_RADIUS_ACL=y
|
||||||
|
|
||||||
# IEEE 802.11n (High Throughput) support
|
|
||||||
CONFIG_IEEE80211N=y
|
|
||||||
|
|
||||||
# Remove debugging code that is printing out debug messages to stdout.
|
# 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
|
# This can be used to reduce the size of the hostapd considerably if debugging
|
||||||
# code is not needed.
|
# code is not needed.
|
||||||
@ -187,7 +184,7 @@ CONFIG_AP=y
|
|||||||
#CONFIG_FST=y
|
#CONFIG_FST=y
|
||||||
|
|
||||||
# Multiband Operation support
|
# 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.
|
# available to the AP and the devices that may associate with it.
|
||||||
#CONFIG_MBO=y
|
#CONFIG_MBO=y
|
||||||
|
|
||||||
@ -204,3 +201,11 @@ CONFIG_WPA_CLI_EDIT=y
|
|||||||
# /dev/urandom earlier in boot' seeds /dev/urandom with that entropy before
|
# /dev/urandom earlier in boot' seeds /dev/urandom with that entropy before
|
||||||
# either wpa_supplicant or hostapd are run.
|
# either wpa_supplicant or hostapd are run.
|
||||||
CONFIG_NO_RANDOM_POOL=y
|
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/common.h"
|
||||||
#include "utils/uuid.h"
|
#include "utils/uuid.h"
|
||||||
#include "common/ieee802_11_defs.h"
|
#include "common/ieee802_11_defs.h"
|
||||||
|
#include "common/sae.h"
|
||||||
#include "crypto/sha256.h"
|
#include "crypto/sha256.h"
|
||||||
#include "crypto/tls.h"
|
#include "crypto/tls.h"
|
||||||
#include "drivers/driver.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;
|
struct hostapd_radius_attr *attr, *a;
|
||||||
attr = hostapd_parse_radius_attr(buf + 19);
|
attr = hostapd_parse_radius_attr(buf + 19);
|
||||||
if (attr == NULL) {
|
if (attr == NULL) {
|
||||||
wpa_printf(MSG_ERROR, "Invalid radius_auth_req_attr: %s",
|
wpa_printf(MSG_ERROR, "Invalid radius_accept_attr: %s",
|
||||||
buf + 19);
|
buf + 19);
|
||||||
user = NULL; /* already in the BSS list */
|
user = NULL; /* already in the BSS list */
|
||||||
goto failed;
|
goto failed;
|
||||||
@ -793,6 +794,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,
|
static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx,
|
||||||
char *val)
|
char *val)
|
||||||
{
|
{
|
||||||
@ -843,6 +845,7 @@ static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
|
|
||||||
|
|
||||||
static int hostapd_parse_chanlist(struct hostapd_config *conf, char *val)
|
static int hostapd_parse_chanlist(struct hostapd_config *conf, char *val)
|
||||||
@ -940,104 +943,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
|
#ifdef CONFIG_IEEE80211R_AP
|
||||||
|
|
||||||
static int rkh_derive_key(const char *pos, u8 *key, size_t key_len)
|
static int rkh_derive_key(const char *pos, u8 *key, size_t key_len)
|
||||||
@ -1151,7 +1056,6 @@ static int add_r1kh(struct hostapd_bss_config *bss, char *value)
|
|||||||
#endif /* CONFIG_IEEE80211R_AP */
|
#endif /* CONFIG_IEEE80211R_AP */
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211N
|
|
||||||
static int hostapd_config_ht_capab(struct hostapd_config *conf,
|
static int hostapd_config_ht_capab(struct hostapd_config *conf,
|
||||||
const char *capab)
|
const char *capab)
|
||||||
{
|
{
|
||||||
@ -1171,14 +1075,6 @@ static int hostapd_config_ht_capab(struct hostapd_config *conf,
|
|||||||
}
|
}
|
||||||
if (!os_strstr(capab, "[HT40+]") && !os_strstr(capab, "[HT40-]"))
|
if (!os_strstr(capab, "[HT40+]") && !os_strstr(capab, "[HT40-]"))
|
||||||
conf->secondary_channel = 0;
|
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]"))
|
if (os_strstr(capab, "[GF]"))
|
||||||
conf->ht_capab |= HT_CAP_INFO_GREEN_FIELD;
|
conf->ht_capab |= HT_CAP_INFO_GREEN_FIELD;
|
||||||
if (os_strstr(capab, "[SHORT-GI-20]"))
|
if (os_strstr(capab, "[SHORT-GI-20]"))
|
||||||
@ -1212,7 +1108,6 @@ static int hostapd_config_ht_capab(struct hostapd_config *conf,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211N */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211AC
|
#ifdef CONFIG_IEEE80211AC
|
||||||
@ -2298,6 +2193,35 @@ static int parse_sae_password(struct hostapd_bss_config *bss, const char *val)
|
|||||||
pw->vlan_id = atoi(pos2);
|
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=");
|
pos2 = os_strstr(pos, "|id=");
|
||||||
if (pos2) {
|
if (pos2) {
|
||||||
if (!end)
|
if (!end)
|
||||||
@ -2320,6 +2244,18 @@ static int parse_sae_password(struct hostapd_bss_config *bss, const char *val)
|
|||||||
pw->password[end - val] = '\0';
|
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;
|
pw->next = bss->sae_passwords;
|
||||||
bss->sae_passwords = pw;
|
bss->sae_passwords = pw;
|
||||||
|
|
||||||
@ -2327,6 +2263,9 @@ static int parse_sae_password(struct hostapd_bss_config *bss, const char *val)
|
|||||||
fail:
|
fail:
|
||||||
str_clear_free(pw->password);
|
str_clear_free(pw->password);
|
||||||
os_free(pw->identifier);
|
os_free(pw->identifier);
|
||||||
|
#ifdef CONFIG_SAE_PK
|
||||||
|
sae_deinit_pk(pw->pk);
|
||||||
|
#endif /* CONFIG_SAE_PK */
|
||||||
os_free(pw);
|
os_free(pw);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -2471,6 +2410,13 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||||||
} else if (os_strcmp(buf, "skip_inactivity_poll") == 0) {
|
} else if (os_strcmp(buf, "skip_inactivity_poll") == 0) {
|
||||||
bss->skip_inactivity_poll = atoi(pos);
|
bss->skip_inactivity_poll = atoi(pos);
|
||||||
} else if (os_strcmp(buf, "country_code") == 0) {
|
} 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);
|
os_memcpy(conf->country, pos, 2);
|
||||||
} else if (os_strcmp(buf, "country3") == 0) {
|
} else if (os_strcmp(buf, "country3") == 0) {
|
||||||
conf->country[2] = strtol(pos, NULL, 16);
|
conf->country[2] = strtol(pos, NULL, 16);
|
||||||
@ -2613,7 +2559,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||||||
} else if (os_strcmp(buf, "eap_teap_auth") == 0) {
|
} else if (os_strcmp(buf, "eap_teap_auth") == 0) {
|
||||||
int val = atoi(pos);
|
int val = atoi(pos);
|
||||||
|
|
||||||
if (val < 0 || val > 1) {
|
if (val < 0 || val > 2) {
|
||||||
wpa_printf(MSG_ERROR,
|
wpa_printf(MSG_ERROR,
|
||||||
"Line %d: Invalid eap_teap_auth value",
|
"Line %d: Invalid eap_teap_auth value",
|
||||||
line);
|
line);
|
||||||
@ -2674,6 +2620,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||||||
} else if (os_strcmp(buf, "erp_domain") == 0) {
|
} else if (os_strcmp(buf, "erp_domain") == 0) {
|
||||||
os_free(bss->erp_domain);
|
os_free(bss->erp_domain);
|
||||||
bss->erp_domain = os_strdup(pos);
|
bss->erp_domain = os_strdup(pos);
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
} else if (os_strcmp(buf, "wep_key_len_broadcast") == 0) {
|
} else if (os_strcmp(buf, "wep_key_len_broadcast") == 0) {
|
||||||
int val = atoi(pos);
|
int val = atoi(pos);
|
||||||
|
|
||||||
@ -2701,6 +2648,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||||||
line, bss->wep_rekeying_period);
|
line, bss->wep_rekeying_period);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
} else if (os_strcmp(buf, "eap_reauth_period") == 0) {
|
} else if (os_strcmp(buf, "eap_reauth_period") == 0) {
|
||||||
bss->eap_reauth_period = atoi(pos);
|
bss->eap_reauth_period = atoi(pos);
|
||||||
if (bss->eap_reauth_period < 0) {
|
if (bss->eap_reauth_period < 0) {
|
||||||
@ -2875,6 +2823,16 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||||||
}
|
}
|
||||||
} else if (os_strcmp(buf, "wpa") == 0) {
|
} else if (os_strcmp(buf, "wpa") == 0) {
|
||||||
bss->wpa = atoi(pos);
|
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) {
|
} else if (os_strcmp(buf, "wpa_group_rekey") == 0) {
|
||||||
bss->wpa_group_rekey = atoi(pos);
|
bss->wpa_group_rekey = atoi(pos);
|
||||||
bss->wpa_group_rekey_set = 1;
|
bss->wpa_group_rekey_set = 1;
|
||||||
@ -2884,6 +2842,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||||||
bss->wpa_gmk_rekey = atoi(pos);
|
bss->wpa_gmk_rekey = atoi(pos);
|
||||||
} else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) {
|
} else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) {
|
||||||
bss->wpa_ptk_rekey = atoi(pos);
|
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) {
|
} else if (os_strcmp(buf, "wpa_group_update_count") == 0) {
|
||||||
char *endp;
|
char *endp;
|
||||||
unsigned long val = strtoul(pos, &endp, 0);
|
unsigned long val = strtoul(pos, &endp, 0);
|
||||||
@ -3312,6 +3279,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||||||
bss->ignore_broadcast_ssid = atoi(pos);
|
bss->ignore_broadcast_ssid = atoi(pos);
|
||||||
} else if (os_strcmp(buf, "no_probe_resp_if_max_sta") == 0) {
|
} else if (os_strcmp(buf, "no_probe_resp_if_max_sta") == 0) {
|
||||||
bss->no_probe_resp_if_max_sta = atoi(pos);
|
bss->no_probe_resp_if_max_sta = atoi(pos);
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
} else if (os_strcmp(buf, "wep_default_key") == 0) {
|
} else if (os_strcmp(buf, "wep_default_key") == 0) {
|
||||||
bss->ssid.wep.idx = atoi(pos);
|
bss->ssid.wep.idx = atoi(pos);
|
||||||
if (bss->ssid.wep.idx > 3) {
|
if (bss->ssid.wep.idx > 3) {
|
||||||
@ -3330,6 +3298,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||||||
line, buf);
|
line, buf);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
#ifndef CONFIG_NO_VLAN
|
#ifndef CONFIG_NO_VLAN
|
||||||
} else if (os_strcmp(buf, "dynamic_vlan") == 0) {
|
} else if (os_strcmp(buf, "dynamic_vlan") == 0) {
|
||||||
bss->ssid.dynamic_vlan = atoi(pos);
|
bss->ssid.dynamic_vlan = atoi(pos);
|
||||||
@ -3361,7 +3330,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||||||
} else if (os_strcmp(buf, "ap_table_expiration_time") == 0) {
|
} else if (os_strcmp(buf, "ap_table_expiration_time") == 0) {
|
||||||
conf->ap_table_expiration_time = atoi(pos);
|
conf->ap_table_expiration_time = atoi(pos);
|
||||||
} else if (os_strncmp(buf, "tx_queue_", 9) == 0) {
|
} 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",
|
wpa_printf(MSG_ERROR, "Line %d: invalid TX queue item",
|
||||||
line);
|
line);
|
||||||
return 1;
|
return 1;
|
||||||
@ -3408,6 +3377,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||||||
line, pos);
|
line, pos);
|
||||||
return 1;
|
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) {
|
} else if (os_strcmp(buf, "assoc_sa_query_max_timeout") == 0) {
|
||||||
bss->assoc_sa_query_max_timeout = atoi(pos);
|
bss->assoc_sa_query_max_timeout = atoi(pos);
|
||||||
if (bss->assoc_sa_query_max_timeout == 0) {
|
if (bss->assoc_sa_query_max_timeout == 0) {
|
||||||
@ -3428,7 +3399,6 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||||||
if (bss->ocv && !bss->ieee80211w)
|
if (bss->ocv && !bss->ieee80211w)
|
||||||
bss->ieee80211w = 1;
|
bss->ieee80211w = 1;
|
||||||
#endif /* CONFIG_OCV */
|
#endif /* CONFIG_OCV */
|
||||||
#ifdef CONFIG_IEEE80211N
|
|
||||||
} else if (os_strcmp(buf, "ieee80211n") == 0) {
|
} else if (os_strcmp(buf, "ieee80211n") == 0) {
|
||||||
conf->ieee80211n = atoi(pos);
|
conf->ieee80211n = atoi(pos);
|
||||||
} else if (os_strcmp(buf, "ht_capab") == 0) {
|
} else if (os_strcmp(buf, "ht_capab") == 0) {
|
||||||
@ -3441,7 +3411,6 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||||||
conf->require_ht = atoi(pos);
|
conf->require_ht = atoi(pos);
|
||||||
} else if (os_strcmp(buf, "obss_interval") == 0) {
|
} else if (os_strcmp(buf, "obss_interval") == 0) {
|
||||||
conf->obss_interval = atoi(pos);
|
conf->obss_interval = atoi(pos);
|
||||||
#endif /* CONFIG_IEEE80211N */
|
|
||||||
#ifdef CONFIG_IEEE80211AC
|
#ifdef CONFIG_IEEE80211AC
|
||||||
} else if (os_strcmp(buf, "ieee80211ac") == 0) {
|
} else if (os_strcmp(buf, "ieee80211ac") == 0) {
|
||||||
conf->ieee80211ac = atoi(pos);
|
conf->ieee80211ac = atoi(pos);
|
||||||
@ -3474,7 +3443,10 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||||||
} else if (os_strcmp(buf, "he_mu_beamformer") == 0) {
|
} else if (os_strcmp(buf, "he_mu_beamformer") == 0) {
|
||||||
conf->he_phy_capab.he_mu_beamformer = atoi(pos);
|
conf->he_phy_capab.he_mu_beamformer = atoi(pos);
|
||||||
} else if (os_strcmp(buf, "he_bss_color") == 0) {
|
} 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) {
|
} else if (os_strcmp(buf, "he_default_pe_duration") == 0) {
|
||||||
conf->he_op.he_default_pe_duration = atoi(pos);
|
conf->he_op.he_default_pe_duration = atoi(pos);
|
||||||
} else if (os_strcmp(buf, "he_twt_required") == 0) {
|
} else if (os_strcmp(buf, "he_twt_required") == 0) {
|
||||||
@ -4165,18 +4137,53 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||||||
bss->own_ie_override = tmp;
|
bss->own_ie_override = tmp;
|
||||||
} else if (os_strcmp(buf, "sae_reflection_attack") == 0) {
|
} else if (os_strcmp(buf, "sae_reflection_attack") == 0) {
|
||||||
bss->sae_reflection_attack = atoi(pos);
|
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) {
|
} else if (os_strcmp(buf, "sae_commit_override") == 0) {
|
||||||
wpabuf_free(bss->sae_commit_override);
|
wpabuf_free(bss->sae_commit_override);
|
||||||
bss->sae_commit_override = wpabuf_parse_bin(pos);
|
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) {
|
} else if (os_strcmp(buf, "rsnxe_override_eapol") == 0) {
|
||||||
wpabuf_free(bss->rsnxe_override_eapol);
|
wpabuf_free(bss->rsnxe_override_eapol);
|
||||||
bss->rsnxe_override_eapol = wpabuf_parse_bin(pos);
|
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) {
|
} else if (os_strcmp(buf, "gtk_rsc_override") == 0) {
|
||||||
wpabuf_free(bss->gtk_rsc_override);
|
wpabuf_free(bss->gtk_rsc_override);
|
||||||
bss->gtk_rsc_override = wpabuf_parse_bin(pos);
|
bss->gtk_rsc_override = wpabuf_parse_bin(pos);
|
||||||
} else if (os_strcmp(buf, "igtk_rsc_override") == 0) {
|
} else if (os_strcmp(buf, "igtk_rsc_override") == 0) {
|
||||||
wpabuf_free(bss->igtk_rsc_override);
|
wpabuf_free(bss->igtk_rsc_override);
|
||||||
bss->igtk_rsc_override = wpabuf_parse_bin(pos);
|
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 */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
#ifdef CONFIG_SAE
|
#ifdef CONFIG_SAE
|
||||||
} else if (os_strcmp(buf, "sae_password") == 0) {
|
} else if (os_strcmp(buf, "sae_password") == 0) {
|
||||||
@ -4379,6 +4386,18 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||||||
} else if (os_strcmp(buf, "dpp_controller") == 0) {
|
} else if (os_strcmp(buf, "dpp_controller") == 0) {
|
||||||
if (hostapd_dpp_controller_parse(bss, pos))
|
if (hostapd_dpp_controller_parse(bss, pos))
|
||||||
return 1;
|
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_DPP2 */
|
||||||
#endif /* CONFIG_DPP */
|
#endif /* CONFIG_DPP */
|
||||||
#ifdef CONFIG_OWE
|
#ifdef CONFIG_OWE
|
||||||
@ -4431,8 +4450,12 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||||||
conf->rssi_reject_assoc_rssi = atoi(pos);
|
conf->rssi_reject_assoc_rssi = atoi(pos);
|
||||||
} else if (os_strcmp(buf, "rssi_reject_assoc_timeout") == 0) {
|
} else if (os_strcmp(buf, "rssi_reject_assoc_timeout") == 0) {
|
||||||
conf->rssi_reject_assoc_timeout = atoi(pos);
|
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) {
|
} else if (os_strcmp(buf, "pbss") == 0) {
|
||||||
bss->pbss = atoi(pos);
|
bss->pbss = atoi(pos);
|
||||||
|
} else if (os_strcmp(buf, "transition_disable") == 0) {
|
||||||
|
bss->transition_disable = strtol(pos, NULL, 16);
|
||||||
#ifdef CONFIG_AIRTIME_POLICY
|
#ifdef CONFIG_AIRTIME_POLICY
|
||||||
} else if (os_strcmp(buf, "airtime_mode") == 0) {
|
} else if (os_strcmp(buf, "airtime_mode") == 0) {
|
||||||
int val = atoi(pos);
|
int val = atoi(pos);
|
||||||
@ -4548,6 +4571,12 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||||||
}
|
}
|
||||||
bss->mka_psk_set |= MKA_PSK_SET_CKN;
|
bss->mka_psk_set |= MKA_PSK_SET_CKN;
|
||||||
#endif /* CONFIG_MACSEC */
|
#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);
|
||||||
} else {
|
} else {
|
||||||
wpa_printf(MSG_ERROR,
|
wpa_printf(MSG_ERROR,
|
||||||
"Line %d: unknown configuration item '%s'",
|
"Line %d: unknown configuration item '%s'",
|
||||||
|
@ -49,6 +49,7 @@
|
|||||||
#include "ap/ieee802_1x.h"
|
#include "ap/ieee802_1x.h"
|
||||||
#include "ap/wpa_auth.h"
|
#include "ap/wpa_auth.h"
|
||||||
#include "ap/wpa_auth_i.h"
|
#include "ap/wpa_auth_i.h"
|
||||||
|
#include "ap/pmksa_cache_auth.h"
|
||||||
#include "ap/ieee802_11.h"
|
#include "ap/ieee802_11.h"
|
||||||
#include "ap/sta_info.h"
|
#include "ap/sta_info.h"
|
||||||
#include "ap/wps_hostapd.h"
|
#include "ap/wps_hostapd.h"
|
||||||
@ -61,6 +62,7 @@
|
|||||||
#include "ap/neighbor_db.h"
|
#include "ap/neighbor_db.h"
|
||||||
#include "ap/rrm.h"
|
#include "ap/rrm.h"
|
||||||
#include "ap/dpp_hostapd.h"
|
#include "ap/dpp_hostapd.h"
|
||||||
|
#include "ap/dfs.h"
|
||||||
#include "wps/wps_defs.h"
|
#include "wps/wps_defs.h"
|
||||||
#include "wps/wps.h"
|
#include "wps/wps.h"
|
||||||
#include "fst/fst_ctrl_iface.h"
|
#include "fst/fst_ctrl_iface.h"
|
||||||
@ -71,9 +73,6 @@
|
|||||||
#define HOSTAPD_CLI_DUP_VALUE_MAX_LEN 256
|
#define HOSTAPD_CLI_DUP_VALUE_MAX_LEN 256
|
||||||
|
|
||||||
#ifdef CONFIG_CTRL_IFACE_UDP
|
#ifdef CONFIG_CTRL_IFACE_UDP
|
||||||
#define COOKIE_LEN 8
|
|
||||||
static unsigned char cookie[COOKIE_LEN];
|
|
||||||
static unsigned char gcookie[COOKIE_LEN];
|
|
||||||
#define HOSTAPD_CTRL_IFACE_PORT 8877
|
#define HOSTAPD_CTRL_IFACE_PORT 8877
|
||||||
#define HOSTAPD_CTRL_IFACE_PORT_LIMIT 50
|
#define HOSTAPD_CTRL_IFACE_PORT_LIMIT 50
|
||||||
#define HOSTAPD_GLOBAL_CTRL_IFACE_PORT 8878
|
#define HOSTAPD_GLOBAL_CTRL_IFACE_PORT 8878
|
||||||
@ -1294,6 +1293,22 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
|
|||||||
pos += ret;
|
pos += ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hapd->conf->wpa && hapd->conf->wpa_deny_ptk0_rekey) {
|
||||||
|
ret = os_snprintf(pos, end - pos, "wpa_deny_ptk0_rekey=%d\n",
|
||||||
|
hapd->conf->wpa_deny_ptk0_rekey);
|
||||||
|
if (os_snprintf_error(end - pos, ret))
|
||||||
|
return pos - buf;
|
||||||
|
pos += ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->extended_key_id) {
|
||||||
|
ret = os_snprintf(pos, end - pos, "extended_key_id=%d\n",
|
||||||
|
hapd->conf->extended_key_id);
|
||||||
|
if (os_snprintf_error(end - pos, ret))
|
||||||
|
return pos - buf;
|
||||||
|
pos += ret;
|
||||||
|
}
|
||||||
|
|
||||||
return pos - buf;
|
return pos - buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1336,21 +1351,29 @@ static void hostapd_disassoc_deny_mac(struct hostapd_data *hapd)
|
|||||||
|
|
||||||
|
|
||||||
static int hostapd_ctrl_iface_set_band(struct hostapd_data *hapd,
|
static int hostapd_ctrl_iface_set_band(struct hostapd_data *hapd,
|
||||||
const char *band)
|
const char *bands)
|
||||||
{
|
{
|
||||||
union wpa_event_data event;
|
union wpa_event_data event;
|
||||||
enum set_band setband;
|
u32 setband_mask = WPA_SETBAND_AUTO;
|
||||||
|
|
||||||
if (os_strcmp(band, "AUTO") == 0)
|
/*
|
||||||
setband = WPA_SETBAND_AUTO;
|
* For example:
|
||||||
else if (os_strcmp(band, "5G") == 0)
|
* SET setband 2G,6G
|
||||||
setband = WPA_SETBAND_5G;
|
* SET setband 5G
|
||||||
else if (os_strcmp(band, "2G") == 0)
|
* SET setband AUTO
|
||||||
setband = WPA_SETBAND_2G;
|
*/
|
||||||
else
|
if (!os_strstr(bands, "AUTO")) {
|
||||||
return -1;
|
if (os_strstr(bands, "5G"))
|
||||||
|
setband_mask |= WPA_SETBAND_5G;
|
||||||
|
if (os_strstr(bands, "6G"))
|
||||||
|
setband_mask |= WPA_SETBAND_6G;
|
||||||
|
if (os_strstr(bands, "2G"))
|
||||||
|
setband_mask |= WPA_SETBAND_2G;
|
||||||
|
if (setband_mask == WPA_SETBAND_AUTO)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (hostapd_drv_set_band(hapd, setband) == 0) {
|
if (hostapd_drv_set_band(hapd, setband_mask) == 0) {
|
||||||
os_memset(&event, 0, sizeof(event));
|
os_memset(&event, 0, sizeof(event));
|
||||||
event.channel_list_changed.initiator = REGDOM_SET_BY_USER;
|
event.channel_list_changed.initiator = REGDOM_SET_BY_USER;
|
||||||
event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN;
|
event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN;
|
||||||
@ -1418,6 +1441,8 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
|
|||||||
hapd->dpp_ignore_netaccesskey_mismatch = atoi(value);
|
hapd->dpp_ignore_netaccesskey_mismatch = atoi(value);
|
||||||
} else if (os_strcasecmp(cmd, "dpp_test") == 0) {
|
} else if (os_strcasecmp(cmd, "dpp_test") == 0) {
|
||||||
dpp_test = atoi(value);
|
dpp_test = atoi(value);
|
||||||
|
} else if (os_strcasecmp(cmd, "dpp_version_override") == 0) {
|
||||||
|
dpp_version_override = atoi(value);
|
||||||
#endif /* CONFIG_DPP */
|
#endif /* CONFIG_DPP */
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
#ifdef CONFIG_MBO
|
#ifdef CONFIG_MBO
|
||||||
@ -1466,7 +1491,32 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
|
|||||||
os_strcmp(cmd, "sae_pwe") == 0) {
|
os_strcmp(cmd, "sae_pwe") == 0) {
|
||||||
if (hapd->started)
|
if (hapd->started)
|
||||||
hostapd_setup_sae_pt(hapd->conf);
|
hostapd_setup_sae_pt(hapd->conf);
|
||||||
|
} else if (os_strcasecmp(cmd, "transition_disable") == 0) {
|
||||||
|
wpa_auth_set_transition_disable(hapd->wpa_auth,
|
||||||
|
hapd->conf->transition_disable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
if (os_strcmp(cmd, "ft_rsnxe_used") == 0)
|
||||||
|
wpa_auth_set_ft_rsnxe_used(hapd->wpa_auth,
|
||||||
|
hapd->conf->ft_rsnxe_used);
|
||||||
|
else if (os_strcmp(cmd, "oci_freq_override_eapol_m3") == 0)
|
||||||
|
wpa_auth_set_ocv_override_freq(
|
||||||
|
hapd->wpa_auth, WPA_AUTH_OCV_OVERRIDE_EAPOL_M3,
|
||||||
|
atoi(value));
|
||||||
|
else if (os_strcmp(cmd, "oci_freq_override_eapol_g1") == 0)
|
||||||
|
wpa_auth_set_ocv_override_freq(
|
||||||
|
hapd->wpa_auth, WPA_AUTH_OCV_OVERRIDE_EAPOL_G1,
|
||||||
|
atoi(value));
|
||||||
|
else if (os_strcmp(cmd, "oci_freq_override_ft_assoc") == 0)
|
||||||
|
wpa_auth_set_ocv_override_freq(
|
||||||
|
hapd->wpa_auth, WPA_AUTH_OCV_OVERRIDE_FT_ASSOC,
|
||||||
|
atoi(value));
|
||||||
|
else if (os_strcmp(cmd, "oci_freq_override_fils_assoc") == 0)
|
||||||
|
wpa_auth_set_ocv_override_freq(
|
||||||
|
hapd->wpa_auth,
|
||||||
|
WPA_AUTH_OCV_OVERRIDE_FILS_ASSOC, atoi(value));
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -1884,7 +1934,7 @@ static void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
|
|||||||
if (ip.ip_hl != 5 || ip.ip_v != 4 ||
|
if (ip.ip_hl != 5 || ip.ip_v != 4 ||
|
||||||
ntohs(ip.ip_len) > HWSIM_IP_LEN) {
|
ntohs(ip.ip_len) > HWSIM_IP_LEN) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"test data: RX - ignore unexpect IP header");
|
"test data: RX - ignore unexpected IP header");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2147,6 +2197,32 @@ static int hostapd_ctrl_reset_pn(struct hostapd_data *hapd, const char *cmd)
|
|||||||
if (hwaddr_aton(cmd, addr))
|
if (hwaddr_aton(cmd, addr))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (is_broadcast_ether_addr(addr) && os_strstr(cmd, " BIGTK")) {
|
||||||
|
if (hapd->last_bigtk_alg == WPA_ALG_NONE)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
wpa_printf(MSG_INFO, "TESTING: Reset BIPN for BIGTK");
|
||||||
|
|
||||||
|
/* First, use a zero key to avoid any possible duplicate key
|
||||||
|
* avoidance in the driver. */
|
||||||
|
if (hostapd_drv_set_key(hapd->conf->iface, hapd,
|
||||||
|
hapd->last_bigtk_alg,
|
||||||
|
broadcast_ether_addr,
|
||||||
|
hapd->last_bigtk_key_idx, 0, 1, NULL, 0,
|
||||||
|
zero, hapd->last_bigtk_len,
|
||||||
|
KEY_FLAG_GROUP_TX_DEFAULT) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Set the previously configured key to reset its TSC */
|
||||||
|
return hostapd_drv_set_key(hapd->conf->iface, hapd,
|
||||||
|
hapd->last_bigtk_alg,
|
||||||
|
broadcast_ether_addr,
|
||||||
|
hapd->last_bigtk_key_idx, 0, 1, NULL,
|
||||||
|
0, hapd->last_bigtk,
|
||||||
|
hapd->last_bigtk_len,
|
||||||
|
KEY_FLAG_GROUP_TX_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
if (is_broadcast_ether_addr(addr) && os_strstr(cmd, "IGTK")) {
|
if (is_broadcast_ether_addr(addr) && os_strstr(cmd, "IGTK")) {
|
||||||
if (hapd->last_igtk_alg == WPA_ALG_NONE)
|
if (hapd->last_igtk_alg == WPA_ALG_NONE)
|
||||||
return -1;
|
return -1;
|
||||||
@ -2412,6 +2488,19 @@ static int hostapd_ctrl_resend_group_m1(struct hostapd_data *hapd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int hostapd_ctrl_get_pmksa_pmk(struct hostapd_data *hapd, const u8 *addr,
|
||||||
|
char *buf, size_t buflen)
|
||||||
|
{
|
||||||
|
struct rsn_pmksa_cache_entry *pmksa;
|
||||||
|
|
||||||
|
pmksa = wpa_auth_pmksa_get(hapd->wpa_auth, addr, NULL);
|
||||||
|
if (!pmksa)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return wpa_snprintf_hex(buf, buflen, pmksa->pmk, pmksa->pmk_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int hostapd_ctrl_get_pmk(struct hostapd_data *hapd, const char *cmd,
|
static int hostapd_ctrl_get_pmk(struct hostapd_data *hapd, const char *cmd,
|
||||||
char *buf, size_t buflen)
|
char *buf, size_t buflen)
|
||||||
{
|
{
|
||||||
@ -2427,13 +2516,13 @@ static int hostapd_ctrl_get_pmk(struct hostapd_data *hapd, const char *cmd,
|
|||||||
if (!sta || !sta->wpa_sm) {
|
if (!sta || !sta->wpa_sm) {
|
||||||
wpa_printf(MSG_DEBUG, "No STA WPA state machine for " MACSTR,
|
wpa_printf(MSG_DEBUG, "No STA WPA state machine for " MACSTR,
|
||||||
MAC2STR(addr));
|
MAC2STR(addr));
|
||||||
return -1;
|
return hostapd_ctrl_get_pmksa_pmk(hapd, addr, buf, buflen);
|
||||||
}
|
}
|
||||||
pmk = wpa_auth_get_pmk(sta->wpa_sm, &pmk_len);
|
pmk = wpa_auth_get_pmk(sta->wpa_sm, &pmk_len);
|
||||||
if (!pmk) {
|
if (!pmk || !pmk_len) {
|
||||||
wpa_printf(MSG_DEBUG, "No PMK stored for " MACSTR,
|
wpa_printf(MSG_DEBUG, "No PMK stored for " MACSTR,
|
||||||
MAC2STR(addr));
|
MAC2STR(addr));
|
||||||
return -1;
|
return hostapd_ctrl_get_pmksa_pmk(hapd, addr, buf, buflen);
|
||||||
}
|
}
|
||||||
|
|
||||||
return wpa_snprintf_hex(buf, buflen, pmk, pmk_len);
|
return wpa_snprintf_hex(buf, buflen, pmk, pmk_len);
|
||||||
@ -2501,18 +2590,175 @@ static int hostapd_get_channel(struct hostapd_data *hapd, char *buf, size_t buf
|
|||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef NEED_AP_MLME
|
||||||
|
static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params)
|
||||||
|
{
|
||||||
|
switch (params->bandwidth) {
|
||||||
|
case 0:
|
||||||
|
/* bandwidth not specified: use 20 MHz by default */
|
||||||
|
/* fall-through */
|
||||||
|
case 20:
|
||||||
|
if (params->center_freq1 &&
|
||||||
|
params->center_freq1 != params->freq)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (params->center_freq2 || params->sec_channel_offset)
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
case 40:
|
||||||
|
if (params->center_freq2 || !params->sec_channel_offset)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!params->center_freq1)
|
||||||
|
break;
|
||||||
|
switch (params->sec_channel_offset) {
|
||||||
|
case 1:
|
||||||
|
if (params->freq + 10 != params->center_freq1)
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
case -1:
|
||||||
|
if (params->freq - 10 != params->center_freq1)
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 80:
|
||||||
|
if (!params->center_freq1 || !params->sec_channel_offset)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
switch (params->sec_channel_offset) {
|
||||||
|
case 1:
|
||||||
|
if (params->freq - 10 != params->center_freq1 &&
|
||||||
|
params->freq + 30 != params->center_freq1)
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
case -1:
|
||||||
|
if (params->freq + 10 != params->center_freq1 &&
|
||||||
|
params->freq - 30 != params->center_freq1)
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adjacent and overlapped are not allowed for 80+80 */
|
||||||
|
if (params->center_freq2 &&
|
||||||
|
params->center_freq1 - params->center_freq2 <= 80 &&
|
||||||
|
params->center_freq2 - params->center_freq1 <= 80)
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
case 160:
|
||||||
|
if (!params->center_freq1 || params->center_freq2 ||
|
||||||
|
!params->sec_channel_offset)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
switch (params->sec_channel_offset) {
|
||||||
|
case 1:
|
||||||
|
if (params->freq + 70 != params->center_freq1 &&
|
||||||
|
params->freq + 30 != params->center_freq1 &&
|
||||||
|
params->freq - 10 != params->center_freq1 &&
|
||||||
|
params->freq - 50 != params->center_freq1)
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
case -1:
|
||||||
|
if (params->freq + 50 != params->center_freq1 &&
|
||||||
|
params->freq + 10 != params->center_freq1 &&
|
||||||
|
params->freq - 30 != params->center_freq1 &&
|
||||||
|
params->freq - 70 != params->center_freq1)
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* NEED_AP_MLME */
|
||||||
|
|
||||||
|
|
||||||
static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
|
static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
|
||||||
char *pos)
|
char *pos)
|
||||||
{
|
{
|
||||||
#ifdef NEED_AP_MLME
|
#ifdef NEED_AP_MLME
|
||||||
struct csa_settings settings;
|
struct csa_settings settings;
|
||||||
int ret;
|
int ret;
|
||||||
|
int dfs_range = 0;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
int bandwidth;
|
||||||
|
u8 chan;
|
||||||
|
|
||||||
ret = hostapd_parse_csa_settings(pos, &settings);
|
ret = hostapd_parse_csa_settings(pos, &settings);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
ret = hostapd_ctrl_check_freq_params(&settings.freq_params);
|
||||||
|
if (ret) {
|
||||||
|
wpa_printf(MSG_INFO,
|
||||||
|
"chanswitch: invalid frequency settings provided");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (settings.freq_params.bandwidth) {
|
||||||
|
case 40:
|
||||||
|
bandwidth = CHAN_WIDTH_40;
|
||||||
|
break;
|
||||||
|
case 80:
|
||||||
|
if (settings.freq_params.center_freq2)
|
||||||
|
bandwidth = CHAN_WIDTH_80P80;
|
||||||
|
else
|
||||||
|
bandwidth = CHAN_WIDTH_80;
|
||||||
|
break;
|
||||||
|
case 160:
|
||||||
|
bandwidth = CHAN_WIDTH_160;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
bandwidth = CHAN_WIDTH_20;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings.freq_params.center_freq1)
|
||||||
|
dfs_range += hostapd_is_dfs_overlap(
|
||||||
|
iface, bandwidth, settings.freq_params.center_freq1);
|
||||||
|
else
|
||||||
|
dfs_range += hostapd_is_dfs_overlap(
|
||||||
|
iface, bandwidth, settings.freq_params.freq);
|
||||||
|
|
||||||
|
if (settings.freq_params.center_freq2)
|
||||||
|
dfs_range += hostapd_is_dfs_overlap(
|
||||||
|
iface, bandwidth, settings.freq_params.center_freq2);
|
||||||
|
|
||||||
|
if (dfs_range) {
|
||||||
|
ret = ieee80211_freq_to_chan(settings.freq_params.freq, &chan);
|
||||||
|
if (ret == NUM_HOSTAPD_MODES) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"Failed to get channel for (freq=%d, sec_channel_offset=%d, bw=%d)",
|
||||||
|
settings.freq_params.freq,
|
||||||
|
settings.freq_params.sec_channel_offset,
|
||||||
|
settings.freq_params.bandwidth);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.freq_params.channel = chan;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DFS/CAC to (channel=%u, freq=%d, sec_channel_offset=%d, bw=%d, center_freq1=%d)",
|
||||||
|
settings.freq_params.channel,
|
||||||
|
settings.freq_params.freq,
|
||||||
|
settings.freq_params.sec_channel_offset,
|
||||||
|
settings.freq_params.bandwidth,
|
||||||
|
settings.freq_params.center_freq1);
|
||||||
|
|
||||||
|
/* Perform CAC and switch channel */
|
||||||
|
hostapd_switch_channel_fallback(iface, &settings.freq_params);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < iface->num_bss; i++) {
|
for (i = 0; i < iface->num_bss; i++) {
|
||||||
|
|
||||||
/* Save CHAN_SWITCH VHT config */
|
/* Save CHAN_SWITCH VHT config */
|
||||||
@ -2551,13 +2797,17 @@ static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd,
|
|||||||
char *buf, size_t buflen)
|
char *buf, size_t buflen)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
char *pos;
|
char *pos, *temp = NULL;
|
||||||
u8 *data = NULL;
|
u8 *data = NULL;
|
||||||
unsigned int vendor_id, subcmd;
|
unsigned int vendor_id, subcmd;
|
||||||
|
enum nested_attr nested_attr_flag = NESTED_ATTR_UNSPECIFIED;
|
||||||
struct wpabuf *reply;
|
struct wpabuf *reply;
|
||||||
size_t data_len = 0;
|
size_t data_len = 0;
|
||||||
|
|
||||||
/* cmd: <vendor id> <subcommand id> [<hex formatted data>] */
|
/**
|
||||||
|
* cmd: <vendor id> <subcommand id> [<hex formatted data>]
|
||||||
|
* [nested=<0|1>]
|
||||||
|
*/
|
||||||
vendor_id = strtoul(cmd, &pos, 16);
|
vendor_id = strtoul(cmd, &pos, 16);
|
||||||
if (!isblank((unsigned char) *pos))
|
if (!isblank((unsigned char) *pos))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -2567,7 +2817,9 @@ static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd,
|
|||||||
if (*pos != '\0') {
|
if (*pos != '\0') {
|
||||||
if (!isblank((unsigned char) *pos++))
|
if (!isblank((unsigned char) *pos++))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
data_len = os_strlen(pos);
|
|
||||||
|
temp = os_strchr(pos, ' ');
|
||||||
|
data_len = temp ? (size_t) (temp - pos) : os_strlen(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data_len) {
|
if (data_len) {
|
||||||
@ -2584,6 +2836,11 @@ static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pos = os_strstr(cmd, "nested=");
|
||||||
|
if (pos)
|
||||||
|
nested_attr_flag = atoi(pos + 7) ? NESTED_ATTR_USED :
|
||||||
|
NESTED_ATTR_NOT_USED;
|
||||||
|
|
||||||
reply = wpabuf_alloc((buflen - 1) / 2);
|
reply = wpabuf_alloc((buflen - 1) / 2);
|
||||||
if (!reply) {
|
if (!reply) {
|
||||||
os_free(data);
|
os_free(data);
|
||||||
@ -2591,7 +2848,7 @@ static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = hostapd_drv_vendor_cmd(hapd, vendor_id, subcmd, data, data_len,
|
ret = hostapd_drv_vendor_cmd(hapd, vendor_id, subcmd, data, data_len,
|
||||||
reply);
|
nested_attr_flag, reply);
|
||||||
|
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
|
ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
|
||||||
@ -3012,6 +3269,34 @@ static int hostapd_ctrl_driver_flags(struct hostapd_iface *iface, char *buf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int hostapd_ctrl_driver_flags2(struct hostapd_iface *iface, char *buf,
|
||||||
|
size_t buflen)
|
||||||
|
{
|
||||||
|
int ret, i;
|
||||||
|
char *pos, *end;
|
||||||
|
|
||||||
|
ret = os_snprintf(buf, buflen, "%016llX:\n",
|
||||||
|
(long long unsigned) iface->drv_flags2);
|
||||||
|
if (os_snprintf_error(buflen, ret))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
pos = buf + ret;
|
||||||
|
end = buf + buflen;
|
||||||
|
|
||||||
|
for (i = 0; i < 64; i++) {
|
||||||
|
if (iface->drv_flags2 & (1LLU << i)) {
|
||||||
|
ret = os_snprintf(pos, end - pos, "%s\n",
|
||||||
|
driver_flag2_to_string(1LLU << i));
|
||||||
|
if (os_snprintf_error(end - pos, ret))
|
||||||
|
return -1;
|
||||||
|
pos += ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pos - buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int hostapd_ctrl_iface_acl_del_mac(struct mac_acl_entry **acl, int *num,
|
static int hostapd_ctrl_iface_acl_del_mac(struct mac_acl_entry **acl, int *num,
|
||||||
const char *txtaddr)
|
const char *txtaddr)
|
||||||
{
|
{
|
||||||
@ -3443,6 +3728,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
|
|||||||
} else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) {
|
} else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) {
|
||||||
reply_len = hostapd_ctrl_driver_flags(hapd->iface, reply,
|
reply_len = hostapd_ctrl_driver_flags(hapd->iface, reply,
|
||||||
reply_size);
|
reply_size);
|
||||||
|
} else if (os_strcmp(buf, "DRIVER_FLAGS2") == 0) {
|
||||||
|
reply_len = hostapd_ctrl_driver_flags2(hapd->iface, reply,
|
||||||
|
reply_size);
|
||||||
} else if (os_strcmp(buf, "TERMINATE") == 0) {
|
} else if (os_strcmp(buf, "TERMINATE") == 0) {
|
||||||
eloop_terminate();
|
eloop_terminate();
|
||||||
} else if (os_strncmp(buf, "ACCEPT_ACL ", 11) == 0) {
|
} else if (os_strncmp(buf, "ACCEPT_ACL ", 11) == 0) {
|
||||||
@ -3551,6 +3839,11 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
|
|||||||
reply_len = dpp_bootstrap_info(hapd->iface->interfaces->dpp,
|
reply_len = dpp_bootstrap_info(hapd->iface->interfaces->dpp,
|
||||||
atoi(buf + 19),
|
atoi(buf + 19),
|
||||||
reply, reply_size);
|
reply, reply_size);
|
||||||
|
} else if (os_strncmp(buf, "DPP_BOOTSTRAP_SET ", 18) == 0) {
|
||||||
|
if (dpp_bootstrap_set(hapd->iface->interfaces->dpp,
|
||||||
|
atoi(buf + 18),
|
||||||
|
os_strchr(buf + 18, ' ')) < 0)
|
||||||
|
reply_len = -1;
|
||||||
} else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) {
|
} else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) {
|
||||||
if (hostapd_dpp_auth_init(hapd, buf + 13) < 0)
|
if (hostapd_dpp_auth_init(hapd, buf + 13) < 0)
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
@ -3594,6 +3887,21 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
|
|||||||
} else if (os_strncmp(buf, "DPP_PKEX_REMOVE ", 16) == 0) {
|
} else if (os_strncmp(buf, "DPP_PKEX_REMOVE ", 16) == 0) {
|
||||||
if (hostapd_dpp_pkex_remove(hapd, buf + 16) < 0)
|
if (hostapd_dpp_pkex_remove(hapd, buf + 16) < 0)
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
} else if (os_strncmp(buf, "DPP_CONTROLLER_START ", 21) == 0) {
|
||||||
|
if (hostapd_dpp_controller_start(hapd, buf + 20) < 0)
|
||||||
|
reply_len = -1;
|
||||||
|
} else if (os_strcmp(buf, "DPP_CONTROLLER_START") == 0) {
|
||||||
|
if (hostapd_dpp_controller_start(hapd, NULL) < 0)
|
||||||
|
reply_len = -1;
|
||||||
|
} else if (os_strcmp(buf, "DPP_CONTROLLER_STOP") == 0) {
|
||||||
|
dpp_controller_stop(hapd->iface->interfaces->dpp);
|
||||||
|
} else if (os_strncmp(buf, "DPP_CHIRP ", 10) == 0) {
|
||||||
|
if (hostapd_dpp_chirp(hapd, buf + 9) < 0)
|
||||||
|
reply_len = -1;
|
||||||
|
} else if (os_strcmp(buf, "DPP_STOP_CHIRP") == 0) {
|
||||||
|
hostapd_dpp_chirp_stop(hapd);
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
#endif /* CONFIG_DPP */
|
#endif /* CONFIG_DPP */
|
||||||
#ifdef RADIUS_SERVER
|
#ifdef RADIUS_SERVER
|
||||||
} else if (os_strncmp(buf, "DAC_REQUEST ", 12) == 0) {
|
} else if (os_strncmp(buf, "DAC_REQUEST ", 12) == 0) {
|
||||||
@ -3642,7 +3950,7 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
|
|||||||
int reply_len;
|
int reply_len;
|
||||||
int level = MSG_DEBUG;
|
int level = MSG_DEBUG;
|
||||||
#ifdef CONFIG_CTRL_IFACE_UDP
|
#ifdef CONFIG_CTRL_IFACE_UDP
|
||||||
unsigned char lcookie[COOKIE_LEN];
|
unsigned char lcookie[CTRL_IFACE_COOKIE_LEN];
|
||||||
#endif /* CONFIG_CTRL_IFACE_UDP */
|
#endif /* CONFIG_CTRL_IFACE_UDP */
|
||||||
|
|
||||||
res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
|
res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
|
||||||
@ -3667,28 +3975,30 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
|
|||||||
#ifdef CONFIG_CTRL_IFACE_UDP
|
#ifdef CONFIG_CTRL_IFACE_UDP
|
||||||
if (os_strcmp(buf, "GET_COOKIE") == 0) {
|
if (os_strcmp(buf, "GET_COOKIE") == 0) {
|
||||||
os_memcpy(reply, "COOKIE=", 7);
|
os_memcpy(reply, "COOKIE=", 7);
|
||||||
wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
|
wpa_snprintf_hex(reply + 7, 2 * CTRL_IFACE_COOKIE_LEN + 1,
|
||||||
cookie, COOKIE_LEN);
|
hapd->ctrl_iface_cookie,
|
||||||
reply_len = 7 + 2 * COOKIE_LEN;
|
CTRL_IFACE_COOKIE_LEN);
|
||||||
|
reply_len = 7 + 2 * CTRL_IFACE_COOKIE_LEN;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (os_strncmp(buf, "COOKIE=", 7) != 0 ||
|
if (os_strncmp(buf, "COOKIE=", 7) != 0 ||
|
||||||
hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) {
|
hexstr2bin(buf + 7, lcookie, CTRL_IFACE_COOKIE_LEN) < 0) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"CTRL: No cookie in the request - drop request");
|
"CTRL: No cookie in the request - drop request");
|
||||||
os_free(reply);
|
os_free(reply);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (os_memcmp(cookie, lcookie, COOKIE_LEN) != 0) {
|
if (os_memcmp(hapd->ctrl_iface_cookie, lcookie,
|
||||||
|
CTRL_IFACE_COOKIE_LEN) != 0) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"CTRL: Invalid cookie in the request - drop request");
|
"CTRL: Invalid cookie in the request - drop request");
|
||||||
os_free(reply);
|
os_free(reply);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = buf + 7 + 2 * COOKIE_LEN;
|
pos = buf + 7 + 2 * CTRL_IFACE_COOKIE_LEN;
|
||||||
while (*pos == ' ')
|
while (*pos == ' ')
|
||||||
pos++;
|
pos++;
|
||||||
#endif /* CONFIG_CTRL_IFACE_UDP */
|
#endif /* CONFIG_CTRL_IFACE_UDP */
|
||||||
@ -3777,7 +4087,7 @@ int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
|
|||||||
|
|
||||||
dl_list_init(&hapd->ctrl_dst);
|
dl_list_init(&hapd->ctrl_dst);
|
||||||
hapd->ctrl_sock = -1;
|
hapd->ctrl_sock = -1;
|
||||||
os_get_random(cookie, COOKIE_LEN);
|
os_get_random(hapd->ctrl_iface_cookie, CTRL_IFACE_COOKIE_LEN);
|
||||||
|
|
||||||
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
|
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
|
||||||
hints.ai_flags = AI_PASSIVE;
|
hints.ai_flags = AI_PASSIVE;
|
||||||
@ -4091,6 +4401,11 @@ static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces)
|
|||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
#ifdef CONFIG_DPP
|
#ifdef CONFIG_DPP
|
||||||
dpp_test = DPP_TEST_DISABLED;
|
dpp_test = DPP_TEST_DISABLED;
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
dpp_version_override = 2;
|
||||||
|
#else /* CONFIG_DPP2 */
|
||||||
|
dpp_version_override = 1;
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
#endif /* CONFIG_DPP */
|
#endif /* CONFIG_DPP */
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
@ -4356,7 +4671,7 @@ static int hostapd_global_ctrl_iface_ifname(struct hapd_interfaces *interfaces,
|
|||||||
static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
|
static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
|
||||||
void *sock_ctx)
|
void *sock_ctx)
|
||||||
{
|
{
|
||||||
void *interfaces = eloop_ctx;
|
struct hapd_interfaces *interfaces = eloop_ctx;
|
||||||
char buffer[256], *buf = buffer;
|
char buffer[256], *buf = buffer;
|
||||||
int res;
|
int res;
|
||||||
struct sockaddr_storage from;
|
struct sockaddr_storage from;
|
||||||
@ -4365,7 +4680,7 @@ static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
|
|||||||
int reply_len;
|
int reply_len;
|
||||||
const int reply_size = 4096;
|
const int reply_size = 4096;
|
||||||
#ifdef CONFIG_CTRL_IFACE_UDP
|
#ifdef CONFIG_CTRL_IFACE_UDP
|
||||||
unsigned char lcookie[COOKIE_LEN];
|
unsigned char lcookie[CTRL_IFACE_COOKIE_LEN];
|
||||||
#endif /* CONFIG_CTRL_IFACE_UDP */
|
#endif /* CONFIG_CTRL_IFACE_UDP */
|
||||||
|
|
||||||
res = recvfrom(sock, buffer, sizeof(buffer) - 1, 0,
|
res = recvfrom(sock, buffer, sizeof(buffer) - 1, 0,
|
||||||
@ -4394,28 +4709,30 @@ static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
|
|||||||
#ifdef CONFIG_CTRL_IFACE_UDP
|
#ifdef CONFIG_CTRL_IFACE_UDP
|
||||||
if (os_strcmp(buf, "GET_COOKIE") == 0) {
|
if (os_strcmp(buf, "GET_COOKIE") == 0) {
|
||||||
os_memcpy(reply, "COOKIE=", 7);
|
os_memcpy(reply, "COOKIE=", 7);
|
||||||
wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
|
wpa_snprintf_hex(reply + 7, 2 * CTRL_IFACE_COOKIE_LEN + 1,
|
||||||
gcookie, COOKIE_LEN);
|
interfaces->ctrl_iface_cookie,
|
||||||
reply_len = 7 + 2 * COOKIE_LEN;
|
CTRL_IFACE_COOKIE_LEN);
|
||||||
|
reply_len = 7 + 2 * CTRL_IFACE_COOKIE_LEN;
|
||||||
goto send_reply;
|
goto send_reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (os_strncmp(buf, "COOKIE=", 7) != 0 ||
|
if (os_strncmp(buf, "COOKIE=", 7) != 0 ||
|
||||||
hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) {
|
hexstr2bin(buf + 7, lcookie, CTRL_IFACE_COOKIE_LEN) < 0) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"CTRL: No cookie in the request - drop request");
|
"CTRL: No cookie in the request - drop request");
|
||||||
os_free(reply);
|
os_free(reply);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (os_memcmp(gcookie, lcookie, COOKIE_LEN) != 0) {
|
if (os_memcmp(interfaces->ctrl_iface_cookie, lcookie,
|
||||||
|
CTRL_IFACE_COOKIE_LEN) != 0) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"CTRL: Invalid cookie in the request - drop request");
|
"CTRL: Invalid cookie in the request - drop request");
|
||||||
os_free(reply);
|
os_free(reply);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf += 7 + 2 * COOKIE_LEN;
|
buf += 7 + 2 * CTRL_IFACE_COOKIE_LEN;
|
||||||
while (*buf == ' ')
|
while (*buf == ' ')
|
||||||
buf++;
|
buf++;
|
||||||
#endif /* CONFIG_CTRL_IFACE_UDP */
|
#endif /* CONFIG_CTRL_IFACE_UDP */
|
||||||
@ -4559,7 +4876,7 @@ int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
os_get_random(gcookie, COOKIE_LEN);
|
os_get_random(interface->ctrl_iface_cookie, CTRL_IFACE_COOKIE_LEN);
|
||||||
|
|
||||||
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
|
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
|
||||||
hints.ai_flags = AI_PASSIVE;
|
hints.ai_flags = AI_PASSIVE;
|
||||||
@ -4802,13 +5119,8 @@ static void hostapd_ctrl_iface_send_internal(int sock, struct dl_list *ctrl_dst,
|
|||||||
return;
|
return;
|
||||||
idx = 0;
|
idx = 0;
|
||||||
if (ifname) {
|
if (ifname) {
|
||||||
#ifdef CONFIG_CTRL_IFACE_UDP
|
|
||||||
io[idx].iov_base = "IFACE=";
|
|
||||||
io[idx].iov_len = 6;
|
|
||||||
#else /* CONFIG_CTRL_IFACE_UDP */
|
|
||||||
io[idx].iov_base = "IFNAME=";
|
io[idx].iov_base = "IFNAME=";
|
||||||
io[idx].iov_len = 7;
|
io[idx].iov_len = 7;
|
||||||
#endif /* CONFIG_CTRL_IFACE_UDP */
|
|
||||||
idx++;
|
idx++;
|
||||||
io[idx].iov_base = (char *) ifname;
|
io[idx].iov_base = (char *) ifname;
|
||||||
io[idx].iov_len = os_strlen(ifname);
|
io[idx].iov_len = os_strlen(ifname);
|
||||||
|
@ -148,9 +148,6 @@ CONFIG_IEEE80211R=y
|
|||||||
# the IEEE 802.11 Management capability (e.g., FreeBSD/net80211)
|
# the IEEE 802.11 Management capability (e.g., FreeBSD/net80211)
|
||||||
#CONFIG_DRIVER_RADIUS_ACL=y
|
#CONFIG_DRIVER_RADIUS_ACL=y
|
||||||
|
|
||||||
# IEEE 802.11n (High Throughput) support
|
|
||||||
CONFIG_IEEE80211N=y
|
|
||||||
|
|
||||||
# Wireless Network Management (IEEE Std 802.11v-2011)
|
# Wireless Network Management (IEEE Std 802.11v-2011)
|
||||||
# Note: This is experimental and not complete implementation.
|
# Note: This is experimental and not complete implementation.
|
||||||
#CONFIG_WNM=y
|
#CONFIG_WNM=y
|
||||||
@ -354,7 +351,7 @@ CONFIG_INTERWORKING=y
|
|||||||
#CONFIG_ACS=y
|
#CONFIG_ACS=y
|
||||||
|
|
||||||
# Multiband Operation support
|
# 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.
|
# available to the AP and the devices that may associate with it.
|
||||||
#CONFIG_MBO=y
|
#CONFIG_MBO=y
|
||||||
|
|
||||||
@ -384,6 +381,19 @@ CONFIG_INTERWORKING=y
|
|||||||
# parameter. See that parameter in hostapd.conf for more details.
|
# parameter. See that parameter in hostapd.conf for more details.
|
||||||
#CFLAGS += -DDEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES=1
|
#CFLAGS += -DDEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES=1
|
||||||
|
|
||||||
CONFIG_TESTING_OPTIONS=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
|
||||||
|
|
||||||
CONFIG_SAE=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
|
||||||
|
|
||||||
|
CONFIG_TESTING_OPTIONS=y
|
||||||
|
@ -210,7 +210,7 @@ channel=1
|
|||||||
# Frequency list can be provided as range using hyphen ('-') or individual
|
# Frequency list can be provided as range using hyphen ('-') or individual
|
||||||
# frequencies can be specified by comma (',') separated values
|
# frequencies can be specified by comma (',') separated values
|
||||||
# Default: all frequencies allowed in selected hw_mode
|
# Default: all frequencies allowed in selected hw_mode
|
||||||
#freqlist=2437,5945,5965
|
#freqlist=2437,5955,5975
|
||||||
#freqlist=2437,5985-6105
|
#freqlist=2437,5985-6105
|
||||||
|
|
||||||
# Exclude DFS channels from ACS
|
# Exclude DFS channels from ACS
|
||||||
@ -580,6 +580,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.
|
# Note: hw_mode=g (2.4 GHz) and hw_mode=a (5 GHz) is used to specify the band.
|
||||||
ieee80211n=1
|
ieee80211n=1
|
||||||
|
|
||||||
|
# disable_11n: Boolean (0/1) to disable HT for a specific BSS
|
||||||
|
#disable_11n=0
|
||||||
|
|
||||||
# ht_capab: HT capabilities (list of flags)
|
# ht_capab: HT capabilities (list of flags)
|
||||||
# LDPC coding capability: [LDPC] = supported
|
# LDPC coding capability: [LDPC] = supported
|
||||||
# Supported channel width set: [HT40-] = both 20 MHz and 40 MHz with secondary
|
# Supported channel width set: [HT40-] = both 20 MHz and 40 MHz with secondary
|
||||||
@ -598,8 +601,6 @@ ieee80211n=1
|
|||||||
# channels if needed or creation of 40 MHz channel maybe rejected based
|
# channels if needed or creation of 40 MHz channel maybe rejected based
|
||||||
# on overlapping BSSes. These changes are done automatically when hostapd
|
# on overlapping BSSes. These changes are done automatically when hostapd
|
||||||
# is setting up the 40 MHz channel.
|
# 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)
|
# HT-greenfield: [GF] (disabled if not set)
|
||||||
# Short GI for 20 MHz: [SHORT-GI-20] (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)
|
# Short GI for 40 MHz: [SHORT-GI-40] (disabled if not set)
|
||||||
@ -634,6 +635,9 @@ ieee80211n=1
|
|||||||
# Note: hw_mode=a is used to specify that 5 GHz band is used with VHT.
|
# Note: hw_mode=a is used to specify that 5 GHz band is used with VHT.
|
||||||
#ieee80211ac=1
|
#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_capab: VHT capabilities (list of flags)
|
||||||
#
|
#
|
||||||
# vht_max_mpdu_len: [MAX-MPDU-7991] [MAX-MPDU-11454]
|
# vht_max_mpdu_len: [MAX-MPDU-7991] [MAX-MPDU-11454]
|
||||||
@ -788,6 +792,9 @@ ieee80211n=1
|
|||||||
# 1 = enabled
|
# 1 = enabled
|
||||||
#ieee80211ax=1
|
#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
|
#he_su_beamformer: HE single user beamformer support
|
||||||
# 0 = not supported (default)
|
# 0 = not supported (default)
|
||||||
# 1 = supported
|
# 1 = supported
|
||||||
@ -806,6 +813,9 @@ ieee80211n=1
|
|||||||
# he_bss_color: BSS color (1-63)
|
# he_bss_color: BSS color (1-63)
|
||||||
#he_bss_color=1
|
#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
|
#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
|
# Possible values are 0 us (default), 4 us, 8 us, 12 us, and 16 us
|
||||||
#he_default_pe_duration=0
|
#he_default_pe_duration=0
|
||||||
@ -821,11 +831,11 @@ ieee80211n=1
|
|||||||
#he_rts_threshold=0
|
#he_rts_threshold=0
|
||||||
|
|
||||||
# HE operating channel information; see matching vht_* parameters for details.
|
# HE operating channel information; see matching vht_* parameters for details.
|
||||||
# On the 6 GHz band the center freq calculation starts from 5.940 GHz offset.
|
# On the 6 GHz band the center freq calculation starts from 5.950 GHz offset.
|
||||||
# For example idx=3 would result in 5955 MHz center frequency. In addition,
|
# 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
|
# he_oper_chwidth is ignored, and the channel width is derived from the
|
||||||
# configured operating class or center frequency indexes (see
|
# configured operating class or center frequency indexes (see
|
||||||
# IEEE P802.11ax/D4.3 Annex E, Table E-4).
|
# IEEE P802.11ax/D6.1 Annex E, Table E-4).
|
||||||
#he_oper_chwidth
|
#he_oper_chwidth
|
||||||
#he_oper_centr_freq_seg0_idx
|
#he_oper_centr_freq_seg0_idx
|
||||||
#he_oper_centr_freq_seg1_idx
|
#he_oper_centr_freq_seg1_idx
|
||||||
@ -903,6 +913,8 @@ eapol_key_index_workaround=0
|
|||||||
|
|
||||||
# EAP reauthentication period in seconds (default: 3600 seconds; 0 = disable
|
# EAP reauthentication period in seconds (default: 3600 seconds; 0 = disable
|
||||||
# reauthentication).
|
# reauthentication).
|
||||||
|
# Note: Reauthentications may enforce a disconnection, check the related
|
||||||
|
# parameter wpa_deny_ptk0_rekey for details.
|
||||||
#eap_reauth_period=3600
|
#eap_reauth_period=3600
|
||||||
|
|
||||||
# Use PAE group address (01:80:c2:00:00:03) instead of individual target
|
# Use PAE group address (01:80:c2:00:00:03) instead of individual target
|
||||||
@ -1199,7 +1211,7 @@ eap_server=0
|
|||||||
# should be unique across all issuing servers. In theory, this is a variable
|
# 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
|
# 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
|
# 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.
|
# field is configured in hex format.
|
||||||
#eap_fast_a_id=101112131415161718191a1b1c1d1e1f
|
#eap_fast_a_id=101112131415161718191a1b1c1d1e1f
|
||||||
|
|
||||||
@ -1226,6 +1238,8 @@ eap_server=0
|
|||||||
# EAP-TEAP authentication type
|
# EAP-TEAP authentication type
|
||||||
# 0 = inner EAP (default)
|
# 0 = inner EAP (default)
|
||||||
# 1 = Basic-Password-Auth
|
# 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_auth=0
|
||||||
|
|
||||||
# EAP-TEAP authentication behavior when using PAC
|
# EAP-TEAP authentication behavior when using PAC
|
||||||
@ -1507,6 +1521,17 @@ own_ip_addr=127.0.0.1
|
|||||||
# wpa_key_mgmt=SAE for WPA3-Personal instead of wpa_key_mgmt=WPA-PSK).
|
# wpa_key_mgmt=SAE for WPA3-Personal instead of wpa_key_mgmt=WPA-PSK).
|
||||||
wpa=2
|
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
|
# 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
|
# 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
|
# (8..63 characters) that will be converted to PSK. This conversion uses SSID
|
||||||
@ -1607,8 +1632,26 @@ group_cipher=CCMP
|
|||||||
|
|
||||||
# Maximum lifetime for PTK in seconds. This can be used to enforce rekeying of
|
# Maximum lifetime for PTK in seconds. This can be used to enforce rekeying of
|
||||||
# PTK to mitigate some attacks against TKIP deficiencies.
|
# 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
|
#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
|
# 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.
|
# Handshake are retried per 4-Way Handshake attempt.
|
||||||
# (dot11RSNAConfigPairwiseUpdateCount)
|
# (dot11RSNAConfigPairwiseUpdateCount)
|
||||||
@ -1677,6 +1720,12 @@ wpa_pairwise_update_count=100
|
|||||||
# available in deployed devices.
|
# available in deployed devices.
|
||||||
#group_mgmt_cipher=AES-128-CMAC
|
#group_mgmt_cipher=AES-128-CMAC
|
||||||
|
|
||||||
|
# Beacon Protection (management frame protection for Beacon frames)
|
||||||
|
# This depends on management frame protection being enabled (ieee80211w != 0).
|
||||||
|
# 0 = disabled (default)
|
||||||
|
# 1 = enabled
|
||||||
|
#beacon_prot=0
|
||||||
|
|
||||||
# Association SA Query maximum timeout (in TU = 1.024 ms; for MFP)
|
# Association SA Query maximum timeout (in TU = 1.024 ms; for MFP)
|
||||||
# (maximum time to wait for a SA Query response)
|
# (maximum time to wait for a SA Query response)
|
||||||
# dot11AssociationSAQueryMaximumTimeout, 1...4294967295
|
# dot11AssociationSAQueryMaximumTimeout, 1...4294967295
|
||||||
@ -1692,6 +1741,19 @@ wpa_pairwise_update_count=100
|
|||||||
# Enabling this automatically also enables ieee80211w, if not yet enabled.
|
# Enabling this automatically also enables ieee80211w, if not yet enabled.
|
||||||
# 0 = disabled (default)
|
# 0 = disabled (default)
|
||||||
# 1 = enabled
|
# 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
|
#ocv=1
|
||||||
|
|
||||||
# disable_pmksa_caching: Disable PMKSA caching
|
# disable_pmksa_caching: Disable PMKSA caching
|
||||||
@ -1723,7 +1785,7 @@ wpa_pairwise_update_count=100
|
|||||||
# be followed by optional peer MAC address (dot11RSNAConfigPasswordPeerMac) and
|
# be followed by optional peer MAC address (dot11RSNAConfigPasswordPeerMac) and
|
||||||
# by optional password identifier (dot11RSNAConfigPasswordIdentifier). In
|
# by optional password identifier (dot11RSNAConfigPasswordIdentifier). In
|
||||||
# addition, an optional VLAN ID specification can be used to bind the station
|
# 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
|
# 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
|
# (ff:ff:ff:ff:ff:ff), the entry is available for any station to use. If a
|
||||||
@ -1738,7 +1800,8 @@ wpa_pairwise_update_count=100
|
|||||||
# special meaning of removing all previously added entries.
|
# special meaning of removing all previously added entries.
|
||||||
#
|
#
|
||||||
# sae_password uses the following encoding:
|
# 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:
|
# Examples:
|
||||||
#sae_password=secret
|
#sae_password=secret
|
||||||
#sae_password=really secret|mac=ff:ff:ff:ff:ff:ff
|
#sae_password=really secret|mac=ff:ff:ff:ff:ff:ff
|
||||||
@ -1867,6 +1930,23 @@ wpa_pairwise_update_count=100
|
|||||||
# default: 30 TUs (= 30.72 milliseconds)
|
# default: 30 TUs (= 30.72 milliseconds)
|
||||||
#fils_hlp_wait_time=30
|
#fils_hlp_wait_time=30
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
##### IEEE 802.11r configuration ##############################################
|
##### IEEE 802.11r configuration ##############################################
|
||||||
|
|
||||||
# Mobility Domain identifier (dot11FTMobilityDomainID, MDID)
|
# Mobility Domain identifier (dot11FTMobilityDomainID, MDID)
|
||||||
@ -1910,7 +1990,7 @@ wpa_pairwise_update_count=100
|
|||||||
# Wildcard entry:
|
# Wildcard entry:
|
||||||
# Upon receiving a response from R0KH, it will be added to this list, so
|
# 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
|
# 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
|
#r0kh=ff:ff:ff:ff:ff:ff * 00112233445566778899aabbccddeeff
|
||||||
|
|
||||||
# List of R1KHs in the same Mobility Domain
|
# List of R1KHs in the same Mobility Domain
|
||||||
@ -1966,7 +2046,7 @@ wpa_pairwise_update_count=100
|
|||||||
#ft_psk_generate_local=0
|
#ft_psk_generate_local=0
|
||||||
|
|
||||||
##### Neighbor table ##########################################################
|
##### 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
|
# detecting Overlapping Legacy BSS Condition). The oldest entry will be
|
||||||
# removed when adding a new entry that would make the list grow over this
|
# 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
|
# limit. Note! WFA certification for IEEE 802.11g requires that OLBC is
|
||||||
@ -2249,6 +2329,17 @@ wpa_pairwise_update_count=100
|
|||||||
#dpp_csign
|
#dpp_csign
|
||||||
#dpp_controller
|
#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) #################################################
|
#### TDLS (IEEE 802.11z-2010) #################################################
|
||||||
|
|
||||||
# Prohibit use of TDLS in this BSS
|
# Prohibit use of TDLS in this BSS
|
||||||
@ -2644,6 +2735,10 @@ wpa_pairwise_update_count=100
|
|||||||
# threshold (range: 0..255, default=30).
|
# threshold (range: 0..255, default=30).
|
||||||
#rssi_reject_assoc_timeout=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 #####################################
|
##### Fast Session Transfer (FST) support #####################################
|
||||||
#
|
#
|
||||||
# The options in this section are only available when the build configuration
|
# The options in this section are only available when the build configuration
|
||||||
|
@ -975,7 +975,7 @@ static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
|
|||||||
dir = opendir(ctrl_iface_dir);
|
dir = opendir(ctrl_iface_dir);
|
||||||
if (dir == NULL) {
|
if (dir == NULL) {
|
||||||
printf("Control interface directory '%s' could not be "
|
printf("Control interface directory '%s' could not be "
|
||||||
"openned.\n", ctrl_iface_dir);
|
"opened.\n", ctrl_iface_dir);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1227,14 +1227,15 @@ static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
|||||||
char cmd[256];
|
char cmd[256];
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
if (argc < 2 || argc > 3) {
|
if (argc < 2 || argc > 4) {
|
||||||
printf("Invalid vendor command\n"
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s", argv[0], argv[1],
|
res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s%s%s", argv[0],
|
||||||
argc == 3 ? argv[2] : "");
|
argv[1], argc >= 3 ? argv[2] : "",
|
||||||
|
argc == 4 ? " " : "", argc == 4 ? argv[3] : "");
|
||||||
if (os_snprintf_error(sizeof(cmd), res)) {
|
if (os_snprintf_error(sizeof(cmd), res)) {
|
||||||
printf("Too long VENDOR command.\n");
|
printf("Too long VENDOR command.\n");
|
||||||
return -1;
|
return -1;
|
||||||
@ -1402,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,
|
static int hostapd_cli_cmd_dpp_auth_init(struct wpa_ctrl *ctrl, int argc,
|
||||||
char *argv[])
|
char *argv[])
|
||||||
{
|
{
|
||||||
@ -1464,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);
|
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 */
|
#endif /* CONFIG_DPP */
|
||||||
|
|
||||||
|
|
||||||
@ -1650,6 +1689,8 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
|
|||||||
"<id> = get DPP bootstrap URI" },
|
"<id> = get DPP bootstrap URI" },
|
||||||
{ "dpp_bootstrap_info", hostapd_cli_cmd_dpp_bootstrap_info, NULL,
|
{ "dpp_bootstrap_info", hostapd_cli_cmd_dpp_bootstrap_info, NULL,
|
||||||
"<id> = show DPP bootstrap information" },
|
"<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,
|
{ "dpp_auth_init", hostapd_cli_cmd_dpp_auth_init, NULL,
|
||||||
"peer=<id> [own=<id>] = initiate DPP bootstrapping" },
|
"peer=<id> [own=<id>] = initiate DPP bootstrapping" },
|
||||||
{ "dpp_listen", hostapd_cli_cmd_dpp_listen, NULL,
|
{ "dpp_listen", hostapd_cli_cmd_dpp_listen, NULL,
|
||||||
@ -1670,6 +1711,16 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
|
|||||||
"add PKEX code" },
|
"add PKEX code" },
|
||||||
{ "dpp_pkex_remove", hostapd_cli_cmd_dpp_pkex_remove, NULL,
|
{ "dpp_pkex_remove", hostapd_cli_cmd_dpp_pkex_remove, NULL,
|
||||||
"*|<id> = remove DPP pkex information" },
|
"*|<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 */
|
#endif /* CONFIG_DPP */
|
||||||
{ "accept_acl", hostapd_cli_cmd_accept_macacl, NULL,
|
{ "accept_acl", hostapd_cli_cmd_accept_macacl, NULL,
|
||||||
"=Add/Delete/Show/Clear accept MAC ACL" },
|
"=Add/Delete/Show/Clear accept MAC ACL" },
|
||||||
|
@ -218,7 +218,7 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
|
|||||||
struct wowlan_triggers *triggs;
|
struct wowlan_triggers *triggs;
|
||||||
|
|
||||||
iface->drv_flags = capa.flags;
|
iface->drv_flags = capa.flags;
|
||||||
iface->smps_modes = capa.smps_modes;
|
iface->drv_flags2 = capa.flags2;
|
||||||
iface->probe_resp_offloads = capa.probe_resp_offloads;
|
iface->probe_resp_offloads = capa.probe_resp_offloads;
|
||||||
/*
|
/*
|
||||||
* Use default extended capa values from per-radio information
|
* Use default extended capa values from per-radio information
|
||||||
@ -451,11 +451,12 @@ static int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize,
|
|||||||
static void show_version(void)
|
static void show_version(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"hostapd v" VERSION_STR "\n"
|
"hostapd v%s\n"
|
||||||
"User space daemon for IEEE 802.11 AP management,\n"
|
"User space daemon for IEEE 802.11 AP management,\n"
|
||||||
"IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
|
"IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
|
||||||
"Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi> "
|
"Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi> "
|
||||||
"and contributors\n");
|
"and contributors\n",
|
||||||
|
VERSION_STR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -673,7 +674,10 @@ int main(int argc, char *argv[])
|
|||||||
#endif /* CONFIG_ETH_P_OUI */
|
#endif /* CONFIG_ETH_P_OUI */
|
||||||
#ifdef CONFIG_DPP
|
#ifdef CONFIG_DPP
|
||||||
os_memset(&dpp_conf, 0, sizeof(dpp_conf));
|
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);
|
interfaces.dpp = dpp_global_init(&dpp_conf);
|
||||||
if (!interfaces.dpp)
|
if (!interfaces.dpp)
|
||||||
return -1;
|
return -1;
|
||||||
@ -902,8 +906,11 @@ int main(int argc, char *argv[])
|
|||||||
!!(interfaces.iface[i]->drv_flags &
|
!!(interfaces.iface[i]->drv_flags &
|
||||||
WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
|
WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
|
||||||
hostapd_interface_deinit_free(interfaces.iface[i]);
|
hostapd_interface_deinit_free(interfaces.iface[i]);
|
||||||
|
interfaces.iface[i] = NULL;
|
||||||
}
|
}
|
||||||
os_free(interfaces.iface);
|
os_free(interfaces.iface);
|
||||||
|
interfaces.iface = NULL;
|
||||||
|
interfaces.count = 0;
|
||||||
|
|
||||||
#ifdef CONFIG_DPP
|
#ifdef CONFIG_DPP
|
||||||
dpp_global_deinit(interfaces.dpp);
|
dpp_global_deinit(interfaces.dpp);
|
||||||
|
196
hostapd/sae_pk_gen.c
Normal file
196
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
|
include ../../src/build.rules
|
||||||
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
|
|
||||||
|
|
||||||
CFLAGS += -I../../src/utils
|
CFLAGS += -I../../src/utils
|
||||||
CFLAGS += -I../../src/common
|
CFLAGS += -I../../src/common
|
||||||
@ -30,8 +8,17 @@ CFLAGS += -I../../src
|
|||||||
|
|
||||||
ifndef CONFIG_NO_BROWSER
|
ifndef CONFIG_NO_BROWSER
|
||||||
ifndef CONFIG_BROWSER_SYSTEM
|
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)
|
GTKCFLAGS := $(shell pkg-config --cflags gtk+-3.0 webkitgtk-3.0)
|
||||||
GTKLIBS := $(shell pkg-config --libs gtk+-3.0 webkitgtk-3.0)
|
GTKLIBS := $(shell pkg-config --libs gtk+-3.0 webkitgtk-3.0)
|
||||||
|
endif
|
||||||
|
|
||||||
CFLAGS += $(GTKCFLAGS)
|
CFLAGS += $(GTKCFLAGS)
|
||||||
LIBS += $(GTKLIBS)
|
LIBS += $(GTKLIBS)
|
||||||
endif
|
endif
|
||||||
@ -84,23 +71,11 @@ CFLAGS += -DEAP_TLS_OPENSSL
|
|||||||
OBJS += ../../src/crypto/tls_openssl_ocsp.o
|
OBJS += ../../src/crypto/tls_openssl_ocsp.o
|
||||||
LIBS += -lssl -lcrypto
|
LIBS += -lssl -lcrypto
|
||||||
|
|
||||||
|
_OBJS_VAR := OBJS
|
||||||
|
include ../../src/objs.mk
|
||||||
hs20-osu-client: $(OBJS)
|
hs20-osu-client: $(OBJS)
|
||||||
$(Q)$(LDO) $(LDFLAGS) -o hs20-osu-client $(OBJS) $(LIBS)
|
$(Q)$(LDO) $(LDFLAGS) -o hs20-osu-client $(OBJS) $(LIBS)
|
||||||
@$(E) " LD " $@
|
@$(E) " LD " $@
|
||||||
|
|
||||||
%.o: %.c
|
clean: common-clean
|
||||||
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
|
rm -f core *~
|
||||||
@$(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)
|
|
||||||
|
@ -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, "Data: %s", data);
|
||||||
wpa_printf(MSG_INFO, "Launch browser to URI '%s'", data);
|
wpa_printf(MSG_INFO, "Launch browser to URI '%s'", data);
|
||||||
write_summary(ctx, "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);
|
xml_node_get_text_free(ctx->xml, data);
|
||||||
if (res > 0) {
|
if (res > 0) {
|
||||||
wpa_printf(MSG_INFO, "User response in browser completed successfully");
|
wpa_printf(MSG_INFO, "User response in browser completed successfully");
|
||||||
|
@ -2233,7 +2233,7 @@ static int osu_connect(struct hs20_osu_client *ctx, const char *bssid,
|
|||||||
wpa_ctrl_close(mon);
|
wpa_ctrl_close(mon);
|
||||||
|
|
||||||
if (res < 0) {
|
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");
|
write_summary(ctx, "Could not connect to OSU network");
|
||||||
wpa_printf(MSG_INFO, "Remove OSU network connection");
|
wpa_printf(MSG_INFO, "Remove OSU network connection");
|
||||||
snprintf(buf, sizeof(buf), "REMOVE_NETWORK %d", id);
|
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);
|
snprintf(fname, sizeof(fname), "file://%s/osu-providers.html", dir);
|
||||||
write_summary(ctx, "Start web browser with OSU provider selection page");
|
write_summary(ctx, "Start web browser with OSU provider selection page");
|
||||||
ret = hs20_web_browser(fname);
|
ret = hs20_web_browser(fname, 0);
|
||||||
|
|
||||||
selected:
|
selected:
|
||||||
if (ret > 0 && (size_t) ret <= osu_count) {
|
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)
|
static int osu_cert_cb(void *_ctx, struct http_cert *cert)
|
||||||
{
|
{
|
||||||
struct hs20_osu_client *ctx = _ctx;
|
struct hs20_osu_client *ctx = _ctx;
|
||||||
unsigned int i, j;
|
size_t i, j;
|
||||||
int found;
|
int found;
|
||||||
char *host = NULL;
|
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);
|
size_t name_len = os_strlen(name);
|
||||||
|
|
||||||
wpa_printf(MSG_INFO,
|
wpa_printf(MSG_INFO,
|
||||||
"[%i] Looking for icon file name '%s' match",
|
"[%zu] Looking for icon file name '%s' match",
|
||||||
j, name);
|
j, name);
|
||||||
for (i = 0; i < cert->num_logo; i++) {
|
for (i = 0; i < cert->num_logo; i++) {
|
||||||
struct http_logo *logo = &cert->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;
|
char *pos;
|
||||||
|
|
||||||
wpa_printf(MSG_INFO,
|
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);
|
i, logo->uri, (int) uri_len, (int) name_len);
|
||||||
if (uri_len < 1 + name_len) {
|
if (uri_len < 1 + name_len) {
|
||||||
wpa_printf(MSG_INFO, "URI Length is too short");
|
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) {
|
if (logo->hash_len != 32) {
|
||||||
wpa_printf(MSG_INFO,
|
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);
|
j, i, (int) logo->hash_len);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -3054,7 +3054,7 @@ static int osu_cert_cb(void *_ctx, struct http_cert *cert)
|
|||||||
}
|
}
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG,
|
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",
|
wpa_hexdump_ascii(MSG_DEBUG, "logo->hash",
|
||||||
logo->hash, 32);
|
logo->hash, 32);
|
||||||
wpa_hexdump_ascii(MSG_DEBUG, "ctx->icon_hash[j]",
|
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)
|
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>] "
|
" [-w<wpa_supplicant ctrl_iface dir>] "
|
||||||
"[-r<result file>] [-f<debug file>] \\\n"
|
"[-r<result file>] [-f<debug file>] \\\n"
|
||||||
" [-s<summary file>] \\\n"
|
" [-s<summary file>] \\\n"
|
||||||
@ -3198,7 +3198,7 @@ int main(int argc, char *argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
for (;;) {
|
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)
|
if (c < 0)
|
||||||
break;
|
break;
|
||||||
switch (c) {
|
switch (c) {
|
||||||
@ -3236,6 +3236,9 @@ int main(int argc, char *argv[])
|
|||||||
case 't':
|
case 't':
|
||||||
wpa_debug_timestamp++;
|
wpa_debug_timestamp++;
|
||||||
break;
|
break;
|
||||||
|
case 'T':
|
||||||
|
ctx.ignore_tls = 1;
|
||||||
|
break;
|
||||||
case 'w':
|
case 'w':
|
||||||
wpas_ctrl_path = optarg;
|
wpas_ctrl_path = optarg;
|
||||||
break;
|
break;
|
||||||
@ -3403,7 +3406,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
wpa_printf(MSG_INFO, "Launch web browser to URL %s",
|
wpa_printf(MSG_INFO, "Launch web browser to URL %s",
|
||||||
argv[optind + 1]);
|
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);
|
wpa_printf(MSG_INFO, "Web browser result: %d", ret);
|
||||||
} else if (strcmp(argv[optind], "parse_cert") == 0) {
|
} else if (strcmp(argv[optind], "parse_cert") == 0) {
|
||||||
if (argc - optind < 2) {
|
if (argc - optind < 2) {
|
||||||
|
@ -50,6 +50,8 @@ struct hs20_osu_client {
|
|||||||
const char *osu_ssid; /* Enforced OSU_SSID for testing purposes */
|
const char *osu_ssid; /* Enforced OSU_SSID for testing purposes */
|
||||||
#define WORKAROUND_OCSP_OPTIONAL 0x00000001
|
#define WORKAROUND_OCSP_OPTIONAL 0x00000001
|
||||||
unsigned long int workarounds;
|
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);
|
wpa_printf(MSG_INFO, "Launch browser to URI '%s'", uri);
|
||||||
write_summary(ctx, "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);
|
xml_node_get_text_free(ctx->xml, uri);
|
||||||
if (res > 0) {
|
if (res > 0) {
|
||||||
wpa_printf(MSG_INFO, "User response in browser completed successfully - sessionid='%s'",
|
wpa_printf(MSG_INFO, "User response in browser completed successfully - sessionid='%s'",
|
||||||
|
1
hs20/server/.gitignore
vendored
Normal file
1
hs20/server/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
hs20_spp_server
|
@ -1,16 +1,6 @@
|
|||||||
all: hs20_spp_server
|
ALL=hs20_spp_server
|
||||||
|
|
||||||
ifndef CC
|
include ../../src/build.rules
|
||||||
CC=gcc
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifndef LDO
|
|
||||||
LDO=$(CC)
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifndef CFLAGS
|
|
||||||
CFLAGS = -MMD -O2 -Wall -g
|
|
||||||
endif
|
|
||||||
|
|
||||||
CFLAGS += -I../../src
|
CFLAGS += -I../../src
|
||||||
CFLAGS += -I../../src/utils
|
CFLAGS += -I../../src/utils
|
||||||
@ -43,14 +33,10 @@ CFLAGS += $(shell xml2-config --cflags)
|
|||||||
LIBS += $(shell xml2-config --libs)
|
LIBS += $(shell xml2-config --libs)
|
||||||
OBJS += ../../src/utils/xml_libxml2.o
|
OBJS += ../../src/utils/xml_libxml2.o
|
||||||
|
|
||||||
|
_OBJS_VAR := OBJS
|
||||||
|
include ../../src/objs.mk
|
||||||
hs20_spp_server: $(OBJS)
|
hs20_spp_server: $(OBJS)
|
||||||
$(LDO) $(LDFLAGS) -o hs20_spp_server $(OBJS) $(LIBS)
|
$(LDO) $(LDFLAGS) -o hs20_spp_server $(OBJS) $(LIBS)
|
||||||
|
|
||||||
clean:
|
clean: common-clean
|
||||||
rm -f core *~ *.o *.d hs20_spp_server
|
rm -f core *~
|
||||||
rm -f ../../src/utils/*.o
|
|
||||||
rm -f ../../src/utils/*.d
|
|
||||||
rm -f ../../src/crypto/*.o
|
|
||||||
rm -f ../../src/crypto/*.d
|
|
||||||
|
|
||||||
-include $(OBJS:%.o=%.d)
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
openssl ocsp -index demoCA/index.txt -port 8888 -nmin 5 -rsigner ocsp.pem -rkey ocsp.key -CA demoCA/cacert.pem -text
|
openssl ocsp -index demoCA/index.txt -port 8888 -nmin 5 -rsigner ocsp.pem -rkey ocsp.key -CA demoCA/cacert.pem -text -ignore_err
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
|
# NOTE: You may need to replace 'localhost' with your OCSP server hostname.
|
||||||
openssl ocsp \
|
openssl ocsp \
|
||||||
-no_nonce \
|
-no_nonce \
|
||||||
-CAfile ca.pem \
|
-CAfile ca.pem \
|
||||||
|
@ -176,7 +176,7 @@ int main(int argc, char *argv[])
|
|||||||
ctx.root_dir = optarg;
|
ctx.root_dir = optarg;
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
printf("hs20_spp_server v" VERSION_STR "\n");
|
printf("hs20_spp_server v%s\n", VERSION_STR);
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
|
@ -1,18 +1,6 @@
|
|||||||
ALL=radius_example
|
ALL=radius_example
|
||||||
|
|
||||||
all: $(ALL)
|
include ../src/build.rules
|
||||||
|
|
||||||
ifndef CC
|
|
||||||
CC=gcc
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifndef LDO
|
|
||||||
LDO=$(CC)
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifndef CFLAGS
|
|
||||||
CFLAGS = -MMD -O2 -Wall -g
|
|
||||||
endif
|
|
||||||
|
|
||||||
CFLAGS += -I.
|
CFLAGS += -I.
|
||||||
CFLAGS += -I../src
|
CFLAGS += -I../src
|
||||||
@ -23,24 +11,18 @@ LIBS += ../src/crypto/libcrypto.a
|
|||||||
LIBS += ../src/utils/libutils.a
|
LIBS += ../src/utils/libutils.a
|
||||||
LLIBS = -lrt
|
LLIBS = -lrt
|
||||||
|
|
||||||
../src/utils/libutils.a:
|
|
||||||
$(MAKE) -C ../src/utils
|
|
||||||
|
|
||||||
../src/crypto/libcrypto.a:
|
|
||||||
$(MAKE) -C ../src/crypto
|
|
||||||
|
|
||||||
../src/radius/libradius.a:
|
|
||||||
$(MAKE) -C ../src/radius
|
|
||||||
|
|
||||||
#CLAGS += -DCONFIG_IPV6
|
#CLAGS += -DCONFIG_IPV6
|
||||||
|
|
||||||
OBJS_ex = radius_example.o
|
OBJS_ex = radius_example.o
|
||||||
|
|
||||||
|
_OBJS_VAR := OBJS_ex
|
||||||
|
include ../src/objs.mk
|
||||||
|
|
||||||
|
_OBJS_VAR := LIBS
|
||||||
|
include ../src/objs.mk
|
||||||
|
|
||||||
radius_example: $(OBJS_ex) $(LIBS)
|
radius_example: $(OBJS_ex) $(LIBS)
|
||||||
$(LDO) $(LDFLAGS) -o radius_example $(OBJS_ex) $(LIBS) $(LLIBS)
|
$(LDO) $(LDFLAGS) -o radius_example $(OBJS_ex) $(LIBS) $(LLIBS)
|
||||||
|
|
||||||
clean:
|
clean: common-clean
|
||||||
$(MAKE) -C ../src clean
|
rm -f core *~ *.o *.d
|
||||||
rm -f core *~ *.o *.d $(ALL)
|
|
||||||
|
|
||||||
-include $(OBJS:%.o=%.d)
|
|
||||||
|
@ -5,8 +5,8 @@ all:
|
|||||||
for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d; done
|
for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d; done
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d clean; done
|
$(Q)for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d clean; done
|
||||||
rm -f *~
|
$(Q)rm -f *~
|
||||||
|
|
||||||
install:
|
install:
|
||||||
for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d install; done
|
for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d install; done
|
||||||
|
@ -1,13 +1,3 @@
|
|||||||
all: libap.a
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f *~ *.o *.d *.gcno *.gcda *.gcov libap.a
|
|
||||||
|
|
||||||
install:
|
|
||||||
@echo Nothing to be made.
|
|
||||||
|
|
||||||
include ../lib.rules
|
|
||||||
|
|
||||||
CFLAGS += -DHOSTAPD
|
CFLAGS += -DHOSTAPD
|
||||||
CFLAGS += -DNEED_AP_MLME
|
CFLAGS += -DNEED_AP_MLME
|
||||||
CFLAGS += -DCONFIG_ETH_P_OUI
|
CFLAGS += -DCONFIG_ETH_P_OUI
|
||||||
@ -67,7 +57,4 @@ LIB_OBJS= \
|
|||||||
wps_hostapd.o \
|
wps_hostapd.o \
|
||||||
x_snoop.o
|
x_snoop.o
|
||||||
|
|
||||||
libap.a: $(LIB_OBJS)
|
include ../lib.rules
|
||||||
$(AR) crT $@ $?
|
|
||||||
|
|
||||||
-include $(OBJS:%.o=%.d)
|
|
||||||
|
300
src/ap/acs.c
300
src/ap/acs.c
@ -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;
|
int i;
|
||||||
struct hostapd_channel_data *chan;
|
struct hostapd_channel_data *chan;
|
||||||
|
|
||||||
for (i = 0; i < iface->current_mode->num_channels; i++) {
|
for (i = 0; i < mode->num_channels; i++) {
|
||||||
chan = &iface->current_mode->channels[i];
|
chan = &mode->channels[i];
|
||||||
|
|
||||||
if (chan->flag & HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED)
|
if (chan->flag & HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED)
|
||||||
acs_clean_chan_surveys(chan);
|
acs_clean_chan_surveys(chan);
|
||||||
@ -276,6 +276,15 @@ void acs_cleanup(struct hostapd_iface *iface)
|
|||||||
chan->flag |= HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED;
|
chan->flag |= HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED;
|
||||||
chan->min_nf = 0;
|
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->chans_surveyed = 0;
|
||||||
iface->acs_num_completed_scans = 0;
|
iface->acs_num_completed_scans = 0;
|
||||||
@ -453,21 +462,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;
|
int i;
|
||||||
struct hostapd_channel_data *chan;
|
struct hostapd_channel_data *chan;
|
||||||
int valid = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < iface->current_mode->num_channels; i++) {
|
for (i = 0; i < mode->num_channels; i++) {
|
||||||
chan = &iface->current_mode->channels[i];
|
chan = &mode->channels[i];
|
||||||
if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
|
if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
|
||||||
acs_survey_list_is_sufficient(chan))
|
acs_survey_list_is_sufficient(chan))
|
||||||
valid++;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We need at least survey data for one channel */
|
return 0;
|
||||||
return !!valid;
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 +512,25 @@ static int is_in_chanlist(struct hostapd_iface *iface,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void acs_survey_all_chans_intereference_factor(
|
static int is_in_freqlist(struct hostapd_iface *iface,
|
||||||
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;
|
int i;
|
||||||
struct hostapd_channel_data *chan;
|
struct hostapd_channel_data *chan;
|
||||||
|
|
||||||
for (i = 0; i < iface->current_mode->num_channels; i++) {
|
for (i = 0; i < mode->num_channels; i++) {
|
||||||
chan = &iface->current_mode->channels[i];
|
chan = &mode->channels[i];
|
||||||
|
|
||||||
if (!acs_usable_chan(chan))
|
if (!acs_usable_chan(chan))
|
||||||
continue;
|
continue;
|
||||||
@ -504,6 +538,9 @@ static void acs_survey_all_chans_intereference_factor(
|
|||||||
if (!is_in_chanlist(iface, chan))
|
if (!is_in_chanlist(iface, chan))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (!is_in_freqlist(iface, chan))
|
||||||
|
continue;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "ACS: Survey analysis for channel %d (%d MHz)",
|
wpa_printf(MSG_DEBUG, "ACS: Survey analysis for channel %d (%d MHz)",
|
||||||
chan->chan, chan->freq);
|
chan->chan, chan->freq);
|
||||||
|
|
||||||
@ -515,14 +552,28 @@ static void acs_survey_all_chans_intereference_factor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct hostapd_channel_data *acs_find_chan(struct hostapd_iface *iface,
|
static void acs_survey_all_chans_interference_factor(
|
||||||
int freq)
|
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;
|
struct hostapd_channel_data *chan;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < iface->current_mode->num_channels; i++) {
|
for (i = 0; i < mode->num_channels; i++) {
|
||||||
chan = &iface->current_mode->channels[i];
|
chan = &mode->channels[i];
|
||||||
|
|
||||||
if (chan->flag & HOSTAPD_CHAN_DISABLED)
|
if (chan->flag & HOSTAPD_CHAN_DISABLED)
|
||||||
continue;
|
continue;
|
||||||
@ -535,6 +586,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)
|
static int is_24ghz_mode(enum hostapd_hw_mode mode)
|
||||||
{
|
{
|
||||||
return mode == HOSTAPD_MODE_IEEE80211B ||
|
return mode == HOSTAPD_MODE_IEEE80211B ||
|
||||||
@ -565,58 +636,24 @@ static int is_common_24ghz_chan(int chan)
|
|||||||
#define ACS_24GHZ_PREFER_1_6_11 0.8
|
#define ACS_24GHZ_PREFER_1_6_11 0.8
|
||||||
#endif /* ACS_24GHZ_PREFER_1_6_11 */
|
#endif /* ACS_24GHZ_PREFER_1_6_11 */
|
||||||
|
|
||||||
/*
|
static void
|
||||||
* At this point it's assumed chan->interface_factor has been computed.
|
acs_find_ideal_chan_mode(struct hostapd_iface *iface,
|
||||||
* This function should be reusable regardless of interference computation
|
struct hostapd_hw_modes *mode,
|
||||||
* option (survey, BSS, spectral, ...). chan->interference factor must be
|
int n_chans, u32 bw,
|
||||||
* summable (i.e., must be always greater than zero).
|
struct hostapd_channel_data **rand_chan,
|
||||||
*/
|
struct hostapd_channel_data **ideal_chan,
|
||||||
static struct hostapd_channel_data *
|
long double *ideal_factor)
|
||||||
acs_find_ideal_chan(struct hostapd_iface *iface)
|
|
||||||
{
|
{
|
||||||
struct hostapd_channel_data *chan, *adj_chan, *ideal_chan = NULL,
|
struct hostapd_channel_data *chan, *adj_chan = NULL;
|
||||||
*rand_chan = NULL;
|
long double factor;
|
||||||
long double factor, ideal_factor = 0;
|
|
||||||
int i, j;
|
int i, j;
|
||||||
int n_chans = 1;
|
|
||||||
u32 bw;
|
|
||||||
unsigned int k;
|
unsigned int k;
|
||||||
|
|
||||||
/* TODO: HT40- support */
|
for (i = 0; i < mode->num_channels; i++) {
|
||||||
|
|
||||||
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++) {
|
|
||||||
double total_weight;
|
double total_weight;
|
||||||
struct acs_bias *bias, tmp_bias;
|
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
|
/* Since in the current ACS implementation the first channel is
|
||||||
* always a primary channel, skip channels not available as
|
* always a primary channel, skip channels not available as
|
||||||
@ -628,6 +665,9 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
|
|||||||
if (!is_in_chanlist(iface, chan))
|
if (!is_in_chanlist(iface, chan))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (!is_in_freqlist(iface, chan))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (!chan_bw_allowed(chan, bw, 1, 1)) {
|
if (!chan_bw_allowed(chan, bw, 1, 1)) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"ACS: Channel %d: BW %u is not supported",
|
"ACS: Channel %d: BW %u is not supported",
|
||||||
@ -637,7 +677,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
|
|||||||
|
|
||||||
/* HT40 on 5 GHz has a limited set of primary channels as per
|
/* HT40 on 5 GHz has a limited set of primary channels as per
|
||||||
* 11n Annex J */
|
* 11n Annex J */
|
||||||
if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
|
if (mode->mode == HOSTAPD_MODE_IEEE80211A &&
|
||||||
iface->conf->ieee80211n &&
|
iface->conf->ieee80211n &&
|
||||||
iface->conf->secondary_channel &&
|
iface->conf->secondary_channel &&
|
||||||
!acs_usable_ht40_chan(chan)) {
|
!acs_usable_ht40_chan(chan)) {
|
||||||
@ -646,7 +686,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
|
if (mode->mode == HOSTAPD_MODE_IEEE80211A &&
|
||||||
(iface->conf->ieee80211ac || iface->conf->ieee80211ax)) {
|
(iface->conf->ieee80211ac || iface->conf->ieee80211ax)) {
|
||||||
if (hostapd_get_oper_chwidth(iface->conf) ==
|
if (hostapd_get_oper_chwidth(iface->conf) ==
|
||||||
CHANWIDTH_80MHZ &&
|
CHANWIDTH_80MHZ &&
|
||||||
@ -698,7 +738,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
|
|||||||
|
|
||||||
/* 2.4 GHz has overlapping 20 MHz channels. Include adjacent
|
/* 2.4 GHz has overlapping 20 MHz channels. Include adjacent
|
||||||
* channel interference factor. */
|
* channel interference factor. */
|
||||||
if (is_24ghz_mode(iface->current_mode->mode)) {
|
if (is_24ghz_mode(mode->mode)) {
|
||||||
for (j = 0; j < n_chans; j++) {
|
for (j = 0; j < n_chans; j++) {
|
||||||
adj_chan = acs_find_chan(iface, chan->freq +
|
adj_chan = acs_find_chan(iface, chan->freq +
|
||||||
(j * 20) - 5);
|
(j * 20) - 5);
|
||||||
@ -744,7 +784,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
|
|||||||
break;
|
break;
|
||||||
bias = NULL;
|
bias = NULL;
|
||||||
}
|
}
|
||||||
} else if (is_24ghz_mode(iface->current_mode->mode) &&
|
} else if (is_24ghz_mode(mode->mode) &&
|
||||||
is_common_24ghz_chan(chan->chan)) {
|
is_common_24ghz_chan(chan->chan)) {
|
||||||
tmp_bias.channel = chan->chan;
|
tmp_bias.channel = chan->chan;
|
||||||
tmp_bias.bias = ACS_24GHZ_PREFER_1_6_11;
|
tmp_bias.bias = ACS_24GHZ_PREFER_1_6_11;
|
||||||
@ -763,14 +803,71 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (acs_usable_chan(chan) &&
|
if (acs_usable_chan(chan) &&
|
||||||
(!ideal_chan || factor < ideal_factor)) {
|
(!*ideal_chan || factor < *ideal_factor)) {
|
||||||
ideal_factor = factor;
|
*ideal_factor = factor;
|
||||||
ideal_chan = chan;
|
*ideal_chan = chan;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This channel would at least be usable */
|
/* This channel would at least be usable */
|
||||||
if (!rand_chan)
|
if (!(*rand_chan))
|
||||||
rand_chan = 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;
|
||||||
|
|
||||||
|
/* 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->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) {
|
if (ideal_chan) {
|
||||||
@ -826,7 +923,7 @@ static int acs_study_survey_based(struct hostapd_iface *iface)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
acs_survey_all_chans_intereference_factor(iface);
|
acs_survey_all_chans_interference_factor(iface);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -918,29 +1015,59 @@ 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;
|
struct hostapd_channel_data *chan;
|
||||||
int i, *freq;
|
int i;
|
||||||
|
|
||||||
os_memset(¶ms, 0, sizeof(params));
|
for (i = 0; i < mode->num_channels; i++) {
|
||||||
params.freqs = os_calloc(iface->current_mode->num_channels + 1,
|
chan = &mode->channels[i];
|
||||||
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];
|
|
||||||
if (chan->flag & HOSTAPD_CHAN_DISABLED)
|
if (chan->flag & HOSTAPD_CHAN_DISABLED)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!is_in_chanlist(iface, chan))
|
if (!is_in_chanlist(iface, chan))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (!is_in_freqlist(iface, chan))
|
||||||
|
continue;
|
||||||
|
|
||||||
*freq++ = chan->freq;
|
*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;
|
*freq = 0;
|
||||||
|
|
||||||
if (params.freqs == freq) {
|
if (params.freqs == freq) {
|
||||||
@ -978,7 +1105,8 @@ enum hostapd_chan_status acs_init(struct hostapd_iface *iface)
|
|||||||
return HOSTAPD_CHAN_ACS;
|
return HOSTAPD_CHAN_ACS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!iface->current_mode)
|
if (!iface->current_mode &&
|
||||||
|
iface->conf->hw_mode != HOSTAPD_MODE_IEEE80211ANY)
|
||||||
return HOSTAPD_CHAN_INVALID;
|
return HOSTAPD_CHAN_INVALID;
|
||||||
|
|
||||||
acs_cleanup(iface);
|
acs_cleanup(iface);
|
||||||
|
@ -134,8 +134,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,
|
unsigned int num_sta_min = 0, num_sta_prod = 1, num_sta_sum = 0,
|
||||||
wt_sum = 0;
|
wt_sum = 0;
|
||||||
unsigned int quantum;
|
unsigned int quantum;
|
||||||
Boolean all_div_min = TRUE;
|
bool all_div_min = true;
|
||||||
Boolean apply_limit = iface->conf->airtime_mode == AIRTIME_MODE_DYNAMIC;
|
bool apply_limit = iface->conf->airtime_mode == AIRTIME_MODE_DYNAMIC;
|
||||||
int wt, num_bss = 0, max_wt = 0;
|
int wt, num_bss = 0, max_wt = 0;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
@ -169,7 +169,7 @@ static void update_airtime_weights(void *eloop_data, void *user_data)
|
|||||||
* integers. */
|
* integers. */
|
||||||
if (bss->num_backlogged_sta &&
|
if (bss->num_backlogged_sta &&
|
||||||
bss->num_backlogged_sta % num_sta_min > 0)
|
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
|
/* If we're in LIMIT mode, we only apply the weight
|
||||||
* scaling when the BSS(es) marked as limited would a
|
* scaling when the BSS(es) marked as limited would a
|
||||||
@ -178,7 +178,7 @@ static void update_airtime_weights(void *eloop_data, void *user_data)
|
|||||||
if (!apply_limit && bss->conf->airtime_limit) {
|
if (!apply_limit && bss->conf->airtime_limit) {
|
||||||
if (bss->num_backlogged_sta * wt_sum >
|
if (bss->num_backlogged_sta * wt_sum >
|
||||||
bss->conf->airtime_weight * num_sta_sum)
|
bss->conf->airtime_weight * num_sta_sum)
|
||||||
apply_limit = TRUE;
|
apply_limit = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (all_div_min)
|
if (all_div_min)
|
||||||
|
@ -54,23 +54,33 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
|
|||||||
bss->logger_syslog = (unsigned int) -1;
|
bss->logger_syslog = (unsigned int) -1;
|
||||||
bss->logger_stdout = (unsigned int) -1;
|
bss->logger_stdout = (unsigned int) -1;
|
||||||
|
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
bss->auth_algs = WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED;
|
bss->auth_algs = WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED;
|
||||||
|
|
||||||
bss->wep_rekeying_period = 300;
|
bss->wep_rekeying_period = 300;
|
||||||
/* use key0 in individual key and key1 in broadcast key */
|
/* use key0 in individual key and key1 in broadcast key */
|
||||||
bss->broadcast_key_idx_min = 1;
|
bss->broadcast_key_idx_min = 1;
|
||||||
bss->broadcast_key_idx_max = 2;
|
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->eap_reauth_period = 3600;
|
||||||
|
|
||||||
bss->wpa_group_rekey = 600;
|
bss->wpa_group_rekey = 600;
|
||||||
bss->wpa_gmk_rekey = 86400;
|
bss->wpa_gmk_rekey = 86400;
|
||||||
|
bss->wpa_deny_ptk0_rekey = PTK0_REKEY_ALLOW_ALWAYS;
|
||||||
bss->wpa_group_update_count = 4;
|
bss->wpa_group_update_count = 4;
|
||||||
bss->wpa_pairwise_update_count = 4;
|
bss->wpa_pairwise_update_count = 4;
|
||||||
bss->wpa_disable_eapol_key_retries =
|
bss->wpa_disable_eapol_key_retries =
|
||||||
DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES;
|
DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES;
|
||||||
bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
|
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_pairwise = WPA_CIPHER_TKIP;
|
||||||
bss->wpa_group = WPA_CIPHER_TKIP;
|
bss->wpa_group = WPA_CIPHER_TKIP;
|
||||||
|
#endif /* CONFIG_NO_TKIP */
|
||||||
bss->rsn_pairwise = 0;
|
bss->rsn_pairwise = 0;
|
||||||
|
|
||||||
bss->max_num_sta = MAX_STA_COUNT;
|
bss->max_num_sta = MAX_STA_COUNT;
|
||||||
@ -150,6 +160,10 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
|
|||||||
|
|
||||||
/* Default to strict CRL checking. */
|
/* Default to strict CRL checking. */
|
||||||
bss->check_crl_strict = 1;
|
bss->check_crl_strict = 1;
|
||||||
|
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
bss->sae_commit_status = -1;
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -251,6 +265,9 @@ struct hostapd_config * hostapd_config_defaults(void)
|
|||||||
HE_OPERATION_RTS_THRESHOLD_OFFSET;
|
HE_OPERATION_RTS_THRESHOLD_OFFSET;
|
||||||
/* Set default basic MCS/NSS set to single stream MCS 0-7 */
|
/* 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_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;
|
||||||
#endif /* CONFIG_IEEE80211AX */
|
#endif /* CONFIG_IEEE80211AX */
|
||||||
|
|
||||||
/* The third octet of the country string uses an ASCII space character
|
/* The third octet of the country string uses an ASCII space character
|
||||||
@ -448,7 +465,8 @@ int hostapd_setup_sae_pt(struct hostapd_bss_config *conf)
|
|||||||
struct hostapd_ssid *ssid = &conf->ssid;
|
struct hostapd_ssid *ssid = &conf->ssid;
|
||||||
struct sae_password_entry *pw;
|
struct sae_password_entry *pw;
|
||||||
|
|
||||||
if ((conf->sae_pwe == 0 && !hostapd_sae_pw_id_in_use(conf)) ||
|
if ((conf->sae_pwe == 0 && !hostapd_sae_pw_id_in_use(conf) &&
|
||||||
|
!hostapd_sae_pk_in_use(conf)) ||
|
||||||
conf->sae_pwe == 3 ||
|
conf->sae_pwe == 3 ||
|
||||||
!wpa_key_mgmt_sae(conf->wpa_key_mgmt))
|
!wpa_key_mgmt_sae(conf->wpa_key_mgmt))
|
||||||
return 0; /* PT not needed */
|
return 0; /* PT not needed */
|
||||||
@ -632,6 +650,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)
|
static void hostapd_config_free_wep(struct hostapd_wep_keys *keys)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -640,6 +659,7 @@ static void hostapd_config_free_wep(struct hostapd_wep_keys *keys)
|
|||||||
keys->key[i] = NULL;
|
keys->key[i] = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
|
|
||||||
|
|
||||||
void hostapd_config_clear_wpa_psk(struct hostapd_wpa_psk **l)
|
void hostapd_config_clear_wpa_psk(struct hostapd_wpa_psk **l)
|
||||||
@ -696,6 +716,9 @@ static void hostapd_config_free_sae_passwords(struct hostapd_bss_config *conf)
|
|||||||
#ifdef CONFIG_SAE
|
#ifdef CONFIG_SAE
|
||||||
sae_deinit_pt(tmp->pt);
|
sae_deinit_pt(tmp->pt);
|
||||||
#endif /* CONFIG_SAE */
|
#endif /* CONFIG_SAE */
|
||||||
|
#ifdef CONFIG_SAE_PK
|
||||||
|
sae_deinit_pk(tmp->pk);
|
||||||
|
#endif /* CONFIG_SAE_PK */
|
||||||
os_free(tmp);
|
os_free(tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -728,7 +751,9 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
|
|||||||
|
|
||||||
str_clear_free(conf->ssid.wpa_passphrase);
|
str_clear_free(conf->ssid.wpa_passphrase);
|
||||||
os_free(conf->ssid.wpa_psk_file);
|
os_free(conf->ssid.wpa_psk_file);
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
hostapd_config_free_wep(&conf->ssid.wep);
|
hostapd_config_free_wep(&conf->ssid.wep);
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
#ifdef CONFIG_FULL_DYNAMIC_VLAN
|
#ifdef CONFIG_FULL_DYNAMIC_VLAN
|
||||||
os_free(conf->ssid.vlan_tagged_interface);
|
os_free(conf->ssid.vlan_tagged_interface);
|
||||||
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
|
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
|
||||||
@ -890,7 +915,10 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
|
|||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
wpabuf_free(conf->own_ie_override);
|
wpabuf_free(conf->own_ie_override);
|
||||||
wpabuf_free(conf->sae_commit_override);
|
wpabuf_free(conf->sae_commit_override);
|
||||||
|
wpabuf_free(conf->rsne_override_eapol);
|
||||||
wpabuf_free(conf->rsnxe_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->gtk_rsc_override);
|
||||||
wpabuf_free(conf->igtk_rsc_override);
|
wpabuf_free(conf->igtk_rsc_override);
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
@ -1091,6 +1119,37 @@ 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 int hostapd_config_check_bss(struct hostapd_bss_config *bss,
|
static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
|
||||||
struct hostapd_config *conf,
|
struct hostapd_config *conf,
|
||||||
int full_config)
|
int full_config)
|
||||||
@ -1102,6 +1161,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
if (bss->wpa) {
|
if (bss->wpa) {
|
||||||
int wep, i;
|
int wep, i;
|
||||||
|
|
||||||
@ -1119,6 +1179,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
|
|
||||||
if (full_config && bss->wpa &&
|
if (full_config && bss->wpa &&
|
||||||
bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
|
bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
|
||||||
@ -1166,47 +1227,49 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211R_AP */
|
#endif /* CONFIG_IEEE80211R_AP */
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211N
|
|
||||||
if (full_config && conf->ieee80211n &&
|
if (full_config && conf->ieee80211n &&
|
||||||
conf->hw_mode == HOSTAPD_MODE_IEEE80211B) {
|
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 "
|
wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) in 11b mode is not "
|
||||||
"allowed, disabling HT capabilities");
|
"allowed, disabling HT capabilities");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
if (full_config && conf->ieee80211n &&
|
if (full_config && conf->ieee80211n &&
|
||||||
bss->ssid.security_policy == SECURITY_STATIC_WEP) {
|
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 "
|
wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WEP is not "
|
||||||
"allowed, disabling HT capabilities");
|
"allowed, disabling HT capabilities");
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
|
|
||||||
if (full_config && conf->ieee80211n && bss->wpa &&
|
if (full_config && conf->ieee80211n && bss->wpa &&
|
||||||
!(bss->wpa_pairwise & WPA_CIPHER_CCMP) &&
|
!(bss->wpa_pairwise & WPA_CIPHER_CCMP) &&
|
||||||
!(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
|
!(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
|
||||||
WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256)))
|
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 "
|
wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WPA/WPA2 "
|
||||||
"requires CCMP/GCMP to be enabled, disabling HT "
|
"requires CCMP/GCMP to be enabled, disabling HT "
|
||||||
"capabilities");
|
"capabilities");
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211N */
|
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211AC
|
#ifdef CONFIG_IEEE80211AC
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
if (full_config && conf->ieee80211ac &&
|
if (full_config && conf->ieee80211ac &&
|
||||||
bss->ssid.security_policy == SECURITY_STATIC_WEP) {
|
bss->ssid.security_policy == SECURITY_STATIC_WEP) {
|
||||||
bss->disable_11ac = 1;
|
bss->disable_11ac = true;
|
||||||
wpa_printf(MSG_ERROR,
|
wpa_printf(MSG_ERROR,
|
||||||
"VHT (IEEE 802.11ac) with WEP is not allowed, disabling VHT capabilities");
|
"VHT (IEEE 802.11ac) with WEP is not allowed, disabling VHT capabilities");
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
|
|
||||||
if (full_config && conf->ieee80211ac && bss->wpa &&
|
if (full_config && conf->ieee80211ac && bss->wpa &&
|
||||||
!(bss->wpa_pairwise & WPA_CIPHER_CCMP) &&
|
!(bss->wpa_pairwise & WPA_CIPHER_CCMP) &&
|
||||||
!(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
|
!(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
|
||||||
WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256)))
|
WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256)))
|
||||||
{
|
{
|
||||||
bss->disable_11ac = 1;
|
bss->disable_11ac = true;
|
||||||
wpa_printf(MSG_ERROR,
|
wpa_printf(MSG_ERROR,
|
||||||
"VHT (IEEE 802.11ac) with WPA/WPA2 requires CCMP/GCMP to be enabled, disabling VHT capabilities");
|
"VHT (IEEE 802.11ac) with WPA/WPA2 requires CCMP/GCMP to be enabled, disabling VHT capabilities");
|
||||||
}
|
}
|
||||||
@ -1219,12 +1282,14 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
|
|||||||
bss->wps_state = 0;
|
bss->wps_state = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
if (full_config && bss->wps_state &&
|
if (full_config && bss->wps_state &&
|
||||||
bss->ssid.wep.keys_set && bss->wpa == 0) {
|
bss->ssid.wep.keys_set && bss->wpa == 0) {
|
||||||
wpa_printf(MSG_INFO, "WPS: WEP configuration forced WPS to be "
|
wpa_printf(MSG_INFO, "WPS: WEP configuration forced WPS to be "
|
||||||
"disabled");
|
"disabled");
|
||||||
bss->wps_state = 0;
|
bss->wps_state = 0;
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
|
|
||||||
if (full_config && bss->wps_state && bss->wpa &&
|
if (full_config && bss->wps_state && bss->wpa &&
|
||||||
(!(bss->wpa & 2) ||
|
(!(bss->wpa & 2) ||
|
||||||
@ -1268,6 +1333,15 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_OCV */
|
#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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1348,11 +1422,13 @@ int hostapd_config_check(struct hostapd_config *conf, int full_config)
|
|||||||
void hostapd_set_security_params(struct hostapd_bss_config *bss,
|
void hostapd_set_security_params(struct hostapd_bss_config *bss,
|
||||||
int full_config)
|
int full_config)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
if (bss->individual_wep_key_len == 0) {
|
if (bss->individual_wep_key_len == 0) {
|
||||||
/* individual keys are not use; can use key idx0 for
|
/* individual keys are not use; can use key idx0 for
|
||||||
* broadcast keys */
|
* broadcast keys */
|
||||||
bss->broadcast_key_idx_min = 0;
|
bss->broadcast_key_idx_min = 0;
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
|
|
||||||
if ((bss->wpa & 2) && bss->rsn_pairwise == 0)
|
if ((bss->wpa & 2) && bss->rsn_pairwise == 0)
|
||||||
bss->rsn_pairwise = bss->wpa_pairwise;
|
bss->rsn_pairwise = bss->wpa_pairwise;
|
||||||
@ -1378,6 +1454,7 @@ void hostapd_set_security_params(struct hostapd_bss_config *bss,
|
|||||||
} else if (bss->ieee802_1x) {
|
} else if (bss->ieee802_1x) {
|
||||||
int cipher = WPA_CIPHER_NONE;
|
int cipher = WPA_CIPHER_NONE;
|
||||||
bss->ssid.security_policy = SECURITY_IEEE_802_1X;
|
bss->ssid.security_policy = SECURITY_IEEE_802_1X;
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
bss->ssid.wep.default_len = bss->default_wep_key_len;
|
bss->ssid.wep.default_len = bss->default_wep_key_len;
|
||||||
if (full_config && bss->default_wep_key_len) {
|
if (full_config && bss->default_wep_key_len) {
|
||||||
cipher = bss->default_wep_key_len >= 13 ?
|
cipher = bss->default_wep_key_len >= 13 ?
|
||||||
@ -1388,11 +1465,13 @@ void hostapd_set_security_params(struct hostapd_bss_config *bss,
|
|||||||
else
|
else
|
||||||
cipher = WPA_CIPHER_WEP40;
|
cipher = WPA_CIPHER_WEP40;
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
bss->wpa_group = cipher;
|
bss->wpa_group = cipher;
|
||||||
bss->wpa_pairwise = cipher;
|
bss->wpa_pairwise = cipher;
|
||||||
bss->rsn_pairwise = cipher;
|
bss->rsn_pairwise = cipher;
|
||||||
if (full_config)
|
if (full_config)
|
||||||
bss->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
|
bss->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
} else if (bss->ssid.wep.keys_set) {
|
} else if (bss->ssid.wep.keys_set) {
|
||||||
int cipher = WPA_CIPHER_WEP40;
|
int cipher = WPA_CIPHER_WEP40;
|
||||||
if (bss->ssid.wep.len[0] >= 13)
|
if (bss->ssid.wep.len[0] >= 13)
|
||||||
@ -1403,6 +1482,7 @@ void hostapd_set_security_params(struct hostapd_bss_config *bss,
|
|||||||
bss->rsn_pairwise = cipher;
|
bss->rsn_pairwise = cipher;
|
||||||
if (full_config)
|
if (full_config)
|
||||||
bss->wpa_key_mgmt = WPA_KEY_MGMT_NONE;
|
bss->wpa_key_mgmt = WPA_KEY_MGMT_NONE;
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
} else if (bss->osen) {
|
} else if (bss->osen) {
|
||||||
bss->ssid.security_policy = SECURITY_OSEN;
|
bss->ssid.security_policy = SECURITY_OSEN;
|
||||||
bss->wpa_group = WPA_CIPHER_CCMP;
|
bss->wpa_group = WPA_CIPHER_CCMP;
|
||||||
@ -1441,3 +1521,38 @@ int hostapd_sae_pw_id_in_use(struct hostapd_bss_config *conf)
|
|||||||
return 2;
|
return 2;
|
||||||
return with_id;
|
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_r0kh;
|
||||||
struct ft_remote_r1kh;
|
struct ft_remote_r1kh;
|
||||||
|
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
#define NUM_WEP_KEYS 4
|
#define NUM_WEP_KEYS 4
|
||||||
struct hostapd_wep_keys {
|
struct hostapd_wep_keys {
|
||||||
u8 idx;
|
u8 idx;
|
||||||
@ -75,10 +76,13 @@ struct hostapd_wep_keys {
|
|||||||
int keys_set;
|
int keys_set;
|
||||||
size_t default_len; /* key length used for dynamic key generation */
|
size_t default_len; /* key length used for dynamic key generation */
|
||||||
};
|
};
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
|
|
||||||
typedef enum hostap_security_policy {
|
typedef enum hostap_security_policy {
|
||||||
SECURITY_PLAINTEXT = 0,
|
SECURITY_PLAINTEXT = 0,
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
SECURITY_STATIC_WEP = 1,
|
SECURITY_STATIC_WEP = 1,
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
SECURITY_IEEE_802_1X = 2,
|
SECURITY_IEEE_802_1X = 2,
|
||||||
SECURITY_WPA_PSK = 3,
|
SECURITY_WPA_PSK = 3,
|
||||||
SECURITY_WPA = 4,
|
SECURITY_WPA = 4,
|
||||||
@ -102,7 +106,9 @@ struct hostapd_ssid {
|
|||||||
char *wpa_psk_file;
|
char *wpa_psk_file;
|
||||||
struct sae_pt *pt;
|
struct sae_pt *pt;
|
||||||
|
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
struct hostapd_wep_keys wep;
|
struct hostapd_wep_keys wep;
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
|
|
||||||
#define DYNAMIC_VLAN_DISABLED 0
|
#define DYNAMIC_VLAN_DISABLED 0
|
||||||
#define DYNAMIC_VLAN_OPTIONAL 1
|
#define DYNAMIC_VLAN_OPTIONAL 1
|
||||||
@ -191,15 +197,6 @@ struct hostapd_radius_attr {
|
|||||||
|
|
||||||
|
|
||||||
#define NUM_TX_QUEUES 4
|
#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
|
#define MAX_ROAMING_CONSORTIUM_LEN 15
|
||||||
|
|
||||||
struct hostapd_roaming_consortium {
|
struct hostapd_roaming_consortium {
|
||||||
@ -255,6 +252,7 @@ struct sae_password_entry {
|
|||||||
u8 peer_addr[ETH_ALEN];
|
u8 peer_addr[ETH_ALEN];
|
||||||
int vlan_id;
|
int vlan_id;
|
||||||
struct sae_pt *pt;
|
struct sae_pt *pt;
|
||||||
|
struct sae_pk *pk;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dpp_controller_conf {
|
struct dpp_controller_conf {
|
||||||
@ -321,10 +319,12 @@ struct hostapd_bss_config {
|
|||||||
size_t eap_req_id_text_len;
|
size_t eap_req_id_text_len;
|
||||||
int eapol_key_index_workaround;
|
int eapol_key_index_workaround;
|
||||||
|
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
size_t default_wep_key_len;
|
size_t default_wep_key_len;
|
||||||
int individual_wep_key_len;
|
int individual_wep_key_len;
|
||||||
int wep_rekeying_period;
|
int wep_rekeying_period;
|
||||||
int broadcast_key_idx_min, broadcast_key_idx_max;
|
int broadcast_key_idx_min, broadcast_key_idx_max;
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
int eap_reauth_period;
|
int eap_reauth_period;
|
||||||
int erp_send_reauth_start;
|
int erp_send_reauth_start;
|
||||||
char *erp_domain;
|
char *erp_domain;
|
||||||
@ -346,9 +346,11 @@ struct hostapd_bss_config {
|
|||||||
* algorithms, WPA_AUTH_ALG_{OPEN,SHARED,LEAP} */
|
* algorithms, WPA_AUTH_ALG_{OPEN,SHARED,LEAP} */
|
||||||
|
|
||||||
int wpa; /* bitfield of WPA_PROTO_WPA, WPA_PROTO_RSN */
|
int wpa; /* bitfield of WPA_PROTO_WPA, WPA_PROTO_RSN */
|
||||||
|
int extended_key_id;
|
||||||
int wpa_key_mgmt;
|
int wpa_key_mgmt;
|
||||||
enum mfp_options ieee80211w;
|
enum mfp_options ieee80211w;
|
||||||
int group_mgmt_cipher;
|
int group_mgmt_cipher;
|
||||||
|
int beacon_prot;
|
||||||
/* dot11AssociationSAQueryMaximumTimeout (in TUs) */
|
/* dot11AssociationSAQueryMaximumTimeout (in TUs) */
|
||||||
unsigned int assoc_sa_query_max_timeout;
|
unsigned int assoc_sa_query_max_timeout;
|
||||||
/* dot11AssociationSAQueryRetryTimeout (in TUs) */
|
/* dot11AssociationSAQueryRetryTimeout (in TUs) */
|
||||||
@ -369,6 +371,7 @@ struct hostapd_bss_config {
|
|||||||
int wpa_strict_rekey;
|
int wpa_strict_rekey;
|
||||||
int wpa_gmk_rekey;
|
int wpa_gmk_rekey;
|
||||||
int wpa_ptk_rekey;
|
int wpa_ptk_rekey;
|
||||||
|
enum ptk0_rekey_handling wpa_deny_ptk0_rekey;
|
||||||
u32 wpa_group_update_count;
|
u32 wpa_group_update_count;
|
||||||
u32 wpa_pairwise_update_count;
|
u32 wpa_pairwise_update_count;
|
||||||
int wpa_disable_eapol_key_retries;
|
int wpa_disable_eapol_key_retries;
|
||||||
@ -528,8 +531,9 @@ struct hostapd_bss_config {
|
|||||||
#define TDLS_PROHIBIT BIT(0)
|
#define TDLS_PROHIBIT BIT(0)
|
||||||
#define TDLS_PROHIBIT_CHAN_SWITCH BIT(1)
|
#define TDLS_PROHIBIT_CHAN_SWITCH BIT(1)
|
||||||
int tdls;
|
int tdls;
|
||||||
int disable_11n;
|
bool disable_11n;
|
||||||
int disable_11ac;
|
bool disable_11ac;
|
||||||
|
bool disable_11ax;
|
||||||
|
|
||||||
/* IEEE 802.11v */
|
/* IEEE 802.11v */
|
||||||
int time_advertisement;
|
int time_advertisement;
|
||||||
@ -666,10 +670,26 @@ struct hostapd_bss_config {
|
|||||||
u8 bss_load_test_set;
|
u8 bss_load_test_set;
|
||||||
struct wpabuf *own_ie_override;
|
struct wpabuf *own_ie_override;
|
||||||
int sae_reflection_attack;
|
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 *sae_commit_override;
|
||||||
|
struct wpabuf *rsne_override_eapol;
|
||||||
struct wpabuf *rsnxe_override_eapol;
|
struct wpabuf *rsnxe_override_eapol;
|
||||||
|
struct wpabuf *rsne_override_ft;
|
||||||
|
struct wpabuf *rsnxe_override_ft;
|
||||||
struct wpabuf *gtk_rsc_override;
|
struct wpabuf *gtk_rsc_override;
|
||||||
struct wpabuf *igtk_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 */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
#define MESH_ENABLED BIT(0)
|
#define MESH_ENABLED BIT(0)
|
||||||
@ -725,6 +745,8 @@ struct hostapd_bss_config {
|
|||||||
struct wpabuf *dpp_csign;
|
struct wpabuf *dpp_csign;
|
||||||
#ifdef CONFIG_DPP2
|
#ifdef CONFIG_DPP2
|
||||||
struct dpp_controller_conf *dpp_controller;
|
struct dpp_controller_conf *dpp_controller;
|
||||||
|
int dpp_configurator_connectivity;
|
||||||
|
int dpp_pfs;
|
||||||
#endif /* CONFIG_DPP2 */
|
#endif /* CONFIG_DPP2 */
|
||||||
#endif /* CONFIG_DPP */
|
#endif /* CONFIG_DPP */
|
||||||
|
|
||||||
@ -741,6 +763,8 @@ struct hostapd_bss_config {
|
|||||||
|
|
||||||
u8 send_probe_response;
|
u8 send_probe_response;
|
||||||
|
|
||||||
|
u8 transition_disable;
|
||||||
|
|
||||||
#define BACKHAUL_BSS 1
|
#define BACKHAUL_BSS 1
|
||||||
#define FRONTHAUL_BSS 2
|
#define FRONTHAUL_BSS 2
|
||||||
int multi_ap; /* bitmap of BACKHAUL_BSS, FRONTHAUL_BSS */
|
int multi_ap; /* bitmap of BACKHAUL_BSS, FRONTHAUL_BSS */
|
||||||
@ -844,9 +868,9 @@ struct hostapd_bss_config {
|
|||||||
* struct he_phy_capabilities_info - HE PHY capabilities
|
* struct he_phy_capabilities_info - HE PHY capabilities
|
||||||
*/
|
*/
|
||||||
struct he_phy_capabilities_info {
|
struct he_phy_capabilities_info {
|
||||||
Boolean he_su_beamformer;
|
bool he_su_beamformer;
|
||||||
Boolean he_su_beamformee;
|
bool he_su_beamformee;
|
||||||
Boolean he_mu_beamformer;
|
bool he_mu_beamformer;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -854,6 +878,8 @@ struct he_phy_capabilities_info {
|
|||||||
*/
|
*/
|
||||||
struct he_operation {
|
struct he_operation {
|
||||||
u8 he_bss_color;
|
u8 he_bss_color;
|
||||||
|
u8 he_bss_color_disabled;
|
||||||
|
u8 he_bss_color_partial;
|
||||||
u8 he_default_pe_duration;
|
u8 he_default_pe_duration;
|
||||||
u8 he_twt_required;
|
u8 he_twt_required;
|
||||||
u16 he_rts_threshold;
|
u16 he_rts_threshold;
|
||||||
@ -1013,6 +1039,7 @@ struct hostapd_config {
|
|||||||
|
|
||||||
int rssi_reject_assoc_rssi;
|
int rssi_reject_assoc_rssi;
|
||||||
int rssi_reject_assoc_timeout;
|
int rssi_reject_assoc_timeout;
|
||||||
|
int rssi_ignore_probe_request;
|
||||||
|
|
||||||
#ifdef CONFIG_AIRTIME_POLICY
|
#ifdef CONFIG_AIRTIME_POLICY
|
||||||
enum {
|
enum {
|
||||||
@ -1117,6 +1144,8 @@ int hostapd_config_check(struct hostapd_config *conf, int full_config);
|
|||||||
void hostapd_set_security_params(struct hostapd_bss_config *bss,
|
void hostapd_set_security_params(struct hostapd_bss_config *bss,
|
||||||
int full_config);
|
int full_config);
|
||||||
int hostapd_sae_pw_id_in_use(struct hostapd_bss_config *conf);
|
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);
|
int hostapd_setup_sae_pt(struct hostapd_bss_config *conf);
|
||||||
|
|
||||||
#endif /* HOSTAPD_CONFIG_H */
|
#endif /* HOSTAPD_CONFIG_H */
|
||||||
|
@ -418,6 +418,7 @@ int hostapd_sta_add(struct hostapd_data *hapd,
|
|||||||
const struct ieee80211_vht_capabilities *vht_capab,
|
const struct ieee80211_vht_capabilities *vht_capab,
|
||||||
const struct ieee80211_he_capabilities *he_capab,
|
const struct ieee80211_he_capabilities *he_capab,
|
||||||
size_t he_capab_len,
|
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,
|
u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps,
|
||||||
int set)
|
int set)
|
||||||
{
|
{
|
||||||
@ -439,6 +440,7 @@ int hostapd_sta_add(struct hostapd_data *hapd,
|
|||||||
params.vht_capabilities = vht_capab;
|
params.vht_capabilities = vht_capab;
|
||||||
params.he_capab = he_capab;
|
params.he_capab = he_capab;
|
||||||
params.he_capab_len = he_capab_len;
|
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_enabled = !!(flags & WLAN_STA_VHT_OPMODE_ENABLED);
|
||||||
params.vht_opmode = vht_opmode;
|
params.vht_opmode = vht_opmode;
|
||||||
params.flags = hostapd_sta_flags_to_drv(flags);
|
params.flags = hostapd_sta_flags_to_drv(flags);
|
||||||
@ -588,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 hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
|
||||||
int total_flags, int flags_or, int flags_and)
|
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 0;
|
||||||
return hapd->driver->sta_set_flags(hapd->drv_priv, addr, total_flags,
|
return hapd->driver->sta_set_flags(hapd->drv_priv, addr, total_flags,
|
||||||
flags_or, flags_and);
|
flags_or, flags_and);
|
||||||
@ -650,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,
|
int hostapd_driver_scan(struct hostapd_data *hapd,
|
||||||
struct wpa_driver_scan_params *params)
|
struct wpa_driver_scan_params *params)
|
||||||
{
|
{
|
||||||
@ -714,7 +722,7 @@ int hostapd_drv_send_mlme(struct hostapd_data *hapd,
|
|||||||
if (!hapd->driver || !hapd->driver->send_mlme || !hapd->drv_priv)
|
if (!hapd->driver || !hapd->driver->send_mlme || !hapd->drv_priv)
|
||||||
return 0;
|
return 0;
|
||||||
return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0,
|
return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0,
|
||||||
csa_offs, csa_offs_len, no_encrypt);
|
csa_offs, csa_offs_len, no_encrypt, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -938,6 +946,7 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
params.freq_list = freq_list;
|
params.freq_list = freq_list;
|
||||||
|
params.edmg_enabled = hapd->iface->conf->enable_edmg;
|
||||||
|
|
||||||
params.ht_enabled = !!(hapd->iface->conf->ieee80211n);
|
params.ht_enabled = !!(hapd->iface->conf->ieee80211n);
|
||||||
params.ht40_enabled = !!(hapd->iface->conf->ht_capab &
|
params.ht40_enabled = !!(hapd->iface->conf->ht_capab &
|
||||||
|
@ -43,6 +43,7 @@ int hostapd_sta_add(struct hostapd_data *hapd,
|
|||||||
const struct ieee80211_vht_capabilities *vht_capab,
|
const struct ieee80211_vht_capabilities *vht_capab,
|
||||||
const struct ieee80211_he_capabilities *he_capab,
|
const struct ieee80211_he_capabilities *he_capab,
|
||||||
size_t he_capab_len,
|
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,
|
u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps,
|
||||||
int set);
|
int set);
|
||||||
int hostapd_set_privacy(struct hostapd_data *hapd, int enabled);
|
int hostapd_set_privacy(struct hostapd_data *hapd, int enabled);
|
||||||
@ -80,6 +81,7 @@ hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
|
|||||||
u16 *flags, u8 *dfs_domain);
|
u16 *flags, u8 *dfs_domain);
|
||||||
int hostapd_driver_commit(struct hostapd_data *hapd);
|
int hostapd_driver_commit(struct hostapd_data *hapd);
|
||||||
int hostapd_drv_none(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,
|
int hostapd_driver_scan(struct hostapd_data *hapd,
|
||||||
struct wpa_driver_scan_params *params);
|
struct wpa_driver_scan_params *params);
|
||||||
struct wpa_scan_results * hostapd_driver_get_scan_results(
|
struct wpa_scan_results * hostapd_driver_get_scan_results(
|
||||||
@ -348,12 +350,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,
|
static inline int hostapd_drv_vendor_cmd(struct hostapd_data *hapd,
|
||||||
int vendor_id, int subcmd,
|
int vendor_id, int subcmd,
|
||||||
const u8 *data, size_t data_len,
|
const u8 *data, size_t data_len,
|
||||||
|
enum nested_attr nested_attr_flag,
|
||||||
struct wpabuf *buf)
|
struct wpabuf *buf)
|
||||||
{
|
{
|
||||||
if (hapd->driver == NULL || hapd->driver->vendor_cmd == NULL)
|
if (hapd->driver == NULL || hapd->driver->vendor_cmd == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
return hapd->driver->vendor_cmd(hapd->drv_priv, vendor_id, subcmd, data,
|
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)
|
static inline int hostapd_drv_stop_ap(struct hostapd_data *hapd)
|
||||||
@ -382,11 +385,11 @@ hostapd_drv_send_external_auth_status(struct hostapd_data *hapd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
hostapd_drv_set_band(struct hostapd_data *hapd, enum set_band band)
|
hostapd_drv_set_band(struct hostapd_data *hapd, u32 band_mask)
|
||||||
{
|
{
|
||||||
if (!hapd->driver || !hapd->drv_priv || !hapd->driver->set_band)
|
if (!hapd->driver || !hapd->drv_priv || !hapd->driver->set_band)
|
||||||
return -1;
|
return -1;
|
||||||
return hapd->driver->set_band(hapd->drv_priv, band);
|
return hapd->driver->set_band(hapd->drv_priv, band_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* AP_DRV_OPS */
|
#endif /* AP_DRV_OPS */
|
||||||
|
@ -228,7 +228,6 @@ void ap_list_process_beacon(struct hostapd_iface *iface,
|
|||||||
set_beacon++;
|
set_beacon++;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211N
|
|
||||||
if (!iface->olbc_ht && !ap->ht_support &&
|
if (!iface->olbc_ht && !ap->ht_support &&
|
||||||
(ap->channel == 0 ||
|
(ap->channel == 0 ||
|
||||||
ap->channel == iface->conf->channel ||
|
ap->channel == iface->conf->channel ||
|
||||||
@ -241,7 +240,6 @@ void ap_list_process_beacon(struct hostapd_iface *iface,
|
|||||||
MAC2STR(ap->addr), ap->channel);
|
MAC2STR(ap->addr), ap->channel);
|
||||||
set_beacon++;
|
set_beacon++;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211N */
|
|
||||||
|
|
||||||
if (set_beacon)
|
if (set_beacon)
|
||||||
ieee802_11_update_beacons(iface);
|
ieee802_11_update_beacons(iface);
|
||||||
@ -285,14 +283,12 @@ void ap_list_timer(struct hostapd_iface *iface)
|
|||||||
iface->olbc = 0;
|
iface->olbc = 0;
|
||||||
set_beacon++;
|
set_beacon++;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_IEEE80211N
|
|
||||||
if (!olbc_ht && iface->olbc_ht) {
|
if (!olbc_ht && iface->olbc_ht) {
|
||||||
wpa_printf(MSG_DEBUG, "OLBC HT not detected anymore");
|
wpa_printf(MSG_DEBUG, "OLBC HT not detected anymore");
|
||||||
iface->olbc_ht = 0;
|
iface->olbc_ht = 0;
|
||||||
hostapd_ht_operation_update(iface);
|
hostapd_ht_operation_update(iface);
|
||||||
set_beacon++;
|
set_beacon++;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211N */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (set_beacon)
|
if (set_beacon)
|
||||||
|
214
src/ap/beacon.c
214
src/ap/beacon.c
@ -266,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)
|
static 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;
|
const u8 *ie;
|
||||||
size_t ielen;
|
|
||||||
|
|
||||||
ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ielen);
|
ie = hostapd_wpa_ie(hapd, WLAN_EID_RSN);
|
||||||
if (ie == NULL || ielen > len)
|
if (!ie || 2U + ie[1] > len)
|
||||||
return eid;
|
return pos;
|
||||||
|
|
||||||
os_memcpy(eid, ie, ielen);
|
os_memcpy(pos, ie, 2 + ie[1]);
|
||||||
return eid + ielen;
|
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];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -374,16 +458,20 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211AX
|
#ifdef CONFIG_IEEE80211AX
|
||||||
if (hapd->iconf->ieee80211ax) {
|
if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) {
|
||||||
buflen += 3 + sizeof(struct ieee80211_he_capabilities) +
|
buflen += 3 + sizeof(struct ieee80211_he_capabilities) +
|
||||||
3 + sizeof(struct ieee80211_he_operation) +
|
3 + sizeof(struct ieee80211_he_operation) +
|
||||||
3 + sizeof(struct ieee80211_he_mu_edca_parameter_set) +
|
3 + sizeof(struct ieee80211_he_mu_edca_parameter_set) +
|
||||||
3 + sizeof(struct ieee80211_spatial_reuse);
|
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 */
|
#endif /* CONFIG_IEEE80211AX */
|
||||||
|
|
||||||
buflen += hostapd_mbo_ie_len(hapd);
|
buflen += hostapd_mbo_ie_len(hapd);
|
||||||
buflen += hostapd_eid_owe_trans_len(hapd);
|
buflen += hostapd_eid_owe_trans_len(hapd);
|
||||||
|
buflen += hostapd_eid_dpp_cc_len(hapd);
|
||||||
|
|
||||||
resp = os_zalloc(buflen);
|
resp = os_zalloc(buflen);
|
||||||
if (resp == NULL)
|
if (resp == NULL)
|
||||||
@ -434,14 +522,10 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
|
|||||||
/* Extended supported rates */
|
/* Extended supported rates */
|
||||||
pos = hostapd_eid_ext_supp_rates(hapd, pos);
|
pos = hostapd_eid_ext_supp_rates(hapd, pos);
|
||||||
|
|
||||||
/* RSN, MDIE */
|
pos = hostapd_get_rsne(hapd, pos, epos - pos);
|
||||||
if (!(hapd->conf->wpa == WPA_PROTO_WPA ||
|
|
||||||
(hapd->conf->osen && !hapd->conf->wpa)))
|
|
||||||
pos = hostapd_eid_wpa(hapd, pos, epos - pos);
|
|
||||||
|
|
||||||
pos = hostapd_eid_bss_load(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_eid_rm_enabled_capab(hapd, pos, epos - pos);
|
||||||
|
pos = hostapd_get_mde(hapd, pos, epos - pos);
|
||||||
|
|
||||||
/* eCSA IE */
|
/* eCSA IE */
|
||||||
csa_pos = hostapd_eid_ecsa(hapd, pos);
|
csa_pos = hostapd_eid_ecsa(hapd, pos);
|
||||||
@ -450,15 +534,8 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
|
|||||||
pos = csa_pos;
|
pos = csa_pos;
|
||||||
|
|
||||||
pos = hostapd_eid_supported_op_classes(hapd, 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_capabilities(hapd, pos);
|
||||||
pos = hostapd_eid_ht_operation(hapd, pos);
|
pos = hostapd_eid_ht_operation(hapd, pos);
|
||||||
#endif /* CONFIG_IEEE80211N */
|
|
||||||
|
|
||||||
pos = hostapd_eid_ext_capab(hapd, pos);
|
pos = hostapd_eid_ext_capab(hapd, pos);
|
||||||
|
|
||||||
@ -483,18 +560,23 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
|
|||||||
pos = hostapd_eid_vht_capabilities(hapd, pos, 0);
|
pos = hostapd_eid_vht_capabilities(hapd, pos, 0);
|
||||||
pos = hostapd_eid_vht_operation(hapd, pos);
|
pos = hostapd_eid_vht_operation(hapd, pos);
|
||||||
pos = hostapd_eid_txpower_envelope(hapd, pos);
|
pos = hostapd_eid_txpower_envelope(hapd, pos);
|
||||||
pos = hostapd_eid_wb_chsw_wrapper(hapd, pos);
|
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211AC */
|
#endif /* CONFIG_IEEE80211AC */
|
||||||
|
|
||||||
|
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_eid_fils_indic(hapd, pos, 0);
|
||||||
|
pos = hostapd_get_rsnxe(hapd, pos, epos - pos);
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211AX
|
#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_capab(hapd, pos, IEEE80211_MODE_AP);
|
||||||
pos = hostapd_eid_he_operation(hapd, pos);
|
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_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 */
|
#endif /* CONFIG_IEEE80211AX */
|
||||||
|
|
||||||
@ -503,10 +585,9 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
|
|||||||
pos = hostapd_eid_vendor_vht(hapd, pos);
|
pos = hostapd_eid_vendor_vht(hapd, pos);
|
||||||
#endif /* CONFIG_IEEE80211AC */
|
#endif /* CONFIG_IEEE80211AC */
|
||||||
|
|
||||||
/* WPA */
|
/* WPA / OSEN */
|
||||||
if (hapd->conf->wpa == WPA_PROTO_WPA ||
|
pos = hostapd_get_wpa_ie(hapd, pos, epos - pos);
|
||||||
(hapd->conf->osen && !hapd->conf->wpa))
|
pos = hostapd_get_osen_ie(hapd, pos, epos - pos);
|
||||||
pos = hostapd_eid_wpa(hapd, pos, epos - pos);
|
|
||||||
|
|
||||||
/* Wi-Fi Alliance WMM */
|
/* Wi-Fi Alliance WMM */
|
||||||
pos = hostapd_eid_wmm(hapd, pos);
|
pos = hostapd_eid_wmm(hapd, pos);
|
||||||
@ -539,6 +620,7 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
|
|||||||
|
|
||||||
pos = hostapd_eid_mbo(hapd, pos, (u8 *) resp + buflen - pos);
|
pos = hostapd_eid_mbo(hapd, pos, (u8 *) resp + buflen - pos);
|
||||||
pos = hostapd_eid_owe_trans(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) {
|
if (hapd->conf->vendor_elements) {
|
||||||
os_memcpy(pos, wpabuf_head(hapd->conf->vendor_elements),
|
os_memcpy(pos, wpabuf_head(hapd->conf->vendor_elements),
|
||||||
@ -736,6 +818,10 @@ void handle_probe_req(struct hostapd_data *hapd,
|
|||||||
size_t csa_offs_len;
|
size_t csa_offs_len;
|
||||||
struct radius_sta rad_info;
|
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)
|
if (len < IEEE80211_HDRLEN)
|
||||||
return;
|
return;
|
||||||
ie = ((const u8 *) mgmt) + IEEE80211_HDRLEN;
|
ie = ((const u8 *) mgmt) + IEEE80211_HDRLEN;
|
||||||
@ -1052,7 +1138,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
|||||||
size_t resp_len = 0;
|
size_t resp_len = 0;
|
||||||
#ifdef NEED_AP_MLME
|
#ifdef NEED_AP_MLME
|
||||||
u16 capab_info;
|
u16 capab_info;
|
||||||
u8 *pos, *tailpos, *csa_pos;
|
u8 *pos, *tailpos, *tailend, *csa_pos;
|
||||||
|
|
||||||
#define BEACON_HEAD_BUF_SIZE 256
|
#define BEACON_HEAD_BUF_SIZE 256
|
||||||
#define BEACON_TAIL_BUF_SIZE 512
|
#define BEACON_TAIL_BUF_SIZE 512
|
||||||
@ -1081,16 +1167,20 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
|||||||
#endif /* CONFIG_IEEE80211AC */
|
#endif /* CONFIG_IEEE80211AC */
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211AX
|
#ifdef CONFIG_IEEE80211AX
|
||||||
if (hapd->iconf->ieee80211ax) {
|
if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) {
|
||||||
tail_len += 3 + sizeof(struct ieee80211_he_capabilities) +
|
tail_len += 3 + sizeof(struct ieee80211_he_capabilities) +
|
||||||
3 + sizeof(struct ieee80211_he_operation) +
|
3 + sizeof(struct ieee80211_he_operation) +
|
||||||
3 + sizeof(struct ieee80211_he_mu_edca_parameter_set) +
|
3 + sizeof(struct ieee80211_he_mu_edca_parameter_set) +
|
||||||
3 + sizeof(struct ieee80211_spatial_reuse);
|
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 */
|
#endif /* CONFIG_IEEE80211AX */
|
||||||
|
|
||||||
tail_len += hostapd_mbo_ie_len(hapd);
|
tail_len += hostapd_mbo_ie_len(hapd);
|
||||||
tail_len += hostapd_eid_owe_trans_len(hapd);
|
tail_len += hostapd_eid_owe_trans_len(hapd);
|
||||||
|
tail_len += hostapd_eid_dpp_cc_len(hapd);
|
||||||
|
|
||||||
tailpos = tail = os_malloc(tail_len);
|
tailpos = tail = os_malloc(tail_len);
|
||||||
if (head == NULL || tail == NULL) {
|
if (head == NULL || tail == NULL) {
|
||||||
@ -1099,6 +1189,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
|||||||
os_free(tail);
|
os_free(tail);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
tailend = tail + tail_len;
|
||||||
|
|
||||||
head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
||||||
WLAN_FC_STYPE_BEACON);
|
WLAN_FC_STYPE_BEACON);
|
||||||
@ -1139,8 +1230,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
|||||||
|
|
||||||
head_len = pos - (u8 *) head;
|
head_len = pos - (u8 *) head;
|
||||||
|
|
||||||
tailpos = hostapd_eid_country(hapd, tailpos,
|
tailpos = hostapd_eid_country(hapd, tailpos, tailend - tailpos);
|
||||||
tail + BEACON_TAIL_BUF_SIZE - tailpos);
|
|
||||||
|
|
||||||
/* Power Constraint element */
|
/* Power Constraint element */
|
||||||
tailpos = hostapd_eid_pwr_constraint(hapd, tailpos);
|
tailpos = hostapd_eid_pwr_constraint(hapd, tailpos);
|
||||||
@ -1157,19 +1247,11 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
|||||||
/* Extended supported rates */
|
/* Extended supported rates */
|
||||||
tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos);
|
tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos);
|
||||||
|
|
||||||
/* RSN, MDIE */
|
tailpos = hostapd_get_rsne(hapd, tailpos, tailend - tailpos);
|
||||||
if (!(hapd->conf->wpa == WPA_PROTO_WPA ||
|
tailpos = hostapd_eid_bss_load(hapd, tailpos, tailend - tailpos);
|
||||||
(hapd->conf->osen && !hapd->conf->wpa)))
|
|
||||||
tailpos = hostapd_eid_wpa(hapd, tailpos,
|
|
||||||
tail + BEACON_TAIL_BUF_SIZE -
|
|
||||||
tailpos);
|
|
||||||
|
|
||||||
tailpos = hostapd_eid_rm_enabled_capab(hapd, tailpos,
|
tailpos = hostapd_eid_rm_enabled_capab(hapd, tailpos,
|
||||||
tail + BEACON_TAIL_BUF_SIZE -
|
tailend - tailpos);
|
||||||
tailpos);
|
tailpos = hostapd_get_mde(hapd, tailpos, tailend - tailpos);
|
||||||
|
|
||||||
tailpos = hostapd_eid_bss_load(hapd, tailpos,
|
|
||||||
tail + BEACON_TAIL_BUF_SIZE - tailpos);
|
|
||||||
|
|
||||||
/* eCSA IE */
|
/* eCSA IE */
|
||||||
csa_pos = hostapd_eid_ecsa(hapd, tailpos);
|
csa_pos = hostapd_eid_ecsa(hapd, tailpos);
|
||||||
@ -1178,15 +1260,8 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
|||||||
tailpos = csa_pos;
|
tailpos = csa_pos;
|
||||||
|
|
||||||
tailpos = hostapd_eid_supported_op_classes(hapd, tailpos);
|
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_capabilities(hapd, tailpos);
|
||||||
tailpos = hostapd_eid_ht_operation(hapd, tailpos);
|
tailpos = hostapd_eid_ht_operation(hapd, tailpos);
|
||||||
#endif /* CONFIG_IEEE80211N */
|
|
||||||
|
|
||||||
tailpos = hostapd_eid_ext_capab(hapd, tailpos);
|
tailpos = hostapd_eid_ext_capab(hapd, tailpos);
|
||||||
|
|
||||||
@ -1213,19 +1288,24 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
|||||||
tailpos = hostapd_eid_vht_capabilities(hapd, tailpos, 0);
|
tailpos = hostapd_eid_vht_capabilities(hapd, tailpos, 0);
|
||||||
tailpos = hostapd_eid_vht_operation(hapd, tailpos);
|
tailpos = hostapd_eid_vht_operation(hapd, tailpos);
|
||||||
tailpos = hostapd_eid_txpower_envelope(hapd, tailpos);
|
tailpos = hostapd_eid_txpower_envelope(hapd, tailpos);
|
||||||
tailpos = hostapd_eid_wb_chsw_wrapper(hapd, tailpos);
|
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211AC */
|
#endif /* CONFIG_IEEE80211AC */
|
||||||
|
|
||||||
|
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_eid_fils_indic(hapd, tailpos, 0);
|
||||||
|
tailpos = hostapd_get_rsnxe(hapd, tailpos, tailend - tailpos);
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211AX
|
#ifdef CONFIG_IEEE80211AX
|
||||||
if (hapd->iconf->ieee80211ax) {
|
if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) {
|
||||||
tailpos = hostapd_eid_he_capab(hapd, tailpos,
|
tailpos = hostapd_eid_he_capab(hapd, tailpos,
|
||||||
IEEE80211_MODE_AP);
|
IEEE80211_MODE_AP);
|
||||||
tailpos = hostapd_eid_he_operation(hapd, tailpos);
|
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_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 */
|
#endif /* CONFIG_IEEE80211AX */
|
||||||
|
|
||||||
@ -1234,12 +1314,9 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
|||||||
tailpos = hostapd_eid_vendor_vht(hapd, tailpos);
|
tailpos = hostapd_eid_vendor_vht(hapd, tailpos);
|
||||||
#endif /* CONFIG_IEEE80211AC */
|
#endif /* CONFIG_IEEE80211AC */
|
||||||
|
|
||||||
/* WPA */
|
/* WPA / OSEN */
|
||||||
if (hapd->conf->wpa == WPA_PROTO_WPA ||
|
tailpos = hostapd_get_wpa_ie(hapd, tailpos, tailend - tailpos);
|
||||||
(hapd->conf->osen && !hapd->conf->wpa))
|
tailpos = hostapd_get_osen_ie(hapd, tailpos, tailend - tailpos);
|
||||||
tailpos = hostapd_eid_wpa(hapd, tailpos,
|
|
||||||
tail + BEACON_TAIL_BUF_SIZE -
|
|
||||||
tailpos);
|
|
||||||
|
|
||||||
/* Wi-Fi Alliance WMM */
|
/* Wi-Fi Alliance WMM */
|
||||||
tailpos = hostapd_eid_wmm(hapd, tailpos);
|
tailpos = hostapd_eid_wmm(hapd, tailpos);
|
||||||
@ -1272,6 +1349,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
|||||||
tailpos = hostapd_eid_mbo(hapd, tailpos, tail + tail_len - tailpos);
|
tailpos = hostapd_eid_mbo(hapd, tailpos, tail + tail_len - tailpos);
|
||||||
tailpos = hostapd_eid_owe_trans(hapd, tailpos,
|
tailpos = hostapd_eid_owe_trans(hapd, tailpos,
|
||||||
tail + tail_len - tailpos);
|
tail + tail_len - tailpos);
|
||||||
|
tailpos = hostapd_eid_dpp_cc(hapd, tailpos, tail + tail_len - tailpos);
|
||||||
|
|
||||||
if (hapd->conf->vendor_elements) {
|
if (hapd->conf->vendor_elements) {
|
||||||
os_memcpy(tailpos, wpabuf_head(hapd->conf->vendor_elements),
|
os_memcpy(tailpos, wpabuf_head(hapd->conf->vendor_elements),
|
||||||
@ -1310,10 +1388,13 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
|||||||
params->key_mgmt_suites = hapd->conf->wpa_key_mgmt;
|
params->key_mgmt_suites = hapd->conf->wpa_key_mgmt;
|
||||||
params->auth_algs = hapd->conf->auth_algs;
|
params->auth_algs = hapd->conf->auth_algs;
|
||||||
params->wpa_version = hapd->conf->wpa;
|
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->ieee802_1x &&
|
||||||
(hapd->conf->default_wep_key_len ||
|
(hapd->conf->default_wep_key_len ||
|
||||||
hapd->conf->individual_wep_key_len));
|
hapd->conf->individual_wep_key_len));
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
switch (hapd->conf->ignore_broadcast_ssid) {
|
switch (hapd->conf->ignore_broadcast_ssid) {
|
||||||
case 0:
|
case 0:
|
||||||
params->hide_ssid = NO_SSID_HIDING;
|
params->hide_ssid = NO_SSID_HIDING;
|
||||||
@ -1326,7 +1407,6 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
params->isolate = hapd->conf->isolate;
|
params->isolate = hapd->conf->isolate;
|
||||||
params->smps_mode = hapd->iconf->ht_capab & HT_CAP_INFO_SMPS_MASK;
|
|
||||||
#ifdef NEED_AP_MLME
|
#ifdef NEED_AP_MLME
|
||||||
params->cts_protect = !!(ieee802_11_erp_info(hapd) &
|
params->cts_protect = !!(ieee802_11_erp_info(hapd) &
|
||||||
ERP_INFO_USE_PROTECTION);
|
ERP_INFO_USE_PROTECTION);
|
||||||
@ -1422,8 +1502,18 @@ int ieee802_11_set_beacon(struct hostapd_data *hapd)
|
|||||||
hapd->iface->conf->spr.srg_obss_pd_min_offset;
|
hapd->iface->conf->spr.srg_obss_pd_min_offset;
|
||||||
params.he_spr_srg_obss_pd_max_offset =
|
params.he_spr_srg_obss_pd_max_offset =
|
||||||
hapd->iface->conf->spr.srg_obss_pd_max_offset;
|
hapd->iface->conf->spr.srg_obss_pd_max_offset;
|
||||||
|
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);
|
||||||
#endif /* CONFIG_IEEE80211AX */
|
#endif /* CONFIG_IEEE80211AX */
|
||||||
hapd->reenable_beacon = 0;
|
hapd->reenable_beacon = 0;
|
||||||
|
#ifdef CONFIG_SAE
|
||||||
|
params.sae_pwe = hapd->conf->sae_pwe;
|
||||||
|
#endif /* CONFIG_SAE */
|
||||||
|
|
||||||
if (cmode &&
|
if (cmode &&
|
||||||
hostapd_set_freq_params(&freq, iconf->hw_mode, iface->freq,
|
hostapd_set_freq_params(&freq, iconf->hw_mode, iface->freq,
|
||||||
|
@ -345,7 +345,6 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211AC */
|
#endif /* CONFIG_IEEE80211AC */
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211N
|
|
||||||
if ((sta->flags & WLAN_STA_HT) && sta->ht_capabilities) {
|
if ((sta->flags & WLAN_STA_HT) && sta->ht_capabilities) {
|
||||||
res = os_snprintf(buf + len, buflen - len,
|
res = os_snprintf(buf + len, buflen - len,
|
||||||
"ht_caps_info=0x%04x\n",
|
"ht_caps_info=0x%04x\n",
|
||||||
@ -354,7 +353,6 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
|
|||||||
if (!os_snprintf_error(buflen - len, res))
|
if (!os_snprintf_error(buflen - len, res))
|
||||||
len += res;
|
len += res;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211N */
|
|
||||||
|
|
||||||
if (sta->ext_capability &&
|
if (sta->ext_capability &&
|
||||||
buflen - len > (unsigned) (11 + 2 * sta->ext_capability[0])) {
|
buflen - len > (unsigned) (11 + 2 * sta->ext_capability[0])) {
|
||||||
@ -750,7 +748,8 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
|
|||||||
iface->conf->ieee80211n && !hapd->conf->disable_11n,
|
iface->conf->ieee80211n && !hapd->conf->disable_11n,
|
||||||
iface->conf->ieee80211ac &&
|
iface->conf->ieee80211ac &&
|
||||||
!hapd->conf->disable_11ac,
|
!hapd->conf->disable_11ac,
|
||||||
iface->conf->ieee80211ax,
|
iface->conf->ieee80211ax &&
|
||||||
|
!hapd->conf->disable_11ax,
|
||||||
iface->conf->beacon_int,
|
iface->conf->beacon_int,
|
||||||
hapd->conf->dtim_period);
|
hapd->conf->dtim_period);
|
||||||
if (os_snprintf_error(buflen - len, ret))
|
if (os_snprintf_error(buflen - len, ret))
|
||||||
@ -758,7 +757,7 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
|
|||||||
len += ret;
|
len += ret;
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211AX
|
#ifdef CONFIG_IEEE80211AX
|
||||||
if (iface->conf->ieee80211ax) {
|
if (iface->conf->ieee80211ax && !hapd->conf->disable_11ax) {
|
||||||
ret = os_snprintf(buf + len, buflen - len,
|
ret = os_snprintf(buf + len, buflen - len,
|
||||||
"he_oper_chwidth=%d\n"
|
"he_oper_chwidth=%d\n"
|
||||||
"he_oper_centr_freq_seg0_idx=%d\n"
|
"he_oper_centr_freq_seg0_idx=%d\n"
|
||||||
|
274
src/ap/dfs.c
274
src/ap/dfs.c
@ -144,30 +144,44 @@ static int dfs_chan_range_available(struct hostapd_hw_modes *mode,
|
|||||||
int i;
|
int i;
|
||||||
u32 bw = num_chan_to_bw(num_chans);
|
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;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
first_chan = &mode->channels[first_chan_idx];
|
first_chan = &mode->channels[first_chan_idx];
|
||||||
|
|
||||||
/* hostapd DFS implementation assumes the first channel as primary.
|
/* hostapd DFS implementation assumes the first channel as primary.
|
||||||
* If it's not allowed to use the first channel as primary, decline the
|
* If it's not allowed to use the first channel as primary, decline the
|
||||||
* whole channel range. */
|
* 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;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < num_chans; i++) {
|
for (i = 0; i < num_chans; i++) {
|
||||||
chan = dfs_get_chan_data(mode, first_chan->freq + i * 20,
|
chan = dfs_get_chan_data(mode, first_chan->freq + i * 20,
|
||||||
first_chan_idx);
|
first_chan_idx);
|
||||||
if (!chan)
|
if (!chan) {
|
||||||
|
wpa_printf(MSG_DEBUG, "DFS: no channel data for %d",
|
||||||
|
first_chan->freq + i * 20);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* HT 40 MHz secondary channel availability checked only for
|
/* HT 40 MHz secondary channel availability checked only for
|
||||||
* primary channel */
|
* 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;
|
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 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -210,22 +224,36 @@ static int dfs_find_channel(struct hostapd_iface *iface,
|
|||||||
if (iface->conf->ieee80211n &&
|
if (iface->conf->ieee80211n &&
|
||||||
iface->conf->secondary_channel &&
|
iface->conf->secondary_channel &&
|
||||||
(!dfs_is_chan_allowed(chan, n_chans) ||
|
(!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;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* Skip incompatible chandefs */
|
/* 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;
|
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;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (ret_chan && idx == channel_idx) {
|
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;
|
*ret_chan = chan;
|
||||||
return idx;
|
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++;
|
channel_idx++;
|
||||||
}
|
}
|
||||||
return 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,
|
static void dfs_adjust_center_freq(struct hostapd_iface *iface,
|
||||||
struct hostapd_channel_data *chan,
|
struct hostapd_channel_data *chan,
|
||||||
int secondary_channel,
|
int secondary_channel,
|
||||||
|
int sec_chan_idx_80p80,
|
||||||
u8 *oper_centr_freq_seg0_idx,
|
u8 *oper_centr_freq_seg0_idx,
|
||||||
u8 *oper_centr_freq_seg1_idx)
|
u8 *oper_centr_freq_seg1_idx)
|
||||||
{
|
{
|
||||||
@ -261,8 +290,14 @@ static void dfs_adjust_center_freq(struct hostapd_iface *iface,
|
|||||||
case CHANWIDTH_160MHZ:
|
case CHANWIDTH_160MHZ:
|
||||||
*oper_centr_freq_seg0_idx = chan->chan + 14;
|
*oper_centr_freq_seg0_idx = chan->chan + 14;
|
||||||
break;
|
break;
|
||||||
|
case CHANWIDTH_80P80MHZ:
|
||||||
|
*oper_centr_freq_seg0_idx = chan->chan + 6;
|
||||||
|
*oper_centr_freq_seg1_idx = sec_chan_idx_80p80 + 6;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
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;
|
*oper_centr_freq_seg0_idx = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -441,8 +476,11 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
|
|||||||
{
|
{
|
||||||
struct hostapd_hw_modes *mode;
|
struct hostapd_hw_modes *mode;
|
||||||
struct hostapd_channel_data *chan = NULL;
|
struct hostapd_channel_data *chan = NULL;
|
||||||
|
struct hostapd_channel_data *chan2 = NULL;
|
||||||
int num_available_chandefs;
|
int num_available_chandefs;
|
||||||
int chan_idx;
|
int chan_idx, chan_idx2;
|
||||||
|
int sec_chan_idx_80p80 = -1;
|
||||||
|
int i;
|
||||||
u32 _rand;
|
u32 _rand;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "DFS: Selecting random channel");
|
wpa_printf(MSG_DEBUG, "DFS: Selecting random channel");
|
||||||
@ -459,6 +497,8 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
|
|||||||
|
|
||||||
/* Get the count first */
|
/* Get the count first */
|
||||||
num_available_chandefs = dfs_find_channel(iface, NULL, 0, skip_radar);
|
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)
|
if (num_available_chandefs == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -466,6 +506,12 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
|
|||||||
return NULL;
|
return NULL;
|
||||||
chan_idx = _rand % num_available_chandefs;
|
chan_idx = _rand % num_available_chandefs;
|
||||||
dfs_find_channel(iface, &chan, chan_idx, skip_radar);
|
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+ */
|
/* dfs_find_channel() calculations assume HT40+ */
|
||||||
if (iface->conf->secondary_channel)
|
if (iface->conf->secondary_channel)
|
||||||
@ -473,8 +519,45 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
|
|||||||
else
|
else
|
||||||
*secondary_channel = 0;
|
*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,
|
dfs_adjust_center_freq(iface, chan,
|
||||||
*secondary_channel,
|
*secondary_channel,
|
||||||
|
sec_chan_idx_80p80,
|
||||||
oper_centr_freq_seg0_idx,
|
oper_centr_freq_seg0_idx,
|
||||||
oper_centr_freq_seg1_idx);
|
oper_centr_freq_seg1_idx);
|
||||||
|
|
||||||
@ -773,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;
|
int n_chans, n_chans1, start_chan_idx, start_chan_idx1;
|
||||||
|
|
||||||
@ -821,7 +904,7 @@ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
|
|||||||
* another radio.
|
* another radio.
|
||||||
*/
|
*/
|
||||||
if (iface->state != HAPD_IFACE_ENABLED &&
|
if (iface->state != HAPD_IFACE_ENABLED &&
|
||||||
hostapd_config_dfs_chan_available(iface)) {
|
hostapd_is_dfs_chan_available(iface)) {
|
||||||
hostapd_setup_interface_complete(iface, 0);
|
hostapd_setup_interface_complete(iface, 0);
|
||||||
iface->cac_started = 0;
|
iface->cac_started = 0;
|
||||||
}
|
}
|
||||||
@ -851,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)
|
static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface)
|
||||||
{
|
{
|
||||||
struct hostapd_channel_data *channel;
|
struct hostapd_channel_data *channel;
|
||||||
@ -868,8 +989,14 @@ static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface)
|
|||||||
skip_radar);
|
skip_radar);
|
||||||
|
|
||||||
if (!channel) {
|
if (!channel) {
|
||||||
wpa_printf(MSG_ERROR, "No valid channel available");
|
channel = dfs_downgrade_bandwidth(iface, &secondary_channel,
|
||||||
return err;
|
&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",
|
wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d",
|
||||||
@ -898,11 +1025,14 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
|
|||||||
int secondary_channel;
|
int secondary_channel;
|
||||||
u8 oper_centr_freq_seg0_idx;
|
u8 oper_centr_freq_seg0_idx;
|
||||||
u8 oper_centr_freq_seg1_idx;
|
u8 oper_centr_freq_seg1_idx;
|
||||||
|
u8 new_vht_oper_chwidth;
|
||||||
int skip_radar = 1;
|
int skip_radar = 1;
|
||||||
struct csa_settings csa_settings;
|
struct csa_settings csa_settings;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int err = 1;
|
int err = 1;
|
||||||
struct hostapd_hw_modes *cmode = iface->current_mode;
|
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)",
|
wpa_printf(MSG_DEBUG, "%s called (CAC active: %s, CSA active: %s)",
|
||||||
__func__, iface->cac_started ? "yes" : "no",
|
__func__, iface->cac_started ? "yes" : "no",
|
||||||
@ -936,28 +1066,33 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
|
|||||||
* requires to perform a CAC first.
|
* requires to perform a CAC first.
|
||||||
*/
|
*/
|
||||||
skip_radar = 0;
|
skip_radar = 0;
|
||||||
channel = dfs_get_valid_channel(iface, &secondary_channel,
|
channel = dfs_downgrade_bandwidth(iface, &secondary_channel,
|
||||||
&oper_centr_freq_seg0_idx,
|
&oper_centr_freq_seg0_idx,
|
||||||
&oper_centr_freq_seg1_idx,
|
&oper_centr_freq_seg1_idx,
|
||||||
skip_radar);
|
&skip_radar);
|
||||||
if (!channel) {
|
if (!channel) {
|
||||||
wpa_printf(MSG_INFO,
|
/*
|
||||||
"%s: no DFS channels left, waiting for NOP to finish",
|
* Toggle interface state to enter DFS state
|
||||||
__func__);
|
* until NOP is finished.
|
||||||
return err;
|
*/
|
||||||
|
hostapd_disable_iface(iface);
|
||||||
|
hostapd_enable_iface(iface);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
iface->freq = channel->freq;
|
if (!skip_radar) {
|
||||||
iface->conf->channel = channel->chan;
|
iface->freq = channel->freq;
|
||||||
iface->conf->secondary_channel = secondary_channel;
|
iface->conf->channel = channel->chan;
|
||||||
hostapd_set_oper_centr_freq_seg0_idx(iface->conf,
|
iface->conf->secondary_channel = secondary_channel;
|
||||||
oper_centr_freq_seg0_idx);
|
hostapd_set_oper_centr_freq_seg0_idx(
|
||||||
hostapd_set_oper_centr_freq_seg1_idx(iface->conf,
|
iface->conf, oper_centr_freq_seg0_idx);
|
||||||
oper_centr_freq_seg1_idx);
|
hostapd_set_oper_centr_freq_seg1_idx(
|
||||||
|
iface->conf, oper_centr_freq_seg1_idx);
|
||||||
|
|
||||||
hostapd_disable_iface(iface);
|
hostapd_disable_iface(iface);
|
||||||
hostapd_enable_iface(iface);
|
hostapd_enable_iface(iface);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d",
|
wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d",
|
||||||
@ -966,10 +1101,17 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
|
|||||||
"freq=%d chan=%d sec_chan=%d", channel->freq,
|
"freq=%d chan=%d sec_chan=%d", channel->freq,
|
||||||
channel->chan, secondary_channel);
|
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 */
|
/* Setup CSA request */
|
||||||
os_memset(&csa_settings, 0, sizeof(csa_settings));
|
os_memset(&csa_settings, 0, sizeof(csa_settings));
|
||||||
csa_settings.cs_count = 5;
|
csa_settings.cs_count = 5;
|
||||||
csa_settings.block_tx = 1;
|
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,
|
err = hostapd_set_freq_params(&csa_settings.freq_params,
|
||||||
iface->conf->hw_mode,
|
iface->conf->hw_mode,
|
||||||
channel->freq,
|
channel->freq,
|
||||||
@ -980,11 +1122,11 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
|
|||||||
iface->conf->ieee80211ac,
|
iface->conf->ieee80211ac,
|
||||||
iface->conf->ieee80211ax,
|
iface->conf->ieee80211ax,
|
||||||
secondary_channel,
|
secondary_channel,
|
||||||
hostapd_get_oper_chwidth(iface->conf),
|
new_vht_oper_chwidth,
|
||||||
oper_centr_freq_seg0_idx,
|
oper_centr_freq_seg0_idx,
|
||||||
oper_centr_freq_seg1_idx,
|
oper_centr_freq_seg1_idx,
|
||||||
cmode->vht_capab,
|
cmode->vht_capab,
|
||||||
&cmode->he_capab[IEEE80211_MODE_AP]);
|
&cmode->he_capab[ieee80211_mode]);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params");
|
wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params");
|
||||||
@ -1004,6 +1146,7 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
|
|||||||
iface->freq = channel->freq;
|
iface->freq = channel->freq;
|
||||||
iface->conf->channel = channel->chan;
|
iface->conf->channel = channel->chan;
|
||||||
iface->conf->secondary_channel = secondary_channel;
|
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,
|
hostapd_set_oper_centr_freq_seg0_idx(iface->conf,
|
||||||
oper_centr_freq_seg0_idx);
|
oper_centr_freq_seg0_idx);
|
||||||
hostapd_set_oper_centr_freq_seg1_idx(iface->conf,
|
hostapd_set_oper_centr_freq_seg1_idx(iface->conf,
|
||||||
@ -1040,8 +1183,10 @@ int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* mark radar frequency as invalid */
|
/* mark radar frequency as invalid */
|
||||||
set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width,
|
res = set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width,
|
||||||
cf1, cf2, HOSTAPD_CHAN_DFS_UNAVAILABLE);
|
cf1, cf2, HOSTAPD_CHAN_DFS_UNAVAILABLE);
|
||||||
|
if (!res)
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* Skip if reported radar event not overlapped our channels */
|
/* Skip if reported radar event not overlapped our channels */
|
||||||
res = dfs_are_channels_overlapped(iface, freq, chan_width, cf1, cf2);
|
res = dfs_are_channels_overlapped(iface, freq, chan_width, cf1, cf2);
|
||||||
@ -1161,3 +1306,56 @@ int hostapd_handle_dfs_offload(struct hostapd_iface *iface)
|
|||||||
__func__, iface->freq);
|
__func__, iface->freq);
|
||||||
return 2;
|
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 (center_freq - chan->freq < half_width &&
|
||||||
|
chan->freq - center_freq < half_width)
|
||||||
|
res++;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "DFS: (%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 ht_enabled,
|
||||||
int chan_offset, int chan_width, int cf1, int cf2);
|
int chan_offset, int chan_width, int cf1, int cf2);
|
||||||
int hostapd_is_dfs_required(struct hostapd_iface *iface);
|
int hostapd_is_dfs_required(struct hostapd_iface *iface);
|
||||||
|
int hostapd_is_dfs_chan_available(struct hostapd_iface *iface);
|
||||||
int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
|
int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
|
||||||
int ht_enabled, int chan_offset, int chan_width,
|
int ht_enabled, int chan_offset, int chan_width,
|
||||||
int cf1, int cf2);
|
int cf1, int cf2);
|
||||||
int hostapd_handle_dfs_offload(struct hostapd_iface *iface);
|
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 */
|
#endif /* DFS_H */
|
||||||
|
@ -26,6 +26,13 @@ static void hostapd_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx);
|
|||||||
static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator);
|
static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator);
|
||||||
static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx);
|
static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx);
|
||||||
static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd);
|
static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd);
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
static void hostapd_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
|
||||||
|
void *timeout_ctx);
|
||||||
|
static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd,
|
||||||
|
struct dpp_authentication *auth,
|
||||||
|
struct dpp_config_obj *conf);
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||||
|
|
||||||
@ -59,6 +66,10 @@ int hostapd_dpp_qr_code(struct hostapd_data *hapd, const char *cmd)
|
|||||||
wpabuf_len(hapd->dpp_auth->resp_msg));
|
wpabuf_len(hapd->dpp_auth->resp_msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
dpp_controller_new_qr_code(hapd->iface->interfaces->dpp, bi);
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
return bi->id;
|
return bi->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,6 +248,10 @@ void hostapd_dpp_tx_status(struct hostapd_data *hapd, const u8 *dst,
|
|||||||
hapd, NULL);
|
hapd, NULL);
|
||||||
eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd,
|
eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd,
|
||||||
NULL);
|
NULL);
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
|
||||||
|
hapd, NULL);
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
hostapd_drv_send_action_cancel_wait(hapd);
|
hostapd_drv_send_action_cancel_wait(hapd);
|
||||||
dpp_auth_deinit(hapd->dpp_auth);
|
dpp_auth_deinit(hapd->dpp_auth);
|
||||||
hapd->dpp_auth = NULL;
|
hapd->dpp_auth = NULL;
|
||||||
@ -478,12 +493,35 @@ static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
static int hostapd_dpp_process_conf_obj(void *ctx,
|
||||||
|
struct dpp_authentication *auth)
|
||||||
|
{
|
||||||
|
struct hostapd_data *hapd = ctx;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < auth->num_conf_obj; i++)
|
||||||
|
hostapd_dpp_handle_config_obj(hapd, auth,
|
||||||
|
&auth->conf_obj[i]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
|
|
||||||
int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd)
|
int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd)
|
||||||
{
|
{
|
||||||
const char *pos;
|
const char *pos;
|
||||||
struct dpp_bootstrap_info *peer_bi, *own_bi = NULL;
|
struct dpp_bootstrap_info *peer_bi, *own_bi = NULL;
|
||||||
|
struct dpp_authentication *auth;
|
||||||
u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
|
u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
|
||||||
unsigned int neg_freq = 0;
|
unsigned int neg_freq = 0;
|
||||||
|
int tcp = 0;
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
int tcp_port = DPP_TCP_PORT;
|
||||||
|
struct hostapd_ip_addr ipaddr;
|
||||||
|
char *addr;
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
pos = os_strstr(cmd, " peer=");
|
pos = os_strstr(cmd, " peer=");
|
||||||
if (!pos)
|
if (!pos)
|
||||||
@ -496,6 +534,25 @@ int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
pos = os_strstr(cmd, " tcp_port=");
|
||||||
|
if (pos) {
|
||||||
|
pos += 10;
|
||||||
|
tcp_port = atoi(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = get_param(cmd, " tcp_addr=");
|
||||||
|
if (addr) {
|
||||||
|
int res;
|
||||||
|
|
||||||
|
res = hostapd_parse_ip_addr(addr, &ipaddr);
|
||||||
|
os_free(addr);
|
||||||
|
if (res)
|
||||||
|
return -1;
|
||||||
|
tcp = 1;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
pos = os_strstr(cmd, " own=");
|
pos = os_strstr(cmd, " own=");
|
||||||
if (pos) {
|
if (pos) {
|
||||||
pos += 5;
|
pos += 5;
|
||||||
@ -533,36 +590,46 @@ int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd)
|
|||||||
if (pos)
|
if (pos)
|
||||||
neg_freq = atoi(pos + 10);
|
neg_freq = atoi(pos + 10);
|
||||||
|
|
||||||
if (hapd->dpp_auth) {
|
if (!tcp && hapd->dpp_auth) {
|
||||||
eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
|
eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
|
||||||
eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
|
eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
|
||||||
hapd, NULL);
|
hapd, NULL);
|
||||||
eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd,
|
eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd,
|
||||||
NULL);
|
NULL);
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
|
||||||
|
hapd, NULL);
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
hostapd_drv_send_action_cancel_wait(hapd);
|
hostapd_drv_send_action_cancel_wait(hapd);
|
||||||
dpp_auth_deinit(hapd->dpp_auth);
|
dpp_auth_deinit(hapd->dpp_auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
hapd->dpp_auth = dpp_auth_init(hapd->msg_ctx, peer_bi, own_bi,
|
auth = dpp_auth_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
|
||||||
allowed_roles, neg_freq,
|
peer_bi, own_bi, allowed_roles, neg_freq,
|
||||||
hapd->iface->hw_features,
|
hapd->iface->hw_features,
|
||||||
hapd->iface->num_hw_features);
|
hapd->iface->num_hw_features);
|
||||||
if (!hapd->dpp_auth)
|
if (!auth)
|
||||||
goto fail;
|
goto fail;
|
||||||
hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
|
hostapd_dpp_set_testing_options(hapd, auth);
|
||||||
if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx,
|
if (dpp_set_configurator(auth, cmd) < 0) {
|
||||||
hapd->dpp_auth, cmd) < 0) {
|
dpp_auth_deinit(auth);
|
||||||
dpp_auth_deinit(hapd->dpp_auth);
|
|
||||||
hapd->dpp_auth = NULL;
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
hapd->dpp_auth->neg_freq = neg_freq;
|
auth->neg_freq = neg_freq;
|
||||||
|
|
||||||
if (!is_zero_ether_addr(peer_bi->mac_addr))
|
if (!is_zero_ether_addr(peer_bi->mac_addr))
|
||||||
os_memcpy(hapd->dpp_auth->peer_mac_addr, peer_bi->mac_addr,
|
os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN);
|
||||||
ETH_ALEN);
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
if (tcp)
|
||||||
|
return dpp_tcp_init(hapd->iface->interfaces->dpp, auth,
|
||||||
|
&ipaddr, tcp_port, hapd->conf->dpp_name,
|
||||||
|
DPP_NETROLE_AP, hapd->msg_ctx, hapd,
|
||||||
|
hostapd_dpp_process_conf_obj);
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
|
hapd->dpp_auth = auth;
|
||||||
return hostapd_dpp_auth_init_next(hapd);
|
return hostapd_dpp_auth_init_next(hapd);
|
||||||
fail:
|
fail:
|
||||||
return -1;
|
return -1;
|
||||||
@ -618,6 +685,10 @@ static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src,
|
|||||||
wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
|
wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
|
||||||
MAC2STR(src));
|
MAC2STR(src));
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
hostapd_dpp_chirp_stop(hapd);
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
|
r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
|
||||||
&r_bootstrap_len);
|
&r_bootstrap_len);
|
||||||
if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
|
if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
|
||||||
@ -663,7 +734,8 @@ static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src,
|
|||||||
}
|
}
|
||||||
|
|
||||||
hapd->dpp_auth_ok_on_ack = 0;
|
hapd->dpp_auth_ok_on_ack = 0;
|
||||||
hapd->dpp_auth = dpp_auth_req_rx(hapd->msg_ctx, hapd->dpp_allowed_roles,
|
hapd->dpp_auth = dpp_auth_req_rx(hapd->iface->interfaces->dpp,
|
||||||
|
hapd->msg_ctx, hapd->dpp_allowed_roles,
|
||||||
hapd->dpp_qr_mutual,
|
hapd->dpp_qr_mutual,
|
||||||
peer_bi, own_bi, freq, hdr, buf, len);
|
peer_bi, own_bi, freq, hdr, buf, len);
|
||||||
if (!hapd->dpp_auth) {
|
if (!hapd->dpp_auth) {
|
||||||
@ -671,8 +743,7 @@ static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
|
hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
|
||||||
if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx,
|
if (dpp_set_configurator(hapd->dpp_auth,
|
||||||
hapd->dpp_auth,
|
|
||||||
hapd->dpp_configurator_params) < 0) {
|
hapd->dpp_configurator_params) < 0) {
|
||||||
dpp_auth_deinit(hapd->dpp_auth);
|
dpp_auth_deinit(hapd->dpp_auth);
|
||||||
hapd->dpp_auth = NULL;
|
hapd->dpp_auth = NULL;
|
||||||
@ -708,7 +779,8 @@ static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd,
|
|||||||
* message. */
|
* message. */
|
||||||
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
|
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
|
||||||
conf->connector);
|
conf->connector);
|
||||||
} else if (conf->passphrase[0]) {
|
}
|
||||||
|
if (conf->passphrase[0]) {
|
||||||
char hex[64 * 2 + 1];
|
char hex[64 * 2 + 1];
|
||||||
|
|
||||||
wpa_snprintf_hex(hex, sizeof(hex),
|
wpa_snprintf_hex(hex, sizeof(hex),
|
||||||
@ -1132,6 +1204,227 @@ static void hostapd_dpp_rx_conn_status_result(struct hostapd_data *hapd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
hostapd_dpp_rx_presence_announcement(struct hostapd_data *hapd, const u8 *src,
|
||||||
|
const u8 *hdr, const u8 *buf, size_t len,
|
||||||
|
unsigned int freq)
|
||||||
|
{
|
||||||
|
const u8 *r_bootstrap;
|
||||||
|
u16 r_bootstrap_len;
|
||||||
|
struct dpp_bootstrap_info *peer_bi;
|
||||||
|
struct dpp_authentication *auth;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Presence Announcement from " MACSTR,
|
||||||
|
MAC2STR(src));
|
||||||
|
|
||||||
|
r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
|
||||||
|
&r_bootstrap_len);
|
||||||
|
if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
|
||||||
|
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
|
||||||
|
"Missing or invalid required Responder Bootstrapping Key Hash attribute");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
|
||||||
|
r_bootstrap, r_bootstrap_len);
|
||||||
|
peer_bi = dpp_bootstrap_find_chirp(hapd->iface->interfaces->dpp,
|
||||||
|
r_bootstrap);
|
||||||
|
dpp_notify_chirp_received(hapd->msg_ctx,
|
||||||
|
peer_bi ? (int) peer_bi->id : -1,
|
||||||
|
src, freq, r_bootstrap);
|
||||||
|
if (!peer_bi) {
|
||||||
|
if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
|
||||||
|
src, hdr, buf, len, freq, NULL,
|
||||||
|
r_bootstrap) == 0)
|
||||||
|
return;
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: No matching bootstrapping information found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hapd->dpp_auth) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: Ignore Presence Announcement during ongoing Authentication");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auth = dpp_auth_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
|
||||||
|
peer_bi, NULL, DPP_CAPAB_CONFIGURATOR, freq, NULL,
|
||||||
|
0);
|
||||||
|
if (!auth)
|
||||||
|
return;
|
||||||
|
hostapd_dpp_set_testing_options(hapd, auth);
|
||||||
|
if (dpp_set_configurator(auth,
|
||||||
|
hapd->dpp_configurator_params) < 0) {
|
||||||
|
dpp_auth_deinit(auth);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auth->neg_freq = freq;
|
||||||
|
|
||||||
|
if (!is_zero_ether_addr(peer_bi->mac_addr))
|
||||||
|
os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN);
|
||||||
|
|
||||||
|
hapd->dpp_auth = auth;
|
||||||
|
if (hostapd_dpp_auth_init_next(hapd) < 0) {
|
||||||
|
dpp_auth_deinit(hapd->dpp_auth);
|
||||||
|
hapd->dpp_auth = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void hostapd_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
|
||||||
|
void *timeout_ctx)
|
||||||
|
{
|
||||||
|
struct hostapd_data *hapd = eloop_ctx;
|
||||||
|
struct dpp_authentication *auth = hapd->dpp_auth;
|
||||||
|
|
||||||
|
if (!auth)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Reconfig Reply wait timeout");
|
||||||
|
hostapd_dpp_listen_stop(hapd);
|
||||||
|
dpp_auth_deinit(auth);
|
||||||
|
hapd->dpp_auth = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
hostapd_dpp_rx_reconfig_announcement(struct hostapd_data *hapd, const u8 *src,
|
||||||
|
const u8 *hdr, const u8 *buf, size_t len,
|
||||||
|
unsigned int freq)
|
||||||
|
{
|
||||||
|
const u8 *csign_hash, *fcgroup, *a_nonce, *e_id;
|
||||||
|
u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len;
|
||||||
|
struct dpp_configurator *conf;
|
||||||
|
struct dpp_authentication *auth;
|
||||||
|
unsigned int wait_time, max_wait_time;
|
||||||
|
u16 group;
|
||||||
|
|
||||||
|
if (hapd->dpp_auth) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: Ignore Reconfig Announcement during ongoing Authentication");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement from " MACSTR,
|
||||||
|
MAC2STR(src));
|
||||||
|
|
||||||
|
csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH,
|
||||||
|
&csign_hash_len);
|
||||||
|
if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) {
|
||||||
|
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
|
||||||
|
"Missing or invalid required Configurator C-sign key Hash attribute");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)",
|
||||||
|
csign_hash, csign_hash_len);
|
||||||
|
conf = dpp_configurator_find_kid(hapd->iface->interfaces->dpp,
|
||||||
|
csign_hash);
|
||||||
|
if (!conf) {
|
||||||
|
if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
|
||||||
|
src, hdr, buf, len, freq, NULL,
|
||||||
|
NULL) == 0)
|
||||||
|
return;
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: No matching Configurator information found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
|
||||||
|
&fcgroup_len);
|
||||||
|
if (!fcgroup || fcgroup_len != 2) {
|
||||||
|
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
|
||||||
|
"Missing or invalid required Finite Cyclic Group attribute");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
group = WPA_GET_LE16(fcgroup);
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group);
|
||||||
|
|
||||||
|
a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len);
|
||||||
|
e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len);
|
||||||
|
|
||||||
|
auth = dpp_reconfig_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
|
||||||
|
conf, freq, group, a_nonce, a_nonce_len,
|
||||||
|
e_id, e_id_len);
|
||||||
|
if (!auth)
|
||||||
|
return;
|
||||||
|
hostapd_dpp_set_testing_options(hapd, auth);
|
||||||
|
if (dpp_set_configurator(auth, hapd->dpp_configurator_params) < 0) {
|
||||||
|
dpp_auth_deinit(auth);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
|
||||||
|
hapd->dpp_auth = auth;
|
||||||
|
|
||||||
|
hapd->dpp_in_response_listen = 0;
|
||||||
|
hapd->dpp_auth_ok_on_ack = 0;
|
||||||
|
wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */
|
||||||
|
max_wait_time = hapd->dpp_resp_wait_time ?
|
||||||
|
hapd->dpp_resp_wait_time : 2000;
|
||||||
|
if (wait_time > max_wait_time)
|
||||||
|
wait_time = max_wait_time;
|
||||||
|
wait_time += 10; /* give the driver some extra time to complete */
|
||||||
|
eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
|
||||||
|
hostapd_dpp_reconfig_reply_wait_timeout,
|
||||||
|
hapd, NULL);
|
||||||
|
wait_time -= 10;
|
||||||
|
|
||||||
|
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
|
||||||
|
" freq=%u type=%d",
|
||||||
|
MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_REQ);
|
||||||
|
if (hostapd_drv_send_action(hapd, freq, wait_time, src,
|
||||||
|
wpabuf_head(auth->reconfig_req_msg),
|
||||||
|
wpabuf_len(auth->reconfig_req_msg)) < 0) {
|
||||||
|
dpp_auth_deinit(hapd->dpp_auth);
|
||||||
|
hapd->dpp_auth = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
hostapd_dpp_rx_reconfig_auth_resp(struct hostapd_data *hapd, const u8 *src,
|
||||||
|
const u8 *hdr, const u8 *buf, size_t len,
|
||||||
|
unsigned int freq)
|
||||||
|
{
|
||||||
|
struct dpp_authentication *auth = hapd->dpp_auth;
|
||||||
|
struct wpabuf *conf;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response from "
|
||||||
|
MACSTR, MAC2STR(src));
|
||||||
|
|
||||||
|
if (!auth || !auth->reconfig || !auth->configurator) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: No DPP Reconfig Authentication in progress - drop");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
|
||||||
|
MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len);
|
||||||
|
if (!conf)
|
||||||
|
return;
|
||||||
|
|
||||||
|
eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
|
||||||
|
hapd, NULL);
|
||||||
|
|
||||||
|
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
|
||||||
|
" freq=%u type=%d",
|
||||||
|
MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_CONF);
|
||||||
|
if (hostapd_drv_send_action(hapd, freq, 500, src,
|
||||||
|
wpabuf_head(conf), wpabuf_len(conf)) < 0) {
|
||||||
|
wpabuf_free(conf);
|
||||||
|
dpp_auth_deinit(hapd->dpp_auth);
|
||||||
|
hapd->dpp_auth = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wpabuf_free(conf);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_DPP2 */
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
|
|
||||||
@ -1141,9 +1434,13 @@ static void hostapd_dpp_send_peer_disc_resp(struct hostapd_data *hapd,
|
|||||||
enum dpp_status_error status)
|
enum dpp_status_error status)
|
||||||
{
|
{
|
||||||
struct wpabuf *msg;
|
struct wpabuf *msg;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_RESP,
|
len = 5 + 5 + 4 + os_strlen(hapd->conf->dpp_connector);
|
||||||
5 + 5 + 4 + os_strlen(hapd->conf->dpp_connector));
|
#ifdef CONFIG_DPP2
|
||||||
|
len += 5;
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
|
msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_RESP, len);
|
||||||
if (!msg)
|
if (!msg)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1216,6 +1513,15 @@ skip_status:
|
|||||||
skip_connector:
|
skip_connector:
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
if (DPP_VERSION > 1) {
|
||||||
|
/* Protocol Version */
|
||||||
|
wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
|
||||||
|
wpabuf_put_le16(msg, 1);
|
||||||
|
wpabuf_put_u8(msg, DPP_VERSION);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "DPP: Send Peer Discovery Response to " MACSTR
|
wpa_printf(MSG_DEBUG, "DPP: Send Peer Discovery Response to " MACSTR
|
||||||
" status=%d", MAC2STR(src), status);
|
" status=%d", MAC2STR(src), status);
|
||||||
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
|
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
|
||||||
@ -1581,6 +1887,18 @@ void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src,
|
|||||||
case DPP_PA_CONNECTION_STATUS_RESULT:
|
case DPP_PA_CONNECTION_STATUS_RESULT:
|
||||||
hostapd_dpp_rx_conn_status_result(hapd, src, hdr, buf, len);
|
hostapd_dpp_rx_conn_status_result(hapd, src, hdr, buf, len);
|
||||||
break;
|
break;
|
||||||
|
case DPP_PA_PRESENCE_ANNOUNCEMENT:
|
||||||
|
hostapd_dpp_rx_presence_announcement(hapd, src, hdr, buf, len,
|
||||||
|
freq);
|
||||||
|
break;
|
||||||
|
case DPP_PA_RECONFIG_ANNOUNCEMENT:
|
||||||
|
hostapd_dpp_rx_reconfig_announcement(hapd, src, hdr, buf, len,
|
||||||
|
freq);
|
||||||
|
break;
|
||||||
|
case DPP_PA_RECONFIG_AUTH_RESP:
|
||||||
|
hostapd_dpp_rx_reconfig_auth_resp(hapd, src, hdr, buf, len,
|
||||||
|
freq);
|
||||||
|
break;
|
||||||
#endif /* CONFIG_DPP2 */
|
#endif /* CONFIG_DPP2 */
|
||||||
default:
|
default:
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
@ -1610,7 +1928,7 @@ hostapd_dpp_gas_req_handler(struct hostapd_data *hapd, const u8 *sa,
|
|||||||
struct wpabuf *resp;
|
struct wpabuf *resp;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR, MAC2STR(sa));
|
wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR, MAC2STR(sa));
|
||||||
if (!auth || !auth->auth_success ||
|
if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
|
||||||
os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
|
os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
|
||||||
#ifdef CONFIG_DPP2
|
#ifdef CONFIG_DPP2
|
||||||
if (dpp_relay_rx_gas_req(hapd->iface->interfaces->dpp, sa, data,
|
if (dpp_relay_rx_gas_req(hapd->iface->interfaces->dpp, sa, data,
|
||||||
@ -1646,6 +1964,8 @@ void hostapd_dpp_gas_status_handler(struct hostapd_data *hapd, int ok)
|
|||||||
eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
|
eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
|
||||||
eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
|
eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
|
||||||
#ifdef CONFIG_DPP2
|
#ifdef CONFIG_DPP2
|
||||||
|
eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
|
||||||
|
hapd, NULL);
|
||||||
if (ok && auth->peer_version >= 2 &&
|
if (ok && auth->peer_version >= 2 &&
|
||||||
auth->conf_resp_status == DPP_STATUS_OK) {
|
auth->conf_resp_status == DPP_STATUS_OK) {
|
||||||
wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
|
wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
|
||||||
@ -1675,14 +1995,13 @@ int hostapd_dpp_configurator_sign(struct hostapd_data *hapd, const char *cmd)
|
|||||||
int ret = -1;
|
int ret = -1;
|
||||||
char *curve = NULL;
|
char *curve = NULL;
|
||||||
|
|
||||||
auth = os_zalloc(sizeof(*auth));
|
auth = dpp_alloc_auth(hapd->iface->interfaces->dpp, hapd->msg_ctx);
|
||||||
if (!auth)
|
if (!auth)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
curve = get_param(cmd, " curve=");
|
curve = get_param(cmd, " curve=");
|
||||||
hostapd_dpp_set_testing_options(hapd, auth);
|
hostapd_dpp_set_testing_options(hapd, auth);
|
||||||
if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx,
|
if (dpp_set_configurator(auth, cmd) == 0 &&
|
||||||
auth, cmd) == 0 &&
|
|
||||||
dpp_configurator_own_config(auth, curve, 1) == 0) {
|
dpp_configurator_own_config(auth, curve, 1) == 0) {
|
||||||
hostapd_dpp_handle_config_obj(hapd, auth, &auth->conf_obj[0]);
|
hostapd_dpp_handle_config_obj(hapd, auth, &auth->conf_obj[0]);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
@ -1891,10 +2210,13 @@ void hostapd_dpp_deinit(struct hostapd_data *hapd)
|
|||||||
eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
|
eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
|
||||||
eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
|
eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
|
||||||
#ifdef CONFIG_DPP2
|
#ifdef CONFIG_DPP2
|
||||||
|
eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
|
||||||
|
hapd, NULL);
|
||||||
eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd,
|
eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd,
|
||||||
NULL);
|
NULL);
|
||||||
eloop_cancel_timeout(hostapd_dpp_conn_status_result_wait_timeout, hapd,
|
eloop_cancel_timeout(hostapd_dpp_conn_status_result_wait_timeout, hapd,
|
||||||
NULL);
|
NULL);
|
||||||
|
hostapd_dpp_chirp_stop(hapd);
|
||||||
#endif /* CONFIG_DPP2 */
|
#endif /* CONFIG_DPP2 */
|
||||||
dpp_auth_deinit(hapd->dpp_auth);
|
dpp_auth_deinit(hapd->dpp_auth);
|
||||||
hapd->dpp_auth = NULL;
|
hapd->dpp_auth = NULL;
|
||||||
@ -1903,3 +2225,359 @@ void hostapd_dpp_deinit(struct hostapd_data *hapd)
|
|||||||
os_free(hapd->dpp_configurator_params);
|
os_free(hapd->dpp_configurator_params);
|
||||||
hapd->dpp_configurator_params = NULL;
|
hapd->dpp_configurator_params = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
|
||||||
|
int hostapd_dpp_controller_start(struct hostapd_data *hapd, const char *cmd)
|
||||||
|
{
|
||||||
|
struct dpp_controller_config config;
|
||||||
|
const char *pos;
|
||||||
|
|
||||||
|
os_memset(&config, 0, sizeof(config));
|
||||||
|
config.allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR;
|
||||||
|
config.netrole = DPP_NETROLE_AP;
|
||||||
|
config.msg_ctx = hapd->msg_ctx;
|
||||||
|
config.cb_ctx = hapd;
|
||||||
|
config.process_conf_obj = hostapd_dpp_process_conf_obj;
|
||||||
|
if (cmd) {
|
||||||
|
pos = os_strstr(cmd, " tcp_port=");
|
||||||
|
if (pos) {
|
||||||
|
pos += 10;
|
||||||
|
config.tcp_port = atoi(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = os_strstr(cmd, " role=");
|
||||||
|
if (pos) {
|
||||||
|
pos += 6;
|
||||||
|
if (os_strncmp(pos, "configurator", 12) == 0)
|
||||||
|
config.allowed_roles = DPP_CAPAB_CONFIGURATOR;
|
||||||
|
else if (os_strncmp(pos, "enrollee", 8) == 0)
|
||||||
|
config.allowed_roles = DPP_CAPAB_ENROLLEE;
|
||||||
|
else if (os_strncmp(pos, "either", 6) == 0)
|
||||||
|
config.allowed_roles = DPP_CAPAB_CONFIGURATOR |
|
||||||
|
DPP_CAPAB_ENROLLEE;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
config.qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
|
||||||
|
}
|
||||||
|
config.configurator_params = hapd->dpp_configurator_params;
|
||||||
|
return dpp_controller_start(hapd->iface->interfaces->dpp, &config);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void hostapd_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx);
|
||||||
|
|
||||||
|
static void hostapd_dpp_chirp_timeout(void *eloop_ctx, void *timeout_ctx)
|
||||||
|
{
|
||||||
|
struct hostapd_data *hapd = eloop_ctx;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: No chirp response received");
|
||||||
|
hostapd_drv_send_action_cancel_wait(hapd);
|
||||||
|
hostapd_dpp_chirp_next(hapd, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void hostapd_dpp_chirp_start(struct hostapd_data *hapd)
|
||||||
|
{
|
||||||
|
struct wpabuf *msg;
|
||||||
|
int type;
|
||||||
|
|
||||||
|
msg = hapd->dpp_presence_announcement;
|
||||||
|
type = DPP_PA_PRESENCE_ANNOUNCEMENT;
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", hapd->dpp_chirp_freq);
|
||||||
|
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
|
||||||
|
" freq=%u type=%d",
|
||||||
|
MAC2STR(broadcast), hapd->dpp_chirp_freq, type);
|
||||||
|
if (hostapd_drv_send_action(
|
||||||
|
hapd, hapd->dpp_chirp_freq, 2000, broadcast,
|
||||||
|
wpabuf_head(msg), wpabuf_len(msg)) < 0 ||
|
||||||
|
eloop_register_timeout(2, 0, hostapd_dpp_chirp_timeout,
|
||||||
|
hapd, NULL) < 0)
|
||||||
|
hostapd_dpp_chirp_stop(hapd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct hostapd_hw_modes *
|
||||||
|
dpp_get_mode(struct hostapd_data *hapd,
|
||||||
|
enum hostapd_hw_mode mode)
|
||||||
|
{
|
||||||
|
struct hostapd_hw_modes *modes = hapd->iface->hw_features;
|
||||||
|
u16 num_modes = hapd->iface->num_hw_features;
|
||||||
|
u16 i;
|
||||||
|
|
||||||
|
for (i = 0; i < num_modes; i++) {
|
||||||
|
if (modes[i].mode != mode ||
|
||||||
|
!modes[i].num_channels || !modes[i].channels)
|
||||||
|
continue;
|
||||||
|
return &modes[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
hostapd_dpp_chirp_scan_res_handler(struct hostapd_iface *iface)
|
||||||
|
{
|
||||||
|
struct hostapd_data *hapd = iface->bss[0];
|
||||||
|
struct wpa_scan_results *scan_res;
|
||||||
|
struct dpp_bootstrap_info *bi = hapd->dpp_chirp_bi;
|
||||||
|
unsigned int i;
|
||||||
|
struct hostapd_hw_modes *mode;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
if (!bi)
|
||||||
|
return;
|
||||||
|
|
||||||
|
hapd->dpp_chirp_scan_done = 1;
|
||||||
|
|
||||||
|
scan_res = hostapd_driver_get_scan_results(hapd);
|
||||||
|
|
||||||
|
os_free(hapd->dpp_chirp_freqs);
|
||||||
|
hapd->dpp_chirp_freqs = NULL;
|
||||||
|
|
||||||
|
/* Channels from own bootstrapping info */
|
||||||
|
if (bi) {
|
||||||
|
for (i = 0; i < bi->num_freq; i++)
|
||||||
|
int_array_add_unique(&hapd->dpp_chirp_freqs,
|
||||||
|
bi->freq[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Preferred chirping channels */
|
||||||
|
int_array_add_unique(&hapd->dpp_chirp_freqs, 2437);
|
||||||
|
|
||||||
|
mode = dpp_get_mode(hapd, HOSTAPD_MODE_IEEE80211A);
|
||||||
|
if (mode) {
|
||||||
|
int chan44 = 0, chan149 = 0;
|
||||||
|
|
||||||
|
for (c = 0; c < mode->num_channels; c++) {
|
||||||
|
struct hostapd_channel_data *chan = &mode->channels[c];
|
||||||
|
|
||||||
|
if (chan->flag & (HOSTAPD_CHAN_DISABLED |
|
||||||
|
HOSTAPD_CHAN_RADAR))
|
||||||
|
continue;
|
||||||
|
if (chan->freq == 5220)
|
||||||
|
chan44 = 1;
|
||||||
|
if (chan->freq == 5745)
|
||||||
|
chan149 = 1;
|
||||||
|
}
|
||||||
|
if (chan149)
|
||||||
|
int_array_add_unique(&hapd->dpp_chirp_freqs, 5745);
|
||||||
|
else if (chan44)
|
||||||
|
int_array_add_unique(&hapd->dpp_chirp_freqs, 5220);
|
||||||
|
}
|
||||||
|
|
||||||
|
mode = dpp_get_mode(hapd, HOSTAPD_MODE_IEEE80211AD);
|
||||||
|
if (mode) {
|
||||||
|
for (c = 0; c < mode->num_channels; c++) {
|
||||||
|
struct hostapd_channel_data *chan = &mode->channels[c];
|
||||||
|
|
||||||
|
if ((chan->flag & (HOSTAPD_CHAN_DISABLED |
|
||||||
|
HOSTAPD_CHAN_RADAR)) ||
|
||||||
|
chan->freq != 60480)
|
||||||
|
continue;
|
||||||
|
int_array_add_unique(&hapd->dpp_chirp_freqs, 60480);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add channels from scan results for APs that advertise Configurator
|
||||||
|
* Connectivity element */
|
||||||
|
for (i = 0; scan_res && i < scan_res->num; i++) {
|
||||||
|
struct wpa_scan_res *bss = scan_res->res[i];
|
||||||
|
size_t ie_len = bss->ie_len;
|
||||||
|
|
||||||
|
if (!ie_len)
|
||||||
|
ie_len = bss->beacon_ie_len;
|
||||||
|
if (get_vendor_ie((const u8 *) (bss + 1), ie_len,
|
||||||
|
DPP_CC_IE_VENDOR_TYPE))
|
||||||
|
int_array_add_unique(&hapd->dpp_chirp_freqs,
|
||||||
|
bss->freq);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hapd->dpp_chirp_freqs ||
|
||||||
|
eloop_register_timeout(0, 0, hostapd_dpp_chirp_next,
|
||||||
|
hapd, NULL) < 0)
|
||||||
|
hostapd_dpp_chirp_stop(hapd);
|
||||||
|
|
||||||
|
wpa_scan_results_free(scan_res);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void hostapd_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx)
|
||||||
|
{
|
||||||
|
struct hostapd_data *hapd = eloop_ctx;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (hapd->dpp_chirp_listen)
|
||||||
|
hostapd_dpp_listen_stop(hapd);
|
||||||
|
|
||||||
|
if (hapd->dpp_chirp_freq == 0) {
|
||||||
|
if (hapd->dpp_chirp_round % 4 == 0 &&
|
||||||
|
!hapd->dpp_chirp_scan_done) {
|
||||||
|
struct wpa_driver_scan_params params;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: Update channel list for chirping");
|
||||||
|
os_memset(¶ms, 0, sizeof(params));
|
||||||
|
ret = hostapd_driver_scan(hapd, ¶ms);
|
||||||
|
if (ret < 0) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: Failed to request a scan ret=%d (%s)",
|
||||||
|
ret, strerror(-ret));
|
||||||
|
hostapd_dpp_chirp_scan_res_handler(hapd->iface);
|
||||||
|
} else {
|
||||||
|
hapd->iface->scan_cb =
|
||||||
|
hostapd_dpp_chirp_scan_res_handler;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hapd->dpp_chirp_freq = hapd->dpp_chirp_freqs[0];
|
||||||
|
hapd->dpp_chirp_round++;
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Start chirping round %d",
|
||||||
|
hapd->dpp_chirp_round);
|
||||||
|
} else {
|
||||||
|
for (i = 0; hapd->dpp_chirp_freqs[i]; i++)
|
||||||
|
if (hapd->dpp_chirp_freqs[i] == hapd->dpp_chirp_freq)
|
||||||
|
break;
|
||||||
|
if (!hapd->dpp_chirp_freqs[i]) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: Previous chirp freq %d not found",
|
||||||
|
hapd->dpp_chirp_freq);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
if (hapd->dpp_chirp_freqs[i]) {
|
||||||
|
hapd->dpp_chirp_freq = hapd->dpp_chirp_freqs[i];
|
||||||
|
} else {
|
||||||
|
hapd->dpp_chirp_iter--;
|
||||||
|
if (hapd->dpp_chirp_iter <= 0) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: Chirping iterations completed");
|
||||||
|
hostapd_dpp_chirp_stop(hapd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hapd->dpp_chirp_freq = 0;
|
||||||
|
hapd->dpp_chirp_scan_done = 0;
|
||||||
|
if (eloop_register_timeout(30, 0,
|
||||||
|
hostapd_dpp_chirp_next,
|
||||||
|
hapd, NULL) < 0) {
|
||||||
|
hostapd_dpp_chirp_stop(hapd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (hapd->dpp_chirp_listen) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: Listen on %d MHz during chirp 30 second wait",
|
||||||
|
hapd->dpp_chirp_listen);
|
||||||
|
/* TODO: start listen on the channel */
|
||||||
|
} else {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: Wait 30 seconds before starting the next chirping round");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hostapd_dpp_chirp_start(hapd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int hostapd_dpp_chirp(struct hostapd_data *hapd, const char *cmd)
|
||||||
|
{
|
||||||
|
const char *pos;
|
||||||
|
int iter = 1, listen_freq = 0;
|
||||||
|
struct dpp_bootstrap_info *bi;
|
||||||
|
|
||||||
|
pos = os_strstr(cmd, " own=");
|
||||||
|
if (!pos)
|
||||||
|
return -1;
|
||||||
|
pos += 5;
|
||||||
|
bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
|
||||||
|
if (!bi) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: Identified bootstrap info not found");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = os_strstr(cmd, " iter=");
|
||||||
|
if (pos) {
|
||||||
|
iter = atoi(pos + 6);
|
||||||
|
if (iter <= 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = os_strstr(cmd, " listen=");
|
||||||
|
if (pos) {
|
||||||
|
listen_freq = atoi(pos + 8);
|
||||||
|
if (listen_freq <= 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
hostapd_dpp_chirp_stop(hapd);
|
||||||
|
hapd->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
|
||||||
|
hapd->dpp_qr_mutual = 0;
|
||||||
|
hapd->dpp_chirp_bi = bi;
|
||||||
|
hapd->dpp_presence_announcement = dpp_build_presence_announcement(bi);
|
||||||
|
if (!hapd->dpp_presence_announcement)
|
||||||
|
return -1;
|
||||||
|
hapd->dpp_chirp_iter = iter;
|
||||||
|
hapd->dpp_chirp_round = 0;
|
||||||
|
hapd->dpp_chirp_scan_done = 0;
|
||||||
|
hapd->dpp_chirp_listen = listen_freq;
|
||||||
|
|
||||||
|
return eloop_register_timeout(0, 0, hostapd_dpp_chirp_next, hapd, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void hostapd_dpp_chirp_stop(struct hostapd_data *hapd)
|
||||||
|
{
|
||||||
|
if (hapd->dpp_presence_announcement) {
|
||||||
|
hostapd_drv_send_action_cancel_wait(hapd);
|
||||||
|
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CHIRP_STOPPED);
|
||||||
|
}
|
||||||
|
hapd->dpp_chirp_bi = NULL;
|
||||||
|
wpabuf_free(hapd->dpp_presence_announcement);
|
||||||
|
hapd->dpp_presence_announcement = NULL;
|
||||||
|
if (hapd->dpp_chirp_listen)
|
||||||
|
hostapd_dpp_listen_stop(hapd);
|
||||||
|
hapd->dpp_chirp_listen = 0;
|
||||||
|
hapd->dpp_chirp_freq = 0;
|
||||||
|
os_free(hapd->dpp_chirp_freqs);
|
||||||
|
hapd->dpp_chirp_freqs = NULL;
|
||||||
|
eloop_cancel_timeout(hostapd_dpp_chirp_next, hapd, NULL);
|
||||||
|
eloop_cancel_timeout(hostapd_dpp_chirp_timeout, hapd, NULL);
|
||||||
|
if (hapd->iface->scan_cb == hostapd_dpp_chirp_scan_res_handler) {
|
||||||
|
/* TODO: abort ongoing scan */
|
||||||
|
hapd->iface->scan_cb = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int handle_dpp_remove_bi(struct hostapd_iface *iface, void *ctx)
|
||||||
|
{
|
||||||
|
struct dpp_bootstrap_info *bi = ctx;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < iface->num_bss; i++) {
|
||||||
|
struct hostapd_data *hapd = iface->bss[i];
|
||||||
|
|
||||||
|
if (bi == hapd->dpp_chirp_bi)
|
||||||
|
hostapd_dpp_chirp_stop(hapd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void hostapd_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi)
|
||||||
|
{
|
||||||
|
struct hapd_interfaces *interfaces = ctx;
|
||||||
|
|
||||||
|
hostapd_for_each_interface(interfaces, handle_dpp_remove_bi, bi);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
#ifndef DPP_HOSTAPD_H
|
#ifndef DPP_HOSTAPD_H
|
||||||
#define 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_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_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_req(struct hostapd_data *hapd, const char *cmd);
|
||||||
@ -39,4 +41,9 @@ void hostapd_dpp_deinit(struct hostapd_data *hapd);
|
|||||||
void hostapd_dpp_init_global(struct hapd_interfaces *ifaces);
|
void hostapd_dpp_init_global(struct hapd_interfaces *ifaces);
|
||||||
void hostapd_dpp_deinit_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 */
|
#endif /* DPP_HOSTAPD_H */
|
||||||
|
@ -106,18 +106,45 @@ void hostapd_notify_assoc_fils_finish(struct hostapd_data *hapd,
|
|||||||
#endif /* CONFIG_FILS */
|
#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,
|
int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
||||||
const u8 *req_ies, size_t req_ies_len, int reassoc)
|
const u8 *req_ies, size_t req_ies_len, int reassoc)
|
||||||
{
|
{
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
int new_assoc, res;
|
int new_assoc;
|
||||||
|
enum wpa_validate_result res;
|
||||||
struct ieee802_11_elems elems;
|
struct ieee802_11_elems elems;
|
||||||
const u8 *ie;
|
const u8 *ie;
|
||||||
size_t ielen;
|
size_t ielen;
|
||||||
u8 buf[sizeof(struct ieee80211_mgmt) + 1024];
|
u8 buf[sizeof(struct ieee80211_mgmt) + 1024];
|
||||||
u8 *p = buf;
|
u8 *p = buf;
|
||||||
u16 reason = WLAN_REASON_UNSPECIFIED;
|
u16 reason = WLAN_REASON_UNSPECIFIED;
|
||||||
u16 status = WLAN_STATUS_SUCCESS;
|
int status = WLAN_STATUS_SUCCESS;
|
||||||
const u8 *p2p_dev_addr = NULL;
|
const u8 *p2p_dev_addr = NULL;
|
||||||
|
|
||||||
if (addr == NULL) {
|
if (addr == NULL) {
|
||||||
@ -226,7 +253,6 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_P2P */
|
#endif /* CONFIG_P2P */
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211N
|
|
||||||
#ifdef NEED_AP_MLME
|
#ifdef NEED_AP_MLME
|
||||||
if (elems.ht_capabilities &&
|
if (elems.ht_capabilities &&
|
||||||
(hapd->iface->conf->ht_capab &
|
(hapd->iface->conf->ht_capab &
|
||||||
@ -240,7 +266,6 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
|||||||
ht40_intolerant_add(hapd->iface, sta);
|
ht40_intolerant_add(hapd->iface, sta);
|
||||||
}
|
}
|
||||||
#endif /* NEED_AP_MLME */
|
#endif /* NEED_AP_MLME */
|
||||||
#endif /* CONFIG_IEEE80211N */
|
|
||||||
|
|
||||||
#ifdef CONFIG_INTERWORKING
|
#ifdef CONFIG_INTERWORKING
|
||||||
if (elems.ext_capab && elems.ext_capab_len > 4) {
|
if (elems.ext_capab && elems.ext_capab_len > 4) {
|
||||||
@ -300,6 +325,17 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
|||||||
os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
|
os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
|
||||||
struct wpabuf *wps;
|
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;
|
sta->flags |= WLAN_STA_WPS;
|
||||||
wps = ieee802_11_vendor_ie_concat(ie, ielen,
|
wps = ieee802_11_vendor_ie_concat(ie, ielen,
|
||||||
WPS_IE_VENDOR_TYPE);
|
WPS_IE_VENDOR_TYPE);
|
||||||
@ -331,55 +367,71 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
|||||||
elems.rsnxe ? elems.rsnxe_len + 2 : 0,
|
elems.rsnxe ? elems.rsnxe_len + 2 : 0,
|
||||||
elems.mdie, elems.mdie_len,
|
elems.mdie, elems.mdie_len,
|
||||||
elems.owe_dh, elems.owe_dh_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_printf(MSG_DEBUG,
|
||||||
"WPA/RSN information element rejected? (res %u)",
|
"WPA/RSN information element rejected? (res %u)",
|
||||||
res);
|
res);
|
||||||
wpa_hexdump(MSG_DEBUG, "IE", ie, ielen);
|
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;
|
|
||||||
} 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;
|
|
||||||
} else if (res == WPA_INVALID_PMKID) {
|
|
||||||
reason = WLAN_REASON_INVALID_PMKID;
|
|
||||||
status = WLAN_STATUS_INVALID_PMKID;
|
|
||||||
} else {
|
|
||||||
reason = WLAN_REASON_INVALID_IE;
|
|
||||||
status = WLAN_STATUS_INVALID_IE;
|
|
||||||
}
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) ==
|
if (check_sa_query_need(hapd, sta)) {
|
||||||
(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);
|
|
||||||
|
|
||||||
status = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
|
status = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
|
||||||
|
|
||||||
p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
|
p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
|
||||||
@ -412,7 +464,7 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
|||||||
#ifdef CONFIG_SAE
|
#ifdef CONFIG_SAE
|
||||||
if (hapd->conf->sae_pwe == 2 &&
|
if (hapd->conf->sae_pwe == 2 &&
|
||||||
sta->auth_alg == WLAN_AUTH_SAE &&
|
sta->auth_alg == WLAN_AUTH_SAE &&
|
||||||
sta->sae && sta->sae->tmp && !sta->sae->tmp->h2e &&
|
sta->sae && !sta->sae->h2e &&
|
||||||
elems.rsnxe && elems.rsnxe_len >= 1 &&
|
elems.rsnxe && elems.rsnxe_len >= 1 &&
|
||||||
(elems.rsnxe[0] & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) {
|
(elems.rsnxe[0] & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) {
|
||||||
wpa_printf(MSG_INFO, "SAE: " MACSTR
|
wpa_printf(MSG_INFO, "SAE: " MACSTR
|
||||||
@ -475,6 +527,9 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
|||||||
return WLAN_STATUS_INVALID_IE;
|
return WLAN_STATUS_INVALID_IE;
|
||||||
#endif /* CONFIG_HS20 */
|
#endif /* CONFIG_HS20 */
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_WPS
|
||||||
|
skip_wpa_check:
|
||||||
|
#endif /* CONFIG_WPS */
|
||||||
|
|
||||||
#ifdef CONFIG_MBO
|
#ifdef CONFIG_MBO
|
||||||
if (hapd->conf->mbo_enabled && (hapd->conf->wpa & 2) &&
|
if (hapd->conf->mbo_enabled && (hapd->conf->wpa & 2) &&
|
||||||
@ -486,13 +541,10 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_MBO */
|
#endif /* CONFIG_MBO */
|
||||||
|
|
||||||
#ifdef CONFIG_WPS
|
|
||||||
skip_wpa_check:
|
|
||||||
#endif /* CONFIG_WPS */
|
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211R_AP
|
#ifdef CONFIG_IEEE80211R_AP
|
||||||
p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, buf, sizeof(buf),
|
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) {
|
if (!p) {
|
||||||
wpa_printf(MSG_DEBUG, "FT: Failed to write AssocResp IEs");
|
wpa_printf(MSG_DEBUG, "FT: Failed to write AssocResp IEs");
|
||||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||||
@ -579,17 +631,19 @@ skip_wpa_check:
|
|||||||
wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_OWE &&
|
wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_OWE &&
|
||||||
elems.owe_dh) {
|
elems.owe_dh) {
|
||||||
u8 *npos;
|
u8 *npos;
|
||||||
|
u16 ret_status;
|
||||||
|
|
||||||
npos = owe_assoc_req_process(hapd, sta,
|
npos = owe_assoc_req_process(hapd, sta,
|
||||||
elems.owe_dh, elems.owe_dh_len,
|
elems.owe_dh, elems.owe_dh_len,
|
||||||
p, sizeof(buf) - (p - buf),
|
p, sizeof(buf) - (p - buf),
|
||||||
&status);
|
&ret_status);
|
||||||
|
status = ret_status;
|
||||||
if (npos)
|
if (npos)
|
||||||
p = npos;
|
p = npos;
|
||||||
|
|
||||||
if (!npos &&
|
if (!npos &&
|
||||||
status == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
|
status == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
|
||||||
hostapd_sta_assoc(hapd, addr, reassoc, status, buf,
|
hostapd_sta_assoc(hapd, addr, reassoc, ret_status, buf,
|
||||||
p - buf);
|
p - buf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -631,6 +685,11 @@ skip_wpa_check:
|
|||||||
pfs_fail:
|
pfs_fail:
|
||||||
#endif /* CONFIG_DPP2 */
|
#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)
|
#if defined(CONFIG_IEEE80211R_AP) || defined(CONFIG_FILS) || defined(CONFIG_OWE)
|
||||||
hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
|
hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
|
||||||
|
|
||||||
@ -677,7 +736,8 @@ skip_wpa_check:
|
|||||||
|
|
||||||
fail:
|
fail:
|
||||||
#ifdef CONFIG_IEEE80211R_AP
|
#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 */
|
#endif /* CONFIG_IEEE80211R_AP */
|
||||||
hostapd_drv_sta_disassoc(hapd, sta->addr, reason);
|
hostapd_drv_sta_disassoc(hapd, sta->addr, reason);
|
||||||
ap_free_sta(hapd, sta);
|
ap_free_sta(hapd, sta);
|
||||||
@ -715,6 +775,7 @@ void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
|
|||||||
|
|
||||||
ap_sta_set_authorized(hapd, sta, 0);
|
ap_sta_set_authorized(hapd, sta, 0);
|
||||||
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
|
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
|
||||||
|
hostapd_set_sta_flags(hapd, sta);
|
||||||
wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
|
wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
|
||||||
sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
|
sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
|
||||||
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
|
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
|
||||||
@ -808,8 +869,6 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
|
|||||||
int offset, int width, int cf1, int cf2,
|
int offset, int width, int cf1, int cf2,
|
||||||
int finished)
|
int finished)
|
||||||
{
|
{
|
||||||
/* TODO: If OCV is enabled deauth STAs that don't perform a SA Query */
|
|
||||||
|
|
||||||
#ifdef NEED_AP_MLME
|
#ifdef NEED_AP_MLME
|
||||||
int channel, chwidth, is_dfs;
|
int channel, chwidth, is_dfs;
|
||||||
u8 seg0_idx = 0, seg1_idx = 0;
|
u8 seg0_idx = 0, seg1_idx = 0;
|
||||||
@ -859,9 +918,18 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
|
|||||||
|
|
||||||
switch (hapd->iface->current_mode->mode) {
|
switch (hapd->iface->current_mode->mode) {
|
||||||
case HOSTAPD_MODE_IEEE80211A:
|
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;
|
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;
|
seg1_idx = (cf2 - 5000) / 5;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -912,10 +980,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) {
|
} else if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) {
|
||||||
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED
|
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED
|
||||||
"freq=%d dfs=%d", freq, is_dfs);
|
"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++)
|
for (i = 0; i < hapd->iface->num_bss; i++)
|
||||||
hostapd_neighbor_set_own_report(hapd->iface->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 */
|
#endif /* NEED_AP_MLME */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1011,6 +1108,8 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hapd->iconf->edmg_channel = acs_res->edmg_channel;
|
||||||
|
|
||||||
if (hapd->iface->conf->ieee80211ac || hapd->iface->conf->ieee80211ax) {
|
if (hapd->iface->conf->ieee80211ac || hapd->iface->conf->ieee80211ax) {
|
||||||
/* set defaults for backwards compatibility */
|
/* set defaults for backwards compatibility */
|
||||||
hostapd_set_oper_centr_freq_seg1_idx(hapd->iconf, 0);
|
hostapd_set_oper_centr_freq_seg1_idx(hapd->iconf, 0);
|
||||||
@ -1433,15 +1532,33 @@ static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src,
|
|||||||
#endif /* HOSTAPD */
|
#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(
|
static struct hostapd_channel_data * hostapd_get_mode_channel(
|
||||||
struct hostapd_iface *iface, unsigned int freq)
|
struct hostapd_iface *iface, unsigned int freq)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct hostapd_channel_data *chan;
|
struct hostapd_channel_data *chan;
|
||||||
|
|
||||||
for (i = 0; i < iface->current_mode->num_channels; i++) {
|
for (i = 0; i < iface->num_hw_features; i++) {
|
||||||
chan = &iface->current_mode->channels[i];
|
if (hostapd_hw_skip_mode(iface, &iface->hw_features[i]))
|
||||||
if ((unsigned int) chan->freq == freq)
|
continue;
|
||||||
|
chan = hostapd_get_mode_chan(&iface->hw_features[i], freq);
|
||||||
|
if (chan)
|
||||||
return chan;
|
return chan;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1555,11 +1555,14 @@ void gas_serv_req_dpp_processing(struct hostapd_data *hapd,
|
|||||||
di->prot = prot;
|
di->prot = prot;
|
||||||
di->sd_resp = buf;
|
di->sd_resp = buf;
|
||||||
di->sd_resp_pos = 0;
|
di->sd_resp_pos = 0;
|
||||||
|
di->dpp = 1;
|
||||||
tx_buf = gas_build_initial_resp(
|
tx_buf = gas_build_initial_resp(
|
||||||
dialog_token, WLAN_STATUS_SUCCESS,
|
dialog_token, WLAN_STATUS_SUCCESS,
|
||||||
comeback_delay, 10);
|
comeback_delay, 10 + 2);
|
||||||
if (tx_buf)
|
if (tx_buf) {
|
||||||
gas_serv_write_dpp_adv_proto(tx_buf);
|
gas_serv_write_dpp_adv_proto(tx_buf);
|
||||||
|
wpabuf_put_le16(tx_buf, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
wpa_printf(MSG_DEBUG,
|
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,
|
tx_buf = gas_build_comeback_resp(dialog_token,
|
||||||
WLAN_STATUS_SUCCESS,
|
WLAN_STATUS_SUCCESS,
|
||||||
dialog->sd_frag_id, more, 0,
|
dialog->sd_frag_id, more, 0,
|
||||||
10 + frag_len);
|
10 + 2 + frag_len);
|
||||||
if (tx_buf) {
|
if (tx_buf) {
|
||||||
gas_serv_write_dpp_adv_proto(tx_buf);
|
gas_serv_write_dpp_adv_proto(tx_buf);
|
||||||
|
wpabuf_put_le16(tx_buf, frag_len);
|
||||||
wpabuf_put_buf(tx_buf, buf);
|
wpabuf_put_buf(tx_buf, buf);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
|
115
src/ap/hostapd.c
115
src/ap/hostapd.c
@ -58,8 +58,10 @@
|
|||||||
|
|
||||||
|
|
||||||
static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason);
|
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_setup_encryption(char *iface, struct hostapd_data *hapd);
|
||||||
static int hostapd_broadcast_wep_clear(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 int setup_interface2(struct hostapd_iface *iface);
|
||||||
static void channel_list_update_timeout(void *eloop_ctx, void *timeout_ctx);
|
static void channel_list_update_timeout(void *eloop_ctx, void *timeout_ctx);
|
||||||
static void hostapd_interface_setup_failure_handler(void *eloop_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;
|
int ret;
|
||||||
|
|
||||||
for (i = 0; i < interfaces->count; i++) {
|
for (i = 0; i < interfaces->count; i++) {
|
||||||
|
if (!interfaces->iface[i])
|
||||||
|
continue;
|
||||||
ret = cb(interfaces->iface[i], ctx);
|
ret = cb(interfaces->iface[i], ctx);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
@ -89,7 +93,9 @@ void hostapd_reconfig_encryption(struct hostapd_data *hapd)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
hostapd_set_privacy(hapd, 0);
|
hostapd_set_privacy(hapd, 0);
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
hostapd_setup_encryption(hapd->conf->iface, hapd);
|
hostapd_setup_encryption(hapd->conf->iface, hapd);
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -142,7 +148,9 @@ static void hostapd_reload_bss(struct hostapd_data *hapd)
|
|||||||
wpa_deinit(hapd->wpa_auth);
|
wpa_deinit(hapd->wpa_auth);
|
||||||
hapd->wpa_auth = NULL;
|
hapd->wpa_auth = NULL;
|
||||||
hostapd_set_privacy(hapd, 0);
|
hostapd_set_privacy(hapd, 0);
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
hostapd_setup_encryption(hapd->conf->iface, hapd);
|
hostapd_setup_encryption(hapd->conf->iface, hapd);
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
hostapd_set_generic_elem(hapd, (u8 *) "", 0);
|
hostapd_set_generic_elem(hapd, (u8 *) "", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +178,9 @@ static void hostapd_clear_old(struct hostapd_iface *iface)
|
|||||||
for (j = 0; j < iface->num_bss; j++) {
|
for (j = 0; j < iface->num_bss; j++) {
|
||||||
hostapd_flush_old_stations(iface->bss[j],
|
hostapd_flush_old_stations(iface->bss[j],
|
||||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
hostapd_broadcast_wep_clear(iface->bss[j]);
|
hostapd_broadcast_wep_clear(iface->bss[j]);
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
|
|
||||||
#ifndef CONFIG_NO_RADIUS
|
#ifndef CONFIG_NO_RADIUS
|
||||||
/* TODO: update dynamic data based on changed configuration
|
/* TODO: update dynamic data based on changed configuration
|
||||||
@ -284,6 +294,8 @@ int hostapd_reload_config(struct hostapd_iface *iface)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
|
|
||||||
static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd,
|
static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd,
|
||||||
const char *ifname)
|
const char *ifname)
|
||||||
{
|
{
|
||||||
@ -326,7 +338,7 @@ static int hostapd_broadcast_wep_set(struct hostapd_data *hapd)
|
|||||||
struct hostapd_ssid *ssid = &hapd->conf->ssid;
|
struct hostapd_ssid *ssid = &hapd->conf->ssid;
|
||||||
|
|
||||||
idx = ssid->wep.idx;
|
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,
|
hostapd_drv_set_key(hapd->conf->iface,
|
||||||
hapd, WPA_ALG_WEP, broadcast_ether_addr, idx, 0,
|
hapd, WPA_ALG_WEP, broadcast_ether_addr, idx, 0,
|
||||||
1, NULL, 0, ssid->wep.key[idx],
|
1, NULL, 0, ssid->wep.key[idx],
|
||||||
@ -339,8 +351,10 @@ static int hostapd_broadcast_wep_set(struct hostapd_data *hapd)
|
|||||||
return errors;
|
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);
|
os_free(hapd->probereq_cb);
|
||||||
hapd->probereq_cb = NULL;
|
hapd->probereq_cb = NULL;
|
||||||
@ -420,11 +434,17 @@ static void hostapd_free_hapd_data(struct hostapd_data *hapd)
|
|||||||
#ifdef CONFIG_MESH
|
#ifdef CONFIG_MESH
|
||||||
wpabuf_free(hapd->mesh_pending_auth);
|
wpabuf_free(hapd->mesh_pending_auth);
|
||||||
hapd->mesh_pending_auth = NULL;
|
hapd->mesh_pending_auth = NULL;
|
||||||
|
/* handling setup failure is already done */
|
||||||
|
hapd->setup_complete_cb = NULL;
|
||||||
#endif /* CONFIG_MESH */
|
#endif /* CONFIG_MESH */
|
||||||
|
|
||||||
hostapd_clean_rrm(hapd);
|
hostapd_clean_rrm(hapd);
|
||||||
fils_hlp_deinit(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
|
#ifdef CONFIG_SAE
|
||||||
{
|
{
|
||||||
struct hostapd_sae_commit_queue *q;
|
struct hostapd_sae_commit_queue *q;
|
||||||
@ -478,14 +498,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);
|
wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
|
||||||
#ifdef CONFIG_IEEE80211N
|
|
||||||
#ifdef NEED_AP_MLME
|
#ifdef NEED_AP_MLME
|
||||||
hostapd_stop_setup_timers(iface);
|
hostapd_stop_setup_timers(iface);
|
||||||
#endif /* NEED_AP_MLME */
|
#endif /* NEED_AP_MLME */
|
||||||
#endif /* CONFIG_IEEE80211N */
|
|
||||||
if (iface->current_mode)
|
if (iface->current_mode)
|
||||||
acs_cleanup(iface);
|
acs_cleanup(iface);
|
||||||
hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
|
hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
|
||||||
@ -526,6 +544,8 @@ static void hostapd_cleanup_iface(struct hostapd_iface *iface)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
|
|
||||||
static void hostapd_clear_wep(struct hostapd_data *hapd)
|
static void hostapd_clear_wep(struct hostapd_data *hapd)
|
||||||
{
|
{
|
||||||
if (hapd->drv_priv && !hapd->iface->driver_ap_teardown && hapd->conf) {
|
if (hapd->drv_priv && !hapd->iface->driver_ap_teardown && hapd->conf) {
|
||||||
@ -573,6 +593,8 @@ static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
|
|
||||||
|
|
||||||
static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason)
|
static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason)
|
||||||
{
|
{
|
||||||
@ -604,11 +626,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_free_stas(hapd);
|
||||||
hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING);
|
hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING);
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
hostapd_clear_wep(hapd);
|
hostapd_clear_wep(hapd);
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1159,13 +1183,15 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
|
|||||||
#endif /* CONFIG_MESH */
|
#endif /* CONFIG_MESH */
|
||||||
|
|
||||||
if (flush_old_stations)
|
if (flush_old_stations)
|
||||||
hostapd_flush_old_stations(hapd,
|
hostapd_flush(hapd);
|
||||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
|
||||||
hostapd_set_privacy(hapd, 0);
|
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))
|
if (hostapd_setup_encryption(conf->iface, hapd))
|
||||||
return -1;
|
return -1;
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fetch the SSID from the system and use it or,
|
* Fetch the SSID from the system and use it or,
|
||||||
@ -1351,6 +1377,21 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
|
|||||||
if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
|
if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
|
||||||
return -1;
|
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)
|
if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -1754,7 +1795,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,
|
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;
|
struct sta_info *s = (struct sta_info *) *get_ctx;
|
||||||
|
|
||||||
@ -1776,7 +1817,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,
|
static const u8 * fst_hostapd_get_peer_first(void *ctx,
|
||||||
struct fst_get_peer_ctx **get_ctx,
|
struct fst_get_peer_ctx **get_ctx,
|
||||||
Boolean mb_only)
|
bool mb_only)
|
||||||
{
|
{
|
||||||
struct hostapd_data *hapd = ctx;
|
struct hostapd_data *hapd = ctx;
|
||||||
|
|
||||||
@ -1788,7 +1829,7 @@ static const u8 * fst_hostapd_get_peer_first(void *ctx,
|
|||||||
|
|
||||||
static const u8 * fst_hostapd_get_peer_next(void *ctx,
|
static const u8 * fst_hostapd_get_peer_next(void *ctx,
|
||||||
struct fst_get_peer_ctx **get_ctx,
|
struct fst_get_peer_ctx **get_ctx,
|
||||||
Boolean mb_only)
|
bool mb_only)
|
||||||
{
|
{
|
||||||
return fst_hostapd_get_sta(get_ctx, mb_only);
|
return fst_hostapd_get_sta(get_ctx, mb_only);
|
||||||
}
|
}
|
||||||
@ -1876,6 +1917,13 @@ static int hostapd_owe_iface_iter2(struct hostapd_iface *iface, void *ctx)
|
|||||||
|
|
||||||
if (!bss->conf->owe_transition_ifname[0])
|
if (!bss->conf->owe_transition_ifname[0])
|
||||||
continue;
|
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);
|
res = hostapd_owe_trans_get_info(bss);
|
||||||
if (res == 0)
|
if (res == 0)
|
||||||
continue;
|
continue;
|
||||||
@ -2110,6 +2158,13 @@ dfs_offload:
|
|||||||
if (hapd->setup_complete_cb)
|
if (hapd->setup_complete_cb)
|
||||||
hapd->setup_complete_cb(hapd->setup_complete_cb_ctx);
|
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.",
|
wpa_printf(MSG_DEBUG, "%s: Setup of interface done.",
|
||||||
iface->bss[0]->conf->iface);
|
iface->bss[0]->conf->iface);
|
||||||
if (iface->interfaces && iface->interfaces->terminate_on_error > 0)
|
if (iface->interfaces && iface->interfaces->terminate_on_error > 0)
|
||||||
@ -2253,7 +2308,7 @@ int hostapd_setup_interface(struct hostapd_iface *iface)
|
|||||||
ret = setup_interface(iface);
|
ret = setup_interface(iface);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
wpa_printf(MSG_ERROR, "%s: Unable to setup interface.",
|
wpa_printf(MSG_ERROR, "%s: Unable to setup interface.",
|
||||||
iface->bss[0]->conf->iface);
|
iface->conf ? iface->conf->bss[0]->iface : "N/A");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2349,12 +2404,10 @@ void hostapd_interface_deinit(struct hostapd_iface *iface)
|
|||||||
hostapd_bss_deinit(iface->bss[j]);
|
hostapd_bss_deinit(iface->bss[j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211N
|
|
||||||
#ifdef NEED_AP_MLME
|
#ifdef NEED_AP_MLME
|
||||||
hostapd_stop_setup_timers(iface);
|
hostapd_stop_setup_timers(iface);
|
||||||
eloop_cancel_timeout(ap_ht2040_timeout, iface, NULL);
|
eloop_cancel_timeout(ap_ht2040_timeout, iface, NULL);
|
||||||
#endif /* NEED_AP_MLME */
|
#endif /* NEED_AP_MLME */
|
||||||
#endif /* CONFIG_IEEE80211N */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2637,6 +2690,12 @@ int hostapd_enable_iface(struct hostapd_iface *hapd_iface)
|
|||||||
{
|
{
|
||||||
size_t j;
|
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) {
|
if (hapd_iface->bss[0]->drv_priv != NULL) {
|
||||||
wpa_printf(MSG_ERROR, "Interface %s already enabled",
|
wpa_printf(MSG_ERROR, "Interface %s already enabled",
|
||||||
hapd_iface->conf->bss[0]->iface);
|
hapd_iface->conf->bss[0]->iface);
|
||||||
@ -2698,6 +2757,9 @@ int hostapd_disable_iface(struct hostapd_iface *hapd_iface)
|
|||||||
if (hapd_iface == NULL)
|
if (hapd_iface == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (hapd_iface->disable_iface_cb)
|
||||||
|
return hapd_iface->disable_iface_cb(hapd_iface);
|
||||||
|
|
||||||
if (hapd_iface->bss[0]->drv_priv == NULL) {
|
if (hapd_iface->bss[0]->drv_priv == NULL) {
|
||||||
wpa_printf(MSG_INFO, "Interface %s already disabled",
|
wpa_printf(MSG_INFO, "Interface %s already disabled",
|
||||||
hapd_iface->conf->bss[0]->iface);
|
hapd_iface->conf->bss[0]->iface);
|
||||||
@ -3118,6 +3180,7 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
|
|
||||||
hostapd_prune_associations(hapd, sta->addr);
|
hostapd_prune_associations(hapd, sta->addr);
|
||||||
ap_sta_clear_disconnect_timeouts(hapd, sta);
|
ap_sta_clear_disconnect_timeouts(hapd, sta);
|
||||||
|
sta->post_csa_sa_query = 0;
|
||||||
|
|
||||||
#ifdef CONFIG_P2P
|
#ifdef CONFIG_P2P
|
||||||
if (sta->p2p_ie == NULL && !sta->no_p2p_set) {
|
if (sta->p2p_ie == NULL && !sta->no_p2p_set) {
|
||||||
@ -3629,3 +3692,25 @@ void hostapd_periodic_iface(struct hostapd_iface *iface)
|
|||||||
#endif /* CONFIG_NO_RADIUS */
|
#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;
|
struct mesh_conf;
|
||||||
#endif /* CONFIG_MESH */
|
#endif /* CONFIG_MESH */
|
||||||
|
|
||||||
|
#ifdef CONFIG_CTRL_IFACE_UDP
|
||||||
|
#define CTRL_IFACE_COOKIE_LEN 8
|
||||||
|
#endif /* CONFIG_CTRL_IFACE_UDP */
|
||||||
|
|
||||||
struct hostapd_iface;
|
struct hostapd_iface;
|
||||||
|
|
||||||
struct hapd_interfaces {
|
struct hapd_interfaces {
|
||||||
@ -72,6 +76,11 @@ struct hapd_interfaces {
|
|||||||
#ifdef CONFIG_DPP
|
#ifdef CONFIG_DPP
|
||||||
struct dpp_global *dpp;
|
struct dpp_global *dpp;
|
||||||
#endif /* CONFIG_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 {
|
enum hostapd_chan_status {
|
||||||
@ -340,6 +349,11 @@ struct hostapd_data {
|
|||||||
int last_igtk_key_idx;
|
int last_igtk_key_idx;
|
||||||
u8 last_igtk[WPA_IGTK_MAX_LEN];
|
u8 last_igtk[WPA_IGTK_MAX_LEN];
|
||||||
size_t last_igtk_len;
|
size_t last_igtk_len;
|
||||||
|
|
||||||
|
enum wpa_alg last_bigtk_alg;
|
||||||
|
int last_bigtk_key_idx;
|
||||||
|
u8 last_bigtk[WPA_BIGTK_MAX_LEN];
|
||||||
|
size_t last_bigtk_len;
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
#ifdef CONFIG_MBO
|
#ifdef CONFIG_MBO
|
||||||
@ -377,6 +391,16 @@ struct hostapd_data {
|
|||||||
unsigned int dpp_resp_wait_time;
|
unsigned int dpp_resp_wait_time;
|
||||||
unsigned int dpp_resp_max_tries;
|
unsigned int dpp_resp_max_tries;
|
||||||
unsigned int dpp_resp_retry_time;
|
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
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
char *dpp_config_obj_override;
|
char *dpp_config_obj_override;
|
||||||
char *dpp_discovery_override;
|
char *dpp_discovery_override;
|
||||||
@ -395,6 +419,10 @@ struct hostapd_data {
|
|||||||
#ifdef CONFIG_SQLITE
|
#ifdef CONFIG_SQLITE
|
||||||
sqlite3 *rad_attr_db;
|
sqlite3 *rad_attr_db;
|
||||||
#endif /* CONFIG_SQLITE */
|
#endif /* CONFIG_SQLITE */
|
||||||
|
|
||||||
|
#ifdef CONFIG_CTRL_IFACE_UDP
|
||||||
|
unsigned char ctrl_iface_cookie[CTRL_IFACE_COOKIE_LEN];
|
||||||
|
#endif /* CONFIG_CTRL_IFACE_UDP */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -462,9 +490,7 @@ struct hostapd_iface {
|
|||||||
struct ap_info *ap_hash[STA_HASH_SIZE];
|
struct ap_info *ap_hash[STA_HASH_SIZE];
|
||||||
|
|
||||||
u64 drv_flags;
|
u64 drv_flags;
|
||||||
|
u64 drv_flags2;
|
||||||
/* SMPS modes supported by the driver (WPA_DRIVER_SMPS_MODE_*) */
|
|
||||||
unsigned int smps_modes;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A bitmap of supported protocols for probe response offload. See
|
* A bitmap of supported protocols for probe response offload. See
|
||||||
@ -563,6 +589,9 @@ struct hostapd_iface {
|
|||||||
|
|
||||||
/* Previous WMM element information */
|
/* Previous WMM element information */
|
||||||
struct hostapd_wmm_ac_params prev_wmm[WMM_AC_NUM];
|
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 */
|
/* hostapd.c */
|
||||||
@ -591,6 +620,9 @@ void hostapd_interface_deinit_free(struct hostapd_iface *iface);
|
|||||||
int hostapd_enable_iface(struct hostapd_iface *hapd_iface);
|
int hostapd_enable_iface(struct hostapd_iface *hapd_iface);
|
||||||
int hostapd_reload_iface(struct hostapd_iface *hapd_iface);
|
int hostapd_reload_iface(struct hostapd_iface *hapd_iface);
|
||||||
int hostapd_disable_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_add_iface(struct hapd_interfaces *ifaces, char *buf);
|
||||||
int hostapd_remove_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_channel_list_updated(struct hostapd_iface *iface, int initiator);
|
||||||
@ -606,6 +638,7 @@ hostapd_switch_channel_fallback(struct hostapd_iface *iface,
|
|||||||
void hostapd_cleanup_cs_params(struct hostapd_data *hapd);
|
void hostapd_cleanup_cs_params(struct hostapd_data *hapd);
|
||||||
void hostapd_periodic_iface(struct hostapd_iface *iface);
|
void hostapd_periodic_iface(struct hostapd_iface *iface);
|
||||||
int hostapd_owe_trans_get_info(struct hostapd_data *hapd);
|
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 */
|
/* utils.c */
|
||||||
int hostapd_register_probereq_cb(struct hostapd_data *hapd,
|
int hostapd_register_probereq_cb(struct hostapd_data *hapd,
|
||||||
|
@ -224,7 +224,6 @@ int hostapd_prepare_rates(struct hostapd_iface *iface,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211N
|
|
||||||
static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface)
|
static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface)
|
||||||
{
|
{
|
||||||
int pri_freq, sec_freq;
|
int pri_freq, sec_freq;
|
||||||
@ -561,26 +560,6 @@ static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface)
|
|||||||
return 0;
|
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) &&
|
if ((conf & HT_CAP_INFO_GREEN_FIELD) &&
|
||||||
!(hw & HT_CAP_INFO_GREEN_FIELD)) {
|
!(hw & HT_CAP_INFO_GREEN_FIELD)) {
|
||||||
wpa_printf(MSG_ERROR, "Driver does not support configured "
|
wpa_printf(MSG_ERROR, "Driver does not support configured "
|
||||||
@ -687,12 +666,9 @@ static int ieee80211ax_supported_he_capab(struct hostapd_iface *iface)
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211AX */
|
#endif /* CONFIG_IEEE80211AX */
|
||||||
|
|
||||||
#endif /* CONFIG_IEEE80211N */
|
|
||||||
|
|
||||||
|
|
||||||
int hostapd_check_ht_capab(struct hostapd_iface *iface)
|
int hostapd_check_ht_capab(struct hostapd_iface *iface)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_IEEE80211N
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (is_6ghz_freq(iface->freq))
|
if (is_6ghz_freq(iface->freq))
|
||||||
@ -725,7 +701,6 @@ int hostapd_check_ht_capab(struct hostapd_iface *iface)
|
|||||||
return ret;
|
return ret;
|
||||||
if (!ieee80211n_allowed_ht40_channel_pair(iface))
|
if (!ieee80211n_allowed_ht40_channel_pair(iface))
|
||||||
return -1;
|
return -1;
|
||||||
#endif /* CONFIG_IEEE80211N */
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -810,7 +785,7 @@ static int hostapd_is_usable_edmg(struct hostapd_iface *iface)
|
|||||||
|
|
||||||
/* 60 GHz channels 1..6 */
|
/* 60 GHz channels 1..6 */
|
||||||
for (i = 0; i < 6; i++) {
|
for (i = 0; i < 6; i++) {
|
||||||
int freq = 56160 + 2160 * i;
|
int freq = 56160 + 2160 * (i + 1);
|
||||||
|
|
||||||
if (edmg.channels & BIT(i)) {
|
if (edmg.channels & BIT(i)) {
|
||||||
contiguous++;
|
contiguous++;
|
||||||
@ -904,10 +879,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
|
static enum hostapd_chan_status
|
||||||
hostapd_check_chans(struct hostapd_iface *iface)
|
hostapd_check_chans(struct hostapd_iface *iface)
|
||||||
{
|
{
|
||||||
if (iface->freq) {
|
if (iface->freq) {
|
||||||
|
hostapd_determine_mode(iface);
|
||||||
if (hostapd_is_usable_chans(iface))
|
if (hostapd_is_usable_chans(iface))
|
||||||
return HOSTAPD_CHAN_VALID;
|
return HOSTAPD_CHAN_VALID;
|
||||||
else
|
else
|
||||||
@ -1033,9 +1041,15 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (iface->current_mode == NULL) {
|
if (iface->current_mode == NULL) {
|
||||||
if (!(iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) ||
|
if ((iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) &&
|
||||||
!(iface->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY))
|
(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,
|
wpa_printf(MSG_ERROR,
|
||||||
"Hardware does not support configured mode");
|
"Hardware does not support configured mode");
|
||||||
hostapd_logger(iface->bss[0], NULL,
|
hostapd_logger(iface->bss[0], NULL,
|
||||||
@ -1110,3 +1124,20 @@ int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq)
|
|||||||
}
|
}
|
||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
@ -25,6 +25,8 @@ int hostapd_check_edmg_capab(struct hostapd_iface *iface);
|
|||||||
int hostapd_prepare_rates(struct hostapd_iface *iface,
|
int hostapd_prepare_rates(struct hostapd_iface *iface,
|
||||||
struct hostapd_hw_modes *mode);
|
struct hostapd_hw_modes *mode);
|
||||||
void hostapd_stop_setup_timers(struct hostapd_iface *iface);
|
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 */
|
#else /* NEED_AP_MLME */
|
||||||
static inline void
|
static inline void
|
||||||
hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
|
hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
|
||||||
@ -77,6 +79,12 @@ 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;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* NEED_AP_MLME */
|
#endif /* NEED_AP_MLME */
|
||||||
|
|
||||||
#endif /* HW_FEATURES_H */
|
#endif /* HW_FEATURES_H */
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "common/dpp.h"
|
#include "common/dpp.h"
|
||||||
#include "common/ocv.h"
|
#include "common/ocv.h"
|
||||||
#include "common/wpa_common.h"
|
#include "common/wpa_common.h"
|
||||||
|
#include "common/wpa_ctrl.h"
|
||||||
#include "radius/radius.h"
|
#include "radius/radius.h"
|
||||||
#include "radius/radius_client.h"
|
#include "radius/radius_client.h"
|
||||||
#include "p2p/p2p.h"
|
#include "p2p/p2p.h"
|
||||||
@ -224,7 +225,7 @@ u8 * hostapd_eid_rm_enabled_capab(struct hostapd_data *hapd, u8 *eid,
|
|||||||
u16 hostapd_own_capab_info(struct hostapd_data *hapd)
|
u16 hostapd_own_capab_info(struct hostapd_data *hapd)
|
||||||
{
|
{
|
||||||
int capab = WLAN_CAPABILITY_ESS;
|
int capab = WLAN_CAPABILITY_ESS;
|
||||||
int privacy;
|
int privacy = 0;
|
||||||
int dfs;
|
int dfs;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -240,12 +241,14 @@ u16 hostapd_own_capab_info(struct hostapd_data *hapd)
|
|||||||
hapd->iconf->preamble == SHORT_PREAMBLE)
|
hapd->iconf->preamble == SHORT_PREAMBLE)
|
||||||
capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
|
capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
|
||||||
|
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
privacy = hapd->conf->ssid.wep.keys_set;
|
privacy = hapd->conf->ssid.wep.keys_set;
|
||||||
|
|
||||||
if (hapd->conf->ieee802_1x &&
|
if (hapd->conf->ieee802_1x &&
|
||||||
(hapd->conf->default_wep_key_len ||
|
(hapd->conf->default_wep_key_len ||
|
||||||
hapd->conf->individual_wep_key_len))
|
hapd->conf->individual_wep_key_len))
|
||||||
privacy = 1;
|
privacy = 1;
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
|
|
||||||
if (hapd->conf->wpa)
|
if (hapd->conf->wpa)
|
||||||
privacy = 1;
|
privacy = 1;
|
||||||
@ -285,6 +288,7 @@ u16 hostapd_own_capab_info(struct hostapd_data *hapd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
#ifndef CONFIG_NO_RC4
|
#ifndef CONFIG_NO_RC4
|
||||||
static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta,
|
static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
u16 auth_transaction, const u8 *challenge,
|
u16 auth_transaction, const u8 *challenge,
|
||||||
@ -341,6 +345,7 @@ static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_NO_RC4 */
|
#endif /* CONFIG_NO_RC4 */
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
|
|
||||||
|
|
||||||
static int send_auth_reply(struct hostapd_data *hapd, struct sta_info *sta,
|
static int send_auth_reply(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
@ -380,9 +385,10 @@ static int send_auth_reply(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
#ifdef CONFIG_SAE
|
#ifdef CONFIG_SAE
|
||||||
if (hapd->conf->sae_confirm_immediate == 2 &&
|
if (hapd->conf->sae_confirm_immediate == 2 &&
|
||||||
auth_alg == WLAN_AUTH_SAE) {
|
auth_alg == WLAN_AUTH_SAE) {
|
||||||
if (auth_transaction == 1 &&
|
if (auth_transaction == 1 && sta &&
|
||||||
(resp == WLAN_STATUS_SUCCESS ||
|
(resp == WLAN_STATUS_SUCCESS ||
|
||||||
resp == WLAN_STATUS_SAE_HASH_TO_ELEMENT)) {
|
resp == WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
|
||||||
|
resp == WLAN_STATUS_SAE_PK)) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"TESTING: Postpone SAE Commit transmission until Confirm is ready");
|
"TESTING: Postpone SAE Commit transmission until Confirm is ready");
|
||||||
os_free(sta->sae_postponed_commit);
|
os_free(sta->sae_postponed_commit);
|
||||||
@ -474,17 +480,23 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
|
|||||||
const char *rx_id = NULL;
|
const char *rx_id = NULL;
|
||||||
int use_pt = 0;
|
int use_pt = 0;
|
||||||
struct sae_pt *pt = NULL;
|
struct sae_pt *pt = NULL;
|
||||||
|
const struct sae_pk *pk = NULL;
|
||||||
|
|
||||||
if (sta->sae->tmp) {
|
if (sta->sae->tmp) {
|
||||||
rx_id = sta->sae->tmp->pw_id;
|
rx_id = sta->sae->tmp->pw_id;
|
||||||
use_pt = sta->sae->tmp->h2e;
|
use_pt = sta->sae->h2e;
|
||||||
|
#ifdef CONFIG_SAE_PK
|
||||||
|
os_memcpy(sta->sae->tmp->own_addr, hapd->own_addr, ETH_ALEN);
|
||||||
|
os_memcpy(sta->sae->tmp->peer_addr, sta->addr, ETH_ALEN);
|
||||||
|
#endif /* CONFIG_SAE_PK */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rx_id && hapd->conf->sae_pwe != 3)
|
if (rx_id && hapd->conf->sae_pwe != 3)
|
||||||
use_pt = 1;
|
use_pt = 1;
|
||||||
else if (status_code == WLAN_STATUS_SUCCESS)
|
else if (status_code == WLAN_STATUS_SUCCESS)
|
||||||
use_pt = 0;
|
use_pt = 0;
|
||||||
else if (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT)
|
else if (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
|
||||||
|
status_code == WLAN_STATUS_SAE_PK)
|
||||||
use_pt = 1;
|
use_pt = 1;
|
||||||
|
|
||||||
for (pw = hapd->conf->sae_passwords; pw; pw = pw->next) {
|
for (pw = hapd->conf->sae_passwords; pw; pw = pw->next) {
|
||||||
@ -498,6 +510,8 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
|
|||||||
continue;
|
continue;
|
||||||
password = pw->password;
|
password = pw->password;
|
||||||
pt = pw->pt;
|
pt = pw->pt;
|
||||||
|
if (!(hapd->conf->mesh & MESH_ENABLED))
|
||||||
|
pk = pw->pk;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!password) {
|
if (!password) {
|
||||||
@ -511,7 +525,7 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
|
|||||||
|
|
||||||
if (update && use_pt &&
|
if (update && use_pt &&
|
||||||
sae_prepare_commit_pt(sta->sae, pt, hapd->own_addr, sta->addr,
|
sae_prepare_commit_pt(sta->sae, pt, hapd->own_addr, sta->addr,
|
||||||
NULL) < 0)
|
NULL, pk) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (update && !use_pt &&
|
if (update && !use_pt &&
|
||||||
@ -533,10 +547,13 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
|
|||||||
|
|
||||||
buf = wpabuf_alloc(SAE_COMMIT_MAX_LEN +
|
buf = wpabuf_alloc(SAE_COMMIT_MAX_LEN +
|
||||||
(rx_id ? 3 + os_strlen(rx_id) : 0));
|
(rx_id ? 3 + os_strlen(rx_id) : 0));
|
||||||
if (buf == NULL)
|
if (buf &&
|
||||||
return NULL;
|
sae_write_commit(sta->sae, buf, sta->sae->tmp ?
|
||||||
sae_write_commit(sta->sae, buf, sta->sae->tmp ?
|
sta->sae->tmp->anti_clogging_token : NULL,
|
||||||
sta->sae->tmp->anti_clogging_token : NULL, rx_id);
|
rx_id) < 0) {
|
||||||
|
wpabuf_free(buf);
|
||||||
|
buf = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
@ -551,7 +568,17 @@ static struct wpabuf * auth_build_sae_confirm(struct hostapd_data *hapd,
|
|||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
sae_write_confirm(sta->sae, buf);
|
#ifdef CONFIG_SAE_PK
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
if (sta->sae->tmp)
|
||||||
|
sta->sae->tmp->omit_pk_elem = hapd->conf->sae_pk_omit;
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
#endif /* CONFIG_SAE_PK */
|
||||||
|
|
||||||
|
if (sae_write_confirm(sta->sae, buf) < 0) {
|
||||||
|
wpabuf_free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
@ -571,8 +598,21 @@ static int auth_sae_send_commit(struct hostapd_data *hapd,
|
|||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||||
|
|
||||||
status = (sta->sae->tmp && sta->sae->tmp->h2e) ?
|
if (sta->sae->tmp && sta->sae->pk)
|
||||||
WLAN_STATUS_SAE_HASH_TO_ELEMENT : WLAN_STATUS_SUCCESS;
|
status = WLAN_STATUS_SAE_PK;
|
||||||
|
else if (sta->sae->tmp && sta->sae->h2e)
|
||||||
|
status = WLAN_STATUS_SAE_HASH_TO_ELEMENT;
|
||||||
|
else
|
||||||
|
status = WLAN_STATUS_SUCCESS;
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
if (hapd->conf->sae_commit_status >= 0 &&
|
||||||
|
hapd->conf->sae_commit_status != status) {
|
||||||
|
wpa_printf(MSG_INFO,
|
||||||
|
"TESTING: Override SAE commit status code %u --> %d",
|
||||||
|
status, hapd->conf->sae_commit_status);
|
||||||
|
status = hapd->conf->sae_commit_status;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
reply_res = send_auth_reply(hapd, sta, sta->addr, bssid,
|
reply_res = send_auth_reply(hapd, sta, sta->addr, bssid,
|
||||||
WLAN_AUTH_SAE, 1,
|
WLAN_AUTH_SAE, 1,
|
||||||
status, wpabuf_head(data),
|
status, wpabuf_head(data),
|
||||||
@ -636,13 +676,15 @@ static int use_sae_anti_clogging(struct hostapd_data *hapd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static u8 sae_token_hash(struct hostapd_data *hapd, const u8 *addr)
|
static int sae_token_hash(struct hostapd_data *hapd, const u8 *addr, u8 *idx)
|
||||||
{
|
{
|
||||||
u8 hash[SHA256_MAC_LEN];
|
u8 hash[SHA256_MAC_LEN];
|
||||||
|
|
||||||
hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key),
|
if (hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key),
|
||||||
addr, ETH_ALEN, hash);
|
addr, ETH_ALEN, hash) < 0)
|
||||||
return hash[0];
|
return -1;
|
||||||
|
*idx = hash[0];
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -655,9 +697,8 @@ static int check_sae_token(struct hostapd_data *hapd, const u8 *addr,
|
|||||||
u16 token_idx;
|
u16 token_idx;
|
||||||
u8 idx;
|
u8 idx;
|
||||||
|
|
||||||
if (token_len != SHA256_MAC_LEN)
|
if (token_len != SHA256_MAC_LEN || sae_token_hash(hapd, addr, &idx) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
idx = sae_token_hash(hapd, addr);
|
|
||||||
token_idx = hapd->sae_pending_token_idx[idx];
|
token_idx = hapd->sae_pending_token_idx[idx];
|
||||||
if (token_idx == 0 || token_idx != WPA_GET_BE16(token)) {
|
if (token_idx == 0 || token_idx != WPA_GET_BE16(token)) {
|
||||||
wpa_printf(MSG_DEBUG, "SAE: Invalid anti-clogging token from "
|
wpa_printf(MSG_DEBUG, "SAE: Invalid anti-clogging token from "
|
||||||
@ -721,7 +762,10 @@ static struct wpabuf * auth_build_token_req(struct hostapd_data *hapd,
|
|||||||
wpabuf_put_u8(buf, WLAN_EID_EXT_ANTI_CLOGGING_TOKEN);
|
wpabuf_put_u8(buf, WLAN_EID_EXT_ANTI_CLOGGING_TOKEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
p_idx = sae_token_hash(hapd, addr);
|
if (sae_token_hash(hapd, addr, &p_idx) < 0) {
|
||||||
|
wpabuf_free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
token_idx = hapd->sae_pending_token_idx[p_idx];
|
token_idx = hapd->sae_pending_token_idx[p_idx];
|
||||||
if (!token_idx) {
|
if (!token_idx) {
|
||||||
hapd->sae_token_idx++;
|
hapd->sae_token_idx++;
|
||||||
@ -889,9 +933,14 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
switch (sta->sae->state) {
|
switch (sta->sae->state) {
|
||||||
case SAE_NOTHING:
|
case SAE_NOTHING:
|
||||||
if (auth_transaction == 1) {
|
if (auth_transaction == 1) {
|
||||||
if (sta->sae->tmp)
|
if (sta->sae->tmp) {
|
||||||
sta->sae->tmp->h2e = status_code ==
|
sta->sae->h2e =
|
||||||
WLAN_STATUS_SAE_HASH_TO_ELEMENT;
|
(status_code ==
|
||||||
|
WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
|
||||||
|
status_code == WLAN_STATUS_SAE_PK);
|
||||||
|
sta->sae->pk =
|
||||||
|
status_code == WLAN_STATUS_SAE_PK;
|
||||||
|
}
|
||||||
ret = auth_sae_send_commit(hapd, sta, bssid,
|
ret = auth_sae_send_commit(hapd, sta, bssid,
|
||||||
!allow_reuse, status_code);
|
!allow_reuse, status_code);
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -1101,20 +1150,28 @@ static int sae_status_success(struct hostapd_data *hapd, u16 status_code)
|
|||||||
{
|
{
|
||||||
int sae_pwe = hapd->conf->sae_pwe;
|
int sae_pwe = hapd->conf->sae_pwe;
|
||||||
int id_in_use;
|
int id_in_use;
|
||||||
|
bool sae_pk = false;
|
||||||
|
|
||||||
id_in_use = hostapd_sae_pw_id_in_use(hapd->conf);
|
id_in_use = hostapd_sae_pw_id_in_use(hapd->conf);
|
||||||
if (id_in_use == 2 && sae_pwe != 3)
|
if (id_in_use == 2 && sae_pwe != 3)
|
||||||
sae_pwe = 1;
|
sae_pwe = 1;
|
||||||
else if (id_in_use == 1 && sae_pwe == 0)
|
else if (id_in_use == 1 && sae_pwe == 0)
|
||||||
sae_pwe = 2;
|
sae_pwe = 2;
|
||||||
|
#ifdef CONFIG_SAE_PK
|
||||||
|
sae_pk = hostapd_sae_pk_in_use(hapd->conf);
|
||||||
|
if (sae_pwe == 0 && sae_pk)
|
||||||
|
sae_pwe = 2;
|
||||||
|
#endif /* CONFIG_SAE_PK */
|
||||||
|
|
||||||
return ((sae_pwe == 0 || sae_pwe == 3) &&
|
return ((sae_pwe == 0 || sae_pwe == 3) &&
|
||||||
status_code == WLAN_STATUS_SUCCESS) ||
|
status_code == WLAN_STATUS_SUCCESS) ||
|
||||||
(sae_pwe == 1 &&
|
(sae_pwe == 1 &&
|
||||||
status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT) ||
|
(status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
|
||||||
|
(sae_pk && status_code == WLAN_STATUS_SAE_PK))) ||
|
||||||
(sae_pwe == 2 &&
|
(sae_pwe == 2 &&
|
||||||
(status_code == WLAN_STATUS_SUCCESS ||
|
(status_code == WLAN_STATUS_SUCCESS ||
|
||||||
status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT));
|
status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
|
||||||
|
(sae_pk && status_code == WLAN_STATUS_SAE_PK)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1137,11 +1194,15 @@ static int sae_is_group_enabled(struct hostapd_data *hapd, int group)
|
|||||||
|
|
||||||
|
|
||||||
static int check_sae_rejected_groups(struct hostapd_data *hapd,
|
static int check_sae_rejected_groups(struct hostapd_data *hapd,
|
||||||
const struct wpabuf *groups)
|
struct sae_data *sae)
|
||||||
{
|
{
|
||||||
|
const struct wpabuf *groups;
|
||||||
size_t i, count;
|
size_t i, count;
|
||||||
const u8 *pos;
|
const u8 *pos;
|
||||||
|
|
||||||
|
if (!sae->tmp)
|
||||||
|
return 0;
|
||||||
|
groups = sae->tmp->peer_rejected_groups;
|
||||||
if (!groups)
|
if (!groups)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -1183,6 +1244,7 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
wpa_printf(MSG_DEBUG, "SAE: TESTING - reflection attack");
|
wpa_printf(MSG_DEBUG, "SAE: TESTING - reflection attack");
|
||||||
pos = mgmt->u.auth.variable;
|
pos = mgmt->u.auth.variable;
|
||||||
end = ((const u8 *) mgmt) + len;
|
end = ((const u8 *) mgmt) + len;
|
||||||
|
resp = status_code;
|
||||||
send_auth_reply(hapd, sta, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
|
send_auth_reply(hapd, sta, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
|
||||||
auth_transaction, resp, pos, end - pos,
|
auth_transaction, resp, pos, end - pos,
|
||||||
"auth-sae-reflection-attack");
|
"auth-sae-reflection-attack");
|
||||||
@ -1328,7 +1390,8 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
((const u8 *) mgmt) + len -
|
((const u8 *) mgmt) + len -
|
||||||
mgmt->u.auth.variable, &token,
|
mgmt->u.auth.variable, &token,
|
||||||
&token_len, groups, status_code ==
|
&token_len, groups, status_code ==
|
||||||
WLAN_STATUS_SAE_HASH_TO_ELEMENT);
|
WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
|
||||||
|
status_code == WLAN_STATUS_SAE_PK);
|
||||||
if (resp == SAE_SILENTLY_DISCARD) {
|
if (resp == SAE_SILENTLY_DISCARD) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"SAE: Drop commit message from " MACSTR " due to reflection attack",
|
"SAE: Drop commit message from " MACSTR " due to reflection attack",
|
||||||
@ -1358,9 +1421,7 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
if (resp != WLAN_STATUS_SUCCESS)
|
if (resp != WLAN_STATUS_SUCCESS)
|
||||||
goto reply;
|
goto reply;
|
||||||
|
|
||||||
if (sta->sae->tmp &&
|
if (check_sae_rejected_groups(hapd, sta->sae)) {
|
||||||
check_sae_rejected_groups(
|
|
||||||
hapd, sta->sae->tmp->peer_rejected_groups)) {
|
|
||||||
resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||||
goto reply;
|
goto reply;
|
||||||
}
|
}
|
||||||
@ -1372,8 +1433,9 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
"SAE: Request anti-clogging token from "
|
"SAE: Request anti-clogging token from "
|
||||||
MACSTR, MAC2STR(sta->addr));
|
MACSTR, MAC2STR(sta->addr));
|
||||||
if (sta->sae->tmp)
|
if (sta->sae->tmp)
|
||||||
h2e = sta->sae->tmp->h2e;
|
h2e = sta->sae->h2e;
|
||||||
if (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT)
|
if (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
|
||||||
|
status_code == WLAN_STATUS_SAE_PK)
|
||||||
h2e = 1;
|
h2e = 1;
|
||||||
data = auth_build_token_req(hapd, sta->sae->group,
|
data = auth_build_token_req(hapd, sta->sae->group,
|
||||||
sta->addr, h2e);
|
sta->addr, h2e);
|
||||||
@ -1601,27 +1663,37 @@ static int auth_sae_queued_addr(struct hostapd_data *hapd, const u8 *addr)
|
|||||||
#endif /* CONFIG_SAE */
|
#endif /* CONFIG_SAE */
|
||||||
|
|
||||||
|
|
||||||
static u16 wpa_res_to_status_code(int res)
|
static u16 wpa_res_to_status_code(enum wpa_validate_result res)
|
||||||
{
|
{
|
||||||
if (res == WPA_INVALID_GROUP)
|
switch (res) {
|
||||||
return WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
|
case WPA_IE_OK:
|
||||||
if (res == WPA_INVALID_PAIRWISE)
|
return WLAN_STATUS_SUCCESS;
|
||||||
return WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
|
case WPA_INVALID_IE:
|
||||||
if (res == WPA_INVALID_AKMP)
|
|
||||||
return WLAN_STATUS_AKMP_NOT_VALID;
|
|
||||||
if (res == WPA_ALLOC_FAIL)
|
|
||||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
|
||||||
if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION)
|
|
||||||
return WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
|
|
||||||
if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
|
|
||||||
return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
|
|
||||||
if (res == WPA_INVALID_MDIE)
|
|
||||||
return WLAN_STATUS_INVALID_MDIE;
|
|
||||||
if (res == WPA_INVALID_PMKID)
|
|
||||||
return WLAN_STATUS_INVALID_PMKID;
|
|
||||||
if (res != WPA_IE_OK)
|
|
||||||
return WLAN_STATUS_INVALID_IE;
|
return WLAN_STATUS_INVALID_IE;
|
||||||
return WLAN_STATUS_SUCCESS;
|
case WPA_INVALID_GROUP:
|
||||||
|
return WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
|
||||||
|
case WPA_INVALID_PAIRWISE:
|
||||||
|
return WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
|
||||||
|
case WPA_INVALID_AKMP:
|
||||||
|
return WLAN_STATUS_AKMP_NOT_VALID;
|
||||||
|
case WPA_NOT_ENABLED:
|
||||||
|
return WLAN_STATUS_INVALID_IE;
|
||||||
|
case WPA_ALLOC_FAIL:
|
||||||
|
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||||
|
case WPA_MGMT_FRAME_PROTECTION_VIOLATION:
|
||||||
|
return WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
|
||||||
|
case WPA_INVALID_MGMT_GROUP_CIPHER:
|
||||||
|
return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
|
||||||
|
case WPA_INVALID_MDIE:
|
||||||
|
return WLAN_STATUS_INVALID_MDIE;
|
||||||
|
case WPA_INVALID_PROTO:
|
||||||
|
return WLAN_STATUS_INVALID_IE;
|
||||||
|
case WPA_INVALID_PMKID:
|
||||||
|
return WLAN_STATUS_INVALID_PMKID;
|
||||||
|
case WPA_DENIED_OTHER_REASON:
|
||||||
|
return WLAN_STATUS_ASSOC_DENIED_UNSPEC;
|
||||||
|
}
|
||||||
|
return WLAN_STATUS_INVALID_IE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1641,7 +1713,7 @@ void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
u16 resp = WLAN_STATUS_SUCCESS;
|
u16 resp = WLAN_STATUS_SUCCESS;
|
||||||
const u8 *end;
|
const u8 *end;
|
||||||
struct ieee802_11_elems elems;
|
struct ieee802_11_elems elems;
|
||||||
int res;
|
enum wpa_validate_result res;
|
||||||
struct wpa_ie_data rsn;
|
struct wpa_ie_data rsn;
|
||||||
struct rsn_pmksa_cache_entry *pmksa = NULL;
|
struct rsn_pmksa_cache_entry *pmksa = NULL;
|
||||||
|
|
||||||
@ -1817,11 +1889,11 @@ void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
FILS_SESSION_LEN);
|
FILS_SESSION_LEN);
|
||||||
os_memcpy(sta->fils_session, elems.fils_session, FILS_SESSION_LEN);
|
os_memcpy(sta->fils_session, elems.fils_session, FILS_SESSION_LEN);
|
||||||
|
|
||||||
/* FILS Wrapped Data */
|
/* Wrapped Data */
|
||||||
if (elems.fils_wrapped_data) {
|
if (elems.wrapped_data) {
|
||||||
wpa_hexdump(MSG_DEBUG, "FILS: Wrapped Data",
|
wpa_hexdump(MSG_DEBUG, "FILS: Wrapped Data",
|
||||||
elems.fils_wrapped_data,
|
elems.wrapped_data,
|
||||||
elems.fils_wrapped_data_len);
|
elems.wrapped_data_len);
|
||||||
if (!pmksa) {
|
if (!pmksa) {
|
||||||
#ifndef CONFIG_NO_RADIUS
|
#ifndef CONFIG_NO_RADIUS
|
||||||
if (!sta->eapol_sm) {
|
if (!sta->eapol_sm) {
|
||||||
@ -1831,8 +1903,8 @@ void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"FILS: Forward EAP-Initiate/Re-auth to authentication server");
|
"FILS: Forward EAP-Initiate/Re-auth to authentication server");
|
||||||
ieee802_1x_encapsulate_radius(
|
ieee802_1x_encapsulate_radius(
|
||||||
hapd, sta, elems.fils_wrapped_data,
|
hapd, sta, elems.wrapped_data,
|
||||||
elems.fils_wrapped_data_len);
|
elems.wrapped_data_len);
|
||||||
sta->fils_pending_cb = cb;
|
sta->fils_pending_cb = cb;
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"FILS: Will send Authentication frame once the response from authentication server is available");
|
"FILS: Will send Authentication frame once the response from authentication server is available");
|
||||||
@ -1841,8 +1913,8 @@ void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
* to maintain a copy of the EAP-Initiate/Reauth
|
* to maintain a copy of the EAP-Initiate/Reauth
|
||||||
* message. */
|
* message. */
|
||||||
if (fils_pmkid_erp(wpa_auth_sta_key_mgmt(sta->wpa_sm),
|
if (fils_pmkid_erp(wpa_auth_sta_key_mgmt(sta->wpa_sm),
|
||||||
elems.fils_wrapped_data,
|
elems.wrapped_data,
|
||||||
elems.fils_wrapped_data_len,
|
elems.wrapped_data_len,
|
||||||
sta->fils_erp_pmkid) == 0)
|
sta->fils_erp_pmkid) == 0)
|
||||||
sta->fils_erp_pmkid_set = 1;
|
sta->fils_erp_pmkid_set = 1;
|
||||||
return;
|
return;
|
||||||
@ -1985,12 +2057,12 @@ prepare_auth_resp_fils(struct hostapd_data *hapd,
|
|||||||
wpabuf_put_u8(data, WLAN_EID_EXT_FILS_SESSION);
|
wpabuf_put_u8(data, WLAN_EID_EXT_FILS_SESSION);
|
||||||
wpabuf_put_data(data, sta->fils_session, FILS_SESSION_LEN);
|
wpabuf_put_data(data, sta->fils_session, FILS_SESSION_LEN);
|
||||||
|
|
||||||
/* FILS Wrapped Data */
|
/* Wrapped Data */
|
||||||
if (!pmksa && erp_resp) {
|
if (!pmksa && erp_resp) {
|
||||||
wpabuf_put_u8(data, WLAN_EID_EXTENSION); /* Element ID */
|
wpabuf_put_u8(data, WLAN_EID_EXTENSION); /* Element ID */
|
||||||
wpabuf_put_u8(data, 1 + wpabuf_len(erp_resp)); /* Length */
|
wpabuf_put_u8(data, 1 + wpabuf_len(erp_resp)); /* Length */
|
||||||
/* Element ID Extension */
|
/* Element ID Extension */
|
||||||
wpabuf_put_u8(data, WLAN_EID_EXT_FILS_WRAPPED_DATA);
|
wpabuf_put_u8(data, WLAN_EID_EXT_WRAPPED_DATA);
|
||||||
wpabuf_put_buf(data, erp_resp);
|
wpabuf_put_buf(data, erp_resp);
|
||||||
|
|
||||||
if (fils_rmsk_to_pmk(wpa_auth_sta_key_mgmt(sta->wpa_sm),
|
if (fils_rmsk_to_pmk(wpa_auth_sta_key_mgmt(sta->wpa_sm),
|
||||||
@ -2506,32 +2578,10 @@ static void handle_auth(struct hostapd_data *hapd,
|
|||||||
(!(sta->flags & WLAN_STA_MFP) || !ap_sta_is_authorized(sta)) &&
|
(!(sta->flags & WLAN_STA_MFP) || !ap_sta_is_authorized(sta)) &&
|
||||||
!(hapd->conf->mesh & MESH_ENABLED) &&
|
!(hapd->conf->mesh & MESH_ENABLED) &&
|
||||||
!(sta->added_unassoc)) {
|
!(sta->added_unassoc)) {
|
||||||
/*
|
if (ap_sta_re_add(hapd, sta) < 0) {
|
||||||
* 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,
|
|
||||||
sta->flags, 0, 0, 0, 0)) {
|
|
||||||
hostapd_logger(hapd, sta->addr,
|
|
||||||
HOSTAPD_MODULE_IEEE80211,
|
|
||||||
HOSTAPD_LEVEL_NOTICE,
|
|
||||||
"Could not add STA to kernel driver");
|
|
||||||
resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
|
resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
sta->added_unassoc = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (auth_alg) {
|
switch (auth_alg) {
|
||||||
@ -2544,6 +2594,7 @@ static void handle_auth(struct hostapd_data *hapd,
|
|||||||
sta->auth_alg = WLAN_AUTH_OPEN;
|
sta->auth_alg = WLAN_AUTH_OPEN;
|
||||||
mlme_authenticate_indication(hapd, sta);
|
mlme_authenticate_indication(hapd, sta);
|
||||||
break;
|
break;
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
#ifndef CONFIG_NO_RC4
|
#ifndef CONFIG_NO_RC4
|
||||||
case WLAN_AUTH_SHARED_KEY:
|
case WLAN_AUTH_SHARED_KEY:
|
||||||
resp = auth_shared_key(hapd, sta, auth_transaction, challenge,
|
resp = auth_shared_key(hapd, sta, auth_transaction, challenge,
|
||||||
@ -2562,6 +2613,7 @@ static void handle_auth(struct hostapd_data *hapd,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif /* CONFIG_NO_RC4 */
|
#endif /* CONFIG_NO_RC4 */
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
#ifdef CONFIG_IEEE80211R_AP
|
#ifdef CONFIG_IEEE80211R_AP
|
||||||
case WLAN_AUTH_FT:
|
case WLAN_AUTH_FT:
|
||||||
sta->auth_alg = WLAN_AUTH_FT;
|
sta->auth_alg = WLAN_AUTH_FT;
|
||||||
@ -3032,7 +3084,7 @@ u16 owe_process_rsn_ie(struct hostapd_data *hapd,
|
|||||||
u16 status;
|
u16 status;
|
||||||
u8 *owe_buf, ie[256 * 2];
|
u8 *owe_buf, ie[256 * 2];
|
||||||
size_t ie_len = 0;
|
size_t ie_len = 0;
|
||||||
int res;
|
enum wpa_validate_result res;
|
||||||
|
|
||||||
if (!rsn_ie || rsn_ie_len < 2) {
|
if (!rsn_ie || rsn_ie_len < 2) {
|
||||||
wpa_printf(MSG_DEBUG, "OWE: No RSNE in (Re)AssocReq");
|
wpa_printf(MSG_DEBUG, "OWE: No RSNE in (Re)AssocReq");
|
||||||
@ -3104,11 +3156,39 @@ end:
|
|||||||
#endif /* CONFIG_OWE */
|
#endif /* CONFIG_OWE */
|
||||||
|
|
||||||
|
|
||||||
static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
|
static bool check_sa_query(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
|
int reassoc)
|
||||||
|
{
|
||||||
|
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 &&
|
||||||
|
(!reassoc || 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
const u8 *ies, size_t ies_len, int reassoc)
|
const u8 *ies, size_t ies_len, int reassoc)
|
||||||
{
|
{
|
||||||
struct ieee802_11_elems elems;
|
struct ieee802_11_elems elems;
|
||||||
u16 resp;
|
int resp;
|
||||||
const u8 *wpa_ie;
|
const u8 *wpa_ie;
|
||||||
size_t wpa_ie_len;
|
size_t wpa_ie_len;
|
||||||
const u8 *p2p_dev_addr = NULL;
|
const u8 *p2p_dev_addr = NULL;
|
||||||
@ -3137,7 +3217,6 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
if (resp != WLAN_STATUS_SUCCESS)
|
if (resp != WLAN_STATUS_SUCCESS)
|
||||||
return resp;
|
return resp;
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211N
|
|
||||||
resp = copy_sta_ht_capab(hapd, sta, elems.ht_capabilities);
|
resp = copy_sta_ht_capab(hapd, sta, elems.ht_capabilities);
|
||||||
if (resp != WLAN_STATUS_SUCCESS)
|
if (resp != WLAN_STATUS_SUCCESS)
|
||||||
return resp;
|
return resp;
|
||||||
@ -3148,7 +3227,6 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
"mandatory HT PHY - reject association");
|
"mandatory HT PHY - reject association");
|
||||||
return WLAN_STATUS_ASSOC_DENIED_NO_HT;
|
return WLAN_STATUS_ASSOC_DENIED_NO_HT;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211N */
|
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211AC
|
#ifdef CONFIG_IEEE80211AC
|
||||||
if (hapd->iconf->ieee80211ac) {
|
if (hapd->iconf->ieee80211ac) {
|
||||||
@ -3177,12 +3255,25 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211AC */
|
#endif /* CONFIG_IEEE80211AC */
|
||||||
#ifdef CONFIG_IEEE80211AX
|
#ifdef CONFIG_IEEE80211AX
|
||||||
if (hapd->iconf->ieee80211ax) {
|
if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) {
|
||||||
resp = copy_sta_he_capab(hapd, sta, IEEE80211_MODE_AP,
|
resp = copy_sta_he_capab(hapd, sta, IEEE80211_MODE_AP,
|
||||||
elems.he_capabilities,
|
elems.he_capabilities,
|
||||||
elems.he_capabilities_len);
|
elems.he_capabilities_len);
|
||||||
if (resp != WLAN_STATUS_SUCCESS)
|
if (resp != WLAN_STATUS_SUCCESS)
|
||||||
return resp;
|
return resp;
|
||||||
|
if (is_6ghz_op_class(hapd->iconf->op_class)) {
|
||||||
|
if (!(sta->flags & WLAN_STA_HE)) {
|
||||||
|
hostapd_logger(hapd, sta->addr,
|
||||||
|
HOSTAPD_MODULE_IEEE80211,
|
||||||
|
HOSTAPD_LEVEL_INFO,
|
||||||
|
"Station does not support mandatory HE PHY - reject association");
|
||||||
|
return WLAN_STATUS_DENIED_HE_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
resp = copy_sta_he_6ghz_capab(hapd, sta,
|
||||||
|
elems.he_6ghz_band_cap);
|
||||||
|
if (resp != WLAN_STATUS_SUCCESS)
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211AX */
|
#endif /* CONFIG_IEEE80211AX */
|
||||||
|
|
||||||
@ -3216,6 +3307,8 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
if (hapd->conf->wps_state && elems.wps_ie) {
|
if (hapd->conf->wps_state && elems.wps_ie) {
|
||||||
wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)Association "
|
wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)Association "
|
||||||
"Request - assume WPS is used");
|
"Request - assume WPS is used");
|
||||||
|
if (check_sa_query(hapd, sta, reassoc))
|
||||||
|
return WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
|
||||||
sta->flags |= WLAN_STA_WPS;
|
sta->flags |= WLAN_STA_WPS;
|
||||||
wpabuf_free(sta->wps_ie);
|
wpabuf_free(sta->wps_ie);
|
||||||
sta->wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
|
sta->wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
|
||||||
@ -3245,7 +3338,8 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (hapd->conf->wpa && wpa_ie) {
|
if (hapd->conf->wpa && wpa_ie) {
|
||||||
int res;
|
enum wpa_validate_result res;
|
||||||
|
|
||||||
wpa_ie -= 2;
|
wpa_ie -= 2;
|
||||||
wpa_ie_len += 2;
|
wpa_ie_len += 2;
|
||||||
if (sta->wpa_sm == NULL)
|
if (sta->wpa_sm == NULL)
|
||||||
@ -3268,27 +3362,9 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
resp = wpa_res_to_status_code(res);
|
resp = wpa_res_to_status_code(res);
|
||||||
if (resp != WLAN_STATUS_SUCCESS)
|
if (resp != WLAN_STATUS_SUCCESS)
|
||||||
return resp;
|
return resp;
|
||||||
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 &&
|
|
||||||
(!reassoc || 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(hapd, sta, reassoc))
|
||||||
return WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
|
return WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
|
||||||
}
|
|
||||||
|
|
||||||
if (wpa_auth_uses_mfp(sta->wpa_sm))
|
if (wpa_auth_uses_mfp(sta->wpa_sm))
|
||||||
sta->flags |= WLAN_STA_MFP;
|
sta->flags |= WLAN_STA_MFP;
|
||||||
@ -3341,7 +3417,7 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
|
|
||||||
if (hapd->conf->sae_pwe == 2 &&
|
if (hapd->conf->sae_pwe == 2 &&
|
||||||
sta->auth_alg == WLAN_AUTH_SAE &&
|
sta->auth_alg == WLAN_AUTH_SAE &&
|
||||||
sta->sae && sta->sae->tmp && !sta->sae->tmp->h2e &&
|
sta->sae && !sta->sae->h2e &&
|
||||||
elems.rsnxe && elems.rsnxe_len >= 1 &&
|
elems.rsnxe && elems.rsnxe_len >= 1 &&
|
||||||
(elems.rsnxe[0] & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) {
|
(elems.rsnxe[0] & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) {
|
||||||
wpa_printf(MSG_INFO, "SAE: " MACSTR
|
wpa_printf(MSG_INFO, "SAE: " MACSTR
|
||||||
@ -3366,7 +3442,8 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
dpp_pfs_free(sta->dpp_pfs);
|
dpp_pfs_free(sta->dpp_pfs);
|
||||||
sta->dpp_pfs = NULL;
|
sta->dpp_pfs = NULL;
|
||||||
|
|
||||||
if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) &&
|
if (DPP_VERSION > 1 &&
|
||||||
|
(hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) &&
|
||||||
hapd->conf->dpp_netaccesskey && sta->wpa_sm &&
|
hapd->conf->dpp_netaccesskey && sta->wpa_sm &&
|
||||||
wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_DPP &&
|
wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_DPP &&
|
||||||
elems.owe_dh) {
|
elems.owe_dh) {
|
||||||
@ -3393,7 +3470,6 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
pfs_fail:
|
pfs_fail:
|
||||||
#endif /* CONFIG_DPP2 */
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211N
|
|
||||||
if ((sta->flags & (WLAN_STA_HT | WLAN_STA_VHT)) &&
|
if ((sta->flags & (WLAN_STA_HT | WLAN_STA_VHT)) &&
|
||||||
wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) {
|
wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) {
|
||||||
hostapd_logger(hapd, sta->addr,
|
hostapd_logger(hapd, sta->addr,
|
||||||
@ -3403,7 +3479,6 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
"association");
|
"association");
|
||||||
return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
|
return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211N */
|
|
||||||
#ifdef CONFIG_HS20
|
#ifdef CONFIG_HS20
|
||||||
} else if (hapd->conf->osen) {
|
} else if (hapd->conf->osen) {
|
||||||
if (elems.osen == NULL) {
|
if (elems.osen == NULL) {
|
||||||
@ -3490,6 +3565,7 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
struct wpa_channel_info ci;
|
struct wpa_channel_info ci;
|
||||||
int tx_chanwidth;
|
int tx_chanwidth;
|
||||||
int tx_seg1_idx;
|
int tx_seg1_idx;
|
||||||
|
enum oci_verify_result res;
|
||||||
|
|
||||||
if (hostapd_drv_channel_info(hapd, &ci) != 0) {
|
if (hostapd_drv_channel_info(hapd, &ci) != 0) {
|
||||||
wpa_printf(MSG_WARNING,
|
wpa_printf(MSG_WARNING,
|
||||||
@ -3503,9 +3579,20 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
&tx_seg1_idx) < 0)
|
&tx_seg1_idx) < 0)
|
||||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||||
|
|
||||||
if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
|
res = ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
|
||||||
tx_chanwidth, tx_seg1_idx) != 0) {
|
tx_chanwidth, tx_seg1_idx);
|
||||||
wpa_printf(MSG_WARNING, "FILS: %s", ocv_errorstr);
|
if (wpa_auth_uses_ocv(sta->wpa_sm) == 2 &&
|
||||||
|
res == OCI_NOT_FOUND) {
|
||||||
|
/* Work around misbehaving STAs */
|
||||||
|
wpa_printf(MSG_INFO,
|
||||||
|
"FILS: Disable OCV with a STA that does not send OCI");
|
||||||
|
wpa_auth_set_ocv(sta->wpa_sm, 0);
|
||||||
|
} else if (res != OCI_SUCCESS) {
|
||||||
|
wpa_printf(MSG_WARNING, "FILS: OCV failed: %s",
|
||||||
|
ocv_errorstr);
|
||||||
|
wpa_msg(hapd->msg_ctx, MSG_INFO, OCV_FAILURE "addr="
|
||||||
|
MACSTR " frame=fils-reassoc-req error=%s",
|
||||||
|
MAC2STR(sta->addr), ocv_errorstr);
|
||||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3604,10 +3691,8 @@ static int add_associated_sta(struct hostapd_data *hapd,
|
|||||||
sta->ft_over_ds = 0;
|
sta->ft_over_ds = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211N
|
|
||||||
if (sta->flags & WLAN_STA_HT)
|
if (sta->flags & WLAN_STA_HT)
|
||||||
hostapd_get_ht_capab(hapd, sta->ht_capabilities, &ht_cap);
|
hostapd_get_ht_capab(hapd, sta->ht_capabilities, &ht_cap);
|
||||||
#endif /* CONFIG_IEEE80211N */
|
|
||||||
#ifdef CONFIG_IEEE80211AC
|
#ifdef CONFIG_IEEE80211AC
|
||||||
if (sta->flags & WLAN_STA_VHT)
|
if (sta->flags & WLAN_STA_VHT)
|
||||||
hostapd_get_vht_capab(hapd, sta->vht_capabilities, &vht_cap);
|
hostapd_get_vht_capab(hapd, sta->vht_capabilities, &vht_cap);
|
||||||
@ -3631,6 +3716,7 @@ static int add_associated_sta(struct hostapd_data *hapd,
|
|||||||
sta->flags & WLAN_STA_VHT ? &vht_cap : NULL,
|
sta->flags & WLAN_STA_VHT ? &vht_cap : NULL,
|
||||||
sta->flags & WLAN_STA_HE ? &he_cap : NULL,
|
sta->flags & WLAN_STA_HE ? &he_cap : NULL,
|
||||||
sta->flags & WLAN_STA_HE ? sta->he_capab_len : 0,
|
sta->flags & WLAN_STA_HE ? sta->he_capab_len : 0,
|
||||||
|
sta->he_6ghz_capab,
|
||||||
sta->flags | WLAN_STA_ASSOC, sta->qosinfo,
|
sta->flags | WLAN_STA_ASSOC, sta->qosinfo,
|
||||||
sta->vht_opmode, sta->p2p_ie ? 1 : 0,
|
sta->vht_opmode, sta->p2p_ie ? 1 : 0,
|
||||||
set)) {
|
set)) {
|
||||||
@ -3655,7 +3741,8 @@ static int add_associated_sta(struct hostapd_data *hapd,
|
|||||||
|
|
||||||
static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
|
static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
const u8 *addr, u16 status_code, int reassoc,
|
const u8 *addr, u16 status_code, int reassoc,
|
||||||
const u8 *ies, size_t ies_len, int rssi)
|
const u8 *ies, size_t ies_len, int rssi,
|
||||||
|
int omit_rsnxe)
|
||||||
{
|
{
|
||||||
int send_len;
|
int send_len;
|
||||||
u8 *buf;
|
u8 *buf;
|
||||||
@ -3725,7 +3812,8 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
* Transition Information, RSN, [RIC Response] */
|
* Transition Information, RSN, [RIC Response] */
|
||||||
p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p,
|
p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p,
|
||||||
buf + buflen - p,
|
buf + buflen - p,
|
||||||
sta->auth_alg, ies, ies_len);
|
sta->auth_alg, ies, ies_len,
|
||||||
|
omit_rsnxe);
|
||||||
if (!p) {
|
if (!p) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"FT: Failed to write AssocResp IEs");
|
"FT: Failed to write AssocResp IEs");
|
||||||
@ -3755,10 +3843,8 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
if (sta && status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY)
|
if (sta && status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY)
|
||||||
p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
|
p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211N
|
|
||||||
p = hostapd_eid_ht_capabilities(hapd, p);
|
p = hostapd_eid_ht_capabilities(hapd, p);
|
||||||
p = hostapd_eid_ht_operation(hapd, p);
|
p = hostapd_eid_ht_operation(hapd, p);
|
||||||
#endif /* CONFIG_IEEE80211N */
|
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211AC
|
#ifdef CONFIG_IEEE80211AC
|
||||||
if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac &&
|
if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac &&
|
||||||
@ -3785,11 +3871,12 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
#endif /* CONFIG_IEEE80211AC */
|
#endif /* CONFIG_IEEE80211AC */
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211AX
|
#ifdef CONFIG_IEEE80211AX
|
||||||
if (hapd->iconf->ieee80211ax) {
|
if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) {
|
||||||
p = hostapd_eid_he_capab(hapd, p, IEEE80211_MODE_AP);
|
p = hostapd_eid_he_capab(hapd, p, IEEE80211_MODE_AP);
|
||||||
p = hostapd_eid_he_operation(hapd, p);
|
p = hostapd_eid_he_operation(hapd, p);
|
||||||
p = hostapd_eid_spatial_reuse(hapd, p);
|
p = hostapd_eid_spatial_reuse(hapd, p);
|
||||||
p = hostapd_eid_he_mu_edca_parameter_set(hapd, p);
|
p = hostapd_eid_he_mu_edca_parameter_set(hapd, p);
|
||||||
|
p = hostapd_eid_he_6ghz_band_cap(hapd, p);
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211AX */
|
#endif /* CONFIG_IEEE80211AX */
|
||||||
|
|
||||||
@ -3806,12 +3893,29 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_FST */
|
#endif /* CONFIG_FST */
|
||||||
|
|
||||||
p = hostapd_eid_rsnxe(hapd, p, buf + buflen - p);
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
if (hapd->conf->rsnxe_override_ft &&
|
||||||
|
buf + buflen - p >=
|
||||||
|
(long int) wpabuf_len(hapd->conf->rsnxe_override_ft) &&
|
||||||
|
sta && sta->auth_alg == WLAN_AUTH_FT) {
|
||||||
|
wpa_printf(MSG_DEBUG, "TESTING: RSNXE FT override");
|
||||||
|
os_memcpy(p, wpabuf_head(hapd->conf->rsnxe_override_ft),
|
||||||
|
wpabuf_len(hapd->conf->rsnxe_override_ft));
|
||||||
|
p += wpabuf_len(hapd->conf->rsnxe_override_ft);
|
||||||
|
goto rsnxe_done;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
if (!omit_rsnxe)
|
||||||
|
p = hostapd_eid_rsnxe(hapd, p, buf + buflen - p);
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
rsnxe_done:
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
#ifdef CONFIG_OWE
|
#ifdef CONFIG_OWE
|
||||||
if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) &&
|
if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) &&
|
||||||
sta && sta->owe_ecdh && status_code == WLAN_STATUS_SUCCESS &&
|
sta && sta->owe_ecdh && status_code == WLAN_STATUS_SUCCESS &&
|
||||||
wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_OWE) {
|
wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_OWE &&
|
||||||
|
!wpa_auth_sta_get_pmksa(sta->wpa_sm)) {
|
||||||
struct wpabuf *pub;
|
struct wpabuf *pub;
|
||||||
|
|
||||||
pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0);
|
pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0);
|
||||||
@ -3832,7 +3936,7 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
#endif /* CONFIG_OWE */
|
#endif /* CONFIG_OWE */
|
||||||
|
|
||||||
#ifdef CONFIG_DPP2
|
#ifdef CONFIG_DPP2
|
||||||
if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) &&
|
if (DPP_VERSION > 1 && (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) &&
|
||||||
sta && sta->dpp_pfs && status_code == WLAN_STATUS_SUCCESS &&
|
sta && sta->dpp_pfs && status_code == WLAN_STATUS_SUCCESS &&
|
||||||
wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_DPP) {
|
wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_DPP) {
|
||||||
os_memcpy(p, wpabuf_head(sta->dpp_pfs->ie),
|
os_memcpy(p, wpabuf_head(sta->dpp_pfs->ie),
|
||||||
@ -4024,7 +4128,7 @@ void fils_hlp_finish_assoc(struct hostapd_data *hapd, struct sta_info *sta)
|
|||||||
reply_res = send_assoc_resp(hapd, sta, sta->addr, WLAN_STATUS_SUCCESS,
|
reply_res = send_assoc_resp(hapd, sta, sta->addr, WLAN_STATUS_SUCCESS,
|
||||||
sta->fils_pending_assoc_is_reassoc,
|
sta->fils_pending_assoc_is_reassoc,
|
||||||
sta->fils_pending_assoc_req,
|
sta->fils_pending_assoc_req,
|
||||||
sta->fils_pending_assoc_req_len, 0);
|
sta->fils_pending_assoc_req_len, 0, 0);
|
||||||
os_free(sta->fils_pending_assoc_req);
|
os_free(sta->fils_pending_assoc_req);
|
||||||
sta->fils_pending_assoc_req = NULL;
|
sta->fils_pending_assoc_req = NULL;
|
||||||
sta->fils_pending_assoc_req_len = 0;
|
sta->fils_pending_assoc_req_len = 0;
|
||||||
@ -4064,7 +4168,8 @@ static void handle_assoc(struct hostapd_data *hapd,
|
|||||||
int reassoc, int rssi)
|
int reassoc, int rssi)
|
||||||
{
|
{
|
||||||
u16 capab_info, listen_interval, seq_ctrl, fc;
|
u16 capab_info, listen_interval, seq_ctrl, fc;
|
||||||
u16 resp = WLAN_STATUS_SUCCESS, reply_res;
|
int resp = WLAN_STATUS_SUCCESS;
|
||||||
|
u16 reply_res = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||||
const u8 *pos;
|
const u8 *pos;
|
||||||
int left, i;
|
int left, i;
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
@ -4072,6 +4177,7 @@ static void handle_assoc(struct hostapd_data *hapd,
|
|||||||
#ifdef CONFIG_FILS
|
#ifdef CONFIG_FILS
|
||||||
int delay_assoc = 0;
|
int delay_assoc = 0;
|
||||||
#endif /* CONFIG_FILS */
|
#endif /* CONFIG_FILS */
|
||||||
|
int omit_rsnxe = 0;
|
||||||
|
|
||||||
if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) :
|
if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) :
|
||||||
sizeof(mgmt->u.assoc_req))) {
|
sizeof(mgmt->u.assoc_req))) {
|
||||||
@ -4284,6 +4390,7 @@ static void handle_assoc(struct hostapd_data *hapd,
|
|||||||
resp = check_assoc_ies(hapd, sta, pos, left, reassoc);
|
resp = check_assoc_ies(hapd, sta, pos, left, reassoc);
|
||||||
if (resp != WLAN_STATUS_SUCCESS)
|
if (resp != WLAN_STATUS_SUCCESS)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
omit_rsnxe = !get_ie(pos, left, WLAN_EID_RSNX);
|
||||||
|
|
||||||
if (hostapd_get_aid(hapd, sta) < 0) {
|
if (hostapd_get_aid(hapd, sta) < 0) {
|
||||||
hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
|
hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
|
||||||
@ -4336,9 +4443,7 @@ static void handle_assoc(struct hostapd_data *hapd,
|
|||||||
ieee802_11_set_beacons(hapd->iface);
|
ieee802_11_set_beacons(hapd->iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211N
|
|
||||||
update_ht_state(hapd, sta);
|
update_ht_state(hapd, sta);
|
||||||
#endif /* CONFIG_IEEE80211N */
|
|
||||||
|
|
||||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||||
HOSTAPD_LEVEL_DEBUG,
|
HOSTAPD_LEVEL_DEBUG,
|
||||||
@ -4443,12 +4548,13 @@ static void handle_assoc(struct hostapd_data *hapd,
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_FILS */
|
#endif /* CONFIG_FILS */
|
||||||
|
|
||||||
reply_res = send_assoc_resp(hapd, sta, mgmt->sa, resp, reassoc, pos,
|
if (resp >= 0)
|
||||||
left, rssi);
|
reply_res = send_assoc_resp(hapd, sta, mgmt->sa, resp, reassoc,
|
||||||
|
pos, left, rssi, omit_rsnxe);
|
||||||
os_free(tmp);
|
os_free(tmp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove the station in case tranmission of a success response fails
|
* Remove the station in case transmission of a success response fails
|
||||||
* (the STA was added associated to the driver) or if the station was
|
* (the STA was added associated to the driver) or if the station was
|
||||||
* previously added unassociated.
|
* previously added unassociated.
|
||||||
*/
|
*/
|
||||||
@ -4485,6 +4591,7 @@ static void handle_disassoc(struct hostapd_data *hapd,
|
|||||||
ap_sta_set_authorized(hapd, sta, 0);
|
ap_sta_set_authorized(hapd, sta, 0);
|
||||||
sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
|
sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
|
||||||
sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
|
sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
|
||||||
|
hostapd_set_sta_flags(hapd, sta);
|
||||||
wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
|
wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
|
||||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||||
HOSTAPD_LEVEL_INFO, "disassociated");
|
HOSTAPD_LEVEL_INFO, "disassociated");
|
||||||
@ -4551,6 +4658,7 @@ static void handle_deauth(struct hostapd_data *hapd,
|
|||||||
sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
|
sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
|
||||||
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC |
|
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC |
|
||||||
WLAN_STA_ASSOC_REQ_OK);
|
WLAN_STA_ASSOC_REQ_OK);
|
||||||
|
hostapd_set_sta_flags(hapd, sta);
|
||||||
wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
|
wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
|
||||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||||
HOSTAPD_LEVEL_DEBUG, "deauthenticated");
|
HOSTAPD_LEVEL_DEBUG, "deauthenticated");
|
||||||
@ -4682,14 +4790,12 @@ static int handle_action(struct hostapd_data *hapd,
|
|||||||
#endif /* CONFIG_FST */
|
#endif /* CONFIG_FST */
|
||||||
case WLAN_ACTION_PUBLIC:
|
case WLAN_ACTION_PUBLIC:
|
||||||
case WLAN_ACTION_PROTECTED_DUAL:
|
case WLAN_ACTION_PROTECTED_DUAL:
|
||||||
#ifdef CONFIG_IEEE80211N
|
|
||||||
if (len >= IEEE80211_HDRLEN + 2 &&
|
if (len >= IEEE80211_HDRLEN + 2 &&
|
||||||
mgmt->u.action.u.public_action.action ==
|
mgmt->u.action.u.public_action.action ==
|
||||||
WLAN_PA_20_40_BSS_COEX) {
|
WLAN_PA_20_40_BSS_COEX) {
|
||||||
hostapd_2040_coex_action(hapd, mgmt, len);
|
hostapd_2040_coex_action(hapd, mgmt, len);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211N */
|
|
||||||
#ifdef CONFIG_DPP
|
#ifdef CONFIG_DPP
|
||||||
if (len >= IEEE80211_HDRLEN + 6 &&
|
if (len >= IEEE80211_HDRLEN + 6 &&
|
||||||
mgmt->u.action.u.vs_public_action.action ==
|
mgmt->u.action.u.vs_public_action.action ==
|
||||||
@ -4849,6 +4955,11 @@ int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hapd->iface->state != HAPD_IFACE_ENABLED) {
|
||||||
|
wpa_printf(MSG_DEBUG, "MGMT: Ignore management frame while interface is not enabled (SA=" MACSTR " DA=" MACSTR " subtype=%u)",
|
||||||
|
MAC2STR(mgmt->sa), MAC2STR(mgmt->da), stype);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (stype == WLAN_FC_STYPE_PROBE_REQ) {
|
if (stype == WLAN_FC_STYPE_PROBE_REQ) {
|
||||||
handle_probe_req(hapd, mgmt, len, ssi_signal);
|
handle_probe_req(hapd, mgmt, len, ssi_signal);
|
||||||
@ -4967,6 +5078,7 @@ static void hostapd_set_wds_encryption(struct hostapd_data *hapd,
|
|||||||
struct sta_info *sta,
|
struct sta_info *sta,
|
||||||
char *ifname_wds)
|
char *ifname_wds)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
int i;
|
int i;
|
||||||
struct hostapd_ssid *ssid = &hapd->conf->ssid;
|
struct hostapd_ssid *ssid = &hapd->conf->ssid;
|
||||||
|
|
||||||
@ -4987,6 +5099,7 @@ static void hostapd_set_wds_encryption(struct hostapd_data *hapd,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -5487,4 +5600,57 @@ void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 &&
|
||||||
|
!hapd->cs_freq_params.he_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;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_NATIVE_WINDOWS */
|
#endif /* CONFIG_NATIVE_WINDOWS */
|
||||||
|
@ -53,7 +53,6 @@ u8 * hostapd_eid_rm_enabled_capab(struct hostapd_data *hapd, u8 *eid,
|
|||||||
size_t len);
|
size_t len);
|
||||||
u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid);
|
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_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_capabilities(struct hostapd_data *hapd, u8 *eid, u32 nsts);
|
||||||
u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid);
|
u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid);
|
||||||
u8 * hostapd_eid_vendor_vht(struct hostapd_data *hapd, u8 *eid);
|
u8 * hostapd_eid_vendor_vht(struct hostapd_data *hapd, u8 *eid);
|
||||||
@ -64,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_operation(struct hostapd_data *hapd, u8 *eid);
|
||||||
u8 * hostapd_eid_he_mu_edca_parameter_set(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_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);
|
int hostapd_ht_operation_update(struct hostapd_iface *iface);
|
||||||
void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
|
void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
|
||||||
@ -96,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,
|
u16 copy_sta_he_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
enum ieee80211_op_mode opmode, const u8 *he_capab,
|
enum ieee80211_op_mode opmode, const u8 *he_capab,
|
||||||
size_t he_capab_len);
|
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,
|
void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
|
||||||
const u8 *buf, size_t len, int ack);
|
const u8 *buf, size_t len, int ack);
|
||||||
void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
|
void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
|
||||||
@ -182,6 +186,9 @@ void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
size_t hostapd_eid_owe_trans_len(struct hostapd_data *hapd);
|
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);
|
u8 * hostapd_eid_owe_trans(struct hostapd_data *hapd, u8 *eid, size_t len);
|
||||||
|
|
||||||
|
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 get_tx_parameters(struct sta_info *sta, int ap_max_chanwidth,
|
||||||
int ap_seg1_idx, int *bandwidth, int *seg1_idx);
|
int ap_seg1_idx, int *bandwidth, int *seg1_idx);
|
||||||
|
|
||||||
|
@ -192,9 +192,12 @@ u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid)
|
|||||||
params |= (hapd->iface->conf->he_op.he_rts_threshold <<
|
params |= (hapd->iface->conf->he_op.he_rts_threshold <<
|
||||||
HE_OPERATION_RTS_THRESHOLD_OFFSET);
|
HE_OPERATION_RTS_THRESHOLD_OFFSET);
|
||||||
|
|
||||||
if (hapd->iface->conf->he_op.he_bss_color)
|
if (hapd->iface->conf->he_op.he_bss_color_disabled)
|
||||||
params |= (hapd->iface->conf->he_op.he_bss_color <<
|
params |= HE_OPERATION_BSS_COLOR_DISABLED;
|
||||||
HE_OPERATION_BSS_COLOR_OFFSET);
|
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 */
|
/* HE minimum required basic MCS and NSS for STAs */
|
||||||
oper->he_mcs_nss_set =
|
oper->he_mcs_nss_set =
|
||||||
@ -308,6 +311,35 @@ 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_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;
|
||||||
|
capab |= HE_6GHZ_BAND_CAP_SMPS_DISABLED;
|
||||||
|
|
||||||
|
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,
|
void hostapd_get_he_capab(struct hostapd_data *hapd,
|
||||||
const struct ieee80211_he_capabilities *he_cap,
|
const struct ieee80211_he_capabilities *he_cap,
|
||||||
struct ieee80211_he_capabilities *neg_he_cap,
|
struct ieee80211_he_capabilities *neg_he_cap,
|
||||||
@ -387,6 +419,7 @@ u16 copy_sta_he_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
size_t he_capab_len)
|
size_t he_capab_len)
|
||||||
{
|
{
|
||||||
if (!he_capab || !hapd->iconf->ieee80211ax ||
|
if (!he_capab || !hapd->iconf->ieee80211ax ||
|
||||||
|
hapd->conf->disable_11ax ||
|
||||||
!check_valid_he_mcs(hapd, he_capab, opmode) ||
|
!check_valid_he_mcs(hapd, he_capab, opmode) ||
|
||||||
ieee80211_invalid_he_cap_size(he_capab, he_capab_len) ||
|
ieee80211_invalid_he_cap_size(he_capab, he_capab_len) ||
|
||||||
he_capab_len > sizeof(struct ieee80211_he_capabilities)) {
|
he_capab_len > sizeof(struct ieee80211_he_capabilities)) {
|
||||||
@ -410,3 +443,45 @@ u16 copy_sta_he_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
|
|
||||||
return WLAN_STATUS_SUCCESS;
|
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);
|
||||||
|
}
|
||||||
|
@ -109,33 +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 ||
|
|
||||||
is_6ghz_op_class(hapd->iconf->op_class))
|
|
||||||
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
|
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/40 MHz HT in 20/40 MHz BSS or
|
||||||
- all STAs in the BSS are 20 MHz HT in 20 MHz BSS
|
- 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
|
Set to 1 (HT non-member protection) if there may be non-HT STAs
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "utils/common.h"
|
#include "utils/common.h"
|
||||||
#include "common/ieee802_11_defs.h"
|
#include "common/ieee802_11_defs.h"
|
||||||
#include "common/ocv.h"
|
#include "common/ocv.h"
|
||||||
|
#include "common/wpa_ctrl.h"
|
||||||
#include "hostapd.h"
|
#include "hostapd.h"
|
||||||
#include "sta_info.h"
|
#include "sta_info.h"
|
||||||
#include "ap_config.h"
|
#include "ap_config.h"
|
||||||
@ -72,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");
|
"Failed to get channel info for OCI element in SA Query Request");
|
||||||
return;
|
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_len = OCV_OCI_EXTENDED_LEN;
|
||||||
oci_ie = os_zalloc(oci_ie_len);
|
oci_ie = os_zalloc(oci_ie_len);
|
||||||
@ -151,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");
|
"Failed to get channel info for OCI element in SA Query Response");
|
||||||
return;
|
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_len = OCV_OCI_EXTENDED_LEN;
|
||||||
oci_ie = os_zalloc(oci_ie_len);
|
oci_ie = os_zalloc(oci_ie_len);
|
||||||
@ -254,14 +275,21 @@ void ieee802_11_sa_query_action(struct hostapd_data *hapd,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
|
if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
|
||||||
tx_chanwidth, tx_seg1_idx) != 0) {
|
tx_chanwidth, tx_seg1_idx) !=
|
||||||
wpa_printf(MSG_WARNING, "%s", ocv_errorstr);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_OCV */
|
#endif /* CONFIG_OCV */
|
||||||
|
|
||||||
if (action_type == WLAN_SA_QUERY_REQUEST) {
|
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);
|
ieee802_11_send_sa_query_resp(hapd, sa, trans_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -377,6 +405,11 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
|
|||||||
wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt))
|
wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt))
|
||||||
*pos |= 0x01;
|
*pos |= 0x01;
|
||||||
#endif /* CONFIG_FILS */
|
#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;
|
break;
|
||||||
case 10: /* Bits 80-87 */
|
case 10: /* Bits 80-87 */
|
||||||
#ifdef CONFIG_SAE
|
#ifdef CONFIG_SAE
|
||||||
@ -392,6 +425,16 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
|
|||||||
* Identifiers Used Exclusively */
|
* Identifiers Used Exclusively */
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_SAE */
|
#endif /* CONFIG_SAE */
|
||||||
|
if (hapd->conf->beacon_prot)
|
||||||
|
*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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -440,12 +483,25 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
|
|||||||
!wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) && len < 10)
|
!wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) && len < 10)
|
||||||
len = 10;
|
len = 10;
|
||||||
#endif /* CONFIG_FILS */
|
#endif /* CONFIG_FILS */
|
||||||
|
#ifdef CONFIG_IEEE80211AX
|
||||||
|
if (len < 10 && hapd->iconf->ieee80211ax &&
|
||||||
|
hostapd_get_he_twt_responder(hapd, IEEE80211_MODE_AP))
|
||||||
|
len = 10;
|
||||||
|
#endif /* CONFIG_IEEE80211AX */
|
||||||
#ifdef CONFIG_SAE
|
#ifdef CONFIG_SAE
|
||||||
if (len < 11 && hapd->conf->wpa &&
|
if (len < 11 && hapd->conf->wpa &&
|
||||||
wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
|
wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
|
||||||
hostapd_sae_pw_id_in_use(hapd->conf))
|
hostapd_sae_pw_id_in_use(hapd->conf))
|
||||||
len = 11;
|
len = 11;
|
||||||
#endif /* CONFIG_SAE */
|
#endif /* CONFIG_SAE */
|
||||||
|
if (len < 11 && hapd->conf->beacon_prot)
|
||||||
|
len = 11;
|
||||||
|
#ifdef CONFIG_SAE_PK
|
||||||
|
if (len < 12 && hapd->conf->wpa &&
|
||||||
|
wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
|
||||||
|
hostapd_sae_pk_exclusively(hapd->conf))
|
||||||
|
len = 12;
|
||||||
|
#endif /* CONFIG_SAE_PK */
|
||||||
if (len < hapd->iface->extended_capa_len)
|
if (len < hapd->iface->extended_capa_len)
|
||||||
len = hapd->iface->extended_capa_len;
|
len = hapd->iface->extended_capa_len;
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
@ -860,6 +916,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,
|
void ap_copy_sta_supp_op_classes(struct sta_info *sta,
|
||||||
const u8 *supp_op_classes,
|
const u8 *supp_op_classes,
|
||||||
size_t supp_op_classes_len)
|
size_t supp_op_classes_len)
|
||||||
@ -1011,11 +1096,16 @@ int get_tx_parameters(struct sta_info *sta, int ap_max_chanwidth,
|
|||||||
u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len)
|
u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len)
|
||||||
{
|
{
|
||||||
u8 *pos = eid;
|
u8 *pos = eid;
|
||||||
|
bool sae_pk = false;
|
||||||
|
|
||||||
|
#ifdef CONFIG_SAE_PK
|
||||||
|
sae_pk = hostapd_sae_pk_in_use(hapd->conf);
|
||||||
|
#endif /* CONFIG_SAE_PK */
|
||||||
|
|
||||||
if (!(hapd->conf->wpa & WPA_PROTO_RSN) ||
|
if (!(hapd->conf->wpa & WPA_PROTO_RSN) ||
|
||||||
!wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) ||
|
!wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) ||
|
||||||
(hapd->conf->sae_pwe != 1 && hapd->conf->sae_pwe != 2 &&
|
(hapd->conf->sae_pwe != 1 && hapd->conf->sae_pwe != 2 &&
|
||||||
!hostapd_sae_pw_id_in_use(hapd->conf)) ||
|
!hostapd_sae_pw_id_in_use(hapd->conf) && !sae_pk) ||
|
||||||
hapd->conf->sae_pwe == 3 ||
|
hapd->conf->sae_pwe == 3 ||
|
||||||
len < 3)
|
len < 3)
|
||||||
return pos;
|
return pos;
|
||||||
@ -1024,7 +1114,12 @@ u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len)
|
|||||||
*pos++ = 1;
|
*pos++ = 1;
|
||||||
/* bits 0-3 = 0 since only one octet of Extended RSN Capabilities is
|
/* bits 0-3 = 0 since only one octet of Extended RSN Capabilities is
|
||||||
* used for now */
|
* used for now */
|
||||||
*pos++ = BIT(WLAN_RSNX_CAPAB_SAE_H2E);
|
*pos = BIT(WLAN_RSNX_CAPAB_SAE_H2E);
|
||||||
|
#ifdef CONFIG_SAE_PK
|
||||||
|
if (sae_pk)
|
||||||
|
*pos |= BIT(WLAN_RSNX_CAPAB_SAE_PK);
|
||||||
|
#endif /* CONFIG_SAE_PK */
|
||||||
|
pos++;
|
||||||
|
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
@ -167,59 +167,6 @@ 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)
|
u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid)
|
||||||
{
|
{
|
||||||
struct hostapd_iface *iface = hapd->iface;
|
struct hostapd_iface *iface = hapd->iface;
|
||||||
@ -425,7 +372,9 @@ u8 * hostapd_eid_vendor_vht(struct hostapd_data *hapd, u8 *eid)
|
|||||||
{
|
{
|
||||||
u8 *pos = 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;
|
return eid;
|
||||||
|
|
||||||
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
|
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||||
|
@ -137,6 +137,7 @@ void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
#ifndef CONFIG_FIPS
|
#ifndef CONFIG_FIPS
|
||||||
#ifndef CONFIG_NO_RC4
|
#ifndef CONFIG_NO_RC4
|
||||||
|
|
||||||
@ -297,6 +298,7 @@ static void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta)
|
|||||||
|
|
||||||
#endif /* CONFIG_NO_RC4 */
|
#endif /* CONFIG_NO_RC4 */
|
||||||
#endif /* CONFIG_FIPS */
|
#endif /* CONFIG_FIPS */
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
|
|
||||||
|
|
||||||
const char *radius_mode_txt(struct hostapd_data *hapd)
|
const char *radius_mode_txt(struct hostapd_data *hapd)
|
||||||
@ -876,7 +878,7 @@ static void handle_eap_response(struct hostapd_data *hapd,
|
|||||||
|
|
||||||
wpabuf_free(sm->eap_if->eapRespData);
|
wpabuf_free(sm->eap_if->eapRespData);
|
||||||
sm->eap_if->eapRespData = wpabuf_alloc_copy(eap, len);
|
sm->eap_if->eapRespData = wpabuf_alloc_copy(eap, len);
|
||||||
sm->eapolEap = TRUE;
|
sm->eapolEap = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -907,7 +909,7 @@ static void handle_eap_initiate(struct hostapd_data *hapd,
|
|||||||
|
|
||||||
wpabuf_free(sm->eap_if->eapRespData);
|
wpabuf_free(sm->eap_if->eapRespData);
|
||||||
sm->eap_if->eapRespData = wpabuf_alloc_copy(eap, len);
|
sm->eap_if->eapRespData = wpabuf_alloc_copy(eap, len);
|
||||||
sm->eapolEap = TRUE;
|
sm->eapolEap = true;
|
||||||
#endif /* CONFIG_ERP */
|
#endif /* CONFIG_ERP */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1138,7 +1140,7 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_WPS */
|
#endif /* CONFIG_WPS */
|
||||||
|
|
||||||
sta->eapol_sm->eap_if->portEnabled = TRUE;
|
sta->eapol_sm->eap_if->portEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* since we support version 1, we can ignore version field and proceed
|
/* since we support version 1, we can ignore version field and proceed
|
||||||
@ -1165,7 +1167,7 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
|
|||||||
"cached PMKSA available - ignore it since STA sent EAPOL-Start");
|
"cached PMKSA available - ignore it since STA sent EAPOL-Start");
|
||||||
wpa_auth_sta_clear_pmksa(sta->wpa_sm, pmksa);
|
wpa_auth_sta_clear_pmksa(sta->wpa_sm, pmksa);
|
||||||
}
|
}
|
||||||
sta->eapol_sm->eapolStart = TRUE;
|
sta->eapol_sm->eapolStart = true;
|
||||||
sta->eapol_sm->dot1xAuthEapolStartFramesRx++;
|
sta->eapol_sm->dot1xAuthEapolStartFramesRx++;
|
||||||
eap_server_clear_identity(sta->eapol_sm->eap);
|
eap_server_clear_identity(sta->eapol_sm->eap);
|
||||||
wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH_EAPOL);
|
wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH_EAPOL);
|
||||||
@ -1178,7 +1180,7 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
|
|||||||
sta->acct_terminate_cause =
|
sta->acct_terminate_cause =
|
||||||
RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
|
RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
|
||||||
accounting_sta_stop(hapd, sta);
|
accounting_sta_stop(hapd, sta);
|
||||||
sta->eapol_sm->eapolLogoff = TRUE;
|
sta->eapol_sm->eapolLogoff = true;
|
||||||
sta->eapol_sm->dot1xAuthEapolLogoffFramesRx++;
|
sta->eapol_sm->dot1xAuthEapolLogoffFramesRx++;
|
||||||
eap_server_clear_identity(sta->eapol_sm->eap);
|
eap_server_clear_identity(sta->eapol_sm->eap);
|
||||||
break;
|
break;
|
||||||
@ -1295,7 +1297,7 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_WPS */
|
#endif /* CONFIG_WPS */
|
||||||
|
|
||||||
sta->eapol_sm->eap_if->portEnabled = TRUE;
|
sta->eapol_sm->eap_if->portEnabled = true;
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211R_AP
|
#ifdef CONFIG_IEEE80211R_AP
|
||||||
if (sta->auth_alg == WLAN_AUTH_FT) {
|
if (sta->auth_alg == WLAN_AUTH_FT) {
|
||||||
@ -1304,13 +1306,13 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
|
|||||||
"PMK from FT - skip IEEE 802.1X/EAP");
|
"PMK from FT - skip IEEE 802.1X/EAP");
|
||||||
/* Setup EAPOL state machines to already authenticated state
|
/* Setup EAPOL state machines to already authenticated state
|
||||||
* because of existing FT information from R0KH. */
|
* because of existing FT information from R0KH. */
|
||||||
sta->eapol_sm->keyRun = TRUE;
|
sta->eapol_sm->keyRun = true;
|
||||||
sta->eapol_sm->eap_if->eapKeyAvailable = TRUE;
|
sta->eapol_sm->eap_if->eapKeyAvailable = true;
|
||||||
sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING;
|
sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING;
|
||||||
sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS;
|
sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS;
|
||||||
sta->eapol_sm->authSuccess = TRUE;
|
sta->eapol_sm->authSuccess = true;
|
||||||
sta->eapol_sm->authFail = FALSE;
|
sta->eapol_sm->authFail = false;
|
||||||
sta->eapol_sm->portValid = TRUE;
|
sta->eapol_sm->portValid = true;
|
||||||
if (sta->eapol_sm->eap)
|
if (sta->eapol_sm->eap)
|
||||||
eap_sm_notify_cached(sta->eapol_sm->eap);
|
eap_sm_notify_cached(sta->eapol_sm->eap);
|
||||||
ap_sta_bind_vlan(hapd, sta);
|
ap_sta_bind_vlan(hapd, sta);
|
||||||
@ -1327,13 +1329,13 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
|
|||||||
"PMK from FILS - skip IEEE 802.1X/EAP");
|
"PMK from FILS - skip IEEE 802.1X/EAP");
|
||||||
/* Setup EAPOL state machines to already authenticated state
|
/* Setup EAPOL state machines to already authenticated state
|
||||||
* because of existing FILS information. */
|
* because of existing FILS information. */
|
||||||
sta->eapol_sm->keyRun = TRUE;
|
sta->eapol_sm->keyRun = true;
|
||||||
sta->eapol_sm->eap_if->eapKeyAvailable = TRUE;
|
sta->eapol_sm->eap_if->eapKeyAvailable = true;
|
||||||
sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING;
|
sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING;
|
||||||
sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS;
|
sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS;
|
||||||
sta->eapol_sm->authSuccess = TRUE;
|
sta->eapol_sm->authSuccess = true;
|
||||||
sta->eapol_sm->authFail = FALSE;
|
sta->eapol_sm->authFail = false;
|
||||||
sta->eapol_sm->portValid = TRUE;
|
sta->eapol_sm->portValid = true;
|
||||||
if (sta->eapol_sm->eap)
|
if (sta->eapol_sm->eap)
|
||||||
eap_sm_notify_cached(sta->eapol_sm->eap);
|
eap_sm_notify_cached(sta->eapol_sm->eap);
|
||||||
wpa_auth_set_ptk_rekey_timer(sta->wpa_sm);
|
wpa_auth_set_ptk_rekey_timer(sta->wpa_sm);
|
||||||
@ -1348,12 +1350,12 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
|
|||||||
"PMK from PMKSA cache - skip IEEE 802.1X/EAP");
|
"PMK from PMKSA cache - skip IEEE 802.1X/EAP");
|
||||||
/* Setup EAPOL state machines to already authenticated state
|
/* Setup EAPOL state machines to already authenticated state
|
||||||
* because of existing PMKSA information in the cache. */
|
* because of existing PMKSA information in the cache. */
|
||||||
sta->eapol_sm->keyRun = TRUE;
|
sta->eapol_sm->keyRun = true;
|
||||||
sta->eapol_sm->eap_if->eapKeyAvailable = TRUE;
|
sta->eapol_sm->eap_if->eapKeyAvailable = true;
|
||||||
sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING;
|
sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING;
|
||||||
sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS;
|
sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS;
|
||||||
sta->eapol_sm->authSuccess = TRUE;
|
sta->eapol_sm->authSuccess = true;
|
||||||
sta->eapol_sm->authFail = FALSE;
|
sta->eapol_sm->authFail = false;
|
||||||
if (sta->eapol_sm->eap)
|
if (sta->eapol_sm->eap)
|
||||||
eap_sm_notify_cached(sta->eapol_sm->eap);
|
eap_sm_notify_cached(sta->eapol_sm->eap);
|
||||||
pmksa_cache_to_eapol_data(hapd, pmksa, sta->eapol_sm);
|
pmksa_cache_to_eapol_data(hapd, pmksa, sta->eapol_sm);
|
||||||
@ -1365,7 +1367,7 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
|
|||||||
* re-authentication without having to wait for the
|
* re-authentication without having to wait for the
|
||||||
* Supplicant to send EAPOL-Start.
|
* Supplicant to send EAPOL-Start.
|
||||||
*/
|
*/
|
||||||
sta->eapol_sm->reAuthenticate = TRUE;
|
sta->eapol_sm->reAuthenticate = true;
|
||||||
}
|
}
|
||||||
eapol_auth_step(sta->eapol_sm);
|
eapol_auth_step(sta->eapol_sm);
|
||||||
}
|
}
|
||||||
@ -1413,7 +1415,7 @@ static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd,
|
|||||||
|
|
||||||
if (!sm || !sm->last_recv_radius) {
|
if (!sm || !sm->last_recv_radius) {
|
||||||
if (sm)
|
if (sm)
|
||||||
sm->eap_if->aaaEapNoReq = TRUE;
|
sm->eap_if->aaaEapNoReq = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1427,7 +1429,7 @@ static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd,
|
|||||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
|
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
|
||||||
HOSTAPD_LEVEL_WARNING,
|
HOSTAPD_LEVEL_WARNING,
|
||||||
"could not extract EAP-Message from RADIUS message");
|
"could not extract EAP-Message from RADIUS message");
|
||||||
sm->eap_if->aaaEapNoReq = TRUE;
|
sm->eap_if->aaaEapNoReq = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1436,7 +1438,7 @@ static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd,
|
|||||||
HOSTAPD_LEVEL_WARNING,
|
HOSTAPD_LEVEL_WARNING,
|
||||||
"too short EAP packet received from authentication server");
|
"too short EAP packet received from authentication server");
|
||||||
wpabuf_free(eap);
|
wpabuf_free(eap);
|
||||||
sm->eap_if->aaaEapNoReq = TRUE;
|
sm->eap_if->aaaEapNoReq = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1471,7 +1473,7 @@ static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd,
|
|||||||
"decapsulated EAP packet (code=%d id=%d len=%d) from RADIUS server: %s",
|
"decapsulated EAP packet (code=%d id=%d len=%d) from RADIUS server: %s",
|
||||||
hdr->code, hdr->identifier, be_to_host16(hdr->length),
|
hdr->code, hdr->identifier, be_to_host16(hdr->length),
|
||||||
buf);
|
buf);
|
||||||
sm->eap_if->aaaEapReq = TRUE;
|
sm->eap_if->aaaEapReq = true;
|
||||||
|
|
||||||
wpabuf_free(sm->eap_if->aaaEapReqData);
|
wpabuf_free(sm->eap_if->aaaEapReqData);
|
||||||
sm->eap_if->aaaEapReqData = eap;
|
sm->eap_if->aaaEapReqData = eap;
|
||||||
@ -1510,7 +1512,7 @@ static void ieee802_1x_get_keys(struct hostapd_data *hapd,
|
|||||||
os_memcpy(sm->eap_if->aaaEapKeyData + keys->recv_len,
|
os_memcpy(sm->eap_if->aaaEapKeyData + keys->recv_len,
|
||||||
keys->send, keys->send_len);
|
keys->send, keys->send_len);
|
||||||
sm->eap_if->aaaEapKeyDataLen = len;
|
sm->eap_if->aaaEapKeyDataLen = len;
|
||||||
sm->eap_if->aaaEapKeyAvailable = TRUE;
|
sm->eap_if->aaaEapKeyAvailable = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
@ -1878,7 +1880,7 @@ static int ieee802_1x_update_vlan(struct radius_msg *msg,
|
|||||||
|
|
||||||
if (vlan_desc.notempty &&
|
if (vlan_desc.notempty &&
|
||||||
!hostapd_vlan_valid(hapd->conf->vlan, &vlan_desc)) {
|
!hostapd_vlan_valid(hapd->conf->vlan, &vlan_desc)) {
|
||||||
sta->eapol_sm->authFail = TRUE;
|
sta->eapol_sm->authFail = true;
|
||||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
|
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
|
||||||
HOSTAPD_LEVEL_INFO,
|
HOSTAPD_LEVEL_INFO,
|
||||||
"Invalid VLAN %d%s received from RADIUS server",
|
"Invalid VLAN %d%s received from RADIUS server",
|
||||||
@ -1891,7 +1893,7 @@ static int ieee802_1x_update_vlan(struct radius_msg *msg,
|
|||||||
|
|
||||||
if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_REQUIRED &&
|
if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_REQUIRED &&
|
||||||
!vlan_desc.notempty) {
|
!vlan_desc.notempty) {
|
||||||
sta->eapol_sm->authFail = TRUE;
|
sta->eapol_sm->authFail = true;
|
||||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
|
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
|
||||||
HOSTAPD_LEVEL_INFO,
|
HOSTAPD_LEVEL_INFO,
|
||||||
"authentication server did not include required VLAN ID in Access-Accept");
|
"authentication server did not include required VLAN ID in Access-Accept");
|
||||||
@ -2017,7 +2019,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
|
|||||||
else
|
else
|
||||||
ap_sta_no_session_timeout(hapd, sta);
|
ap_sta_no_session_timeout(hapd, sta);
|
||||||
|
|
||||||
sm->eap_if->aaaSuccess = TRUE;
|
sm->eap_if->aaaSuccess = true;
|
||||||
override_eapReq = 1;
|
override_eapReq = 1;
|
||||||
ieee802_1x_get_keys(hapd, sta, msg, req, shared_secret,
|
ieee802_1x_get_keys(hapd, sta, msg, req, shared_secret,
|
||||||
shared_secret_len);
|
shared_secret_len);
|
||||||
@ -2029,7 +2031,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
|
|||||||
(int) session_timeout : -1);
|
(int) session_timeout : -1);
|
||||||
break;
|
break;
|
||||||
case RADIUS_CODE_ACCESS_REJECT:
|
case RADIUS_CODE_ACCESS_REJECT:
|
||||||
sm->eap_if->aaaFail = TRUE;
|
sm->eap_if->aaaFail = true;
|
||||||
override_eapReq = 1;
|
override_eapReq = 1;
|
||||||
if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_WLAN_REASON_CODE,
|
if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_WLAN_REASON_CODE,
|
||||||
&reason_code) == 0) {
|
&reason_code) == 0) {
|
||||||
@ -2040,7 +2042,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RADIUS_CODE_ACCESS_CHALLENGE:
|
case RADIUS_CODE_ACCESS_CHALLENGE:
|
||||||
sm->eap_if->aaaEapReq = TRUE;
|
sm->eap_if->aaaEapReq = true;
|
||||||
if (session_timeout_set) {
|
if (session_timeout_set) {
|
||||||
/* RFC 2869, Ch. 2.3.2; RFC 3580, Ch. 3.17 */
|
/* RFC 2869, Ch. 2.3.2; RFC 3580, Ch. 3.17 */
|
||||||
sm->eap_if->aaaMethodTimeout = session_timeout;
|
sm->eap_if->aaaMethodTimeout = session_timeout;
|
||||||
@ -2061,7 +2063,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
|
|||||||
|
|
||||||
ieee802_1x_decapsulate_radius(hapd, sta);
|
ieee802_1x_decapsulate_radius(hapd, sta);
|
||||||
if (override_eapReq)
|
if (override_eapReq)
|
||||||
sm->eap_if->aaaEapReq = FALSE;
|
sm->eap_if->aaaEapReq = false;
|
||||||
|
|
||||||
#ifdef CONFIG_FILS
|
#ifdef CONFIG_FILS
|
||||||
#ifdef NEED_AP_MLME
|
#ifdef NEED_AP_MLME
|
||||||
@ -2107,13 +2109,15 @@ void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta)
|
|||||||
wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "EAP Timeout, STA " MACSTR,
|
wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "EAP Timeout, STA " MACSTR,
|
||||||
MAC2STR(sta->addr));
|
MAC2STR(sta->addr));
|
||||||
|
|
||||||
sm->eap_if->portEnabled = FALSE;
|
sm->eap_if->portEnabled = false;
|
||||||
ap_sta_disconnect(hapd, sta, sta->addr,
|
ap_sta_disconnect(hapd, sta, sta->addr,
|
||||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
|
|
||||||
static int ieee802_1x_rekey_broadcast(struct hostapd_data *hapd)
|
static int ieee802_1x_rekey_broadcast(struct hostapd_data *hapd)
|
||||||
{
|
{
|
||||||
struct eapol_authenticator *eapol = hapd->eapol_auth;
|
struct eapol_authenticator *eapol = hapd->eapol_auth;
|
||||||
@ -2144,7 +2148,7 @@ static int ieee802_1x_sta_key_available(struct hostapd_data *hapd,
|
|||||||
struct sta_info *sta, void *ctx)
|
struct sta_info *sta, void *ctx)
|
||||||
{
|
{
|
||||||
if (sta->eapol_sm) {
|
if (sta->eapol_sm) {
|
||||||
sta->eapol_sm->eap_if->eapKeyAvailable = TRUE;
|
sta->eapol_sm->eap_if->eapKeyAvailable = true;
|
||||||
eapol_auth_step(sta->eapol_sm);
|
eapol_auth_step(sta->eapol_sm);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -2198,6 +2202,8 @@ static void ieee802_1x_rekey(void *eloop_ctx, void *timeout_ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
|
|
||||||
|
|
||||||
static void ieee802_1x_eapol_send(void *ctx, void *sta_ctx, u8 type,
|
static void ieee802_1x_eapol_send(void *ctx, void *sta_ctx, u8 type,
|
||||||
const u8 *data, size_t datalen)
|
const u8 *data, size_t datalen)
|
||||||
@ -2361,6 +2367,7 @@ static void _ieee802_1x_abort_auth(void *ctx, void *sta_ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
static void _ieee802_1x_tx_key(void *ctx, void *sta_ctx)
|
static void _ieee802_1x_tx_key(void *ctx, void *sta_ctx)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_FIPS
|
#ifndef CONFIG_FIPS
|
||||||
@ -2372,6 +2379,7 @@ static void _ieee802_1x_tx_key(void *ctx, void *sta_ctx)
|
|||||||
#endif /* CONFIG_NO_RC4 */
|
#endif /* CONFIG_NO_RC4 */
|
||||||
#endif /* CONFIG_FIPS */
|
#endif /* CONFIG_FIPS */
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
|
|
||||||
|
|
||||||
static void ieee802_1x_eapol_event(void *ctx, void *sta_ctx,
|
static void ieee802_1x_eapol_event(void *ctx, void *sta_ctx,
|
||||||
@ -2422,7 +2430,6 @@ static int ieee802_1x_erp_add_key(void *ctx, struct eap_server_erp_key *erp)
|
|||||||
|
|
||||||
int ieee802_1x_init(struct hostapd_data *hapd)
|
int ieee802_1x_init(struct hostapd_data *hapd)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
struct eapol_auth_config conf;
|
struct eapol_auth_config conf;
|
||||||
struct eapol_auth_cb cb;
|
struct eapol_auth_cb cb;
|
||||||
|
|
||||||
@ -2433,7 +2440,9 @@ int ieee802_1x_init(struct hostapd_data *hapd)
|
|||||||
conf.ctx = hapd;
|
conf.ctx = hapd;
|
||||||
conf.eap_reauth_period = hapd->conf->eap_reauth_period;
|
conf.eap_reauth_period = hapd->conf->eap_reauth_period;
|
||||||
conf.wpa = hapd->conf->wpa;
|
conf.wpa = hapd->conf->wpa;
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
conf.individual_wep_key_len = hapd->conf->individual_wep_key_len;
|
conf.individual_wep_key_len = hapd->conf->individual_wep_key_len;
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
conf.eap_req_id_text = hapd->conf->eap_req_id_text;
|
conf.eap_req_id_text = hapd->conf->eap_req_id_text;
|
||||||
conf.eap_req_id_text_len = hapd->conf->eap_req_id_text_len;
|
conf.eap_req_id_text_len = hapd->conf->eap_req_id_text_len;
|
||||||
conf.erp_send_reauth_start = hapd->conf->erp_send_reauth_start;
|
conf.erp_send_reauth_start = hapd->conf->erp_send_reauth_start;
|
||||||
@ -2448,7 +2457,9 @@ int ieee802_1x_init(struct hostapd_data *hapd)
|
|||||||
cb.logger = ieee802_1x_logger;
|
cb.logger = ieee802_1x_logger;
|
||||||
cb.set_port_authorized = ieee802_1x_set_port_authorized;
|
cb.set_port_authorized = ieee802_1x_set_port_authorized;
|
||||||
cb.abort_auth = _ieee802_1x_abort_auth;
|
cb.abort_auth = _ieee802_1x_abort_auth;
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
cb.tx_key = _ieee802_1x_tx_key;
|
cb.tx_key = _ieee802_1x_tx_key;
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
cb.eapol_event = ieee802_1x_eapol_event;
|
cb.eapol_event = ieee802_1x_eapol_event;
|
||||||
#ifdef CONFIG_ERP
|
#ifdef CONFIG_ERP
|
||||||
cb.erp_get_key = ieee802_1x_erp_get_key;
|
cb.erp_get_key = ieee802_1x_erp_get_key;
|
||||||
@ -2469,17 +2480,21 @@ int ieee802_1x_init(struct hostapd_data *hapd)
|
|||||||
return -1;
|
return -1;
|
||||||
#endif /* CONFIG_NO_RADIUS */
|
#endif /* CONFIG_NO_RADIUS */
|
||||||
|
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
if (hapd->conf->default_wep_key_len) {
|
if (hapd->conf->default_wep_key_len) {
|
||||||
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
hostapd_drv_set_key(hapd->conf->iface, hapd,
|
hostapd_drv_set_key(hapd->conf->iface, hapd,
|
||||||
WPA_ALG_NONE, NULL, i, 0, 0, NULL,
|
WPA_ALG_NONE, NULL, i, 0, 0, NULL,
|
||||||
0, NULL, 0, KEY_FLAG_GROUP_RX_TX);
|
0, NULL, 0, KEY_FLAG_GROUP);
|
||||||
|
|
||||||
ieee802_1x_rekey(hapd, NULL);
|
ieee802_1x_rekey(hapd, NULL);
|
||||||
|
|
||||||
if (!hapd->eapol_auth->default_wep_key)
|
if (!hapd->eapol_auth->default_wep_key)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2499,7 +2514,9 @@ void ieee802_1x_erp_flush(struct hostapd_data *hapd)
|
|||||||
|
|
||||||
void ieee802_1x_deinit(struct hostapd_data *hapd)
|
void ieee802_1x_deinit(struct hostapd_data *hapd)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
eloop_cancel_timeout(ieee802_1x_rekey, hapd, NULL);
|
eloop_cancel_timeout(ieee802_1x_rekey, hapd, NULL);
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
|
|
||||||
if (hapd->driver && hapd->drv_priv &&
|
if (hapd->driver && hapd->drv_priv &&
|
||||||
(hapd->conf->ieee802_1x || hapd->conf->wpa))
|
(hapd->conf->ieee802_1x || hapd->conf->wpa))
|
||||||
@ -2660,26 +2677,25 @@ const u8 * ieee802_1x_get_session_id(struct eapol_state_machine *sm,
|
|||||||
|
|
||||||
|
|
||||||
void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm,
|
void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm,
|
||||||
int enabled)
|
bool enabled)
|
||||||
{
|
{
|
||||||
if (!sm)
|
if (!sm)
|
||||||
return;
|
return;
|
||||||
sm->eap_if->portEnabled = enabled ? TRUE : FALSE;
|
sm->eap_if->portEnabled = enabled;
|
||||||
eapol_auth_step(sm);
|
eapol_auth_step(sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm,
|
void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm, bool valid)
|
||||||
int valid)
|
|
||||||
{
|
{
|
||||||
if (!sm)
|
if (!sm)
|
||||||
return;
|
return;
|
||||||
sm->portValid = valid ? TRUE : FALSE;
|
sm->portValid = valid;
|
||||||
eapol_auth_step(sm);
|
eapol_auth_step(sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth)
|
void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, bool pre_auth)
|
||||||
{
|
{
|
||||||
if (!sm)
|
if (!sm)
|
||||||
return;
|
return;
|
||||||
@ -2690,7 +2706,7 @@ void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const char * bool_txt(Boolean val)
|
static const char * bool_txt(bool val)
|
||||||
{
|
{
|
||||||
return val ? "TRUE" : "FALSE";
|
return val ? "TRUE" : "FALSE";
|
||||||
}
|
}
|
||||||
|
@ -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,
|
const u8 * ieee802_1x_get_session_id(struct eapol_state_machine *sm,
|
||||||
size_t *len);
|
size_t *len);
|
||||||
void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm,
|
void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm,
|
||||||
int enabled);
|
bool enabled);
|
||||||
void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm,
|
void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm, bool valid);
|
||||||
int valid);
|
void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, bool pre_auth);
|
||||||
void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth);
|
|
||||||
int ieee802_1x_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen);
|
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,
|
int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
char *buf, size_t buflen);
|
char *buf, size_t buflen);
|
||||||
|
@ -220,7 +220,7 @@ void hostapd_neighbor_set_own_report(struct hostapd_data *hapd)
|
|||||||
u16 capab = hostapd_own_capab_info(hapd);
|
u16 capab = hostapd_own_capab_info(hapd);
|
||||||
int ht = hapd->iconf->ieee80211n && !hapd->conf->disable_11n;
|
int ht = hapd->iconf->ieee80211n && !hapd->conf->disable_11n;
|
||||||
int vht = hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac;
|
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;
|
struct wpa_ssid_value ssid;
|
||||||
u8 channel, op_class;
|
u8 channel, op_class;
|
||||||
u8 center_freq1_idx = 0, center_freq2_idx = 0;
|
u8 center_freq1_idx = 0, center_freq2_idx = 0;
|
||||||
@ -256,6 +256,8 @@ void hostapd_neighbor_set_own_report(struct hostapd_data *hapd)
|
|||||||
/* VHT bit added in IEEE P802.11-REVmc/D4.3 */
|
/* VHT bit added in IEEE P802.11-REVmc/D4.3 */
|
||||||
if (vht)
|
if (vht)
|
||||||
bssid_info |= NEI_REP_BSSID_INFO_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 */
|
/* TODO: Set NEI_REP_BSSID_INFO_MOBILITY_DOMAIN if MDE is set */
|
||||||
|
@ -516,6 +516,11 @@ struct rsn_pmksa_cache_entry * pmksa_cache_get_okc(
|
|||||||
for (entry = pmksa->pmksa; entry; entry = entry->next) {
|
for (entry = pmksa->pmksa; entry; entry = entry->next) {
|
||||||
if (os_memcmp(entry->spa, spa, ETH_ALEN) != 0)
|
if (os_memcmp(entry->spa, spa, ETH_ALEN) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
if (wpa_key_mgmt_sae(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,
|
rsn_pmkid(entry->pmk, entry->pmk_len, aa, spa, new_pmkid,
|
||||||
entry->akmp);
|
entry->akmp);
|
||||||
if (os_memcmp(new_pmkid, pmkid, PMKID_LEN) == 0)
|
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;
|
sta = NULL;
|
||||||
} else {
|
} else {
|
||||||
sta->eapol_sm->radius_identifier = -1;
|
sta->eapol_sm->radius_identifier = -1;
|
||||||
sta->eapol_sm->portValid = TRUE;
|
sta->eapol_sm->portValid = true;
|
||||||
sta->eapol_sm->flags |= EAPOL_SM_PREAUTH;
|
sta->eapol_sm->flags |= EAPOL_SM_PREAUTH;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,6 +165,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
|||||||
|
|
||||||
/* just in case */
|
/* just in case */
|
||||||
ap_sta_set_authorized(hapd, sta, 0);
|
ap_sta_set_authorized(hapd, sta, 0);
|
||||||
|
hostapd_set_sta_flags(hapd, sta);
|
||||||
|
|
||||||
if (sta->flags & (WLAN_STA_WDS | WLAN_STA_MULTI_AP))
|
if (sta->flags & (WLAN_STA_WDS | WLAN_STA_MULTI_AP))
|
||||||
hostapd_set_wds_sta(hapd, NULL, sta->addr, sta->aid, 0);
|
hostapd_set_wds_sta(hapd, NULL, sta->addr, sta->aid, 0);
|
||||||
@ -234,9 +235,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
|||||||
sta->assoc_ie_taxonomy = NULL;
|
sta->assoc_ie_taxonomy = NULL;
|
||||||
#endif /* CONFIG_TAXONOMY */
|
#endif /* CONFIG_TAXONOMY */
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211N
|
|
||||||
ht40_intolerant_remove(hapd->iface, sta);
|
ht40_intolerant_remove(hapd->iface, sta);
|
||||||
#endif /* CONFIG_IEEE80211N */
|
|
||||||
|
|
||||||
#ifdef CONFIG_P2P
|
#ifdef CONFIG_P2P
|
||||||
if (sta->no_p2p_set) {
|
if (sta->no_p2p_set) {
|
||||||
@ -247,10 +246,10 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_P2P */
|
#endif /* CONFIG_P2P */
|
||||||
|
|
||||||
#if defined(NEED_AP_MLME) && defined(CONFIG_IEEE80211N)
|
#ifdef NEED_AP_MLME
|
||||||
if (hostapd_ht_operation_update(hapd->iface) > 0)
|
if (hostapd_ht_operation_update(hapd->iface) > 0)
|
||||||
set_beacon++;
|
set_beacon++;
|
||||||
#endif /* NEED_AP_MLME && CONFIG_IEEE80211N */
|
#endif /* NEED_AP_MLME */
|
||||||
|
|
||||||
#ifdef CONFIG_MESH
|
#ifdef CONFIG_MESH
|
||||||
if (hapd->mesh_sta_free_cb)
|
if (hapd->mesh_sta_free_cb)
|
||||||
@ -328,6 +327,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
|||||||
os_free(sta->vht_capabilities);
|
os_free(sta->vht_capabilities);
|
||||||
os_free(sta->vht_operation);
|
os_free(sta->vht_operation);
|
||||||
os_free(sta->he_capab);
|
os_free(sta->he_capab);
|
||||||
|
os_free(sta->he_6ghz_capab);
|
||||||
hostapd_free_psk_list(sta->psk);
|
hostapd_free_psk_list(sta->psk);
|
||||||
os_free(sta->identity);
|
os_free(sta->identity);
|
||||||
os_free(sta->radius_cui);
|
os_free(sta->radius_cui);
|
||||||
@ -547,6 +547,7 @@ skip_poll:
|
|||||||
case STA_DISASSOC_FROM_CLI:
|
case STA_DISASSOC_FROM_CLI:
|
||||||
ap_sta_set_authorized(hapd, sta, 0);
|
ap_sta_set_authorized(hapd, sta, 0);
|
||||||
sta->flags &= ~WLAN_STA_ASSOC;
|
sta->flags &= ~WLAN_STA_ASSOC;
|
||||||
|
hostapd_set_sta_flags(hapd, sta);
|
||||||
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
|
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
|
||||||
if (!sta->acct_terminate_cause)
|
if (!sta->acct_terminate_cause)
|
||||||
sta->acct_terminate_cause =
|
sta->acct_terminate_cause =
|
||||||
@ -815,6 +816,7 @@ void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
sta->timeout_next = STA_DEAUTH;
|
sta->timeout_next = STA_DEAUTH;
|
||||||
}
|
}
|
||||||
ap_sta_set_authorized(hapd, sta, 0);
|
ap_sta_set_authorized(hapd, sta, 0);
|
||||||
|
hostapd_set_sta_flags(hapd, sta);
|
||||||
wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
|
wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
|
||||||
"for " MACSTR " (%d seconds - "
|
"for " MACSTR " (%d seconds - "
|
||||||
"AP_MAX_INACTIVITY_AFTER_DISASSOC)",
|
"AP_MAX_INACTIVITY_AFTER_DISASSOC)",
|
||||||
@ -865,6 +867,7 @@ void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
|
sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
|
||||||
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
|
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
|
||||||
ap_sta_set_authorized(hapd, sta, 0);
|
ap_sta_set_authorized(hapd, sta, 0);
|
||||||
|
hostapd_set_sta_flags(hapd, sta);
|
||||||
sta->timeout_next = STA_REMOVE;
|
sta->timeout_next = STA_REMOVE;
|
||||||
wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
|
wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
|
||||||
"for " MACSTR " (%d seconds - "
|
"for " MACSTR " (%d seconds - "
|
||||||
@ -1030,6 +1033,13 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta)
|
|||||||
int ret;
|
int ret;
|
||||||
int old_vlanid = sta->vlan_id_bound;
|
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;
|
iface = hapd->conf->iface;
|
||||||
if (hapd->conf->ssid.vlan[0])
|
if (hapd->conf->ssid.vlan[0])
|
||||||
iface = hapd->conf->ssid.vlan;
|
iface = hapd->conf->ssid.vlan;
|
||||||
@ -1136,6 +1146,8 @@ static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
|
|||||||
if (sta->sa_query_count > 0 &&
|
if (sta->sa_query_count > 0 &&
|
||||||
ap_check_sa_query_timeout(hapd, sta))
|
ap_check_sa_query_timeout(hapd, sta))
|
||||||
return;
|
return;
|
||||||
|
if (sta->sa_query_count >= 1000)
|
||||||
|
return;
|
||||||
|
|
||||||
nbuf = os_realloc_array(sta->sa_query_trans_id,
|
nbuf = os_realloc_array(sta->sa_query_trans_id,
|
||||||
sta->sa_query_count + 1,
|
sta->sa_query_count + 1,
|
||||||
@ -1330,9 +1342,10 @@ void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
if (sta == NULL)
|
if (sta == NULL)
|
||||||
return;
|
return;
|
||||||
ap_sta_set_authorized(hapd, sta, 0);
|
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);
|
wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
|
||||||
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
|
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 "
|
wpa_printf(MSG_DEBUG, "%s: %s: reschedule ap_handle_timer timeout "
|
||||||
"for " MACSTR " (%d seconds - "
|
"for " MACSTR " (%d seconds - "
|
||||||
"AP_MAX_INACTIVITY_AFTER_DEAUTH)",
|
"AP_MAX_INACTIVITY_AFTER_DEAUTH)",
|
||||||
@ -1420,7 +1433,8 @@ int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen)
|
|||||||
int res;
|
int res;
|
||||||
|
|
||||||
buf[0] = '\0';
|
buf[0] = '\0';
|
||||||
res = os_snprintf(buf, buflen, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
|
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_AUTH ? "[AUTH]" : ""),
|
||||||
(flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""),
|
(flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""),
|
||||||
(flags & WLAN_STA_AUTHORIZED ? "[AUTHORIZED]" : ""),
|
(flags & WLAN_STA_AUTHORIZED ? "[AUTHORIZED]" : ""),
|
||||||
@ -1440,6 +1454,7 @@ int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen)
|
|||||||
(flags & WLAN_STA_HT ? "[HT]" : ""),
|
(flags & WLAN_STA_HT ? "[HT]" : ""),
|
||||||
(flags & WLAN_STA_VHT ? "[VHT]" : ""),
|
(flags & WLAN_STA_VHT ? "[VHT]" : ""),
|
||||||
(flags & WLAN_STA_HE ? "[HE]" : ""),
|
(flags & WLAN_STA_HE ? "[HE]" : ""),
|
||||||
|
(flags & WLAN_STA_6GHZ ? "[6GHZ]" : ""),
|
||||||
(flags & WLAN_STA_VENDOR_VHT ? "[VENDOR_VHT]" : ""),
|
(flags & WLAN_STA_VENDOR_VHT ? "[VENDOR_VHT]" : ""),
|
||||||
(flags & WLAN_STA_WNM_SLEEP_MODE ?
|
(flags & WLAN_STA_WNM_SLEEP_MODE ?
|
||||||
"[WNM_SLEEP_MODE]" : ""));
|
"[WNM_SLEEP_MODE]" : ""));
|
||||||
@ -1493,3 +1508,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,
|
return eloop_is_timeout_registered(ap_sta_delayed_1x_auth_fail_cb,
|
||||||
hapd, sta);
|
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;
|
||||||
|
}
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#define WLAN_STA_PENDING_FILS_ERP BIT(22)
|
#define WLAN_STA_PENDING_FILS_ERP BIT(22)
|
||||||
#define WLAN_STA_MULTI_AP BIT(23)
|
#define WLAN_STA_MULTI_AP BIT(23)
|
||||||
#define WLAN_STA_HE BIT(24)
|
#define WLAN_STA_HE BIT(24)
|
||||||
|
#define WLAN_STA_6GHZ BIT(25)
|
||||||
#define WLAN_STA_PENDING_DISASSOC_CB BIT(29)
|
#define WLAN_STA_PENDING_DISASSOC_CB BIT(29)
|
||||||
#define WLAN_STA_PENDING_DEAUTH_CB BIT(30)
|
#define WLAN_STA_PENDING_DEAUTH_CB BIT(30)
|
||||||
#define WLAN_STA_NONERP BIT(31)
|
#define WLAN_STA_NONERP BIT(31)
|
||||||
@ -121,6 +122,7 @@ struct sta_info {
|
|||||||
unsigned int hs20_t_c_filtering:1;
|
unsigned int hs20_t_c_filtering:1;
|
||||||
unsigned int ft_over_ds:1;
|
unsigned int ft_over_ds:1;
|
||||||
unsigned int external_dh_updated:1;
|
unsigned int external_dh_updated:1;
|
||||||
|
unsigned int post_csa_sa_query:1;
|
||||||
|
|
||||||
u16 auth_alg;
|
u16 auth_alg;
|
||||||
|
|
||||||
@ -170,6 +172,7 @@ struct sta_info {
|
|||||||
u8 vht_opmode;
|
u8 vht_opmode;
|
||||||
struct ieee80211_he_capabilities *he_capab;
|
struct ieee80211_he_capabilities *he_capab;
|
||||||
size_t he_capab_len;
|
size_t he_capab_len;
|
||||||
|
struct ieee80211_he_6ghz_band_cap *he_6ghz_capab;
|
||||||
|
|
||||||
int sa_query_count; /* number of pending SA Query requests;
|
int sa_query_count; /* number of pending SA Query requests;
|
||||||
* 0 = no SA Query in progress */
|
* 0 = no SA Query in progress */
|
||||||
@ -358,5 +361,6 @@ void ap_sta_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
|
|||||||
struct sta_info *sta);
|
struct sta_info *sta);
|
||||||
int ap_sta_pending_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
|
int ap_sta_pending_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
|
||||||
struct sta_info *sta);
|
struct sta_info *sta);
|
||||||
|
int ap_sta_re_add(struct hostapd_data *hapd, struct sta_info *sta);
|
||||||
|
|
||||||
#endif /* STA_INFO_H */
|
#endif /* STA_INFO_H */
|
||||||
|
@ -56,6 +56,10 @@ static int prune_associations(struct hostapd_iface *iface, void *ctx)
|
|||||||
ohapd = iface->bss[j];
|
ohapd = iface->bss[j];
|
||||||
if (ohapd == data->hapd)
|
if (ohapd == data->hapd)
|
||||||
continue;
|
continue;
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
if (ohapd->conf->skip_prune_assoc)
|
||||||
|
continue;
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
#ifdef CONFIG_FST
|
#ifdef CONFIG_FST
|
||||||
/* Don't prune STAs belong to same FST */
|
/* Don't prune STAs belong to same FST */
|
||||||
if (ohapd->iface->fst &&
|
if (ohapd->iface->fst &&
|
||||||
|
@ -22,7 +22,9 @@
|
|||||||
static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
|
static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
|
||||||
int existsok)
|
int existsok)
|
||||||
{
|
{
|
||||||
int ret, i;
|
int ret;
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < NUM_WEP_KEYS; i++) {
|
for (i = 0; i < NUM_WEP_KEYS; i++) {
|
||||||
if (!hapd->conf->ssid.wep.key[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);
|
vlan->ifname);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
|
|
||||||
if (!iface_exists(vlan->ifname))
|
if (!iface_exists(vlan->ifname))
|
||||||
ret = hostapd_vlan_if_add(hapd, vlan->ifname);
|
ret = hostapd_vlan_if_add(hapd, vlan->ifname);
|
||||||
|
@ -54,6 +54,7 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
|
|||||||
size_t len;
|
size_t len;
|
||||||
size_t gtk_elem_len = 0;
|
size_t gtk_elem_len = 0;
|
||||||
size_t igtk_elem_len = 0;
|
size_t igtk_elem_len = 0;
|
||||||
|
size_t bigtk_elem_len = 0;
|
||||||
struct wnm_sleep_element wnmsleep_ie;
|
struct wnm_sleep_element wnmsleep_ie;
|
||||||
u8 *wnmtfs_ie, *oci_ie;
|
u8 *wnmtfs_ie, *oci_ie;
|
||||||
u8 wnmsleep_ie_len, oci_ie_len;
|
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);
|
os_free(wnmtfs_ie);
|
||||||
return -1;
|
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_len = OCV_OCI_EXTENDED_LEN;
|
||||||
oci_ie = os_zalloc(oci_ie_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_GTK_SUBELEM_LEN 45
|
||||||
#define MAX_IGTK_SUBELEM_LEN 26
|
#define MAX_IGTK_SUBELEM_LEN 26
|
||||||
|
#define MAX_BIGTK_SUBELEM_LEN 26
|
||||||
mgmt = os_zalloc(sizeof(*mgmt) + wnmsleep_ie_len +
|
mgmt = os_zalloc(sizeof(*mgmt) + wnmsleep_ie_len +
|
||||||
MAX_GTK_SUBELEM_LEN + MAX_IGTK_SUBELEM_LEN +
|
MAX_GTK_SUBELEM_LEN + MAX_IGTK_SUBELEM_LEN +
|
||||||
|
MAX_BIGTK_SUBELEM_LEN +
|
||||||
oci_ie_len);
|
oci_ie_len);
|
||||||
if (mgmt == NULL) {
|
if (mgmt == NULL) {
|
||||||
wpa_printf(MSG_DEBUG, "MLME: Failed to allocate buffer for "
|
wpa_printf(MSG_DEBUG, "MLME: Failed to allocate buffer for "
|
||||||
@ -157,10 +169,19 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
|
|||||||
pos += igtk_elem_len;
|
pos += igtk_elem_len;
|
||||||
wpa_printf(MSG_DEBUG, "Pass 4 igtk_len = %d",
|
wpa_printf(MSG_DEBUG, "Pass 4 igtk_len = %d",
|
||||||
(int) igtk_elem_len);
|
(int) igtk_elem_len);
|
||||||
|
if (hapd->conf->beacon_prot) {
|
||||||
|
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 *)
|
WPA_PUT_LE16((u8 *)
|
||||||
&mgmt->u.action.u.wnm_sleep_resp.keydata_len,
|
&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);
|
os_memcpy(pos, &wnmsleep_ie, wnmsleep_ie_len);
|
||||||
/* copy TFS IE here */
|
/* copy TFS IE here */
|
||||||
@ -176,7 +197,8 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
|
|||||||
#endif /* CONFIG_OCV */
|
#endif /* CONFIG_OCV */
|
||||||
|
|
||||||
len = 1 + sizeof(mgmt->u.action.u.wnm_sleep_resp) + gtk_elem_len +
|
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
|
/* In driver, response frame should be forced to sent when STA is in
|
||||||
* PS mode */
|
* PS mode */
|
||||||
@ -189,8 +211,8 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
|
|||||||
|
|
||||||
/* when entering wnmsleep
|
/* when entering wnmsleep
|
||||||
* 1. pause the node in driver
|
* 1. pause the node in driver
|
||||||
* 2. mark the node so that AP won't update GTK/IGTK during
|
* 2. mark the node so that AP won't update GTK/IGTK/BIGTK
|
||||||
* WNM Sleep
|
* during WNM Sleep
|
||||||
*/
|
*/
|
||||||
if (wnmsleep_ie.status == WNM_STATUS_SLEEP_ACCEPT &&
|
if (wnmsleep_ie.status == WNM_STATUS_SLEEP_ACCEPT &&
|
||||||
wnmsleep_ie.action_type == WNM_SLEEP_MODE_ENTER) {
|
wnmsleep_ie.action_type == WNM_SLEEP_MODE_ENTER) {
|
||||||
@ -201,7 +223,7 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
|
|||||||
}
|
}
|
||||||
/* when exiting wnmsleep
|
/* when exiting wnmsleep
|
||||||
* 1. unmark the node
|
* 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
|
* 3. unpause the node in driver
|
||||||
*/
|
*/
|
||||||
if ((wnmsleep_ie.status == WNM_STATUS_SLEEP_ACCEPT ||
|
if ((wnmsleep_ie.status == WNM_STATUS_SLEEP_ACCEPT ||
|
||||||
@ -221,6 +243,7 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
|
|||||||
|
|
||||||
#undef MAX_GTK_SUBELEM_LEN
|
#undef MAX_GTK_SUBELEM_LEN
|
||||||
#undef MAX_IGTK_SUBELEM_LEN
|
#undef MAX_IGTK_SUBELEM_LEN
|
||||||
|
#undef MAX_BIGTK_SUBELEM_LEN
|
||||||
fail:
|
fail:
|
||||||
os_free(wnmtfs_ie);
|
os_free(wnmtfs_ie);
|
||||||
os_free(oci_ie);
|
os_free(oci_ie);
|
||||||
@ -303,8 +326,9 @@ static void ieee802_11_rx_wnmsleep_req(struct hostapd_data *hapd,
|
|||||||
|
|
||||||
if (ocv_verify_tx_params(oci_ie, oci_ie_len, &ci,
|
if (ocv_verify_tx_params(oci_ie, oci_ie_len, &ci,
|
||||||
channel_width_to_int(ci.chanwidth),
|
channel_width_to_int(ci.chanwidth),
|
||||||
ci.seg1_idx) != 0) {
|
ci.seg1_idx) != OCI_SUCCESS) {
|
||||||
wpa_msg(hapd, MSG_WARNING, "WNM: %s", ocv_errorstr);
|
wpa_msg(hapd, MSG_WARNING, "WNM: OCV failed: %s",
|
||||||
|
ocv_errorstr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -508,6 +532,30 @@ 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)
|
||||||
|
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,
|
static void ieee802_11_rx_wnm_notification_req(struct hostapd_data *hapd,
|
||||||
const u8 *addr, const u8 *buf,
|
const u8 *addr, const u8 *buf,
|
||||||
size_t len)
|
size_t len)
|
||||||
@ -526,8 +574,14 @@ static void ieee802_11_rx_wnm_notification_req(struct hostapd_data *hapd,
|
|||||||
MAC2STR(addr), dialog_token, type);
|
MAC2STR(addr), dialog_token, type);
|
||||||
wpa_hexdump(MSG_MSGDUMP, "WNM: Notification Request subelements",
|
wpa_hexdump(MSG_MSGDUMP, "WNM: Notification Request subelements",
|
||||||
buf, len);
|
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);
|
mbo_ap_wnm_notification_req(hapd, addr, buf, len);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
1198
src/ap/wpa_auth.c
1198
src/ap/wpa_auth.c
File diff suppressed because it is too large
Load Diff
@ -169,7 +169,9 @@ struct ft_remote_r1kh {
|
|||||||
|
|
||||||
|
|
||||||
struct wpa_auth_config {
|
struct wpa_auth_config {
|
||||||
|
void *msg_ctx;
|
||||||
int wpa;
|
int wpa;
|
||||||
|
int extended_key_id;
|
||||||
int wpa_key_mgmt;
|
int wpa_key_mgmt;
|
||||||
int wpa_pairwise;
|
int wpa_pairwise;
|
||||||
int wpa_group;
|
int wpa_group;
|
||||||
@ -177,6 +179,7 @@ struct wpa_auth_config {
|
|||||||
int wpa_strict_rekey;
|
int wpa_strict_rekey;
|
||||||
int wpa_gmk_rekey;
|
int wpa_gmk_rekey;
|
||||||
int wpa_ptk_rekey;
|
int wpa_ptk_rekey;
|
||||||
|
int wpa_deny_ptk0_rekey;
|
||||||
u32 wpa_group_update_count;
|
u32 wpa_group_update_count;
|
||||||
u32 wpa_pairwise_update_count;
|
u32 wpa_pairwise_update_count;
|
||||||
int wpa_disable_eapol_key_retries;
|
int wpa_disable_eapol_key_retries;
|
||||||
@ -189,6 +192,7 @@ struct wpa_auth_config {
|
|||||||
int okc;
|
int okc;
|
||||||
int tx_status;
|
int tx_status;
|
||||||
enum mfp_options ieee80211w;
|
enum mfp_options ieee80211w;
|
||||||
|
int beacon_prot;
|
||||||
int group_mgmt_cipher;
|
int group_mgmt_cipher;
|
||||||
int sae_require_mfp;
|
int sae_require_mfp;
|
||||||
#ifdef CONFIG_OCV
|
#ifdef CONFIG_OCV
|
||||||
@ -220,13 +224,28 @@ struct wpa_auth_config {
|
|||||||
double corrupt_gtk_rekey_mic_probability;
|
double corrupt_gtk_rekey_mic_probability;
|
||||||
u8 own_ie_override[MAX_OWN_IE_OVERRIDE];
|
u8 own_ie_override[MAX_OWN_IE_OVERRIDE];
|
||||||
size_t own_ie_override_len;
|
size_t own_ie_override_len;
|
||||||
|
u8 rsne_override_eapol[MAX_OWN_IE_OVERRIDE];
|
||||||
|
size_t rsne_override_eapol_len;
|
||||||
u8 rsnxe_override_eapol[MAX_OWN_IE_OVERRIDE];
|
u8 rsnxe_override_eapol[MAX_OWN_IE_OVERRIDE];
|
||||||
size_t rsnxe_override_eapol_len;
|
size_t rsnxe_override_eapol_len;
|
||||||
|
u8 rsne_override_ft[MAX_OWN_IE_OVERRIDE];
|
||||||
|
size_t rsne_override_ft_len;
|
||||||
|
u8 rsnxe_override_ft[MAX_OWN_IE_OVERRIDE];
|
||||||
|
size_t rsnxe_override_ft_len;
|
||||||
u8 gtk_rsc_override[WPA_KEY_RSC_LEN];
|
u8 gtk_rsc_override[WPA_KEY_RSC_LEN];
|
||||||
u8 igtk_rsc_override[WPA_KEY_RSC_LEN];
|
u8 igtk_rsc_override[WPA_KEY_RSC_LEN];
|
||||||
|
unsigned int rsne_override_eapol_set:1;
|
||||||
|
unsigned int rsnxe_override_eapol_set:1;
|
||||||
|
unsigned int rsne_override_ft_set:1;
|
||||||
|
unsigned int rsnxe_override_ft_set:1;
|
||||||
unsigned int gtk_rsc_override_set:1;
|
unsigned int gtk_rsc_override_set:1;
|
||||||
unsigned int igtk_rsc_override_set:1;
|
unsigned int igtk_rsc_override_set:1;
|
||||||
|
int ft_rsnxe_used;
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
unsigned int oci_freq_override_eapol_m3;
|
||||||
|
unsigned int oci_freq_override_eapol_g1;
|
||||||
|
unsigned int oci_freq_override_ft_assoc;
|
||||||
|
unsigned int oci_freq_override_fils_assoc;
|
||||||
#ifdef CONFIG_P2P
|
#ifdef CONFIG_P2P
|
||||||
u8 ip_addr_go[4];
|
u8 ip_addr_go[4];
|
||||||
u8 ip_addr_mask[4];
|
u8 ip_addr_mask[4];
|
||||||
@ -238,7 +257,12 @@ struct wpa_auth_config {
|
|||||||
u8 fils_cache_id[FILS_CACHE_ID_LEN];
|
u8 fils_cache_id[FILS_CACHE_ID_LEN];
|
||||||
#endif /* CONFIG_FILS */
|
#endif /* CONFIG_FILS */
|
||||||
int sae_pwe;
|
int sae_pwe;
|
||||||
|
bool sae_pk;
|
||||||
int owe_ptk_workaround;
|
int owe_ptk_workaround;
|
||||||
|
u8 transition_disable;
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
int dpp_pfs;
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -285,6 +309,7 @@ struct wpa_auth_callbacks {
|
|||||||
int *bandwidth, int *seg1_idx);
|
int *bandwidth, int *seg1_idx);
|
||||||
#ifdef CONFIG_IEEE80211R_AP
|
#ifdef CONFIG_IEEE80211R_AP
|
||||||
struct wpa_state_machine * (*add_sta)(void *ctx, const u8 *sta_addr);
|
struct wpa_state_machine * (*add_sta)(void *ctx, const u8 *sta_addr);
|
||||||
|
int (*add_sta_ft)(void *ctx, const u8 *sta_addr);
|
||||||
int (*set_vlan)(void *ctx, const u8 *sta_addr,
|
int (*set_vlan)(void *ctx, const u8 *sta_addr,
|
||||||
struct vlan_description *vlan);
|
struct vlan_description *vlan);
|
||||||
int (*get_vlan)(void *ctx, const u8 *sta_addr,
|
int (*get_vlan)(void *ctx, const u8 *sta_addr,
|
||||||
@ -318,19 +343,21 @@ void wpa_deinit(struct wpa_authenticator *wpa_auth);
|
|||||||
int wpa_reconfig(struct wpa_authenticator *wpa_auth,
|
int wpa_reconfig(struct wpa_authenticator *wpa_auth,
|
||||||
struct wpa_auth_config *conf);
|
struct wpa_auth_config *conf);
|
||||||
|
|
||||||
enum {
|
enum wpa_validate_result {
|
||||||
WPA_IE_OK, WPA_INVALID_IE, WPA_INVALID_GROUP, WPA_INVALID_PAIRWISE,
|
WPA_IE_OK, WPA_INVALID_IE, WPA_INVALID_GROUP, WPA_INVALID_PAIRWISE,
|
||||||
WPA_INVALID_AKMP, WPA_NOT_ENABLED, WPA_ALLOC_FAIL,
|
WPA_INVALID_AKMP, WPA_NOT_ENABLED, WPA_ALLOC_FAIL,
|
||||||
WPA_MGMT_FRAME_PROTECTION_VIOLATION, WPA_INVALID_MGMT_GROUP_CIPHER,
|
WPA_MGMT_FRAME_PROTECTION_VIOLATION, WPA_INVALID_MGMT_GROUP_CIPHER,
|
||||||
WPA_INVALID_MDIE, WPA_INVALID_PROTO, WPA_INVALID_PMKID
|
WPA_INVALID_MDIE, WPA_INVALID_PROTO, WPA_INVALID_PMKID,
|
||||||
|
WPA_DENIED_OTHER_REASON
|
||||||
};
|
};
|
||||||
|
|
||||||
int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
enum wpa_validate_result
|
||||||
struct wpa_state_machine *sm, int freq,
|
wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
||||||
const u8 *wpa_ie, size_t wpa_ie_len,
|
struct wpa_state_machine *sm, int freq,
|
||||||
const u8 *rsnxe, size_t rsnxe_len,
|
const u8 *wpa_ie, size_t wpa_ie_len,
|
||||||
const u8 *mdie, size_t mdie_len,
|
const u8 *rsnxe, size_t rsnxe_len,
|
||||||
const u8 *owe_dh, size_t owe_dh_len);
|
const u8 *mdie, size_t mdie_len,
|
||||||
|
const u8 *owe_dh, size_t owe_dh_len);
|
||||||
int wpa_validate_osen(struct wpa_authenticator *wpa_auth,
|
int wpa_validate_osen(struct wpa_authenticator *wpa_auth,
|
||||||
struct wpa_state_machine *sm,
|
struct wpa_state_machine *sm,
|
||||||
const u8 *osen_ie, size_t osen_ie_len);
|
const u8 *osen_ie, size_t osen_ie_len);
|
||||||
@ -414,14 +441,15 @@ void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth,
|
|||||||
#ifdef CONFIG_IEEE80211R_AP
|
#ifdef CONFIG_IEEE80211R_AP
|
||||||
u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
|
u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
|
||||||
size_t max_len, int auth_alg,
|
size_t max_len, int auth_alg,
|
||||||
const u8 *req_ies, size_t req_ies_len);
|
const u8 *req_ies, size_t req_ies_len,
|
||||||
|
int omit_rsnxe);
|
||||||
void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid,
|
void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid,
|
||||||
u16 auth_transaction, const u8 *ies, size_t ies_len,
|
u16 auth_transaction, const u8 *ies, size_t ies_len,
|
||||||
void (*cb)(void *ctx, const u8 *dst, const u8 *bssid,
|
void (*cb)(void *ctx, const u8 *dst, const u8 *bssid,
|
||||||
u16 auth_transaction, u16 resp,
|
u16 auth_transaction, u16 resp,
|
||||||
const u8 *ies, size_t ies_len),
|
const u8 *ies, size_t ies_len),
|
||||||
void *ctx);
|
void *ctx);
|
||||||
u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
|
int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
|
||||||
size_t ies_len);
|
size_t ies_len);
|
||||||
int wpa_ft_action_rx(struct wpa_state_machine *sm, const u8 *data, size_t len);
|
int wpa_ft_action_rx(struct wpa_state_machine *sm, const u8 *data, size_t len);
|
||||||
int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr,
|
int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr,
|
||||||
@ -438,6 +466,7 @@ void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm);
|
|||||||
void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag);
|
void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag);
|
||||||
int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos);
|
int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos);
|
||||||
int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos);
|
int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos);
|
||||||
|
int wpa_wnmsleep_bigtk_subelem(struct wpa_state_machine *sm, u8 *pos);
|
||||||
|
|
||||||
int wpa_auth_uses_sae(struct wpa_state_machine *sm);
|
int wpa_auth_uses_sae(struct wpa_state_machine *sm);
|
||||||
int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm);
|
int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm);
|
||||||
@ -489,6 +518,8 @@ u8 * wpa_auth_write_assoc_resp_fils(struct wpa_state_machine *sm,
|
|||||||
const u8 *req_ies, size_t req_ies_len);
|
const u8 *req_ies, size_t req_ies_len);
|
||||||
void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg);
|
void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg);
|
||||||
void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z);
|
void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z);
|
||||||
|
void wpa_auth_set_transition_disable(struct wpa_authenticator *wpa_auth,
|
||||||
|
u8 val);
|
||||||
|
|
||||||
int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce,
|
int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce,
|
||||||
void (*cb)(void *ctx1, void *ctx2),
|
void (*cb)(void *ctx1, void *ctx2),
|
||||||
@ -502,5 +533,16 @@ int wpa_auth_resend_group_m1(struct wpa_state_machine *sm,
|
|||||||
int wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth);
|
int wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth);
|
||||||
int wpa_auth_rekey_ptk(struct wpa_state_machine *sm, int early_install);
|
int wpa_auth_rekey_ptk(struct wpa_state_machine *sm, int early_install);
|
||||||
void wpa_auth_set_ptk_rekey_timer(struct wpa_state_machine *sm);
|
void wpa_auth_set_ptk_rekey_timer(struct wpa_state_machine *sm);
|
||||||
|
void wpa_auth_set_ft_rsnxe_used(struct wpa_authenticator *wpa_auth, int val);
|
||||||
|
|
||||||
|
enum wpa_auth_ocv_override_frame {
|
||||||
|
WPA_AUTH_OCV_OVERRIDE_EAPOL_M3,
|
||||||
|
WPA_AUTH_OCV_OVERRIDE_EAPOL_G1,
|
||||||
|
WPA_AUTH_OCV_OVERRIDE_FT_ASSOC,
|
||||||
|
WPA_AUTH_OCV_OVERRIDE_FILS_ASSOC,
|
||||||
|
};
|
||||||
|
void wpa_auth_set_ocv_override_freq(struct wpa_authenticator *wpa_auth,
|
||||||
|
enum wpa_auth_ocv_override_frame frame,
|
||||||
|
unsigned int freq);
|
||||||
|
|
||||||
#endif /* WPA_AUTH_H */
|
#endif /* WPA_AUTH_H */
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "common/ieee802_11_defs.h"
|
#include "common/ieee802_11_defs.h"
|
||||||
#include "common/ieee802_11_common.h"
|
#include "common/ieee802_11_common.h"
|
||||||
#include "common/ocv.h"
|
#include "common/ocv.h"
|
||||||
|
#include "common/wpa_ctrl.h"
|
||||||
#include "drivers/driver.h"
|
#include "drivers/driver.h"
|
||||||
#include "crypto/aes.h"
|
#include "crypto/aes.h"
|
||||||
#include "crypto/aes_siv.h"
|
#include "crypto/aes_siv.h"
|
||||||
@ -808,7 +809,7 @@ int wpa_write_ftie(struct wpa_auth_config *conf, int use_sha384,
|
|||||||
const u8 *r0kh_id, size_t r0kh_id_len,
|
const u8 *r0kh_id, size_t r0kh_id_len,
|
||||||
const u8 *anonce, const u8 *snonce,
|
const u8 *anonce, const u8 *snonce,
|
||||||
u8 *buf, size_t len, const u8 *subelem,
|
u8 *buf, size_t len, const u8 *subelem,
|
||||||
size_t subelem_len)
|
size_t subelem_len, int rsnxe_used)
|
||||||
{
|
{
|
||||||
u8 *pos = buf, *ielen;
|
u8 *pos = buf, *ielen;
|
||||||
size_t hdrlen = use_sha384 ? sizeof(struct rsn_ftie_sha384) :
|
size_t hdrlen = use_sha384 ? sizeof(struct rsn_ftie_sha384) :
|
||||||
@ -826,7 +827,7 @@ int wpa_write_ftie(struct wpa_auth_config *conf, int use_sha384,
|
|||||||
|
|
||||||
os_memset(hdr, 0, sizeof(*hdr));
|
os_memset(hdr, 0, sizeof(*hdr));
|
||||||
pos += sizeof(*hdr);
|
pos += sizeof(*hdr);
|
||||||
WPA_PUT_LE16(hdr->mic_control, 0);
|
WPA_PUT_LE16(hdr->mic_control, !!rsnxe_used);
|
||||||
if (anonce)
|
if (anonce)
|
||||||
os_memcpy(hdr->anonce, anonce, WPA_NONCE_LEN);
|
os_memcpy(hdr->anonce, anonce, WPA_NONCE_LEN);
|
||||||
if (snonce)
|
if (snonce)
|
||||||
@ -836,7 +837,7 @@ int wpa_write_ftie(struct wpa_auth_config *conf, int use_sha384,
|
|||||||
|
|
||||||
os_memset(hdr, 0, sizeof(*hdr));
|
os_memset(hdr, 0, sizeof(*hdr));
|
||||||
pos += sizeof(*hdr);
|
pos += sizeof(*hdr);
|
||||||
WPA_PUT_LE16(hdr->mic_control, 0);
|
WPA_PUT_LE16(hdr->mic_control, !!rsnxe_used);
|
||||||
if (anonce)
|
if (anonce)
|
||||||
os_memcpy(hdr->anonce, anonce, WPA_NONCE_LEN);
|
os_memcpy(hdr->anonce, anonce, WPA_NONCE_LEN);
|
||||||
if (snonce)
|
if (snonce)
|
||||||
@ -1897,7 +1898,7 @@ static void wpa_ft_block_r0kh(struct wpa_authenticator *wpa_auth,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wpa_hexdump(MSG_DEBUG, "FT: Blacklist R0KH-ID",
|
wpa_hexdump(MSG_DEBUG, "FT: Temporarily block R0KH-ID",
|
||||||
f_r0kh_id, f_r0kh_id_len);
|
f_r0kh_id, f_r0kh_id_len);
|
||||||
|
|
||||||
if (r0kh) {
|
if (r0kh) {
|
||||||
@ -1985,7 +1986,7 @@ static int wpa_ft_pull_pmk_r1(struct wpa_state_machine *sm,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (is_zero_ether_addr(r0kh->addr)) {
|
if (is_zero_ether_addr(r0kh->addr)) {
|
||||||
wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID is blacklisted",
|
wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID is temporarily blocked",
|
||||||
sm->r0kh_id, sm->r0kh_id_len);
|
sm->r0kh_id, sm->r0kh_id_len);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -2128,8 +2129,6 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk)
|
|||||||
pmk_r0, pmk_r0_name,
|
pmk_r0, pmk_r0_name,
|
||||||
wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) < 0)
|
wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", pmk_r0, pmk_r0_len);
|
|
||||||
wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", pmk_r0_name, WPA_PMK_NAME_LEN);
|
|
||||||
if (!psk_local || !wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt))
|
if (!psk_local || !wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt))
|
||||||
wpa_ft_store_pmk_r0(sm->wpa_auth, sm->addr, pmk_r0, pmk_r0_len,
|
wpa_ft_store_pmk_r0(sm->wpa_auth, sm->addr, pmk_r0, pmk_r0_len,
|
||||||
pmk_r0_name,
|
pmk_r0_name,
|
||||||
@ -2140,9 +2139,6 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk)
|
|||||||
if (wpa_derive_pmk_r1(pmk_r0, pmk_r0_len, pmk_r0_name, r1kh, sm->addr,
|
if (wpa_derive_pmk_r1(pmk_r0, pmk_r0_len, pmk_r0_name, r1kh, sm->addr,
|
||||||
pmk_r1, sm->pmk_r1_name) < 0)
|
pmk_r1, sm->pmk_r1_name) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", pmk_r1, pmk_r1_len);
|
|
||||||
wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", sm->pmk_r1_name,
|
|
||||||
WPA_PMK_NAME_LEN);
|
|
||||||
if (!psk_local || !wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt))
|
if (!psk_local || !wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt))
|
||||||
wpa_ft_store_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1, pmk_r1_len,
|
wpa_ft_store_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1, pmk_r1_len,
|
||||||
sm->pmk_r1_name, sm->pairwise, &vlan,
|
sm->pmk_r1_name, sm->pairwise, &vlan,
|
||||||
@ -2167,11 +2163,12 @@ static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth,
|
|||||||
static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len)
|
static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len)
|
||||||
{
|
{
|
||||||
u8 *subelem;
|
u8 *subelem;
|
||||||
|
struct wpa_auth_config *conf = &sm->wpa_auth->conf;
|
||||||
struct wpa_group *gsm = sm->group;
|
struct wpa_group *gsm = sm->group;
|
||||||
size_t subelem_len, pad_len;
|
size_t subelem_len, pad_len;
|
||||||
const u8 *key;
|
const u8 *key;
|
||||||
size_t key_len;
|
size_t key_len;
|
||||||
u8 keybuf[32];
|
u8 keybuf[WPA_GTK_MAX_LEN];
|
||||||
const u8 *kek;
|
const u8 *kek;
|
||||||
size_t kek_len;
|
size_t kek_len;
|
||||||
|
|
||||||
@ -2198,12 +2195,30 @@ static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len)
|
|||||||
pad_len += 8;
|
pad_len += 8;
|
||||||
if (pad_len && key_len < sizeof(keybuf)) {
|
if (pad_len && key_len < sizeof(keybuf)) {
|
||||||
os_memcpy(keybuf, gsm->GTK[gsm->GN - 1], key_len);
|
os_memcpy(keybuf, gsm->GTK[gsm->GN - 1], key_len);
|
||||||
|
if (conf->disable_gtk ||
|
||||||
|
sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
|
||||||
|
/*
|
||||||
|
* Provide unique random GTK to each STA to prevent use
|
||||||
|
* of GTK in the BSS.
|
||||||
|
*/
|
||||||
|
if (random_get_bytes(keybuf, key_len) < 0)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
os_memset(keybuf + key_len, 0, pad_len);
|
os_memset(keybuf + key_len, 0, pad_len);
|
||||||
keybuf[key_len] = 0xdd;
|
keybuf[key_len] = 0xdd;
|
||||||
key_len += pad_len;
|
key_len += pad_len;
|
||||||
key = keybuf;
|
key = keybuf;
|
||||||
} else
|
} else if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
|
||||||
|
/*
|
||||||
|
* Provide unique random GTK to each STA to prevent use of GTK
|
||||||
|
* in the BSS.
|
||||||
|
*/
|
||||||
|
if (random_get_bytes(keybuf, key_len) < 0)
|
||||||
|
return NULL;
|
||||||
|
key = keybuf;
|
||||||
|
} else {
|
||||||
key = gsm->GTK[gsm->GN - 1];
|
key = gsm->GTK[gsm->GN - 1];
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] |
|
* Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] |
|
||||||
@ -2237,11 +2252,13 @@ static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len)
|
|||||||
static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len)
|
static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len)
|
||||||
{
|
{
|
||||||
u8 *subelem, *pos;
|
u8 *subelem, *pos;
|
||||||
|
struct wpa_auth_config *conf = &sm->wpa_auth->conf;
|
||||||
struct wpa_group *gsm = sm->group;
|
struct wpa_group *gsm = sm->group;
|
||||||
size_t subelem_len;
|
size_t subelem_len;
|
||||||
const u8 *kek;
|
const u8 *kek, *igtk;
|
||||||
size_t kek_len;
|
size_t kek_len;
|
||||||
size_t igtk_len;
|
size_t igtk_len;
|
||||||
|
u8 dummy_igtk[WPA_IGTK_MAX_LEN];
|
||||||
|
|
||||||
if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
|
if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
|
||||||
kek = sm->PTK.kek2;
|
kek = sm->PTK.kek2;
|
||||||
@ -2268,8 +2285,19 @@ static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len)
|
|||||||
wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos);
|
wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos);
|
||||||
pos += 6;
|
pos += 6;
|
||||||
*pos++ = igtk_len;
|
*pos++ = igtk_len;
|
||||||
if (aes_wrap(kek, kek_len, igtk_len / 8,
|
igtk = gsm->IGTK[gsm->GN_igtk - 4];
|
||||||
gsm->IGTK[gsm->GN_igtk - 4], pos)) {
|
if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
|
||||||
|
/*
|
||||||
|
* Provide unique random IGTK to each STA to prevent use of
|
||||||
|
* IGTK in the BSS.
|
||||||
|
*/
|
||||||
|
if (random_get_bytes(dummy_igtk, igtk_len / 8) < 0) {
|
||||||
|
os_free(subelem);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
igtk = dummy_igtk;
|
||||||
|
}
|
||||||
|
if (aes_wrap(kek, kek_len, igtk_len / 8, igtk, pos)) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"FT: IGTK subelem encryption failed: kek_len=%d",
|
"FT: IGTK subelem encryption failed: kek_len=%d",
|
||||||
(int) kek_len);
|
(int) kek_len);
|
||||||
@ -2282,6 +2310,66 @@ static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static u8 * wpa_ft_bigtk_subelem(struct wpa_state_machine *sm, size_t *len)
|
||||||
|
{
|
||||||
|
u8 *subelem, *pos;
|
||||||
|
struct wpa_group *gsm = sm->group;
|
||||||
|
size_t subelem_len;
|
||||||
|
const u8 *kek, *bigtk;
|
||||||
|
size_t kek_len;
|
||||||
|
size_t bigtk_len;
|
||||||
|
u8 dummy_bigtk[WPA_IGTK_MAX_LEN];
|
||||||
|
|
||||||
|
if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
|
||||||
|
kek = sm->PTK.kek2;
|
||||||
|
kek_len = sm->PTK.kek2_len;
|
||||||
|
} else {
|
||||||
|
kek = sm->PTK.kek;
|
||||||
|
kek_len = sm->PTK.kek_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
bigtk_len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
|
||||||
|
|
||||||
|
/* Sub-elem ID[1] | Length[1] | KeyID[2] | BIPN[6] | Key Length[1] |
|
||||||
|
* Key[16+8] */
|
||||||
|
subelem_len = 1 + 1 + 2 + 6 + 1 + bigtk_len + 8;
|
||||||
|
subelem = os_zalloc(subelem_len);
|
||||||
|
if (subelem == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
pos = subelem;
|
||||||
|
*pos++ = FTIE_SUBELEM_BIGTK;
|
||||||
|
*pos++ = subelem_len - 2;
|
||||||
|
WPA_PUT_LE16(pos, gsm->GN_bigtk);
|
||||||
|
pos += 2;
|
||||||
|
wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_bigtk, pos);
|
||||||
|
pos += 6;
|
||||||
|
*pos++ = bigtk_len;
|
||||||
|
bigtk = gsm->IGTK[gsm->GN_bigtk - 6];
|
||||||
|
if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
|
||||||
|
/*
|
||||||
|
* Provide unique random BIGTK to each OSEN STA to prevent use
|
||||||
|
* of BIGTK in the BSS.
|
||||||
|
*/
|
||||||
|
if (random_get_bytes(dummy_bigtk, bigtk_len / 8) < 0) {
|
||||||
|
os_free(subelem);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
bigtk = dummy_bigtk;
|
||||||
|
}
|
||||||
|
if (aes_wrap(kek, kek_len, bigtk_len / 8, bigtk, pos)) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"FT: BIGTK subelem encryption failed: kek_len=%d",
|
||||||
|
(int) kek_len);
|
||||||
|
os_free(subelem);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*len = subelem_len;
|
||||||
|
return subelem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static u8 * wpa_ft_process_rdie(struct wpa_state_machine *sm,
|
static u8 * wpa_ft_process_rdie(struct wpa_state_machine *sm,
|
||||||
u8 *pos, u8 *end, u8 id, u8 descr_count,
|
u8 *pos, u8 *end, u8 id, u8 descr_count,
|
||||||
const u8 *ies, size_t ies_len)
|
const u8 *ies, size_t ies_len)
|
||||||
@ -2415,13 +2503,15 @@ static u8 * wpa_ft_process_ric(struct wpa_state_machine *sm, u8 *pos, u8 *end,
|
|||||||
|
|
||||||
u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
|
u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
|
||||||
size_t max_len, int auth_alg,
|
size_t max_len, int auth_alg,
|
||||||
const u8 *req_ies, size_t req_ies_len)
|
const u8 *req_ies, size_t req_ies_len,
|
||||||
|
int omit_rsnxe)
|
||||||
{
|
{
|
||||||
u8 *end, *mdie, *ftie, *rsnie = NULL, *r0kh_id, *subelem = NULL;
|
u8 *end, *mdie, *ftie, *rsnie = NULL, *r0kh_id, *subelem = NULL;
|
||||||
u8 *fte_mic, *elem_count;
|
u8 *fte_mic, *elem_count;
|
||||||
size_t mdie_len, ftie_len, rsnie_len = 0, r0kh_id_len, subelem_len = 0;
|
size_t mdie_len, ftie_len, rsnie_len = 0, r0kh_id_len, subelem_len = 0;
|
||||||
u8 rsnxe[10];
|
u8 rsnxe_buf[10], *rsnxe = rsnxe_buf;
|
||||||
size_t rsnxe_len;
|
size_t rsnxe_len;
|
||||||
|
int rsnxe_used;
|
||||||
int res;
|
int res;
|
||||||
struct wpa_auth_config *conf;
|
struct wpa_auth_config *conf;
|
||||||
struct wpa_ft_ies parse;
|
struct wpa_ft_ies parse;
|
||||||
@ -2442,6 +2532,32 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
|
|||||||
|
|
||||||
end = pos + max_len;
|
end = pos + max_len;
|
||||||
|
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
if (auth_alg == WLAN_AUTH_FT &&
|
||||||
|
sm->wpa_auth->conf.rsne_override_ft_set) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"TESTING: RSNE FT override for MIC calculation");
|
||||||
|
rsnie = sm->wpa_auth->conf.rsne_override_ft;
|
||||||
|
rsnie_len = sm->wpa_auth->conf.rsne_override_ft_len;
|
||||||
|
if (end - pos < (long int) rsnie_len)
|
||||||
|
return pos;
|
||||||
|
os_memcpy(pos, rsnie, rsnie_len);
|
||||||
|
rsnie = pos;
|
||||||
|
pos += rsnie_len;
|
||||||
|
if (rsnie_len > PMKID_LEN && sm->pmk_r1_name_valid) {
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
/* Replace all 0xff PMKID with the valid PMKR1Name */
|
||||||
|
for (idx = 0; idx < PMKID_LEN; idx++) {
|
||||||
|
if (rsnie[rsnie_len - 1 - idx] != 0xff)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (idx == PMKID_LEN)
|
||||||
|
os_memcpy(&rsnie[rsnie_len - PMKID_LEN],
|
||||||
|
sm->pmk_r1_name, WPA_PMK_NAME_LEN);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
if (auth_alg == WLAN_AUTH_FT ||
|
if (auth_alg == WLAN_AUTH_FT ||
|
||||||
((auth_alg == WLAN_AUTH_FILS_SK ||
|
((auth_alg == WLAN_AUTH_FILS_SK ||
|
||||||
auth_alg == WLAN_AUTH_FILS_SK_PFS ||
|
auth_alg == WLAN_AUTH_FILS_SK_PFS ||
|
||||||
@ -2511,6 +2627,29 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
|
|||||||
subelem_len += igtk_len;
|
subelem_len += igtk_len;
|
||||||
os_free(igtk);
|
os_free(igtk);
|
||||||
}
|
}
|
||||||
|
if (sm->mgmt_frame_prot && conf->beacon_prot) {
|
||||||
|
u8 *bigtk;
|
||||||
|
size_t bigtk_len;
|
||||||
|
u8 *nbuf;
|
||||||
|
|
||||||
|
bigtk = wpa_ft_bigtk_subelem(sm, &bigtk_len);
|
||||||
|
if (!bigtk) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"FT: Failed to add BIGTK subelement");
|
||||||
|
os_free(subelem);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
nbuf = os_realloc(subelem, subelem_len + bigtk_len);
|
||||||
|
if (!nbuf) {
|
||||||
|
os_free(subelem);
|
||||||
|
os_free(bigtk);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
subelem = nbuf;
|
||||||
|
os_memcpy(subelem + subelem_len, bigtk, bigtk_len);
|
||||||
|
subelem_len += bigtk_len;
|
||||||
|
os_free(bigtk);
|
||||||
|
}
|
||||||
#ifdef CONFIG_OCV
|
#ifdef CONFIG_OCV
|
||||||
if (wpa_auth_uses_ocv(sm)) {
|
if (wpa_auth_uses_ocv(sm)) {
|
||||||
struct wpa_channel_info ci;
|
struct wpa_channel_info ci;
|
||||||
@ -2522,6 +2661,15 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
|
|||||||
os_free(subelem);
|
os_free(subelem);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
if (conf->oci_freq_override_ft_assoc) {
|
||||||
|
wpa_printf(MSG_INFO,
|
||||||
|
"TEST: Override OCI frequency %d -> %u MHz",
|
||||||
|
ci.frequency,
|
||||||
|
conf->oci_freq_override_ft_assoc);
|
||||||
|
ci.frequency = conf->oci_freq_override_ft_assoc;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
subelem_len += 2 + OCV_OCI_LEN;
|
subelem_len += 2 + OCV_OCI_LEN;
|
||||||
nbuf = os_realloc(subelem, subelem_len);
|
nbuf = os_realloc(subelem, subelem_len);
|
||||||
@ -2546,9 +2694,18 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
|
|||||||
anonce = NULL;
|
anonce = NULL;
|
||||||
snonce = NULL;
|
snonce = NULL;
|
||||||
}
|
}
|
||||||
|
rsnxe_used = (auth_alg == WLAN_AUTH_FT) &&
|
||||||
|
(conf->sae_pwe == 1 || conf->sae_pwe == 2);
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
if (sm->wpa_auth->conf.ft_rsnxe_used) {
|
||||||
|
rsnxe_used = sm->wpa_auth->conf.ft_rsnxe_used == 1;
|
||||||
|
wpa_printf(MSG_DEBUG, "TESTING: FT: Force RSNXE Used %d",
|
||||||
|
rsnxe_used);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
res = wpa_write_ftie(conf, use_sha384, r0kh_id, r0kh_id_len,
|
res = wpa_write_ftie(conf, use_sha384, r0kh_id, r0kh_id_len,
|
||||||
anonce, snonce, pos, end - pos,
|
anonce, snonce, pos, end - pos,
|
||||||
subelem, subelem_len);
|
subelem, subelem_len, rsnxe_used);
|
||||||
os_free(subelem);
|
os_free(subelem);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -2584,10 +2741,24 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
|
|||||||
if (ric_start == pos)
|
if (ric_start == pos)
|
||||||
ric_start = NULL;
|
ric_start = NULL;
|
||||||
|
|
||||||
res = wpa_write_rsnxe(&sm->wpa_auth->conf, rsnxe, sizeof(rsnxe));
|
if (omit_rsnxe) {
|
||||||
if (res < 0)
|
rsnxe_len = 0;
|
||||||
return NULL;
|
} else {
|
||||||
rsnxe_len = res;
|
res = wpa_write_rsnxe(&sm->wpa_auth->conf, rsnxe,
|
||||||
|
sizeof(rsnxe_buf));
|
||||||
|
if (res < 0)
|
||||||
|
return NULL;
|
||||||
|
rsnxe_len = res;
|
||||||
|
}
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
if (auth_alg == WLAN_AUTH_FT &&
|
||||||
|
sm->wpa_auth->conf.rsnxe_override_ft_set) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"TESTING: RSNXE FT override for MIC calculation");
|
||||||
|
rsnxe = sm->wpa_auth->conf.rsnxe_override_ft;
|
||||||
|
rsnxe_len = sm->wpa_auth->conf.rsnxe_override_ft_len;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
if (auth_alg == WLAN_AUTH_FT && rsnxe_len)
|
if (auth_alg == WLAN_AUTH_FT && rsnxe_len)
|
||||||
*elem_count += 1;
|
*elem_count += 1;
|
||||||
|
|
||||||
@ -2632,7 +2803,16 @@ static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void wpa_ft_install_ptk(struct wpa_state_machine *sm)
|
static inline int wpa_auth_add_sta_ft(struct wpa_authenticator *wpa_auth,
|
||||||
|
const u8 *addr)
|
||||||
|
{
|
||||||
|
if (!wpa_auth->cb->add_sta_ft)
|
||||||
|
return -1;
|
||||||
|
return wpa_auth->cb->add_sta_ft(wpa_auth->cb_ctx, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void wpa_ft_install_ptk(struct wpa_state_machine *sm, int retry)
|
||||||
{
|
{
|
||||||
enum wpa_alg alg;
|
enum wpa_alg alg;
|
||||||
int klen;
|
int klen;
|
||||||
@ -2654,19 +2834,22 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!retry)
|
||||||
|
wpa_auth_add_sta_ft(sm->wpa_auth, sm->addr);
|
||||||
|
|
||||||
/* FIX: add STA entry to kernel/driver here? The set_key will fail
|
/* FIX: add STA entry to kernel/driver here? The set_key will fail
|
||||||
* most likely without this.. At the moment, STA entry is added only
|
* most likely without this.. At the moment, STA entry is added only
|
||||||
* after association has been completed. This function will be called
|
* after association has been completed. This function will be called
|
||||||
* again after association to get the PTK configured, but that could be
|
* again after association to get the PTK configured, but that could be
|
||||||
* optimized by adding the STA entry earlier.
|
* optimized by adding the STA entry earlier.
|
||||||
*/
|
*/
|
||||||
if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0,
|
if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, sm->keyidx_active,
|
||||||
sm->PTK.tk, klen, KEY_FLAG_PAIRWISE_RX_TX))
|
sm->PTK.tk, klen, KEY_FLAG_PAIRWISE_RX_TX))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
|
/* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
|
||||||
sm->pairwise_set = TRUE;
|
sm->pairwise_set = true;
|
||||||
sm->tk_already_set = TRUE;
|
sm->tk_already_set = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2827,8 +3010,6 @@ static int wpa_ft_local_derive_pmk_r1(struct wpa_authenticator *wpa_auth,
|
|||||||
conf->r1_key_holder,
|
conf->r1_key_holder,
|
||||||
sm->addr, out_pmk_r1, pmk_r1_name) < 0)
|
sm->addr, out_pmk_r1, pmk_r1_name) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", out_pmk_r1, r0->pmk_r0_len);
|
|
||||||
wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN);
|
|
||||||
|
|
||||||
os_get_reltime(&now);
|
os_get_reltime(&now);
|
||||||
if (r0->expiration)
|
if (r0->expiration)
|
||||||
@ -2957,8 +3138,6 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm,
|
|||||||
sm->wpa_auth->conf.r1_key_holder, sm->addr,
|
sm->wpa_auth->conf.r1_key_holder, sm->addr,
|
||||||
pmk_r1_name, use_sha384) < 0)
|
pmk_r1_name, use_sha384) < 0)
|
||||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||||
wpa_hexdump(MSG_DEBUG, "FT: Derived requested PMKR1Name",
|
|
||||||
pmk_r1_name, WPA_PMK_NAME_LEN);
|
|
||||||
|
|
||||||
if (conf->ft_psk_generate_local &&
|
if (conf->ft_psk_generate_local &&
|
||||||
wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) {
|
wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) {
|
||||||
@ -3023,9 +3202,9 @@ pmk_r1_derived:
|
|||||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||||
|
|
||||||
sm->pairwise = pairwise;
|
sm->pairwise = pairwise;
|
||||||
sm->PTK_valid = TRUE;
|
sm->PTK_valid = true;
|
||||||
sm->tk_already_set = FALSE;
|
sm->tk_already_set = false;
|
||||||
wpa_ft_install_ptk(sm);
|
wpa_ft_install_ptk(sm, 0);
|
||||||
|
|
||||||
if (wpa_ft_set_vlan(sm->wpa_auth, sm->addr, &vlan) < 0) {
|
if (wpa_ft_set_vlan(sm->wpa_auth, sm->addr, &vlan) < 0) {
|
||||||
wpa_printf(MSG_DEBUG, "FT: Failed to configure VLAN");
|
wpa_printf(MSG_DEBUG, "FT: Failed to configure VLAN");
|
||||||
@ -3060,7 +3239,8 @@ pmk_r1_derived:
|
|||||||
pos += ret;
|
pos += ret;
|
||||||
|
|
||||||
ret = wpa_write_ftie(conf, use_sha384, parse.r0kh_id, parse.r0kh_id_len,
|
ret = wpa_write_ftie(conf, use_sha384, parse.r0kh_id, parse.r0kh_id_len,
|
||||||
sm->ANonce, sm->SNonce, pos, end - pos, NULL, 0);
|
sm->ANonce, sm->SNonce, pos, end - pos, NULL, 0,
|
||||||
|
0);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
pos += ret;
|
pos += ret;
|
||||||
@ -3119,7 +3299,7 @@ void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
|
int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
|
||||||
size_t ies_len)
|
size_t ies_len)
|
||||||
{
|
{
|
||||||
struct wpa_ft_ies parse;
|
struct wpa_ft_ies parse;
|
||||||
@ -3132,10 +3312,13 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
|
|||||||
int use_sha384;
|
int use_sha384;
|
||||||
const u8 *anonce, *snonce, *fte_mic;
|
const u8 *anonce, *snonce, *fte_mic;
|
||||||
u8 fte_elem_count;
|
u8 fte_elem_count;
|
||||||
|
int rsnxe_used;
|
||||||
|
struct wpa_auth_config *conf;
|
||||||
|
|
||||||
if (sm == NULL)
|
if (sm == NULL)
|
||||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||||
|
|
||||||
|
conf = &sm->wpa_auth->conf;
|
||||||
use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
|
use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
|
||||||
|
|
||||||
wpa_hexdump(MSG_DEBUG, "FT: Reassoc Req IEs", ies, ies_len);
|
wpa_hexdump(MSG_DEBUG, "FT: Reassoc Req IEs", ies, ies_len);
|
||||||
@ -3164,8 +3347,7 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
|
|||||||
|
|
||||||
mdie = (struct rsn_mdie *) parse.mdie;
|
mdie = (struct rsn_mdie *) parse.mdie;
|
||||||
if (mdie == NULL || parse.mdie_len < sizeof(*mdie) ||
|
if (mdie == NULL || parse.mdie_len < sizeof(*mdie) ||
|
||||||
os_memcmp(mdie->mobility_domain,
|
os_memcmp(mdie->mobility_domain, conf->mobility_domain,
|
||||||
sm->wpa_auth->conf.mobility_domain,
|
|
||||||
MOBILITY_DOMAIN_ID_LEN) != 0) {
|
MOBILITY_DOMAIN_ID_LEN) != 0) {
|
||||||
wpa_printf(MSG_DEBUG, "FT: Invalid MDIE");
|
wpa_printf(MSG_DEBUG, "FT: Invalid MDIE");
|
||||||
return WLAN_STATUS_INVALID_MDIE;
|
return WLAN_STATUS_INVALID_MDIE;
|
||||||
@ -3182,6 +3364,7 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
|
|||||||
|
|
||||||
anonce = ftie->anonce;
|
anonce = ftie->anonce;
|
||||||
snonce = ftie->snonce;
|
snonce = ftie->snonce;
|
||||||
|
rsnxe_used = ftie->mic_control[0] & 0x01;
|
||||||
fte_elem_count = ftie->mic_control[1];
|
fte_elem_count = ftie->mic_control[1];
|
||||||
fte_mic = ftie->mic;
|
fte_mic = ftie->mic;
|
||||||
} else {
|
} else {
|
||||||
@ -3195,6 +3378,7 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
|
|||||||
|
|
||||||
anonce = ftie->anonce;
|
anonce = ftie->anonce;
|
||||||
snonce = ftie->snonce;
|
snonce = ftie->snonce;
|
||||||
|
rsnxe_used = ftie->mic_control[0] & 0x01;
|
||||||
fte_elem_count = ftie->mic_control[1];
|
fte_elem_count = ftie->mic_control[1];
|
||||||
fte_mic = ftie->mic;
|
fte_mic = ftie->mic;
|
||||||
}
|
}
|
||||||
@ -3240,14 +3424,14 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
|
|||||||
return WLAN_STATUS_INVALID_FTIE;
|
return WLAN_STATUS_INVALID_FTIE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (os_memcmp_const(parse.r1kh_id, sm->wpa_auth->conf.r1_key_holder,
|
if (os_memcmp_const(parse.r1kh_id, conf->r1_key_holder,
|
||||||
FT_R1KH_ID_LEN) != 0) {
|
FT_R1KH_ID_LEN) != 0) {
|
||||||
wpa_printf(MSG_DEBUG, "FT: Unknown R1KH-ID used in "
|
wpa_printf(MSG_DEBUG, "FT: Unknown R1KH-ID used in "
|
||||||
"ReassocReq");
|
"ReassocReq");
|
||||||
wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID in FTIE",
|
wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID in FTIE",
|
||||||
parse.r1kh_id, FT_R1KH_ID_LEN);
|
parse.r1kh_id, FT_R1KH_ID_LEN);
|
||||||
wpa_hexdump(MSG_DEBUG, "FT: Expected R1KH-ID",
|
wpa_hexdump(MSG_DEBUG, "FT: Expected R1KH-ID",
|
||||||
sm->wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN);
|
conf->r1_key_holder, FT_R1KH_ID_LEN);
|
||||||
return WLAN_STATUS_INVALID_FTIE;
|
return WLAN_STATUS_INVALID_FTIE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3309,11 +3493,19 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
|
|||||||
return WLAN_STATUS_INVALID_FTIE;
|
return WLAN_STATUS_INVALID_FTIE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rsnxe_used && (conf->sae_pwe == 1 || conf->sae_pwe == 2) &&
|
||||||
|
!parse.rsnxe) {
|
||||||
|
wpa_printf(MSG_INFO,
|
||||||
|
"FT: FTE indicated that STA uses RSNXE, but RSNXE was not included");
|
||||||
|
return -1; /* discard request */
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_OCV
|
#ifdef CONFIG_OCV
|
||||||
if (wpa_auth_uses_ocv(sm)) {
|
if (wpa_auth_uses_ocv(sm)) {
|
||||||
struct wpa_channel_info ci;
|
struct wpa_channel_info ci;
|
||||||
int tx_chanwidth;
|
int tx_chanwidth;
|
||||||
int tx_seg1_idx;
|
int tx_seg1_idx;
|
||||||
|
enum oci_verify_result res;
|
||||||
|
|
||||||
if (wpa_channel_info(sm->wpa_auth, &ci) != 0) {
|
if (wpa_channel_info(sm->wpa_auth, &ci) != 0) {
|
||||||
wpa_printf(MSG_WARNING,
|
wpa_printf(MSG_WARNING,
|
||||||
@ -3327,10 +3519,21 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
|
|||||||
&tx_seg1_idx) < 0)
|
&tx_seg1_idx) < 0)
|
||||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||||
|
|
||||||
if (ocv_verify_tx_params(parse.oci, parse.oci_len, &ci,
|
res = ocv_verify_tx_params(parse.oci, parse.oci_len, &ci,
|
||||||
tx_chanwidth, tx_seg1_idx) != 0) {
|
tx_chanwidth, tx_seg1_idx);
|
||||||
wpa_printf(MSG_WARNING, "%s", ocv_errorstr);
|
if (wpa_auth_uses_ocv(sm) == 2 && res == OCI_NOT_FOUND) {
|
||||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
/* Work around misbehaving STAs */
|
||||||
|
wpa_printf(MSG_INFO,
|
||||||
|
"Disable OCV with a STA that does not send OCI");
|
||||||
|
wpa_auth_set_ocv(sm, 0);
|
||||||
|
} else if (res != OCI_SUCCESS) {
|
||||||
|
wpa_printf(MSG_WARNING, "OCV failed: %s", ocv_errorstr);
|
||||||
|
if (sm->wpa_auth->conf.msg_ctx)
|
||||||
|
wpa_msg(sm->wpa_auth->conf.msg_ctx, MSG_INFO,
|
||||||
|
OCV_FAILURE "addr=" MACSTR
|
||||||
|
" frame=ft-reassoc-req error=%s",
|
||||||
|
MAC2STR(sm->addr), ocv_errorstr);
|
||||||
|
return WLAN_STATUS_INVALID_FTIE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_OCV */
|
#endif /* CONFIG_OCV */
|
||||||
@ -3553,14 +3756,11 @@ static int wpa_ft_rrb_build_r0(const u8 *key, const size_t key_len,
|
|||||||
{ .type = FT_RRB_LAST_EMPTY, .len = 0, .data = NULL },
|
{ .type = FT_RRB_LAST_EMPTY, .len = 0, .data = NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "FT: Derive PMK-R1 for peer AP");
|
||||||
if (wpa_derive_pmk_r1(pmk_r0->pmk_r0, pmk_r0->pmk_r0_len,
|
if (wpa_derive_pmk_r1(pmk_r0->pmk_r0, pmk_r0->pmk_r0_len,
|
||||||
pmk_r0->pmk_r0_name, r1kh_id,
|
pmk_r0->pmk_r0_name, r1kh_id,
|
||||||
s1kh_id, pmk_r1, pmk_r1_name) < 0)
|
s1kh_id, pmk_r1, pmk_r1_name) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1 (for peer AP)",
|
|
||||||
pmk_r1, pmk_r1_len);
|
|
||||||
wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name (for peer AP)",
|
|
||||||
pmk_r1_name, WPA_PMK_NAME_LEN);
|
|
||||||
WPA_PUT_LE16(f_pairwise, pmk_r0->pairwise);
|
WPA_PUT_LE16(f_pairwise, pmk_r0->pairwise);
|
||||||
|
|
||||||
os_get_reltime(&now);
|
os_get_reltime(&now);
|
||||||
@ -4433,7 +4633,6 @@ int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
status_code = WPA_GET_LE16(pos);
|
status_code = WPA_GET_LE16(pos);
|
||||||
pos += 2;
|
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "FT: FT Packet Type - Response "
|
wpa_printf(MSG_DEBUG, "FT: FT Packet Type - Response "
|
||||||
"(status_code=%d)", status_code);
|
"(status_code=%d)", status_code);
|
||||||
@ -4446,11 +4645,6 @@ int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (end > pos) {
|
|
||||||
wpa_hexdump(MSG_DEBUG, "FT: Ignore extra data in end",
|
|
||||||
pos, end - pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
|
|||||||
|
|
||||||
os_memset(wconf, 0, sizeof(*wconf));
|
os_memset(wconf, 0, sizeof(*wconf));
|
||||||
wconf->wpa = conf->wpa;
|
wconf->wpa = conf->wpa;
|
||||||
|
wconf->extended_key_id = conf->extended_key_id;
|
||||||
wconf->wpa_key_mgmt = conf->wpa_key_mgmt;
|
wconf->wpa_key_mgmt = conf->wpa_key_mgmt;
|
||||||
wconf->wpa_pairwise = conf->wpa_pairwise;
|
wconf->wpa_pairwise = conf->wpa_pairwise;
|
||||||
wconf->wpa_group = conf->wpa_group;
|
wconf->wpa_group = conf->wpa_group;
|
||||||
@ -67,6 +68,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
|
|||||||
#endif /* CONFIG_OCV */
|
#endif /* CONFIG_OCV */
|
||||||
wconf->okc = conf->okc;
|
wconf->okc = conf->okc;
|
||||||
wconf->ieee80211w = conf->ieee80211w;
|
wconf->ieee80211w = conf->ieee80211w;
|
||||||
|
wconf->beacon_prot = conf->beacon_prot;
|
||||||
wconf->group_mgmt_cipher = conf->group_mgmt_cipher;
|
wconf->group_mgmt_cipher = conf->group_mgmt_cipher;
|
||||||
wconf->sae_require_mfp = conf->sae_require_mfp;
|
wconf->sae_require_mfp = conf->sae_require_mfp;
|
||||||
#ifdef CONFIG_IEEE80211R_AP
|
#ifdef CONFIG_IEEE80211R_AP
|
||||||
@ -120,14 +122,42 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
|
|||||||
wpabuf_head(conf->own_ie_override),
|
wpabuf_head(conf->own_ie_override),
|
||||||
wconf->own_ie_override_len);
|
wconf->own_ie_override_len);
|
||||||
}
|
}
|
||||||
|
if (conf->rsne_override_eapol &&
|
||||||
|
wpabuf_len(conf->rsne_override_eapol) <= MAX_OWN_IE_OVERRIDE) {
|
||||||
|
wconf->rsne_override_eapol_set = 1;
|
||||||
|
wconf->rsne_override_eapol_len =
|
||||||
|
wpabuf_len(conf->rsne_override_eapol);
|
||||||
|
os_memcpy(wconf->rsne_override_eapol,
|
||||||
|
wpabuf_head(conf->rsne_override_eapol),
|
||||||
|
wconf->rsne_override_eapol_len);
|
||||||
|
}
|
||||||
if (conf->rsnxe_override_eapol &&
|
if (conf->rsnxe_override_eapol &&
|
||||||
wpabuf_len(conf->rsnxe_override_eapol) <= MAX_OWN_IE_OVERRIDE) {
|
wpabuf_len(conf->rsnxe_override_eapol) <= MAX_OWN_IE_OVERRIDE) {
|
||||||
|
wconf->rsnxe_override_eapol_set = 1;
|
||||||
wconf->rsnxe_override_eapol_len =
|
wconf->rsnxe_override_eapol_len =
|
||||||
wpabuf_len(conf->rsnxe_override_eapol);
|
wpabuf_len(conf->rsnxe_override_eapol);
|
||||||
os_memcpy(wconf->rsnxe_override_eapol,
|
os_memcpy(wconf->rsnxe_override_eapol,
|
||||||
wpabuf_head(conf->rsnxe_override_eapol),
|
wpabuf_head(conf->rsnxe_override_eapol),
|
||||||
wconf->rsnxe_override_eapol_len);
|
wconf->rsnxe_override_eapol_len);
|
||||||
}
|
}
|
||||||
|
if (conf->rsne_override_ft &&
|
||||||
|
wpabuf_len(conf->rsne_override_ft) <= MAX_OWN_IE_OVERRIDE) {
|
||||||
|
wconf->rsne_override_ft_set = 1;
|
||||||
|
wconf->rsne_override_ft_len =
|
||||||
|
wpabuf_len(conf->rsne_override_ft);
|
||||||
|
os_memcpy(wconf->rsne_override_ft,
|
||||||
|
wpabuf_head(conf->rsne_override_ft),
|
||||||
|
wconf->rsne_override_ft_len);
|
||||||
|
}
|
||||||
|
if (conf->rsnxe_override_ft &&
|
||||||
|
wpabuf_len(conf->rsnxe_override_ft) <= MAX_OWN_IE_OVERRIDE) {
|
||||||
|
wconf->rsnxe_override_ft_set = 1;
|
||||||
|
wconf->rsnxe_override_ft_len =
|
||||||
|
wpabuf_len(conf->rsnxe_override_ft);
|
||||||
|
os_memcpy(wconf->rsnxe_override_ft,
|
||||||
|
wpabuf_head(conf->rsnxe_override_ft),
|
||||||
|
wconf->rsnxe_override_ft_len);
|
||||||
|
}
|
||||||
if (conf->gtk_rsc_override &&
|
if (conf->gtk_rsc_override &&
|
||||||
wpabuf_len(conf->gtk_rsc_override) > 0 &&
|
wpabuf_len(conf->gtk_rsc_override) > 0 &&
|
||||||
wpabuf_len(conf->gtk_rsc_override) <= WPA_KEY_RSC_LEN) {
|
wpabuf_len(conf->gtk_rsc_override) <= WPA_KEY_RSC_LEN) {
|
||||||
@ -144,6 +174,12 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
|
|||||||
wpabuf_len(conf->igtk_rsc_override));
|
wpabuf_len(conf->igtk_rsc_override));
|
||||||
wconf->igtk_rsc_override_set = 1;
|
wconf->igtk_rsc_override_set = 1;
|
||||||
}
|
}
|
||||||
|
wconf->ft_rsnxe_used = conf->ft_rsnxe_used;
|
||||||
|
wconf->oci_freq_override_eapol_m3 = conf->oci_freq_override_eapol_m3;
|
||||||
|
wconf->oci_freq_override_eapol_g1 = conf->oci_freq_override_eapol_g1;
|
||||||
|
wconf->oci_freq_override_ft_assoc = conf->oci_freq_override_ft_assoc;
|
||||||
|
wconf->oci_freq_override_fils_assoc =
|
||||||
|
conf->oci_freq_override_fils_assoc;
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
#ifdef CONFIG_P2P
|
#ifdef CONFIG_P2P
|
||||||
os_memcpy(wconf->ip_addr_go, conf->ip_addr_go, 4);
|
os_memcpy(wconf->ip_addr_go, conf->ip_addr_go, 4);
|
||||||
@ -162,9 +198,16 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
|
|||||||
wconf->sae_pwe = 1;
|
wconf->sae_pwe = 1;
|
||||||
else if (sae_pw_id == 1 && wconf->sae_pwe == 0)
|
else if (sae_pw_id == 1 && wconf->sae_pwe == 0)
|
||||||
wconf->sae_pwe = 2;
|
wconf->sae_pwe = 2;
|
||||||
|
#ifdef CONFIG_SAE_PK
|
||||||
|
wconf->sae_pk = hostapd_sae_pk_in_use(conf);
|
||||||
|
#endif /* CONFIG_SAE_PK */
|
||||||
#ifdef CONFIG_OWE
|
#ifdef CONFIG_OWE
|
||||||
wconf->owe_ptk_workaround = conf->owe_ptk_workaround;
|
wconf->owe_ptk_workaround = conf->owe_ptk_workaround;
|
||||||
#endif /* CONFIG_OWE */
|
#endif /* CONFIG_OWE */
|
||||||
|
wconf->transition_disable = conf->transition_disable;
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
wconf->dpp_pfs = conf->dpp_pfs;
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -242,16 +285,15 @@ static void hostapd_wpa_auth_set_eapol(void *ctx, const u8 *addr,
|
|||||||
break;
|
break;
|
||||||
case WPA_EAPOL_keyRun:
|
case WPA_EAPOL_keyRun:
|
||||||
if (sta->eapol_sm)
|
if (sta->eapol_sm)
|
||||||
sta->eapol_sm->keyRun = value ? TRUE : FALSE;
|
sta->eapol_sm->keyRun = value;
|
||||||
break;
|
break;
|
||||||
case WPA_EAPOL_keyAvailable:
|
case WPA_EAPOL_keyAvailable:
|
||||||
if (sta->eapol_sm)
|
if (sta->eapol_sm)
|
||||||
sta->eapol_sm->eap_if->eapKeyAvailable =
|
sta->eapol_sm->eap_if->eapKeyAvailable = value;
|
||||||
value ? TRUE : FALSE;
|
|
||||||
break;
|
break;
|
||||||
case WPA_EAPOL_keyDone:
|
case WPA_EAPOL_keyDone:
|
||||||
if (sta->eapol_sm)
|
if (sta->eapol_sm)
|
||||||
sta->eapol_sm->keyDone = value ? TRUE : FALSE;
|
sta->eapol_sm->keyDone = value;
|
||||||
break;
|
break;
|
||||||
case WPA_EAPOL_inc_EapolFramesTx:
|
case WPA_EAPOL_inc_EapolFramesTx:
|
||||||
if (sta->eapol_sm)
|
if (sta->eapol_sm)
|
||||||
@ -404,7 +446,11 @@ static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
if (addr && !is_broadcast_ether_addr(addr)) {
|
if (key_flag & KEY_FLAG_MODIFY) {
|
||||||
|
/* We are updating an already installed key. Don't overwrite
|
||||||
|
* the already stored key information with zeros.
|
||||||
|
*/
|
||||||
|
} else if (addr && !is_broadcast_ether_addr(addr)) {
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
|
|
||||||
sta = ap_get_sta(hapd, addr);
|
sta = ap_get_sta(hapd, addr);
|
||||||
@ -415,15 +461,23 @@ static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg,
|
|||||||
os_memcpy(sta->last_tk, key, key_len);
|
os_memcpy(sta->last_tk, key, key_len);
|
||||||
sta->last_tk_len = key_len;
|
sta->last_tk_len = key_len;
|
||||||
}
|
}
|
||||||
} else if (alg == WPA_ALG_IGTK ||
|
} else if (alg == WPA_ALG_BIP_CMAC_128 ||
|
||||||
alg == WPA_ALG_BIP_GMAC_128 ||
|
alg == WPA_ALG_BIP_GMAC_128 ||
|
||||||
alg == WPA_ALG_BIP_GMAC_256 ||
|
alg == WPA_ALG_BIP_GMAC_256 ||
|
||||||
alg == WPA_ALG_BIP_CMAC_256) {
|
alg == WPA_ALG_BIP_CMAC_256) {
|
||||||
hapd->last_igtk_alg = alg;
|
if (idx == 4 || idx == 5) {
|
||||||
hapd->last_igtk_key_idx = idx;
|
hapd->last_igtk_alg = alg;
|
||||||
if (key)
|
hapd->last_igtk_key_idx = idx;
|
||||||
os_memcpy(hapd->last_igtk, key, key_len);
|
if (key)
|
||||||
hapd->last_igtk_len = key_len;
|
os_memcpy(hapd->last_igtk, key, key_len);
|
||||||
|
hapd->last_igtk_len = key_len;
|
||||||
|
} else if (idx == 6 || idx == 7) {
|
||||||
|
hapd->last_bigtk_alg = alg;
|
||||||
|
hapd->last_bigtk_key_idx = idx;
|
||||||
|
if (key)
|
||||||
|
os_memcpy(hapd->last_bigtk, key, key_len);
|
||||||
|
hapd->last_bigtk_len = key_len;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
hapd->last_gtk_alg = alg;
|
hapd->last_gtk_alg = alg;
|
||||||
hapd->last_gtk_key_idx = idx;
|
hapd->last_gtk_key_idx = idx;
|
||||||
@ -1000,6 +1054,34 @@ hostapd_wpa_auth_add_sta(void *ctx, const u8 *sta_addr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int hostapd_wpa_auth_add_sta_ft(void *ctx, const u8 *sta_addr)
|
||||||
|
{
|
||||||
|
struct hostapd_data *hapd = ctx;
|
||||||
|
struct sta_info *sta;
|
||||||
|
|
||||||
|
sta = ap_get_sta(hapd, sta_addr);
|
||||||
|
if (!sta)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (FULL_AP_CLIENT_STATE_SUPP(hapd->iface->drv_flags) &&
|
||||||
|
(sta->flags & WLAN_STA_MFP) && ap_sta_is_authorized(sta) &&
|
||||||
|
!(hapd->conf->mesh & MESH_ENABLED) && !(sta->added_unassoc)) {
|
||||||
|
/* We could not do this in handle_auth() since there was a
|
||||||
|
* PMF-enabled association for the STA and the new
|
||||||
|
* authentication attempt was not yet fully processed. Now that
|
||||||
|
* we are ready to configure the TK to the driver,
|
||||||
|
* authentication has succeeded and we can clean up the driver
|
||||||
|
* STA entry to avoid issues with any maintained state from the
|
||||||
|
* previous association. */
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"FT: Remove and re-add driver STA entry after successful FT authentication");
|
||||||
|
return ap_sta_re_add(hapd, sta);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int hostapd_wpa_auth_set_vlan(void *ctx, const u8 *sta_addr,
|
static int hostapd_wpa_auth_set_vlan(void *ctx, const u8 *sta_addr,
|
||||||
struct vlan_description *vlan)
|
struct vlan_description *vlan)
|
||||||
{
|
{
|
||||||
@ -1361,6 +1443,7 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
|
|||||||
#ifdef CONFIG_IEEE80211R_AP
|
#ifdef CONFIG_IEEE80211R_AP
|
||||||
.send_ft_action = hostapd_wpa_auth_send_ft_action,
|
.send_ft_action = hostapd_wpa_auth_send_ft_action,
|
||||||
.add_sta = hostapd_wpa_auth_add_sta,
|
.add_sta = hostapd_wpa_auth_add_sta,
|
||||||
|
.add_sta_ft = hostapd_wpa_auth_add_sta_ft,
|
||||||
.add_tspec = hostapd_wpa_auth_add_tspec,
|
.add_tspec = hostapd_wpa_auth_add_tspec,
|
||||||
.set_vlan = hostapd_wpa_auth_set_vlan,
|
.set_vlan = hostapd_wpa_auth_set_vlan,
|
||||||
.get_vlan = hostapd_wpa_auth_get_vlan,
|
.get_vlan = hostapd_wpa_auth_get_vlan,
|
||||||
@ -1376,10 +1459,27 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
|
|||||||
size_t wpa_ie_len;
|
size_t wpa_ie_len;
|
||||||
|
|
||||||
hostapd_wpa_auth_conf(hapd->conf, hapd->iconf, &_conf);
|
hostapd_wpa_auth_conf(hapd->conf, hapd->iconf, &_conf);
|
||||||
|
_conf.msg_ctx = hapd->msg_ctx;
|
||||||
if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EAPOL_TX_STATUS)
|
if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EAPOL_TX_STATUS)
|
||||||
_conf.tx_status = 1;
|
_conf.tx_status = 1;
|
||||||
if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_MLME)
|
if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_MLME)
|
||||||
_conf.ap_mlme = 1;
|
_conf.ap_mlme = 1;
|
||||||
|
|
||||||
|
if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
|
||||||
|
(hapd->conf->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
|
||||||
|
(hapd->conf->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
|
||||||
|
!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
|
||||||
|
wpa_msg(hapd->msg_ctx, MSG_INFO,
|
||||||
|
"Disable PTK0 rekey support - replaced with disconnect");
|
||||||
|
_conf.wpa_deny_ptk0_rekey = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_conf.extended_key_id &&
|
||||||
|
(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID))
|
||||||
|
wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Extended Key ID supported");
|
||||||
|
else
|
||||||
|
_conf.extended_key_id = 0;
|
||||||
|
|
||||||
hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb, hapd);
|
hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb, hapd);
|
||||||
if (hapd->wpa_auth == NULL) {
|
if (hapd->wpa_auth == NULL) {
|
||||||
wpa_printf(MSG_ERROR, "WPA initialization failed.");
|
wpa_printf(MSG_ERROR, "WPA initialization failed.");
|
||||||
|
@ -40,20 +40,20 @@ struct wpa_state_machine {
|
|||||||
WPA_PTK_GROUP_KEYERROR
|
WPA_PTK_GROUP_KEYERROR
|
||||||
} wpa_ptk_group_state;
|
} wpa_ptk_group_state;
|
||||||
|
|
||||||
Boolean Init;
|
bool Init;
|
||||||
Boolean DeauthenticationRequest;
|
bool DeauthenticationRequest;
|
||||||
Boolean AuthenticationRequest;
|
bool AuthenticationRequest;
|
||||||
Boolean ReAuthenticationRequest;
|
bool ReAuthenticationRequest;
|
||||||
Boolean Disconnect;
|
bool Disconnect;
|
||||||
u16 disconnect_reason; /* specific reason code to use with Disconnect */
|
u16 disconnect_reason; /* specific reason code to use with Disconnect */
|
||||||
u32 TimeoutCtr;
|
u32 TimeoutCtr;
|
||||||
u32 GTimeoutCtr;
|
u32 GTimeoutCtr;
|
||||||
Boolean TimeoutEvt;
|
bool TimeoutEvt;
|
||||||
Boolean EAPOLKeyReceived;
|
bool EAPOLKeyReceived;
|
||||||
Boolean EAPOLKeyPairwise;
|
bool EAPOLKeyPairwise;
|
||||||
Boolean EAPOLKeyRequest;
|
bool EAPOLKeyRequest;
|
||||||
Boolean MICVerified;
|
bool MICVerified;
|
||||||
Boolean GUpdateStationKeys;
|
bool GUpdateStationKeys;
|
||||||
u8 ANonce[WPA_NONCE_LEN];
|
u8 ANonce[WPA_NONCE_LEN];
|
||||||
u8 SNonce[WPA_NONCE_LEN];
|
u8 SNonce[WPA_NONCE_LEN];
|
||||||
u8 alt_SNonce[WPA_NONCE_LEN];
|
u8 alt_SNonce[WPA_NONCE_LEN];
|
||||||
@ -62,20 +62,22 @@ struct wpa_state_machine {
|
|||||||
unsigned int pmk_len;
|
unsigned int pmk_len;
|
||||||
u8 pmkid[PMKID_LEN]; /* valid if pmkid_set == 1 */
|
u8 pmkid[PMKID_LEN]; /* valid if pmkid_set == 1 */
|
||||||
struct wpa_ptk PTK;
|
struct wpa_ptk PTK;
|
||||||
Boolean PTK_valid;
|
u8 keyidx_active;
|
||||||
Boolean pairwise_set;
|
bool use_ext_key_id;
|
||||||
Boolean tk_already_set;
|
bool PTK_valid;
|
||||||
|
bool pairwise_set;
|
||||||
|
bool tk_already_set;
|
||||||
int keycount;
|
int keycount;
|
||||||
Boolean Pair;
|
bool Pair;
|
||||||
struct wpa_key_replay_counter {
|
struct wpa_key_replay_counter {
|
||||||
u8 counter[WPA_REPLAY_COUNTER_LEN];
|
u8 counter[WPA_REPLAY_COUNTER_LEN];
|
||||||
Boolean valid;
|
bool valid;
|
||||||
} key_replay[RSNA_MAX_EAPOL_RETRIES],
|
} key_replay[RSNA_MAX_EAPOL_RETRIES],
|
||||||
prev_key_replay[RSNA_MAX_EAPOL_RETRIES];
|
prev_key_replay[RSNA_MAX_EAPOL_RETRIES];
|
||||||
Boolean PInitAKeys; /* WPA only, not in IEEE 802.11i */
|
bool PInitAKeys; /* WPA only, not in IEEE 802.11i */
|
||||||
Boolean PTKRequest; /* not in IEEE 802.11i state machine */
|
bool PTKRequest; /* not in IEEE 802.11i state machine */
|
||||||
Boolean has_GTK;
|
bool has_GTK;
|
||||||
Boolean PtkGroupInit; /* init request for PTK Group state machine */
|
bool PtkGroupInit; /* init request for PTK Group state machine */
|
||||||
|
|
||||||
u8 *last_rx_eapol_key; /* starting from IEEE 802.1X header */
|
u8 *last_rx_eapol_key; /* starting from IEEE 802.1X header */
|
||||||
size_t last_rx_eapol_key_len;
|
size_t last_rx_eapol_key_len;
|
||||||
@ -94,8 +96,9 @@ struct wpa_state_machine {
|
|||||||
#endif /* CONFIG_IEEE80211R_AP */
|
#endif /* CONFIG_IEEE80211R_AP */
|
||||||
unsigned int is_wnmsleep:1;
|
unsigned int is_wnmsleep:1;
|
||||||
unsigned int pmkid_set:1;
|
unsigned int pmkid_set:1;
|
||||||
|
|
||||||
#ifdef CONFIG_OCV
|
#ifdef CONFIG_OCV
|
||||||
unsigned int ocv_enabled:1;
|
int ocv_enabled;
|
||||||
#endif /* CONFIG_OCV */
|
#endif /* CONFIG_OCV */
|
||||||
|
|
||||||
u8 req_replay_counter[WPA_REPLAY_COUNTER_LEN];
|
u8 req_replay_counter[WPA_REPLAY_COUNTER_LEN];
|
||||||
@ -174,12 +177,12 @@ struct wpa_group {
|
|||||||
struct wpa_group *next;
|
struct wpa_group *next;
|
||||||
int vlan_id;
|
int vlan_id;
|
||||||
|
|
||||||
Boolean GInit;
|
bool GInit;
|
||||||
int GKeyDoneStations;
|
int GKeyDoneStations;
|
||||||
Boolean GTKReKey;
|
bool GTKReKey;
|
||||||
int GTK_len;
|
int GTK_len;
|
||||||
int GN, GM;
|
int GN, GM;
|
||||||
Boolean GTKAuthenticator;
|
bool GTKAuthenticator;
|
||||||
u8 Counter[WPA_NONCE_LEN];
|
u8 Counter[WPA_NONCE_LEN];
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -191,11 +194,13 @@ struct wpa_group {
|
|||||||
u8 GMK[WPA_GMK_LEN];
|
u8 GMK[WPA_GMK_LEN];
|
||||||
u8 GTK[2][WPA_GTK_MAX_LEN];
|
u8 GTK[2][WPA_GTK_MAX_LEN];
|
||||||
u8 GNonce[WPA_NONCE_LEN];
|
u8 GNonce[WPA_NONCE_LEN];
|
||||||
Boolean changed;
|
bool changed;
|
||||||
Boolean first_sta_seen;
|
bool first_sta_seen;
|
||||||
Boolean reject_4way_hs_for_entropy;
|
bool reject_4way_hs_for_entropy;
|
||||||
u8 IGTK[2][WPA_IGTK_MAX_LEN];
|
u8 IGTK[2][WPA_IGTK_MAX_LEN];
|
||||||
|
u8 BIGTK[2][WPA_IGTK_MAX_LEN];
|
||||||
int GN_igtk, GM_igtk;
|
int GN_igtk, GM_igtk;
|
||||||
|
int GN_bigtk, GM_bigtk;
|
||||||
/* Number of references except those in struct wpa_group->next */
|
/* Number of references except those in struct wpa_group->next */
|
||||||
unsigned int references;
|
unsigned int references;
|
||||||
unsigned int num_setup_iface;
|
unsigned int num_setup_iface;
|
||||||
@ -275,7 +280,8 @@ int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len);
|
|||||||
void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr,
|
void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr,
|
||||||
logger_level level, const char *txt);
|
logger_level level, const char *txt);
|
||||||
void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr,
|
void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr,
|
||||||
logger_level level, const char *fmt, ...);
|
logger_level level, const char *fmt, ...)
|
||||||
|
PRINTF_FORMAT(4, 5);
|
||||||
void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
|
void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
|
||||||
struct wpa_state_machine *sm, int key_info,
|
struct wpa_state_machine *sm, int key_info,
|
||||||
const u8 *key_rsc, const u8 *nonce,
|
const u8 *key_rsc, const u8 *nonce,
|
||||||
@ -294,11 +300,11 @@ int wpa_write_ftie(struct wpa_auth_config *conf, int use_sha384,
|
|||||||
const u8 *r0kh_id, size_t r0kh_id_len,
|
const u8 *r0kh_id, size_t r0kh_id_len,
|
||||||
const u8 *anonce, const u8 *snonce,
|
const u8 *anonce, const u8 *snonce,
|
||||||
u8 *buf, size_t len, const u8 *subelem,
|
u8 *buf, size_t len, const u8 *subelem,
|
||||||
size_t subelem_len);
|
size_t subelem_len, int rsnxe_used);
|
||||||
int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk);
|
int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk);
|
||||||
struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void);
|
struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void);
|
||||||
void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache);
|
void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache);
|
||||||
void wpa_ft_install_ptk(struct wpa_state_machine *sm);
|
void wpa_ft_install_ptk(struct wpa_state_machine *sm, int retry);
|
||||||
int wpa_ft_store_pmk_fils(struct wpa_state_machine *sm, const u8 *pmk_r0,
|
int wpa_ft_store_pmk_fils(struct wpa_state_machine *sm, const u8 *pmk_r0,
|
||||||
const u8 *pmk_r0_name);
|
const u8 *pmk_r0_name);
|
||||||
#endif /* CONFIG_IEEE80211R_AP */
|
#endif /* CONFIG_IEEE80211R_AP */
|
||||||
|
@ -297,6 +297,8 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
|||||||
if (rsn_testing)
|
if (rsn_testing)
|
||||||
capab |= BIT(8) | BIT(15);
|
capab |= BIT(8) | BIT(15);
|
||||||
#endif /* CONFIG_RSN_TESTING */
|
#endif /* CONFIG_RSN_TESTING */
|
||||||
|
if (conf->extended_key_id)
|
||||||
|
capab |= WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST;
|
||||||
WPA_PUT_LE16(pos, capab);
|
WPA_PUT_LE16(pos, capab);
|
||||||
pos += 2;
|
pos += 2;
|
||||||
|
|
||||||
@ -376,7 +378,7 @@ int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len)
|
|||||||
{
|
{
|
||||||
u8 *pos = buf;
|
u8 *pos = buf;
|
||||||
|
|
||||||
if (conf->sae_pwe != 1 && conf->sae_pwe != 2)
|
if (conf->sae_pwe != 1 && conf->sae_pwe != 2 && !conf->sae_pk)
|
||||||
return 0; /* no supported extended RSN capabilities */
|
return 0; /* no supported extended RSN capabilities */
|
||||||
|
|
||||||
if (len < 3)
|
if (len < 3)
|
||||||
@ -386,7 +388,12 @@ int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len)
|
|||||||
*pos++ = 1;
|
*pos++ = 1;
|
||||||
/* bits 0-3 = 0 since only one octet of Extended RSN Capabilities is
|
/* bits 0-3 = 0 since only one octet of Extended RSN Capabilities is
|
||||||
* used for now */
|
* used for now */
|
||||||
*pos++ = BIT(WLAN_RSNX_CAPAB_SAE_H2E);
|
*pos = BIT(WLAN_RSNX_CAPAB_SAE_H2E);
|
||||||
|
#ifdef CONFIG_SAE_PK
|
||||||
|
if (conf->sae_pk)
|
||||||
|
*pos |= BIT(WLAN_RSNX_CAPAB_SAE_PK);
|
||||||
|
#endif /* CONFIG_SAE_PK */
|
||||||
|
pos++;
|
||||||
|
|
||||||
return pos - buf;
|
return pos - buf;
|
||||||
}
|
}
|
||||||
@ -546,13 +553,15 @@ static int wpa_auth_okc_iter(struct wpa_authenticator *a, void *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
enum wpa_validate_result
|
||||||
struct wpa_state_machine *sm, int freq,
|
wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
||||||
const u8 *wpa_ie, size_t wpa_ie_len,
|
struct wpa_state_machine *sm, int freq,
|
||||||
const u8 *rsnxe, size_t rsnxe_len,
|
const u8 *wpa_ie, size_t wpa_ie_len,
|
||||||
const u8 *mdie, size_t mdie_len,
|
const u8 *rsnxe, size_t rsnxe_len,
|
||||||
const u8 *owe_dh, size_t owe_dh_len)
|
const u8 *mdie, size_t mdie_len,
|
||||||
|
const u8 *owe_dh, size_t owe_dh_len)
|
||||||
{
|
{
|
||||||
|
struct wpa_auth_config *conf = &wpa_auth->conf;
|
||||||
struct wpa_ie_data data;
|
struct wpa_ie_data data;
|
||||||
int ciphers, key_mgmt, res, version;
|
int ciphers, key_mgmt, res, version;
|
||||||
u32 selector;
|
u32 selector;
|
||||||
@ -799,14 +808,26 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
|||||||
#endif /* CONFIG_SAE */
|
#endif /* CONFIG_SAE */
|
||||||
|
|
||||||
#ifdef CONFIG_OCV
|
#ifdef CONFIG_OCV
|
||||||
if ((data.capabilities & WPA_CAPABILITY_OCVC) &&
|
if (wpa_auth->conf.ocv && (data.capabilities & WPA_CAPABILITY_OCVC) &&
|
||||||
!(data.capabilities & WPA_CAPABILITY_MFPC)) {
|
!(data.capabilities & WPA_CAPABILITY_MFPC)) {
|
||||||
wpa_printf(MSG_DEBUG,
|
/* Some legacy MFP incapable STAs wrongly copy OCVC bit from
|
||||||
"Management frame protection required with OCV, but client did not enable it");
|
* AP RSN capabilities. To improve interoperability with such
|
||||||
return WPA_MGMT_FRAME_PROTECTION_VIOLATION;
|
* legacy STAs allow connection without enabling OCV when the
|
||||||
|
* workaround mode (ocv=2) is enabled.
|
||||||
|
*/
|
||||||
|
if (wpa_auth->conf.ocv == 2) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"Allow connecting MFP incapable and OCV capable STA without enabling OCV");
|
||||||
|
wpa_auth_set_ocv(sm, 0);
|
||||||
|
} else {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"Management frame protection required with OCV, but client did not enable it");
|
||||||
|
return WPA_MGMT_FRAME_PROTECTION_VIOLATION;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
wpa_auth_set_ocv(sm, (data.capabilities & WPA_CAPABILITY_OCVC) ?
|
||||||
|
wpa_auth->conf.ocv : 0);
|
||||||
}
|
}
|
||||||
wpa_auth_set_ocv(sm, wpa_auth->conf.ocv &&
|
|
||||||
(data.capabilities & WPA_CAPABILITY_OCVC));
|
|
||||||
#endif /* CONFIG_OCV */
|
#endif /* CONFIG_OCV */
|
||||||
|
|
||||||
if (wpa_auth->conf.ieee80211w == NO_MGMT_FRAME_PROTECTION ||
|
if (wpa_auth->conf.ieee80211w == NO_MGMT_FRAME_PROTECTION ||
|
||||||
@ -847,19 +868,18 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
|||||||
"OWE: No Diffie-Hellman Parameter element");
|
"OWE: No Diffie-Hellman Parameter element");
|
||||||
return WPA_INVALID_AKMP;
|
return WPA_INVALID_AKMP;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_DPP
|
|
||||||
if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && owe_dh) {
|
|
||||||
/* Diffie-Hellman Parameter element can be used with DPP as
|
|
||||||
* well, so allow this to proceed. */
|
|
||||||
} else
|
|
||||||
#endif /* CONFIG_DPP */
|
|
||||||
if (sm->wpa_key_mgmt != WPA_KEY_MGMT_OWE && owe_dh) {
|
|
||||||
wpa_printf(MSG_DEBUG,
|
|
||||||
"OWE: Unexpected Diffie-Hellman Parameter element with non-OWE AKM");
|
|
||||||
return WPA_INVALID_AKMP;
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_OWE */
|
#endif /* CONFIG_OWE */
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP &&
|
||||||
|
((conf->dpp_pfs == 1 && !owe_dh) ||
|
||||||
|
(conf->dpp_pfs == 2 && owe_dh))) {
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: PFS %s",
|
||||||
|
conf->dpp_pfs == 1 ? "required" : "not allowed");
|
||||||
|
return WPA_DENIED_OTHER_REASON;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
sm->pairwise = wpa_pick_pairwise_cipher(ciphers, 0);
|
sm->pairwise = wpa_pick_pairwise_cipher(ciphers, 0);
|
||||||
if (sm->pairwise < 0)
|
if (sm->pairwise < 0)
|
||||||
return WPA_INVALID_PAIRWISE;
|
return WPA_INVALID_PAIRWISE;
|
||||||
@ -944,6 +964,23 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_DPP */
|
#endif /* CONFIG_DPP */
|
||||||
|
|
||||||
|
if (conf->extended_key_id && sm->wpa == WPA_VERSION_WPA2 &&
|
||||||
|
sm->pairwise != WPA_CIPHER_TKIP &&
|
||||||
|
(data.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST)) {
|
||||||
|
sm->use_ext_key_id = true;
|
||||||
|
if (conf->extended_key_id == 2 &&
|
||||||
|
!wpa_key_mgmt_ft(sm->wpa_key_mgmt) &&
|
||||||
|
!wpa_key_mgmt_fils(sm->wpa_key_mgmt))
|
||||||
|
sm->keyidx_active = 1;
|
||||||
|
else
|
||||||
|
sm->keyidx_active = 0;
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"RSN: Extended Key ID supported (start with %d)",
|
||||||
|
sm->keyidx_active);
|
||||||
|
} else {
|
||||||
|
sm->use_ext_key_id = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (sm->wpa_ie == NULL || sm->wpa_ie_len < wpa_ie_len) {
|
if (sm->wpa_ie == NULL || sm->wpa_ie_len < wpa_ie_len) {
|
||||||
os_free(sm->wpa_ie);
|
os_free(sm->wpa_ie);
|
||||||
sm->wpa_ie = os_malloc(wpa_ie_len);
|
sm->wpa_ie = os_malloc(wpa_ie_len);
|
||||||
|
@ -52,7 +52,7 @@ static int hapd_macsec_get_capability(void *priv, enum macsec_cap *cap)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int hapd_enable_protect_frames(void *priv, Boolean enabled)
|
static int hapd_enable_protect_frames(void *priv, bool enabled)
|
||||||
{
|
{
|
||||||
struct hostapd_data *hapd = priv;
|
struct hostapd_data *hapd = priv;
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ static int hapd_enable_protect_frames(void *priv, Boolean enabled)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int hapd_enable_encrypt(void *priv, Boolean enabled)
|
static int hapd_enable_encrypt(void *priv, bool enabled)
|
||||||
{
|
{
|
||||||
struct hostapd_data *hapd = priv;
|
struct hostapd_data *hapd = priv;
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ static int hapd_enable_encrypt(void *priv, Boolean enabled)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int hapd_set_replay_protect(void *priv, Boolean enabled, u32 window)
|
static int hapd_set_replay_protect(void *priv, bool enabled, u32 window)
|
||||||
{
|
{
|
||||||
struct hostapd_data *hapd = priv;
|
struct hostapd_data *hapd = priv;
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ static int hapd_set_current_cipher_suite(void *priv, u64 cs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int hapd_enable_controlled_port(void *priv, Boolean enabled)
|
static int hapd_enable_controlled_port(void *priv, bool enabled)
|
||||||
{
|
{
|
||||||
struct hostapd_data *hapd = priv;
|
struct hostapd_data *hapd = priv;
|
||||||
|
|
||||||
@ -465,7 +465,7 @@ void * ieee802_1x_notify_create_actor_hapd(struct hostapd_data *hapd,
|
|||||||
wpa_hexdump(MSG_DEBUG, "Derived CKN", ckn->name, ckn->len);
|
wpa_hexdump(MSG_DEBUG, "Derived CKN", ckn->name, ckn->len);
|
||||||
|
|
||||||
res = ieee802_1x_kay_create_mka(hapd->kay, ckn, cak, 0, EAP_EXCHANGE,
|
res = ieee802_1x_kay_create_mka(hapd->kay, ckn, cak, 0, EAP_EXCHANGE,
|
||||||
TRUE);
|
true);
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
bin_clear_free(msk, sizeof(*msk));
|
bin_clear_free(msk, sizeof(*msk));
|
||||||
@ -507,7 +507,7 @@ void * ieee802_1x_create_preshared_mka_hapd(struct hostapd_data *hapd,
|
|||||||
ckn->len = hapd->conf->mka_ckn_len;;
|
ckn->len = hapd->conf->mka_ckn_len;;
|
||||||
os_memcpy(ckn->name, hapd->conf->mka_ckn, ckn->len);
|
os_memcpy(ckn->name, hapd->conf->mka_ckn, ckn->len);
|
||||||
|
|
||||||
res = ieee802_1x_kay_create_mka(hapd->kay, ckn, cak, 0, PSK, TRUE);
|
res = ieee802_1x_kay_create_mka(hapd->kay, ckn, cak, 0, PSK, true);
|
||||||
if (res)
|
if (res)
|
||||||
goto free_cak;
|
goto free_cak;
|
||||||
|
|
||||||
|
@ -125,6 +125,7 @@ static int hostapd_wps_new_psk_cb(void *ctx, const u8 *mac_addr,
|
|||||||
os_memcpy(p->addr, mac_addr, ETH_ALEN);
|
os_memcpy(p->addr, mac_addr, ETH_ALEN);
|
||||||
os_memcpy(p->p2p_dev_addr, p2p_dev_addr, ETH_ALEN);
|
os_memcpy(p->p2p_dev_addr, p2p_dev_addr, ETH_ALEN);
|
||||||
os_memcpy(p->psk, psk, PMK_LEN);
|
os_memcpy(p->psk, psk, PMK_LEN);
|
||||||
|
p->wps = 1;
|
||||||
|
|
||||||
if (hapd->new_psk_cb) {
|
if (hapd->new_psk_cb) {
|
||||||
hapd->new_psk_cb(hapd->new_psk_cb_ctx, mac_addr, p2p_dev_addr,
|
hapd->new_psk_cb(hapd->new_psk_cb_ctx, mac_addr, p2p_dev_addr,
|
||||||
@ -363,6 +364,13 @@ static int hapd_wps_reconfig_in_memory(struct hostapd_data *hapd,
|
|||||||
bss->ssid.ssid_set = 1;
|
bss->ssid.ssid_set = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_NO_TKIP
|
||||||
|
if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK |
|
||||||
|
WPS_AUTH_WPA | WPS_AUTH_WPAPSK))
|
||||||
|
bss->wpa = 2;
|
||||||
|
else
|
||||||
|
bss->wpa = 0;
|
||||||
|
#else /* CONFIG_NO_TKIP */
|
||||||
if ((cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK)) &&
|
if ((cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK)) &&
|
||||||
(cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK)))
|
(cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK)))
|
||||||
bss->wpa = 3;
|
bss->wpa = 3;
|
||||||
@ -372,6 +380,7 @@ static int hapd_wps_reconfig_in_memory(struct hostapd_data *hapd,
|
|||||||
bss->wpa = 1;
|
bss->wpa = 1;
|
||||||
else
|
else
|
||||||
bss->wpa = 0;
|
bss->wpa = 0;
|
||||||
|
#endif /* CONFIG_NO_TKIP */
|
||||||
|
|
||||||
if (bss->wpa) {
|
if (bss->wpa) {
|
||||||
if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA))
|
if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA))
|
||||||
@ -386,8 +395,10 @@ static int hapd_wps_reconfig_in_memory(struct hostapd_data *hapd,
|
|||||||
else
|
else
|
||||||
bss->wpa_pairwise |= WPA_CIPHER_CCMP;
|
bss->wpa_pairwise |= WPA_CIPHER_CCMP;
|
||||||
}
|
}
|
||||||
|
#ifndef CONFIG_NO_TKIP
|
||||||
if (cred->encr_type & WPS_ENCR_TKIP)
|
if (cred->encr_type & WPS_ENCR_TKIP)
|
||||||
bss->wpa_pairwise |= WPA_CIPHER_TKIP;
|
bss->wpa_pairwise |= WPA_CIPHER_TKIP;
|
||||||
|
#endif /* CONFIG_NO_TKIP */
|
||||||
bss->rsn_pairwise = bss->wpa_pairwise;
|
bss->rsn_pairwise = bss->wpa_pairwise;
|
||||||
bss->wpa_group = wpa_select_ap_group_cipher(bss->wpa,
|
bss->wpa_group = wpa_select_ap_group_cipher(bss->wpa,
|
||||||
bss->wpa_pairwise,
|
bss->wpa_pairwise,
|
||||||
@ -558,6 +569,13 @@ static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx)
|
|||||||
fprintf(nconf, "\n");
|
fprintf(nconf, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_NO_TKIP
|
||||||
|
if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK |
|
||||||
|
WPS_AUTH_WPA | WPS_AUTH_WPAPSK))
|
||||||
|
wpa = 2;
|
||||||
|
else
|
||||||
|
wpa = 0;
|
||||||
|
#else /* CONFIG_NO_TKIP */
|
||||||
if ((cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK)) &&
|
if ((cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK)) &&
|
||||||
(cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK)))
|
(cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK)))
|
||||||
wpa = 3;
|
wpa = 3;
|
||||||
@ -567,6 +585,7 @@ static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx)
|
|||||||
wpa = 1;
|
wpa = 1;
|
||||||
else
|
else
|
||||||
wpa = 0;
|
wpa = 0;
|
||||||
|
#endif /* CONFIG_NO_TKIP */
|
||||||
|
|
||||||
if (wpa) {
|
if (wpa) {
|
||||||
char *prefix;
|
char *prefix;
|
||||||
@ -610,9 +629,11 @@ static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx)
|
|||||||
|
|
||||||
prefix = " ";
|
prefix = " ";
|
||||||
}
|
}
|
||||||
|
#ifndef CONFIG_NO_TKIP
|
||||||
if (cred->encr_type & WPS_ENCR_TKIP) {
|
if (cred->encr_type & WPS_ENCR_TKIP) {
|
||||||
fprintf(nconf, "%sTKIP", prefix);
|
fprintf(nconf, "%sTKIP", prefix);
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_NO_TKIP */
|
||||||
fprintf(nconf, "\n");
|
fprintf(nconf, "\n");
|
||||||
|
|
||||||
if (cred->key_len >= 8 && cred->key_len < 64) {
|
if (cred->key_len >= 8 && cred->key_len < 64) {
|
||||||
@ -650,8 +671,10 @@ static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx)
|
|||||||
(str_starts(buf, "ssid=") ||
|
(str_starts(buf, "ssid=") ||
|
||||||
str_starts(buf, "ssid2=") ||
|
str_starts(buf, "ssid2=") ||
|
||||||
str_starts(buf, "auth_algs=") ||
|
str_starts(buf, "auth_algs=") ||
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
str_starts(buf, "wep_default_key=") ||
|
str_starts(buf, "wep_default_key=") ||
|
||||||
str_starts(buf, "wep_key") ||
|
str_starts(buf, "wep_key") ||
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
str_starts(buf, "wps_state=") ||
|
str_starts(buf, "wps_state=") ||
|
||||||
(pmf_changed && str_starts(buf, "ieee80211w=")) ||
|
(pmf_changed && str_starts(buf, "ieee80211w=")) ||
|
||||||
str_starts(buf, "wpa=") ||
|
str_starts(buf, "wpa=") ||
|
||||||
@ -1157,12 +1180,24 @@ int hostapd_init_wps(struct hostapd_data *hapd,
|
|||||||
wps->encr_types_rsn |= WPS_ENCR_AES;
|
wps->encr_types_rsn |= WPS_ENCR_AES;
|
||||||
}
|
}
|
||||||
if (conf->rsn_pairwise & WPA_CIPHER_TKIP) {
|
if (conf->rsn_pairwise & WPA_CIPHER_TKIP) {
|
||||||
|
#ifdef CONFIG_NO_TKIP
|
||||||
|
wpa_printf(MSG_INFO, "WPS: TKIP not supported");
|
||||||
|
goto fail;
|
||||||
|
#else /* CONFIG_NO_TKIP */
|
||||||
wps->encr_types |= WPS_ENCR_TKIP;
|
wps->encr_types |= WPS_ENCR_TKIP;
|
||||||
wps->encr_types_rsn |= WPS_ENCR_TKIP;
|
wps->encr_types_rsn |= WPS_ENCR_TKIP;
|
||||||
|
#endif /* CONFIG_NO_TKIP */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conf->wpa & WPA_PROTO_WPA) {
|
if (conf->wpa & WPA_PROTO_WPA) {
|
||||||
|
#ifdef CONFIG_NO_TKIP
|
||||||
|
if (!(conf->wpa & WPA_PROTO_RSN)) {
|
||||||
|
wpa_printf(MSG_INFO, "WPS: WPA(v1) not supported");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
conf->wpa &= ~WPA_PROTO_WPA;
|
||||||
|
#else /* CONFIG_NO_TKIP */
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK)
|
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK)
|
||||||
wps->auth_types |= WPS_AUTH_WPAPSK;
|
wps->auth_types |= WPS_AUTH_WPAPSK;
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X)
|
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X)
|
||||||
@ -1176,6 +1211,7 @@ int hostapd_init_wps(struct hostapd_data *hapd,
|
|||||||
wps->encr_types |= WPS_ENCR_TKIP;
|
wps->encr_types |= WPS_ENCR_TKIP;
|
||||||
wps->encr_types_wpa |= WPS_ENCR_TKIP;
|
wps->encr_types_wpa |= WPS_ENCR_TKIP;
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_NO_TKIP */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conf->ssid.security_policy == SECURITY_PLAINTEXT) {
|
if (conf->ssid.security_policy == SECURITY_PLAINTEXT) {
|
||||||
@ -1195,6 +1231,7 @@ int hostapd_init_wps(struct hostapd_data *hapd,
|
|||||||
wpa_snprintf_hex((char *) wps->network_key, 2 * PMK_LEN + 1,
|
wpa_snprintf_hex((char *) wps->network_key, 2 * PMK_LEN + 1,
|
||||||
conf->ssid.wpa_psk->psk, PMK_LEN);
|
conf->ssid.wpa_psk->psk, PMK_LEN);
|
||||||
wps->network_key_len = 2 * PMK_LEN;
|
wps->network_key_len = 2 * PMK_LEN;
|
||||||
|
#ifdef CONFIG_WEP
|
||||||
} else if (conf->ssid.wep.keys_set && conf->ssid.wep.key[0]) {
|
} else if (conf->ssid.wep.keys_set && conf->ssid.wep.key[0]) {
|
||||||
wps->network_key = os_malloc(conf->ssid.wep.len[0]);
|
wps->network_key = os_malloc(conf->ssid.wep.len[0]);
|
||||||
if (wps->network_key == NULL)
|
if (wps->network_key == NULL)
|
||||||
@ -1202,6 +1239,7 @@ int hostapd_init_wps(struct hostapd_data *hapd,
|
|||||||
os_memcpy(wps->network_key, conf->ssid.wep.key[0],
|
os_memcpy(wps->network_key, conf->ssid.wep.key[0],
|
||||||
conf->ssid.wep.len[0]);
|
conf->ssid.wep.len[0]);
|
||||||
wps->network_key_len = conf->ssid.wep.len[0];
|
wps->network_key_len = conf->ssid.wep.len[0];
|
||||||
|
#endif /* CONFIG_WEP */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conf->ssid.wpa_psk) {
|
if (conf->ssid.wpa_psk) {
|
||||||
@ -1213,10 +1251,17 @@ int hostapd_init_wps(struct hostapd_data *hapd,
|
|||||||
wps->ap_encr_type = wps->encr_types;
|
wps->ap_encr_type = wps->encr_types;
|
||||||
if (conf->wps_state == WPS_STATE_NOT_CONFIGURED) {
|
if (conf->wps_state == WPS_STATE_NOT_CONFIGURED) {
|
||||||
/* Override parameters to enable security by default */
|
/* Override parameters to enable security by default */
|
||||||
|
#ifdef CONFIG_NO_TKIP
|
||||||
|
wps->auth_types = WPS_AUTH_WPA2PSK;
|
||||||
|
wps->encr_types = WPS_ENCR_AES;
|
||||||
|
wps->encr_types_rsn = WPS_ENCR_AES;
|
||||||
|
wps->encr_types_wpa = WPS_ENCR_AES;
|
||||||
|
#else /* CONFIG_NO_TKIP */
|
||||||
wps->auth_types = WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK;
|
wps->auth_types = WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK;
|
||||||
wps->encr_types = WPS_ENCR_AES | WPS_ENCR_TKIP;
|
wps->encr_types = WPS_ENCR_AES | WPS_ENCR_TKIP;
|
||||||
wps->encr_types_rsn = WPS_ENCR_AES | WPS_ENCR_TKIP;
|
wps->encr_types_rsn = WPS_ENCR_AES | WPS_ENCR_TKIP;
|
||||||
wps->encr_types_wpa = WPS_ENCR_AES | WPS_ENCR_TKIP;
|
wps->encr_types_wpa = WPS_ENCR_AES | WPS_ENCR_TKIP;
|
||||||
|
#endif /* CONFIG_NO_TKIP */
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((hapd->conf->multi_ap & FRONTHAUL_BSS) &&
|
if ((hapd->conf->multi_ap & FRONTHAUL_BSS) &&
|
||||||
@ -1259,8 +1304,6 @@ int hostapd_init_wps(struct hostapd_data *hapd,
|
|||||||
cfg.extra_cred_len = conf->extra_cred_len;
|
cfg.extra_cred_len = conf->extra_cred_len;
|
||||||
cfg.disable_auto_conf = (hapd->conf->wps_cred_processing == 1) &&
|
cfg.disable_auto_conf = (hapd->conf->wps_cred_processing == 1) &&
|
||||||
conf->skip_cred_build;
|
conf->skip_cred_build;
|
||||||
if (conf->ssid.security_policy == SECURITY_STATIC_WEP)
|
|
||||||
cfg.static_wep_only = 1;
|
|
||||||
cfg.dualband = interface_count(hapd->iface) > 1;
|
cfg.dualband = interface_count(hapd->iface) > 1;
|
||||||
if ((wps->dev.rf_bands & (WPS_RF_50GHZ | WPS_RF_24GHZ)) ==
|
if ((wps->dev.rf_bands & (WPS_RF_50GHZ | WPS_RF_24GHZ)) ==
|
||||||
(WPS_RF_50GHZ | WPS_RF_24GHZ))
|
(WPS_RF_50GHZ | WPS_RF_24GHZ))
|
||||||
@ -1798,8 +1841,10 @@ int hostapd_wps_config_ap(struct hostapd_data *hapd, const char *ssid,
|
|||||||
|
|
||||||
if (os_strncmp(auth, "OPEN", 4) == 0)
|
if (os_strncmp(auth, "OPEN", 4) == 0)
|
||||||
cred.auth_type = WPS_AUTH_OPEN;
|
cred.auth_type = WPS_AUTH_OPEN;
|
||||||
|
#ifndef CONFIG_NO_TKIP
|
||||||
else if (os_strncmp(auth, "WPAPSK", 6) == 0)
|
else if (os_strncmp(auth, "WPAPSK", 6) == 0)
|
||||||
cred.auth_type = WPS_AUTH_WPAPSK;
|
cred.auth_type = WPS_AUTH_WPAPSK;
|
||||||
|
#endif /* CONFIG_NO_TKIP */
|
||||||
else if (os_strncmp(auth, "WPA2PSK", 7) == 0)
|
else if (os_strncmp(auth, "WPA2PSK", 7) == 0)
|
||||||
cred.auth_type = WPS_AUTH_WPA2PSK;
|
cred.auth_type = WPS_AUTH_WPA2PSK;
|
||||||
else
|
else
|
||||||
@ -1808,8 +1853,10 @@ int hostapd_wps_config_ap(struct hostapd_data *hapd, const char *ssid,
|
|||||||
if (encr) {
|
if (encr) {
|
||||||
if (os_strncmp(encr, "NONE", 4) == 0)
|
if (os_strncmp(encr, "NONE", 4) == 0)
|
||||||
cred.encr_type = WPS_ENCR_NONE;
|
cred.encr_type = WPS_ENCR_NONE;
|
||||||
|
#ifndef CONFIG_NO_TKIP
|
||||||
else if (os_strncmp(encr, "TKIP", 4) == 0)
|
else if (os_strncmp(encr, "TKIP", 4) == 0)
|
||||||
cred.encr_type = WPS_ENCR_TKIP;
|
cred.encr_type = WPS_ENCR_TKIP;
|
||||||
|
#endif /* CONFIG_NO_TKIP */
|
||||||
else if (os_strncmp(encr, "CCMP", 4) == 0)
|
else if (os_strncmp(encr, "CCMP", 4) == 0)
|
||||||
cred.encr_type = WPS_ENCR_AES;
|
cred.encr_type = WPS_ENCR_AES;
|
||||||
else
|
else
|
||||||
|
109
src/build.rules
Normal file
109
src/build.rules
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
.PHONY: all
|
||||||
|
all: _all
|
||||||
|
|
||||||
|
# disable built-in rules
|
||||||
|
.SUFFIXES:
|
||||||
|
|
||||||
|
# setup some variables
|
||||||
|
ROOTDIR := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||||
|
ROOTDIR := $(dir $(ROOTDIR:%../src/=%))../
|
||||||
|
BUILDDIR ?= $(abspath $(ROOTDIR)build)
|
||||||
|
BUILDDIR := $(BUILDDIR:%/=%)
|
||||||
|
ABSROOT := $(abspath $(ROOTDIR))
|
||||||
|
ifeq ($(origin OUT),command line)
|
||||||
|
_PROJ := $(OUT:%/=%)
|
||||||
|
_PROJ := $(_PROJ:$(BUILDDIR)/%=%)
|
||||||
|
else
|
||||||
|
_PROJ := $(abspath $(dir $(firstword $(MAKEFILE_LIST))))
|
||||||
|
_PROJ := $(_PROJ:$(ABSROOT)/%=%)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifndef CC
|
||||||
|
CC=gcc
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifndef RANLIB
|
||||||
|
RANLIB=ranlib
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifndef LDO
|
||||||
|
LDO=$(CC)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifndef CFLAGS
|
||||||
|
CFLAGS = -MMD -O2 -Wall -g
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(CONFIG_FILE),)
|
||||||
|
-include $(CONFIG_FILE)
|
||||||
|
|
||||||
|
# export for sub-makefiles
|
||||||
|
export CONFIG_CODE_COVERAGE
|
||||||
|
|
||||||
|
.PHONY: verify_config
|
||||||
|
verify_config:
|
||||||
|
@if [ ! -r $(CONFIG_FILE) ]; then \
|
||||||
|
echo 'Building $(firstword $(ALL)) requires a configuration file'; \
|
||||||
|
echo '(.config). See README for more instructions. You can'; \
|
||||||
|
echo 'run "cp defconfig .config" to create an example'; \
|
||||||
|
echo 'configuration.'; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
VERIFY := verify_config
|
||||||
|
else
|
||||||
|
VERIFY :=
|
||||||
|
endif
|
||||||
|
|
||||||
|
# default target
|
||||||
|
.PHONY: _all
|
||||||
|
_all: $(VERIFY) $(ALL) $(EXTRA_TARGETS)
|
||||||
|
|
||||||
|
# continue setup
|
||||||
|
COVSUFFIX := $(if $(CONFIG_CODE_COVERAGE),-cov,)
|
||||||
|
PROJ := $(_PROJ)$(COVSUFFIX)
|
||||||
|
|
||||||
|
Q=@
|
||||||
|
E=echo
|
||||||
|
ifeq ($(V), 1)
|
||||||
|
Q=
|
||||||
|
E=true
|
||||||
|
endif
|
||||||
|
ifeq ($(QUIET), 1)
|
||||||
|
Q=@
|
||||||
|
E=true
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(Q),@)
|
||||||
|
MAKEFLAGS += --no-print-directory
|
||||||
|
endif
|
||||||
|
|
||||||
|
_DIRS := $(BUILDDIR)/$(PROJ)
|
||||||
|
.PHONY: _make_dirs
|
||||||
|
_make_dirs:
|
||||||
|
@mkdir -p $(_DIRS)
|
||||||
|
|
||||||
|
$(BUILDDIR)/$(PROJ)/src/%.o: $(ROOTDIR)src/%.c $(CONFIG_FILE) | _make_dirs
|
||||||
|
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
|
||||||
|
@$(E) " CC " $<
|
||||||
|
$(BUILDDIR)/$(PROJ)/%.o: %.c $(CONFIG_FILE) | _make_dirs
|
||||||
|
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
|
||||||
|
@$(E) " CC " $<
|
||||||
|
# for the fuzzing tests
|
||||||
|
$(BUILDDIR)/$(PROJ)/wpa_supplicant/%.o: $(ROOTDIR)wpa_supplicant/%.c $(CONFIG_FILE) | _make_dirs
|
||||||
|
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
|
||||||
|
@$(E) " CC " $<
|
||||||
|
|
||||||
|
# libraries - they know how to build themselves
|
||||||
|
# (lib_phony so we recurse all the time)
|
||||||
|
.PHONY: lib_phony
|
||||||
|
lib_phony:
|
||||||
|
# nothing
|
||||||
|
|
||||||
|
$(BUILDDIR)/$(PROJ)/%.a: $(CONFIG_FILE) lib_phony
|
||||||
|
$(Q)$(MAKE) -C $(ROOTDIR)$(dir $(@:$(BUILDDIR)/$(PROJ)/%=%)) OUT=$(abspath $(dir $@))/
|
||||||
|
|
||||||
|
BUILDOBJ = $(patsubst %,$(BUILDDIR)/$(PROJ)/%,$(patsubst $(ROOTDIR)%,%,$(1)))
|
||||||
|
|
||||||
|
.PHONY: common-clean
|
||||||
|
common-clean:
|
||||||
|
$(Q)rm -rf $(ALL) $(BUILDDIR)/$(PROJ)
|
@ -1,13 +1,3 @@
|
|||||||
all: libcommon.a
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f *~ *.o *.d *.gcno *.gcda *.gcov libcommon.a
|
|
||||||
|
|
||||||
install:
|
|
||||||
@echo Nothing to be made.
|
|
||||||
|
|
||||||
include ../lib.rules
|
|
||||||
|
|
||||||
CFLAGS += -DCONFIG_IEEE80211R
|
CFLAGS += -DCONFIG_IEEE80211R
|
||||||
CFLAGS += -DCONFIG_HS20
|
CFLAGS += -DCONFIG_HS20
|
||||||
CFLAGS += -DCONFIG_SAE
|
CFLAGS += -DCONFIG_SAE
|
||||||
@ -21,7 +11,4 @@ LIB_OBJS= \
|
|||||||
sae.o \
|
sae.o \
|
||||||
wpa_common.o
|
wpa_common.o
|
||||||
|
|
||||||
libcommon.a: $(LIB_OBJS)
|
include ../lib.rules
|
||||||
$(AR) crT $@ $?
|
|
||||||
|
|
||||||
-include $(OBJS:%.o=%.d)
|
|
||||||
|
@ -434,7 +434,8 @@ static int sae_tests(void)
|
|||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
/* Check that output matches the test vector */
|
/* Check that output matches the test vector */
|
||||||
sae_write_commit(&sae, buf, NULL, pwid);
|
if (sae_write_commit(&sae, buf, NULL, pwid) < 0)
|
||||||
|
goto fail;
|
||||||
wpa_hexdump_buf(MSG_DEBUG, "SAE: Commit message", buf);
|
wpa_hexdump_buf(MSG_DEBUG, "SAE: Commit message", buf);
|
||||||
|
|
||||||
if (wpabuf_len(buf) != sizeof(local_commit) ||
|
if (wpabuf_len(buf) != sizeof(local_commit) ||
|
||||||
@ -547,6 +548,95 @@ fail:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int sae_pk_tests(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_SAE_PK
|
||||||
|
const char *invalid[] = { "a2bc-de3f-ghim-", "a2bcde3fghim", "", NULL };
|
||||||
|
struct {
|
||||||
|
const char *pw;
|
||||||
|
const u8 *val;
|
||||||
|
} valid[] = {
|
||||||
|
{ "a2bc-de3f-ghim", (u8 *) "\x06\x82\x21\x93\x65\x31\xd0\xc0" },
|
||||||
|
{ "aaaa-aaaa-aaaj", (u8 *) "\x00\x00\x00\x00\x00\x00\x00\x90" },
|
||||||
|
{ "7777-7777-777f", (u8 *) "\xff\xff\xff\xff\xff\xff\xfe\x50" },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
int i;
|
||||||
|
bool failed;
|
||||||
|
|
||||||
|
for (i = 0; invalid[i]; i++) {
|
||||||
|
if (sae_pk_valid_password(invalid[i])) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"SAE-PK: Invalid password '%s' not recognized",
|
||||||
|
invalid[i]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
failed = false;
|
||||||
|
for (i = 0; valid[i].pw; i++) {
|
||||||
|
u8 *res;
|
||||||
|
size_t res_len;
|
||||||
|
char *b32;
|
||||||
|
const char *pw = valid[i].pw;
|
||||||
|
const u8 *val = valid[i].val;
|
||||||
|
size_t pw_len = os_strlen(pw);
|
||||||
|
size_t bits = (pw_len - pw_len / 5) * 5;
|
||||||
|
size_t bytes = (bits + 7) / 8;
|
||||||
|
|
||||||
|
if (!sae_pk_valid_password(pw)) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"SAE-PK: Valid password '%s' not recognized",
|
||||||
|
pw);
|
||||||
|
failed = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = sae_pk_base32_decode(pw, pw_len, &res_len);
|
||||||
|
if (!res) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"SAE-PK: Failed to decode password '%s'",
|
||||||
|
valid[i].pw);
|
||||||
|
failed = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (res_len != bytes || os_memcmp(val, res, res_len) != 0) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"SAE-PK: Mismatch for decoded password '%s'",
|
||||||
|
valid[i].pw);
|
||||||
|
wpa_hexdump(MSG_INFO, "SAE-PK: Decoded value",
|
||||||
|
res, res_len);
|
||||||
|
wpa_hexdump(MSG_INFO, "SAE-PK: Expected value",
|
||||||
|
val, bytes);
|
||||||
|
failed = true;
|
||||||
|
}
|
||||||
|
os_free(res);
|
||||||
|
|
||||||
|
b32 = sae_pk_base32_encode(val, bits - 5);
|
||||||
|
if (!b32) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"SAE-PK: Failed to encode password '%s'",
|
||||||
|
pw);
|
||||||
|
failed = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (os_strcmp(b32, pw) != 0) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"SAE-PK: Mismatch for password '%s'", pw);
|
||||||
|
wpa_printf(MSG_INFO, "SAE-PK: Encoded value: '%s'",
|
||||||
|
b32);
|
||||||
|
failed = true;
|
||||||
|
}
|
||||||
|
os_free(b32);
|
||||||
|
}
|
||||||
|
|
||||||
|
return failed ? -1 : 0;
|
||||||
|
#else /* CONFIG_SAE_PK */
|
||||||
|
return 0;
|
||||||
|
#endif /* CONFIG_SAE_PK */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int common_module_tests(void)
|
int common_module_tests(void)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@ -556,6 +646,7 @@ int common_module_tests(void)
|
|||||||
if (ieee802_11_parse_tests() < 0 ||
|
if (ieee802_11_parse_tests() < 0 ||
|
||||||
gas_tests() < 0 ||
|
gas_tests() < 0 ||
|
||||||
sae_tests() < 0 ||
|
sae_tests() < 0 ||
|
||||||
|
sae_pk_tests() < 0 ||
|
||||||
rsn_ie_parse_tests() < 0)
|
rsn_ie_parse_tests() < 0)
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
|
||||||
|
@ -9,15 +9,6 @@
|
|||||||
#ifndef DEFS_H
|
#ifndef DEFS_H
|
||||||
#define DEFS_H
|
#define DEFS_H
|
||||||
|
|
||||||
#ifdef FALSE
|
|
||||||
#undef FALSE
|
|
||||||
#endif
|
|
||||||
#ifdef TRUE
|
|
||||||
#undef TRUE
|
|
||||||
#endif
|
|
||||||
typedef enum { FALSE = 0, TRUE = 1 } Boolean;
|
|
||||||
|
|
||||||
|
|
||||||
#define WPA_CIPHER_NONE BIT(0)
|
#define WPA_CIPHER_NONE BIT(0)
|
||||||
#define WPA_CIPHER_WEP40 BIT(1)
|
#define WPA_CIPHER_WEP40 BIT(1)
|
||||||
#define WPA_CIPHER_WEP104 BIT(2)
|
#define WPA_CIPHER_WEP104 BIT(2)
|
||||||
@ -82,6 +73,13 @@ static inline int wpa_key_mgmt_wpa_ieee8021x(int akm)
|
|||||||
WPA_KEY_MGMT_FT_FILS_SHA384));
|
WPA_KEY_MGMT_FT_FILS_SHA384));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int wpa_key_mgmt_wpa_psk_no_sae(int akm)
|
||||||
|
{
|
||||||
|
return !!(akm & (WPA_KEY_MGMT_PSK |
|
||||||
|
WPA_KEY_MGMT_FT_PSK |
|
||||||
|
WPA_KEY_MGMT_PSK_SHA256));
|
||||||
|
}
|
||||||
|
|
||||||
static inline int wpa_key_mgmt_wpa_psk(int akm)
|
static inline int wpa_key_mgmt_wpa_psk(int akm)
|
||||||
{
|
{
|
||||||
return !!(akm & (WPA_KEY_MGMT_PSK |
|
return !!(akm & (WPA_KEY_MGMT_PSK |
|
||||||
@ -192,8 +190,7 @@ enum wpa_alg {
|
|||||||
WPA_ALG_WEP,
|
WPA_ALG_WEP,
|
||||||
WPA_ALG_TKIP,
|
WPA_ALG_TKIP,
|
||||||
WPA_ALG_CCMP,
|
WPA_ALG_CCMP,
|
||||||
WPA_ALG_IGTK,
|
WPA_ALG_BIP_CMAC_128,
|
||||||
WPA_ALG_PMK,
|
|
||||||
WPA_ALG_GCMP,
|
WPA_ALG_GCMP,
|
||||||
WPA_ALG_SMS4,
|
WPA_ALG_SMS4,
|
||||||
WPA_ALG_KRK,
|
WPA_ALG_KRK,
|
||||||
@ -204,6 +201,14 @@ enum wpa_alg {
|
|||||||
WPA_ALG_BIP_CMAC_256
|
WPA_ALG_BIP_CMAC_256
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline int wpa_alg_bip(enum wpa_alg alg)
|
||||||
|
{
|
||||||
|
return alg == WPA_ALG_BIP_CMAC_128 ||
|
||||||
|
alg == WPA_ALG_BIP_GMAC_128 ||
|
||||||
|
alg == WPA_ALG_BIP_GMAC_256 ||
|
||||||
|
alg == WPA_ALG_BIP_CMAC_256;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enum wpa_states - wpa_supplicant state
|
* enum wpa_states - wpa_supplicant state
|
||||||
*
|
*
|
||||||
@ -383,9 +388,10 @@ enum mesh_plink_state {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum set_band {
|
enum set_band {
|
||||||
WPA_SETBAND_AUTO,
|
WPA_SETBAND_AUTO = 0,
|
||||||
WPA_SETBAND_5G,
|
WPA_SETBAND_5G = BIT(0),
|
||||||
WPA_SETBAND_2G
|
WPA_SETBAND_2G = BIT(1),
|
||||||
|
WPA_SETBAND_6G = BIT(2),
|
||||||
};
|
};
|
||||||
|
|
||||||
enum wpa_radio_work_band {
|
enum wpa_radio_work_band {
|
||||||
@ -443,6 +449,27 @@ enum key_flag {
|
|||||||
KEY_FLAG_PAIRWISE_RX = KEY_FLAG_PAIRWISE | KEY_FLAG_RX,
|
KEY_FLAG_PAIRWISE_RX = KEY_FLAG_PAIRWISE | KEY_FLAG_RX,
|
||||||
KEY_FLAG_PAIRWISE_RX_TX_MODIFY = KEY_FLAG_PAIRWISE_RX_TX |
|
KEY_FLAG_PAIRWISE_RX_TX_MODIFY = KEY_FLAG_PAIRWISE_RX_TX |
|
||||||
KEY_FLAG_MODIFY,
|
KEY_FLAG_MODIFY,
|
||||||
|
/* Max allowed flags for each key type */
|
||||||
|
KEY_FLAG_PAIRWISE_MASK = KEY_FLAG_PAIRWISE_RX_TX_MODIFY,
|
||||||
|
KEY_FLAG_GROUP_MASK = KEY_FLAG_GROUP_RX_TX_DEFAULT,
|
||||||
|
KEY_FLAG_PMK_MASK = KEY_FLAG_PMK,
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline int check_key_flag(enum key_flag key_flag)
|
||||||
|
{
|
||||||
|
return !!(!key_flag ||
|
||||||
|
((key_flag & (KEY_FLAG_PAIRWISE | KEY_FLAG_MODIFY)) &&
|
||||||
|
(key_flag & ~KEY_FLAG_PAIRWISE_MASK)) ||
|
||||||
|
((key_flag & KEY_FLAG_GROUP) &&
|
||||||
|
(key_flag & ~KEY_FLAG_GROUP_MASK)) ||
|
||||||
|
((key_flag & KEY_FLAG_PMK) &&
|
||||||
|
(key_flag & ~KEY_FLAG_PMK_MASK)));
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ptk0_rekey_handling {
|
||||||
|
PTK0_REKEY_ALLOW_ALWAYS,
|
||||||
|
PTK0_REKEY_ALLOW_LOCAL_OK,
|
||||||
|
PTK0_REKEY_ALLOW_NEVER
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* DEFS_H */
|
#endif /* DEFS_H */
|
||||||
|
9093
src/common/dpp.c
9093
src/common/dpp.c
File diff suppressed because it is too large
Load Diff
166
src/common/dpp.h
166
src/common/dpp.h
@ -20,9 +20,22 @@
|
|||||||
struct crypto_ecdh;
|
struct crypto_ecdh;
|
||||||
struct hostapd_ip_addr;
|
struct hostapd_ip_addr;
|
||||||
struct dpp_global;
|
struct dpp_global;
|
||||||
|
struct json_token;
|
||||||
|
struct dpp_reconfig_id;
|
||||||
|
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
#define DPP_VERSION (dpp_version_override)
|
||||||
|
extern int dpp_version_override;
|
||||||
|
#else /* CONFIG_TESTING_OPTIONS */
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
#define DPP_VERSION 2
|
||||||
|
#else
|
||||||
|
#define DPP_VERSION 1
|
||||||
|
#endif
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
#define DPP_HDR_LEN (4 + 2) /* OUI, OUI Type, Crypto Suite, DPP frame type */
|
#define DPP_HDR_LEN (4 + 2) /* OUI, OUI Type, Crypto Suite, DPP frame type */
|
||||||
#define DPP_TCP_PORT 7871
|
#define DPP_TCP_PORT 8908
|
||||||
|
|
||||||
enum dpp_public_action_frame_type {
|
enum dpp_public_action_frame_type {
|
||||||
DPP_PA_AUTHENTICATION_REQ = 0,
|
DPP_PA_AUTHENTICATION_REQ = 0,
|
||||||
@ -36,6 +49,11 @@ enum dpp_public_action_frame_type {
|
|||||||
DPP_PA_PKEX_COMMIT_REVEAL_RESP = 10,
|
DPP_PA_PKEX_COMMIT_REVEAL_RESP = 10,
|
||||||
DPP_PA_CONFIGURATION_RESULT = 11,
|
DPP_PA_CONFIGURATION_RESULT = 11,
|
||||||
DPP_PA_CONNECTION_STATUS_RESULT = 12,
|
DPP_PA_CONNECTION_STATUS_RESULT = 12,
|
||||||
|
DPP_PA_PRESENCE_ANNOUNCEMENT = 13,
|
||||||
|
DPP_PA_RECONFIG_ANNOUNCEMENT = 14,
|
||||||
|
DPP_PA_RECONFIG_AUTH_REQ = 15,
|
||||||
|
DPP_PA_RECONFIG_AUTH_RESP = 16,
|
||||||
|
DPP_PA_RECONFIG_AUTH_CONF = 17,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum dpp_attribute_id {
|
enum dpp_attribute_id {
|
||||||
@ -67,6 +85,12 @@ enum dpp_attribute_id {
|
|||||||
DPP_ATTR_ENVELOPED_DATA = 0x101A,
|
DPP_ATTR_ENVELOPED_DATA = 0x101A,
|
||||||
DPP_ATTR_SEND_CONN_STATUS = 0x101B,
|
DPP_ATTR_SEND_CONN_STATUS = 0x101B,
|
||||||
DPP_ATTR_CONN_STATUS = 0x101C,
|
DPP_ATTR_CONN_STATUS = 0x101C,
|
||||||
|
DPP_ATTR_RECONFIG_FLAGS = 0x101D,
|
||||||
|
DPP_ATTR_C_SIGN_KEY_HASH = 0x101E,
|
||||||
|
DPP_ATTR_CSR_ATTR_REQ = 0x101F,
|
||||||
|
DPP_ATTR_A_NONCE = 0x1020,
|
||||||
|
DPP_ATTR_E_PRIME_ID = 0x1021,
|
||||||
|
DPP_ATTR_CONFIGURATOR_NONCE = 0x1022,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum dpp_status_error {
|
enum dpp_status_error {
|
||||||
@ -81,6 +105,15 @@ enum dpp_status_error {
|
|||||||
DPP_STATUS_NO_MATCH = 8,
|
DPP_STATUS_NO_MATCH = 8,
|
||||||
DPP_STATUS_CONFIG_REJECTED = 9,
|
DPP_STATUS_CONFIG_REJECTED = 9,
|
||||||
DPP_STATUS_NO_AP = 10,
|
DPP_STATUS_NO_AP = 10,
|
||||||
|
DPP_STATUS_CONFIGURE_PENDING = 11,
|
||||||
|
DPP_STATUS_CSR_NEEDED = 12,
|
||||||
|
DPP_STATUS_CSR_BAD = 13,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* DPP Reconfig Flags object - connectorKey values */
|
||||||
|
enum dpp_connector_key {
|
||||||
|
DPP_CONFIG_REUSEKEY = 0,
|
||||||
|
DPP_CONFIG_REPLACEKEY = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DPP_CAPAB_ENROLLEE BIT(0)
|
#define DPP_CAPAB_ENROLLEE BIT(0)
|
||||||
@ -91,6 +124,7 @@ enum dpp_status_error {
|
|||||||
#define DPP_MAX_NONCE_LEN 32
|
#define DPP_MAX_NONCE_LEN 32
|
||||||
#define DPP_MAX_HASH_LEN 64
|
#define DPP_MAX_HASH_LEN 64
|
||||||
#define DPP_MAX_SHARED_SECRET_LEN 66
|
#define DPP_MAX_SHARED_SECRET_LEN 66
|
||||||
|
#define DPP_CP_LEN 64
|
||||||
|
|
||||||
struct dpp_curve_params {
|
struct dpp_curve_params {
|
||||||
const char *name;
|
const char *name;
|
||||||
@ -120,12 +154,18 @@ struct dpp_bootstrap_info {
|
|||||||
char *pk;
|
char *pk;
|
||||||
unsigned int freq[DPP_BOOTSTRAP_MAX_FREQ];
|
unsigned int freq[DPP_BOOTSTRAP_MAX_FREQ];
|
||||||
unsigned int num_freq;
|
unsigned int num_freq;
|
||||||
|
bool channels_listed;
|
||||||
|
u8 version;
|
||||||
int own;
|
int own;
|
||||||
EVP_PKEY *pubkey;
|
EVP_PKEY *pubkey;
|
||||||
u8 pubkey_hash[SHA256_MAC_LEN];
|
u8 pubkey_hash[SHA256_MAC_LEN];
|
||||||
|
u8 pubkey_hash_chirp[SHA256_MAC_LEN];
|
||||||
const struct dpp_curve_params *curve;
|
const struct dpp_curve_params *curve;
|
||||||
unsigned int pkex_t; /* number of failures before dpp_pkex
|
unsigned int pkex_t; /* number of failures before dpp_pkex
|
||||||
* instantiation */
|
* instantiation */
|
||||||
|
int nfc_negotiated; /* whether this has been used in NFC negotiated
|
||||||
|
* connection handover */
|
||||||
|
char *configurator_params;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PKEX_COUNTER_T_LIMIT 5
|
#define PKEX_COUNTER_T_LIMIT 5
|
||||||
@ -162,6 +202,7 @@ enum dpp_akm {
|
|||||||
DPP_AKM_PSK_SAE,
|
DPP_AKM_PSK_SAE,
|
||||||
DPP_AKM_SAE_DPP,
|
DPP_AKM_SAE_DPP,
|
||||||
DPP_AKM_PSK_SAE_DPP,
|
DPP_AKM_PSK_SAE_DPP,
|
||||||
|
DPP_AKM_DOT1X,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum dpp_netrole {
|
enum dpp_netrole {
|
||||||
@ -187,11 +228,14 @@ struct dpp_configuration {
|
|||||||
char *passphrase;
|
char *passphrase;
|
||||||
u8 psk[32];
|
u8 psk[32];
|
||||||
int psk_set;
|
int psk_set;
|
||||||
|
|
||||||
|
char *csrattrs;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dpp_asymmetric_key {
|
struct dpp_asymmetric_key {
|
||||||
struct dpp_asymmetric_key *next;
|
struct dpp_asymmetric_key *next;
|
||||||
EVP_PKEY *csign;
|
EVP_PKEY *csign;
|
||||||
|
EVP_PKEY *pp_key;
|
||||||
char *config_template;
|
char *config_template;
|
||||||
char *connector_template;
|
char *connector_template;
|
||||||
};
|
};
|
||||||
@ -199,26 +243,36 @@ struct dpp_asymmetric_key {
|
|||||||
#define DPP_MAX_CONF_OBJ 10
|
#define DPP_MAX_CONF_OBJ 10
|
||||||
|
|
||||||
struct dpp_authentication {
|
struct dpp_authentication {
|
||||||
|
struct dpp_global *global;
|
||||||
void *msg_ctx;
|
void *msg_ctx;
|
||||||
u8 peer_version;
|
u8 peer_version;
|
||||||
const struct dpp_curve_params *curve;
|
const struct dpp_curve_params *curve;
|
||||||
struct dpp_bootstrap_info *peer_bi;
|
struct dpp_bootstrap_info *peer_bi;
|
||||||
struct dpp_bootstrap_info *own_bi;
|
struct dpp_bootstrap_info *own_bi;
|
||||||
struct dpp_bootstrap_info *tmp_own_bi;
|
struct dpp_bootstrap_info *tmp_own_bi;
|
||||||
|
struct dpp_bootstrap_info *tmp_peer_bi;
|
||||||
u8 waiting_pubkey_hash[SHA256_MAC_LEN];
|
u8 waiting_pubkey_hash[SHA256_MAC_LEN];
|
||||||
int response_pending;
|
int response_pending;
|
||||||
|
int reconfig;
|
||||||
|
enum dpp_connector_key reconfig_connector_key;
|
||||||
enum dpp_status_error auth_resp_status;
|
enum dpp_status_error auth_resp_status;
|
||||||
enum dpp_status_error conf_resp_status;
|
enum dpp_status_error conf_resp_status;
|
||||||
|
enum dpp_status_error force_conf_resp_status;
|
||||||
u8 peer_mac_addr[ETH_ALEN];
|
u8 peer_mac_addr[ETH_ALEN];
|
||||||
u8 i_nonce[DPP_MAX_NONCE_LEN];
|
u8 i_nonce[DPP_MAX_NONCE_LEN];
|
||||||
u8 r_nonce[DPP_MAX_NONCE_LEN];
|
u8 r_nonce[DPP_MAX_NONCE_LEN];
|
||||||
u8 e_nonce[DPP_MAX_NONCE_LEN];
|
u8 e_nonce[DPP_MAX_NONCE_LEN];
|
||||||
|
u8 c_nonce[DPP_MAX_NONCE_LEN];
|
||||||
u8 i_capab;
|
u8 i_capab;
|
||||||
u8 r_capab;
|
u8 r_capab;
|
||||||
|
enum dpp_netrole e_netrole;
|
||||||
EVP_PKEY *own_protocol_key;
|
EVP_PKEY *own_protocol_key;
|
||||||
EVP_PKEY *peer_protocol_key;
|
EVP_PKEY *peer_protocol_key;
|
||||||
|
EVP_PKEY *reconfig_old_protocol_key;
|
||||||
struct wpabuf *req_msg;
|
struct wpabuf *req_msg;
|
||||||
struct wpabuf *resp_msg;
|
struct wpabuf *resp_msg;
|
||||||
|
struct wpabuf *reconfig_req_msg;
|
||||||
|
struct wpabuf *reconfig_resp_msg;
|
||||||
/* Intersection of possible frequencies for initiating DPP
|
/* Intersection of possible frequencies for initiating DPP
|
||||||
* Authentication exchange */
|
* Authentication exchange */
|
||||||
unsigned int freq[DPP_BOOTSTRAP_MAX_FREQ];
|
unsigned int freq[DPP_BOOTSTRAP_MAX_FREQ];
|
||||||
@ -236,6 +290,7 @@ struct dpp_authentication {
|
|||||||
u8 k1[DPP_MAX_HASH_LEN];
|
u8 k1[DPP_MAX_HASH_LEN];
|
||||||
u8 k2[DPP_MAX_HASH_LEN];
|
u8 k2[DPP_MAX_HASH_LEN];
|
||||||
u8 ke[DPP_MAX_HASH_LEN];
|
u8 ke[DPP_MAX_HASH_LEN];
|
||||||
|
u8 bk[DPP_MAX_HASH_LEN];
|
||||||
int initiator;
|
int initiator;
|
||||||
int waiting_auth_resp;
|
int waiting_auth_resp;
|
||||||
int waiting_auth_conf;
|
int waiting_auth_conf;
|
||||||
@ -248,8 +303,10 @@ struct dpp_authentication {
|
|||||||
int waiting_conf_result;
|
int waiting_conf_result;
|
||||||
int waiting_conn_status_result;
|
int waiting_conn_status_result;
|
||||||
int auth_success;
|
int auth_success;
|
||||||
|
bool reconfig_success;
|
||||||
struct wpabuf *conf_req;
|
struct wpabuf *conf_req;
|
||||||
const struct wpabuf *conf_resp; /* owned by GAS server */
|
const struct wpabuf *conf_resp; /* owned by GAS server */
|
||||||
|
struct wpabuf *conf_resp_tcp;
|
||||||
struct dpp_configuration *conf_ap;
|
struct dpp_configuration *conf_ap;
|
||||||
struct dpp_configuration *conf2_ap;
|
struct dpp_configuration *conf2_ap;
|
||||||
struct dpp_configuration *conf_sta;
|
struct dpp_configuration *conf_sta;
|
||||||
@ -266,6 +323,11 @@ struct dpp_authentication {
|
|||||||
int psk_set;
|
int psk_set;
|
||||||
enum dpp_akm akm;
|
enum dpp_akm akm;
|
||||||
struct wpabuf *c_sign_key;
|
struct wpabuf *c_sign_key;
|
||||||
|
struct wpabuf *certbag;
|
||||||
|
struct wpabuf *certs;
|
||||||
|
struct wpabuf *cacert;
|
||||||
|
char *server_name;
|
||||||
|
struct wpabuf *pp_key;
|
||||||
} conf_obj[DPP_MAX_CONF_OBJ];
|
} conf_obj[DPP_MAX_CONF_OBJ];
|
||||||
unsigned int num_conf_obj;
|
unsigned int num_conf_obj;
|
||||||
struct dpp_asymmetric_key *conf_key_pkg;
|
struct dpp_asymmetric_key *conf_key_pkg;
|
||||||
@ -274,6 +336,18 @@ struct dpp_authentication {
|
|||||||
int send_conn_status;
|
int send_conn_status;
|
||||||
int conn_status_requested;
|
int conn_status_requested;
|
||||||
int akm_use_selector;
|
int akm_use_selector;
|
||||||
|
int configurator_set;
|
||||||
|
u8 transaction_id;
|
||||||
|
u8 *csrattrs;
|
||||||
|
size_t csrattrs_len;
|
||||||
|
bool waiting_csr;
|
||||||
|
struct wpabuf *csr;
|
||||||
|
struct wpabuf *priv_key; /* DER-encoded private key used for csr */
|
||||||
|
bool waiting_cert;
|
||||||
|
char *trusted_eap_server_name;
|
||||||
|
struct wpabuf *cacert;
|
||||||
|
struct wpabuf *certbag;
|
||||||
|
void *cert_resp_ctx;
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
char *config_obj_override;
|
char *config_obj_override;
|
||||||
char *discovery_override;
|
char *discovery_override;
|
||||||
@ -287,8 +361,12 @@ struct dpp_configurator {
|
|||||||
unsigned int id;
|
unsigned int id;
|
||||||
int own;
|
int own;
|
||||||
EVP_PKEY *csign;
|
EVP_PKEY *csign;
|
||||||
|
u8 kid_hash[SHA256_MAC_LEN];
|
||||||
char *kid;
|
char *kid;
|
||||||
const struct dpp_curve_params *curve;
|
const struct dpp_curve_params *curve;
|
||||||
|
char *connector; /* own Connector for reconfiguration */
|
||||||
|
EVP_PKEY *connector_key;
|
||||||
|
EVP_PKEY *pp_key;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dpp_introduction {
|
struct dpp_introduction {
|
||||||
@ -301,6 +379,7 @@ struct dpp_relay_config {
|
|||||||
const struct hostapd_ip_addr *ipaddr;
|
const struct hostapd_ip_addr *ipaddr;
|
||||||
const u8 *pkhash;
|
const u8 *pkhash;
|
||||||
|
|
||||||
|
void *msg_ctx;
|
||||||
void *cb_ctx;
|
void *cb_ctx;
|
||||||
void (*tx)(void *ctx, const u8 *addr, unsigned int freq, const u8 *msg,
|
void (*tx)(void *ctx, const u8 *addr, unsigned int freq, const u8 *msg,
|
||||||
size_t len);
|
size_t len);
|
||||||
@ -311,6 +390,12 @@ struct dpp_relay_config {
|
|||||||
struct dpp_controller_config {
|
struct dpp_controller_config {
|
||||||
const char *configurator_params;
|
const char *configurator_params;
|
||||||
int tcp_port;
|
int tcp_port;
|
||||||
|
u8 allowed_roles;
|
||||||
|
int qr_mutual;
|
||||||
|
enum dpp_netrole netrole;
|
||||||
|
void *msg_ctx;
|
||||||
|
void *cb_ctx;
|
||||||
|
int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth);
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
@ -422,15 +507,16 @@ extern size_t dpp_nonce_override_len;
|
|||||||
|
|
||||||
void dpp_bootstrap_info_free(struct dpp_bootstrap_info *info);
|
void dpp_bootstrap_info_free(struct dpp_bootstrap_info *info);
|
||||||
const char * dpp_bootstrap_type_txt(enum dpp_bootstrap_type type);
|
const char * dpp_bootstrap_type_txt(enum dpp_bootstrap_type type);
|
||||||
int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi);
|
|
||||||
int dpp_parse_uri_chan_list(struct dpp_bootstrap_info *bi,
|
int dpp_parse_uri_chan_list(struct dpp_bootstrap_info *bi,
|
||||||
const char *chan_list);
|
const char *chan_list);
|
||||||
int dpp_parse_uri_mac(struct dpp_bootstrap_info *bi, const char *mac);
|
int dpp_parse_uri_mac(struct dpp_bootstrap_info *bi, const char *mac);
|
||||||
int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info);
|
int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info);
|
||||||
int dpp_nfc_update_bi(struct dpp_bootstrap_info *own_bi,
|
int dpp_nfc_update_bi(struct dpp_bootstrap_info *own_bi,
|
||||||
struct dpp_bootstrap_info *peer_bi);
|
struct dpp_bootstrap_info *peer_bi);
|
||||||
|
struct dpp_authentication *
|
||||||
|
dpp_alloc_auth(struct dpp_global *dpp, void *msg_ctx);
|
||||||
struct hostapd_hw_modes;
|
struct hostapd_hw_modes;
|
||||||
struct dpp_authentication * dpp_auth_init(void *msg_ctx,
|
struct dpp_authentication * dpp_auth_init(struct dpp_global *dpp, void *msg_ctx,
|
||||||
struct dpp_bootstrap_info *peer_bi,
|
struct dpp_bootstrap_info *peer_bi,
|
||||||
struct dpp_bootstrap_info *own_bi,
|
struct dpp_bootstrap_info *own_bi,
|
||||||
u8 dpp_allowed_roles,
|
u8 dpp_allowed_roles,
|
||||||
@ -438,8 +524,8 @@ struct dpp_authentication * dpp_auth_init(void *msg_ctx,
|
|||||||
struct hostapd_hw_modes *own_modes,
|
struct hostapd_hw_modes *own_modes,
|
||||||
u16 num_modes);
|
u16 num_modes);
|
||||||
struct dpp_authentication *
|
struct dpp_authentication *
|
||||||
dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual,
|
dpp_auth_req_rx(struct dpp_global *dpp, void *msg_ctx, u8 dpp_allowed_roles,
|
||||||
struct dpp_bootstrap_info *peer_bi,
|
int qr_mutual, struct dpp_bootstrap_info *peer_bi,
|
||||||
struct dpp_bootstrap_info *own_bi,
|
struct dpp_bootstrap_info *own_bi,
|
||||||
unsigned int freq, const u8 *hdr, const u8 *attr_start,
|
unsigned int freq, const u8 *hdr, const u8 *attr_start,
|
||||||
size_t attr_len);
|
size_t attr_len);
|
||||||
@ -464,11 +550,13 @@ int dpp_akm_dpp(enum dpp_akm akm);
|
|||||||
int dpp_akm_ver2(enum dpp_akm akm);
|
int dpp_akm_ver2(enum dpp_akm akm);
|
||||||
int dpp_configuration_valid(const struct dpp_configuration *conf);
|
int dpp_configuration_valid(const struct dpp_configuration *conf);
|
||||||
void dpp_configuration_free(struct dpp_configuration *conf);
|
void dpp_configuration_free(struct dpp_configuration *conf);
|
||||||
int dpp_set_configurator(struct dpp_global *dpp, void *msg_ctx,
|
int dpp_set_configurator(struct dpp_authentication *auth, const char *cmd);
|
||||||
struct dpp_authentication *auth,
|
|
||||||
const char *cmd);
|
|
||||||
void dpp_auth_deinit(struct dpp_authentication *auth);
|
void dpp_auth_deinit(struct dpp_authentication *auth);
|
||||||
struct wpabuf *
|
struct wpabuf *
|
||||||
|
dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce,
|
||||||
|
u16 e_nonce_len, enum dpp_netrole netrole,
|
||||||
|
bool cert_req);
|
||||||
|
struct wpabuf *
|
||||||
dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start,
|
dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start,
|
||||||
size_t attr_len);
|
size_t attr_len);
|
||||||
int dpp_conf_resp_rx(struct dpp_authentication *auth,
|
int dpp_conf_resp_rx(struct dpp_authentication *auth,
|
||||||
@ -498,9 +586,6 @@ const char * dpp_akm_selector_str(enum dpp_akm akm);
|
|||||||
int dpp_configurator_get_key(const struct dpp_configurator *conf, char *buf,
|
int dpp_configurator_get_key(const struct dpp_configurator *conf, char *buf,
|
||||||
size_t buflen);
|
size_t buflen);
|
||||||
void dpp_configurator_free(struct dpp_configurator *conf);
|
void dpp_configurator_free(struct dpp_configurator *conf);
|
||||||
struct dpp_configurator *
|
|
||||||
dpp_keygen_configurator(const char *curve, const u8 *privkey,
|
|
||||||
size_t privkey_len);
|
|
||||||
int dpp_configurator_own_config(struct dpp_authentication *auth,
|
int dpp_configurator_own_config(struct dpp_authentication *auth,
|
||||||
const char *curve, int ap);
|
const char *curve, int ap);
|
||||||
enum dpp_status_error
|
enum dpp_status_error
|
||||||
@ -545,6 +630,11 @@ struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key,
|
|||||||
int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len);
|
int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len);
|
||||||
void dpp_pfs_free(struct dpp_pfs *pfs);
|
void dpp_pfs_free(struct dpp_pfs *pfs);
|
||||||
|
|
||||||
|
struct wpabuf * dpp_build_csr(struct dpp_authentication *auth,
|
||||||
|
const char *name);
|
||||||
|
struct wpabuf * dpp_pkcs7_certs(const struct wpabuf *pkcs7);
|
||||||
|
int dpp_validate_csr(struct dpp_authentication *auth, const struct wpabuf *csr);
|
||||||
|
|
||||||
struct dpp_bootstrap_info * dpp_add_qr_code(struct dpp_global *dpp,
|
struct dpp_bootstrap_info * dpp_add_qr_code(struct dpp_global *dpp,
|
||||||
const char *uri);
|
const char *uri);
|
||||||
struct dpp_bootstrap_info * dpp_add_nfc_uri(struct dpp_global *dpp,
|
struct dpp_bootstrap_info * dpp_add_nfc_uri(struct dpp_global *dpp,
|
||||||
@ -559,16 +649,21 @@ dpp_pkex_finish(struct dpp_global *dpp, struct dpp_pkex *pkex, const u8 *peer,
|
|||||||
const char * dpp_bootstrap_get_uri(struct dpp_global *dpp, unsigned int id);
|
const char * dpp_bootstrap_get_uri(struct dpp_global *dpp, unsigned int id);
|
||||||
int dpp_bootstrap_info(struct dpp_global *dpp, int id,
|
int dpp_bootstrap_info(struct dpp_global *dpp, int id,
|
||||||
char *reply, int reply_size);
|
char *reply, int reply_size);
|
||||||
|
int dpp_bootstrap_set(struct dpp_global *dpp, int id, const char *params);
|
||||||
void dpp_bootstrap_find_pair(struct dpp_global *dpp, const u8 *i_bootstrap,
|
void dpp_bootstrap_find_pair(struct dpp_global *dpp, const u8 *i_bootstrap,
|
||||||
const u8 *r_bootstrap,
|
const u8 *r_bootstrap,
|
||||||
struct dpp_bootstrap_info **own_bi,
|
struct dpp_bootstrap_info **own_bi,
|
||||||
struct dpp_bootstrap_info **peer_bi);
|
struct dpp_bootstrap_info **peer_bi);
|
||||||
|
struct dpp_bootstrap_info * dpp_bootstrap_find_chirp(struct dpp_global *dpp,
|
||||||
|
const u8 *hash);
|
||||||
int dpp_configurator_add(struct dpp_global *dpp, const char *cmd);
|
int dpp_configurator_add(struct dpp_global *dpp, const char *cmd);
|
||||||
int dpp_configurator_remove(struct dpp_global *dpp, const char *id);
|
int dpp_configurator_remove(struct dpp_global *dpp, const char *id);
|
||||||
int dpp_configurator_get_key_id(struct dpp_global *dpp, unsigned int id,
|
int dpp_configurator_get_key_id(struct dpp_global *dpp, unsigned int id,
|
||||||
char *buf, size_t buflen);
|
char *buf, size_t buflen);
|
||||||
int dpp_configurator_from_backup(struct dpp_global *dpp,
|
int dpp_configurator_from_backup(struct dpp_global *dpp,
|
||||||
struct dpp_asymmetric_key *key);
|
struct dpp_asymmetric_key *key);
|
||||||
|
struct dpp_configurator * dpp_configurator_find_kid(struct dpp_global *dpp,
|
||||||
|
const u8 *kid);
|
||||||
int dpp_relay_add_controller(struct dpp_global *dpp,
|
int dpp_relay_add_controller(struct dpp_global *dpp,
|
||||||
struct dpp_relay_config *config);
|
struct dpp_relay_config *config);
|
||||||
int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr,
|
int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr,
|
||||||
@ -579,18 +674,61 @@ int dpp_relay_rx_gas_req(struct dpp_global *dpp, const u8 *src, const u8 *data,
|
|||||||
int dpp_controller_start(struct dpp_global *dpp,
|
int dpp_controller_start(struct dpp_global *dpp,
|
||||||
struct dpp_controller_config *config);
|
struct dpp_controller_config *config);
|
||||||
void dpp_controller_stop(struct dpp_global *dpp);
|
void dpp_controller_stop(struct dpp_global *dpp);
|
||||||
|
struct dpp_authentication * dpp_controller_get_auth(struct dpp_global *dpp,
|
||||||
|
unsigned int id);
|
||||||
|
void dpp_controller_new_qr_code(struct dpp_global *dpp,
|
||||||
|
struct dpp_bootstrap_info *bi);
|
||||||
int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth,
|
int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth,
|
||||||
const struct hostapd_ip_addr *addr, int port);
|
const struct hostapd_ip_addr *addr, int port,
|
||||||
|
const char *name, enum dpp_netrole netrole, void *msg_ctx,
|
||||||
|
void *cb_ctx,
|
||||||
|
int (*process_conf_obj)(void *ctx,
|
||||||
|
struct dpp_authentication *auth));
|
||||||
|
|
||||||
|
struct wpabuf * dpp_build_presence_announcement(struct dpp_bootstrap_info *bi);
|
||||||
|
void dpp_notify_chirp_received(void *msg_ctx, int id, const u8 *src,
|
||||||
|
unsigned int freq, const u8 *hash);
|
||||||
|
|
||||||
struct dpp_global_config {
|
struct dpp_global_config {
|
||||||
void *msg_ctx;
|
|
||||||
void *cb_ctx;
|
void *cb_ctx;
|
||||||
int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth);
|
void (*remove_bi)(void *ctx, struct dpp_bootstrap_info *bi);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dpp_global * dpp_global_init(struct dpp_global_config *config);
|
struct dpp_global * dpp_global_init(struct dpp_global_config *config);
|
||||||
void dpp_global_clear(struct dpp_global *dpp);
|
void dpp_global_clear(struct dpp_global *dpp);
|
||||||
void dpp_global_deinit(struct dpp_global *dpp);
|
void dpp_global_deinit(struct dpp_global *dpp);
|
||||||
|
|
||||||
|
/* dpp_reconfig.c */
|
||||||
|
|
||||||
|
struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key,
|
||||||
|
size_t csign_key_len,
|
||||||
|
const u8 *net_access_key,
|
||||||
|
size_t net_access_key_len,
|
||||||
|
struct dpp_reconfig_id *id);
|
||||||
|
struct dpp_authentication *
|
||||||
|
dpp_reconfig_init(struct dpp_global *dpp, void *msg_ctx,
|
||||||
|
struct dpp_configurator *conf, unsigned int freq, u16 group,
|
||||||
|
const u8 *a_nonce_attr, size_t a_nonce_len,
|
||||||
|
const u8 *e_id_attr, size_t e_id_len);
|
||||||
|
struct dpp_authentication *
|
||||||
|
dpp_reconfig_auth_req_rx(struct dpp_global *dpp, void *msg_ctx,
|
||||||
|
const char *own_connector,
|
||||||
|
const u8 *net_access_key, size_t net_access_key_len,
|
||||||
|
const u8 *csign_key, size_t csign_key_len,
|
||||||
|
unsigned int freq, const u8 *hdr,
|
||||||
|
const u8 *attr_start, size_t attr_len);
|
||||||
|
struct wpabuf *
|
||||||
|
dpp_reconfig_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr,
|
||||||
|
const u8 *attr_start, size_t attr_len);
|
||||||
|
int dpp_reconfig_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr,
|
||||||
|
const u8 *attr_start, size_t attr_len);
|
||||||
|
|
||||||
|
struct dpp_reconfig_id * dpp_gen_reconfig_id(const u8 *csign_key,
|
||||||
|
size_t csign_key_len,
|
||||||
|
const u8 *pp_key,
|
||||||
|
size_t pp_key_len);
|
||||||
|
int dpp_update_reconfig_id(struct dpp_reconfig_id *id);
|
||||||
|
void dpp_free_reconfig_id(struct dpp_reconfig_id *id);
|
||||||
|
|
||||||
#endif /* CONFIG_DPP */
|
#endif /* CONFIG_DPP */
|
||||||
#endif /* DPP_H */
|
#endif /* DPP_H */
|
||||||
|
1976
src/common/dpp_auth.c
Normal file
1976
src/common/dpp_auth.c
Normal file
File diff suppressed because it is too large
Load Diff
1292
src/common/dpp_backup.c
Normal file
1292
src/common/dpp_backup.c
Normal file
File diff suppressed because it is too large
Load Diff
3329
src/common/dpp_crypto.c
Normal file
3329
src/common/dpp_crypto.c
Normal file
File diff suppressed because it is too large
Load Diff
160
src/common/dpp_i.h
Normal file
160
src/common/dpp_i.h
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
* DPP module internal definitions
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DPP_I_H
|
||||||
|
#define DPP_I_H
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP
|
||||||
|
|
||||||
|
struct dpp_global {
|
||||||
|
void *msg_ctx;
|
||||||
|
struct dl_list bootstrap; /* struct dpp_bootstrap_info */
|
||||||
|
struct dl_list configurator; /* struct dpp_configurator */
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
struct dl_list controllers; /* struct dpp_relay_controller */
|
||||||
|
struct dpp_controller *controller;
|
||||||
|
struct dl_list tcp_init; /* struct dpp_connection */
|
||||||
|
void *cb_ctx;
|
||||||
|
int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth);
|
||||||
|
void (*remove_bi)(void *ctx, struct dpp_bootstrap_info *bi);
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* dpp.c */
|
||||||
|
|
||||||
|
void dpp_build_attr_status(struct wpabuf *msg, enum dpp_status_error status);
|
||||||
|
void dpp_build_attr_r_bootstrap_key_hash(struct wpabuf *msg, const u8 *hash);
|
||||||
|
unsigned int dpp_next_id(struct dpp_global *dpp);
|
||||||
|
struct wpabuf * dpp_build_conn_status(enum dpp_status_error result,
|
||||||
|
const u8 *ssid, size_t ssid_len,
|
||||||
|
const char *channel_list);
|
||||||
|
struct json_token * dpp_parse_own_connector(const char *own_connector);
|
||||||
|
int dpp_connector_match_groups(struct json_token *own_root,
|
||||||
|
struct json_token *peer_root, bool reconfig);
|
||||||
|
int dpp_build_jwk(struct wpabuf *buf, const char *name, EVP_PKEY *key,
|
||||||
|
const char *kid, const struct dpp_curve_params *curve);
|
||||||
|
EVP_PKEY * dpp_parse_jwk(struct json_token *jwk,
|
||||||
|
const struct dpp_curve_params **key_curve);
|
||||||
|
int dpp_prepare_channel_list(struct dpp_authentication *auth,
|
||||||
|
unsigned int neg_freq,
|
||||||
|
struct hostapd_hw_modes *own_modes, u16 num_modes);
|
||||||
|
void dpp_auth_fail(struct dpp_authentication *auth, const char *txt);
|
||||||
|
int dpp_gen_uri(struct dpp_bootstrap_info *bi);
|
||||||
|
void dpp_write_adv_proto(struct wpabuf *buf);
|
||||||
|
void dpp_write_gas_query(struct wpabuf *buf, struct wpabuf *query);
|
||||||
|
|
||||||
|
/* dpp_backup.c */
|
||||||
|
|
||||||
|
void dpp_free_asymmetric_key(struct dpp_asymmetric_key *key);
|
||||||
|
struct wpabuf * dpp_build_enveloped_data(struct dpp_authentication *auth);
|
||||||
|
int dpp_conf_resp_env_data(struct dpp_authentication *auth,
|
||||||
|
const u8 *env_data, size_t env_data_len);
|
||||||
|
|
||||||
|
/* dpp_crypto.c */
|
||||||
|
|
||||||
|
struct dpp_signed_connector_info {
|
||||||
|
unsigned char *payload;
|
||||||
|
size_t payload_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum dpp_status_error
|
||||||
|
dpp_process_signed_connector(struct dpp_signed_connector_info *info,
|
||||||
|
EVP_PKEY *csign_pub, const char *connector);
|
||||||
|
enum dpp_status_error
|
||||||
|
dpp_check_signed_connector(struct dpp_signed_connector_info *info,
|
||||||
|
const u8 *csign_key, size_t csign_key_len,
|
||||||
|
const u8 *peer_connector, size_t peer_connector_len);
|
||||||
|
const struct dpp_curve_params * dpp_get_curve_name(const char *name);
|
||||||
|
const struct dpp_curve_params * dpp_get_curve_jwk_crv(const char *name);
|
||||||
|
const struct dpp_curve_params * dpp_get_curve_nid(int nid);
|
||||||
|
const struct dpp_curve_params * dpp_get_curve_ike_group(u16 group);
|
||||||
|
int dpp_bi_pubkey_hash(struct dpp_bootstrap_info *bi,
|
||||||
|
const u8 *data, size_t data_len);
|
||||||
|
struct wpabuf * dpp_get_pubkey_point(EVP_PKEY *pkey, int prefix);
|
||||||
|
EVP_PKEY * dpp_set_pubkey_point_group(const EC_GROUP *group,
|
||||||
|
const u8 *buf_x, const u8 *buf_y,
|
||||||
|
size_t len);
|
||||||
|
EVP_PKEY * dpp_set_pubkey_point(EVP_PKEY *group_key, const u8 *buf, size_t len);
|
||||||
|
int dpp_bn2bin_pad(const BIGNUM *bn, u8 *pos, size_t len);
|
||||||
|
int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len,
|
||||||
|
const char *label, u8 *out, size_t outlen);
|
||||||
|
int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len,
|
||||||
|
size_t num_elem, const u8 *addr[], const size_t *len,
|
||||||
|
u8 *mac);
|
||||||
|
int dpp_ecdh(EVP_PKEY *own, EVP_PKEY *peer, u8 *secret, size_t *secret_len);
|
||||||
|
void dpp_debug_print_point(const char *title, const EC_GROUP *group,
|
||||||
|
const EC_POINT *point);
|
||||||
|
void dpp_debug_print_key(const char *title, EVP_PKEY *key);
|
||||||
|
int dpp_pbkdf2(size_t hash_len, const u8 *password, size_t password_len,
|
||||||
|
const u8 *salt, size_t salt_len, unsigned int iterations,
|
||||||
|
u8 *buf, size_t buflen);
|
||||||
|
int dpp_get_subject_public_key(struct dpp_bootstrap_info *bi,
|
||||||
|
const u8 *data, size_t data_len);
|
||||||
|
int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi);
|
||||||
|
int dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
|
||||||
|
const u8 *privkey, size_t privkey_len);
|
||||||
|
EVP_PKEY * dpp_set_keypair(const struct dpp_curve_params **curve,
|
||||||
|
const u8 *privkey, size_t privkey_len);
|
||||||
|
EVP_PKEY * dpp_gen_keypair(const struct dpp_curve_params *curve);
|
||||||
|
int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1, unsigned int hash_len);
|
||||||
|
int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, unsigned int hash_len);
|
||||||
|
int dpp_derive_bk_ke(struct dpp_authentication *auth);
|
||||||
|
int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth);
|
||||||
|
int dpp_gen_i_auth(struct dpp_authentication *auth, u8 *i_auth);
|
||||||
|
int dpp_auth_derive_l_responder(struct dpp_authentication *auth);
|
||||||
|
int dpp_auth_derive_l_initiator(struct dpp_authentication *auth);
|
||||||
|
int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk, unsigned int hash_len);
|
||||||
|
int dpp_derive_pmkid(const struct dpp_curve_params *curve,
|
||||||
|
EVP_PKEY *own_key, EVP_PKEY *peer_key, u8 *pmkid);
|
||||||
|
EC_POINT * dpp_pkex_derive_Qi(const struct dpp_curve_params *curve,
|
||||||
|
const u8 *mac_init, const char *code,
|
||||||
|
const char *identifier, BN_CTX *bnctx,
|
||||||
|
EC_GROUP **ret_group);
|
||||||
|
EC_POINT * dpp_pkex_derive_Qr(const struct dpp_curve_params *curve,
|
||||||
|
const u8 *mac_resp, const char *code,
|
||||||
|
const char *identifier, BN_CTX *bnctx,
|
||||||
|
EC_GROUP **ret_group);
|
||||||
|
int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
|
||||||
|
const u8 *Mx, size_t Mx_len,
|
||||||
|
const u8 *Nx, size_t Nx_len,
|
||||||
|
const char *code,
|
||||||
|
const u8 *Kx, size_t Kx_len,
|
||||||
|
u8 *z, unsigned int hash_len);
|
||||||
|
int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth,
|
||||||
|
const u8 *net_access_key,
|
||||||
|
size_t net_access_key_len,
|
||||||
|
struct json_token *peer_net_access_key);
|
||||||
|
int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth,
|
||||||
|
const u8 *r_proto, u16 r_proto_len,
|
||||||
|
struct json_token *net_access_key);
|
||||||
|
EC_POINT * dpp_decrypt_e_id(EVP_PKEY *ppkey, EVP_PKEY *a_nonce,
|
||||||
|
EVP_PKEY *e_prime_id);
|
||||||
|
char * dpp_sign_connector(struct dpp_configurator *conf,
|
||||||
|
const struct wpabuf *dppcon);
|
||||||
|
int dpp_test_gen_invalid_key(struct wpabuf *msg,
|
||||||
|
const struct dpp_curve_params *curve);
|
||||||
|
|
||||||
|
struct dpp_reconfig_id {
|
||||||
|
const EC_GROUP *group;
|
||||||
|
EC_POINT *e_id; /* E-id */
|
||||||
|
EVP_PKEY *csign;
|
||||||
|
EVP_PKEY *a_nonce; /* A-NONCE */
|
||||||
|
EVP_PKEY *e_prime_id; /* E'-id */
|
||||||
|
EVP_PKEY *pp_key;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* dpp_tcp.c */
|
||||||
|
|
||||||
|
void dpp_controller_conn_status_result_wait_timeout(void *eloop_ctx,
|
||||||
|
void *timeout_ctx);
|
||||||
|
void dpp_tcp_init_flush(struct dpp_global *dpp);
|
||||||
|
void dpp_relay_flush_controllers(struct dpp_global *dpp);
|
||||||
|
|
||||||
|
#endif /* CONFIG_DPP */
|
||||||
|
#endif /* DPP_I_H */
|
1324
src/common/dpp_pkex.c
Normal file
1324
src/common/dpp_pkex.c
Normal file
File diff suppressed because it is too large
Load Diff
958
src/common/dpp_reconfig.c
Normal file
958
src/common/dpp_reconfig.c
Normal file
@ -0,0 +1,958 @@
|
|||||||
|
/*
|
||||||
|
* DPP reconfiguration
|
||||||
|
* 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 <openssl/opensslv.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
|
||||||
|
#include "utils/common.h"
|
||||||
|
#include "utils/json.h"
|
||||||
|
#include "crypto/crypto.h"
|
||||||
|
#include "crypto/random.h"
|
||||||
|
#include "crypto/aes.h"
|
||||||
|
#include "crypto/aes_siv.h"
|
||||||
|
#include "dpp.h"
|
||||||
|
#include "dpp_i.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
|
||||||
|
static void dpp_build_attr_csign_key_hash(struct wpabuf *msg, const u8 *hash)
|
||||||
|
{
|
||||||
|
if (hash) {
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Configurator C-sign key Hash");
|
||||||
|
wpabuf_put_le16(msg, DPP_ATTR_C_SIGN_KEY_HASH);
|
||||||
|
wpabuf_put_le16(msg, SHA256_MAC_LEN);
|
||||||
|
wpabuf_put_data(msg, hash, SHA256_MAC_LEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key,
|
||||||
|
size_t csign_key_len,
|
||||||
|
const u8 *net_access_key,
|
||||||
|
size_t net_access_key_len,
|
||||||
|
struct dpp_reconfig_id *id)
|
||||||
|
{
|
||||||
|
struct wpabuf *msg = NULL;
|
||||||
|
EVP_PKEY *csign = NULL;
|
||||||
|
const unsigned char *p;
|
||||||
|
struct wpabuf *uncomp;
|
||||||
|
u8 hash[SHA256_MAC_LEN];
|
||||||
|
const u8 *addr[1];
|
||||||
|
size_t len[1];
|
||||||
|
int res;
|
||||||
|
size_t attr_len;
|
||||||
|
const struct dpp_curve_params *own_curve;
|
||||||
|
EVP_PKEY *own_key;
|
||||||
|
struct wpabuf *a_nonce = NULL, *e_id = NULL;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Build Reconfig Announcement frame");
|
||||||
|
|
||||||
|
own_key = dpp_set_keypair(&own_curve, net_access_key,
|
||||||
|
net_access_key_len);
|
||||||
|
if (!own_key) {
|
||||||
|
wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = csign_key;
|
||||||
|
csign = d2i_PUBKEY(NULL, &p, csign_key_len);
|
||||||
|
if (!csign) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"DPP: Failed to parse local C-sign-key information");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
uncomp = dpp_get_pubkey_point(csign, 1);
|
||||||
|
EVP_PKEY_free(csign);
|
||||||
|
if (!uncomp)
|
||||||
|
goto fail;
|
||||||
|
addr[0] = wpabuf_head(uncomp);
|
||||||
|
len[0] = wpabuf_len(uncomp);
|
||||||
|
wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed C-sign key", addr[0], len[0]);
|
||||||
|
res = sha256_vector(1, addr, len, hash);
|
||||||
|
wpabuf_free(uncomp);
|
||||||
|
if (res < 0)
|
||||||
|
goto fail;
|
||||||
|
wpa_hexdump(MSG_DEBUG, "DPP: kid = SHA256(uncompressed C-sign key)",
|
||||||
|
hash, SHA256_MAC_LEN);
|
||||||
|
|
||||||
|
if (dpp_update_reconfig_id(id) < 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "DPP: Failed to generate E'-id");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
a_nonce = dpp_get_pubkey_point(id->a_nonce, 0);
|
||||||
|
e_id = dpp_get_pubkey_point(id->e_prime_id, 0);
|
||||||
|
if (!a_nonce || !e_id)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
attr_len = 4 + SHA256_MAC_LEN;
|
||||||
|
attr_len += 4 + 2;
|
||||||
|
attr_len += 4 + wpabuf_len(a_nonce);
|
||||||
|
attr_len += 4 + wpabuf_len(e_id);
|
||||||
|
msg = dpp_alloc_msg(DPP_PA_RECONFIG_ANNOUNCEMENT, attr_len);
|
||||||
|
if (!msg)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* Configurator C-sign key Hash */
|
||||||
|
dpp_build_attr_csign_key_hash(msg, hash);
|
||||||
|
|
||||||
|
/* Finite Cyclic Group attribute */
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Finite Cyclic Group: %u",
|
||||||
|
own_curve->ike_group);
|
||||||
|
wpabuf_put_le16(msg, DPP_ATTR_FINITE_CYCLIC_GROUP);
|
||||||
|
wpabuf_put_le16(msg, 2);
|
||||||
|
wpabuf_put_le16(msg, own_curve->ike_group);
|
||||||
|
|
||||||
|
/* A-NONCE */
|
||||||
|
wpabuf_put_le16(msg, DPP_ATTR_A_NONCE);
|
||||||
|
wpabuf_put_le16(msg, wpabuf_len(a_nonce));
|
||||||
|
wpabuf_put_buf(msg, a_nonce);
|
||||||
|
|
||||||
|
/* E'-id */
|
||||||
|
wpabuf_put_le16(msg, DPP_ATTR_E_PRIME_ID);
|
||||||
|
wpabuf_put_le16(msg, wpabuf_len(e_id));
|
||||||
|
wpabuf_put_buf(msg, e_id);
|
||||||
|
|
||||||
|
wpa_hexdump_buf(MSG_DEBUG,
|
||||||
|
"DPP: Reconfig Announcement frame attributes", msg);
|
||||||
|
fail:
|
||||||
|
wpabuf_free(a_nonce);
|
||||||
|
wpabuf_free(e_id);
|
||||||
|
EVP_PKEY_free(own_key);
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct wpabuf * dpp_reconfig_build_req(struct dpp_authentication *auth)
|
||||||
|
{
|
||||||
|
struct wpabuf *msg;
|
||||||
|
size_t attr_len;
|
||||||
|
|
||||||
|
/* Build DPP Reconfig Authentication Request frame attributes */
|
||||||
|
attr_len = 4 + 1 + 4 + 1 + 4 + os_strlen(auth->conf->connector) +
|
||||||
|
4 + auth->curve->nonce_len;
|
||||||
|
msg = dpp_alloc_msg(DPP_PA_RECONFIG_AUTH_REQ, attr_len);
|
||||||
|
if (!msg)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Transaction ID */
|
||||||
|
wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
|
||||||
|
wpabuf_put_le16(msg, 1);
|
||||||
|
wpabuf_put_u8(msg, auth->transaction_id);
|
||||||
|
|
||||||
|
/* Protocol Version */
|
||||||
|
wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
|
||||||
|
wpabuf_put_le16(msg, 1);
|
||||||
|
wpabuf_put_u8(msg, DPP_VERSION);
|
||||||
|
|
||||||
|
/* DPP Connector */
|
||||||
|
wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
|
||||||
|
wpabuf_put_le16(msg, os_strlen(auth->conf->connector));
|
||||||
|
wpabuf_put_str(msg, auth->conf->connector);
|
||||||
|
|
||||||
|
/* C-nonce */
|
||||||
|
wpabuf_put_le16(msg, DPP_ATTR_CONFIGURATOR_NONCE);
|
||||||
|
wpabuf_put_le16(msg, auth->curve->nonce_len);
|
||||||
|
wpabuf_put_data(msg, auth->c_nonce, auth->curve->nonce_len);
|
||||||
|
|
||||||
|
wpa_hexdump_buf(MSG_DEBUG,
|
||||||
|
"DPP: Reconfig Authentication Request frame attributes",
|
||||||
|
msg);
|
||||||
|
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
dpp_configurator_build_own_connector(struct dpp_configurator *conf,
|
||||||
|
const struct dpp_curve_params *curve)
|
||||||
|
{
|
||||||
|
struct wpabuf *dppcon = NULL;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (conf->connector)
|
||||||
|
return 0; /* already generated */
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: Sign own Configurator Connector for reconfiguration with curve %s",
|
||||||
|
conf->curve->name);
|
||||||
|
conf->connector_key = dpp_gen_keypair(curve);
|
||||||
|
if (!conf->connector_key)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* Connector (JSON dppCon object) */
|
||||||
|
dppcon = wpabuf_alloc(1000 + 2 * curve->prime_len * 4 / 3);
|
||||||
|
if (!dppcon)
|
||||||
|
goto fail;
|
||||||
|
json_start_object(dppcon, NULL);
|
||||||
|
json_start_array(dppcon, "groups");
|
||||||
|
json_start_object(dppcon, NULL);
|
||||||
|
json_add_string(dppcon, "groupId", "*");
|
||||||
|
json_value_sep(dppcon);
|
||||||
|
json_add_string(dppcon, "netRole", "configurator");
|
||||||
|
json_end_object(dppcon);
|
||||||
|
json_end_array(dppcon);
|
||||||
|
json_value_sep(dppcon);
|
||||||
|
if (dpp_build_jwk(dppcon, "netAccessKey", conf->connector_key, NULL,
|
||||||
|
curve) < 0) {
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Failed to build netAccessKey JWK");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
json_end_object(dppcon);
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: dppCon: %s",
|
||||||
|
(const char *) wpabuf_head(dppcon));
|
||||||
|
|
||||||
|
conf->connector = dpp_sign_connector(conf, dppcon);
|
||||||
|
if (!conf->connector)
|
||||||
|
goto fail;
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: signedConnector: %s", conf->connector);
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
fail:
|
||||||
|
wpabuf_free(dppcon);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct dpp_authentication *
|
||||||
|
dpp_reconfig_init(struct dpp_global *dpp, void *msg_ctx,
|
||||||
|
struct dpp_configurator *conf, unsigned int freq, u16 group,
|
||||||
|
const u8 *a_nonce_attr, size_t a_nonce_len,
|
||||||
|
const u8 *e_id_attr, size_t e_id_len)
|
||||||
|
{
|
||||||
|
struct dpp_authentication *auth;
|
||||||
|
const struct dpp_curve_params *curve;
|
||||||
|
EVP_PKEY *a_nonce, *e_prime_id;
|
||||||
|
EC_POINT *e_id;
|
||||||
|
|
||||||
|
curve = dpp_get_curve_ike_group(group);
|
||||||
|
if (!curve) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: Unsupported group %u - cannot reconfigure",
|
||||||
|
group);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!a_nonce_attr) {
|
||||||
|
wpa_printf(MSG_INFO, "DPP: Missing required A-NONCE attribute");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
wpa_hexdump(MSG_MSGDUMP, "DPP: A-NONCE", a_nonce_attr, a_nonce_len);
|
||||||
|
a_nonce = dpp_set_pubkey_point(conf->csign, a_nonce_attr, a_nonce_len);
|
||||||
|
if (!a_nonce) {
|
||||||
|
wpa_printf(MSG_INFO, "DPP: Invalid A-NONCE");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
dpp_debug_print_key("A-NONCE", a_nonce);
|
||||||
|
|
||||||
|
if (!e_id_attr) {
|
||||||
|
wpa_printf(MSG_INFO, "DPP: Missing required E'-id attribute");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
e_prime_id = dpp_set_pubkey_point(conf->csign, e_id_attr, e_id_len);
|
||||||
|
if (!e_prime_id) {
|
||||||
|
wpa_printf(MSG_INFO, "DPP: Invalid E'-id");
|
||||||
|
EVP_PKEY_free(a_nonce);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
dpp_debug_print_key("E'-id", e_prime_id);
|
||||||
|
e_id = dpp_decrypt_e_id(conf->pp_key, a_nonce, e_prime_id);
|
||||||
|
EVP_PKEY_free(a_nonce);
|
||||||
|
EVP_PKEY_free(e_prime_id);
|
||||||
|
if (!e_id) {
|
||||||
|
wpa_printf(MSG_INFO, "DPP: Could not decrypt E'-id");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* TODO: could use E-id to determine whether reconfiguration with this
|
||||||
|
* Enrollee has already been started and is waiting for updated
|
||||||
|
* configuration instead of replying again before such configuration
|
||||||
|
* becomes available */
|
||||||
|
EC_POINT_clear_free(e_id);
|
||||||
|
|
||||||
|
auth = dpp_alloc_auth(dpp, msg_ctx);
|
||||||
|
if (!auth)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
auth->conf = conf;
|
||||||
|
auth->reconfig = 1;
|
||||||
|
auth->initiator = 1;
|
||||||
|
auth->waiting_auth_resp = 1;
|
||||||
|
auth->allowed_roles = DPP_CAPAB_CONFIGURATOR;
|
||||||
|
auth->configurator = 1;
|
||||||
|
auth->curve = curve;
|
||||||
|
auth->transaction_id = 1;
|
||||||
|
if (freq && dpp_prepare_channel_list(auth, freq, NULL, 0) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (dpp_configurator_build_own_connector(conf, curve) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (random_get_bytes(auth->c_nonce, auth->curve->nonce_len)) {
|
||||||
|
wpa_printf(MSG_ERROR, "DPP: Failed to generate C-nonce");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
auth->reconfig_req_msg = dpp_reconfig_build_req(auth);
|
||||||
|
if (!auth->reconfig_req_msg)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
out:
|
||||||
|
return auth;
|
||||||
|
fail:
|
||||||
|
dpp_auth_deinit(auth);
|
||||||
|
auth = NULL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int dpp_reconfig_build_resp(struct dpp_authentication *auth,
|
||||||
|
const char *own_connector,
|
||||||
|
struct wpabuf *conn_status)
|
||||||
|
{
|
||||||
|
struct wpabuf *msg = NULL, *clear, *pr = NULL;
|
||||||
|
u8 *attr_start, *attr_end;
|
||||||
|
size_t clear_len, attr_len, len[2];
|
||||||
|
const u8 *addr[2];
|
||||||
|
u8 *wrapped;
|
||||||
|
int res = -1;
|
||||||
|
|
||||||
|
/* Build DPP Reconfig Authentication Response frame attributes */
|
||||||
|
clear_len = 4 + auth->curve->nonce_len +
|
||||||
|
4 + wpabuf_len(conn_status);
|
||||||
|
clear = wpabuf_alloc(clear_len);
|
||||||
|
if (!clear)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* C-nonce (wrapped) */
|
||||||
|
wpabuf_put_le16(clear, DPP_ATTR_CONFIGURATOR_NONCE);
|
||||||
|
wpabuf_put_le16(clear, auth->curve->nonce_len);
|
||||||
|
wpabuf_put_data(clear, auth->c_nonce, auth->curve->nonce_len);
|
||||||
|
|
||||||
|
/* Connection Status (wrapped) */
|
||||||
|
wpabuf_put_le16(clear, DPP_ATTR_CONN_STATUS);
|
||||||
|
wpabuf_put_le16(clear, wpabuf_len(conn_status));
|
||||||
|
wpabuf_put_buf(clear, conn_status);
|
||||||
|
|
||||||
|
pr = dpp_get_pubkey_point(auth->own_protocol_key, 0);
|
||||||
|
if (!pr)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
attr_len = 4 + 1 + 4 + 1 +
|
||||||
|
4 + os_strlen(own_connector) +
|
||||||
|
4 + auth->curve->nonce_len +
|
||||||
|
4 + wpabuf_len(pr) +
|
||||||
|
4 + wpabuf_len(clear) + AES_BLOCK_SIZE;
|
||||||
|
msg = dpp_alloc_msg(DPP_PA_RECONFIG_AUTH_RESP, attr_len);
|
||||||
|
if (!msg)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
attr_start = wpabuf_put(msg, 0);
|
||||||
|
|
||||||
|
/* Transaction ID */
|
||||||
|
wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
|
||||||
|
wpabuf_put_le16(msg, 1);
|
||||||
|
wpabuf_put_u8(msg, auth->transaction_id);
|
||||||
|
|
||||||
|
/* Protocol Version */
|
||||||
|
wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
|
||||||
|
wpabuf_put_le16(msg, 1);
|
||||||
|
wpabuf_put_u8(msg, DPP_VERSION);
|
||||||
|
|
||||||
|
/* R-Connector */
|
||||||
|
wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
|
||||||
|
wpabuf_put_le16(msg, os_strlen(own_connector));
|
||||||
|
wpabuf_put_str(msg, own_connector);
|
||||||
|
|
||||||
|
/* E-nonce */
|
||||||
|
wpabuf_put_le16(msg, DPP_ATTR_ENROLLEE_NONCE);
|
||||||
|
wpabuf_put_le16(msg, auth->curve->nonce_len);
|
||||||
|
wpabuf_put_data(msg, auth->e_nonce, auth->curve->nonce_len);
|
||||||
|
|
||||||
|
/* Responder Protocol Key (Pr) */
|
||||||
|
wpabuf_put_le16(msg, DPP_ATTR_R_PROTOCOL_KEY);
|
||||||
|
wpabuf_put_le16(msg, wpabuf_len(pr));
|
||||||
|
wpabuf_put_buf(msg, pr);
|
||||||
|
|
||||||
|
attr_end = wpabuf_put(msg, 0);
|
||||||
|
|
||||||
|
/* OUI, OUI type, Crypto Suite, DPP frame type */
|
||||||
|
addr[0] = wpabuf_head_u8(msg) + 2;
|
||||||
|
len[0] = 3 + 1 + 1 + 1;
|
||||||
|
wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
|
||||||
|
|
||||||
|
/* Attributes before Wrapped Data */
|
||||||
|
addr[1] = attr_start;
|
||||||
|
len[1] = attr_end - attr_start;
|
||||||
|
wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
|
||||||
|
|
||||||
|
/* Wrapped Data: {C-nonce, E-nonce, Connection Status}ke */
|
||||||
|
wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
|
||||||
|
wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
|
||||||
|
wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
|
||||||
|
|
||||||
|
wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
|
||||||
|
if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
|
||||||
|
wpabuf_head(clear), wpabuf_len(clear),
|
||||||
|
2, addr, len, wrapped) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
wpa_hexdump_buf(MSG_DEBUG,
|
||||||
|
"DPP: Reconfig Authentication Response frame attributes",
|
||||||
|
msg);
|
||||||
|
|
||||||
|
wpabuf_free(auth->reconfig_resp_msg);
|
||||||
|
auth->reconfig_resp_msg = msg;
|
||||||
|
|
||||||
|
res = 0;
|
||||||
|
out:
|
||||||
|
wpabuf_free(clear);
|
||||||
|
wpabuf_free(pr);
|
||||||
|
return res;
|
||||||
|
fail:
|
||||||
|
wpabuf_free(msg);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct dpp_authentication *
|
||||||
|
dpp_reconfig_auth_req_rx(struct dpp_global *dpp, void *msg_ctx,
|
||||||
|
const char *own_connector,
|
||||||
|
const u8 *net_access_key, size_t net_access_key_len,
|
||||||
|
const u8 *csign_key, size_t csign_key_len,
|
||||||
|
unsigned int freq, const u8 *hdr,
|
||||||
|
const u8 *attr_start, size_t attr_len)
|
||||||
|
{
|
||||||
|
struct dpp_authentication *auth = NULL;
|
||||||
|
const u8 *trans_id, *version, *i_connector, *c_nonce;
|
||||||
|
u16 trans_id_len, version_len, i_connector_len, c_nonce_len;
|
||||||
|
struct dpp_signed_connector_info info;
|
||||||
|
enum dpp_status_error res;
|
||||||
|
struct json_token *root = NULL, *own_root = NULL, *token;
|
||||||
|
unsigned char *own_conn = NULL;
|
||||||
|
struct wpabuf *conn_status = NULL;
|
||||||
|
|
||||||
|
os_memset(&info, 0, sizeof(info));
|
||||||
|
|
||||||
|
trans_id = dpp_get_attr(attr_start, attr_len, DPP_ATTR_TRANSACTION_ID,
|
||||||
|
&trans_id_len);
|
||||||
|
if (!trans_id || trans_id_len != 1) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: Peer did not include Transaction ID");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
version = dpp_get_attr(attr_start, attr_len, DPP_ATTR_PROTOCOL_VERSION,
|
||||||
|
&version_len);
|
||||||
|
if (!version || version_len < 1 || version[0] < 2) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: Missing or invalid Protocol Version attribute");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
i_connector = dpp_get_attr(attr_start, attr_len, DPP_ATTR_CONNECTOR,
|
||||||
|
&i_connector_len);
|
||||||
|
if (!i_connector) {
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Missing I-Connector attribute");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
wpa_hexdump_ascii(MSG_DEBUG, "DPP: I-Connector",
|
||||||
|
i_connector, i_connector_len);
|
||||||
|
|
||||||
|
c_nonce = dpp_get_attr(attr_start, attr_len,
|
||||||
|
DPP_ATTR_CONFIGURATOR_NONCE, &c_nonce_len);
|
||||||
|
if (!c_nonce || c_nonce_len > DPP_MAX_NONCE_LEN) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: Missing or invalid C-nonce attribute");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
wpa_hexdump(MSG_DEBUG, "DPP: C-nonce", c_nonce, c_nonce_len);
|
||||||
|
|
||||||
|
res = dpp_check_signed_connector(&info, csign_key, csign_key_len,
|
||||||
|
i_connector, i_connector_len);
|
||||||
|
if (res != DPP_STATUS_OK) {
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Invalid I-Connector");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
root = json_parse((const char *) info.payload, info.payload_len);
|
||||||
|
own_root = dpp_parse_own_connector(own_connector);
|
||||||
|
if (!root || !own_root ||
|
||||||
|
!dpp_connector_match_groups(own_root, root, true)) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: I-Connector does not include compatible group netrole with own connector");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
token = json_get_member(root, "expiry");
|
||||||
|
if (token && token->type == JSON_STRING &&
|
||||||
|
dpp_key_expired(token->string, NULL)) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: I-Connector (netAccessKey) has expired");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
token = json_get_member(root, "netAccessKey");
|
||||||
|
if (!token || token->type != JSON_OBJECT) {
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
auth = dpp_alloc_auth(dpp, msg_ctx);
|
||||||
|
if (!auth)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
auth->reconfig = 1;
|
||||||
|
auth->allowed_roles = DPP_CAPAB_ENROLLEE;
|
||||||
|
if (dpp_prepare_channel_list(auth, freq, NULL, 0) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
auth->transaction_id = trans_id[0];
|
||||||
|
|
||||||
|
auth->peer_version = version[0];
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u",
|
||||||
|
auth->peer_version);
|
||||||
|
|
||||||
|
os_memcpy(auth->c_nonce, c_nonce, c_nonce_len);
|
||||||
|
|
||||||
|
if (dpp_reconfig_derive_ke_responder(auth, net_access_key,
|
||||||
|
net_access_key_len, token) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (c_nonce_len != auth->curve->nonce_len) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: Unexpected C-nonce length %u (curve nonce len %zu)",
|
||||||
|
c_nonce_len, auth->curve->nonce_len);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build Connection Status object */
|
||||||
|
/* TODO: Get appropriate result value */
|
||||||
|
/* TODO: ssid64 and channelList */
|
||||||
|
conn_status = dpp_build_conn_status(DPP_STATUS_NO_AP, NULL, 0, NULL);
|
||||||
|
if (!conn_status)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (dpp_reconfig_build_resp(auth, own_connector, conn_status) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
out:
|
||||||
|
os_free(info.payload);
|
||||||
|
os_free(own_conn);
|
||||||
|
json_free(root);
|
||||||
|
json_free(own_root);
|
||||||
|
wpabuf_free(conn_status);
|
||||||
|
return auth;
|
||||||
|
fail:
|
||||||
|
dpp_auth_deinit(auth);
|
||||||
|
auth = NULL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct wpabuf *
|
||||||
|
dpp_reconfig_build_conf(struct dpp_authentication *auth)
|
||||||
|
{
|
||||||
|
struct wpabuf *msg = NULL, *clear;
|
||||||
|
u8 *attr_start, *attr_end;
|
||||||
|
size_t clear_len, attr_len, len[2];
|
||||||
|
const u8 *addr[2];
|
||||||
|
u8 *wrapped;
|
||||||
|
u8 flags;
|
||||||
|
|
||||||
|
/* Build DPP Reconfig Authentication Confirm frame attributes */
|
||||||
|
clear_len = 4 + 1 + 4 + 1 + 2 * (4 + auth->curve->nonce_len) +
|
||||||
|
4 + 1;
|
||||||
|
clear = wpabuf_alloc(clear_len);
|
||||||
|
if (!clear)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* Transaction ID */
|
||||||
|
wpabuf_put_le16(clear, DPP_ATTR_TRANSACTION_ID);
|
||||||
|
wpabuf_put_le16(clear, 1);
|
||||||
|
wpabuf_put_u8(clear, auth->transaction_id);
|
||||||
|
|
||||||
|
/* Protocol Version */
|
||||||
|
wpabuf_put_le16(clear, DPP_ATTR_PROTOCOL_VERSION);
|
||||||
|
wpabuf_put_le16(clear, 1);
|
||||||
|
wpabuf_put_u8(clear, auth->peer_version);
|
||||||
|
|
||||||
|
/* C-nonce (wrapped) */
|
||||||
|
wpabuf_put_le16(clear, DPP_ATTR_CONFIGURATOR_NONCE);
|
||||||
|
wpabuf_put_le16(clear, auth->curve->nonce_len);
|
||||||
|
wpabuf_put_data(clear, auth->c_nonce, auth->curve->nonce_len);
|
||||||
|
|
||||||
|
/* E-nonce (wrapped) */
|
||||||
|
wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
|
||||||
|
wpabuf_put_le16(clear, auth->curve->nonce_len);
|
||||||
|
wpabuf_put_data(clear, auth->e_nonce, auth->curve->nonce_len);
|
||||||
|
|
||||||
|
/* Reconfig-Flags (wrapped) */
|
||||||
|
flags = DPP_CONFIG_REPLACEKEY;
|
||||||
|
wpabuf_put_le16(clear, DPP_ATTR_RECONFIG_FLAGS);
|
||||||
|
wpabuf_put_le16(clear, 1);
|
||||||
|
wpabuf_put_u8(clear, flags);
|
||||||
|
|
||||||
|
attr_len = 4 + wpabuf_len(clear) + AES_BLOCK_SIZE;
|
||||||
|
attr_len += 4 + 1;
|
||||||
|
msg = dpp_alloc_msg(DPP_PA_RECONFIG_AUTH_CONF, attr_len);
|
||||||
|
if (!msg)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
attr_start = wpabuf_put(msg, 0);
|
||||||
|
|
||||||
|
/* DPP Status */
|
||||||
|
dpp_build_attr_status(msg, DPP_STATUS_OK);
|
||||||
|
|
||||||
|
attr_end = wpabuf_put(msg, 0);
|
||||||
|
|
||||||
|
/* OUI, OUI type, Crypto Suite, DPP frame type */
|
||||||
|
addr[0] = wpabuf_head_u8(msg) + 2;
|
||||||
|
len[0] = 3 + 1 + 1 + 1;
|
||||||
|
wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
|
||||||
|
|
||||||
|
/* Attributes before Wrapped Data */
|
||||||
|
addr[1] = attr_start;
|
||||||
|
len[1] = attr_end - attr_start;
|
||||||
|
wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
|
||||||
|
|
||||||
|
/* Wrapped Data */
|
||||||
|
wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
|
||||||
|
wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
|
||||||
|
wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
|
||||||
|
|
||||||
|
wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
|
||||||
|
if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
|
||||||
|
wpabuf_head(clear), wpabuf_len(clear),
|
||||||
|
2, addr, len, wrapped) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
wpa_hexdump_buf(MSG_DEBUG,
|
||||||
|
"DPP: Reconfig Authentication Confirm frame attributes",
|
||||||
|
msg);
|
||||||
|
|
||||||
|
out:
|
||||||
|
wpabuf_free(clear);
|
||||||
|
return msg;
|
||||||
|
fail:
|
||||||
|
wpabuf_free(msg);
|
||||||
|
msg = NULL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct wpabuf *
|
||||||
|
dpp_reconfig_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr,
|
||||||
|
const u8 *attr_start, size_t attr_len)
|
||||||
|
{
|
||||||
|
const u8 *trans_id, *version, *r_connector, *r_proto, *wrapped_data,
|
||||||
|
*c_nonce, *e_nonce, *conn_status;
|
||||||
|
u16 trans_id_len, version_len, r_connector_len, r_proto_len,
|
||||||
|
wrapped_data_len, c_nonce_len, e_nonce_len, conn_status_len;
|
||||||
|
struct wpabuf *conf = NULL;
|
||||||
|
char *signed_connector = NULL;
|
||||||
|
struct dpp_signed_connector_info info;
|
||||||
|
enum dpp_status_error res;
|
||||||
|
struct json_token *root = NULL, *token, *conn_status_json = NULL;
|
||||||
|
const u8 *addr[2];
|
||||||
|
size_t len[2];
|
||||||
|
u8 *unwrapped = NULL;
|
||||||
|
size_t unwrapped_len = 0;
|
||||||
|
|
||||||
|
os_memset(&info, 0, sizeof(info));
|
||||||
|
|
||||||
|
if (!auth->reconfig || !auth->configurator)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
|
||||||
|
&wrapped_data_len);
|
||||||
|
if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
|
||||||
|
dpp_auth_fail(auth,
|
||||||
|
"Missing or invalid required Wrapped Data attribute");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
wpa_hexdump(MSG_MSGDUMP, "DPP: Wrapped Data",
|
||||||
|
wrapped_data, wrapped_data_len);
|
||||||
|
attr_len = wrapped_data - 4 - attr_start;
|
||||||
|
|
||||||
|
trans_id = dpp_get_attr(attr_start, attr_len, DPP_ATTR_TRANSACTION_ID,
|
||||||
|
&trans_id_len);
|
||||||
|
if (!trans_id || trans_id_len != 1) {
|
||||||
|
dpp_auth_fail(auth, "Peer did not include Transaction ID");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (trans_id[0] != auth->transaction_id) {
|
||||||
|
dpp_auth_fail(auth, "Transaction ID mismatch");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
version = dpp_get_attr(attr_start, attr_len, DPP_ATTR_PROTOCOL_VERSION,
|
||||||
|
&version_len);
|
||||||
|
if (!version || version_len < 1 || version[0] < 2) {
|
||||||
|
dpp_auth_fail(auth,
|
||||||
|
"Missing or invalid Protocol Version attribute");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
auth->peer_version = version[0];
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u",
|
||||||
|
auth->peer_version);
|
||||||
|
|
||||||
|
r_connector = dpp_get_attr(attr_start, attr_len, DPP_ATTR_CONNECTOR,
|
||||||
|
&r_connector_len);
|
||||||
|
if (!r_connector) {
|
||||||
|
dpp_auth_fail(auth, " Missing R-Connector attribute");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
wpa_hexdump_ascii(MSG_DEBUG, "DPP: R-Connector",
|
||||||
|
r_connector, r_connector_len);
|
||||||
|
|
||||||
|
e_nonce = dpp_get_attr(attr_start, attr_len,
|
||||||
|
DPP_ATTR_ENROLLEE_NONCE, &e_nonce_len);
|
||||||
|
if (!e_nonce || e_nonce_len != auth->curve->nonce_len) {
|
||||||
|
dpp_auth_fail(auth, "Missing or invalid E-nonce");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
wpa_hexdump(MSG_DEBUG, "DPP: E-nonce", e_nonce, e_nonce_len);
|
||||||
|
os_memcpy(auth->e_nonce, e_nonce, e_nonce_len);
|
||||||
|
|
||||||
|
r_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_R_PROTOCOL_KEY,
|
||||||
|
&r_proto_len);
|
||||||
|
if (!r_proto) {
|
||||||
|
dpp_auth_fail(auth,
|
||||||
|
"Missing required Responder Protocol Key attribute");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Protocol Key",
|
||||||
|
r_proto, r_proto_len);
|
||||||
|
|
||||||
|
signed_connector = os_malloc(r_connector_len + 1);
|
||||||
|
if (!signed_connector)
|
||||||
|
goto fail;
|
||||||
|
os_memcpy(signed_connector, r_connector, r_connector_len);
|
||||||
|
signed_connector[r_connector_len] = '\0';
|
||||||
|
|
||||||
|
res = dpp_process_signed_connector(&info, auth->conf->csign,
|
||||||
|
signed_connector);
|
||||||
|
if (res != DPP_STATUS_OK) {
|
||||||
|
dpp_auth_fail(auth, "Invalid R-Connector");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
root = json_parse((const char *) info.payload, info.payload_len);
|
||||||
|
if (!root) {
|
||||||
|
dpp_auth_fail(auth, "Invalid Connector payload");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do not check netAccessKey expiration for reconfiguration to allow
|
||||||
|
* expired Connector to be updated. */
|
||||||
|
|
||||||
|
token = json_get_member(root, "netAccessKey");
|
||||||
|
if (!token || token->type != JSON_OBJECT) {
|
||||||
|
dpp_auth_fail(auth, "No netAccessKey object found");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dpp_reconfig_derive_ke_initiator(auth, r_proto, r_proto_len,
|
||||||
|
token) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
addr[0] = hdr;
|
||||||
|
len[0] = DPP_HDR_LEN;
|
||||||
|
addr[1] = attr_start;
|
||||||
|
len[1] = attr_len;
|
||||||
|
wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
|
||||||
|
wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
|
||||||
|
wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
|
||||||
|
wrapped_data, wrapped_data_len);
|
||||||
|
unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
|
||||||
|
unwrapped = os_malloc(unwrapped_len);
|
||||||
|
if (!unwrapped)
|
||||||
|
goto fail;
|
||||||
|
if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
|
||||||
|
wrapped_data, wrapped_data_len,
|
||||||
|
2, addr, len, unwrapped) < 0) {
|
||||||
|
dpp_auth_fail(auth, "AES-SIV decryption failed");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
|
||||||
|
unwrapped, unwrapped_len);
|
||||||
|
|
||||||
|
if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
|
||||||
|
dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
c_nonce = dpp_get_attr(unwrapped, unwrapped_len,
|
||||||
|
DPP_ATTR_CONFIGURATOR_NONCE, &c_nonce_len);
|
||||||
|
if (!c_nonce || c_nonce_len != auth->curve->nonce_len ||
|
||||||
|
os_memcmp(c_nonce, auth->c_nonce, c_nonce_len) != 0) {
|
||||||
|
dpp_auth_fail(auth, "Missing or invalid C-nonce");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
wpa_hexdump(MSG_DEBUG, "DPP: C-nonce", c_nonce, c_nonce_len);
|
||||||
|
|
||||||
|
conn_status = dpp_get_attr(unwrapped, unwrapped_len,
|
||||||
|
DPP_ATTR_CONN_STATUS, &conn_status_len);
|
||||||
|
if (!conn_status) {
|
||||||
|
dpp_auth_fail(auth, "Missing Connection Status attribute");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
wpa_hexdump_ascii(MSG_DEBUG, "DPP: connStatus",
|
||||||
|
conn_status, conn_status_len);
|
||||||
|
|
||||||
|
conn_status_json = json_parse((const char *) conn_status,
|
||||||
|
conn_status_len);
|
||||||
|
if (!conn_status_json) {
|
||||||
|
dpp_auth_fail(auth, "Could not parse connStatus");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
/* TODO: use connStatus information */
|
||||||
|
|
||||||
|
conf = dpp_reconfig_build_conf(auth);
|
||||||
|
if (conf)
|
||||||
|
auth->reconfig_success = true;
|
||||||
|
|
||||||
|
out:
|
||||||
|
json_free(root);
|
||||||
|
json_free(conn_status_json);
|
||||||
|
bin_clear_free(unwrapped, unwrapped_len);
|
||||||
|
os_free(info.payload);
|
||||||
|
os_free(signed_connector);
|
||||||
|
return conf;
|
||||||
|
fail:
|
||||||
|
wpabuf_free(conf);
|
||||||
|
conf = NULL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int dpp_reconfig_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr,
|
||||||
|
const u8 *attr_start, size_t attr_len)
|
||||||
|
{
|
||||||
|
const u8 *trans_id, *version, *wrapped_data, *c_nonce, *e_nonce,
|
||||||
|
*reconfig_flags, *status;
|
||||||
|
u16 trans_id_len, version_len, wrapped_data_len, c_nonce_len,
|
||||||
|
e_nonce_len, reconfig_flags_len, status_len;
|
||||||
|
const u8 *addr[2];
|
||||||
|
size_t len[2];
|
||||||
|
u8 *unwrapped = NULL;
|
||||||
|
size_t unwrapped_len = 0;
|
||||||
|
int res = -1;
|
||||||
|
u8 flags;
|
||||||
|
|
||||||
|
if (!auth->reconfig || auth->configurator)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
|
||||||
|
&wrapped_data_len);
|
||||||
|
if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
|
||||||
|
dpp_auth_fail(auth,
|
||||||
|
"Missing or invalid required Wrapped Data attribute");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
wpa_hexdump(MSG_MSGDUMP, "DPP: Wrapped Data",
|
||||||
|
wrapped_data, wrapped_data_len);
|
||||||
|
attr_len = wrapped_data - 4 - attr_start;
|
||||||
|
|
||||||
|
status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS,
|
||||||
|
&status_len);
|
||||||
|
if (!status || status_len < 1) {
|
||||||
|
dpp_auth_fail(auth,
|
||||||
|
"Missing or invalid required DPP Status attribute");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
|
||||||
|
if (status[0] != DPP_STATUS_OK) {
|
||||||
|
dpp_auth_fail(auth,
|
||||||
|
"Reconfiguration did not complete successfully");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr[0] = hdr;
|
||||||
|
len[0] = DPP_HDR_LEN;
|
||||||
|
addr[1] = attr_start;
|
||||||
|
len[1] = attr_len;
|
||||||
|
wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
|
||||||
|
wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
|
||||||
|
wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
|
||||||
|
wrapped_data, wrapped_data_len);
|
||||||
|
unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
|
||||||
|
unwrapped = os_malloc(unwrapped_len);
|
||||||
|
if (!unwrapped)
|
||||||
|
goto fail;
|
||||||
|
if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
|
||||||
|
wrapped_data, wrapped_data_len,
|
||||||
|
2, addr, len, unwrapped) < 0) {
|
||||||
|
dpp_auth_fail(auth, "AES-SIV decryption failed");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
|
||||||
|
unwrapped, unwrapped_len);
|
||||||
|
|
||||||
|
if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
|
||||||
|
dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
trans_id = dpp_get_attr(unwrapped, unwrapped_len,
|
||||||
|
DPP_ATTR_TRANSACTION_ID, &trans_id_len);
|
||||||
|
if (!trans_id || trans_id_len != 1 ||
|
||||||
|
trans_id[0] != auth->transaction_id) {
|
||||||
|
dpp_auth_fail(auth,
|
||||||
|
"Peer did not include valid Transaction ID");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
version = dpp_get_attr(unwrapped, unwrapped_len,
|
||||||
|
DPP_ATTR_PROTOCOL_VERSION, &version_len);
|
||||||
|
if (!version || version_len < 1 || version[0] != DPP_VERSION) {
|
||||||
|
dpp_auth_fail(auth,
|
||||||
|
"Missing or invalid Protocol Version attribute");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
c_nonce = dpp_get_attr(unwrapped, unwrapped_len,
|
||||||
|
DPP_ATTR_CONFIGURATOR_NONCE, &c_nonce_len);
|
||||||
|
if (!c_nonce || c_nonce_len != auth->curve->nonce_len ||
|
||||||
|
os_memcmp(c_nonce, auth->c_nonce, c_nonce_len) != 0) {
|
||||||
|
dpp_auth_fail(auth, "Missing or invalid C-nonce");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
wpa_hexdump(MSG_DEBUG, "DPP: C-nonce", c_nonce, c_nonce_len);
|
||||||
|
|
||||||
|
e_nonce = dpp_get_attr(unwrapped, unwrapped_len,
|
||||||
|
DPP_ATTR_ENROLLEE_NONCE, &e_nonce_len);
|
||||||
|
if (!e_nonce || e_nonce_len != auth->curve->nonce_len ||
|
||||||
|
os_memcmp(e_nonce, auth->e_nonce, e_nonce_len) != 0) {
|
||||||
|
dpp_auth_fail(auth, "Missing or invalid E-nonce");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
wpa_hexdump(MSG_DEBUG, "DPP: E-nonce", e_nonce, e_nonce_len);
|
||||||
|
|
||||||
|
reconfig_flags = dpp_get_attr(unwrapped, unwrapped_len,
|
||||||
|
DPP_ATTR_RECONFIG_FLAGS,
|
||||||
|
&reconfig_flags_len);
|
||||||
|
if (!reconfig_flags || reconfig_flags_len < 1) {
|
||||||
|
dpp_auth_fail(auth, "Missing or invalid Reconfig-Flags");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
flags = reconfig_flags[0] & BIT(0);
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Reconfig Flags connectorKey=%u", flags);
|
||||||
|
auth->reconfig_connector_key = flags;
|
||||||
|
|
||||||
|
auth->reconfig_success = true;
|
||||||
|
res = 0;
|
||||||
|
fail:
|
||||||
|
bin_clear_free(unwrapped, unwrapped_len);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_DPP2 */
|
1794
src/common/dpp_tcp.c
Normal file
1794
src/common/dpp_tcp.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Generic advertisement service (GAS) server
|
* Generic advertisement service (GAS) server
|
||||||
* Copyright (c) 2017, Qualcomm Atheros, Inc.
|
* Copyright (c) 2017, Qualcomm Atheros, Inc.
|
||||||
|
* Copyright (c) 2020, The Linux Foundation
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* See README for more details.
|
||||||
@ -23,8 +24,9 @@ struct gas_server_handler {
|
|||||||
struct dl_list list;
|
struct dl_list list;
|
||||||
u8 adv_proto_id[MAX_ADV_PROTO_ID_LEN];
|
u8 adv_proto_id[MAX_ADV_PROTO_ID_LEN];
|
||||||
u8 adv_proto_id_len;
|
u8 adv_proto_id_len;
|
||||||
struct wpabuf * (*req_cb)(void *ctx, const u8 *sa,
|
struct wpabuf * (*req_cb)(void *ctx, void *resp_ctx, const u8 *sa,
|
||||||
const u8 *query, size_t query_len);
|
const u8 *query, size_t query_len,
|
||||||
|
u16 *comeback_delay);
|
||||||
void (*status_cb)(void *ctx, struct wpabuf *resp, int ok);
|
void (*status_cb)(void *ctx, struct wpabuf *resp, int ok);
|
||||||
void *ctx;
|
void *ctx;
|
||||||
struct gas_server *gas;
|
struct gas_server *gas;
|
||||||
@ -39,6 +41,7 @@ struct gas_server_response {
|
|||||||
u8 dst[ETH_ALEN];
|
u8 dst[ETH_ALEN];
|
||||||
u8 dialog_token;
|
u8 dialog_token;
|
||||||
struct gas_server_handler *handler;
|
struct gas_server_handler *handler;
|
||||||
|
u16 comeback_delay;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct gas_server {
|
struct gas_server {
|
||||||
@ -61,7 +64,8 @@ static void gas_server_response_timeout(void *eloop_ctx, void *user_ctx)
|
|||||||
response, MAC2STR(response->dst), response->dialog_token,
|
response, MAC2STR(response->dst), response->dialog_token,
|
||||||
response->freq, response->frag_id,
|
response->freq, response->frag_id,
|
||||||
(unsigned long) response->offset,
|
(unsigned long) response->offset,
|
||||||
(unsigned long) wpabuf_len(response->resp));
|
(unsigned long) (response->resp ?
|
||||||
|
wpabuf_len(response->resp) : 0));
|
||||||
response->handler->status_cb(response->handler->ctx,
|
response->handler->status_cb(response->handler->ctx,
|
||||||
response->resp, 0);
|
response->resp, 0);
|
||||||
response->resp = NULL;
|
response->resp = NULL;
|
||||||
@ -83,30 +87,29 @@ static void gas_server_free_response(struct gas_server_response *response)
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
gas_server_send_resp(struct gas_server *gas, struct gas_server_handler *handler,
|
gas_server_send_resp(struct gas_server *gas, struct gas_server_handler *handler,
|
||||||
|
struct gas_server_response *response,
|
||||||
const u8 *da, int freq, u8 dialog_token,
|
const u8 *da, int freq, u8 dialog_token,
|
||||||
struct wpabuf *query_resp)
|
struct wpabuf *query_resp, u16 comeback_delay)
|
||||||
{
|
{
|
||||||
size_t max_len = (freq > 56160) ? 928 : 1400;
|
size_t max_len = (freq > 56160) ? 928 : 1400;
|
||||||
size_t hdr_len = 24 + 2 + 5 + 3 + handler->adv_proto_id_len + 2;
|
size_t hdr_len = 24 + 2 + 5 + 3 + handler->adv_proto_id_len + 2;
|
||||||
size_t resp_frag_len;
|
size_t resp_frag_len;
|
||||||
struct wpabuf *resp;
|
struct wpabuf *resp;
|
||||||
u16 comeback_delay;
|
|
||||||
struct gas_server_response *response;
|
|
||||||
|
|
||||||
if (!query_resp)
|
if (comeback_delay == 0 && !query_resp) {
|
||||||
return;
|
gas_server_free_response(response);
|
||||||
|
|
||||||
response = os_zalloc(sizeof(*response));
|
|
||||||
if (!response) {
|
|
||||||
wpabuf_free(query_resp);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
wpa_printf(MSG_DEBUG, "DPP: Allocated GAS response @%p", response);
|
|
||||||
response->freq = freq;
|
response->freq = freq;
|
||||||
response->handler = handler;
|
response->handler = handler;
|
||||||
os_memcpy(response->dst, da, ETH_ALEN);
|
os_memcpy(response->dst, da, ETH_ALEN);
|
||||||
response->dialog_token = dialog_token;
|
response->dialog_token = dialog_token;
|
||||||
if (hdr_len + wpabuf_len(query_resp) > max_len) {
|
if (comeback_delay) {
|
||||||
|
/* Need more time to prepare the response */
|
||||||
|
resp_frag_len = 0;
|
||||||
|
response->comeback_delay = comeback_delay;
|
||||||
|
} else if (hdr_len + wpabuf_len(query_resp) > max_len) {
|
||||||
/* Need to use comeback to initiate fragmentation */
|
/* Need to use comeback to initiate fragmentation */
|
||||||
comeback_delay = 1;
|
comeback_delay = 1;
|
||||||
resp_frag_len = 0;
|
resp_frag_len = 0;
|
||||||
@ -135,10 +138,12 @@ gas_server_send_resp(struct gas_server *gas, struct gas_server_handler *handler,
|
|||||||
|
|
||||||
/* Query Response Length */
|
/* Query Response Length */
|
||||||
wpabuf_put_le16(resp, resp_frag_len);
|
wpabuf_put_le16(resp, resp_frag_len);
|
||||||
if (!comeback_delay)
|
if (!comeback_delay && query_resp)
|
||||||
wpabuf_put_buf(resp, query_resp);
|
wpabuf_put_buf(resp, query_resp);
|
||||||
|
|
||||||
if (comeback_delay) {
|
if (comeback_delay && !query_resp) {
|
||||||
|
wpa_printf(MSG_DEBUG, "GAS: No response available yet");
|
||||||
|
} else if (comeback_delay) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"GAS: Need to fragment query response");
|
"GAS: Need to fragment query response");
|
||||||
} else {
|
} else {
|
||||||
@ -165,6 +170,7 @@ gas_server_rx_initial_req(struct gas_server *gas, const u8 *da, const u8 *sa,
|
|||||||
u16 query_req_len;
|
u16 query_req_len;
|
||||||
struct gas_server_handler *handler;
|
struct gas_server_handler *handler;
|
||||||
struct wpabuf *resp;
|
struct wpabuf *resp;
|
||||||
|
struct gas_server_response *response;
|
||||||
|
|
||||||
wpa_hexdump(MSG_MSGDUMP, "GAS: Received GAS Initial Request frame",
|
wpa_hexdump(MSG_MSGDUMP, "GAS: Received GAS Initial Request frame",
|
||||||
data, len);
|
data, len);
|
||||||
@ -210,8 +216,15 @@ gas_server_rx_initial_req(struct gas_server *gas, const u8 *da, const u8 *sa,
|
|||||||
pos, end - pos);
|
pos, end - pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
response = os_zalloc(sizeof(*response));
|
||||||
|
if (!response)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Allocated GAS response @%p", response);
|
||||||
dl_list_for_each(handler, &gas->handlers, struct gas_server_handler,
|
dl_list_for_each(handler, &gas->handlers, struct gas_server_handler,
|
||||||
list) {
|
list) {
|
||||||
|
u16 comeback_delay = 0;
|
||||||
|
|
||||||
if (adv_proto_len < 1 + handler->adv_proto_id_len ||
|
if (adv_proto_len < 1 + handler->adv_proto_id_len ||
|
||||||
os_memcmp(adv_proto + 1, handler->adv_proto_id,
|
os_memcmp(adv_proto + 1, handler->adv_proto_id,
|
||||||
handler->adv_proto_id_len) != 0)
|
handler->adv_proto_id_len) != 0)
|
||||||
@ -219,17 +232,22 @@ gas_server_rx_initial_req(struct gas_server *gas, const u8 *da, const u8 *sa,
|
|||||||
|
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"GAS: Calling handler for the requested Advertisement Protocol ID");
|
"GAS: Calling handler for the requested Advertisement Protocol ID");
|
||||||
resp = handler->req_cb(handler->ctx, sa, query_req,
|
resp = handler->req_cb(handler->ctx, response, sa, query_req,
|
||||||
query_req_len);
|
query_req_len, &comeback_delay);
|
||||||
wpa_hexdump_buf(MSG_MSGDUMP, "GAS: Response from the handler",
|
wpa_hexdump_buf(MSG_MSGDUMP, "GAS: Response from the handler",
|
||||||
resp);
|
resp);
|
||||||
gas_server_send_resp(gas, handler, sa, freq, dialog_token,
|
if (comeback_delay)
|
||||||
resp);
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"GAS: Handler requested comeback delay: %u TU",
|
||||||
|
comeback_delay);
|
||||||
|
gas_server_send_resp(gas, handler, response, sa, freq,
|
||||||
|
dialog_token, resp, comeback_delay);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"GAS: No registered handler for the requested Advertisement Protocol ID");
|
"GAS: No registered handler for the requested Advertisement Protocol ID");
|
||||||
|
gas_server_free_response(response);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,6 +261,31 @@ gas_server_handle_rx_comeback_req(struct gas_server_response *response)
|
|||||||
size_t hdr_len = 24 + 2 + 6 + 3 + handler->adv_proto_id_len + 2;
|
size_t hdr_len = 24 + 2 + 6 + 3 + handler->adv_proto_id_len + 2;
|
||||||
size_t remaining, resp_frag_len;
|
size_t remaining, resp_frag_len;
|
||||||
struct wpabuf *resp;
|
struct wpabuf *resp;
|
||||||
|
unsigned int wait_time = 0;
|
||||||
|
|
||||||
|
if (!response->resp) {
|
||||||
|
resp = gas_build_comeback_resp(response->dialog_token,
|
||||||
|
WLAN_STATUS_SUCCESS, 0, 0,
|
||||||
|
response->comeback_delay,
|
||||||
|
handler->adv_proto_id_len);
|
||||||
|
if (!resp) {
|
||||||
|
dl_list_del(&response->list);
|
||||||
|
gas_server_free_response(response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Advertisement Protocol element */
|
||||||
|
wpabuf_put_u8(resp, WLAN_EID_ADV_PROTO);
|
||||||
|
wpabuf_put_u8(resp, 1 + handler->adv_proto_id_len); /* Length */
|
||||||
|
wpabuf_put_u8(resp, 0x7f);
|
||||||
|
/* Advertisement Protocol ID */
|
||||||
|
wpabuf_put_data(resp, handler->adv_proto_id,
|
||||||
|
handler->adv_proto_id_len);
|
||||||
|
|
||||||
|
/* Query Response Length */
|
||||||
|
wpabuf_put_le16(resp, 0);
|
||||||
|
goto send_resp;
|
||||||
|
}
|
||||||
|
|
||||||
remaining = wpabuf_len(response->resp) - response->offset;
|
remaining = wpabuf_len(response->resp) - response->offset;
|
||||||
if (hdr_len + remaining > max_len)
|
if (hdr_len + remaining > max_len)
|
||||||
@ -279,8 +322,11 @@ gas_server_handle_rx_comeback_req(struct gas_server_response *response)
|
|||||||
|
|
||||||
response->offset += resp_frag_len;
|
response->offset += resp_frag_len;
|
||||||
|
|
||||||
gas->tx(gas->ctx, response->freq, response->dst, resp,
|
if (remaining > resp_frag_len)
|
||||||
remaining > resp_frag_len ? 2000 : 0);
|
wait_time = 2000;
|
||||||
|
|
||||||
|
send_resp:
|
||||||
|
gas->tx(gas->ctx, response->freq, response->dst, resp, wait_time);
|
||||||
wpabuf_free(resp);
|
wpabuf_free(resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -359,12 +405,19 @@ int gas_server_rx(struct gas_server *gas, const u8 *da, const u8 *sa,
|
|||||||
static void gas_server_handle_tx_status(struct gas_server_response *response,
|
static void gas_server_handle_tx_status(struct gas_server_response *response,
|
||||||
int ack)
|
int ack)
|
||||||
{
|
{
|
||||||
if (ack && response->offset < wpabuf_len(response->resp)) {
|
if (ack && response->resp &&
|
||||||
|
response->offset < wpabuf_len(response->resp)) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"GAS: More fragments remaining - keep pending entry");
|
"GAS: More fragments remaining - keep pending entry");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ack && !response->resp && response->comeback_delay) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"GAS: Waiting for response - keep pending entry");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!ack)
|
if (!ack)
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"GAS: No ACK received - drop pending entry");
|
"GAS: No ACK received - drop pending entry");
|
||||||
@ -415,6 +468,27 @@ void gas_server_tx_status(struct gas_server *gas, const u8 *dst, const u8 *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int gas_server_set_resp(struct gas_server *gas, void *resp_ctx,
|
||||||
|
struct wpabuf *resp)
|
||||||
|
{
|
||||||
|
struct gas_server_response *tmp, *response = NULL;
|
||||||
|
|
||||||
|
dl_list_for_each(tmp, &gas->responses, struct gas_server_response,
|
||||||
|
list) {
|
||||||
|
if (tmp == resp_ctx) {
|
||||||
|
response = tmp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!response || response->resp)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
response->resp = resp;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct gas_server * gas_server_init(void *ctx,
|
struct gas_server * gas_server_init(void *ctx,
|
||||||
void (*tx)(void *ctx, int freq,
|
void (*tx)(void *ctx, int freq,
|
||||||
const u8 *da,
|
const u8 *da,
|
||||||
@ -461,8 +535,9 @@ void gas_server_deinit(struct gas_server *gas)
|
|||||||
int gas_server_register(struct gas_server *gas,
|
int gas_server_register(struct gas_server *gas,
|
||||||
const u8 *adv_proto_id, u8 adv_proto_id_len,
|
const u8 *adv_proto_id, u8 adv_proto_id_len,
|
||||||
struct wpabuf *
|
struct wpabuf *
|
||||||
(*req_cb)(void *ctx, const u8 *sa,
|
(*req_cb)(void *ctx, void *resp_ctx, const u8 *sa,
|
||||||
const u8 *query, size_t query_len),
|
const u8 *query, size_t query_len,
|
||||||
|
u16 *comeback_delay),
|
||||||
void (*status_cb)(void *ctx, struct wpabuf *resp,
|
void (*status_cb)(void *ctx, struct wpabuf *resp,
|
||||||
int ok),
|
int ok),
|
||||||
void *ctx)
|
void *ctx)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Generic advertisement service (GAS) server
|
* Generic advertisement service (GAS) server
|
||||||
* Copyright (c) 2017, Qualcomm Atheros, Inc.
|
* Copyright (c) 2017, Qualcomm Atheros, Inc.
|
||||||
|
* Copyright (c) 2020, The Linux Foundation
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* See README for more details.
|
||||||
@ -22,8 +23,9 @@ void gas_server_deinit(struct gas_server *gas);
|
|||||||
int gas_server_register(struct gas_server *gas,
|
int gas_server_register(struct gas_server *gas,
|
||||||
const u8 *adv_proto_id, u8 adv_proto_id_len,
|
const u8 *adv_proto_id, u8 adv_proto_id_len,
|
||||||
struct wpabuf *
|
struct wpabuf *
|
||||||
(*req_cb)(void *ctx, const u8 *sa,
|
(*req_cb)(void *ctx, void *resp_ctx, const u8 *sa,
|
||||||
const u8 *query, size_t query_len),
|
const u8 *query, size_t query_len,
|
||||||
|
u16 *comeback_delay),
|
||||||
void (*status_cb)(void *ctx, struct wpabuf *resp,
|
void (*status_cb)(void *ctx, struct wpabuf *resp,
|
||||||
int ok),
|
int ok),
|
||||||
void *ctx);
|
void *ctx);
|
||||||
@ -32,6 +34,8 @@ int gas_server_rx(struct gas_server *gas, const u8 *da, const u8 *sa,
|
|||||||
int freq);
|
int freq);
|
||||||
void gas_server_tx_status(struct gas_server *gas, const u8 *dst, const u8 *data,
|
void gas_server_tx_status(struct gas_server *gas, const u8 *dst, const u8 *data,
|
||||||
size_t data_len, int ack);
|
size_t data_len, int ack);
|
||||||
|
int gas_server_set_resp(struct gas_server *gas, void *resp_ctx,
|
||||||
|
struct wpabuf *resp);
|
||||||
|
|
||||||
#else /* CONFIG_GAS_SERVER */
|
#else /* CONFIG_GAS_SERVER */
|
||||||
|
|
||||||
|
@ -415,7 +415,7 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (center_idx_to_bw_6ghz(channel) != 0) {
|
if (center_idx_to_bw_6ghz(channel) < 0) {
|
||||||
wpa_printf(MSG_ERROR,
|
wpa_printf(MSG_ERROR,
|
||||||
"Invalid control channel for 6 GHz band");
|
"Invalid control channel for 6 GHz band");
|
||||||
return -1;
|
return -1;
|
||||||
@ -475,13 +475,46 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->vht_enabled) switch (oper_chwidth) {
|
if (data->he_enabled) switch (oper_chwidth) {
|
||||||
case CHANWIDTH_USE_HT:
|
case CHANWIDTH_USE_HT:
|
||||||
if (center_segment1 ||
|
if (mode == HOSTAPD_MODE_IEEE80211G && sec_channel_offset) {
|
||||||
(center_segment0 != 0 &&
|
if (!(he_cap->phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
|
||||||
5000 + center_segment0 * 5 != data->center_freq1 &&
|
HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G)) {
|
||||||
2407 + center_segment0 * 5 != data->center_freq1))
|
wpa_printf(MSG_ERROR,
|
||||||
|
"40 MHz channel width is not supported in 2.4 GHz");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* fall through */
|
||||||
|
case CHANWIDTH_80MHZ:
|
||||||
|
if (mode == HOSTAPD_MODE_IEEE80211A) {
|
||||||
|
if (!(he_cap->phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
|
||||||
|
HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G)) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"40/80 MHz channel width is not supported in 5/6 GHz");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CHANWIDTH_80P80MHZ:
|
||||||
|
if (!(he_cap->phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
|
||||||
|
HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G)) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"80+80 MHz channel width is not supported in 5/6 GHz");
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CHANWIDTH_160MHZ:
|
||||||
|
if (!(he_cap->phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
|
||||||
|
HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G)) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"160 MHz channel width is not supported in 5 / 6GHz");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else if (data->vht_enabled) switch (oper_chwidth) {
|
||||||
|
case CHANWIDTH_USE_HT:
|
||||||
break;
|
break;
|
||||||
case CHANWIDTH_80P80MHZ:
|
case CHANWIDTH_80P80MHZ:
|
||||||
if (!(vht_caps & VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)) {
|
if (!(vht_caps & VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)) {
|
||||||
@ -489,9 +522,38 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
|
|||||||
"80+80 channel width is not supported!");
|
"80+80 channel width is not supported!");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (center_segment1 == center_segment0 + 4 ||
|
/* fall through */
|
||||||
center_segment1 == center_segment0 - 4)
|
case CHANWIDTH_80MHZ:
|
||||||
|
break;
|
||||||
|
case CHANWIDTH_160MHZ:
|
||||||
|
if (!(vht_caps & (VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
|
||||||
|
VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"160 MHz channel width is not supported!");
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data->he_enabled || data->vht_enabled) switch (oper_chwidth) {
|
||||||
|
case CHANWIDTH_USE_HT:
|
||||||
|
if (center_segment1 ||
|
||||||
|
(center_segment0 != 0 &&
|
||||||
|
5000 + center_segment0 * 5 != data->center_freq1 &&
|
||||||
|
2407 + center_segment0 * 5 != data->center_freq1)) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"20/40 MHz: center segment 0 (=%d) and center freq 1 (=%d) not in sync",
|
||||||
|
center_segment0, data->center_freq1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CHANWIDTH_80P80MHZ:
|
||||||
|
if (center_segment1 == center_segment0 + 4 ||
|
||||||
|
center_segment1 == center_segment0 - 4) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"80+80 MHz: center segment 1 only 20 MHz apart");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
data->center_freq2 = 5000 + center_segment1 * 5;
|
data->center_freq2 = 5000 + center_segment1 * 5;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case CHANWIDTH_80MHZ:
|
case CHANWIDTH_80MHZ:
|
||||||
@ -500,8 +562,11 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
|
|||||||
center_segment1) ||
|
center_segment1) ||
|
||||||
(oper_chwidth == CHANWIDTH_80P80MHZ &&
|
(oper_chwidth == CHANWIDTH_80P80MHZ &&
|
||||||
!center_segment1) ||
|
!center_segment1) ||
|
||||||
!sec_channel_offset)
|
!sec_channel_offset) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"80/80+80 MHz: center segment 1 wrong or no second channel offset");
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
if (!center_segment0) {
|
if (!center_segment0) {
|
||||||
if (channel <= 48)
|
if (channel <= 48)
|
||||||
center_segment0 = 42;
|
center_segment0 = 42;
|
||||||
@ -527,22 +592,25 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
|
|||||||
center_segment0 == channel - 2 ||
|
center_segment0 == channel - 2 ||
|
||||||
center_segment0 == channel - 6)
|
center_segment0 == channel - 6)
|
||||||
data->center_freq1 = 5000 + center_segment0 * 5;
|
data->center_freq1 = 5000 + center_segment0 * 5;
|
||||||
else
|
else {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"Wrong coupling between HT and VHT/HE channel setting");
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CHANWIDTH_160MHZ:
|
case CHANWIDTH_160MHZ:
|
||||||
data->bandwidth = 160;
|
data->bandwidth = 160;
|
||||||
if (!(vht_caps & (VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
|
if (center_segment1) {
|
||||||
VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))) {
|
|
||||||
wpa_printf(MSG_ERROR,
|
wpa_printf(MSG_ERROR,
|
||||||
"160MHZ channel width is not supported!");
|
"160 MHz: center segment 1 should not be set");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (center_segment1)
|
if (!sec_channel_offset) {
|
||||||
return -1;
|
wpa_printf(MSG_ERROR,
|
||||||
if (!sec_channel_offset)
|
"160 MHz: second channel offset not set");
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Note: HT/VHT config and params are coupled. Check if
|
* Note: HT/VHT config and params are coupled. Check if
|
||||||
* HT40 channel band is in VHT160 channel band configuration.
|
* HT40 channel band is in VHT160 channel band configuration.
|
||||||
@ -556,8 +624,11 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
|
|||||||
center_segment0 == channel - 10 ||
|
center_segment0 == channel - 10 ||
|
||||||
center_segment0 == channel - 14)
|
center_segment0 == channel - 14)
|
||||||
data->center_freq1 = 5000 + center_segment0 * 5;
|
data->center_freq1 = 5000 + center_segment0 * 5;
|
||||||
else
|
else {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"160 MHz: HT40 channel band is not in 160 MHz band");
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,6 +130,16 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
|
|||||||
elems->multi_ap = pos;
|
elems->multi_ap = pos;
|
||||||
elems->multi_ap_len = elen;
|
elems->multi_ap_len = elen;
|
||||||
break;
|
break;
|
||||||
|
case OWE_OUI_TYPE:
|
||||||
|
/* OWE Transition Mode element */
|
||||||
|
break;
|
||||||
|
case DPP_CC_OUI_TYPE:
|
||||||
|
/* DPP Configurator Connectivity element */
|
||||||
|
break;
|
||||||
|
case SAE_PK_OUI_TYPE:
|
||||||
|
elems->sae_pk = pos + 4;
|
||||||
|
elems->sae_pk_len = elen - 4;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
wpa_printf(MSG_MSGDUMP, "Unknown WFA "
|
wpa_printf(MSG_MSGDUMP, "Unknown WFA "
|
||||||
"information element ignored "
|
"information element ignored "
|
||||||
@ -206,6 +216,8 @@ static int ieee802_11_parse_extension(const u8 *pos, size_t elen,
|
|||||||
ext_id = *pos++;
|
ext_id = *pos++;
|
||||||
elen--;
|
elen--;
|
||||||
|
|
||||||
|
elems->frag_ies.last_eid_ext = 0;
|
||||||
|
|
||||||
switch (ext_id) {
|
switch (ext_id) {
|
||||||
case WLAN_EID_EXT_ASSOC_DELAY_INFO:
|
case WLAN_EID_EXT_ASSOC_DELAY_INFO:
|
||||||
if (elen != 1)
|
if (elen != 1)
|
||||||
@ -245,9 +257,9 @@ static int ieee802_11_parse_extension(const u8 *pos, size_t elen,
|
|||||||
elems->key_delivery = pos;
|
elems->key_delivery = pos;
|
||||||
elems->key_delivery_len = elen;
|
elems->key_delivery_len = elen;
|
||||||
break;
|
break;
|
||||||
case WLAN_EID_EXT_FILS_WRAPPED_DATA:
|
case WLAN_EID_EXT_WRAPPED_DATA:
|
||||||
elems->fils_wrapped_data = pos;
|
elems->wrapped_data = pos;
|
||||||
elems->fils_wrapped_data_len = elen;
|
elems->wrapped_data_len = elen;
|
||||||
break;
|
break;
|
||||||
case WLAN_EID_EXT_FILS_PUBLIC_KEY:
|
case WLAN_EID_EXT_FILS_PUBLIC_KEY:
|
||||||
if (elen < 1)
|
if (elen < 1)
|
||||||
@ -286,6 +298,11 @@ static int ieee802_11_parse_extension(const u8 *pos, size_t elen,
|
|||||||
elems->short_ssid_list = pos;
|
elems->short_ssid_list = pos;
|
||||||
elems->short_ssid_list_len = elen;
|
elems->short_ssid_list_len = elen;
|
||||||
break;
|
break;
|
||||||
|
case WLAN_EID_EXT_HE_6GHZ_BAND_CAP:
|
||||||
|
if (elen < sizeof(struct ieee80211_he_6ghz_band_cap))
|
||||||
|
break;
|
||||||
|
elems->he_6ghz_band_cap = pos;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (show_errors) {
|
if (show_errors) {
|
||||||
wpa_printf(MSG_MSGDUMP,
|
wpa_printf(MSG_MSGDUMP,
|
||||||
@ -295,10 +312,39 @@ static int ieee802_11_parse_extension(const u8 *pos, size_t elen,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (elen == 254)
|
||||||
|
elems->frag_ies.last_eid_ext = ext_id;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ieee802_11_parse_fragment(struct frag_ies_info *frag_ies,
|
||||||
|
const u8 *pos, u8 elen)
|
||||||
|
{
|
||||||
|
if (frag_ies->n_frags >= MAX_NUM_FRAG_IES_SUPPORTED) {
|
||||||
|
wpa_printf(MSG_MSGDUMP, "Too many element fragments - skip");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note: while EID == 0 is a valid ID (SSID IE), it should not be
|
||||||
|
* fragmented.
|
||||||
|
*/
|
||||||
|
if (!frag_ies->last_eid) {
|
||||||
|
wpa_printf(MSG_MSGDUMP,
|
||||||
|
"Fragment without a valid last element - skip");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
frag_ies->frags[frag_ies->n_frags].ie = pos;
|
||||||
|
frag_ies->frags[frag_ies->n_frags].ie_len = elen;
|
||||||
|
frag_ies->frags[frag_ies->n_frags].eid = frag_ies->last_eid;
|
||||||
|
frag_ies->frags[frag_ies->n_frags].eid_ext = frag_ies->last_eid_ext;
|
||||||
|
frag_ies->n_frags++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ieee802_11_parse_elems - Parse information elements in management frames
|
* ieee802_11_parse_elems - Parse information elements in management frames
|
||||||
* @start: Pointer to the start of IEs
|
* @start: Pointer to the start of IEs
|
||||||
@ -331,6 +377,11 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
|
|||||||
elen);
|
elen);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (elems->ssid) {
|
||||||
|
wpa_printf(MSG_MSGDUMP,
|
||||||
|
"Ignored duplicated SSID element");
|
||||||
|
break;
|
||||||
|
}
|
||||||
elems->ssid = pos;
|
elems->ssid = pos;
|
||||||
elems->ssid_len = elen;
|
elems->ssid_len = elen;
|
||||||
break;
|
break;
|
||||||
@ -515,8 +566,13 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
|
|||||||
elems->dils = pos;
|
elems->dils = pos;
|
||||||
elems->dils_len = elen;
|
elems->dils_len = elen;
|
||||||
break;
|
break;
|
||||||
|
case WLAN_EID_S1G_CAPABILITIES:
|
||||||
|
if (elen < 15)
|
||||||
|
break;
|
||||||
|
elems->s1g_capab = pos;
|
||||||
|
break;
|
||||||
case WLAN_EID_FRAGMENT:
|
case WLAN_EID_FRAGMENT:
|
||||||
/* TODO */
|
ieee802_11_parse_fragment(&elems->frag_ies, pos, elen);
|
||||||
break;
|
break;
|
||||||
case WLAN_EID_EXTENSION:
|
case WLAN_EID_EXTENSION:
|
||||||
if (ieee802_11_parse_extension(pos, elen, elems,
|
if (ieee802_11_parse_extension(pos, elen, elems,
|
||||||
@ -532,6 +588,12 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
|
|||||||
id, elen);
|
id, elen);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (id != WLAN_EID_FRAGMENT && elen == 255)
|
||||||
|
elems->frag_ies.last_eid = id;
|
||||||
|
|
||||||
|
if (id == WLAN_EID_EXTENSION && !elems->frag_ies.last_eid_ext)
|
||||||
|
elems->frag_ies.last_eid = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!for_each_element_completed(elem, start, len)) {
|
if (!for_each_element_completed(elem, start, len)) {
|
||||||
@ -710,6 +772,98 @@ int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int hostapd_config_tx_queue(struct hostapd_tx_queue_params tx_queue[],
|
||||||
|
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 = &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 queue field '%s'", pos);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel)
|
enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel)
|
||||||
{
|
{
|
||||||
u8 op_class;
|
u8 op_class;
|
||||||
@ -880,16 +1034,35 @@ enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq,
|
|||||||
return HOSTAPD_MODE_IEEE80211A;
|
return HOSTAPD_MODE_IEEE80211A;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (freq > 5940 && freq <= 7105) {
|
if (freq > 5950 && freq <= 7115) {
|
||||||
int bw;
|
if ((freq - 5950) % 5)
|
||||||
u8 idx = (freq - 5940) / 5;
|
|
||||||
|
|
||||||
bw = center_idx_to_bw_6ghz(idx);
|
|
||||||
if (bw < 0)
|
|
||||||
return NUM_HOSTAPD_MODES;
|
return NUM_HOSTAPD_MODES;
|
||||||
|
|
||||||
*channel = idx;
|
switch (chanwidth) {
|
||||||
*op_class = 131 + bw;
|
case CHANWIDTH_80MHZ:
|
||||||
|
*op_class = 133;
|
||||||
|
break;
|
||||||
|
case CHANWIDTH_160MHZ:
|
||||||
|
*op_class = 134;
|
||||||
|
break;
|
||||||
|
case CHANWIDTH_80P80MHZ:
|
||||||
|
*op_class = 135;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (sec_channel)
|
||||||
|
*op_class = 132;
|
||||||
|
else
|
||||||
|
*op_class = 131;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*channel = (freq - 5950) / 5;
|
||||||
|
return HOSTAPD_MODE_IEEE80211A;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (freq == 5935) {
|
||||||
|
*op_class = 136;
|
||||||
|
*channel = (freq - 5925) / 5;
|
||||||
return HOSTAPD_MODE_IEEE80211A;
|
return HOSTAPD_MODE_IEEE80211A;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1269,7 +1442,11 @@ static int ieee80211_chan_to_freq_global(u8 op_class, u8 chan)
|
|||||||
case 135: /* UHB channels, 80+80 MHz: 7, 23, 39.. */
|
case 135: /* UHB channels, 80+80 MHz: 7, 23, 39.. */
|
||||||
if (chan < 1 || chan > 233)
|
if (chan < 1 || chan > 233)
|
||||||
return -1;
|
return -1;
|
||||||
return 5940 + chan * 5;
|
return 5950 + chan * 5;
|
||||||
|
case 136: /* UHB channels, 20 MHz: 2 */
|
||||||
|
if (chan == 2)
|
||||||
|
return 5935;
|
||||||
|
return -1;
|
||||||
case 180: /* 60 GHz band, channels 1..8 */
|
case 180: /* 60 GHz band, channels 1..8 */
|
||||||
if (chan < 1 || chan > 8)
|
if (chan < 1 || chan > 8)
|
||||||
return -1;
|
return -1;
|
||||||
@ -1613,7 +1790,9 @@ const char * status2str(u16 status)
|
|||||||
S2S(FILS_AUTHENTICATION_FAILURE)
|
S2S(FILS_AUTHENTICATION_FAILURE)
|
||||||
S2S(UNKNOWN_AUTHENTICATION_SERVER)
|
S2S(UNKNOWN_AUTHENTICATION_SERVER)
|
||||||
S2S(UNKNOWN_PASSWORD_IDENTIFIER)
|
S2S(UNKNOWN_PASSWORD_IDENTIFIER)
|
||||||
|
S2S(DENIED_HE_NOT_SUPPORTED)
|
||||||
S2S(SAE_HASH_TO_ELEMENT)
|
S2S(SAE_HASH_TO_ELEMENT)
|
||||||
|
S2S(SAE_PK)
|
||||||
}
|
}
|
||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
#undef S2S
|
#undef S2S
|
||||||
@ -1711,8 +1890,12 @@ const struct oper_class_map global_op_class[] = {
|
|||||||
*/
|
*/
|
||||||
{ HOSTAPD_MODE_IEEE80211A, 128, 36, 161, 4, BW80, P2P_SUPP },
|
{ HOSTAPD_MODE_IEEE80211A, 128, 36, 161, 4, BW80, P2P_SUPP },
|
||||||
{ HOSTAPD_MODE_IEEE80211A, 129, 50, 114, 16, BW160, P2P_SUPP },
|
{ HOSTAPD_MODE_IEEE80211A, 129, 50, 114, 16, BW160, P2P_SUPP },
|
||||||
{ HOSTAPD_MODE_IEEE80211A, 130, 36, 161, 4, BW80P80, P2P_SUPP },
|
{ HOSTAPD_MODE_IEEE80211A, 131, 1, 233, 4, BW20, NO_P2P_SUPP },
|
||||||
{ HOSTAPD_MODE_IEEE80211A, 131, 1, 233, 4, BW20, P2P_SUPP },
|
{ HOSTAPD_MODE_IEEE80211A, 132, 1, 233, 8, BW40, NO_P2P_SUPP },
|
||||||
|
{ HOSTAPD_MODE_IEEE80211A, 133, 1, 233, 16, BW80, NO_P2P_SUPP },
|
||||||
|
{ HOSTAPD_MODE_IEEE80211A, 134, 1, 233, 32, BW160, NO_P2P_SUPP },
|
||||||
|
{ HOSTAPD_MODE_IEEE80211A, 135, 1, 233, 16, BW80P80, NO_P2P_SUPP },
|
||||||
|
{ HOSTAPD_MODE_IEEE80211A, 136, 2, 2, 4, BW20, NO_P2P_SUPP },
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IEEE Std 802.11ad-2012 and P802.ay/D5.0 60 GHz operating classes.
|
* IEEE Std 802.11ad-2012 and P802.ay/D5.0 60 GHz operating classes.
|
||||||
@ -1723,6 +1906,12 @@ const struct oper_class_map global_op_class[] = {
|
|||||||
{ HOSTAPD_MODE_IEEE80211AD, 181, 9, 13, 1, BW4320, P2P_SUPP },
|
{ HOSTAPD_MODE_IEEE80211AD, 181, 9, 13, 1, BW4320, P2P_SUPP },
|
||||||
{ HOSTAPD_MODE_IEEE80211AD, 182, 17, 20, 1, BW6480, P2P_SUPP },
|
{ HOSTAPD_MODE_IEEE80211AD, 182, 17, 20, 1, BW6480, P2P_SUPP },
|
||||||
{ HOSTAPD_MODE_IEEE80211AD, 183, 25, 27, 1, BW8640, P2P_SUPP },
|
{ HOSTAPD_MODE_IEEE80211AD, 183, 25, 27, 1, BW8640, P2P_SUPP },
|
||||||
|
|
||||||
|
/* Keep the operating class 130 as the last entry as a workaround for
|
||||||
|
* the OneHundredAndThirty Delimiter value used in the Supported
|
||||||
|
* Operating Classes element to indicate the end of the Operating
|
||||||
|
* Classes field. */
|
||||||
|
{ HOSTAPD_MODE_IEEE80211A, 130, 36, 161, 4, BW80P80, P2P_SUPP },
|
||||||
{ -1, 0, 0, 0, 0, BW20, NO_P2P_SUPP }
|
{ -1, 0, 0, 0, 0, BW20, NO_P2P_SUPP }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2020,6 +2209,7 @@ int oper_class_bw_to_int(const struct oper_class_map *map)
|
|||||||
switch (map->bw) {
|
switch (map->bw) {
|
||||||
case BW20:
|
case BW20:
|
||||||
return 20;
|
return 20;
|
||||||
|
case BW40:
|
||||||
case BW40PLUS:
|
case BW40PLUS:
|
||||||
case BW40MINUS:
|
case BW40MINUS:
|
||||||
return 40;
|
return 40;
|
||||||
@ -2055,41 +2245,44 @@ int center_idx_to_bw_6ghz(u8 idx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int is_6ghz_freq(int freq)
|
bool is_6ghz_freq(int freq)
|
||||||
{
|
{
|
||||||
if (freq < 5940 || freq > 7105)
|
if (freq < 5935 || freq > 7115)
|
||||||
return 0;
|
return false;
|
||||||
|
|
||||||
if (center_idx_to_bw_6ghz((freq - 5940) / 5) < 0)
|
if (freq == 5935)
|
||||||
return 0;
|
return true;
|
||||||
|
|
||||||
return 1;
|
if (center_idx_to_bw_6ghz((freq - 5950) / 5) < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int is_6ghz_op_class(u8 op_class)
|
bool is_6ghz_op_class(u8 op_class)
|
||||||
{
|
{
|
||||||
return op_class >= 131 && op_class <= 135;
|
return op_class >= 131 && op_class <= 136;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int is_6ghz_psc_frequency(int freq)
|
bool is_6ghz_psc_frequency(int freq)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!is_6ghz_freq(freq))
|
if (!is_6ghz_freq(freq) || freq == 5935)
|
||||||
return 0;
|
return false;
|
||||||
if ((((freq - 5940) / 5) & 0x3) != 0x1)
|
if ((((freq - 5950) / 5) & 0x3) != 0x1)
|
||||||
return 0;
|
return false;
|
||||||
|
|
||||||
i = (freq - 5940 + 55) % 80;
|
i = (freq - 5950 + 55) % 80;
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
i = (freq - 5940 + 55) / 80;
|
i = (freq - 5950 + 55) / 80;
|
||||||
|
|
||||||
if (i >= 1 && i <= 15)
|
if (i >= 1 && i <= 15)
|
||||||
return 1;
|
return true;
|
||||||
|
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2320,6 +2513,8 @@ int op_class_to_bandwidth(u8 op_class)
|
|||||||
case 134: /* UHB channels, 160 MHz: 15, 47, 79.. */
|
case 134: /* UHB channels, 160 MHz: 15, 47, 79.. */
|
||||||
case 135: /* UHB channels, 80+80 MHz: 7, 23, 39.. */
|
case 135: /* UHB channels, 80+80 MHz: 7, 23, 39.. */
|
||||||
return 160;
|
return 160;
|
||||||
|
case 136: /* UHB channels, 20 MHz: 2 */
|
||||||
|
return 20;
|
||||||
case 180: /* 60 GHz band, channels 1..8 */
|
case 180: /* 60 GHz band, channels 1..8 */
|
||||||
return 2160;
|
return 2160;
|
||||||
case 181: /* 60 GHz band, EDMG CB2, channels 9..15 */
|
case 181: /* 60 GHz band, EDMG CB2, channels 9..15 */
|
||||||
@ -2380,6 +2575,8 @@ int op_class_to_ch_width(u8 op_class)
|
|||||||
return CHANWIDTH_160MHZ;
|
return CHANWIDTH_160MHZ;
|
||||||
case 135: /* UHB channels, 80+80 MHz: 7, 23, 39.. */
|
case 135: /* UHB channels, 80+80 MHz: 7, 23, 39.. */
|
||||||
return CHANWIDTH_80P80MHZ;
|
return CHANWIDTH_80P80MHZ;
|
||||||
|
case 136: /* UHB channels, 20 MHz: 2 */
|
||||||
|
return CHANWIDTH_USE_HT;
|
||||||
case 180: /* 60 GHz band, channels 1..8 */
|
case 180: /* 60 GHz band, channels 1..8 */
|
||||||
return CHANWIDTH_2160MHZ;
|
return CHANWIDTH_2160MHZ;
|
||||||
case 181: /* 60 GHz band, EDMG CB2, channels 9..15 */
|
case 181: /* 60 GHz band, EDMG CB2, channels 9..15 */
|
||||||
@ -2391,3 +2588,78 @@ int op_class_to_ch_width(u8 op_class)
|
|||||||
}
|
}
|
||||||
return CHANWIDTH_USE_HT;
|
return CHANWIDTH_USE_HT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct wpabuf * ieee802_11_defrag_data(struct ieee802_11_elems *elems,
|
||||||
|
u8 eid, u8 eid_ext,
|
||||||
|
const u8 *data, u8 len)
|
||||||
|
{
|
||||||
|
struct frag_ies_info *frag_ies = &elems->frag_ies;
|
||||||
|
struct wpabuf *buf;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (!elems || !data || !len)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
buf = wpabuf_alloc_copy(data, len);
|
||||||
|
if (!buf)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < frag_ies->n_frags; i++) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (frag_ies->frags[i].eid != eid ||
|
||||||
|
frag_ies->frags[i].eid_ext != eid_ext)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ret = wpabuf_resize(&buf, frag_ies->frags[i].ie_len);
|
||||||
|
if (ret < 0) {
|
||||||
|
wpabuf_free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy only the fragment data (without the EID and length) */
|
||||||
|
wpabuf_put_data(buf, frag_ies->frags[i].ie,
|
||||||
|
frag_ies->frags[i].ie_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct wpabuf * ieee802_11_defrag(struct ieee802_11_elems *elems,
|
||||||
|
u8 eid, u8 eid_ext)
|
||||||
|
{
|
||||||
|
const u8 *data;
|
||||||
|
u8 len;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: Defragmentation mechanism can be supported for all IEs. For now
|
||||||
|
* handle only those that are used (or use ieee802_11_defrag_data()).
|
||||||
|
*/
|
||||||
|
switch (eid) {
|
||||||
|
case WLAN_EID_EXTENSION:
|
||||||
|
switch (eid_ext) {
|
||||||
|
case WLAN_EID_EXT_FILS_HLP_CONTAINER:
|
||||||
|
data = elems->fils_hlp;
|
||||||
|
len = elems->fils_hlp_len;
|
||||||
|
break;
|
||||||
|
case WLAN_EID_EXT_WRAPPED_DATA:
|
||||||
|
data = elems->wrapped_data;
|
||||||
|
len = elems->wrapped_data_len;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"Defragmentation not supported. eid_ext=%u",
|
||||||
|
eid_ext);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"Defragmentation not supported. eid=%u", eid);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ieee802_11_defrag_data(elems, eid, eid_ext, data, len);
|
||||||
|
}
|
||||||
|
@ -21,6 +21,7 @@ struct element {
|
|||||||
struct hostapd_hw_modes;
|
struct hostapd_hw_modes;
|
||||||
|
|
||||||
#define MAX_NOF_MB_IES_SUPPORTED 5
|
#define MAX_NOF_MB_IES_SUPPORTED 5
|
||||||
|
#define MAX_NUM_FRAG_IES_SUPPORTED 3
|
||||||
|
|
||||||
struct mb_ies_info {
|
struct mb_ies_info {
|
||||||
struct {
|
struct {
|
||||||
@ -30,6 +31,21 @@ struct mb_ies_info {
|
|||||||
u8 nof_ies;
|
u8 nof_ies;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct frag_ies_info {
|
||||||
|
struct {
|
||||||
|
u8 eid;
|
||||||
|
u8 eid_ext;
|
||||||
|
const u8 *ie;
|
||||||
|
u8 ie_len;
|
||||||
|
} frags[MAX_NUM_FRAG_IES_SUPPORTED];
|
||||||
|
|
||||||
|
u8 n_frags;
|
||||||
|
|
||||||
|
/* the last parsed element ID and element extension ID */
|
||||||
|
u8 last_eid;
|
||||||
|
u8 last_eid_ext;
|
||||||
|
};
|
||||||
|
|
||||||
/* Parsed Information Elements */
|
/* Parsed Information Elements */
|
||||||
struct ieee802_11_elems {
|
struct ieee802_11_elems {
|
||||||
const u8 *ssid;
|
const u8 *ssid;
|
||||||
@ -85,7 +101,7 @@ struct ieee802_11_elems {
|
|||||||
const u8 *fils_hlp;
|
const u8 *fils_hlp;
|
||||||
const u8 *fils_ip_addr_assign;
|
const u8 *fils_ip_addr_assign;
|
||||||
const u8 *key_delivery;
|
const u8 *key_delivery;
|
||||||
const u8 *fils_wrapped_data;
|
const u8 *wrapped_data;
|
||||||
const u8 *fils_pk;
|
const u8 *fils_pk;
|
||||||
const u8 *fils_nonce;
|
const u8 *fils_nonce;
|
||||||
const u8 *owe_dh;
|
const u8 *owe_dh;
|
||||||
@ -97,6 +113,9 @@ struct ieee802_11_elems {
|
|||||||
const u8 *he_capabilities;
|
const u8 *he_capabilities;
|
||||||
const u8 *he_operation;
|
const u8 *he_operation;
|
||||||
const u8 *short_ssid_list;
|
const u8 *short_ssid_list;
|
||||||
|
const u8 *he_6ghz_band_cap;
|
||||||
|
const u8 *sae_pk;
|
||||||
|
const u8 *s1g_capab;
|
||||||
|
|
||||||
u8 ssid_len;
|
u8 ssid_len;
|
||||||
u8 supp_rates_len;
|
u8 supp_rates_len;
|
||||||
@ -138,7 +157,7 @@ struct ieee802_11_elems {
|
|||||||
u8 fils_hlp_len;
|
u8 fils_hlp_len;
|
||||||
u8 fils_ip_addr_assign_len;
|
u8 fils_ip_addr_assign_len;
|
||||||
u8 key_delivery_len;
|
u8 key_delivery_len;
|
||||||
u8 fils_wrapped_data_len;
|
u8 wrapped_data_len;
|
||||||
u8 fils_pk_len;
|
u8 fils_pk_len;
|
||||||
u8 owe_dh_len;
|
u8 owe_dh_len;
|
||||||
u8 power_capab_len;
|
u8 power_capab_len;
|
||||||
@ -149,8 +168,10 @@ struct ieee802_11_elems {
|
|||||||
u8 he_capabilities_len;
|
u8 he_capabilities_len;
|
||||||
u8 he_operation_len;
|
u8 he_operation_len;
|
||||||
u8 short_ssid_list_len;
|
u8 short_ssid_list_len;
|
||||||
|
u8 sae_pk_len;
|
||||||
|
|
||||||
struct mb_ies_info mb_ies;
|
struct mb_ies_info mb_ies;
|
||||||
|
struct frag_ies_info frag_ies;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes;
|
typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes;
|
||||||
@ -174,6 +195,18 @@ struct hostapd_wmm_ac_params {
|
|||||||
|
|
||||||
int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
|
int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
|
||||||
const char *name, const char *val);
|
const char *name, const char *val);
|
||||||
|
|
||||||
|
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 NUM_TX_QUEUES 4
|
||||||
|
|
||||||
|
int hostapd_config_tx_queue(struct hostapd_tx_queue_params queue[],
|
||||||
|
const char *name, const char *val);
|
||||||
enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel);
|
enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel);
|
||||||
int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan);
|
int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan);
|
||||||
enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq,
|
enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq,
|
||||||
@ -200,8 +233,8 @@ struct oper_class_map {
|
|||||||
u8 min_chan;
|
u8 min_chan;
|
||||||
u8 max_chan;
|
u8 max_chan;
|
||||||
u8 inc;
|
u8 inc;
|
||||||
enum { BW20, BW40PLUS, BW40MINUS, BW80, BW2160, BW160, BW80P80, BW4320,
|
enum { BW20, BW40PLUS, BW40MINUS, BW40, BW80, BW2160, BW160, BW80P80,
|
||||||
BW6480, BW8640} bw;
|
BW4320, BW6480, BW8640} bw;
|
||||||
enum { P2P_SUPP, NO_P2P_SUPP } p2p;
|
enum { P2P_SUPP, NO_P2P_SUPP } p2p;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -226,9 +259,9 @@ u8 country_to_global_op_class(const char *country, u8 op_class);
|
|||||||
const struct oper_class_map * get_oper_class(const char *country, u8 op_class);
|
const struct oper_class_map * get_oper_class(const char *country, u8 op_class);
|
||||||
int oper_class_bw_to_int(const struct oper_class_map *map);
|
int oper_class_bw_to_int(const struct oper_class_map *map);
|
||||||
int center_idx_to_bw_6ghz(u8 idx);
|
int center_idx_to_bw_6ghz(u8 idx);
|
||||||
int is_6ghz_freq(int freq);
|
bool is_6ghz_freq(int freq);
|
||||||
int is_6ghz_op_class(u8 op_class);
|
bool is_6ghz_op_class(u8 op_class);
|
||||||
int is_6ghz_psc_frequency(int freq);
|
bool is_6ghz_psc_frequency(int freq);
|
||||||
|
|
||||||
int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
|
int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
|
||||||
size_t nei_rep_len);
|
size_t nei_rep_len);
|
||||||
@ -293,4 +326,10 @@ void hostapd_encode_edmg_chan(int edmg_enable, u8 edmg_channel,
|
|||||||
int ieee802_edmg_is_allowed(struct ieee80211_edmg_config allowed,
|
int ieee802_edmg_is_allowed(struct ieee80211_edmg_config allowed,
|
||||||
struct ieee80211_edmg_config requested);
|
struct ieee80211_edmg_config requested);
|
||||||
|
|
||||||
|
struct wpabuf * ieee802_11_defrag_data(struct ieee802_11_elems *elems,
|
||||||
|
u8 eid, u8 eid_ext,
|
||||||
|
const u8 *data, u8 len);
|
||||||
|
struct wpabuf * ieee802_11_defrag(struct ieee802_11_elems *elems,
|
||||||
|
u8 eid, u8 eid_ext);
|
||||||
|
|
||||||
#endif /* IEEE802_11_COMMON_H */
|
#endif /* IEEE802_11_COMMON_H */
|
||||||
|
@ -204,7 +204,9 @@
|
|||||||
#define WLAN_STATUS_FILS_AUTHENTICATION_FAILURE 112
|
#define WLAN_STATUS_FILS_AUTHENTICATION_FAILURE 112
|
||||||
#define WLAN_STATUS_UNKNOWN_AUTHENTICATION_SERVER 113
|
#define WLAN_STATUS_UNKNOWN_AUTHENTICATION_SERVER 113
|
||||||
#define WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER 123
|
#define WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER 123
|
||||||
|
#define WLAN_STATUS_DENIED_HE_NOT_SUPPORTED 124
|
||||||
#define WLAN_STATUS_SAE_HASH_TO_ELEMENT 126
|
#define WLAN_STATUS_SAE_HASH_TO_ELEMENT 126
|
||||||
|
#define WLAN_STATUS_SAE_PK 127
|
||||||
|
|
||||||
/* Reason codes (IEEE Std 802.11-2016, 9.4.1.7, Table 9-45) */
|
/* Reason codes (IEEE Std 802.11-2016, 9.4.1.7, Table 9-45) */
|
||||||
#define WLAN_REASON_UNSPECIFIED 1
|
#define WLAN_REASON_UNSPECIFIED 1
|
||||||
@ -441,7 +443,10 @@
|
|||||||
#define WLAN_EID_DEVICE_LOCATION 204
|
#define WLAN_EID_DEVICE_LOCATION 204
|
||||||
#define WLAN_EID_WHITE_SPACE_MAP 205
|
#define WLAN_EID_WHITE_SPACE_MAP 205
|
||||||
#define WLAN_EID_FTM_PARAMETERS 206
|
#define WLAN_EID_FTM_PARAMETERS 206
|
||||||
|
#define WLAN_EID_S1G_BCN_COMPAT 213
|
||||||
|
#define WLAN_EID_S1G_CAPABILITIES 217
|
||||||
#define WLAN_EID_VENDOR_SPECIFIC 221
|
#define WLAN_EID_VENDOR_SPECIFIC 221
|
||||||
|
#define WLAN_EID_S1G_OPERATION 232
|
||||||
#define WLAN_EID_CAG_NUMBER 237
|
#define WLAN_EID_CAG_NUMBER 237
|
||||||
#define WLAN_EID_AP_CSN 239
|
#define WLAN_EID_AP_CSN 239
|
||||||
#define WLAN_EID_FILS_INDICATION 240
|
#define WLAN_EID_FILS_INDICATION 240
|
||||||
@ -458,7 +463,7 @@
|
|||||||
#define WLAN_EID_EXT_FILS_HLP_CONTAINER 5
|
#define WLAN_EID_EXT_FILS_HLP_CONTAINER 5
|
||||||
#define WLAN_EID_EXT_FILS_IP_ADDR_ASSIGN 6
|
#define WLAN_EID_EXT_FILS_IP_ADDR_ASSIGN 6
|
||||||
#define WLAN_EID_EXT_KEY_DELIVERY 7
|
#define WLAN_EID_EXT_KEY_DELIVERY 7
|
||||||
#define WLAN_EID_EXT_FILS_WRAPPED_DATA 8
|
#define WLAN_EID_EXT_WRAPPED_DATA 8
|
||||||
#define WLAN_EID_EXT_FTM_SYNC_INFO 9
|
#define WLAN_EID_EXT_FTM_SYNC_INFO 9
|
||||||
#define WLAN_EID_EXT_EXTENDED_REQUEST 10
|
#define WLAN_EID_EXT_EXTENDED_REQUEST 10
|
||||||
#define WLAN_EID_EXT_ESTIMATED_SERVICE_PARAMS 11
|
#define WLAN_EID_EXT_ESTIMATED_SERVICE_PARAMS 11
|
||||||
@ -473,8 +478,11 @@
|
|||||||
#define WLAN_EID_EXT_SPATIAL_REUSE 39
|
#define WLAN_EID_EXT_SPATIAL_REUSE 39
|
||||||
#define WLAN_EID_EXT_OCV_OCI 54
|
#define WLAN_EID_EXT_OCV_OCI 54
|
||||||
#define WLAN_EID_EXT_SHORT_SSID_LIST 58
|
#define WLAN_EID_EXT_SHORT_SSID_LIST 58
|
||||||
|
#define WLAN_EID_EXT_HE_6GHZ_BAND_CAP 59
|
||||||
#define WLAN_EID_EXT_EDMG_CAPABILITIES 61
|
#define WLAN_EID_EXT_EDMG_CAPABILITIES 61
|
||||||
#define WLAN_EID_EXT_EDMG_OPERATION 62
|
#define WLAN_EID_EXT_EDMG_OPERATION 62
|
||||||
|
#define WLAN_EID_EXT_MSCS_DESCRIPTOR 88
|
||||||
|
#define WLAN_EID_EXT_TCLAS_MASK 89
|
||||||
#define WLAN_EID_EXT_REJECTED_GROUPS 92
|
#define WLAN_EID_EXT_REJECTED_GROUPS 92
|
||||||
#define WLAN_EID_EXT_ANTI_CLOGGING_TOKEN 93
|
#define WLAN_EID_EXT_ANTI_CLOGGING_TOKEN 93
|
||||||
|
|
||||||
@ -558,11 +566,15 @@
|
|||||||
#define WLAN_EXT_CAPAB_COMPLETE_NON_TX_BSSID_PROFILE 80
|
#define WLAN_EXT_CAPAB_COMPLETE_NON_TX_BSSID_PROFILE 80
|
||||||
#define WLAN_EXT_CAPAB_SAE_PW_ID 81
|
#define WLAN_EXT_CAPAB_SAE_PW_ID 81
|
||||||
#define WLAN_EXT_CAPAB_SAE_PW_ID_EXCLUSIVELY 82
|
#define WLAN_EXT_CAPAB_SAE_PW_ID_EXCLUSIVELY 82
|
||||||
|
#define WLAN_EXT_CAPAB_BEACON_PROTECTION 84
|
||||||
|
#define WLAN_EXT_CAPAB_MSCS 85
|
||||||
|
#define WLAN_EXT_CAPAB_SAE_PK_EXCLUSIVELY 88
|
||||||
|
|
||||||
/* Extended RSN Capabilities */
|
/* Extended RSN Capabilities */
|
||||||
/* bits 0-3: Field length (n-1) */
|
/* bits 0-3: Field length (n-1) */
|
||||||
#define WLAN_RSNX_CAPAB_PROTECTED_TWT 4
|
#define WLAN_RSNX_CAPAB_PROTECTED_TWT 4
|
||||||
#define WLAN_RSNX_CAPAB_SAE_H2E 5
|
#define WLAN_RSNX_CAPAB_SAE_H2E 5
|
||||||
|
#define WLAN_RSNX_CAPAB_SAE_PK 6
|
||||||
|
|
||||||
/* Action frame categories (IEEE Std 802.11-2016, 9.4.1.11, Table 9-76) */
|
/* Action frame categories (IEEE Std 802.11-2016, 9.4.1.11, Table 9-76) */
|
||||||
#define WLAN_ACTION_SPECTRUM_MGMT 0
|
#define WLAN_ACTION_SPECTRUM_MGMT 0
|
||||||
@ -1315,6 +1327,10 @@ struct ieee80211_ampe_ie {
|
|||||||
#define OWE_IE_VENDOR_TYPE 0x506f9a1c
|
#define OWE_IE_VENDOR_TYPE 0x506f9a1c
|
||||||
#define OWE_OUI_TYPE 28
|
#define OWE_OUI_TYPE 28
|
||||||
#define MULTI_AP_OUI_TYPE 0x1B
|
#define MULTI_AP_OUI_TYPE 0x1B
|
||||||
|
#define DPP_CC_IE_VENDOR_TYPE 0x506f9a1e
|
||||||
|
#define DPP_CC_OUI_TYPE 0x1e
|
||||||
|
#define SAE_PK_IE_VENDOR_TYPE 0x506f9a1f
|
||||||
|
#define SAE_PK_OUI_TYPE 0x1f
|
||||||
|
|
||||||
#define MULTI_AP_SUB_ELEM_TYPE 0x06
|
#define MULTI_AP_SUB_ELEM_TYPE 0x06
|
||||||
#define MULTI_AP_TEAR_DOWN BIT(4)
|
#define MULTI_AP_TEAR_DOWN BIT(4)
|
||||||
@ -1874,7 +1890,15 @@ enum wnm_sleep_mode_response_status {
|
|||||||
/* WNM-Sleep Mode subelement IDs */
|
/* WNM-Sleep Mode subelement IDs */
|
||||||
enum wnm_sleep_mode_subelement_id {
|
enum wnm_sleep_mode_subelement_id {
|
||||||
WNM_SLEEP_SUBELEM_GTK = 0,
|
WNM_SLEEP_SUBELEM_GTK = 0,
|
||||||
WNM_SLEEP_SUBELEM_IGTK = 1
|
WNM_SLEEP_SUBELEM_IGTK = 1,
|
||||||
|
WNM_SLEEP_SUBELEM_BIGTK = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* WNM notification type (IEEE P802.11-REVmd/D3.0, Table 9-430) */
|
||||||
|
enum wnm_notification_Type {
|
||||||
|
WNM_NOTIF_TYPE_FIRMWARE_UPDATE = 0,
|
||||||
|
WNM_NOTIF_TYPE_BEACON_PROTECTION_FAILURE = 2,
|
||||||
|
WNM_NOTIF_TYPE_VENDOR_SPECIFIC = 221,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Channel Switch modes (802.11h) */
|
/* Channel Switch modes (802.11h) */
|
||||||
@ -2090,7 +2114,7 @@ enum phy_type {
|
|||||||
PHY_TYPE_VHT = 9,
|
PHY_TYPE_VHT = 9,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* IEEE P802.11-REVmc/D5.0, 9.4.2.37 - Neighbor Report element */
|
/* IEEE P802.11-REVmd/D3.0, 9.4.2.36 - Neighbor Report element */
|
||||||
/* BSSID Information Field */
|
/* BSSID Information Field */
|
||||||
#define NEI_REP_BSSID_INFO_AP_NOT_REACH BIT(0)
|
#define NEI_REP_BSSID_INFO_AP_NOT_REACH BIT(0)
|
||||||
#define NEI_REP_BSSID_INFO_AP_UNKNOWN_REACH BIT(1)
|
#define NEI_REP_BSSID_INFO_AP_UNKNOWN_REACH BIT(1)
|
||||||
@ -2107,6 +2131,7 @@ enum phy_type {
|
|||||||
#define NEI_REP_BSSID_INFO_HT BIT(11)
|
#define NEI_REP_BSSID_INFO_HT BIT(11)
|
||||||
#define NEI_REP_BSSID_INFO_VHT BIT(12)
|
#define NEI_REP_BSSID_INFO_VHT BIT(12)
|
||||||
#define NEI_REP_BSSID_INFO_FTM BIT(13)
|
#define NEI_REP_BSSID_INFO_FTM BIT(13)
|
||||||
|
#define NEI_REP_BSSID_INFO_HE BIT(14)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IEEE P802.11-REVmc/D5.0 Table 9-152 - HT/VHT Operation Information
|
* IEEE P802.11-REVmc/D5.0 Table 9-152 - HT/VHT Operation Information
|
||||||
@ -2133,12 +2158,53 @@ struct ieee80211_he_operation {
|
|||||||
le32 he_oper_params; /* HE Operation Parameters[3] and
|
le32 he_oper_params; /* HE Operation Parameters[3] and
|
||||||
* BSS Color Information[1] */
|
* BSS Color Information[1] */
|
||||||
le16 he_mcs_nss_set;
|
le16 he_mcs_nss_set;
|
||||||
u8 vht_op_info_chwidth;
|
/* Followed by conditional VHT Operation Information (3 octets),
|
||||||
u8 vht_op_info_chan_center_freq_seg0_idx;
|
* Max Co-Hosted BSSID Indicator subfield (1 octet), and/or 6 GHz
|
||||||
u8 vht_op_info_chan_center_freq_seg1_idx;
|
* Operation Information subfield (5 octets). */
|
||||||
/* Followed by conditional MaxBSSID Indicator subfield (u8) */
|
|
||||||
} STRUCT_PACKED;
|
} STRUCT_PACKED;
|
||||||
|
|
||||||
|
/* IEEE P802.11ax/D6.0, Figure 9-787k - 6 GHz Operation Information field */
|
||||||
|
struct ieee80211_he_6ghz_oper_info {
|
||||||
|
u8 primary_chan;
|
||||||
|
u8 control;
|
||||||
|
u8 chan_center_freq_seg0;
|
||||||
|
u8 chan_center_freq_seg1;
|
||||||
|
u8 min_rate;
|
||||||
|
} STRUCT_PACKED;
|
||||||
|
|
||||||
|
#define HE_6GHZ_OPER_INFO_CTRL_CHAN_WIDTH_MASK (BIT(0) | BIT(1))
|
||||||
|
#define HE_6GHZ_OPER_INFO_CTRL_DUP_BEACON BIT(2)
|
||||||
|
|
||||||
|
/* IEEE P802.11ax/D6.0, 9.4.2.261 HE 6 GHz Band Capabilities element */
|
||||||
|
struct ieee80211_he_6ghz_band_cap {
|
||||||
|
/* Minimum MPDU Start Spacing B0..B2
|
||||||
|
* Maximum A-MPDU Length Exponent B3..B5
|
||||||
|
* Maximum MPDU Length B6..B7 */
|
||||||
|
le16 capab;
|
||||||
|
} STRUCT_PACKED;
|
||||||
|
|
||||||
|
#define HE_6GHZ_BAND_CAP_MIN_MPDU_START (BIT(0) | BIT(1) | BIT(2))
|
||||||
|
#define HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_16K BIT(3)
|
||||||
|
#define HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_32K BIT(4)
|
||||||
|
#define HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_64K (BIT(3) | BIT(4))
|
||||||
|
#define HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_128K BIT(5)
|
||||||
|
#define HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_256K (BIT(3) | BIT(5))
|
||||||
|
#define HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_512K (BIT(4) | BIT(5))
|
||||||
|
#define HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_1024K (BIT(3) | BIT(4) | BIT(5))
|
||||||
|
#define HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_MASK (BIT(3) | BIT(4) | BIT(5))
|
||||||
|
#define HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_SHIFT 3
|
||||||
|
#define HE_6GHZ_BAND_CAP_MAX_MPDU_LEN_7991 BIT(6)
|
||||||
|
#define HE_6GHZ_BAND_CAP_MAX_MPDU_LEN_11454 BIT(7)
|
||||||
|
#define HE_6GHZ_BAND_CAP_MAX_MPDU_LEN_MASK (BIT(6) | BIT(7))
|
||||||
|
#define HE_6GHZ_BAND_CAP_MAX_MPDU_LEN_SHIFT 6
|
||||||
|
#define HE_6GHZ_BAND_CAP_SMPS_MASK (BIT(9) | BIT(10))
|
||||||
|
#define HE_6GHZ_BAND_CAP_SMPS_STATIC 0
|
||||||
|
#define HE_6GHZ_BAND_CAP_SMPS_DYNAMIC BIT(9)
|
||||||
|
#define HE_6GHZ_BAND_CAP_SMPS_DISABLED (BIT(9) | BIT(10))
|
||||||
|
#define HE_6GHZ_BAND_CAP_RD_RESPONDER BIT(11)
|
||||||
|
#define HE_6GHZ_BAND_CAP_RX_ANTPAT_CONS BIT(12)
|
||||||
|
#define HE_6GHZ_BAND_CAP_TX_ANTPAT_CONS BIT(13)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IEEE P802.11ax/D4.0, 9.4.2.246 Spatial Reuse Parameter Set element
|
* IEEE P802.11ax/D4.0, 9.4.2.246 Spatial Reuse Parameter Set element
|
||||||
*/
|
*/
|
||||||
@ -2156,6 +2222,8 @@ struct ieee80211_spatial_reuse {
|
|||||||
|
|
||||||
/* HE Capabilities Information defines */
|
/* HE Capabilities Information defines */
|
||||||
|
|
||||||
|
#define HE_MACCAP_TWT_RESPONDER ((u8) BIT(2))
|
||||||
|
|
||||||
#define HE_PHYCAP_CHANNEL_WIDTH_SET_IDX 0
|
#define HE_PHYCAP_CHANNEL_WIDTH_SET_IDX 0
|
||||||
#define HE_PHYCAP_CHANNEL_WIDTH_MASK ((u8) (BIT(1) | BIT(2) | \
|
#define HE_PHYCAP_CHANNEL_WIDTH_MASK ((u8) (BIT(1) | BIT(2) | \
|
||||||
BIT(3) | BIT(4)))
|
BIT(3) | BIT(4)))
|
||||||
@ -2198,7 +2266,7 @@ struct ieee80211_spatial_reuse {
|
|||||||
#define HE_OPERATION_BSS_COLOR_MASK ((u32) (BIT(24) | BIT(25) | \
|
#define HE_OPERATION_BSS_COLOR_MASK ((u32) (BIT(24) | BIT(25) | \
|
||||||
BIT(26) | BIT(27) | \
|
BIT(26) | BIT(27) | \
|
||||||
BIT(28) | BIT(29)))
|
BIT(28) | BIT(29)))
|
||||||
#define HE_OPERATION_PARTIAL_BSS_COLOR ((u32) BIT(30))
|
#define HE_OPERATION_BSS_COLOR_PARTIAL ((u32) BIT(30))
|
||||||
#define HE_OPERATION_BSS_COLOR_DISABLED ((u32) BIT(31))
|
#define HE_OPERATION_BSS_COLOR_DISABLED ((u32) BIT(31))
|
||||||
#define HE_OPERATION_BSS_COLOR_OFFSET 24
|
#define HE_OPERATION_BSS_COLOR_OFFSET 24
|
||||||
|
|
||||||
@ -2278,4 +2346,25 @@ enum edmg_bw_config {
|
|||||||
/* DPP Public Action frame identifiers - OUI_WFA */
|
/* DPP Public Action frame identifiers - OUI_WFA */
|
||||||
#define DPP_OUI_TYPE 0x1A
|
#define DPP_OUI_TYPE 0x1A
|
||||||
|
|
||||||
|
/* Robust AV streaming Action field values */
|
||||||
|
enum robust_av_streaming_action {
|
||||||
|
ROBUST_AV_SCS_REQ = 0,
|
||||||
|
ROBUST_AV_SCS_RESP = 1,
|
||||||
|
ROBUST_AV_GROUP_MEMBERSHIP_REQ = 2,
|
||||||
|
ROBUST_AV_GROUP_MEMBERSHIP_RESP = 3,
|
||||||
|
ROBUST_AV_MSCS_REQ = 4,
|
||||||
|
ROBUST_AV_MSCS_RESP = 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum scs_request_type {
|
||||||
|
SCS_REQ_ADD = 0,
|
||||||
|
SCS_REQ_REMOVE = 1,
|
||||||
|
SCS_REQ_CHANGE = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Optional subelement IDs for MSCS Descriptor element */
|
||||||
|
enum mscs_description_subelem {
|
||||||
|
MCSC_SUBELEM_STATUS = 1,
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* IEEE802_11_DEFS_H */
|
#endif /* IEEE802_11_DEFS_H */
|
||||||
|
@ -45,6 +45,8 @@ int ocv_derive_all_parameters(struct oci_info *oci)
|
|||||||
oci->sec_channel = 1;
|
oci->sec_channel = 1;
|
||||||
else if (op_class_map->bw == BW40MINUS)
|
else if (op_class_map->bw == BW40MINUS)
|
||||||
oci->sec_channel = -1;
|
oci->sec_channel = -1;
|
||||||
|
else if (op_class_map->bw == BW40)
|
||||||
|
oci->sec_channel = (((oci->channel - 1) / 4) % 2) ? -1 : 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -95,23 +97,24 @@ int ocv_insert_extended_oci(struct wpa_channel_info *ci, u8 *pos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len,
|
enum oci_verify_result
|
||||||
struct wpa_channel_info *ci, int tx_chanwidth,
|
ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len,
|
||||||
int tx_seg1_idx)
|
struct wpa_channel_info *ci, int tx_chanwidth,
|
||||||
|
int tx_seg1_idx)
|
||||||
{
|
{
|
||||||
struct oci_info oci;
|
struct oci_info oci;
|
||||||
|
|
||||||
if (!oci_ie) {
|
if (!oci_ie) {
|
||||||
os_snprintf(ocv_errorstr, sizeof(ocv_errorstr),
|
os_snprintf(ocv_errorstr, sizeof(ocv_errorstr),
|
||||||
"OCV failed: did not receive mandatory OCI");
|
"did not receive mandatory OCI");
|
||||||
return -1;
|
return OCI_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oci_ie_len != 3) {
|
if (oci_ie_len != 3) {
|
||||||
os_snprintf(ocv_errorstr, sizeof(ocv_errorstr),
|
os_snprintf(ocv_errorstr, sizeof(ocv_errorstr),
|
||||||
"OCV failed: received OCI of unexpected length (%d)",
|
"received OCI of unexpected length (%d)",
|
||||||
(int) oci_ie_len);
|
(int) oci_ie_len);
|
||||||
return -1;
|
return OCI_INVALID_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
os_memset(&oci, 0, sizeof(oci));
|
os_memset(&oci, 0, sizeof(oci));
|
||||||
@ -120,25 +123,25 @@ int ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len,
|
|||||||
oci.seg1_idx = oci_ie[2];
|
oci.seg1_idx = oci_ie[2];
|
||||||
if (ocv_derive_all_parameters(&oci) != 0) {
|
if (ocv_derive_all_parameters(&oci) != 0) {
|
||||||
os_snprintf(ocv_errorstr, sizeof(ocv_errorstr),
|
os_snprintf(ocv_errorstr, sizeof(ocv_errorstr),
|
||||||
"OCV failed: unable to interpret received OCI");
|
"unable to interpret received OCI");
|
||||||
return -1;
|
return OCI_PARSE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Primary frequency used to send frames to STA must match the STA's */
|
/* Primary frequency used to send frames to STA must match the STA's */
|
||||||
if ((int) ci->frequency != oci.freq) {
|
if ((int) ci->frequency != oci.freq) {
|
||||||
os_snprintf(ocv_errorstr, sizeof(ocv_errorstr),
|
os_snprintf(ocv_errorstr, sizeof(ocv_errorstr),
|
||||||
"OCV failed: primary channel mismatch in received OCI (we use %d but receiver is using %d)",
|
"primary channel mismatch in received OCI (we use %d but receiver is using %d)",
|
||||||
ci->frequency, oci.freq);
|
ci->frequency, oci.freq);
|
||||||
return -1;
|
return OCI_PRIMARY_FREQ_MISMATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We shouldn't transmit with a higher bandwidth than the STA supports
|
/* We shouldn't transmit with a higher bandwidth than the STA supports
|
||||||
*/
|
*/
|
||||||
if (tx_chanwidth > oci.chanwidth) {
|
if (tx_chanwidth > oci.chanwidth) {
|
||||||
os_snprintf(ocv_errorstr, sizeof(ocv_errorstr),
|
os_snprintf(ocv_errorstr, sizeof(ocv_errorstr),
|
||||||
"OCV failed: channel bandwidth mismatch in received OCI (we use %d but receiver only supports %d)",
|
"channel bandwidth mismatch in received OCI (we use %d but receiver only supports %d)",
|
||||||
tx_chanwidth, oci.chanwidth);
|
tx_chanwidth, oci.chanwidth);
|
||||||
return -1;
|
return OCI_CHANNEL_WIDTH_MISMATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -150,9 +153,9 @@ int ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len,
|
|||||||
if (tx_chanwidth == 40 && ci->frequency < 2500 &&
|
if (tx_chanwidth == 40 && ci->frequency < 2500 &&
|
||||||
ci->sec_channel != oci.sec_channel) {
|
ci->sec_channel != oci.sec_channel) {
|
||||||
os_snprintf(ocv_errorstr, sizeof(ocv_errorstr),
|
os_snprintf(ocv_errorstr, sizeof(ocv_errorstr),
|
||||||
"OCV failed: secondary channel mismatch in received OCI (we use %d but receiver is using %d)",
|
"secondary channel mismatch in received OCI (we use %d but receiver is using %d)",
|
||||||
ci->sec_channel, oci.sec_channel);
|
ci->sec_channel, oci.sec_channel);
|
||||||
return -1;
|
return OCI_SECONDARY_FREQ_MISMATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -163,10 +166,10 @@ int ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len,
|
|||||||
ci->chanwidth == CHAN_WIDTH_80P80) &&
|
ci->chanwidth == CHAN_WIDTH_80P80) &&
|
||||||
tx_seg1_idx != oci.seg1_idx) {
|
tx_seg1_idx != oci.seg1_idx) {
|
||||||
os_snprintf(ocv_errorstr, sizeof(ocv_errorstr),
|
os_snprintf(ocv_errorstr, sizeof(ocv_errorstr),
|
||||||
"OCV failed: frequency segment 1 mismatch in received OCI (we use %d but receiver is using %d)",
|
"frequency segment 1 mismatch in received OCI (we use %d but receiver is using %d)",
|
||||||
tx_seg1_idx, oci.seg1_idx);
|
tx_seg1_idx, oci.seg1_idx);
|
||||||
return -1;
|
return OCI_SEG_1_INDEX_MISMATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return OCI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -27,14 +27,21 @@ struct oci_info {
|
|||||||
#define OCV_OCI_EXTENDED_LEN (3 + OCV_OCI_LEN)
|
#define OCV_OCI_EXTENDED_LEN (3 + OCV_OCI_LEN)
|
||||||
#define OCV_OCI_KDE_LEN (2 + RSN_SELECTOR_LEN + OCV_OCI_LEN)
|
#define OCV_OCI_KDE_LEN (2 + RSN_SELECTOR_LEN + OCV_OCI_LEN)
|
||||||
|
|
||||||
|
enum oci_verify_result {
|
||||||
|
OCI_SUCCESS, OCI_NOT_FOUND, OCI_INVALID_LENGTH, OCI_PARSE_ERROR,
|
||||||
|
OCI_PRIMARY_FREQ_MISMATCH, OCI_CHANNEL_WIDTH_MISMATCH,
|
||||||
|
OCI_SECONDARY_FREQ_MISMATCH, OCI_SEG_1_INDEX_MISMATCH
|
||||||
|
};
|
||||||
|
|
||||||
extern char ocv_errorstr[256];
|
extern char ocv_errorstr[256];
|
||||||
|
|
||||||
int ocv_derive_all_parameters(struct oci_info *oci);
|
int ocv_derive_all_parameters(struct oci_info *oci);
|
||||||
int ocv_insert_oci(struct wpa_channel_info *ci, u8 **argpos);
|
int ocv_insert_oci(struct wpa_channel_info *ci, u8 **argpos);
|
||||||
int ocv_insert_oci_kde(struct wpa_channel_info *ci, u8 **argpos);
|
int ocv_insert_oci_kde(struct wpa_channel_info *ci, u8 **argpos);
|
||||||
int ocv_insert_extended_oci(struct wpa_channel_info *ci, u8 *pos);
|
int ocv_insert_extended_oci(struct wpa_channel_info *ci, u8 *pos);
|
||||||
int ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len,
|
enum oci_verify_result
|
||||||
struct wpa_channel_info *ci, int tx_chanwidth,
|
ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len,
|
||||||
int tx_seg1_idx);
|
struct wpa_channel_info *ci, int tx_chanwidth,
|
||||||
|
int tx_seg1_idx);
|
||||||
|
|
||||||
#endif /* OCV_H */
|
#endif /* OCV_H */
|
||||||
|
@ -82,6 +82,7 @@ struct privsep_cmd_set_key {
|
|||||||
size_t seq_len;
|
size_t seq_len;
|
||||||
u8 key[32];
|
u8 key[32];
|
||||||
size_t key_len;
|
size_t key_len;
|
||||||
|
enum key_flag key_flag;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum privsep_event {
|
enum privsep_event {
|
||||||
|
File diff suppressed because it is too large
Load Diff
133
src/common/sae.c
133
src/common/sae.c
@ -169,7 +169,7 @@ static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed,
|
|||||||
* being smaller than prime. */
|
* being smaller than prime. */
|
||||||
in_range = const_time_fill_msb((unsigned int) cmp_prime);
|
in_range = const_time_fill_msb((unsigned int) cmp_prime);
|
||||||
/* The algorithm description would skip the next steps if
|
/* The algorithm description would skip the next steps if
|
||||||
* cmp_prime >= 0 (reutnr 0 here), but go through them regardless to
|
* cmp_prime >= 0 (return 0 here), but go through them regardless to
|
||||||
* minimize externally observable differences in behavior. */
|
* minimize externally observable differences in behavior. */
|
||||||
|
|
||||||
x_cand = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len);
|
x_cand = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len);
|
||||||
@ -713,6 +713,8 @@ static struct crypto_ec_point * sswu(struct crypto_ec *ec, int group,
|
|||||||
goto fail;
|
goto fail;
|
||||||
const_time_select_bin(m_is_zero, bin1, bin2, prime_len, bin);
|
const_time_select_bin(m_is_zero, bin1, bin2, prime_len, bin);
|
||||||
x1 = crypto_bignum_init_set(bin, prime_len);
|
x1 = crypto_bignum_init_set(bin, prime_len);
|
||||||
|
if (!x1)
|
||||||
|
goto fail;
|
||||||
debug_print_bignum("SSWU: x1 = CSEL(l, x1a, x1b)", x1, prime_len);
|
debug_print_bignum("SSWU: x1 = CSEL(l, x1a, x1b)", x1, prime_len);
|
||||||
|
|
||||||
/* gx1 = x1^3 + a * x1 + b */
|
/* gx1 = x1^3 + a * x1 + b */
|
||||||
@ -753,6 +755,8 @@ static struct crypto_ec_point * sswu(struct crypto_ec *ec, int group,
|
|||||||
goto fail;
|
goto fail;
|
||||||
const_time_select_bin(is_qr, bin1, bin2, prime_len, bin);
|
const_time_select_bin(is_qr, bin1, bin2, prime_len, bin);
|
||||||
v = crypto_bignum_init_set(bin, prime_len);
|
v = crypto_bignum_init_set(bin, prime_len);
|
||||||
|
if (!v)
|
||||||
|
goto fail;
|
||||||
debug_print_bignum("SSWU: v = CSEL(l, gx1, gx2)", v, prime_len);
|
debug_print_bignum("SSWU: v = CSEL(l, gx1, gx2)", v, prime_len);
|
||||||
|
|
||||||
/* x = CSEL(l, x1, x2) */
|
/* x = CSEL(l, x1, x2) */
|
||||||
@ -1052,10 +1056,17 @@ sae_derive_pt_group(int group, const u8 *ssid, size_t ssid_len,
|
|||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "SAE: Derive PT - group %d", group);
|
wpa_printf(MSG_DEBUG, "SAE: Derive PT - group %d", group);
|
||||||
|
|
||||||
|
if (ssid_len > 32)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
pt = os_zalloc(sizeof(*pt));
|
pt = os_zalloc(sizeof(*pt));
|
||||||
if (!pt)
|
if (!pt)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
#ifdef CONFIG_SAE_PK
|
||||||
|
os_memcpy(pt->ssid, ssid, ssid_len);
|
||||||
|
pt->ssid_len = ssid_len;
|
||||||
|
#endif /* CONFIG_SAE_PK */
|
||||||
pt->group = group;
|
pt->group = group;
|
||||||
pt->ec = crypto_ec_init(group);
|
pt->ec = crypto_ec_init(group);
|
||||||
if (pt->ec) {
|
if (pt->ec) {
|
||||||
@ -1354,14 +1365,15 @@ int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
|
|||||||
identifier) < 0))
|
identifier) < 0))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
sae->tmp->h2e = 0;
|
sae->h2e = 0;
|
||||||
|
sae->pk = 0;
|
||||||
return sae_derive_commit(sae);
|
return sae_derive_commit(sae);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int sae_prepare_commit_pt(struct sae_data *sae, const struct sae_pt *pt,
|
int sae_prepare_commit_pt(struct sae_data *sae, const struct sae_pt *pt,
|
||||||
const u8 *addr1, const u8 *addr2,
|
const u8 *addr1, const u8 *addr2,
|
||||||
int *rejected_groups)
|
int *rejected_groups, const struct sae_pk *pk)
|
||||||
{
|
{
|
||||||
if (!sae->tmp)
|
if (!sae->tmp)
|
||||||
return -1;
|
return -1;
|
||||||
@ -1377,6 +1389,11 @@ int sae_prepare_commit_pt(struct sae_data *sae, const struct sae_pt *pt,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SAE_PK
|
||||||
|
os_memcpy(sae->tmp->ssid, pt->ssid, pt->ssid_len);
|
||||||
|
sae->tmp->ssid_len = pt->ssid_len;
|
||||||
|
sae->tmp->ap_pk = pk;
|
||||||
|
#endif /* CONFIG_SAE_PK */
|
||||||
sae->tmp->own_addr_higher = os_memcmp(addr1, addr2, ETH_ALEN) > 0;
|
sae->tmp->own_addr_higher = os_memcmp(addr1, addr2, ETH_ALEN) > 0;
|
||||||
wpabuf_free(sae->tmp->own_rejected_groups);
|
wpabuf_free(sae->tmp->own_rejected_groups);
|
||||||
sae->tmp->own_rejected_groups = NULL;
|
sae->tmp->own_rejected_groups = NULL;
|
||||||
@ -1409,7 +1426,7 @@ int sae_prepare_commit_pt(struct sae_data *sae, const struct sae_pt *pt,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sae->tmp->h2e = 1;
|
sae->h2e = 1;
|
||||||
return sae_derive_commit(sae);
|
return sae_derive_commit(sae);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1515,7 +1532,7 @@ static int sae_derive_keys(struct sae_data *sae, const u8 *k)
|
|||||||
const u8 *salt;
|
const u8 *salt;
|
||||||
struct wpabuf *rejected_groups = NULL;
|
struct wpabuf *rejected_groups = NULL;
|
||||||
u8 keyseed[SAE_MAX_HASH_LEN];
|
u8 keyseed[SAE_MAX_HASH_LEN];
|
||||||
u8 keys[SAE_MAX_HASH_LEN + SAE_PMK_LEN];
|
u8 keys[2 * SAE_MAX_HASH_LEN + SAE_PMK_LEN];
|
||||||
struct crypto_bignum *tmp;
|
struct crypto_bignum *tmp;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
size_t hash_len, salt_len, prime_len = sae->tmp->prime_len;
|
size_t hash_len, salt_len, prime_len = sae->tmp->prime_len;
|
||||||
@ -1530,15 +1547,18 @@ static int sae_derive_keys(struct sae_data *sae, const u8 *k)
|
|||||||
* KCK || PMK = KDF-Hash-Length(keyseed, "SAE KCK and PMK",
|
* KCK || PMK = KDF-Hash-Length(keyseed, "SAE KCK and PMK",
|
||||||
* (commit-scalar + peer-commit-scalar) modulo r)
|
* (commit-scalar + peer-commit-scalar) modulo r)
|
||||||
* PMKID = L((commit-scalar + peer-commit-scalar) modulo r, 0, 128)
|
* PMKID = L((commit-scalar + peer-commit-scalar) modulo r, 0, 128)
|
||||||
|
*
|
||||||
|
* When SAE-PK is used,
|
||||||
|
* KCK || PMK || KEK = KDF-Hash-Length(keyseed, "SAE-PK keys", context)
|
||||||
*/
|
*/
|
||||||
if (!sae->tmp->h2e)
|
if (!sae->h2e)
|
||||||
hash_len = SHA256_MAC_LEN;
|
hash_len = SHA256_MAC_LEN;
|
||||||
else if (sae->tmp->dh)
|
else if (sae->tmp->dh)
|
||||||
hash_len = sae_ffc_prime_len_2_hash_len(prime_len);
|
hash_len = sae_ffc_prime_len_2_hash_len(prime_len);
|
||||||
else
|
else
|
||||||
hash_len = sae_ecc_prime_len_2_hash_len(prime_len);
|
hash_len = sae_ecc_prime_len_2_hash_len(prime_len);
|
||||||
if (sae->tmp->h2e && (sae->tmp->own_rejected_groups ||
|
if (sae->h2e && (sae->tmp->own_rejected_groups ||
|
||||||
sae->tmp->peer_rejected_groups)) {
|
sae->tmp->peer_rejected_groups)) {
|
||||||
struct wpabuf *own, *peer;
|
struct wpabuf *own, *peer;
|
||||||
|
|
||||||
own = sae->tmp->own_rejected_groups;
|
own = sae->tmp->own_rejected_groups;
|
||||||
@ -1589,15 +1609,40 @@ static int sae_derive_keys(struct sae_data *sae, const u8 *k)
|
|||||||
* octets). */
|
* octets). */
|
||||||
crypto_bignum_to_bin(tmp, val, sizeof(val), sae->tmp->order_len);
|
crypto_bignum_to_bin(tmp, val, sizeof(val), sae->tmp->order_len);
|
||||||
wpa_hexdump(MSG_DEBUG, "SAE: PMKID", val, SAE_PMKID_LEN);
|
wpa_hexdump(MSG_DEBUG, "SAE: PMKID", val, SAE_PMKID_LEN);
|
||||||
|
|
||||||
|
#ifdef CONFIG_SAE_PK
|
||||||
|
if (sae->pk) {
|
||||||
|
if (sae_kdf_hash(hash_len, keyseed, "SAE-PK keys",
|
||||||
|
val, sae->tmp->order_len,
|
||||||
|
keys, 2 * hash_len + SAE_PMK_LEN) < 0)
|
||||||
|
goto fail;
|
||||||
|
} else {
|
||||||
|
if (sae_kdf_hash(hash_len, keyseed, "SAE KCK and PMK",
|
||||||
|
val, sae->tmp->order_len,
|
||||||
|
keys, hash_len + SAE_PMK_LEN) < 0)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#else /* CONFIG_SAE_PK */
|
||||||
if (sae_kdf_hash(hash_len, keyseed, "SAE KCK and PMK",
|
if (sae_kdf_hash(hash_len, keyseed, "SAE KCK and PMK",
|
||||||
val, sae->tmp->order_len,
|
val, sae->tmp->order_len,
|
||||||
keys, hash_len + SAE_PMK_LEN) < 0)
|
keys, hash_len + SAE_PMK_LEN) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
#endif /* !CONFIG_SAE_PK */
|
||||||
|
|
||||||
forced_memzero(keyseed, sizeof(keyseed));
|
forced_memzero(keyseed, sizeof(keyseed));
|
||||||
os_memcpy(sae->tmp->kck, keys, hash_len);
|
os_memcpy(sae->tmp->kck, keys, hash_len);
|
||||||
sae->tmp->kck_len = hash_len;
|
sae->tmp->kck_len = hash_len;
|
||||||
os_memcpy(sae->pmk, keys + hash_len, SAE_PMK_LEN);
|
os_memcpy(sae->pmk, keys + hash_len, SAE_PMK_LEN);
|
||||||
os_memcpy(sae->pmkid, val, SAE_PMKID_LEN);
|
os_memcpy(sae->pmkid, val, SAE_PMKID_LEN);
|
||||||
|
#ifdef CONFIG_SAE_PK
|
||||||
|
if (sae->pk) {
|
||||||
|
os_memcpy(sae->tmp->kek, keys + hash_len + SAE_PMK_LEN,
|
||||||
|
hash_len);
|
||||||
|
sae->tmp->kek_len = hash_len;
|
||||||
|
wpa_hexdump_key(MSG_DEBUG, "SAE: KEK for SAE-PK",
|
||||||
|
sae->tmp->kek, sae->tmp->kek_len);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_SAE_PK */
|
||||||
forced_memzero(keys, sizeof(keys));
|
forced_memzero(keys, sizeof(keys));
|
||||||
wpa_hexdump_key(MSG_DEBUG, "SAE: KCK",
|
wpa_hexdump_key(MSG_DEBUG, "SAE: KCK",
|
||||||
sae->tmp->kck, sae->tmp->kck_len);
|
sae->tmp->kck, sae->tmp->kck_len);
|
||||||
@ -1623,38 +1668,42 @@ int sae_process_commit(struct sae_data *sae)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
|
int sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
|
||||||
const struct wpabuf *token, const char *identifier)
|
const struct wpabuf *token, const char *identifier)
|
||||||
{
|
{
|
||||||
u8 *pos;
|
u8 *pos;
|
||||||
|
|
||||||
if (sae->tmp == NULL)
|
if (sae->tmp == NULL)
|
||||||
return;
|
return -1;
|
||||||
|
|
||||||
wpabuf_put_le16(buf, sae->group); /* Finite Cyclic Group */
|
wpabuf_put_le16(buf, sae->group); /* Finite Cyclic Group */
|
||||||
if (!sae->tmp->h2e && token) {
|
if (!sae->h2e && token) {
|
||||||
wpabuf_put_buf(buf, token);
|
wpabuf_put_buf(buf, token);
|
||||||
wpa_hexdump(MSG_DEBUG, "SAE: Anti-clogging token",
|
wpa_hexdump(MSG_DEBUG, "SAE: Anti-clogging token",
|
||||||
wpabuf_head(token), wpabuf_len(token));
|
wpabuf_head(token), wpabuf_len(token));
|
||||||
}
|
}
|
||||||
pos = wpabuf_put(buf, sae->tmp->prime_len);
|
pos = wpabuf_put(buf, sae->tmp->prime_len);
|
||||||
crypto_bignum_to_bin(sae->tmp->own_commit_scalar, pos,
|
if (crypto_bignum_to_bin(sae->tmp->own_commit_scalar, pos,
|
||||||
sae->tmp->prime_len, sae->tmp->prime_len);
|
sae->tmp->prime_len, sae->tmp->prime_len) < 0)
|
||||||
|
return -1;
|
||||||
wpa_hexdump(MSG_DEBUG, "SAE: own commit-scalar",
|
wpa_hexdump(MSG_DEBUG, "SAE: own commit-scalar",
|
||||||
pos, sae->tmp->prime_len);
|
pos, sae->tmp->prime_len);
|
||||||
if (sae->tmp->ec) {
|
if (sae->tmp->ec) {
|
||||||
pos = wpabuf_put(buf, 2 * sae->tmp->prime_len);
|
pos = wpabuf_put(buf, 2 * sae->tmp->prime_len);
|
||||||
crypto_ec_point_to_bin(sae->tmp->ec,
|
if (crypto_ec_point_to_bin(sae->tmp->ec,
|
||||||
sae->tmp->own_commit_element_ecc,
|
sae->tmp->own_commit_element_ecc,
|
||||||
pos, pos + sae->tmp->prime_len);
|
pos, pos + sae->tmp->prime_len) < 0)
|
||||||
|
return -1;
|
||||||
wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(x)",
|
wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(x)",
|
||||||
pos, sae->tmp->prime_len);
|
pos, sae->tmp->prime_len);
|
||||||
wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(y)",
|
wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(y)",
|
||||||
pos + sae->tmp->prime_len, sae->tmp->prime_len);
|
pos + sae->tmp->prime_len, sae->tmp->prime_len);
|
||||||
} else {
|
} else {
|
||||||
pos = wpabuf_put(buf, sae->tmp->prime_len);
|
pos = wpabuf_put(buf, sae->tmp->prime_len);
|
||||||
crypto_bignum_to_bin(sae->tmp->own_commit_element_ffc, pos,
|
if (crypto_bignum_to_bin(sae->tmp->own_commit_element_ffc, pos,
|
||||||
sae->tmp->prime_len, sae->tmp->prime_len);
|
sae->tmp->prime_len,
|
||||||
|
sae->tmp->prime_len) < 0)
|
||||||
|
return -1;
|
||||||
wpa_hexdump(MSG_DEBUG, "SAE: own commit-element",
|
wpa_hexdump(MSG_DEBUG, "SAE: own commit-element",
|
||||||
pos, sae->tmp->prime_len);
|
pos, sae->tmp->prime_len);
|
||||||
}
|
}
|
||||||
@ -1669,7 +1718,7 @@ void sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
|
|||||||
identifier);
|
identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sae->tmp->h2e && sae->tmp->own_rejected_groups) {
|
if (sae->h2e && sae->tmp->own_rejected_groups) {
|
||||||
wpa_hexdump_buf(MSG_DEBUG, "SAE: own Rejected Groups",
|
wpa_hexdump_buf(MSG_DEBUG, "SAE: own Rejected Groups",
|
||||||
sae->tmp->own_rejected_groups);
|
sae->tmp->own_rejected_groups);
|
||||||
wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
|
wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
|
||||||
@ -1679,7 +1728,7 @@ void sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
|
|||||||
wpabuf_put_buf(buf, sae->tmp->own_rejected_groups);
|
wpabuf_put_buf(buf, sae->tmp->own_rejected_groups);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sae->tmp->h2e && token) {
|
if (sae->h2e && token) {
|
||||||
wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
|
wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
|
||||||
wpabuf_put_u8(buf, 1 + wpabuf_len(token));
|
wpabuf_put_u8(buf, 1 + wpabuf_len(token));
|
||||||
wpabuf_put_u8(buf, WLAN_EID_EXT_ANTI_CLOGGING_TOKEN);
|
wpabuf_put_u8(buf, WLAN_EID_EXT_ANTI_CLOGGING_TOKEN);
|
||||||
@ -1688,6 +1737,8 @@ void sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
|
|||||||
"SAE: Anti-clogging token (in container)",
|
"SAE: Anti-clogging token (in container)",
|
||||||
token);
|
token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2183,13 +2234,14 @@ static int sae_cn_confirm_ffc(struct sae_data *sae, const u8 *sc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf)
|
int sae_write_confirm(struct sae_data *sae, struct wpabuf *buf)
|
||||||
{
|
{
|
||||||
const u8 *sc;
|
const u8 *sc;
|
||||||
size_t hash_len;
|
size_t hash_len;
|
||||||
|
int res;
|
||||||
|
|
||||||
if (sae->tmp == NULL)
|
if (sae->tmp == NULL)
|
||||||
return;
|
return -1;
|
||||||
|
|
||||||
hash_len = sae->tmp->kck_len;
|
hash_len = sae->tmp->kck_len;
|
||||||
|
|
||||||
@ -2200,17 +2252,26 @@ void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf)
|
|||||||
sae->send_confirm++;
|
sae->send_confirm++;
|
||||||
|
|
||||||
if (sae->tmp->ec)
|
if (sae->tmp->ec)
|
||||||
sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar,
|
res = sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar,
|
||||||
sae->tmp->own_commit_element_ecc,
|
sae->tmp->own_commit_element_ecc,
|
||||||
sae->peer_commit_scalar,
|
sae->peer_commit_scalar,
|
||||||
sae->tmp->peer_commit_element_ecc,
|
sae->tmp->peer_commit_element_ecc,
|
||||||
wpabuf_put(buf, hash_len));
|
wpabuf_put(buf, hash_len));
|
||||||
else
|
else
|
||||||
sae_cn_confirm_ffc(sae, sc, sae->tmp->own_commit_scalar,
|
res = sae_cn_confirm_ffc(sae, sc, sae->tmp->own_commit_scalar,
|
||||||
sae->tmp->own_commit_element_ffc,
|
sae->tmp->own_commit_element_ffc,
|
||||||
sae->peer_commit_scalar,
|
sae->peer_commit_scalar,
|
||||||
sae->tmp->peer_commit_element_ffc,
|
sae->tmp->peer_commit_element_ffc,
|
||||||
wpabuf_put(buf, hash_len));
|
wpabuf_put(buf, hash_len));
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
#ifdef CONFIG_SAE_PK
|
||||||
|
if (sae_write_confirm_pk(sae, buf) < 0)
|
||||||
|
return -1;
|
||||||
|
#endif /* CONFIG_SAE_PK */
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2264,6 +2325,12 @@ int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SAE_PK
|
||||||
|
if (sae_check_confirm_pk(sae, data + 2 + hash_len,
|
||||||
|
len - 2 - hash_len) < 0)
|
||||||
|
return -1;
|
||||||
|
#endif /* CONFIG_SAE_PK */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user