Compare commits
168 commits
hostap-lim
...
main
Author | SHA1 | Date | |
---|---|---|---|
|
bde17063d5 | ||
|
809d9d8172 | ||
|
3ab781fb29 | ||
|
0012c4433c | ||
|
782c89c359 | ||
|
de40e08f70 | ||
|
c3ee46bcbe | ||
|
63df62c6c0 | ||
|
f3fd2f699f | ||
|
14cb3906af | ||
|
757d8d9aac | ||
|
61dfd7ae35 | ||
|
8625001ce5 | ||
|
b7963348cd | ||
|
d15403aefb | ||
|
3935d78e7b | ||
|
2b7277d3f0 | ||
|
97c6ef2588 | ||
|
e33acc2178 | ||
|
59299a8a7d | ||
|
6aa9ad8f8f | ||
|
b4f9742ee2 | ||
|
fa389f2a3b | ||
|
25c6598f30 | ||
|
bcab29a78c | ||
|
58ba550c53 | ||
|
5b0112a185 | ||
|
29f70292e5 | ||
|
a58b2ba2fc | ||
|
ae221945f6 | ||
|
633e969311 | ||
|
87c6b322ee | ||
|
d984172189 | ||
|
c6a8db47c3 | ||
|
c03edfd5bd | ||
|
7683ce1cff | ||
|
d9bb64914a | ||
|
8f21cdf9d7 | ||
|
18116e38a2 | ||
|
882bd2edd5 | ||
|
503e22025b | ||
|
064a46b478 | ||
|
9da9e41612 | ||
|
df8c5e22d7 | ||
|
bbb55af8c3 | ||
|
66d8ac8ccc | ||
|
70b8f64faf | ||
|
5fd3d05a40 | ||
|
fd72d395db | ||
|
88150522ce | ||
|
bc5d3bf623 | ||
|
8c9b9ccb49 | ||
|
7275b65149 | ||
|
5dbbca24ea | ||
|
19e12d5e2d | ||
|
189972d129 | ||
|
43943ea5b3 | ||
|
c4f9279267 | ||
|
7e7e43d6b3 | ||
|
1282787878 | ||
|
015f6a5a0c | ||
|
3e2758b19a | ||
|
15bf093b5b | ||
|
c43e1e5a5f | ||
|
c3beaf6b86 | ||
|
3e420372e7 | ||
|
c6ff28cb63 | ||
|
e1bf37022e | ||
|
f519f472e6 | ||
|
2d290f1966 | ||
|
e9984e3db2 | ||
|
8324947a67 | ||
|
abd7f47958 | ||
|
72ac0ee026 | ||
|
e900bcb149 | ||
|
e33a55d31d | ||
|
de2ee083e7 | ||
|
bd8a1f5ff5 | ||
|
c6faa89366 | ||
|
74db2b7449 | ||
|
023d70d6ca | ||
|
b5359d01ed | ||
|
abe990afb9 | ||
|
2042cae9b3 | ||
|
8f07e9699b | ||
|
5cb6747f97 | ||
|
b7f08c28cd | ||
|
c7e704bdf9 | ||
|
c9d0c6fd7e | ||
|
b592c1586e | ||
|
89c31feb31 | ||
|
83c4adcdac | ||
|
9f334fe683 | ||
|
69deac87fb | ||
|
ca58be3da4 | ||
|
666d695bbd | ||
|
fd55dfe16e | ||
|
23456e480e | ||
|
619ff3d2e8 | ||
|
733069fd4c | ||
|
222d443950 | ||
|
205dbb0fef | ||
|
9ff4fd30ff | ||
|
871bfdcdf6 | ||
|
d3f340c869 | ||
|
d42cfaa397 | ||
|
a66cb09930 | ||
|
acd9332c3b | ||
|
d40788a5cb | ||
|
9c0a6d64d0 | ||
|
b53d7a6a86 | ||
|
9e50c12b31 | ||
|
3cf4b4ad88 | ||
|
54b25b7c1d | ||
|
d9d8627873 | ||
|
3b6abe3580 | ||
|
f4a9cb96d6 | ||
|
020f20a222 | ||
|
adc6ca34a0 | ||
|
a832312806 | ||
|
582b5eff40 | ||
|
4bbe004e06 | ||
|
b791d1f342 | ||
|
da1a86afc6 | ||
|
ebd18f1ade | ||
|
93eb3b83c6 | ||
|
63ac001ed2 | ||
|
bb96540ef5 | ||
|
bc43e75b2b | ||
|
69d18ab9f2 | ||
|
56e8f8bf34 | ||
|
ddfed3f084 | ||
|
1e54160515 | ||
|
21c3a7494c | ||
|
5942965955 | ||
|
e1ab680c98 | ||
|
7e0e69cfea | ||
|
be6e4279fa | ||
|
4d110b4f87 | ||
|
521374b978 | ||
|
6f522baa1b | ||
|
62ca121f96 | ||
|
524c452153 | ||
|
13648dde91 | ||
|
376adfea8d | ||
|
4adf234cd3 | ||
|
9732c8b85c | ||
|
e0053bf9d0 | ||
|
296104d35c | ||
|
2e4c612dd2 | ||
|
bb61f6cb95 | ||
|
8b2ddfdbb6 | ||
|
92374d59d4 | ||
|
ff99012d84 | ||
|
526ea193c8 | ||
|
4417b5ba86 | ||
|
8d54863550 | ||
|
765c48d5ad | ||
|
d0b55eb360 | ||
|
5488e120d3 | ||
|
341bcb2b5c | ||
|
6fad7224be | ||
|
157b016383 | ||
|
b8a2d11ae0 | ||
|
48ca68f6f8 | ||
|
c16ac89be2 | ||
|
6b0ce29d25 | ||
|
e99cdfae41 |
145 changed files with 8873 additions and 3898 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -6,3 +6,6 @@ wpaspy/build
|
||||||
**/parallel-vm.log
|
**/parallel-vm.log
|
||||||
tags
|
tags
|
||||||
build/
|
build/
|
||||||
|
# clangd commands and cache
|
||||||
|
compile_commands.json
|
||||||
|
.cache
|
||||||
|
|
|
@ -883,6 +883,11 @@ fi.w1.wpa_supplicant1.CreateInterface.
|
||||||
<p>The most recent roam success or failure.</p>
|
<p>The most recent roam success or failure.</p>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<h3>ScanInProgress6GHz - b - (read)</h3>
|
||||||
|
<p>Whether a 6GHz scan is currently in progress.</p>
|
||||||
|
</li>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<h3>SessionLength - u - (read)</h3>
|
<h3>SessionLength - u - (read)</h3>
|
||||||
<p>The most recent BSS session length in milliseconds.</p>
|
<p>The most recent BSS session length in milliseconds.</p>
|
||||||
|
|
54
gen_compile_commands.py
Executable file
54
gen_compile_commands.py
Executable file
|
@ -0,0 +1,54 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# compile_commands.json generator
|
||||||
|
# Copyright (C) 2024 Intel Corporation
|
||||||
|
#
|
||||||
|
# This software may be distributed under the terms of the BSD license.
|
||||||
|
# See README for more details.
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import glob
|
||||||
|
import json
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description='Read each of the build directories that are given and generate '
|
||||||
|
'a compile_commands.json file. If a source file is found multiple times, '
|
||||||
|
'then the compile flags from the last build directory will be used.')
|
||||||
|
parser.add_argument('-o', '--output', default='compile_commands.json', type=str,
|
||||||
|
help="Output file to generate")
|
||||||
|
parser.add_argument('builddirs', nargs='+', type=str, metavar="builddir",
|
||||||
|
help='Build directories to search')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
files = {}
|
||||||
|
|
||||||
|
for builddir in args.builddirs:
|
||||||
|
for cmd_file in glob.glob('**/*.o.cmd', root_dir=builddir, recursive=True):
|
||||||
|
with open(os.path.join(builddir, cmd_file), encoding='ascii') as f:
|
||||||
|
base_dir, cmd = f.readline().split(':', 1)
|
||||||
|
src_file = cmd.rsplit(maxsplit=1)[1]
|
||||||
|
|
||||||
|
src_file = os.path.abspath(os.path.join(base_dir, src_file))
|
||||||
|
files[src_file] = {
|
||||||
|
'command': cmd.strip(),
|
||||||
|
'directory': base_dir,
|
||||||
|
'file': src_file,
|
||||||
|
}
|
||||||
|
|
||||||
|
flist = json.dumps(sorted(list(files.values()), key=lambda k: k['file']), indent=2, sort_keys=True)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Avoid writing the file if it did not change, first read original
|
||||||
|
with open(args.output, 'rt', encoding='UTF-8') as f:
|
||||||
|
orig = []
|
||||||
|
while data := f.read():
|
||||||
|
orig.append(data)
|
||||||
|
orig = ''.join(orig)
|
||||||
|
except OSError:
|
||||||
|
orig = ''
|
||||||
|
|
||||||
|
# And only write if something changed
|
||||||
|
if orig != flist:
|
||||||
|
with open(args.output, 'wt', encoding='UTF-8') as f:
|
||||||
|
f.write(flist)
|
|
@ -166,12 +166,6 @@ OBJS += ../src/common/hw_features_common.o
|
||||||
|
|
||||||
OBJS += ../src/eapol_auth/eapol_auth_sm.o
|
OBJS += ../src/eapol_auth/eapol_auth_sm.o
|
||||||
|
|
||||||
ifdef CONFIG_UBUS
|
|
||||||
CFLAGS += -DUBUS_SUPPORT
|
|
||||||
OBJS += ../src/utils/uloop.o
|
|
||||||
OBJS += ../src/ap/ubus.o
|
|
||||||
LIBS += -lubox -lubus
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifdef CONFIG_CODE_COVERAGE
|
ifdef CONFIG_CODE_COVERAGE
|
||||||
CFLAGS += -O0 -fprofile-arcs -ftest-coverage -U_FORTIFY_SOURCE
|
CFLAGS += -O0 -fprofile-arcs -ftest-coverage -U_FORTIFY_SOURCE
|
||||||
|
|
|
@ -2436,6 +2436,31 @@ static int get_u16(const char *pos, int line, u16 *ret_val)
|
||||||
#endif /* CONFIG_IEEE80211BE */
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
static bool get_hexstream(const char *val, struct wpabuf **var,
|
||||||
|
const char *name, int line)
|
||||||
|
{
|
||||||
|
struct wpabuf *tmp;
|
||||||
|
size_t len = os_strlen(val) / 2;
|
||||||
|
|
||||||
|
tmp = wpabuf_alloc(len);
|
||||||
|
if (!tmp)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (hexstr2bin(val, wpabuf_put(tmp, len), len)) {
|
||||||
|
wpabuf_free(tmp);
|
||||||
|
wpa_printf(MSG_ERROR, "Line %d: Invalid %s '%s'",
|
||||||
|
line, name, val);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpabuf_free(*var);
|
||||||
|
*var = tmp;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
|
|
||||||
static int hostapd_config_fill(struct hostapd_config *conf,
|
static int hostapd_config_fill(struct hostapd_config *conf,
|
||||||
struct hostapd_bss_config *bss,
|
struct hostapd_bss_config *bss,
|
||||||
const char *buf, char *pos, int line)
|
const char *buf, char *pos, int line)
|
||||||
|
@ -3156,6 +3181,16 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
||||||
bss->wpa_key_mgmt = hostapd_config_parse_key_mgmt(line, pos);
|
bss->wpa_key_mgmt = hostapd_config_parse_key_mgmt(line, pos);
|
||||||
if (bss->wpa_key_mgmt == -1)
|
if (bss->wpa_key_mgmt == -1)
|
||||||
return 1;
|
return 1;
|
||||||
|
} else if (os_strcmp(buf, "rsn_override_key_mgmt") == 0) {
|
||||||
|
bss->rsn_override_key_mgmt =
|
||||||
|
hostapd_config_parse_key_mgmt(line, pos);
|
||||||
|
if (bss->rsn_override_key_mgmt == -1)
|
||||||
|
return 1;
|
||||||
|
} else if (os_strcmp(buf, "rsn_override_key_mgmt_2") == 0) {
|
||||||
|
bss->rsn_override_key_mgmt_2 =
|
||||||
|
hostapd_config_parse_key_mgmt(line, pos);
|
||||||
|
if (bss->rsn_override_key_mgmt_2 == -1)
|
||||||
|
return 1;
|
||||||
} else if (os_strcmp(buf, "wpa_psk_radius") == 0) {
|
} else if (os_strcmp(buf, "wpa_psk_radius") == 0) {
|
||||||
bss->wpa_psk_radius = atoi(pos);
|
bss->wpa_psk_radius = atoi(pos);
|
||||||
if (bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
|
if (bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
|
||||||
|
@ -3187,6 +3222,32 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
||||||
line, pos);
|
line, pos);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
} else if (os_strcmp(buf, "rsn_override_pairwise") == 0) {
|
||||||
|
bss->rsn_override_pairwise =
|
||||||
|
hostapd_config_parse_cipher(line, pos);
|
||||||
|
if (bss->rsn_override_pairwise == -1 ||
|
||||||
|
bss->rsn_override_pairwise == 0)
|
||||||
|
return 1;
|
||||||
|
if (bss->rsn_override_pairwise &
|
||||||
|
(WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"Line %d: unsupported pairwise cipher suite '%s'",
|
||||||
|
line, pos);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else if (os_strcmp(buf, "rsn_override_pairwise_2") == 0) {
|
||||||
|
bss->rsn_override_pairwise_2 =
|
||||||
|
hostapd_config_parse_cipher(line, pos);
|
||||||
|
if (bss->rsn_override_pairwise_2 == -1 ||
|
||||||
|
bss->rsn_override_pairwise_2 == 0)
|
||||||
|
return 1;
|
||||||
|
if (bss->rsn_override_pairwise_2 &
|
||||||
|
(WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"Line %d: unsupported pairwise cipher suite '%s'",
|
||||||
|
line, pos);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
} else if (os_strcmp(buf, "group_cipher") == 0) {
|
} else if (os_strcmp(buf, "group_cipher") == 0) {
|
||||||
bss->group_cipher = hostapd_config_parse_cipher(line, pos);
|
bss->group_cipher = hostapd_config_parse_cipher(line, pos);
|
||||||
if (bss->group_cipher == -1 || bss->group_cipher == 0)
|
if (bss->group_cipher == -1 || bss->group_cipher == 0)
|
||||||
|
@ -3208,6 +3269,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
||||||
os_free(bss->rsn_preauth_interfaces);
|
os_free(bss->rsn_preauth_interfaces);
|
||||||
bss->rsn_preauth_interfaces = os_strdup(pos);
|
bss->rsn_preauth_interfaces = os_strdup(pos);
|
||||||
#endif /* CONFIG_RSN_PREAUTH */
|
#endif /* CONFIG_RSN_PREAUTH */
|
||||||
|
} else if (os_strcmp(buf, "rsn_override_omit_rsnxe") == 0) {
|
||||||
|
bss->rsn_override_omit_rsnxe = atoi(pos);
|
||||||
} else if (os_strcmp(buf, "peerkey") == 0) {
|
} else if (os_strcmp(buf, "peerkey") == 0) {
|
||||||
wpa_printf(MSG_INFO,
|
wpa_printf(MSG_INFO,
|
||||||
"Line %d: Obsolete peerkey parameter ignored", line);
|
"Line %d: Obsolete peerkey parameter ignored", line);
|
||||||
|
@ -3642,6 +3705,10 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
||||||
conf->use_driver_iface_addr = atoi(pos);
|
conf->use_driver_iface_addr = atoi(pos);
|
||||||
} else if (os_strcmp(buf, "ieee80211w") == 0) {
|
} else if (os_strcmp(buf, "ieee80211w") == 0) {
|
||||||
bss->ieee80211w = atoi(pos);
|
bss->ieee80211w = atoi(pos);
|
||||||
|
} else if (os_strcmp(buf, "rsn_override_mfp") == 0) {
|
||||||
|
bss->rsn_override_mfp = atoi(pos);
|
||||||
|
} else if (os_strcmp(buf, "rsn_override_mfp_2") == 0) {
|
||||||
|
bss->rsn_override_mfp_2 = atoi(pos);
|
||||||
} else if (os_strcmp(buf, "group_mgmt_cipher") == 0) {
|
} else if (os_strcmp(buf, "group_mgmt_cipher") == 0) {
|
||||||
if (os_strcmp(pos, "AES-128-CMAC") == 0) {
|
if (os_strcmp(pos, "AES-128-CMAC") == 0) {
|
||||||
bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC;
|
bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC;
|
||||||
|
@ -4462,23 +4529,29 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
||||||
bss->radio_measurements[0] |=
|
bss->radio_measurements[0] |=
|
||||||
WLAN_RRM_CAPS_NEIGHBOR_REPORT;
|
WLAN_RRM_CAPS_NEIGHBOR_REPORT;
|
||||||
} else if (os_strcmp(buf, "own_ie_override") == 0) {
|
} else if (os_strcmp(buf, "own_ie_override") == 0) {
|
||||||
struct wpabuf *tmp;
|
if (!get_hexstream(pos, &bss->own_ie_override,
|
||||||
size_t len = os_strlen(pos) / 2;
|
"own_ie_override", line))
|
||||||
|
|
||||||
tmp = wpabuf_alloc(len);
|
|
||||||
if (!tmp)
|
|
||||||
return 1;
|
return 1;
|
||||||
|
} else if (os_strcmp(buf, "rsne_override") == 0) {
|
||||||
if (hexstr2bin(pos, wpabuf_put(tmp, len), len)) {
|
if (!get_hexstream(pos, &bss->rsne_override,
|
||||||
wpabuf_free(tmp);
|
"rsne_override", line))
|
||||||
wpa_printf(MSG_ERROR,
|
return 1;
|
||||||
"Line %d: Invalid own_ie_override '%s'",
|
} else if (os_strcmp(buf, "rsnoe_override") == 0) {
|
||||||
line, pos);
|
if (!get_hexstream(pos, &bss->rsnoe_override,
|
||||||
|
"rsnoe_override", line))
|
||||||
|
return 1;
|
||||||
|
} else if (os_strcmp(buf, "rsno2e_override") == 0) {
|
||||||
|
if (!get_hexstream(pos, &bss->rsno2e_override,
|
||||||
|
"rsno2e_override", line))
|
||||||
|
return 1;
|
||||||
|
} else if (os_strcmp(buf, "rsnxe_override") == 0) {
|
||||||
|
if (!get_hexstream(pos, &bss->rsnxe_override,
|
||||||
|
"rsnxe_override", line))
|
||||||
|
return 1;
|
||||||
|
} else if (os_strcmp(buf, "rsnxoe_override") == 0) {
|
||||||
|
if (!get_hexstream(pos, &bss->rsnxoe_override,
|
||||||
|
"rsnxoe_override", line))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
|
|
||||||
wpabuf_free(bss->own_ie_override);
|
|
||||||
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) {
|
} else if (os_strcmp(buf, "sae_commit_status") == 0) {
|
||||||
|
@ -4540,6 +4613,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
||||||
return 1;
|
return 1;
|
||||||
} else if (os_strcmp(buf, "eapol_m3_no_encrypt") == 0) {
|
} else if (os_strcmp(buf, "eapol_m3_no_encrypt") == 0) {
|
||||||
bss->eapol_m3_no_encrypt = atoi(pos);
|
bss->eapol_m3_no_encrypt = atoi(pos);
|
||||||
|
} else if (os_strcmp(buf, "eapol_key_reserved_random") == 0) {
|
||||||
|
bss->eapol_key_reserved_random = atoi(pos);
|
||||||
} else if (os_strcmp(buf, "test_assoc_comeback_type") == 0) {
|
} else if (os_strcmp(buf, "test_assoc_comeback_type") == 0) {
|
||||||
bss->test_assoc_comeback_type = atoi(pos);
|
bss->test_assoc_comeback_type = atoi(pos);
|
||||||
} else if (os_strcmp(buf, "presp_elements") == 0) {
|
} else if (os_strcmp(buf, "presp_elements") == 0) {
|
||||||
|
|
|
@ -2454,6 +2454,31 @@ static int hostapd_ctrl_register_frame(struct hostapd_data *hapd,
|
||||||
|
|
||||||
|
|
||||||
#ifdef NEED_AP_MLME
|
#ifdef NEED_AP_MLME
|
||||||
|
|
||||||
|
static bool
|
||||||
|
hostapd_ctrl_is_freq_in_cmode(struct hostapd_hw_modes *mode,
|
||||||
|
struct hostapd_multi_hw_info *current_hw_info,
|
||||||
|
int freq)
|
||||||
|
{
|
||||||
|
struct hostapd_channel_data *chan;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < mode->num_channels; i++) {
|
||||||
|
chan = &mode->channels[i];
|
||||||
|
|
||||||
|
if (chan->flag & HOSTAPD_CHAN_DISABLED)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!chan_in_current_hw_info(current_hw_info, chan))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (chan->freq == freq)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params,
|
static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params,
|
||||||
u16 punct_bitmap)
|
u16 punct_bitmap)
|
||||||
{
|
{
|
||||||
|
@ -2668,6 +2693,15 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
|
||||||
settings.link_id = iface->bss[0]->mld_link_id;
|
settings.link_id = iface->bss[0]->mld_link_id;
|
||||||
#endif /* CONFIG_IEEE80211BE */
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
|
if (iface->num_hw_features > 1 &&
|
||||||
|
!hostapd_ctrl_is_freq_in_cmode(iface->current_mode,
|
||||||
|
iface->current_hw_info,
|
||||||
|
settings.freq_params.freq)) {
|
||||||
|
wpa_printf(MSG_INFO,
|
||||||
|
"chanswitch: Invalid frequency settings provided for multi band phy");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
ret = hostapd_ctrl_check_freq_params(&settings.freq_params,
|
ret = hostapd_ctrl_check_freq_params(&settings.freq_params,
|
||||||
settings.punct_bitmap);
|
settings.punct_bitmap);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -2735,6 +2769,12 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (iface->cac_started) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"CAC is in progress - switching channel without CSA");
|
||||||
|
return hostapd_force_channel_switch(iface, settings);
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < iface->num_bss; i++) {
|
for (i = 0; i < iface->num_bss; i++) {
|
||||||
|
|
||||||
/* Save CHAN_SWITCH VHT, HE, and EHT config */
|
/* Save CHAN_SWITCH VHT, HE, and EHT config */
|
||||||
|
@ -3705,6 +3745,7 @@ static int hostapd_ctrl_nan_publish(struct hostapd_data *hapd, char *cmd,
|
||||||
struct wpabuf *ssi = NULL;
|
struct wpabuf *ssi = NULL;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
enum nan_service_protocol_type srv_proto_type = 0;
|
enum nan_service_protocol_type srv_proto_type = 0;
|
||||||
|
bool p2p = false;
|
||||||
|
|
||||||
os_memset(¶ms, 0, sizeof(params));
|
os_memset(¶ms, 0, sizeof(params));
|
||||||
/* USD shall use both solicited and unsolicited transmissions */
|
/* USD shall use both solicited and unsolicited transmissions */
|
||||||
|
@ -3738,6 +3779,11 @@ static int hostapd_ctrl_nan_publish(struct hostapd_data *hapd, char *cmd,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (os_strcmp(token, "p2p=1") == 0) {
|
||||||
|
p2p = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (os_strcmp(token, "solicited=0") == 0) {
|
if (os_strcmp(token, "solicited=0") == 0) {
|
||||||
params.solicited = false;
|
params.solicited = false;
|
||||||
continue;
|
continue;
|
||||||
|
@ -3759,7 +3805,7 @@ static int hostapd_ctrl_nan_publish(struct hostapd_data *hapd, char *cmd,
|
||||||
}
|
}
|
||||||
|
|
||||||
publish_id = hostapd_nan_usd_publish(hapd, service_name, srv_proto_type,
|
publish_id = hostapd_nan_usd_publish(hapd, service_name, srv_proto_type,
|
||||||
ssi, ¶ms);
|
ssi, ¶ms, p2p);
|
||||||
if (publish_id > 0)
|
if (publish_id > 0)
|
||||||
ret = os_snprintf(buf, buflen, "%d", publish_id);
|
ret = os_snprintf(buf, buflen, "%d", publish_id);
|
||||||
fail:
|
fail:
|
||||||
|
@ -3842,6 +3888,7 @@ static int hostapd_ctrl_nan_subscribe(struct hostapd_data *hapd, char *cmd,
|
||||||
struct wpabuf *ssi = NULL;
|
struct wpabuf *ssi = NULL;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
enum nan_service_protocol_type srv_proto_type = 0;
|
enum nan_service_protocol_type srv_proto_type = 0;
|
||||||
|
bool p2p = false;
|
||||||
|
|
||||||
os_memset(¶ms, 0, sizeof(params));
|
os_memset(¶ms, 0, sizeof(params));
|
||||||
|
|
||||||
|
@ -3875,6 +3922,11 @@ static int hostapd_ctrl_nan_subscribe(struct hostapd_data *hapd, char *cmd,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (os_strcmp(token, "p2p=1") == 0) {
|
||||||
|
p2p = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
wpa_printf(MSG_INFO,
|
wpa_printf(MSG_INFO,
|
||||||
"CTRL: Invalid NAN_SUBSCRIBE parameter: %s",
|
"CTRL: Invalid NAN_SUBSCRIBE parameter: %s",
|
||||||
token);
|
token);
|
||||||
|
@ -3883,7 +3935,7 @@ static int hostapd_ctrl_nan_subscribe(struct hostapd_data *hapd, char *cmd,
|
||||||
|
|
||||||
subscribe_id = hostapd_nan_usd_subscribe(hapd, service_name,
|
subscribe_id = hostapd_nan_usd_subscribe(hapd, service_name,
|
||||||
srv_proto_type, ssi,
|
srv_proto_type, ssi,
|
||||||
¶ms);
|
¶ms, p2p);
|
||||||
if (subscribe_id > 0)
|
if (subscribe_id > 0)
|
||||||
ret = os_snprintf(buf, buflen, "%d", subscribe_id);
|
ret = os_snprintf(buf, buflen, "%d", subscribe_id);
|
||||||
fail:
|
fail:
|
||||||
|
@ -4682,23 +4734,360 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
#ifndef CONFIG_CTRL_IFACE_UDP
|
||||||
|
|
||||||
|
static int hostapd_mld_ctrl_iface_receive_process(struct hostapd_mld *mld,
|
||||||
|
char *buf, char *reply,
|
||||||
|
size_t reply_size,
|
||||||
|
struct sockaddr_storage *from,
|
||||||
|
socklen_t fromlen)
|
||||||
|
{
|
||||||
|
struct hostapd_data *link_hapd, *link_itr;
|
||||||
|
int reply_len = -1, link_id = -1;
|
||||||
|
char *cmd;
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
os_memcpy(reply, "OK\n", 3);
|
||||||
|
reply_len = 3;
|
||||||
|
|
||||||
|
cmd = buf;
|
||||||
|
|
||||||
|
/* Check whether the link ID is provided in the command */
|
||||||
|
if (os_strncmp(cmd, "LINKID ", 7) == 0) {
|
||||||
|
cmd += 7;
|
||||||
|
link_id = atoi(cmd);
|
||||||
|
if (link_id < 0 || link_id >= 15) {
|
||||||
|
os_memcpy(reply, "INVALID LINK ID\n", 16);
|
||||||
|
reply_len = 16;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = os_strchr(cmd, ' ');
|
||||||
|
if (!cmd)
|
||||||
|
goto out;
|
||||||
|
cmd++;
|
||||||
|
}
|
||||||
|
if (link_id >= 0) {
|
||||||
|
link_hapd = mld->fbss;
|
||||||
|
if (!link_hapd) {
|
||||||
|
os_memcpy(reply, "NO LINKS ACTIVE\n", 16);
|
||||||
|
reply_len = 16;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
for_each_mld_link(link_itr, link_hapd) {
|
||||||
|
if (link_itr->mld_link_id == link_id) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
link_hapd = link_itr;
|
||||||
|
} else {
|
||||||
|
link_hapd = mld->fbss;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (os_strcmp(cmd, "PING") == 0) {
|
||||||
|
os_memcpy(reply, "PONG\n", 5);
|
||||||
|
reply_len = 5;
|
||||||
|
} else if (os_strcmp(cmd, "ATTACH") == 0) {
|
||||||
|
if (ctrl_iface_attach(&mld->ctrl_dst, from, fromlen, NULL))
|
||||||
|
reply_len = -1;
|
||||||
|
} else if (os_strncmp(cmd, "ATTACH ", 7) == 0) {
|
||||||
|
if (ctrl_iface_attach(&mld->ctrl_dst, from, fromlen, cmd + 7))
|
||||||
|
reply_len = -1;
|
||||||
|
} else if (os_strcmp(cmd, "DETACH") == 0) {
|
||||||
|
if (ctrl_iface_detach(&mld->ctrl_dst, from, fromlen))
|
||||||
|
reply_len = -1;
|
||||||
|
} else {
|
||||||
|
if (link_id == -1)
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"Link ID not provided, using the first link BSS (if available)");
|
||||||
|
|
||||||
|
if (!link_hapd)
|
||||||
|
reply_len = -1;
|
||||||
|
else
|
||||||
|
reply_len =
|
||||||
|
hostapd_ctrl_iface_receive_process(
|
||||||
|
link_hapd, cmd, reply, reply_size,
|
||||||
|
from, fromlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (reply_len < 0) {
|
||||||
|
os_memcpy(reply, "FAIL\n", 5);
|
||||||
|
reply_len = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
return reply_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void hostapd_mld_ctrl_iface_receive(int sock, void *eloop_ctx,
|
||||||
|
void *sock_ctx)
|
||||||
|
{
|
||||||
|
struct hostapd_mld *mld = eloop_ctx;
|
||||||
|
char buf[4096];
|
||||||
|
int res;
|
||||||
|
struct sockaddr_storage from;
|
||||||
|
socklen_t fromlen = sizeof(from);
|
||||||
|
char *reply, *pos = buf;
|
||||||
|
const size_t reply_size = 4096;
|
||||||
|
int reply_len;
|
||||||
|
int level = MSG_DEBUG;
|
||||||
|
|
||||||
|
res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
|
||||||
|
(struct sockaddr *) &from, &fromlen);
|
||||||
|
if (res < 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "recvfrom(mld ctrl_iface): %s",
|
||||||
|
strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
buf[res] = '\0';
|
||||||
|
|
||||||
|
reply = os_malloc(reply_size);
|
||||||
|
if (!reply) {
|
||||||
|
if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
|
||||||
|
fromlen) < 0) {
|
||||||
|
wpa_printf(MSG_DEBUG, "MLD CTRL: sendto failed: %s",
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (os_strcmp(pos, "PING") == 0)
|
||||||
|
level = MSG_EXCESSIVE;
|
||||||
|
|
||||||
|
wpa_hexdump_ascii(level, "RX MLD ctrl_iface", pos, res);
|
||||||
|
|
||||||
|
reply_len = hostapd_mld_ctrl_iface_receive_process(mld, pos,
|
||||||
|
reply, reply_size,
|
||||||
|
&from, fromlen);
|
||||||
|
|
||||||
|
if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
|
||||||
|
fromlen) < 0) {
|
||||||
|
wpa_printf(MSG_DEBUG, "MLD CTRL: sendto failed: %s",
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
os_free(reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char * hostapd_mld_ctrl_iface_path(struct hostapd_mld *mld)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
char *buf;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!mld->ctrl_interface)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
len = os_strlen(mld->ctrl_interface) + os_strlen(mld->name) + 2;
|
||||||
|
|
||||||
|
buf = os_malloc(len);
|
||||||
|
if (!buf)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ret = os_snprintf(buf, len, "%s/%s", mld->ctrl_interface, mld->name);
|
||||||
|
if (os_snprintf_error(len, ret)) {
|
||||||
|
os_free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !CONFIG_CTRL_IFACE_UDP */
|
||||||
|
|
||||||
|
|
||||||
|
int hostapd_mld_ctrl_iface_init(struct hostapd_mld *mld)
|
||||||
|
{
|
||||||
|
#ifndef CONFIG_CTRL_IFACE_UDP
|
||||||
|
struct sockaddr_un addr;
|
||||||
|
int s = -1;
|
||||||
|
char *fname = NULL;
|
||||||
|
|
||||||
|
if (!mld)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (mld->ctrl_sock > -1) {
|
||||||
|
wpa_printf(MSG_DEBUG, "MLD %s ctrl_iface already exists!",
|
||||||
|
mld->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl_list_init(&mld->ctrl_dst);
|
||||||
|
|
||||||
|
if (!mld->ctrl_interface)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (mkdir(mld->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
|
||||||
|
if (errno == EEXIST) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"Using existing control interface directory.");
|
||||||
|
} else {
|
||||||
|
wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
|
||||||
|
strerror(errno));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (os_strlen(mld->ctrl_interface) + 1 + os_strlen(mld->name) >=
|
||||||
|
sizeof(addr.sun_path))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
s = socket(PF_UNIX, SOCK_DGRAM, 0);
|
||||||
|
if (s < 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
os_memset(&addr, 0, sizeof(addr));
|
||||||
|
#ifdef __FreeBSD__
|
||||||
|
addr.sun_len = sizeof(addr);
|
||||||
|
#endif /* __FreeBSD__ */
|
||||||
|
addr.sun_family = AF_UNIX;
|
||||||
|
|
||||||
|
fname = hostapd_mld_ctrl_iface_path(mld);
|
||||||
|
if (!fname)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "Setting up MLD %s ctrl_iface", mld->name);
|
||||||
|
|
||||||
|
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
||||||
|
wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
|
||||||
|
strerror(errno));
|
||||||
|
if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
||||||
|
wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not allow connections - assuming it was left over from forced program termination");
|
||||||
|
if (unlink(fname) < 0) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"Could not unlink existing ctrl_iface socket '%s': %s",
|
||||||
|
fname, strerror(errno));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
|
||||||
|
0) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"hostapd-ctrl-iface: bind(PF_UNIX): %s",
|
||||||
|
strerror(errno));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"Successfully replaced leftover ctrl_iface socket '%s'",
|
||||||
|
fname);
|
||||||
|
} else {
|
||||||
|
wpa_printf(MSG_INFO,
|
||||||
|
"ctrl_iface exists and seems to be in use - cannot override it");
|
||||||
|
wpa_printf(MSG_INFO,
|
||||||
|
"Delete '%s' manually if it is not used anymore", fname);
|
||||||
|
os_free(fname);
|
||||||
|
fname = NULL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
|
||||||
|
strerror(errno));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
os_free(fname);
|
||||||
|
|
||||||
|
mld->ctrl_sock = s;
|
||||||
|
|
||||||
|
if (eloop_register_read_sock(s, hostapd_mld_ctrl_iface_receive, mld,
|
||||||
|
NULL) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (s >= 0)
|
||||||
|
close(s);
|
||||||
|
if (fname) {
|
||||||
|
unlink(fname);
|
||||||
|
os_free(fname);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
#endif /* !CONFIG_CTRL_IFACE_UDP */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void hostapd_mld_ctrl_iface_deinit(struct hostapd_mld *mld)
|
||||||
|
{
|
||||||
|
#ifndef CONFIG_CTRL_IFACE_UDP
|
||||||
|
struct wpa_ctrl_dst *dst, *prev;
|
||||||
|
|
||||||
|
if (mld->ctrl_sock > -1) {
|
||||||
|
char *fname;
|
||||||
|
|
||||||
|
eloop_unregister_read_sock(mld->ctrl_sock);
|
||||||
|
close(mld->ctrl_sock);
|
||||||
|
mld->ctrl_sock = -1;
|
||||||
|
|
||||||
|
fname = hostapd_mld_ctrl_iface_path(mld);
|
||||||
|
if (fname) {
|
||||||
|
unlink(fname);
|
||||||
|
os_free(fname);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mld->ctrl_interface &&
|
||||||
|
rmdir(mld->ctrl_interface) < 0) {
|
||||||
|
if (errno == ENOTEMPTY) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"MLD control interface directory not empty - leaving it behind");
|
||||||
|
} else {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"rmdir[ctrl_interface=%s]: %s",
|
||||||
|
mld->ctrl_interface,
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dl_list_for_each_safe(dst, prev, &mld->ctrl_dst, struct wpa_ctrl_dst,
|
||||||
|
list)
|
||||||
|
os_free(dst);
|
||||||
|
#endif /* !CONFIG_CTRL_IFACE_UDP */
|
||||||
|
|
||||||
|
os_free(mld->ctrl_interface);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
|
|
||||||
#ifndef CONFIG_CTRL_IFACE_UDP
|
#ifndef CONFIG_CTRL_IFACE_UDP
|
||||||
static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
|
static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
|
||||||
{
|
{
|
||||||
char *buf;
|
char *buf;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
const char *ctrl_sock_iface;
|
||||||
|
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
ctrl_sock_iface = hapd->ctrl_sock_iface;
|
||||||
|
#else /* CONFIG_IEEE80211BE */
|
||||||
|
ctrl_sock_iface = hapd->conf->iface;
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
if (hapd->conf->ctrl_interface == NULL)
|
if (hapd->conf->ctrl_interface == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
len = os_strlen(hapd->conf->ctrl_interface) +
|
len = os_strlen(hapd->conf->ctrl_interface) +
|
||||||
os_strlen(hapd->conf->iface) + 2;
|
os_strlen(ctrl_sock_iface) + 2;
|
||||||
|
|
||||||
buf = os_malloc(len);
|
buf = os_malloc(len);
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
os_snprintf(buf, len, "%s/%s",
|
os_snprintf(buf, len, "%s/%s",
|
||||||
hapd->conf->ctrl_interface, hapd->conf->iface);
|
hapd->conf->ctrl_interface, ctrl_sock_iface);
|
||||||
buf[len - 1] = '\0';
|
buf[len - 1] = '\0';
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
@ -4814,6 +5203,7 @@ fail:
|
||||||
struct sockaddr_un addr;
|
struct sockaddr_un addr;
|
||||||
int s = -1;
|
int s = -1;
|
||||||
char *fname = NULL;
|
char *fname = NULL;
|
||||||
|
size_t iflen;
|
||||||
|
|
||||||
if (hapd->ctrl_sock > -1) {
|
if (hapd->ctrl_sock > -1) {
|
||||||
wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
|
wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
|
||||||
|
@ -4868,8 +5258,13 @@ fail:
|
||||||
}
|
}
|
||||||
#endif /* ANDROID */
|
#endif /* ANDROID */
|
||||||
|
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
iflen = os_strlen(hapd->ctrl_sock_iface);
|
||||||
|
#else /* CONFIG_IEEE80211BE */
|
||||||
|
iflen = os_strlen(hapd->conf->iface);
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
if (os_strlen(hapd->conf->ctrl_interface) + 1 +
|
if (os_strlen(hapd->conf->ctrl_interface) + 1 +
|
||||||
os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
|
iflen >= sizeof(addr.sun_path))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
s = socket(PF_UNIX, SOCK_DGRAM, 0);
|
s = socket(PF_UNIX, SOCK_DGRAM, 0);
|
||||||
|
|
|
@ -14,6 +14,8 @@ int hostapd_ctrl_iface_init(struct hostapd_data *hapd);
|
||||||
void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd);
|
void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd);
|
||||||
int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface);
|
int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface);
|
||||||
void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interface);
|
void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interface);
|
||||||
|
int hostapd_mld_ctrl_iface_init(struct hostapd_mld *mld);
|
||||||
|
void hostapd_mld_ctrl_iface_deinit(struct hostapd_mld *mld);
|
||||||
#else /* CONFIG_NO_CTRL_IFACE */
|
#else /* CONFIG_NO_CTRL_IFACE */
|
||||||
static inline int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
|
static inline int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2298,6 +2298,67 @@ own_ip_addr=127.0.0.1
|
||||||
#
|
#
|
||||||
#ssid_protection=0
|
#ssid_protection=0
|
||||||
|
|
||||||
|
# RSNE/RSNXE override
|
||||||
|
#
|
||||||
|
# These parameters can be used to configure RSN parameters for STAs that support
|
||||||
|
# the override elements. The RSN parameters for STAs that do not support these
|
||||||
|
# mechanisms are configured in the referenced configuration parameters. The AP
|
||||||
|
# allows STAs to use either of the configured sets for negotiating RSN
|
||||||
|
# parameters.
|
||||||
|
#
|
||||||
|
# The main purpose of this mechanism is to make the AP look like it is using an
|
||||||
|
# older security mechanism (e.g., WPA2-Personal) to older STAs while allowing
|
||||||
|
# new stations use newer security mechanisms (e.g., WPA3-Personal) based on the
|
||||||
|
# override values. This might be needed to work around issues with deployed
|
||||||
|
# STAs that do not implement RSNE extensibility correctly and may fail to
|
||||||
|
# connect when the AP is using a transition mode like WPA3-Personal transition
|
||||||
|
# mode.
|
||||||
|
#
|
||||||
|
# Key management; see wpa_key_mgmt for RSNE configuration
|
||||||
|
#rsn_override_key_mgmt=<accepted key management algorithms>
|
||||||
|
#
|
||||||
|
# Pairwise cipher suites; see rsn_pairwise for RSNE configuration
|
||||||
|
#rsn_override_pairwise=<accepted cipher suites)
|
||||||
|
#
|
||||||
|
# Management frame protection (MFP/PMF); see ieee80211w for RSNE configuration
|
||||||
|
# 0 = disabled
|
||||||
|
# 1 = optional
|
||||||
|
# 2 = required
|
||||||
|
#rsn_override_mfp=<0/1/2>
|
||||||
|
#
|
||||||
|
# Second set of similar parameters. These are required to be used for
|
||||||
|
# Wi-Fi 7 (EHT/MLO) associations with RSN overriding and can optionally be used
|
||||||
|
# in cases that do not use Wi-Fi 7.
|
||||||
|
#rsn_override_key_mgmt_2
|
||||||
|
#rsn_override_pairwise_2
|
||||||
|
#rsn_override_mfp_2
|
||||||
|
#
|
||||||
|
# The RSNXE is normally included if any of the extended RSN capabilities is
|
||||||
|
# enabled/supported. When using RSN overriding, a separate RSNXOE is included
|
||||||
|
# and it may be more interoperable to omit the RSNXE completely. This
|
||||||
|
# configuration parameter can be used to do that.
|
||||||
|
# 0 = Include the RSNXE if any extended RSN capability is enabled/supported
|
||||||
|
# (default).
|
||||||
|
# 1 = Do not include the RSNXE.
|
||||||
|
#rsn_override_omit_rsnxe=0
|
||||||
|
#
|
||||||
|
# Example configuration for WPA2-Personal/PMF-optional in RSNE and
|
||||||
|
# WPA3-Personal/PMF-required/MLO in override elements
|
||||||
|
#wpa_key_mgmt=WPA-PSK
|
||||||
|
#rsn_pairwise=CCMP
|
||||||
|
#ieee80211w=1
|
||||||
|
#rsn_override_key_mgmt=SAE
|
||||||
|
#rsn_override_pairwise=GCMP-256
|
||||||
|
#rsn_override_mfp=2
|
||||||
|
#rsn_override_key_mgmt_2=SAE-EXT-KEY
|
||||||
|
#rsn_override_pairwise_2=GCMP-256
|
||||||
|
#rsn_override_mfp_2=2
|
||||||
|
#beacon_prot=1
|
||||||
|
#sae_groups=19 20
|
||||||
|
#sae_require_mfp=1
|
||||||
|
#sae_pwe=2
|
||||||
|
|
||||||
|
|
||||||
##### IEEE 802.11r configuration ##############################################
|
##### IEEE 802.11r configuration ##############################################
|
||||||
|
|
||||||
# Mobility Domain identifier (dot11FTMobilityDomainID, MDID)
|
# Mobility Domain identifier (dot11FTMobilityDomainID, MDID)
|
||||||
|
|
|
@ -54,7 +54,11 @@ static void usage(void)
|
||||||
fprintf(stderr, "%s\n", hostapd_cli_version);
|
fprintf(stderr, "%s\n", hostapd_cli_version);
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"\n"
|
"\n"
|
||||||
"usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvBr] "
|
"usage: hostapd_cli [-p<path>] [-i<ifname>] "
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
"[-l<link_id>] "
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
"[-hvBr] "
|
||||||
"[-a<path>] \\\n"
|
"[-a<path>] \\\n"
|
||||||
" [-P<pid file>] [-G<ping interval>] [command..]\n"
|
" [-P<pid file>] [-G<ping interval>] [command..]\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
@ -74,7 +78,11 @@ static void usage(void)
|
||||||
" -B run a daemon in the background\n"
|
" -B run a daemon in the background\n"
|
||||||
" -i<ifname> Interface to listen on (default: first "
|
" -i<ifname> Interface to listen on (default: first "
|
||||||
"interface found in the\n"
|
"interface found in the\n"
|
||||||
" socket path)\n\n");
|
" socket path)\n"
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
" -l<link_id> Link ID of the interface in case of Multi-Link Operation\n"
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
"\n");
|
||||||
print_help(stderr, NULL);
|
print_help(stderr, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2212,12 +2220,15 @@ int main(int argc, char *argv[])
|
||||||
int c;
|
int c;
|
||||||
int daemonize = 0;
|
int daemonize = 0;
|
||||||
int reconnect = 0;
|
int reconnect = 0;
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
int link_id = -1;
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
if (os_program_init())
|
if (os_program_init())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
c = getopt(argc, argv, "a:BhG:i:p:P:rs:v");
|
c = getopt(argc, argv, "a:BhG:i:l:p:P:rs:v");
|
||||||
if (c < 0)
|
if (c < 0)
|
||||||
break;
|
break;
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
@ -2252,6 +2263,11 @@ int main(int argc, char *argv[])
|
||||||
case 's':
|
case 's':
|
||||||
client_socket_dir = optarg;
|
client_socket_dir = optarg;
|
||||||
break;
|
break;
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
case 'l':
|
||||||
|
link_id = atoi(optarg);
|
||||||
|
break;
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -2285,6 +2301,24 @@ int main(int argc, char *argv[])
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
if (link_id >= 0 && ctrl_ifname) {
|
||||||
|
int ret;
|
||||||
|
char buf[300];
|
||||||
|
|
||||||
|
ret = os_snprintf(buf, sizeof(buf), "%s_%s%d",
|
||||||
|
ctrl_ifname, WPA_CTRL_IFACE_LINK_NAME,
|
||||||
|
link_id);
|
||||||
|
if (os_snprintf_error(sizeof(buf), ret))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
os_free(ctrl_ifname);
|
||||||
|
ctrl_ifname = os_strdup(buf);
|
||||||
|
link_id = -1;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
hostapd_cli_reconnect(ctrl_ifname);
|
hostapd_cli_reconnect(ctrl_ifname);
|
||||||
if (ctrl_conn) {
|
if (ctrl_conn) {
|
||||||
if (warning_displayed)
|
if (warning_displayed)
|
||||||
|
|
|
@ -191,7 +191,6 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
|
||||||
os_memcpy(hapd->own_addr, b, ETH_ALEN);
|
os_memcpy(hapd->own_addr, b, ETH_ALEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
hostapd_mld_add_link(hapd);
|
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"Setup of non first link (%d) BSS of MLD %s",
|
"Setup of non first link (%d) BSS of MLD %s",
|
||||||
hapd->mld_link_id, hapd->conf->iface);
|
hapd->mld_link_id, hapd->conf->iface);
|
||||||
|
@ -278,7 +277,6 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
|
||||||
else
|
else
|
||||||
os_memcpy(hapd->own_addr, b, ETH_ALEN);
|
os_memcpy(hapd->own_addr, b, ETH_ALEN);
|
||||||
|
|
||||||
hostapd_mld_add_link(hapd);
|
|
||||||
wpa_printf(MSG_DEBUG, "Setup of first link (%d) BSS of MLD %s",
|
wpa_printf(MSG_DEBUG, "Setup of first link (%d) BSS of MLD %s",
|
||||||
hapd->mld_link_id, hapd->conf->iface);
|
hapd->mld_link_id, hapd->conf->iface);
|
||||||
}
|
}
|
||||||
|
@ -338,8 +336,14 @@ setup_mld:
|
||||||
hapd->mld_link_id, MAC2STR(hapd->mld->mld_addr),
|
hapd->mld_link_id, MAC2STR(hapd->mld->mld_addr),
|
||||||
MAC2STR(hapd->own_addr));
|
MAC2STR(hapd->own_addr));
|
||||||
|
|
||||||
hostapd_drv_link_add(hapd, hapd->mld_link_id,
|
if (hostapd_drv_link_add(hapd, hapd->mld_link_id,
|
||||||
hapd->own_addr);
|
hapd->own_addr)) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"MLD: Failed to add link %d in MLD %s",
|
||||||
|
hapd->mld_link_id, hapd->conf->iface);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
hostapd_mld_add_link(hapd);
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211BE */
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
|
@ -748,6 +752,7 @@ static void hostapd_global_cleanup_mld(struct hapd_interfaces *interfaces)
|
||||||
if (!interfaces->mld[i])
|
if (!interfaces->mld[i])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
interfaces->mld_ctrl_iface_deinit(interfaces->mld[i]);
|
||||||
os_free(interfaces->mld[i]);
|
os_free(interfaces->mld[i]);
|
||||||
interfaces->mld[i] = NULL;
|
interfaces->mld[i] = NULL;
|
||||||
}
|
}
|
||||||
|
@ -793,6 +798,10 @@ int main(int argc, char *argv[])
|
||||||
interfaces.global_iface_path = NULL;
|
interfaces.global_iface_path = NULL;
|
||||||
interfaces.global_iface_name = NULL;
|
interfaces.global_iface_name = NULL;
|
||||||
interfaces.global_ctrl_sock = -1;
|
interfaces.global_ctrl_sock = -1;
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
interfaces.mld_ctrl_iface_init = hostapd_mld_ctrl_iface_init;
|
||||||
|
interfaces.mld_ctrl_iface_deinit = hostapd_mld_ctrl_iface_deinit;
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
dl_list_init(&interfaces.global_ctrl_dst);
|
dl_list_init(&interfaces.global_ctrl_dst);
|
||||||
#ifdef CONFIG_ETH_P_OUI
|
#ifdef CONFIG_ETH_P_OUI
|
||||||
dl_list_init(&interfaces.eth_p_oui);
|
dl_list_init(&interfaces.eth_p_oui);
|
||||||
|
|
|
@ -112,14 +112,8 @@ static void set_sta_weights(struct hostapd_data *hapd, unsigned int weight)
|
||||||
{
|
{
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
|
|
||||||
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
for (sta = hapd->sta_list; sta; sta = sta->next)
|
||||||
unsigned int sta_weight = weight;
|
sta_set_airtime_weight(hapd, sta, weight);
|
||||||
|
|
||||||
if (sta->dyn_airtime_weight)
|
|
||||||
sta_weight = (weight * sta->dyn_airtime_weight) / 256;
|
|
||||||
|
|
||||||
sta_set_airtime_weight(hapd, sta, sta_weight);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -250,10 +244,7 @@ int airtime_policy_new_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
||||||
unsigned int weight;
|
unsigned int weight;
|
||||||
|
|
||||||
if (hapd->iconf->airtime_mode == AIRTIME_MODE_STATIC) {
|
if (hapd->iconf->airtime_mode == AIRTIME_MODE_STATIC) {
|
||||||
if (sta->dyn_airtime_weight)
|
weight = get_weight_for_sta(hapd, sta->addr);
|
||||||
weight = sta->dyn_airtime_weight;
|
|
||||||
else
|
|
||||||
weight = get_weight_for_sta(hapd, sta->addr);
|
|
||||||
if (weight)
|
if (weight)
|
||||||
return sta_set_airtime_weight(hapd, sta, weight);
|
return sta_set_airtime_weight(hapd, sta, weight);
|
||||||
}
|
}
|
||||||
|
|
|
@ -491,20 +491,33 @@ int hostapd_setup_sae_pt(struct hostapd_bss_config *conf)
|
||||||
#ifdef CONFIG_SAE
|
#ifdef CONFIG_SAE
|
||||||
struct hostapd_ssid *ssid = &conf->ssid;
|
struct hostapd_ssid *ssid = &conf->ssid;
|
||||||
struct sae_password_entry *pw;
|
struct sae_password_entry *pw;
|
||||||
|
int *groups = conf->sae_groups;
|
||||||
|
int default_groups[] = { 19, 0, 0 };
|
||||||
|
|
||||||
if ((conf->sae_pwe == SAE_PWE_HUNT_AND_PECK &&
|
if ((conf->sae_pwe == SAE_PWE_HUNT_AND_PECK &&
|
||||||
!hostapd_sae_pw_id_in_use(conf) &&
|
!hostapd_sae_pw_id_in_use(conf) &&
|
||||||
!wpa_key_mgmt_sae_ext_key(conf->wpa_key_mgmt) &&
|
!wpa_key_mgmt_sae_ext_key(conf->wpa_key_mgmt |
|
||||||
|
conf->rsn_override_key_mgmt |
|
||||||
|
conf->rsn_override_key_mgmt_2) &&
|
||||||
!hostapd_sae_pk_in_use(conf)) ||
|
!hostapd_sae_pk_in_use(conf)) ||
|
||||||
conf->sae_pwe == SAE_PWE_FORCE_HUNT_AND_PECK ||
|
conf->sae_pwe == SAE_PWE_FORCE_HUNT_AND_PECK ||
|
||||||
!wpa_key_mgmt_sae(conf->wpa_key_mgmt))
|
!wpa_key_mgmt_sae(conf->wpa_key_mgmt |
|
||||||
|
conf->rsn_override_key_mgmt |
|
||||||
|
conf->rsn_override_key_mgmt_2))
|
||||||
return 0; /* PT not needed */
|
return 0; /* PT not needed */
|
||||||
|
|
||||||
|
if (!groups) {
|
||||||
|
groups = default_groups;
|
||||||
|
if (wpa_key_mgmt_sae_ext_key(conf->wpa_key_mgmt |
|
||||||
|
conf->rsn_override_key_mgmt |
|
||||||
|
conf->rsn_override_key_mgmt_2))
|
||||||
|
default_groups[1] = 20;
|
||||||
|
}
|
||||||
|
|
||||||
sae_deinit_pt(ssid->pt);
|
sae_deinit_pt(ssid->pt);
|
||||||
ssid->pt = NULL;
|
ssid->pt = NULL;
|
||||||
if (ssid->wpa_passphrase) {
|
if (ssid->wpa_passphrase) {
|
||||||
ssid->pt = sae_derive_pt(conf->sae_groups, ssid->ssid,
|
ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
|
||||||
ssid->ssid_len,
|
|
||||||
(const u8 *) ssid->wpa_passphrase,
|
(const u8 *) ssid->wpa_passphrase,
|
||||||
os_strlen(ssid->wpa_passphrase),
|
os_strlen(ssid->wpa_passphrase),
|
||||||
NULL);
|
NULL);
|
||||||
|
@ -514,8 +527,7 @@ int hostapd_setup_sae_pt(struct hostapd_bss_config *conf)
|
||||||
|
|
||||||
for (pw = conf->sae_passwords; pw; pw = pw->next) {
|
for (pw = conf->sae_passwords; pw; pw = pw->next) {
|
||||||
sae_deinit_pt(pw->pt);
|
sae_deinit_pt(pw->pt);
|
||||||
pw->pt = sae_derive_pt(conf->sae_groups, ssid->ssid,
|
pw->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
|
||||||
ssid->ssid_len,
|
|
||||||
(const u8 *) pw->password,
|
(const u8 *) pw->password,
|
||||||
os_strlen(pw->password),
|
os_strlen(pw->password),
|
||||||
pw->identifier);
|
pw->identifier);
|
||||||
|
@ -960,6 +972,11 @@ 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->rsne_override);
|
||||||
|
wpabuf_free(conf->rsnoe_override);
|
||||||
|
wpabuf_free(conf->rsno2e_override);
|
||||||
|
wpabuf_free(conf->rsnxe_override);
|
||||||
|
wpabuf_free(conf->rsnxoe_override);
|
||||||
wpabuf_free(conf->sae_commit_override);
|
wpabuf_free(conf->sae_commit_override);
|
||||||
wpabuf_free(conf->rsne_override_eapol);
|
wpabuf_free(conf->rsne_override_eapol);
|
||||||
wpabuf_free(conf->rsnxe_override_eapol);
|
wpabuf_free(conf->rsnxe_override_eapol);
|
||||||
|
|
|
@ -358,7 +358,11 @@ struct hostapd_bss_config {
|
||||||
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 extended_key_id;
|
||||||
int wpa_key_mgmt;
|
int wpa_key_mgmt;
|
||||||
|
int rsn_override_key_mgmt;
|
||||||
|
int rsn_override_key_mgmt_2;
|
||||||
enum mfp_options ieee80211w;
|
enum mfp_options ieee80211w;
|
||||||
|
enum mfp_options rsn_override_mfp;
|
||||||
|
enum mfp_options rsn_override_mfp_2;
|
||||||
int group_mgmt_cipher;
|
int group_mgmt_cipher;
|
||||||
int beacon_prot;
|
int beacon_prot;
|
||||||
/* dot11AssociationSAQueryMaximumTimeout (in TUs) */
|
/* dot11AssociationSAQueryMaximumTimeout (in TUs) */
|
||||||
|
@ -387,9 +391,13 @@ struct hostapd_bss_config {
|
||||||
u32 wpa_pairwise_update_count;
|
u32 wpa_pairwise_update_count;
|
||||||
int wpa_disable_eapol_key_retries;
|
int wpa_disable_eapol_key_retries;
|
||||||
int rsn_pairwise;
|
int rsn_pairwise;
|
||||||
|
int rsn_override_pairwise;
|
||||||
|
int rsn_override_pairwise_2;
|
||||||
int rsn_preauth;
|
int rsn_preauth;
|
||||||
char *rsn_preauth_interfaces;
|
char *rsn_preauth_interfaces;
|
||||||
|
|
||||||
|
int rsn_override_omit_rsnxe;
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211R_AP
|
#ifdef CONFIG_IEEE80211R_AP
|
||||||
/* IEEE 802.11r - Fast BSS Transition */
|
/* IEEE 802.11r - Fast BSS Transition */
|
||||||
u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN];
|
u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN];
|
||||||
|
@ -688,6 +696,11 @@ struct hostapd_bss_config {
|
||||||
u8 bss_load_test[5];
|
u8 bss_load_test[5];
|
||||||
u8 bss_load_test_set;
|
u8 bss_load_test_set;
|
||||||
struct wpabuf *own_ie_override;
|
struct wpabuf *own_ie_override;
|
||||||
|
struct wpabuf *rsne_override;
|
||||||
|
struct wpabuf *rsnoe_override;
|
||||||
|
struct wpabuf *rsno2e_override;
|
||||||
|
struct wpabuf *rsnxe_override;
|
||||||
|
struct wpabuf *rsnxoe_override;
|
||||||
int sae_reflection_attack;
|
int sae_reflection_attack;
|
||||||
int sae_commit_status;
|
int sae_commit_status;
|
||||||
int sae_pk_omit;
|
int sae_pk_omit;
|
||||||
|
@ -712,6 +725,7 @@ struct hostapd_bss_config {
|
||||||
struct wpabuf *eapol_m1_elements;
|
struct wpabuf *eapol_m1_elements;
|
||||||
struct wpabuf *eapol_m3_elements;
|
struct wpabuf *eapol_m3_elements;
|
||||||
bool eapol_m3_no_encrypt;
|
bool eapol_m3_no_encrypt;
|
||||||
|
bool eapol_key_reserved_random;
|
||||||
int test_assoc_comeback_type;
|
int test_assoc_comeback_type;
|
||||||
struct wpabuf *presp_elements;
|
struct wpabuf *presp_elements;
|
||||||
|
|
||||||
|
|
|
@ -1250,3 +1250,14 @@ int hostapd_drv_set_secure_ranging_ctx(struct hostapd_data *hapd,
|
||||||
return hapd->driver->set_secure_ranging_ctx(hapd->drv_priv, ¶ms);
|
return hapd->driver->set_secure_ranging_ctx(hapd->drv_priv, ¶ms);
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_PASN */
|
#endif /* CONFIG_PASN */
|
||||||
|
|
||||||
|
|
||||||
|
struct hostapd_multi_hw_info *
|
||||||
|
hostapd_get_multi_hw_info(struct hostapd_data *hapd,
|
||||||
|
unsigned int *num_multi_hws)
|
||||||
|
{
|
||||||
|
if (!hapd->driver || !hapd->driver->get_multi_hw_info)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return hapd->driver->get_multi_hw_info(hapd->drv_priv, num_multi_hws);
|
||||||
|
}
|
||||||
|
|
|
@ -478,4 +478,8 @@ static inline int hostapd_drv_link_sta_remove(struct hostapd_data *hapd,
|
||||||
|
|
||||||
#endif /* CONFIG_IEEE80211BE */
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
|
struct hostapd_multi_hw_info *
|
||||||
|
hostapd_get_multi_hw_info(struct hostapd_data *hapd,
|
||||||
|
unsigned int *num_multi_hws);
|
||||||
|
|
||||||
#endif /* AP_DRV_OPS */
|
#endif /* AP_DRV_OPS */
|
||||||
|
|
722
src/ap/beacon.c
722
src/ap/beacon.c
|
@ -403,6 +403,81 @@ static u8 * hostapd_get_osen_ie(struct hostapd_data *hapd, u8 *pos, size_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static u8 * hostapd_get_rsne_override(struct hostapd_data *hapd, u8 *pos,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
const u8 *ie;
|
||||||
|
|
||||||
|
ie = hostapd_vendor_wpa_ie(hapd, RSNE_OVERRIDE_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_rsne_override_2(struct hostapd_data *hapd, u8 *pos,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
const u8 *ie;
|
||||||
|
|
||||||
|
ie = hostapd_vendor_wpa_ie(hapd, RSNE_OVERRIDE_2_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_rsnxe_override(struct hostapd_data *hapd, u8 *pos,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
const u8 *ie;
|
||||||
|
|
||||||
|
ie = hostapd_vendor_wpa_ie(hapd, RSNXE_OVERRIDE_IE_VENDOR_TYPE);
|
||||||
|
if (!ie || 2U + ie[1] > len)
|
||||||
|
return pos;
|
||||||
|
|
||||||
|
os_memcpy(pos, ie, 2 + ie[1]);
|
||||||
|
return pos + 2 + ie[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static size_t hostapd_get_rsne_override_len(struct hostapd_data *hapd)
|
||||||
|
{
|
||||||
|
const u8 *ie;
|
||||||
|
|
||||||
|
ie = hostapd_vendor_wpa_ie(hapd, RSNE_OVERRIDE_IE_VENDOR_TYPE);
|
||||||
|
if (!ie)
|
||||||
|
return 0;
|
||||||
|
return 2 + ie[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static size_t hostapd_get_rsne_override_2_len(struct hostapd_data *hapd)
|
||||||
|
{
|
||||||
|
const u8 *ie;
|
||||||
|
|
||||||
|
ie = hostapd_vendor_wpa_ie(hapd, RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
|
||||||
|
if (!ie)
|
||||||
|
return 0;
|
||||||
|
return 2 + ie[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static size_t hostapd_get_rsnxe_override_len(struct hostapd_data *hapd)
|
||||||
|
{
|
||||||
|
const u8 *ie;
|
||||||
|
|
||||||
|
ie = hostapd_vendor_wpa_ie(hapd, RSNXE_OVERRIDE_IE_VENDOR_TYPE);
|
||||||
|
if (!ie)
|
||||||
|
return 0;
|
||||||
|
return 2 + ie[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static u8 * hostapd_eid_csa(struct hostapd_data *hapd, u8 *eid)
|
static u8 * hostapd_eid_csa(struct hostapd_data *hapd, u8 *eid)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
@ -439,6 +514,35 @@ static u8 * hostapd_eid_ecsa(struct hostapd_data *hapd, u8 *eid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static u8 * hostapd_eid_max_cs_time(struct hostapd_data *hapd, u8 *eid)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
u32 switch_time;
|
||||||
|
|
||||||
|
/* Add Max Channel Switch Time element only if this AP is affiliated
|
||||||
|
* with an AP MLD and channel switch is in process. */
|
||||||
|
if (!hapd->conf->mld_ap || !hapd->cs_freq_params.channel)
|
||||||
|
return eid;
|
||||||
|
|
||||||
|
/* Switch time is basically time between CSA count 1 and CSA count
|
||||||
|
* 0 (1 beacon interval) + time for interface restart + time to
|
||||||
|
* send a Beacon frame in the new channel (1 beacon interval).
|
||||||
|
*
|
||||||
|
* TODO: Use dynamic interface restart time. For now, assume 1 sec.
|
||||||
|
*/
|
||||||
|
switch_time = USEC_TO_TU(1000 * 1000) + 2 * hapd->iconf->beacon_int;
|
||||||
|
|
||||||
|
*eid++ = WLAN_EID_EXTENSION;
|
||||||
|
*eid++ = 4;
|
||||||
|
*eid++ = WLAN_EID_EXT_MAX_CHANNEL_SWITCH_TIME;
|
||||||
|
WPA_PUT_LE24(eid, switch_time);
|
||||||
|
eid += 3;
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
|
return eid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static u8 * hostapd_eid_supported_op_classes(struct hostapd_data *hapd, u8 *eid)
|
static u8 * hostapd_eid_supported_op_classes(struct hostapd_data *hapd, u8 *eid)
|
||||||
{
|
{
|
||||||
u8 op_class, channel;
|
u8 op_class, channel;
|
||||||
|
@ -601,7 +705,6 @@ struct probe_resp_params {
|
||||||
bool is_p2p;
|
bool is_p2p;
|
||||||
|
|
||||||
/* Generated IEs will be included inside an ML element */
|
/* Generated IEs will be included inside an ML element */
|
||||||
bool is_ml_sta_info;
|
|
||||||
struct hostapd_data *mld_ap;
|
struct hostapd_data *mld_ap;
|
||||||
struct mld_info *mld_info;
|
struct mld_info *mld_info;
|
||||||
|
|
||||||
|
@ -623,7 +726,7 @@ static void hostapd_free_probe_resp_params(struct probe_resp_params *params)
|
||||||
#ifdef CONFIG_IEEE80211BE
|
#ifdef CONFIG_IEEE80211BE
|
||||||
if (!params)
|
if (!params)
|
||||||
return;
|
return;
|
||||||
ap_sta_free_sta_profile(params->mld_info);
|
|
||||||
os_free(params->mld_info);
|
os_free(params->mld_info);
|
||||||
params->mld_info = NULL;
|
params->mld_info = NULL;
|
||||||
#endif /* CONFIG_IEEE80211BE */
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
@ -662,17 +765,21 @@ static size_t hostapd_probe_resp_elems_len(struct hostapd_data *hapd,
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211BE
|
#ifdef CONFIG_IEEE80211BE
|
||||||
if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) {
|
if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) {
|
||||||
|
struct hostapd_data *ml_elem_ap =
|
||||||
|
params->mld_ap ? params->mld_ap : hapd;
|
||||||
|
|
||||||
buflen += hostapd_eid_eht_capab_len(hapd, IEEE80211_MODE_AP);
|
buflen += hostapd_eid_eht_capab_len(hapd, IEEE80211_MODE_AP);
|
||||||
buflen += 3 + sizeof(struct ieee80211_eht_operation);
|
buflen += 3 + sizeof(struct ieee80211_eht_operation);
|
||||||
if (hapd->iconf->punct_bitmap)
|
if (hapd->iconf->punct_bitmap)
|
||||||
buflen += EHT_OPER_DISABLED_SUBCHAN_BITMAP_SIZE;
|
buflen += EHT_OPER_DISABLED_SUBCHAN_BITMAP_SIZE;
|
||||||
|
|
||||||
if (!params->is_ml_sta_info && hapd->conf->mld_ap) {
|
if (ml_elem_ap->conf->mld_ap) {
|
||||||
struct hostapd_data *ml_elem_ap =
|
|
||||||
params->mld_ap ? params->mld_ap : hapd;
|
|
||||||
|
|
||||||
buflen += hostapd_eid_eht_ml_beacon_len(
|
buflen += hostapd_eid_eht_ml_beacon_len(
|
||||||
ml_elem_ap, params->mld_info, !!params->mld_ap);
|
ml_elem_ap, params->mld_info, !!params->mld_ap);
|
||||||
|
|
||||||
|
/* For Max Channel Switch Time element during channel
|
||||||
|
* switch */
|
||||||
|
buflen += 6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211BE */
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
@ -680,12 +787,13 @@ static size_t hostapd_probe_resp_elems_len(struct hostapd_data *hapd,
|
||||||
buflen += hostapd_eid_mbssid_len(hapd, WLAN_FC_STYPE_PROBE_RESP, NULL,
|
buflen += hostapd_eid_mbssid_len(hapd, WLAN_FC_STYPE_PROBE_RESP, NULL,
|
||||||
params->known_bss,
|
params->known_bss,
|
||||||
params->known_bss_len, NULL);
|
params->known_bss_len, NULL);
|
||||||
if (!params->is_ml_sta_info)
|
buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP, true);
|
||||||
buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP,
|
|
||||||
true);
|
|
||||||
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);
|
buflen += hostapd_eid_dpp_cc_len(hapd);
|
||||||
|
buflen += hostapd_get_rsne_override_len(hapd);
|
||||||
|
buflen += hostapd_get_rsne_override_2_len(hapd);
|
||||||
|
buflen += hostapd_get_rsnxe_override_len(hapd);
|
||||||
|
|
||||||
return buflen;
|
return buflen;
|
||||||
}
|
}
|
||||||
|
@ -700,13 +808,11 @@ static u8 * hostapd_probe_resp_fill_elems(struct hostapd_data *hapd,
|
||||||
|
|
||||||
epos = pos + len;
|
epos = pos + len;
|
||||||
|
|
||||||
if (!params->is_ml_sta_info) {
|
*pos++ = WLAN_EID_SSID;
|
||||||
*pos++ = WLAN_EID_SSID;
|
*pos++ = hapd->conf->ssid.ssid_len;
|
||||||
*pos++ = hapd->conf->ssid.ssid_len;
|
os_memcpy(pos, hapd->conf->ssid.ssid,
|
||||||
os_memcpy(pos, hapd->conf->ssid.ssid,
|
hapd->conf->ssid.ssid_len);
|
||||||
hapd->conf->ssid.ssid_len);
|
pos += hapd->conf->ssid.ssid_len;
|
||||||
pos += hapd->conf->ssid.ssid_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Supported rates */
|
/* Supported rates */
|
||||||
pos = hostapd_eid_supp_rates(hapd, pos);
|
pos = hostapd_eid_supp_rates(hapd, pos);
|
||||||
|
@ -719,18 +825,13 @@ static u8 * hostapd_probe_resp_fill_elems(struct hostapd_data *hapd,
|
||||||
/* Power Constraint element */
|
/* Power Constraint element */
|
||||||
pos = hostapd_eid_pwr_constraint(hapd, pos);
|
pos = hostapd_eid_pwr_constraint(hapd, pos);
|
||||||
|
|
||||||
/*
|
/* CSA element */
|
||||||
* CSA IE
|
csa_pos = hostapd_eid_csa(hapd, pos);
|
||||||
* TODO: This should be included inside the ML sta profile
|
if (csa_pos != pos)
|
||||||
*/
|
params->csa_pos = csa_pos - 1;
|
||||||
if (!params->is_ml_sta_info) {
|
else
|
||||||
csa_pos = hostapd_eid_csa(hapd, pos);
|
params->csa_pos = NULL;
|
||||||
if (csa_pos != pos)
|
pos = csa_pos;
|
||||||
params->csa_pos = csa_pos - 1;
|
|
||||||
else
|
|
||||||
params->csa_pos = NULL;
|
|
||||||
pos = csa_pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ERP Information element */
|
/* ERP Information element */
|
||||||
pos = hostapd_eid_erp_info(hapd, pos);
|
pos = hostapd_eid_erp_info(hapd, pos);
|
||||||
|
@ -746,18 +847,13 @@ static u8 * hostapd_probe_resp_fill_elems(struct hostapd_data *hapd,
|
||||||
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);
|
pos = hostapd_get_mde(hapd, pos, epos - pos);
|
||||||
|
|
||||||
/*
|
/* eCSA element */
|
||||||
* eCSA IE
|
csa_pos = hostapd_eid_ecsa(hapd, pos);
|
||||||
* TODO: This should be included inside the ML sta profile
|
if (csa_pos != pos)
|
||||||
*/
|
params->ecsa_pos = csa_pos - 1;
|
||||||
if (!params->is_ml_sta_info) {
|
else
|
||||||
csa_pos = hostapd_eid_ecsa(hapd, pos);
|
params->ecsa_pos = NULL;
|
||||||
if (csa_pos != pos)
|
pos = csa_pos;
|
||||||
params->ecsa_pos = csa_pos - 1;
|
|
||||||
else
|
|
||||||
params->ecsa_pos = NULL;
|
|
||||||
pos = csa_pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
pos = hostapd_eid_supported_op_classes(hapd, pos);
|
pos = hostapd_eid_supported_op_classes(hapd, pos);
|
||||||
pos = hostapd_eid_ht_capabilities(hapd, pos);
|
pos = hostapd_eid_ht_capabilities(hapd, pos);
|
||||||
|
@ -799,12 +895,14 @@ static u8 * hostapd_probe_resp_fill_elems(struct hostapd_data *hapd,
|
||||||
pos = hostapd_eid_txpower_envelope(hapd, pos);
|
pos = hostapd_eid_txpower_envelope(hapd, pos);
|
||||||
#endif /* CONFIG_IEEE80211AX */
|
#endif /* CONFIG_IEEE80211AX */
|
||||||
|
|
||||||
pos = hostapd_eid_wb_chsw_wrapper(hapd, pos);
|
pos = hostapd_eid_chsw_wrapper(hapd, pos);
|
||||||
|
|
||||||
if (!params->is_ml_sta_info)
|
pos = hostapd_eid_rnr(hapd, pos, WLAN_FC_STYPE_PROBE_RESP, true);
|
||||||
pos = hostapd_eid_rnr(hapd, pos, WLAN_FC_STYPE_PROBE_RESP,
|
|
||||||
true);
|
|
||||||
pos = hostapd_eid_fils_indic(hapd, pos, 0);
|
pos = hostapd_eid_fils_indic(hapd, pos, 0);
|
||||||
|
|
||||||
|
/* Max Channel Switch Time element */
|
||||||
|
pos = hostapd_eid_max_cs_time(hapd, pos);
|
||||||
|
|
||||||
pos = hostapd_get_rsnxe(hapd, pos, epos - pos);
|
pos = hostapd_get_rsnxe(hapd, pos, epos - pos);
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211AX
|
#ifdef CONFIG_IEEE80211AX
|
||||||
|
@ -885,6 +983,10 @@ static u8 * hostapd_probe_resp_fill_elems(struct hostapd_data *hapd,
|
||||||
pos = hostapd_eid_owe_trans(hapd, pos, epos - pos);
|
pos = hostapd_eid_owe_trans(hapd, pos, epos - pos);
|
||||||
pos = hostapd_eid_dpp_cc(hapd, pos, epos - pos);
|
pos = hostapd_eid_dpp_cc(hapd, pos, epos - pos);
|
||||||
|
|
||||||
|
pos = hostapd_get_rsne_override(hapd, pos, epos - pos);
|
||||||
|
pos = hostapd_get_rsne_override_2(hapd, pos, epos - pos);
|
||||||
|
pos = hostapd_get_rsnxe_override(hapd, pos, epos - 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),
|
||||||
wpabuf_len(hapd->conf->vendor_elements));
|
wpabuf_len(hapd->conf->vendor_elements));
|
||||||
|
@ -957,7 +1059,6 @@ static void hostapd_fill_probe_resp_ml_params(struct hostapd_data *hapd,
|
||||||
const struct ieee80211_mgmt *mgmt,
|
const struct ieee80211_mgmt *mgmt,
|
||||||
int mld_id, u16 links)
|
int mld_id, u16 links)
|
||||||
{
|
{
|
||||||
struct probe_resp_params sta_info_params;
|
|
||||||
struct hostapd_data *link;
|
struct hostapd_data *link;
|
||||||
|
|
||||||
params->mld_ap = NULL;
|
params->mld_ap = NULL;
|
||||||
|
@ -971,10 +1072,7 @@ static void hostapd_fill_probe_resp_ml_params(struct hostapd_data *hapd,
|
||||||
|
|
||||||
for_each_mld_link(link, hapd) {
|
for_each_mld_link(link, hapd) {
|
||||||
struct mld_link_info *link_info;
|
struct mld_link_info *link_info;
|
||||||
size_t buflen;
|
|
||||||
u8 mld_link_id = link->mld_link_id;
|
u8 mld_link_id = link->mld_link_id;
|
||||||
u8 *epos;
|
|
||||||
u8 buf[EHT_ML_MAX_STA_PROF_LEN];
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set mld_ap iff the ML probe request explicitly
|
* Set mld_ap iff the ML probe request explicitly
|
||||||
|
@ -994,49 +1092,12 @@ static void hostapd_fill_probe_resp_ml_params(struct hostapd_data *hapd,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
link_info = ¶ms->mld_info->links[mld_link_id];
|
link_info = ¶ms->mld_info->links[mld_link_id];
|
||||||
|
os_memcpy(link_info, &hapd->partner_links[mld_link_id],
|
||||||
sta_info_params.req = params->req;
|
sizeof(hapd->partner_links[mld_link_id]));
|
||||||
sta_info_params.is_p2p = false;
|
|
||||||
sta_info_params.is_ml_sta_info = true;
|
|
||||||
sta_info_params.mld_ap = NULL;
|
|
||||||
sta_info_params.mld_info = NULL;
|
|
||||||
|
|
||||||
buflen = MAX_PROBERESP_LEN;
|
|
||||||
buflen += hostapd_probe_resp_elems_len(link, &sta_info_params);
|
|
||||||
|
|
||||||
if (buflen > EHT_ML_MAX_STA_PROF_LEN) {
|
|
||||||
wpa_printf(MSG_DEBUG,
|
|
||||||
"MLD: Not including link %d in ML probe response (%zu bytes is too long)",
|
|
||||||
mld_link_id, buflen);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NOTE: This does not properly handle inheritance and
|
|
||||||
* various other things.
|
|
||||||
*/
|
|
||||||
link_info->valid = true;
|
|
||||||
epos = buf;
|
|
||||||
|
|
||||||
/* Capabilities is the only fixed parameter */
|
|
||||||
WPA_PUT_LE16(epos, hostapd_own_capab_info(hapd));
|
|
||||||
epos += 2;
|
|
||||||
|
|
||||||
epos = hostapd_probe_resp_fill_elems(
|
|
||||||
link, &sta_info_params, epos,
|
|
||||||
EHT_ML_MAX_STA_PROF_LEN - 2);
|
|
||||||
link_info->resp_sta_profile_len = epos - buf;
|
|
||||||
os_free(link_info->resp_sta_profile);
|
|
||||||
link_info->resp_sta_profile = os_memdup(
|
|
||||||
buf, link_info->resp_sta_profile_len);
|
|
||||||
if (!link_info->resp_sta_profile)
|
|
||||||
link_info->resp_sta_profile_len = 0;
|
|
||||||
os_memcpy(link_info->local_addr, link->own_addr, ETH_ALEN);
|
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"MLD: ML probe response includes link sta info for %d: %u bytes (estimate %zu)",
|
"MLD: ML probe response includes link STA info for %d: %u bytes",
|
||||||
mld_link_id, link_info->resp_sta_profile_len,
|
mld_link_id, link_info->resp_sta_profile_len);
|
||||||
buflen);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mld_id != -1 && !params->mld_ap) {
|
if (mld_id != -1 && !params->mld_ap) {
|
||||||
|
@ -1357,12 +1418,6 @@ void handle_probe_req(struct hostapd_data *hapd,
|
||||||
int mld_id;
|
int mld_id;
|
||||||
u16 links;
|
u16 links;
|
||||||
#endif /* CONFIG_IEEE80211BE */
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
struct hostapd_ubus_request req = {
|
|
||||||
.type = HOSTAPD_UBUS_PROBE_REQ,
|
|
||||||
.mgmt_frame = mgmt,
|
|
||||||
.ssi_signal = ssi_signal,
|
|
||||||
.elems = &elems,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (hapd->iconf->rssi_ignore_probe_request && ssi_signal &&
|
if (hapd->iconf->rssi_ignore_probe_request && ssi_signal &&
|
||||||
ssi_signal < hapd->iconf->rssi_ignore_probe_request)
|
ssi_signal < hapd->iconf->rssi_ignore_probe_request)
|
||||||
|
@ -1549,12 +1604,6 @@ void handle_probe_req(struct hostapd_data *hapd,
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_P2P */
|
#endif /* CONFIG_P2P */
|
||||||
|
|
||||||
if (hostapd_ubus_handle_event(hapd, &req)) {
|
|
||||||
wpa_printf(MSG_DEBUG, "Probe request for " MACSTR " rejected by ubus handler.\n",
|
|
||||||
MAC2STR(mgmt->sa));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: verify that supp_rates contains at least one matching rate
|
/* TODO: verify that supp_rates contains at least one matching rate
|
||||||
* with AP configuration */
|
* with AP configuration */
|
||||||
|
|
||||||
|
@ -1615,7 +1664,6 @@ void handle_probe_req(struct hostapd_data *hapd,
|
||||||
params.is_p2p = !!elems.p2p;
|
params.is_p2p = !!elems.p2p;
|
||||||
params.known_bss = elems.mbssid_known_bss;
|
params.known_bss = elems.mbssid_known_bss;
|
||||||
params.known_bss_len = elems.mbssid_known_bss_len;
|
params.known_bss_len = elems.mbssid_known_bss_len;
|
||||||
params.is_ml_sta_info = false;
|
|
||||||
|
|
||||||
hostapd_gen_probe_resp(hapd, ¶ms);
|
hostapd_gen_probe_resp(hapd, ¶ms);
|
||||||
|
|
||||||
|
@ -1696,7 +1744,6 @@ static u8 * hostapd_probe_resp_offloads(struct hostapd_data *hapd,
|
||||||
params.is_p2p = false;
|
params.is_p2p = false;
|
||||||
params.known_bss = NULL;
|
params.known_bss = NULL;
|
||||||
params.known_bss_len = 0;
|
params.known_bss_len = 0;
|
||||||
params.is_ml_sta_info = false;
|
|
||||||
params.mld_ap = NULL;
|
params.mld_ap = NULL;
|
||||||
params.mld_info = NULL;
|
params.mld_info = NULL;
|
||||||
|
|
||||||
|
@ -1740,7 +1787,6 @@ u8 * hostapd_unsol_bcast_probe_resp(struct hostapd_data *hapd,
|
||||||
probe_params.is_p2p = false;
|
probe_params.is_p2p = false;
|
||||||
probe_params.known_bss = NULL;
|
probe_params.known_bss = NULL;
|
||||||
probe_params.known_bss_len = 0;
|
probe_params.known_bss_len = 0;
|
||||||
probe_params.is_ml_sta_info = false;
|
|
||||||
probe_params.mld_ap = NULL;
|
probe_params.mld_ap = NULL;
|
||||||
probe_params.mld_info = NULL;
|
probe_params.mld_info = NULL;
|
||||||
|
|
||||||
|
@ -2118,7 +2164,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
||||||
|
|
||||||
#ifdef NEED_AP_MLME
|
#ifdef NEED_AP_MLME
|
||||||
#define BEACON_HEAD_BUF_SIZE 256
|
#define BEACON_HEAD_BUF_SIZE 256
|
||||||
#define BEACON_TAIL_BUF_SIZE 512
|
#define BEACON_TAIL_BUF_SIZE 1500
|
||||||
head = os_zalloc(BEACON_HEAD_BUF_SIZE);
|
head = os_zalloc(BEACON_HEAD_BUF_SIZE);
|
||||||
tail_len = BEACON_TAIL_BUF_SIZE;
|
tail_len = BEACON_TAIL_BUF_SIZE;
|
||||||
#ifdef CONFIG_WPS
|
#ifdef CONFIG_WPS
|
||||||
|
@ -2157,8 +2203,13 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
||||||
* long based on the common info and number of per
|
* long based on the common info and number of per
|
||||||
* station profiles. For now use 256.
|
* station profiles. For now use 256.
|
||||||
*/
|
*/
|
||||||
if (hapd->conf->mld_ap)
|
if (hapd->conf->mld_ap) {
|
||||||
tail_len += 256;
|
tail_len += 256;
|
||||||
|
|
||||||
|
/* for Max Channel Switch Time element during channel
|
||||||
|
* switch */
|
||||||
|
tail_len += 6;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211BE */
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
|
@ -2169,6 +2220,9 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
||||||
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);
|
tail_len += hostapd_eid_dpp_cc_len(hapd);
|
||||||
|
tail_len += hostapd_get_rsne_override_len(hapd);
|
||||||
|
tail_len += hostapd_get_rsne_override_2_len(hapd);
|
||||||
|
tail_len += hostapd_get_rsnxe_override_len(hapd);
|
||||||
|
|
||||||
tailpos = tail = os_malloc(tail_len);
|
tailpos = tail = os_malloc(tail_len);
|
||||||
if (head == NULL || tail == NULL) {
|
if (head == NULL || tail == NULL) {
|
||||||
|
@ -2299,10 +2353,14 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
||||||
tailpos = hostapd_eid_txpower_envelope(hapd, tailpos);
|
tailpos = hostapd_eid_txpower_envelope(hapd, tailpos);
|
||||||
#endif /* CONFIG_IEEE80211AX */
|
#endif /* CONFIG_IEEE80211AX */
|
||||||
|
|
||||||
tailpos = hostapd_eid_wb_chsw_wrapper(hapd, tailpos);
|
tailpos = hostapd_eid_chsw_wrapper(hapd, tailpos);
|
||||||
|
|
||||||
tailpos = hostapd_eid_rnr(hapd, tailpos, WLAN_FC_STYPE_BEACON, true);
|
tailpos = hostapd_eid_rnr(hapd, tailpos, WLAN_FC_STYPE_BEACON, true);
|
||||||
tailpos = hostapd_eid_fils_indic(hapd, tailpos, 0);
|
tailpos = hostapd_eid_fils_indic(hapd, tailpos, 0);
|
||||||
|
|
||||||
|
/* Max Channel Switch Time element */
|
||||||
|
tailpos = hostapd_eid_max_cs_time(hapd, tailpos);
|
||||||
|
|
||||||
tailpos = hostapd_get_rsnxe(hapd, tailpos, tailend - tailpos);
|
tailpos = hostapd_get_rsnxe(hapd, tailpos, tailend - tailpos);
|
||||||
tailpos = hostapd_eid_mbssid_config(hapd, tailpos,
|
tailpos = hostapd_eid_mbssid_config(hapd, tailpos,
|
||||||
params->mbssid_elem_count);
|
params->mbssid_elem_count);
|
||||||
|
@ -2380,6 +2438,13 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
||||||
tail + tail_len - tailpos);
|
tail + tail_len - tailpos);
|
||||||
tailpos = hostapd_eid_dpp_cc(hapd, tailpos, tail + tail_len - tailpos);
|
tailpos = hostapd_eid_dpp_cc(hapd, tailpos, tail + tail_len - tailpos);
|
||||||
|
|
||||||
|
tailpos = hostapd_get_rsne_override(hapd, tailpos,
|
||||||
|
tail + tail_len - tailpos);
|
||||||
|
tailpos = hostapd_get_rsne_override_2(hapd, tailpos,
|
||||||
|
tail + tail_len - tailpos);
|
||||||
|
tailpos = hostapd_get_rsnxe_override(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),
|
||||||
wpabuf_len(hapd->conf->vendor_elements));
|
wpabuf_len(hapd->conf->vendor_elements));
|
||||||
|
@ -2412,7 +2477,9 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
||||||
/* If SAE offload is enabled, provide password to lower layer for
|
/* If SAE offload is enabled, provide password to lower layer for
|
||||||
* SAE authentication and PMK generation.
|
* SAE authentication and PMK generation.
|
||||||
*/
|
*/
|
||||||
if (wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
|
if (wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt |
|
||||||
|
hapd->conf->rsn_override_key_mgmt |
|
||||||
|
hapd->conf->rsn_override_key_mgmt_2) &&
|
||||||
(hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SAE_OFFLOAD_AP)) {
|
(hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SAE_OFFLOAD_AP)) {
|
||||||
if (hostapd_sae_pk_in_use(hapd->conf)) {
|
if (hostapd_sae_pk_in_use(hapd->conf)) {
|
||||||
wpa_printf(MSG_ERROR,
|
wpa_printf(MSG_ERROR,
|
||||||
|
@ -2457,7 +2524,9 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
||||||
else if (hapd->conf->wpa & WPA_PROTO_WPA)
|
else if (hapd->conf->wpa & WPA_PROTO_WPA)
|
||||||
params->pairwise_ciphers = hapd->conf->wpa_pairwise;
|
params->pairwise_ciphers = hapd->conf->wpa_pairwise;
|
||||||
params->group_cipher = hapd->conf->wpa_group;
|
params->group_cipher = hapd->conf->wpa_group;
|
||||||
params->key_mgmt_suites = hapd->conf->wpa_key_mgmt;
|
params->key_mgmt_suites = hapd->conf->wpa_key_mgmt |
|
||||||
|
hapd->conf->rsn_override_key_mgmt |
|
||||||
|
hapd->conf->rsn_override_key_mgmt_2;
|
||||||
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->wpa;
|
params->privacy = hapd->conf->wpa;
|
||||||
|
@ -2691,12 +2760,438 @@ void ieee802_11_set_beacon_per_bss_only(struct hostapd_data *hapd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
|
||||||
|
static int hostapd_get_probe_resp_tmpl(struct hostapd_data *hapd,
|
||||||
|
struct probe_resp_params *params,
|
||||||
|
bool is_ml_sta_info)
|
||||||
|
{
|
||||||
|
os_memset(params, 0, sizeof(*params));
|
||||||
|
hostapd_gen_probe_resp(hapd, params);
|
||||||
|
if (!params->resp)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* The caller takes care of freeing params->resp. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool is_restricted_eid_in_sta_profile(u8 eid, bool tx_vap)
|
||||||
|
{
|
||||||
|
switch (eid) {
|
||||||
|
case WLAN_EID_TIM:
|
||||||
|
case WLAN_EID_BSS_MAX_IDLE_PERIOD:
|
||||||
|
case WLAN_EID_MULTIPLE_BSSID:
|
||||||
|
case WLAN_EID_REDUCED_NEIGHBOR_REPORT:
|
||||||
|
case WLAN_EID_NEIGHBOR_REPORT:
|
||||||
|
return true;
|
||||||
|
case WLAN_EID_SSID:
|
||||||
|
/* SSID is not restricted for non-transmitted BSSID */
|
||||||
|
return tx_vap;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool is_restricted_ext_eid_in_sta_profile(u8 ext_id)
|
||||||
|
{
|
||||||
|
switch (ext_id) {
|
||||||
|
case WLAN_EID_EXT_MULTI_LINK:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Create the link STA profiles based on inheritance from the reporting
|
||||||
|
* profile.
|
||||||
|
*
|
||||||
|
* NOTE: The same function is used for length calculation as well as filling
|
||||||
|
* data in the given buffer. This avoids risk of not updating the length
|
||||||
|
* function but filling function or vice versa.
|
||||||
|
*/
|
||||||
|
static size_t hostapd_add_sta_profile(struct ieee80211_mgmt *link_fdata,
|
||||||
|
size_t link_data_len,
|
||||||
|
struct ieee80211_mgmt *own_fdata,
|
||||||
|
size_t own_data_len,
|
||||||
|
u8 *sta_profile, bool tx_vap)
|
||||||
|
{
|
||||||
|
const struct element *link_elem;
|
||||||
|
size_t sta_profile_len = 0;
|
||||||
|
const u8 *link_elem_data;
|
||||||
|
u8 link_ele_len;
|
||||||
|
u8 *link_data;
|
||||||
|
const struct element *own_elem;
|
||||||
|
u8 link_eid, own_eid, own_ele_len;
|
||||||
|
const u8 *own_elem_data;
|
||||||
|
u8 *own_data;
|
||||||
|
bool is_ext;
|
||||||
|
bool ie_found;
|
||||||
|
u8 non_inherit_ele_ext_list[256] = { 0 };
|
||||||
|
u8 non_inherit_ele_ext_list_len = 0;
|
||||||
|
u8 non_inherit_ele_list[256] = { 0 };
|
||||||
|
u8 non_inherit_ele_list_len = 0;
|
||||||
|
u8 num_link_elem_vendor_ies = 0, num_own_elem_vendor_ies = 0;
|
||||||
|
bool add_vendor_ies = false, is_identical_vendor_ies = true;
|
||||||
|
/* The bitmap of parsed EIDs. There are 256 EIDs and ext EIDs, so 32
|
||||||
|
* bytes to store the bitmaps. */
|
||||||
|
u8 parsed_eid_bmap[32] = { 0 }, parsed_ext_eid_bmap[32] = { 0 };
|
||||||
|
/* extra len used in the logic includes the element id and len */
|
||||||
|
u8 extra_len = 2;
|
||||||
|
|
||||||
|
/* Include len for capab info */
|
||||||
|
sta_profile_len += sizeof(le16);
|
||||||
|
if (sta_profile) {
|
||||||
|
os_memcpy(sta_profile, &link_fdata->u.probe_resp.capab_info,
|
||||||
|
sizeof(le16));
|
||||||
|
sta_profile += sizeof(le16);
|
||||||
|
}
|
||||||
|
|
||||||
|
own_data = own_fdata->u.probe_resp.variable;
|
||||||
|
link_data = link_fdata->u.probe_resp.variable;
|
||||||
|
|
||||||
|
/* The below logic takes the reporting BSS data and reported BSS data
|
||||||
|
* and performs intersection to build the STA profile of the reported
|
||||||
|
* BSS. Certain elements are not added to the STA profile as
|
||||||
|
* recommended in standard. Matching element information in the
|
||||||
|
* reporting BSS profile are ignored in the STA profile. Remaining
|
||||||
|
* elements pertaining to the STA profile are appended at the end. */
|
||||||
|
for_each_element(own_elem, own_data, own_data_len) {
|
||||||
|
is_ext = false;
|
||||||
|
ie_found = false;
|
||||||
|
|
||||||
|
/* Pick one of own elements and get its EID and length */
|
||||||
|
own_elem_data = own_elem->data;
|
||||||
|
own_ele_len = own_elem->datalen;
|
||||||
|
|
||||||
|
if (own_elem->id == WLAN_EID_EXTENSION) {
|
||||||
|
is_ext = true;
|
||||||
|
own_eid = *(own_elem_data);
|
||||||
|
if (is_restricted_ext_eid_in_sta_profile(own_eid))
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
own_eid = own_elem->id;
|
||||||
|
if (is_restricted_eid_in_sta_profile(own_eid, tx_vap))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for_each_element(link_elem, link_data, link_data_len) {
|
||||||
|
/* If the element type mismatches, do not consider
|
||||||
|
* this link element for comparison. */
|
||||||
|
if ((link_elem->id == WLAN_EID_EXTENSION &&
|
||||||
|
!is_ext) ||
|
||||||
|
(is_ext && link_elem->id != WLAN_EID_EXTENSION))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Comparison can be done so get the link element and
|
||||||
|
* its EID and length. */
|
||||||
|
link_elem_data = link_elem->data;
|
||||||
|
link_ele_len = link_elem->datalen;
|
||||||
|
|
||||||
|
if (link_elem->id == WLAN_EID_EXTENSION)
|
||||||
|
link_eid = *(link_elem_data);
|
||||||
|
else
|
||||||
|
link_eid = link_elem->id;
|
||||||
|
|
||||||
|
/* Ignore if EID does not match */
|
||||||
|
if (own_eid != link_eid)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ie_found = true;
|
||||||
|
|
||||||
|
/* Ignore if the contents is identical. */
|
||||||
|
if (own_ele_len == link_ele_len &&
|
||||||
|
os_memcmp(own_elem->data, link_elem->data,
|
||||||
|
own_ele_len) == 0) {
|
||||||
|
if (own_eid == WLAN_EID_VENDOR_SPECIFIC) {
|
||||||
|
is_identical_vendor_ies = true;
|
||||||
|
num_own_elem_vendor_ies++;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No need to include this non-matching Vendor Specific
|
||||||
|
* element explicitly at this point. */
|
||||||
|
if (own_eid == WLAN_EID_VENDOR_SPECIFIC) {
|
||||||
|
is_identical_vendor_ies = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This element is present in the reported profile
|
||||||
|
* as well as present in the reporting profile.
|
||||||
|
* However, there is a mismatch in the contents and
|
||||||
|
* hence, include this in the per STA profile. */
|
||||||
|
sta_profile_len += link_ele_len + extra_len;
|
||||||
|
if (sta_profile) {
|
||||||
|
os_memcpy(sta_profile,
|
||||||
|
link_elem->data - extra_len,
|
||||||
|
link_ele_len + extra_len);
|
||||||
|
sta_profile += link_ele_len + extra_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the parsed EIDs bitmap */
|
||||||
|
if (is_ext)
|
||||||
|
parsed_ext_eid_bmap[own_eid / 8] |=
|
||||||
|
BIT(own_eid % 8);
|
||||||
|
else
|
||||||
|
parsed_eid_bmap[own_eid / 8] |=
|
||||||
|
BIT(own_eid % 8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We found at least one Vendor Specific element in reporting
|
||||||
|
* link which is not same (or present) in the reported link. We
|
||||||
|
* need to include all Vendor Specific elements from the
|
||||||
|
* reported link. */
|
||||||
|
if (!is_identical_vendor_ies)
|
||||||
|
add_vendor_ies = true;
|
||||||
|
|
||||||
|
/* This is a unique element in the reporting profile which is
|
||||||
|
* not present in the reported profile. Update the
|
||||||
|
* non-inheritance list. */
|
||||||
|
if (!ie_found) {
|
||||||
|
u8 idx;
|
||||||
|
|
||||||
|
if (is_ext) {
|
||||||
|
idx = non_inherit_ele_ext_list_len++;
|
||||||
|
non_inherit_ele_ext_list[idx] = own_eid;
|
||||||
|
} else {
|
||||||
|
idx = non_inherit_ele_list_len++;
|
||||||
|
non_inherit_ele_list[idx] = own_eid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse the remaining elements in the reported profile */
|
||||||
|
for_each_element(link_elem, link_data, link_data_len) {
|
||||||
|
link_elem_data = link_elem->data;
|
||||||
|
link_ele_len = link_elem->datalen;
|
||||||
|
|
||||||
|
/* No need to check this Vendor Specific element at this point.
|
||||||
|
* Just take the count and continue. */
|
||||||
|
if (link_elem->id == WLAN_EID_VENDOR_SPECIFIC) {
|
||||||
|
num_link_elem_vendor_ies++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (link_elem->id == WLAN_EID_EXTENSION) {
|
||||||
|
link_eid = *(link_elem_data);
|
||||||
|
|
||||||
|
if ((parsed_ext_eid_bmap[link_eid / 8] &
|
||||||
|
BIT(link_eid % 8)) ||
|
||||||
|
is_restricted_ext_eid_in_sta_profile(link_eid))
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
link_eid = link_elem->id;
|
||||||
|
|
||||||
|
if ((parsed_eid_bmap[link_eid / 8] &
|
||||||
|
BIT(link_eid % 8)) ||
|
||||||
|
is_restricted_eid_in_sta_profile(link_eid, tx_vap))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sta_profile_len += link_ele_len + extra_len;
|
||||||
|
if (sta_profile) {
|
||||||
|
os_memcpy(sta_profile, link_elem_data - extra_len,
|
||||||
|
link_ele_len + extra_len);
|
||||||
|
sta_profile += link_ele_len + extra_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle Vendor Specific elements
|
||||||
|
* Add all the Vendor Specific elements of the reported link if
|
||||||
|
* a. There is at least one non-matching Vendor Specific element, or
|
||||||
|
* b. The number of Vendor Specific elements in reporting and reported
|
||||||
|
* link is not same. */
|
||||||
|
if (add_vendor_ies ||
|
||||||
|
num_own_elem_vendor_ies != num_link_elem_vendor_ies) {
|
||||||
|
for_each_element(link_elem, link_data, link_data_len) {
|
||||||
|
link_elem_data = link_elem->data;
|
||||||
|
link_ele_len = link_elem->datalen;
|
||||||
|
|
||||||
|
if (link_elem->id != WLAN_EID_VENDOR_SPECIFIC)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sta_profile_len += link_ele_len + extra_len;
|
||||||
|
if (sta_profile) {
|
||||||
|
os_memcpy(sta_profile,
|
||||||
|
link_elem_data - extra_len,
|
||||||
|
link_ele_len + extra_len);
|
||||||
|
sta_profile += link_ele_len + extra_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle non-inheritance
|
||||||
|
* Non-Inheritance element:
|
||||||
|
* Element ID Ext: 1 octet
|
||||||
|
* Length: 1 octet
|
||||||
|
* Ext tag number: 1 octet
|
||||||
|
* Length of Elements ID list: 1 octet
|
||||||
|
* Elements ID list: variable
|
||||||
|
* Length of Elements ID Extension list: 1 octet
|
||||||
|
* Elements ID extensions list: variable
|
||||||
|
*/
|
||||||
|
if (non_inherit_ele_list_len || non_inherit_ele_ext_list_len)
|
||||||
|
sta_profile_len += 3 + 2 + non_inherit_ele_list_len +
|
||||||
|
non_inherit_ele_ext_list_len;
|
||||||
|
|
||||||
|
if (sta_profile &&
|
||||||
|
(non_inherit_ele_list_len || non_inherit_ele_ext_list_len)) {
|
||||||
|
*sta_profile++ = WLAN_EID_EXTENSION;
|
||||||
|
*sta_profile++ = non_inherit_ele_list_len +
|
||||||
|
non_inherit_ele_ext_list_len + 3;
|
||||||
|
*sta_profile++ = WLAN_EID_EXT_NON_INHERITANCE;
|
||||||
|
*sta_profile++ = non_inherit_ele_list_len;
|
||||||
|
os_memcpy(sta_profile, non_inherit_ele_list,
|
||||||
|
non_inherit_ele_list_len);
|
||||||
|
sta_profile += non_inherit_ele_list_len;
|
||||||
|
*sta_profile++ = non_inherit_ele_ext_list_len;
|
||||||
|
os_memcpy(sta_profile, non_inherit_ele_ext_list,
|
||||||
|
non_inherit_ele_ext_list_len);
|
||||||
|
sta_profile += non_inherit_ele_ext_list_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sta_profile_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static u8 * hostapd_gen_sta_profile(struct ieee80211_mgmt *link_data,
|
||||||
|
size_t link_data_len,
|
||||||
|
struct ieee80211_mgmt *own_data,
|
||||||
|
size_t own_data_len,
|
||||||
|
size_t *sta_profile_len, bool tx_vap)
|
||||||
|
{
|
||||||
|
u8 *sta_profile;
|
||||||
|
|
||||||
|
/* Get the length first */
|
||||||
|
*sta_profile_len = hostapd_add_sta_profile(link_data, link_data_len,
|
||||||
|
own_data, own_data_len,
|
||||||
|
NULL, tx_vap);
|
||||||
|
if (!(*sta_profile_len) || *sta_profile_len > EHT_ML_MAX_STA_PROF_LEN)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
sta_profile = os_zalloc(*sta_profile_len);
|
||||||
|
if (!sta_profile)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Now fill in the data */
|
||||||
|
hostapd_add_sta_profile(link_data, link_data_len, own_data,
|
||||||
|
own_data_len, sta_profile, tx_vap);
|
||||||
|
|
||||||
|
/* The caller takes care of freeing the returned sta_profile */
|
||||||
|
return sta_profile;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void hostapd_gen_per_sta_profiles(struct hostapd_data *hapd)
|
||||||
|
{
|
||||||
|
bool tx_vap = hapd == hostapd_mbssid_get_tx_bss(hapd);
|
||||||
|
size_t link_data_len, sta_profile_len;
|
||||||
|
size_t own_data_len;
|
||||||
|
struct probe_resp_params link_params;
|
||||||
|
struct probe_resp_params own_params;
|
||||||
|
struct ieee80211_mgmt *link_data;
|
||||||
|
struct ieee80211_mgmt *own_data;
|
||||||
|
struct mld_link_info *link_info;
|
||||||
|
struct hostapd_data *link_bss;
|
||||||
|
u8 link_id, *sta_profile;
|
||||||
|
|
||||||
|
if (!hapd->conf->mld_ap)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "MLD: Generating per STA profiles for MLD %s",
|
||||||
|
hapd->conf->iface);
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "MLD: Reporting link %d", hapd->mld_link_id);
|
||||||
|
|
||||||
|
/* Generate a Probe Response template for self */
|
||||||
|
if (hostapd_get_probe_resp_tmpl(hapd, &own_params, false)) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"MLD: Error in building per STA profiles");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
own_data = own_params.resp;
|
||||||
|
own_data_len = own_params.resp_len;
|
||||||
|
|
||||||
|
/* Consider the length of the variable fields */
|
||||||
|
own_data_len -= offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
|
||||||
|
|
||||||
|
for_each_mld_link(link_bss, hapd) {
|
||||||
|
if (link_bss == hapd || !link_bss->started)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
link_id = link_bss->mld_link_id;
|
||||||
|
if (link_id > MAX_NUM_MLD_LINKS)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sta_profile = NULL;
|
||||||
|
sta_profile_len = 0;
|
||||||
|
|
||||||
|
/* Generate a Probe Response frame template for partner link */
|
||||||
|
if (hostapd_get_probe_resp_tmpl(link_bss, &link_params, true)) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"MLD: Could not get link STA probe response template for link %d",
|
||||||
|
link_id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
link_data = link_params.resp;
|
||||||
|
link_data_len = link_params.resp_len;
|
||||||
|
|
||||||
|
/* Consider length of the variable fields */
|
||||||
|
link_data_len -= offsetof(struct ieee80211_mgmt,
|
||||||
|
u.probe_resp.variable);
|
||||||
|
|
||||||
|
sta_profile = hostapd_gen_sta_profile(link_data, link_data_len,
|
||||||
|
own_data, own_data_len,
|
||||||
|
&sta_profile_len, tx_vap);
|
||||||
|
if (!sta_profile) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"MLD: Could not generate link STA profile for link %d",
|
||||||
|
link_id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
link_info = &hapd->partner_links[link_id];
|
||||||
|
link_info->valid = true;
|
||||||
|
|
||||||
|
os_free(link_info->resp_sta_profile);
|
||||||
|
link_info->resp_sta_profile_len = sta_profile_len;
|
||||||
|
|
||||||
|
link_info->resp_sta_profile = os_memdup(sta_profile,
|
||||||
|
sta_profile_len);
|
||||||
|
if (!link_info->resp_sta_profile)
|
||||||
|
link_info->resp_sta_profile_len = 0;
|
||||||
|
|
||||||
|
os_memcpy(link_info->local_addr, link_bss->own_addr, ETH_ALEN);
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"MLD: Reported link STA info for %d: %u bytes",
|
||||||
|
link_id, link_info->resp_sta_profile_len);
|
||||||
|
|
||||||
|
os_free(sta_profile);
|
||||||
|
os_free(link_params.resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
os_free(own_params.resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
|
|
||||||
int ieee802_11_set_beacon(struct hostapd_data *hapd)
|
int ieee802_11_set_beacon(struct hostapd_data *hapd)
|
||||||
{
|
{
|
||||||
struct hostapd_iface *iface = hapd->iface;
|
struct hostapd_iface *iface = hapd->iface;
|
||||||
int ret;
|
int ret;
|
||||||
size_t i, j;
|
size_t i, j;
|
||||||
bool is_6g, hapd_mld = false;
|
bool is_6g, hapd_mld = false;
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
struct hostapd_data *link_bss;
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
ret = __ieee802_11_set_beacon(hapd);
|
ret = __ieee802_11_set_beacon(hapd);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
|
@ -2737,6 +3232,15 @@ int ieee802_11_set_beacon(struct hostapd_data *hapd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
if (!hapd_mld)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Generate per STA profiles for each affiliated APs */
|
||||||
|
for_each_mld_link(link_bss, hapd)
|
||||||
|
hostapd_gen_per_sta_profiles(link_bss);
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -661,15 +661,18 @@ int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd,
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_P2P_MANAGER */
|
#endif /* CONFIG_P2P_MANAGER */
|
||||||
|
|
||||||
if (os_strstr(txtaddr, " tx=0"))
|
|
||||||
hostapd_drv_sta_remove(hapd, addr);
|
|
||||||
else
|
|
||||||
hostapd_drv_sta_deauth(hapd, addr, reason);
|
|
||||||
sta = ap_get_sta(hapd, addr);
|
sta = ap_get_sta(hapd, addr);
|
||||||
if (sta)
|
if (os_strstr(txtaddr, " tx=0")) {
|
||||||
ap_sta_deauthenticate(hapd, sta, reason);
|
hostapd_drv_sta_remove(hapd, addr);
|
||||||
else if (addr[0] == 0xff)
|
if (sta)
|
||||||
hostapd_free_stas(hapd);
|
ap_free_sta(hapd, sta);
|
||||||
|
} else {
|
||||||
|
hostapd_drv_sta_deauth(hapd, addr, reason);
|
||||||
|
if (sta)
|
||||||
|
ap_sta_deauthenticate(hapd, sta, reason);
|
||||||
|
else if (addr[0] == 0xff)
|
||||||
|
hostapd_free_stas(hapd);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -723,15 +726,18 @@ int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd,
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_P2P_MANAGER */
|
#endif /* CONFIG_P2P_MANAGER */
|
||||||
|
|
||||||
if (os_strstr(txtaddr, " tx=0"))
|
|
||||||
hostapd_drv_sta_remove(hapd, addr);
|
|
||||||
else
|
|
||||||
hostapd_drv_sta_disassoc(hapd, addr, reason);
|
|
||||||
sta = ap_get_sta(hapd, addr);
|
sta = ap_get_sta(hapd, addr);
|
||||||
if (sta)
|
if (os_strstr(txtaddr, " tx=0")) {
|
||||||
ap_sta_disassociate(hapd, sta, reason);
|
hostapd_drv_sta_remove(hapd, addr);
|
||||||
else if (addr[0] == 0xff)
|
if (sta)
|
||||||
hostapd_free_stas(hapd);
|
ap_free_sta(hapd, sta);
|
||||||
|
} else {
|
||||||
|
hostapd_drv_sta_disassoc(hapd, addr, reason);
|
||||||
|
if (sta)
|
||||||
|
ap_sta_disassociate(hapd, sta, reason);
|
||||||
|
else if (addr[0] == 0xff)
|
||||||
|
hostapd_free_stas(hapd);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1137,8 +1143,9 @@ int hostapd_parse_csa_settings(const char *pos,
|
||||||
SET_CSA_SETTING_EXT(punct_bitmap);
|
SET_CSA_SETTING_EXT(punct_bitmap);
|
||||||
settings->freq_params.ht_enabled = !!os_strstr(pos, " ht");
|
settings->freq_params.ht_enabled = !!os_strstr(pos, " ht");
|
||||||
settings->freq_params.vht_enabled = !!os_strstr(pos, " vht");
|
settings->freq_params.vht_enabled = !!os_strstr(pos, " vht");
|
||||||
settings->freq_params.he_enabled = !!os_strstr(pos, " he");
|
|
||||||
settings->freq_params.eht_enabled = !!os_strstr(pos, " eht");
|
settings->freq_params.eht_enabled = !!os_strstr(pos, " eht");
|
||||||
|
settings->freq_params.he_enabled = !!os_strstr(pos, " he") ||
|
||||||
|
settings->freq_params.eht_enabled;
|
||||||
settings->block_tx = !!os_strstr(pos, " blocktx");
|
settings->block_tx = !!os_strstr(pos, " blocktx");
|
||||||
#undef SET_CSA_SETTING
|
#undef SET_CSA_SETTING
|
||||||
#undef SET_CSA_SETTING_EXT
|
#undef SET_CSA_SETTING_EXT
|
||||||
|
|
|
@ -253,6 +253,13 @@ static int dfs_find_channel(struct hostapd_iface *iface,
|
||||||
for (i = 0; i < mode->num_channels; i++) {
|
for (i = 0; i < mode->num_channels; i++) {
|
||||||
chan = &mode->channels[i];
|
chan = &mode->channels[i];
|
||||||
|
|
||||||
|
if (!chan_in_current_hw_info(iface->current_hw_info, chan)) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DFS: channel %d (%d) is not under current hardware index",
|
||||||
|
chan->freq, chan->chan);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* Skip HT40/VHT incompatible channels */
|
/* Skip HT40/VHT incompatible channels */
|
||||||
if (iface->conf->ieee80211n &&
|
if (iface->conf->ieee80211n &&
|
||||||
iface->conf->secondary_channel &&
|
iface->conf->secondary_channel &&
|
||||||
|
@ -1218,8 +1225,6 @@ int hostapd_dfs_pre_cac_expired(struct hostapd_iface *iface, int freq,
|
||||||
"freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d",
|
"freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d",
|
||||||
freq, ht_enabled, chan_offset, chan_width, cf1, cf2);
|
freq, ht_enabled, chan_offset, chan_width, cf1, cf2);
|
||||||
|
|
||||||
hostapd_ubus_notify_radar_detected(iface, freq, chan_width, cf1, cf2);
|
|
||||||
|
|
||||||
/* Proceed only if DFS is not offloaded to the driver */
|
/* Proceed only if DFS is not offloaded to the driver */
|
||||||
if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
|
if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -73,6 +73,8 @@ void hostapd_notify_assoc_fils_finish(struct hostapd_data *hapd,
|
||||||
p = hostapd_eid_assoc_fils_session(sta->wpa_sm, p,
|
p = hostapd_eid_assoc_fils_session(sta->wpa_sm, p,
|
||||||
elems.fils_session,
|
elems.fils_session,
|
||||||
sta->fils_hlp_resp);
|
sta->fils_hlp_resp);
|
||||||
|
if (!p)
|
||||||
|
return;
|
||||||
|
|
||||||
reply_res = hostapd_sta_assoc(hapd, sta->addr,
|
reply_res = hostapd_sta_assoc(hapd, sta->addr,
|
||||||
sta->fils_pending_assoc_is_reassoc,
|
sta->fils_pending_assoc_is_reassoc,
|
||||||
|
@ -248,6 +250,52 @@ out:
|
||||||
#endif /* CONFIG_IEEE80211BE */
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(HOSTAPD) || defined(CONFIG_IEEE80211BE)
|
||||||
|
static struct hostapd_data * hostapd_find_by_sta(struct hostapd_iface *iface,
|
||||||
|
const u8 *src, bool rsn,
|
||||||
|
struct sta_info **sta_ret)
|
||||||
|
{
|
||||||
|
struct hostapd_data *hapd;
|
||||||
|
struct sta_info *sta;
|
||||||
|
unsigned int j;
|
||||||
|
|
||||||
|
if (sta_ret)
|
||||||
|
*sta_ret = NULL;
|
||||||
|
|
||||||
|
for (j = 0; j < iface->num_bss; j++) {
|
||||||
|
hapd = iface->bss[j];
|
||||||
|
sta = ap_get_sta(hapd, src);
|
||||||
|
if (sta && (sta->flags & WLAN_STA_ASSOC) &&
|
||||||
|
(!rsn || sta->wpa_sm)) {
|
||||||
|
if (sta_ret)
|
||||||
|
*sta_ret = sta;
|
||||||
|
return hapd;
|
||||||
|
}
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
if (hapd->conf->mld_ap) {
|
||||||
|
struct hostapd_data *p_hapd;
|
||||||
|
|
||||||
|
for_each_mld_link(p_hapd, hapd) {
|
||||||
|
if (p_hapd == hapd)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sta = ap_get_sta(p_hapd, src);
|
||||||
|
if (sta && (sta->flags & WLAN_STA_ASSOC) &&
|
||||||
|
(!rsn || sta->wpa_sm)) {
|
||||||
|
if (sta_ret)
|
||||||
|
*sta_ret = sta;
|
||||||
|
return p_hapd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif /* HOSTAPD || CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
|
|
||||||
int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
||||||
const u8 *req_ies, size_t req_ies_len,
|
const u8 *req_ies, size_t req_ies_len,
|
||||||
const u8 *resp_ies, size_t resp_ies_len,
|
const u8 *resp_ies, size_t resp_ies_len,
|
||||||
|
@ -268,10 +316,6 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
||||||
struct hostapd_iface *iface = hapd->iface;
|
struct hostapd_iface *iface = hapd->iface;
|
||||||
#endif /* CONFIG_OWE */
|
#endif /* CONFIG_OWE */
|
||||||
bool updated = false;
|
bool updated = false;
|
||||||
struct hostapd_ubus_request req = {
|
|
||||||
.type = HOSTAPD_UBUS_ASSOC_REQ,
|
|
||||||
.addr = addr,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (addr == NULL) {
|
if (addr == NULL) {
|
||||||
/*
|
/*
|
||||||
|
@ -416,12 +460,6 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hostapd_ubus_handle_event(hapd, &req)) {
|
|
||||||
wpa_printf(MSG_DEBUG, "Station " MACSTR " assoc rejected by ubus handler.\n",
|
|
||||||
MAC2STR(req.addr));
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_P2P
|
#ifdef CONFIG_P2P
|
||||||
if (elems.p2p) {
|
if (elems.p2p) {
|
||||||
wpabuf_free(sta->p2p_ie);
|
wpabuf_free(sta->p2p_ie);
|
||||||
|
@ -523,6 +561,8 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
||||||
"Failed to initialize WPA state machine");
|
"Failed to initialize WPA state machine");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
wpa_auth_set_rsn_selection(sta->wpa_sm, elems.rsn_selection,
|
||||||
|
elems.rsn_selection_len);
|
||||||
#ifdef CONFIG_IEEE80211BE
|
#ifdef CONFIG_IEEE80211BE
|
||||||
if (ap_sta_is_mld(hapd, sta)) {
|
if (ap_sta_is_mld(hapd, sta)) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
|
@ -783,6 +823,9 @@ skip_wpa_check:
|
||||||
p = hostapd_eid_assoc_fils_session(sta->wpa_sm, p,
|
p = hostapd_eid_assoc_fils_session(sta->wpa_sm, p,
|
||||||
elems.fils_session,
|
elems.fils_session,
|
||||||
sta->fils_hlp_resp);
|
sta->fils_hlp_resp);
|
||||||
|
if (!p)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
wpa_hexdump(MSG_DEBUG, "FILS Assoc Resp BUF (IEs)",
|
wpa_hexdump(MSG_DEBUG, "FILS Assoc Resp BUF (IEs)",
|
||||||
buf, p - buf);
|
buf, p - buf);
|
||||||
}
|
}
|
||||||
|
@ -1047,6 +1090,20 @@ legacy:
|
||||||
void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr)
|
void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr)
|
||||||
{
|
{
|
||||||
struct sta_info *sta = ap_get_sta(hapd, addr);
|
struct sta_info *sta = ap_get_sta(hapd, addr);
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
struct hostapd_data *orig_hapd = hapd;
|
||||||
|
|
||||||
|
if (!sta && hapd->conf->mld_ap) {
|
||||||
|
hapd = hostapd_find_by_sta(hapd->iface, addr, true, &sta);
|
||||||
|
if (!hapd) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"No partner link BSS found for STA " MACSTR
|
||||||
|
" - fallback to received context",
|
||||||
|
MAC2STR(addr));
|
||||||
|
hapd = orig_hapd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
if (!sta || !hapd->conf->disassoc_low_ack || sta->agreed_to_steer)
|
if (!sta || !hapd->conf->disassoc_low_ack || sta->agreed_to_steer)
|
||||||
return;
|
return;
|
||||||
|
@ -1989,50 +2046,6 @@ static int hostapd_event_new_sta(struct hostapd_data *hapd, const u8 *addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct hostapd_data * hostapd_find_by_sta(struct hostapd_iface *iface,
|
|
||||||
const u8 *src, bool rsn,
|
|
||||||
struct sta_info **sta_ret)
|
|
||||||
{
|
|
||||||
struct hostapd_data *hapd;
|
|
||||||
struct sta_info *sta;
|
|
||||||
unsigned int j;
|
|
||||||
|
|
||||||
if (sta_ret)
|
|
||||||
*sta_ret = NULL;
|
|
||||||
|
|
||||||
for (j = 0; j < iface->num_bss; j++) {
|
|
||||||
hapd = iface->bss[j];
|
|
||||||
sta = ap_get_sta(hapd, src);
|
|
||||||
if (sta && (sta->flags & WLAN_STA_ASSOC) &&
|
|
||||||
(!rsn || sta->wpa_sm)) {
|
|
||||||
if (sta_ret)
|
|
||||||
*sta_ret = sta;
|
|
||||||
return hapd;
|
|
||||||
}
|
|
||||||
#ifdef CONFIG_IEEE80211BE
|
|
||||||
if (hapd->conf->mld_ap) {
|
|
||||||
struct hostapd_data *p_hapd;
|
|
||||||
|
|
||||||
for_each_mld_link(p_hapd, hapd) {
|
|
||||||
if (p_hapd == hapd)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
sta = ap_get_sta(p_hapd, src);
|
|
||||||
if (sta && (sta->flags & WLAN_STA_ASSOC) &&
|
|
||||||
(!rsn || sta->wpa_sm)) {
|
|
||||||
if (sta_ret)
|
|
||||||
*sta_ret = sta;
|
|
||||||
return p_hapd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_IEEE80211BE */
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src,
|
static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src,
|
||||||
const u8 *data, size_t data_len,
|
const u8 *data, size_t data_len,
|
||||||
enum frame_encryption encrypted,
|
enum frame_encryption encrypted,
|
||||||
|
@ -2419,6 +2432,88 @@ static void hostapd_event_color_change(struct hostapd_data *hapd, bool success)
|
||||||
#endif /* CONFIG_IEEE80211AX */
|
#endif /* CONFIG_IEEE80211AX */
|
||||||
|
|
||||||
|
|
||||||
|
static void hostapd_iface_enable(struct hostapd_data *hapd)
|
||||||
|
{
|
||||||
|
wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_ENABLED);
|
||||||
|
if (hapd->disabled && hapd->started) {
|
||||||
|
hapd->disabled = 0;
|
||||||
|
/*
|
||||||
|
* Try to re-enable interface if the driver stopped it
|
||||||
|
* when the interface got disabled.
|
||||||
|
*/
|
||||||
|
if (hapd->wpa_auth)
|
||||||
|
wpa_auth_reconfig_group_keys(hapd->wpa_auth);
|
||||||
|
else
|
||||||
|
hostapd_reconfig_encryption(hapd);
|
||||||
|
hapd->reenable_beacon = 1;
|
||||||
|
ieee802_11_set_beacon(hapd);
|
||||||
|
#ifdef NEED_AP_MLME
|
||||||
|
} else if (hapd->disabled && hapd->iface->cac_started) {
|
||||||
|
wpa_printf(MSG_DEBUG, "DFS: restarting pending CAC");
|
||||||
|
hostapd_handle_dfs(hapd->iface);
|
||||||
|
#endif /* NEED_AP_MLME */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void hostapd_iface_disable(struct hostapd_data *hapd)
|
||||||
|
{
|
||||||
|
hostapd_free_stas(hapd);
|
||||||
|
wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_DISABLED);
|
||||||
|
hapd->disabled = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
|
||||||
|
static void hostapd_mld_iface_enable(struct hostapd_data *hapd)
|
||||||
|
{
|
||||||
|
struct hostapd_data *first_link, *link_bss;
|
||||||
|
|
||||||
|
first_link = hostapd_mld_is_first_bss(hapd) ? hapd :
|
||||||
|
hostapd_mld_get_first_bss(hapd);
|
||||||
|
|
||||||
|
/* Links have been removed. Re-add all links and enable them, but
|
||||||
|
* enable the first link BSS before doing that. */
|
||||||
|
if (hostapd_drv_link_add(first_link, first_link->mld_link_id,
|
||||||
|
first_link->own_addr)) {
|
||||||
|
wpa_printf(MSG_ERROR, "MLD: Failed to re-add link %d in MLD %s",
|
||||||
|
first_link->mld_link_id, first_link->conf->iface);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hostapd_iface_enable(first_link);
|
||||||
|
|
||||||
|
/* Add other affiliated links */
|
||||||
|
for_each_mld_link(link_bss, first_link) {
|
||||||
|
if (link_bss == first_link)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (hostapd_drv_link_add(link_bss, link_bss->mld_link_id,
|
||||||
|
link_bss->own_addr)) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"MLD: Failed to re-add link %d in MLD %s",
|
||||||
|
link_bss->mld_link_id,
|
||||||
|
link_bss->conf->iface);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
hostapd_iface_enable(link_bss);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void hostapd_mld_iface_disable(struct hostapd_data *hapd)
|
||||||
|
{
|
||||||
|
struct hostapd_data *link_bss;
|
||||||
|
|
||||||
|
for_each_mld_link(link_bss, hapd)
|
||||||
|
hostapd_iface_disable(link_bss);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
|
|
||||||
void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||||
union wpa_event_data *data)
|
union wpa_event_data *data)
|
||||||
{
|
{
|
||||||
|
@ -2696,30 +2791,22 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||||
break;
|
break;
|
||||||
#endif /* NEED_AP_MLME */
|
#endif /* NEED_AP_MLME */
|
||||||
case EVENT_INTERFACE_ENABLED:
|
case EVENT_INTERFACE_ENABLED:
|
||||||
wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_ENABLED);
|
#ifdef CONFIG_IEEE80211BE
|
||||||
if (hapd->disabled && hapd->started) {
|
if (hapd->conf->mld_ap) {
|
||||||
hapd->disabled = 0;
|
hostapd_mld_iface_enable(hapd);
|
||||||
/*
|
break;
|
||||||
* Try to re-enable interface if the driver stopped it
|
|
||||||
* when the interface got disabled.
|
|
||||||
*/
|
|
||||||
if (hapd->wpa_auth)
|
|
||||||
wpa_auth_reconfig_group_keys(hapd->wpa_auth);
|
|
||||||
else
|
|
||||||
hostapd_reconfig_encryption(hapd);
|
|
||||||
hapd->reenable_beacon = 1;
|
|
||||||
ieee802_11_set_beacon(hapd);
|
|
||||||
#ifdef NEED_AP_MLME
|
|
||||||
} else if (hapd->disabled && hapd->iface->cac_started) {
|
|
||||||
wpa_printf(MSG_DEBUG, "DFS: restarting pending CAC");
|
|
||||||
hostapd_handle_dfs(hapd->iface);
|
|
||||||
#endif /* NEED_AP_MLME */
|
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
hostapd_iface_enable(hapd);
|
||||||
break;
|
break;
|
||||||
case EVENT_INTERFACE_DISABLED:
|
case EVENT_INTERFACE_DISABLED:
|
||||||
hostapd_free_stas(hapd);
|
#ifdef CONFIG_IEEE80211BE
|
||||||
wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_DISABLED);
|
if (hapd->conf->mld_ap) {
|
||||||
hapd->disabled = 1;
|
hostapd_mld_iface_disable(hapd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
hostapd_iface_disable(hapd);
|
||||||
break;
|
break;
|
||||||
#ifdef CONFIG_ACS
|
#ifdef CONFIG_ACS
|
||||||
case EVENT_ACS_CHANNEL_SELECTED:
|
case EVENT_ACS_CHANNEL_SELECTED:
|
||||||
|
@ -2772,6 +2859,13 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||||
hostapd_event_color_change(hapd, true);
|
hostapd_event_color_change(hapd, true);
|
||||||
break;
|
break;
|
||||||
#endif /* CONFIG_IEEE80211AX */
|
#endif /* CONFIG_IEEE80211AX */
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
case EVENT_MLD_INTERFACE_FREED:
|
||||||
|
wpa_printf(MSG_DEBUG, "MLD: Interface %s freed",
|
||||||
|
hapd->conf->iface);
|
||||||
|
hostapd_mld_interface_freed(hapd);
|
||||||
|
break;
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
default:
|
default:
|
||||||
wpa_printf(MSG_DEBUG, "Unknown event %d", event);
|
wpa_printf(MSG_DEBUG, "Unknown event %d", event);
|
||||||
break;
|
break;
|
||||||
|
|
130
src/ap/hostapd.c
130
src/ap/hostapd.c
|
@ -400,8 +400,6 @@ static int hostapd_broadcast_wep_set(struct hostapd_data *hapd)
|
||||||
#ifdef CONFIG_IEEE80211BE
|
#ifdef CONFIG_IEEE80211BE
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
|
||||||
#define TU_TO_USEC(_val) ((_val) * 1024)
|
|
||||||
|
|
||||||
static void hostapd_link_remove_timeout_handler(void *eloop_data,
|
static void hostapd_link_remove_timeout_handler(void *eloop_data,
|
||||||
void *user_ctx)
|
void *user_ctx)
|
||||||
{
|
{
|
||||||
|
@ -440,6 +438,8 @@ int hostapd_link_remove(struct hostapd_data *hapd, u32 count)
|
||||||
|
|
||||||
hapd->eht_mld_link_removal_count = count;
|
hapd->eht_mld_link_removal_count = count;
|
||||||
hapd->eht_mld_bss_param_change++;
|
hapd->eht_mld_bss_param_change++;
|
||||||
|
if (hapd->eht_mld_bss_param_change == 255)
|
||||||
|
hapd->eht_mld_bss_param_change = 0;
|
||||||
|
|
||||||
eloop_register_timeout(0, TU_TO_USEC(hapd->iconf->beacon_int),
|
eloop_register_timeout(0, TU_TO_USEC(hapd->iconf->beacon_int),
|
||||||
hostapd_link_remove_timeout_handler,
|
hostapd_link_remove_timeout_handler,
|
||||||
|
@ -475,7 +475,6 @@ void hostapd_free_hapd_data(struct hostapd_data *hapd)
|
||||||
hapd->beacon_set_done = 0;
|
hapd->beacon_set_done = 0;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface);
|
wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface);
|
||||||
hostapd_ubus_free_bss(hapd);
|
|
||||||
accounting_deinit(hapd);
|
accounting_deinit(hapd);
|
||||||
hostapd_deinit_wpa(hapd);
|
hostapd_deinit_wpa(hapd);
|
||||||
vlan_deinit(hapd);
|
vlan_deinit(hapd);
|
||||||
|
@ -621,9 +620,19 @@ void hostapd_free_hapd_data(struct hostapd_data *hapd)
|
||||||
static void hostapd_bss_link_deinit(struct hostapd_data *hapd)
|
static void hostapd_bss_link_deinit(struct hostapd_data *hapd)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_IEEE80211BE
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
int i;
|
||||||
|
|
||||||
if (!hapd->conf || !hapd->conf->mld_ap)
|
if (!hapd->conf || !hapd->conf->mld_ap)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Free per STA profiles */
|
||||||
|
for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
|
||||||
|
os_free(hapd->partner_links[i].resp_sta_profile);
|
||||||
|
os_memset(&hapd->partner_links[i], 0,
|
||||||
|
sizeof(hapd->partner_links[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Put all freeing logic above this */
|
||||||
if (!hapd->mld->num_links)
|
if (!hapd->mld->num_links)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -703,6 +712,9 @@ void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
|
||||||
ap_list_deinit(iface);
|
ap_list_deinit(iface);
|
||||||
sta_track_deinit(iface);
|
sta_track_deinit(iface);
|
||||||
airtime_policy_update_deinit(iface);
|
airtime_policy_update_deinit(iface);
|
||||||
|
hostapd_free_multi_hw_info(iface->multi_hw_info);
|
||||||
|
iface->multi_hw_info = NULL;
|
||||||
|
iface->current_hw_info = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1304,8 +1316,6 @@ static int hostapd_start_beacon(struct hostapd_data *hapd,
|
||||||
if (hapd->driver && hapd->driver->set_operstate)
|
if (hapd->driver && hapd->driver->set_operstate)
|
||||||
hapd->driver->set_operstate(hapd->drv_priv, 1);
|
hapd->driver->set_operstate(hapd->drv_priv, 1);
|
||||||
|
|
||||||
hostapd_ubus_add_bss(hapd);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1443,7 +1453,6 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first,
|
||||||
if (h_hapd) {
|
if (h_hapd) {
|
||||||
hapd->drv_priv = h_hapd->drv_priv;
|
hapd->drv_priv = h_hapd->drv_priv;
|
||||||
hapd->interface_added = h_hapd->interface_added;
|
hapd->interface_added = h_hapd->interface_added;
|
||||||
hostapd_mld_add_link(hapd);
|
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"Setup of non first link (%d) BSS of MLD %s",
|
"Setup of non first link (%d) BSS of MLD %s",
|
||||||
hapd->mld_link_id, hapd->conf->iface);
|
hapd->mld_link_id, hapd->conf->iface);
|
||||||
|
@ -1474,7 +1483,6 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first,
|
||||||
hapd->mld_link_id, hapd->conf->iface);
|
hapd->mld_link_id, hapd->conf->iface);
|
||||||
os_memcpy(hapd->mld->mld_addr, hapd->own_addr,
|
os_memcpy(hapd->mld->mld_addr, hapd->own_addr,
|
||||||
ETH_ALEN);
|
ETH_ALEN);
|
||||||
hostapd_mld_add_link(hapd);
|
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211BE */
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
}
|
}
|
||||||
|
@ -1489,8 +1497,13 @@ setup_mld:
|
||||||
MAC2STR(hapd->own_addr));
|
MAC2STR(hapd->own_addr));
|
||||||
|
|
||||||
if (hostapd_drv_link_add(hapd, hapd->mld_link_id,
|
if (hostapd_drv_link_add(hapd, hapd->mld_link_id,
|
||||||
hapd->own_addr))
|
hapd->own_addr)) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"MLD: Failed to add link %d in MLD %s",
|
||||||
|
hapd->mld_link_id, hapd->conf->iface);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
hostapd_mld_add_link(hapd);
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211BE */
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
|
@ -1811,12 +1824,36 @@ int hostapd_set_acl(struct hostapd_data *hapd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int hostapd_set_ctrl_sock_iface(struct hostapd_data *hapd)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (hapd->conf->mld_ap) {
|
||||||
|
ret = os_snprintf(hapd->ctrl_sock_iface,
|
||||||
|
sizeof(hapd->ctrl_sock_iface), "%s_%s%d",
|
||||||
|
hapd->conf->iface, WPA_CTRL_IFACE_LINK_NAME,
|
||||||
|
hapd->mld_link_id);
|
||||||
|
if (os_snprintf_error(sizeof(hapd->ctrl_sock_iface), ret))
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
os_strlcpy(hapd->ctrl_sock_iface, hapd->conf->iface,
|
||||||
|
sizeof(hapd->ctrl_sock_iface));
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int start_ctrl_iface_bss(struct hostapd_data *hapd)
|
static int start_ctrl_iface_bss(struct hostapd_data *hapd)
|
||||||
{
|
{
|
||||||
if (!hapd->iface->interfaces ||
|
if (!hapd->iface->interfaces ||
|
||||||
!hapd->iface->interfaces->ctrl_iface_init)
|
!hapd->iface->interfaces->ctrl_iface_init)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (hostapd_set_ctrl_sock_iface(hapd))
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (hapd->iface->interfaces->ctrl_iface_init(hapd)) {
|
if (hapd->iface->interfaces->ctrl_iface_init(hapd)) {
|
||||||
wpa_printf(MSG_ERROR,
|
wpa_printf(MSG_ERROR,
|
||||||
"Failed to setup control interface for %s",
|
"Failed to setup control interface for %s",
|
||||||
|
@ -1837,6 +1874,10 @@ static int start_ctrl_iface(struct hostapd_iface *iface)
|
||||||
|
|
||||||
for (i = 0; i < iface->num_bss; i++) {
|
for (i = 0; i < iface->num_bss; i++) {
|
||||||
struct hostapd_data *hapd = iface->bss[i];
|
struct hostapd_data *hapd = iface->bss[i];
|
||||||
|
|
||||||
|
if (hostapd_set_ctrl_sock_iface(hapd))
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (iface->interfaces->ctrl_iface_init(hapd)) {
|
if (iface->interfaces->ctrl_iface_init(hapd)) {
|
||||||
wpa_printf(MSG_ERROR,
|
wpa_printf(MSG_ERROR,
|
||||||
"Failed to setup control interface for %s",
|
"Failed to setup control interface for %s",
|
||||||
|
@ -2484,7 +2525,6 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
|
||||||
if (err)
|
if (err)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
hostapd_ubus_add_iface(iface);
|
|
||||||
wpa_printf(MSG_DEBUG, "Completing interface initialization");
|
wpa_printf(MSG_DEBUG, "Completing interface initialization");
|
||||||
if (iface->freq) {
|
if (iface->freq) {
|
||||||
#ifdef NEED_AP_MLME
|
#ifdef NEED_AP_MLME
|
||||||
|
@ -2496,6 +2536,12 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
|
||||||
hostapd_hw_mode_txt(iface->conf->hw_mode),
|
hostapd_hw_mode_txt(iface->conf->hw_mode),
|
||||||
iface->conf->channel, iface->freq);
|
iface->conf->channel, iface->freq);
|
||||||
|
|
||||||
|
if (hostapd_set_current_hw_info(iface, iface->freq)) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"Failed to set current hardware info");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef NEED_AP_MLME
|
#ifdef NEED_AP_MLME
|
||||||
/* Handle DFS only if it is not offloaded to the driver */
|
/* Handle DFS only if it is not offloaded to the driver */
|
||||||
if (!(iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)) {
|
if (!(iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)) {
|
||||||
|
@ -2676,8 +2722,6 @@ dfs_offload:
|
||||||
#endif /* CONFIG_FST */
|
#endif /* CONFIG_FST */
|
||||||
|
|
||||||
hostapd_set_state(iface, HAPD_IFACE_ENABLED);
|
hostapd_set_state(iface, HAPD_IFACE_ENABLED);
|
||||||
// TODO: log everything in `hostapd_set_state` directly
|
|
||||||
hostapd_ubus_notify_readiness(hapd);
|
|
||||||
hostapd_owe_update_trans(iface);
|
hostapd_owe_update_trans(iface);
|
||||||
airtime_policy_update_init(iface);
|
airtime_policy_update_init(iface);
|
||||||
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_ENABLED);
|
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_ENABLED);
|
||||||
|
@ -2706,7 +2750,6 @@ dfs_offload:
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
wpa_printf(MSG_ERROR, "Interface initialization failed");
|
wpa_printf(MSG_ERROR, "Interface initialization failed");
|
||||||
hostapd_ubus_free_iface(iface);
|
|
||||||
|
|
||||||
if (iface->is_no_ir) {
|
if (iface->is_no_ir) {
|
||||||
hostapd_set_state(iface, HAPD_IFACE_NO_IR);
|
hostapd_set_state(iface, HAPD_IFACE_NO_IR);
|
||||||
|
@ -3072,9 +3115,17 @@ static void hostapd_bss_setup_multi_link(struct hostapd_data *hapd,
|
||||||
|
|
||||||
os_strlcpy(mld->name, conf->iface, sizeof(conf->iface));
|
os_strlcpy(mld->name, conf->iface, sizeof(conf->iface));
|
||||||
dl_list_init(&mld->links);
|
dl_list_init(&mld->links);
|
||||||
|
mld->ctrl_sock = -1;
|
||||||
|
if (hapd->conf->ctrl_interface)
|
||||||
|
mld->ctrl_interface = os_strdup(hapd->conf->ctrl_interface);
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "AP MLD %s created", mld->name);
|
wpa_printf(MSG_DEBUG, "AP MLD %s created", mld->name);
|
||||||
|
|
||||||
|
/* Initialize MLD control interfaces early to allow external monitoring
|
||||||
|
* of link setup operations. */
|
||||||
|
if (interfaces->mld_ctrl_iface_init(mld))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
hapd->mld = mld;
|
hapd->mld = mld;
|
||||||
hostapd_mld_ref_inc(mld);
|
hostapd_mld_ref_inc(mld);
|
||||||
hostapd_bss_alloc_link_id(hapd);
|
hostapd_bss_alloc_link_id(hapd);
|
||||||
|
@ -3134,6 +3185,8 @@ static void hostapd_cleanup_unused_mlds(struct hapd_interfaces *interfaces)
|
||||||
if (!remove && !forced_remove)
|
if (!remove && !forced_remove)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
interfaces->mld_ctrl_iface_deinit(mld);
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "AP MLD %s: Freed%s", mld->name,
|
wpa_printf(MSG_DEBUG, "AP MLD %s: Freed%s", mld->name,
|
||||||
forced_remove ? " (forced)" : "");
|
forced_remove ? " (forced)" : "");
|
||||||
os_free(mld);
|
os_free(mld);
|
||||||
|
@ -3394,8 +3447,10 @@ static void hostapd_cleanup_driver(const struct wpa_driver_ops *driver,
|
||||||
driver->hapd_deinit(drv_priv);
|
driver->hapd_deinit(drv_priv);
|
||||||
} else if (hostapd_mld_is_first_bss(iface->bss[0]) &&
|
} else if (hostapd_mld_is_first_bss(iface->bss[0]) &&
|
||||||
driver->is_drv_shared &&
|
driver->is_drv_shared &&
|
||||||
!driver->is_drv_shared(drv_priv, iface->bss[0])) {
|
!driver->is_drv_shared(drv_priv,
|
||||||
|
iface->bss[0]->mld_link_id)) {
|
||||||
driver->hapd_deinit(drv_priv);
|
driver->hapd_deinit(drv_priv);
|
||||||
|
hostapd_mld_interface_freed(iface->bss[0]);
|
||||||
} else if (hostapd_if_link_remove(iface->bss[0],
|
} else if (hostapd_if_link_remove(iface->bss[0],
|
||||||
WPA_IF_AP_BSS,
|
WPA_IF_AP_BSS,
|
||||||
iface->bss[0]->conf->iface,
|
iface->bss[0]->conf->iface,
|
||||||
|
@ -3423,7 +3478,6 @@ void hostapd_interface_deinit_free(struct hostapd_iface *iface)
|
||||||
(unsigned int) iface->conf->num_bss);
|
(unsigned int) iface->conf->num_bss);
|
||||||
driver = iface->bss[0]->driver;
|
driver = iface->bss[0]->driver;
|
||||||
drv_priv = iface->bss[0]->drv_priv;
|
drv_priv = iface->bss[0]->drv_priv;
|
||||||
hostapd_ubus_free_iface(iface);
|
|
||||||
hostapd_interface_deinit(iface);
|
hostapd_interface_deinit(iface);
|
||||||
wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
|
wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
|
||||||
__func__, driver, drv_priv);
|
__func__, driver, drv_priv);
|
||||||
|
@ -4509,6 +4563,42 @@ int hostapd_switch_channel(struct hostapd_data *hapd,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int hostapd_force_channel_switch(struct hostapd_iface *iface,
|
||||||
|
struct csa_settings settings)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (!settings.freq_params.channel) {
|
||||||
|
/* Check if the new channel is supported */
|
||||||
|
settings.freq_params.channel = hostapd_hw_get_channel(
|
||||||
|
iface->bss[0], settings.freq_params.freq);
|
||||||
|
if (!settings.freq_params.channel)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = hostapd_disable_iface(iface);
|
||||||
|
if (ret) {
|
||||||
|
wpa_printf(MSG_DEBUG, "Failed to disable the interface");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
hostapd_chan_switch_config(iface->bss[0], &settings.freq_params);
|
||||||
|
ret = hostapd_change_config_freq(iface->bss[0], iface->conf,
|
||||||
|
&settings.freq_params, NULL);
|
||||||
|
if (ret) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"Failed to set the new channel in config");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = hostapd_enable_iface(iface);
|
||||||
|
if (ret)
|
||||||
|
wpa_printf(MSG_DEBUG, "Failed to enable the interface");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
hostapd_switch_channel_fallback(struct hostapd_iface *iface,
|
hostapd_switch_channel_fallback(struct hostapd_iface *iface,
|
||||||
const struct hostapd_freq_params *freq_params)
|
const struct hostapd_freq_params *freq_params)
|
||||||
|
@ -4940,6 +5030,18 @@ struct hostapd_data * hostapd_mld_get_first_bss(struct hostapd_data *hapd)
|
||||||
return mld->fbss;
|
return mld->fbss;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void hostapd_mld_interface_freed(struct hostapd_data *hapd)
|
||||||
|
{
|
||||||
|
struct hostapd_data *link_bss = NULL;
|
||||||
|
|
||||||
|
if (!hapd || !hapd->conf->mld_ap)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for_each_mld_link(link_bss, hapd)
|
||||||
|
link_bss->drv_priv = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_IEEE80211BE */
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#include "utils/list.h"
|
#include "utils/list.h"
|
||||||
#include "ap_config.h"
|
#include "ap_config.h"
|
||||||
#include "drivers/driver.h"
|
#include "drivers/driver.h"
|
||||||
#include "ubus.h"
|
|
||||||
|
|
||||||
#define OCE_STA_CFON_ENABLED(hapd) \
|
#define OCE_STA_CFON_ENABLED(hapd) \
|
||||||
((hapd->conf->oce & OCE_STA_CFON) && \
|
((hapd->conf->oce & OCE_STA_CFON) && \
|
||||||
|
@ -98,6 +97,8 @@ struct hapd_interfaces {
|
||||||
#ifdef CONFIG_IEEE80211BE
|
#ifdef CONFIG_IEEE80211BE
|
||||||
struct hostapd_mld **mld;
|
struct hostapd_mld **mld;
|
||||||
size_t mld_count;
|
size_t mld_count;
|
||||||
|
int (*mld_ctrl_iface_init)(struct hostapd_mld *mld);
|
||||||
|
void (*mld_ctrl_iface_deinit)(struct hostapd_mld *mld);
|
||||||
#endif /* CONFIG_IEEE80211BE */
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -168,23 +169,21 @@ struct hostapd_sae_commit_queue {
|
||||||
u8 msg[];
|
u8 msg[];
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
struct mld_link_info {
|
||||||
* struct hostapd_liminix_stats - Liminix custom STA/AP statistics
|
u8 valid:1;
|
||||||
* Inspired from the OpenWRT patch of David Bauer.
|
u8 nstr_bitmap_len:2;
|
||||||
*/
|
u8 local_addr[ETH_ALEN];
|
||||||
struct hostapd_liminix_stats {
|
u8 peer_addr[ETH_ALEN];
|
||||||
struct {
|
|
||||||
u64 neighbor_report_tx;
|
|
||||||
} rrm;
|
|
||||||
|
|
||||||
struct {
|
u8 nstr_bitmap[2];
|
||||||
u64 bss_transition_query_rx;
|
|
||||||
u64 bss_transition_request_tx;
|
u16 capability;
|
||||||
u64 bss_transition_response_rx;
|
|
||||||
} wnm;
|
u16 status;
|
||||||
|
u16 resp_sta_profile_len;
|
||||||
|
u8 *resp_sta_profile;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct hostapd_data - hostapd per-BSS data structure
|
* struct hostapd_data - hostapd per-BSS data structure
|
||||||
*/
|
*/
|
||||||
|
@ -192,7 +191,6 @@ struct hostapd_data {
|
||||||
struct hostapd_iface *iface;
|
struct hostapd_iface *iface;
|
||||||
struct hostapd_config *iconf;
|
struct hostapd_config *iconf;
|
||||||
struct hostapd_bss_config *conf;
|
struct hostapd_bss_config *conf;
|
||||||
struct hostapd_ubus_bss ubus;
|
|
||||||
int interface_added; /* virtual interface added for this BSS */
|
int interface_added; /* virtual interface added for this BSS */
|
||||||
unsigned int started:1;
|
unsigned int started:1;
|
||||||
unsigned int disabled:1;
|
unsigned int disabled:1;
|
||||||
|
@ -200,9 +198,6 @@ struct hostapd_data {
|
||||||
|
|
||||||
u8 own_addr[ETH_ALEN];
|
u8 own_addr[ETH_ALEN];
|
||||||
|
|
||||||
/* Liminix specific statistics */
|
|
||||||
struct hostapd_liminix_stats liminix_stats;
|
|
||||||
|
|
||||||
int num_sta; /* number of entries in sta_list */
|
int num_sta; /* number of entries in sta_list */
|
||||||
struct sta_info *sta_list; /* STA info list head */
|
struct sta_info *sta_list; /* STA info list head */
|
||||||
#define STA_HASH_SIZE 256
|
#define STA_HASH_SIZE 256
|
||||||
|
@ -498,6 +493,14 @@ struct hostapd_data {
|
||||||
struct hostapd_mld *mld;
|
struct hostapd_mld *mld;
|
||||||
struct dl_list link;
|
struct dl_list link;
|
||||||
u8 mld_link_id;
|
u8 mld_link_id;
|
||||||
|
|
||||||
|
/* Cached partner info for ML probe response */
|
||||||
|
struct mld_link_info partner_links[MAX_NUM_MLD_LINKS];
|
||||||
|
|
||||||
|
/* 5 characters for "_link", up to 2 characters for <link ID>, so in
|
||||||
|
* total, additional 7 characters required. */
|
||||||
|
char ctrl_sock_iface[IFNAMSIZ + 7 + 1];
|
||||||
|
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
u8 eht_mld_link_removal_count;
|
u8 eht_mld_link_removal_count;
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
@ -540,6 +543,10 @@ struct hostapd_mld {
|
||||||
|
|
||||||
struct hostapd_data *fbss;
|
struct hostapd_data *fbss;
|
||||||
struct dl_list links; /* List head of all affiliated links */
|
struct dl_list links; /* List head of all affiliated links */
|
||||||
|
|
||||||
|
int ctrl_sock;
|
||||||
|
struct dl_list ctrl_dst;
|
||||||
|
char *ctrl_interface; /* Directory for UNIX domain sockets */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define HOSTAPD_MLD_MAX_REF_COUNT 0xFF
|
#define HOSTAPD_MLD_MAX_REF_COUNT 0xFF
|
||||||
|
@ -733,6 +740,10 @@ struct hostapd_iface {
|
||||||
bool is_no_ir;
|
bool is_no_ir;
|
||||||
|
|
||||||
bool is_ch_switch_dfs; /* Channel switch from ACS to DFS */
|
bool is_ch_switch_dfs; /* Channel switch from ACS to DFS */
|
||||||
|
|
||||||
|
struct hostapd_multi_hw_info *multi_hw_info;
|
||||||
|
unsigned int num_multi_hws;
|
||||||
|
struct hostapd_multi_hw_info *current_hw_info;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* hostapd.c */
|
/* hostapd.c */
|
||||||
|
@ -747,7 +758,6 @@ hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
|
||||||
struct hostapd_bss_config *bss);
|
struct hostapd_bss_config *bss);
|
||||||
int hostapd_setup_interface(struct hostapd_iface *iface);
|
int hostapd_setup_interface(struct hostapd_iface *iface);
|
||||||
int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err);
|
int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err);
|
||||||
void hostapd_set_own_neighbor_report(struct hostapd_data *hapd);
|
|
||||||
void hostapd_interface_deinit(struct hostapd_iface *iface);
|
void hostapd_interface_deinit(struct hostapd_iface *iface);
|
||||||
void hostapd_interface_free(struct hostapd_iface *iface);
|
void hostapd_interface_free(struct hostapd_iface *iface);
|
||||||
struct hostapd_iface * hostapd_alloc_iface(void);
|
struct hostapd_iface * hostapd_alloc_iface(void);
|
||||||
|
@ -776,6 +786,8 @@ void hostapd_chan_switch_config(struct hostapd_data *hapd,
|
||||||
struct hostapd_freq_params *freq_params);
|
struct hostapd_freq_params *freq_params);
|
||||||
int hostapd_switch_channel(struct hostapd_data *hapd,
|
int hostapd_switch_channel(struct hostapd_data *hapd,
|
||||||
struct csa_settings *settings);
|
struct csa_settings *settings);
|
||||||
|
int hostapd_force_channel_switch(struct hostapd_iface *iface,
|
||||||
|
struct csa_settings settings);
|
||||||
void
|
void
|
||||||
hostapd_switch_channel_fallback(struct hostapd_iface *iface,
|
hostapd_switch_channel_fallback(struct hostapd_iface *iface,
|
||||||
const struct hostapd_freq_params *freq_params);
|
const struct hostapd_freq_params *freq_params);
|
||||||
|
@ -854,6 +866,7 @@ int hostapd_fill_cca_settings(struct hostapd_data *hapd,
|
||||||
#ifdef CONFIG_IEEE80211BE
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
|
||||||
bool hostapd_mld_is_first_bss(struct hostapd_data *hapd);
|
bool hostapd_mld_is_first_bss(struct hostapd_data *hapd);
|
||||||
|
void hostapd_mld_interface_freed(struct hostapd_data *hapd);
|
||||||
|
|
||||||
#define for_each_mld_link(partner, self) \
|
#define for_each_mld_link(partner, self) \
|
||||||
dl_list_for_each(partner, &self->mld->links, struct hostapd_data, link)
|
dl_list_for_each(partner, &self->mld->links, struct hostapd_data, link)
|
||||||
|
|
|
@ -76,12 +76,15 @@ int hostapd_get_hw_features(struct hostapd_iface *iface)
|
||||||
{
|
{
|
||||||
struct hostapd_data *hapd = iface->bss[0];
|
struct hostapd_data *hapd = iface->bss[0];
|
||||||
int i, j;
|
int i, j;
|
||||||
|
unsigned int k;
|
||||||
u16 num_modes, flags;
|
u16 num_modes, flags;
|
||||||
struct hostapd_hw_modes *modes;
|
struct hostapd_hw_modes *modes;
|
||||||
u8 dfs_domain;
|
u8 dfs_domain;
|
||||||
enum hostapd_hw_mode mode = HOSTAPD_MODE_IEEE80211ANY;
|
enum hostapd_hw_mode mode = HOSTAPD_MODE_IEEE80211ANY;
|
||||||
bool is_6ghz = false;
|
bool is_6ghz = false;
|
||||||
bool orig_mode_valid = false;
|
bool orig_mode_valid = false;
|
||||||
|
struct hostapd_multi_hw_info *multi_hw_info;
|
||||||
|
unsigned int num_multi_hws;
|
||||||
|
|
||||||
if (hostapd_drv_none(hapd))
|
if (hostapd_drv_none(hapd))
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -168,6 +171,25 @@ int hostapd_get_hw_features(struct hostapd_iface *iface)
|
||||||
__func__);
|
__func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
multi_hw_info = hostapd_get_multi_hw_info(hapd, &num_multi_hws);
|
||||||
|
if (!multi_hw_info)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
hostapd_free_multi_hw_info(iface->multi_hw_info);
|
||||||
|
iface->multi_hw_info = multi_hw_info;
|
||||||
|
iface->num_multi_hws = num_multi_hws;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "Multiple underlying hardwares info:");
|
||||||
|
|
||||||
|
for (k = 0; k < num_multi_hws; k++) {
|
||||||
|
struct hostapd_multi_hw_info *hw_info = &multi_hw_info[k];
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
" %d. hw_idx=%u, frequency range: %d-%d MHz",
|
||||||
|
k + 1, hw_info->hw_idx, hw_info->start_freq,
|
||||||
|
hw_info->end_freq);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1391,3 +1413,34 @@ int hostapd_hw_skip_mode(struct hostapd_iface *iface,
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void hostapd_free_multi_hw_info(struct hostapd_multi_hw_info *multi_hw_info)
|
||||||
|
{
|
||||||
|
os_free(multi_hw_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int hostapd_set_current_hw_info(struct hostapd_iface *iface, int oper_freq)
|
||||||
|
{
|
||||||
|
struct hostapd_multi_hw_info *hw_info;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (!iface->num_multi_hws)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (i = 0; i < iface->num_multi_hws; i++) {
|
||||||
|
hw_info = &iface->multi_hw_info[i];
|
||||||
|
|
||||||
|
if (hw_info->start_freq <= oper_freq &&
|
||||||
|
hw_info->end_freq >= oper_freq) {
|
||||||
|
iface->current_hw_info = hw_info;
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"Mode: Selected underlying hardware: hw_idx=%u",
|
||||||
|
iface->current_hw_info->hw_idx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
|
@ -30,6 +30,8 @@ void hostapd_stop_setup_timers(struct hostapd_iface *iface);
|
||||||
int hostapd_hw_skip_mode(struct hostapd_iface *iface,
|
int hostapd_hw_skip_mode(struct hostapd_iface *iface,
|
||||||
struct hostapd_hw_modes *mode);
|
struct hostapd_hw_modes *mode);
|
||||||
int hostapd_determine_mode(struct hostapd_iface *iface);
|
int hostapd_determine_mode(struct hostapd_iface *iface);
|
||||||
|
void hostapd_free_multi_hw_info(struct hostapd_multi_hw_info *multi_hw_info);
|
||||||
|
int hostapd_set_current_hw_info(struct hostapd_iface *iface, int oper_freq);
|
||||||
#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,
|
||||||
|
@ -103,6 +105,16 @@ static inline int hostapd_determine_mode(struct hostapd_iface *iface)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void hostapd_free_multi_hw_info(struct hostapd_multi_hw_info *multi_hw_info)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int hostapd_set_current_hw_info(struct hostapd_iface *iface,
|
||||||
|
u32 oper_freq)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif /* NEED_AP_MLME */
|
#endif /* NEED_AP_MLME */
|
||||||
|
|
||||||
#endif /* HW_FEATURES_H */
|
#endif /* HW_FEATURES_H */
|
||||||
|
|
|
@ -1173,16 +1173,23 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
static void sae_pick_next_group(struct hostapd_data *hapd, struct sta_info *sta)
|
static void sae_pick_next_group(struct hostapd_data *hapd, struct sta_info *sta)
|
||||||
{
|
{
|
||||||
struct sae_data *sae = sta->sae;
|
struct sae_data *sae = sta->sae;
|
||||||
int i, *groups = hapd->conf->sae_groups;
|
struct hostapd_bss_config *conf = hapd->conf;
|
||||||
int default_groups[] = { 19, 0 };
|
int i, *groups = conf->sae_groups;
|
||||||
|
int default_groups[] = { 19, 0, 0 };
|
||||||
|
|
||||||
if (sae->state != SAE_COMMITTED)
|
if (sae->state != SAE_COMMITTED)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "SAE: Previously selected group: %d", sae->group);
|
wpa_printf(MSG_DEBUG, "SAE: Previously selected group: %d", sae->group);
|
||||||
|
|
||||||
if (!groups)
|
if (!groups) {
|
||||||
groups = default_groups;
|
groups = default_groups;
|
||||||
|
if (wpa_key_mgmt_sae_ext_key(conf->wpa_key_mgmt |
|
||||||
|
conf->rsn_override_key_mgmt |
|
||||||
|
conf->rsn_override_key_mgmt_2))
|
||||||
|
default_groups[1] = 20;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; groups[i] > 0; i++) {
|
for (i = 0; groups[i] > 0; i++) {
|
||||||
if (sae->group == groups[i])
|
if (sae->group == groups[i])
|
||||||
break;
|
break;
|
||||||
|
@ -1247,12 +1254,18 @@ static int sae_status_success(struct hostapd_data *hapd, u16 status_code)
|
||||||
|
|
||||||
static int sae_is_group_enabled(struct hostapd_data *hapd, int group)
|
static int sae_is_group_enabled(struct hostapd_data *hapd, int group)
|
||||||
{
|
{
|
||||||
int *groups = hapd->conf->sae_groups;
|
struct hostapd_bss_config *conf = hapd->conf;
|
||||||
int default_groups[] = { 19, 0 };
|
int *groups = conf->sae_groups;
|
||||||
|
int default_groups[] = { 19, 0, 0 };
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!groups)
|
if (!groups) {
|
||||||
groups = default_groups;
|
groups = default_groups;
|
||||||
|
if (wpa_key_mgmt_sae_ext_key(conf->wpa_key_mgmt |
|
||||||
|
conf->rsn_override_key_mgmt |
|
||||||
|
conf->rsn_override_key_mgmt_2))
|
||||||
|
default_groups[1] = 20;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; groups[i] > 0; i++) {
|
for (i = 0; groups[i] > 0; i++) {
|
||||||
if (groups[i] == group)
|
if (groups[i] == group)
|
||||||
|
@ -1309,14 +1322,20 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
{
|
{
|
||||||
int resp = WLAN_STATUS_SUCCESS;
|
int resp = WLAN_STATUS_SUCCESS;
|
||||||
struct wpabuf *data = NULL;
|
struct wpabuf *data = NULL;
|
||||||
int *groups = hapd->conf->sae_groups;
|
struct hostapd_bss_config *conf = hapd->conf;
|
||||||
int default_groups[] = { 19, 0 };
|
int *groups = conf->sae_groups;
|
||||||
|
int default_groups[] = { 19, 0, 0 };
|
||||||
const u8 *pos, *end;
|
const u8 *pos, *end;
|
||||||
int sta_removed = 0;
|
int sta_removed = 0;
|
||||||
bool success_status;
|
bool success_status;
|
||||||
|
|
||||||
if (!groups)
|
if (!groups) {
|
||||||
groups = default_groups;
|
groups = default_groups;
|
||||||
|
if (wpa_key_mgmt_sae_ext_key(conf->wpa_key_mgmt |
|
||||||
|
conf->rsn_override_key_mgmt |
|
||||||
|
conf->rsn_override_key_mgmt_2))
|
||||||
|
default_groups[1] = 20;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
if (hapd->conf->sae_reflection_attack && auth_transaction == 1) {
|
if (hapd->conf->sae_reflection_attack && auth_transaction == 1) {
|
||||||
|
@ -1609,12 +1628,12 @@ reply:
|
||||||
!data && end - pos >= 2)
|
!data && end - pos >= 2)
|
||||||
data = wpabuf_alloc_copy(pos, 2);
|
data = wpabuf_alloc_copy(pos, 2);
|
||||||
|
|
||||||
sae_sme_send_external_auth_status(hapd, sta, resp);
|
|
||||||
send_auth_reply(hapd, sta, sta->addr,
|
send_auth_reply(hapd, sta, sta->addr,
|
||||||
WLAN_AUTH_SAE,
|
WLAN_AUTH_SAE,
|
||||||
auth_transaction, resp,
|
auth_transaction, resp,
|
||||||
data ? wpabuf_head(data) : (u8 *) "",
|
data ? wpabuf_head(data) : (u8 *) "",
|
||||||
data ? wpabuf_len(data) : 0, "auth-sae");
|
data ? wpabuf_len(data) : 0, "auth-sae");
|
||||||
|
sae_sme_send_external_auth_status(hapd, sta, resp);
|
||||||
if (sta->sae && sta->sae->tmp && sta->sae->tmp->pw_id &&
|
if (sta->sae && sta->sae->tmp && sta->sae->tmp->pw_id &&
|
||||||
resp == WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER &&
|
resp == WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER &&
|
||||||
auth_transaction == 1) {
|
auth_transaction == 1) {
|
||||||
|
@ -1935,6 +1954,8 @@ void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wpa_auth_set_rsn_selection(sta->wpa_sm, elems.rsn_selection,
|
||||||
|
elems.rsn_selection_len);
|
||||||
res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
|
res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
|
||||||
hapd->iface->freq,
|
hapd->iface->freq,
|
||||||
elems.rsn_ie - 2, elems.rsn_ie_len + 2,
|
elems.rsn_ie - 2, elems.rsn_ie_len + 2,
|
||||||
|
@ -2829,7 +2850,7 @@ static void handle_auth_pasn(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
|
|
||||||
hapd_pasn_update_params(hapd, sta, mgmt, len);
|
hapd_pasn_update_params(hapd, sta, mgmt, len);
|
||||||
if (handle_auth_pasn_1(sta->pasn, hapd->own_addr,
|
if (handle_auth_pasn_1(sta->pasn, hapd->own_addr,
|
||||||
sta->addr, mgmt, len) < 0)
|
sta->addr, mgmt, len, false) < 0)
|
||||||
ap_free_sta(hapd, sta);
|
ap_free_sta(hapd, sta);
|
||||||
} else if (trans_seq == 3) {
|
} else if (trans_seq == 3) {
|
||||||
if (!sta->pasn) {
|
if (!sta->pasn) {
|
||||||
|
@ -2874,7 +2895,7 @@ static void handle_auth(struct hostapd_data *hapd,
|
||||||
u16 auth_alg, auth_transaction, status_code;
|
u16 auth_alg, auth_transaction, status_code;
|
||||||
u16 resp = WLAN_STATUS_SUCCESS;
|
u16 resp = WLAN_STATUS_SUCCESS;
|
||||||
struct sta_info *sta = NULL;
|
struct sta_info *sta = NULL;
|
||||||
int res, reply_res, ubus_resp;
|
int res, reply_res;
|
||||||
u16 fc;
|
u16 fc;
|
||||||
const u8 *challenge = NULL;
|
const u8 *challenge = NULL;
|
||||||
u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
|
u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
|
||||||
|
@ -2886,12 +2907,6 @@ static void handle_auth(struct hostapd_data *hapd,
|
||||||
bool mld_sta = false;
|
bool mld_sta = false;
|
||||||
#endif /* CONFIG_IEEE80211BE */
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
struct hostapd_ubus_request req = {
|
|
||||||
.type = HOSTAPD_UBUS_AUTH_REQ,
|
|
||||||
.mgmt_frame = mgmt,
|
|
||||||
.ssi_signal = rssi,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
|
if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
|
||||||
wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)",
|
wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)",
|
||||||
(unsigned long) len);
|
(unsigned long) len);
|
||||||
|
@ -2967,7 +2982,10 @@ static void handle_auth(struct hostapd_data *hapd,
|
||||||
auth_alg == WLAN_AUTH_FT) ||
|
auth_alg == WLAN_AUTH_FT) ||
|
||||||
#endif /* CONFIG_IEEE80211R_AP */
|
#endif /* CONFIG_IEEE80211R_AP */
|
||||||
#ifdef CONFIG_SAE
|
#ifdef CONFIG_SAE
|
||||||
(hapd->conf->wpa && wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
|
(hapd->conf->wpa &&
|
||||||
|
wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt |
|
||||||
|
hapd->conf->rsn_override_key_mgmt |
|
||||||
|
hapd->conf->rsn_override_key_mgmt_2) &&
|
||||||
auth_alg == WLAN_AUTH_SAE) ||
|
auth_alg == WLAN_AUTH_SAE) ||
|
||||||
#endif /* CONFIG_SAE */
|
#endif /* CONFIG_SAE */
|
||||||
#ifdef CONFIG_FILS
|
#ifdef CONFIG_FILS
|
||||||
|
@ -3008,14 +3026,6 @@ static void handle_auth(struct hostapd_data *hapd,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
ubus_resp = hostapd_ubus_handle_event(hapd, &req);
|
|
||||||
if (ubus_resp) {
|
|
||||||
wpa_printf(MSG_DEBUG, "Station " MACSTR " rejected by ubus handler.\n",
|
|
||||||
MAC2STR(mgmt->sa));
|
|
||||||
resp = ubus_resp > 0 ? (u16) ubus_resp : WLAN_STATUS_UNSPECIFIED_FAILURE;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211BE
|
#ifdef CONFIG_IEEE80211BE
|
||||||
if (mld_sta &&
|
if (mld_sta &&
|
||||||
(ether_addr_equal(sa, hapd->own_addr) ||
|
(ether_addr_equal(sa, hapd->own_addr) ||
|
||||||
|
@ -4142,6 +4152,8 @@ static int __check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
#endif /* CONFIG_IEEE80211BE */
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
wpa_auth_set_auth_alg(sta->wpa_sm, sta->auth_alg);
|
wpa_auth_set_auth_alg(sta->wpa_sm, sta->auth_alg);
|
||||||
|
wpa_auth_set_rsn_selection(sta->wpa_sm, elems->rsn_selection,
|
||||||
|
elems->rsn_selection_len);
|
||||||
res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
|
res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
|
||||||
hapd->iface->freq,
|
hapd->iface->freq,
|
||||||
wpa_ie, wpa_ie_len,
|
wpa_ie, wpa_ie_len,
|
||||||
|
@ -5002,7 +5014,8 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
#endif /* CONFIG_IEEE80211AX */
|
#endif /* CONFIG_IEEE80211AX */
|
||||||
|
|
||||||
p = hostapd_eid_ext_capab(hapd, p, false);
|
p = hostapd_eid_ext_capab(hapd, p, false);
|
||||||
p = hostapd_eid_bss_max_idle_period(hapd, p, sta->max_idle_period);
|
p = hostapd_eid_bss_max_idle_period(hapd, p,
|
||||||
|
sta ? sta->max_idle_period : 0);
|
||||||
if (sta && sta->qos_map_enabled)
|
if (sta && sta->qos_map_enabled)
|
||||||
p = hostapd_eid_qos_map_set(hapd, p);
|
p = hostapd_eid_qos_map_set(hapd, p);
|
||||||
|
|
||||||
|
@ -5344,7 +5357,7 @@ static void handle_assoc(struct hostapd_data *hapd,
|
||||||
int resp = WLAN_STATUS_SUCCESS;
|
int resp = WLAN_STATUS_SUCCESS;
|
||||||
u16 reply_res = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
u16 reply_res = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||||
const u8 *pos;
|
const u8 *pos;
|
||||||
int left, i, ubus_resp;
|
int left, i;
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
u8 *tmp = NULL;
|
u8 *tmp = NULL;
|
||||||
#ifdef CONFIG_FILS
|
#ifdef CONFIG_FILS
|
||||||
|
@ -5587,12 +5600,6 @@ static void handle_assoc(struct hostapd_data *hapd,
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_FILS */
|
#endif /* CONFIG_FILS */
|
||||||
|
|
||||||
struct hostapd_ubus_request req = {
|
|
||||||
.type = HOSTAPD_UBUS_ASSOC_REQ,
|
|
||||||
.mgmt_frame = mgmt,
|
|
||||||
.ssi_signal = rssi,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* followed by SSID and Supported rates; and HT capabilities if 802.11n
|
/* followed by SSID and Supported rates; and HT capabilities if 802.11n
|
||||||
* is used */
|
* is used */
|
||||||
resp = check_assoc_ies(hapd, sta, pos, left, reassoc);
|
resp = check_assoc_ies(hapd, sta, pos, left, reassoc);
|
||||||
|
@ -5694,14 +5701,6 @@ static void handle_assoc(struct hostapd_data *hapd,
|
||||||
if (set_beacon)
|
if (set_beacon)
|
||||||
ieee802_11_update_beacons(hapd->iface);
|
ieee802_11_update_beacons(hapd->iface);
|
||||||
|
|
||||||
ubus_resp = hostapd_ubus_handle_event(hapd, &req);
|
|
||||||
if (ubus_resp) {
|
|
||||||
wpa_printf(MSG_DEBUG, "Station " MACSTR " assoc rejected by ubus handler.\n",
|
|
||||||
MAC2STR(mgmt->sa));
|
|
||||||
resp = ubus_resp > 0 ? (u16) ubus_resp : WLAN_STATUS_UNSPECIFIED_FAILURE;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -5931,7 +5930,6 @@ static void handle_disassoc(struct hostapd_data *hapd,
|
||||||
(unsigned long) len);
|
(unsigned long) len);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
hostapd_ubus_notify(hapd, "disassoc", mgmt->sa);
|
|
||||||
|
|
||||||
sta = ap_get_sta(hapd, mgmt->sa);
|
sta = ap_get_sta(hapd, mgmt->sa);
|
||||||
if (!sta) {
|
if (!sta) {
|
||||||
|
@ -5960,8 +5958,6 @@ static void handle_deauth(struct hostapd_data *hapd,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
hostapd_ubus_notify(hapd, "deauth", mgmt->sa);
|
|
||||||
|
|
||||||
/* Clear the PTKSA cache entries for PASN */
|
/* Clear the PTKSA cache entries for PASN */
|
||||||
ptksa_cache_flush(hapd->ptksa, mgmt->sa, WPA_CIPHER_NONE);
|
ptksa_cache_flush(hapd->ptksa, mgmt->sa, WPA_CIPHER_NONE);
|
||||||
|
|
||||||
|
@ -7251,16 +7247,11 @@ u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid)
|
/* Wide Bandwidth Channel Switch subelement */
|
||||||
|
static u8 * hostapd_eid_wb_channel_switch(struct hostapd_data *hapd, u8 *eid,
|
||||||
|
u8 chan1, u8 chan2)
|
||||||
{
|
{
|
||||||
u8 bw, chan1 = 0, chan2 = 0;
|
u8 bw;
|
||||||
int freq1;
|
|
||||||
|
|
||||||
if (!hapd->cs_freq_params.channel ||
|
|
||||||
(!hapd->cs_freq_params.vht_enabled &&
|
|
||||||
!hapd->cs_freq_params.he_enabled &&
|
|
||||||
!hapd->cs_freq_params.eht_enabled))
|
|
||||||
return eid;
|
|
||||||
|
|
||||||
/* bandwidth: 0: 40, 1: 80, 160, 80+80, 4: 320 as per
|
/* bandwidth: 0: 40, 1: 80, 160, 80+80, 4: 320 as per
|
||||||
* IEEE P802.11-REVme/D4.0, 9.4.2.159 and Table 9-314. */
|
* IEEE P802.11-REVme/D4.0, 9.4.2.159 and Table 9-314. */
|
||||||
|
@ -7282,20 +7273,6 @@ u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid)
|
||||||
return eid;
|
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_CHANNEL_SWITCH_WRAPPER;
|
|
||||||
*eid++ = 5; /* Length of Channel Switch Wrapper */
|
|
||||||
*eid++ = WLAN_EID_WIDE_BW_CHSWITCH;
|
*eid++ = WLAN_EID_WIDE_BW_CHSWITCH;
|
||||||
*eid++ = 3; /* Length of Wide Bandwidth Channel Switch element */
|
*eid++ = 3; /* Length of Wide Bandwidth Channel Switch element */
|
||||||
*eid++ = bw; /* New Channel Width */
|
*eid++ = bw; /* New Channel Width */
|
||||||
|
@ -7321,6 +7298,118 @@ u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
/* Bandwidth Indication element that is also used as the Bandwidth Indication
|
||||||
|
* For Channel Switch subelement within a Channel Switch Wrapper element. */
|
||||||
|
static u8 * hostapd_eid_bw_indication(struct hostapd_data *hapd, u8 *eid,
|
||||||
|
u8 chan1, u8 chan2)
|
||||||
|
{
|
||||||
|
u16 punct_bitmap = hostapd_get_punct_bitmap(hapd);
|
||||||
|
struct ieee80211_bw_ind_element *bw_ind_elem;
|
||||||
|
size_t elen = 3;
|
||||||
|
|
||||||
|
if (hapd->cs_freq_params.bandwidth <= 160 && !punct_bitmap)
|
||||||
|
return eid;
|
||||||
|
|
||||||
|
if (punct_bitmap)
|
||||||
|
elen += EHT_OPER_DISABLED_SUBCHAN_BITMAP_SIZE;
|
||||||
|
|
||||||
|
*eid++ = WLAN_EID_EXTENSION;
|
||||||
|
*eid++ = 1 + elen;
|
||||||
|
*eid++ = WLAN_EID_EXT_BANDWIDTH_INDICATION;
|
||||||
|
|
||||||
|
bw_ind_elem = (struct ieee80211_bw_ind_element *) eid;
|
||||||
|
os_memset(bw_ind_elem, 0, sizeof(struct ieee80211_bw_ind_element));
|
||||||
|
|
||||||
|
switch (hapd->cs_freq_params.bandwidth) {
|
||||||
|
case 320:
|
||||||
|
bw_ind_elem->bw_ind_info.control |= BW_IND_CHANNEL_WIDTH_320MHZ;
|
||||||
|
chan2 = chan1;
|
||||||
|
if (hapd->cs_freq_params.channel < chan1)
|
||||||
|
chan1 -= 16;
|
||||||
|
else
|
||||||
|
chan1 += 16;
|
||||||
|
break;
|
||||||
|
case 160:
|
||||||
|
bw_ind_elem->bw_ind_info.control |= BW_IND_CHANNEL_WIDTH_160MHZ;
|
||||||
|
chan2 = chan1;
|
||||||
|
if (hapd->cs_freq_params.channel < chan1)
|
||||||
|
chan1 -= 8;
|
||||||
|
else
|
||||||
|
chan1 += 8;
|
||||||
|
break;
|
||||||
|
case 80:
|
||||||
|
bw_ind_elem->bw_ind_info.control |= BW_IND_CHANNEL_WIDTH_80MHZ;
|
||||||
|
break;
|
||||||
|
case 40:
|
||||||
|
if (hapd->cs_freq_params.sec_channel_offset == 1)
|
||||||
|
bw_ind_elem->bw_ind_info.control |=
|
||||||
|
BW_IND_CHANNEL_WIDTH_40MHZ;
|
||||||
|
else
|
||||||
|
bw_ind_elem->bw_ind_info.control |=
|
||||||
|
BW_IND_CHANNEL_WIDTH_20MHZ;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
bw_ind_elem->bw_ind_info.control |= BW_IND_CHANNEL_WIDTH_20MHZ;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bw_ind_elem->bw_ind_info.ccfs0 = chan1;
|
||||||
|
bw_ind_elem->bw_ind_info.ccfs1 = chan2;
|
||||||
|
|
||||||
|
if (punct_bitmap) {
|
||||||
|
bw_ind_elem->bw_ind_params |=
|
||||||
|
BW_IND_PARAMETER_DISABLED_SUBCHAN_BITMAP_PRESENT;
|
||||||
|
bw_ind_elem->bw_ind_info.disabled_chan_bitmap =
|
||||||
|
host_to_le16(punct_bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
return eid + elen;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
|
|
||||||
|
u8 * hostapd_eid_chsw_wrapper(struct hostapd_data *hapd, u8 *eid)
|
||||||
|
{
|
||||||
|
u8 chan1 = 0, chan2 = 0;
|
||||||
|
u8 *eid_len_offset;
|
||||||
|
int freq1;
|
||||||
|
|
||||||
|
if (!hapd->cs_freq_params.channel ||
|
||||||
|
(!hapd->cs_freq_params.vht_enabled &&
|
||||||
|
!hapd->cs_freq_params.he_enabled &&
|
||||||
|
!hapd->cs_freq_params.eht_enabled))
|
||||||
|
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_CHANNEL_SWITCH_WRAPPER;
|
||||||
|
eid_len_offset = eid++; /* Length of Channel Switch Wrapper element */
|
||||||
|
|
||||||
|
eid = hostapd_eid_wb_channel_switch(hapd, eid, chan1, chan2);
|
||||||
|
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) {
|
||||||
|
/* Bandwidth Indication For Channel Switch subelement */
|
||||||
|
eid = hostapd_eid_bw_indication(hapd, eid, chan1, chan2);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
|
*eid_len_offset = (eid - eid_len_offset) - 1;
|
||||||
|
return eid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static size_t hostapd_eid_nr_db_len(struct hostapd_data *hapd,
|
static size_t hostapd_eid_nr_db_len(struct hostapd_data *hapd,
|
||||||
size_t *current_len)
|
size_t *current_len)
|
||||||
{
|
{
|
||||||
|
|
|
@ -63,7 +63,7 @@ u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid);
|
||||||
u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid, u32 nsts);
|
u8 * hostapd_eid_vht_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);
|
||||||
u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid);
|
u8 * hostapd_eid_chsw_wrapper(struct hostapd_data *hapd, u8 *eid);
|
||||||
u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid);
|
u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid);
|
||||||
u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
|
u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
|
||||||
enum ieee80211_op_mode opmode);
|
enum ieee80211_op_mode opmode);
|
||||||
|
|
|
@ -871,6 +871,8 @@ sae_commit_skip_fixed_fields(const struct ieee80211_mgmt *mgmt, size_t len,
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "EHT: SAE scalar length is %zu", prime_len);
|
wpa_printf(MSG_DEBUG, "EHT: SAE scalar length is %zu", prime_len);
|
||||||
|
|
||||||
|
if (len - 2 < prime_len * (ec ? 3 : 2))
|
||||||
|
goto truncated;
|
||||||
/* scalar */
|
/* scalar */
|
||||||
pos += prime_len;
|
pos += prime_len;
|
||||||
|
|
||||||
|
@ -882,6 +884,7 @@ sae_commit_skip_fixed_fields(const struct ieee80211_mgmt *mgmt, size_t len,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pos - mgmt->u.auth.variable > (int) len) {
|
if (pos - mgmt->u.auth.variable > (int) len) {
|
||||||
|
truncated:
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"EHT: Too short SAE commit Authentication frame");
|
"EHT: Too short SAE commit Authentication frame");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -905,16 +908,38 @@ sae_confirm_skip_fixed_fields(struct hostapd_data *hapd,
|
||||||
return pos;
|
return pos;
|
||||||
|
|
||||||
/* send confirm integer */
|
/* send confirm integer */
|
||||||
|
if (len < 2)
|
||||||
|
goto truncated;
|
||||||
pos += 2;
|
pos += 2;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* At this stage we should already have an MLD station and actually SA
|
* At this stage we should already have an MLD station and actually SA
|
||||||
* will be replaced with the MLD MAC address by the driver.
|
* will be replaced with the MLD MAC address by the driver. However,
|
||||||
|
* there is at least a theoretical race condition in a case where the
|
||||||
|
* peer sends the SAE confirm message quickly enough for the driver
|
||||||
|
* translation mechanism to not be available to update the SAE confirm
|
||||||
|
* message addresses. Work around that by searching for the STA entry
|
||||||
|
* using the link address of the non-AP MLD if no match is found based
|
||||||
|
* on the MLD MAC address.
|
||||||
*/
|
*/
|
||||||
sta = ap_get_sta(hapd, mgmt->sa);
|
sta = ap_get_sta(hapd, mgmt->sa);
|
||||||
if (!sta) {
|
if (!sta) {
|
||||||
wpa_printf(MSG_DEBUG, "SAE: No MLD STA for SAE confirm");
|
wpa_printf(MSG_DEBUG, "SAE: No MLD STA for SAE confirm");
|
||||||
return NULL;
|
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
||||||
|
int link_id = hapd->mld_link_id;
|
||||||
|
|
||||||
|
if (!sta->mld_info.mld_sta ||
|
||||||
|
sta->mld_info.links[link_id].valid ||
|
||||||
|
!ether_addr_equal(
|
||||||
|
mgmt->sa,
|
||||||
|
sta->mld_info.links[link_id].peer_addr))
|
||||||
|
continue;
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"SAE: Found MLD STA for SAE confirm based on link address");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!sta)
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sta->sae || sta->sae->state < SAE_COMMITTED || !sta->sae->tmp) {
|
if (!sta->sae || sta->sae->state < SAE_COMMITTED || !sta->sae->tmp) {
|
||||||
|
@ -929,9 +954,12 @@ sae_confirm_skip_fixed_fields(struct hostapd_data *hapd,
|
||||||
wpa_printf(MSG_DEBUG, "SAE: confirm: kck_len=%zu",
|
wpa_printf(MSG_DEBUG, "SAE: confirm: kck_len=%zu",
|
||||||
sta->sae->tmp->kck_len);
|
sta->sae->tmp->kck_len);
|
||||||
|
|
||||||
|
if (len - 2 < sta->sae->tmp->kck_len)
|
||||||
|
goto truncated;
|
||||||
pos += sta->sae->tmp->kck_len;
|
pos += sta->sae->tmp->kck_len;
|
||||||
|
|
||||||
if (pos - mgmt->u.auth.variable > (int) len) {
|
if (pos - mgmt->u.auth.variable > (int) len) {
|
||||||
|
truncated:
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"EHT: Too short SAE confirm Authentication frame");
|
"EHT: Too short SAE confirm Authentication frame");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -79,6 +79,51 @@ u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void set_ht_param(struct hostapd_data *hapd,
|
||||||
|
struct ieee80211_ht_operation *oper)
|
||||||
|
{
|
||||||
|
int secondary_channel = hapd->iconf->secondary_channel;
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
enum oper_chan_width chwidth = hostapd_get_oper_chwidth(hapd->iconf);
|
||||||
|
u16 bw = 0, punct_bitmap = hostapd_get_punct_bitmap(hapd);
|
||||||
|
u8 offset, chan_bit_pos;
|
||||||
|
|
||||||
|
switch (chwidth) {
|
||||||
|
case CONF_OPER_CHWIDTH_80MHZ:
|
||||||
|
bw = 80;
|
||||||
|
offset = 6;
|
||||||
|
break;
|
||||||
|
case CONF_OPER_CHWIDTH_160MHZ:
|
||||||
|
bw = 160;
|
||||||
|
offset = 14;
|
||||||
|
break;
|
||||||
|
case CONF_OPER_CHWIDTH_320MHZ:
|
||||||
|
bw = 320;
|
||||||
|
offset = 30;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto no_update;
|
||||||
|
}
|
||||||
|
|
||||||
|
chan_bit_pos = (hapd->iconf->channel -
|
||||||
|
hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf) +
|
||||||
|
offset) / 4;
|
||||||
|
/* Check if secondary channel is punctured */
|
||||||
|
if (bw >= 80 && punct_bitmap && secondary_channel &&
|
||||||
|
(punct_bitmap & BIT(chan_bit_pos + secondary_channel)))
|
||||||
|
return; /* Do not indicate punctured secondary channel for HT */
|
||||||
|
no_update:
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
|
if (secondary_channel == 1)
|
||||||
|
oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE |
|
||||||
|
HT_INFO_HT_PARAM_STA_CHNL_WIDTH;
|
||||||
|
if (secondary_channel == -1)
|
||||||
|
oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW |
|
||||||
|
HT_INFO_HT_PARAM_STA_CHNL_WIDTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid)
|
u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid)
|
||||||
{
|
{
|
||||||
struct ieee80211_ht_operation *oper;
|
struct ieee80211_ht_operation *oper;
|
||||||
|
@ -96,12 +141,7 @@ u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid)
|
||||||
|
|
||||||
oper->primary_chan = hapd->iconf->channel;
|
oper->primary_chan = hapd->iconf->channel;
|
||||||
oper->operation_mode = host_to_le16(hapd->iface->ht_op_mode);
|
oper->operation_mode = host_to_le16(hapd->iface->ht_op_mode);
|
||||||
if (hapd->iconf->secondary_channel == 1)
|
set_ht_param(hapd, oper);
|
||||||
oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE |
|
|
||||||
HT_INFO_HT_PARAM_STA_CHNL_WIDTH;
|
|
||||||
if (hapd->iconf->secondary_channel == -1)
|
|
||||||
oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW |
|
|
||||||
HT_INFO_HT_PARAM_STA_CHNL_WIDTH;
|
|
||||||
|
|
||||||
pos += sizeof(*oper);
|
pos += sizeof(*oper);
|
||||||
|
|
||||||
|
|
|
@ -158,7 +158,7 @@ int hostapd_nan_usd_init(struct hostapd_data *hapd)
|
||||||
cb.subscribe_terminated = hostapd_nan_de_subscribe_terminated;
|
cb.subscribe_terminated = hostapd_nan_de_subscribe_terminated;
|
||||||
cb.receive = hostapd_nan_de_receive;
|
cb.receive = hostapd_nan_de_receive;
|
||||||
|
|
||||||
hapd->nan_de = nan_de_init(hapd->own_addr, true, &cb);
|
hapd->nan_de = nan_de_init(hapd->own_addr, false, true, &cb);
|
||||||
if (!hapd->nan_de)
|
if (!hapd->nan_de)
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -192,7 +192,7 @@ void hostapd_nan_usd_flush(struct hostapd_data *hapd)
|
||||||
int hostapd_nan_usd_publish(struct hostapd_data *hapd, const char *service_name,
|
int hostapd_nan_usd_publish(struct hostapd_data *hapd, const char *service_name,
|
||||||
enum nan_service_protocol_type srv_proto_type,
|
enum nan_service_protocol_type srv_proto_type,
|
||||||
const struct wpabuf *ssi,
|
const struct wpabuf *ssi,
|
||||||
struct nan_publish_params *params)
|
struct nan_publish_params *params, bool p2p)
|
||||||
{
|
{
|
||||||
int publish_id;
|
int publish_id;
|
||||||
struct wpabuf *elems = NULL;
|
struct wpabuf *elems = NULL;
|
||||||
|
@ -201,7 +201,7 @@ int hostapd_nan_usd_publish(struct hostapd_data *hapd, const char *service_name,
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
publish_id = nan_de_publish(hapd->nan_de, service_name, srv_proto_type,
|
publish_id = nan_de_publish(hapd->nan_de, service_name, srv_proto_type,
|
||||||
ssi, elems, params);
|
ssi, elems, params, p2p);
|
||||||
wpabuf_free(elems);
|
wpabuf_free(elems);
|
||||||
return publish_id;
|
return publish_id;
|
||||||
}
|
}
|
||||||
|
@ -231,7 +231,7 @@ int hostapd_nan_usd_subscribe(struct hostapd_data *hapd,
|
||||||
const char *service_name,
|
const char *service_name,
|
||||||
enum nan_service_protocol_type srv_proto_type,
|
enum nan_service_protocol_type srv_proto_type,
|
||||||
const struct wpabuf *ssi,
|
const struct wpabuf *ssi,
|
||||||
struct nan_subscribe_params *params)
|
struct nan_subscribe_params *params, bool p2p)
|
||||||
{
|
{
|
||||||
int subscribe_id;
|
int subscribe_id;
|
||||||
struct wpabuf *elems = NULL;
|
struct wpabuf *elems = NULL;
|
||||||
|
@ -240,7 +240,7 @@ int hostapd_nan_usd_subscribe(struct hostapd_data *hapd,
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
subscribe_id = nan_de_subscribe(hapd->nan_de, service_name,
|
subscribe_id = nan_de_subscribe(hapd->nan_de, service_name,
|
||||||
srv_proto_type, ssi, elems, params);
|
srv_proto_type, ssi, elems, params, p2p);
|
||||||
wpabuf_free(elems);
|
wpabuf_free(elems);
|
||||||
return subscribe_id;
|
return subscribe_id;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ void hostapd_nan_usd_flush(struct hostapd_data *hapd);
|
||||||
int hostapd_nan_usd_publish(struct hostapd_data *hapd, const char *service_name,
|
int hostapd_nan_usd_publish(struct hostapd_data *hapd, const char *service_name,
|
||||||
enum nan_service_protocol_type srv_proto_type,
|
enum nan_service_protocol_type srv_proto_type,
|
||||||
const struct wpabuf *ssi,
|
const struct wpabuf *ssi,
|
||||||
struct nan_publish_params *params);
|
struct nan_publish_params *params, bool p2p);
|
||||||
void hostapd_nan_usd_cancel_publish(struct hostapd_data *hapd, int publish_id);
|
void hostapd_nan_usd_cancel_publish(struct hostapd_data *hapd, int publish_id);
|
||||||
int hostapd_nan_usd_update_publish(struct hostapd_data *hapd, int publish_id,
|
int hostapd_nan_usd_update_publish(struct hostapd_data *hapd, int publish_id,
|
||||||
const struct wpabuf *ssi);
|
const struct wpabuf *ssi);
|
||||||
|
@ -29,7 +29,7 @@ int hostapd_nan_usd_subscribe(struct hostapd_data *hapd,
|
||||||
const char *service_name,
|
const char *service_name,
|
||||||
enum nan_service_protocol_type srv_proto_type,
|
enum nan_service_protocol_type srv_proto_type,
|
||||||
const struct wpabuf *ssi,
|
const struct wpabuf *ssi,
|
||||||
struct nan_subscribe_params *params);
|
struct nan_subscribe_params *params, bool p2p);
|
||||||
void hostapd_nan_usd_cancel_subscribe(struct hostapd_data *hapd,
|
void hostapd_nan_usd_cancel_subscribe(struct hostapd_data *hapd,
|
||||||
int subscribe_id);
|
int subscribe_id);
|
||||||
int hostapd_nan_usd_transmit(struct hostapd_data *hapd, int handle,
|
int hostapd_nan_usd_transmit(struct hostapd_data *hapd, int handle,
|
||||||
|
|
|
@ -89,9 +89,6 @@ static void hostapd_handle_beacon_report(struct hostapd_data *hapd,
|
||||||
return;
|
return;
|
||||||
wpa_msg(hapd->msg_ctx, MSG_INFO, BEACON_RESP_RX MACSTR " %u %02x %s",
|
wpa_msg(hapd->msg_ctx, MSG_INFO, BEACON_RESP_RX MACSTR " %u %02x %s",
|
||||||
MAC2STR(addr), token, rep_mode, report);
|
MAC2STR(addr), token, rep_mode, report);
|
||||||
if (len < sizeof(struct rrm_measurement_beacon_report))
|
|
||||||
return;
|
|
||||||
hostapd_ubus_notify_beacon_report(hapd, addr, token, rep_mode, (struct rrm_measurement_beacon_report*) pos, len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -272,7 +269,6 @@ static void hostapd_send_nei_report_resp(struct hostapd_data *hapd,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hapd->liminix_stats.rrm.neighbor_report_tx++;
|
|
||||||
hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
|
hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
|
||||||
wpabuf_head(buf), wpabuf_len(buf));
|
wpabuf_head(buf), wpabuf_len(buf));
|
||||||
wpabuf_free(buf);
|
wpabuf_free(buf);
|
||||||
|
@ -408,7 +404,6 @@ void hostapd_handle_radio_measurement(struct hostapd_data *hapd,
|
||||||
hostapd_handle_nei_report_req(hapd, buf, len);
|
hostapd_handle_nei_report_req(hapd, buf, len);
|
||||||
break;
|
break;
|
||||||
case WLAN_RRM_LINK_MEASUREMENT_REPORT:
|
case WLAN_RRM_LINK_MEASUREMENT_REPORT:
|
||||||
hostapd_ubus_handle_link_measurement(hapd, buf, len);
|
|
||||||
hostapd_handle_link_mesr_report(hapd, buf, len);
|
hostapd_handle_link_mesr_report(hapd, buf, len);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -542,7 +542,6 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
|
||||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||||
HOSTAPD_LEVEL_INFO, "deauthenticated due to "
|
HOSTAPD_LEVEL_INFO, "deauthenticated due to "
|
||||||
"local deauth request");
|
"local deauth request");
|
||||||
hostapd_ubus_notify(hapd, "local-deauth", sta->addr);
|
|
||||||
ap_free_sta(hapd, sta);
|
ap_free_sta(hapd, sta);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -700,7 +699,6 @@ skip_poll:
|
||||||
mlme_deauthenticate_indication(
|
mlme_deauthenticate_indication(
|
||||||
hapd, sta,
|
hapd, sta,
|
||||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||||
hostapd_ubus_notify(hapd, "inactive-deauth", sta->addr);
|
|
||||||
ap_free_sta(hapd, sta);
|
ap_free_sta(hapd, sta);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1526,28 +1524,15 @@ void ap_sta_set_authorized_event(struct hostapd_data *hapd,
|
||||||
os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(sta->addr));
|
os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(sta->addr));
|
||||||
|
|
||||||
if (authorized) {
|
if (authorized) {
|
||||||
static const char * const auth_algs[] = {
|
|
||||||
[WLAN_AUTH_OPEN] = "open",
|
|
||||||
[WLAN_AUTH_SHARED_KEY] = "shared",
|
|
||||||
[WLAN_AUTH_FT] = "ft",
|
|
||||||
[WLAN_AUTH_SAE] = "sae",
|
|
||||||
[WLAN_AUTH_FILS_SK] = "fils-sk",
|
|
||||||
[WLAN_AUTH_FILS_SK_PFS] = "fils-sk-pfs",
|
|
||||||
[WLAN_AUTH_FILS_PK] = "fils-pk",
|
|
||||||
[WLAN_AUTH_PASN] = "pasn",
|
|
||||||
};
|
|
||||||
const char *auth_alg = NULL;
|
|
||||||
const u8 *dpp_pkhash;
|
const u8 *dpp_pkhash;
|
||||||
const char *keyid;
|
const char *keyid;
|
||||||
char dpp_pkhash_buf[100];
|
char dpp_pkhash_buf[100];
|
||||||
char keyid_buf[100];
|
char keyid_buf[100];
|
||||||
char ip_addr[100];
|
char ip_addr[100];
|
||||||
char alg_buf[100];
|
|
||||||
|
|
||||||
dpp_pkhash_buf[0] = '\0';
|
dpp_pkhash_buf[0] = '\0';
|
||||||
keyid_buf[0] = '\0';
|
keyid_buf[0] = '\0';
|
||||||
ip_addr[0] = '\0';
|
ip_addr[0] = '\0';
|
||||||
alg_buf[0] = '\0';
|
|
||||||
#ifdef CONFIG_P2P
|
#ifdef CONFIG_P2P
|
||||||
if (wpa_auth_get_ip_addr(sta->wpa_sm, ip_addr_buf) == 0) {
|
if (wpa_auth_get_ip_addr(sta->wpa_sm, ip_addr_buf) == 0) {
|
||||||
os_snprintf(ip_addr, sizeof(ip_addr),
|
os_snprintf(ip_addr, sizeof(ip_addr),
|
||||||
|
@ -1558,13 +1543,6 @@ void ap_sta_set_authorized_event(struct hostapd_data *hapd,
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_P2P */
|
#endif /* CONFIG_P2P */
|
||||||
|
|
||||||
if (sta->auth_alg < ARRAY_SIZE(auth_algs))
|
|
||||||
auth_alg = auth_algs[sta->auth_alg];
|
|
||||||
|
|
||||||
if (auth_alg)
|
|
||||||
os_snprintf(alg_buf, sizeof(alg_buf),
|
|
||||||
" auth_alg=%s", auth_alg);
|
|
||||||
|
|
||||||
keyid = ap_sta_wpa_get_keyid(hapd, sta);
|
keyid = ap_sta_wpa_get_keyid(hapd, sta);
|
||||||
if (keyid) {
|
if (keyid) {
|
||||||
os_snprintf(keyid_buf, sizeof(keyid_buf),
|
os_snprintf(keyid_buf, sizeof(keyid_buf),
|
||||||
|
@ -1583,19 +1561,17 @@ void ap_sta_set_authorized_event(struct hostapd_data *hapd,
|
||||||
dpp_pkhash, SHA256_MAC_LEN);
|
dpp_pkhash, SHA256_MAC_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
hostapd_ubus_notify_authorized(hapd, sta, auth_alg);
|
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s%s%s",
|
||||||
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s%s%s%s",
|
buf, ip_addr, keyid_buf, dpp_pkhash_buf);
|
||||||
buf, ip_addr, keyid_buf, dpp_pkhash_buf, alg_buf);
|
|
||||||
|
|
||||||
if (hapd->msg_ctx_parent &&
|
if (hapd->msg_ctx_parent &&
|
||||||
hapd->msg_ctx_parent != hapd->msg_ctx)
|
hapd->msg_ctx_parent != hapd->msg_ctx)
|
||||||
wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO,
|
wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO,
|
||||||
AP_STA_CONNECTED "%s%s%s%s%s",
|
AP_STA_CONNECTED "%s%s%s%s",
|
||||||
buf, ip_addr, keyid_buf,
|
buf, ip_addr, keyid_buf,
|
||||||
dpp_pkhash_buf, alg_buf);
|
dpp_pkhash_buf);
|
||||||
} else {
|
} else {
|
||||||
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf);
|
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf);
|
||||||
hostapd_ubus_notify(hapd, "disassoc", sta->addr);
|
|
||||||
|
|
||||||
if (hapd->msg_ctx_parent &&
|
if (hapd->msg_ctx_parent &&
|
||||||
hapd->msg_ctx_parent != hapd->msg_ctx)
|
hapd->msg_ctx_parent != hapd->msg_ctx)
|
||||||
|
|
|
@ -81,20 +81,7 @@ struct mld_info {
|
||||||
u16 mld_capa;
|
u16 mld_capa;
|
||||||
} common_info;
|
} common_info;
|
||||||
|
|
||||||
struct mld_link_info {
|
struct mld_link_info links[MAX_NUM_MLD_LINKS];
|
||||||
u8 valid:1;
|
|
||||||
u8 nstr_bitmap_len:2;
|
|
||||||
u8 local_addr[ETH_ALEN];
|
|
||||||
u8 peer_addr[ETH_ALEN];
|
|
||||||
|
|
||||||
u8 nstr_bitmap[2];
|
|
||||||
|
|
||||||
u16 capability;
|
|
||||||
|
|
||||||
u16 status;
|
|
||||||
u16 resp_sta_profile_len;
|
|
||||||
u8 *resp_sta_profile;
|
|
||||||
} links[MAX_NUM_MLD_LINKS];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sta_info {
|
struct sta_info {
|
||||||
|
@ -321,7 +308,6 @@ struct sta_info {
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
#ifdef CONFIG_AIRTIME_POLICY
|
#ifdef CONFIG_AIRTIME_POLICY
|
||||||
unsigned int airtime_weight;
|
unsigned int airtime_weight;
|
||||||
unsigned int dyn_airtime_weight;
|
|
||||||
struct os_reltime backlogged_until;
|
struct os_reltime backlogged_until;
|
||||||
#endif /* CONFIG_AIRTIME_POLICY */
|
#endif /* CONFIG_AIRTIME_POLICY */
|
||||||
|
|
||||||
|
|
2010
src/ap/ubus.c
2010
src/ap/ubus.c
File diff suppressed because it is too large
Load diff
162
src/ap/ubus.h
162
src/ap/ubus.h
|
@ -1,162 +0,0 @@
|
||||||
/*
|
|
||||||
* hostapd / ubus support
|
|
||||||
* Copyright (c) 2013, Felix Fietkau <nbd@nbd.name>
|
|
||||||
*
|
|
||||||
* This software may be distributed under the terms of the BSD license.
|
|
||||||
* See README for more details.
|
|
||||||
*/
|
|
||||||
#ifndef __HOSTAPD_UBUS_H
|
|
||||||
#define __HOSTAPD_UBUS_H
|
|
||||||
|
|
||||||
#include "sta_info.h"
|
|
||||||
|
|
||||||
enum hostapd_ubus_event_type {
|
|
||||||
HOSTAPD_UBUS_PROBE_REQ,
|
|
||||||
HOSTAPD_UBUS_AUTH_REQ,
|
|
||||||
HOSTAPD_UBUS_ASSOC_REQ,
|
|
||||||
HOSTAPD_UBUS_TYPE_MAX
|
|
||||||
};
|
|
||||||
|
|
||||||
struct hostapd_ubus_request {
|
|
||||||
enum hostapd_ubus_event_type type;
|
|
||||||
const struct ieee80211_mgmt *mgmt_frame;
|
|
||||||
const struct ieee802_11_elems *elems;
|
|
||||||
int ssi_signal; /* dBm */
|
|
||||||
const u8 *addr;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct hostapd_iface;
|
|
||||||
struct hostapd_data;
|
|
||||||
struct hapd_interfaces;
|
|
||||||
struct rrm_measurement_beacon_report;
|
|
||||||
struct sta_info;
|
|
||||||
|
|
||||||
#ifdef UBUS_SUPPORT
|
|
||||||
|
|
||||||
#include <libubox/avl.h>
|
|
||||||
#include <libubus.h>
|
|
||||||
|
|
||||||
struct hostapd_ubus_bss {
|
|
||||||
struct ubus_object obj;
|
|
||||||
struct avl_tree banned;
|
|
||||||
int notify_response;
|
|
||||||
};
|
|
||||||
|
|
||||||
void hostapd_ubus_add_iface(struct hostapd_iface *iface);
|
|
||||||
void hostapd_ubus_free_iface(struct hostapd_iface *iface);
|
|
||||||
void hostapd_ubus_add_bss(struct hostapd_data *hapd);
|
|
||||||
void hostapd_ubus_free_bss(struct hostapd_data *hapd);
|
|
||||||
void hostapd_ubus_add_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vlan);
|
|
||||||
void hostapd_ubus_remove_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vlan);
|
|
||||||
|
|
||||||
int hostapd_ubus_handle_event(struct hostapd_data *hapd, struct hostapd_ubus_request *req);
|
|
||||||
void hostapd_ubus_handle_link_measurement(struct hostapd_data *hapd, const u8 *data, size_t len);
|
|
||||||
void hostapd_ubus_notify(struct hostapd_data *hapd, const char *type, const u8 *mac);
|
|
||||||
void hostapd_ubus_notify_beacon_report(struct hostapd_data *hapd,
|
|
||||||
const u8 *addr, u8 token, u8 rep_mode,
|
|
||||||
struct rrm_measurement_beacon_report *rep,
|
|
||||||
size_t len);
|
|
||||||
void hostapd_ubus_notify_radar_detected(struct hostapd_iface *iface, int frequency,
|
|
||||||
int chan_width, int cf1, int cf2);
|
|
||||||
|
|
||||||
void hostapd_ubus_notify_bss_transition_response(
|
|
||||||
struct hostapd_data *hapd, const u8 *addr, u8 dialog_token, u8 status_code,
|
|
||||||
u8 bss_termination_delay, const u8 *target_bssid,
|
|
||||||
const u8 *candidate_list, u16 candidate_list_len);
|
|
||||||
void hostapd_ubus_add(struct hapd_interfaces *interfaces);
|
|
||||||
void hostapd_ubus_free(struct hapd_interfaces *interfaces);
|
|
||||||
int hostapd_ubus_notify_bss_transition_query(
|
|
||||||
struct hostapd_data *hapd, const u8 *addr, u8 dialog_token, u8 reason,
|
|
||||||
const u8 *candidate_list, u16 candidate_list_len);
|
|
||||||
void hostapd_ubus_notify_authorized(struct hostapd_data *hapd, struct sta_info *sta,
|
|
||||||
const char *auth_alg);
|
|
||||||
void hostapd_ubus_notify_readiness(struct hostapd_data *hapd);
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
struct hostapd_ubus_bss {};
|
|
||||||
|
|
||||||
static inline void hostapd_ubus_add_iface(struct hostapd_iface *iface)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void hostapd_ubus_free_iface(struct hostapd_iface *iface)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void hostapd_ubus_add_bss(struct hostapd_data *hapd)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void hostapd_ubus_free_bss(struct hostapd_data *hapd)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void hostapd_ubus_add_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vlan)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void hostapd_ubus_remove_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vlan)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int hostapd_ubus_handle_event(struct hostapd_data *hapd, struct hostapd_ubus_request *req)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void hostapd_ubus_handle_link_measurement(struct hostapd_data *hapd, const u8 *data, size_t len)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void hostapd_ubus_notify(struct hostapd_data *hapd, const char *type, const u8 *mac)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void hostapd_ubus_notify_readiness(struct hostapd_data *hapd)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void hostapd_ubus_notify_beacon_report(struct hostapd_data *hapd,
|
|
||||||
const u8 *addr, u8 token,
|
|
||||||
u8 rep_mode,
|
|
||||||
struct rrm_measurement_beacon_report *rep,
|
|
||||||
size_t len)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
static inline void hostapd_ubus_notify_radar_detected(struct hostapd_iface *iface, int frequency,
|
|
||||||
int chan_width, int cf1, int cf2)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void hostapd_ubus_notify_bss_transition_response(
|
|
||||||
struct hostapd_data *hapd, const u8 *addr, u8 dialog_token, u8 status_code,
|
|
||||||
u8 bss_termination_delay, const u8 *target_bssid,
|
|
||||||
const u8 *candidate_list, u16 candidate_list_len)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void hostapd_ubus_add(struct hapd_interfaces *interfaces)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void hostapd_ubus_free(struct hapd_interfaces *interfaces)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int hostapd_ubus_notify_bss_transition_query(
|
|
||||||
struct hostapd_data *hapd, const u8 *addr, u8 dialog_token, u8 reason,
|
|
||||||
const u8 *candidate_list, u16 candidate_list_len)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
hostapd_ubus_notify_authorized(struct hostapd_data *hapd, struct sta_info *sta,
|
|
||||||
const char *auth_alg)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -22,7 +22,6 @@
|
||||||
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)
|
||||||
{
|
{
|
||||||
bool vlan_exists = iface_exists(vlan->ifname);
|
|
||||||
int ret;
|
int ret;
|
||||||
#ifdef CONFIG_WEP
|
#ifdef CONFIG_WEP
|
||||||
int i;
|
int i;
|
||||||
|
@ -37,7 +36,7 @@ static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_WEP */
|
#endif /* CONFIG_WEP */
|
||||||
|
|
||||||
if (!vlan_exists)
|
if (!iface_exists(vlan->ifname))
|
||||||
ret = hostapd_vlan_if_add(hapd, vlan->ifname);
|
ret = hostapd_vlan_if_add(hapd, vlan->ifname);
|
||||||
else if (!existsok)
|
else if (!existsok)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -52,9 +51,6 @@ static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
|
||||||
if (hapd->wpa_auth)
|
if (hapd->wpa_auth)
|
||||||
ret = wpa_auth_ensure_group(hapd->wpa_auth, vlan->vlan_id);
|
ret = wpa_auth_ensure_group(hapd->wpa_auth, vlan->vlan_id);
|
||||||
|
|
||||||
if (!ret && !vlan_exists)
|
|
||||||
hostapd_ubus_add_vlan(hapd, vlan);
|
|
||||||
|
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -81,8 +77,6 @@ int vlan_if_remove(struct hostapd_data *hapd, struct hostapd_vlan *vlan)
|
||||||
"WPA deinitialization for VLAN %d failed (%d)",
|
"WPA deinitialization for VLAN %d failed (%d)",
|
||||||
vlan->vlan_id, ret);
|
vlan->vlan_id, ret);
|
||||||
|
|
||||||
hostapd_ubus_remove_vlan(hapd, vlan);
|
|
||||||
|
|
||||||
return hostapd_vlan_if_remove(hapd, vlan->ifname);
|
return hostapd_vlan_if_remove(hapd, vlan->ifname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -410,7 +410,6 @@ static int ieee802_11_send_bss_trans_mgmt_request(struct hostapd_data *hapd,
|
||||||
mgmt->u.action.u.bss_tm_req.validity_interval = 1;
|
mgmt->u.action.u.bss_tm_req.validity_interval = 1;
|
||||||
pos = mgmt->u.action.u.bss_tm_req.variable;
|
pos = mgmt->u.action.u.bss_tm_req.variable;
|
||||||
|
|
||||||
hapd->liminix_stats.wnm.bss_transition_request_tx++;
|
|
||||||
wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request to "
|
wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request to "
|
||||||
MACSTR " dialog_token=%u req_mode=0x%x disassoc_timer=%u "
|
MACSTR " dialog_token=%u req_mode=0x%x disassoc_timer=%u "
|
||||||
"validity_interval=%u",
|
"validity_interval=%u",
|
||||||
|
@ -479,8 +478,7 @@ static void ieee802_11_rx_bss_trans_mgmt_query(struct hostapd_data *hapd,
|
||||||
MAC2STR(addr), reason, hex ? " neighbor=" : "", hex);
|
MAC2STR(addr), reason, hex ? " neighbor=" : "", hex);
|
||||||
os_free(hex);
|
os_free(hex);
|
||||||
|
|
||||||
if (!hostapd_ubus_notify_bss_transition_query(hapd, addr, dialog_token, reason, pos, end - pos))
|
ieee802_11_send_bss_trans_mgmt_request(hapd, addr, dialog_token);
|
||||||
ieee802_11_send_bss_trans_mgmt_request(hapd, addr, dialog_token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -502,7 +500,7 @@ static void ieee802_11_rx_bss_trans_mgmt_resp(struct hostapd_data *hapd,
|
||||||
size_t len)
|
size_t len)
|
||||||
{
|
{
|
||||||
u8 dialog_token, status_code, bss_termination_delay;
|
u8 dialog_token, status_code, bss_termination_delay;
|
||||||
const u8 *pos, *end, *target_bssid = NULL;
|
const u8 *pos, *end;
|
||||||
int enabled = hapd->conf->bss_transition;
|
int enabled = hapd->conf->bss_transition;
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
|
|
||||||
|
@ -549,7 +547,6 @@ static void ieee802_11_rx_bss_trans_mgmt_resp(struct hostapd_data *hapd,
|
||||||
wpa_printf(MSG_DEBUG, "WNM: not enough room for Target BSSID field");
|
wpa_printf(MSG_DEBUG, "WNM: not enough room for Target BSSID field");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
target_bssid = pos;
|
|
||||||
sta->agreed_to_steer = 1;
|
sta->agreed_to_steer = 1;
|
||||||
eloop_cancel_timeout(ap_sta_reset_steer_flag_timer, hapd, sta);
|
eloop_cancel_timeout(ap_sta_reset_steer_flag_timer, hapd, sta);
|
||||||
eloop_register_timeout(2, 0, ap_sta_reset_steer_flag_timer,
|
eloop_register_timeout(2, 0, ap_sta_reset_steer_flag_timer,
|
||||||
|
@ -569,10 +566,6 @@ static void ieee802_11_rx_bss_trans_mgmt_resp(struct hostapd_data *hapd,
|
||||||
MAC2STR(addr), status_code, bss_termination_delay);
|
MAC2STR(addr), status_code, bss_termination_delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
hostapd_ubus_notify_bss_transition_response(hapd, sta->addr, dialog_token,
|
|
||||||
status_code, bss_termination_delay,
|
|
||||||
target_bssid, pos, end - pos);
|
|
||||||
|
|
||||||
wpa_hexdump(MSG_DEBUG, "WNM: BSS Transition Candidate List Entries",
|
wpa_hexdump(MSG_DEBUG, "WNM: BSS Transition Candidate List Entries",
|
||||||
pos, end - pos);
|
pos, end - pos);
|
||||||
}
|
}
|
||||||
|
@ -821,12 +814,10 @@ int ieee802_11_rx_wnm_action_ap(struct hostapd_data *hapd,
|
||||||
plen);
|
plen);
|
||||||
return 0;
|
return 0;
|
||||||
case WNM_BSS_TRANS_MGMT_QUERY:
|
case WNM_BSS_TRANS_MGMT_QUERY:
|
||||||
hapd->liminix_stats.wnm.bss_transition_query_rx++;
|
|
||||||
ieee802_11_rx_bss_trans_mgmt_query(hapd, mgmt->sa, payload,
|
ieee802_11_rx_bss_trans_mgmt_query(hapd, mgmt->sa, payload,
|
||||||
plen);
|
plen);
|
||||||
return 0;
|
return 0;
|
||||||
case WNM_BSS_TRANS_MGMT_RESP:
|
case WNM_BSS_TRANS_MGMT_RESP:
|
||||||
hapd->liminix_stats.wnm.bss_transition_response_rx++;
|
|
||||||
ieee802_11_rx_bss_trans_mgmt_resp(hapd, mgmt->sa, payload,
|
ieee802_11_rx_bss_trans_mgmt_resp(hapd, mgmt->sa, payload,
|
||||||
plen);
|
plen);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -874,7 +865,6 @@ int wnm_send_disassoc_imminent(struct hostapd_data *hapd,
|
||||||
|
|
||||||
pos = mgmt->u.action.u.bss_tm_req.variable;
|
pos = mgmt->u.action.u.bss_tm_req.variable;
|
||||||
|
|
||||||
hapd->liminix_stats.wnm.bss_transition_request_tx++;
|
|
||||||
wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request frame to indicate imminent disassociation (disassoc_timer=%d) to "
|
wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request frame to indicate imminent disassociation (disassoc_timer=%d) to "
|
||||||
MACSTR, disassoc_timer, MAC2STR(sta->addr));
|
MACSTR, disassoc_timer, MAC2STR(sta->addr));
|
||||||
if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0, NULL, 0, 0) < 0) {
|
if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0, NULL, 0, 0) < 0) {
|
||||||
|
@ -957,7 +947,6 @@ int wnm_send_ess_disassoc_imminent(struct hostapd_data *hapd,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
hapd->liminix_stats.wnm.bss_transition_request_tx++;
|
|
||||||
if (disassoc_timer) {
|
if (disassoc_timer) {
|
||||||
/* send disassociation frame after time-out */
|
/* send disassociation frame after time-out */
|
||||||
set_disassoc_timer(hapd, sta, disassoc_timer);
|
set_disassoc_timer(hapd, sta, disassoc_timer);
|
||||||
|
@ -1039,7 +1028,6 @@ int wnm_send_bss_tm_req(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
}
|
}
|
||||||
os_free(buf);
|
os_free(buf);
|
||||||
|
|
||||||
hapd->liminix_stats.wnm.bss_transition_request_tx++;
|
|
||||||
if (disassoc_timer) {
|
if (disassoc_timer) {
|
||||||
#ifdef CONFIG_IEEE80211BE
|
#ifdef CONFIG_IEEE80211BE
|
||||||
if (ap_sta_is_mld(hapd, sta)) {
|
if (ap_sta_is_mld(hapd, sta)) {
|
||||||
|
|
|
@ -112,10 +112,7 @@ static void wpa_gkeydone_sta(struct wpa_state_machine *sm)
|
||||||
int link_id;
|
int link_id;
|
||||||
#endif /* CONFIG_IEEE80211BE */
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
if (!sm->wpa_auth)
|
sm->group->GKeyDoneStations--;
|
||||||
return;
|
|
||||||
|
|
||||||
sm->wpa_auth->group->GKeyDoneStations--;
|
|
||||||
sm->GUpdateStationKeys = false;
|
sm->GUpdateStationKeys = false;
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211BE
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
@ -1046,6 +1043,7 @@ static void wpa_free_sta_sm(struct wpa_state_machine *sm)
|
||||||
os_free(sm->last_rx_eapol_key);
|
os_free(sm->last_rx_eapol_key);
|
||||||
os_free(sm->wpa_ie);
|
os_free(sm->wpa_ie);
|
||||||
os_free(sm->rsnxe);
|
os_free(sm->rsnxe);
|
||||||
|
os_free(sm->rsn_selection);
|
||||||
#ifdef CONFIG_IEEE80211BE
|
#ifdef CONFIG_IEEE80211BE
|
||||||
for_each_sm_auth(sm, link_id) {
|
for_each_sm_auth(sm, link_id) {
|
||||||
wpa_group_put(sm->mld_links[link_id].wpa_auth,
|
wpa_group_put(sm->mld_links[link_id].wpa_auth,
|
||||||
|
@ -1886,7 +1884,8 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
|
||||||
sm->EAPOLKeyReceived = true;
|
sm->EAPOLKeyReceived = true;
|
||||||
sm->EAPOLKeyPairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE);
|
sm->EAPOLKeyPairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE);
|
||||||
sm->EAPOLKeyRequest = !!(key_info & WPA_KEY_INFO_REQUEST);
|
sm->EAPOLKeyRequest = !!(key_info & WPA_KEY_INFO_REQUEST);
|
||||||
os_memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN);
|
if (msg == PAIRWISE_2)
|
||||||
|
os_memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN);
|
||||||
wpa_sm_step(sm);
|
wpa_sm_step(sm);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
@ -2064,6 +2063,11 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
|
||||||
if (key_rsc)
|
if (key_rsc)
|
||||||
os_memcpy(key->key_rsc, key_rsc, WPA_KEY_RSC_LEN);
|
os_memcpy(key->key_rsc, key_rsc, WPA_KEY_RSC_LEN);
|
||||||
|
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
if (conf->eapol_key_reserved_random)
|
||||||
|
random_get_bytes(key->key_id, sizeof(key->key_id));
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
if (kde && !encr) {
|
if (kde && !encr) {
|
||||||
os_memcpy(key_data, kde, kde_len);
|
os_memcpy(key_data, kde, kde_len);
|
||||||
WPA_PUT_BE16(key_mic + mic_len, kde_len);
|
WPA_PUT_BE16(key_mic + mic_len, kde_len);
|
||||||
|
@ -3914,6 +3918,34 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211R_AP */
|
#endif /* CONFIG_IEEE80211R_AP */
|
||||||
|
|
||||||
|
/* Verify RSN Selection element for RSN overriding */
|
||||||
|
if ((wpa_auth->conf.rsn_override_key_mgmt ||
|
||||||
|
wpa_auth->conf.rsn_override_key_mgmt_2) &&
|
||||||
|
((rsn_is_snonce_cookie(sm->SNonce) && !kde.rsn_selection) ||
|
||||||
|
(!rsn_is_snonce_cookie(sm->SNonce) && kde.rsn_selection) ||
|
||||||
|
(sm->rsn_selection && !kde.rsn_selection) ||
|
||||||
|
(!sm->rsn_selection && kde.rsn_selection) ||
|
||||||
|
(sm->rsn_selection && kde.rsn_selection &&
|
||||||
|
(sm->rsn_selection_len != kde.rsn_selection_len ||
|
||||||
|
os_memcmp(sm->rsn_selection, kde.rsn_selection,
|
||||||
|
sm->rsn_selection_len) != 0)))) {
|
||||||
|
wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
|
||||||
|
"RSN Selection element from (Re)AssocReq did not match the one in EAPOL-Key msg 2/4");
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"SNonce cookie for RSN overriding %sused",
|
||||||
|
rsn_is_snonce_cookie(sm->SNonce) ? "" : "not ");
|
||||||
|
wpa_hexdump(MSG_DEBUG, "RSN Selection in AssocReq",
|
||||||
|
sm->rsn_selection, sm->rsn_selection_len);
|
||||||
|
wpa_hexdump(MSG_DEBUG, "RSN Selection in EAPOL-Key msg 2/4",
|
||||||
|
kde.rsn_selection, kde.rsn_selection_len);
|
||||||
|
/* MLME-DEAUTHENTICATE.request */
|
||||||
|
wpa_sta_disconnect(wpa_auth, sm->addr,
|
||||||
|
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_P2P
|
#ifdef CONFIG_P2P
|
||||||
if (kde.ip_addr_req && kde.ip_addr_req[0] &&
|
if (kde.ip_addr_req && kde.ip_addr_req[0] &&
|
||||||
wpa_auth->ip_pool && WPA_GET_BE32(sm->ip_addr) == 0) {
|
wpa_auth->ip_pool && WPA_GET_BE32(sm->ip_addr) == 0) {
|
||||||
|
@ -4177,7 +4209,8 @@ static u8 * replace_ie(const char *name, const u8 *old_buf, size_t *len, u8 eid,
|
||||||
|
|
||||||
void wpa_auth_ml_get_key_info(struct wpa_authenticator *a,
|
void wpa_auth_ml_get_key_info(struct wpa_authenticator *a,
|
||||||
struct wpa_auth_ml_link_key_info *info,
|
struct wpa_auth_ml_link_key_info *info,
|
||||||
bool mgmt_frame_prot, bool beacon_prot)
|
bool mgmt_frame_prot, bool beacon_prot,
|
||||||
|
bool rekey)
|
||||||
{
|
{
|
||||||
struct wpa_group *gsm = a->group;
|
struct wpa_group *gsm = a->group;
|
||||||
u8 rsc[WPA_KEY_RSC_LEN];
|
u8 rsc[WPA_KEY_RSC_LEN];
|
||||||
|
@ -4190,7 +4223,7 @@ void wpa_auth_ml_get_key_info(struct wpa_authenticator *a,
|
||||||
info->gtk = gsm->GTK[gsm->GN - 1];
|
info->gtk = gsm->GTK[gsm->GN - 1];
|
||||||
info->gtk_len = gsm->GTK_len;
|
info->gtk_len = gsm->GTK_len;
|
||||||
|
|
||||||
if (wpa_auth_get_seqnum(a, NULL, gsm->GN, rsc) < 0)
|
if (rekey || wpa_auth_get_seqnum(a, NULL, gsm->GN, rsc) < 0)
|
||||||
os_memset(info->pn, 0, sizeof(info->pn));
|
os_memset(info->pn, 0, sizeof(info->pn));
|
||||||
else
|
else
|
||||||
os_memcpy(info->pn, rsc, sizeof(info->pn));
|
os_memcpy(info->pn, rsc, sizeof(info->pn));
|
||||||
|
@ -4202,7 +4235,7 @@ void wpa_auth_ml_get_key_info(struct wpa_authenticator *a,
|
||||||
info->igtk = gsm->IGTK[gsm->GN_igtk - 4];
|
info->igtk = gsm->IGTK[gsm->GN_igtk - 4];
|
||||||
info->igtk_len = wpa_cipher_key_len(a->conf.group_mgmt_cipher);
|
info->igtk_len = wpa_cipher_key_len(a->conf.group_mgmt_cipher);
|
||||||
|
|
||||||
if (wpa_auth_get_seqnum(a, NULL, gsm->GN_igtk, rsc) < 0)
|
if (rekey || wpa_auth_get_seqnum(a, NULL, gsm->GN_igtk, rsc) < 0)
|
||||||
os_memset(info->ipn, 0, sizeof(info->ipn));
|
os_memset(info->ipn, 0, sizeof(info->ipn));
|
||||||
else
|
else
|
||||||
os_memcpy(info->ipn, rsc, sizeof(info->ipn));
|
os_memcpy(info->ipn, rsc, sizeof(info->ipn));
|
||||||
|
@ -4218,7 +4251,7 @@ void wpa_auth_ml_get_key_info(struct wpa_authenticator *a,
|
||||||
info->bigtkidx = gsm->GN_bigtk;
|
info->bigtkidx = gsm->GN_bigtk;
|
||||||
info->bigtk = gsm->BIGTK[gsm->GN_bigtk - 6];
|
info->bigtk = gsm->BIGTK[gsm->GN_bigtk - 6];
|
||||||
|
|
||||||
if (wpa_auth_get_seqnum(a, NULL, gsm->GN_bigtk, rsc) < 0)
|
if (rekey || wpa_auth_get_seqnum(a, NULL, gsm->GN_bigtk, rsc) < 0)
|
||||||
os_memset(info->bipn, 0, sizeof(info->bipn));
|
os_memset(info->bipn, 0, sizeof(info->bipn));
|
||||||
else
|
else
|
||||||
os_memcpy(info->bipn, rsc, sizeof(info->bipn));
|
os_memcpy(info->bipn, rsc, sizeof(info->bipn));
|
||||||
|
@ -4226,12 +4259,13 @@ void wpa_auth_ml_get_key_info(struct wpa_authenticator *a,
|
||||||
|
|
||||||
|
|
||||||
static void wpa_auth_get_ml_key_info(struct wpa_authenticator *wpa_auth,
|
static void wpa_auth_get_ml_key_info(struct wpa_authenticator *wpa_auth,
|
||||||
struct wpa_auth_ml_key_info *info)
|
struct wpa_auth_ml_key_info *info,
|
||||||
|
bool rekey)
|
||||||
{
|
{
|
||||||
if (!wpa_auth->cb->get_ml_key_info)
|
if (!wpa_auth->cb->get_ml_key_info)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
wpa_auth->cb->get_ml_key_info(wpa_auth->cb_ctx, info);
|
wpa_auth->cb->get_ml_key_info(wpa_auth->cb_ctx, info, rekey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -4288,6 +4322,7 @@ static u8 * wpa_auth_ml_group_kdes(struct wpa_state_machine *sm, u8 *pos)
|
||||||
struct wpa_auth_ml_key_info ml_key_info;
|
struct wpa_auth_ml_key_info ml_key_info;
|
||||||
unsigned int i, link_id;
|
unsigned int i, link_id;
|
||||||
u8 *start = pos;
|
u8 *start = pos;
|
||||||
|
bool rekey = sm->wpa_ptk_group_state == WPA_PTK_GROUP_REKEYNEGOTIATING;
|
||||||
|
|
||||||
/* First fetch the key information from all the authenticators */
|
/* First fetch the key information from all the authenticators */
|
||||||
os_memset(&ml_key_info, 0, sizeof(ml_key_info));
|
os_memset(&ml_key_info, 0, sizeof(ml_key_info));
|
||||||
|
@ -4307,7 +4342,7 @@ static u8 * wpa_auth_ml_group_kdes(struct wpa_state_machine *sm, u8 *pos)
|
||||||
ml_key_info.links[i++].link_id = link_id;
|
ml_key_info.links[i++].link_id = link_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
wpa_auth_get_ml_key_info(sm->wpa_auth, &ml_key_info);
|
wpa_auth_get_ml_key_info(sm->wpa_auth, &ml_key_info, rekey);
|
||||||
|
|
||||||
/* Add MLO GTK KDEs */
|
/* Add MLO GTK KDEs */
|
||||||
for (i = 0, link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
|
for (i = 0, link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
|
||||||
|
@ -4446,7 +4481,7 @@ static size_t wpa_auth_ml_kdes_len(struct wpa_state_machine *sm)
|
||||||
/* For the MAC Address KDE */
|
/* For the MAC Address KDE */
|
||||||
kde_len = 2 + RSN_SELECTOR_LEN + ETH_ALEN;
|
kde_len = 2 + RSN_SELECTOR_LEN + ETH_ALEN;
|
||||||
|
|
||||||
/* MLO Link KDE for each link */
|
/* MLO Link KDE and RSN Override Link KDE for each link */
|
||||||
for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
|
for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
|
||||||
struct wpa_authenticator *wpa_auth;
|
struct wpa_authenticator *wpa_auth;
|
||||||
const u8 *ie;
|
const u8 *ie;
|
||||||
|
@ -4455,15 +4490,39 @@ static size_t wpa_auth_ml_kdes_len(struct wpa_state_machine *sm)
|
||||||
if (!wpa_auth)
|
if (!wpa_auth)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* MLO Link KDE */
|
||||||
kde_len += 2 + RSN_SELECTOR_LEN + 1 + ETH_ALEN;
|
kde_len += 2 + RSN_SELECTOR_LEN + 1 + ETH_ALEN;
|
||||||
|
|
||||||
ie = get_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
|
ie = get_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
|
||||||
WLAN_EID_RSN);
|
WLAN_EID_RSN);
|
||||||
if (ie)
|
if (ie)
|
||||||
kde_len += 2 + ie[1];
|
kde_len += 2 + ie[1];
|
||||||
|
|
||||||
ie = get_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
|
ie = get_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
|
||||||
WLAN_EID_RSNX);
|
WLAN_EID_RSNX);
|
||||||
if (ie)
|
if (ie)
|
||||||
kde_len += 2 + ie[1];
|
kde_len += 2 + ie[1];
|
||||||
|
|
||||||
|
if (!rsn_is_snonce_cookie(sm->SNonce))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* RSN Override Link KDE */
|
||||||
|
kde_len += 2 + RSN_SELECTOR_LEN + 1;
|
||||||
|
|
||||||
|
ie = get_vendor_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
|
||||||
|
RSNE_OVERRIDE_IE_VENDOR_TYPE);
|
||||||
|
if (ie)
|
||||||
|
kde_len += 2 + ie[1];
|
||||||
|
|
||||||
|
ie = get_vendor_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
|
||||||
|
RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
|
||||||
|
if (ie)
|
||||||
|
kde_len += 2 + ie[1];
|
||||||
|
|
||||||
|
ie = get_vendor_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
|
||||||
|
RSNXE_OVERRIDE_IE_VENDOR_TYPE);
|
||||||
|
if (ie)
|
||||||
|
kde_len += 2 + ie[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
kde_len += wpa_auth_ml_group_kdes_len(sm);
|
kde_len += wpa_auth_ml_group_kdes_len(sm);
|
||||||
|
@ -4488,8 +4547,9 @@ static u8 * wpa_auth_ml_kdes(struct wpa_state_machine *sm, u8 *pos)
|
||||||
|
|
||||||
for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
|
for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
|
||||||
struct wpa_authenticator *wpa_auth;
|
struct wpa_authenticator *wpa_auth;
|
||||||
const u8 *rsne, *rsnxe;
|
const u8 *rsne, *rsnxe, *rsnoe, *rsno2e, *rsnxoe;
|
||||||
size_t rsne_len, rsnxe_len;
|
size_t rsne_len, rsnxe_len, rsnoe_len, rsno2e_len, rsnxoe_len;
|
||||||
|
size_t kde_len;
|
||||||
|
|
||||||
wpa_auth = wpa_get_link_auth(sm->wpa_auth, link_id);
|
wpa_auth = wpa_get_link_auth(sm->wpa_auth, link_id);
|
||||||
if (!wpa_auth)
|
if (!wpa_auth)
|
||||||
|
@ -4508,6 +4568,7 @@ static u8 * wpa_auth_ml_kdes(struct wpa_state_machine *sm, u8 *pos)
|
||||||
RSN_SELECTOR_LEN + 1 + ETH_ALEN +
|
RSN_SELECTOR_LEN + 1 + ETH_ALEN +
|
||||||
rsne_len + rsnxe_len);
|
rsne_len + rsnxe_len);
|
||||||
|
|
||||||
|
/* MLO Link KDE */
|
||||||
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
|
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||||
*pos++ = RSN_SELECTOR_LEN + 1 + ETH_ALEN +
|
*pos++ = RSN_SELECTOR_LEN + 1 + ETH_ALEN +
|
||||||
rsne_len + rsnxe_len;
|
rsne_len + rsnxe_len;
|
||||||
|
@ -4535,9 +4596,63 @@ static u8 * wpa_auth_ml_kdes(struct wpa_state_machine *sm, u8 *pos)
|
||||||
os_memcpy(pos, rsnxe, rsnxe_len);
|
os_memcpy(pos, rsnxe, rsnxe_len);
|
||||||
pos += rsnxe_len;
|
pos += rsnxe_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!rsn_is_snonce_cookie(sm->SNonce))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
rsnoe = get_vendor_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
|
||||||
|
RSNE_OVERRIDE_IE_VENDOR_TYPE);
|
||||||
|
rsnoe_len = rsnoe ? 2 + rsnoe[1] : 0;
|
||||||
|
|
||||||
|
rsno2e = get_vendor_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
|
||||||
|
RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
|
||||||
|
rsno2e_len = rsno2e ? 2 + rsno2e[1] : 0;
|
||||||
|
|
||||||
|
rsnxoe = get_vendor_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
|
||||||
|
RSNXE_OVERRIDE_IE_VENDOR_TYPE);
|
||||||
|
rsnxoe_len = rsnxoe ? 2 + rsnxoe[1] : 0;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"RSN: RSN Override Link KDE: link=%u, len=%zu",
|
||||||
|
link_id, RSN_SELECTOR_LEN + rsnoe_len + rsno2e_len +
|
||||||
|
rsnxoe_len);
|
||||||
|
|
||||||
|
/* RSN Override Link KDE */
|
||||||
|
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||||
|
kde_len = RSN_SELECTOR_LEN + 1 + rsnoe_len + rsno2e_len +
|
||||||
|
rsnxoe_len;
|
||||||
|
if (kde_len > 255) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"RSN: RSNOE/RSNO2E/RSNXOE too long (KDE length %zu) to fit in RSN Override Link KDE for link %u",
|
||||||
|
kde_len, link_id);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
*pos++ = kde_len;
|
||||||
|
|
||||||
|
RSN_SELECTOR_PUT(pos, WFA_KEY_DATA_RSN_OVERRIDE_LINK);
|
||||||
|
pos += RSN_SELECTOR_LEN;
|
||||||
|
|
||||||
|
*pos++ = link_id;
|
||||||
|
|
||||||
|
if (rsnoe_len) {
|
||||||
|
os_memcpy(pos, rsnoe, rsnoe_len);
|
||||||
|
pos += rsnoe_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rsno2e_len) {
|
||||||
|
os_memcpy(pos, rsno2e, rsno2e_len);
|
||||||
|
pos += rsno2e_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rsnxoe_len) {
|
||||||
|
os_memcpy(pos, rsnxoe, rsnxoe_len);
|
||||||
|
pos += rsnxoe_len;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "RSN: MLO Link KDE len = %ld", pos - start);
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"RSN: MLO Link KDEs and RSN Override Link KDEs len = %ld",
|
||||||
|
pos - start);
|
||||||
pos = wpa_auth_ml_group_kdes(sm, pos);
|
pos = wpa_auth_ml_group_kdes(sm, pos);
|
||||||
#endif /* CONFIG_IEEE80211BE */
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
|
@ -4552,7 +4667,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
|
||||||
struct wpa_group *gsm = sm->group;
|
struct wpa_group *gsm = sm->group;
|
||||||
u8 *wpa_ie;
|
u8 *wpa_ie;
|
||||||
int secure, gtkidx, encr = 0;
|
int secure, gtkidx, encr = 0;
|
||||||
u8 *wpa_ie_buf = NULL, *wpa_ie_buf2 = NULL;
|
u8 *wpa_ie_buf = NULL, *wpa_ie_buf2 = NULL, *wpa_ie_buf3 = NULL;
|
||||||
u8 hdr[2];
|
u8 hdr[2];
|
||||||
struct wpa_auth_config *conf = &sm->wpa_auth->conf;
|
struct wpa_auth_config *conf = &sm->wpa_auth->conf;
|
||||||
#ifdef CONFIG_IEEE80211BE
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
@ -4593,6 +4708,39 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
|
||||||
wpa_ie = wpa_ie + wpa_ie[1] + 2;
|
wpa_ie = wpa_ie + wpa_ie[1] + 2;
|
||||||
wpa_ie_len = wpa_ie[1] + 2;
|
wpa_ie_len = wpa_ie[1] + 2;
|
||||||
}
|
}
|
||||||
|
if ((conf->rsn_override_key_mgmt || conf->rsn_override_key_mgmt_2) &&
|
||||||
|
!rsn_is_snonce_cookie(sm->SNonce)) {
|
||||||
|
u8 *ie;
|
||||||
|
size_t ie_len;
|
||||||
|
u32 ids[] = {
|
||||||
|
RSNE_OVERRIDE_IE_VENDOR_TYPE,
|
||||||
|
RSNE_OVERRIDE_2_IE_VENDOR_TYPE,
|
||||||
|
RSNXE_OVERRIDE_IE_VENDOR_TYPE,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
int i;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"RSN: Remove RSNE/RSNXE override elements");
|
||||||
|
wpa_hexdump(MSG_DEBUG, "EAPOL-Key msg 3/4 IEs before edits",
|
||||||
|
wpa_ie, wpa_ie_len);
|
||||||
|
wpa_ie_buf3 = os_memdup(wpa_ie, wpa_ie_len);
|
||||||
|
if (!wpa_ie_buf3)
|
||||||
|
goto done;
|
||||||
|
wpa_ie = wpa_ie_buf3;
|
||||||
|
|
||||||
|
for (i = 0; ids[i]; i++) {
|
||||||
|
ie = (u8 *) get_vendor_ie(wpa_ie, wpa_ie_len, ids[i]);
|
||||||
|
if (ie) {
|
||||||
|
ie_len = 2 + ie[1];
|
||||||
|
os_memmove(ie, ie + ie_len,
|
||||||
|
wpa_ie_len - (ie + ie_len - wpa_ie));
|
||||||
|
wpa_ie_len -= ie_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wpa_hexdump(MSG_DEBUG, "EAPOL-Key msg 3/4 IEs after edits",
|
||||||
|
wpa_ie, wpa_ie_len);
|
||||||
|
}
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
if (conf->rsne_override_eapol_set) {
|
if (conf->rsne_override_eapol_set) {
|
||||||
wpa_ie_buf2 = replace_ie(
|
wpa_ie_buf2 = replace_ie(
|
||||||
|
@ -4832,6 +4980,10 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
|
||||||
#endif /* CONFIG_DPP2 */
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
pos = wpa_auth_ml_kdes(sm, pos);
|
pos = wpa_auth_ml_kdes(sm, pos);
|
||||||
|
if (!pos) {
|
||||||
|
wpa_printf(MSG_ERROR, "RSN: Failed to add MLO KDEs");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
if (sm->ssid_protection) {
|
if (sm->ssid_protection) {
|
||||||
*pos++ = WLAN_EID_SSID;
|
*pos++ = WLAN_EID_SSID;
|
||||||
|
@ -4862,6 +5014,7 @@ done:
|
||||||
bin_clear_free(kde, kde_len);
|
bin_clear_free(kde, kde_len);
|
||||||
os_free(wpa_ie_buf);
|
os_free(wpa_ie_buf);
|
||||||
os_free(wpa_ie_buf2);
|
os_free(wpa_ie_buf2);
|
||||||
|
os_free(wpa_ie_buf3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -5475,11 +5628,38 @@ static void wpa_group_gtk_init(struct wpa_authenticator *wpa_auth,
|
||||||
|
|
||||||
static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx)
|
static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx)
|
||||||
{
|
{
|
||||||
if (ctx != NULL && ctx != sm->group)
|
struct wpa_authenticator *wpa_auth = sm->wpa_auth;
|
||||||
|
struct wpa_group *group = sm->group;
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
int link_id;
|
||||||
|
|
||||||
|
for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
|
||||||
|
if (!sm->mld_links[link_id].valid)
|
||||||
|
continue;
|
||||||
|
if (sm->mld_links[link_id].wpa_auth &&
|
||||||
|
sm->mld_links[link_id].wpa_auth->group == ctx) {
|
||||||
|
group = sm->mld_links[link_id].wpa_auth->group;
|
||||||
|
wpa_auth = sm->mld_links[link_id].wpa_auth;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
|
if (ctx && ctx != group)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
/* For ML STA, run rekey on the association link and send G1 with keys
|
||||||
|
* for all links. This is based on assumption that MLD level
|
||||||
|
* Authenticator updates group keys on all affiliated links in one shot
|
||||||
|
* and not independently or concurrently for separate links. */
|
||||||
|
if (sm->mld_assoc_link_id >= 0 &&
|
||||||
|
sm->mld_assoc_link_id != wpa_auth->link_id)
|
||||||
|
return 0;
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
if (sm->wpa_ptk_state != WPA_PTK_PTKINITDONE) {
|
if (sm->wpa_ptk_state != WPA_PTK_PTKINITDONE) {
|
||||||
wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm),
|
wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
|
||||||
LOGGER_DEBUG,
|
LOGGER_DEBUG,
|
||||||
"Not in PTKINITDONE; skip Group Key update");
|
"Not in PTKINITDONE; skip Group Key update");
|
||||||
sm->GUpdateStationKeys = false;
|
sm->GUpdateStationKeys = false;
|
||||||
|
@ -5491,7 +5671,7 @@ static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx)
|
||||||
* Since we clear the GKeyDoneStations before the loop, the
|
* Since we clear the GKeyDoneStations before the loop, the
|
||||||
* station needs to be counted here anyway.
|
* station needs to be counted here anyway.
|
||||||
*/
|
*/
|
||||||
wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm),
|
wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
|
||||||
LOGGER_DEBUG,
|
LOGGER_DEBUG,
|
||||||
"GUpdateStationKeys was already set when marking station for GTK rekeying");
|
"GUpdateStationKeys was already set when marking station for GTK rekeying");
|
||||||
}
|
}
|
||||||
|
@ -5501,6 +5681,11 @@ static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
sm->group->GKeyDoneStations++;
|
sm->group->GKeyDoneStations++;
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
for_each_sm_auth(sm, link_id)
|
||||||
|
sm->mld_links[link_id].wpa_auth->group->GKeyDoneStations++;
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
sm->GUpdateStationKeys = true;
|
sm->GUpdateStationKeys = true;
|
||||||
|
|
||||||
wpa_sm_step(sm);
|
wpa_sm_step(sm);
|
||||||
|
@ -6813,6 +6998,30 @@ void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void wpa_auth_set_rsn_selection(struct wpa_state_machine *sm, const u8 *ie,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
if (!sm)
|
||||||
|
return;
|
||||||
|
os_free(sm->rsn_selection);
|
||||||
|
sm->rsn_selection = NULL;
|
||||||
|
sm->rsn_selection_len = 0;
|
||||||
|
sm->rsn_override = false;
|
||||||
|
sm->rsn_override_2 = false;
|
||||||
|
if (ie) {
|
||||||
|
if (len >= 1) {
|
||||||
|
if (ie[0] == RSN_SELECTION_RSNE_OVERRIDE)
|
||||||
|
sm->rsn_override = true;
|
||||||
|
else if (ie[0] == RSN_SELECTION_RSNE_OVERRIDE_2)
|
||||||
|
sm->rsn_override_2 = true;
|
||||||
|
}
|
||||||
|
sm->rsn_selection = os_memdup(ie, len);
|
||||||
|
if (sm->rsn_selection)
|
||||||
|
sm->rsn_selection_len = len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_DPP2
|
#ifdef CONFIG_DPP2
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
struct vlan_description;
|
struct vlan_description;
|
||||||
struct mld_info;
|
struct mld_info;
|
||||||
|
|
||||||
#define MAX_OWN_IE_OVERRIDE 256
|
#define MAX_OWN_IE_OVERRIDE 257
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
|
@ -173,6 +173,8 @@ struct wpa_auth_config {
|
||||||
int wpa;
|
int wpa;
|
||||||
int extended_key_id;
|
int extended_key_id;
|
||||||
int wpa_key_mgmt;
|
int wpa_key_mgmt;
|
||||||
|
int rsn_override_key_mgmt;
|
||||||
|
int rsn_override_key_mgmt_2;
|
||||||
int wpa_pairwise;
|
int wpa_pairwise;
|
||||||
int wpa_group;
|
int wpa_group;
|
||||||
int wpa_group_rekey;
|
int wpa_group_rekey;
|
||||||
|
@ -184,6 +186,8 @@ struct wpa_auth_config {
|
||||||
u32 wpa_pairwise_update_count;
|
u32 wpa_pairwise_update_count;
|
||||||
int wpa_disable_eapol_key_retries;
|
int wpa_disable_eapol_key_retries;
|
||||||
int rsn_pairwise;
|
int rsn_pairwise;
|
||||||
|
int rsn_override_pairwise;
|
||||||
|
int rsn_override_pairwise_2;
|
||||||
int rsn_preauth;
|
int rsn_preauth;
|
||||||
int eapol_version;
|
int eapol_version;
|
||||||
int wmm_enabled;
|
int wmm_enabled;
|
||||||
|
@ -192,6 +196,8 @@ struct wpa_auth_config {
|
||||||
int okc;
|
int okc;
|
||||||
int tx_status;
|
int tx_status;
|
||||||
enum mfp_options ieee80211w;
|
enum mfp_options ieee80211w;
|
||||||
|
enum mfp_options rsn_override_mfp;
|
||||||
|
enum mfp_options rsn_override_mfp_2;
|
||||||
int beacon_prot;
|
int beacon_prot;
|
||||||
int group_mgmt_cipher;
|
int group_mgmt_cipher;
|
||||||
int sae_require_mfp;
|
int sae_require_mfp;
|
||||||
|
@ -224,6 +230,21 @@ 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;
|
||||||
|
bool rsne_override_set;
|
||||||
|
u8 rsne_override[MAX_OWN_IE_OVERRIDE];
|
||||||
|
size_t rsne_override_len;
|
||||||
|
bool rsnoe_override_set;
|
||||||
|
u8 rsnoe_override[MAX_OWN_IE_OVERRIDE];
|
||||||
|
size_t rsnoe_override_len;
|
||||||
|
bool rsno2e_override_set;
|
||||||
|
u8 rsno2e_override[MAX_OWN_IE_OVERRIDE];
|
||||||
|
size_t rsno2e_override_len;
|
||||||
|
bool rsnxe_override_set;
|
||||||
|
u8 rsnxe_override[MAX_OWN_IE_OVERRIDE];
|
||||||
|
size_t rsnxe_override_len;
|
||||||
|
bool rsnxoe_override_set;
|
||||||
|
u8 rsnxoe_override[MAX_OWN_IE_OVERRIDE];
|
||||||
|
size_t rsnxoe_override_len;
|
||||||
u8 rsne_override_eapol[MAX_OWN_IE_OVERRIDE];
|
u8 rsne_override_eapol[MAX_OWN_IE_OVERRIDE];
|
||||||
size_t rsne_override_eapol_len;
|
size_t rsne_override_eapol_len;
|
||||||
u8 rsnxe_override_eapol[MAX_OWN_IE_OVERRIDE];
|
u8 rsnxe_override_eapol[MAX_OWN_IE_OVERRIDE];
|
||||||
|
@ -245,6 +266,7 @@ struct wpa_auth_config {
|
||||||
struct wpabuf *eapol_m1_elements;
|
struct wpabuf *eapol_m1_elements;
|
||||||
struct wpabuf *eapol_m3_elements;
|
struct wpabuf *eapol_m3_elements;
|
||||||
bool eapol_m3_no_encrypt;
|
bool eapol_m3_no_encrypt;
|
||||||
|
bool eapol_key_reserved_random;
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
unsigned int oci_freq_override_eapol_m3;
|
unsigned int oci_freq_override_eapol_m3;
|
||||||
unsigned int oci_freq_override_eapol_g1;
|
unsigned int oci_freq_override_eapol_g1;
|
||||||
|
@ -295,6 +317,8 @@ struct wpa_auth_config {
|
||||||
#endif /* CONFIG_IEEE80211BE */
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
bool ssid_protection;
|
bool ssid_protection;
|
||||||
|
|
||||||
|
int rsn_override_omit_rsnxe;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -400,7 +424,8 @@ struct wpa_auth_callbacks {
|
||||||
size_t ltf_keyseed_len);
|
size_t ltf_keyseed_len);
|
||||||
#endif /* CONFIG_PASN */
|
#endif /* CONFIG_PASN */
|
||||||
#ifdef CONFIG_IEEE80211BE
|
#ifdef CONFIG_IEEE80211BE
|
||||||
int (*get_ml_key_info)(void *ctx, struct wpa_auth_ml_key_info *info);
|
int (*get_ml_key_info)(void *ctx, struct wpa_auth_ml_key_info *info,
|
||||||
|
bool rekey);
|
||||||
#endif /* CONFIG_IEEE80211BE */
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
int (*get_drv_flags)(void *ctx, u64 *drv_flags, u64 *drv_flags2);
|
int (*get_drv_flags)(void *ctx, u64 *drv_flags, u64 *drv_flags2);
|
||||||
};
|
};
|
||||||
|
@ -605,6 +630,8 @@ u8 * wpa_auth_write_assoc_resp_fils(struct wpa_state_machine *sm,
|
||||||
bool wpa_auth_write_fd_rsn_info(struct wpa_authenticator *wpa_auth,
|
bool wpa_auth_write_fd_rsn_info(struct wpa_authenticator *wpa_auth,
|
||||||
u8 *fd_rsn_info);
|
u8 *fd_rsn_info);
|
||||||
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_rsn_selection(struct wpa_state_machine *sm, const u8 *ie,
|
||||||
|
size_t len);
|
||||||
void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z);
|
void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z);
|
||||||
void wpa_auth_set_ssid_protection(struct wpa_state_machine *sm, bool val);
|
void wpa_auth_set_ssid_protection(struct wpa_state_machine *sm, bool val);
|
||||||
void wpa_auth_set_transition_disable(struct wpa_authenticator *wpa_auth,
|
void wpa_auth_set_transition_disable(struct wpa_authenticator *wpa_auth,
|
||||||
|
@ -644,7 +671,8 @@ void wpa_auth_set_ml_info(struct wpa_state_machine *sm,
|
||||||
u8 mld_assoc_link_id, struct mld_info *info);
|
u8 mld_assoc_link_id, struct mld_info *info);
|
||||||
void wpa_auth_ml_get_key_info(struct wpa_authenticator *a,
|
void wpa_auth_ml_get_key_info(struct wpa_authenticator *a,
|
||||||
struct wpa_auth_ml_link_key_info *info,
|
struct wpa_auth_ml_link_key_info *info,
|
||||||
bool mgmt_frame_prot, bool beacon_prot);
|
bool mgmt_frame_prot, bool beacon_prot,
|
||||||
|
bool rekey);
|
||||||
|
|
||||||
void wpa_release_link_auth_ref(struct wpa_state_machine *sm,
|
void wpa_release_link_auth_ref(struct wpa_state_machine *sm,
|
||||||
int release_link_id);
|
int release_link_id);
|
||||||
|
|
|
@ -45,6 +45,8 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
|
||||||
wconf->wpa = conf->wpa;
|
wconf->wpa = conf->wpa;
|
||||||
wconf->extended_key_id = conf->extended_key_id;
|
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->rsn_override_key_mgmt = conf->rsn_override_key_mgmt;
|
||||||
|
wconf->rsn_override_key_mgmt_2 = conf->rsn_override_key_mgmt_2;
|
||||||
wconf->wpa_pairwise = conf->wpa_pairwise;
|
wconf->wpa_pairwise = conf->wpa_pairwise;
|
||||||
wconf->wpa_group = conf->wpa_group;
|
wconf->wpa_group = conf->wpa_group;
|
||||||
wconf->wpa_group_rekey = conf->wpa_group_rekey;
|
wconf->wpa_group_rekey = conf->wpa_group_rekey;
|
||||||
|
@ -56,6 +58,8 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
|
||||||
conf->wpa_disable_eapol_key_retries;
|
conf->wpa_disable_eapol_key_retries;
|
||||||
wconf->wpa_pairwise_update_count = conf->wpa_pairwise_update_count;
|
wconf->wpa_pairwise_update_count = conf->wpa_pairwise_update_count;
|
||||||
wconf->rsn_pairwise = conf->rsn_pairwise;
|
wconf->rsn_pairwise = conf->rsn_pairwise;
|
||||||
|
wconf->rsn_override_pairwise = conf->rsn_override_pairwise;
|
||||||
|
wconf->rsn_override_pairwise_2 = conf->rsn_override_pairwise_2;
|
||||||
wconf->rsn_preauth = conf->rsn_preauth;
|
wconf->rsn_preauth = conf->rsn_preauth;
|
||||||
wconf->eapol_version = conf->eapol_version;
|
wconf->eapol_version = conf->eapol_version;
|
||||||
#ifdef CONFIG_MACSEC
|
#ifdef CONFIG_MACSEC
|
||||||
|
@ -70,6 +74,8 @@ 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->rsn_override_mfp = conf->rsn_override_mfp;
|
||||||
|
wconf->rsn_override_mfp_2 = conf->rsn_override_mfp_2;
|
||||||
wconf->beacon_prot = conf->beacon_prot;
|
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;
|
||||||
|
@ -126,6 +132,46 @@ 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 &&
|
||||||
|
wpabuf_len(conf->rsne_override) <= MAX_OWN_IE_OVERRIDE) {
|
||||||
|
wconf->rsne_override_len = wpabuf_len(conf->rsne_override);
|
||||||
|
os_memcpy(wconf->rsne_override,
|
||||||
|
wpabuf_head(conf->rsne_override),
|
||||||
|
wconf->rsne_override_len);
|
||||||
|
wconf->rsne_override_set = true;
|
||||||
|
}
|
||||||
|
if (conf->rsnoe_override &&
|
||||||
|
wpabuf_len(conf->rsnoe_override) <= MAX_OWN_IE_OVERRIDE) {
|
||||||
|
wconf->rsnoe_override_len = wpabuf_len(conf->rsnoe_override);
|
||||||
|
os_memcpy(wconf->rsnoe_override,
|
||||||
|
wpabuf_head(conf->rsnoe_override),
|
||||||
|
wconf->rsnoe_override_len);
|
||||||
|
wconf->rsnoe_override_set = true;
|
||||||
|
}
|
||||||
|
if (conf->rsno2e_override &&
|
||||||
|
wpabuf_len(conf->rsno2e_override) <= MAX_OWN_IE_OVERRIDE) {
|
||||||
|
wconf->rsno2e_override_len = wpabuf_len(conf->rsno2e_override);
|
||||||
|
os_memcpy(wconf->rsno2e_override,
|
||||||
|
wpabuf_head(conf->rsno2e_override),
|
||||||
|
wconf->rsno2e_override_len);
|
||||||
|
wconf->rsno2e_override_set = true;
|
||||||
|
}
|
||||||
|
if (conf->rsnxe_override &&
|
||||||
|
wpabuf_len(conf->rsnxe_override) <= MAX_OWN_IE_OVERRIDE) {
|
||||||
|
wconf->rsnxe_override_len = wpabuf_len(conf->rsnxe_override);
|
||||||
|
os_memcpy(wconf->rsnxe_override,
|
||||||
|
wpabuf_head(conf->rsnxe_override),
|
||||||
|
wconf->rsnxe_override_len);
|
||||||
|
wconf->rsnxe_override_set = true;
|
||||||
|
}
|
||||||
|
if (conf->rsnxoe_override &&
|
||||||
|
wpabuf_len(conf->rsnxoe_override) <= MAX_OWN_IE_OVERRIDE) {
|
||||||
|
wconf->rsnxoe_override_len = wpabuf_len(conf->rsnxoe_override);
|
||||||
|
os_memcpy(wconf->rsnxoe_override,
|
||||||
|
wpabuf_head(conf->rsnxoe_override),
|
||||||
|
wconf->rsnxoe_override_len);
|
||||||
|
wconf->rsnxoe_override_set = true;
|
||||||
|
}
|
||||||
if (conf->rsne_override_eapol &&
|
if (conf->rsne_override_eapol &&
|
||||||
wpabuf_len(conf->rsne_override_eapol) <= MAX_OWN_IE_OVERRIDE) {
|
wpabuf_len(conf->rsne_override_eapol) <= MAX_OWN_IE_OVERRIDE) {
|
||||||
wconf->rsne_override_eapol_set = 1;
|
wconf->rsne_override_eapol_set = 1;
|
||||||
|
@ -190,6 +236,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
|
||||||
if (conf->eapol_m3_elements)
|
if (conf->eapol_m3_elements)
|
||||||
wconf->eapol_m3_elements = wpabuf_dup(conf->eapol_m3_elements);
|
wconf->eapol_m3_elements = wpabuf_dup(conf->eapol_m3_elements);
|
||||||
wconf->eapol_m3_no_encrypt = conf->eapol_m3_no_encrypt;
|
wconf->eapol_m3_no_encrypt = conf->eapol_m3_no_encrypt;
|
||||||
|
wconf->eapol_key_reserved_random = conf->eapol_key_reserved_random;
|
||||||
#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);
|
||||||
|
@ -228,6 +275,8 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
|
||||||
wconf->no_disconnect_on_group_keyerror =
|
wconf->no_disconnect_on_group_keyerror =
|
||||||
conf->bss_max_idle && conf->ap_max_inactivity &&
|
conf->bss_max_idle && conf->ap_max_inactivity &&
|
||||||
conf->no_disconnect_on_group_keyerror;
|
conf->no_disconnect_on_group_keyerror;
|
||||||
|
|
||||||
|
wconf->rsn_override_omit_rsnxe = conf->rsn_override_omit_rsnxe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -279,7 +328,6 @@ static void hostapd_wpa_auth_psk_failure_report(void *ctx, const u8 *addr)
|
||||||
struct hostapd_data *hapd = ctx;
|
struct hostapd_data *hapd = ctx;
|
||||||
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_POSSIBLE_PSK_MISMATCH MACSTR,
|
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_POSSIBLE_PSK_MISMATCH MACSTR,
|
||||||
MAC2STR(addr));
|
MAC2STR(addr));
|
||||||
hostapd_ubus_notify(hapd, "key-mismatch", addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1539,7 +1587,8 @@ static int hostapd_set_ltf_keyseed(void *ctx, const u8 *peer_addr,
|
||||||
#ifdef CONFIG_IEEE80211BE
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
|
||||||
static int hostapd_wpa_auth_get_ml_key_info(void *ctx,
|
static int hostapd_wpa_auth_get_ml_key_info(void *ctx,
|
||||||
struct wpa_auth_ml_key_info *info)
|
struct wpa_auth_ml_key_info *info,
|
||||||
|
bool rekey)
|
||||||
{
|
{
|
||||||
struct hostapd_data *hapd = ctx;
|
struct hostapd_data *hapd = ctx;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
@ -1563,7 +1612,8 @@ static int hostapd_wpa_auth_get_ml_key_info(void *ctx,
|
||||||
wpa_auth_ml_get_key_info(hapd->wpa_auth,
|
wpa_auth_ml_get_key_info(hapd->wpa_auth,
|
||||||
&info->links[i],
|
&info->links[i],
|
||||||
info->mgmt_frame_prot,
|
info->mgmt_frame_prot,
|
||||||
info->beacon_prot);
|
info->beacon_prot,
|
||||||
|
rekey);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1574,7 +1624,8 @@ static int hostapd_wpa_auth_get_ml_key_info(void *ctx,
|
||||||
wpa_auth_ml_get_key_info(bss->wpa_auth,
|
wpa_auth_ml_get_key_info(bss->wpa_auth,
|
||||||
&info->links[i],
|
&info->links[i],
|
||||||
info->mgmt_frame_prot,
|
info->mgmt_frame_prot,
|
||||||
info->beacon_prot);
|
info->beacon_prot,
|
||||||
|
rekey);
|
||||||
link_bss_found = true;
|
link_bss_found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,6 +111,8 @@ struct wpa_state_machine {
|
||||||
size_t wpa_ie_len;
|
size_t wpa_ie_len;
|
||||||
u8 *rsnxe;
|
u8 *rsnxe;
|
||||||
size_t rsnxe_len;
|
size_t rsnxe_len;
|
||||||
|
u8 *rsn_selection;
|
||||||
|
size_t rsn_selection_len;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
WPA_VERSION_NO_WPA = 0 /* WPA not used */,
|
WPA_VERSION_NO_WPA = 0 /* WPA not used */,
|
||||||
|
@ -124,6 +126,9 @@ struct wpa_state_machine {
|
||||||
u32 dot11RSNAStatsTKIPLocalMICFailures;
|
u32 dot11RSNAStatsTKIPLocalMICFailures;
|
||||||
u32 dot11RSNAStatsTKIPRemoteMICFailures;
|
u32 dot11RSNAStatsTKIPRemoteMICFailures;
|
||||||
|
|
||||||
|
bool rsn_override;
|
||||||
|
bool rsn_override_2;
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211R_AP
|
#ifdef CONFIG_IEEE80211R_AP
|
||||||
u8 xxkey[PMK_LEN_MAX]; /* PSK or the second 256 bits of MSK, or the
|
u8 xxkey[PMK_LEN_MAX]; /* PSK or the second 256 bits of MSK, or the
|
||||||
* first 384 bits of MSK */
|
* first 384 bits of MSK */
|
||||||
|
|
|
@ -89,7 +89,8 @@ static int wpa_write_wpa_ie(struct wpa_auth_config *conf, u8 *buf, size_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static u16 wpa_own_rsn_capab(struct wpa_auth_config *conf)
|
static u16 wpa_own_rsn_capab(struct wpa_auth_config *conf,
|
||||||
|
enum mfp_options mfp)
|
||||||
{
|
{
|
||||||
u16 capab = 0;
|
u16 capab = 0;
|
||||||
|
|
||||||
|
@ -99,9 +100,9 @@ static u16 wpa_own_rsn_capab(struct wpa_auth_config *conf)
|
||||||
/* 4 PTKSA replay counters when using WMM */
|
/* 4 PTKSA replay counters when using WMM */
|
||||||
capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
|
capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
|
||||||
}
|
}
|
||||||
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
|
if (mfp != NO_MGMT_FRAME_PROTECTION) {
|
||||||
capab |= WPA_CAPABILITY_MFPC;
|
capab |= WPA_CAPABILITY_MFPC;
|
||||||
if (conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED)
|
if (mfp == MGMT_FRAME_PROTECTION_REQUIRED)
|
||||||
capab |= WPA_CAPABILITY_MFPR;
|
capab |= WPA_CAPABILITY_MFPR;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_OCV
|
#ifdef CONFIG_OCV
|
||||||
|
@ -119,24 +120,19 @@ static u16 wpa_own_rsn_capab(struct wpa_auth_config *conf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
static u8 * rsne_write_data(u8 *buf, size_t len, u8 *pos, int group,
|
||||||
const u8 *pmkid)
|
int pairwise, int key_mgmt, u16 rsn_capab,
|
||||||
|
const u8 *pmkid, enum mfp_options mfp,
|
||||||
|
int group_mgmt_cipher)
|
||||||
{
|
{
|
||||||
struct rsn_ie_hdr *hdr;
|
|
||||||
int num_suites, res;
|
int num_suites, res;
|
||||||
u8 *pos, *count;
|
u8 *count;
|
||||||
u32 suite;
|
u32 suite;
|
||||||
|
|
||||||
hdr = (struct rsn_ie_hdr *) buf;
|
suite = wpa_cipher_to_suite(WPA_PROTO_RSN, group);
|
||||||
hdr->elem_id = WLAN_EID_RSN;
|
|
||||||
WPA_PUT_LE16(hdr->version, RSN_VERSION);
|
|
||||||
pos = (u8 *) (hdr + 1);
|
|
||||||
|
|
||||||
suite = wpa_cipher_to_suite(WPA_PROTO_RSN, conf->wpa_group);
|
|
||||||
if (suite == 0) {
|
if (suite == 0) {
|
||||||
wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).",
|
wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).", group);
|
||||||
conf->wpa_group);
|
return NULL;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
RSN_SELECTOR_PUT(pos, suite);
|
RSN_SELECTOR_PUT(pos, suite);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
|
@ -153,7 +149,7 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_RSN_TESTING */
|
#endif /* CONFIG_RSN_TESTING */
|
||||||
|
|
||||||
res = rsn_cipher_put_suites(pos, conf->rsn_pairwise);
|
res = rsn_cipher_put_suites(pos, pairwise);
|
||||||
num_suites += res;
|
num_suites += res;
|
||||||
pos += res * RSN_SELECTOR_LEN;
|
pos += res * RSN_SELECTOR_LEN;
|
||||||
|
|
||||||
|
@ -167,8 +163,8 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||||
|
|
||||||
if (num_suites == 0) {
|
if (num_suites == 0) {
|
||||||
wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).",
|
wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).",
|
||||||
conf->rsn_pairwise);
|
pairwise);
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
WPA_PUT_LE16(count, num_suites);
|
WPA_PUT_LE16(count, num_suites);
|
||||||
|
|
||||||
|
@ -184,102 +180,102 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_RSN_TESTING */
|
#endif /* CONFIG_RSN_TESTING */
|
||||||
|
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
|
if (key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
|
if (key_mgmt & WPA_KEY_MGMT_PSK) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_IEEE80211R_AP
|
#ifdef CONFIG_IEEE80211R_AP
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
|
if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_SHA384
|
#ifdef CONFIG_SHA384
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) {
|
if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_SHA384 */
|
#endif /* CONFIG_SHA384 */
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
|
if (key_mgmt & WPA_KEY_MGMT_FT_PSK) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211R_AP */
|
#endif /* CONFIG_IEEE80211R_AP */
|
||||||
#ifdef CONFIG_SHA384
|
#ifdef CONFIG_SHA384
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA384) {
|
if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA384) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA384);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA384);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_SHA384 */
|
#endif /* CONFIG_SHA384 */
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
|
if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
|
if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_SAE
|
#ifdef CONFIG_SAE
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
|
if (key_mgmt & WPA_KEY_MGMT_SAE) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
|
if (key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE_EXT_KEY);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE_EXT_KEY);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
|
if (key_mgmt & WPA_KEY_MGMT_FT_SAE) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
|
if (key_mgmt & WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE_EXT_KEY);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE_EXT_KEY);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_SAE */
|
#endif /* CONFIG_SAE */
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
|
if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
|
if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_FILS
|
#ifdef CONFIG_FILS
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FILS_SHA256) {
|
if (key_mgmt & WPA_KEY_MGMT_FILS_SHA256) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FILS_SHA256);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FILS_SHA256);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FILS_SHA384) {
|
if (key_mgmt & WPA_KEY_MGMT_FILS_SHA384) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FILS_SHA384);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FILS_SHA384);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_IEEE80211R_AP
|
#ifdef CONFIG_IEEE80211R_AP
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) {
|
if (key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA256);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA256);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) {
|
if (key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA384);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA384);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
|
@ -287,28 +283,28 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||||
#endif /* CONFIG_IEEE80211R_AP */
|
#endif /* CONFIG_IEEE80211R_AP */
|
||||||
#endif /* CONFIG_FILS */
|
#endif /* CONFIG_FILS */
|
||||||
#ifdef CONFIG_OWE
|
#ifdef CONFIG_OWE
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) {
|
if (key_mgmt & WPA_KEY_MGMT_OWE) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OWE);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OWE);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_OWE */
|
#endif /* CONFIG_OWE */
|
||||||
#ifdef CONFIG_DPP
|
#ifdef CONFIG_DPP
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) {
|
if (key_mgmt & WPA_KEY_MGMT_DPP) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_DPP);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_DPP);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_DPP */
|
#endif /* CONFIG_DPP */
|
||||||
#ifdef CONFIG_HS20
|
#ifdef CONFIG_HS20
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_OSEN) {
|
if (key_mgmt & WPA_KEY_MGMT_OSEN) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OSEN);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OSEN);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_HS20 */
|
#endif /* CONFIG_HS20 */
|
||||||
#ifdef CONFIG_PASN
|
#ifdef CONFIG_PASN
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PASN) {
|
if (key_mgmt & WPA_KEY_MGMT_PASN) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PASN);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PASN);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
|
@ -325,18 +321,18 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||||
|
|
||||||
if (num_suites == 0) {
|
if (num_suites == 0) {
|
||||||
wpa_printf(MSG_DEBUG, "Invalid key management type (%d).",
|
wpa_printf(MSG_DEBUG, "Invalid key management type (%d).",
|
||||||
conf->wpa_key_mgmt);
|
key_mgmt);
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
WPA_PUT_LE16(count, num_suites);
|
WPA_PUT_LE16(count, num_suites);
|
||||||
|
|
||||||
/* RSN Capabilities */
|
/* RSN Capabilities */
|
||||||
WPA_PUT_LE16(pos, wpa_own_rsn_capab(conf));
|
WPA_PUT_LE16(pos, rsn_capab);
|
||||||
pos += 2;
|
pos += 2;
|
||||||
|
|
||||||
if (pmkid) {
|
if (pmkid) {
|
||||||
if (2 + PMKID_LEN > buf + len - pos)
|
if (2 + PMKID_LEN > buf + len - pos)
|
||||||
return -1;
|
return NULL;
|
||||||
/* PMKID Count */
|
/* PMKID Count */
|
||||||
WPA_PUT_LE16(pos, 1);
|
WPA_PUT_LE16(pos, 1);
|
||||||
pos += 2;
|
pos += 2;
|
||||||
|
@ -344,18 +340,19 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||||
pos += PMKID_LEN;
|
pos += PMKID_LEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION &&
|
|
||||||
conf->group_mgmt_cipher != WPA_CIPHER_AES_128_CMAC) {
|
if (mfp != NO_MGMT_FRAME_PROTECTION &&
|
||||||
|
group_mgmt_cipher != WPA_CIPHER_AES_128_CMAC) {
|
||||||
if (2 + 4 > buf + len - pos)
|
if (2 + 4 > buf + len - pos)
|
||||||
return -1;
|
return NULL;
|
||||||
if (pmkid == NULL) {
|
if (!pmkid) {
|
||||||
/* PMKID Count */
|
/* PMKID Count */
|
||||||
WPA_PUT_LE16(pos, 0);
|
WPA_PUT_LE16(pos, 0);
|
||||||
pos += 2;
|
pos += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Management Group Cipher Suite */
|
/* Management Group Cipher Suite */
|
||||||
switch (conf->group_mgmt_cipher) {
|
switch (group_mgmt_cipher) {
|
||||||
case WPA_CIPHER_AES_128_CMAC:
|
case WPA_CIPHER_AES_128_CMAC:
|
||||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
|
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
|
||||||
break;
|
break;
|
||||||
|
@ -371,8 +368,8 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||||
default:
|
default:
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"Invalid group management cipher (0x%x)",
|
"Invalid group management cipher (0x%x)",
|
||||||
conf->group_mgmt_cipher);
|
group_mgmt_cipher);
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
}
|
}
|
||||||
|
@ -384,12 +381,12 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||||
* the element.
|
* the element.
|
||||||
*/
|
*/
|
||||||
int pmkid_count_set = pmkid != NULL;
|
int pmkid_count_set = pmkid != NULL;
|
||||||
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION)
|
if (mfp != NO_MGMT_FRAME_PROTECTION)
|
||||||
pmkid_count_set = 1;
|
pmkid_count_set = 1;
|
||||||
/* PMKID Count */
|
/* PMKID Count */
|
||||||
WPA_PUT_LE16(pos, 0);
|
WPA_PUT_LE16(pos, 0);
|
||||||
pos += 2;
|
pos += 2;
|
||||||
if (conf->ieee80211w == NO_MGMT_FRAME_PROTECTION) {
|
if (mfp == NO_MGMT_FRAME_PROTECTION) {
|
||||||
/* Management Group Cipher Suite */
|
/* Management Group Cipher Suite */
|
||||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
|
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
|
@ -399,6 +396,27 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||||
pos += 17;
|
pos += 17;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_RSN_TESTING */
|
#endif /* CONFIG_RSN_TESTING */
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||||
|
const u8 *pmkid)
|
||||||
|
{
|
||||||
|
struct rsn_ie_hdr *hdr;
|
||||||
|
u8 *pos;
|
||||||
|
|
||||||
|
hdr = (struct rsn_ie_hdr *) buf;
|
||||||
|
hdr->elem_id = WLAN_EID_RSN;
|
||||||
|
WPA_PUT_LE16(hdr->version, RSN_VERSION);
|
||||||
|
pos = (u8 *) (hdr + 1);
|
||||||
|
|
||||||
|
pos = rsne_write_data(buf, len, pos, conf->wpa_group,
|
||||||
|
conf->rsn_pairwise, conf->wpa_key_mgmt,
|
||||||
|
wpa_own_rsn_capab(conf, conf->ieee80211w), pmkid,
|
||||||
|
conf->ieee80211w, conf->group_mgmt_cipher);
|
||||||
|
if (!pos)
|
||||||
|
return -1;
|
||||||
|
|
||||||
hdr->len = (pos - buf) - 2;
|
hdr->len = (pos - buf) - 2;
|
||||||
|
|
||||||
|
@ -406,16 +424,74 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len)
|
static int wpa_write_rsne_override(struct wpa_auth_config *conf, u8 *buf,
|
||||||
|
size_t len)
|
||||||
{
|
{
|
||||||
u8 *pos = buf;
|
u8 *pos, *len_pos;
|
||||||
u32 capab = 0, tmp;
|
|
||||||
size_t flen;
|
|
||||||
|
|
||||||
if (wpa_key_mgmt_sae(conf->wpa_key_mgmt) &&
|
pos = buf;
|
||||||
|
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||||
|
len_pos = pos++;
|
||||||
|
|
||||||
|
WPA_PUT_BE32(pos, RSNE_OVERRIDE_IE_VENDOR_TYPE);
|
||||||
|
pos += 4;
|
||||||
|
|
||||||
|
WPA_PUT_LE16(pos, RSN_VERSION);
|
||||||
|
pos += 2;
|
||||||
|
|
||||||
|
pos = rsne_write_data(buf, len, pos, conf->wpa_group,
|
||||||
|
conf->rsn_override_pairwise,
|
||||||
|
conf->rsn_override_key_mgmt,
|
||||||
|
wpa_own_rsn_capab(conf, conf->rsn_override_mfp),
|
||||||
|
NULL, conf->rsn_override_mfp,
|
||||||
|
conf->group_mgmt_cipher);
|
||||||
|
if (!pos)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*len_pos = (pos - buf) - 2;
|
||||||
|
|
||||||
|
return pos - buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_write_rsne_override_2(struct wpa_auth_config *conf, u8 *buf,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
u8 *pos, *len_pos;
|
||||||
|
|
||||||
|
pos = buf;
|
||||||
|
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||||
|
len_pos = pos++;
|
||||||
|
|
||||||
|
WPA_PUT_BE32(pos, RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
|
||||||
|
pos += 4;
|
||||||
|
|
||||||
|
WPA_PUT_LE16(pos, RSN_VERSION);
|
||||||
|
pos += 2;
|
||||||
|
|
||||||
|
pos = rsne_write_data(buf, len, pos, conf->wpa_group,
|
||||||
|
conf->rsn_override_pairwise_2,
|
||||||
|
conf->rsn_override_key_mgmt_2,
|
||||||
|
wpa_own_rsn_capab(conf, conf->rsn_override_mfp_2),
|
||||||
|
NULL, conf->rsn_override_mfp_2,
|
||||||
|
conf->group_mgmt_cipher);
|
||||||
|
if (!pos)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*len_pos = (pos - buf) - 2;
|
||||||
|
|
||||||
|
return pos - buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static u32 rsnxe_capab(struct wpa_auth_config *conf, int key_mgmt)
|
||||||
|
{
|
||||||
|
u32 capab = 0;
|
||||||
|
|
||||||
|
if (wpa_key_mgmt_sae(key_mgmt) &&
|
||||||
(conf->sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
|
(conf->sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
|
||||||
conf->sae_pwe == SAE_PWE_BOTH || conf->sae_pk ||
|
conf->sae_pwe == SAE_PWE_BOTH || conf->sae_pk ||
|
||||||
wpa_key_mgmt_sae_ext_key(conf->wpa_key_mgmt))) {
|
wpa_key_mgmt_sae_ext_key(key_mgmt))) {
|
||||||
capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
|
capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
|
||||||
#ifdef CONFIG_SAE_PK
|
#ifdef CONFIG_SAE_PK
|
||||||
if (conf->sae_pk)
|
if (conf->sae_pk)
|
||||||
|
@ -432,6 +508,18 @@ int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len)
|
||||||
if (conf->ssid_protection)
|
if (conf->ssid_protection)
|
||||||
capab |= BIT(WLAN_RSNX_CAPAB_SSID_PROTECTION);
|
capab |= BIT(WLAN_RSNX_CAPAB_SSID_PROTECTION);
|
||||||
|
|
||||||
|
return capab;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len)
|
||||||
|
{
|
||||||
|
u8 *pos = buf;
|
||||||
|
u32 capab = 0, tmp;
|
||||||
|
size_t flen;
|
||||||
|
|
||||||
|
capab = rsnxe_capab(conf, conf->wpa_key_mgmt);
|
||||||
|
|
||||||
if (!capab)
|
if (!capab)
|
||||||
return 0; /* no supported extended RSN capabilities */
|
return 0; /* no supported extended RSN capabilities */
|
||||||
tmp = capab;
|
tmp = capab;
|
||||||
|
@ -455,6 +543,42 @@ int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_write_rsnxe_override(struct wpa_auth_config *conf, u8 *buf,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
u8 *pos = buf;
|
||||||
|
u32 capab, tmp;
|
||||||
|
size_t flen;
|
||||||
|
|
||||||
|
capab = rsnxe_capab(conf, conf->rsn_override_key_mgmt |
|
||||||
|
conf->rsn_override_key_mgmt_2);
|
||||||
|
|
||||||
|
if (!capab)
|
||||||
|
return 0; /* no supported extended RSN capabilities */
|
||||||
|
tmp = capab;
|
||||||
|
flen = 0;
|
||||||
|
while (tmp) {
|
||||||
|
flen++;
|
||||||
|
tmp >>= 8;
|
||||||
|
}
|
||||||
|
if (len < 2 + flen)
|
||||||
|
return -1;
|
||||||
|
capab |= flen - 1; /* bit 0-3 = Field length (n - 1) */
|
||||||
|
|
||||||
|
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||||
|
*pos++ = 4 + flen;
|
||||||
|
WPA_PUT_BE32(pos, RSNXE_OVERRIDE_IE_VENDOR_TYPE);
|
||||||
|
pos += 4;
|
||||||
|
|
||||||
|
while (capab) {
|
||||||
|
*pos++ = capab & 0xff;
|
||||||
|
capab >>= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pos - buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static u8 * wpa_write_osen(struct wpa_auth_config *conf, u8 *eid)
|
static u8 * wpa_write_osen(struct wpa_auth_config *conf, u8 *eid)
|
||||||
{
|
{
|
||||||
u8 *len;
|
u8 *len;
|
||||||
|
@ -508,7 +632,7 @@ static u8 * wpa_write_osen(struct wpa_auth_config *conf, u8 *eid)
|
||||||
|
|
||||||
int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
|
int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
|
||||||
{
|
{
|
||||||
u8 *pos, buf[128];
|
u8 *pos, buf[1500];
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
@ -534,17 +658,54 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
|
||||||
pos = wpa_write_osen(&wpa_auth->conf, pos);
|
pos = wpa_write_osen(&wpa_auth->conf, pos);
|
||||||
}
|
}
|
||||||
if (wpa_auth->conf.wpa & WPA_PROTO_RSN) {
|
if (wpa_auth->conf.wpa & WPA_PROTO_RSN) {
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
if (wpa_auth->conf.rsne_override_set) {
|
||||||
|
wpa_hexdump(MSG_DEBUG,
|
||||||
|
"RSN: Forced own RSNE for testing",
|
||||||
|
wpa_auth->conf.rsne_override,
|
||||||
|
wpa_auth->conf.rsne_override_len);
|
||||||
|
if (sizeof(buf) - (pos - buf) <
|
||||||
|
wpa_auth->conf.rsne_override_len)
|
||||||
|
return -1;
|
||||||
|
os_memcpy(pos, wpa_auth->conf.rsne_override,
|
||||||
|
wpa_auth->conf.rsne_override_len);
|
||||||
|
pos += wpa_auth->conf.rsne_override_len;
|
||||||
|
goto rsnxe;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
res = wpa_write_rsn_ie(&wpa_auth->conf,
|
res = wpa_write_rsn_ie(&wpa_auth->conf,
|
||||||
pos, buf + sizeof(buf) - pos, NULL);
|
pos, buf + sizeof(buf) - pos, NULL);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
return res;
|
return res;
|
||||||
pos += res;
|
pos += res;
|
||||||
res = wpa_write_rsnxe(&wpa_auth->conf, pos,
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
buf + sizeof(buf) - pos);
|
rsnxe:
|
||||||
|
if (wpa_auth->conf.rsnxe_override_set) {
|
||||||
|
wpa_hexdump(MSG_DEBUG,
|
||||||
|
"RSN: Forced own RSNXE for testing",
|
||||||
|
wpa_auth->conf.rsnxe_override,
|
||||||
|
wpa_auth->conf.rsnxe_override_len);
|
||||||
|
if (sizeof(buf) - (pos - buf) <
|
||||||
|
wpa_auth->conf.rsnxe_override_len)
|
||||||
|
return -1;
|
||||||
|
os_memcpy(pos, wpa_auth->conf.rsnxe_override,
|
||||||
|
wpa_auth->conf.rsnxe_override_len);
|
||||||
|
pos += wpa_auth->conf.rsnxe_override_len;
|
||||||
|
goto fte;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
if (wpa_auth->conf.rsn_override_omit_rsnxe)
|
||||||
|
res = 0;
|
||||||
|
else
|
||||||
|
res = wpa_write_rsnxe(&wpa_auth->conf, pos,
|
||||||
|
buf + sizeof(buf) - pos);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
return res;
|
return res;
|
||||||
pos += res;
|
pos += res;
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
fte:
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
#ifdef CONFIG_IEEE80211R_AP
|
#ifdef CONFIG_IEEE80211R_AP
|
||||||
if (wpa_key_mgmt_ft(wpa_auth->conf.wpa_key_mgmt)) {
|
if (wpa_key_mgmt_ft(wpa_auth->conf.wpa_key_mgmt)) {
|
||||||
res = wpa_write_mdie(&wpa_auth->conf, pos,
|
res = wpa_write_mdie(&wpa_auth->conf, pos,
|
||||||
|
@ -561,7 +722,87 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
|
||||||
return res;
|
return res;
|
||||||
pos += res;
|
pos += res;
|
||||||
}
|
}
|
||||||
|
if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
|
||||||
|
wpa_auth->conf.rsn_override_key_mgmt) {
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
if (wpa_auth->conf.rsnoe_override_set) {
|
||||||
|
wpa_hexdump(MSG_DEBUG,
|
||||||
|
"RSN: Forced own RSNOE for testing",
|
||||||
|
wpa_auth->conf.rsnoe_override,
|
||||||
|
wpa_auth->conf.rsnoe_override_len);
|
||||||
|
if (sizeof(buf) - (pos - buf) <
|
||||||
|
wpa_auth->conf.rsnoe_override_len)
|
||||||
|
return -1;
|
||||||
|
os_memcpy(pos, wpa_auth->conf.rsnoe_override,
|
||||||
|
wpa_auth->conf.rsnoe_override_len);
|
||||||
|
pos += wpa_auth->conf.rsnoe_override_len;
|
||||||
|
goto rsno2e;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
res = wpa_write_rsne_override(&wpa_auth->conf,
|
||||||
|
pos, buf + sizeof(buf) - pos);
|
||||||
|
if (res < 0)
|
||||||
|
return res;
|
||||||
|
pos += res;
|
||||||
|
}
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
rsno2e:
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
|
||||||
|
wpa_auth->conf.rsn_override_key_mgmt_2) {
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
if (wpa_auth->conf.rsno2e_override_set) {
|
||||||
|
wpa_hexdump(MSG_DEBUG,
|
||||||
|
"RSN: Forced own RSNO2E for testing",
|
||||||
|
wpa_auth->conf.rsno2e_override,
|
||||||
|
wpa_auth->conf.rsno2e_override_len);
|
||||||
|
if (sizeof(buf) - (pos - buf) <
|
||||||
|
wpa_auth->conf.rsno2e_override_len)
|
||||||
|
return -1;
|
||||||
|
os_memcpy(pos, wpa_auth->conf.rsno2e_override,
|
||||||
|
wpa_auth->conf.rsno2e_override_len);
|
||||||
|
pos += wpa_auth->conf.rsno2e_override_len;
|
||||||
|
goto rsnxoe;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
res = wpa_write_rsne_override_2(&wpa_auth->conf, pos,
|
||||||
|
buf + sizeof(buf) - pos);
|
||||||
|
if (res < 0)
|
||||||
|
return res;
|
||||||
|
pos += res;
|
||||||
|
}
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
rsnxoe:
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
|
||||||
|
(wpa_auth->conf.rsn_override_key_mgmt ||
|
||||||
|
wpa_auth->conf.rsn_override_key_mgmt_2)) {
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
if (wpa_auth->conf.rsnxoe_override_set) {
|
||||||
|
wpa_hexdump(MSG_DEBUG,
|
||||||
|
"RSN: Forced own RSNXOE for testing",
|
||||||
|
wpa_auth->conf.rsnxoe_override,
|
||||||
|
wpa_auth->conf.rsnxoe_override_len);
|
||||||
|
if (sizeof(buf) - (pos - buf) <
|
||||||
|
wpa_auth->conf.rsnxoe_override_len)
|
||||||
|
return -1;
|
||||||
|
os_memcpy(pos, wpa_auth->conf.rsnxoe_override,
|
||||||
|
wpa_auth->conf.rsnxoe_override_len);
|
||||||
|
pos += wpa_auth->conf.rsnxoe_override_len;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
res = wpa_write_rsnxe_override(&wpa_auth->conf, pos,
|
||||||
|
buf + sizeof(buf) - pos);
|
||||||
|
if (res < 0)
|
||||||
|
return res;
|
||||||
|
pos += res;
|
||||||
|
}
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
done:
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
|
wpa_hexdump(MSG_DEBUG, "RSN: Own IEs", buf, pos - buf);
|
||||||
os_free(wpa_auth->wpa_ie);
|
os_free(wpa_auth->wpa_ie);
|
||||||
wpa_auth->wpa_ie = os_malloc(pos - buf);
|
wpa_auth->wpa_ie = os_malloc(pos - buf);
|
||||||
if (wpa_auth->wpa_ie == NULL)
|
if (wpa_auth->wpa_ie == NULL)
|
||||||
|
@ -773,7 +1014,13 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
||||||
return WPA_INVALID_GROUP;
|
return WPA_INVALID_GROUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
key_mgmt = data.key_mgmt & wpa_auth->conf.wpa_key_mgmt;
|
if (sm->rsn_override_2)
|
||||||
|
key_mgmt = data.key_mgmt &
|
||||||
|
wpa_auth->conf.rsn_override_key_mgmt_2;
|
||||||
|
else if (sm->rsn_override)
|
||||||
|
key_mgmt = data.key_mgmt & wpa_auth->conf.rsn_override_key_mgmt;
|
||||||
|
else
|
||||||
|
key_mgmt = data.key_mgmt & wpa_auth->conf.wpa_key_mgmt;
|
||||||
if (!key_mgmt) {
|
if (!key_mgmt) {
|
||||||
wpa_printf(MSG_DEBUG, "Invalid WPA key mgmt (0x%x) from "
|
wpa_printf(MSG_DEBUG, "Invalid WPA key mgmt (0x%x) from "
|
||||||
MACSTR, data.key_mgmt, MAC2STR(sm->addr));
|
MACSTR, data.key_mgmt, MAC2STR(sm->addr));
|
||||||
|
@ -842,7 +1089,13 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
||||||
else
|
else
|
||||||
sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
|
sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
|
||||||
|
|
||||||
if (version == WPA_PROTO_RSN)
|
if (version == WPA_PROTO_RSN && sm->rsn_override_2)
|
||||||
|
ciphers = data.pairwise_cipher &
|
||||||
|
wpa_auth->conf.rsn_override_pairwise_2;
|
||||||
|
else if (version == WPA_PROTO_RSN && sm->rsn_override)
|
||||||
|
ciphers = data.pairwise_cipher &
|
||||||
|
wpa_auth->conf.rsn_override_pairwise;
|
||||||
|
else if (version == WPA_PROTO_RSN)
|
||||||
ciphers = data.pairwise_cipher & wpa_auth->conf.rsn_pairwise;
|
ciphers = data.pairwise_cipher & wpa_auth->conf.rsn_pairwise;
|
||||||
else
|
else
|
||||||
ciphers = data.pairwise_cipher & wpa_auth->conf.wpa_pairwise;
|
ciphers = data.pairwise_cipher & wpa_auth->conf.wpa_pairwise;
|
||||||
|
@ -1229,7 +1482,7 @@ bool wpa_auth_write_fd_rsn_info(struct wpa_authenticator *wpa_auth,
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* RSN Capability (B0..B15) */
|
/* RSN Capability (B0..B15) */
|
||||||
WPA_PUT_LE16(pos, wpa_own_rsn_capab(conf));
|
WPA_PUT_LE16(pos, wpa_own_rsn_capab(conf, conf->ieee80211w));
|
||||||
pos += 2;
|
pos += 2;
|
||||||
|
|
||||||
/* Group Data Cipher Suite Selector (B16..B21) */
|
/* Group Data Cipher Suite Selector (B16..B21) */
|
||||||
|
|
|
@ -83,13 +83,16 @@ _make_dirs:
|
||||||
@mkdir -p $(sort $(_DIRS))
|
@mkdir -p $(sort $(_DIRS))
|
||||||
|
|
||||||
$(BUILDDIR)/$(PROJ)/src/%.o: $(ROOTDIR)src/%.c $(CONFIG_FILE) | _make_dirs
|
$(BUILDDIR)/$(PROJ)/src/%.o: $(ROOTDIR)src/%.c $(CONFIG_FILE) | _make_dirs
|
||||||
|
@echo $(CURDIR): '$(CC) -c -o $@ $(CFLAGS) $<' >$@.cmd
|
||||||
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
|
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
|
||||||
@$(E) " CC " $<
|
@$(E) " CC " $<
|
||||||
$(BUILDDIR)/$(PROJ)/%.o: %.c $(CONFIG_FILE) | _make_dirs
|
$(BUILDDIR)/$(PROJ)/%.o: %.c $(CONFIG_FILE) | _make_dirs
|
||||||
|
@echo $(CURDIR): '$(CC) -c -o $@ $(CFLAGS) $<' >$@.cmd
|
||||||
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
|
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
|
||||||
@$(E) " CC " $<
|
@$(E) " CC " $<
|
||||||
# for the fuzzing tests
|
# for the fuzzing tests
|
||||||
$(BUILDDIR)/$(PROJ)/wpa_supplicant/%.o: $(ROOTDIR)wpa_supplicant/%.c $(CONFIG_FILE) | _make_dirs
|
$(BUILDDIR)/$(PROJ)/wpa_supplicant/%.o: $(ROOTDIR)wpa_supplicant/%.c $(CONFIG_FILE) | _make_dirs
|
||||||
|
@echo $(CURDIR): '$(CC) -c -o $@ $(CFLAGS) $<' >$@.cmd
|
||||||
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
|
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
|
||||||
@$(E) " CC " $<
|
@$(E) " CC " $<
|
||||||
|
|
||||||
|
|
|
@ -532,4 +532,9 @@ enum sae_pwe {
|
||||||
SAE_PWE_NOT_SET = 4,
|
SAE_PWE_NOT_SET = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define USEC_80211_TU 1024
|
||||||
|
|
||||||
|
#define USEC_TO_TU(m) ((m) / USEC_80211_TU)
|
||||||
|
#define TU_TO_USEC(m) ((m) * USEC_80211_TU)
|
||||||
|
|
||||||
#endif /* DEFS_H */
|
#endif /* DEFS_H */
|
||||||
|
|
|
@ -1035,6 +1035,10 @@ struct wpabuf * dpp_build_conf_req_helper(struct dpp_authentication *auth,
|
||||||
json_value_sep(json);
|
json_value_sep(json);
|
||||||
json_add_string(json, "pkcs10", csr);
|
json_add_string(json, "pkcs10", csr);
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_DPP3
|
||||||
|
json_value_sep(json);
|
||||||
|
json_add_int(json, "capabilities", DPP_ENROLLEE_CAPAB_SAE_PW_ID);
|
||||||
|
#endif /* CONFIG_DPP3 */
|
||||||
if (extra_name && extra_value && extra_name[0] && extra_value[0]) {
|
if (extra_name && extra_value && extra_name[0] && extra_value[0]) {
|
||||||
json_value_sep(json);
|
json_value_sep(json);
|
||||||
wpabuf_printf(json, "\"%s\":%s", extra_name, extra_value);
|
wpabuf_printf(json, "\"%s\":%s", extra_name, extra_value);
|
||||||
|
@ -1139,8 +1143,18 @@ int dpp_configuration_valid(const struct dpp_configuration *conf)
|
||||||
return 0;
|
return 0;
|
||||||
if (dpp_akm_psk(conf->akm) && !conf->passphrase && !conf->psk_set)
|
if (dpp_akm_psk(conf->akm) && !conf->passphrase && !conf->psk_set)
|
||||||
return 0;
|
return 0;
|
||||||
|
if (dpp_akm_psk(conf->akm) && conf->passphrase) {
|
||||||
|
size_t len = os_strlen(conf->passphrase);
|
||||||
|
|
||||||
|
if (len > 63 || len < 8)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (dpp_akm_sae(conf->akm) && !conf->passphrase)
|
if (dpp_akm_sae(conf->akm) && !conf->passphrase)
|
||||||
return 0;
|
return 0;
|
||||||
|
#ifdef CONFIG_DPP3
|
||||||
|
if (conf->idpass && (!conf->passphrase || !dpp_akm_sae(conf->akm)))
|
||||||
|
return 0;
|
||||||
|
#endif /* CONFIG_DPP3 */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1150,6 +1164,9 @@ void dpp_configuration_free(struct dpp_configuration *conf)
|
||||||
if (!conf)
|
if (!conf)
|
||||||
return;
|
return;
|
||||||
str_clear_free(conf->passphrase);
|
str_clear_free(conf->passphrase);
|
||||||
|
#ifdef CONFIG_DPP3
|
||||||
|
os_free(conf->idpass);
|
||||||
|
#endif /* CONFIG_DPP3 */
|
||||||
os_free(conf->group_id);
|
os_free(conf->group_id);
|
||||||
os_free(conf->csrattrs);
|
os_free(conf->csrattrs);
|
||||||
os_free(conf->extra_name);
|
os_free(conf->extra_name);
|
||||||
|
@ -1228,14 +1245,28 @@ static int dpp_configuration_parse_helper(struct dpp_authentication *auth,
|
||||||
end = os_strchr(pos, ' ');
|
end = os_strchr(pos, ' ');
|
||||||
pass_len = end ? (size_t) (end - pos) : os_strlen(pos);
|
pass_len = end ? (size_t) (end - pos) : os_strlen(pos);
|
||||||
pass_len /= 2;
|
pass_len /= 2;
|
||||||
if (pass_len > 63 || pass_len < 8)
|
|
||||||
goto fail;
|
|
||||||
conf->passphrase = os_zalloc(pass_len + 1);
|
conf->passphrase = os_zalloc(pass_len + 1);
|
||||||
if (!conf->passphrase ||
|
if (!conf->passphrase ||
|
||||||
hexstr2bin(pos, (u8 *) conf->passphrase, pass_len) < 0)
|
hexstr2bin(pos, (u8 *) conf->passphrase, pass_len) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP3
|
||||||
|
pos = os_strstr(cmd, " idpass=");
|
||||||
|
if (pos) {
|
||||||
|
size_t idpass_len;
|
||||||
|
|
||||||
|
pos += 8;
|
||||||
|
end = os_strchr(pos, ' ');
|
||||||
|
idpass_len = end ? (size_t) (end - pos) : os_strlen(pos);
|
||||||
|
idpass_len /= 2;
|
||||||
|
conf->idpass = os_zalloc(idpass_len + 1);
|
||||||
|
if (!conf->idpass ||
|
||||||
|
hexstr2bin(pos, (u8 *) conf->idpass, idpass_len) < 0)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DPP3 */
|
||||||
|
|
||||||
pos = os_strstr(cmd, " psk=");
|
pos = os_strstr(cmd, " psk=");
|
||||||
if (pos) {
|
if (pos) {
|
||||||
pos += 5;
|
pos += 5;
|
||||||
|
@ -1595,6 +1626,13 @@ static void dpp_build_legacy_cred_params(struct wpabuf *buf,
|
||||||
if (conf->passphrase && os_strlen(conf->passphrase) < 64) {
|
if (conf->passphrase && os_strlen(conf->passphrase) < 64) {
|
||||||
json_add_string_escape(buf, "pass", conf->passphrase,
|
json_add_string_escape(buf, "pass", conf->passphrase,
|
||||||
os_strlen(conf->passphrase));
|
os_strlen(conf->passphrase));
|
||||||
|
#ifdef CONFIG_DPP3
|
||||||
|
if (conf->idpass) {
|
||||||
|
json_value_sep(buf);
|
||||||
|
json_add_string_escape(buf, "idpass", conf->idpass,
|
||||||
|
os_strlen(conf->idpass));
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DPP3 */
|
||||||
} else if (conf->psk_set) {
|
} else if (conf->psk_set) {
|
||||||
char psk[2 * sizeof(conf->psk) + 1];
|
char psk[2 * sizeof(conf->psk) + 1];
|
||||||
|
|
||||||
|
@ -1917,6 +1955,16 @@ dpp_build_conf_obj_legacy(struct dpp_authentication *auth,
|
||||||
const char *akm_str;
|
const char *akm_str;
|
||||||
size_t len = 1000;
|
size_t len = 1000;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP3
|
||||||
|
if (conf->idpass &&
|
||||||
|
!(auth->enrollee_capabilities & DPP_ENROLLEE_CAPAB_SAE_PW_ID)) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: Enrollee does not support SAE Password Identifier - cannot generate config object");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DPP3 */
|
||||||
|
|
||||||
if (conf->extra_name && conf->extra_value)
|
if (conf->extra_name && conf->extra_value)
|
||||||
len += 10 + os_strlen(conf->extra_name) +
|
len += 10 + os_strlen(conf->extra_name) +
|
||||||
os_strlen(conf->extra_value);
|
os_strlen(conf->extra_value);
|
||||||
|
@ -2535,6 +2583,18 @@ dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start,
|
||||||
cont:
|
cont:
|
||||||
#endif /* CONFIG_DPP2 */
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP3
|
||||||
|
token = json_get_member(root, "capabilities");
|
||||||
|
if (token && token->type == JSON_NUMBER) {
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: capabilities = 0x%x",
|
||||||
|
token->number);
|
||||||
|
wpa_msg(auth->msg_ctx, MSG_INFO,
|
||||||
|
DPP_EVENT_ENROLLEE_CAPABILITY "%d",
|
||||||
|
token->number);
|
||||||
|
auth->enrollee_capabilities = token->number;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DPP3 */
|
||||||
|
|
||||||
resp = dpp_build_conf_resp(auth, e_nonce, e_nonce_len, netrole,
|
resp = dpp_build_conf_resp(auth, e_nonce, e_nonce_len, netrole,
|
||||||
cert_req);
|
cert_req);
|
||||||
|
|
||||||
|
@ -2558,13 +2618,25 @@ static int dpp_parse_cred_legacy(struct dpp_config_obj *conf,
|
||||||
|
|
||||||
if (pass && pass->type == JSON_STRING) {
|
if (pass && pass->type == JSON_STRING) {
|
||||||
size_t len = os_strlen(pass->string);
|
size_t len = os_strlen(pass->string);
|
||||||
|
#ifdef CONFIG_DPP3
|
||||||
|
struct json_token *saepi = json_get_member(cred, "idpass");
|
||||||
|
#endif /* CONFIG_DPP3 */
|
||||||
|
|
||||||
wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Legacy passphrase",
|
wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Legacy passphrase",
|
||||||
pass->string, len);
|
pass->string, len);
|
||||||
if (len < 8 || len > 63)
|
if (dpp_akm_psk(conf->akm) && (len < 8 || len > 63)) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: Unexpected pass length %zu for a config object that includes PSK",
|
||||||
|
len);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
os_strlcpy(conf->passphrase, pass->string,
|
os_strlcpy(conf->passphrase, pass->string,
|
||||||
sizeof(conf->passphrase));
|
sizeof(conf->passphrase));
|
||||||
|
#ifdef CONFIG_DPP3
|
||||||
|
if (saepi && saepi->type == JSON_STRING)
|
||||||
|
os_strlcpy(conf->password_id, saepi->string,
|
||||||
|
sizeof(conf->password_id));
|
||||||
|
#endif /* CONFIG_DPP3 */
|
||||||
} else if (psk_hex && psk_hex->type == JSON_STRING) {
|
} else if (psk_hex && psk_hex->type == JSON_STRING) {
|
||||||
if (dpp_akm_sae(conf->akm) && !dpp_akm_psk(conf->akm)) {
|
if (dpp_akm_sae(conf->akm) && !dpp_akm_psk(conf->akm)) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
|
|
|
@ -134,6 +134,9 @@ enum dpp_connector_key {
|
||||||
#define DPP_MAX_SHARED_SECRET_LEN 66
|
#define DPP_MAX_SHARED_SECRET_LEN 66
|
||||||
#define DPP_CP_LEN 64
|
#define DPP_CP_LEN 64
|
||||||
|
|
||||||
|
/* DPP Configuration Request - Enrollee Capabilities */
|
||||||
|
#define DPP_ENROLLEE_CAPAB_SAE_PW_ID BIT(0)
|
||||||
|
|
||||||
struct dpp_curve_params {
|
struct dpp_curve_params {
|
||||||
const char *name;
|
const char *name;
|
||||||
size_t hash_len;
|
size_t hash_len;
|
||||||
|
@ -260,6 +263,7 @@ struct dpp_configuration {
|
||||||
|
|
||||||
/* For legacy configuration */
|
/* For legacy configuration */
|
||||||
char *passphrase;
|
char *passphrase;
|
||||||
|
char *idpass;
|
||||||
u8 psk[32];
|
u8 psk[32];
|
||||||
int psk_set;
|
int psk_set;
|
||||||
|
|
||||||
|
@ -356,6 +360,9 @@ struct dpp_authentication {
|
||||||
u8 ssid_len;
|
u8 ssid_len;
|
||||||
int ssid_charset;
|
int ssid_charset;
|
||||||
char passphrase[64];
|
char passphrase[64];
|
||||||
|
#ifdef CONFIG_DPP3
|
||||||
|
char password_id[64];
|
||||||
|
#endif /* CONFIG_DPP3 */
|
||||||
u8 psk[PMK_LEN];
|
u8 psk[PMK_LEN];
|
||||||
int psk_set;
|
int psk_set;
|
||||||
enum dpp_akm akm;
|
enum dpp_akm akm;
|
||||||
|
@ -393,6 +400,7 @@ struct dpp_authentication {
|
||||||
char *e_name;
|
char *e_name;
|
||||||
char *e_mud_url;
|
char *e_mud_url;
|
||||||
int *e_band_support;
|
int *e_band_support;
|
||||||
|
unsigned int enrollee_capabilities;
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
char *config_obj_override;
|
char *config_obj_override;
|
||||||
char *discovery_override;
|
char *discovery_override;
|
||||||
|
|
|
@ -1033,3 +1033,18 @@ bool is_punct_bitmap_valid(u16 bw, u16 pri_ch_bit_pos, u16 punct_bitmap)
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool chan_in_current_hw_info(struct hostapd_multi_hw_info *current_hw_info,
|
||||||
|
struct hostapd_channel_data *chan)
|
||||||
|
{
|
||||||
|
/* Assuming that if current_hw_info is not set full
|
||||||
|
* iface->current_mode->channels[] can be used to scan for channels,
|
||||||
|
* hence we return true.
|
||||||
|
*/
|
||||||
|
if (!current_hw_info)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return current_hw_info->start_freq <= chan->freq &&
|
||||||
|
current_hw_info->end_freq >= chan->freq;
|
||||||
|
}
|
||||||
|
|
|
@ -58,5 +58,7 @@ int chan_bw_allowed(const struct hostapd_channel_data *chan, u32 bw,
|
||||||
int ht40_plus, int pri);
|
int ht40_plus, int pri);
|
||||||
int chan_pri_allowed(const struct hostapd_channel_data *chan);
|
int chan_pri_allowed(const struct hostapd_channel_data *chan);
|
||||||
bool is_punct_bitmap_valid(u16 bw, u16 pri_ch_bit_pos, u16 punct_bitmap);
|
bool is_punct_bitmap_valid(u16 bw, u16 pri_ch_bit_pos, u16 punct_bitmap);
|
||||||
|
bool chan_in_current_hw_info(struct hostapd_multi_hw_info *current_hw_info,
|
||||||
|
struct hostapd_channel_data *chan);
|
||||||
|
|
||||||
#endif /* HW_FEATURES_COMMON_H */
|
#endif /* HW_FEATURES_COMMON_H */
|
||||||
|
|
|
@ -140,6 +140,28 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
|
||||||
elems->sae_pk = pos + 4;
|
elems->sae_pk = pos + 4;
|
||||||
elems->sae_pk_len = elen - 4;
|
elems->sae_pk_len = elen - 4;
|
||||||
break;
|
break;
|
||||||
|
case WFA_RSNE_OVERRIDE_OUI_TYPE:
|
||||||
|
elems->rsne_override = pos;
|
||||||
|
elems->rsne_override_len = elen;
|
||||||
|
break;
|
||||||
|
case WFA_RSNE_OVERRIDE_2_OUI_TYPE:
|
||||||
|
elems->rsne_override_2 = pos;
|
||||||
|
elems->rsne_override_2_len = elen;
|
||||||
|
break;
|
||||||
|
case WFA_RSN_SELECTION_OUI_TYPE:
|
||||||
|
if (elen < 4 + 1) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"Too short RSN Selection element ignored");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
elems->rsn_selection = pos + 4;
|
||||||
|
elems->rsn_selection_len = elen - 4;
|
||||||
|
break;
|
||||||
|
case P2P2_OUI_TYPE:
|
||||||
|
/* Wi-Fi Alliance - P2P2 IE */
|
||||||
|
elems->p2p2_ie = pos;
|
||||||
|
elems->p2p2_ie_len = elen;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
wpa_printf(MSG_MSGDUMP, "Unknown WFA "
|
wpa_printf(MSG_MSGDUMP, "Unknown WFA "
|
||||||
"information element ignored "
|
"information element ignored "
|
||||||
|
@ -3123,8 +3145,12 @@ bool ieee802_11_rsnx_capab_len(const u8 *rsnxe, size_t rsnxe_len,
|
||||||
|
|
||||||
bool ieee802_11_rsnx_capab(const u8 *rsnxe, unsigned int capab)
|
bool ieee802_11_rsnx_capab(const u8 *rsnxe, unsigned int capab)
|
||||||
{
|
{
|
||||||
return ieee802_11_rsnx_capab_len(rsnxe ? rsnxe + 2 : NULL,
|
if (!rsnxe)
|
||||||
rsnxe ? rsnxe[1] : 0, capab);
|
return false;
|
||||||
|
if (rsnxe[0] == WLAN_EID_VENDOR_SPECIFIC && rsnxe[1] >= 4 + 1)
|
||||||
|
return ieee802_11_rsnx_capab_len(rsnxe + 2 + 4, rsnxe[1] - 4,
|
||||||
|
capab);
|
||||||
|
return ieee802_11_rsnx_capab_len(rsnxe + 2, rsnxe[1], capab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,7 @@ struct ieee802_11_elems {
|
||||||
const u8 *vendor_ht_cap;
|
const u8 *vendor_ht_cap;
|
||||||
const u8 *vendor_vht;
|
const u8 *vendor_vht;
|
||||||
const u8 *p2p;
|
const u8 *p2p;
|
||||||
|
const u8 *p2p2_ie;
|
||||||
const u8 *wfd;
|
const u8 *wfd;
|
||||||
const u8 *link_id;
|
const u8 *link_id;
|
||||||
const u8 *interworking;
|
const u8 *interworking;
|
||||||
|
@ -116,6 +117,9 @@ struct ieee802_11_elems {
|
||||||
const u8 *prior_access_mle;
|
const u8 *prior_access_mle;
|
||||||
const u8 *mbssid_known_bss;
|
const u8 *mbssid_known_bss;
|
||||||
const u8 *mbssid;
|
const u8 *mbssid;
|
||||||
|
const u8 *rsne_override;
|
||||||
|
const u8 *rsne_override_2;
|
||||||
|
const u8 *rsn_selection;
|
||||||
|
|
||||||
u8 ssid_len;
|
u8 ssid_len;
|
||||||
u8 supp_rates_len;
|
u8 supp_rates_len;
|
||||||
|
@ -136,6 +140,7 @@ struct ieee802_11_elems {
|
||||||
u8 vendor_ht_cap_len;
|
u8 vendor_ht_cap_len;
|
||||||
u8 vendor_vht_len;
|
u8 vendor_vht_len;
|
||||||
u8 p2p_len;
|
u8 p2p_len;
|
||||||
|
u8 p2p2_ie_len;
|
||||||
u8 wfd_len;
|
u8 wfd_len;
|
||||||
u8 interworking_len;
|
u8 interworking_len;
|
||||||
u8 qos_map_set_len;
|
u8 qos_map_set_len;
|
||||||
|
@ -179,6 +184,9 @@ struct ieee802_11_elems {
|
||||||
size_t prior_access_mle_len;
|
size_t prior_access_mle_len;
|
||||||
u8 mbssid_known_bss_len;
|
u8 mbssid_known_bss_len;
|
||||||
u8 mbssid_len;
|
u8 mbssid_len;
|
||||||
|
size_t rsne_override_len;
|
||||||
|
size_t rsne_override_2_len;
|
||||||
|
size_t rsn_selection_len;
|
||||||
|
|
||||||
struct mb_ies_info mb_ies;
|
struct mb_ies_info mb_ies;
|
||||||
|
|
||||||
|
|
|
@ -504,6 +504,7 @@
|
||||||
#define WLAN_EID_EXT_HE_MU_EDCA_PARAMS 38
|
#define WLAN_EID_EXT_HE_MU_EDCA_PARAMS 38
|
||||||
#define WLAN_EID_EXT_SPATIAL_REUSE 39
|
#define WLAN_EID_EXT_SPATIAL_REUSE 39
|
||||||
#define WLAN_EID_EXT_COLOR_CHANGE_ANNOUNCEMENT 42
|
#define WLAN_EID_EXT_COLOR_CHANGE_ANNOUNCEMENT 42
|
||||||
|
#define WLAN_EID_EXT_MAX_CHANNEL_SWITCH_TIME 52
|
||||||
#define WLAN_EID_EXT_OCV_OCI 54
|
#define WLAN_EID_EXT_OCV_OCI 54
|
||||||
#define WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION 55
|
#define WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION 55
|
||||||
#define WLAN_EID_EXT_NON_INHERITANCE 56
|
#define WLAN_EID_EXT_NON_INHERITANCE 56
|
||||||
|
@ -524,6 +525,7 @@
|
||||||
#define WLAN_EID_EXT_MULTI_LINK_TRAFFIC_INDICATION 110
|
#define WLAN_EID_EXT_MULTI_LINK_TRAFFIC_INDICATION 110
|
||||||
#define WLAN_EID_EXT_QOS_CHARACTERISTICS 113
|
#define WLAN_EID_EXT_QOS_CHARACTERISTICS 113
|
||||||
#define WLAN_EID_EXT_AKM_SUITE_SELECTOR 114
|
#define WLAN_EID_EXT_AKM_SUITE_SELECTOR 114
|
||||||
|
#define WLAN_EID_EXT_BANDWIDTH_INDICATION 135
|
||||||
|
|
||||||
/* Extended Capabilities field */
|
/* Extended Capabilities field */
|
||||||
#define WLAN_EXT_CAPAB_20_40_COEX 0
|
#define WLAN_EXT_CAPAB_20_40_COEX 0
|
||||||
|
@ -1425,6 +1427,7 @@ struct ieee80211_ampe_ie {
|
||||||
#define WPS_IE_VENDOR_TYPE 0x0050f204
|
#define WPS_IE_VENDOR_TYPE 0x0050f204
|
||||||
#define OUI_WFA 0x506f9a
|
#define OUI_WFA 0x506f9a
|
||||||
#define P2P_IE_VENDOR_TYPE 0x506f9a09
|
#define P2P_IE_VENDOR_TYPE 0x506f9a09
|
||||||
|
#define P2P2_IE_VENDOR_TYPE 0x506f9a28
|
||||||
#define WFD_IE_VENDOR_TYPE 0x506f9a0a
|
#define WFD_IE_VENDOR_TYPE 0x506f9a0a
|
||||||
#define WFD_OUI_TYPE 10
|
#define WFD_OUI_TYPE 10
|
||||||
#define HS20_IE_VENDOR_TYPE 0x506f9a10
|
#define HS20_IE_VENDOR_TYPE 0x506f9a10
|
||||||
|
@ -1446,6 +1449,14 @@ struct ieee80211_ampe_ie {
|
||||||
#define QM_IE_OUI_TYPE 0x22
|
#define QM_IE_OUI_TYPE 0x22
|
||||||
#define WFA_CAPA_IE_VENDOR_TYPE 0x506f9a23
|
#define WFA_CAPA_IE_VENDOR_TYPE 0x506f9a23
|
||||||
#define WFA_CAPA_OUI_TYPE 0x23
|
#define WFA_CAPA_OUI_TYPE 0x23
|
||||||
|
#define WFA_RSNE_OVERRIDE_OUI_TYPE 0x29
|
||||||
|
#define WFA_RSNE_OVERRIDE_2_OUI_TYPE 0x2a
|
||||||
|
#define WFA_RSNXE_OVERRIDE_OUI_TYPE 0x2b
|
||||||
|
#define WFA_RSN_SELECTION_OUI_TYPE 0x2c
|
||||||
|
#define RSNE_OVERRIDE_IE_VENDOR_TYPE 0x506f9a29
|
||||||
|
#define RSNE_OVERRIDE_2_IE_VENDOR_TYPE 0x506f9a2a
|
||||||
|
#define RSNXE_OVERRIDE_IE_VENDOR_TYPE 0x506f9a2b
|
||||||
|
#define RSN_SELECTION_IE_VENDOR_TYPE 0x506f9a2c
|
||||||
|
|
||||||
#define MULTI_AP_SUB_ELEM_TYPE 0x06
|
#define MULTI_AP_SUB_ELEM_TYPE 0x06
|
||||||
#define MULTI_AP_PROFILE_SUB_ELEM_TYPE 0x07
|
#define MULTI_AP_PROFILE_SUB_ELEM_TYPE 0x07
|
||||||
|
@ -1710,6 +1721,7 @@ enum mbo_transition_reject_reason {
|
||||||
/* Wi-Fi Direct (P2P) */
|
/* Wi-Fi Direct (P2P) */
|
||||||
|
|
||||||
#define P2P_OUI_TYPE 9
|
#define P2P_OUI_TYPE 9
|
||||||
|
#define P2P2_OUI_TYPE 0x28
|
||||||
|
|
||||||
enum p2p_attr_id {
|
enum p2p_attr_id {
|
||||||
P2P_ATTR_STATUS = 0,
|
P2P_ATTR_STATUS = 0,
|
||||||
|
@ -1740,6 +1752,13 @@ enum p2p_attr_id {
|
||||||
P2P_ATTR_SESSION_ID = 26,
|
P2P_ATTR_SESSION_ID = 26,
|
||||||
P2P_ATTR_FEATURE_CAPABILITY = 27,
|
P2P_ATTR_FEATURE_CAPABILITY = 27,
|
||||||
P2P_ATTR_PERSISTENT_GROUP = 28,
|
P2P_ATTR_PERSISTENT_GROUP = 28,
|
||||||
|
P2P_ATTR_CAPABILITY_EXTENSION = 29,
|
||||||
|
P2P_ATTR_WLAN_AP_INFORMATION = 30,
|
||||||
|
P2P_ATTR_DEVICE_IDENTITY_KEY = 31,
|
||||||
|
P2P_ATTR_DEVICE_IDENTITY_RESOLUTION = 32,
|
||||||
|
P2P_ATTR_PAIRING_AND_BOOTSTRAPPING = 33,
|
||||||
|
P2P_ATTR_PASSWORD = 34,
|
||||||
|
P2P_ATTR_ACTION_FRAME_WRAPPER = 35,
|
||||||
P2P_ATTR_VENDOR_SPECIFIC = 221
|
P2P_ATTR_VENDOR_SPECIFIC = 221
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1764,6 +1783,31 @@ enum p2p_attr_id {
|
||||||
#define P2P_GROUP_CAPAB_GROUP_FORMATION BIT(6)
|
#define P2P_GROUP_CAPAB_GROUP_FORMATION BIT(6)
|
||||||
#define P2P_GROUP_CAPAB_IP_ADDR_ALLOCATION BIT(7)
|
#define P2P_GROUP_CAPAB_IP_ADDR_ALLOCATION BIT(7)
|
||||||
|
|
||||||
|
/* P2P Capability Extension attribute - Capability info */
|
||||||
|
#define P2P_PCEA_LEN_MASK (BIT(0) | BIT(1) | BIT(2) | BIT(3))
|
||||||
|
#define P2P_PCEA_6GHZ BIT(4)
|
||||||
|
#define P2P_PCEA_REG_INFO BIT(5)
|
||||||
|
#define P2P_PCEA_DFS_OWNER BIT(6)
|
||||||
|
#define P2P_PCEA_CLI_REQ_CS BIT(7)
|
||||||
|
#define P2P_PCEA_PAIRING_CAPABLE BIT(8)
|
||||||
|
#define P2P_PCEA_PAIRING_SETUP_ENABLED BIT(9)
|
||||||
|
#define P2P_PCEA_PMK_CACHING BIT(10)
|
||||||
|
#define P2P_PCEA_PASN_TYPE BIT(11)
|
||||||
|
#define P2P_PCEA_TWT_POWER_MGMT BIT(12)
|
||||||
|
|
||||||
|
/* P2P Pairing Bootstrapping Method attribute - Bootstrapping Method */
|
||||||
|
#define P2P_PBMA_OPPORTUNISTIC BIT(0)
|
||||||
|
#define P2P_PBMA_PIN_CODE_DISPLAY BIT(1)
|
||||||
|
#define P2P_PBMA_PASSPHRASE_DISPLAY BIT(2)
|
||||||
|
#define P2P_PBMA_QR_DISPLAY BIT(3)
|
||||||
|
#define P2P_PBMA_NFC_TAG BIT(4)
|
||||||
|
#define P2P_PBMA_PIN_CODE_KEYPAD BIT(5)
|
||||||
|
#define P2P_PBMA_PASSPHRASE_KEYPAD BIT(6)
|
||||||
|
#define P2P_PBMA_QR_SCAN BIT(7)
|
||||||
|
#define P2P_PBMA_NFC_READER BIT(8)
|
||||||
|
#define P2P_PBMA_SERVICE_MANAGED BIT(14)
|
||||||
|
#define P2P_PBMA_HANDSHAKE_SKIP BIT(15)
|
||||||
|
|
||||||
/* P2PS Coordination Protocol Transport Bitmap */
|
/* P2PS Coordination Protocol Transport Bitmap */
|
||||||
#define P2PS_FEATURE_CAPAB_UDP_TRANSPORT BIT(0)
|
#define P2PS_FEATURE_CAPAB_UDP_TRANSPORT BIT(0)
|
||||||
#define P2PS_FEATURE_CAPAB_MAC_TRANSPORT BIT(1)
|
#define P2PS_FEATURE_CAPAB_MAC_TRANSPORT BIT(1)
|
||||||
|
@ -1795,6 +1839,7 @@ enum p2p_status_code {
|
||||||
P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD = 10,
|
P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD = 10,
|
||||||
P2P_SC_FAIL_REJECTED_BY_USER = 11,
|
P2P_SC_FAIL_REJECTED_BY_USER = 11,
|
||||||
P2P_SC_SUCCESS_DEFERRED = 12,
|
P2P_SC_SUCCESS_DEFERRED = 12,
|
||||||
|
P2P_SC_COMEBACK = 13,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum p2p_role_indication {
|
enum p2p_role_indication {
|
||||||
|
@ -2863,6 +2908,33 @@ enum ieee80211_eht_ml_sub_elem {
|
||||||
EHT_ML_SUB_ELEM_FRAGMENT = 254,
|
EHT_ML_SUB_ELEM_FRAGMENT = 254,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* IEEE P802.11be/D7.0, 9.4.2.329 (Bandwidth Indication element) defines the
|
||||||
|
* Bandwidth Indication Information field to have the same definition as the
|
||||||
|
* EHT Operation Information field in the EHT Operation element.
|
||||||
|
*/
|
||||||
|
struct ieee80211_bw_ind_info {
|
||||||
|
u8 control; /* B0..B2: Channel Width */
|
||||||
|
u8 ccfs0;
|
||||||
|
u8 ccfs1;
|
||||||
|
le16 disabled_chan_bitmap; /* 0 or 2 octets */
|
||||||
|
} STRUCT_PACKED;
|
||||||
|
|
||||||
|
/* Control subfield: Channel Width subfield; see Table 9-417e (Channel width,
|
||||||
|
* CCFS0, and CCFS1 subfields) in IEEE P802.11be/D7.0. */
|
||||||
|
#define BW_IND_CHANNEL_WIDTH_20MHZ EHT_OPER_CHANNEL_WIDTH_20MHZ
|
||||||
|
#define BW_IND_CHANNEL_WIDTH_40MHZ EHT_OPER_CHANNEL_WIDTH_40MHZ
|
||||||
|
#define BW_IND_CHANNEL_WIDTH_80MHZ EHT_OPER_CHANNEL_WIDTH_80MHZ
|
||||||
|
#define BW_IND_CHANNEL_WIDTH_160MHZ EHT_OPER_CHANNEL_WIDTH_160MHZ
|
||||||
|
#define BW_IND_CHANNEL_WIDTH_320MHZ EHT_OPER_CHANNEL_WIDTH_320MHZ
|
||||||
|
|
||||||
|
/* IEEE P802.11be/D7.0, 9.4.2.329 (Bandwidth Indication element) */
|
||||||
|
struct ieee80211_bw_ind_element {
|
||||||
|
u8 bw_ind_params; /* Bandwidth Indication Parameters */
|
||||||
|
struct ieee80211_bw_ind_info bw_ind_info; /* 3 or 5 octets */
|
||||||
|
} STRUCT_PACKED;
|
||||||
|
|
||||||
|
#define BW_IND_PARAMETER_DISABLED_SUBCHAN_BITMAP_PRESENT BIT(1)
|
||||||
|
|
||||||
/* IEEE P802.11ay/D4.0, 9.4.2.251 - EDMG Operation element */
|
/* IEEE P802.11ay/D4.0, 9.4.2.251 - EDMG Operation element */
|
||||||
#define EDMG_BSS_OPERATING_CHANNELS_OFFSET 6
|
#define EDMG_BSS_OPERATING_CHANNELS_OFFSET 6
|
||||||
#define EDMG_OPERATING_CHANNEL_WIDTH_OFFSET 7
|
#define EDMG_OPERATING_CHANNEL_WIDTH_OFFSET 7
|
||||||
|
|
|
@ -58,10 +58,12 @@ struct nan_de_service {
|
||||||
struct os_reltime next_publish_state;
|
struct os_reltime next_publish_state;
|
||||||
struct os_reltime next_publish_chan;
|
struct os_reltime next_publish_chan;
|
||||||
unsigned int next_publish_duration;
|
unsigned int next_publish_duration;
|
||||||
|
bool is_p2p;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nan_de {
|
struct nan_de {
|
||||||
u8 nmi[ETH_ALEN];
|
u8 nmi[ETH_ALEN];
|
||||||
|
bool offload;
|
||||||
bool ap;
|
bool ap;
|
||||||
struct nan_callbacks cb;
|
struct nan_callbacks cb;
|
||||||
|
|
||||||
|
@ -77,7 +79,7 @@ struct nan_de {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct nan_de * nan_de_init(const u8 *nmi, bool ap,
|
struct nan_de * nan_de_init(const u8 *nmi, bool offload, bool ap,
|
||||||
const struct nan_callbacks *cb)
|
const struct nan_callbacks *cb)
|
||||||
{
|
{
|
||||||
struct nan_de *de;
|
struct nan_de *de;
|
||||||
|
@ -87,6 +89,7 @@ struct nan_de * nan_de_init(const u8 *nmi, bool ap,
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
os_memcpy(de->nmi, nmi, ETH_ALEN);
|
os_memcpy(de->nmi, nmi, ETH_ALEN);
|
||||||
|
de->offload = offload;
|
||||||
de->ap = ap;
|
de->ap = ap;
|
||||||
os_memcpy(&de->cb, cb, sizeof(*cb));
|
os_memcpy(&de->cb, cb, sizeof(*cb));
|
||||||
|
|
||||||
|
@ -590,7 +593,7 @@ static void nan_de_timer(void *eloop_ctx, void *timeout_ctx)
|
||||||
if (srv_next >= 0 && (next == -1 || srv_next < next))
|
if (srv_next >= 0 && (next == -1 || srv_next < next))
|
||||||
next = srv_next;
|
next = srv_next;
|
||||||
|
|
||||||
if (srv_next == 0 && !started &&
|
if (srv_next == 0 && !started && !de->offload &&
|
||||||
de->listen_freq == 0 && de->ext_listen_freq == 0 &&
|
de->listen_freq == 0 && de->ext_listen_freq == 0 &&
|
||||||
de->tx_wait_end_freq == 0 &&
|
de->tx_wait_end_freq == 0 &&
|
||||||
nan_de_next_multicast(de, srv, &now) == 0) {
|
nan_de_next_multicast(de, srv, &now) == 0) {
|
||||||
|
@ -598,7 +601,7 @@ static void nan_de_timer(void *eloop_ctx, void *timeout_ctx)
|
||||||
nan_de_tx_multicast(de, srv, 0);
|
nan_de_tx_multicast(de, srv, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!started && de->cb.listen &&
|
if (!started && !de->offload && de->cb.listen &&
|
||||||
de->listen_freq == 0 && de->ext_listen_freq == 0 &&
|
de->listen_freq == 0 && de->ext_listen_freq == 0 &&
|
||||||
de->tx_wait_end_freq == 0 &&
|
de->tx_wait_end_freq == 0 &&
|
||||||
((srv->type == NAN_DE_PUBLISH &&
|
((srv->type == NAN_DE_PUBLISH &&
|
||||||
|
@ -774,6 +777,34 @@ static void nan_de_get_sdea(const u8 *buf, size_t len, u8 instance_id,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void nan_de_process_elem_container(struct nan_de *de, const u8 *buf,
|
||||||
|
size_t len, const u8 *peer_addr,
|
||||||
|
unsigned int freq, bool p2p)
|
||||||
|
{
|
||||||
|
const u8 *elem;
|
||||||
|
u16 elem_len;
|
||||||
|
|
||||||
|
elem = nan_de_get_attr(buf, len, NAN_ATTR_ELEM_CONTAINER, 0);
|
||||||
|
if (!elem)
|
||||||
|
return;
|
||||||
|
|
||||||
|
elem++;
|
||||||
|
elem_len = WPA_GET_LE16(elem);
|
||||||
|
elem += 2;
|
||||||
|
/* Skip the attribute if there is not enough froom for an element. */
|
||||||
|
if (elem_len < 1 + 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Skip Map ID */
|
||||||
|
elem++;
|
||||||
|
elem_len--;
|
||||||
|
|
||||||
|
if (p2p && de->cb.process_p2p_usd_elems)
|
||||||
|
de->cb.process_p2p_usd_elems(de->cb.ctx, elem, elem_len,
|
||||||
|
peer_addr, freq);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void nan_de_rx_publish(struct nan_de *de, struct nan_de_service *srv,
|
static void nan_de_rx_publish(struct nan_de *de, struct nan_de_service *srv,
|
||||||
const u8 *peer_addr, u8 instance_id,
|
const u8 *peer_addr, u8 instance_id,
|
||||||
u8 req_instance_id, u16 sdea_control,
|
u8 req_instance_id, u16 sdea_control,
|
||||||
|
@ -787,13 +818,13 @@ static void nan_de_rx_publish(struct nan_de *de, struct nan_de_service *srv,
|
||||||
nan_de_run_timer(de);
|
nan_de_run_timer(de);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (srv->subscribe.active && req_instance_id == 0) {
|
if (!de->offload && srv->subscribe.active && req_instance_id == 0) {
|
||||||
/* Active subscriber replies with a Subscribe message if it
|
/* Active subscriber replies with a Subscribe message if it
|
||||||
* received a matching unsolicited Publish message. */
|
* received a matching unsolicited Publish message. */
|
||||||
nan_de_tx_multicast(de, srv, instance_id);
|
nan_de_tx_multicast(de, srv, instance_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!srv->subscribe.active && req_instance_id == 0) {
|
if (!de->offload && !srv->subscribe.active && req_instance_id == 0) {
|
||||||
/* Passive subscriber replies with a Follow-up message without
|
/* Passive subscriber replies with a Follow-up message without
|
||||||
* Service Specific Info field if it received a matching
|
* Service Specific Info field if it received a matching
|
||||||
* unsolicited Publish message. */
|
* unsolicited Publish message. */
|
||||||
|
@ -873,6 +904,9 @@ static void nan_de_rx_subscribe(struct nan_de *de, struct nan_de_service *srv,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (de->offload)
|
||||||
|
goto offload;
|
||||||
|
|
||||||
/* Reply with a solicited Publish message */
|
/* Reply with a solicited Publish message */
|
||||||
/* Service Descriptor attribute */
|
/* Service Descriptor attribute */
|
||||||
sda_len = NAN_SERVICE_ID_LEN + 1 + 1 + 1;
|
sda_len = NAN_SERVICE_ID_LEN + 1 + 1 + 1;
|
||||||
|
@ -939,6 +973,7 @@ static void nan_de_rx_subscribe(struct nan_de *de, struct nan_de_service *srv,
|
||||||
|
|
||||||
nan_de_pause_state(srv, peer_addr, instance_id);
|
nan_de_pause_state(srv, peer_addr, instance_id);
|
||||||
|
|
||||||
|
offload:
|
||||||
if (!srv->publish.disable_events && de->cb.replied)
|
if (!srv->publish.disable_events && de->cb.replied)
|
||||||
de->cb.replied(de->cb.ctx, srv->id, peer_addr, instance_id,
|
de->cb.replied(de->cb.ctx, srv->id, peer_addr, instance_id,
|
||||||
srv_proto_type, ssi, ssi_len);
|
srv_proto_type, ssi, ssi_len);
|
||||||
|
@ -1094,6 +1129,8 @@ static void nan_de_rx_sda(struct nan_de *de, const u8 *peer_addr,
|
||||||
wpa_hexdump(MSG_MSGDUMP, "NAN: ssi",
|
wpa_hexdump(MSG_MSGDUMP, "NAN: ssi",
|
||||||
ssi, ssi_len);
|
ssi, ssi_len);
|
||||||
}
|
}
|
||||||
|
nan_de_process_elem_container(de, buf, len, peer_addr,
|
||||||
|
freq, srv->is_p2p);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -1196,10 +1233,23 @@ static int nan_de_derive_service_id(struct nan_de_service *srv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const u8 * nan_de_get_service_id(struct nan_de *de, int id)
|
||||||
|
{
|
||||||
|
struct nan_de_service *srv;
|
||||||
|
|
||||||
|
if (id < 1 || id > NAN_DE_MAX_SERVICE)
|
||||||
|
return NULL;
|
||||||
|
srv = de->service[id - 1];
|
||||||
|
if (!srv)
|
||||||
|
return NULL;
|
||||||
|
return srv->service_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int nan_de_publish(struct nan_de *de, const char *service_name,
|
int nan_de_publish(struct nan_de *de, const char *service_name,
|
||||||
enum nan_service_protocol_type srv_proto_type,
|
enum nan_service_protocol_type srv_proto_type,
|
||||||
const struct wpabuf *ssi, const struct wpabuf *elems,
|
const struct wpabuf *ssi, const struct wpabuf *elems,
|
||||||
struct nan_publish_params *params)
|
struct nan_publish_params *params, bool p2p)
|
||||||
{
|
{
|
||||||
int publish_id;
|
int publish_id;
|
||||||
struct nan_de_service *srv;
|
struct nan_de_service *srv;
|
||||||
|
@ -1261,6 +1311,7 @@ int nan_de_publish(struct nan_de *de, const char *service_name,
|
||||||
wpa_printf(MSG_DEBUG, "NAN: Assigned new publish handle %d for %s",
|
wpa_printf(MSG_DEBUG, "NAN: Assigned new publish handle %d for %s",
|
||||||
publish_id, service_name);
|
publish_id, service_name);
|
||||||
srv->id = publish_id;
|
srv->id = publish_id;
|
||||||
|
srv->is_p2p = p2p;
|
||||||
nan_de_add_srv(de, srv);
|
nan_de_add_srv(de, srv);
|
||||||
nan_de_run_timer(de);
|
nan_de_run_timer(de);
|
||||||
return publish_id;
|
return publish_id;
|
||||||
|
@ -1312,7 +1363,7 @@ int nan_de_update_publish(struct nan_de *de, int publish_id,
|
||||||
int nan_de_subscribe(struct nan_de *de, const char *service_name,
|
int nan_de_subscribe(struct nan_de *de, const char *service_name,
|
||||||
enum nan_service_protocol_type srv_proto_type,
|
enum nan_service_protocol_type srv_proto_type,
|
||||||
const struct wpabuf *ssi, const struct wpabuf *elems,
|
const struct wpabuf *ssi, const struct wpabuf *elems,
|
||||||
struct nan_subscribe_params *params)
|
struct nan_subscribe_params *params, bool p2p)
|
||||||
{
|
{
|
||||||
int subscribe_id;
|
int subscribe_id;
|
||||||
struct nan_de_service *srv;
|
struct nan_de_service *srv;
|
||||||
|
@ -1337,6 +1388,17 @@ int nan_de_subscribe(struct nan_de *de, const char *service_name,
|
||||||
if (nan_de_derive_service_id(srv) < 0)
|
if (nan_de_derive_service_id(srv) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
os_memcpy(&srv->subscribe, params, sizeof(*params));
|
os_memcpy(&srv->subscribe, params, sizeof(*params));
|
||||||
|
|
||||||
|
if (params->freq_list) {
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
len = (int_array_len(params->freq_list) + 1) * sizeof(int);
|
||||||
|
srv->freq_list = os_memdup(params->freq_list, len);
|
||||||
|
if (!srv->freq_list)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
srv->subscribe.freq_list = NULL;
|
||||||
|
|
||||||
srv->srv_proto_type = srv_proto_type;
|
srv->srv_proto_type = srv_proto_type;
|
||||||
if (ssi) {
|
if (ssi) {
|
||||||
srv->ssi = wpabuf_dup(ssi);
|
srv->ssi = wpabuf_dup(ssi);
|
||||||
|
@ -1352,6 +1414,7 @@ int nan_de_subscribe(struct nan_de *de, const char *service_name,
|
||||||
wpa_printf(MSG_DEBUG, "NAN: Assigned new subscribe handle %d for %s",
|
wpa_printf(MSG_DEBUG, "NAN: Assigned new subscribe handle %d for %s",
|
||||||
subscribe_id, service_name);
|
subscribe_id, service_name);
|
||||||
srv->id = subscribe_id;
|
srv->id = subscribe_id;
|
||||||
|
srv->is_p2p = p2p;
|
||||||
nan_de_add_srv(de, srv);
|
nan_de_add_srv(de, srv);
|
||||||
nan_de_run_timer(de);
|
nan_de_run_timer(de);
|
||||||
return subscribe_id;
|
return subscribe_id;
|
||||||
|
|
|
@ -53,9 +53,13 @@ struct nan_callbacks {
|
||||||
void (*receive)(void *ctx, int id, int peer_instance_id,
|
void (*receive)(void *ctx, int id, int peer_instance_id,
|
||||||
const u8 *ssi, size_t ssi_len,
|
const u8 *ssi, size_t ssi_len,
|
||||||
const u8 *peer_addr);
|
const u8 *peer_addr);
|
||||||
|
|
||||||
|
void (*process_p2p_usd_elems)(void *ctx, const u8 *buf,
|
||||||
|
u16 buf_len, const u8 *peer_addr,
|
||||||
|
unsigned int freq);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nan_de * nan_de_init(const u8 *nmi, bool ap,
|
struct nan_de * nan_de_init(const u8 *nmi, bool offload, bool ap,
|
||||||
const struct nan_callbacks *cb);
|
const struct nan_callbacks *cb);
|
||||||
void nan_de_flush(struct nan_de *de);
|
void nan_de_flush(struct nan_de *de);
|
||||||
void nan_de_deinit(struct nan_de *de);
|
void nan_de_deinit(struct nan_de *de);
|
||||||
|
@ -68,6 +72,7 @@ void nan_de_tx_wait_ended(struct nan_de *de);
|
||||||
|
|
||||||
void nan_de_rx_sdf(struct nan_de *de, const u8 *peer_addr, unsigned int freq,
|
void nan_de_rx_sdf(struct nan_de *de, const u8 *peer_addr, unsigned int freq,
|
||||||
const u8 *buf, size_t len);
|
const u8 *buf, size_t len);
|
||||||
|
const u8 * nan_de_get_service_id(struct nan_de *de, int id);
|
||||||
|
|
||||||
struct nan_publish_params {
|
struct nan_publish_params {
|
||||||
/* configuration_parameters */
|
/* configuration_parameters */
|
||||||
|
@ -105,7 +110,7 @@ struct nan_publish_params {
|
||||||
int nan_de_publish(struct nan_de *de, const char *service_name,
|
int nan_de_publish(struct nan_de *de, const char *service_name,
|
||||||
enum nan_service_protocol_type srv_proto_type,
|
enum nan_service_protocol_type srv_proto_type,
|
||||||
const struct wpabuf *ssi, const struct wpabuf *elems,
|
const struct wpabuf *ssi, const struct wpabuf *elems,
|
||||||
struct nan_publish_params *params);
|
struct nan_publish_params *params, bool p2p);
|
||||||
|
|
||||||
void nan_de_cancel_publish(struct nan_de *de, int publish_id);
|
void nan_de_cancel_publish(struct nan_de *de, int publish_id);
|
||||||
|
|
||||||
|
@ -124,6 +129,9 @@ struct nan_subscribe_params {
|
||||||
/* Selected frequency */
|
/* Selected frequency */
|
||||||
unsigned int freq;
|
unsigned int freq;
|
||||||
|
|
||||||
|
/* Multi-channel frequencies (publishChannelList) */
|
||||||
|
const int *freq_list;
|
||||||
|
|
||||||
/* Query period in ms; 0 = use default */
|
/* Query period in ms; 0 = use default */
|
||||||
unsigned int query_period;
|
unsigned int query_period;
|
||||||
};
|
};
|
||||||
|
@ -132,7 +140,7 @@ struct nan_subscribe_params {
|
||||||
int nan_de_subscribe(struct nan_de *de, const char *service_name,
|
int nan_de_subscribe(struct nan_de *de, const char *service_name,
|
||||||
enum nan_service_protocol_type srv_proto_type,
|
enum nan_service_protocol_type srv_proto_type,
|
||||||
const struct wpabuf *ssi, const struct wpabuf *elems,
|
const struct wpabuf *ssi, const struct wpabuf *elems,
|
||||||
struct nan_subscribe_params *params);
|
struct nan_subscribe_params *params, bool p2p);
|
||||||
|
|
||||||
void nan_de_cancel_subscribe(struct nan_de *de, int subscribe_id);
|
void nan_de_cancel_subscribe(struct nan_de *de, int subscribe_id);
|
||||||
|
|
||||||
|
|
|
@ -230,7 +230,8 @@ enum qca_radiotap_vendor_ids {
|
||||||
*
|
*
|
||||||
* @QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES: Command to get the features
|
* @QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES: Command to get the features
|
||||||
* supported by the driver. enum qca_wlan_vendor_features defines
|
* supported by the driver. enum qca_wlan_vendor_features defines
|
||||||
* the possible features.
|
* the possible features that are encoded in
|
||||||
|
* QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS.
|
||||||
*
|
*
|
||||||
* @QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED: Event used by driver,
|
* @QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED: Event used by driver,
|
||||||
* which supports DFS offloading, to indicate a channel availability check
|
* which supports DFS offloading, to indicate a channel availability check
|
||||||
|
@ -1132,6 +1133,39 @@ enum qca_radiotap_vendor_ids {
|
||||||
* Uses the attributes defined in
|
* Uses the attributes defined in
|
||||||
* enum qca_wlan_vendor_attr_tdls_disc_rsp_ext.
|
* enum qca_wlan_vendor_attr_tdls_disc_rsp_ext.
|
||||||
*
|
*
|
||||||
|
* @QCA_NL80211_VENDOR_SUBCMD_AUDIO_TRANSPORT_SWITCH: This vendor subcommand is
|
||||||
|
* used to configure and indicate the audio transport switch in both
|
||||||
|
* command and event paths. This is used when two or more audio transports
|
||||||
|
* (e.g., WLAN and Bluetooth) are available between peers.
|
||||||
|
*
|
||||||
|
* If the driver needs to perform operations like scan, connection,
|
||||||
|
* roaming, RoC, etc. and AP concurrency policy is set to either
|
||||||
|
* QCA_WLAN_CONCURRENT_AP_POLICY_GAMING_AUDIO or
|
||||||
|
* QCA_WLAN_CONCURRENT_AP_POLICY_LOSSLESS_AUDIO_STREAMING, the driver sends
|
||||||
|
* audio transport switch event to userspace. Userspace application upon
|
||||||
|
* receiving the event, can try to switch to the requested audio transport.
|
||||||
|
* The userspace uses this command to send the status of transport
|
||||||
|
* switching (either confirm or reject) to the driver using this
|
||||||
|
* subcommand. The driver continues with the pending operation either upon
|
||||||
|
* receiving the command from userspace or after waiting for a timeout from
|
||||||
|
* sending the event to userspace. The driver can request userspace to
|
||||||
|
* switch to WLAN upon availability of WLAN audio transport once after the
|
||||||
|
* concurrent operations are completed.
|
||||||
|
*
|
||||||
|
* Userspace can also request audio transport switch from non-WLAN to WLAN
|
||||||
|
* using this subcommand to the driver. The driver can accept or reject
|
||||||
|
* depending on other concurrent operations in progress. The driver returns
|
||||||
|
* success if it can allow audio transport when it receives the command or
|
||||||
|
* appropriate kernel error code otherwise. Userspace indicates the audio
|
||||||
|
* transport switch from WLAN to non-WLAN using this subcommand and the
|
||||||
|
* driver can do other concurrent operations without needing to send any
|
||||||
|
* event to userspace. This subcommand is used by userspace only when the
|
||||||
|
* driver advertises support for
|
||||||
|
* QCA_WLAN_VENDOR_FEATURE_ENHANCED_AUDIO_EXPERIENCE_OVER_WLAN.
|
||||||
|
*
|
||||||
|
* The attributes used with this command are defined in enum
|
||||||
|
* qca_wlan_vendor_attr_audio_transport_switch.
|
||||||
|
*
|
||||||
* @QCA_NL80211_VENDOR_SUBCMD_TX_LATENCY: This vendor subcommand is used to
|
* @QCA_NL80211_VENDOR_SUBCMD_TX_LATENCY: This vendor subcommand is used to
|
||||||
* configure, retrieve, and report per-link transmit latency statistics.
|
* configure, retrieve, and report per-link transmit latency statistics.
|
||||||
*
|
*
|
||||||
|
@ -1227,6 +1261,35 @@ enum qca_radiotap_vendor_ids {
|
||||||
* collection of these statistics has been enabled by the command
|
* collection of these statistics has been enabled by the command
|
||||||
* @QCA_NL80211_VENDOR_SUBCMD_ASYNC_STATS_POLICY. The attributes for this
|
* @QCA_NL80211_VENDOR_SUBCMD_ASYNC_STATS_POLICY. The attributes for this
|
||||||
* event are defined in enum qca_wlan_vendor_attr_flow_stats.
|
* event are defined in enum qca_wlan_vendor_attr_flow_stats.
|
||||||
|
*
|
||||||
|
* @QCA_NL80211_VENDOR_SUBCMD_USD: Vendor subcommand to implement unsynchronized
|
||||||
|
* service discovery (USD). Based on the type of the USD subcommand the USD
|
||||||
|
* operation to publish, subscribe, update publish, cancel publish, or
|
||||||
|
* cancel subscribe is triggered.
|
||||||
|
*
|
||||||
|
* When used as an event, the driver notifies the status of an USD command.
|
||||||
|
*
|
||||||
|
* The attributes used with this command are defined in
|
||||||
|
* enum qca_wlan_vendor_attr_usd.
|
||||||
|
*
|
||||||
|
* @QCA_NL80211_VENDOR_SUBCMD_CONNECT_EXT: This is an extension to
|
||||||
|
* %NL80211_CMD_CONNECT command. Userspace can use this to indicate
|
||||||
|
* additional information to be considered for the subsequent
|
||||||
|
* (re)association request attempts with %NL80211_CMD_CONNECT. The
|
||||||
|
* additional information sent with this command is applicable for the
|
||||||
|
* entire duration of the connection established with %NL80211_CMD_CONNECT,
|
||||||
|
* including the roams triggered by the driver internally due to other
|
||||||
|
* vendor interfaces, driver internal logic, and BTM requests from the
|
||||||
|
* connected AP.
|
||||||
|
*
|
||||||
|
* @QCA_NL80211_VENDOR_SUBCMD_SET_P2P_MODE: Vendor subcommand to configure
|
||||||
|
* Wi-Fi Direct mode. This command sets the configuration through
|
||||||
|
* the attributes defined in the enum qca_wlan_vendor_attr_set_p2p_mode.
|
||||||
|
* It is applicable for P2P Group Owner only. This command is used before
|
||||||
|
* starting the GO.
|
||||||
|
*
|
||||||
|
* The attributes used with this command are defined in
|
||||||
|
* enum qca_wlan_vendor_attr_connect_ext.
|
||||||
*/
|
*/
|
||||||
enum qca_nl80211_vendor_subcmds {
|
enum qca_nl80211_vendor_subcmds {
|
||||||
QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0,
|
QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0,
|
||||||
|
@ -1442,7 +1505,7 @@ enum qca_nl80211_vendor_subcmds {
|
||||||
QCA_NL80211_VENDOR_SUBCMD_TID_TO_LINK_MAP = 229,
|
QCA_NL80211_VENDOR_SUBCMD_TID_TO_LINK_MAP = 229,
|
||||||
QCA_NL80211_VENDOR_SUBCMD_LINK_RECONFIG = 230,
|
QCA_NL80211_VENDOR_SUBCMD_LINK_RECONFIG = 230,
|
||||||
QCA_NL80211_VENDOR_SUBCMD_TDLS_DISC_RSP_EXT = 231,
|
QCA_NL80211_VENDOR_SUBCMD_TDLS_DISC_RSP_EXT = 231,
|
||||||
/* 232 - reserved for QCA */
|
QCA_NL80211_VENDOR_SUBCMD_AUDIO_TRANSPORT_SWITCH = 232,
|
||||||
QCA_NL80211_VENDOR_SUBCMD_TX_LATENCY = 233,
|
QCA_NL80211_VENDOR_SUBCMD_TX_LATENCY = 233,
|
||||||
/* 234 - reserved for QCA */
|
/* 234 - reserved for QCA */
|
||||||
QCA_NL80211_VENDOR_SUBCMD_SDWF_PHY_OPS = 235,
|
QCA_NL80211_VENDOR_SUBCMD_SDWF_PHY_OPS = 235,
|
||||||
|
@ -1459,6 +1522,9 @@ enum qca_nl80211_vendor_subcmds {
|
||||||
QCA_NL80211_VENDOR_SUBCMD_FLOW_CLASSIFY_RESULT = 246,
|
QCA_NL80211_VENDOR_SUBCMD_FLOW_CLASSIFY_RESULT = 246,
|
||||||
QCA_NL80211_VENDOR_SUBCMD_ASYNC_STATS_POLICY = 247,
|
QCA_NL80211_VENDOR_SUBCMD_ASYNC_STATS_POLICY = 247,
|
||||||
QCA_NL80211_VENDOR_SUBCMD_CLASSIFIED_FLOW_REPORT = 248,
|
QCA_NL80211_VENDOR_SUBCMD_CLASSIFIED_FLOW_REPORT = 248,
|
||||||
|
QCA_NL80211_VENDOR_SUBCMD_USD = 249,
|
||||||
|
QCA_NL80211_VENDOR_SUBCMD_CONNECT_EXT = 250,
|
||||||
|
QCA_NL80211_VENDOR_SUBCMD_SET_P2P_MODE = 251,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Compatibility defines for previously used subcmd names.
|
/* Compatibility defines for previously used subcmd names.
|
||||||
|
@ -1485,7 +1551,11 @@ enum qca_wlan_vendor_attr {
|
||||||
*/
|
*/
|
||||||
QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY = 5,
|
QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY = 5,
|
||||||
QCA_WLAN_VENDOR_ATTR_MAC_ADDR = 6,
|
QCA_WLAN_VENDOR_ATTR_MAC_ADDR = 6,
|
||||||
/* used by QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES */
|
/* Feature flags contained in a byte array. The feature flags are
|
||||||
|
* identified by their bit index (see &enum qca_wlan_vendor_features)
|
||||||
|
* with the first byte being the least significant one and the last one
|
||||||
|
* being the most significant one. Used by
|
||||||
|
* QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES. */
|
||||||
QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS = 7,
|
QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS = 7,
|
||||||
QCA_WLAN_VENDOR_ATTR_TEST = 8,
|
QCA_WLAN_VENDOR_ATTR_TEST = 8,
|
||||||
/* used by QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES */
|
/* used by QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES */
|
||||||
|
@ -2180,6 +2250,15 @@ enum qca_wlan_vendor_acs_hw_mode {
|
||||||
* that the device supports enhanced audio experience over WLAN feature.
|
* that the device supports enhanced audio experience over WLAN feature.
|
||||||
* @QCA_WLAN_VENDOR_FEATURE_HT_VHT_TWT_RESPONDER: Flag indicates that the device
|
* @QCA_WLAN_VENDOR_FEATURE_HT_VHT_TWT_RESPONDER: Flag indicates that the device
|
||||||
* in AP mode supports TWT responder mode in HT and VHT modes.
|
* in AP mode supports TWT responder mode in HT and VHT modes.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_FEATURE_RSN_OVERRIDE_STA: Flag indicates that the device
|
||||||
|
* supports RSNE/RSNXE overriding in STA mode. Supplicant should enable
|
||||||
|
* RSN overriding elements use only when the driver indicates this feature
|
||||||
|
* flag. For BSS selection offload to the driver case, the driver shall
|
||||||
|
* strip/modify the RSN Selection element indicated in connect request
|
||||||
|
* elements or add that element if none was provided based on the BSS
|
||||||
|
* selected by the driver.
|
||||||
|
*
|
||||||
* @NUM_QCA_WLAN_VENDOR_FEATURES: Number of assigned feature bits
|
* @NUM_QCA_WLAN_VENDOR_FEATURES: Number of assigned feature bits
|
||||||
*/
|
*/
|
||||||
enum qca_wlan_vendor_features {
|
enum qca_wlan_vendor_features {
|
||||||
|
@ -2208,6 +2287,7 @@ enum qca_wlan_vendor_features {
|
||||||
QCA_WLAN_VENDOR_FEATURE_AP_ALLOWED_FREQ_LIST = 22,
|
QCA_WLAN_VENDOR_FEATURE_AP_ALLOWED_FREQ_LIST = 22,
|
||||||
QCA_WLAN_VENDOR_FEATURE_ENHANCED_AUDIO_EXPERIENCE_OVER_WLAN = 23,
|
QCA_WLAN_VENDOR_FEATURE_ENHANCED_AUDIO_EXPERIENCE_OVER_WLAN = 23,
|
||||||
QCA_WLAN_VENDOR_FEATURE_HT_VHT_TWT_RESPONDER = 24,
|
QCA_WLAN_VENDOR_FEATURE_HT_VHT_TWT_RESPONDER = 24,
|
||||||
|
QCA_WLAN_VENDOR_FEATURE_RSN_OVERRIDE_STA = 25,
|
||||||
NUM_QCA_WLAN_VENDOR_FEATURES /* keep last */
|
NUM_QCA_WLAN_VENDOR_FEATURES /* keep last */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2627,6 +2707,9 @@ enum qca_wlan_vendor_scan_priority {
|
||||||
* when AP is operating as MLD to specify which link is requesting the
|
* when AP is operating as MLD to specify which link is requesting the
|
||||||
* scan or which link the scan result is for. No need of this attribute
|
* scan or which link the scan result is for. No need of this attribute
|
||||||
* in other cases.
|
* in other cases.
|
||||||
|
* @QCA_WLAN_VENDOR_ATTR_SCAN_SKIP_CHANNEL_RECENCY_PERIOD: Optional (u32). Skip
|
||||||
|
* scanning channels which are scanned recently within configured time
|
||||||
|
* (in ms).
|
||||||
*/
|
*/
|
||||||
enum qca_wlan_vendor_attr_scan {
|
enum qca_wlan_vendor_attr_scan {
|
||||||
QCA_WLAN_VENDOR_ATTR_SCAN_INVALID_PARAM = 0,
|
QCA_WLAN_VENDOR_ATTR_SCAN_INVALID_PARAM = 0,
|
||||||
|
@ -2645,6 +2728,7 @@ enum qca_wlan_vendor_attr_scan {
|
||||||
QCA_WLAN_VENDOR_ATTR_SCAN_PRIORITY = 13,
|
QCA_WLAN_VENDOR_ATTR_SCAN_PRIORITY = 13,
|
||||||
QCA_WLAN_VENDOR_ATTR_SCAN_PAD = 14,
|
QCA_WLAN_VENDOR_ATTR_SCAN_PAD = 14,
|
||||||
QCA_WLAN_VENDOR_ATTR_SCAN_LINK_ID = 15,
|
QCA_WLAN_VENDOR_ATTR_SCAN_LINK_ID = 15,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_SCAN_SKIP_CHANNEL_RECENCY_PERIOD = 16,
|
||||||
QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST,
|
QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST,
|
||||||
QCA_WLAN_VENDOR_ATTR_SCAN_MAX =
|
QCA_WLAN_VENDOR_ATTR_SCAN_MAX =
|
||||||
QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST - 1
|
QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST - 1
|
||||||
|
@ -3646,6 +3730,17 @@ enum qca_wlan_vendor_attr_config {
|
||||||
*/
|
*/
|
||||||
QCA_WLAN_VENDOR_ATTR_CONFIG_FOLLOW_AP_PREFERENCE_FOR_CNDS_SELECT = 121,
|
QCA_WLAN_VENDOR_ATTR_CONFIG_FOLLOW_AP_PREFERENCE_FOR_CNDS_SELECT = 121,
|
||||||
|
|
||||||
|
/* 16-bit unsigned value to configure P2P GO beacon interval in TUs.
|
||||||
|
* This attribute is used to update the P2P GO beacon interval
|
||||||
|
* dynamically.
|
||||||
|
*
|
||||||
|
* Updating the beacon interval while the GO continues operating the BSS
|
||||||
|
* will likely interoperability issues and is not recommended to be
|
||||||
|
* used. All the values should be multiples of the minimum used value to
|
||||||
|
* minimize risk of issues.
|
||||||
|
*/
|
||||||
|
QCA_WLAN_VENDOR_ATTR_CONFIG_P2P_GO_BEACON_INTERVAL = 122,
|
||||||
|
|
||||||
/* keep last */
|
/* keep last */
|
||||||
QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST,
|
QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST,
|
||||||
QCA_WLAN_VENDOR_ATTR_CONFIG_MAX =
|
QCA_WLAN_VENDOR_ATTR_CONFIG_MAX =
|
||||||
|
@ -7417,6 +7512,10 @@ enum qca_wlan_vendor_attr_external_acs_event {
|
||||||
* for External ACS
|
* for External ACS
|
||||||
*/
|
*/
|
||||||
QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_AFC_CAPABILITY = 15,
|
QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_AFC_CAPABILITY = 15,
|
||||||
|
/* Link ID attibute (u8) is used to identify a specific link affiliated
|
||||||
|
* to an AP MLD.
|
||||||
|
*/
|
||||||
|
QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_LINK_ID = 16,
|
||||||
|
|
||||||
/* keep last */
|
/* keep last */
|
||||||
QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_LAST,
|
QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_LAST,
|
||||||
|
@ -10358,6 +10457,14 @@ enum qca_wlan_vendor_attr_wifi_test_config {
|
||||||
*/
|
*/
|
||||||
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_SCS_TRAFFIC_SUPPORT = 73,
|
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_SCS_TRAFFIC_SUPPORT = 73,
|
||||||
|
|
||||||
|
/* 8-bit unsigned value to disable or not disable the channel switch
|
||||||
|
* initiation in P2P GO mode.
|
||||||
|
* 0 - Not-disable, 1 - Disable
|
||||||
|
*
|
||||||
|
* This attribute is used for testing purposes.
|
||||||
|
*/
|
||||||
|
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_DISABLE_CHAN_SWITCH_INITIATION = 74,
|
||||||
|
|
||||||
/* keep last */
|
/* keep last */
|
||||||
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST,
|
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST,
|
||||||
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX =
|
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX =
|
||||||
|
@ -12411,6 +12518,12 @@ enum qca_wlan_vendor_attr_add_sta_node_params {
|
||||||
*/
|
*/
|
||||||
QCA_WLAN_VENDOR_ATTR_ADD_STA_NODE_IS_ML = 3,
|
QCA_WLAN_VENDOR_ATTR_ADD_STA_NODE_IS_ML = 3,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is u8 attribute used to identify a specific link affiliated
|
||||||
|
* to an AP MLD.
|
||||||
|
*/
|
||||||
|
QCA_WLAN_VENDOR_ATTR_ADD_STA_NODE_LINK_ID = 4,
|
||||||
|
|
||||||
/* keep last */
|
/* keep last */
|
||||||
QCA_WLAN_VENDOR_ATTR_ADD_STA_NODE_PARAM_AFTER_LAST,
|
QCA_WLAN_VENDOR_ATTR_ADD_STA_NODE_PARAM_AFTER_LAST,
|
||||||
QCA_WLAN_VENDOR_ATTR_ADD_STA_NODE_PARAM_MAX =
|
QCA_WLAN_VENDOR_ATTR_ADD_STA_NODE_PARAM_MAX =
|
||||||
|
@ -17849,4 +17962,318 @@ enum qca_wlan_intf_offload_type {
|
||||||
QCA_WLAN_INTF_OFFLOAD_TYPE_PPE_DS = 3,
|
QCA_WLAN_INTF_OFFLOAD_TYPE_PPE_DS = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum qca_wlan_vendor_attr_usd_op_type: Attribute values for
|
||||||
|
* %QCA_WLAN_VENDOR_ATTR_USD_OP_TYPE to the vendor subcmd
|
||||||
|
* %QCA_NL80211_VENDOR_SUBCMD_USD. This is a mandatory u8 attribute which
|
||||||
|
* represents the USD command type.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_USD_OP_TYPE_FLUSH: Indicates USD tear down of all active
|
||||||
|
* publish and subscribe sessions.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_USD_OP_TYPE_PUBLISH: Indicates USD solicited publish
|
||||||
|
* operation that enables to offer a service for other devices based on
|
||||||
|
* given parameters.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_USD_OP_TYPE_SUBSCRIBE: Indicates USD active subscribe
|
||||||
|
* operation that requests for a given service with given parameters from
|
||||||
|
* other devices that offer the service.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_USD_OP_TYPE_UPDATE_PUBLISH: Indicates update of an instance
|
||||||
|
* of the publish function of given publish id.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_USD_OP_TYPE_CANCEL_PUBLISH: Indicates cancellation of an
|
||||||
|
* instance of the publish function.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_USD_OP_TYPE_CANCEL_SUBSCRIBE: Indicates cancellation of an
|
||||||
|
* instance of the subscribe function.
|
||||||
|
*/
|
||||||
|
enum qca_wlan_vendor_attr_an_usd_op_type {
|
||||||
|
QCA_WLAN_VENDOR_USD_OP_TYPE_FLUSH = 0,
|
||||||
|
QCA_WLAN_VENDOR_USD_OP_TYPE_PUBLISH = 1,
|
||||||
|
QCA_WLAN_VENDOR_USD_OP_TYPE_SUBSCRIBE = 2,
|
||||||
|
QCA_WLAN_VENDOR_USD_OP_TYPE_UPDATE_PUBLISH = 3,
|
||||||
|
QCA_WLAN_VENDOR_USD_OP_TYPE_CANCEL_PUBLISH = 4,
|
||||||
|
QCA_WLAN_VENDOR_USD_OP_TYPE_CANCEL_SUBSCRIBE = 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum qca_wlan_vendor_attr_usd_service_protocol_type: Attribute values for
|
||||||
|
* %QCA_WLAN_VENDOR_ATTR_USD_SERVICE_PROTOCOL_TYPE to the vendor subcmd
|
||||||
|
* %QCA_NL80211_VENDOR_SUBCMD_USD. This is a u8 attribute which represents the
|
||||||
|
* USD service protocol type for service specific information.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_USD_SERVICE_PROTOCOL_TYPE_BONJOUR: Indicates SSI info is
|
||||||
|
* of type Bonjour
|
||||||
|
* @QCA_WLAN_VENDOR_USD_SERVICE_PROTOCOL_TYPE_GENERIC: Indicates SSI info is
|
||||||
|
* of type generic
|
||||||
|
* @QCA_WLAN_VENDOR_USD_SERVICE_PROTOCOL_TYPE_CSA_MATTER: Indicates SSI info
|
||||||
|
* is of type CSA/Matter
|
||||||
|
*/
|
||||||
|
enum qca_wlan_vendor_attr_usd_service_protocol_type {
|
||||||
|
QCA_WLAN_VENDOR_USD_SERVICE_PROTOCOL_TYPE_BONJOUR = 1,
|
||||||
|
QCA_WLAN_VENDOR_USD_SERVICE_PROTOCOL_TYPE_GENERIC = 2,
|
||||||
|
QCA_WLAN_VENDOR_USD_SERVICE_PROTOCOL_TYPE_CSA_MATTER = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum qca_wlan_vendor_attr_usd_chan_config - Attributes used inside nested
|
||||||
|
* attribute %QCA_WLAN_VENDOR_ATTR_USD_CHAN_CONFIG.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_ATTR_USD_CHAN_CONFIG_DEFAULT_FREQ: Required
|
||||||
|
* u32 attribute containing the default channel frequency (MHz).
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_ATTR_USD_CHAN_CONFIG_FREQ_LIST: Optional array of channel
|
||||||
|
* frequencies in MHz (u32) to publish or subscribe.
|
||||||
|
*/
|
||||||
|
enum qca_wlan_vendor_attr_usd_chan_config {
|
||||||
|
QCA_WLAN_VENDOR_ATTR_USD_CHAN_CONFIG_INVALID = 0,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_USD_CHAN_CONFIG_DEFAULT_FREQ = 1,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_USD_CHAN_CONFIG_FREQ_LIST = 2,
|
||||||
|
|
||||||
|
QCA_WLAN_VENDOR_ATTR_USD_CHAN_CONFIG_AFTER_LAST,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_USD_CHAN_CONFIG_MAX =
|
||||||
|
QCA_WLAN_VENDOR_ATTR_USD_CHAN_CONFIG_AFTER_LAST - 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum qca_wlan_vendor_attr_usd_status
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_ATTR_USD_STATUS_SUCCESS: USD request success status.
|
||||||
|
* @QCA_WLAN_VENDOR_ATTR_USD_STATUS_FAILED: USD request failed status.
|
||||||
|
*/
|
||||||
|
enum qca_wlan_vendor_attr_usd_status {
|
||||||
|
QCA_WLAN_VENDOR_ATTR_USD_STATUS_SUCCESS,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_USD_STATUS_FAILED,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* enum qca_wlan_vendor_attr_usd: Attributes used by vendor command
|
||||||
|
* %QCA_NL80211_VENDOR_SUBCMD_USD.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_ATTR_USD_SRC_ADDR: 6-byte source MAC address
|
||||||
|
* Mandatory attribute used with type
|
||||||
|
* %QCA_WLAN_VENDOR_USD_OP_TYPE_PUBLISH and
|
||||||
|
* %QCA_WLAN_VENDOR_USD_OP_TYPE_SUBSCRIBE.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_ATTR_USD_OP_TYPE: Required u8 attribute.
|
||||||
|
* It indicates the type of the USD command. It uses values defined in enum
|
||||||
|
* qca_wlan_vendor_attr_usd_op_type.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_ATTR_USD_INSTANCE_ID: Required u8 attribute.
|
||||||
|
* It contains the publisher/subscribe id that is specific to the
|
||||||
|
* publish/subscribe instance.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_ATTR_USD_SERVICE_ID: Required 6-byte attribute.
|
||||||
|
* It contains the service id that is specific to the service being
|
||||||
|
* published/subscribed.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_ATTR_USD_SERVICE_PROTOCOL_TYPE: u8 attribute that indicates
|
||||||
|
* the service protocol type of service specific info. It uses values
|
||||||
|
* defined in enum qca_wlan_vendor_attr_usd_service_protocol_type. It is
|
||||||
|
* applicable when %QCA_WLAN_VENDOR_ATTR_USD_SSI is present.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_ATTR_USD_SSI: u8 array containing service specific
|
||||||
|
* information that has to be conveyed in publish/subscribe message.
|
||||||
|
* Optional attribute used with type
|
||||||
|
* %QCA_WLAN_VENDOR_USD_OP_TYPE_PUBLISH,
|
||||||
|
* %QCA_WLAN_VENDOR_USD_OP_TYPE_SUBSCRIBE, and
|
||||||
|
* %QCA_WLAN_VENDOR_USD_OP_TYPE_UPDATE_PUBLISH.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_ATTR_USD_CHAN_CONFIG: Nested attribute containing USD
|
||||||
|
* channel configuration parameters.
|
||||||
|
* Required for type %QCA_WLAN_VENDOR_USD_OP_TYPE_PUBLISH and
|
||||||
|
* %QCA_WLAN_VENDOR_USD_OP_TYPE_SUBSCRIBE.
|
||||||
|
* See enum qca_wlan_vendor_attr_usd_chan_config for nested attributes.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_ATTR_USD_ELEMENT_CONTAINER: u8 array containing a USD
|
||||||
|
* element container buffer that has to be conveyed in publish/subscribe
|
||||||
|
* message.
|
||||||
|
* Required for type %QCA_WLAN_VENDOR_USD_OP_TYPE_PUBLISH and
|
||||||
|
* %QCA_WLAN_VENDOR_USD_OP_TYPE_SUBSCRIBE.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_ATTR_USD_TTL: u16 attribute. Indicates the timeout
|
||||||
|
* for each request in seconds. Timeout value 0 represents single time
|
||||||
|
* operation.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_ATTR_USD_STATUS: u8 attribute. Status received in event
|
||||||
|
* indicating whether the underlying driver/firmware has started the USD
|
||||||
|
* operation as indicated by attributes
|
||||||
|
* %QCA_WLAN_VENDOR_ATTR_USD_OP_TYPE and
|
||||||
|
* %QCA_WLAN_VENDOR_ATTR_USD_INSTANCE_ID.
|
||||||
|
* enum qca_wlan_vendor_attr_usd_status indicates status values.
|
||||||
|
*/
|
||||||
|
enum qca_wlan_vendor_attr_usd {
|
||||||
|
QCA_WLAN_VENDOR_ATTR_USD_INVALID = 0,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_USD_SRC_ADDR = 1,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_USD_OP_TYPE = 2,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_USD_INSTANCE_ID = 3,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_USD_SERVICE_ID = 4,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_USD_SERVICE_PROTOCOL_TYPE = 5,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_USD_SSI = 6,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_USD_CHAN_CONFIG = 7,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_USD_ELEMENT_CONTAINER = 8,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_USD_TTL = 9,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_USD_STATUS = 10,
|
||||||
|
|
||||||
|
QCA_WLAN_VENDOR_ATTR_USD_AFTER_LAST,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_USD_MAX =
|
||||||
|
QCA_WLAN_VENDOR_ATTR_USD_AFTER_LAST - 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum qca_wlan_audio_transport_switch_type - Represents the possible transport
|
||||||
|
* switch types.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_AUDIO_TRANSPORT_SWITCH_TYPE_NON_WLAN: Request to route audio data
|
||||||
|
* via non-WLAN transport (e.g., Bluetooth).
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_AUDIO_TRANSPORT_SWITCH_TYPE_WLAN: Request to route audio data via
|
||||||
|
* WLAN transport.
|
||||||
|
*/
|
||||||
|
enum qca_wlan_audio_transport_switch_type {
|
||||||
|
QCA_WLAN_AUDIO_TRANSPORT_SWITCH_TYPE_NON_WLAN = 0,
|
||||||
|
QCA_WLAN_AUDIO_TRANSPORT_SWITCH_TYPE_WLAN = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum qca_wlan_audio_transport_switch_status - Represents the status of audio
|
||||||
|
* transport switch request.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_AUDIO_TRANSPORT_SWITCH_STATUS_REJECTED: Request to switch transport
|
||||||
|
* has been rejected. For example, when transport switch is requested from WLAN
|
||||||
|
* to non-WLAN transport, user space modules and peers would evaluate the switch
|
||||||
|
* request and may not be ready for switch and hence switch to non-WLAN
|
||||||
|
* transport gets rejected.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_AUDIO_TRANSPORT_SWITCH_STATUS_COMPLETED: Request to switch
|
||||||
|
* transport has been completed. This is sent only in the command path. For
|
||||||
|
* example, when the driver had requested for audio transport switch and
|
||||||
|
* userspace modules as well as peers are ready for the switch, userspace module
|
||||||
|
* switches the transport and sends the subcommand with status completed to the
|
||||||
|
* driver.
|
||||||
|
*/
|
||||||
|
enum qca_wlan_audio_transport_switch_status {
|
||||||
|
QCA_WLAN_AUDIO_TRANSPORT_SWITCH_STATUS_REJECTED = 0,
|
||||||
|
QCA_WLAN_AUDIO_TRANSPORT_SWITCH_STATUS_COMPLETED = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum qca_wlan_audio_transport_switch_reason - Represents the reason of audio
|
||||||
|
* transport switch request.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_AUDIO_TRANSPORT_SWITCH_REASON_TERMINATING: Requester transport is
|
||||||
|
* terminating. After this indication, requester module may not be available to
|
||||||
|
* process further request on its transport. For example, to handle a high
|
||||||
|
* priority concurrent interface, WLAN transport needs to terminate and hence
|
||||||
|
* indicates switch to a non-WLAN transport with reason terminating. User space
|
||||||
|
* modules switch to non-WLAN immediately without waiting for further
|
||||||
|
* confirmation.
|
||||||
|
*/
|
||||||
|
enum qca_wlan_audio_transport_switch_reason {
|
||||||
|
QCA_WLAN_AUDIO_TRANSPORT_SWITCH_REASON_TERMINATING = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum qca_wlan_vendor_attr_audio_transport_switch - Attributes used by
|
||||||
|
* %QCA_NL80211_VENDOR_SUBCMD_AUDIO_TRANSPORT_SWITCH vendor command.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_ATTR_AUDIO_TRANSPORT_SWITCH_TYPE: u8 attribute. Indicates
|
||||||
|
* the transport switch type from one of the values in enum
|
||||||
|
* qca_wlan_audio_transport_switch_type. This is mandatory attribute in both
|
||||||
|
* command and event path. This attribute is included in both requests and
|
||||||
|
* responses.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_ATTR_AUDIO_TRANSPORT_SWITCH_STATUS: u8 attribute. Indicates
|
||||||
|
* the transport switch status from one of the values in enum
|
||||||
|
* qca_wlan_audio_transport_switch_status. This is optional attribute and used
|
||||||
|
* in both command and event path. This attribute must not be included in
|
||||||
|
* requests.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_ATTR_AUDIO_TRANSPORT_SWITCH_REASON: u8 attribute. Indicates
|
||||||
|
* the transport switch reason from one of the values in enum
|
||||||
|
* qca_wlan_audio_transport_switch_reason. This is optional attribute and used
|
||||||
|
* in both command and event path.
|
||||||
|
*/
|
||||||
|
enum qca_wlan_vendor_attr_audio_transport_switch {
|
||||||
|
QCA_WLAN_VENDOR_ATTR_AUDIO_TRANSPORT_SWITCH_INVALID = 0,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_AUDIO_TRANSPORT_SWITCH_TYPE = 1,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_AUDIO_TRANSPORT_SWITCH_STATUS = 2,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_AUDIO_TRANSPORT_SWITCH_REASON = 3,
|
||||||
|
|
||||||
|
/* keep last */
|
||||||
|
QCA_WLAN_VENDOR_ATTR_AUDIO_TRANSPORT_SWITCH_AFTER_LAST,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_AUDIO_TRANSPORT_SWITCH_MAX =
|
||||||
|
QCA_WLAN_VENDOR_ATTR_AUDIO_TRANSPORT_SWITCH_AFTER_LAST - 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum qca_wlan_connect_ext_features - Feature flags for
|
||||||
|
* %QCA_WLAN_VENDOR_ATTR_CONNECT_EXT_FEATURES
|
||||||
|
*
|
||||||
|
* @QCA_CONNECT_EXT_FEATURE_RSNO: Flag attribute. This indicates supplicant
|
||||||
|
* support for RSN overriding. The driver shall enable RSN overriding in the
|
||||||
|
* (re)association attempts only if this flag is indicated. This functionality
|
||||||
|
* is available only when the driver indicates support for
|
||||||
|
* @QCA_WLAN_VENDOR_FEATURE_RSN_OVERRIDE_STA.
|
||||||
|
*
|
||||||
|
* @NUM_QCA_WLAN_VENDOR_FEATURES: Number of assigned feature bits.
|
||||||
|
*/
|
||||||
|
enum qca_wlan_connect_ext_features {
|
||||||
|
QCA_CONNECT_EXT_FEATURE_RSNO = 0,
|
||||||
|
NUM_QCA_CONNECT_EXT_FEATURES /* keep last */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* enum qca_wlan_vendor_attr_connect_ext: Attributes used by vendor command
|
||||||
|
* %QCA_NL80211_VENDOR_SUBCMD_CONNECT_EXT.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_ATTR_CONNECT_EXT_FEATURES: Feature flags contained in a byte
|
||||||
|
* array. The feature flags are identified by their bit index (see &enum
|
||||||
|
* qca_wlan_connect_ext_features) with the first byte being the least
|
||||||
|
* significant one and the last one being the most significant one.
|
||||||
|
*/
|
||||||
|
enum qca_wlan_vendor_attr_connect_ext {
|
||||||
|
QCA_WLAN_VENDOR_ATTR_CONNECT_EXT_INVALID = 0,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_CONNECT_EXT_FEATURES = 1,
|
||||||
|
|
||||||
|
QCA_WLAN_VENDOR_ATTR_CONNECT_EXT_AFTER_LAST,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_CONNECT_EXT_MAX =
|
||||||
|
QCA_WLAN_VENDOR_ATTR_CONNECT_EXT_AFTER_LAST - 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum qca_wlan_vendor_p2p_mode - Defines the values used with
|
||||||
|
* %QCA_WLAN_VENDOR_ATTR_SET_P2P_MODE_CONFIG.
|
||||||
|
*
|
||||||
|
* @QCA_P2P_MODE_WFD_R1: Wi-Fi Direct R1 only.
|
||||||
|
* @QCA_P2P_MODE_WFD_R2: Wi-Fi Direct R2 only.
|
||||||
|
* @QCA_P2P_MODE_WFD_PCC: P2P Connection Compatibility Mode which supports both
|
||||||
|
* Wi-Fi Direct R1 and R2.
|
||||||
|
*/
|
||||||
|
enum qca_wlan_vendor_p2p_mode {
|
||||||
|
QCA_P2P_MODE_WFD_R1 = 0,
|
||||||
|
QCA_P2P_MODE_WFD_R2 = 1,
|
||||||
|
QCA_P2P_MODE_WFD_PCC = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* enum qca_wlan_vendor_attr_set_p2p_mode: Attributes used by vendor command
|
||||||
|
* %QCA_NL80211_VENDOR_SUBCMD_SET_P2P_MODE.
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_ATTR_SET_P2P_MODE_CONFIG: u8 attribute. Sets the P2P device
|
||||||
|
* mode. The values used are defined in enum qca_wlan_vendor_p2p_mode.
|
||||||
|
* This configuration is valid until the interface is brought up next time after
|
||||||
|
* this configuration and the driver shall use this configuration only when the
|
||||||
|
* interface is brought up in NL80211_IFTYPE_P2P_GO mode.
|
||||||
|
* When this parameter has not been set, the interface is brought up with
|
||||||
|
* Wi-Fi Direct R1 only configuration by default.
|
||||||
|
*/
|
||||||
|
enum qca_wlan_vendor_attr_set_p2p_mode {
|
||||||
|
QCA_WLAN_VENDOR_ATTR_SET_P2P_MODE_INVALID = 0,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_SET_P2P_MODE_CONFIG = 1,
|
||||||
|
|
||||||
|
QCA_WLAN_VENDOR_ATTR_SET_P2P_MODE_AFTER_LAST,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_SET_P2P_MODE_MAX =
|
||||||
|
QCA_WLAN_VENDOR_ATTR_SET_P2P_MODE_AFTER_LAST - 1,
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* QCA_VENDOR_H */
|
#endif /* QCA_VENDOR_H */
|
||||||
|
|
|
@ -9,6 +9,6 @@
|
||||||
#define GIT_VERSION_STR_POSTFIX ""
|
#define GIT_VERSION_STR_POSTFIX ""
|
||||||
#endif /* GIT_VERSION_STR_POSTFIX */
|
#endif /* GIT_VERSION_STR_POSTFIX */
|
||||||
|
|
||||||
#define VERSION_STR "2.11" VERSION_STR_POSTFIX GIT_VERSION_STR_POSTFIX
|
#define VERSION_STR "2.12-devel" VERSION_STR_POSTFIX GIT_VERSION_STR_POSTFIX
|
||||||
|
|
||||||
#endif /* VERSION_H */
|
#endif /* VERSION_H */
|
||||||
|
|
|
@ -1890,6 +1890,14 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
|
||||||
data->has_group = 1;
|
data->has_group = 1;
|
||||||
data->key_mgmt = WPA_KEY_MGMT_OSEN;
|
data->key_mgmt = WPA_KEY_MGMT_OSEN;
|
||||||
data->proto = WPA_PROTO_OSEN;
|
data->proto = WPA_PROTO_OSEN;
|
||||||
|
} else if (rsn_ie_len >= 2 + 4 + 2 && rsn_ie[1] >= 4 + 2 &&
|
||||||
|
rsn_ie[1] == rsn_ie_len - 2 &&
|
||||||
|
(WPA_GET_BE32(&rsn_ie[2]) == RSNE_OVERRIDE_IE_VENDOR_TYPE ||
|
||||||
|
WPA_GET_BE32(&rsn_ie[2]) ==
|
||||||
|
RSNE_OVERRIDE_2_IE_VENDOR_TYPE) &&
|
||||||
|
WPA_GET_LE16(&rsn_ie[2 + 4]) == RSN_VERSION) {
|
||||||
|
pos = rsn_ie + 2 + 4 + 2;
|
||||||
|
left = rsn_ie_len - 2 - 4 - 2;
|
||||||
} else {
|
} else {
|
||||||
const struct rsn_ie_hdr *hdr;
|
const struct rsn_ie_hdr *hdr;
|
||||||
|
|
||||||
|
@ -3440,7 +3448,7 @@ static int wpa_parse_generic(const u8 *pos, struct wpa_eapol_ie_parse *ie)
|
||||||
const u8 *p;
|
const u8 *p;
|
||||||
size_t left;
|
size_t left;
|
||||||
u8 link_id;
|
u8 link_id;
|
||||||
char title[50];
|
char title[100];
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
|
@ -3621,6 +3629,57 @@ static int wpa_parse_generic(const u8 *pos, struct wpa_eapol_ie_parse *ie)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (left >= 1 && selector == WFA_KEY_DATA_RSN_OVERRIDE_LINK) {
|
||||||
|
link_id = p[0];
|
||||||
|
if (link_id >= MAX_NUM_MLD_LINKS)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
ie->rsn_override_link[link_id] = p;
|
||||||
|
ie->rsn_override_link_len[link_id] = left;
|
||||||
|
ret = os_snprintf(title, sizeof(title),
|
||||||
|
"RSN: Link ID %u - RSN Override Link KDE in EAPOL-Key",
|
||||||
|
link_id);
|
||||||
|
if (!os_snprintf_error(sizeof(title), ret))
|
||||||
|
wpa_hexdump(MSG_DEBUG, title, pos, dlen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selector == RSNE_OVERRIDE_IE_VENDOR_TYPE) {
|
||||||
|
ie->rsne_override = pos;
|
||||||
|
ie->rsne_override_len = dlen;
|
||||||
|
wpa_hexdump(MSG_DEBUG,
|
||||||
|
"RSN: RSNE Override element in EAPOL-Key",
|
||||||
|
ie->rsne_override, ie->rsne_override_len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selector == RSNE_OVERRIDE_2_IE_VENDOR_TYPE) {
|
||||||
|
ie->rsne_override_2 = pos;
|
||||||
|
ie->rsne_override_2_len = dlen;
|
||||||
|
wpa_hexdump(MSG_DEBUG,
|
||||||
|
"RSN: RSNE Override 2 element in EAPOL-Key",
|
||||||
|
ie->rsne_override_2, ie->rsne_override_2_len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selector == RSNXE_OVERRIDE_IE_VENDOR_TYPE) {
|
||||||
|
ie->rsnxe_override = pos;
|
||||||
|
ie->rsnxe_override_len = dlen;
|
||||||
|
wpa_hexdump(MSG_DEBUG,
|
||||||
|
"RSN: RSNXE Override element in EAPOL-Key",
|
||||||
|
ie->rsnxe_override, ie->rsnxe_override_len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selector == RSN_SELECTION_IE_VENDOR_TYPE) {
|
||||||
|
ie->rsn_selection = p;
|
||||||
|
ie->rsn_selection_len = left;
|
||||||
|
wpa_hexdump(MSG_DEBUG,
|
||||||
|
"RSN: RSN Selection element in EAPOL-Key",
|
||||||
|
ie->rsn_selection, ie->rsn_selection_len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4260,3 +4319,24 @@ int wpa_pasn_add_extra_ies(struct wpabuf *buf, const u8 *extra_ies, size_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_PASN */
|
#endif /* CONFIG_PASN */
|
||||||
|
|
||||||
|
|
||||||
|
void rsn_set_snonce_cookie(u8 *snonce)
|
||||||
|
{
|
||||||
|
u8 *pos;
|
||||||
|
|
||||||
|
pos = snonce + WPA_NONCE_LEN - 6;
|
||||||
|
WPA_PUT_BE24(pos, OUI_WFA);
|
||||||
|
pos += 3;
|
||||||
|
WPA_PUT_BE24(pos, 0x000029);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool rsn_is_snonce_cookie(const u8 *snonce)
|
||||||
|
{
|
||||||
|
const u8 *pos;
|
||||||
|
|
||||||
|
pos = snonce + WPA_NONCE_LEN - 6;
|
||||||
|
return WPA_GET_BE24(pos) == OUI_WFA &&
|
||||||
|
WPA_GET_BE24(pos + 3) == 0x000029;
|
||||||
|
}
|
||||||
|
|
|
@ -144,6 +144,7 @@ WPA_CIPHER_BIP_CMAC_256)
|
||||||
#define WFA_KEY_DATA_IP_ADDR_ALLOC RSN_SELECTOR(0x50, 0x6f, 0x9a, 5)
|
#define WFA_KEY_DATA_IP_ADDR_ALLOC RSN_SELECTOR(0x50, 0x6f, 0x9a, 5)
|
||||||
#define WFA_KEY_DATA_TRANSITION_DISABLE RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x20)
|
#define WFA_KEY_DATA_TRANSITION_DISABLE RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x20)
|
||||||
#define WFA_KEY_DATA_DPP RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x21)
|
#define WFA_KEY_DATA_DPP RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x21)
|
||||||
|
#define WFA_KEY_DATA_RSN_OVERRIDE_LINK RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x2d)
|
||||||
|
|
||||||
#define WPA_OUI_TYPE RSN_SELECTOR(0x00, 0x50, 0xf2, 1)
|
#define WPA_OUI_TYPE RSN_SELECTOR(0x00, 0x50, 0xf2, 1)
|
||||||
|
|
||||||
|
@ -643,6 +644,14 @@ struct wpa_pasn_params_data {
|
||||||
#define WPA_PASN_PUBKEY_COMPRESSED_1 0x03
|
#define WPA_PASN_PUBKEY_COMPRESSED_1 0x03
|
||||||
#define WPA_PASN_PUBKEY_UNCOMPRESSED 0x04
|
#define WPA_PASN_PUBKEY_UNCOMPRESSED 0x04
|
||||||
|
|
||||||
|
/* WPA3 specification - RSN Selection element */
|
||||||
|
enum rsn_selection_variant {
|
||||||
|
RSN_SELECTION_RSNE = 0,
|
||||||
|
RSN_SELECTION_RSNE_OVERRIDE = 1,
|
||||||
|
RSN_SELECTION_RSNE_OVERRIDE_2 = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse,
|
int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse,
|
||||||
int key_mgmt, bool reassoc_resp);
|
int key_mgmt, bool reassoc_resp);
|
||||||
void wpa_ft_parse_ies_free(struct wpa_ft_ies *parse);
|
void wpa_ft_parse_ies_free(struct wpa_ft_ies *parse);
|
||||||
|
@ -704,6 +713,14 @@ struct wpa_eapol_ie_parse {
|
||||||
u16 aid;
|
u16 aid;
|
||||||
const u8 *wmm;
|
const u8 *wmm;
|
||||||
size_t wmm_len;
|
size_t wmm_len;
|
||||||
|
const u8 *rsn_selection;
|
||||||
|
size_t rsn_selection_len;
|
||||||
|
const u8 *rsne_override;
|
||||||
|
size_t rsne_override_len;
|
||||||
|
const u8 *rsne_override_2;
|
||||||
|
size_t rsne_override_2_len;
|
||||||
|
const u8 *rsnxe_override;
|
||||||
|
size_t rsnxe_override_len;
|
||||||
u16 valid_mlo_gtks; /* bitmap of valid link GTK KDEs */
|
u16 valid_mlo_gtks; /* bitmap of valid link GTK KDEs */
|
||||||
const u8 *mlo_gtk[MAX_NUM_MLD_LINKS];
|
const u8 *mlo_gtk[MAX_NUM_MLD_LINKS];
|
||||||
size_t mlo_gtk_len[MAX_NUM_MLD_LINKS];
|
size_t mlo_gtk_len[MAX_NUM_MLD_LINKS];
|
||||||
|
@ -716,6 +733,8 @@ struct wpa_eapol_ie_parse {
|
||||||
u16 valid_mlo_links; /* bitmap of valid MLO link KDEs */
|
u16 valid_mlo_links; /* bitmap of valid MLO link KDEs */
|
||||||
const u8 *mlo_link[MAX_NUM_MLD_LINKS];
|
const u8 *mlo_link[MAX_NUM_MLD_LINKS];
|
||||||
size_t mlo_link_len[MAX_NUM_MLD_LINKS];
|
size_t mlo_link_len[MAX_NUM_MLD_LINKS];
|
||||||
|
const u8 *rsn_override_link[MAX_NUM_MLD_LINKS];
|
||||||
|
size_t rsn_override_link_len[MAX_NUM_MLD_LINKS];
|
||||||
};
|
};
|
||||||
|
|
||||||
int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie);
|
int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie);
|
||||||
|
@ -787,4 +806,7 @@ int wpa_pasn_parse_parameter_ie(const u8 *data, u8 len, bool from_ap,
|
||||||
void wpa_pasn_add_rsnxe(struct wpabuf *buf, u16 capab);
|
void wpa_pasn_add_rsnxe(struct wpabuf *buf, u16 capab);
|
||||||
int wpa_pasn_add_extra_ies(struct wpabuf *buf, const u8 *extra_ies, size_t len);
|
int wpa_pasn_add_extra_ies(struct wpabuf *buf, const u8 *extra_ies, size_t len);
|
||||||
|
|
||||||
|
void rsn_set_snonce_cookie(u8 *snonce);
|
||||||
|
bool rsn_is_snonce_cookie(const u8 *snonce);
|
||||||
|
|
||||||
#endif /* WPA_COMMON_H */
|
#endif /* WPA_COMMON_H */
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define WPA_CTRL_IFACE_LINK_NAME "link"
|
||||||
|
|
||||||
/* wpa_supplicant control interface - fixed message prefixes */
|
/* wpa_supplicant control interface - fixed message prefixes */
|
||||||
|
|
||||||
/** Interactive request for identity/password/pin */
|
/** Interactive request for identity/password/pin */
|
||||||
|
@ -204,6 +206,7 @@ extern "C" {
|
||||||
#define DPP_EVENT_CONFOBJ_SSID "DPP-CONFOBJ-SSID "
|
#define DPP_EVENT_CONFOBJ_SSID "DPP-CONFOBJ-SSID "
|
||||||
#define DPP_EVENT_CONFOBJ_SSID_CHARSET "DPP-CONFOBJ-SSID-CHARSET "
|
#define DPP_EVENT_CONFOBJ_SSID_CHARSET "DPP-CONFOBJ-SSID-CHARSET "
|
||||||
#define DPP_EVENT_CONFOBJ_PASS "DPP-CONFOBJ-PASS "
|
#define DPP_EVENT_CONFOBJ_PASS "DPP-CONFOBJ-PASS "
|
||||||
|
#define DPP_EVENT_CONFOBJ_IDPASS "DPP-CONFOBJ-IDPASS "
|
||||||
#define DPP_EVENT_CONFOBJ_PSK "DPP-CONFOBJ-PSK "
|
#define DPP_EVENT_CONFOBJ_PSK "DPP-CONFOBJ-PSK "
|
||||||
#define DPP_EVENT_CONNECTOR "DPP-CONNECTOR "
|
#define DPP_EVENT_CONNECTOR "DPP-CONNECTOR "
|
||||||
#define DPP_EVENT_C_SIGN_KEY "DPP-C-SIGN-KEY "
|
#define DPP_EVENT_C_SIGN_KEY "DPP-C-SIGN-KEY "
|
||||||
|
@ -225,6 +228,7 @@ extern "C" {
|
||||||
#define DPP_EVENT_CHIRP_STOPPED "DPP-CHIRP-STOPPED "
|
#define DPP_EVENT_CHIRP_STOPPED "DPP-CHIRP-STOPPED "
|
||||||
#define DPP_EVENT_MUD_URL "DPP-MUD-URL "
|
#define DPP_EVENT_MUD_URL "DPP-MUD-URL "
|
||||||
#define DPP_EVENT_BAND_SUPPORT "DPP-BAND-SUPPORT "
|
#define DPP_EVENT_BAND_SUPPORT "DPP-BAND-SUPPORT "
|
||||||
|
#define DPP_EVENT_ENROLLEE_CAPABILITY "DPP-ENROLLEE-CAPABILITY "
|
||||||
#define DPP_EVENT_CSR "DPP-CSR "
|
#define DPP_EVENT_CSR "DPP-CSR "
|
||||||
#define DPP_EVENT_CHIRP_RX "DPP-CHIRP-RX "
|
#define DPP_EVENT_CHIRP_RX "DPP-CHIRP-RX "
|
||||||
#define DPP_EVENT_CONF_NEEDED "DPP-CONF-NEEDED "
|
#define DPP_EVENT_CONF_NEEDED "DPP-CONF-NEEDED "
|
||||||
|
|
|
@ -27,6 +27,10 @@
|
||||||
#endif /* CONFIG_MACSEC */
|
#endif /* CONFIG_MACSEC */
|
||||||
#include "utils/list.h"
|
#include "utils/list.h"
|
||||||
|
|
||||||
|
struct nan_subscribe_params;
|
||||||
|
struct nan_publish_params;
|
||||||
|
enum nan_service_protocol_type;
|
||||||
|
|
||||||
#define HOSTAPD_CHAN_DISABLED 0x00000001
|
#define HOSTAPD_CHAN_DISABLED 0x00000001
|
||||||
#define HOSTAPD_CHAN_NO_IR 0x00000002
|
#define HOSTAPD_CHAN_NO_IR 0x00000002
|
||||||
#define HOSTAPD_CHAN_RADAR 0x00000008
|
#define HOSTAPD_CHAN_RADAR 0x00000008
|
||||||
|
@ -317,6 +321,27 @@ struct hostapd_hw_modes {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct hostapd_multi_hw_info: Supported multiple underlying hardware info
|
||||||
|
*/
|
||||||
|
struct hostapd_multi_hw_info {
|
||||||
|
/**
|
||||||
|
* hw_idx - Hardware index
|
||||||
|
*/
|
||||||
|
u8 hw_idx;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* start_freq - Frequency range start in MHz
|
||||||
|
*/
|
||||||
|
int start_freq;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* end_freq - Frequency range end in MHz
|
||||||
|
*/
|
||||||
|
int end_freq;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#define IEEE80211_CAP_ESS 0x0001
|
#define IEEE80211_CAP_ESS 0x0001
|
||||||
#define IEEE80211_CAP_IBSS 0x0002
|
#define IEEE80211_CAP_IBSS 0x0002
|
||||||
#define IEEE80211_CAP_PRIVACY 0x0010
|
#define IEEE80211_CAP_PRIVACY 0x0010
|
||||||
|
@ -1363,6 +1388,12 @@ struct wpa_driver_associate_params {
|
||||||
* mld_params - MLD association parameters
|
* mld_params - MLD association parameters
|
||||||
*/
|
*/
|
||||||
struct wpa_driver_mld_params mld_params;
|
struct wpa_driver_mld_params mld_params;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rsn_overriding - wpa_supplicant RSN overriding support
|
||||||
|
*/
|
||||||
|
bool rsn_overriding;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum hide_ssid {
|
enum hide_ssid {
|
||||||
|
@ -2330,6 +2361,10 @@ struct wpa_driver_capa {
|
||||||
#define WPA_DRIVER_FLAGS2_SAE_OFFLOAD_AP 0x0000000000100000ULL
|
#define WPA_DRIVER_FLAGS2_SAE_OFFLOAD_AP 0x0000000000100000ULL
|
||||||
/** Driver supports TWT responder in HT and VHT modes */
|
/** Driver supports TWT responder in HT and VHT modes */
|
||||||
#define WPA_DRIVER_FLAGS2_HT_VHT_TWT_RESPONDER 0x0000000000200000ULL
|
#define WPA_DRIVER_FLAGS2_HT_VHT_TWT_RESPONDER 0x0000000000200000ULL
|
||||||
|
/** Driver supports RSN override elements */
|
||||||
|
#define WPA_DRIVER_FLAGS2_RSN_OVERRIDE_STA 0x0000000000400000ULL
|
||||||
|
/** Driver supports NAN offload */
|
||||||
|
#define WPA_DRIVER_FLAGS2_NAN_OFFLOAD 0x0000000000800000ULL
|
||||||
u64 flags2;
|
u64 flags2;
|
||||||
|
|
||||||
#define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \
|
#define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \
|
||||||
|
@ -5194,15 +5229,19 @@ struct wpa_driver_ops {
|
||||||
/**
|
/**
|
||||||
* is_drv_shared - Check whether the driver interface is shared
|
* is_drv_shared - Check whether the driver interface is shared
|
||||||
* @priv: Private driver interface data from init()
|
* @priv: Private driver interface data from init()
|
||||||
* @bss_ctx: BSS context for %WPA_IF_AP_BSS interfaces
|
* @link_id: Link ID to match
|
||||||
|
* Returns: true if it is being used or else false.
|
||||||
*
|
*
|
||||||
* Checks whether the driver interface is being used by other partner
|
* Checks whether the driver interface is being used by other partner
|
||||||
* BSS(s) or not. This is used to decide whether the driver interface
|
* BSS(s) or not. This is used to decide whether the driver interface
|
||||||
* needs to be deinitilized when one interface is getting deinitialized.
|
* needs to be deinitilized when one interface is getting deinitialized.
|
||||||
*
|
*
|
||||||
* Returns: true if it is being used or else false.
|
* NOTE: @link_id will be used only when there is only one BSS
|
||||||
|
* present and if that single link is active. In that case, the
|
||||||
|
* link ID is matched with the active link_id to decide whether the
|
||||||
|
* driver interface is being used by other partner BSS(s).
|
||||||
*/
|
*/
|
||||||
bool (*is_drv_shared)(void *priv, void *bss_ctx);
|
bool (*is_drv_shared)(void *priv, int link_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* link_sta_remove - Remove a link STA from an MLD STA
|
* link_sta_remove - Remove a link STA from an MLD STA
|
||||||
|
@ -5213,11 +5252,94 @@ struct wpa_driver_ops {
|
||||||
*/
|
*/
|
||||||
int (*link_sta_remove)(void *priv, u8 link_id, const u8 *addr);
|
int (*link_sta_remove)(void *priv, u8 link_id, const u8 *addr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nan_flush - Flush all NAN offload services
|
||||||
|
* @priv: Private driver interface data
|
||||||
|
* Returns: 0 on success, negative value on failure
|
||||||
|
*/
|
||||||
|
int (*nan_flush)(void *priv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nan_publish - NAN offload for Publish()
|
||||||
|
* @priv: Private driver interface data
|
||||||
|
* @src: Source P2P device addr
|
||||||
|
* @publish_id: Publish instance to add
|
||||||
|
* @service_name: Service name
|
||||||
|
* @service_id: Service ID (6 octet value derived from service name)
|
||||||
|
* @srv_proto_type: Service protocol type
|
||||||
|
* @ssi: Service specific information or %NULL
|
||||||
|
* @elems: Information elements for Element Container attribute or %NULL
|
||||||
|
* @params: Configuration parameters
|
||||||
|
* Returns: 0 on success, negative value on failure
|
||||||
|
*/
|
||||||
|
int (*nan_publish)(void *priv, const u8 *src, int publish_id,
|
||||||
|
const char *service_name, const u8 *service_id,
|
||||||
|
enum nan_service_protocol_type srv_proto_type,
|
||||||
|
const struct wpabuf *ssi, const struct wpabuf *elems,
|
||||||
|
struct nan_publish_params *params);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nan_cancel_publish - NAN offload for CancelPublish()
|
||||||
|
* @priv: Private driver interface data
|
||||||
|
* @publish_id: Publish instance to cancel
|
||||||
|
* Returns: 0 on success, negative value on failure
|
||||||
|
*/
|
||||||
|
int (*nan_cancel_publish)(void *priv, int publish_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nan_update_publish - NAN offload for UpdatePublish()
|
||||||
|
* @priv: Private driver interface data
|
||||||
|
* @ssi: Service specific information or %NULL
|
||||||
|
* Returns: 0 on success, negative value on failure
|
||||||
|
*/
|
||||||
|
int (*nan_update_publish)(void *priv, int publish_id,
|
||||||
|
const struct wpabuf *ssi);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nan_subscribe - NAN offload for Subscribe()
|
||||||
|
* @priv: Private driver interface data
|
||||||
|
* @src: Source P2P device addr
|
||||||
|
* @subscribe_id: Subscribe instance to add
|
||||||
|
* @service_name: Service name
|
||||||
|
* @service_id: Service ID (6 octet value derived from service name)
|
||||||
|
* @srv_proto_type: Service protocol type
|
||||||
|
* @ssi: Service specific information or %NULL
|
||||||
|
* @elems: Information elements for Element Container attribute or %NULL
|
||||||
|
* @params: Configuration parameters
|
||||||
|
* Returns: 0 on success, negative value on failure
|
||||||
|
*/
|
||||||
|
int (*nan_subscribe)(void *priv, const u8 *src, int subscribe_id,
|
||||||
|
const char *service_name, const u8 *service_id,
|
||||||
|
enum nan_service_protocol_type srv_proto_type,
|
||||||
|
const struct wpabuf *ssi,
|
||||||
|
const struct wpabuf *elems,
|
||||||
|
struct nan_subscribe_params *params);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nan_cancel_subscribe - NAN offload for CancelSubscribe()
|
||||||
|
* @priv: Private driver interface data
|
||||||
|
* @subscribe_id: Subscribe instance to cancel
|
||||||
|
* Returns: 0 on success, negative value on failure
|
||||||
|
*/
|
||||||
|
int (*nan_cancel_subscribe)(void *priv, int subscribe_id);
|
||||||
|
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
int (*register_frame)(void *priv, u16 type,
|
int (*register_frame)(void *priv, u16 type,
|
||||||
const u8 *match, size_t match_len,
|
const u8 *match, size_t match_len,
|
||||||
bool multicast);
|
bool multicast);
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get_multi_hw_info - Get multiple underlying hardware information
|
||||||
|
* (hardware IDx and supported frequency range)
|
||||||
|
* @priv: Private driver interface data
|
||||||
|
* @num_multi_hws: Variable for returning the number of returned
|
||||||
|
* hardware info data
|
||||||
|
* Returns: Pointer to allocated multiple hardware data on success
|
||||||
|
* or %NULL on failure. Caller is responsible for freeing this.
|
||||||
|
*/
|
||||||
|
struct hostapd_multi_hw_info *
|
||||||
|
(*get_multi_hw_info)(void *priv, unsigned int *num_multi_hws);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5845,6 +5967,11 @@ enum wpa_event_type {
|
||||||
* EVENT_LINK_RECONFIG - Notification that AP links removed
|
* EVENT_LINK_RECONFIG - Notification that AP links removed
|
||||||
*/
|
*/
|
||||||
EVENT_LINK_RECONFIG,
|
EVENT_LINK_RECONFIG,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EVENT_MLD_INTERFACE_FREED - Notification of AP MLD interface removal
|
||||||
|
*/
|
||||||
|
EVENT_MLD_INTERFACE_FREED,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -100,6 +100,7 @@ const char * event_to_string(enum wpa_event_type event)
|
||||||
E2S(LINK_CH_SWITCH_STARTED);
|
E2S(LINK_CH_SWITCH_STARTED);
|
||||||
E2S(TID_LINK_MAP);
|
E2S(TID_LINK_MAP);
|
||||||
E2S(LINK_RECONFIG);
|
E2S(LINK_RECONFIG);
|
||||||
|
E2S(MLD_INTERFACE_FREED);
|
||||||
}
|
}
|
||||||
|
|
||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <netlink/route/link.h>
|
#include <netlink/route/link.h>
|
||||||
#include <netlink/route/link/macsec.h>
|
#include <netlink/route/link/macsec.h>
|
||||||
#include <linux/if_macsec.h>
|
#include <linux/if_macsec.h>
|
||||||
|
#include <linux/version.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
#include "utils/common.h"
|
#include "utils/common.h"
|
||||||
|
@ -32,7 +33,8 @@
|
||||||
|
|
||||||
#define UNUSED_SCI 0xffffffffffffffff
|
#define UNUSED_SCI 0xffffffffffffffff
|
||||||
|
|
||||||
#if LIBNL_VER_NUM >= LIBNL_VER(3, 6)
|
#if (LIBNL_VER_NUM >= LIBNL_VER(3, 6) && \
|
||||||
|
LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
|
||||||
#define LIBNL_HAS_OFFLOAD
|
#define LIBNL_HAS_OFFLOAD
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -3083,7 +3083,7 @@ static int wpa_driver_nl80211_del_beacon(struct i802_bss *bss,
|
||||||
struct wpa_driver_nl80211_data *drv = bss->drv;
|
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||||
struct i802_link *link = nl80211_get_link(bss, link_id);
|
struct i802_link *link = nl80211_get_link(bss, link_id);
|
||||||
|
|
||||||
if (!link->beacon_set)
|
if (!link || !link->beacon_set)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Remove beacon (ifindex=%d)",
|
wpa_printf(MSG_DEBUG, "nl80211: Remove beacon (ifindex=%d)",
|
||||||
|
@ -3151,9 +3151,6 @@ static void wpa_driver_nl80211_deinit(struct i802_bss *bss)
|
||||||
bss->ifname, bss->brname, strerror(errno));
|
bss->ifname, bss->brname, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drv->rtnl_sk)
|
|
||||||
nl_socket_free(drv->rtnl_sk);
|
|
||||||
|
|
||||||
if (bss->added_bridge) {
|
if (bss->added_bridge) {
|
||||||
if (linux_set_iface_flags(drv->global->ioctl_sock, bss->brname,
|
if (linux_set_iface_flags(drv->global->ioctl_sock, bss->brname,
|
||||||
0) < 0)
|
0) < 0)
|
||||||
|
@ -3173,6 +3170,9 @@ static void wpa_driver_nl80211_deinit(struct i802_bss *bss)
|
||||||
nl80211_remove_links(bss);
|
nl80211_remove_links(bss);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (drv->rtnl_sk)
|
||||||
|
nl_socket_free(drv->rtnl_sk);
|
||||||
|
|
||||||
if (drv->eapol_sock >= 0) {
|
if (drv->eapol_sock >= 0) {
|
||||||
eloop_unregister_read_sock(drv->eapol_sock);
|
eloop_unregister_read_sock(drv->eapol_sock);
|
||||||
close(drv->eapol_sock);
|
close(drv->eapol_sock);
|
||||||
|
@ -3189,7 +3189,7 @@ static void wpa_driver_nl80211_deinit(struct i802_bss *bss)
|
||||||
eloop_cancel_timeout(wpa_driver_nl80211_send_rfkill, drv, drv->ctx);
|
eloop_cancel_timeout(wpa_driver_nl80211_send_rfkill, drv, drv->ctx);
|
||||||
rfkill_deinit(drv->rfkill);
|
rfkill_deinit(drv->rfkill);
|
||||||
|
|
||||||
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
|
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, bss->ctx);
|
||||||
|
|
||||||
if (!drv->start_iface_up)
|
if (!drv->start_iface_up)
|
||||||
(void) i802_set_iface_flags(bss, 0);
|
(void) i802_set_iface_flags(bss, 0);
|
||||||
|
@ -4207,6 +4207,22 @@ struct i802_link * nl80211_get_link(struct i802_bss *bss, s8 link_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
u8 nl80211_get_link_id_from_link(struct i802_bss *bss, struct i802_link *link)
|
||||||
|
{
|
||||||
|
u8 link_id;
|
||||||
|
|
||||||
|
if (link == bss->flink)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for_each_link(bss->valid_links, link_id) {
|
||||||
|
if (&bss->links[link_id] == link)
|
||||||
|
return link_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void nl80211_link_set_freq(struct i802_bss *bss, s8 link_id, int freq)
|
static void nl80211_link_set_freq(struct i802_bss *bss, s8 link_id, int freq)
|
||||||
{
|
{
|
||||||
struct i802_link *link = nl80211_get_link(bss, link_id);
|
struct i802_link *link = nl80211_get_link(bss, link_id);
|
||||||
|
@ -5865,13 +5881,15 @@ fail:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void rtnl_neigh_delete_fdb_entry(struct i802_bss *bss, const u8 *addr)
|
static void rtnl_neigh_delete_fdb_entry(struct i802_bss *bss, const u8 *addr,
|
||||||
|
bool is_bridge)
|
||||||
{
|
{
|
||||||
struct wpa_driver_nl80211_data *drv = bss->drv;
|
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||||
struct ndmsg nhdr = {
|
struct ndmsg nhdr = {
|
||||||
.ndm_state = NUD_PERMANENT,
|
.ndm_state = NUD_PERMANENT,
|
||||||
.ndm_ifindex = bss->ifindex,
|
.ndm_ifindex = is_bridge ? bss->br_ifindex : bss->ifindex,
|
||||||
.ndm_family = AF_BRIDGE,
|
.ndm_family = AF_BRIDGE,
|
||||||
|
.ndm_type = is_bridge ? NTF_SELF : 0,
|
||||||
};
|
};
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
int err;
|
int err;
|
||||||
|
@ -5888,11 +5906,61 @@ static void rtnl_neigh_delete_fdb_entry(struct i802_bss *bss, const u8 *addr)
|
||||||
err = nl_wait_for_ack(drv->rtnl_sk);
|
err = nl_wait_for_ack(drv->rtnl_sk);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: bridge FDB entry delete for "
|
wpa_printf(MSG_DEBUG, "nl80211: bridge FDB entry delete for "
|
||||||
MACSTR " ifindex=%d failed: %s", MAC2STR(addr),
|
MACSTR " ifindex=%d ifname %s failed: %s",
|
||||||
bss->ifindex, nl_geterror(err));
|
MAC2STR(addr),
|
||||||
|
is_bridge ? bss->br_ifindex : bss->ifindex,
|
||||||
|
is_bridge ? bss->brname : bss->ifname,
|
||||||
|
nl_geterror(err));
|
||||||
} else {
|
} else {
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: deleted bridge FDB entry for "
|
wpa_printf(MSG_DEBUG, "nl80211: deleted bridge FDB entry "
|
||||||
MACSTR, MAC2STR(addr));
|
MACSTR " from %s",
|
||||||
|
MAC2STR(addr),
|
||||||
|
is_bridge ? bss->brname : bss->ifname);
|
||||||
|
}
|
||||||
|
|
||||||
|
errout:
|
||||||
|
nlmsg_free(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void rtnl_neigh_add_fdb_entry(struct i802_bss *bss, const u8 *addr,
|
||||||
|
bool is_bridge)
|
||||||
|
{
|
||||||
|
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||||
|
struct ndmsg nhdr = {
|
||||||
|
.ndm_state = NUD_PERMANENT,
|
||||||
|
.ndm_ifindex = is_bridge ? bss->br_ifindex : bss->ifindex,
|
||||||
|
.ndm_family = AF_BRIDGE,
|
||||||
|
/* TODO: remove this check if this flag needs to be used,
|
||||||
|
* for other interfaces type.
|
||||||
|
*/
|
||||||
|
.ndm_flags = is_bridge ? NTF_SELF : 0,
|
||||||
|
};
|
||||||
|
struct nl_msg *msg;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
msg = nlmsg_alloc_simple(RTM_NEWNEIGH, NLM_F_CREATE);
|
||||||
|
if (!msg)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (nlmsg_append(msg, &nhdr, sizeof(nhdr), NLMSG_ALIGNTO) < 0 ||
|
||||||
|
nla_put(msg, NDA_LLADDR, ETH_ALEN, (void *) addr) ||
|
||||||
|
nl_send_auto_complete(drv->rtnl_sk, msg) < 0)
|
||||||
|
goto errout;
|
||||||
|
|
||||||
|
err = nl_wait_for_ack(drv->rtnl_sk);
|
||||||
|
if (err < 0) {
|
||||||
|
wpa_printf(MSG_DEBUG, "nl80211: bridge FDB entry addition for "
|
||||||
|
MACSTR " ifindex=%d ifname %s failed: %s",
|
||||||
|
MAC2STR(addr),
|
||||||
|
is_bridge ? bss->br_ifindex : bss->ifindex,
|
||||||
|
is_bridge ? bss->brname : bss->ifname,
|
||||||
|
nl_geterror(err));
|
||||||
|
} else {
|
||||||
|
wpa_printf(MSG_DEBUG, "nl80211: added bridge FDB entry " MACSTR
|
||||||
|
" to %s",
|
||||||
|
MAC2STR(addr),
|
||||||
|
is_bridge ? bss->brname : bss->ifname);
|
||||||
}
|
}
|
||||||
|
|
||||||
errout:
|
errout:
|
||||||
|
@ -5927,7 +5995,7 @@ static int wpa_driver_nl80211_sta_remove(struct i802_bss *bss, const u8 *addr,
|
||||||
bss->ifname, MAC2STR(addr), ret, strerror(-ret));
|
bss->ifname, MAC2STR(addr), ret, strerror(-ret));
|
||||||
|
|
||||||
if (drv->rtnl_sk)
|
if (drv->rtnl_sk)
|
||||||
rtnl_neigh_delete_fdb_entry(bss, addr);
|
rtnl_neigh_delete_fdb_entry(bss, addr, false);
|
||||||
|
|
||||||
if (ret == -ENOENT)
|
if (ret == -ENOENT)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -7066,6 +7134,60 @@ static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_DRIVER_NL80211_QCA
|
||||||
|
static void connect_ext_feature_set(u8 *features,
|
||||||
|
enum qca_wlan_connect_ext_features idx)
|
||||||
|
{
|
||||||
|
u8 *idx_byte = &features[idx / 8];
|
||||||
|
|
||||||
|
*idx_byte |= BIT(idx % 8);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DRIVER_NL80211_QCA */
|
||||||
|
|
||||||
|
|
||||||
|
static int nl80211_connect_ext(struct wpa_driver_nl80211_data *drv,
|
||||||
|
struct wpa_driver_associate_params *params)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_DRIVER_NL80211_QCA
|
||||||
|
struct nl_msg *msg;
|
||||||
|
struct nlattr *attr;
|
||||||
|
u8 features[(NUM_QCA_CONNECT_EXT_FEATURES + 7) / 8] = {};
|
||||||
|
|
||||||
|
if (!drv->connect_ext_vendor_cmd_avail)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "nl80211: Connect_ext (ifindex=%d)",
|
||||||
|
drv->ifindex);
|
||||||
|
|
||||||
|
if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
|
||||||
|
nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
|
||||||
|
nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
|
||||||
|
QCA_NL80211_VENDOR_SUBCMD_CONNECT_EXT))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
|
||||||
|
if (!attr)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (params->rsn_overriding) {
|
||||||
|
wpa_printf(MSG_DEBUG, "- RSN overriding");
|
||||||
|
connect_ext_feature_set(features, QCA_CONNECT_EXT_FEATURE_RSNO);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nla_put(msg, QCA_WLAN_VENDOR_ATTR_CONNECT_EXT_FEATURES,
|
||||||
|
sizeof(features), features))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
nla_nest_end(msg, attr);
|
||||||
|
|
||||||
|
return send_and_recv_cmd(drv, msg);
|
||||||
|
fail:
|
||||||
|
nlmsg_free(msg);
|
||||||
|
#endif /* CONFIG_DRIVER_NL80211_QCA */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int wpa_driver_nl80211_try_connect(
|
static int wpa_driver_nl80211_try_connect(
|
||||||
struct wpa_driver_nl80211_data *drv,
|
struct wpa_driver_nl80211_data *drv,
|
||||||
struct wpa_driver_associate_params *params,
|
struct wpa_driver_associate_params *params,
|
||||||
|
@ -7087,6 +7209,7 @@ static int wpa_driver_nl80211_try_connect(
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_DRIVER_NL80211_QCA */
|
#endif /* CONFIG_DRIVER_NL80211_QCA */
|
||||||
|
|
||||||
|
nl80211_connect_ext(drv, params);
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Connect (ifindex=%d)", drv->ifindex);
|
wpa_printf(MSG_DEBUG, "nl80211: Connect (ifindex=%d)", drv->ifindex);
|
||||||
msg = nl80211_drv_msg(drv, 0, NL80211_CMD_CONNECT);
|
msg = nl80211_drv_msg(drv, 0, NL80211_CMD_CONNECT);
|
||||||
if (!msg)
|
if (!msg)
|
||||||
|
@ -8420,6 +8543,7 @@ static int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val,
|
||||||
struct wpa_driver_nl80211_data *drv = bss->drv;
|
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||||
char name[IFNAMSIZ + 1];
|
char name[IFNAMSIZ + 1];
|
||||||
union wpa_event_data event;
|
union wpa_event_data event;
|
||||||
|
bool add_br = false;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = os_snprintf(name, sizeof(name), "%s.sta%d", bss->ifname, aid);
|
ret = os_snprintf(name, sizeof(name), "%s.sta%d", bss->ifname, aid);
|
||||||
|
@ -8441,10 +8565,9 @@ static int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val,
|
||||||
bss->addr, 1, NULL, NULL, 0) <
|
bss->addr, 1, NULL, NULL, 0) <
|
||||||
0)
|
0)
|
||||||
return -1;
|
return -1;
|
||||||
if (bridge_ifname &&
|
|
||||||
linux_br_add_if(drv->global->ioctl_sock,
|
if (bridge_ifname)
|
||||||
bridge_ifname, name) < 0)
|
add_br = true;
|
||||||
return -1;
|
|
||||||
|
|
||||||
os_memset(&event, 0, sizeof(event));
|
os_memset(&event, 0, sizeof(event));
|
||||||
event.wds_sta_interface.sta_addr = addr;
|
event.wds_sta_interface.sta_addr = addr;
|
||||||
|
@ -8458,6 +8581,12 @@ static int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val,
|
||||||
wpa_printf(MSG_ERROR, "nl80211: Failed to set WDS STA "
|
wpa_printf(MSG_ERROR, "nl80211: Failed to set WDS STA "
|
||||||
"interface %s up", name);
|
"interface %s up", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (add_br &&
|
||||||
|
linux_br_add_if(drv->global->ioctl_sock,
|
||||||
|
bridge_ifname, name) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
return i802_set_sta_vlan(priv, addr, name, 0,
|
return i802_set_sta_vlan(priv, addr, name, 0,
|
||||||
NL80211_DRV_LINK_ID_NA);
|
NL80211_DRV_LINK_ID_NA);
|
||||||
} else {
|
} else {
|
||||||
|
@ -9442,13 +9571,14 @@ fail:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int nl80211_remove_link(struct i802_bss *bss, int link_id)
|
int nl80211_remove_link(struct i802_bss *bss, int link_id)
|
||||||
{
|
{
|
||||||
struct wpa_driver_nl80211_data *drv = bss->drv;
|
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||||
struct i802_link *link;
|
struct i802_link *link;
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
size_t i;
|
size_t i;
|
||||||
int ret;
|
int ret;
|
||||||
|
u8 link_addr[ETH_ALEN];
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Remove link (ifindex=%d link_id=%u)",
|
wpa_printf(MSG_DEBUG, "nl80211: Remove link (ifindex=%d link_id=%u)",
|
||||||
bss->ifindex, link_id);
|
bss->ifindex, link_id);
|
||||||
|
@ -9463,6 +9593,7 @@ static int nl80211_remove_link(struct i802_bss *bss, int link_id)
|
||||||
|
|
||||||
wpa_driver_nl80211_del_beacon(bss, link_id);
|
wpa_driver_nl80211_del_beacon(bss, link_id);
|
||||||
|
|
||||||
|
os_memcpy(link_addr, link->addr, ETH_ALEN);
|
||||||
/* First remove the link locally */
|
/* First remove the link locally */
|
||||||
bss->valid_links &= ~BIT(link_id);
|
bss->valid_links &= ~BIT(link_id);
|
||||||
os_memset(link->addr, 0, ETH_ALEN);
|
os_memset(link->addr, 0, ETH_ALEN);
|
||||||
|
@ -9500,6 +9631,9 @@ static int nl80211_remove_link(struct i802_bss *bss, int link_id)
|
||||||
"nl80211: remove link (%d) failed. ret=%d (%s)",
|
"nl80211: remove link (%d) failed. ret=%d (%s)",
|
||||||
link_id, ret, strerror(-ret));
|
link_id, ret, strerror(-ret));
|
||||||
|
|
||||||
|
if (drv->rtnl_sk)
|
||||||
|
rtnl_neigh_delete_fdb_entry(bss, link_addr, true);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9899,6 +10033,9 @@ static int nl80211_set_param(void *priv, const char *param)
|
||||||
WPA_DRIVER_FLAGS2_SEC_LTF_AP;
|
WPA_DRIVER_FLAGS2_SEC_LTF_AP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (os_strstr(param, "rsn_override_in_driver=1"))
|
||||||
|
drv->capa.flags2 |= WPA_DRIVER_FLAGS2_RSN_OVERRIDE_STA;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10249,6 +10386,8 @@ static int wpa_driver_nl80211_get_survey(void *priv, unsigned int freq)
|
||||||
int err;
|
int err;
|
||||||
union wpa_event_data data;
|
union wpa_event_data data;
|
||||||
struct survey_results *survey_results;
|
struct survey_results *survey_results;
|
||||||
|
void *ctx = (bss->scan_link && bss->scan_link->ctx) ?
|
||||||
|
bss->scan_link->ctx : bss->ctx;
|
||||||
|
|
||||||
os_memset(&data, 0, sizeof(data));
|
os_memset(&data, 0, sizeof(data));
|
||||||
survey_results = &data.survey_results;
|
survey_results = &data.survey_results;
|
||||||
|
@ -10271,7 +10410,7 @@ static int wpa_driver_nl80211_get_survey(void *priv, unsigned int freq)
|
||||||
if (err)
|
if (err)
|
||||||
wpa_printf(MSG_ERROR, "nl80211: Failed to process survey data");
|
wpa_printf(MSG_ERROR, "nl80211: Failed to process survey data");
|
||||||
else
|
else
|
||||||
wpa_supplicant_event(drv->ctx, EVENT_SURVEY, &data);
|
wpa_supplicant_event(ctx, EVENT_SURVEY, &data);
|
||||||
|
|
||||||
clean_survey_results(survey_results);
|
clean_survey_results(survey_results);
|
||||||
return err;
|
return err;
|
||||||
|
@ -10744,6 +10883,7 @@ static int driver_nl80211_link_remove(void *priv, enum wpa_driver_if_type type,
|
||||||
{
|
{
|
||||||
struct i802_bss *bss = priv;
|
struct i802_bss *bss = priv;
|
||||||
struct wpa_driver_nl80211_data *drv = bss->drv;
|
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (type != WPA_IF_AP_BSS ||
|
if (type != WPA_IF_AP_BSS ||
|
||||||
!nl80211_link_valid(bss->valid_links, link_id))
|
!nl80211_link_valid(bss->valid_links, link_id))
|
||||||
|
@ -10763,18 +10903,25 @@ static int driver_nl80211_link_remove(void *priv, enum wpa_driver_if_type type,
|
||||||
if (!bss->valid_links) {
|
if (!bss->valid_links) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"nl80211: No more links remaining, so remove interface");
|
"nl80211: No more links remaining, so remove interface");
|
||||||
return wpa_driver_nl80211_if_remove(bss, type, ifname);
|
ret = wpa_driver_nl80211_if_remove(bss, type, ifname);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Notify that the MLD interface is removed */
|
||||||
|
wpa_supplicant_event(bss->ctx, EVENT_MLD_INTERFACE_FREED, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool nl80211_is_drv_shared(void *priv, void *bss_ctx)
|
static bool nl80211_is_drv_shared(void *priv, int link_id)
|
||||||
{
|
{
|
||||||
struct i802_bss *bss = priv;
|
struct i802_bss *bss = priv;
|
||||||
struct wpa_driver_nl80211_data *drv = bss->drv;
|
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||||
unsigned int num_bss = 0;
|
unsigned int num_bss = 0, num_links = 0;
|
||||||
|
bool self = false;
|
||||||
|
u8 i;
|
||||||
|
|
||||||
/* If any other BSS exist, someone else is using this since at this
|
/* If any other BSS exist, someone else is using this since at this
|
||||||
* time, we would have removed all BSSs created by this driver and only
|
* time, we would have removed all BSSs created by this driver and only
|
||||||
|
@ -10789,13 +10936,23 @@ static bool nl80211_is_drv_shared(void *priv, void *bss_ctx)
|
||||||
/* This is the only BSS present */
|
/* This is the only BSS present */
|
||||||
bss = priv;
|
bss = priv;
|
||||||
|
|
||||||
/* If only one/no link is there no one is sharing */
|
for_each_link(bss->valid_links, i) {
|
||||||
if (bss->valid_links <= 1)
|
num_links++;
|
||||||
|
if (i == link_id)
|
||||||
|
self = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* More than one links means some one is still sharing */
|
||||||
|
if (num_links > 1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* Even if only one link is there, it should match the given
|
||||||
|
* link ID to assert that no one else is sharing. */
|
||||||
|
if (num_links == 1 && self)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* More than one link means someone is still using. To check if
|
/* No links are active means no one is sharing */
|
||||||
* only 1 bit is set, power of 2 condition can be checked. */
|
if (num_links == 0)
|
||||||
if (!(bss->valid_links & (bss->valid_links - 1)))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -13918,6 +14075,10 @@ static int nl80211_link_add(void *priv, u8 link_id, const u8 *addr,
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: MLD: valid_links=0x%04x on %s",
|
wpa_printf(MSG_DEBUG, "nl80211: MLD: valid_links=0x%04x on %s",
|
||||||
bss->valid_links, bss->ifname);
|
bss->valid_links, bss->ifname);
|
||||||
|
|
||||||
|
if (drv->rtnl_sk)
|
||||||
|
rtnl_neigh_add_fdb_entry(bss, addr, true);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13997,6 +14158,15 @@ static int testing_nl80211_radio_disable(void *priv, int disabled)
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
|
|
||||||
|
static struct hostapd_multi_hw_info *
|
||||||
|
wpa_driver_get_multi_hw_info(void *priv, unsigned int *num_multi_hws)
|
||||||
|
{
|
||||||
|
struct i802_bss *bss = priv;
|
||||||
|
|
||||||
|
return nl80211_get_multi_hw_info(bss, num_multi_hws);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
||||||
.name = "nl80211",
|
.name = "nl80211",
|
||||||
.desc = "Linux nl80211/cfg80211",
|
.desc = "Linux nl80211/cfg80211",
|
||||||
|
@ -14155,4 +14325,5 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
||||||
.register_frame = testing_nl80211_register_frame,
|
.register_frame = testing_nl80211_register_frame,
|
||||||
.radio_disable = testing_nl80211_radio_disable,
|
.radio_disable = testing_nl80211_radio_disable,
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
.get_multi_hw_info = wpa_driver_get_multi_hw_info,
|
||||||
};
|
};
|
||||||
|
|
|
@ -67,7 +67,7 @@ struct i802_bss {
|
||||||
|
|
||||||
u16 valid_links;
|
u16 valid_links;
|
||||||
struct i802_link links[MAX_NUM_MLD_LINKS];
|
struct i802_link links[MAX_NUM_MLD_LINKS];
|
||||||
struct i802_link *flink;
|
struct i802_link *flink, *scan_link;
|
||||||
|
|
||||||
int ifindex;
|
int ifindex;
|
||||||
int br_ifindex;
|
int br_ifindex;
|
||||||
|
@ -200,6 +200,7 @@ struct wpa_driver_nl80211_data {
|
||||||
unsigned int secure_ranging_ctx_vendor_cmd_avail:1;
|
unsigned int secure_ranging_ctx_vendor_cmd_avail:1;
|
||||||
unsigned int puncturing:1;
|
unsigned int puncturing:1;
|
||||||
unsigned int qca_ap_allowed_freqs:1;
|
unsigned int qca_ap_allowed_freqs:1;
|
||||||
|
unsigned int connect_ext_vendor_cmd_avail:1;
|
||||||
|
|
||||||
u32 ignore_next_local_disconnect;
|
u32 ignore_next_local_disconnect;
|
||||||
u32 ignore_next_local_deauth;
|
u32 ignore_next_local_deauth;
|
||||||
|
@ -352,6 +353,8 @@ const char * nl80211_iftype_str(enum nl80211_iftype mode);
|
||||||
|
|
||||||
void nl80211_restore_ap_mode(struct i802_bss *bss);
|
void nl80211_restore_ap_mode(struct i802_bss *bss);
|
||||||
struct i802_link * nl80211_get_link(struct i802_bss *bss, s8 link_id);
|
struct i802_link * nl80211_get_link(struct i802_bss *bss, s8 link_id);
|
||||||
|
u8 nl80211_get_link_id_from_link(struct i802_bss *bss, struct i802_link *link);
|
||||||
|
int nl80211_remove_link(struct i802_bss *bss, int link_id);
|
||||||
|
|
||||||
static inline bool nl80211_link_valid(u16 links, s8 link_id)
|
static inline bool nl80211_link_valid(u16 links, s8 link_id)
|
||||||
{
|
{
|
||||||
|
@ -409,5 +412,7 @@ int wpa_driver_nl80211_abort_scan(void *priv, u64 scan_cookie);
|
||||||
int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss,
|
int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss,
|
||||||
struct wpa_driver_scan_params *params);
|
struct wpa_driver_scan_params *params);
|
||||||
int nl80211_set_default_scan_ies(void *priv, const u8 *ies, size_t ies_len);
|
int nl80211_set_default_scan_ies(void *priv, const u8 *ies, size_t ies_len);
|
||||||
|
struct hostapd_multi_hw_info *
|
||||||
|
nl80211_get_multi_hw_info(struct i802_bss *bss, unsigned int *num_multi_hws);
|
||||||
|
|
||||||
#endif /* DRIVER_NL80211_H */
|
#endif /* DRIVER_NL80211_H */
|
||||||
|
|
|
@ -1120,6 +1120,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
|
||||||
case QCA_NL80211_VENDOR_SUBCMD_SECURE_RANGING_CONTEXT:
|
case QCA_NL80211_VENDOR_SUBCMD_SECURE_RANGING_CONTEXT:
|
||||||
drv->secure_ranging_ctx_vendor_cmd_avail = 1;
|
drv->secure_ranging_ctx_vendor_cmd_avail = 1;
|
||||||
break;
|
break;
|
||||||
|
case QCA_NL80211_VENDOR_SUBCMD_CONNECT_EXT:
|
||||||
|
drv->connect_ext_vendor_cmd_avail = 1;
|
||||||
|
break;
|
||||||
#endif /* CONFIG_DRIVER_NL80211_QCA */
|
#endif /* CONFIG_DRIVER_NL80211_QCA */
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_DRIVER_NL80211_BRCM
|
#ifdef CONFIG_DRIVER_NL80211_BRCM
|
||||||
|
@ -1443,6 +1446,12 @@ static void qca_nl80211_get_features(struct wpa_driver_nl80211_data *drv)
|
||||||
drv->qca_ap_allowed_freqs = 1;
|
drv->qca_ap_allowed_freqs = 1;
|
||||||
if (check_feature(QCA_WLAN_VENDOR_FEATURE_HT_VHT_TWT_RESPONDER, &info))
|
if (check_feature(QCA_WLAN_VENDOR_FEATURE_HT_VHT_TWT_RESPONDER, &info))
|
||||||
drv->capa.flags2 |= WPA_DRIVER_FLAGS2_HT_VHT_TWT_RESPONDER;
|
drv->capa.flags2 |= WPA_DRIVER_FLAGS2_HT_VHT_TWT_RESPONDER;
|
||||||
|
if (check_feature(QCA_WLAN_VENDOR_FEATURE_RSN_OVERRIDE_STA, &info)) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"The driver supports RSN overriding in STA mode");
|
||||||
|
drv->capa.flags2 |= WPA_DRIVER_FLAGS2_RSN_OVERRIDE_STA;
|
||||||
|
}
|
||||||
|
|
||||||
os_free(info.flags);
|
os_free(info.flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1470,6 +1479,7 @@ int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
|
||||||
WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
|
WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
|
||||||
WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
|
WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
|
||||||
WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK |
|
WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK |
|
||||||
|
WPA_DRIVER_CAPA_KEY_MGMT_PSK_SHA256 |
|
||||||
WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B |
|
WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B |
|
||||||
WPA_DRIVER_CAPA_KEY_MGMT_OWE |
|
WPA_DRIVER_CAPA_KEY_MGMT_OWE |
|
||||||
WPA_DRIVER_CAPA_KEY_MGMT_DPP;
|
WPA_DRIVER_CAPA_KEY_MGMT_DPP;
|
||||||
|
@ -1485,6 +1495,7 @@ int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
|
||||||
WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384 |
|
WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384 |
|
||||||
WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256 |
|
WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256 |
|
||||||
WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384 |
|
WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384 |
|
||||||
|
WPA_DRIVER_CAPA_KEY_MGMT_SAE_EXT_KEY |
|
||||||
WPA_DRIVER_CAPA_KEY_MGMT_SAE;
|
WPA_DRIVER_CAPA_KEY_MGMT_SAE;
|
||||||
else if (drv->capa.flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)
|
else if (drv->capa.flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)
|
||||||
drv->capa.key_mgmt |=
|
drv->capa.key_mgmt |=
|
||||||
|
@ -2728,3 +2739,133 @@ nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags,
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int phy_multi_hw_info_parse(struct hostapd_multi_hw_info *hw_info,
|
||||||
|
struct nlattr *radio_attr)
|
||||||
|
{
|
||||||
|
struct nlattr *tb_freq[NL80211_WIPHY_RADIO_FREQ_ATTR_MAX + 1];
|
||||||
|
int start_freq, end_freq;
|
||||||
|
|
||||||
|
switch (nla_type(radio_attr)) {
|
||||||
|
case NL80211_WIPHY_RADIO_ATTR_INDEX:
|
||||||
|
hw_info->hw_idx = nla_get_u32(radio_attr);
|
||||||
|
return NL_OK;
|
||||||
|
case NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE:
|
||||||
|
nla_parse_nested(tb_freq, NL80211_WIPHY_RADIO_FREQ_ATTR_MAX,
|
||||||
|
radio_attr, NULL);
|
||||||
|
|
||||||
|
if (!tb_freq[NL80211_WIPHY_RADIO_FREQ_ATTR_START] ||
|
||||||
|
!tb_freq[NL80211_WIPHY_RADIO_FREQ_ATTR_END])
|
||||||
|
return NL_STOP;
|
||||||
|
|
||||||
|
start_freq = nla_get_u32(
|
||||||
|
tb_freq[NL80211_WIPHY_RADIO_FREQ_ATTR_START]);
|
||||||
|
end_freq = nla_get_u32(
|
||||||
|
tb_freq[NL80211_WIPHY_RADIO_FREQ_ATTR_END]);
|
||||||
|
|
||||||
|
/* Convert to MHz and store */
|
||||||
|
hw_info->start_freq = start_freq / 1000;
|
||||||
|
hw_info->end_freq = end_freq / 1000;
|
||||||
|
return NL_OK;
|
||||||
|
default:
|
||||||
|
return NL_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct phy_multi_hw_info_arg {
|
||||||
|
bool failed;
|
||||||
|
unsigned int *num_multi_hws;
|
||||||
|
struct hostapd_multi_hw_info *multi_hws;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static int phy_multi_hw_info_handler(struct nl_msg *msg, void *arg)
|
||||||
|
{
|
||||||
|
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
|
||||||
|
struct phy_multi_hw_info_arg *multi_hw_info = arg;
|
||||||
|
struct hostapd_multi_hw_info *multi_hws, hw_info;
|
||||||
|
struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
|
||||||
|
struct nlattr *nl_hw, *radio_attr;
|
||||||
|
int rem_hw, rem_radio_prop, res;
|
||||||
|
|
||||||
|
nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
|
||||||
|
genlmsg_attrlen(gnlh, 0), NULL);
|
||||||
|
|
||||||
|
if (!tb_msg[NL80211_ATTR_WIPHY_RADIOS])
|
||||||
|
return NL_SKIP;
|
||||||
|
|
||||||
|
*multi_hw_info->num_multi_hws = 0;
|
||||||
|
|
||||||
|
nla_for_each_nested(nl_hw, tb_msg[NL80211_ATTR_WIPHY_RADIOS], rem_hw) {
|
||||||
|
os_memset(&hw_info, 0, sizeof(hw_info));
|
||||||
|
|
||||||
|
nla_for_each_nested(radio_attr, nl_hw, rem_radio_prop) {
|
||||||
|
res = phy_multi_hw_info_parse(&hw_info, radio_attr);
|
||||||
|
if (res != NL_OK)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hw_info.start_freq == 0 || hw_info.end_freq == 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
multi_hws = os_realloc_array(multi_hw_info->multi_hws,
|
||||||
|
*multi_hw_info->num_multi_hws + 1,
|
||||||
|
sizeof(*multi_hws));
|
||||||
|
if (!multi_hws)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
multi_hw_info->multi_hws = multi_hws;
|
||||||
|
os_memcpy(&multi_hws[*(multi_hw_info->num_multi_hws)],
|
||||||
|
&hw_info, sizeof(struct hostapd_multi_hw_info));
|
||||||
|
*(multi_hw_info->num_multi_hws) += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NL_OK;
|
||||||
|
out:
|
||||||
|
multi_hw_info->failed = true;
|
||||||
|
return NL_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct hostapd_multi_hw_info *
|
||||||
|
nl80211_get_multi_hw_info(struct i802_bss *bss, unsigned int *num_multi_hws)
|
||||||
|
{
|
||||||
|
u32 feat;
|
||||||
|
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||||
|
int nl_flags = 0;
|
||||||
|
struct nl_msg *msg;
|
||||||
|
struct phy_multi_hw_info_arg result = {
|
||||||
|
.failed = false,
|
||||||
|
.num_multi_hws = num_multi_hws,
|
||||||
|
.multi_hws = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
*num_multi_hws = 0;
|
||||||
|
|
||||||
|
if (!drv->has_capability || !(drv->capa.flags2 & WPA_DRIVER_FLAGS2_MLO))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
feat = get_nl80211_protocol_features(drv);
|
||||||
|
if (feat & NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP)
|
||||||
|
nl_flags = NLM_F_DUMP;
|
||||||
|
if (!(msg = nl80211_cmd_msg(bss, nl_flags, NL80211_CMD_GET_WIPHY)) ||
|
||||||
|
nla_put_flag(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP)) {
|
||||||
|
nlmsg_free(msg);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (send_and_recv_resp(drv, msg, phy_multi_hw_info_handler,
|
||||||
|
&result) == 0) {
|
||||||
|
if (result.failed) {
|
||||||
|
os_free(result.multi_hws);
|
||||||
|
*num_multi_hws = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.multi_hws;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
|
@ -186,6 +186,7 @@ static const char * nl80211_command_to_string(enum nl80211_commands cmd)
|
||||||
C2S(NL80211_CMD_REMOVE_LINK_STA)
|
C2S(NL80211_CMD_REMOVE_LINK_STA)
|
||||||
C2S(NL80211_CMD_SET_HW_TIMESTAMP)
|
C2S(NL80211_CMD_SET_HW_TIMESTAMP)
|
||||||
C2S(NL80211_CMD_LINKS_REMOVED)
|
C2S(NL80211_CMD_LINKS_REMOVED)
|
||||||
|
C2S(NL80211_CMD_SET_TID_TO_LINK_MAPPING)
|
||||||
C2S(__NL80211_CMD_AFTER_LAST)
|
C2S(__NL80211_CMD_AFTER_LAST)
|
||||||
}
|
}
|
||||||
#undef C2S
|
#undef C2S
|
||||||
|
@ -1204,9 +1205,6 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
|
||||||
int chan_offset = 0;
|
int chan_offset = 0;
|
||||||
int ifidx;
|
int ifidx;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Channel switch%s event",
|
|
||||||
finished ? "" : " started");
|
|
||||||
|
|
||||||
if (!freq)
|
if (!freq)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1218,6 +1216,9 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "nl80211: Channel switch%s event for %s",
|
||||||
|
finished ? "" : " started", bss->ifname);
|
||||||
|
|
||||||
if (type) {
|
if (type) {
|
||||||
enum nl80211_channel_type ch_type = nla_get_u32(type);
|
enum nl80211_channel_type ch_type = nla_get_u32(type);
|
||||||
|
|
||||||
|
@ -1260,10 +1261,13 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
|
||||||
if (cf2)
|
if (cf2)
|
||||||
data.ch_switch.cf2 = nla_get_u32(cf2);
|
data.ch_switch.cf2 = nla_get_u32(cf2);
|
||||||
|
|
||||||
if (link)
|
if (link) {
|
||||||
data.ch_switch.link_id = nla_get_u8(link);
|
data.ch_switch.link_id = nla_get_u8(link);
|
||||||
else
|
wpa_printf(MSG_DEBUG, "nl80211: Link ID: %d",
|
||||||
|
data.ch_switch.link_id);
|
||||||
|
} else {
|
||||||
data.ch_switch.link_id = NL80211_DRV_LINK_ID_NA;
|
data.ch_switch.link_id = NL80211_DRV_LINK_ID_NA;
|
||||||
|
}
|
||||||
|
|
||||||
if (finished) {
|
if (finished) {
|
||||||
if (data.ch_switch.link_id != NL80211_DRV_LINK_ID_NA) {
|
if (data.ch_switch.link_id != NL80211_DRV_LINK_ID_NA) {
|
||||||
|
@ -1300,6 +1304,14 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (link && is_ap_interface(drv->nlmode) &&
|
||||||
|
!nl80211_link_valid(bss->valid_links, data.ch_switch.link_id)) {
|
||||||
|
wpa_printf(MSG_WARNING,
|
||||||
|
"nl80211: Unknown link ID (%d) for channel switch (%s), ignoring",
|
||||||
|
data.ch_switch.link_id, bss->ifname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
drv->assoc_freq = data.ch_switch.freq;
|
drv->assoc_freq = data.ch_switch.freq;
|
||||||
|
|
||||||
wpa_supplicant_event(bss->ctx, finished ?
|
wpa_supplicant_event(bss->ctx, finished ?
|
||||||
|
@ -1965,9 +1977,10 @@ static void mlme_event_dh_event(struct wpa_driver_nl80211_data *drv,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
|
static void send_scan_event(struct i802_bss *bss, int aborted,
|
||||||
struct nlattr *tb[], int external_scan)
|
struct nlattr *tb[], int external_scan)
|
||||||
{
|
{
|
||||||
|
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||||
union wpa_event_data event;
|
union wpa_event_data event;
|
||||||
struct nlattr *nl;
|
struct nlattr *nl;
|
||||||
int rem;
|
int rem;
|
||||||
|
@ -1975,6 +1988,8 @@ static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
|
||||||
#define MAX_REPORT_FREQS 110
|
#define MAX_REPORT_FREQS 110
|
||||||
int freqs[MAX_REPORT_FREQS];
|
int freqs[MAX_REPORT_FREQS];
|
||||||
int num_freqs = 0;
|
int num_freqs = 0;
|
||||||
|
struct i802_link *mld_link;
|
||||||
|
void *ctx = bss->ctx;
|
||||||
|
|
||||||
if (!external_scan && drv->scan_for_auth) {
|
if (!external_scan && drv->scan_for_auth) {
|
||||||
drv->scan_for_auth = 0;
|
drv->scan_for_auth = 0;
|
||||||
|
@ -2038,13 +2053,30 @@ static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
|
||||||
ETH_ALEN);
|
ETH_ALEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, &event);
|
/* Need to pass to the correct link ctx during AP MLD operation */
|
||||||
|
if (is_ap_interface(drv->nlmode)) {
|
||||||
|
mld_link = bss->scan_link;
|
||||||
|
if (!mld_link) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"nl80211: Scan event on unknown link");
|
||||||
|
} else if (mld_link->ctx) {
|
||||||
|
u8 link_id = nl80211_get_link_id_from_link(bss,
|
||||||
|
mld_link);
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"nl80211: Scan event for link_id %d",
|
||||||
|
link_id);
|
||||||
|
ctx = mld_link->ctx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, &event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void nl80211_cqm_event(struct wpa_driver_nl80211_data *drv,
|
static void nl80211_cqm_event(struct i802_bss *bss, struct nlattr *tb[])
|
||||||
struct nlattr *tb[])
|
|
||||||
{
|
{
|
||||||
|
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||||
static struct nla_policy cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
|
static struct nla_policy cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
|
||||||
[NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 },
|
[NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 },
|
||||||
[NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U8 },
|
[NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U8 },
|
||||||
|
@ -2079,7 +2111,7 @@ static void nl80211_cqm_event(struct wpa_driver_nl80211_data *drv,
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Packet loss event for " MACSTR
|
wpa_printf(MSG_DEBUG, "nl80211: Packet loss event for " MACSTR
|
||||||
" (num_packets %u)",
|
" (num_packets %u)",
|
||||||
MAC2STR(ed.low_ack.addr), ed.low_ack.num_packets);
|
MAC2STR(ed.low_ack.addr), ed.low_ack.num_packets);
|
||||||
wpa_supplicant_event(drv->ctx, EVENT_STATION_LOW_ACK, &ed);
|
wpa_supplicant_event(bss->ctx, EVENT_STATION_LOW_ACK, &ed);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2411,10 +2443,33 @@ static void nl80211_tdls_oper_event(struct wpa_driver_nl80211_data *drv,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void nl80211_stop_ap(struct wpa_driver_nl80211_data *drv,
|
static void nl80211_stop_ap(struct i802_bss *bss, struct nlattr **tb)
|
||||||
struct nlattr **tb)
|
|
||||||
{
|
{
|
||||||
wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_UNAVAILABLE, NULL);
|
struct i802_link *mld_link = NULL;
|
||||||
|
void *ctx = bss->ctx;
|
||||||
|
int link_id = -1;
|
||||||
|
|
||||||
|
if (tb[NL80211_ATTR_MLO_LINK_ID]) {
|
||||||
|
link_id = nla_get_u8(tb[NL80211_ATTR_MLO_LINK_ID]);
|
||||||
|
if (!nl80211_link_valid(bss->valid_links, link_id)) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"nl80211: Ignoring STOP_AP event for invalid link ID %d (valid: 0x%04x)",
|
||||||
|
link_id, bss->valid_links);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mld_link = nl80211_get_link(bss, link_id);
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"nl80211: STOP_AP event on link %d", link_id);
|
||||||
|
ctx = mld_link->ctx;
|
||||||
|
|
||||||
|
/* The driver would have already deleted the link and this call
|
||||||
|
* will return an error. Ignore that since nl80211_remove_link()
|
||||||
|
* is called here only to update the bss->links[] state. */
|
||||||
|
nl80211_remove_link(bss, link_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_supplicant_event(ctx, EVENT_INTERFACE_UNAVAILABLE, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3055,7 +3110,7 @@ static void qca_nl80211_scan_done_event(struct wpa_driver_nl80211_data *drv,
|
||||||
drv->scan_state = SCAN_ABORTED;
|
drv->scan_state = SCAN_ABORTED;
|
||||||
|
|
||||||
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv,
|
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv,
|
||||||
drv->ctx);
|
drv->first_bss->ctx);
|
||||||
drv->vendor_scan_cookie = 0;
|
drv->vendor_scan_cookie = 0;
|
||||||
drv->last_scan_cmd = 0;
|
drv->last_scan_cmd = 0;
|
||||||
}
|
}
|
||||||
|
@ -3894,7 +3949,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case NL80211_CMD_TRIGGER_SCAN:
|
case NL80211_CMD_TRIGGER_SCAN:
|
||||||
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Scan trigger");
|
wpa_dbg(bss->ctx, MSG_DEBUG, "nl80211: Scan trigger");
|
||||||
drv->scan_state = SCAN_STARTED;
|
drv->scan_state = SCAN_STARTED;
|
||||||
if (drv->scan_for_auth) {
|
if (drv->scan_for_auth) {
|
||||||
/*
|
/*
|
||||||
|
@ -3906,40 +3961,40 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Do not indicate scan-start event due to internal scan_for_auth");
|
wpa_printf(MSG_DEBUG, "nl80211: Do not indicate scan-start event due to internal scan_for_auth");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
wpa_supplicant_event(drv->ctx, EVENT_SCAN_STARTED, NULL);
|
wpa_supplicant_event(bss->ctx, EVENT_SCAN_STARTED, NULL);
|
||||||
break;
|
break;
|
||||||
case NL80211_CMD_START_SCHED_SCAN:
|
case NL80211_CMD_START_SCHED_SCAN:
|
||||||
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Sched scan started");
|
wpa_dbg(bss->ctx, MSG_DEBUG, "nl80211: Sched scan started");
|
||||||
drv->scan_state = SCHED_SCAN_STARTED;
|
drv->scan_state = SCHED_SCAN_STARTED;
|
||||||
break;
|
break;
|
||||||
case NL80211_CMD_SCHED_SCAN_STOPPED:
|
case NL80211_CMD_SCHED_SCAN_STOPPED:
|
||||||
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Sched scan stopped");
|
wpa_dbg(bss->ctx, MSG_DEBUG, "nl80211: Sched scan stopped");
|
||||||
drv->scan_state = SCHED_SCAN_STOPPED;
|
drv->scan_state = SCHED_SCAN_STOPPED;
|
||||||
wpa_supplicant_event(drv->ctx, EVENT_SCHED_SCAN_STOPPED, NULL);
|
wpa_supplicant_event(bss->ctx, EVENT_SCHED_SCAN_STOPPED, NULL);
|
||||||
break;
|
break;
|
||||||
case NL80211_CMD_NEW_SCAN_RESULTS:
|
case NL80211_CMD_NEW_SCAN_RESULTS:
|
||||||
wpa_dbg(drv->ctx, MSG_DEBUG,
|
wpa_dbg(bss->ctx, MSG_DEBUG,
|
||||||
"nl80211: New scan results available");
|
"nl80211: New scan results available");
|
||||||
if (drv->last_scan_cmd != NL80211_CMD_VENDOR)
|
if (drv->last_scan_cmd != NL80211_CMD_VENDOR)
|
||||||
drv->scan_state = SCAN_COMPLETED;
|
drv->scan_state = SCAN_COMPLETED;
|
||||||
drv->scan_complete_events = 1;
|
drv->scan_complete_events = 1;
|
||||||
if (drv->last_scan_cmd == NL80211_CMD_TRIGGER_SCAN) {
|
if (drv->last_scan_cmd == NL80211_CMD_TRIGGER_SCAN) {
|
||||||
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout,
|
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout,
|
||||||
drv, drv->ctx);
|
drv, bss->ctx);
|
||||||
drv->last_scan_cmd = 0;
|
drv->last_scan_cmd = 0;
|
||||||
} else {
|
} else {
|
||||||
external_scan_event = 1;
|
external_scan_event = 1;
|
||||||
}
|
}
|
||||||
send_scan_event(drv, 0, tb, external_scan_event);
|
send_scan_event(bss, 0, tb, external_scan_event);
|
||||||
break;
|
break;
|
||||||
case NL80211_CMD_SCHED_SCAN_RESULTS:
|
case NL80211_CMD_SCHED_SCAN_RESULTS:
|
||||||
wpa_dbg(drv->ctx, MSG_DEBUG,
|
wpa_dbg(bss->ctx, MSG_DEBUG,
|
||||||
"nl80211: New sched scan results available");
|
"nl80211: New sched scan results available");
|
||||||
drv->scan_state = SCHED_SCAN_RESULTS;
|
drv->scan_state = SCHED_SCAN_RESULTS;
|
||||||
send_scan_event(drv, 0, tb, 0);
|
send_scan_event(bss, 0, tb, 0);
|
||||||
break;
|
break;
|
||||||
case NL80211_CMD_SCAN_ABORTED:
|
case NL80211_CMD_SCAN_ABORTED:
|
||||||
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Scan aborted");
|
wpa_dbg(bss->ctx, MSG_DEBUG, "nl80211: Scan aborted");
|
||||||
if (drv->last_scan_cmd != NL80211_CMD_VENDOR)
|
if (drv->last_scan_cmd != NL80211_CMD_VENDOR)
|
||||||
drv->scan_state = SCAN_ABORTED;
|
drv->scan_state = SCAN_ABORTED;
|
||||||
if (drv->last_scan_cmd == NL80211_CMD_TRIGGER_SCAN) {
|
if (drv->last_scan_cmd == NL80211_CMD_TRIGGER_SCAN) {
|
||||||
|
@ -3948,12 +4003,12 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
|
||||||
* order not to make wpa_supplicant stop its scanning.
|
* order not to make wpa_supplicant stop its scanning.
|
||||||
*/
|
*/
|
||||||
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout,
|
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout,
|
||||||
drv, drv->ctx);
|
drv, bss->ctx);
|
||||||
drv->last_scan_cmd = 0;
|
drv->last_scan_cmd = 0;
|
||||||
} else {
|
} else {
|
||||||
external_scan_event = 1;
|
external_scan_event = 1;
|
||||||
}
|
}
|
||||||
send_scan_event(drv, 1, tb, external_scan_event);
|
send_scan_event(bss, 1, tb, external_scan_event);
|
||||||
break;
|
break;
|
||||||
case NL80211_CMD_AUTHENTICATE:
|
case NL80211_CMD_AUTHENTICATE:
|
||||||
case NL80211_CMD_ASSOCIATE:
|
case NL80211_CMD_ASSOCIATE:
|
||||||
|
@ -4031,7 +4086,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
|
||||||
mlme_event_remain_on_channel(drv, 1, tb);
|
mlme_event_remain_on_channel(drv, 1, tb);
|
||||||
break;
|
break;
|
||||||
case NL80211_CMD_NOTIFY_CQM:
|
case NL80211_CMD_NOTIFY_CQM:
|
||||||
nl80211_cqm_event(drv, tb);
|
nl80211_cqm_event(bss, tb);
|
||||||
break;
|
break;
|
||||||
case NL80211_CMD_REG_CHANGE:
|
case NL80211_CMD_REG_CHANGE:
|
||||||
case NL80211_CMD_WIPHY_REG_CHANGE:
|
case NL80211_CMD_WIPHY_REG_CHANGE:
|
||||||
|
@ -4068,7 +4123,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
|
||||||
nl80211_radar_event(drv, tb);
|
nl80211_radar_event(drv, tb);
|
||||||
break;
|
break;
|
||||||
case NL80211_CMD_STOP_AP:
|
case NL80211_CMD_STOP_AP:
|
||||||
nl80211_stop_ap(drv, tb);
|
nl80211_stop_ap(bss, tb);
|
||||||
break;
|
break;
|
||||||
case NL80211_CMD_VENDOR:
|
case NL80211_CMD_VENDOR:
|
||||||
nl80211_vendor_event(drv, tb);
|
nl80211_vendor_event(drv, tb);
|
||||||
|
@ -4202,7 +4257,16 @@ int process_global_event(struct nl_msg *msg, void *arg)
|
||||||
wdev_id == bss->wdev_id)) {
|
wdev_id == bss->wdev_id)) {
|
||||||
processed = true;
|
processed = true;
|
||||||
do_process_drv_event(bss, gnlh->cmd, tb);
|
do_process_drv_event(bss, gnlh->cmd, tb);
|
||||||
if (!wiphy_idx_set)
|
/* There are two types of events that may need
|
||||||
|
* to be delivered to multiple interfaces:
|
||||||
|
* 1. Events for a wiphy, as it can have
|
||||||
|
* multiple interfaces.
|
||||||
|
* 2. "Global" events, like
|
||||||
|
* NL80211_CMD_REG_CHANGE.
|
||||||
|
*
|
||||||
|
* Terminate early only if the event is directed
|
||||||
|
* to a specific interface or wdev. */
|
||||||
|
if (ifidx != -1 || wdev_id_set)
|
||||||
return NL_SKIP;
|
return NL_SKIP;
|
||||||
/* The driver instance could have been removed,
|
/* The driver instance could have been removed,
|
||||||
* e.g., due to NL80211_CMD_RADAR_DETECT event,
|
* e.g., due to NL80211_CMD_RADAR_DETECT event,
|
||||||
|
|
|
@ -153,6 +153,7 @@ fail:
|
||||||
void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx)
|
void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx)
|
||||||
{
|
{
|
||||||
struct wpa_driver_nl80211_data *drv = eloop_ctx;
|
struct wpa_driver_nl80211_data *drv = eloop_ctx;
|
||||||
|
struct i802_bss *bss;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Scan timeout - try to abort it");
|
wpa_printf(MSG_DEBUG, "nl80211: Scan timeout - try to abort it");
|
||||||
#ifdef CONFIG_DRIVER_NL80211_QCA
|
#ifdef CONFIG_DRIVER_NL80211_QCA
|
||||||
|
@ -160,14 +161,27 @@ void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx)
|
||||||
nl80211_abort_vendor_scan(drv, drv->vendor_scan_cookie) == 0)
|
nl80211_abort_vendor_scan(drv, drv->vendor_scan_cookie) == 0)
|
||||||
return;
|
return;
|
||||||
#endif /* CONFIG_DRIVER_NL80211_QCA */
|
#endif /* CONFIG_DRIVER_NL80211_QCA */
|
||||||
if (!drv->vendor_scan_cookie &&
|
|
||||||
nl80211_abort_scan(drv->first_bss) == 0)
|
for (bss = drv->first_bss; bss; bss = bss->next) {
|
||||||
|
if (bss->scan_link)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bss) {
|
||||||
|
wpa_printf(MSG_DEBUG, "nl80211: Failed to find scan BSS");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!drv->vendor_scan_cookie &&
|
||||||
|
nl80211_abort_scan(bss) == 0) {
|
||||||
|
bss->scan_link = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Failed to abort scan");
|
wpa_printf(MSG_DEBUG, "nl80211: Failed to abort scan");
|
||||||
|
|
||||||
if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED)
|
if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED)
|
||||||
nl80211_restore_ap_mode(drv->first_bss);
|
nl80211_restore_ap_mode(bss);
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Try to get scan results");
|
wpa_printf(MSG_DEBUG, "nl80211: Try to get scan results");
|
||||||
wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
|
wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
|
||||||
|
@ -347,7 +361,7 @@ int wpa_driver_nl80211_scan(struct i802_bss *bss,
|
||||||
int ret = -1, timeout;
|
int ret = -1, timeout;
|
||||||
struct nl_msg *msg = NULL;
|
struct nl_msg *msg = NULL;
|
||||||
|
|
||||||
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: scan request");
|
wpa_dbg(bss->ctx, MSG_DEBUG, "nl80211: scan request");
|
||||||
drv->scan_for_auth = 0;
|
drv->scan_for_auth = 0;
|
||||||
|
|
||||||
if (TEST_FAIL())
|
if (TEST_FAIL())
|
||||||
|
@ -402,6 +416,40 @@ int wpa_driver_nl80211_scan(struct i802_bss *bss,
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Scan trigger failed: ret=%d "
|
wpa_printf(MSG_DEBUG, "nl80211: Scan trigger failed: ret=%d "
|
||||||
"(%s)", ret, strerror(-ret));
|
"(%s)", ret, strerror(-ret));
|
||||||
if (drv->hostapd && is_ap_interface(drv->nlmode)) {
|
if (drv->hostapd && is_ap_interface(drv->nlmode)) {
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
/* For multi link BSS, retry scan if any other links
|
||||||
|
* are busy scanning. */
|
||||||
|
if (ret == -EBUSY &&
|
||||||
|
nl80211_link_valid(bss->valid_links,
|
||||||
|
params->link_id)) {
|
||||||
|
struct i802_bss *link_bss;
|
||||||
|
u8 link_id;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"nl80211: Scan trigger on multi link BSS failed (requested link=%d on interface %s)",
|
||||||
|
params->link_id, bss->ifname);
|
||||||
|
|
||||||
|
for (link_bss = drv->first_bss; link_bss;
|
||||||
|
link_bss = link_bss->next) {
|
||||||
|
if (link_bss->scan_link)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!link_bss) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"nl80211: BSS information already running scan not available");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
link_id = nl80211_get_link_id_from_link(
|
||||||
|
link_bss, link_bss->scan_link);
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"nl80211: Scan already running on interface %s link %d",
|
||||||
|
link_bss->ifname, link_id);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* mac80211 does not allow scan requests in AP mode, so
|
* mac80211 does not allow scan requests in AP mode, so
|
||||||
* try to do this in station mode.
|
* try to do this in station mode.
|
||||||
|
@ -435,11 +483,20 @@ int wpa_driver_nl80211_scan(struct i802_bss *bss,
|
||||||
}
|
}
|
||||||
wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d "
|
wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d "
|
||||||
"seconds", ret, timeout);
|
"seconds", ret, timeout);
|
||||||
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
|
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, bss->ctx);
|
||||||
eloop_register_timeout(timeout, 0, wpa_driver_nl80211_scan_timeout,
|
eloop_register_timeout(timeout, 0, wpa_driver_nl80211_scan_timeout,
|
||||||
drv, drv->ctx);
|
drv, bss->ctx);
|
||||||
drv->last_scan_cmd = NL80211_CMD_TRIGGER_SCAN;
|
drv->last_scan_cmd = NL80211_CMD_TRIGGER_SCAN;
|
||||||
|
|
||||||
|
bss->scan_link = bss->flink;
|
||||||
|
if (is_ap_interface(drv->nlmode) &&
|
||||||
|
nl80211_link_valid(bss->valid_links, params->link_id)) {
|
||||||
|
wpa_dbg(bss->ctx, MSG_DEBUG,
|
||||||
|
"nl80211: Scan requested for link %d",
|
||||||
|
params->link_id);
|
||||||
|
bss->scan_link = nl80211_get_link(bss, params->link_id);
|
||||||
|
}
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
nlmsg_free(msg);
|
nlmsg_free(msg);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1294,9 +1351,9 @@ int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss,
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"nl80211: Vendor scan requested (ret=%d) - scan timeout 30 seconds, scan cookie:0x%llx",
|
"nl80211: Vendor scan requested (ret=%d) - scan timeout 30 seconds, scan cookie:0x%llx",
|
||||||
ret, (long long unsigned int) cookie);
|
ret, (long long unsigned int) cookie);
|
||||||
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
|
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, bss->ctx);
|
||||||
eloop_register_timeout(30, 0, wpa_driver_nl80211_scan_timeout,
|
eloop_register_timeout(30, 0, wpa_driver_nl80211_scan_timeout,
|
||||||
drv, drv->ctx);
|
drv, bss->ctx);
|
||||||
drv->last_scan_cmd = NL80211_CMD_VENDOR;
|
drv->last_scan_cmd = NL80211_CMD_VENDOR;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -18,11 +18,6 @@
|
||||||
#include "fst/fst_ctrl_defs.h"
|
#include "fst/fst_ctrl_defs.h"
|
||||||
#endif /* CONFIG_FST_TEST */
|
#endif /* CONFIG_FST_TEST */
|
||||||
|
|
||||||
#define US_80211_TU 1024
|
|
||||||
|
|
||||||
#define US_TO_TU(m) ((m) * / US_80211_TU)
|
|
||||||
#define TU_TO_US(m) ((m) * US_80211_TU)
|
|
||||||
|
|
||||||
#define FST_LLT_SWITCH_IMMEDIATELY 0
|
#define FST_LLT_SWITCH_IMMEDIATELY 0
|
||||||
|
|
||||||
#define fst_printf_session(s, level, format, ...) \
|
#define fst_printf_session(s, level, format, ...) \
|
||||||
|
@ -182,7 +177,8 @@ static void fst_session_timeout_handler(void *eloop_data, void *user_ctx)
|
||||||
static void fst_session_stt_arm(struct fst_session *s)
|
static void fst_session_stt_arm(struct fst_session *s)
|
||||||
{
|
{
|
||||||
/* Action frames sometimes get delayed. Use relaxed timeout (2*) */
|
/* Action frames sometimes get delayed. Use relaxed timeout (2*) */
|
||||||
eloop_register_timeout(0, 2 * TU_TO_US(FST_DEFAULT_SESSION_TIMEOUT_TU),
|
eloop_register_timeout(0,
|
||||||
|
2 * TU_TO_USEC(FST_DEFAULT_SESSION_TIMEOUT_TU),
|
||||||
fst_session_timeout_handler, NULL, s);
|
fst_session_timeout_handler, NULL, s);
|
||||||
s->stt_armed = true;
|
s->stt_armed = true;
|
||||||
}
|
}
|
||||||
|
|
245
src/p2p/p2p.c
245
src/p2p/p2p.c
|
@ -954,6 +954,7 @@ static void p2p_device_free(struct p2p_data *p2p, struct p2p_device *dev)
|
||||||
dev->info.wps_vendor_ext[i] = NULL;
|
dev->info.wps_vendor_ext[i] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
os_free(dev->bootstrap_params);
|
||||||
wpabuf_free(dev->info.wfd_subelems);
|
wpabuf_free(dev->info.wfd_subelems);
|
||||||
wpabuf_free(dev->info.vendor_elems);
|
wpabuf_free(dev->info.vendor_elems);
|
||||||
wpabuf_free(dev->go_neg_conf);
|
wpabuf_free(dev->go_neg_conf);
|
||||||
|
@ -1599,7 +1600,8 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
|
||||||
int go_intent, const u8 *own_interface_addr,
|
int go_intent, const u8 *own_interface_addr,
|
||||||
unsigned int force_freq, int persistent_group,
|
unsigned int force_freq, int persistent_group,
|
||||||
const u8 *force_ssid, size_t force_ssid_len,
|
const u8 *force_ssid, size_t force_ssid_len,
|
||||||
int pd_before_go_neg, unsigned int pref_freq, u16 oob_pw_id)
|
int pd_before_go_neg, unsigned int pref_freq, u16 oob_pw_id,
|
||||||
|
bool p2p2, u16 bootstrap, const char *password)
|
||||||
{
|
{
|
||||||
struct p2p_device *dev;
|
struct p2p_device *dev;
|
||||||
|
|
||||||
|
@ -1683,6 +1685,10 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
|
||||||
|
|
||||||
dev->wps_method = wps_method;
|
dev->wps_method = wps_method;
|
||||||
dev->oob_pw_id = oob_pw_id;
|
dev->oob_pw_id = oob_pw_id;
|
||||||
|
dev->p2p2 = p2p2;
|
||||||
|
dev->req_bootstrap_method = bootstrap;
|
||||||
|
if (password && os_strlen(password) < sizeof(dev->password))
|
||||||
|
os_strlcpy(dev->password, password, sizeof(dev->password));
|
||||||
dev->status = P2P_SC_SUCCESS;
|
dev->status = P2P_SC_SUCCESS;
|
||||||
|
|
||||||
if (p2p->p2p_scan_running) {
|
if (p2p->p2p_scan_running) {
|
||||||
|
@ -1701,7 +1707,8 @@ int p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr,
|
||||||
int go_intent, const u8 *own_interface_addr,
|
int go_intent, const u8 *own_interface_addr,
|
||||||
unsigned int force_freq, int persistent_group,
|
unsigned int force_freq, int persistent_group,
|
||||||
const u8 *force_ssid, size_t force_ssid_len,
|
const u8 *force_ssid, size_t force_ssid_len,
|
||||||
unsigned int pref_freq, u16 oob_pw_id)
|
unsigned int pref_freq, u16 oob_pw_id, u16 bootstrap,
|
||||||
|
const char *password)
|
||||||
{
|
{
|
||||||
struct p2p_device *dev;
|
struct p2p_device *dev;
|
||||||
|
|
||||||
|
@ -1735,6 +1742,10 @@ int p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr,
|
||||||
dev->flags &= ~P2P_DEV_USER_REJECTED;
|
dev->flags &= ~P2P_DEV_USER_REJECTED;
|
||||||
dev->go_neg_req_sent = 0;
|
dev->go_neg_req_sent = 0;
|
||||||
dev->go_state = UNKNOWN_GO;
|
dev->go_state = UNKNOWN_GO;
|
||||||
|
dev->req_bootstrap_method = bootstrap;
|
||||||
|
|
||||||
|
if (password && os_strlen(password) < sizeof(dev->password))
|
||||||
|
os_strlcpy(dev->password, password, sizeof(dev->password));
|
||||||
p2p_set_dev_persistent(dev, persistent_group);
|
p2p_set_dev_persistent(dev, persistent_group);
|
||||||
p2p->go_intent = go_intent;
|
p2p->go_intent = go_intent;
|
||||||
os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN);
|
os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN);
|
||||||
|
@ -1924,10 +1935,10 @@ static void p2p_rx_p2p_action(struct p2p_data *p2p, const u8 *sa,
|
||||||
p2p_process_invitation_resp(p2p, sa, data + 1, len - 1);
|
p2p_process_invitation_resp(p2p, sa, data + 1, len - 1);
|
||||||
break;
|
break;
|
||||||
case P2P_PROV_DISC_REQ:
|
case P2P_PROV_DISC_REQ:
|
||||||
p2p_process_prov_disc_req(p2p, sa, data + 1, len - 1, rx_freq);
|
p2p_handle_prov_disc_req(p2p, sa, data + 1, len - 1, rx_freq);
|
||||||
break;
|
break;
|
||||||
case P2P_PROV_DISC_RESP:
|
case P2P_PROV_DISC_RESP:
|
||||||
p2p_process_prov_disc_resp(p2p, sa, data + 1, len - 1);
|
p2p_handle_prov_disc_resp(p2p, sa, data + 1, len - 1, rx_freq);
|
||||||
break;
|
break;
|
||||||
case P2P_DEV_DISC_REQ:
|
case P2P_DEV_DISC_REQ:
|
||||||
p2p_process_dev_disc_req(p2p, sa, data + 1, len - 1, rx_freq);
|
p2p_process_dev_disc_req(p2p, sa, data + 1, len - 1, rx_freq);
|
||||||
|
@ -2968,6 +2979,44 @@ bool is_p2p_6ghz_disabled(struct p2p_data *p2p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void p2p_pairing_info_deinit(struct p2p_data *p2p)
|
||||||
|
{
|
||||||
|
os_free(p2p->pairing_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int p2p_pairing_info_init(struct p2p_data *p2p)
|
||||||
|
{
|
||||||
|
struct p2p_pairing_info *pairing_info;
|
||||||
|
|
||||||
|
if (p2p->cfg->pairing_config.dik_len > DEVICE_IDENTITY_KEY_MAX_LEN)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
pairing_info = os_zalloc(sizeof(struct p2p_pairing_info));
|
||||||
|
if (!pairing_info)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
pairing_info->enable_pairing_setup =
|
||||||
|
p2p->cfg->pairing_config.enable_pairing_setup;
|
||||||
|
pairing_info->enable_pairing_cache =
|
||||||
|
p2p->cfg->pairing_config.enable_pairing_cache;
|
||||||
|
pairing_info->supported_bootstrap =
|
||||||
|
p2p->cfg->pairing_config.bootstrap_methods;
|
||||||
|
|
||||||
|
pairing_info->dev_ik.cipher_version =
|
||||||
|
p2p->cfg->pairing_config.dik_cipher;
|
||||||
|
pairing_info->dev_ik.dik_len = p2p->cfg->pairing_config.dik_len;
|
||||||
|
os_memcpy(pairing_info->dev_ik.dik_data,
|
||||||
|
p2p->cfg->pairing_config.dik_data,
|
||||||
|
p2p->cfg->pairing_config.dik_len);
|
||||||
|
|
||||||
|
p2p_pairing_info_deinit(p2p);
|
||||||
|
p2p->pairing_info = pairing_info;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct p2p_data * p2p_init(const struct p2p_config *cfg)
|
struct p2p_data * p2p_init(const struct p2p_config *cfg)
|
||||||
{
|
{
|
||||||
struct p2p_data *p2p;
|
struct p2p_data *p2p;
|
||||||
|
@ -3023,6 +3072,10 @@ struct p2p_data * p2p_init(const struct p2p_config *cfg)
|
||||||
p2p->go_timeout = 100;
|
p2p->go_timeout = 100;
|
||||||
p2p->client_timeout = 20;
|
p2p->client_timeout = 20;
|
||||||
p2p->num_p2p_sd_queries = 0;
|
p2p->num_p2p_sd_queries = 0;
|
||||||
|
/* Default comeback after one second */
|
||||||
|
if (!p2p->cfg->comeback_after)
|
||||||
|
p2p->cfg->comeback_after = 977; /* TUs */
|
||||||
|
p2p_pairing_info_init(p2p);
|
||||||
|
|
||||||
p2p_dbg(p2p, "initialized");
|
p2p_dbg(p2p, "initialized");
|
||||||
p2p_channels_dump(p2p, "channels", &p2p->cfg->channels);
|
p2p_channels_dump(p2p, "channels", &p2p->cfg->channels);
|
||||||
|
@ -3066,6 +3119,7 @@ void p2p_deinit(struct p2p_data *p2p)
|
||||||
p2p_remove_wps_vendor_extensions(p2p);
|
p2p_remove_wps_vendor_extensions(p2p);
|
||||||
os_free(p2p->no_go_freq.range);
|
os_free(p2p->no_go_freq.range);
|
||||||
p2p_service_flush_asp(p2p);
|
p2p_service_flush_asp(p2p);
|
||||||
|
p2p_pairing_info_deinit(p2p);
|
||||||
|
|
||||||
os_free(p2p);
|
os_free(p2p);
|
||||||
}
|
}
|
||||||
|
@ -3399,7 +3453,7 @@ static void p2p_retry_pd(struct p2p_data *p2p)
|
||||||
if (!ether_addr_equal(p2p->pending_pd_devaddr,
|
if (!ether_addr_equal(p2p->pending_pd_devaddr,
|
||||||
dev->info.p2p_device_addr))
|
dev->info.p2p_device_addr))
|
||||||
continue;
|
continue;
|
||||||
if (!dev->req_config_methods)
|
if (!dev->req_config_methods && !dev->req_bootstrap_method)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
p2p_dbg(p2p, "Send pending Provision Discovery Request to "
|
p2p_dbg(p2p, "Send pending Provision Discovery Request to "
|
||||||
|
@ -5688,3 +5742,184 @@ void set_p2p_allow_6ghz(struct p2p_data *p2p, bool value)
|
||||||
{
|
{
|
||||||
p2p->allow_6ghz = value;
|
p2p->allow_6ghz = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int p2p_derive_nonce_tag(struct p2p_data *p2p)
|
||||||
|
{
|
||||||
|
u8 dira_nonce[DEVICE_IDENTITY_NONCE_LEN];
|
||||||
|
u8 dira_tag[DEVICE_MAX_HASH_LEN];
|
||||||
|
u8 data[DIR_STR_LEN + DEVICE_IDENTITY_NONCE_LEN + ETH_ALEN];
|
||||||
|
struct p2p_id_key *dev_ik;
|
||||||
|
|
||||||
|
dev_ik = &p2p->pairing_info->dev_ik;
|
||||||
|
|
||||||
|
if (dev_ik->cipher_version != DIRA_CIPHER_VERSION_128) {
|
||||||
|
wpa_printf(MSG_INFO,
|
||||||
|
"P2P: Unsupported DIRA Cipher version = %d",
|
||||||
|
dev_ik->cipher_version);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dev_ik->dik_len != DEVICE_IDENTITY_KEY_LEN) {
|
||||||
|
wpa_printf(MSG_INFO, "P2P: Invalid DIK length = %zu",
|
||||||
|
dev_ik->dik_len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
os_memset(data, 0, sizeof(data));
|
||||||
|
|
||||||
|
if (os_get_random(dira_nonce, DEVICE_IDENTITY_NONCE_LEN) < 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "P2P: Failed to generate DIRA nonce");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tag = Truncate-64(HMAC-SHA-256(DevIK,
|
||||||
|
* "DIR" || P2P Device Address || Nonce))
|
||||||
|
*/
|
||||||
|
os_memcpy(data, "DIR", DIR_STR_LEN);
|
||||||
|
os_memcpy(&data[DIR_STR_LEN], p2p->cfg->dev_addr, ETH_ALEN);
|
||||||
|
os_memcpy(&data[DIR_STR_LEN + ETH_ALEN], dira_nonce,
|
||||||
|
DEVICE_IDENTITY_NONCE_LEN);
|
||||||
|
|
||||||
|
if (hmac_sha256(dev_ik->dik_data, dev_ik->dik_len, data, sizeof(data),
|
||||||
|
dira_tag) < 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "P2P: Could not derive DIRA tag");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_ik->dira_nonce_len = DEVICE_IDENTITY_NONCE_LEN;
|
||||||
|
os_memcpy(dev_ik->dira_nonce, dira_nonce, DEVICE_IDENTITY_NONCE_LEN);
|
||||||
|
dev_ik->dira_tag_len = DEVICE_IDENTITY_TAG_LEN;
|
||||||
|
os_memcpy(dev_ik->dira_tag, dira_tag, DEVICE_IDENTITY_TAG_LEN);
|
||||||
|
|
||||||
|
wpa_hexdump_key(MSG_DEBUG, "P2P: DIK", dev_ik->dik_data,
|
||||||
|
dev_ik->dik_len);
|
||||||
|
wpa_hexdump_key(MSG_DEBUG, "P2P: DIRA-NONCE", dev_ik->dira_nonce,
|
||||||
|
dev_ik->dira_nonce_len);
|
||||||
|
wpa_hexdump_key(MSG_DEBUG, "P2P: DIRA-TAG", dev_ik->dira_tag,
|
||||||
|
dev_ik->dira_tag_len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct wpabuf * p2p_usd_elems(struct p2p_data *p2p)
|
||||||
|
{
|
||||||
|
struct wpabuf *buf;
|
||||||
|
u8 *len;
|
||||||
|
u8 group_capab;
|
||||||
|
|
||||||
|
buf = wpabuf_alloc(1000);
|
||||||
|
if (!buf)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
len = p2p_buf_add_ie_hdr(buf);
|
||||||
|
|
||||||
|
/* P2P Capability attribute */
|
||||||
|
group_capab = 0;
|
||||||
|
if (p2p->num_groups) {
|
||||||
|
group_capab |= P2P_GROUP_CAPAB_GROUP_OWNER;
|
||||||
|
if ((p2p->dev_capab & P2P_DEV_CAPAB_CONCURRENT_OPER) &&
|
||||||
|
(p2p->dev_capab & P2P_DEV_CAPAB_INFRA_MANAGED) &&
|
||||||
|
p2p->cross_connect)
|
||||||
|
group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
|
||||||
|
}
|
||||||
|
if (p2p->cfg->p2p_intra_bss)
|
||||||
|
group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST;
|
||||||
|
p2p_buf_add_capability(buf, p2p->dev_capab &
|
||||||
|
~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY,
|
||||||
|
group_capab);
|
||||||
|
|
||||||
|
/* P2P Device Info attribute */
|
||||||
|
p2p_buf_add_device_info(buf, p2p, NULL);
|
||||||
|
|
||||||
|
p2p_buf_update_ie_hdr(buf, len);
|
||||||
|
|
||||||
|
len = p2p_buf_add_p2p2_ie_hdr(buf);
|
||||||
|
|
||||||
|
/* P2P Capability Extension attribute */
|
||||||
|
p2p_buf_add_pcea(buf, p2p);
|
||||||
|
|
||||||
|
/* P2P Pairing Bootstrapping Method attribute */
|
||||||
|
p2p_buf_add_pbma(buf, p2p->cfg->pairing_config.bootstrap_methods, NULL,
|
||||||
|
0, 0);
|
||||||
|
|
||||||
|
/* P2P Device Identity Resolution attribute */
|
||||||
|
if (p2p->pairing_info &&
|
||||||
|
p2p->cfg->pairing_config.pairing_capable &&
|
||||||
|
p2p->cfg->pairing_config.enable_pairing_cache &&
|
||||||
|
p2p->cfg->pairing_config.enable_pairing_verification &&
|
||||||
|
p2p_derive_nonce_tag(p2p) == 0)
|
||||||
|
p2p_buf_add_dira(buf, p2p);
|
||||||
|
|
||||||
|
p2p_buf_update_ie_hdr(buf, len);
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void p2p_process_usd_elems(struct p2p_data *p2p, const u8 *ies, u16 ies_len,
|
||||||
|
const u8 *peer_addr, unsigned int freq)
|
||||||
|
{
|
||||||
|
struct p2p_device *dev;
|
||||||
|
struct p2p_message msg;
|
||||||
|
const u8 *p2p_dev_addr;
|
||||||
|
|
||||||
|
os_memset(&msg, 0, sizeof(msg));
|
||||||
|
if (p2p_parse_ies(ies, ies_len, &msg)) {
|
||||||
|
p2p_dbg(p2p, "Failed to parse P2P IE for a device entry");
|
||||||
|
p2p_parse_free(&msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (msg.p2p_device_addr)
|
||||||
|
p2p_dev_addr = msg.p2p_device_addr;
|
||||||
|
else
|
||||||
|
p2p_dev_addr = peer_addr;
|
||||||
|
|
||||||
|
dev = p2p_create_device(p2p, p2p_dev_addr);
|
||||||
|
if (!dev) {
|
||||||
|
p2p_parse_free(&msg);
|
||||||
|
p2p_dbg(p2p, "Failed to add a peer P2P Device");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->p2p2 = true;
|
||||||
|
/* Reset info from old IEs */
|
||||||
|
dev->info.reg_info = 0;
|
||||||
|
os_memset(&dev->info.pairing_config, 0,
|
||||||
|
sizeof(struct p2p_pairing_config));
|
||||||
|
|
||||||
|
os_get_reltime(&dev->last_seen);
|
||||||
|
dev->listen_freq = freq;
|
||||||
|
dev->oper_freq = freq;
|
||||||
|
|
||||||
|
if (msg.capability) {
|
||||||
|
/*
|
||||||
|
* P2P Client Discoverability bit is reserved in all frames
|
||||||
|
* that use this function, so do not change its value here.
|
||||||
|
*/
|
||||||
|
dev->info.dev_capab &= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
|
||||||
|
dev->info.dev_capab |= msg.capability[0] &
|
||||||
|
~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
|
||||||
|
dev->info.group_capab = msg.capability[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg.pcea_info && msg.pcea_info_len >= 2)
|
||||||
|
p2p_process_pcea(p2p, &msg, dev);
|
||||||
|
|
||||||
|
if (msg.pbma_info && msg.pbma_info_len == 2)
|
||||||
|
dev->info.pairing_config.bootstrap_methods =
|
||||||
|
WPA_GET_LE16(msg.pbma_info);
|
||||||
|
|
||||||
|
if (!ether_addr_equal(peer_addr, p2p_dev_addr))
|
||||||
|
os_memcpy(dev->interface_addr, peer_addr, ETH_ALEN);
|
||||||
|
|
||||||
|
p2p_dbg(p2p, "Updated device entry based on USD frame: " MACSTR
|
||||||
|
" dev_capab=0x%x group_capab=0x%x listen_freq=%d",
|
||||||
|
MAC2STR(dev->info.p2p_device_addr), dev->info.dev_capab,
|
||||||
|
dev->info.group_capab, dev->listen_freq);
|
||||||
|
|
||||||
|
p2p->cfg->dev_found(p2p->cfg->cb_ctx, dev->info.p2p_device_addr,
|
||||||
|
&dev->info, !(dev->flags & P2P_DEV_REPORTED_ONCE));
|
||||||
|
|
||||||
|
p2p_parse_free(&msg);
|
||||||
|
}
|
||||||
|
|
125
src/p2p/p2p.h
125
src/p2p/p2p.h
|
@ -12,6 +12,16 @@
|
||||||
#include "common/ieee802_11_defs.h"
|
#include "common/ieee802_11_defs.h"
|
||||||
#include "wps/wps.h"
|
#include "wps/wps.h"
|
||||||
|
|
||||||
|
#define DEVICE_IDENTITY_KEY_MAX_LEN 64
|
||||||
|
#define DEVICE_IDENTITY_KEY_LEN 16
|
||||||
|
#define DEVICE_IDENTITY_TAG_LEN 8
|
||||||
|
#define DEVICE_IDENTITY_NONCE_LEN 8
|
||||||
|
#define DEVICE_MAX_HASH_LEN 32
|
||||||
|
#define DIR_STR_LEN 3
|
||||||
|
|
||||||
|
/* DIRA Cipher versions */
|
||||||
|
#define DIRA_CIPHER_VERSION_128 0
|
||||||
|
|
||||||
struct weighted_pcl;
|
struct weighted_pcl;
|
||||||
|
|
||||||
/* P2P ASP Setup Capability */
|
/* P2P ASP Setup Capability */
|
||||||
|
@ -320,6 +330,50 @@ enum p2p_scan_type {
|
||||||
|
|
||||||
#define P2P_MAX_WPS_VENDOR_EXT 10
|
#define P2P_MAX_WPS_VENDOR_EXT 10
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct p2p_pairing_config - P2P pairing configuration
|
||||||
|
*/
|
||||||
|
struct p2p_pairing_config {
|
||||||
|
/**
|
||||||
|
* Pairing capable
|
||||||
|
*/
|
||||||
|
bool pairing_capable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable P2P pairing setup
|
||||||
|
*/
|
||||||
|
bool enable_pairing_setup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable pairing cache to allow verification
|
||||||
|
*/
|
||||||
|
bool enable_pairing_cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable P2P pairing verification with cached NIK/NPK
|
||||||
|
*/
|
||||||
|
bool enable_pairing_verification;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* P2P bootstrapping methods supported
|
||||||
|
*/
|
||||||
|
u16 bootstrap_methods;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bitmap of supported PASN types
|
||||||
|
*/
|
||||||
|
u8 pasn_type;
|
||||||
|
|
||||||
|
/* Cipher version type */
|
||||||
|
int dik_cipher;
|
||||||
|
|
||||||
|
/* Buffer to hold the DevIK */
|
||||||
|
u8 dik_data[DEVICE_IDENTITY_KEY_MAX_LEN];
|
||||||
|
|
||||||
|
/* Length of DevIK in octets */
|
||||||
|
size_t dik_len;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct p2p_peer_info - P2P peer information
|
* struct p2p_peer_info - P2P peer information
|
||||||
*/
|
*/
|
||||||
|
@ -411,6 +465,21 @@ struct p2p_peer_info {
|
||||||
* p2ps_instance - P2PS Application Service Info
|
* p2ps_instance - P2PS Application Service Info
|
||||||
*/
|
*/
|
||||||
struct wpabuf *p2ps_instance;
|
struct wpabuf *p2ps_instance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pcea_cap_info - Capability info in PCEA
|
||||||
|
*/
|
||||||
|
u16 pcea_cap_info;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The regulatory info encoding for operation in 6 GHz band
|
||||||
|
*/
|
||||||
|
u8 reg_info;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* p2p_pairing_config - P2P pairing configuration
|
||||||
|
*/
|
||||||
|
struct p2p_pairing_config pairing_config;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum p2p_prov_disc_status {
|
enum p2p_prov_disc_status {
|
||||||
|
@ -589,6 +658,33 @@ struct p2p_config {
|
||||||
*/
|
*/
|
||||||
unsigned int passphrase_len;
|
unsigned int passphrase_len;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* p2p_pairing_config - P2P pairing configuration
|
||||||
|
*/
|
||||||
|
struct p2p_pairing_config pairing_config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* reg_info - Regulatory info encoding for operation in 6 GHz band
|
||||||
|
*/
|
||||||
|
u8 reg_info;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dfs_owner - Enable P2P GO to act as DFS Owner
|
||||||
|
*/
|
||||||
|
bool dfs_owner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* twt_power_mgmt - Enable TWT based power management for P2P
|
||||||
|
*/
|
||||||
|
bool twt_power_mgmt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* comeback_after - Bootstrap request unauthorized for peer
|
||||||
|
*
|
||||||
|
* Ask to come back after this many TUs.
|
||||||
|
*/
|
||||||
|
u16 comeback_after;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cb_ctx - Context to use with callback functions
|
* cb_ctx - Context to use with callback functions
|
||||||
*/
|
*/
|
||||||
|
@ -1136,6 +1232,19 @@ struct p2p_config {
|
||||||
int (*get_pref_freq_list)(void *ctx, int go,
|
int (*get_pref_freq_list)(void *ctx, int go,
|
||||||
unsigned int *len,
|
unsigned int *len,
|
||||||
struct weighted_pcl *freq_list);
|
struct weighted_pcl *freq_list);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* register_bootstrap_comeback - Register timeout to initiate bootstrap
|
||||||
|
* comeback request
|
||||||
|
* @ctx: Callback context from cb_ctx
|
||||||
|
* @addr: P2P Device Address to which comeback request is to be sent
|
||||||
|
* @comeback_after: Time in TUs after which comeback request is sent
|
||||||
|
*
|
||||||
|
* This function can be used to send comeback request after given
|
||||||
|
* timeout.
|
||||||
|
*/
|
||||||
|
void (*register_bootstrap_comeback)(void *ctx, const u8 *addr,
|
||||||
|
u16 comeback_after);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1319,6 +1428,10 @@ void p2p_stop_listen(struct p2p_data *p2p);
|
||||||
* formation
|
* formation
|
||||||
* @pref_freq: Preferred operating frequency in MHz or 0 (this is only used if
|
* @pref_freq: Preferred operating frequency in MHz or 0 (this is only used if
|
||||||
* force_freq == 0)
|
* force_freq == 0)
|
||||||
|
* @oob_pw_id: OOB password identifier
|
||||||
|
* @p2p2: Device supports P2P2 features
|
||||||
|
* @bootstrap: Bootstrapping method requested for P2P2 provision discovery
|
||||||
|
* @password: P2P2 pairing password or %NULL for opportunistic method
|
||||||
* Returns: 0 on success, -1 on failure
|
* Returns: 0 on success, -1 on failure
|
||||||
*/
|
*/
|
||||||
int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
|
int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
|
||||||
|
@ -1326,7 +1439,8 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
|
||||||
int go_intent, const u8 *own_interface_addr,
|
int go_intent, const u8 *own_interface_addr,
|
||||||
unsigned int force_freq, int persistent_group,
|
unsigned int force_freq, int persistent_group,
|
||||||
const u8 *force_ssid, size_t force_ssid_len,
|
const u8 *force_ssid, size_t force_ssid_len,
|
||||||
int pd_before_go_neg, unsigned int pref_freq, u16 oob_pw_id);
|
int pd_before_go_neg, unsigned int pref_freq, u16 oob_pw_id,
|
||||||
|
bool p2p2, u16 bootstrap, const char *password);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* p2p_authorize - Authorize P2P group formation (GO negotiation)
|
* p2p_authorize - Authorize P2P group formation (GO negotiation)
|
||||||
|
@ -1344,6 +1458,9 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
|
||||||
* @force_ssid_len: Length of $force_ssid buffer
|
* @force_ssid_len: Length of $force_ssid buffer
|
||||||
* @pref_freq: Preferred operating frequency in MHz or 0 (this is only used if
|
* @pref_freq: Preferred operating frequency in MHz or 0 (this is only used if
|
||||||
* force_freq == 0)
|
* force_freq == 0)
|
||||||
|
* @oob_pw_id: OOB password identifier
|
||||||
|
* @bootstrap: Bootstrapping method requested for P2P2 provision discovery
|
||||||
|
* @password: P2P2 pairing password or %NULL for opportunistic method
|
||||||
* Returns: 0 on success, -1 on failure
|
* Returns: 0 on success, -1 on failure
|
||||||
*
|
*
|
||||||
* This is like p2p_connect(), but the actual group negotiation is not
|
* This is like p2p_connect(), but the actual group negotiation is not
|
||||||
|
@ -1354,7 +1471,8 @@ int p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr,
|
||||||
int go_intent, const u8 *own_interface_addr,
|
int go_intent, const u8 *own_interface_addr,
|
||||||
unsigned int force_freq, int persistent_group,
|
unsigned int force_freq, int persistent_group,
|
||||||
const u8 *force_ssid, size_t force_ssid_len,
|
const u8 *force_ssid, size_t force_ssid_len,
|
||||||
unsigned int pref_freq, u16 oob_pw_id);
|
unsigned int pref_freq, u16 oob_pw_id, u16 bootstrap,
|
||||||
|
const char *password);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* p2p_reject - Reject peer device (explicitly block connection attempts)
|
* p2p_reject - Reject peer device (explicitly block connection attempts)
|
||||||
|
@ -2429,5 +2547,8 @@ bool is_p2p_allow_6ghz(struct p2p_data *p2p);
|
||||||
void set_p2p_allow_6ghz(struct p2p_data *p2p, bool value);
|
void set_p2p_allow_6ghz(struct p2p_data *p2p, bool value);
|
||||||
int p2p_remove_6ghz_channels(struct weighted_pcl *pref_freq_list, int size);
|
int p2p_remove_6ghz_channels(struct weighted_pcl *pref_freq_list, int size);
|
||||||
int p2p_channel_to_freq(int op_class, int channel);
|
int p2p_channel_to_freq(int op_class, int channel);
|
||||||
|
struct wpabuf * p2p_usd_elems(struct p2p_data *p2p);
|
||||||
|
void p2p_process_usd_elems(struct p2p_data *p2p, const u8 *ies, u16 ies_len,
|
||||||
|
const u8 *peer_addr, unsigned int freq);
|
||||||
|
|
||||||
#endif /* P2P_H */
|
#endif /* P2P_H */
|
||||||
|
|
|
@ -55,11 +55,24 @@ u8 * p2p_buf_add_ie_hdr(struct wpabuf *buf)
|
||||||
|
|
||||||
void p2p_buf_update_ie_hdr(struct wpabuf *buf, u8 *len)
|
void p2p_buf_update_ie_hdr(struct wpabuf *buf, u8 *len)
|
||||||
{
|
{
|
||||||
/* Update P2P IE Length */
|
/* Update P2P/P2P2 IE Length */
|
||||||
*len = (u8 *) wpabuf_put(buf, 0) - len - 1;
|
*len = (u8 *) wpabuf_put(buf, 0) - len - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
u8 * p2p_buf_add_p2p2_ie_hdr(struct wpabuf *buf)
|
||||||
|
{
|
||||||
|
u8 *len;
|
||||||
|
|
||||||
|
/* P2P2 IE header */
|
||||||
|
wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
|
||||||
|
len = wpabuf_put(buf, 1); /* IE length to be filled */
|
||||||
|
wpabuf_put_be32(buf, P2P2_IE_VENDOR_TYPE);
|
||||||
|
wpa_printf(MSG_DEBUG, "P2P: * P2P2 IE header");
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void p2p_buf_add_capability(struct wpabuf *buf, u8 dev_capab, u8 group_capab)
|
void p2p_buf_add_capability(struct wpabuf *buf, u8 dev_capab, u8 group_capab)
|
||||||
{
|
{
|
||||||
/* P2P Capability */
|
/* P2P Capability */
|
||||||
|
@ -709,6 +722,111 @@ void p2p_buf_add_persistent_group_info(struct wpabuf *buf, const u8 *dev_addr,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void p2p_buf_add_pcea(struct wpabuf *buf, struct p2p_data *p2p)
|
||||||
|
{
|
||||||
|
u8 *len;
|
||||||
|
u16 capability_info = 0;
|
||||||
|
|
||||||
|
/* P2P Capability Extension */
|
||||||
|
wpabuf_put_u8(buf, P2P_ATTR_CAPABILITY_EXTENSION);
|
||||||
|
/* Length to be filled */
|
||||||
|
len = wpabuf_put(buf, 2);
|
||||||
|
|
||||||
|
if (!p2p->cfg->p2p_6ghz_disable)
|
||||||
|
capability_info |= P2P_PCEA_6GHZ;
|
||||||
|
|
||||||
|
if (p2p->cfg->reg_info)
|
||||||
|
capability_info |= P2P_PCEA_REG_INFO;
|
||||||
|
|
||||||
|
if (p2p->cfg->dfs_owner)
|
||||||
|
capability_info |= P2P_PCEA_DFS_OWNER;
|
||||||
|
|
||||||
|
if (p2p->cfg->pairing_config.pairing_capable)
|
||||||
|
capability_info |= P2P_PCEA_PAIRING_CAPABLE;
|
||||||
|
|
||||||
|
if (p2p->cfg->pairing_config.enable_pairing_setup)
|
||||||
|
capability_info |= P2P_PCEA_PAIRING_SETUP_ENABLED;
|
||||||
|
|
||||||
|
if (p2p->cfg->pairing_config.enable_pairing_cache)
|
||||||
|
capability_info |= P2P_PCEA_PMK_CACHING;
|
||||||
|
|
||||||
|
if (p2p->cfg->pairing_config.pasn_type)
|
||||||
|
capability_info |= P2P_PCEA_PASN_TYPE;
|
||||||
|
|
||||||
|
if (p2p->cfg->twt_power_mgmt)
|
||||||
|
capability_info |= P2P_PCEA_TWT_POWER_MGMT;
|
||||||
|
|
||||||
|
/* Field length is (n-1), n in octets */
|
||||||
|
capability_info |= (2 - 1) & P2P_PCEA_LEN_MASK;
|
||||||
|
wpabuf_put_le16(buf, capability_info);
|
||||||
|
|
||||||
|
if (capability_info & P2P_PCEA_REG_INFO)
|
||||||
|
wpabuf_put_u8(buf, p2p->cfg->reg_info);
|
||||||
|
|
||||||
|
if (capability_info & P2P_PCEA_PASN_TYPE)
|
||||||
|
wpabuf_put_u8(buf, p2p->cfg->pairing_config.pasn_type);
|
||||||
|
|
||||||
|
/* Update attribute length */
|
||||||
|
WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "P2P: * Capability Extension info=0x%x",
|
||||||
|
capability_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void p2p_buf_add_pbma(struct wpabuf *buf, u16 bootstrap, const u8 *cookie,
|
||||||
|
size_t cookie_len, int comeback_after)
|
||||||
|
{
|
||||||
|
u8 *len;
|
||||||
|
|
||||||
|
/* P2P Pairing and Bootstrapping methods */
|
||||||
|
wpabuf_put_u8(buf, P2P_ATTR_PAIRING_AND_BOOTSTRAPPING);
|
||||||
|
/* Length to be filled */
|
||||||
|
len = wpabuf_put(buf, 2);
|
||||||
|
|
||||||
|
if (cookie && cookie_len) {
|
||||||
|
if (comeback_after)
|
||||||
|
wpabuf_put_le16(buf, comeback_after);
|
||||||
|
wpabuf_put_u8(buf, cookie_len);
|
||||||
|
wpabuf_put_data(buf, cookie, cookie_len);
|
||||||
|
}
|
||||||
|
wpabuf_put_le16(buf, bootstrap);
|
||||||
|
|
||||||
|
/* Update attribute length */
|
||||||
|
WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "P2P: * Bootstrapping method=0x%x",
|
||||||
|
bootstrap);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void p2p_buf_add_dira(struct wpabuf *buf, struct p2p_data *p2p)
|
||||||
|
{
|
||||||
|
u8 *len;
|
||||||
|
struct p2p_id_key *dev_ik;
|
||||||
|
|
||||||
|
if (!p2p->cfg->pairing_config.pairing_capable ||
|
||||||
|
!p2p->cfg->pairing_config.enable_pairing_cache ||
|
||||||
|
!p2p->cfg->pairing_config.enable_pairing_verification)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dev_ik = &p2p->pairing_info->dev_ik;
|
||||||
|
/* P2P DIRA */
|
||||||
|
wpabuf_put_u8(buf, P2P_ATTR_DEVICE_IDENTITY_RESOLUTION);
|
||||||
|
/* Length to be filled */
|
||||||
|
len = wpabuf_put(buf, 2);
|
||||||
|
|
||||||
|
wpabuf_put_u8(buf, dev_ik->cipher_version);
|
||||||
|
wpabuf_put_data(buf, dev_ik->dira_nonce, dev_ik->dira_nonce_len);
|
||||||
|
wpabuf_put_data(buf, dev_ik->dira_tag, dev_ik->dira_tag_len);
|
||||||
|
|
||||||
|
/* Update attribute length */
|
||||||
|
WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "P2P: * DIRA");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int p2p_add_wps_string(struct wpabuf *buf, enum wps_attribute attr,
|
static int p2p_add_wps_string(struct wpabuf *buf, enum wps_attribute attr,
|
||||||
const char *val)
|
const char *val)
|
||||||
{
|
{
|
||||||
|
|
|
@ -244,6 +244,8 @@ int p2p_connect_send(struct p2p_data *p2p, struct p2p_device *dev)
|
||||||
config_method = WPS_CONFIG_PUSHBUTTON;
|
config_method = WPS_CONFIG_PUSHBUTTON;
|
||||||
else if (dev->wps_method == WPS_P2PS)
|
else if (dev->wps_method == WPS_P2PS)
|
||||||
config_method = WPS_CONFIG_P2PS;
|
config_method = WPS_CONFIG_P2PS;
|
||||||
|
else if (dev->p2p2 && dev->req_bootstrap_method)
|
||||||
|
config_method = WPS_NOT_READY;
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
return p2p_prov_disc_req(p2p, dev->info.p2p_device_addr,
|
return p2p_prov_disc_req(p2p, dev->info.p2p_device_addr,
|
||||||
|
|
|
@ -36,6 +36,26 @@ enum p2p_go_state {
|
||||||
REMOTE_GO
|
REMOTE_GO
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct bootstrap_params - P2P Device bootstrap request parameters
|
||||||
|
*/
|
||||||
|
struct p2p_bootstrap_params {
|
||||||
|
/* Bootstrap method */
|
||||||
|
u16 bootstrap_method;
|
||||||
|
|
||||||
|
/* Status code */
|
||||||
|
enum p2p_status_code status;
|
||||||
|
|
||||||
|
/* Cookie for comeback */
|
||||||
|
u8 cookie[50];
|
||||||
|
|
||||||
|
/* Cookie length */
|
||||||
|
size_t cookie_len;
|
||||||
|
|
||||||
|
/* Comeback time in TUs after which receiver is requested to retry */
|
||||||
|
int comeback_after;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct p2p_device - P2P Device data (internal to P2P module)
|
* struct p2p_device - P2P Device data (internal to P2P module)
|
||||||
*/
|
*/
|
||||||
|
@ -150,6 +170,18 @@ struct p2p_device {
|
||||||
|
|
||||||
int sd_pending_bcast_queries;
|
int sd_pending_bcast_queries;
|
||||||
bool support_6ghz;
|
bool support_6ghz;
|
||||||
|
|
||||||
|
/* Supports P2P2 */
|
||||||
|
bool p2p2;
|
||||||
|
|
||||||
|
/* Requested bootstrap method */
|
||||||
|
u16 req_bootstrap_method;
|
||||||
|
|
||||||
|
/* Bootstrap parameters received from peer */
|
||||||
|
struct p2p_bootstrap_params *bootstrap_params;
|
||||||
|
|
||||||
|
/* Password for P2P2 GO negotiation */
|
||||||
|
char password[100];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct p2p_sd_query {
|
struct p2p_sd_query {
|
||||||
|
@ -160,6 +192,39 @@ struct p2p_sd_query {
|
||||||
struct wpabuf *tlvs;
|
struct wpabuf *tlvs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* P2P Device Identity Key parameters */
|
||||||
|
struct p2p_id_key {
|
||||||
|
/* AKMP used for DevIK derviation */
|
||||||
|
int akmp;
|
||||||
|
/* Cipher version type */
|
||||||
|
int cipher_version;
|
||||||
|
/* Buffer to hold the DevIK */
|
||||||
|
u8 dik_data[DEVICE_IDENTITY_KEY_MAX_LEN];
|
||||||
|
/* Length of DevIK */
|
||||||
|
size_t dik_len;
|
||||||
|
/* Nonce used in DIRA attribute */
|
||||||
|
u8 dira_nonce[DEVICE_IDENTITY_NONCE_LEN];
|
||||||
|
/* Length of nonce */
|
||||||
|
size_t dira_nonce_len;
|
||||||
|
/* Tag computed for nonce using NIK */
|
||||||
|
u8 dira_tag[DEVICE_IDENTITY_TAG_LEN];
|
||||||
|
/* Length of tag in octets */
|
||||||
|
size_t dira_tag_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct p2p_pairing_info {
|
||||||
|
/* P2P device own address */
|
||||||
|
u8 own_addr[ETH_ALEN];
|
||||||
|
/* device capability to enable pairing setup */
|
||||||
|
bool enable_pairing_setup;
|
||||||
|
/* device capability to enable pairing cache */
|
||||||
|
bool enable_pairing_cache;
|
||||||
|
/* device supported bootstrapping */
|
||||||
|
u16 supported_bootstrap;
|
||||||
|
/* P2P Device Identity Key info */
|
||||||
|
struct p2p_id_key dev_ik;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct p2p_data - P2P module data (internal to P2P module)
|
* struct p2p_data - P2P module data (internal to P2P module)
|
||||||
*/
|
*/
|
||||||
|
@ -554,6 +619,8 @@ struct p2p_data {
|
||||||
bool p2p_6ghz_capable;
|
bool p2p_6ghz_capable;
|
||||||
bool include_6ghz;
|
bool include_6ghz;
|
||||||
bool allow_6ghz;
|
bool allow_6ghz;
|
||||||
|
|
||||||
|
struct p2p_pairing_info *pairing_info;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -561,6 +628,7 @@ struct p2p_data {
|
||||||
*/
|
*/
|
||||||
struct p2p_message {
|
struct p2p_message {
|
||||||
struct wpabuf *p2p_attributes;
|
struct wpabuf *p2p_attributes;
|
||||||
|
struct wpabuf *p2p2_attributes;
|
||||||
struct wpabuf *wps_attributes;
|
struct wpabuf *wps_attributes;
|
||||||
struct wpabuf *wfd_subelems;
|
struct wpabuf *wfd_subelems;
|
||||||
|
|
||||||
|
@ -659,6 +727,12 @@ struct p2p_message {
|
||||||
|
|
||||||
const u8 *pref_freq_list;
|
const u8 *pref_freq_list;
|
||||||
size_t pref_freq_list_len;
|
size_t pref_freq_list_len;
|
||||||
|
|
||||||
|
const u8 *pcea_info;
|
||||||
|
size_t pcea_info_len;
|
||||||
|
|
||||||
|
const u8 *pbma_info;
|
||||||
|
size_t pbma_info_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -748,6 +822,7 @@ void p2p_buf_add_action_hdr(struct wpabuf *buf, u8 subtype, u8 dialog_token);
|
||||||
void p2p_buf_add_public_action_hdr(struct wpabuf *buf, u8 subtype,
|
void p2p_buf_add_public_action_hdr(struct wpabuf *buf, u8 subtype,
|
||||||
u8 dialog_token);
|
u8 dialog_token);
|
||||||
u8 * p2p_buf_add_ie_hdr(struct wpabuf *buf);
|
u8 * p2p_buf_add_ie_hdr(struct wpabuf *buf);
|
||||||
|
u8 * p2p_buf_add_p2p2_ie_hdr(struct wpabuf *buf);
|
||||||
void p2p_buf_add_status(struct wpabuf *buf, u8 status);
|
void p2p_buf_add_status(struct wpabuf *buf, u8 status);
|
||||||
void p2p_buf_add_device_info(struct wpabuf *buf, struct p2p_data *p2p,
|
void p2p_buf_add_device_info(struct wpabuf *buf, struct p2p_data *p2p,
|
||||||
struct p2p_device *peer);
|
struct p2p_device *peer);
|
||||||
|
@ -788,6 +863,10 @@ void p2p_buf_add_feature_capability(struct wpabuf *buf, u16 len,
|
||||||
const u8 *mask);
|
const u8 *mask);
|
||||||
void p2p_buf_add_persistent_group_info(struct wpabuf *buf, const u8 *dev_addr,
|
void p2p_buf_add_persistent_group_info(struct wpabuf *buf, const u8 *dev_addr,
|
||||||
const u8 *ssid, size_t ssid_len);
|
const u8 *ssid, size_t ssid_len);
|
||||||
|
void p2p_buf_add_pcea(struct wpabuf *buf, struct p2p_data *p2p);
|
||||||
|
void p2p_buf_add_pbma(struct wpabuf *buf, u16 bootstrap, const u8 *cookie,
|
||||||
|
size_t cookie_len, int comeback_after);
|
||||||
|
void p2p_buf_add_dira(struct wpabuf *buf, struct p2p_data *p2p);
|
||||||
int p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, int pw_id,
|
int p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, int pw_id,
|
||||||
int all_attr);
|
int all_attr);
|
||||||
void p2p_buf_add_pref_channel_list(struct wpabuf *buf,
|
void p2p_buf_add_pref_channel_list(struct wpabuf *buf,
|
||||||
|
@ -826,14 +905,16 @@ void p2p_check_pref_chan(struct p2p_data *p2p, int go,
|
||||||
struct p2p_device *dev, struct p2p_message *msg);
|
struct p2p_device *dev, struct p2p_message *msg);
|
||||||
|
|
||||||
/* p2p_pd.c */
|
/* p2p_pd.c */
|
||||||
void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
|
void p2p_handle_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
|
||||||
|
const u8 *data, size_t len, int rx_freq);
|
||||||
|
void p2p_handle_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
|
||||||
const u8 *data, size_t len, int rx_freq);
|
const u8 *data, size_t len, int rx_freq);
|
||||||
void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
|
|
||||||
const u8 *data, size_t len);
|
|
||||||
int p2p_send_prov_disc_req(struct p2p_data *p2p, struct p2p_device *dev,
|
int p2p_send_prov_disc_req(struct p2p_data *p2p, struct p2p_device *dev,
|
||||||
int join, int force_freq);
|
int join, int force_freq);
|
||||||
void p2p_reset_pending_pd(struct p2p_data *p2p);
|
void p2p_reset_pending_pd(struct p2p_data *p2p);
|
||||||
void p2ps_prov_free(struct p2p_data *p2p);
|
void p2ps_prov_free(struct p2p_data *p2p);
|
||||||
|
void p2p_process_pcea(struct p2p_data *p2p, struct p2p_message *msg,
|
||||||
|
struct p2p_device *dev);
|
||||||
|
|
||||||
/* p2p_invitation.c */
|
/* p2p_invitation.c */
|
||||||
void p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa,
|
void p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa,
|
||||||
|
|
|
@ -417,6 +417,26 @@ static int p2p_parse_attribute(u8 id, const u8 *data, u16 len,
|
||||||
msg->persistent_ssid_len));
|
msg->persistent_ssid_len));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case P2P_ATTR_CAPABILITY_EXTENSION:
|
||||||
|
if (len < 2) {
|
||||||
|
wpa_printf(MSG_DEBUG, "P2P: Too short PCEA (length %d)",
|
||||||
|
len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
msg->pcea_info = data;
|
||||||
|
msg->pcea_info_len = len;
|
||||||
|
wpa_printf(MSG_DEBUG, "P2P: * PCEA (length=%u)", len);
|
||||||
|
break;
|
||||||
|
case P2P_ATTR_PAIRING_AND_BOOTSTRAPPING:
|
||||||
|
if (len < 1) {
|
||||||
|
wpa_printf(MSG_DEBUG, "P2P: Too short PBMA (length %d)",
|
||||||
|
len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
msg->pbma_info = data;
|
||||||
|
msg->pbma_info_len = len;
|
||||||
|
wpa_printf(MSG_DEBUG, "P2P: * PBMA (length=%u)", len);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
wpa_printf(MSG_DEBUG, "P2P: Skipped unknown attribute %d "
|
wpa_printf(MSG_DEBUG, "P2P: Skipped unknown attribute %d "
|
||||||
"(length %d)", id, len);
|
"(length %d)", id, len);
|
||||||
|
@ -573,6 +593,18 @@ int p2p_parse_ies(const u8 *data, size_t len, struct p2p_message *msg)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
msg->p2p2_attributes = ieee802_11_vendor_ie_concat(data, len,
|
||||||
|
P2P2_IE_VENDOR_TYPE);
|
||||||
|
if (msg->p2p2_attributes &&
|
||||||
|
p2p_parse_p2p_ie(msg->p2p2_attributes, msg)) {
|
||||||
|
wpa_printf(MSG_DEBUG, "P2P: Failed to parse P2P2 IE data");
|
||||||
|
if (msg->p2p2_attributes)
|
||||||
|
wpa_hexdump_buf(MSG_MSGDUMP, "P2P: P2P2 IE data",
|
||||||
|
msg->p2p2_attributes);
|
||||||
|
p2p_parse_free(msg);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_WIFI_DISPLAY
|
#ifdef CONFIG_WIFI_DISPLAY
|
||||||
if (elems.wfd) {
|
if (elems.wfd) {
|
||||||
msg->wfd_subelems = ieee802_11_vendor_ie_concat(
|
msg->wfd_subelems = ieee802_11_vendor_ie_concat(
|
||||||
|
@ -647,6 +679,8 @@ void p2p_parse_free(struct p2p_message *msg)
|
||||||
{
|
{
|
||||||
wpabuf_free(msg->p2p_attributes);
|
wpabuf_free(msg->p2p_attributes);
|
||||||
msg->p2p_attributes = NULL;
|
msg->p2p_attributes = NULL;
|
||||||
|
wpabuf_free(msg->p2p2_attributes);
|
||||||
|
msg->p2p2_attributes = NULL;
|
||||||
wpabuf_free(msg->wps_attributes);
|
wpabuf_free(msg->wps_attributes);
|
||||||
msg->wps_attributes = NULL;
|
msg->wps_attributes = NULL;
|
||||||
#ifdef CONFIG_WIFI_DISPLAY
|
#ifdef CONFIG_WIFI_DISPLAY
|
||||||
|
|
794
src/p2p/p2p_pd.c
794
src/p2p/p2p_pd.c
File diff suppressed because it is too large
Load diff
|
@ -192,6 +192,14 @@ int pasn_set_extra_ies(struct pasn_data *pasn, const u8 *extra_ies,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void pasn_set_noauth(struct pasn_data *pasn, bool noauth)
|
||||||
|
{
|
||||||
|
if (!pasn)
|
||||||
|
return;
|
||||||
|
pasn->noauth = noauth;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int pasn_get_akmp(struct pasn_data *pasn)
|
int pasn_get_akmp(struct pasn_data *pasn)
|
||||||
{
|
{
|
||||||
if (!pasn)
|
if (!pasn)
|
||||||
|
|
|
@ -174,7 +174,8 @@ int wpa_pasn_auth_tx_status(struct pasn_data *pasn,
|
||||||
/* Responder */
|
/* Responder */
|
||||||
int handle_auth_pasn_1(struct pasn_data *pasn,
|
int handle_auth_pasn_1(struct pasn_data *pasn,
|
||||||
const u8 *own_addr, const u8 *peer_addr,
|
const u8 *own_addr, const u8 *peer_addr,
|
||||||
const struct ieee80211_mgmt *mgmt, size_t len);
|
const struct ieee80211_mgmt *mgmt, size_t len,
|
||||||
|
bool reject);
|
||||||
int handle_auth_pasn_3(struct pasn_data *pasn, const u8 *own_addr,
|
int handle_auth_pasn_3(struct pasn_data *pasn, const u8 *own_addr,
|
||||||
const u8 *peer_addr,
|
const u8 *peer_addr,
|
||||||
const struct ieee80211_mgmt *mgmt, size_t len);
|
const struct ieee80211_mgmt *mgmt, size_t len);
|
||||||
|
@ -207,6 +208,7 @@ void pasn_set_responder_pmksa(struct pasn_data *pasn,
|
||||||
int pasn_set_pt(struct pasn_data *pasn, struct sae_pt *pt);
|
int pasn_set_pt(struct pasn_data *pasn, struct sae_pt *pt);
|
||||||
|
|
||||||
/* Responder */
|
/* Responder */
|
||||||
|
void pasn_set_noauth(struct pasn_data *pasn, bool noauth);
|
||||||
void pasn_set_password(struct pasn_data *pasn, const char *password);
|
void pasn_set_password(struct pasn_data *pasn, const char *password);
|
||||||
void pasn_set_wpa_key_mgmt(struct pasn_data *pasn, int key_mgmt);
|
void pasn_set_wpa_key_mgmt(struct pasn_data *pasn, int key_mgmt);
|
||||||
void pasn_set_rsn_pairwise(struct pasn_data *pasn, int rsn_pairwise);
|
void pasn_set_rsn_pairwise(struct pasn_data *pasn, int rsn_pairwise);
|
||||||
|
|
|
@ -597,7 +597,8 @@ fail:
|
||||||
|
|
||||||
int handle_auth_pasn_1(struct pasn_data *pasn,
|
int handle_auth_pasn_1(struct pasn_data *pasn,
|
||||||
const u8 *own_addr, const u8 *peer_addr,
|
const u8 *own_addr, const u8 *peer_addr,
|
||||||
const struct ieee80211_mgmt *mgmt, size_t len)
|
const struct ieee80211_mgmt *mgmt, size_t len,
|
||||||
|
bool reject)
|
||||||
{
|
{
|
||||||
struct ieee802_11_elems elems;
|
struct ieee802_11_elems elems;
|
||||||
struct wpa_ie_data rsn_data;
|
struct wpa_ie_data rsn_data;
|
||||||
|
@ -616,6 +617,12 @@ int handle_auth_pasn_1(struct pasn_data *pasn,
|
||||||
if (!groups)
|
if (!groups)
|
||||||
groups = default_groups;
|
groups = default_groups;
|
||||||
|
|
||||||
|
if (reject) {
|
||||||
|
wpa_printf(MSG_DEBUG, "PASN: Received Rejection");
|
||||||
|
status = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||||
|
goto send_resp;
|
||||||
|
}
|
||||||
|
|
||||||
if (ieee802_11_parse_elems(mgmt->u.auth.variable,
|
if (ieee802_11_parse_elems(mgmt->u.auth.variable,
|
||||||
len - offsetof(struct ieee80211_mgmt,
|
len - offsetof(struct ieee80211_mgmt,
|
||||||
u.auth.variable),
|
u.auth.variable),
|
||||||
|
|
|
@ -531,7 +531,7 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
|
||||||
size_t mic_len, hdrlen, rlen, extra_len = 0;
|
size_t mic_len, hdrlen, rlen, extra_len = 0;
|
||||||
struct wpa_eapol_key *reply;
|
struct wpa_eapol_key *reply;
|
||||||
u8 *rbuf, *key_mic;
|
u8 *rbuf, *key_mic;
|
||||||
u8 *rsn_ie_buf = NULL;
|
u8 *rsn_ie_buf = NULL, *buf2 = NULL;
|
||||||
u16 key_info;
|
u16 key_info;
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
size_t pad_len = 0;
|
size_t pad_len = 0;
|
||||||
|
@ -581,6 +581,37 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211R */
|
#endif /* CONFIG_IEEE80211R */
|
||||||
|
|
||||||
|
if (sm->rsn_override != RSN_OVERRIDE_NOT_USED) {
|
||||||
|
u8 *pos;
|
||||||
|
|
||||||
|
buf2 = os_malloc(wpa_ie_len + 2 + 4 + 1);
|
||||||
|
if (!buf2) {
|
||||||
|
os_free(rsn_ie_buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
os_memcpy(buf2, wpa_ie, wpa_ie_len);
|
||||||
|
pos = buf2 + wpa_ie_len;
|
||||||
|
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||||
|
*pos++ = 4 + 1;
|
||||||
|
WPA_PUT_BE32(pos, RSN_SELECTION_IE_VENDOR_TYPE);
|
||||||
|
pos += 4;
|
||||||
|
if (sm->rsn_override == RSN_OVERRIDE_RSNE) {
|
||||||
|
*pos++ = RSN_SELECTION_RSNE;
|
||||||
|
} else if (sm->rsn_override == RSN_OVERRIDE_RSNE_OVERRIDE) {
|
||||||
|
*pos++ = RSN_SELECTION_RSNE_OVERRIDE;
|
||||||
|
} else if (sm->rsn_override == RSN_OVERRIDE_RSNE_OVERRIDE_2) {
|
||||||
|
*pos++ = RSN_SELECTION_RSNE_OVERRIDE_2;
|
||||||
|
} else {
|
||||||
|
os_free(rsn_ie_buf);
|
||||||
|
os_free(buf2);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_ie = buf2;
|
||||||
|
wpa_ie_len += 2 + 4 + 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", wpa_ie, wpa_ie_len);
|
wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", wpa_ie, wpa_ie_len);
|
||||||
|
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
@ -601,6 +632,7 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
|
||||||
&rlen, (void *) &reply);
|
&rlen, (void *) &reply);
|
||||||
if (rbuf == NULL) {
|
if (rbuf == NULL) {
|
||||||
os_free(rsn_ie_buf);
|
os_free(rsn_ie_buf);
|
||||||
|
os_free(buf2);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -633,6 +665,7 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
|
||||||
WPA_PUT_BE16(key_mic + mic_len, wpa_ie_len + extra_len);
|
WPA_PUT_BE16(key_mic + mic_len, wpa_ie_len + extra_len);
|
||||||
os_memcpy(key_mic + mic_len + 2, wpa_ie, wpa_ie_len); /* Key Data */
|
os_memcpy(key_mic + mic_len + 2, wpa_ie, wpa_ie_len); /* Key Data */
|
||||||
os_free(rsn_ie_buf);
|
os_free(rsn_ie_buf);
|
||||||
|
os_free(buf2);
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
if (sm->test_eapol_m2_elems) {
|
if (sm->test_eapol_m2_elems) {
|
||||||
os_memcpy(key_mic + mic_len + 2 + wpa_ie_len,
|
os_memcpy(key_mic + mic_len + 2 + wpa_ie_len,
|
||||||
|
@ -990,6 +1023,8 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
|
||||||
"WPA: Failed to get random data for SNonce");
|
"WPA: Failed to get random data for SNonce");
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
if (wpa_sm_rsn_overriding_supported(sm))
|
||||||
|
rsn_set_snonce_cookie(sm->snonce);
|
||||||
sm->renew_snonce = 0;
|
sm->renew_snonce = 0;
|
||||||
wpa_hexdump(MSG_DEBUG, "WPA: Renewed SNonce",
|
wpa_hexdump(MSG_DEBUG, "WPA: Renewed SNonce",
|
||||||
sm->snonce, WPA_NONCE_LEN);
|
sm->snonce, WPA_NONCE_LEN);
|
||||||
|
@ -2193,6 +2228,68 @@ static int wpa_supplicant_validate_ie(struct wpa_sm *sm,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sm->proto == WPA_PROTO_RSN && wpa_sm_rsn_overriding_supported(sm)) {
|
||||||
|
if ((sm->ap_rsne_override && !ie->rsne_override) ||
|
||||||
|
(!sm->ap_rsne_override && ie->rsne_override) ||
|
||||||
|
(sm->ap_rsne_override && ie->rsne_override &&
|
||||||
|
(sm->ap_rsne_override_len != ie->rsne_override_len ||
|
||||||
|
os_memcmp(sm->ap_rsne_override, ie->rsne_override,
|
||||||
|
sm->ap_rsne_override_len) != 0))) {
|
||||||
|
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
|
||||||
|
"RSN: RSNE Override element mismatch between Beacon/ProbeResp and EAPOL-Key msg 3/4");
|
||||||
|
wpa_hexdump(MSG_INFO,
|
||||||
|
"RSNE Override element in Beacon/ProbeResp",
|
||||||
|
sm->ap_rsne_override,
|
||||||
|
sm->ap_rsne_override_len);
|
||||||
|
wpa_hexdump(MSG_INFO,
|
||||||
|
"RSNE Override element in EAPOL-Key msg 3/4",
|
||||||
|
ie->rsne_override, ie->rsne_override_len);
|
||||||
|
wpa_sm_deauthenticate(sm,
|
||||||
|
WLAN_REASON_IE_IN_4WAY_DIFFERS);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sm->ap_rsne_override_2 && !ie->rsne_override_2) ||
|
||||||
|
(!sm->ap_rsne_override_2 && ie->rsne_override_2) ||
|
||||||
|
(sm->ap_rsne_override_2 && ie->rsne_override_2 &&
|
||||||
|
(sm->ap_rsne_override_2_len != ie->rsne_override_2_len ||
|
||||||
|
os_memcmp(sm->ap_rsne_override_2, ie->rsne_override_2,
|
||||||
|
sm->ap_rsne_override_2_len) != 0))) {
|
||||||
|
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
|
||||||
|
"RSN: RSNE Override 2 element mismatch between Beacon/ProbeResp and EAPOL-Key msg 3/4");
|
||||||
|
wpa_hexdump(MSG_INFO,
|
||||||
|
"RSNE Override 2 element in Beacon/ProbeResp",
|
||||||
|
sm->ap_rsne_override_2,
|
||||||
|
sm->ap_rsne_override_2_len);
|
||||||
|
wpa_hexdump(MSG_INFO,
|
||||||
|
"RSNE Override 2 element in EAPOL-Key msg 3/4",
|
||||||
|
ie->rsne_override_2, ie->rsne_override_2_len);
|
||||||
|
wpa_sm_deauthenticate(sm,
|
||||||
|
WLAN_REASON_IE_IN_4WAY_DIFFERS);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sm->ap_rsnxe_override && !ie->rsnxe_override) ||
|
||||||
|
(!sm->ap_rsnxe_override && ie->rsnxe_override) ||
|
||||||
|
(sm->ap_rsnxe_override && ie->rsnxe_override &&
|
||||||
|
(sm->ap_rsnxe_override_len != ie->rsnxe_override_len ||
|
||||||
|
os_memcmp(sm->ap_rsnxe_override, ie->rsnxe_override,
|
||||||
|
sm->ap_rsnxe_override_len) != 0))) {
|
||||||
|
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
|
||||||
|
"RSN: RSNXE Override element mismatch between Beacon/ProbeResp and EAPOL-Key msg 3/4");
|
||||||
|
wpa_hexdump(MSG_INFO,
|
||||||
|
"RSNXE Override element in Beacon/ProbeResp",
|
||||||
|
sm->ap_rsnxe_override,
|
||||||
|
sm->ap_rsnxe_override_len);
|
||||||
|
wpa_hexdump(MSG_INFO,
|
||||||
|
"RSNXE Override element in EAPOL-Key msg 3/4",
|
||||||
|
ie->rsnxe_override, ie->rsnxe_override_len);
|
||||||
|
wpa_sm_deauthenticate(sm,
|
||||||
|
WLAN_REASON_IE_IN_4WAY_DIFFERS);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211R
|
#ifdef CONFIG_IEEE80211R
|
||||||
if (wpa_key_mgmt_ft(sm->key_mgmt) &&
|
if (wpa_key_mgmt_ft(sm->key_mgmt) &&
|
||||||
wpa_supplicant_validate_ie_ft(sm, src_addr, ie) < 0)
|
wpa_supplicant_validate_ie_ft(sm, src_addr, ie) < 0)
|
||||||
|
@ -2339,10 +2436,14 @@ int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst,
|
||||||
|
|
||||||
static int wpa_supplicant_validate_link_kde(struct wpa_sm *sm, u8 link_id,
|
static int wpa_supplicant_validate_link_kde(struct wpa_sm *sm, u8 link_id,
|
||||||
const u8 *link_kde,
|
const u8 *link_kde,
|
||||||
size_t link_kde_len)
|
size_t link_kde_len,
|
||||||
|
const u8 *rsn_override_link_kde,
|
||||||
|
size_t rsn_override_link_kde_len)
|
||||||
{
|
{
|
||||||
size_t rsne_len = 0, rsnxe_len = 0;
|
size_t rsne_len = 0, rsnxe_len = 0, rsnoe_len = 0, rsno2e_len = 0,
|
||||||
const u8 *rsne = NULL, *rsnxe = NULL;
|
rsnxoe_len = 0;
|
||||||
|
const u8 *rsne = NULL, *rsnxe = NULL, *rsnoe = NULL, *rsno2e = NULL,
|
||||||
|
*rsnxoe = NULL;
|
||||||
|
|
||||||
if (!link_kde ||
|
if (!link_kde ||
|
||||||
link_kde_len < RSN_MLO_LINK_KDE_LINK_MAC_INDEX + ETH_ALEN) {
|
link_kde_len < RSN_MLO_LINK_KDE_LINK_MAC_INDEX + ETH_ALEN) {
|
||||||
|
@ -2403,14 +2504,14 @@ static int wpa_supplicant_validate_link_kde(struct wpa_sm *sm, u8 link_id,
|
||||||
sm->mlo.links[link_id].ap_rsne_len,
|
sm->mlo.links[link_id].ap_rsne_len,
|
||||||
rsne, rsne_len)) {
|
rsne, rsne_len)) {
|
||||||
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
|
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
|
||||||
"RSN MLO: IE in 3/4 msg does not match with IE in Beacon/ProbeResp for link ID %u",
|
"RSN MLO: RSNE in 3/4 msg does not match with IE in Beacon/ProbeResp for link ID %u",
|
||||||
link_id);
|
link_id);
|
||||||
wpa_hexdump(MSG_INFO, "RSNE in Beacon/ProbeResp",
|
wpa_hexdump(MSG_INFO, "RSNE in Beacon/ProbeResp",
|
||||||
sm->mlo.links[link_id].ap_rsne,
|
sm->mlo.links[link_id].ap_rsne,
|
||||||
sm->mlo.links[link_id].ap_rsne_len);
|
sm->mlo.links[link_id].ap_rsne_len);
|
||||||
wpa_hexdump(MSG_INFO, "RSNE in EAPOL-Key msg 3/4",
|
wpa_hexdump(MSG_INFO, "RSNE in EAPOL-Key msg 3/4",
|
||||||
rsne, rsne_len);
|
rsne, rsne_len);
|
||||||
return -1;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((sm->mlo.links[link_id].ap_rsnxe && !rsnxe) ||
|
if ((sm->mlo.links[link_id].ap_rsnxe && !rsnxe) ||
|
||||||
|
@ -2427,11 +2528,89 @@ static int wpa_supplicant_validate_link_kde(struct wpa_sm *sm, u8 link_id,
|
||||||
sm->mlo.links[link_id].ap_rsnxe_len);
|
sm->mlo.links[link_id].ap_rsnxe_len);
|
||||||
wpa_hexdump(MSG_INFO, "RSNXE in EAPOL-Key msg 3/4",
|
wpa_hexdump(MSG_INFO, "RSNXE in EAPOL-Key msg 3/4",
|
||||||
rsnxe, rsnxe_len);
|
rsnxe, rsnxe_len);
|
||||||
wpa_sm_deauthenticate(sm, WLAN_REASON_IE_IN_4WAY_DIFFERS);
|
goto fail;
|
||||||
return -1;
|
}
|
||||||
|
|
||||||
|
if (!wpa_sm_rsn_overriding_supported(sm))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (rsn_override_link_kde) {
|
||||||
|
rsnoe = get_vendor_ie(rsn_override_link_kde + 1,
|
||||||
|
rsn_override_link_kde_len - 1,
|
||||||
|
RSNE_OVERRIDE_IE_VENDOR_TYPE);
|
||||||
|
if (rsnoe)
|
||||||
|
rsnoe_len = 2 + rsnoe[1];
|
||||||
|
|
||||||
|
rsno2e = get_vendor_ie(rsn_override_link_kde + 1,
|
||||||
|
rsn_override_link_kde_len - 1,
|
||||||
|
RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
|
||||||
|
if (rsno2e)
|
||||||
|
rsno2e_len = 2 + rsno2e[1];
|
||||||
|
|
||||||
|
rsnxoe = get_vendor_ie(rsn_override_link_kde + 1,
|
||||||
|
rsn_override_link_kde_len - 1,
|
||||||
|
RSNXE_OVERRIDE_IE_VENDOR_TYPE);
|
||||||
|
if (rsnxoe)
|
||||||
|
rsnxoe_len = 2 + rsnxoe[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sm->mlo.links[link_id].ap_rsnoe && !rsnoe) ||
|
||||||
|
(!sm->mlo.links[link_id].ap_rsnoe && rsnoe) ||
|
||||||
|
(sm->mlo.links[link_id].ap_rsnoe && rsnoe &&
|
||||||
|
wpa_compare_rsn_ie(wpa_key_mgmt_ft(sm->key_mgmt),
|
||||||
|
sm->mlo.links[link_id].ap_rsnoe,
|
||||||
|
sm->mlo.links[link_id].ap_rsnoe_len,
|
||||||
|
rsnoe, rsnoe_len))) {
|
||||||
|
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
|
||||||
|
"RSN MLO: RSNOE in 3/4 msg does not match with IE in Beacon/ProbeResp for link ID %u",
|
||||||
|
link_id);
|
||||||
|
wpa_hexdump(MSG_INFO, "RSNOE in Beacon/ProbeResp",
|
||||||
|
sm->mlo.links[link_id].ap_rsnoe,
|
||||||
|
sm->mlo.links[link_id].ap_rsnoe_len);
|
||||||
|
wpa_hexdump(MSG_INFO, "RSNOE in EAPOL-Key msg 3/4",
|
||||||
|
rsnoe, rsnoe_len);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sm->mlo.links[link_id].ap_rsno2e && !rsno2e) ||
|
||||||
|
(!sm->mlo.links[link_id].ap_rsno2e && rsno2e) ||
|
||||||
|
(sm->mlo.links[link_id].ap_rsno2e && rsno2e &&
|
||||||
|
wpa_compare_rsn_ie(wpa_key_mgmt_ft(sm->key_mgmt),
|
||||||
|
sm->mlo.links[link_id].ap_rsno2e,
|
||||||
|
sm->mlo.links[link_id].ap_rsno2e_len,
|
||||||
|
rsno2e, rsno2e_len))) {
|
||||||
|
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
|
||||||
|
"RSN MLO: RSNO2E in 3/4 msg does not match with IE in Beacon/ProbeResp for link ID %u",
|
||||||
|
link_id);
|
||||||
|
wpa_hexdump(MSG_INFO, "RSNO2E in Beacon/ProbeResp",
|
||||||
|
sm->mlo.links[link_id].ap_rsno2e,
|
||||||
|
sm->mlo.links[link_id].ap_rsno2e_len);
|
||||||
|
wpa_hexdump(MSG_INFO, "RSNOE in EAPOL-Key msg 3/4",
|
||||||
|
rsno2e, rsno2e_len);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sm->mlo.links[link_id].ap_rsnxoe && !rsnxoe) ||
|
||||||
|
(!sm->mlo.links[link_id].ap_rsnxoe && rsnxoe) ||
|
||||||
|
(sm->mlo.links[link_id].ap_rsnxoe && rsnxoe &&
|
||||||
|
(sm->mlo.links[link_id].ap_rsnxoe_len != rsnxoe_len ||
|
||||||
|
os_memcmp(sm->mlo.links[link_id].ap_rsnxoe, rsnxoe,
|
||||||
|
sm->mlo.links[link_id].ap_rsnxoe_len) != 0))) {
|
||||||
|
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
|
||||||
|
"RSN MLO: RSNXOE mismatch between Beacon/ProbeResp and EAPOL-Key msg 3/4 for link ID %u",
|
||||||
|
link_id);
|
||||||
|
wpa_hexdump(MSG_INFO, "RSNXOE in Beacon/ProbeResp",
|
||||||
|
sm->mlo.links[link_id].ap_rsnxoe,
|
||||||
|
sm->mlo.links[link_id].ap_rsnxoe_len);
|
||||||
|
wpa_hexdump(MSG_INFO, "RSNXOE in EAPOL-Key msg 3/4",
|
||||||
|
rsnxoe, rsnxoe_len);
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
fail:
|
||||||
|
wpa_sm_deauthenticate(sm, WLAN_REASON_IE_IN_4WAY_DIFFERS);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2599,8 +2778,10 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,
|
||||||
if (!(sm->mlo.req_links & BIT(i)))
|
if (!(sm->mlo.req_links & BIT(i)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (wpa_supplicant_validate_link_kde(sm, i, ie.mlo_link[i],
|
if (wpa_supplicant_validate_link_kde(
|
||||||
ie.mlo_link_len[i]) < 0)
|
sm, i, ie.mlo_link[i], ie.mlo_link_len[i],
|
||||||
|
ie.rsn_override_link[i],
|
||||||
|
ie.rsn_override_link_len[i]) < 0)
|
||||||
goto failed;
|
goto failed;
|
||||||
|
|
||||||
if (!(sm->mlo.valid_links & BIT(i)))
|
if (!(sm->mlo.valid_links & BIT(i)))
|
||||||
|
@ -4173,9 +4354,15 @@ void wpa_sm_deinit(struct wpa_sm *sm)
|
||||||
os_free(sm->ap_wpa_ie);
|
os_free(sm->ap_wpa_ie);
|
||||||
os_free(sm->ap_rsn_ie);
|
os_free(sm->ap_rsn_ie);
|
||||||
os_free(sm->ap_rsnxe);
|
os_free(sm->ap_rsnxe);
|
||||||
|
os_free(sm->ap_rsne_override);
|
||||||
|
os_free(sm->ap_rsne_override_2);
|
||||||
|
os_free(sm->ap_rsnxe_override);
|
||||||
for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
|
for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
|
||||||
os_free(sm->mlo.links[i].ap_rsne);
|
os_free(sm->mlo.links[i].ap_rsne);
|
||||||
os_free(sm->mlo.links[i].ap_rsnxe);
|
os_free(sm->mlo.links[i].ap_rsnxe);
|
||||||
|
os_free(sm->mlo.links[i].ap_rsnoe);
|
||||||
|
os_free(sm->mlo.links[i].ap_rsno2e);
|
||||||
|
os_free(sm->mlo.links[i].ap_rsnxoe);
|
||||||
}
|
}
|
||||||
wpa_sm_drop_sa(sm);
|
wpa_sm_drop_sa(sm);
|
||||||
os_free(sm->ctx);
|
os_free(sm->ctx);
|
||||||
|
@ -4578,6 +4765,69 @@ int wpa_sm_set_mlo_params(struct wpa_sm *sm, const struct wpa_sm_mlo *mlo)
|
||||||
}
|
}
|
||||||
sm->mlo.links[i].ap_rsnxe_len = len;
|
sm->mlo.links[i].ap_rsnxe_len = len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ie = mlo->links[i].ap_rsnoe;
|
||||||
|
len = mlo->links[i].ap_rsnoe_len;
|
||||||
|
os_free(sm->mlo.links[i].ap_rsnoe);
|
||||||
|
if (!ie || len == 0) {
|
||||||
|
if (sm->mlo.links[i].ap_rsnoe)
|
||||||
|
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
|
||||||
|
"RSN: Clearing MLO link[%u] AP RSNOE",
|
||||||
|
i);
|
||||||
|
sm->mlo.links[i].ap_rsnoe = NULL;
|
||||||
|
sm->mlo.links[i].ap_rsnoe_len = 0;
|
||||||
|
} else {
|
||||||
|
wpa_hexdump_link(MSG_DEBUG, i, "RSN: Set AP RSNOE",
|
||||||
|
ie, len);
|
||||||
|
sm->mlo.links[i].ap_rsnoe = os_memdup(ie, len);
|
||||||
|
if (!sm->mlo.links[i].ap_rsnoe) {
|
||||||
|
sm->mlo.links[i].ap_rsnoe_len = 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
sm->mlo.links[i].ap_rsnoe_len = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
ie = mlo->links[i].ap_rsno2e;
|
||||||
|
len = mlo->links[i].ap_rsno2e_len;
|
||||||
|
os_free(sm->mlo.links[i].ap_rsno2e);
|
||||||
|
if (!ie || len == 0) {
|
||||||
|
if (sm->mlo.links[i].ap_rsno2e)
|
||||||
|
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
|
||||||
|
"RSN: Clearing MLO link[%u] AP RSNO2E",
|
||||||
|
i);
|
||||||
|
sm->mlo.links[i].ap_rsno2e = NULL;
|
||||||
|
sm->mlo.links[i].ap_rsno2e_len = 0;
|
||||||
|
} else {
|
||||||
|
wpa_hexdump_link(MSG_DEBUG, i, "RSN: Set AP RSNO2E",
|
||||||
|
ie, len);
|
||||||
|
sm->mlo.links[i].ap_rsno2e = os_memdup(ie, len);
|
||||||
|
if (!sm->mlo.links[i].ap_rsno2e) {
|
||||||
|
sm->mlo.links[i].ap_rsno2e_len = 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
sm->mlo.links[i].ap_rsno2e_len = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
ie = mlo->links[i].ap_rsnxoe;
|
||||||
|
len = mlo->links[i].ap_rsnxoe_len;
|
||||||
|
os_free(sm->mlo.links[i].ap_rsnxoe);
|
||||||
|
if (!ie || len == 0) {
|
||||||
|
if (sm->mlo.links[i].ap_rsnxoe)
|
||||||
|
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
|
||||||
|
"RSN: Clearing MLO link[%u] AP RSNXOE",
|
||||||
|
i);
|
||||||
|
sm->mlo.links[i].ap_rsnxoe = NULL;
|
||||||
|
sm->mlo.links[i].ap_rsnxoe_len = 0;
|
||||||
|
} else {
|
||||||
|
wpa_hexdump_link(MSG_DEBUG, i, "RSN: Set AP RSNXOE",
|
||||||
|
ie, len);
|
||||||
|
sm->mlo.links[i].ap_rsnxoe = os_memdup(ie, len);
|
||||||
|
if (!sm->mlo.links[i].ap_rsnxoe) {
|
||||||
|
sm->mlo.links[i].ap_rsnxoe_len = 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
sm->mlo.links[i].ap_rsnxoe_len = len;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -4737,6 +4987,12 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
|
||||||
case WPA_PARAM_SSID_PROTECTION:
|
case WPA_PARAM_SSID_PROTECTION:
|
||||||
sm->ssid_protection = value;
|
sm->ssid_protection = value;
|
||||||
break;
|
break;
|
||||||
|
case WPA_PARAM_RSN_OVERRIDE:
|
||||||
|
sm->rsn_override = value;
|
||||||
|
break;
|
||||||
|
case WPA_PARAM_RSN_OVERRIDE_SUPPORT:
|
||||||
|
sm->rsn_override_support = value;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -4745,6 +5001,23 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const u8 * wpa_sm_get_ap_rsne(struct wpa_sm *sm, size_t *len)
|
||||||
|
{
|
||||||
|
if (sm->rsn_override == RSN_OVERRIDE_RSNE_OVERRIDE) {
|
||||||
|
*len = sm->ap_rsne_override_len;
|
||||||
|
return sm->ap_rsne_override;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sm->rsn_override == RSN_OVERRIDE_RSNE_OVERRIDE_2) {
|
||||||
|
*len = sm->ap_rsne_override_2_len;
|
||||||
|
return sm->ap_rsne_override_2;
|
||||||
|
}
|
||||||
|
|
||||||
|
*len = sm->ap_rsn_ie_len;
|
||||||
|
return sm->ap_rsn_ie;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wpa_sm_get_status - Get WPA state machine
|
* wpa_sm_get_status - Get WPA state machine
|
||||||
* @sm: Pointer to WPA state machine data from wpa_sm_init()
|
* @sm: Pointer to WPA state machine data from wpa_sm_init()
|
||||||
|
@ -4762,6 +5035,10 @@ int wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen,
|
||||||
{
|
{
|
||||||
char *pos = buf, *end = buf + buflen;
|
char *pos = buf, *end = buf + buflen;
|
||||||
int ret;
|
int ret;
|
||||||
|
const u8 *rsne;
|
||||||
|
size_t rsne_len;
|
||||||
|
|
||||||
|
rsne = wpa_sm_get_ap_rsne(sm, &rsne_len);
|
||||||
|
|
||||||
ret = os_snprintf(pos, end - pos,
|
ret = os_snprintf(pos, end - pos,
|
||||||
"pairwise_cipher=%s\n"
|
"pairwise_cipher=%s\n"
|
||||||
|
@ -4783,10 +5060,10 @@ int wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen,
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_DPP2 */
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
if (sm->mfp != NO_MGMT_FRAME_PROTECTION && sm->ap_rsn_ie) {
|
if (sm->mfp != NO_MGMT_FRAME_PROTECTION && rsne) {
|
||||||
struct wpa_ie_data rsn;
|
struct wpa_ie_data rsn;
|
||||||
if (wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &rsn)
|
|
||||||
>= 0 &&
|
if (wpa_parse_wpa_ie_rsn(rsne, rsne_len, &rsn) >= 0 &&
|
||||||
rsn.capabilities & (WPA_CAPABILITY_MFPR |
|
rsn.capabilities & (WPA_CAPABILITY_MFPR |
|
||||||
WPA_CAPABILITY_MFPC)) {
|
WPA_CAPABILITY_MFPC)) {
|
||||||
ret = os_snprintf(pos, end - pos, "pmf=%d\n"
|
ret = os_snprintf(pos, end - pos, "pmf=%d\n"
|
||||||
|
@ -4808,11 +5085,15 @@ int wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen,
|
||||||
int wpa_sm_pmf_enabled(struct wpa_sm *sm)
|
int wpa_sm_pmf_enabled(struct wpa_sm *sm)
|
||||||
{
|
{
|
||||||
struct wpa_ie_data rsn;
|
struct wpa_ie_data rsn;
|
||||||
|
const u8 *rsne;
|
||||||
|
size_t rsne_len;
|
||||||
|
|
||||||
if (sm->mfp == NO_MGMT_FRAME_PROTECTION || !sm->ap_rsn_ie)
|
rsne = wpa_sm_get_ap_rsne(sm, &rsne_len);
|
||||||
|
|
||||||
|
if (sm->mfp == NO_MGMT_FRAME_PROTECTION || !rsne)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &rsn) >= 0 &&
|
if (wpa_parse_wpa_ie_rsn(rsne, rsne_len, &rsn) >= 0 &&
|
||||||
rsn.capabilities & (WPA_CAPABILITY_MFPR | WPA_CAPABILITY_MFPC))
|
rsn.capabilities & (WPA_CAPABILITY_MFPR | WPA_CAPABILITY_MFPC))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
@ -4820,6 +5101,17 @@ int wpa_sm_pmf_enabled(struct wpa_sm *sm)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool wpa_sm_rsn_overriding_supported(struct wpa_sm *sm)
|
||||||
|
{
|
||||||
|
const u8 *rsne;
|
||||||
|
size_t rsne_len;
|
||||||
|
|
||||||
|
rsne = wpa_sm_get_ap_rsne(sm, &rsne_len);
|
||||||
|
|
||||||
|
return sm->rsn_override_support && rsne;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int wpa_sm_ext_key_id(struct wpa_sm *sm)
|
int wpa_sm_ext_key_id(struct wpa_sm *sm)
|
||||||
{
|
{
|
||||||
return sm ? sm->ext_key_id : 0;
|
return sm ? sm->ext_key_id : 0;
|
||||||
|
@ -4835,12 +5127,14 @@ int wpa_sm_ext_key_id_active(struct wpa_sm *sm)
|
||||||
int wpa_sm_ocv_enabled(struct wpa_sm *sm)
|
int wpa_sm_ocv_enabled(struct wpa_sm *sm)
|
||||||
{
|
{
|
||||||
struct wpa_ie_data rsn;
|
struct wpa_ie_data rsn;
|
||||||
|
const u8 *rsne;
|
||||||
|
size_t rsne_len;
|
||||||
|
|
||||||
if (!sm->ocv || !sm->ap_rsn_ie)
|
rsne = wpa_sm_get_ap_rsne(sm, &rsne_len);
|
||||||
|
if (!sm->ocv || !rsne)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len,
|
return wpa_parse_wpa_ie_rsn(rsne, rsne_len, &rsn) >= 0 &&
|
||||||
&rsn) >= 0 &&
|
|
||||||
(rsn.capabilities & WPA_CAPABILITY_OCVC);
|
(rsn.capabilities & WPA_CAPABILITY_OCVC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5121,6 +5415,81 @@ int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wpa_sm_set_ap_rsne_override(struct wpa_sm *sm, const u8 *ie, size_t len)
|
||||||
|
{
|
||||||
|
if (!sm)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
os_free(sm->ap_rsne_override);
|
||||||
|
if (!ie || len == 0) {
|
||||||
|
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
|
||||||
|
"RSN: Clearing AP RSNE Override element");
|
||||||
|
sm->ap_rsne_override = NULL;
|
||||||
|
sm->ap_rsne_override_len = 0;
|
||||||
|
} else {
|
||||||
|
wpa_hexdump(MSG_DEBUG, "RSN: Set AP RSNE Override element",
|
||||||
|
ie, len);
|
||||||
|
sm->ap_rsne_override = os_memdup(ie, len);
|
||||||
|
if (!sm->ap_rsne_override)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
sm->ap_rsne_override_len = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wpa_sm_set_ap_rsne_override_2(struct wpa_sm *sm, const u8 *ie, size_t len)
|
||||||
|
{
|
||||||
|
if (!sm)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
os_free(sm->ap_rsne_override_2);
|
||||||
|
if (!ie || len == 0) {
|
||||||
|
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
|
||||||
|
"RSN: Clearing AP RSNE Override 2 element");
|
||||||
|
sm->ap_rsne_override_2 = NULL;
|
||||||
|
sm->ap_rsne_override_2_len = 0;
|
||||||
|
} else {
|
||||||
|
wpa_hexdump(MSG_DEBUG, "RSN: Set AP RSNE Override 2 element",
|
||||||
|
ie, len);
|
||||||
|
sm->ap_rsne_override_2 = os_memdup(ie, len);
|
||||||
|
if (!sm->ap_rsne_override_2)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
sm->ap_rsne_override_2_len = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wpa_sm_set_ap_rsnxe_override(struct wpa_sm *sm, const u8 *ie, size_t len)
|
||||||
|
{
|
||||||
|
if (!sm)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
os_free(sm->ap_rsnxe_override);
|
||||||
|
if (!ie || len == 0) {
|
||||||
|
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
|
||||||
|
"RSN: Clearing AP RSNXE Override element");
|
||||||
|
sm->ap_rsnxe_override = NULL;
|
||||||
|
sm->ap_rsnxe_override_len = 0;
|
||||||
|
} else {
|
||||||
|
wpa_hexdump(MSG_DEBUG, "RSN: Set AP RSNXE Override element",
|
||||||
|
ie, len);
|
||||||
|
sm->ap_rsnxe_override = os_memdup(ie, len);
|
||||||
|
if (!sm->ap_rsnxe_override)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
sm->ap_rsnxe_override_len = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wpa_sm_parse_own_wpa_ie - Parse own WPA/RSN IE
|
* wpa_sm_parse_own_wpa_ie - Parse own WPA/RSN IE
|
||||||
* @sm: Pointer to WPA state machine data from wpa_sm_init()
|
* @sm: Pointer to WPA state machine data from wpa_sm_init()
|
||||||
|
|
|
@ -137,6 +137,15 @@ enum wpa_sm_conf_params {
|
||||||
WPA_PARAM_ENCRYPT_EAPOL_M4,
|
WPA_PARAM_ENCRYPT_EAPOL_M4,
|
||||||
WPA_PARAM_FT_PREPEND_PMKID,
|
WPA_PARAM_FT_PREPEND_PMKID,
|
||||||
WPA_PARAM_SSID_PROTECTION,
|
WPA_PARAM_SSID_PROTECTION,
|
||||||
|
WPA_PARAM_RSN_OVERRIDE,
|
||||||
|
WPA_PARAM_RSN_OVERRIDE_SUPPORT,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum wpa_rsn_override {
|
||||||
|
RSN_OVERRIDE_NOT_USED,
|
||||||
|
RSN_OVERRIDE_RSNE,
|
||||||
|
RSN_OVERRIDE_RSNE_OVERRIDE,
|
||||||
|
RSN_OVERRIDE_RSNE_OVERRIDE_2,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rsn_supp_config {
|
struct rsn_supp_config {
|
||||||
|
@ -160,8 +169,9 @@ struct rsn_supp_config {
|
||||||
struct wpa_sm_link {
|
struct wpa_sm_link {
|
||||||
u8 addr[ETH_ALEN];
|
u8 addr[ETH_ALEN];
|
||||||
u8 bssid[ETH_ALEN];
|
u8 bssid[ETH_ALEN];
|
||||||
u8 *ap_rsne, *ap_rsnxe;
|
u8 *ap_rsne, *ap_rsnxe, *ap_rsnoe, *ap_rsno2e, *ap_rsnxoe;
|
||||||
size_t ap_rsne_len, ap_rsnxe_len;
|
size_t ap_rsne_len, ap_rsnxe_len, ap_rsnoe_len, ap_rsno2e_len,
|
||||||
|
ap_rsnxoe_len;;
|
||||||
struct wpa_gtk gtk;
|
struct wpa_gtk gtk;
|
||||||
struct wpa_gtk gtk_wnm_sleep;
|
struct wpa_gtk gtk_wnm_sleep;
|
||||||
struct wpa_igtk igtk;
|
struct wpa_igtk igtk;
|
||||||
|
@ -204,6 +214,9 @@ int wpa_sm_set_assoc_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len);
|
||||||
int wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len);
|
int wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len);
|
||||||
int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len);
|
int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len);
|
||||||
int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len);
|
int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len);
|
||||||
|
int wpa_sm_set_ap_rsne_override(struct wpa_sm *sm, const u8 *ie, size_t len);
|
||||||
|
int wpa_sm_set_ap_rsne_override_2(struct wpa_sm *sm, const u8 *ie, size_t len);
|
||||||
|
int wpa_sm_set_ap_rsnxe_override(struct wpa_sm *sm, const u8 *ie, size_t len);
|
||||||
int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen);
|
int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen);
|
||||||
|
|
||||||
int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
|
int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
|
||||||
|
@ -348,6 +361,24 @@ static inline int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int wpa_sm_set_ap_rsne_override(struct wpa_sm *sm, const u8 *ie,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wpa_sm_set_ap_rsne_override_2(struct wpa_sm *sm, const u8 *ie,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wpa_sm_set_ap_rsnxe_override(struct wpa_sm *sm, const u8 *ie,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen)
|
static inline int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -120,6 +120,9 @@ struct wpa_sm {
|
||||||
size_t assoc_rsnxe_len;
|
size_t assoc_rsnxe_len;
|
||||||
u8 *ap_wpa_ie, *ap_rsn_ie, *ap_rsnxe;
|
u8 *ap_wpa_ie, *ap_rsn_ie, *ap_rsnxe;
|
||||||
size_t ap_wpa_ie_len, ap_rsn_ie_len, ap_rsnxe_len;
|
size_t ap_wpa_ie_len, ap_rsn_ie_len, ap_rsnxe_len;
|
||||||
|
u8 *ap_rsne_override, *ap_rsne_override_2, *ap_rsnxe_override;
|
||||||
|
size_t ap_rsne_override_len, ap_rsne_override_2_len,
|
||||||
|
ap_rsnxe_override_len;
|
||||||
|
|
||||||
#ifdef CONFIG_TDLS
|
#ifdef CONFIG_TDLS
|
||||||
struct wpa_tdls_peer *tdls;
|
struct wpa_tdls_peer *tdls;
|
||||||
|
@ -229,6 +232,9 @@ struct wpa_sm {
|
||||||
bool wmm_enabled;
|
bool wmm_enabled;
|
||||||
bool driver_bss_selection;
|
bool driver_bss_selection;
|
||||||
bool ft_prepend_pmkid;
|
bool ft_prepend_pmkid;
|
||||||
|
|
||||||
|
bool rsn_override_support;
|
||||||
|
enum wpa_rsn_override rsn_override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -542,5 +548,6 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
|
||||||
|
|
||||||
void wpa_tdls_assoc(struct wpa_sm *sm);
|
void wpa_tdls_assoc(struct wpa_sm *sm);
|
||||||
void wpa_tdls_disassoc(struct wpa_sm *sm);
|
void wpa_tdls_disassoc(struct wpa_sm *sm);
|
||||||
|
bool wpa_sm_rsn_overriding_supported(struct wpa_sm *sm);
|
||||||
|
|
||||||
#endif /* WPA_I_H */
|
#endif /* WPA_I_H */
|
||||||
|
|
|
@ -33,8 +33,15 @@ int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len,
|
||||||
if (wpa_ie_len >= 6 && wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC &&
|
if (wpa_ie_len >= 6 && wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC &&
|
||||||
wpa_ie[1] >= 4 && WPA_GET_BE32(&wpa_ie[2]) == OSEN_IE_VENDOR_TYPE)
|
wpa_ie[1] >= 4 && WPA_GET_BE32(&wpa_ie[2]) == OSEN_IE_VENDOR_TYPE)
|
||||||
return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
|
return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
|
||||||
else
|
if (wpa_ie_len >= 6 && wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC &&
|
||||||
return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data);
|
wpa_ie[1] >= 4 &&
|
||||||
|
WPA_GET_BE32(&wpa_ie[2]) == RSNE_OVERRIDE_IE_VENDOR_TYPE)
|
||||||
|
return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
|
||||||
|
if (wpa_ie_len >= 6 && wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC &&
|
||||||
|
wpa_ie[1] >= 4 &&
|
||||||
|
WPA_GET_BE32(&wpa_ie[2]) == RSNE_OVERRIDE_2_IE_VENDOR_TYPE)
|
||||||
|
return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
|
||||||
|
return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -77,9 +77,6 @@ struct eloop_sock_table {
|
||||||
struct eloop_data {
|
struct eloop_data {
|
||||||
int max_sock;
|
int max_sock;
|
||||||
|
|
||||||
eloop_timeout_poll_handler timeout_poll_cb;
|
|
||||||
eloop_poll_handler poll_cb;
|
|
||||||
|
|
||||||
size_t count; /* sum of all table counts */
|
size_t count; /* sum of all table counts */
|
||||||
#ifdef CONFIG_ELOOP_POLL
|
#ifdef CONFIG_ELOOP_POLL
|
||||||
size_t max_pollfd_map; /* number of pollfds_map currently allocated */
|
size_t max_pollfd_map; /* number of pollfds_map currently allocated */
|
||||||
|
@ -1124,12 +1121,6 @@ void eloop_run(void)
|
||||||
os_reltime_sub(&timeout->time, &now, &tv);
|
os_reltime_sub(&timeout->time, &now, &tv);
|
||||||
else
|
else
|
||||||
tv.sec = tv.usec = 0;
|
tv.sec = tv.usec = 0;
|
||||||
}
|
|
||||||
|
|
||||||
if (eloop.timeout_poll_cb && eloop.timeout_poll_cb(&tv, !!timeout))
|
|
||||||
timeout = (void *)1;
|
|
||||||
|
|
||||||
if (timeout) {
|
|
||||||
#if defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL)
|
#if defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL)
|
||||||
timeout_ms = tv.sec * 1000 + tv.usec / 1000;
|
timeout_ms = tv.sec * 1000 + tv.usec / 1000;
|
||||||
#endif /* defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) */
|
#endif /* defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) */
|
||||||
|
@ -1199,8 +1190,7 @@ void eloop_run(void)
|
||||||
eloop.exceptions.changed = 0;
|
eloop.exceptions.changed = 0;
|
||||||
|
|
||||||
eloop_process_pending_signals();
|
eloop_process_pending_signals();
|
||||||
if (eloop.poll_cb)
|
|
||||||
eloop.poll_cb();
|
|
||||||
|
|
||||||
/* check if some registered timeouts have occurred */
|
/* check if some registered timeouts have occurred */
|
||||||
timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
|
timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
|
||||||
|
@ -1262,14 +1252,6 @@ out:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int eloop_register_cb(eloop_poll_handler poll_cb,
|
|
||||||
eloop_timeout_poll_handler timeout_cb)
|
|
||||||
{
|
|
||||||
eloop.poll_cb = poll_cb;
|
|
||||||
eloop.timeout_poll_cb = timeout_cb;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void eloop_terminate(void)
|
void eloop_terminate(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -65,9 +65,6 @@ typedef void (*eloop_timeout_handler)(void *eloop_ctx, void *user_ctx);
|
||||||
*/
|
*/
|
||||||
typedef void (*eloop_signal_handler)(int sig, void *signal_ctx);
|
typedef void (*eloop_signal_handler)(int sig, void *signal_ctx);
|
||||||
|
|
||||||
typedef bool (*eloop_timeout_poll_handler)(struct os_reltime *tv, bool tv_set);
|
|
||||||
typedef void (*eloop_poll_handler)(void);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* eloop_init() - Initialize global event loop data
|
* eloop_init() - Initialize global event loop data
|
||||||
* Returns: 0 on success, -1 on failure
|
* Returns: 0 on success, -1 on failure
|
||||||
|
@ -76,9 +73,6 @@ typedef void (*eloop_poll_handler)(void);
|
||||||
*/
|
*/
|
||||||
int eloop_init(void);
|
int eloop_init(void);
|
||||||
|
|
||||||
int eloop_register_cb(eloop_poll_handler poll_cb,
|
|
||||||
eloop_timeout_poll_handler timeout_cb);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* eloop_register_read_sock - Register handler for read events
|
* eloop_register_read_sock - Register handler for read events
|
||||||
* @sock: File descriptor number for the socket
|
* @sock: File descriptor number for the socket
|
||||||
|
@ -326,8 +320,6 @@ int eloop_register_signal_reconfig(eloop_signal_handler handler,
|
||||||
*/
|
*/
|
||||||
int eloop_sock_requeue(void);
|
int eloop_sock_requeue(void);
|
||||||
|
|
||||||
void eloop_add_uloop(void);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* eloop_run - Start the event loop
|
* eloop_run - Start the event loop
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
#include <libubox/uloop.h>
|
|
||||||
#include "includes.h"
|
|
||||||
#include "common.h"
|
|
||||||
#include "eloop.h"
|
|
||||||
|
|
||||||
static void eloop_uloop_event_cb(int sock, void *eloop_ctx, void *sock_ctx)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void eloop_uloop_fd_cb(struct uloop_fd *fd, unsigned int events)
|
|
||||||
{
|
|
||||||
unsigned int changed = events ^ fd->flags;
|
|
||||||
|
|
||||||
if (changed & ULOOP_READ) {
|
|
||||||
if (events & ULOOP_READ)
|
|
||||||
eloop_register_sock(fd->fd, EVENT_TYPE_READ, eloop_uloop_event_cb, fd, fd);
|
|
||||||
else
|
|
||||||
eloop_unregister_sock(fd->fd, EVENT_TYPE_READ);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changed & ULOOP_WRITE) {
|
|
||||||
if (events & ULOOP_WRITE)
|
|
||||||
eloop_register_sock(fd->fd, EVENT_TYPE_WRITE, eloop_uloop_event_cb, fd, fd);
|
|
||||||
else
|
|
||||||
eloop_unregister_sock(fd->fd, EVENT_TYPE_WRITE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool uloop_timeout_poll_handler(struct os_reltime *tv, bool tv_set)
|
|
||||||
{
|
|
||||||
struct os_reltime tv_uloop;
|
|
||||||
int timeout_ms = uloop_get_next_timeout();
|
|
||||||
|
|
||||||
if (timeout_ms < 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
tv_uloop.sec = timeout_ms / 1000;
|
|
||||||
tv_uloop.usec = (timeout_ms % 1000) * 1000;
|
|
||||||
|
|
||||||
if (!tv_set || os_reltime_before(&tv_uloop, tv)) {
|
|
||||||
*tv = tv_uloop;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void uloop_poll_handler(void)
|
|
||||||
{
|
|
||||||
uloop_run_timeout(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void eloop_add_uloop(void)
|
|
||||||
{
|
|
||||||
static bool init_done = false;
|
|
||||||
|
|
||||||
if (!init_done) {
|
|
||||||
uloop_init();
|
|
||||||
uloop_fd_set_cb = eloop_uloop_fd_cb;
|
|
||||||
init_done = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
eloop_register_cb(uloop_poll_handler, uloop_timeout_poll_handler);
|
|
||||||
}
|
|
|
@ -15,6 +15,7 @@ import wpaspy
|
||||||
import remotehost
|
import remotehost
|
||||||
import utils
|
import utils
|
||||||
import subprocess
|
import subprocess
|
||||||
|
from remotectrl import RemoteCtrl
|
||||||
|
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
hapd_ctrl = '/var/run/hostapd'
|
hapd_ctrl = '/var/run/hostapd'
|
||||||
|
@ -28,12 +29,18 @@ class HostapdGlobal:
|
||||||
try:
|
try:
|
||||||
hostname = apdev['hostname']
|
hostname = apdev['hostname']
|
||||||
port = apdev['port']
|
port = apdev['port']
|
||||||
|
if 'remote_cli' in apdev:
|
||||||
|
remote_cli = apdev['remote_cli']
|
||||||
|
else:
|
||||||
|
remote_cli = False
|
||||||
except:
|
except:
|
||||||
hostname = None
|
hostname = None
|
||||||
port = 8878
|
port = 8878
|
||||||
|
remote_cli = False
|
||||||
self.host = remotehost.Host(hostname)
|
self.host = remotehost.Host(hostname)
|
||||||
self.hostname = hostname
|
self.hostname = hostname
|
||||||
self.port = port
|
self.port = port
|
||||||
|
self.remote_cli = remote_cli
|
||||||
if hostname is None:
|
if hostname is None:
|
||||||
global_ctrl = hapd_global
|
global_ctrl = hapd_global
|
||||||
if global_ctrl_override:
|
if global_ctrl_override:
|
||||||
|
@ -42,9 +49,17 @@ class HostapdGlobal:
|
||||||
self.mon = wpaspy.Ctrl(global_ctrl)
|
self.mon = wpaspy.Ctrl(global_ctrl)
|
||||||
self.dbg = ""
|
self.dbg = ""
|
||||||
else:
|
else:
|
||||||
self.ctrl = wpaspy.Ctrl(hostname, port)
|
if remote_cli:
|
||||||
self.mon = wpaspy.Ctrl(hostname, port)
|
global_ctrl = hapd_global
|
||||||
self.dbg = hostname + "/" + str(port)
|
if global_ctrl_override:
|
||||||
|
global_ctrl = global_ctrl_override
|
||||||
|
self.ctrl = RemoteCtrl(global_ctrl, port, hostname=hostname)
|
||||||
|
self.mon = RemoteCtrl(global_ctrl, port, hostname=hostname)
|
||||||
|
self.dbg = hostname + "/global"
|
||||||
|
else:
|
||||||
|
self.ctrl = wpaspy.Ctrl(hostname, port)
|
||||||
|
self.mon = wpaspy.Ctrl(hostname, port)
|
||||||
|
self.dbg = hostname + "/" + str(port)
|
||||||
self.mon.attach()
|
self.mon.attach()
|
||||||
|
|
||||||
def cmd_execute(self, cmd_array, shell=False):
|
def cmd_execute(self, cmd_array, shell=False):
|
||||||
|
@ -119,6 +134,9 @@ class HostapdGlobal:
|
||||||
if self.hostname is None:
|
if self.hostname is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
if self.remote_cli:
|
||||||
|
return None
|
||||||
|
|
||||||
res = self.request("INTERFACES ctrl")
|
res = self.request("INTERFACES ctrl")
|
||||||
lines = res.splitlines()
|
lines = res.splitlines()
|
||||||
found = False
|
found = False
|
||||||
|
@ -147,17 +165,26 @@ class HostapdGlobal:
|
||||||
|
|
||||||
class Hostapd:
|
class Hostapd:
|
||||||
def __init__(self, ifname, bssidx=0, hostname=None, ctrl=hapd_ctrl,
|
def __init__(self, ifname, bssidx=0, hostname=None, ctrl=hapd_ctrl,
|
||||||
port=8877):
|
port=8877, remote_cli=False, link=None):
|
||||||
self.hostname = hostname
|
self.hostname = hostname
|
||||||
self.host = remotehost.Host(hostname, ifname)
|
self.host = remotehost.Host(hostname, ifname)
|
||||||
self.ifname = ifname
|
self.ifname = ifname
|
||||||
|
self.remote_cli = remote_cli
|
||||||
if hostname is None:
|
if hostname is None:
|
||||||
|
if link is not None:
|
||||||
|
ifname = ifname + "_link" + str(link)
|
||||||
self.ctrl = wpaspy.Ctrl(os.path.join(ctrl, ifname))
|
self.ctrl = wpaspy.Ctrl(os.path.join(ctrl, ifname))
|
||||||
self.mon = wpaspy.Ctrl(os.path.join(ctrl, ifname))
|
self.mon = wpaspy.Ctrl(os.path.join(ctrl, ifname))
|
||||||
self.dbg = ifname
|
self.dbg = ifname
|
||||||
else:
|
else:
|
||||||
self.ctrl = wpaspy.Ctrl(hostname, port)
|
if remote_cli:
|
||||||
self.mon = wpaspy.Ctrl(hostname, port)
|
self.ctrl = RemoteCtrl(ctrl, port, hostname=hostname,
|
||||||
|
ifname=ifname)
|
||||||
|
self.mon = RemoteCtrl(ctrl, port, hostname=hostname,
|
||||||
|
ifname=ifname)
|
||||||
|
else:
|
||||||
|
self.ctrl = wpaspy.Ctrl(hostname, port)
|
||||||
|
self.mon = wpaspy.Ctrl(hostname, port)
|
||||||
self.dbg = hostname + "/" + ifname
|
self.dbg = hostname + "/" + ifname
|
||||||
self.mon.attach()
|
self.mon.attach()
|
||||||
self.bssid = None
|
self.bssid = None
|
||||||
|
@ -638,22 +665,31 @@ def add_ap(apdev, params, wait_enabled=True, no_enable=False, timeout=30,
|
||||||
try:
|
try:
|
||||||
hostname = apdev['hostname']
|
hostname = apdev['hostname']
|
||||||
port = apdev['port']
|
port = apdev['port']
|
||||||
logger.info("Starting AP " + hostname + "/" + port + " " + ifname)
|
if 'remote_cli' in apdev:
|
||||||
|
remote_cli = apdev['remote_cli']
|
||||||
|
else:
|
||||||
|
remote_cli = False
|
||||||
|
if 'global_ctrl_override' in apdev:
|
||||||
|
global_ctrl_override = apdev['global_ctrl_override']
|
||||||
|
logger.info("Starting AP " + hostname + "/" + port + " " + ifname + " remote_cli " + str(remote_cli))
|
||||||
except:
|
except:
|
||||||
logger.info("Starting AP " + ifname)
|
logger.info("Starting AP " + ifname)
|
||||||
hostname = None
|
hostname = None
|
||||||
port = 8878
|
port = 8878
|
||||||
|
remote_cli = False
|
||||||
else:
|
else:
|
||||||
ifname = apdev
|
ifname = apdev
|
||||||
logger.info("Starting AP " + ifname + " (old add_ap argument type)")
|
logger.info("Starting AP " + ifname + " (old add_ap argument type)")
|
||||||
hostname = None
|
hostname = None
|
||||||
port = 8878
|
port = 8878
|
||||||
|
remote_cli = False
|
||||||
hapd_global = HostapdGlobal(apdev,
|
hapd_global = HostapdGlobal(apdev,
|
||||||
global_ctrl_override=global_ctrl_override)
|
global_ctrl_override=global_ctrl_override)
|
||||||
hapd_global.remove(ifname)
|
hapd_global.remove(ifname)
|
||||||
hapd_global.add(ifname, driver=driver)
|
hapd_global.add(ifname, driver=driver)
|
||||||
port = hapd_global.get_ctrl_iface_port(ifname)
|
port = hapd_global.get_ctrl_iface_port(ifname)
|
||||||
hapd = Hostapd(ifname, hostname=hostname, port=port)
|
hapd = Hostapd(ifname, hostname=hostname, port=port,
|
||||||
|
remote_cli=remote_cli)
|
||||||
if not hapd.ping():
|
if not hapd.ping():
|
||||||
raise Exception("Could not ping hostapd")
|
raise Exception("Could not ping hostapd")
|
||||||
hapd.set_defaults(set_channel=set_channel)
|
hapd.set_defaults(set_channel=set_channel)
|
||||||
|
@ -688,17 +724,22 @@ def add_bss(apdev, ifname, confname, ignore_error=False):
|
||||||
try:
|
try:
|
||||||
hostname = apdev['hostname']
|
hostname = apdev['hostname']
|
||||||
port = apdev['port']
|
port = apdev['port']
|
||||||
logger.info("Starting BSS " + hostname + "/" + port + " phy=" + phy + " ifname=" + ifname)
|
if 'remote_cli' in apdev:
|
||||||
|
remote_cli = apdev['remote_cli']
|
||||||
|
else:
|
||||||
|
remote_cli = False
|
||||||
|
logger.info("Starting BSS " + hostname + "/" + port + " phy=" + phy + " ifname=" + ifname + " remote_cli=" + str(remote_cli))
|
||||||
except:
|
except:
|
||||||
logger.info("Starting BSS phy=" + phy + " ifname=" + ifname)
|
logger.info("Starting BSS phy=" + phy + " ifname=" + ifname)
|
||||||
hostname = None
|
hostname = None
|
||||||
port = 8878
|
port = 8878
|
||||||
|
remote_cli = False
|
||||||
hapd_global = HostapdGlobal(apdev)
|
hapd_global = HostapdGlobal(apdev)
|
||||||
confname = cfg_file(apdev, confname, ifname)
|
confname = cfg_file(apdev, confname, ifname)
|
||||||
hapd_global.send_file(confname, confname)
|
hapd_global.send_file(confname, confname)
|
||||||
hapd_global.add_bss(phy, confname, ignore_error)
|
hapd_global.add_bss(phy, confname, ignore_error)
|
||||||
port = hapd_global.get_ctrl_iface_port(ifname)
|
port = hapd_global.get_ctrl_iface_port(ifname)
|
||||||
hapd = Hostapd(ifname, hostname=hostname, port=port)
|
hapd = Hostapd(ifname, hostname=hostname, port=port, remote_cli=remote_cli)
|
||||||
if not hapd.ping():
|
if not hapd.ping():
|
||||||
raise Exception("Could not ping hostapd")
|
raise Exception("Could not ping hostapd")
|
||||||
return hapd
|
return hapd
|
||||||
|
@ -708,22 +749,27 @@ def add_iface(apdev, confname):
|
||||||
try:
|
try:
|
||||||
hostname = apdev['hostname']
|
hostname = apdev['hostname']
|
||||||
port = apdev['port']
|
port = apdev['port']
|
||||||
logger.info("Starting interface " + hostname + "/" + port + " " + ifname)
|
if 'remote_cli' in apdev:
|
||||||
|
remote_cli = apdev['remote_cli']
|
||||||
|
else:
|
||||||
|
remote_cli = False
|
||||||
|
logger.info("Starting interface " + hostname + "/" + port + " " + ifname + "remote_cli=" + str(remote_cli))
|
||||||
except:
|
except:
|
||||||
logger.info("Starting interface " + ifname)
|
logger.info("Starting interface " + ifname)
|
||||||
hostname = None
|
hostname = None
|
||||||
port = 8878
|
port = 8878
|
||||||
|
remote_cli = False
|
||||||
hapd_global = HostapdGlobal(apdev)
|
hapd_global = HostapdGlobal(apdev)
|
||||||
confname = cfg_file(apdev, confname, ifname)
|
confname = cfg_file(apdev, confname, ifname)
|
||||||
hapd_global.send_file(confname, confname)
|
hapd_global.send_file(confname, confname)
|
||||||
hapd_global.add_iface(ifname, confname)
|
hapd_global.add_iface(ifname, confname)
|
||||||
port = hapd_global.get_ctrl_iface_port(ifname)
|
port = hapd_global.get_ctrl_iface_port(ifname)
|
||||||
hapd = Hostapd(ifname, hostname=hostname, port=port)
|
hapd = Hostapd(ifname, hostname=hostname, port=port, remote_cli=remote_cli)
|
||||||
if not hapd.ping():
|
if not hapd.ping():
|
||||||
raise Exception("Could not ping hostapd")
|
raise Exception("Could not ping hostapd")
|
||||||
return hapd
|
return hapd
|
||||||
|
|
||||||
def add_mld_link(apdev, params):
|
def add_mld_link(apdev, link_id, params):
|
||||||
if isinstance(apdev, dict):
|
if isinstance(apdev, dict):
|
||||||
ifname = apdev['ifname']
|
ifname = apdev['ifname']
|
||||||
try:
|
try:
|
||||||
|
@ -749,7 +795,8 @@ def add_mld_link(apdev, params):
|
||||||
if str(e) == "Could not add hostapd link":
|
if str(e) == "Could not add hostapd link":
|
||||||
raise utils.HwsimSkip("No MLO support in hostapd")
|
raise utils.HwsimSkip("No MLO support in hostapd")
|
||||||
port = hapd_global.get_ctrl_iface_port(ifname)
|
port = hapd_global.get_ctrl_iface_port(ifname)
|
||||||
hapd = Hostapd(ifname, hostname=hostname, ctrl=ctrl_iface, port=port)
|
hapd = Hostapd(ifname, hostname=hostname, ctrl=ctrl_iface, port=port,
|
||||||
|
link=link_id)
|
||||||
if not hapd.ping():
|
if not hapd.ping():
|
||||||
raise Exception("Could not ping hostapd")
|
raise Exception("Could not ping hostapd")
|
||||||
return hapd
|
return hapd
|
||||||
|
@ -1023,9 +1070,6 @@ def cfg_mld_link_file(ifname, params):
|
||||||
fd, fname = tempfile.mkstemp(dir='/tmp', prefix=conf + '-')
|
fd, fname = tempfile.mkstemp(dir='/tmp', prefix=conf + '-')
|
||||||
f = os.fdopen(fd, 'w')
|
f = os.fdopen(fd, 'w')
|
||||||
|
|
||||||
if idx != 0:
|
|
||||||
ctrl_iface="/var/run/hostapd_%d" % idx
|
|
||||||
|
|
||||||
f.write("ctrl_interface=%s\n" % ctrl_iface)
|
f.write("ctrl_interface=%s\n" % ctrl_iface)
|
||||||
f.write("driver=nl80211\n")
|
f.write("driver=nl80211\n")
|
||||||
f.write("ieee80211n=1\n")
|
f.write("ieee80211n=1\n")
|
||||||
|
|
36
tests/hwsim/mld.py
Normal file
36
tests/hwsim/mld.py
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
# Python class for controlling Multi Link Device
|
||||||
|
# Copyright (c) 2024, Jouni Malinen <j@w1.fi>
|
||||||
|
#
|
||||||
|
# This software may be distributed under the terms of the BSD license.
|
||||||
|
# See README for more details.
|
||||||
|
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
import wpaspy
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
hapd_ctrl = '/var/run/hostapd'
|
||||||
|
|
||||||
|
class MultiLinkDevice:
|
||||||
|
def __init__(self, ifname, ctrl=hapd_ctrl, port=8877):
|
||||||
|
self.ifname = ifname
|
||||||
|
self.ctrl = wpaspy.Ctrl(os.path.join(ctrl, ifname))
|
||||||
|
self.dbg = ifname
|
||||||
|
|
||||||
|
def close_ctrl(self):
|
||||||
|
self.ctrl.close()
|
||||||
|
self.ctrl = None
|
||||||
|
|
||||||
|
def request(self, cmd):
|
||||||
|
logger.debug(self.dbg + ": MLD CTRL: " + cmd)
|
||||||
|
return self.ctrl.request(cmd)
|
||||||
|
|
||||||
|
def ping(self):
|
||||||
|
return "PONG" in self.request("PING")
|
||||||
|
|
||||||
|
def get_mld_obj(ifname, ctrl=hapd_ctrl, port=8877):
|
||||||
|
mld = MultiLinkDevice(ifname, ctrl, port)
|
||||||
|
if not mld.ping():
|
||||||
|
raise Exception("Could not ping MLD %s" % ifname)
|
||||||
|
|
||||||
|
return mld
|
92
tests/hwsim/remotectrl.py
Normal file
92
tests/hwsim/remotectrl.py
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
#
|
||||||
|
# wpa_supplicant/hostapd control interface using Python
|
||||||
|
# Copyright (c) 2024, Jouni Malinen <j@w1.fi>
|
||||||
|
#
|
||||||
|
# This software may be distributed under the terms of the BSD license.
|
||||||
|
# See README for more details.
|
||||||
|
|
||||||
|
from wpaspy import Ctrl
|
||||||
|
import remotehost
|
||||||
|
|
||||||
|
class RemoteCtrl(Ctrl):
|
||||||
|
def __init__(self, path, port=9877, hostname=None, ifname=None):
|
||||||
|
self.started = False
|
||||||
|
self.attached = False
|
||||||
|
self.path = path
|
||||||
|
self.port = port
|
||||||
|
self.ifname = ifname
|
||||||
|
self.hostname = hostname
|
||||||
|
self.proc = None
|
||||||
|
|
||||||
|
self.host = remotehost.Host(hostname)
|
||||||
|
self.started = True
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
self.close()
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
if self.attached:
|
||||||
|
try:
|
||||||
|
self.detach()
|
||||||
|
except Exception as e:
|
||||||
|
# Need to ignore this allow the socket to be closed
|
||||||
|
self.attached = False
|
||||||
|
pass
|
||||||
|
|
||||||
|
if self.host and self.started:
|
||||||
|
self.started = False
|
||||||
|
|
||||||
|
def request(self, cmd, timeout=10):
|
||||||
|
if self.host:
|
||||||
|
cmd = '\'' + cmd + '\''
|
||||||
|
if self.ifname:
|
||||||
|
_cmd = ['wpa_cli', '-p', self.path, '-i', self.ifname, "raw " + cmd]
|
||||||
|
else:
|
||||||
|
_cmd = ['wpa_cli', '-g', self.path, "raw " + cmd]
|
||||||
|
status, buf = self.host.execute(_cmd)
|
||||||
|
return buf
|
||||||
|
|
||||||
|
def attach(self):
|
||||||
|
if self.attached:
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.host:
|
||||||
|
if self.ifname:
|
||||||
|
_cmd = [ "wpa_cli", "-p", self.path, "-i", self.ifname ]
|
||||||
|
else:
|
||||||
|
_cmd = [ "wpa_cli", '-g', self.path]
|
||||||
|
self.proc = self.host.proc_run(_cmd)
|
||||||
|
self.attached = True
|
||||||
|
|
||||||
|
def detach(self):
|
||||||
|
if not self.attached:
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.hostname and self.proc:
|
||||||
|
self.request("DETACH")
|
||||||
|
self.request("QUIT")
|
||||||
|
self.host.proc_stop(self.proc)
|
||||||
|
self.attached = False
|
||||||
|
self.proc = None
|
||||||
|
|
||||||
|
def terminate(self):
|
||||||
|
if self.attached:
|
||||||
|
try:
|
||||||
|
self.detach()
|
||||||
|
except Exception as e:
|
||||||
|
# Need to ignore this to allow the socket to be closed
|
||||||
|
self.attached = False
|
||||||
|
self.request("TERMINATE")
|
||||||
|
self.close()
|
||||||
|
|
||||||
|
def pending(self, timeout=0):
|
||||||
|
if self.host and self.proc:
|
||||||
|
return self.host.proc_pending(self.proc, timeout=timeout)
|
||||||
|
return False
|
||||||
|
|
||||||
|
def recv(self):
|
||||||
|
if self.host and self.proc:
|
||||||
|
res = self.host.proc_read(self.proc)
|
||||||
|
return res
|
||||||
|
return ""
|
|
@ -83,7 +83,10 @@ class Host():
|
||||||
if self.host is None:
|
if self.host is None:
|
||||||
return self.local_execute(command)
|
return self.local_execute(command)
|
||||||
|
|
||||||
cmd = ["ssh", self.user + "@" + self.host, ' '.join(command)]
|
if self.user:
|
||||||
|
cmd = ["ssh", self.user + "@" + self.host, ' '.join(command)]
|
||||||
|
else:
|
||||||
|
cmd = ["ssh", self.host, ' '.join(command)]
|
||||||
_cmd = self.name + " execute: " + ' '.join(cmd)
|
_cmd = self.name + " execute: " + ' '.join(cmd)
|
||||||
logger.debug(_cmd)
|
logger.debug(_cmd)
|
||||||
err = tempfile.TemporaryFile()
|
err = tempfile.TemporaryFile()
|
||||||
|
@ -114,7 +117,10 @@ class Host():
|
||||||
if self.host is None:
|
if self.host is None:
|
||||||
cmd = _command
|
cmd = _command
|
||||||
else:
|
else:
|
||||||
cmd = ["ssh", self.user + "@" + self.host, ' '.join(_command)]
|
if self.user:
|
||||||
|
cmd = ["ssh", self.user + "@" + self.host, ' '.join(_command)]
|
||||||
|
else:
|
||||||
|
cmd = ["ssh", self.host, ' '.join(_command)]
|
||||||
_cmd = self.name + " thread_run: " + ' '.join(cmd)
|
_cmd = self.name + " thread_run: " + ' '.join(cmd)
|
||||||
logger.debug(_cmd)
|
logger.debug(_cmd)
|
||||||
t = threading.Thread(target=execute_thread, name=filename, args=(cmd, res))
|
t = threading.Thread(target=execute_thread, name=filename, args=(cmd, res))
|
||||||
|
@ -174,7 +180,10 @@ class Host():
|
||||||
_command = [filename] + command
|
_command = [filename] + command
|
||||||
|
|
||||||
if self.host:
|
if self.host:
|
||||||
cmd = ["ssh", self.user + "@" + self.host, ' '.join(_command)]
|
if self.user:
|
||||||
|
cmd = ["ssh", self.user + "@" + self.host, ' '.join(_command)]
|
||||||
|
else:
|
||||||
|
cmd = ["ssh", self.host, ' '.join(_command)]
|
||||||
else:
|
else:
|
||||||
cmd = _command
|
cmd = _command
|
||||||
|
|
||||||
|
@ -261,12 +270,18 @@ class Host():
|
||||||
def get_logs(self, local_log_dir=None):
|
def get_logs(self, local_log_dir=None):
|
||||||
for log in self.logs:
|
for log in self.logs:
|
||||||
if local_log_dir:
|
if local_log_dir:
|
||||||
self.local_execute(["scp", self.user + "@[" + self.host + "]:" + log, local_log_dir])
|
if self.user:
|
||||||
|
self.local_execute(["scp", self.user + "@[" + self.host + "]:" + log, local_log_dir])
|
||||||
|
else:
|
||||||
|
self.local_execute(["scp", "[" + self.host + "]:" + log, local_log_dir])
|
||||||
self.execute(["rm", log])
|
self.execute(["rm", log])
|
||||||
del self.logs[:]
|
del self.logs[:]
|
||||||
|
|
||||||
def send_file(self, src, dst):
|
def send_file(self, src, dst):
|
||||||
if self.host is None:
|
if self.host is None:
|
||||||
return
|
return
|
||||||
self.local_execute(["scp", src,
|
if self.user:
|
||||||
self.user + "@[" + self.host + "]:" + dst])
|
self.local_execute(["scp", src,
|
||||||
|
self.user + "@[" + self.host + "]:" + dst])
|
||||||
|
else:
|
||||||
|
self.local_execute(["scp", src, "[" + self.host + "]:" + dst])
|
||||||
|
|
|
@ -374,12 +374,12 @@ def test_ap_ft_vlan(dev, apdev):
|
||||||
params = ft_params1(ssid=ssid, passphrase=passphrase)
|
params = ft_params1(ssid=ssid, passphrase=passphrase)
|
||||||
params['dynamic_vlan'] = "1"
|
params['dynamic_vlan'] = "1"
|
||||||
params['accept_mac_file'] = filename
|
params['accept_mac_file'] = filename
|
||||||
hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd0 = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
params = ft_params2(ssid=ssid, passphrase=passphrase)
|
params = ft_params2(ssid=ssid, passphrase=passphrase)
|
||||||
params['dynamic_vlan'] = "1"
|
params['dynamic_vlan'] = "1"
|
||||||
params['accept_mac_file'] = filename
|
params['accept_mac_file'] = filename
|
||||||
hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
|
hapd1 = hostapd.add_ap(apdev[1], params)
|
||||||
|
|
||||||
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, conndev="brvlan1")
|
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, conndev="brvlan1")
|
||||||
if "[WPA2-FT/PSK-CCMP]" not in dev[0].request("SCAN_RESULTS"):
|
if "[WPA2-FT/PSK-CCMP]" not in dev[0].request("SCAN_RESULTS"):
|
||||||
|
@ -413,13 +413,13 @@ def test_ap_ft_vlan_disconnected(dev, apdev):
|
||||||
params['dynamic_vlan'] = "1"
|
params['dynamic_vlan'] = "1"
|
||||||
params['accept_mac_file'] = filename
|
params['accept_mac_file'] = filename
|
||||||
params['ft_psk_generate_local'] = "1"
|
params['ft_psk_generate_local'] = "1"
|
||||||
hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd0 = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
params = ft_params2a(ssid=ssid, passphrase=passphrase)
|
params = ft_params2a(ssid=ssid, passphrase=passphrase)
|
||||||
params['dynamic_vlan'] = "1"
|
params['dynamic_vlan'] = "1"
|
||||||
params['accept_mac_file'] = filename
|
params['accept_mac_file'] = filename
|
||||||
params['ft_psk_generate_local'] = "1"
|
params['ft_psk_generate_local'] = "1"
|
||||||
hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
|
hapd1 = hostapd.add_ap(apdev[1], params)
|
||||||
|
|
||||||
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, conndev="brvlan1")
|
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, conndev="brvlan1")
|
||||||
if "[WPA2-FT/PSK-CCMP]" not in dev[0].request("SCAN_RESULTS"):
|
if "[WPA2-FT/PSK-CCMP]" not in dev[0].request("SCAN_RESULTS"):
|
||||||
|
@ -437,11 +437,11 @@ def test_ap_ft_vlan_2(dev, apdev):
|
||||||
params = ft_params1(ssid=ssid, passphrase=passphrase)
|
params = ft_params1(ssid=ssid, passphrase=passphrase)
|
||||||
params['dynamic_vlan'] = "1"
|
params['dynamic_vlan'] = "1"
|
||||||
params['accept_mac_file'] = filename
|
params['accept_mac_file'] = filename
|
||||||
hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd0 = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
params = ft_params2(ssid=ssid, passphrase=passphrase)
|
params = ft_params2(ssid=ssid, passphrase=passphrase)
|
||||||
params['dynamic_vlan'] = "1"
|
params['dynamic_vlan'] = "1"
|
||||||
hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
|
hapd1 = hostapd.add_ap(apdev[1], params)
|
||||||
|
|
||||||
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, conndev="brvlan1",
|
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, conndev="brvlan1",
|
||||||
force_initial_conn_to_first_ap=True)
|
force_initial_conn_to_first_ap=True)
|
||||||
|
@ -520,12 +520,12 @@ def test_ap_ft_many_vlan(dev, apdev):
|
||||||
params = ft_params1(ssid=ssid, passphrase=passphrase)
|
params = ft_params1(ssid=ssid, passphrase=passphrase)
|
||||||
params['dynamic_vlan'] = "1"
|
params['dynamic_vlan'] = "1"
|
||||||
params['accept_mac_file'] = filename
|
params['accept_mac_file'] = filename
|
||||||
hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd0 = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
params = ft_params2(ssid=ssid, passphrase=passphrase)
|
params = ft_params2(ssid=ssid, passphrase=passphrase)
|
||||||
params['dynamic_vlan'] = "1"
|
params['dynamic_vlan'] = "1"
|
||||||
params['accept_mac_file'] = filename
|
params['accept_mac_file'] = filename
|
||||||
hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
|
hapd1 = hostapd.add_ap(apdev[1], params)
|
||||||
|
|
||||||
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, roams=50,
|
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, roams=50,
|
||||||
conndev="brvlan1")
|
conndev="brvlan1")
|
||||||
|
@ -862,11 +862,11 @@ def test_ap_ft_vlan_over_ds(dev, apdev):
|
||||||
params = ft_params1(ssid=ssid, passphrase=passphrase)
|
params = ft_params1(ssid=ssid, passphrase=passphrase)
|
||||||
params['dynamic_vlan'] = "1"
|
params['dynamic_vlan'] = "1"
|
||||||
params['accept_mac_file'] = filename
|
params['accept_mac_file'] = filename
|
||||||
hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd0 = hostapd.add_ap(apdev[0], params)
|
||||||
params = ft_params2(ssid=ssid, passphrase=passphrase)
|
params = ft_params2(ssid=ssid, passphrase=passphrase)
|
||||||
params['dynamic_vlan'] = "1"
|
params['dynamic_vlan'] = "1"
|
||||||
params['accept_mac_file'] = filename
|
params['accept_mac_file'] = filename
|
||||||
hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
|
hapd1 = hostapd.add_ap(apdev[1], params)
|
||||||
|
|
||||||
dev[0].flush_scan_cache()
|
dev[0].flush_scan_cache()
|
||||||
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
|
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
|
||||||
|
@ -900,11 +900,11 @@ def test_ap_ft_vlan_over_ds_many(dev, apdev):
|
||||||
params = ft_params1(ssid=ssid, passphrase=passphrase)
|
params = ft_params1(ssid=ssid, passphrase=passphrase)
|
||||||
params['dynamic_vlan'] = "1"
|
params['dynamic_vlan'] = "1"
|
||||||
params['accept_mac_file'] = filename
|
params['accept_mac_file'] = filename
|
||||||
hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd0 = hostapd.add_ap(apdev[0], params)
|
||||||
params = ft_params2(ssid=ssid, passphrase=passphrase)
|
params = ft_params2(ssid=ssid, passphrase=passphrase)
|
||||||
params['dynamic_vlan'] = "1"
|
params['dynamic_vlan'] = "1"
|
||||||
params['accept_mac_file'] = filename
|
params['accept_mac_file'] = filename
|
||||||
hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
|
hapd1 = hostapd.add_ap(apdev[1], params)
|
||||||
|
|
||||||
dev[0].flush_scan_cache()
|
dev[0].flush_scan_cache()
|
||||||
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
|
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
|
||||||
|
@ -1115,12 +1115,12 @@ def test_ap_ft_over_ds_pull_vlan(dev, apdev):
|
||||||
params["pmk_r1_push"] = "0"
|
params["pmk_r1_push"] = "0"
|
||||||
params['dynamic_vlan'] = "1"
|
params['dynamic_vlan'] = "1"
|
||||||
params['accept_mac_file'] = filename
|
params['accept_mac_file'] = filename
|
||||||
hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd0 = hostapd.add_ap(apdev[0], params)
|
||||||
params = ft_params2(ssid=ssid, passphrase=passphrase)
|
params = ft_params2(ssid=ssid, passphrase=passphrase)
|
||||||
params["pmk_r1_push"] = "0"
|
params["pmk_r1_push"] = "0"
|
||||||
params['dynamic_vlan'] = "1"
|
params['dynamic_vlan'] = "1"
|
||||||
params['accept_mac_file'] = filename
|
params['accept_mac_file'] = filename
|
||||||
hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
|
hapd1 = hostapd.add_ap(apdev[1], params)
|
||||||
|
|
||||||
dev[0].flush_scan_cache()
|
dev[0].flush_scan_cache()
|
||||||
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
|
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
|
||||||
|
|
|
@ -131,7 +131,7 @@ def test_ap_open_assoc_timeout(dev, apdev):
|
||||||
|
|
||||||
def test_ap_open_auth_drop_sta(dev, apdev):
|
def test_ap_open_auth_drop_sta(dev, apdev):
|
||||||
"""AP dropping station after successful authentication"""
|
"""AP dropping station after successful authentication"""
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], {"ssid": "open"})
|
hapd = hostapd.add_ap(apdev[0], {"ssid": "open"})
|
||||||
dev[0].scan(freq="2412")
|
dev[0].scan(freq="2412")
|
||||||
hapd.set("ext_mgmt_frame_handling", "1")
|
hapd.set("ext_mgmt_frame_handling", "1")
|
||||||
dev[0].connect("open", key_mgmt="NONE", scan_freq="2412",
|
dev[0].connect("open", key_mgmt="NONE", scan_freq="2412",
|
||||||
|
|
|
@ -3759,6 +3759,21 @@ def test_rsn_eapol_m3_extra(dev, apdev):
|
||||||
|
|
||||||
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
|
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
|
||||||
|
|
||||||
|
def test_rsn_eapol_m3_extra_long(dev, apdev):
|
||||||
|
"""Long extra KDE in EAPOL-Key msg 3/4"""
|
||||||
|
ssid = "test-rsn"
|
||||||
|
passphrase = 'qwertyuiop'
|
||||||
|
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
|
||||||
|
# Add a reserved KDEs into EAPOL-Key msg 3/4
|
||||||
|
val = 'dd0507c0d19311'
|
||||||
|
val += 'ddff69b847070102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafb'
|
||||||
|
val += 'dd085ba59d7911223344'
|
||||||
|
val += 'dd0a000face4112233445566'
|
||||||
|
params['eapol_m3_elements'] = val
|
||||||
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
|
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
|
||||||
|
|
||||||
def test_rsn_eapol_m3_no_encrypt(dev, apdev):
|
def test_rsn_eapol_m3_no_encrypt(dev, apdev):
|
||||||
"""EAPOL-Key msg 3/4 Key Data field not encrypted"""
|
"""EAPOL-Key msg 3/4 Key Data field not encrypted"""
|
||||||
ssid = "test-rsn"
|
ssid = "test-rsn"
|
||||||
|
|
|
@ -800,17 +800,21 @@ def test_ap_vlan_psk(dev, apdev, params):
|
||||||
if vlan_id != i + 1:
|
if vlan_id != i + 1:
|
||||||
raise Exception("Unexpected vlan_id %d for dev[%d]" % (vlan_id, i))
|
raise Exception("Unexpected vlan_id %d for dev[%d]" % (vlan_id, i))
|
||||||
|
|
||||||
def test_ap_vlan_sae(dev, apdev, params):
|
def start_ap_vlan_sae(apdev):
|
||||||
"""AP VLAN based on SAE Password Identifier"""
|
|
||||||
for i in range(3):
|
|
||||||
check_sae_capab(dev[i])
|
|
||||||
params = hostapd.wpa2_params(ssid="test-sae-vlan")
|
params = hostapd.wpa2_params(ssid="test-sae-vlan")
|
||||||
params['wpa_key_mgmt'] = 'SAE'
|
params['wpa_key_mgmt'] = 'SAE'
|
||||||
params['sae_password'] = ['pw1|vlanid=1|id=id1',
|
params['sae_password'] = ['pw1|vlanid=1|id=id1',
|
||||||
'pw2|mac=ff:ff:ff:ff:ff:ff|vlanid=2|id=id2',
|
'pw2|mac=ff:ff:ff:ff:ff:ff|vlanid=2|id=id2',
|
||||||
'pw3|vlanid=3|id=id3']
|
'pw3|vlanid=3|id=id3']
|
||||||
params['dynamic_vlan'] = "1"
|
params['dynamic_vlan'] = "1"
|
||||||
hapd = hostapd.add_ap(apdev[0], params)
|
params['wpa_group_rekey'] = '10'
|
||||||
|
return hostapd.add_ap(apdev, params)
|
||||||
|
|
||||||
|
def test_ap_vlan_sae(dev, apdev, params):
|
||||||
|
"""AP VLAN based on SAE Password Identifier"""
|
||||||
|
for i in range(3):
|
||||||
|
check_sae_capab(dev[i])
|
||||||
|
hapd = start_ap_vlan_sae(apdev[0])
|
||||||
|
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
dev[i].request("SET sae_groups ")
|
dev[i].request("SET sae_groups ")
|
||||||
|
@ -830,3 +834,42 @@ def test_ap_vlan_sae(dev, apdev, params):
|
||||||
vlan_id = int(sta["vlan_id"])
|
vlan_id = int(sta["vlan_id"])
|
||||||
if vlan_id != i + 1:
|
if vlan_id != i + 1:
|
||||||
raise Exception("Unexpected vlan_id %d for dev[%d]" % (vlan_id, i))
|
raise Exception("Unexpected vlan_id %d for dev[%d]" % (vlan_id, i))
|
||||||
|
|
||||||
|
ev = dev[i].wait_event(["RSN: Group rekeying completed"], timeout=11)
|
||||||
|
if ev is None:
|
||||||
|
raise Exception("GTK rekey timed out")
|
||||||
|
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1")
|
||||||
|
hwsim_utils.test_connectivity_iface(dev[1], hapd, "brvlan2")
|
||||||
|
hwsim_utils.test_connectivity_iface(dev[2], hapd, "brvlan3")
|
||||||
|
|
||||||
|
def test_ap_vlan_sae_group_rekey(dev, apdev, params):
|
||||||
|
"""AP VLAN and group rekeying"""
|
||||||
|
check_sae_capab(dev[0])
|
||||||
|
hapd = start_ap_vlan_sae(apdev[0])
|
||||||
|
|
||||||
|
dev[0].set("sae_groups", "")
|
||||||
|
dev[0].connect("test-sae-vlan", sae_password="pw1",
|
||||||
|
sae_password_id="id1",
|
||||||
|
key_mgmt="SAE", scan_freq="2412")
|
||||||
|
hapd.wait_sta()
|
||||||
|
|
||||||
|
hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1")
|
||||||
|
|
||||||
|
hapd.set("ext_eapol_frame_io", "1")
|
||||||
|
ev = hapd.wait_event(["EAPOL-TX"], timeout=15)
|
||||||
|
if ev is None:
|
||||||
|
raise Exception("Timeout on EAPOL-TX from hostapd")
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1")
|
||||||
|
hapd.set("ext_eapol_frame_io", "0")
|
||||||
|
|
||||||
|
ev = dev[0].wait_event(["RSN: Group rekeying completed"], timeout=11)
|
||||||
|
if ev is None:
|
||||||
|
raise Exception("GTK rekey timed out")
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1")
|
||||||
|
|
|
@ -2314,6 +2314,23 @@ def test_dpp_auto_connect_legacy_sae_2(dev, apdev):
|
||||||
finally:
|
finally:
|
||||||
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
||||||
|
|
||||||
|
def test_dpp_auto_connect_legacy_sae_3(dev, apdev):
|
||||||
|
"""DPP and auto connect (legacy SAE with short password)"""
|
||||||
|
try:
|
||||||
|
run_dpp_auto_connect_legacy(dev, apdev, conf='sta-sae', sae_only=True,
|
||||||
|
password="1234567")
|
||||||
|
finally:
|
||||||
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
||||||
|
|
||||||
|
def test_dpp_auto_connect_legacy_sae_pw_id(dev, apdev):
|
||||||
|
"""DPP and auto connect (legacy SAE with password identifier)"""
|
||||||
|
check_dpp_capab(dev[0], min_ver=3)
|
||||||
|
try:
|
||||||
|
run_dpp_auto_connect_legacy(dev, apdev, conf='sta-sae', sae_only=True,
|
||||||
|
password_id="id")
|
||||||
|
finally:
|
||||||
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
||||||
|
|
||||||
def test_dpp_auto_connect_legacy_psk_sae_1(dev, apdev):
|
def test_dpp_auto_connect_legacy_psk_sae_1(dev, apdev):
|
||||||
"""DPP and auto connect (legacy PSK+SAE)"""
|
"""DPP and auto connect (legacy PSK+SAE)"""
|
||||||
try:
|
try:
|
||||||
|
@ -2339,16 +2356,22 @@ def test_dpp_auto_connect_legacy_psk_sae_3(dev, apdev):
|
||||||
|
|
||||||
def run_dpp_auto_connect_legacy(dev, apdev, conf='sta-psk',
|
def run_dpp_auto_connect_legacy(dev, apdev, conf='sta-psk',
|
||||||
ssid_charset=None,
|
ssid_charset=None,
|
||||||
psk_sae=False, sae_only=False):
|
psk_sae=False, sae_only=False,
|
||||||
|
password="secret passphrase",
|
||||||
|
password_id=None):
|
||||||
check_dpp_capab(dev[0])
|
check_dpp_capab(dev[0])
|
||||||
check_dpp_capab(dev[1])
|
check_dpp_capab(dev[1])
|
||||||
|
|
||||||
params = hostapd.wpa2_params(ssid="dpp-legacy",
|
if sae_only and password_id:
|
||||||
passphrase="secret passphrase")
|
params = hostapd.wpa3_params(ssid="dpp-legacy",
|
||||||
if sae_only:
|
password=password + '|id=' + password_id)
|
||||||
params['wpa_key_mgmt'] = 'SAE'
|
elif sae_only:
|
||||||
params['ieee80211w'] = '2'
|
params = hostapd.wpa3_params(ssid="dpp-legacy",
|
||||||
elif psk_sae:
|
password=password)
|
||||||
|
else:
|
||||||
|
params = hostapd.wpa2_params(ssid="dpp-legacy",
|
||||||
|
passphrase=password)
|
||||||
|
if psk_sae:
|
||||||
params['wpa_key_mgmt'] = 'WPA-PSK SAE'
|
params['wpa_key_mgmt'] = 'WPA-PSK SAE'
|
||||||
params['ieee80211w'] = '1'
|
params['ieee80211w'] = '1'
|
||||||
params['sae_require_mfp'] = '1'
|
params['sae_require_mfp'] = '1'
|
||||||
|
@ -2363,7 +2386,7 @@ def run_dpp_auto_connect_legacy(dev, apdev, conf='sta-psk',
|
||||||
dev[0].dpp_listen(2412)
|
dev[0].dpp_listen(2412)
|
||||||
dev[1].dpp_auth_init(uri=uri0, conf=conf, ssid="dpp-legacy",
|
dev[1].dpp_auth_init(uri=uri0, conf=conf, ssid="dpp-legacy",
|
||||||
ssid_charset=ssid_charset,
|
ssid_charset=ssid_charset,
|
||||||
passphrase="secret passphrase")
|
passphrase=password, password_id=password_id)
|
||||||
wait_auth_success(dev[0], dev[1], configurator=dev[1], enrollee=dev[0])
|
wait_auth_success(dev[0], dev[1], configurator=dev[1], enrollee=dev[0])
|
||||||
if ssid_charset:
|
if ssid_charset:
|
||||||
ev = dev[0].wait_event(["DPP-CONFOBJ-SSID-CHARSET"], timeout=1)
|
ev = dev[0].wait_event(["DPP-CONFOBJ-SSID-CHARSET"], timeout=1)
|
||||||
|
|
|
@ -13,6 +13,7 @@ from hwsim import HWSimRadio
|
||||||
import hwsim_utils
|
import hwsim_utils
|
||||||
from wpasupplicant import WpaSupplicant
|
from wpasupplicant import WpaSupplicant
|
||||||
import re
|
import re
|
||||||
|
import mld
|
||||||
from tshark import run_tshark
|
from tshark import run_tshark
|
||||||
from test_gas import hs20_ap_params
|
from test_gas import hs20_ap_params
|
||||||
from test_dpp import check_dpp_capab, wait_auth_success
|
from test_dpp import check_dpp_capab, wait_auth_success
|
||||||
|
@ -104,8 +105,9 @@ def eht_verify_status(wpas, hapd, freq, bw, is_ht=False, is_vht=False,
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
_eht_verify_links(wpas, valid_links, active_links)
|
_eht_verify_links(wpas, valid_links, active_links)
|
||||||
|
|
||||||
def traffic_test(wpas, hapd, success=True):
|
def traffic_test(wpas, hapd, success=True, ifname2=None):
|
||||||
hwsim_utils.test_connectivity(wpas, hapd, success_expected=success)
|
hwsim_utils.test_connectivity(wpas, hapd, success_expected=success,
|
||||||
|
ifname2=ifname2)
|
||||||
|
|
||||||
def test_eht_open(dev, apdev):
|
def test_eht_open(dev, apdev):
|
||||||
"""EHT AP with open mode configuration"""
|
"""EHT AP with open mode configuration"""
|
||||||
|
@ -238,8 +240,8 @@ def test_eht_sae_mlo_tm(dev, apdev):
|
||||||
dev[0].set("sae_pwe", "0")
|
dev[0].set("sae_pwe", "0")
|
||||||
dev[1].set("sae_groups", "")
|
dev[1].set("sae_groups", "")
|
||||||
|
|
||||||
def eht_mld_enable_ap(iface, params):
|
def eht_mld_enable_ap(iface, link_id, params):
|
||||||
hapd = hostapd.add_mld_link(iface, params)
|
hapd = hostapd.add_mld_link(iface, link_id, params)
|
||||||
hapd.enable()
|
hapd.enable()
|
||||||
|
|
||||||
ev = hapd.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=1)
|
ev = hapd.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=1)
|
||||||
|
@ -251,7 +253,7 @@ def eht_mld_enable_ap(iface, params):
|
||||||
return hapd
|
return hapd
|
||||||
|
|
||||||
def eht_mld_ap_wpa2_params(ssid, passphrase=None, key_mgmt="WPA-PSK-SHA256",
|
def eht_mld_ap_wpa2_params(ssid, passphrase=None, key_mgmt="WPA-PSK-SHA256",
|
||||||
mfp="2", pwe=None, beacon_prot="1"):
|
mfp="2", pwe=None, beacon_prot="1", bridge=False):
|
||||||
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase,
|
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase,
|
||||||
wpa_key_mgmt=key_mgmt, ieee80211w=mfp)
|
wpa_key_mgmt=key_mgmt, ieee80211w=mfp)
|
||||||
params['ieee80211n'] = '1'
|
params['ieee80211n'] = '1'
|
||||||
|
@ -261,6 +263,8 @@ def eht_mld_ap_wpa2_params(ssid, passphrase=None, key_mgmt="WPA-PSK-SHA256",
|
||||||
params['hw_mode'] = 'g'
|
params['hw_mode'] = 'g'
|
||||||
params['group_mgmt_cipher'] = "AES-128-CMAC"
|
params['group_mgmt_cipher'] = "AES-128-CMAC"
|
||||||
params['beacon_prot'] = beacon_prot
|
params['beacon_prot'] = beacon_prot
|
||||||
|
if bridge:
|
||||||
|
params['bridge'] = 'ap-br0'
|
||||||
|
|
||||||
if pwe is not None:
|
if pwe is not None:
|
||||||
params['sae_pwe'] = pwe
|
params['sae_pwe'] = pwe
|
||||||
|
@ -307,8 +311,8 @@ def test_eht_mld_discovery(dev, apdev):
|
||||||
"hw_mode": "g",
|
"hw_mode": "g",
|
||||||
"channel": "2"}
|
"channel": "2"}
|
||||||
|
|
||||||
hapd0 = eht_mld_enable_ap(hapd_iface, link0_params)
|
hapd0 = eht_mld_enable_ap(hapd_iface, 0, link0_params)
|
||||||
hapd1 = eht_mld_enable_ap(hapd_iface, link1_params)
|
hapd1 = eht_mld_enable_ap(hapd_iface, 1, link1_params)
|
||||||
|
|
||||||
# Only scan link 0
|
# Only scan link 0
|
||||||
res = wpas.request("SCAN freq=2412")
|
res = wpas.request("SCAN freq=2412")
|
||||||
|
@ -388,13 +392,13 @@ def _eht_mld_owe_two_links(dev, apdev, second_link_disabled=False,
|
||||||
ssid = "mld_ap_owe_two_link"
|
ssid = "mld_ap_owe_two_link"
|
||||||
params = eht_mld_ap_wpa2_params(ssid, key_mgmt="OWE", mfp="2")
|
params = eht_mld_ap_wpa2_params(ssid, key_mgmt="OWE", mfp="2")
|
||||||
|
|
||||||
hapd0 = eht_mld_enable_ap(hapd0_iface, params)
|
hapd0 = eht_mld_enable_ap(hapd0_iface, 0, params)
|
||||||
|
|
||||||
params['channel'] = '6'
|
params['channel'] = '6'
|
||||||
if second_link_disabled:
|
if second_link_disabled:
|
||||||
params['mld_indicate_disabled'] = '1'
|
params['mld_indicate_disabled'] = '1'
|
||||||
|
|
||||||
hapd1 = eht_mld_enable_ap(hapd0_iface, params)
|
hapd1 = eht_mld_enable_ap(hapd0_iface, 1, params)
|
||||||
# Check legacy client connection
|
# Check legacy client connection
|
||||||
dev[0].connect(ssid, scan_freq="2437", key_mgmt="OWE", ieee80211w="2")
|
dev[0].connect(ssid, scan_freq="2437", key_mgmt="OWE", ieee80211w="2")
|
||||||
|
|
||||||
|
@ -446,7 +450,7 @@ def test_eht_mld_sae_single_link(dev, apdev):
|
||||||
params = eht_mld_ap_wpa2_params(ssid, passphrase, key_mgmt="SAE",
|
params = eht_mld_ap_wpa2_params(ssid, passphrase, key_mgmt="SAE",
|
||||||
mfp="2", pwe='2')
|
mfp="2", pwe='2')
|
||||||
|
|
||||||
hapd0 = eht_mld_enable_ap(hapd_iface, params)
|
hapd0 = eht_mld_enable_ap(hapd_iface, 0, params)
|
||||||
|
|
||||||
wpas.set("sae_pwe", "1")
|
wpas.set("sae_pwe", "1")
|
||||||
wpas.connect(ssid, sae_password=passphrase, scan_freq="2412",
|
wpas.connect(ssid, sae_password=passphrase, scan_freq="2412",
|
||||||
|
@ -458,7 +462,7 @@ def test_eht_mld_sae_single_link(dev, apdev):
|
||||||
traffic_test(wpas, hapd0)
|
traffic_test(wpas, hapd0)
|
||||||
|
|
||||||
def run_eht_mld_sae_two_links(dev, apdev, beacon_prot="1",
|
def run_eht_mld_sae_two_links(dev, apdev, beacon_prot="1",
|
||||||
disable_enable=False):
|
disable_enable=False, bridge=False):
|
||||||
with HWSimRadio(use_mlo=True) as (hapd_radio, hapd_iface), \
|
with HWSimRadio(use_mlo=True) as (hapd_radio, hapd_iface), \
|
||||||
HWSimRadio(use_mlo=True) as (wpas_radio, wpas_iface):
|
HWSimRadio(use_mlo=True) as (wpas_radio, wpas_iface):
|
||||||
|
|
||||||
|
@ -469,13 +473,18 @@ def run_eht_mld_sae_two_links(dev, apdev, beacon_prot="1",
|
||||||
ssid = "mld_ap_sae_two_link"
|
ssid = "mld_ap_sae_two_link"
|
||||||
params = eht_mld_ap_wpa2_params(ssid, passphrase,
|
params = eht_mld_ap_wpa2_params(ssid, passphrase,
|
||||||
key_mgmt="SAE", mfp="2", pwe='1',
|
key_mgmt="SAE", mfp="2", pwe='1',
|
||||||
beacon_prot=beacon_prot)
|
beacon_prot=beacon_prot,
|
||||||
|
bridge=bridge)
|
||||||
|
|
||||||
hapd0 = eht_mld_enable_ap(hapd_iface, params)
|
hapd0 = eht_mld_enable_ap(hapd_iface, 0, params)
|
||||||
|
|
||||||
params['channel'] = '6'
|
params['channel'] = '6'
|
||||||
|
|
||||||
hapd1 = eht_mld_enable_ap(hapd_iface, params)
|
hapd1 = eht_mld_enable_ap(hapd_iface, 1, params)
|
||||||
|
|
||||||
|
if bridge:
|
||||||
|
hapd0.cmd_execute(['brctl', 'setfd', 'ap-br0', '0'])
|
||||||
|
hapd0.cmd_execute(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
|
||||||
|
|
||||||
wpas.set("sae_pwe", "1")
|
wpas.set("sae_pwe", "1")
|
||||||
|
|
||||||
|
@ -494,8 +503,8 @@ def run_eht_mld_sae_two_links(dev, apdev, beacon_prot="1",
|
||||||
if wpas.get_status_field('sae_group') != '19':
|
if wpas.get_status_field('sae_group') != '19':
|
||||||
raise Exception("Expected SAE group not used")
|
raise Exception("Expected SAE group not used")
|
||||||
|
|
||||||
traffic_test(wpas, hapd0)
|
traffic_test(wpas, hapd0, ifname2='ap-br0' if bridge else None)
|
||||||
traffic_test(wpas, hapd1)
|
traffic_test(wpas, hapd1, ifname2='ap-br0' if bridge else None)
|
||||||
|
|
||||||
if disable_enable:
|
if disable_enable:
|
||||||
if "OK" not in hapd0.request("DISABLE_MLD"):
|
if "OK" not in hapd0.request("DISABLE_MLD"):
|
||||||
|
@ -534,8 +543,8 @@ def run_eht_mld_sae_two_links(dev, apdev, beacon_prot="1",
|
||||||
wpas.wait_connected()
|
wpas.wait_connected()
|
||||||
hapd0.wait_sta()
|
hapd0.wait_sta()
|
||||||
hapd1.wait_sta()
|
hapd1.wait_sta()
|
||||||
traffic_test(wpas, hapd0)
|
traffic_test(wpas, hapd0, ifname2='ap-br0' if bridge else None)
|
||||||
traffic_test(wpas, hapd1)
|
traffic_test(wpas, hapd1, ifname2='ap-br0' if bridge else None)
|
||||||
|
|
||||||
def test_eht_mld_sae_two_links(dev, apdev):
|
def test_eht_mld_sae_two_links(dev, apdev):
|
||||||
"""EHT MLD AP with MLD client SAE H2E connection using two links"""
|
"""EHT MLD AP with MLD client SAE H2E connection using two links"""
|
||||||
|
@ -549,6 +558,10 @@ def test_eht_mld_sae_two_links_disable_enable(dev, apdev):
|
||||||
"""AP MLD with two links and disabling/enabling full AP MLD"""
|
"""AP MLD with two links and disabling/enabling full AP MLD"""
|
||||||
run_eht_mld_sae_two_links(dev, apdev, disable_enable=True)
|
run_eht_mld_sae_two_links(dev, apdev, disable_enable=True)
|
||||||
|
|
||||||
|
def test_eht_mld_sae_two_links_bridge(dev, apdev):
|
||||||
|
"""AP MLD with two links in a bridge"""
|
||||||
|
run_eht_mld_sae_two_links(dev, apdev, bridge=True)
|
||||||
|
|
||||||
def test_eht_mld_sae_ext_one_link(dev, apdev):
|
def test_eht_mld_sae_ext_one_link(dev, apdev):
|
||||||
"""EHT MLD AP with MLD client SAE-EXT H2E connection using single link"""
|
"""EHT MLD AP with MLD client SAE-EXT H2E connection using single link"""
|
||||||
with HWSimRadio(use_mlo=True) as (hapd_radio, hapd_iface), \
|
with HWSimRadio(use_mlo=True) as (hapd_radio, hapd_iface), \
|
||||||
|
@ -561,7 +574,7 @@ def test_eht_mld_sae_ext_one_link(dev, apdev):
|
||||||
ssid = "mld_ap_sae_ext_single_link"
|
ssid = "mld_ap_sae_ext_single_link"
|
||||||
params = eht_mld_ap_wpa2_params(ssid, passphrase, key_mgmt="SAE-EXT-KEY")
|
params = eht_mld_ap_wpa2_params(ssid, passphrase, key_mgmt="SAE-EXT-KEY")
|
||||||
|
|
||||||
hapd0 = eht_mld_enable_ap(hapd_iface, params)
|
hapd0 = eht_mld_enable_ap(hapd_iface, 0, params)
|
||||||
|
|
||||||
wpas.connect(ssid, sae_password=passphrase, scan_freq="2412",
|
wpas.connect(ssid, sae_password=passphrase, scan_freq="2412",
|
||||||
key_mgmt="SAE-EXT-KEY", ieee80211w="2")
|
key_mgmt="SAE-EXT-KEY", ieee80211w="2")
|
||||||
|
@ -584,11 +597,11 @@ def test_eht_mld_sae_ext_two_links(dev, apdev):
|
||||||
params = eht_mld_ap_wpa2_params(ssid, passphrase,
|
params = eht_mld_ap_wpa2_params(ssid, passphrase,
|
||||||
key_mgmt="SAE-EXT-KEY")
|
key_mgmt="SAE-EXT-KEY")
|
||||||
|
|
||||||
hapd0 = eht_mld_enable_ap(hapd_iface, params)
|
hapd0 = eht_mld_enable_ap(hapd_iface, 0, params)
|
||||||
|
|
||||||
params['channel'] = '6'
|
params['channel'] = '6'
|
||||||
|
|
||||||
hapd1 = eht_mld_enable_ap(hapd_iface, params)
|
hapd1 = eht_mld_enable_ap(hapd_iface, 1, params)
|
||||||
|
|
||||||
wpas.connect(ssid, sae_password=passphrase, scan_freq="2412 2437",
|
wpas.connect(ssid, sae_password=passphrase, scan_freq="2412 2437",
|
||||||
key_mgmt="SAE-EXT-KEY", ieee80211w="2")
|
key_mgmt="SAE-EXT-KEY", ieee80211w="2")
|
||||||
|
@ -607,11 +620,11 @@ def test_eht_mld_sae_legacy_client(dev, apdev):
|
||||||
params = eht_mld_ap_wpa2_params(ssid, passphrase,
|
params = eht_mld_ap_wpa2_params(ssid, passphrase,
|
||||||
key_mgmt="SAE", mfp="2", pwe='1')
|
key_mgmt="SAE", mfp="2", pwe='1')
|
||||||
|
|
||||||
hapd0 = eht_mld_enable_ap(hapd_iface, params)
|
hapd0 = eht_mld_enable_ap(hapd_iface, 0, params)
|
||||||
|
|
||||||
params['channel'] = '6'
|
params['channel'] = '6'
|
||||||
|
|
||||||
hapd1 = eht_mld_enable_ap(hapd_iface, params)
|
hapd1 = eht_mld_enable_ap(hapd_iface, 1, params)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
dev[0].set("sae_groups", "")
|
dev[0].set("sae_groups", "")
|
||||||
|
@ -647,11 +660,11 @@ def test_eht_mld_sae_transition(dev, apdev):
|
||||||
key_mgmt="SAE-EXT-KEY SAE WPA-PSK WPA-PSK-SHA256",
|
key_mgmt="SAE-EXT-KEY SAE WPA-PSK WPA-PSK-SHA256",
|
||||||
mfp="1")
|
mfp="1")
|
||||||
|
|
||||||
hapd0 = eht_mld_enable_ap(hapd_iface, params)
|
hapd0 = eht_mld_enable_ap(hapd_iface, 0, params)
|
||||||
|
|
||||||
params['channel'] = '6'
|
params['channel'] = '6'
|
||||||
|
|
||||||
hapd1 = eht_mld_enable_ap(hapd_iface, params)
|
hapd1 = eht_mld_enable_ap(hapd_iface, 1, params)
|
||||||
|
|
||||||
wpas.connect(ssid, sae_password=passphrase, scan_freq="2412 2437",
|
wpas.connect(ssid, sae_password=passphrase, scan_freq="2412 2437",
|
||||||
key_mgmt="SAE-EXT-KEY", ieee80211w="2")
|
key_mgmt="SAE-EXT-KEY", ieee80211w="2")
|
||||||
|
@ -683,11 +696,11 @@ def test_eht_mld_ptk_rekey(dev, apdev):
|
||||||
mfp="1")
|
mfp="1")
|
||||||
params['wpa_ptk_rekey'] = '5'
|
params['wpa_ptk_rekey'] = '5'
|
||||||
|
|
||||||
hapd0 = eht_mld_enable_ap(hapd_iface, params)
|
hapd0 = eht_mld_enable_ap(hapd_iface, 0, params)
|
||||||
|
|
||||||
params['channel'] = '6'
|
params['channel'] = '6'
|
||||||
|
|
||||||
hapd1 = eht_mld_enable_ap(hapd_iface, params)
|
hapd1 = eht_mld_enable_ap(hapd_iface, 1, params)
|
||||||
|
|
||||||
wpas.connect(ssid, sae_password=passphrase, scan_freq="2412 2437",
|
wpas.connect(ssid, sae_password=passphrase, scan_freq="2412 2437",
|
||||||
key_mgmt="SAE-EXT-KEY", ieee80211w="2")
|
key_mgmt="SAE-EXT-KEY", ieee80211w="2")
|
||||||
|
@ -723,11 +736,11 @@ def test_eht_mld_gtk_rekey(dev, apdev):
|
||||||
mfp="1")
|
mfp="1")
|
||||||
params['wpa_group_rekey'] = '5'
|
params['wpa_group_rekey'] = '5'
|
||||||
|
|
||||||
hapd0 = eht_mld_enable_ap(hapd_iface, params)
|
hapd0 = eht_mld_enable_ap(hapd_iface, 0, params)
|
||||||
|
|
||||||
params['channel'] = '6'
|
params['channel'] = '6'
|
||||||
|
|
||||||
hapd1 = eht_mld_enable_ap(hapd_iface, params)
|
hapd1 = eht_mld_enable_ap(hapd_iface, 1, params)
|
||||||
|
|
||||||
wpas.connect(ssid, sae_password=passphrase, scan_freq="2412 2437",
|
wpas.connect(ssid, sae_password=passphrase, scan_freq="2412 2437",
|
||||||
key_mgmt="SAE-EXT-KEY", ieee80211w="2")
|
key_mgmt="SAE-EXT-KEY", ieee80211w="2")
|
||||||
|
@ -745,10 +758,9 @@ def test_eht_mld_gtk_rekey(dev, apdev):
|
||||||
if "CTRL-EVENT-DISCONNECTED" in ev:
|
if "CTRL-EVENT-DISCONNECTED" in ev:
|
||||||
raise Exception("Disconnect instead of rekey")
|
raise Exception("Disconnect instead of rekey")
|
||||||
|
|
||||||
#TODO: Uncomment these ones GTK rekeying works for MLO
|
time.sleep(0.1)
|
||||||
#time.sleep(0.1)
|
traffic_test(wpas, hapd0)
|
||||||
#traffic_test(wpas, hapd0)
|
traffic_test(wpas, hapd1)
|
||||||
#traffic_test(wpas, hapd1)
|
|
||||||
|
|
||||||
def test_eht_ml_probe_req(dev, apdev):
|
def test_eht_ml_probe_req(dev, apdev):
|
||||||
"""AP MLD with two links and non-AP MLD sending ML Probe Request"""
|
"""AP MLD with two links and non-AP MLD sending ML Probe Request"""
|
||||||
|
@ -763,11 +775,11 @@ def test_eht_ml_probe_req(dev, apdev):
|
||||||
params = eht_mld_ap_wpa2_params(ssid, passphrase,
|
params = eht_mld_ap_wpa2_params(ssid, passphrase,
|
||||||
key_mgmt="SAE-EXT-KEY")
|
key_mgmt="SAE-EXT-KEY")
|
||||||
|
|
||||||
hapd0 = eht_mld_enable_ap(hapd_iface, params)
|
hapd0 = eht_mld_enable_ap(hapd_iface, 0, params)
|
||||||
|
|
||||||
params['channel'] = '6'
|
params['channel'] = '6'
|
||||||
|
|
||||||
hapd1 = eht_mld_enable_ap(hapd_iface, params)
|
hapd1 = eht_mld_enable_ap(hapd_iface, 1, params)
|
||||||
|
|
||||||
bssid = hapd0.own_addr()
|
bssid = hapd0.own_addr()
|
||||||
wpas.scan_for_bss(bssid, freq=2412)
|
wpas.scan_for_bss(bssid, freq=2412)
|
||||||
|
@ -804,11 +816,11 @@ def test_eht_mld_connect_probes(dev, apdev, params):
|
||||||
key_mgmt="SAE", pwe='2')
|
key_mgmt="SAE", pwe='2')
|
||||||
link_params['channel'] = '1'
|
link_params['channel'] = '1'
|
||||||
link_params['bssid'] = '00:11:22:33:44:01'
|
link_params['bssid'] = '00:11:22:33:44:01'
|
||||||
hapd0 = eht_mld_enable_ap(hapd_iface, link_params)
|
hapd0 = eht_mld_enable_ap(hapd_iface, 0, link_params)
|
||||||
|
|
||||||
link_params['channel'] = '6'
|
link_params['channel'] = '6'
|
||||||
link_params['bssid'] = '00:11:22:33:44:02'
|
link_params['bssid'] = '00:11:22:33:44:02'
|
||||||
hapd1 = eht_mld_enable_ap(hapd_iface, link_params)
|
hapd1 = eht_mld_enable_ap(hapd_iface, 1, link_params)
|
||||||
|
|
||||||
wpas.set("sae_pwe", "1")
|
wpas.set("sae_pwe", "1")
|
||||||
wpas.connect(ssid, sae_password= passphrase, ieee80211w="2",
|
wpas.connect(ssid, sae_password= passphrase, ieee80211w="2",
|
||||||
|
@ -849,11 +861,11 @@ def test_eht_tx_link_rejected_connect_other(dev, apdev, params):
|
||||||
key_mgmt="SAE", pwe='2')
|
key_mgmt="SAE", pwe='2')
|
||||||
link_params['channel'] = '1'
|
link_params['channel'] = '1'
|
||||||
link_params['bssid'] = '00:11:22:33:44:01'
|
link_params['bssid'] = '00:11:22:33:44:01'
|
||||||
hapd0 = eht_mld_enable_ap(hapd_iface, link_params)
|
hapd0 = eht_mld_enable_ap(hapd_iface, 0, link_params)
|
||||||
|
|
||||||
link_params['channel'] = '6'
|
link_params['channel'] = '6'
|
||||||
link_params['bssid'] = '00:11:22:33:44:02'
|
link_params['bssid'] = '00:11:22:33:44:02'
|
||||||
hapd1 = eht_mld_enable_ap(hapd_iface, link_params)
|
hapd1 = eht_mld_enable_ap(hapd_iface, 1, link_params)
|
||||||
|
|
||||||
wpas.set("sae_pwe", "1")
|
wpas.set("sae_pwe", "1")
|
||||||
with fail_test(hapd0, 1, "hostapd_get_aid"):
|
with fail_test(hapd0, 1, "hostapd_get_aid"):
|
||||||
|
@ -879,11 +891,11 @@ def test_eht_all_links_rejected(dev, apdev, params):
|
||||||
key_mgmt="SAE", pwe='2')
|
key_mgmt="SAE", pwe='2')
|
||||||
link_params['channel'] = '1'
|
link_params['channel'] = '1'
|
||||||
link_params['bssid'] = '00:11:22:33:44:01'
|
link_params['bssid'] = '00:11:22:33:44:01'
|
||||||
hapd0 = eht_mld_enable_ap(hapd_iface, link_params)
|
hapd0 = eht_mld_enable_ap(hapd_iface, 0, link_params)
|
||||||
|
|
||||||
link_params['channel'] = '6'
|
link_params['channel'] = '6'
|
||||||
link_params['bssid'] = '00:11:22:33:44:02'
|
link_params['bssid'] = '00:11:22:33:44:02'
|
||||||
hapd1 = eht_mld_enable_ap(hapd_iface, link_params)
|
hapd1 = eht_mld_enable_ap(hapd_iface, 1, link_params)
|
||||||
wpas.set("mld_connect_bssid_pref", "00:11:22:33:44:01")
|
wpas.set("mld_connect_bssid_pref", "00:11:22:33:44:01")
|
||||||
wpas.set("sae_pwe", "1")
|
wpas.set("sae_pwe", "1")
|
||||||
|
|
||||||
|
@ -922,11 +934,11 @@ def test_eht_connect_invalid_link(dev, apdev, params):
|
||||||
key_mgmt="SAE", pwe='2')
|
key_mgmt="SAE", pwe='2')
|
||||||
link_params['channel'] = '1'
|
link_params['channel'] = '1'
|
||||||
link_params['bssid'] = '00:11:22:33:44:01'
|
link_params['bssid'] = '00:11:22:33:44:01'
|
||||||
hapd0 = eht_mld_enable_ap(hapd_iface, link_params)
|
hapd0 = eht_mld_enable_ap(hapd_iface, 0, link_params)
|
||||||
|
|
||||||
link_params['channel'] = '6'
|
link_params['channel'] = '6'
|
||||||
link_params['bssid'] = '00:11:22:33:44:02'
|
link_params['bssid'] = '00:11:22:33:44:02'
|
||||||
hapd1 = eht_mld_enable_ap(hapd_iface, link_params)
|
hapd1 = eht_mld_enable_ap(hapd_iface, 1, link_params)
|
||||||
|
|
||||||
# We scan for both APs, then try to connect to link 0, but only the
|
# We scan for both APs, then try to connect to link 0, but only the
|
||||||
# second attempt will work if mac80211 rejects the second link.
|
# second attempt will work if mac80211 rejects the second link.
|
||||||
|
@ -957,10 +969,10 @@ def test_eht_mld_link_removal(dev, apdev):
|
||||||
|
|
||||||
ssid = "mld_ap_owe_two_link"
|
ssid = "mld_ap_owe_two_link"
|
||||||
params = eht_mld_ap_wpa2_params(ssid, key_mgmt="OWE", mfp="2")
|
params = eht_mld_ap_wpa2_params(ssid, key_mgmt="OWE", mfp="2")
|
||||||
hapd0 = eht_mld_enable_ap(hapd0_iface, params)
|
hapd0 = eht_mld_enable_ap(hapd0_iface, 0, params)
|
||||||
|
|
||||||
params['channel'] = '6'
|
params['channel'] = '6'
|
||||||
hapd1 = eht_mld_enable_ap(hapd0_iface, params)
|
hapd1 = eht_mld_enable_ap(hapd0_iface, 1, params)
|
||||||
|
|
||||||
wpas.connect(ssid, scan_freq="2412 2437", key_mgmt="OWE",
|
wpas.connect(ssid, scan_freq="2412 2437", key_mgmt="OWE",
|
||||||
ieee80211w="2")
|
ieee80211w="2")
|
||||||
|
@ -1010,11 +1022,11 @@ def test_eht_mld_bss_trans_mgmt_link_removal_imminent(dev, apdev):
|
||||||
params["bss_transition"] = "1"
|
params["bss_transition"] = "1"
|
||||||
params["mbo"] = "1"
|
params["mbo"] = "1"
|
||||||
|
|
||||||
hapd0 = eht_mld_enable_ap(hapd0_iface, params)
|
hapd0 = eht_mld_enable_ap(hapd0_iface, 0, params)
|
||||||
|
|
||||||
params['channel'] = '6'
|
params['channel'] = '6'
|
||||||
|
|
||||||
hapd1 = eht_mld_enable_ap(hapd0_iface, params)
|
hapd1 = eht_mld_enable_ap(hapd0_iface, 1, params)
|
||||||
|
|
||||||
wpas.connect(ssid, scan_freq="2412 2437", key_mgmt="OWE",
|
wpas.connect(ssid, scan_freq="2412 2437", key_mgmt="OWE",
|
||||||
ieee80211w="2")
|
ieee80211w="2")
|
||||||
|
@ -1062,11 +1074,11 @@ def test_eht_ap_mld_proto(dev, apdev):
|
||||||
ssid = "mld_ap_owe_two_link"
|
ssid = "mld_ap_owe_two_link"
|
||||||
params = eht_mld_ap_wpa2_params(ssid, key_mgmt="OWE", mfp="2")
|
params = eht_mld_ap_wpa2_params(ssid, key_mgmt="OWE", mfp="2")
|
||||||
|
|
||||||
hapd0 = eht_mld_enable_ap(hapd0_iface, params)
|
hapd0 = eht_mld_enable_ap(hapd0_iface, 0, params)
|
||||||
|
|
||||||
params['channel'] = '6'
|
params['channel'] = '6'
|
||||||
|
|
||||||
hapd1 = eht_mld_enable_ap(hapd0_iface, params)
|
hapd1 = eht_mld_enable_ap(hapd0_iface, 1, params)
|
||||||
|
|
||||||
ap_mld_addr = hapd0.get_status_field("mld_addr[0]").replace(':', '')
|
ap_mld_addr = hapd0.get_status_field("mld_addr[0]").replace(':', '')
|
||||||
bssid0 = hapd0.own_addr().replace(':', '')
|
bssid0 = hapd0.own_addr().replace(':', '')
|
||||||
|
@ -1351,6 +1363,7 @@ def _test_eht_6ghz(dev, apdev, channel, op_class, ccfs1):
|
||||||
raise Exception("STATUS did not indicate ieee80211be=1")
|
raise Exception("STATUS did not indicate ieee80211be=1")
|
||||||
|
|
||||||
dev[0].set("sae_pwe", "1")
|
dev[0].set("sae_pwe", "1")
|
||||||
|
dev[0].set("sae_groups", "")
|
||||||
|
|
||||||
freq = 5950 + channel * 5
|
freq = 5950 + channel * 5
|
||||||
bw = _6ghz_op_class_to_bw(op_class)
|
bw = _6ghz_op_class_to_bw(op_class)
|
||||||
|
@ -1449,11 +1462,11 @@ def test_eht_mld_gas(dev, apdev):
|
||||||
params['venue_group'] = "7"
|
params['venue_group'] = "7"
|
||||||
params['venue_type'] = "1"
|
params['venue_type'] = "1"
|
||||||
params['venue_name'] = "eng:Example venue"
|
params['venue_name'] = "eng:Example venue"
|
||||||
hapd0 = eht_mld_enable_ap(hapd0_iface, params)
|
hapd0 = eht_mld_enable_ap(hapd0_iface, 0, params)
|
||||||
bssid0 = hapd0.own_addr()
|
bssid0 = hapd0.own_addr()
|
||||||
|
|
||||||
params['channel'] = '6'
|
params['channel'] = '6'
|
||||||
hapd1 = eht_mld_enable_ap(hapd0_iface, params)
|
hapd1 = eht_mld_enable_ap(hapd0_iface, 1, params)
|
||||||
bssid1 = hapd1.own_addr()
|
bssid1 = hapd1.own_addr()
|
||||||
|
|
||||||
wpas.scan_for_bss(bssid0, freq="2412")
|
wpas.scan_for_bss(bssid0, freq="2412")
|
||||||
|
@ -1485,10 +1498,10 @@ def test_eht_mld_dpp_responder_while_assoc(dev, apdev):
|
||||||
|
|
||||||
ssid = "owe_two_link"
|
ssid = "owe_two_link"
|
||||||
params = eht_mld_ap_wpa2_params(ssid, key_mgmt="OWE", mfp="2")
|
params = eht_mld_ap_wpa2_params(ssid, key_mgmt="OWE", mfp="2")
|
||||||
hapd0 = eht_mld_enable_ap(hapd0_iface, params)
|
hapd0 = eht_mld_enable_ap(hapd0_iface, 0, params)
|
||||||
|
|
||||||
params['channel'] = '6'
|
params['channel'] = '6'
|
||||||
hapd1 = eht_mld_enable_ap(hapd0_iface, params)
|
hapd1 = eht_mld_enable_ap(hapd0_iface, 1, params)
|
||||||
|
|
||||||
wpas.connect(ssid, scan_freq="2412 2437", key_mgmt="OWE",
|
wpas.connect(ssid, scan_freq="2412 2437", key_mgmt="OWE",
|
||||||
ieee80211w="2")
|
ieee80211w="2")
|
||||||
|
@ -1513,10 +1526,10 @@ def _eht_mld_disconnect(dev, apdev, disassoc=True):
|
||||||
|
|
||||||
ssid = "mld_ap_owe_two_link"
|
ssid = "mld_ap_owe_two_link"
|
||||||
params = eht_mld_ap_wpa2_params(ssid, key_mgmt="OWE", mfp="2")
|
params = eht_mld_ap_wpa2_params(ssid, key_mgmt="OWE", mfp="2")
|
||||||
hapd0 = eht_mld_enable_ap(hapd0_iface, params)
|
hapd0 = eht_mld_enable_ap(hapd0_iface, 0, params)
|
||||||
|
|
||||||
params['channel'] = '6'
|
params['channel'] = '6'
|
||||||
hapd1 = eht_mld_enable_ap(hapd0_iface, params)
|
hapd1 = eht_mld_enable_ap(hapd0_iface, 1, params)
|
||||||
|
|
||||||
wpas.connect(ssid, scan_freq="2412 2437", key_mgmt="OWE",
|
wpas.connect(ssid, scan_freq="2412 2437", key_mgmt="OWE",
|
||||||
ieee80211w="2")
|
ieee80211w="2")
|
||||||
|
@ -1571,7 +1584,7 @@ def test_eht_mld_non_pref_chan(dev, apdev):
|
||||||
params["bss_transition"] = "1"
|
params["bss_transition"] = "1"
|
||||||
params["mbo"] = "1"
|
params["mbo"] = "1"
|
||||||
|
|
||||||
hapd0 = eht_mld_enable_ap(hapd0_iface, params)
|
hapd0 = eht_mld_enable_ap(hapd0_iface, 0, params)
|
||||||
|
|
||||||
if "OK" not in wpas.request("SET non_pref_chan 81:7:200:1 81:9:100:2"):
|
if "OK" not in wpas.request("SET non_pref_chan 81:7:200:1 81:9:100:2"):
|
||||||
raise Exception("Failed to set non-preferred channel list")
|
raise Exception("Failed to set non-preferred channel list")
|
||||||
|
@ -1659,7 +1672,7 @@ def test_eht_mld_rrm_beacon_req(dev, apdev):
|
||||||
params["mbo"] = "1"
|
params["mbo"] = "1"
|
||||||
params["rrm_beacon_report"] = "1"
|
params["rrm_beacon_report"] = "1"
|
||||||
|
|
||||||
hapd0 = eht_mld_enable_ap(hapd0_iface, params)
|
hapd0 = eht_mld_enable_ap(hapd0_iface, 0, params)
|
||||||
|
|
||||||
wpas.connect(ssid, scan_freq="2412", key_mgmt="OWE", ieee80211w="2",
|
wpas.connect(ssid, scan_freq="2412", key_mgmt="OWE", ieee80211w="2",
|
||||||
owe_only="1")
|
owe_only="1")
|
||||||
|
@ -1673,7 +1686,7 @@ def test_eht_mld_rrm_beacon_req(dev, apdev):
|
||||||
other_ssid = "other"
|
other_ssid = "other"
|
||||||
params = eht_mld_ap_wpa2_params(other_ssid, key_mgmt="OWE", mfp="2")
|
params = eht_mld_ap_wpa2_params(other_ssid, key_mgmt="OWE", mfp="2")
|
||||||
params["channel"] = '6'
|
params["channel"] = '6'
|
||||||
hapd1 = eht_mld_enable_ap(hapd1_iface, params)
|
hapd1 = eht_mld_enable_ap(hapd1_iface, 0, params)
|
||||||
|
|
||||||
# Issue a beacon request for the second AP
|
# Issue a beacon request for the second AP
|
||||||
addr = wpas.own_addr()
|
addr = wpas.own_addr()
|
||||||
|
@ -1712,7 +1725,7 @@ def test_eht_mld_legacy_stas(dev, apdev):
|
||||||
mfp="2", pwe='2')
|
mfp="2", pwe='2')
|
||||||
params['rsn_pairwise'] = "CCMP GCMP-256"
|
params['rsn_pairwise'] = "CCMP GCMP-256"
|
||||||
params['sae_groups'] = "19 20"
|
params['sae_groups'] = "19 20"
|
||||||
hapd0 = eht_mld_enable_ap(hapd_iface, params)
|
hapd0 = eht_mld_enable_ap(hapd_iface, 0, params)
|
||||||
|
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
dev[i].set("sae_groups", "")
|
dev[i].set("sae_groups", "")
|
||||||
|
@ -1751,7 +1764,7 @@ def test_eht_mld_and_mlds(dev, apdev):
|
||||||
mfp="2", pwe='2')
|
mfp="2", pwe='2')
|
||||||
params['rsn_pairwise'] = "CCMP GCMP-256"
|
params['rsn_pairwise'] = "CCMP GCMP-256"
|
||||||
params['sae_groups'] = "19 20"
|
params['sae_groups'] = "19 20"
|
||||||
hapd0 = eht_mld_enable_ap(hapd_iface, params)
|
hapd0 = eht_mld_enable_ap(hapd_iface, 0, params)
|
||||||
|
|
||||||
wpas.set("sae_pwe", "1")
|
wpas.set("sae_pwe", "1")
|
||||||
wpas.connect(ssid, sae_password=password, scan_freq="2412",
|
wpas.connect(ssid, sae_password=password, scan_freq="2412",
|
||||||
|
@ -1816,10 +1829,10 @@ def test_eht_mlo_csa(dev, apdev):
|
||||||
|
|
||||||
params = eht_mld_ap_wpa2_params(ssid, passphrase,
|
params = eht_mld_ap_wpa2_params(ssid, passphrase,
|
||||||
key_mgmt="SAE", mfp="2", pwe='1')
|
key_mgmt="SAE", mfp="2", pwe='1')
|
||||||
hapd0 = eht_mld_enable_ap(hapd_iface, params)
|
hapd0 = eht_mld_enable_ap(hapd_iface, 0, params)
|
||||||
|
|
||||||
params['channel'] = '6'
|
params['channel'] = '6'
|
||||||
hapd1 = eht_mld_enable_ap(hapd_iface, params)
|
hapd1 = eht_mld_enable_ap(hapd_iface, 1, params)
|
||||||
|
|
||||||
wpas.set("sae_pwe", "1")
|
wpas.set("sae_pwe", "1")
|
||||||
wpas.connect(ssid, sae_password=passphrase, scan_freq="2412 2437",
|
wpas.connect(ssid, sae_password=passphrase, scan_freq="2412 2437",
|
||||||
|
@ -1837,6 +1850,21 @@ def test_eht_mlo_csa(dev, apdev):
|
||||||
logger.info("Test traffic after 1st link CSA completes")
|
logger.info("Test traffic after 1st link CSA completes")
|
||||||
traffic_test(wpas, hapd0)
|
traffic_test(wpas, hapd0)
|
||||||
|
|
||||||
|
logger.info("Perform CSA on 2nd link")
|
||||||
|
mlo_perform_csa(hapd1, "CHAN_SWITCH 5 2412 ht he eht blocktx",
|
||||||
|
2412, wpas)
|
||||||
|
|
||||||
|
|
||||||
|
logger.info("Test traffic after 2nd link CSA completes")
|
||||||
|
traffic_test(wpas, hapd1)
|
||||||
|
|
||||||
|
logger.info("Perform CSA on 2nd link and bring it back to original channel")
|
||||||
|
mlo_perform_csa(hapd1, "CHAN_SWITCH 5 2437 ht he eht blocktx",
|
||||||
|
2437, wpas)
|
||||||
|
|
||||||
|
logger.info("Test traffic again after 2nd link CSA completes")
|
||||||
|
traffic_test(wpas, hapd1)
|
||||||
|
|
||||||
logger.info("Perform CSA on 1st link and bring it back to original channel")
|
logger.info("Perform CSA on 1st link and bring it back to original channel")
|
||||||
mlo_perform_csa(hapd0, "CHAN_SWITCH 5 2412 ht he eht blocktx",
|
mlo_perform_csa(hapd0, "CHAN_SWITCH 5 2412 ht he eht blocktx",
|
||||||
2412, wpas)
|
2412, wpas)
|
||||||
|
@ -1844,8 +1872,6 @@ def test_eht_mlo_csa(dev, apdev):
|
||||||
logger.info("Test traffic again after 1st link CSA completes")
|
logger.info("Test traffic again after 1st link CSA completes")
|
||||||
traffic_test(wpas, hapd0)
|
traffic_test(wpas, hapd0)
|
||||||
|
|
||||||
#TODO: CSA on non-first link
|
|
||||||
|
|
||||||
def create_base_conf_file(iface, channel, prefix='hostapd-', hw_mode='g',
|
def create_base_conf_file(iface, channel, prefix='hostapd-', hw_mode='g',
|
||||||
op_class=None):
|
op_class=None):
|
||||||
# Create configuration file and add phy characteristics
|
# Create configuration file and add phy characteristics
|
||||||
|
@ -1903,7 +1929,7 @@ def get_config(iface, count, ssid, passphrase, channel, bssid_regex,
|
||||||
params['sae_pwe'] = "2"
|
params['sae_pwe'] = "2"
|
||||||
params['group_mgmt_cipher'] = "AES-128-CMAC"
|
params['group_mgmt_cipher'] = "AES-128-CMAC"
|
||||||
params['beacon_prot'] = "1"
|
params['beacon_prot'] = "1"
|
||||||
params["ctrl_interface"] = "/var/run/hostapd/chan_" + str(channel)
|
params["ctrl_interface"] = "/var/run/hostapd/"
|
||||||
params["bssid"] = bssid_regex % (i + 1)
|
params["bssid"] = bssid_regex % (i + 1)
|
||||||
|
|
||||||
if rnr:
|
if rnr:
|
||||||
|
@ -1911,7 +1937,7 @@ def get_config(iface, count, ssid, passphrase, channel, bssid_regex,
|
||||||
|
|
||||||
append_bss_conf_to_file(f, ifname, params, first=(i == 0))
|
append_bss_conf_to_file(f, ifname, params, first=(i == 0))
|
||||||
|
|
||||||
hapds.append([ifname, params["ctrl_interface"], i])
|
hapds.append([ifname, i])
|
||||||
|
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
|
@ -1956,15 +1982,15 @@ def get_mld_devs(hapd_iface, count, prefix, rnr=False):
|
||||||
|
|
||||||
start_ap(prefix, fname1 + " " + fname2)
|
start_ap(prefix, fname1 + " " + fname2)
|
||||||
|
|
||||||
hapd_mld1_link0 = hostapd.Hostapd(ifname=hapds1[0][0], ctrl=hapds1[0][1],
|
hapd_mld1_link0 = hostapd.Hostapd(ifname=hapds1[0][0], bssidx=hapds1[0][1],
|
||||||
bssidx=hapds1[0][2])
|
link=0)
|
||||||
hapd_mld1_link1 = hostapd.Hostapd(ifname=hapds2[0][0], ctrl=hapds2[0][1],
|
hapd_mld1_link1 = hostapd.Hostapd(ifname=hapds2[0][0], bssidx=hapds2[0][1],
|
||||||
bssidx=hapds2[0][2])
|
link=1)
|
||||||
|
|
||||||
hapd_mld2_link0 = hostapd.Hostapd(ifname=hapds1[1][0], ctrl=hapds1[1][1],
|
hapd_mld2_link0 = hostapd.Hostapd(ifname=hapds1[1][0], bssidx=hapds1[1][1],
|
||||||
bssidx=hapds1[1][2])
|
link=0)
|
||||||
hapd_mld2_link1 = hostapd.Hostapd(ifname=hapds2[1][0], ctrl=hapds2[1][1],
|
hapd_mld2_link1 = hostapd.Hostapd(ifname=hapds2[1][0], bssidx=hapds2[1][1],
|
||||||
bssidx=hapds2[1][2])
|
link=1)
|
||||||
|
|
||||||
if not hapd_mld1_link0.ping():
|
if not hapd_mld1_link0.ping():
|
||||||
raise Exception("Could not ping hostapd")
|
raise Exception("Could not ping hostapd")
|
||||||
|
@ -2144,12 +2170,12 @@ def test_eht_mlo_color_change(dev, apdev):
|
||||||
key_mgmt="SAE", mfp="2", pwe='1')
|
key_mgmt="SAE", mfp="2", pwe='1')
|
||||||
params['he_bss_color'] = '42'
|
params['he_bss_color'] = '42'
|
||||||
|
|
||||||
hapd0 = eht_mld_enable_ap(hapd_iface, params)
|
hapd0 = eht_mld_enable_ap(hapd_iface, 0, params)
|
||||||
|
|
||||||
params['channel'] = '6'
|
params['channel'] = '6'
|
||||||
params['he_bss_color'] = '24'
|
params['he_bss_color'] = '24'
|
||||||
|
|
||||||
hapd1 = eht_mld_enable_ap(hapd_iface, params)
|
hapd1 = eht_mld_enable_ap(hapd_iface, 1, params)
|
||||||
|
|
||||||
logger.info("Perform CCA on 1st link")
|
logger.info("Perform CCA on 1st link")
|
||||||
if "OK" not in hapd0.request("COLOR_CHANGE 10"):
|
if "OK" not in hapd0.request("COLOR_CHANGE 10"):
|
||||||
|
@ -2190,3 +2216,36 @@ def test_eht_mlo_color_change(dev, apdev):
|
||||||
|
|
||||||
hapd0.dump_monitor()
|
hapd0.dump_monitor()
|
||||||
hapd1.dump_monitor()
|
hapd1.dump_monitor()
|
||||||
|
|
||||||
|
def test_eht_mld_control_socket_connectivity(dev, apdev):
|
||||||
|
"""AP MLD control socket connectivity"""
|
||||||
|
with HWSimRadio(use_mlo=True) as (hapd_radio, hapd_iface), \
|
||||||
|
HWSimRadio(use_mlo=True) as (wpas_radio, wpas_iface):
|
||||||
|
|
||||||
|
ssid = "mld_ap"
|
||||||
|
link0_params = {"ssid": ssid,
|
||||||
|
"hw_mode": "g",
|
||||||
|
"channel": "1"}
|
||||||
|
link1_params = {"ssid": ssid,
|
||||||
|
"hw_mode": "g",
|
||||||
|
"channel": "2"}
|
||||||
|
|
||||||
|
hapd0 = eht_mld_enable_ap(hapd_iface, 0, link0_params)
|
||||||
|
hapd1 = eht_mld_enable_ap(hapd_iface, 1, link1_params)
|
||||||
|
|
||||||
|
mld_dev = mld.get_mld_obj(hapd_iface)
|
||||||
|
|
||||||
|
# Check status of each link
|
||||||
|
res = str(mld_dev.request("LINKID 0 STATUS"))
|
||||||
|
logger.info("LINK 0 STATUS:\n" + res)
|
||||||
|
if "state" not in res:
|
||||||
|
raise Exception("Failed to get link 0 status via MLD socket")
|
||||||
|
if 'link_id=0' not in res.splitlines():
|
||||||
|
raise Exception("link_id=0 not reported for link 0")
|
||||||
|
|
||||||
|
res = mld_dev.request("LINKID 1 STATUS")
|
||||||
|
logger.info("LINK 1 STATUS:\n" + res)
|
||||||
|
if "state" not in res:
|
||||||
|
raise Exception("Failed to get link 1 status via MLD socket")
|
||||||
|
if 'link_id=1' not in res.splitlines():
|
||||||
|
raise Exception("link_id=0 not reported for link 1")
|
||||||
|
|
|
@ -36,7 +36,7 @@ def test_fils_sk_full_auth(dev, apdev, params):
|
||||||
params['erp_domain'] = 'example.com'
|
params['erp_domain'] = 'example.com'
|
||||||
params['fils_realm'] = 'example.com'
|
params['fils_realm'] = 'example.com'
|
||||||
params['wpa_group_rekey'] = '1'
|
params['wpa_group_rekey'] = '1'
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].flush_scan_cache()
|
dev[0].flush_scan_cache()
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
|
@ -86,7 +86,7 @@ def test_fils_sk_sha384_full_auth(dev, apdev, params):
|
||||||
params['erp_domain'] = 'example.com'
|
params['erp_domain'] = 'example.com'
|
||||||
params['fils_realm'] = 'example.com'
|
params['fils_realm'] = 'example.com'
|
||||||
params['wpa_group_rekey'] = '1'
|
params['wpa_group_rekey'] = '1'
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].flush_scan_cache()
|
dev[0].flush_scan_cache()
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
|
@ -134,7 +134,7 @@ def test_fils_sk_pmksa_caching(dev, apdev, params):
|
||||||
params['auth_server_port'] = "18128"
|
params['auth_server_port'] = "18128"
|
||||||
params['erp_domain'] = 'example.com'
|
params['erp_domain'] = 'example.com'
|
||||||
params['fils_realm'] = 'example.com'
|
params['fils_realm'] = 'example.com'
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].request("ERP_FLUSH")
|
dev[0].request("ERP_FLUSH")
|
||||||
|
@ -202,7 +202,7 @@ def test_fils_sk_pmksa_caching_ocv(dev, apdev, params):
|
||||||
params['ieee80211w'] = '1'
|
params['ieee80211w'] = '1'
|
||||||
params['ocv'] = '1'
|
params['ocv'] = '1'
|
||||||
try:
|
try:
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if "Failed to set hostapd parameter ocv" in str(e):
|
if "Failed to set hostapd parameter ocv" in str(e):
|
||||||
raise HwsimSkip("OCV not supported")
|
raise HwsimSkip("OCV not supported")
|
||||||
|
@ -279,7 +279,7 @@ def test_fils_sk_pmksa_caching_and_cache_id(dev, apdev):
|
||||||
params["eap_fast_a_id_info"] = "test server"
|
params["eap_fast_a_id_info"] = "test server"
|
||||||
params["eap_server_erp"] = "1"
|
params["eap_server_erp"] = "1"
|
||||||
params["erp_domain"] = "example.com"
|
params["erp_domain"] = "example.com"
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].request("ERP_FLUSH")
|
dev[0].request("ERP_FLUSH")
|
||||||
|
@ -305,7 +305,7 @@ def test_fils_sk_pmksa_caching_and_cache_id(dev, apdev):
|
||||||
params['erp_domain'] = 'example.com'
|
params['erp_domain'] = 'example.com'
|
||||||
params['fils_realm'] = 'example.com'
|
params['fils_realm'] = 'example.com'
|
||||||
params['fils_cache_id'] = "abcd"
|
params['fils_cache_id'] = "abcd"
|
||||||
hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
|
hapd2 = hostapd.add_ap(apdev[1], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid2, freq=2412)
|
dev[0].scan_for_bss(bssid2, freq=2412)
|
||||||
|
|
||||||
|
@ -348,7 +348,7 @@ def test_fils_sk_pmksa_caching_ctrl_ext(dev, apdev, params):
|
||||||
params['erp_domain'] = 'example.com'
|
params['erp_domain'] = 'example.com'
|
||||||
params['fils_realm'] = 'example.com'
|
params['fils_realm'] = 'example.com'
|
||||||
params['fils_cache_id'] = "ffee"
|
params['fils_cache_id'] = "ffee"
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].request("ERP_FLUSH")
|
dev[0].request("ERP_FLUSH")
|
||||||
|
@ -386,7 +386,7 @@ def test_fils_sk_pmksa_caching_ctrl_ext(dev, apdev, params):
|
||||||
params['erp_domain'] = 'example.com'
|
params['erp_domain'] = 'example.com'
|
||||||
params['fils_realm'] = 'example.com'
|
params['fils_realm'] = 'example.com'
|
||||||
params['fils_cache_id'] = "ffee"
|
params['fils_cache_id'] = "ffee"
|
||||||
hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
|
hapd2 = hostapd.add_ap(apdev[1], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid2, freq=2412)
|
dev[0].scan_for_bss(bssid2, freq=2412)
|
||||||
dev[0].set_network(id, "bssid", bssid2)
|
dev[0].set_network(id, "bssid", bssid2)
|
||||||
|
@ -417,7 +417,7 @@ def run_fils_sk_erp(dev, apdev, key_mgmt, params):
|
||||||
params['erp_domain'] = 'example.com'
|
params['erp_domain'] = 'example.com'
|
||||||
params['fils_realm'] = 'example.com'
|
params['fils_realm'] = 'example.com'
|
||||||
params['disable_pmksa_caching'] = '1'
|
params['disable_pmksa_caching'] = '1'
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].request("ERP_FLUSH")
|
dev[0].request("ERP_FLUSH")
|
||||||
|
@ -458,7 +458,7 @@ def test_fils_sk_erp_followed_by_pmksa_caching(dev, apdev, params):
|
||||||
params['auth_server_port'] = "18128"
|
params['auth_server_port'] = "18128"
|
||||||
params['erp_domain'] = 'example.com'
|
params['erp_domain'] = 'example.com'
|
||||||
params['fils_realm'] = 'example.com'
|
params['fils_realm'] = 'example.com'
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].request("ERP_FLUSH")
|
dev[0].request("ERP_FLUSH")
|
||||||
|
@ -533,7 +533,7 @@ def test_fils_sk_erp_another_ssid(dev, apdev, params):
|
||||||
params['erp_domain'] = 'example.com'
|
params['erp_domain'] = 'example.com'
|
||||||
params['fils_realm'] = 'example.com'
|
params['fils_realm'] = 'example.com'
|
||||||
params['disable_pmksa_caching'] = '1'
|
params['disable_pmksa_caching'] = '1'
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].request("ERP_FLUSH")
|
dev[0].request("ERP_FLUSH")
|
||||||
|
@ -557,7 +557,7 @@ def test_fils_sk_erp_another_ssid(dev, apdev, params):
|
||||||
params['erp_domain'] = 'example.com'
|
params['erp_domain'] = 'example.com'
|
||||||
params['fils_realm'] = 'example.com'
|
params['fils_realm'] = 'example.com'
|
||||||
params['disable_pmksa_caching'] = '1'
|
params['disable_pmksa_caching'] = '1'
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].dump_monitor()
|
dev[0].dump_monitor()
|
||||||
|
@ -600,7 +600,7 @@ def test_fils_sk_multiple_realms(dev, apdev, params):
|
||||||
params['fils_realm'] = fils_realms
|
params['fils_realm'] = fils_realms
|
||||||
params['fils_cache_id'] = "1234"
|
params['fils_cache_id'] = "1234"
|
||||||
params['hessid'] = bssid
|
params['hessid'] = bssid
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].flush_scan_cache()
|
dev[0].flush_scan_cache()
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
|
@ -785,7 +785,7 @@ def run_fils_sk_hlp(dev, apdev, rapid_commit_server, params):
|
||||||
params['fils_hlp_wait_time'] = '10000'
|
params['fils_hlp_wait_time'] = '10000'
|
||||||
if not rapid_commit_server:
|
if not rapid_commit_server:
|
||||||
params['dhcp_rapid_commit_proxy'] = '1'
|
params['dhcp_rapid_commit_proxy'] = '1'
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].request("ERP_FLUSH")
|
dev[0].request("ERP_FLUSH")
|
||||||
|
@ -890,7 +890,7 @@ def test_fils_sk_hlp_timeout(dev, apdev, params):
|
||||||
|
|
||||||
bssid = apdev[0]['bssid']
|
bssid = apdev[0]['bssid']
|
||||||
params = fils_hlp_config(fils_hlp_wait_time=30)
|
params = fils_hlp_config(fils_hlp_wait_time=30)
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].request("ERP_FLUSH")
|
dev[0].request("ERP_FLUSH")
|
||||||
|
@ -937,7 +937,7 @@ def test_fils_sk_hlp_oom(dev, apdev, params):
|
||||||
bssid = apdev[0]['bssid']
|
bssid = apdev[0]['bssid']
|
||||||
params = fils_hlp_config(fils_hlp_wait_time=500)
|
params = fils_hlp_config(fils_hlp_wait_time=500)
|
||||||
params['dhcp_rapid_commit_proxy'] = '1'
|
params['dhcp_rapid_commit_proxy'] = '1'
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].request("ERP_FLUSH")
|
dev[0].request("ERP_FLUSH")
|
||||||
|
@ -1037,7 +1037,7 @@ def test_fils_sk_hlp_req_parsing(dev, apdev, params):
|
||||||
|
|
||||||
bssid = apdev[0]['bssid']
|
bssid = apdev[0]['bssid']
|
||||||
params = fils_hlp_config(fils_hlp_wait_time=30)
|
params = fils_hlp_config(fils_hlp_wait_time=30)
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].request("ERP_FLUSH")
|
dev[0].request("ERP_FLUSH")
|
||||||
|
@ -1212,7 +1212,7 @@ def test_fils_sk_hlp_dhcp_parsing(dev, apdev, params):
|
||||||
bssid = apdev[0]['bssid']
|
bssid = apdev[0]['bssid']
|
||||||
params = fils_hlp_config(fils_hlp_wait_time=30)
|
params = fils_hlp_config(fils_hlp_wait_time=30)
|
||||||
params['dhcp_rapid_commit_proxy'] = '1'
|
params['dhcp_rapid_commit_proxy'] = '1'
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].request("ERP_FLUSH")
|
dev[0].request("ERP_FLUSH")
|
||||||
|
@ -1374,7 +1374,7 @@ def test_fils_sk_erp_and_reauth(dev, apdev, params):
|
||||||
params['fils_realm'] = 'example.com'
|
params['fils_realm'] = 'example.com'
|
||||||
params['disable_pmksa_caching'] = '1'
|
params['disable_pmksa_caching'] = '1'
|
||||||
params['broadcast_deauth'] = '0'
|
params['broadcast_deauth'] = '0'
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].request("ERP_FLUSH")
|
dev[0].request("ERP_FLUSH")
|
||||||
|
@ -1413,7 +1413,7 @@ def test_fils_sk_erp_sim(dev, apdev, params):
|
||||||
params['auth_server_port'] = "18128"
|
params['auth_server_port'] = "18128"
|
||||||
params['fils_realm'] = realm
|
params['fils_realm'] = realm
|
||||||
params['disable_pmksa_caching'] = '1'
|
params['disable_pmksa_caching'] = '1'
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].request("ERP_FLUSH")
|
dev[0].request("ERP_FLUSH")
|
||||||
|
@ -1499,7 +1499,7 @@ def run_fils_sk_pfs(dev, apdev, group, params):
|
||||||
params['fils_realm'] = 'example.com'
|
params['fils_realm'] = 'example.com'
|
||||||
params['disable_pmksa_caching'] = '1'
|
params['disable_pmksa_caching'] = '1'
|
||||||
params['fils_dh_group'] = group
|
params['fils_dh_group'] = group
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].request("ERP_FLUSH")
|
dev[0].request("ERP_FLUSH")
|
||||||
|
@ -1542,7 +1542,7 @@ def test_fils_sk_pfs_group_mismatch(dev, apdev, params):
|
||||||
params['fils_realm'] = 'example.com'
|
params['fils_realm'] = 'example.com'
|
||||||
params['disable_pmksa_caching'] = '1'
|
params['disable_pmksa_caching'] = '1'
|
||||||
params['fils_dh_group'] = "20"
|
params['fils_dh_group'] = "20"
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].request("ERP_FLUSH")
|
dev[0].request("ERP_FLUSH")
|
||||||
|
@ -1577,7 +1577,7 @@ def test_fils_sk_pfs_pmksa_caching(dev, apdev, params):
|
||||||
params['erp_domain'] = 'example.com'
|
params['erp_domain'] = 'example.com'
|
||||||
params['fils_realm'] = 'example.com'
|
params['fils_realm'] = 'example.com'
|
||||||
params['fils_dh_group'] = "19"
|
params['fils_dh_group'] = "19"
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].request("ERP_FLUSH")
|
dev[0].request("ERP_FLUSH")
|
||||||
|
@ -1694,7 +1694,7 @@ def test_fils_sk_auth_mismatch(dev, apdev, params):
|
||||||
params['erp_domain'] = 'example.com'
|
params['erp_domain'] = 'example.com'
|
||||||
params['fils_realm'] = 'example.com'
|
params['fils_realm'] = 'example.com'
|
||||||
params['disable_pmksa_caching'] = '1'
|
params['disable_pmksa_caching'] = '1'
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].request("ERP_FLUSH")
|
dev[0].request("ERP_FLUSH")
|
||||||
|
@ -1741,7 +1741,7 @@ def setup_fils_rekey(dev, apdev, params, wpa_ptk_rekey=0, wpa_group_rekey=0,
|
||||||
params['disable_pmksa_caching'] = '1'
|
params['disable_pmksa_caching'] = '1'
|
||||||
if ext_key_id:
|
if ext_key_id:
|
||||||
params['extended_key_id'] = '1'
|
params['extended_key_id'] = '1'
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].request("ERP_FLUSH")
|
dev[0].request("ERP_FLUSH")
|
||||||
|
@ -1823,7 +1823,7 @@ def test_fils_and_ft(dev, apdev, params):
|
||||||
params['erp_domain'] = 'example.com'
|
params['erp_domain'] = 'example.com'
|
||||||
params['fils_realm'] = 'example.com'
|
params['fils_realm'] = 'example.com'
|
||||||
params['disable_pmksa_caching'] = '1'
|
params['disable_pmksa_caching'] = '1'
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].request("ERP_FLUSH")
|
dev[0].request("ERP_FLUSH")
|
||||||
|
@ -1856,7 +1856,7 @@ def test_fils_and_ft(dev, apdev, params):
|
||||||
params['r0kh'] = ["02:00:00:00:04:00 nas2.w1.fi 300102030405060708090a0b0c0d0e0f"]
|
params['r0kh'] = ["02:00:00:00:04:00 nas2.w1.fi 300102030405060708090a0b0c0d0e0f"]
|
||||||
params['r1kh'] = "02:00:00:00:04:00 00:01:02:03:04:06 200102030405060708090a0b0c0d0e0f"
|
params['r1kh'] = "02:00:00:00:04:00 00:01:02:03:04:06 200102030405060708090a0b0c0d0e0f"
|
||||||
params['ieee80211w'] = "1"
|
params['ieee80211w'] = "1"
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].dump_monitor()
|
dev[0].dump_monitor()
|
||||||
|
@ -1893,7 +1893,7 @@ def test_fils_and_ft(dev, apdev, params):
|
||||||
params['r1_key_holder'] = "000102030406"
|
params['r1_key_holder'] = "000102030406"
|
||||||
params['r0kh'] = ["02:00:00:00:03:00 nas1.w1.fi 200102030405060708090a0b0c0d0e0f"]
|
params['r0kh'] = ["02:00:00:00:03:00 nas1.w1.fi 200102030405060708090a0b0c0d0e0f"]
|
||||||
params['r1kh'] = "02:00:00:00:03:00 00:01:02:03:04:05 300102030405060708090a0b0c0d0e0f"
|
params['r1kh'] = "02:00:00:00:03:00 00:01:02:03:04:05 300102030405060708090a0b0c0d0e0f"
|
||||||
hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
|
hapd2 = hostapd.add_ap(apdev[1], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412", force_scan=True)
|
dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412", force_scan=True)
|
||||||
# FIX: Cannot use FT-over-DS without the FTE MIC issue addressed
|
# FIX: Cannot use FT-over-DS without the FTE MIC issue addressed
|
||||||
|
@ -1984,7 +1984,7 @@ def run_fils_and_ft_setup(dev, apdev, params, key_mgmt):
|
||||||
params['fils_realm'] = 'example.com'
|
params['fils_realm'] = 'example.com'
|
||||||
params['disable_pmksa_caching'] = '1'
|
params['disable_pmksa_caching'] = '1'
|
||||||
params['ieee80211w'] = "2"
|
params['ieee80211w'] = "2"
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].request("ERP_FLUSH")
|
dev[0].request("ERP_FLUSH")
|
||||||
|
@ -2021,7 +2021,7 @@ def run_fils_and_ft_setup(dev, apdev, params, key_mgmt):
|
||||||
"02:00:00:00:04:00 nas2.w1.fi 300102030405060708090a0b0c0d0e0f"]
|
"02:00:00:00:04:00 nas2.w1.fi 300102030405060708090a0b0c0d0e0f"]
|
||||||
params['r1kh'] = "02:00:00:00:04:00 00:01:02:03:04:06 200102030405060708090a0b0c0d0e0f"
|
params['r1kh'] = "02:00:00:00:04:00 00:01:02:03:04:06 200102030405060708090a0b0c0d0e0f"
|
||||||
params['ieee80211w'] = "2"
|
params['ieee80211w'] = "2"
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].dump_monitor()
|
dev[0].dump_monitor()
|
||||||
|
@ -2052,7 +2052,7 @@ def run_fils_and_ft_setup(dev, apdev, params, key_mgmt):
|
||||||
params['r0kh'] = ["02:00:00:00:03:00 nas1.w1.fi 200102030405060708090a0b0c0d0e0f",
|
params['r0kh'] = ["02:00:00:00:03:00 nas1.w1.fi 200102030405060708090a0b0c0d0e0f",
|
||||||
"02:00:00:00:04:00 nas2.w1.fi 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"]
|
"02:00:00:00:04:00 nas2.w1.fi 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"]
|
||||||
params['r1kh'] = "02:00:00:00:03:00 00:01:02:03:04:05 300102030405060708090a0b0c0d0e0f"
|
params['r1kh'] = "02:00:00:00:03:00 00:01:02:03:04:05 300102030405060708090a0b0c0d0e0f"
|
||||||
hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
|
hapd2 = hostapd.add_ap(apdev[1], params)
|
||||||
|
|
||||||
return hapd, hapd2
|
return hapd, hapd2
|
||||||
|
|
||||||
|
@ -2070,7 +2070,7 @@ def test_fils_assoc_replay(dev, apdev, params):
|
||||||
params['auth_server_port'] = "18128"
|
params['auth_server_port'] = "18128"
|
||||||
params['erp_domain'] = 'example.com'
|
params['erp_domain'] = 'example.com'
|
||||||
params['fils_realm'] = 'example.com'
|
params['fils_realm'] = 'example.com'
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].request("ERP_FLUSH")
|
dev[0].request("ERP_FLUSH")
|
||||||
|
@ -2163,7 +2163,7 @@ def test_fils_sk_erp_server_flush(dev, apdev, params):
|
||||||
params['erp_domain'] = 'example.com'
|
params['erp_domain'] = 'example.com'
|
||||||
params['fils_realm'] = 'example.com'
|
params['fils_realm'] = 'example.com'
|
||||||
params['disable_pmksa_caching'] = '1'
|
params['disable_pmksa_caching'] = '1'
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].request("ERP_FLUSH")
|
dev[0].request("ERP_FLUSH")
|
||||||
|
@ -2260,7 +2260,7 @@ def run_fils_sk_erp_radius_ext(dev, apdev, params):
|
||||||
params['erp_domain'] = 'erp.example.com'
|
params['erp_domain'] = 'erp.example.com'
|
||||||
params['fils_realm'] = 'erp.example.com'
|
params['fils_realm'] = 'erp.example.com'
|
||||||
params['disable_pmksa_caching'] = '1'
|
params['disable_pmksa_caching'] = '1'
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].request("ERP_FLUSH")
|
dev[0].request("ERP_FLUSH")
|
||||||
|
@ -2313,7 +2313,7 @@ def run_fils_sk_erp_radius_roam(dev, apdev):
|
||||||
params['erp_domain'] = 'example.com'
|
params['erp_domain'] = 'example.com'
|
||||||
params['fils_realm'] = 'example.com'
|
params['fils_realm'] = 'example.com'
|
||||||
params['disable_pmksa_caching'] = '1'
|
params['disable_pmksa_caching'] = '1'
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].request("ERP_FLUSH")
|
dev[0].request("ERP_FLUSH")
|
||||||
|
@ -2329,7 +2329,7 @@ def run_fils_sk_erp_radius_roam(dev, apdev):
|
||||||
params['erp_domain'] = 'example.com'
|
params['erp_domain'] = 'example.com'
|
||||||
params['fils_realm'] = 'example.com'
|
params['fils_realm'] = 'example.com'
|
||||||
params['disable_pmksa_caching'] = '1'
|
params['disable_pmksa_caching'] = '1'
|
||||||
hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
|
hapd2 = hostapd.add_ap(apdev[1], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid2, freq=2412)
|
dev[0].scan_for_bss(bssid2, freq=2412)
|
||||||
|
|
||||||
|
@ -2362,7 +2362,7 @@ def test_fils_sk_erp_roam_diff_akm(dev, apdev, params):
|
||||||
params['auth_server_port'] = "18128"
|
params['auth_server_port'] = "18128"
|
||||||
params['erp_domain'] = 'example.com'
|
params['erp_domain'] = 'example.com'
|
||||||
params['fils_realm'] = 'example.com'
|
params['fils_realm'] = 'example.com'
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].request("ERP_FLUSH")
|
dev[0].request("ERP_FLUSH")
|
||||||
|
@ -2389,7 +2389,7 @@ def test_fils_sk_erp_roam_diff_akm(dev, apdev, params):
|
||||||
params['auth_server_port'] = "18128"
|
params['auth_server_port'] = "18128"
|
||||||
params['erp_domain'] = 'example.com'
|
params['erp_domain'] = 'example.com'
|
||||||
params['fils_realm'] = 'example.com'
|
params['fils_realm'] = 'example.com'
|
||||||
hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
|
hapd2 = hostapd.add_ap(apdev[1], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid2, freq=2412)
|
dev[0].scan_for_bss(bssid2, freq=2412)
|
||||||
|
|
||||||
|
@ -2452,7 +2452,7 @@ def test_fils_discovery_frame(dev, apdev, params):
|
||||||
params['wpa_group_rekey'] = '1'
|
params['wpa_group_rekey'] = '1'
|
||||||
params['fils_discovery_min_interval'] = '20'
|
params['fils_discovery_min_interval'] = '20'
|
||||||
params['fils_discovery_max_interval'] = '20'
|
params['fils_discovery_max_interval'] = '20'
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params, no_enable=True)
|
hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
|
||||||
|
|
||||||
if "OK" not in hapd.request("ENABLE"):
|
if "OK" not in hapd.request("ENABLE"):
|
||||||
raise HwsimSkip("FILS Discovery frame transmission not supported")
|
raise HwsimSkip("FILS Discovery frame transmission not supported")
|
||||||
|
@ -2493,7 +2493,7 @@ def run_fils_offload_to_driver(dev, apdev, params):
|
||||||
params['erp_domain'] = 'example.com'
|
params['erp_domain'] = 'example.com'
|
||||||
params['fils_realm'] = 'example.com'
|
params['fils_realm'] = 'example.com'
|
||||||
params['disable_pmksa_caching'] = '1'
|
params['disable_pmksa_caching'] = '1'
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev.request("ERP_FLUSH")
|
dev.request("ERP_FLUSH")
|
||||||
id = dev.connect("fils", key_mgmt="FILS-SHA256",
|
id = dev.connect("fils", key_mgmt="FILS-SHA256",
|
||||||
|
@ -2535,7 +2535,7 @@ def test_fils_sk_okc(dev, apdev, params):
|
||||||
params['auth_server_port'] = "18128"
|
params['auth_server_port'] = "18128"
|
||||||
params['erp_domain'] = 'example.com'
|
params['erp_domain'] = 'example.com'
|
||||||
params['fils_realm'] = 'example.com'
|
params['fils_realm'] = 'example.com'
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].request("ERP_FLUSH")
|
dev[0].request("ERP_FLUSH")
|
||||||
|
@ -2584,7 +2584,7 @@ def test_fils_sk_ptk_rekey_request(dev, apdev, params):
|
||||||
params['erp_send_reauth_start'] = '1'
|
params['erp_send_reauth_start'] = '1'
|
||||||
params['erp_domain'] = 'example.com'
|
params['erp_domain'] = 'example.com'
|
||||||
params['fils_realm'] = 'example.com'
|
params['fils_realm'] = 'example.com'
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].flush_scan_cache()
|
dev[0].flush_scan_cache()
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
|
|
16
tests/hwsim/test_hostapd_error.py
Normal file
16
tests/hwsim/test_hostapd_error.py
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
# hostapd error paths
|
||||||
|
# Copyright (c) 2024, Jouni Malinen <j@w1.fi>
|
||||||
|
#
|
||||||
|
# This software may be distributed under the terms of the BSD license.
|
||||||
|
# See README for more details.
|
||||||
|
|
||||||
|
import hostapd
|
||||||
|
from utils import *
|
||||||
|
|
||||||
|
def test_hostapd_error_drv_init(dev, apdev):
|
||||||
|
"""hostapd error path on driver interface initialization failure"""
|
||||||
|
hapd = hostapd.add_ap(apdev[0], {"ssid": "ctrl"})
|
||||||
|
with fail_test(hapd, 1, "nl80211_setup_ap"):
|
||||||
|
hapd1 = hostapd.add_ap(apdev[1], {"ssid": "open"}, no_enable=True)
|
||||||
|
if "FAIL" not in hapd1.request("ENABLE"):
|
||||||
|
raise Exception("ENABLE succeeded unexpectedly")
|
|
@ -428,8 +428,11 @@ def _test_wifi_display_parsing(dev):
|
||||||
dev[1].p2p_connect_group(dev[0].p2p_dev_addr(), pin, timeout=60,
|
dev[1].p2p_connect_group(dev[0].p2p_dev_addr(), pin, timeout=60,
|
||||||
social=True, freq=2412)
|
social=True, freq=2412)
|
||||||
bssid = dev[0].get_group_status_field('bssid')
|
bssid = dev[0].get_group_status_field('bssid')
|
||||||
|
dev[2].flush_scan_cache()
|
||||||
dev[2].scan_for_bss(bssid, freq=2412, force_scan=True)
|
dev[2].scan_for_bss(bssid, freq=2412, force_scan=True)
|
||||||
bss = dev[2].get_bss(bssid)
|
bss = dev[2].get_bss(bssid)
|
||||||
|
if 'wfd_subelems' not in bss:
|
||||||
|
raise Exception("Missing WFD elements in scan results")
|
||||||
if bss['wfd_subelems'] != "000006" + wfd_devinfo:
|
if bss['wfd_subelems'] != "000006" + wfd_devinfo:
|
||||||
raise Exception("Unexpected WFD elements in scan results: " + bss['wfd_subelems'])
|
raise Exception("Unexpected WFD elements in scan results: " + bss['wfd_subelems'])
|
||||||
|
|
||||||
|
|
|
@ -569,7 +569,7 @@ def pasn_fils_setup(wpas, apdev, params, key_mgmt):
|
||||||
params['erp_domain'] = 'example.com'
|
params['erp_domain'] = 'example.com'
|
||||||
params['fils_realm'] = 'example.com'
|
params['fils_realm'] = 'example.com'
|
||||||
params['disable_pmksa_caching'] = '1'
|
params['disable_pmksa_caching'] = '1'
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
id = wpas.connect("fils", key_mgmt=key_mgmt,
|
id = wpas.connect("fils", key_mgmt=key_mgmt,
|
||||||
eap="PSK", identity="psk.user@example.com",
|
eap="PSK", identity="psk.user@example.com",
|
||||||
|
|
|
@ -64,9 +64,9 @@ def check_nr_results(dev, bssids=None, lci=False, civic=False):
|
||||||
def test_rrm_neighbor_db(dev, apdev):
|
def test_rrm_neighbor_db(dev, apdev):
|
||||||
"""hostapd ctrl_iface SET_NEIGHBOR"""
|
"""hostapd ctrl_iface SET_NEIGHBOR"""
|
||||||
params = {"ssid": "test", "rrm_neighbor_report": "1"}
|
params = {"ssid": "test", "rrm_neighbor_report": "1"}
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
params = {"ssid": "test2", "rrm_neighbor_report": "1"}
|
params = {"ssid": "test2", "rrm_neighbor_report": "1"}
|
||||||
hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
|
hapd2 = hostapd.add_ap(apdev[1], params)
|
||||||
|
|
||||||
res = hapd.request("SHOW_NEIGHBOR")
|
res = hapd.request("SHOW_NEIGHBOR")
|
||||||
if len(res.splitlines()) != 1:
|
if len(res.splitlines()) != 1:
|
||||||
|
@ -215,7 +215,7 @@ def test_rrm_neighbor_db(dev, apdev):
|
||||||
def test_rrm_neighbor_db_failures(dev, apdev):
|
def test_rrm_neighbor_db_failures(dev, apdev):
|
||||||
"""hostapd ctrl_iface SET_NEIGHBOR failures"""
|
"""hostapd ctrl_iface SET_NEIGHBOR failures"""
|
||||||
params = {"ssid": "test", "rrm_neighbor_report": "1"}
|
params = {"ssid": "test", "rrm_neighbor_report": "1"}
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
cmd = "SET_NEIGHBOR 00:11:22:33:44:55 ssid=\"test1\" nr=" + nr + " lci=" + lci + " civic=" + civic
|
cmd = "SET_NEIGHBOR 00:11:22:33:44:55 ssid=\"test1\" nr=" + nr + " lci=" + lci + " civic=" + civic
|
||||||
tests = [(1, "hostapd_neighbor_add"),
|
tests = [(1, "hostapd_neighbor_add"),
|
||||||
(1, "wpabuf_dup;hostapd_neighbor_set"),
|
(1, "wpabuf_dup;hostapd_neighbor_set"),
|
||||||
|
@ -229,7 +229,7 @@ def test_rrm_neighbor_db_failures(dev, apdev):
|
||||||
def test_rrm_neighbor_db_disabled(dev, apdev):
|
def test_rrm_neighbor_db_disabled(dev, apdev):
|
||||||
"""hostapd ctrl_iface SHOW_NEIGHBOR while neighbor report disabled"""
|
"""hostapd ctrl_iface SHOW_NEIGHBOR while neighbor report disabled"""
|
||||||
params = {"ssid": "test"}
|
params = {"ssid": "test"}
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
if "FAIL" not in hapd.request("SHOW_NEIGHBOR"):
|
if "FAIL" not in hapd.request("SHOW_NEIGHBOR"):
|
||||||
raise Exception("SHOW_NEIGHBOR accepted")
|
raise Exception("SHOW_NEIGHBOR accepted")
|
||||||
|
|
||||||
|
@ -242,9 +242,9 @@ def test_rrm_neighbor_rep_req(dev, apdev):
|
||||||
nr3 = "dd112233445500000000510107"
|
nr3 = "dd112233445500000000510107"
|
||||||
|
|
||||||
params = {"ssid": "test", "rnr": "1"}
|
params = {"ssid": "test", "rnr": "1"}
|
||||||
hostapd.add_ap(apdev[0]['ifname'], params)
|
hostapd.add_ap(apdev[0], params)
|
||||||
params = {"ssid": "test2", "rrm_neighbor_report": "1", "rnr": "1"}
|
params = {"ssid": "test2", "rrm_neighbor_report": "1", "rnr": "1"}
|
||||||
hapd = hostapd.add_ap(apdev[1]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[1], params)
|
||||||
|
|
||||||
bssid1 = apdev[1]['bssid']
|
bssid1 = apdev[1]['bssid']
|
||||||
|
|
||||||
|
@ -351,7 +351,7 @@ def test_rrm_neighbor_rep_oom(dev, apdev):
|
||||||
nr3 = "dd112233445500000000510107"
|
nr3 = "dd112233445500000000510107"
|
||||||
|
|
||||||
params = {"ssid": "test", "rrm_neighbor_report": "1"}
|
params = {"ssid": "test", "rrm_neighbor_report": "1"}
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].connect("test", key_mgmt="NONE", scan_freq="2412")
|
dev[0].connect("test", key_mgmt="NONE", scan_freq="2412")
|
||||||
|
|
||||||
|
@ -367,7 +367,7 @@ def test_rrm_lci_req(dev, apdev):
|
||||||
check_rrm_support(dev[0])
|
check_rrm_support(dev[0])
|
||||||
|
|
||||||
params = {"ssid": "rrm", "rrm_neighbor_report": "1"}
|
params = {"ssid": "rrm", "rrm_neighbor_report": "1"}
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
# station not specified
|
# station not specified
|
||||||
if "FAIL" not in hapd.request("REQ_LCI "):
|
if "FAIL" not in hapd.request("REQ_LCI "):
|
||||||
|
@ -400,7 +400,7 @@ def test_rrm_lci_req_timeout(dev, apdev):
|
||||||
check_rrm_support(dev[0])
|
check_rrm_support(dev[0])
|
||||||
|
|
||||||
params = {"ssid": "rrm", "rrm_neighbor_report": "1"}
|
params = {"ssid": "rrm", "rrm_neighbor_report": "1"}
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].request("SET LCI " + lci)
|
dev[0].request("SET LCI " + lci)
|
||||||
dev[0].connect("rrm", key_mgmt="NONE", scan_freq="2412")
|
dev[0].connect("rrm", key_mgmt="NONE", scan_freq="2412")
|
||||||
|
@ -431,7 +431,7 @@ def test_rrm_lci_req_oom(dev, apdev):
|
||||||
check_rrm_support(dev[0])
|
check_rrm_support(dev[0])
|
||||||
|
|
||||||
params = {"ssid": "rrm", "rrm_neighbor_report": "1"}
|
params = {"ssid": "rrm", "rrm_neighbor_report": "1"}
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].request("SET LCI " + lci)
|
dev[0].request("SET LCI " + lci)
|
||||||
dev[0].connect("rrm", key_mgmt="NONE", scan_freq="2412")
|
dev[0].connect("rrm", key_mgmt="NONE", scan_freq="2412")
|
||||||
|
@ -454,7 +454,7 @@ def test_rrm_lci_req_ap_oom(dev, apdev):
|
||||||
check_rrm_support(dev[0])
|
check_rrm_support(dev[0])
|
||||||
|
|
||||||
params = {"ssid": "rrm", "rrm_neighbor_report": "1"}
|
params = {"ssid": "rrm", "rrm_neighbor_report": "1"}
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].request("SET LCI " + lci)
|
dev[0].request("SET LCI " + lci)
|
||||||
dev[0].connect("rrm", key_mgmt="NONE", scan_freq="2412")
|
dev[0].connect("rrm", key_mgmt="NONE", scan_freq="2412")
|
||||||
|
@ -472,7 +472,7 @@ def test_rrm_lci_req_get_reltime_failure(dev, apdev):
|
||||||
check_rrm_support(dev[0])
|
check_rrm_support(dev[0])
|
||||||
|
|
||||||
params = {"ssid": "rrm", "rrm_neighbor_report": "1"}
|
params = {"ssid": "rrm", "rrm_neighbor_report": "1"}
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].request("SET LCI " + lci)
|
dev[0].request("SET LCI " + lci)
|
||||||
dev[0].connect("rrm", key_mgmt="NONE", scan_freq="2412")
|
dev[0].connect("rrm", key_mgmt="NONE", scan_freq="2412")
|
||||||
|
@ -488,7 +488,7 @@ def test_rrm_neighbor_rep_req_from_conf(dev, apdev):
|
||||||
|
|
||||||
params = {"ssid": "test2", "rrm_neighbor_report": "1",
|
params = {"ssid": "test2", "rrm_neighbor_report": "1",
|
||||||
"stationary_ap": "1", "lci": lci, "civic": civic}
|
"stationary_ap": "1", "lci": lci, "civic": civic}
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
bssid = apdev[0]['bssid']
|
bssid = apdev[0]['bssid']
|
||||||
|
|
||||||
|
@ -504,7 +504,7 @@ def test_rrm_neighbor_rep_req_timeout(dev, apdev):
|
||||||
|
|
||||||
params = {"ssid": "test2", "rrm_neighbor_report": "1",
|
params = {"ssid": "test2", "rrm_neighbor_report": "1",
|
||||||
"stationary_ap": "1", "lci": lci, "civic": civic}
|
"stationary_ap": "1", "lci": lci, "civic": civic}
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].connect("test2", key_mgmt="NONE", scan_freq="2412")
|
dev[0].connect("test2", key_mgmt="NONE", scan_freq="2412")
|
||||||
|
|
||||||
|
@ -523,7 +523,7 @@ def test_rrm_neighbor_rep_req_oom(dev, apdev):
|
||||||
|
|
||||||
params = {"ssid": "test2", "rrm_neighbor_report": "1",
|
params = {"ssid": "test2", "rrm_neighbor_report": "1",
|
||||||
"stationary_ap": "1", "lci": lci, "civic": civic}
|
"stationary_ap": "1", "lci": lci, "civic": civic}
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].connect("test2", key_mgmt="NONE", scan_freq="2412")
|
dev[0].connect("test2", key_mgmt="NONE", scan_freq="2412")
|
||||||
|
|
||||||
|
@ -548,7 +548,7 @@ def test_rrm_neighbor_rep_req_disconnect(dev, apdev):
|
||||||
|
|
||||||
params = {"ssid": "test2", "rrm_neighbor_report": "1",
|
params = {"ssid": "test2", "rrm_neighbor_report": "1",
|
||||||
"stationary_ap": "1", "lci": lci, "civic": civic}
|
"stationary_ap": "1", "lci": lci, "civic": civic}
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
if "FAIL" not in dev[0].request("NEIGHBOR_REP_REQUEST"):
|
if "FAIL" not in dev[0].request("NEIGHBOR_REP_REQUEST"):
|
||||||
raise Exception("Request accepted while disconnected")
|
raise Exception("Request accepted while disconnected")
|
||||||
|
@ -570,7 +570,7 @@ def test_rrm_neighbor_rep_req_not_supported(dev, apdev):
|
||||||
check_rrm_support(dev[0])
|
check_rrm_support(dev[0])
|
||||||
|
|
||||||
params = {"ssid": "test2", "rrm_beacon_report": "1"}
|
params = {"ssid": "test2", "rrm_beacon_report": "1"}
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].connect("test2", key_mgmt="NONE", scan_freq="2412")
|
dev[0].connect("test2", key_mgmt="NONE", scan_freq="2412")
|
||||||
|
|
||||||
|
@ -583,7 +583,7 @@ def test_rrm_neighbor_rep_req_busy(dev, apdev):
|
||||||
|
|
||||||
params = {"ssid": "test2", "rrm_neighbor_report": "1",
|
params = {"ssid": "test2", "rrm_neighbor_report": "1",
|
||||||
"stationary_ap": "1", "lci": lci, "civic": civic}
|
"stationary_ap": "1", "lci": lci, "civic": civic}
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].connect("test2", key_mgmt="NONE", scan_freq="2412")
|
dev[0].connect("test2", key_mgmt="NONE", scan_freq="2412")
|
||||||
|
|
||||||
|
@ -608,7 +608,7 @@ def test_rrm_ftm_range_req(dev, apdev):
|
||||||
|
|
||||||
def run_rrm_ftm_range_req(dev, apdev):
|
def run_rrm_ftm_range_req(dev, apdev):
|
||||||
params = {"ssid": "rrm", "rrm_neighbor_report": "1"}
|
params = {"ssid": "rrm", "rrm_neighbor_report": "1"}
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
bssid = hapd.own_addr()
|
bssid = hapd.own_addr()
|
||||||
|
|
||||||
# station not specified
|
# station not specified
|
||||||
|
@ -694,7 +694,7 @@ def test_rrm_ftm_range_req_timeout(dev, apdev):
|
||||||
|
|
||||||
def run_rrm_ftm_range_req_timeout(dev, apdev):
|
def run_rrm_ftm_range_req_timeout(dev, apdev):
|
||||||
params = {"ssid": "rrm", "rrm_neighbor_report": "1"}
|
params = {"ssid": "rrm", "rrm_neighbor_report": "1"}
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
bssid = hapd.own_addr()
|
bssid = hapd.own_addr()
|
||||||
|
|
||||||
# Override RM capabilities to include FTM range report
|
# Override RM capabilities to include FTM range report
|
||||||
|
@ -734,7 +734,7 @@ def test_rrm_ftm_range_req_failure(dev, apdev):
|
||||||
|
|
||||||
def run_rrm_ftm_range_req_failure(dev, apdev):
|
def run_rrm_ftm_range_req_failure(dev, apdev):
|
||||||
params = {"ssid": "rrm", "rrm_neighbor_report": "1"}
|
params = {"ssid": "rrm", "rrm_neighbor_report": "1"}
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
bssid = hapd.own_addr()
|
bssid = hapd.own_addr()
|
||||||
|
|
||||||
# Override RM capabilities to include FTM range report
|
# Override RM capabilities to include FTM range report
|
||||||
|
@ -764,7 +764,7 @@ def _test_rrm_ftm_capa_indication(dev, apdev):
|
||||||
params = {"ssid": "ftm",
|
params = {"ssid": "ftm",
|
||||||
"ftm_responder": "1",
|
"ftm_responder": "1",
|
||||||
"ftm_initiator": "1",}
|
"ftm_initiator": "1",}
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
if "OK" not in dev[0].request("SET ftm_initiator 1"):
|
if "OK" not in dev[0].request("SET ftm_initiator 1"):
|
||||||
raise Exception("could not set ftm_initiator")
|
raise Exception("could not set ftm_initiator")
|
||||||
|
@ -1564,7 +1564,7 @@ def test_rrm_beacon_req_active_many(dev, apdev):
|
||||||
|
|
||||||
params = {"ssid": "rrm", "rrm_beacon_report": "1"}
|
params = {"ssid": "rrm", "rrm_beacon_report": "1"}
|
||||||
params['vendor_elements'] = "dd50" + 80*'aa'
|
params['vendor_elements'] = "dd50" + 80*'aa'
|
||||||
hapd = hostapd.add_ap(apdev[1]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[1], params)
|
||||||
|
|
||||||
dev[0].connect("rrm", key_mgmt="NONE", scan_freq="2412")
|
dev[0].connect("rrm", key_mgmt="NONE", scan_freq="2412")
|
||||||
addr = dev[0].own_addr()
|
addr = dev[0].own_addr()
|
||||||
|
@ -2058,7 +2058,7 @@ def test_rrm_beacon_req_ap_errors(dev, apdev):
|
||||||
|
|
||||||
def run_rrm_beacon_req_ap_errors(dev, apdev):
|
def run_rrm_beacon_req_ap_errors(dev, apdev):
|
||||||
params = {"ssid": "rrm", "rrm_beacon_report": "1"}
|
params = {"ssid": "rrm", "rrm_beacon_report": "1"}
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
bssid = hapd.own_addr()
|
bssid = hapd.own_addr()
|
||||||
dev[0].scan_for_bss(bssid, freq=2412)
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
dev[0].connect("rrm", key_mgmt="NONE", scan_freq="2412")
|
dev[0].connect("rrm", key_mgmt="NONE", scan_freq="2412")
|
||||||
|
@ -2106,7 +2106,7 @@ def run_rrm_beacon_req_ap_errors(dev, apdev):
|
||||||
def test_rrm_req_reject_oom(dev, apdev):
|
def test_rrm_req_reject_oom(dev, apdev):
|
||||||
"""Radio measurement request - OOM while rejecting a request"""
|
"""Radio measurement request - OOM while rejecting a request"""
|
||||||
params = {"ssid": "rrm", "rrm_beacon_report": "1"}
|
params = {"ssid": "rrm", "rrm_beacon_report": "1"}
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
bssid = hapd.own_addr()
|
bssid = hapd.own_addr()
|
||||||
|
|
||||||
dev[0].connect("rrm", key_mgmt="NONE", scan_freq="2412")
|
dev[0].connect("rrm", key_mgmt="NONE", scan_freq="2412")
|
||||||
|
@ -2129,7 +2129,7 @@ def test_rrm_req_reject_oom(dev, apdev):
|
||||||
def test_rrm_req_when_rrm_not_used(dev, apdev):
|
def test_rrm_req_when_rrm_not_used(dev, apdev):
|
||||||
"""Radio/link measurement request for non-RRM association"""
|
"""Radio/link measurement request for non-RRM association"""
|
||||||
params = {"ssid": "rrm"}
|
params = {"ssid": "rrm"}
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
bssid = hapd.own_addr()
|
bssid = hapd.own_addr()
|
||||||
|
|
||||||
dev[0].connect("rrm", key_mgmt="NONE", scan_freq="2412")
|
dev[0].connect("rrm", key_mgmt="NONE", scan_freq="2412")
|
||||||
|
@ -2268,7 +2268,7 @@ def test_rrm_link_measurement(dev, apdev):
|
||||||
"""Radio measurement request - link measurement"""
|
"""Radio measurement request - link measurement"""
|
||||||
check_tx_power_support(dev[0])
|
check_tx_power_support(dev[0])
|
||||||
params = {"ssid": "rrm", "rrm_beacon_report": "1"}
|
params = {"ssid": "rrm", "rrm_beacon_report": "1"}
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
bssid = hapd.own_addr()
|
bssid = hapd.own_addr()
|
||||||
|
|
||||||
dev[0].connect("rrm", key_mgmt="NONE", scan_freq="2412")
|
dev[0].connect("rrm", key_mgmt="NONE", scan_freq="2412")
|
||||||
|
@ -2289,7 +2289,7 @@ def test_rrm_link_measurement_oom(dev, apdev):
|
||||||
"""Radio measurement request - link measurement OOM"""
|
"""Radio measurement request - link measurement OOM"""
|
||||||
check_tx_power_support(dev[0])
|
check_tx_power_support(dev[0])
|
||||||
params = {"ssid": "rrm", "rrm_beacon_report": "1"}
|
params = {"ssid": "rrm", "rrm_beacon_report": "1"}
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
bssid = hapd.own_addr()
|
bssid = hapd.own_addr()
|
||||||
|
|
||||||
dev[0].connect("rrm", key_mgmt="NONE", scan_freq="2412")
|
dev[0].connect("rrm", key_mgmt="NONE", scan_freq="2412")
|
||||||
|
@ -2319,7 +2319,7 @@ def test_rrm_rep_parse_proto(dev, apdev):
|
||||||
check_rrm_support(dev[0])
|
check_rrm_support(dev[0])
|
||||||
|
|
||||||
params = {"ssid": "rrm", "rrm_neighbor_report": "1"}
|
params = {"ssid": "rrm", "rrm_neighbor_report": "1"}
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
bssid = hapd.own_addr()
|
bssid = hapd.own_addr()
|
||||||
|
|
||||||
dev[0].request("SET LCI " + lci)
|
dev[0].request("SET LCI " + lci)
|
||||||
|
@ -2354,7 +2354,7 @@ def test_rrm_unexpected(dev, apdev):
|
||||||
check_rrm_support(dev[0])
|
check_rrm_support(dev[0])
|
||||||
|
|
||||||
params = {"ssid": "rrm", "rrm_neighbor_report": "0"}
|
params = {"ssid": "rrm", "rrm_neighbor_report": "0"}
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
bssid = hapd.own_addr()
|
bssid = hapd.own_addr()
|
||||||
|
|
||||||
dev[0].connect("rrm", key_mgmt="NONE", scan_freq="2412")
|
dev[0].connect("rrm", key_mgmt="NONE", scan_freq="2412")
|
||||||
|
@ -2381,7 +2381,7 @@ def check_beacon_req(hapd, addr, idx):
|
||||||
def test_rrm_reassociation(dev, apdev):
|
def test_rrm_reassociation(dev, apdev):
|
||||||
"""Radio measurement request - reassociation"""
|
"""Radio measurement request - reassociation"""
|
||||||
params = {"ssid": "rrm", "rrm_beacon_report": "1"}
|
params = {"ssid": "rrm", "rrm_beacon_report": "1"}
|
||||||
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
bssid = hapd.own_addr()
|
bssid = hapd.own_addr()
|
||||||
|
|
||||||
addr = dev[0].own_addr()
|
addr = dev[0].own_addr()
|
||||||
|
@ -2395,7 +2395,7 @@ def test_rrm_reassociation(dev, apdev):
|
||||||
hapd.wait_sta()
|
hapd.wait_sta()
|
||||||
check_beacon_req(hapd, addr, 1)
|
check_beacon_req(hapd, addr, 1)
|
||||||
|
|
||||||
hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
|
hapd2 = hostapd.add_ap(apdev[1], params)
|
||||||
bssid2 = hapd2.own_addr()
|
bssid2 = hapd2.own_addr()
|
||||||
dev[0].scan_for_bss(bssid2, freq=2412, force_scan=True)
|
dev[0].scan_for_bss(bssid2, freq=2412, force_scan=True)
|
||||||
dev[0].roam(bssid2)
|
dev[0].roam(bssid2)
|
||||||
|
|
437
tests/hwsim/test_rsn_override.py
Normal file
437
tests/hwsim/test_rsn_override.py
Normal file
|
@ -0,0 +1,437 @@
|
||||||
|
# Test cases for RSNE/RSNXE overriding
|
||||||
|
# Copyright (c) 2023-2024, Qualcomm Innovation Center, Inc.
|
||||||
|
#
|
||||||
|
# This software may be distributed under the terms of the BSD license.
|
||||||
|
# See README for more details.
|
||||||
|
|
||||||
|
import hostapd
|
||||||
|
from utils import *
|
||||||
|
from hwsim import HWSimRadio
|
||||||
|
from wpasupplicant import WpaSupplicant
|
||||||
|
from test_eht import eht_mld_enable_ap, eht_verify_status, eht_verify_wifi_version, traffic_test
|
||||||
|
|
||||||
|
def test_rsn_override(dev, apdev):
|
||||||
|
"""RSNE=WPA2-Personal/PMF-optional override=WPA3-Personal/PMF-required (with MLO parameters)"""
|
||||||
|
check_sae_capab(dev[0])
|
||||||
|
|
||||||
|
ssid = "test-rsn-override"
|
||||||
|
params = hostapd.wpa2_params(ssid=ssid,
|
||||||
|
passphrase="12345678",
|
||||||
|
ieee80211w='1')
|
||||||
|
params['rsn_override_key_mgmt'] = 'SAE SAE-EXT-KEY'
|
||||||
|
params['rsn_override_pairwise'] = 'CCMP GCMP-256'
|
||||||
|
params['rsn_override_mfp'] = '2'
|
||||||
|
params['beacon_prot'] = '1'
|
||||||
|
params['sae_groups'] = '19 20'
|
||||||
|
params['sae_require_mfp'] = '1'
|
||||||
|
params['sae_pwe'] = '2'
|
||||||
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
bssid = hapd.own_addr()
|
||||||
|
|
||||||
|
try:
|
||||||
|
dev[0].set("rsn_overriding", "1")
|
||||||
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
|
bss = dev[0].get_bss(bssid)
|
||||||
|
flags = bss['flags']
|
||||||
|
if "PSK" in flags:
|
||||||
|
raise Exception("Unexpected BSS flags: " + flags)
|
||||||
|
if "-SAE+SAE-EXT-KEY-" not in flags:
|
||||||
|
raise Exception("Unexpected BSS flags: " + flags)
|
||||||
|
if "-GCMP-256+CCMP" not in flags:
|
||||||
|
raise Exception("Unexpected BSS flags: " + flags)
|
||||||
|
|
||||||
|
dev[0].set("sae_pwe", "2")
|
||||||
|
dev[0].set("sae_groups", "")
|
||||||
|
dev[0].connect(ssid, sae_password="12345678", key_mgmt="SAE",
|
||||||
|
ieee80211w="2", scan_freq="2412")
|
||||||
|
finally:
|
||||||
|
dev[0].set("sae_pwe", "0")
|
||||||
|
dev[0].set("rsn_overriding", "0")
|
||||||
|
|
||||||
|
def test_rsn_override2(dev, apdev):
|
||||||
|
"""RSNE=WPA2-Personal/PMF-disabled override=WPA3-Personal/PMF-required (with MLO parameters)"""
|
||||||
|
check_sae_capab(dev[0])
|
||||||
|
|
||||||
|
ssid = "test-rsn-override"
|
||||||
|
params = hostapd.wpa2_params(ssid=ssid,
|
||||||
|
passphrase="12345678",
|
||||||
|
ieee80211w='0')
|
||||||
|
params['rsn_override_key_mgmt'] = 'SAE SAE-EXT-KEY'
|
||||||
|
params['rsn_override_pairwise'] = 'CCMP GCMP-256'
|
||||||
|
params['rsn_override_mfp'] = '2'
|
||||||
|
params['beacon_prot'] = '1'
|
||||||
|
params['sae_groups'] = '19 20'
|
||||||
|
params['sae_require_mfp'] = '1'
|
||||||
|
params['sae_pwe'] = '2'
|
||||||
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
bssid = hapd.own_addr()
|
||||||
|
|
||||||
|
try:
|
||||||
|
dev[0].set("rsn_overriding", "1")
|
||||||
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
|
bss = dev[0].get_bss(bssid)
|
||||||
|
flags = bss['flags']
|
||||||
|
if "PSK" in flags:
|
||||||
|
raise Exception("Unexpected BSS flags: " + flags)
|
||||||
|
if "-SAE+SAE-EXT-KEY-" not in flags:
|
||||||
|
raise Exception("Unexpected BSS flags: " + flags)
|
||||||
|
if "-GCMP-256+CCMP" not in flags:
|
||||||
|
raise Exception("Unexpected BSS flags: " + flags)
|
||||||
|
|
||||||
|
dev[0].set("sae_pwe", "2")
|
||||||
|
dev[0].set("sae_groups", "")
|
||||||
|
dev[0].connect(ssid, sae_password="12345678", key_mgmt="SAE",
|
||||||
|
ieee80211w="2", scan_freq="2412")
|
||||||
|
finally:
|
||||||
|
dev[0].set("sae_pwe", "0")
|
||||||
|
dev[0].set("rsn_overriding", "0")
|
||||||
|
|
||||||
|
def test_rsn_override_no_pairwise(dev, apdev):
|
||||||
|
"""RSN overriding and no pairwise cipher match in RSNEO"""
|
||||||
|
check_sae_capab(dev[0])
|
||||||
|
|
||||||
|
ssid = "test-rsn-override"
|
||||||
|
params = hostapd.wpa2_params(ssid=ssid,
|
||||||
|
passphrase="12345678",
|
||||||
|
ieee80211w='1')
|
||||||
|
params['rsn_override_key_mgmt'] = 'SAE SAE-EXT-KEY'
|
||||||
|
params['rsn_override_pairwise'] = 'GCMP-256'
|
||||||
|
params['rsn_override_mfp'] = '2'
|
||||||
|
params['beacon_prot'] = '1'
|
||||||
|
params['sae_groups'] = '19 20'
|
||||||
|
params['sae_require_mfp'] = '1'
|
||||||
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
bssid = hapd.own_addr()
|
||||||
|
|
||||||
|
try:
|
||||||
|
dev[0].set("rsn_overriding", "1")
|
||||||
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
|
|
||||||
|
dev[0].set("sae_groups", "")
|
||||||
|
dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK SAE",
|
||||||
|
pairwise="CCMP", ieee80211w="1", scan_freq="2412")
|
||||||
|
finally:
|
||||||
|
dev[0].set("sae_pwe", "0")
|
||||||
|
dev[0].set("rsn_overriding", "0")
|
||||||
|
|
||||||
|
def test_rsn_override_mld(dev, apdev):
|
||||||
|
"""AP MLD and RSNE=WPA2-Personal/PMF-disabled override=WPA3-Personal/PMF-required"""
|
||||||
|
run_rsn_override_mld(dev, apdev, False)
|
||||||
|
|
||||||
|
def test_rsn_override_mld_mixed(dev, apdev):
|
||||||
|
"""AP MLD and RSNE=WPA2-Personal/PMF-disabled override=WPA3-Personal/PMF-required on one link"""
|
||||||
|
run_rsn_override_mld(dev, apdev, True)
|
||||||
|
|
||||||
|
def test_rsn_override_mld_only_sta(dev, apdev):
|
||||||
|
"""AP MLD and RSN overriding only on STA"""
|
||||||
|
run_rsn_override_mld(dev, apdev, False, only_sta=True)
|
||||||
|
|
||||||
|
def test_rsn_override_mld_too_long_elems(dev, apdev):
|
||||||
|
"""AP MLD and RSN overriding with too long elements"""
|
||||||
|
run_rsn_override_mld(dev, apdev, False, too_long_elems=True)
|
||||||
|
|
||||||
|
def run_rsn_override_mld(dev, apdev, mixed, only_sta=False,
|
||||||
|
too_long_elems=False):
|
||||||
|
with HWSimRadio(use_mlo=True) as (hapd_radio, hapd_iface), \
|
||||||
|
HWSimRadio(use_mlo=True) as (wpas_radio, wpas_iface):
|
||||||
|
|
||||||
|
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
|
||||||
|
wpas.interface_add(wpas_iface)
|
||||||
|
|
||||||
|
passphrase = 'qwertyuiop'
|
||||||
|
ssid = "AP MLD RSN override"
|
||||||
|
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
|
||||||
|
params['ieee80211n'] = '1'
|
||||||
|
params['ieee80211ax'] = '1'
|
||||||
|
params['ieee80211be'] = '1'
|
||||||
|
params['channel'] = '1'
|
||||||
|
params['hw_mode'] = 'g'
|
||||||
|
params['beacon_prot'] = '1'
|
||||||
|
params['sae_groups'] = '19 20'
|
||||||
|
params['sae_require_mfp'] = '1'
|
||||||
|
params['sae_pwe'] = '2'
|
||||||
|
if only_sta:
|
||||||
|
params['wpa_key_mgmt'] = 'SAE SAE-EXT-KEY'
|
||||||
|
params['rsn_pairwise'] = 'CCMP GCMP-256'
|
||||||
|
params['ieee80211w'] = '2'
|
||||||
|
elif not mixed:
|
||||||
|
params['rsn_override_key_mgmt'] = 'SAE'
|
||||||
|
params['rsn_override_key_mgmt_2'] = 'SAE-EXT-KEY'
|
||||||
|
params['rsn_override_pairwise'] = 'CCMP'
|
||||||
|
params['rsn_override_pairwise_2'] = 'GCMP-256'
|
||||||
|
params['rsn_override_mfp'] = '1'
|
||||||
|
params['rsn_override_mfp_2'] = '2'
|
||||||
|
|
||||||
|
params1 = dict(params)
|
||||||
|
|
||||||
|
if mixed:
|
||||||
|
params['wpa_key_mgmt'] = 'SAE SAE-EXT-KEY'
|
||||||
|
params['rsn_pairwise'] = 'CCMP GCMP-256'
|
||||||
|
params['ieee80211w'] = '2'
|
||||||
|
params['rsn_override_key_mgmt_2'] = 'SAE SAE-EXT-KEY'
|
||||||
|
params['rsn_override_pairwise_2'] = 'CCMP GCMP-256'
|
||||||
|
params['rsn_override_mfp_2'] = '2'
|
||||||
|
|
||||||
|
params1['rsn_override_key_mgmt_2'] = 'SAE SAE-EXT-KEY'
|
||||||
|
params1['rsn_override_pairwise_2'] = 'CCMP GCMP-256'
|
||||||
|
params1['rsn_override_mfp_2'] = '2'
|
||||||
|
|
||||||
|
hapd0 = eht_mld_enable_ap(hapd_iface, 0, params)
|
||||||
|
|
||||||
|
params1['channel'] = '6'
|
||||||
|
if too_long_elems:
|
||||||
|
params1['rsnoe_override'] = 'ddff506f9a29' + 251*'cc'
|
||||||
|
hapd1 = eht_mld_enable_ap(hapd_iface, 1, params1)
|
||||||
|
|
||||||
|
wpas.set("sae_pwe", "1")
|
||||||
|
wpas.set("rsn_overriding", "1")
|
||||||
|
wpas.connect(ssid, sae_password=passphrase, scan_freq="2412 2437",
|
||||||
|
key_mgmt="SAE-EXT-KEY", ieee80211w="2", beacon_prot="1",
|
||||||
|
pairwise="GCMP-256 CCMP", wait_connect=not too_long_elems)
|
||||||
|
if too_long_elems:
|
||||||
|
ev = wpas.wait_event(['Associated with'], timeout=10)
|
||||||
|
if ev is None:
|
||||||
|
raise Exception("Association not reported")
|
||||||
|
ev = wpas.wait_event(['EAPOL-RX'], timeout=1)
|
||||||
|
if ev is None:
|
||||||
|
raise Exception("EAPOL-Key M1 not reported")
|
||||||
|
ev = wpas.wait_event(['EAPOL-RX', 'CTRL-EVENT-DISCONNECTED'],
|
||||||
|
timeout=20)
|
||||||
|
if ev is None:
|
||||||
|
raise Exception("Disconnection not reported")
|
||||||
|
# The AP is expected to fail to send M3 due to RSNOE/RSNO2E/RSNXOE
|
||||||
|
# being too long to fit into the RSN Override Link KDE.
|
||||||
|
if 'EAPOL-RX' in ev:
|
||||||
|
raise Exception("Unexpected EAPOL-Key M3 reported")
|
||||||
|
return
|
||||||
|
|
||||||
|
eht_verify_status(wpas, hapd0, 2412, 20, is_ht=True, mld=True,
|
||||||
|
valid_links=3, active_links=3)
|
||||||
|
eht_verify_wifi_version(wpas)
|
||||||
|
traffic_test(wpas, hapd0)
|
||||||
|
traffic_test(wpas, hapd1)
|
||||||
|
if only_sta:
|
||||||
|
return
|
||||||
|
|
||||||
|
dev[0].set("rsn_overriding", "0")
|
||||||
|
dev[0].connect(ssid, psk=passphrase, key_mgmt="WPA-PSK",
|
||||||
|
scan_freq="2412 2437")
|
||||||
|
|
||||||
|
status = wpas.get_status()
|
||||||
|
logger.debug("wpas STATUS:\n" + str(status))
|
||||||
|
if status['key_mgmt'] != 'SAE-EXT-KEY' or \
|
||||||
|
'pmf' not in status or \
|
||||||
|
status['pmf'] != '2' or \
|
||||||
|
status['pairwise_cipher'] != 'GCMP-256':
|
||||||
|
raise Exception("Unexpected result for new STA")
|
||||||
|
|
||||||
|
status = dev[0].get_status()
|
||||||
|
logger.debug("dev[0] STATUS:\n" + str(status))
|
||||||
|
if status['key_mgmt'] != 'WPA2-PSK' or \
|
||||||
|
status['pairwise_cipher'] != 'CCMP':
|
||||||
|
raise Exception("Unexpected result for legacy STA")
|
||||||
|
|
||||||
|
def test_rsn_override_connect_cmd(dev, apdev):
|
||||||
|
"""RSNE=WPA2-Personal/PMF-optional override=WPA3-Personal/PMF-required using cfg80211 connect command"""
|
||||||
|
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
|
||||||
|
wpas.interface_add("wlan5", drv_params="force_connect_cmd=1 rsn_override_in_driver=1")
|
||||||
|
check_sae_capab(wpas)
|
||||||
|
|
||||||
|
ssid = "test-rsn-override"
|
||||||
|
params = hostapd.wpa2_params(ssid=ssid,
|
||||||
|
passphrase="12345678",
|
||||||
|
ieee80211w='1')
|
||||||
|
params['rsn_override_key_mgmt'] = 'WPA-PSK-SHA256'
|
||||||
|
params['rsn_override_pairwise'] = 'CCMP GCMP-256'
|
||||||
|
params['rsn_override_mfp'] = '2'
|
||||||
|
params['beacon_prot'] = '1'
|
||||||
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
|
wpas.set("rsn_overriding", "1")
|
||||||
|
wpas.connect(ssid, psk="12345678", key_mgmt="WPA-PSK-SHA256",
|
||||||
|
ieee80211w="2", scan_freq="2412")
|
||||||
|
|
||||||
|
def test_rsn_override_omit_rsnxe(dev, apdev):
|
||||||
|
"""RSN overriding with RSNXE explicitly omitted"""
|
||||||
|
check_sae_capab(dev[0])
|
||||||
|
|
||||||
|
ssid = "test-rsn-override"
|
||||||
|
params = hostapd.wpa2_params(ssid=ssid,
|
||||||
|
passphrase="12345678",
|
||||||
|
ieee80211w='1')
|
||||||
|
params['rsn_override_key_mgmt'] = 'SAE SAE-EXT-KEY'
|
||||||
|
params['rsn_override_pairwise'] = 'CCMP GCMP-256'
|
||||||
|
params['rsn_override_mfp'] = '2'
|
||||||
|
params['beacon_prot'] = '1'
|
||||||
|
params['sae_groups'] = '19 20'
|
||||||
|
params['sae_require_mfp'] = '1'
|
||||||
|
params['sae_pwe'] = '2'
|
||||||
|
params['ssid_protection'] = '1'
|
||||||
|
params['rsn_override_omit_rsnxe'] = '1'
|
||||||
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
bssid = hapd.own_addr()
|
||||||
|
|
||||||
|
try:
|
||||||
|
dev[0].set("rsn_overriding", "1")
|
||||||
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
|
dev[0].set("sae_pwe", "2")
|
||||||
|
dev[0].set("sae_groups", "")
|
||||||
|
dev[0].connect(ssid, sae_password="12345678", key_mgmt="SAE",
|
||||||
|
ieee80211w="2", ssid_protection="1",
|
||||||
|
scan_freq="2412")
|
||||||
|
finally:
|
||||||
|
dev[0].set("sae_pwe", "0")
|
||||||
|
dev[0].set("rsn_overriding", "0")
|
||||||
|
|
||||||
|
def test_rsn_override_replace_ies(dev, apdev):
|
||||||
|
"""RSN overriding and replaced AP IEs"""
|
||||||
|
check_sae_capab(dev[0])
|
||||||
|
|
||||||
|
ssid = "test-rsn-override"
|
||||||
|
params = hostapd.wpa2_params(ssid=ssid,
|
||||||
|
passphrase="12345678",
|
||||||
|
ieee80211w='1')
|
||||||
|
params['rsn_override_key_mgmt'] = 'SAE'
|
||||||
|
params['rsn_override_key_mgmt_2'] = 'SAE-EXT-KEY'
|
||||||
|
params['rsn_override_pairwise'] = 'CCMP'
|
||||||
|
params['rsn_override_pairwise_2'] = 'GCMP-256'
|
||||||
|
params['rsn_override_mfp'] = '1'
|
||||||
|
params['rsn_override_mfp_2'] = '2'
|
||||||
|
params['beacon_prot'] = '1'
|
||||||
|
params['sae_groups'] = '19 20'
|
||||||
|
params['sae_require_mfp'] = '1'
|
||||||
|
params['sae_pwe'] = '2'
|
||||||
|
params['ssid_protection'] = '1'
|
||||||
|
params['rsne_override'] = '30180100000fac040100000fac040200000facff000fac020c00'
|
||||||
|
params['rsnxe_override'] = 'f40320eeee'
|
||||||
|
params['rsnoe_override'] = 'dd1c506f9a290100000fac040100000fac040200000facff000fac088c00'
|
||||||
|
params['rsno2e_override'] = 'dd1c506f9a2a0100000fac040100000fac090200000facff000fac18cc00'
|
||||||
|
params['rsnxoe_override'] = 'dd07506f9a2b20bbbb'
|
||||||
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
bssid = hapd.own_addr()
|
||||||
|
|
||||||
|
try:
|
||||||
|
dev[0].set("rsn_overriding", "1")
|
||||||
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
|
dev[0].set("sae_pwe", "2")
|
||||||
|
dev[0].set("sae_groups", "")
|
||||||
|
dev[0].connect(ssid, sae_password="12345678", key_mgmt="SAE",
|
||||||
|
ieee80211w="2", ssid_protection="1",
|
||||||
|
scan_freq="2412")
|
||||||
|
finally:
|
||||||
|
dev[0].set("sae_pwe", "0")
|
||||||
|
dev[0].set("rsn_overriding", "0")
|
||||||
|
|
||||||
|
def test_rsn_override_rsnxe_extensibility(dev, apdev):
|
||||||
|
"""RSN overriding and RSNXE extensibility"""
|
||||||
|
check_sae_capab(dev[0])
|
||||||
|
|
||||||
|
ssid = "test-rsn-override"
|
||||||
|
params = hostapd.wpa2_params(ssid=ssid,
|
||||||
|
passphrase="12345678",
|
||||||
|
ieee80211w='1')
|
||||||
|
params['rsn_override_key_mgmt'] = 'SAE SAE-EXT-KEY'
|
||||||
|
params['rsn_override_pairwise'] = 'CCMP GCMP-256'
|
||||||
|
params['rsn_override_mfp'] = '2'
|
||||||
|
params['beacon_prot'] = '1'
|
||||||
|
params['sae_groups'] = '19 20'
|
||||||
|
params['sae_require_mfp'] = '1'
|
||||||
|
params['sae_pwe'] = '2'
|
||||||
|
params['rsnxe_override'] = 'f4182f0000ffffffffffffffffffffffffffeeeeeeeeeeeeeeee'
|
||||||
|
params['rsnxoe_override'] = 'dd1c506f9a2b2f0000ffffffffffffffffffffffffffeeeeeeeeeeeeeeee'
|
||||||
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
bssid = hapd.own_addr()
|
||||||
|
|
||||||
|
try:
|
||||||
|
dev[0].set("rsn_overriding", "1")
|
||||||
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
|
dev[0].set("sae_pwe", "2")
|
||||||
|
dev[0].set("sae_groups", "")
|
||||||
|
dev[0].connect(ssid, sae_password="12345678", key_mgmt="SAE",
|
||||||
|
ieee80211w="2", ssid_protection="1",
|
||||||
|
scan_freq="2412")
|
||||||
|
finally:
|
||||||
|
dev[0].set("sae_pwe", "0")
|
||||||
|
dev[0].set("rsn_overriding", "0")
|
||||||
|
|
||||||
|
def test_rsn_override_sta_only(dev, apdev):
|
||||||
|
"""RSN overriding enabled only on the STA"""
|
||||||
|
check_sae_capab(dev[0])
|
||||||
|
params = hostapd.wpa2_params(ssid="test-sae",
|
||||||
|
passphrase="12345678")
|
||||||
|
params['wpa_key_mgmt'] = 'SAE'
|
||||||
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
|
dev[0].set("sae_groups", "")
|
||||||
|
try:
|
||||||
|
dev[0].set("rsn_overriding", "1")
|
||||||
|
dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
|
||||||
|
scan_freq="2412")
|
||||||
|
finally:
|
||||||
|
dev[0].set("rsn_overriding", "0")
|
||||||
|
|
||||||
|
def test_rsn_override_compatibility_mode(dev, apdev):
|
||||||
|
"""RSN overriding and WPA3-Personal Compatibility Mode"""
|
||||||
|
check_sae_capab(dev[0])
|
||||||
|
|
||||||
|
ssid = "test-rsn-override"
|
||||||
|
params = hostapd.wpa2_params(ssid=ssid,
|
||||||
|
passphrase="12345678")
|
||||||
|
params['rsn_override_key_mgmt'] = 'SAE'
|
||||||
|
params['rsn_override_key_mgmt_2'] = 'SAE-EXT-KEY'
|
||||||
|
params['rsn_override_pairwise'] = 'CCMP'
|
||||||
|
params['rsn_override_pairwise_2'] = 'GCMP-256'
|
||||||
|
params['rsn_override_mfp'] = '2'
|
||||||
|
params['rsn_override_mfp_2'] = '2'
|
||||||
|
params['beacon_prot'] = '1'
|
||||||
|
params['sae_groups'] = '19 20'
|
||||||
|
params['sae_require_mfp'] = '1'
|
||||||
|
params['sae_pwe'] = '2'
|
||||||
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
bssid = hapd.own_addr()
|
||||||
|
|
||||||
|
try:
|
||||||
|
logger.info("RSN overriding capable STA using RSNO2E")
|
||||||
|
dev[0].set("rsn_overriding", "1")
|
||||||
|
dev[0].scan_for_bss(bssid, freq=2412)
|
||||||
|
dev[0].set("sae_pwe", "2")
|
||||||
|
dev[0].set("sae_groups", "")
|
||||||
|
dev[0].connect(ssid, sae_password="12345678",
|
||||||
|
pairwise="GCMP-256", key_mgmt="SAE-EXT-KEY",
|
||||||
|
ieee80211w="2", scan_freq="2412")
|
||||||
|
hapd.wait_sta()
|
||||||
|
dev[0].request("REMOVE_NETWORK all")
|
||||||
|
dev[0].wait_disconnected()
|
||||||
|
hapd.wait_sta_disconnect()
|
||||||
|
|
||||||
|
logger.info("RSN overriding capable STA using RSNOE")
|
||||||
|
dev[0].set("sae_pwe", "0")
|
||||||
|
dev[0].connect(ssid, sae_password="12345678",
|
||||||
|
pairwise="CCMP", key_mgmt="SAE",
|
||||||
|
ieee80211w="2", scan_freq="2412")
|
||||||
|
hapd.wait_sta()
|
||||||
|
dev[0].request("REMOVE_NETWORK all")
|
||||||
|
dev[0].wait_disconnected()
|
||||||
|
hapd.wait_sta_disconnect()
|
||||||
|
|
||||||
|
logger.info("RSN overriding capable STA using RSNE")
|
||||||
|
dev[0].connect(ssid, psk="12345678",
|
||||||
|
pairwise="CCMP", key_mgmt="WPA-PSK",
|
||||||
|
ieee80211w="0", scan_freq="2412")
|
||||||
|
hapd.wait_sta()
|
||||||
|
dev[0].request("REMOVE_NETWORK all")
|
||||||
|
dev[0].wait_disconnected()
|
||||||
|
hapd.wait_sta_disconnect()
|
||||||
|
|
||||||
|
logger.info("RSN overriding uncapable STA using RSNE")
|
||||||
|
dev[0].set("rsn_overriding", "0")
|
||||||
|
dev[0].connect(ssid, psk="12345678",
|
||||||
|
pairwise="CCMP", key_mgmt="WPA-PSK",
|
||||||
|
ieee80211w="0", scan_freq="2412")
|
||||||
|
hapd.wait_sta()
|
||||||
|
dev[0].request("REMOVE_NETWORK all")
|
||||||
|
dev[0].wait_disconnected()
|
||||||
|
hapd.wait_sta_disconnect()
|
||||||
|
finally:
|
||||||
|
dev[0].set("sae_pwe", "0")
|
||||||
|
dev[0].set("rsn_overriding", "0")
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue