aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/dbus.doxygen6
-rw-r--r--hostapd/Makefile2
-rw-r--r--hostapd/config_file.c3
-rw-r--r--hostapd/ctrl_iface.c132
-rw-r--r--hs20/client/est.c7
-rw-r--r--hs20/client/osu_client.c4
-rw-r--r--hs20/server/spp_server.c5
-rw-r--r--src/ap/ap_config.c3
-rw-r--r--src/ap/ap_config.h1
-rw-r--r--src/ap/ap_drv_ops.c13
-rw-r--r--src/ap/ap_drv_ops.h8
-rw-r--r--src/ap/ctrl_iface_ap.c16
-rw-r--r--src/ap/dfs.c14
-rw-r--r--src/ap/dpp_hostapd.c19
-rw-r--r--src/ap/dpp_hostapd.h2
-rw-r--r--src/ap/drv_callbacks.c3
-rw-r--r--src/ap/hw_features.c3
-rw-r--r--src/ap/ieee802_11.c53
-rw-r--r--src/ap/ieee802_11_shared.c17
-rw-r--r--src/ap/sta_info.c3
-rw-r--r--src/ap/wmm.c8
-rw-r--r--src/ap/wpa_auth.c50
-rw-r--r--src/ap/wpa_auth.h2
-rw-r--r--src/ap/wpa_auth_glue.c22
-rw-r--r--src/common/common_module_tests.c116
-rw-r--r--src/common/dpp.c365
-rw-r--r--src/common/dpp.h6
-rw-r--r--src/common/qca-vendor.h62
-rw-r--r--src/common/sae.c37
-rw-r--r--src/common/wpa_common.c4
-rw-r--r--src/common/wpa_ctrl.h1
-rw-r--r--src/crypto/crypto.h11
-rw-r--r--src/crypto/crypto_openssl.c21
-rw-r--r--src/crypto/crypto_wolfssl.c9
-rw-r--r--src/drivers/driver.h6
-rw-r--r--src/drivers/driver_nl80211.c85
-rw-r--r--src/drivers/driver_nl80211.h1
-rw-r--r--src/drivers/driver_nl80211_capa.c8
-rw-r--r--src/drivers/nl80211_copy.h34
-rw-r--r--src/eap_peer/tncc.c5
-rw-r--r--src/eap_server/tncs.c5
-rw-r--r--src/p2p/p2p.c11
-rw-r--r--src/rsn_supp/pmksa_cache.c2
-rw-r--r--src/tls/tlsv1_cred.c8
-rw-r--r--src/utils/base64.c35
-rw-r--r--src/utils/base64.h12
-rw-r--r--src/utils/json.c82
-rw-r--r--src/utils/json.h11
-rw-r--r--src/utils/utils_module_tests.c33
-rw-r--r--src/utils/xml_libxml2.c2
-rw-r--r--src/wps/upnp_xml.c2
-rw-r--r--src/wps/wps_er.c4
-rw-r--r--src/wps/wps_registrar.c3
-rw-r--r--src/wps/wps_upnp.c4
-rw-r--r--src/wps/wps_upnp_web.c4
-rw-r--r--tests/hwsim/test_ap_ft.py2
-rw-r--r--tests/hwsim/test_ap_hs20.py2
-rw-r--r--tests/hwsim/test_dbus.py79
-rw-r--r--tests/hwsim/test_dpp.py72
-rw-r--r--tests/hwsim/test_hapd_ctrl.py11
-rw-r--r--tests/hwsim/test_he.py1008
-rw-r--r--tests/hwsim/test_sae.py349
-rw-r--r--tests/hwsim/test_scan.py17
-rw-r--r--tests/hwsim/test_sigma_dut.py359
-rw-r--r--tests/hwsim/test_wmediumd.py16
-rw-r--r--tests/hwsim/test_wpas_mesh.py4
-rwxr-xr-xtests/hwsim/vm/parallel-vm.py13
-rw-r--r--tests/hwsim/wpasupplicant.py16
-rw-r--r--wpa_supplicant/README-DPP4
-rw-r--r--wpa_supplicant/config_file.c4
-rw-r--r--wpa_supplicant/ctrl_iface.c54
-rw-r--r--wpa_supplicant/dbus/dbus_new.c10
-rw-r--r--wpa_supplicant/dbus/dbus_new_handlers.c179
-rw-r--r--wpa_supplicant/dbus/dbus_new_handlers.h2
-rw-r--r--wpa_supplicant/dbus/dbus_new_handlers_p2p.c69
-rw-r--r--wpa_supplicant/defconfig2
-rw-r--r--wpa_supplicant/dpp_supplicant.c21
-rw-r--r--wpa_supplicant/dpp_supplicant.h1
-rw-r--r--wpa_supplicant/eapol_test.c2
-rw-r--r--wpa_supplicant/events.c20
-rw-r--r--wpa_supplicant/hs20_supplicant.c2
-rw-r--r--wpa_supplicant/interworking.c4
-rw-r--r--wpa_supplicant/scan.c109
-rw-r--r--wpa_supplicant/scan.h2
-rw-r--r--wpa_supplicant/sme.c21
-rw-r--r--wpa_supplicant/wpa_priv.c5
-rw-r--r--wpa_supplicant/wpa_supplicant.c49
-rw-r--r--wpa_supplicant/wpa_supplicant_i.h4
88 files changed, 3353 insertions, 544 deletions
diff --git a/doc/dbus.doxygen b/doc/dbus.doxygen
index 072ed34..9bca70c 100644
--- a/doc/dbus.doxygen
+++ b/doc/dbus.doxygen
@@ -1043,6 +1043,12 @@ fi.w1.wpa_supplicant1.CreateInterface.
<h3>WpsPriority - s - (read/write)</h3>
<p>Priority for the networks added through WPS</p>
</li>
+
+ <li>
+ <h3>MACAddressRandomizationMask - a{say} - (read/write)</h3>
+ <p>Masks to show which bits not to randomize with MAC address randomization. Possible keys are "scan", "sched_scan", and "pno". Values must be an array of 6 bytes.</p>
+ <p>When this property is set, the new dictionary replaces the old value, rather than merging them together. Leaving a key out of the dictionary will turn off MAC address randomization for that scan type.</p>
+ </li>
</ul>
\subsection dbus_interface_signals Signals
diff --git a/hostapd/Makefile b/hostapd/Makefile
index 42bb9e4..955e278 100644
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -121,6 +121,7 @@ CFLAGS += -DPACKAGE="hostapd" -DWPA_TRACE_BFD
LIBS += -lbfd -ldl -liberty -lz
LIBS_c += -lbfd -ldl -liberty -lz
LIBS_h += -lbfd -ldl -liberty -lz
+LIBS_n += -lbfd -ldl -liberty -lz
endif
endif
@@ -1313,7 +1314,6 @@ NOBJS += ../src/utils/wpa_debug.o
NOBJS += ../src/utils/wpabuf.o
ifdef CONFIG_WPA_TRACE
NOBJS += ../src/utils/trace.o
-LIBS_n += -lbfd
endif
HOBJS += hlr_auc_gw.o ../src/utils/common.o ../src/utils/wpa_debug.o ../src/utils/os_$(CONFIG_OS).o ../src/utils/wpabuf.o ../src/crypto/milenage.o
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 40066ad..25dc1fa 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -4156,6 +4156,9 @@ static int hostapd_config_fill(struct hostapd_config *conf,
} else if (os_strcmp(buf, "sae_commit_override") == 0) {
wpabuf_free(bss->sae_commit_override);
bss->sae_commit_override = wpabuf_parse_bin(pos);
+ } else if (os_strcmp(buf, "rsnxe_override_eapol") == 0) {
+ wpabuf_free(bss->rsnxe_override_eapol);
+ bss->rsnxe_override_eapol = wpabuf_parse_bin(pos);
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_SAE
} else if (os_strcmp(buf, "sae_password") == 0) {
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 2c44d1e..8692284 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -1326,6 +1326,33 @@ static void hostapd_disassoc_deny_mac(struct hostapd_data *hapd)
}
}
+
+static int hostapd_ctrl_iface_set_band(struct hostapd_data *hapd,
+ const char *band)
+{
+ union wpa_event_data event;
+ enum set_band setband;
+
+ if (os_strcmp(band, "AUTO") == 0)
+ setband = WPA_SETBAND_AUTO;
+ else if (os_strcmp(band, "5G") == 0)
+ setband = WPA_SETBAND_5G;
+ else if (os_strcmp(band, "2G") == 0)
+ setband = WPA_SETBAND_2G;
+ else
+ return -1;
+
+ if (hostapd_drv_set_band(hapd, setband) == 0) {
+ os_memset(&event, 0, sizeof(event));
+ event.channel_list_changed.initiator = REGDOM_SET_BY_USER;
+ event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN;
+ wpa_supplicant_event(hapd, EVENT_CHANNEL_LIST_CHANGED, &event);
+ }
+
+ return 0;
+}
+
+
static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
{
char *value;
@@ -1409,6 +1436,8 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
os_free(hapd->dpp_configurator_params);
hapd->dpp_configurator_params = os_strdup(value);
#endif /* CONFIG_DPP */
+ } else if (os_strcasecmp(cmd, "setband") == 0) {
+ ret = hostapd_ctrl_iface_set_band(hapd, value);
} else {
ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
if (ret)
@@ -3289,6 +3318,15 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
if (os_snprintf_error(reply_size, reply_len))
reply_len = -1;
}
+ } else if (os_strncmp(buf, "DPP_NFC_URI ", 12) == 0) {
+ res = hostapd_dpp_nfc_uri(hapd, buf + 12);
+ if (res < 0) {
+ reply_len = -1;
+ } else {
+ reply_len = os_snprintf(reply, reply_size, "%d", res);
+ if (os_snprintf_error(reply_size, reply_len))
+ reply_len = -1;
+ }
} else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) {
res = dpp_bootstrap_gen(hapd->iface->interfaces->dpp, buf + 18);
if (res < 0) {
@@ -4364,6 +4402,8 @@ try_again:
return -1;
}
+ wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
+
return 0;
fail:
@@ -4466,6 +4506,8 @@ fail:
eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
interface, NULL);
+ wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
+
return 0;
fail:
@@ -4535,37 +4577,48 @@ static int hostapd_ctrl_check_event_enabled(struct wpa_ctrl_dst *dst,
}
-static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
- enum wpa_msg_type type,
- const char *buf, size_t len)
+static void hostapd_ctrl_iface_send_internal(int sock, struct dl_list *ctrl_dst,
+ const char *ifname, int level,
+ const char *buf, size_t len)
{
struct wpa_ctrl_dst *dst, *next;
- struct dl_list *ctrl_dst;
struct msghdr msg;
- int idx;
- struct iovec io[2];
+ int idx, res;
+ struct iovec io[5];
char levelstr[10];
- int s;
- if (type != WPA_MSG_ONLY_GLOBAL) {
- s = hapd->ctrl_sock;
- ctrl_dst = &hapd->ctrl_dst;
- } else {
- s = hapd->iface->interfaces->global_ctrl_sock;
- ctrl_dst = &hapd->iface->interfaces->global_ctrl_dst;
- }
-
- if (s < 0 || dl_list_empty(ctrl_dst))
+ if (sock < 0 || dl_list_empty(ctrl_dst))
return;
- os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
- io[0].iov_base = levelstr;
- io[0].iov_len = os_strlen(levelstr);
- io[1].iov_base = (char *) buf;
- io[1].iov_len = len;
+ res = os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
+ if (os_snprintf_error(sizeof(levelstr), res))
+ return;
+ idx = 0;
+ if (ifname) {
+#ifdef CONFIG_CTRL_IFACE_UDP
+ io[idx].iov_base = "IFACE=";
+ io[idx].iov_len = 6;
+#else /* CONFIG_CTRL_IFACE_UDP */
+ io[idx].iov_base = "IFNAME=";
+ io[idx].iov_len = 7;
+#endif /* CONFIG_CTRL_IFACE_UDP */
+ idx++;
+ io[idx].iov_base = (char *) ifname;
+ io[idx].iov_len = os_strlen(ifname);
+ idx++;
+ io[idx].iov_base = " ";
+ io[idx].iov_len = 1;
+ idx++;
+ }
+ io[idx].iov_base = levelstr;
+ io[idx].iov_len = os_strlen(levelstr);
+ idx++;
+ io[idx].iov_base = (char *) buf;
+ io[idx].iov_len = len;
+ idx++;
os_memset(&msg, 0, sizeof(msg));
msg.msg_iov = io;
- msg.msg_iovlen = 2;
+ msg.msg_iovlen = idx;
idx = 0;
dl_list_for_each_safe(dst, next, ctrl_dst, struct wpa_ctrl_dst, list) {
@@ -4575,22 +4628,16 @@ static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
&dst->addr, dst->addrlen);
msg.msg_name = &dst->addr;
msg.msg_namelen = dst->addrlen;
- if (sendmsg(s, &msg, 0) < 0) {
+ if (sendmsg(sock, &msg, 0) < 0) {
int _errno = errno;
wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
"%d - %s",
idx, errno, strerror(errno));
dst->errors++;
if (dst->errors > 10 || _errno == ENOENT) {
- if (type != WPA_MSG_ONLY_GLOBAL)
- hostapd_ctrl_iface_detach(
- hapd, &dst->addr,
- dst->addrlen);
- else
- hostapd_global_ctrl_iface_detach(
- hapd->iface->interfaces,
- &dst->addr,
- dst->addrlen);
+ ctrl_iface_detach(ctrl_dst,
+ &dst->addr,
+ dst->addrlen);
}
} else
dst->errors = 0;
@@ -4599,4 +4646,25 @@ static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
}
}
+
+static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
+ enum wpa_msg_type type,
+ const char *buf, size_t len)
+{
+ if (type != WPA_MSG_NO_GLOBAL) {
+ hostapd_ctrl_iface_send_internal(
+ hapd->iface->interfaces->global_ctrl_sock,
+ &hapd->iface->interfaces->global_ctrl_dst,
+ type != WPA_MSG_PER_INTERFACE ?
+ NULL : hapd->conf->iface,
+ level, buf, len);
+ }
+
+ if (type != WPA_MSG_ONLY_GLOBAL) {
+ hostapd_ctrl_iface_send_internal(
+ hapd->ctrl_sock, &hapd->ctrl_dst,
+ NULL, level, buf, len);
+ }
+}
+
#endif /* CONFIG_NATIVE_WINDOWS */
diff --git a/hs20/client/est.c b/hs20/client/est.c
index db65334..97f9132 100644
--- a/hs20/client/est.c
+++ b/hs20/client/est.c
@@ -158,7 +158,7 @@ int est_load_cacerts(struct hs20_osu_client *ctx, const char *url)
return -1;
}
- pkcs7 = base64_decode((unsigned char *) resp, resp_len, &pkcs7_len);
+ pkcs7 = base64_decode(resp, resp_len, &pkcs7_len);
if (pkcs7 && pkcs7_len < resp_len / 2) {
wpa_printf(MSG_INFO, "Too short base64 decode (%u bytes; downloaded %u bytes) - assume this was binary",
(unsigned int) pkcs7_len, (unsigned int) resp_len);
@@ -639,8 +639,7 @@ int est_build_csr(struct hs20_osu_client *ctx, const char *url)
return -1;
}
- attrs = base64_decode((unsigned char *) resp, resp_len,
- &attrs_len);
+ attrs = base64_decode(resp, resp_len, &attrs_len);
os_free(resp);
if (attrs == NULL) {
@@ -734,7 +733,7 @@ int est_simple_enroll(struct hs20_osu_client *ctx, const char *url,
}
wpa_printf(MSG_DEBUG, "EST simpleenroll response: %s", resp);
- pkcs7 = base64_decode((unsigned char *) resp, resp_len, &pkcs7_len);
+ pkcs7 = base64_decode(resp, resp_len, &pkcs7_len);
if (pkcs7 == NULL) {
wpa_printf(MSG_INFO, "EST workaround - Could not decode base64, assume this is DER encoded PKCS7");
pkcs7 = os_malloc(resp_len);
diff --git a/hs20/client/osu_client.c b/hs20/client/osu_client.c
index fd99600..a94f40c 100644
--- a/hs20/client/osu_client.c
+++ b/hs20/client/osu_client.c
@@ -310,7 +310,7 @@ static int download_cert(struct hs20_osu_client *ctx, xml_node_t *params,
size_t len;
u8 digest1[SHA256_MAC_LEN], digest2[SHA256_MAC_LEN];
int res;
- unsigned char *b64;
+ char *b64;
FILE *f;
url_node = get_node(ctx->xml, params, "CertURL");
@@ -364,7 +364,7 @@ static int download_cert(struct hs20_osu_client *ctx, xml_node_t *params,
return -1;
}
- b64 = base64_encode((unsigned char *) cert, len, NULL);
+ b64 = base64_encode(cert, len, NULL);
os_free(cert);
if (b64 == NULL)
return -1;
diff --git a/hs20/server/spp_server.c b/hs20/server/spp_server.c
index 4bef0ff..a50e907 100644
--- a/hs20/server/spp_server.c
+++ b/hs20/server/spp_server.c
@@ -633,7 +633,7 @@ static xml_node_t * build_username_password(struct hs20_svc *ctx,
add_text_node(ctx, node, "Username", user);
- b64 = (char *) base64_encode((unsigned char *) pw, strlen(pw), NULL);
+ b64 = base64_encode(pw, strlen(pw), NULL);
if (b64 == NULL)
return NULL;
len = os_strlen(b64);
@@ -1602,8 +1602,7 @@ static xml_node_t * spp_exec_get_certificate(struct hs20_svc *ctx,
xml_node_create_text(ctx->xml, enroll, ns, "estUserID", user);
- b64 = (char *) base64_encode((unsigned char *) password,
- strlen(password), NULL);
+ b64 = base64_encode(password, strlen(password), NULL);
if (b64 == NULL) {
xml_node_free(ctx->xml, spp_node);
return NULL;
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 58fc3e9..7082967 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -441,7 +441,7 @@ int hostapd_setup_sae_pt(struct hostapd_bss_config *conf)
struct hostapd_ssid *ssid = &conf->ssid;
struct sae_password_entry *pw;
- if (conf->sae_pwe == 0)
+ if (conf->sae_pwe == 0 || !wpa_key_mgmt_sae(conf->wpa_key_mgmt))
return 0; /* PT not needed */
sae_deinit_pt(ssid->pt);
@@ -880,6 +880,7 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
#ifdef CONFIG_TESTING_OPTIONS
wpabuf_free(conf->own_ie_override);
wpabuf_free(conf->sae_commit_override);
+ wpabuf_free(conf->rsnxe_override_eapol);
#endif /* CONFIG_TESTING_OPTIONS */
os_free(conf->no_probe_resp_if_seen_on);
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 2a0c984..23416c6 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -664,6 +664,7 @@ struct hostapd_bss_config {
struct wpabuf *own_ie_override;
int sae_reflection_attack;
struct wpabuf *sae_commit_override;
+ struct wpabuf *rsnxe_override_eapol;
#endif /* CONFIG_TESTING_OPTIONS */
#define MESH_ENABLED BIT(0)
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index de60c79..7e6bf44 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -350,7 +350,7 @@ int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr,
u16 auth_alg)
{
if (hapd->driver == NULL || hapd->driver->add_sta_node == NULL)
- return 0;
+ return -EOPNOTSUPP;
return hapd->driver->add_sta_node(hapd->drv_priv, addr, auth_alg);
}
@@ -884,8 +884,6 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd)
{
struct drv_acs_params params;
int ret, i, acs_ch_list_all = 0;
- u8 *channels = NULL;
- unsigned int num_channels = 0;
struct hostapd_hw_modes *mode;
int *freq_list = NULL;
@@ -904,10 +902,6 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd)
mode = hapd->iface->current_mode;
if (mode) {
- channels = os_malloc(mode->num_channels);
- if (channels == NULL)
- return -1;
-
for (i = 0; i < mode->num_channels; i++) {
struct hostapd_channel_data *chan = &mode->channels[i];
if (!acs_ch_list_all &&
@@ -919,7 +913,6 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd)
(chan->flag & HOSTAPD_CHAN_RADAR))
continue;
if (!(chan->flag & HOSTAPD_CHAN_DISABLED)) {
- channels[num_channels++] = chan->chan;
int_array_add_unique(&freq_list, chan->freq);
}
}
@@ -932,8 +925,6 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd)
}
}
- params.ch_list = channels;
- params.ch_list_len = num_channels;
params.freq_list = freq_list;
params.ht_enabled = !!(hapd->iface->conf->ieee80211n);
@@ -959,7 +950,7 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd)
}
ret = hapd->driver->do_acs(hapd->drv_priv, &params);
- os_free(channels);
+ os_free(freq_list);
return ret;
}
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index 79b1302..fa413df 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -382,4 +382,12 @@ hostapd_drv_send_external_auth_status(struct hostapd_data *hapd,
return hapd->driver->send_external_auth_status(hapd->drv_priv, params);
}
+static inline int
+hostapd_drv_set_band(struct hostapd_data *hapd, enum set_band band)
+{
+ if (!hapd->driver || !hapd->drv_priv || !hapd->driver->set_band)
+ return -1;
+ return hapd->driver->set_band(hapd->drv_priv, band);
+}
+
#endif /* AP_DRV_OPS */
diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index 676a4c7..bde61ee 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -731,6 +731,22 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
if (os_snprintf_error(buflen - len, ret))
return len;
len += ret;
+
+#ifdef CONFIG_IEEE80211AX
+ if (iface->conf->ieee80211ax) {
+ ret = os_snprintf(buf + len, buflen - len,
+ "he_oper_chwidth=%d\n"
+ "he_oper_centr_freq_seg0_idx=%d\n"
+ "he_oper_centr_freq_seg1_idx=%d\n",
+ iface->conf->he_oper_chwidth,
+ iface->conf->he_oper_centr_freq_seg0_idx,
+ iface->conf->he_oper_centr_freq_seg1_idx);
+ if (os_snprintf_error(buflen - len, ret))
+ return len;
+ len += ret;
+ }
+#endif /* CONFIG_IEEE80211AX */
+
if (iface->conf->ieee80211ac && !hapd->conf->disable_11ac) {
ret = os_snprintf(buf + len, buflen - len,
"vht_oper_chwidth=%d\n"
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index c4c00fc..f70ecc9 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -515,6 +515,7 @@ static int set_dfs_state(struct hostapd_iface *iface, int freq, int ht_enabled,
int n_chans = 1, i;
struct hostapd_hw_modes *mode;
int frequency = freq;
+ int frequency2 = 0;
int ret = 0;
mode = iface->current_mode;
@@ -542,6 +543,11 @@ static int set_dfs_state(struct hostapd_iface *iface, int freq, int ht_enabled,
n_chans = 4;
frequency = cf1 - 30;
break;
+ case CHAN_WIDTH_80P80:
+ n_chans = 4;
+ frequency = cf1 - 30;
+ frequency2 = cf2 - 30;
+ break;
case CHAN_WIDTH_160:
n_chans = 8;
frequency = cf1 - 70;
@@ -557,6 +563,11 @@ static int set_dfs_state(struct hostapd_iface *iface, int freq, int ht_enabled,
for (i = 0; i < n_chans; i++) {
ret += set_dfs_state_freq(iface, frequency, state);
frequency = frequency + 20;
+
+ if (chan_width == CHAN_WIDTH_80P80) {
+ ret += set_dfs_state_freq(iface, frequency2, state);
+ frequency2 = frequency2 + 20;
+ }
}
return ret;
@@ -662,6 +673,9 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
int res, n_chans, n_chans1, start_chan_idx, start_chan_idx1;
int skip_radar = 0;
+ if (is_6ghz_freq(iface->freq))
+ return 1;
+
if (!iface->current_mode) {
/*
* This can happen with drivers that do not provide mode
diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c
index 085d423..64158fc 100644
--- a/src/ap/dpp_hostapd.c
+++ b/src/ap/dpp_hostapd.c
@@ -1,6 +1,7 @@
/*
* hostapd / DPP integration
* Copyright (c) 2017, Qualcomm Atheros, Inc.
+ * Copyright (c) 2018-2019, The Linux Foundation
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -62,6 +63,24 @@ int hostapd_dpp_qr_code(struct hostapd_data *hapd, const char *cmd)
}
+/**
+ * hostapd_dpp_nfc_uri - Parse and add DPP bootstrapping info from NFC Tag (URI)
+ * @hapd: Pointer to hostapd_data
+ * @cmd: DPP URI read from a NFC Tag (URI NDEF message)
+ * Returns: Identifier of the stored info or -1 on failure
+ */
+int hostapd_dpp_nfc_uri(struct hostapd_data *hapd, const char *cmd)
+{
+ struct dpp_bootstrap_info *bi;
+
+ bi = dpp_add_nfc_uri(hapd->iface->interfaces->dpp, cmd);
+ if (!bi)
+ return -1;
+
+ return bi->id;
+}
+
+
static void hostapd_dpp_auth_resp_retry_timeout(void *eloop_ctx,
void *timeout_ctx)
{
diff --git a/src/ap/dpp_hostapd.h b/src/ap/dpp_hostapd.h
index c1ec5d7..e151c2f 100644
--- a/src/ap/dpp_hostapd.h
+++ b/src/ap/dpp_hostapd.h
@@ -1,6 +1,7 @@
/*
* hostapd / DPP integration
* Copyright (c) 2017, Qualcomm Atheros, Inc.
+ * Copyright (c) 2018-2019, The Linux Foundation
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -10,6 +11,7 @@
#define DPP_HOSTAPD_H
int hostapd_dpp_qr_code(struct hostapd_data *hapd, const char *cmd);
+int hostapd_dpp_nfc_uri(struct hostapd_data *hapd, const char *cmd);
int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd);
int hostapd_dpp_listen(struct hostapd_data *hapd, const char *cmd);
void hostapd_dpp_listen_stop(struct hostapd_data *hapd);
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 3198bd5..e5ce76d 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -344,6 +344,9 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
} else if (res == WPA_INVALID_MGMT_GROUP_CIPHER) {
reason = WLAN_REASON_CIPHER_SUITE_REJECTED;
status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
+ } else if (res == WPA_INVALID_PMKID) {
+ reason = WLAN_REASON_INVALID_PMKID;
+ status = WLAN_STATUS_INVALID_PMKID;
} else {
reason = WLAN_REASON_INVALID_IE;
status = WLAN_STATUS_INVALID_IE;
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index 2fefaf8..8b1ed70 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -670,6 +670,9 @@ int hostapd_check_ht_capab(struct hostapd_iface *iface)
{
#ifdef CONFIG_IEEE80211N
int ret;
+
+ if (is_6ghz_freq(iface->freq))
+ return 0;
if (!iface->conf->ieee80211n)
return 0;
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 306e989..38199e0 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -98,7 +98,8 @@ u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
num++;
if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
num++;
- if (hapd->conf->sae_pwe == 1)
+ if (hapd->conf->sae_pwe == 1 &&
+ wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt))
num++;
if (num > 8) {
/* rest of the rates are encoded in Extended supported
@@ -126,7 +127,9 @@ u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
}
- if (hapd->conf->sae_pwe == 1 && count < 8) {
+ if (hapd->conf->sae_pwe == 1 &&
+ wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
+ count < 8) {
count++;
*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY;
}
@@ -148,7 +151,8 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
num++;
if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
num++;
- if (hapd->conf->sae_pwe == 1)
+ if (hapd->conf->sae_pwe == 1 &&
+ wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt))
num++;
if (num <= 8)
return eid;
@@ -179,7 +183,8 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
}
- if (hapd->conf->sae_pwe == 1) {
+ if (hapd->conf->sae_pwe == 1 &&
+ wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt)) {
count++;
if (count > 8)
*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY;
@@ -403,7 +408,8 @@ static void sae_set_state(struct sta_info *sta, enum sae_state state,
static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
- struct sta_info *sta, int update)
+ struct sta_info *sta, int update,
+ int status_code)
{
struct wpabuf *buf;
const char *password = NULL;
@@ -417,6 +423,11 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
use_pt = sta->sae->tmp->h2e;
}
+ if (status_code == WLAN_STATUS_SUCCESS)
+ use_pt = 0;
+ else if (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT)
+ use_pt = 1;
+
for (pw = hapd->conf->sae_passwords; pw; pw = pw->next) {
if (!is_broadcast_ether_addr(pw->peer_addr) &&
os_memcmp(pw->peer_addr, sta->addr, ETH_ALEN) != 0)
@@ -489,13 +500,13 @@ static struct wpabuf * auth_build_sae_confirm(struct hostapd_data *hapd,
static int auth_sae_send_commit(struct hostapd_data *hapd,
struct sta_info *sta,
- const u8 *bssid, int update)
+ const u8 *bssid, int update, int status_code)
{
struct wpabuf *data;
int reply_res;
u16 status;
- data = auth_build_sae_commit(hapd, sta, update);
+ data = auth_build_sae_commit(hapd, sta, update, status_code);
if (!data && sta->sae->tmp && sta->sae->tmp->pw_id)
return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER;
if (data == NULL)
@@ -693,7 +704,7 @@ static void auth_sae_retransmit_timer(void *eloop_ctx, void *eloop_data)
switch (sta->sae->state) {
case SAE_COMMITTED:
- ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0);
+ ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0, -1);
eloop_register_timeout(0,
hapd->dot11RSNASAERetransPeriod * 1000,
auth_sae_retransmit_timer, hapd, sta);
@@ -811,7 +822,7 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
sta->sae->tmp->h2e = status_code ==
WLAN_STATUS_SAE_HASH_TO_ELEMENT;
ret = auth_sae_send_commit(hapd, sta, bssid,
- !allow_reuse);
+ !allow_reuse, status_code);
if (ret)
return ret;
sae_set_state(sta, SAE_COMMITTED, "Sent Commit");
@@ -881,7 +892,8 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
return WLAN_STATUS_SUCCESS;
sta->sae->sync++;
- ret = auth_sae_send_commit(hapd, sta, bssid, 0);
+ ret = auth_sae_send_commit(hapd, sta, bssid, 0,
+ status_code);
if (ret)
return ret;
@@ -914,7 +926,8 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
return WLAN_STATUS_SUCCESS;
sta->sae->sync++;
- ret = auth_sae_send_commit(hapd, sta, bssid, 1);
+ ret = auth_sae_send_commit(hapd, sta, bssid, 1,
+ status_code);
if (ret)
return ret;
@@ -942,7 +955,8 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
*sta_removed = 1;
} else if (auth_transaction == 1) {
wpa_printf(MSG_DEBUG, "SAE: Start reauthentication");
- ret = auth_sae_send_commit(hapd, sta, bssid, 1);
+ ret = auth_sae_send_commit(hapd, sta, bssid, 1,
+ status_code);
if (ret)
return ret;
sae_set_state(sta, SAE_COMMITTED, "Sent Commit");
@@ -1108,8 +1122,10 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
if (!sta->sae) {
if (auth_transaction != 1 ||
!sae_status_success(hapd, status_code)) {
- resp = -1;
- goto remove_sta;
+ wpa_printf(MSG_DEBUG, "SAE: Unexpected Status Code %u",
+ status_code);
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto reply;
}
sta->sae = os_zalloc(sizeof(*sta->sae));
if (!sta->sae) {
@@ -1174,7 +1190,8 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
* Authentication frame, and the commit-scalar and
* COMMIT-ELEMENT previously sent.
*/
- resp = auth_sae_send_commit(hapd, sta, mgmt->bssid, 0);
+ resp = auth_sae_send_commit(hapd, sta, mgmt->bssid, 0,
+ status_code);
if (resp != WLAN_STATUS_SUCCESS) {
wpa_printf(MSG_ERROR,
"SAE: Failed to send commit message");
@@ -1263,9 +1280,9 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
if (sta->sae->tmp &&
check_sae_rejected_groups(
- hapd, sta->sae->tmp->peer_rejected_groups) < 0) {
+ hapd, sta->sae->tmp->peer_rejected_groups)) {
resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
- goto remove_sta;
+ goto reply;
}
if (!token && use_sae_anti_clogging(hapd) && !allow_reuse) {
@@ -1385,7 +1402,7 @@ int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta)
if (sta->sae->state != SAE_NOTHING)
return -1;
- ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0);
+ ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0, -1);
if (ret)
return -1;
diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
index f24963e..1e1cc38 100644
--- a/src/ap/ieee802_11_shared.c
+++ b/src/ap/ieee802_11_shared.c
@@ -400,14 +400,22 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
u8 *pos = eid;
u8 len = 0, i;
- if (hapd->conf->tdls & (TDLS_PROHIBIT | TDLS_PROHIBIT_CHAN_SWITCH))
+ if (hapd->conf->qos_map_set_len ||
+ (hapd->conf->tdls & (TDLS_PROHIBIT | TDLS_PROHIBIT_CHAN_SWITCH)))
len = 5;
- if (len < 4 && hapd->conf->interworking)
+ if (len < 4 &&
+ (hapd->conf->time_advertisement == 2 || hapd->conf->interworking))
len = 4;
- if (len < 3 && hapd->conf->wnm_sleep_mode)
+ if (len < 3 &&
+ (hapd->conf->wnm_sleep_mode || hapd->conf->bss_transition))
len = 3;
- if (len < 1 && hapd->iconf->obss_interval)
+ if (len < 1 &&
+ (hapd->iconf->obss_interval ||
+ (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA)))
len = 1;
+ if (len < 2 &&
+ (hapd->conf->proxy_arp || hapd->conf->coloc_intf_reporting))
+ len = 2;
if (len < 7 && hapd->conf->ssid.utf8_ssid)
len = 7;
if (len < 9 &&
@@ -1003,6 +1011,7 @@ u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len)
u8 *pos = eid;
if (!(hapd->conf->wpa & WPA_PROTO_RSN) ||
+ !wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) ||
(hapd->conf->sae_pwe != 1 && hapd->conf->sae_pwe != 2) ||
len < 3)
return pos;
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index d7734ee..cbb8752 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -1406,7 +1406,7 @@ int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen)
int res;
buf[0] = '\0';
- res = os_snprintf(buf, buflen, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ res = os_snprintf(buf, buflen, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
(flags & WLAN_STA_AUTH ? "[AUTH]" : ""),
(flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""),
(flags & WLAN_STA_AUTHORIZED ? "[AUTHORIZED]" : ""),
@@ -1425,6 +1425,7 @@ int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen)
(flags & WLAN_STA_GAS ? "[GAS]" : ""),
(flags & WLAN_STA_HT ? "[HT]" : ""),
(flags & WLAN_STA_VHT ? "[VHT]" : ""),
+ (flags & WLAN_STA_HE ? "[HE]" : ""),
(flags & WLAN_STA_VENDOR_VHT ? "[VENDOR_VHT]" : ""),
(flags & WLAN_STA_WNM_SLEEP_MODE ?
"[WNM_SLEEP_MODE]" : ""));
diff --git a/src/ap/wmm.c b/src/ap/wmm.c
index dc73493..9f52dee 100644
--- a/src/ap/wmm.c
+++ b/src/ap/wmm.c
@@ -291,10 +291,11 @@ int wmm_process_tspec(struct wmm_tspec_element *tspec)
static void wmm_addts_req(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt,
- struct wmm_tspec_element *tspec, size_t len)
+ const struct wmm_tspec_element *tspec, size_t len)
{
const u8 *end = ((const u8 *) mgmt) + len;
int res;
+ struct wmm_tspec_element tspec_resp;
if ((const u8 *) (tspec + 1) > end) {
wpa_printf(MSG_DEBUG, "WMM: TSPEC overflow in ADDTS Request");
@@ -306,10 +307,11 @@ static void wmm_addts_req(struct hostapd_data *hapd,
mgmt->u.action.u.wmm_action.dialog_token,
MAC2STR(mgmt->sa));
- res = wmm_process_tspec(tspec);
+ os_memcpy(&tspec_resp, tspec, sizeof(struct wmm_tspec_element));
+ res = wmm_process_tspec(&tspec_resp);
wpa_printf(MSG_DEBUG, "WMM: ADDTS processing result: %d", res);
- wmm_send_action(hapd, mgmt->sa, tspec, WMM_ACTION_CODE_ADDTS_RESP,
+ wmm_send_action(hapd, mgmt->sa, &tspec_resp, WMM_ACTION_CODE_ADDTS_RESP,
mgmt->u.action.u.wmm_action.dialog_token, res);
}
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 7b690d7..891cdd2 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -3139,11 +3139,12 @@ static int ocv_oci_add(struct wpa_state_machine *sm, u8 **argpos)
SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
{
- u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos, dummy_gtk[32];
+ u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde = NULL, *pos, dummy_gtk[32];
size_t gtk_len, kde_len;
struct wpa_group *gsm = sm->group;
u8 *wpa_ie;
int wpa_ie_len, secure, gtkidx, encr = 0;
+ u8 *wpa_ie_buf = NULL;
SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk);
sm->TimeoutEvt = FALSE;
@@ -3177,6 +3178,35 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
wpa_ie = wpa_ie + wpa_ie[1] + 2;
wpa_ie_len = wpa_ie[1] + 2;
}
+#ifdef CONFIG_TESTING_OPTIONS
+ if (sm->wpa_auth->conf.rsnxe_override_eapol_len) {
+ u8 *obuf = sm->wpa_auth->conf.rsnxe_override_eapol;
+ size_t olen = sm->wpa_auth->conf.rsnxe_override_eapol_len;
+ const u8 *rsnxe;
+
+ wpa_hexdump(MSG_DEBUG,
+ "TESTING: wpa_ie before RSNXE EAPOL override",
+ wpa_ie, wpa_ie_len);
+ wpa_ie_buf = os_malloc(wpa_ie_len + olen);
+ if (!wpa_ie_buf)
+ return;
+ os_memcpy(wpa_ie_buf, wpa_ie, wpa_ie_len);
+ wpa_ie = wpa_ie_buf;
+ rsnxe = get_ie(wpa_ie, wpa_ie_len, WLAN_EID_RSNX);
+ if (rsnxe) {
+ u8 rsnxe_len = 2 + rsnxe[1];
+
+ os_memmove((void *) rsnxe, rsnxe + rsnxe_len,
+ wpa_ie_len - (rsnxe - wpa_ie) - rsnxe_len);
+ wpa_ie_len -= rsnxe_len;
+ }
+ os_memcpy(wpa_ie + wpa_ie_len, obuf, olen);
+ wpa_ie_len += olen;
+ wpa_hexdump(MSG_DEBUG,
+ "TESTING: wpa_ie after RSNXE EAPOL override",
+ wpa_ie, wpa_ie_len);
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
"sending 3/4 msg of 4-Way Handshake");
if (sm->wpa == WPA_VERSION_WPA2) {
@@ -3191,7 +3221,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
* of GTK in the BSS.
*/
if (random_get_bytes(dummy_gtk, gtk_len) < 0)
- return;
+ goto done;
gtk = dummy_gtk;
}
gtkidx = gsm->GN;
@@ -3234,7 +3264,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
#endif /* CONFIG_P2P */
kde = os_malloc(kde_len);
if (kde == NULL)
- return;
+ goto done;
pos = kde;
os_memcpy(pos, wpa_ie, wpa_ie_len);
@@ -3249,8 +3279,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
if (res < 0) {
wpa_printf(MSG_ERROR, "FT: Failed to insert "
"PMKR1Name into RSN IE in EAPOL-Key data");
- os_free(kde);
- return;
+ goto done;
}
pos -= wpa_ie_len;
pos += elen;
@@ -3264,10 +3293,8 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
gtk, gtk_len);
}
pos = ieee80211w_kde_add(sm, pos);
- if (ocv_oci_add(sm, &pos) < 0) {
- os_free(kde);
- return;
- }
+ if (ocv_oci_add(sm, &pos) < 0)
+ goto done;
#ifdef CONFIG_IEEE80211R_AP
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
@@ -3293,8 +3320,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
if (res < 0) {
wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE "
"into EAPOL-Key Key Data");
- os_free(kde);
- return;
+ goto done;
}
pos += res;
@@ -3331,7 +3357,9 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL |
WPA_KEY_INFO_KEY_TYPE,
_rsc, sm->ANonce, kde, pos - kde, 0, encr);
+done:
os_free(kde);
+ os_free(wpa_ie_buf);
}
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index f627838..933a4b8 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -219,6 +219,8 @@ struct wpa_auth_config {
double corrupt_gtk_rekey_mic_probability;
u8 own_ie_override[MAX_OWN_IE_OVERRIDE];
size_t own_ie_override_len;
+ u8 rsnxe_override_eapol[MAX_OWN_IE_OVERRIDE];
+ size_t rsnxe_override_eapol_len;
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_P2P
u8 ip_addr_go[4];
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index 76f86d9..7fb0923 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -118,6 +118,14 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
wpabuf_head(conf->own_ie_override),
wconf->own_ie_override_len);
}
+ if (conf->rsnxe_override_eapol &&
+ wpabuf_len(conf->rsnxe_override_eapol) <= MAX_OWN_IE_OVERRIDE) {
+ wconf->rsnxe_override_eapol_len =
+ wpabuf_len(conf->rsnxe_override_eapol);
+ os_memcpy(wconf->rsnxe_override_eapol,
+ wpabuf_head(conf->rsnxe_override_eapol),
+ wconf->rsnxe_override_eapol_len);
+ }
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_P2P
os_memcpy(wconf->ip_addr_go, conf->ip_addr_go, 4);
@@ -891,18 +899,28 @@ hostapd_wpa_auth_add_sta(void *ctx, const u8 *sta_addr)
{
struct hostapd_data *hapd = ctx;
struct sta_info *sta;
+ int ret;
wpa_printf(MSG_DEBUG, "Add station entry for " MACSTR
" based on WPA authenticator callback",
MAC2STR(sta_addr));
- if (hostapd_add_sta_node(hapd, sta_addr, WLAN_AUTH_FT) < 0)
+ ret = hostapd_add_sta_node(hapd, sta_addr, WLAN_AUTH_FT);
+
+ /*
+ * The expected return values from hostapd_add_sta_node() are
+ * 0: successfully added STA entry
+ * -EOPNOTSUPP: driver or driver wrapper does not support/need this
+ * operations
+ * any other negative value: error in adding the STA entry */
+ if (ret < 0 && ret != -EOPNOTSUPP)
return NULL;
sta = ap_sta_add(hapd, sta_addr);
if (sta == NULL)
return NULL;
- if (hapd->driver && hapd->driver->add_sta_node)
+ if (ret == 0)
sta->added_unassoc = 1;
+
sta->ft_over_ds = 1;
if (sta->wpa_sm) {
sta->auth_alg = WLAN_AUTH_FT;
diff --git a/src/common/common_module_tests.c b/src/common/common_module_tests.c
index fb0cf43..7694c96 100644
--- a/src/common/common_module_tests.c
+++ b/src/common/common_module_tests.c
@@ -341,71 +341,71 @@ static int sae_tests(void)
struct wpabuf *buf = NULL;
struct crypto_bignum *mask = NULL;
const u8 pwe_19_x[32] = {
- 0x19, 0xd3, 0x37, 0xc9, 0x30, 0x79, 0x2b, 0x47,
- 0x2b, 0x14, 0x5f, 0xc1, 0x5b, 0x98, 0x64, 0x0a,
- 0x0e, 0x7d, 0x3b, 0xb0, 0x7d, 0xc0, 0xad, 0xee,
- 0x6f, 0xc9, 0xdf, 0x75, 0xde, 0xc2, 0xd6, 0x94
+ 0xc9, 0x30, 0x49, 0xb9, 0xe6, 0x40, 0x00, 0xf8,
+ 0x48, 0x20, 0x16, 0x49, 0xe9, 0x99, 0xf2, 0xb5,
+ 0xc2, 0x2d, 0xea, 0x69, 0xb5, 0x63, 0x2c, 0x9d,
+ 0xf4, 0xd6, 0x33, 0xb8, 0xaa, 0x1f, 0x6c, 0x1e
};
const u8 pwe_19_y[32] = {
- 0xb7, 0x8a, 0x02, 0x39, 0x20, 0x29, 0xe7, 0xf4,
- 0x52, 0x41, 0x3d, 0x35, 0x8c, 0x88, 0xd9, 0x16,
- 0xc8, 0x90, 0xba, 0x40, 0xd9, 0x93, 0xe3, 0x2d,
- 0xd0, 0x0f, 0xfb, 0x58, 0xee, 0x62, 0x74, 0x98
+ 0x73, 0x63, 0x4e, 0x94, 0xb5, 0x3d, 0x82, 0xe7,
+ 0x38, 0x3a, 0x8d, 0x25, 0x81, 0x99, 0xd9, 0xdc,
+ 0x1a, 0x5e, 0xe8, 0x26, 0x9d, 0x06, 0x03, 0x82,
+ 0xcc, 0xbf, 0x33, 0xe6, 0x14, 0xff, 0x59, 0xa0
};
const u8 pwe_15[384] = {
- 0x59, 0x00, 0x9a, 0x32, 0xbb, 0x37, 0x84, 0x60,
- 0x27, 0xeb, 0x70, 0x20, 0x57, 0x34, 0xf1, 0xb4,
- 0xde, 0x1b, 0x48, 0xfc, 0x0e, 0xa5, 0xb8, 0x65,
- 0xb1, 0xa0, 0xd4, 0xb9, 0x42, 0x1d, 0x6d, 0xdf,
- 0x8b, 0x86, 0xeb, 0x4a, 0x2c, 0x2e, 0x38, 0x06,
- 0x52, 0xae, 0x67, 0x39, 0xed, 0x7d, 0x0c, 0xd0,
- 0xea, 0x30, 0x6e, 0x50, 0xe7, 0xb1, 0x8d, 0x91,
- 0xf0, 0x05, 0x1f, 0x16, 0xf5, 0x45, 0xa7, 0x37,
- 0x21, 0x0d, 0x8a, 0x69, 0x9a, 0xd1, 0xf1, 0x8c,
- 0x2b, 0xbb, 0xd8, 0x21, 0xa2, 0x8f, 0xcc, 0xd1,
- 0x35, 0x98, 0x66, 0xf3, 0x3c, 0x03, 0xba, 0x70,
- 0x72, 0x4e, 0xe4, 0x23, 0xb5, 0x2e, 0x96, 0x5f,
- 0xdd, 0xd1, 0xae, 0x71, 0xb1, 0xc1, 0x4b, 0x69,
- 0x4e, 0x60, 0x0a, 0x08, 0x02, 0xa1, 0x6e, 0x80,
- 0x68, 0x0a, 0xe7, 0x97, 0x9f, 0x5b, 0xbf, 0xa8,
- 0x77, 0xda, 0x5b, 0x26, 0x13, 0x0a, 0xab, 0x92,
- 0x79, 0x87, 0xa3, 0x85, 0x78, 0x74, 0xae, 0xae,
- 0x01, 0xf0, 0x31, 0x8a, 0xc3, 0x96, 0xce, 0xaa,
- 0x57, 0xbf, 0xb3, 0x57, 0xce, 0x2d, 0x2d, 0x36,
- 0xda, 0x02, 0x5b, 0x12, 0xeb, 0xff, 0x13, 0x00,
- 0x9e, 0xf7, 0xae, 0xe0, 0x47, 0xa4, 0x5d, 0x0a,
- 0x88, 0x65, 0xbc, 0x66, 0x23, 0x3e, 0xf2, 0xf1,
- 0xa0, 0x64, 0x5c, 0x6b, 0xdc, 0x81, 0xe9, 0x3c,
- 0x46, 0x4f, 0x83, 0xcf, 0x9f, 0x55, 0x33, 0x8f,
- 0xaa, 0x60, 0x4b, 0xd7, 0x21, 0x73, 0x6b, 0xdb,
- 0x26, 0xad, 0x2f, 0xb7, 0xe2, 0x42, 0x56, 0x33,
- 0xdb, 0xd6, 0xb2, 0x3a, 0x7d, 0x75, 0x87, 0xda,
- 0x86, 0xc4, 0xe9, 0x41, 0x8d, 0x63, 0x19, 0x8e,
- 0x8b, 0x17, 0x95, 0xfe, 0x2b, 0x96, 0xa0, 0x38,
- 0xf1, 0xe2, 0x1d, 0x42, 0xa9, 0xe3, 0x8a, 0xa1,
- 0x61, 0x62, 0x10, 0xf8, 0xb3, 0xb2, 0x2c, 0x7b,
- 0xdf, 0xba, 0x74, 0xb2, 0x5b, 0xf6, 0xa9, 0xae,
- 0x1d, 0x21, 0x0d, 0xc0, 0x48, 0x20, 0xfc, 0x28,
- 0xf6, 0x22, 0xd2, 0xf6, 0x9c, 0x71, 0x3f, 0x9f,
- 0x32, 0xd6, 0xbb, 0x9b, 0xd3, 0x87, 0x25, 0xcf,
- 0x62, 0xd1, 0x68, 0xba, 0x55, 0x3b, 0x74, 0x2b,
- 0x1d, 0x5a, 0xe4, 0x94, 0x59, 0x3b, 0x13, 0x21,
- 0x15, 0x87, 0x3b, 0x09, 0x0e, 0xcf, 0x35, 0x60,
- 0x04, 0xa8, 0xde, 0xa1, 0x09, 0xca, 0xb8, 0x35,
- 0x1e, 0x16, 0x61, 0xed, 0xa1, 0x1f, 0x8c, 0x92,
- 0x83, 0xa5, 0x27, 0x92, 0xf2, 0x80, 0xc3, 0xcb,
- 0xdd, 0x3c, 0x0c, 0xf5, 0x8d, 0x69, 0xb3, 0xe4,
- 0xd5, 0x49, 0x4d, 0x62, 0xcb, 0xb8, 0xe3, 0x9f,
- 0x89, 0xb5, 0x57, 0xff, 0xef, 0x12, 0x37, 0x05,
- 0xb6, 0x35, 0xe5, 0xc6, 0xd9, 0x23, 0xe2, 0xeb,
- 0xe4, 0x0d, 0x1a, 0x30, 0x8f, 0x73, 0x70, 0x3a,
- 0xef, 0x5a, 0xd1, 0x8c, 0x18, 0x34, 0x1e, 0xf0,
- 0xb9, 0x08, 0x57, 0xab, 0xcb, 0x5c, 0x87, 0x10
+ 0x69, 0x68, 0x73, 0x65, 0x8f, 0x65, 0x31, 0x42,
+ 0x9f, 0x97, 0x39, 0x6f, 0xb8, 0x5f, 0x89, 0xe1,
+ 0xfc, 0xd2, 0xf6, 0x92, 0x19, 0xa9, 0x0e, 0x82,
+ 0x2f, 0xf7, 0xf4, 0xbc, 0x0b, 0xd8, 0xa7, 0x9f,
+ 0xf0, 0x80, 0x35, 0x31, 0x6f, 0xca, 0xe1, 0xa5,
+ 0x39, 0x77, 0xdc, 0x11, 0x2b, 0x0b, 0xfe, 0x2e,
+ 0x6f, 0x65, 0x6d, 0xc7, 0xd4, 0xa4, 0x5b, 0x08,
+ 0x1f, 0xd9, 0xbb, 0xe2, 0x22, 0x85, 0x31, 0x81,
+ 0x79, 0x70, 0xbe, 0xa1, 0x66, 0x58, 0x4a, 0x09,
+ 0x3c, 0x57, 0x34, 0x3c, 0x9d, 0x57, 0x8f, 0x42,
+ 0x58, 0xd0, 0x39, 0x81, 0xdb, 0x8f, 0x79, 0xa2,
+ 0x1b, 0x01, 0xcd, 0x27, 0xc9, 0xae, 0xcf, 0xcb,
+ 0x9c, 0xdb, 0x1f, 0x84, 0xb8, 0x88, 0x4e, 0x8f,
+ 0x50, 0x66, 0xb4, 0x29, 0x83, 0x1e, 0xb9, 0x89,
+ 0x0c, 0xa5, 0x47, 0x21, 0xba, 0x10, 0xd5, 0xaa,
+ 0x1a, 0x80, 0xce, 0xf1, 0x4c, 0xad, 0x16, 0xda,
+ 0x57, 0xb2, 0x41, 0x8a, 0xbe, 0x4b, 0x8c, 0xb0,
+ 0xb2, 0xeb, 0xf7, 0xa8, 0x0e, 0x3e, 0xcf, 0x22,
+ 0x8f, 0xd8, 0xb6, 0xdb, 0x79, 0x9c, 0x9b, 0x80,
+ 0xaf, 0xd7, 0x14, 0xad, 0x51, 0x82, 0xf4, 0x64,
+ 0xb6, 0x3f, 0x4c, 0x6c, 0xe5, 0x3f, 0xaa, 0x6f,
+ 0xbf, 0x3d, 0xc2, 0x3f, 0x77, 0xfd, 0xcb, 0xe1,
+ 0x9c, 0xe3, 0x1e, 0x8a, 0x0e, 0x97, 0xe2, 0x2b,
+ 0xe2, 0xdd, 0x37, 0x39, 0x88, 0xc2, 0x8e, 0xbe,
+ 0xfa, 0xac, 0x3d, 0x5b, 0x62, 0x2e, 0x1e, 0x74,
+ 0xa0, 0x9a, 0xf8, 0xed, 0xfa, 0xe1, 0xce, 0x9c,
+ 0xab, 0xbb, 0xdc, 0x36, 0xb1, 0x28, 0x46, 0x3c,
+ 0x7e, 0xa8, 0xbd, 0xb9, 0x36, 0x4c, 0x26, 0x75,
+ 0xe0, 0x17, 0x73, 0x1f, 0xe0, 0xfe, 0xf6, 0x49,
+ 0xfa, 0xa0, 0x45, 0xf4, 0x44, 0x05, 0x20, 0x27,
+ 0x25, 0xc2, 0x99, 0xde, 0x27, 0x8b, 0x70, 0xdc,
+ 0x54, 0x60, 0x90, 0x02, 0x1e, 0x29, 0x97, 0x9a,
+ 0xc4, 0xe7, 0xb6, 0xf5, 0x8b, 0xae, 0x7c, 0x34,
+ 0xaa, 0xef, 0x9b, 0xc6, 0x30, 0xf2, 0x80, 0x8d,
+ 0x80, 0x78, 0xc2, 0x55, 0x63, 0xa0, 0xa1, 0x38,
+ 0x70, 0xfb, 0xf4, 0x74, 0x8d, 0xcd, 0x87, 0x90,
+ 0xb4, 0x54, 0xc3, 0x75, 0xdf, 0x10, 0xc5, 0xb6,
+ 0xb2, 0x08, 0x59, 0x61, 0xe6, 0x68, 0xa5, 0x82,
+ 0xf8, 0x8f, 0x47, 0x30, 0x43, 0xb4, 0xdc, 0x31,
+ 0xfc, 0xbc, 0x69, 0xe7, 0xb4, 0x94, 0xb0, 0x6a,
+ 0x60, 0x59, 0x80, 0x2e, 0xd3, 0xa4, 0xe8, 0x97,
+ 0xa2, 0xa3, 0xc9, 0x08, 0x4b, 0x27, 0x6c, 0xc1,
+ 0x37, 0xe8, 0xfc, 0x5c, 0xe2, 0x54, 0x30, 0x3e,
+ 0xf8, 0xfe, 0xa2, 0xfc, 0xbb, 0xbd, 0x88, 0x6c,
+ 0x92, 0xa3, 0x2a, 0x40, 0x7a, 0x2c, 0x22, 0x38,
+ 0x8c, 0x86, 0x86, 0xfe, 0xb9, 0xd4, 0x6b, 0xd6,
+ 0x47, 0x88, 0xa7, 0xf6, 0x8e, 0x0f, 0x14, 0xad,
+ 0x1e, 0xac, 0xcf, 0x33, 0x01, 0x99, 0xc1, 0x62
};
int pt_groups[] = { 19, 20, 21, 25, 26, 28, 29, 30, 15, 0 };
struct sae_pt *pt_info, *pt;
- u8 addr1b[ETH_ALEN] = { 0x3b, 0x36, 0xc2, 0x8b, 0x83, 0x03 };
- u8 addr2b[ETH_ALEN] = { 0x58, 0x36, 0xc0, 0x64, 0x2d, 0x31 };
+ const u8 addr1b[ETH_ALEN] = { 0x00, 0x09, 0x5b, 0x66, 0xec, 0x1e };
+ const u8 addr2b[ETH_ALEN] = { 0x00, 0x0b, 0x6b, 0xd9, 0x02, 0x46 };
os_memset(&sae, 0, sizeof(sae));
buf = wpabuf_alloc(1000);
diff --git a/src/common/dpp.c b/src/common/dpp.c
index ab7072c..834fae0 100644
--- a/src/common/dpp.c
+++ b/src/common/dpp.c
@@ -830,6 +830,8 @@ const char * dpp_bootstrap_type_txt(enum dpp_bootstrap_type type)
return "QRCODE";
case DPP_BOOTSTRAP_PKEX:
return "PKEX";
+ case DPP_BOOTSTRAP_NFC_URI:
+ return "NFC-URI";
}
return "??";
}
@@ -1007,8 +1009,7 @@ static int dpp_parse_uri_pk(struct dpp_bootstrap_info *bi, const char *info)
if (!end)
return -1;
- data = base64_decode((const unsigned char *) info, end - info,
- &data_len);
+ data = base64_decode(info, end - info, &data_len);
if (!data) {
wpa_printf(MSG_DEBUG,
"DPP: Invalid base64 encoding on URI public-key");
@@ -1182,17 +1183,6 @@ static struct dpp_bootstrap_info * dpp_parse_uri(const char *uri)
}
-struct dpp_bootstrap_info * dpp_parse_qr_code(const char *uri)
-{
- struct dpp_bootstrap_info *bi;
-
- bi = dpp_parse_uri(uri);
- if (bi)
- bi->type = DPP_BOOTSTRAP_QR_CODE;
- return bi;
-}
-
-
static void dpp_debug_print_key(const char *title, EVP_PKEY *key)
{
EC_KEY *eckey;
@@ -1482,7 +1472,7 @@ int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi)
char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
const u8 *privkey, size_t privkey_len)
{
- unsigned char *base64 = NULL;
+ char *base64 = NULL;
char *pos, *end;
size_t len;
struct wpabuf *der = NULL;
@@ -1528,7 +1518,7 @@ char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
der = NULL;
if (!base64)
goto fail;
- pos = (char *) base64;
+ pos = base64;
end = pos + len;
for (;;) {
pos = os_strchr(pos, '\n');
@@ -1536,7 +1526,7 @@ char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
break;
os_memmove(pos, pos + 1, end - pos);
}
- return (char *) base64;
+ return base64;
fail:
os_free(base64);
wpabuf_free(der);
@@ -2544,10 +2534,9 @@ struct wpabuf * dpp_build_conf_req_helper(struct dpp_authentication *auth,
const char *name, int netrole_ap,
const char *mud_url, int *opclasses)
{
- size_t len, nlen;
+ size_t len, name_len;
const char *tech = "infra";
const char *dpp_name;
- char *nbuf;
struct wpabuf *buf, *json;
#ifdef CONFIG_TESTING_OPTIONS
@@ -2560,39 +2549,38 @@ struct wpabuf * dpp_build_conf_req_helper(struct dpp_authentication *auth,
#endif /* CONFIG_TESTING_OPTIONS */
dpp_name = name ? name : "Test";
- len = os_strlen(dpp_name);
- nlen = len * 6 + 1;
- nbuf = os_malloc(nlen);
- if (!nbuf)
- return NULL;
- json_escape_string(nbuf, nlen, dpp_name, len);
+ name_len = os_strlen(dpp_name);
- len = 100 + os_strlen(nbuf) + int_array_len(opclasses) * 4;
+ len = 100 + name_len * 6 + 1 + int_array_len(opclasses) * 4;
if (mud_url && mud_url[0])
len += 10 + os_strlen(mud_url);
json = wpabuf_alloc(len);
- if (!json) {
- os_free(nbuf);
+ if (!json)
return NULL;
- }
- wpabuf_printf(json,
- "{\"name\":\"%s\","
- "\"wi-fi_tech\":\"%s\","
- "\"netRole\":\"%s\"",
- nbuf, tech, netrole_ap ? "ap" : "sta");
- if (mud_url && mud_url[0])
- wpabuf_printf(json, ",\"mudurl\":\"%s\"", mud_url);
+ json_start_object(json, NULL);
+ if (json_add_string_escape(json, "name", dpp_name, name_len) < 0) {
+ wpabuf_free(json);
+ return NULL;
+ }
+ json_value_sep(json);
+ json_add_string(json, "wi-fi_tech", tech);
+ json_value_sep(json);
+ json_add_string(json, "netRole", netrole_ap ? "ap" : "sta");
+ if (mud_url && mud_url[0]) {
+ json_value_sep(json);
+ json_add_string(json, "mudurl", mud_url);
+ }
if (opclasses) {
int i;
- wpabuf_put_str(json, ",\"bandSupport\":[");
+ json_value_sep(json);
+ json_start_array(json, "bandSupport");
for (i = 0; opclasses[i]; i++)
wpabuf_printf(json, "%s%u", i ? "," : "", opclasses[i]);
- wpabuf_put_str(json, "]");
+ json_end_array(json);
}
- wpabuf_put_str(json, "}");
- os_free(nbuf);
+ json_end_object(json);
buf = dpp_build_conf_req(auth, wpabuf_head(json));
wpabuf_free(json);
@@ -4435,6 +4423,16 @@ static int dpp_configuration_parse_helper(struct dpp_authentication *auth,
#endif /* CONFIG_TESTING_OPTIONS */
}
+ pos = os_strstr(cmd, " ssid_charset=");
+ if (pos) {
+ if (conf_ap) {
+ wpa_printf(MSG_INFO,
+ "DPP: ssid64 option (ssid_charset param) not allowed for AP enrollee");
+ goto fail;
+ }
+ conf->ssid_charset = atoi(pos + 14);
+ }
+
pos = os_strstr(cmd, " pass=");
if (pos) {
size_t pass_len;
@@ -4637,7 +4635,6 @@ dpp_build_conf_start(struct dpp_authentication *auth,
struct dpp_configuration *conf, size_t tailroom)
{
struct wpabuf *buf;
- char ssid[6 * sizeof(conf->ssid) + 1];
#ifdef CONFIG_TESTING_OPTIONS
if (auth->discovery_override)
@@ -4647,21 +4644,35 @@ dpp_build_conf_start(struct dpp_authentication *auth,
buf = wpabuf_alloc(200 + tailroom);
if (!buf)
return NULL;
- wpabuf_put_str(buf, "{\"wi-fi_tech\":\"infra\",\"discovery\":");
+ json_start_object(buf, NULL);
+ json_add_string(buf, "wi-fi_tech", "infra");
+ json_value_sep(buf);
#ifdef CONFIG_TESTING_OPTIONS
if (auth->discovery_override) {
wpa_printf(MSG_DEBUG, "DPP: TESTING - discovery override: '%s'",
auth->discovery_override);
+ wpabuf_put_str(buf, "\"discovery\":");
wpabuf_put_str(buf, auth->discovery_override);
- wpabuf_put_u8(buf, ',');
+ json_value_sep(buf);
return buf;
}
#endif /* CONFIG_TESTING_OPTIONS */
- wpabuf_put_str(buf, "{\"ssid\":\"");
- json_escape_string(ssid, sizeof(ssid),
- (const char *) conf->ssid, conf->ssid_len);
- wpabuf_put_str(buf, ssid);
- wpabuf_put_str(buf, "\"},");
+ json_start_object(buf, "discovery");
+ if (((!conf->ssid_charset || auth->peer_version < 2) &&
+ json_add_string_escape(buf, "ssid", conf->ssid,
+ conf->ssid_len) < 0) ||
+ ((conf->ssid_charset && auth->peer_version >= 2) &&
+ json_add_base64url(buf, "ssid64", conf->ssid,
+ conf->ssid_len) < 0)) {
+ wpabuf_free(buf);
+ return NULL;
+ }
+ if (conf->ssid_charset > 0) {
+ json_value_sep(buf);
+ json_add_int(buf, "ssid_charset", conf->ssid_charset);
+ }
+ json_end_object(buf);
+ json_value_sep(buf);
return buf;
}
@@ -4672,37 +4683,32 @@ static int dpp_build_jwk(struct wpabuf *buf, const char *name, EVP_PKEY *key,
{
struct wpabuf *pub;
const u8 *pos;
- char *x = NULL, *y = NULL;
int ret = -1;
pub = dpp_get_pubkey_point(key, 0);
if (!pub)
goto fail;
+
+ json_start_object(buf, name);
+ json_add_string(buf, "kty", "EC");
+ json_value_sep(buf);
+ json_add_string(buf, "crv", curve->jwk_crv);
+ json_value_sep(buf);
pos = wpabuf_head(pub);
- x = (char *) base64_url_encode(pos, curve->prime_len, NULL, 0);
+ if (json_add_base64url(buf, "x", pos, curve->prime_len) < 0)
+ goto fail;
+ json_value_sep(buf);
pos += curve->prime_len;
- y = (char *) base64_url_encode(pos, curve->prime_len, NULL, 0);
- if (!x || !y)
+ if (json_add_base64url(buf, "y", pos, curve->prime_len) < 0)
goto fail;
-
- wpabuf_put_str(buf, "\"");
- wpabuf_put_str(buf, name);
- wpabuf_put_str(buf, "\":{\"kty\":\"EC\",\"crv\":\"");
- wpabuf_put_str(buf, curve->jwk_crv);
- wpabuf_put_str(buf, "\",\"x\":\"");
- wpabuf_put_str(buf, x);
- wpabuf_put_str(buf, "\",\"y\":\"");
- wpabuf_put_str(buf, y);
if (kid) {
- wpabuf_put_str(buf, "\",\"kid\":\"");
- wpabuf_put_str(buf, kid);
+ json_value_sep(buf);
+ json_add_string(buf, "kid", kid);
}
- wpabuf_put_str(buf, "\"}");
+ json_end_object(buf);
ret = 0;
fail:
wpabuf_free(pub);
- os_free(x);
- os_free(y);
return ret;
}
@@ -4711,23 +4717,15 @@ static void dpp_build_legacy_cred_params(struct wpabuf *buf,
struct dpp_configuration *conf)
{
if (conf->passphrase && os_strlen(conf->passphrase) < 64) {
- char pass[63 * 6 + 1];
-
- json_escape_string(pass, sizeof(pass), conf->passphrase,
- os_strlen(conf->passphrase));
- wpabuf_put_str(buf, "\"pass\":\"");
- wpabuf_put_str(buf, pass);
- wpabuf_put_str(buf, "\"");
- os_memset(pass, 0, sizeof(pass));
+ json_add_string_escape(buf, "pass", conf->passphrase,
+ os_strlen(conf->passphrase));
} else if (conf->psk_set) {
char psk[2 * sizeof(conf->psk) + 1];
wpa_snprintf_hex(psk, sizeof(psk),
conf->psk, sizeof(conf->psk));
- wpabuf_put_str(buf, "\"psk_hex\":\"");
- wpabuf_put_str(buf, psk);
- wpabuf_put_str(buf, "\"");
- os_memset(psk, 0, sizeof(psk));
+ json_add_string(buf, "psk_hex", psk);
+ forced_memzero(psk, sizeof(psk));
}
}
@@ -4753,7 +4751,7 @@ dpp_build_conf_obj_dpp(struct dpp_authentication *auth,
char *signed1 = NULL, *signed2 = NULL, *signed3 = NULL;
size_t tailroom;
const struct dpp_curve_params *curve;
- char jws_prot_hdr[100];
+ struct wpabuf *jws_prot_hdr;
size_t signed1_len, signed2_len, signed3_len;
struct wpabuf *dppcon = NULL;
unsigned char *signature = NULL;
@@ -4814,15 +4812,21 @@ dpp_build_conf_obj_dpp(struct dpp_authentication *auth,
auth->groups_override);
wpabuf_put_str(dppcon, "\"groups\":");
wpabuf_put_str(dppcon, auth->groups_override);
- wpabuf_put_u8(dppcon, ',');
+ json_value_sep(dppcon);
}
goto skip_groups;
}
#endif /* CONFIG_TESTING_OPTIONS */
- wpabuf_printf(dppcon, "{\"groups\":[{\"groupId\":\"%s\",",
- conf->group_id ? conf->group_id : "*");
- wpabuf_printf(dppcon, "\"netRole\":\"%s\"}],",
- dpp_netrole_str(conf->netrole));
+ json_start_object(dppcon, NULL);
+ json_start_array(dppcon, "groups");
+ json_start_object(dppcon, NULL);
+ json_add_string(dppcon, "groupId",
+ conf->group_id ? conf->group_id : "*");
+ json_value_sep(dppcon);
+ json_add_string(dppcon, "netRole", dpp_netrole_str(conf->netrole));
+ json_end_object(dppcon);
+ json_end_array(dppcon);
+ json_value_sep(dppcon);
#ifdef CONFIG_TESTING_OPTIONS
skip_groups:
#endif /* CONFIG_TESTING_OPTIONS */
@@ -4833,30 +4837,40 @@ skip_groups:
}
if (conf->netaccesskey_expiry) {
struct os_tm tm;
+ char expiry[30];
if (os_gmtime(conf->netaccesskey_expiry, &tm) < 0) {
wpa_printf(MSG_DEBUG,
"DPP: Failed to generate expiry string");
goto fail;
}
- wpabuf_printf(dppcon,
- ",\"expiry\":\"%04u-%02u-%02uT%02u:%02u:%02uZ\"",
- tm.year, tm.month, tm.day,
- tm.hour, tm.min, tm.sec);
- }
- wpabuf_put_u8(dppcon, '}');
+ os_snprintf(expiry, sizeof(expiry),
+ "%04u-%02u-%02uT%02u:%02u:%02uZ",
+ tm.year, tm.month, tm.day,
+ tm.hour, tm.min, tm.sec);
+ json_value_sep(dppcon);
+ json_add_string(dppcon, "expiry", expiry);
+ }
+ json_end_object(dppcon);
wpa_printf(MSG_DEBUG, "DPP: dppCon: %s",
(const char *) wpabuf_head(dppcon));
- os_snprintf(jws_prot_hdr, sizeof(jws_prot_hdr),
- "{\"typ\":\"dppCon\",\"kid\":\"%s\",\"alg\":\"%s\"}",
- auth->conf->kid, curve->jws_alg);
- signed1 = (char *) base64_url_encode((unsigned char *) jws_prot_hdr,
- os_strlen(jws_prot_hdr),
- &signed1_len, 0);
- signed2 = (char *) base64_url_encode(wpabuf_head(dppcon),
- wpabuf_len(dppcon),
- &signed2_len, 0);
+ jws_prot_hdr = wpabuf_alloc(100);
+ if (!jws_prot_hdr)
+ goto fail;
+ json_start_object(jws_prot_hdr, NULL);
+ json_add_string(jws_prot_hdr, "typ", "dppCon");
+ json_value_sep(jws_prot_hdr);
+ json_add_string(jws_prot_hdr, "kid", auth->conf->kid);
+ json_value_sep(jws_prot_hdr);
+ json_add_string(jws_prot_hdr, "alg", curve->jws_alg);
+ json_end_object(jws_prot_hdr);
+ signed1 = base64_url_encode(wpabuf_head(jws_prot_hdr),
+ wpabuf_len(jws_prot_hdr),
+ &signed1_len);
+ wpabuf_free(jws_prot_hdr);
+ signed2 = base64_url_encode(wpabuf_head(dppcon), wpabuf_len(dppcon),
+ &signed2_len);
if (!signed1 || !signed2)
goto fail;
@@ -4906,8 +4920,7 @@ skip_groups:
signature_len = 2 * curve->prime_len;
wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)",
signature, signature_len);
- signed3 = (char *) base64_url_encode(signature, signature_len,
- &signed3_len, 0);
+ signed3 = base64_url_encode(signature, signature_len, &signed3_len);
if (!signed3)
goto fail;
@@ -4925,10 +4938,12 @@ skip_groups:
akm_str = dpp_akm_selector_str(akm);
else
akm_str = dpp_akm_str(akm);
- wpabuf_printf(buf, "\"cred\":{\"akm\":\"%s\",", akm_str);
+ json_start_object(buf, "cred");
+ json_add_string(buf, "akm", akm_str);
+ json_value_sep(buf);
if (incl_legacy) {
dpp_build_legacy_cred_params(buf, conf);
- wpabuf_put_str(buf, ",");
+ json_value_sep(buf);
}
wpabuf_put_str(buf, "\"signedConnector\":\"");
wpabuf_put_str(buf, signed1);
@@ -4936,14 +4951,16 @@ skip_groups:
wpabuf_put_str(buf, signed2);
wpabuf_put_u8(buf, '.');
wpabuf_put_str(buf, signed3);
- wpabuf_put_str(buf, "\",");
+ wpabuf_put_str(buf, "\"");
+ json_value_sep(buf);
if (dpp_build_jwk(buf, "csign", auth->conf->csign, auth->conf->kid,
curve) < 0) {
wpa_printf(MSG_DEBUG, "DPP: Failed to build csign JWK");
goto fail;
}
- wpabuf_put_str(buf, "}}");
+ json_end_object(buf);
+ json_end_object(buf);
wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Configuration Object",
wpabuf_head(buf), wpabuf_len(buf));
@@ -4980,9 +4997,12 @@ dpp_build_conf_obj_legacy(struct dpp_authentication *auth,
akm_str = dpp_akm_selector_str(conf->akm);
else
akm_str = dpp_akm_str(conf->akm);
- wpabuf_printf(buf, "\"cred\":{\"akm\":\"%s\",", akm_str);
+ json_start_object(buf, "cred");
+ json_add_string(buf, "akm", akm_str);
+ json_value_sep(buf);
dpp_build_legacy_cred_params(buf, conf);
- wpabuf_put_str(buf, "}}");
+ json_end_object(buf);
+ json_end_object(buf);
wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Configuration Object (legacy)",
wpabuf_head(buf), wpabuf_len(buf));
@@ -5819,8 +5839,7 @@ dpp_process_signed_connector(struct dpp_signed_connector_info *info,
ret = DPP_STATUS_INVALID_CONNECTOR;
goto fail;
}
- prot_hdr = base64_url_decode((const unsigned char *) pos,
- end - pos, &prot_hdr_len);
+ prot_hdr = base64_url_decode(pos, end - pos, &prot_hdr_len);
if (!prot_hdr) {
wpa_printf(MSG_DEBUG,
"DPP: Failed to base64url decode signedConnector JWS Protected Header");
@@ -5852,8 +5871,7 @@ dpp_process_signed_connector(struct dpp_signed_connector_info *info,
goto fail;
}
signed_end = end - 1;
- info->payload = base64_url_decode((const unsigned char *) pos,
- end - pos, &info->payload_len);
+ info->payload = base64_url_decode(pos, end - pos, &info->payload_len);
if (!info->payload) {
wpa_printf(MSG_DEBUG,
"DPP: Failed to base64url decode signedConnector JWS Payload");
@@ -5864,8 +5882,7 @@ dpp_process_signed_connector(struct dpp_signed_connector_info *info,
"DPP: signedConnector - JWS Payload",
info->payload, info->payload_len);
pos = end + 1;
- signature = base64_url_decode((const unsigned char *) pos,
- os_strlen(pos), &signature_len);
+ signature = base64_url_decode(pos, os_strlen(pos), &signature_len);
if (!signature) {
wpa_printf(MSG_DEBUG,
"DPP: Failed to base64url decode signedConnector signature");
@@ -6120,6 +6137,7 @@ static int dpp_parse_conf_obj(struct dpp_authentication *auth,
int ret = -1;
struct json_token *root, *token, *discovery, *cred;
struct dpp_config_obj *conf;
+ struct wpabuf *ssid64 = NULL;
root = json_parse((const char *) conf_obj, conf_obj_len);
if (!root)
@@ -6147,28 +6165,52 @@ static int dpp_parse_conf_obj(struct dpp_authentication *auth,
goto fail;
}
- token = json_get_member(discovery, "ssid");
- if (!token || token->type != JSON_STRING) {
- dpp_auth_fail(auth, "No discovery::ssid string value found");
- goto fail;
- }
- wpa_hexdump_ascii(MSG_DEBUG, "DPP: discovery::ssid",
- token->string, os_strlen(token->string));
- if (os_strlen(token->string) > SSID_MAX_LEN) {
- dpp_auth_fail(auth, "Too long discovery::ssid string value");
- goto fail;
+ ssid64 = json_get_member_base64url(discovery, "ssid64");
+ if (ssid64) {
+ wpa_hexdump_ascii(MSG_DEBUG, "DPP: discovery::ssid64",
+ wpabuf_head(ssid64), wpabuf_len(ssid64));
+ if (wpabuf_len(ssid64) > SSID_MAX_LEN) {
+ dpp_auth_fail(auth, "Too long discovery::ssid64 value");
+ goto fail;
+ }
+ } else {
+ token = json_get_member(discovery, "ssid");
+ if (!token || token->type != JSON_STRING) {
+ dpp_auth_fail(auth,
+ "No discovery::ssid string value found");
+ goto fail;
+ }
+ wpa_hexdump_ascii(MSG_DEBUG, "DPP: discovery::ssid",
+ token->string, os_strlen(token->string));
+ if (os_strlen(token->string) > SSID_MAX_LEN) {
+ dpp_auth_fail(auth,
+ "Too long discovery::ssid string value");
+ goto fail;
+ }
}
if (auth->num_conf_obj == DPP_MAX_CONF_OBJ) {
wpa_printf(MSG_DEBUG,
"DPP: No room for this many Config Objects - ignore this one");
- json_free(root);
- return 0;
+ ret = 0;
+ goto fail;
}
conf = &auth->conf_obj[auth->num_conf_obj++];
- conf->ssid_len = os_strlen(token->string);
- os_memcpy(conf->ssid, token->string, conf->ssid_len);
+ if (ssid64) {
+ conf->ssid_len = wpabuf_len(ssid64);
+ os_memcpy(conf->ssid, wpabuf_head(ssid64), conf->ssid_len);
+ } else {
+ conf->ssid_len = os_strlen(token->string);
+ os_memcpy(conf->ssid, token->string, conf->ssid_len);
+ }
+
+ token = json_get_member(discovery, "ssid_charset");
+ if (token && token->type == JSON_NUMBER) {
+ conf->ssid_charset = token->number;
+ wpa_printf(MSG_DEBUG, "DPP: ssid_charset=%d",
+ conf->ssid_charset);
+ }
cred = json_get_member(root, "cred");
if (!cred || cred->type != JSON_OBJECT) {
@@ -6199,6 +6241,7 @@ static int dpp_parse_conf_obj(struct dpp_authentication *auth,
wpa_printf(MSG_DEBUG, "DPP: JSON parsing completed successfully");
ret = 0;
fail:
+ wpabuf_free(ssid64);
json_free(root);
return ret;
}
@@ -6487,6 +6530,7 @@ enum dpp_status_error dpp_conn_status_result_rx(struct dpp_authentication *auth,
size_t unwrapped_len = 0;
enum dpp_status_error ret = 256;
struct json_token *root = NULL, *token;
+ struct wpabuf *ssid64;
*ssid_len = 0;
*channel_list = NULL;
@@ -6561,12 +6605,12 @@ enum dpp_status_error dpp_conn_status_result_rx(struct dpp_authentication *auth,
goto fail;
}
- token = json_get_member(root, "ssid");
- if (token && token->type == JSON_STRING &&
- os_strlen(token->string) <= SSID_MAX_LEN) {
- *ssid_len = os_strlen(token->string);
- os_memcpy(ssid, token->string, *ssid_len);
+ ssid64 = json_get_member_base64url(root, "ssid64");
+ if (ssid64 && wpabuf_len(ssid64) <= SSID_MAX_LEN) {
+ *ssid_len = wpabuf_len(ssid64);
+ os_memcpy(ssid, wpabuf_head(ssid64), *ssid_len);
}
+ wpabuf_free(ssid64);
token = json_get_member(root, "channelList");
if (token && token->type == JSON_STRING &&
@@ -6593,7 +6637,7 @@ struct wpabuf * dpp_build_conn_status_result(struct dpp_authentication *auth,
const u8 *ssid, size_t ssid_len,
const char *channel_list)
{
- struct wpabuf *msg, *clear, *json;
+ struct wpabuf *msg = NULL, *clear = NULL, *json;
size_t nonce_len, clear_len, attr_len;
const u8 *addr[2];
size_t len[2];
@@ -6602,19 +6646,18 @@ struct wpabuf * dpp_build_conn_status_result(struct dpp_authentication *auth,
json = wpabuf_alloc(1000);
if (!json)
return NULL;
- wpabuf_printf(json, "{\"result\":%d", result);
+ json_start_object(json, NULL);
+ json_add_int(json, "result", result);
if (ssid) {
- char ssid_str[6 * SSID_MAX_LEN + 1];
-
- wpabuf_put_str(json, ",\"ssid\":\"");
- json_escape_string(ssid_str, sizeof(ssid_str),
- (const char *) ssid, ssid_len);
- wpabuf_put_str(json, ssid_str);
- wpabuf_put_str(json, "\"");
+ json_value_sep(json);
+ if (json_add_base64url(json, "ssid64", ssid, ssid_len) < 0)
+ goto fail;
}
- if (channel_list)
- wpabuf_printf(json, ",\"channelList\":\"%s\"", channel_list);
- wpabuf_put_str(json, "}");
+ if (channel_list) {
+ json_value_sep(json);
+ json_add_string(json, "channelList", channel_list);
+ }
+ json_end_object(json);
wpa_hexdump_ascii(MSG_DEBUG, "DPP: connStatus JSON",
wpabuf_head(json), wpabuf_len(json));
@@ -6755,8 +6798,7 @@ dpp_keygen_configurator(const char *curve, const u8 *privkey,
goto fail;
}
- conf->kid = (char *) base64_url_encode(kid_hash, sizeof(kid_hash),
- NULL, 0);
+ conf->kid = base64_url_encode(kid_hash, sizeof(kid_hash), NULL);
if (!conf->kid)
goto fail;
out:
@@ -7018,8 +7060,7 @@ dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the second dot (.)");
goto fail;
}
- own_conn = base64_url_decode((const unsigned char *) pos,
- end - pos, &own_conn_len);
+ own_conn = base64_url_decode(pos, end - pos, &own_conn_len);
if (!own_conn) {
wpa_printf(MSG_DEBUG,
"DPP: Failed to base64url decode own signedConnector JWS Payload");
@@ -8753,8 +8794,7 @@ char * dpp_corrupt_connector_signature(const char *connector)
wpa_printf(MSG_DEBUG, "DPP: Original base64url encoded signature: %s",
pos);
- signature = base64_url_decode((const unsigned char *) pos,
- os_strlen(pos), &signature_len);
+ signature = base64_url_decode(pos, os_strlen(pos), &signature_len);
if (!signature || signature_len == 0)
goto fail;
wpa_hexdump(MSG_DEBUG, "DPP: Original Connector signature",
@@ -8762,8 +8802,7 @@ char * dpp_corrupt_connector_signature(const char *connector)
signature[signature_len - 1] ^= 0x01;
wpa_hexdump(MSG_DEBUG, "DPP: Corrupted Connector signature",
signature, signature_len);
- signed3 = (char *) base64_url_encode(signature, signature_len,
- &signed3_len, 0);
+ signed3 = base64_url_encode(signature, signature_len, &signed3_len);
if (!signed3)
goto fail;
os_memcpy(pos, signed3, signed3_len);
@@ -8911,10 +8950,30 @@ struct dpp_bootstrap_info * dpp_add_qr_code(struct dpp_global *dpp,
if (!dpp)
return NULL;
- bi = dpp_parse_qr_code(uri);
+ bi = dpp_parse_uri(uri);
+ if (!bi)
+ return NULL;
+
+ bi->type = DPP_BOOTSTRAP_QR_CODE;
+ bi->id = dpp_next_id(dpp);
+ dl_list_add(&dpp->bootstrap, &bi->list);
+ return bi;
+}
+
+
+struct dpp_bootstrap_info * dpp_add_nfc_uri(struct dpp_global *dpp,
+ const char *uri)
+{
+ struct dpp_bootstrap_info *bi;
+
+ if (!dpp)
+ return NULL;
+
+ bi = dpp_parse_uri(uri);
if (!bi)
return NULL;
+ bi->type = DPP_BOOTSTRAP_NFC_URI;
bi->id = dpp_next_id(dpp);
dl_list_add(&dpp->bootstrap, &bi->list);
return bi;
@@ -8942,6 +9001,8 @@ int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd)
bi->type = DPP_BOOTSTRAP_QR_CODE;
else if (os_strstr(cmd, "type=pkex"))
bi->type = DPP_BOOTSTRAP_PKEX;
+ else if (os_strstr(cmd, "type=nfc-uri"))
+ bi->type = DPP_BOOTSTRAP_NFC_URI;
else
goto fail;
diff --git a/src/common/dpp.h b/src/common/dpp.h
index 0be26d7..7d14e76 100644
--- a/src/common/dpp.h
+++ b/src/common/dpp.h
@@ -106,6 +106,7 @@ struct dpp_curve_params {
enum dpp_bootstrap_type {
DPP_BOOTSTRAP_QR_CODE,
DPP_BOOTSTRAP_PKEX,
+ DPP_BOOTSTRAP_NFC_URI,
};
struct dpp_bootstrap_info {
@@ -169,6 +170,7 @@ enum dpp_netrole {
struct dpp_configuration {
u8 ssid[32];
size_t ssid_len;
+ int ssid_charset;
enum dpp_akm akm;
enum dpp_netrole netrole;
@@ -247,6 +249,7 @@ struct dpp_authentication {
char *connector; /* received signedConnector */
u8 ssid[SSID_MAX_LEN];
u8 ssid_len;
+ int ssid_charset;
char passphrase[64];
u8 psk[PMK_LEN];
int psk_set;
@@ -412,7 +415,6 @@ int dpp_parse_uri_chan_list(struct dpp_bootstrap_info *bi,
const char *chan_list);
int dpp_parse_uri_mac(struct dpp_bootstrap_info *bi, const char *mac);
int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info);
-struct dpp_bootstrap_info * dpp_parse_qr_code(const char *uri);
char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
const u8 *privkey, size_t privkey_len);
struct hostapd_hw_modes;
@@ -532,6 +534,8 @@ void dpp_pfs_free(struct dpp_pfs *pfs);
struct dpp_bootstrap_info * dpp_add_qr_code(struct dpp_global *dpp,
const char *uri);
+struct dpp_bootstrap_info * dpp_add_nfc_uri(struct dpp_global *dpp,
+ const char *uri);
int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd);
struct dpp_bootstrap_info *
dpp_bootstrap_get_id(struct dpp_global *dpp, unsigned int id);
diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h
index a9d284d..a0a0fb5 100644
--- a/src/common/qca-vendor.h
+++ b/src/common/qca-vendor.h
@@ -589,10 +589,11 @@ enum qca_radiotap_vendor_ids {
* by the firmware to user space for persistent storage. The attributes
* defined in enum qca_vendor_attr_interop_issues_ap are used to deliver
* the parameters.
- * @QCA_NL80211_VENDOR_SUBCMD_OEM_DATA: This command is used to send OEM data
- * binary blobs from application/service to firmware. The attributes
- * defined in enum qca_wlan_vendor_attr_oem_data_params are used to deliver
- * the parameters.
+ * @QCA_NL80211_VENDOR_SUBCMD_OEM_DATA: This command/event is used to
+ * send/receive OEM data binary blobs to/from application/service to/from
+ * firmware. The attributes defined in enum
+ * qca_wlan_vendor_attr_oem_data_params are used to deliver the
+ * parameters.
* @QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_EXT: This command/event is used
* to send/receive avoid frequency data using
* enum qca_wlan_vendor_attr_avoid_frequency_ext.
@@ -604,6 +605,10 @@ enum qca_radiotap_vendor_ids {
* @QCA_NL80211_VENDOR_SUBCMD_ADD_STA_NODE: This vendor subcommand is used to
* add the STA node details in driver/firmware. Attributes for this event
* are specified in enum qca_wlan_vendor_attr_add_sta_node_params.
+ * @QCA_NL80211_VENDOR_SUBCMD_BTC_CHAIN_MODE: This command is used to set BT
+ * coex chain mode from application/service.
+ * The attributes defined in enum qca_vendor_attr_btc_chain_mode are used
+ * to deliver the parameters.
*/
enum qca_nl80211_vendor_subcmds {
QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0,
@@ -778,6 +783,7 @@ enum qca_nl80211_vendor_subcmds {
QCA_NL80211_VENDOR_SUBCMD_OEM_DATA = 182,
QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_EXT = 183,
QCA_NL80211_VENDOR_SUBCMD_ADD_STA_NODE = 184,
+ QCA_NL80211_VENDOR_SUBCMD_BTC_CHAIN_MODE = 185,
};
enum qca_wlan_vendor_attr {
@@ -7930,17 +7936,19 @@ enum qca_vendor_oem_device_type {
};
/**
- * enum qca_wlan_vendor_attr_oem_data_params - Used by the vendor command
+ * enum qca_wlan_vendor_attr_oem_data_params - Used by the vendor command/event
* QCA_NL80211_VENDOR_SUBCMD_OEM_DATA.
*
* @QCA_WLAN_VENDOR_ATTR_OEM_DATA_CMD_DATA: The binary blob for the vendor
- * command QCA_NL80211_VENDOR_SUBCMD_OEM_DATA are carried through this attribute.
+ * command/event QCA_NL80211_VENDOR_SUBCMD_OEM_DATA are carried through this
+ * attribute.
* NLA_BINARY attribute, the max size is 1024 bytes.
*
* @QCA_WLAN_VENDOR_ATTR_OEM_DEVICE_INFO: The binary blob will be routed
* based on this field. This optional attribute is included to specify whether
- * the device type is a virtual device or a physical device for the command.
- * This attribute can be omitted for a virtual device (default) command.
+ * the device type is a virtual device or a physical device for the
+ * command/event. This attribute can be omitted for a virtual device (default)
+ * command/event.
* This u8 attribute is used to carry information for the device type using
* values defined by enum qca_vendor_oem_device_type.
*/
@@ -8000,4 +8008,42 @@ enum qca_wlan_vendor_attr_add_sta_node_params {
QCA_WLAN_VENDOR_ATTR_ADD_STA_NODE_PARAM_AFTER_LAST - 1
};
+/**
+ * enum qca_btc_chain_mode - Specifies BT coex chain mode.
+ * This enum defines the valid set of values of BT coex chain mode.
+ * These values are used by attribute %QCA_VENDOR_ATTR_BTC_CHAIN_MODE of
+ * %QCA_NL80211_VENDOR_SUBCMD_BTC_CHAIN_MODE.
+ *
+ * @QCA_BTC_CHAIN_SHARED: chains of BT and WLAN 2.4G are shared.
+ * @QCA_BTC_CHAIN_SEPARATED: chains of BT and WLAN 2.4G are separated.
+ */
+enum qca_btc_chain_mode {
+ QCA_BTC_CHAIN_SHARED = 0,
+ QCA_BTC_CHAIN_SEPARATED = 1,
+};
+
+/**
+ * enum qca_vendor_attr_btc_chain_mode - Specifies attributes for BT coex
+ * chain mode.
+ * Attributes for data used by QCA_NL80211_VENDOR_SUBCMD_BTC_CHAIN_MODE.
+ *
+ * @QCA_VENDOR_ATTR_COEX_BTC_CHAIN_MODE: u32 attribute.
+ * Indicates the BT coex chain mode, are 32-bit values from
+ * enum qca_btc_chain_mode. This attribute is mandatory.
+ *
+ * @QCA_VENDOR_ATTR_COEX_BTC_CHAIN_MODE_RESTART: flag attribute.
+ * If set, vdev should be restarted when BT coex chain mode is updated.
+ * This attribute is optional.
+ */
+enum qca_vendor_attr_btc_chain_mode {
+ QCA_VENDOR_ATTR_BTC_CHAIN_MODE_INVALID = 0,
+ QCA_VENDOR_ATTR_BTC_CHAIN_MODE = 1,
+ QCA_VENDOR_ATTR_BTC_CHAIN_MODE_RESTART = 2,
+
+ /* Keep last */
+ QCA_VENDOR_ATTR_BTC_CHAIN_MODE_LAST,
+ QCA_VENDOR_ATTR_BTC_CHAIN_MODE_MAX =
+ QCA_VENDOR_ATTR_BTC_CHAIN_MODE_LAST - 1,
+};
+
#endif /* QCA_VENDOR_H */
diff --git a/src/common/sae.c b/src/common/sae.c
index 6bb1802..bf8cc9d 100644
--- a/src/common/sae.c
+++ b/src/common/sae.c
@@ -579,20 +579,26 @@ static int sswu_curve_param(int group, int *z)
{
switch (group) {
case 19:
+ *z = -10;
+ return 0;
case 20:
+ *z = -12;
+ return 0;
case 21:
- case 28:
- *z = -2;
+ *z = -4;
return 0;
case 25:
case 29:
*z = -5;
return 0;
case 26:
- *z = -11;
+ *z = 31;
+ return 0;
+ case 28:
+ *z = -2;
return 0;
case 30:
- *z = 2;
+ *z = 7;
return 0;
}
@@ -755,23 +761,20 @@ static struct crypto_ec_point * sswu(struct crypto_ec *ec, int group,
const_time_select_bin(is_qr, bin1, bin2, prime_len, x_y);
wpa_hexdump_key(MSG_DEBUG, "SSWU: x = CSEL(l, x1, x2)", x_y, prime_len);
- /* y = sqrt(v) */
- y = crypto_bignum_init();
- /* TODO: Remove p = 3 mod 4 check and disable group 26 instead(?) */
+ /* y = sqrt(v)
+ * For prime p such that p = 3 mod 4 --> v^((p+1)/4) */
if (crypto_bignum_to_bin(prime, bin1, sizeof(bin1), prime_len) < 0)
goto fail;
- if ((bin1[prime_len - 1] & 0x03) == 3) {
- /* For prime p such that p = 3 mod 4 --> v^((p+1)/4) */
- if (!y ||
- crypto_bignum_add(prime, one, t1) < 0 ||
- crypto_bignum_rshift(t1, 2, t1) < 0 ||
- crypto_bignum_exptmod(v, t1, prime, y) < 0)
- goto fail;
- } else {
+ if ((bin1[prime_len - 1] & 0x03) != 3) {
wpa_printf(MSG_DEBUG, "SSWU: prime does not have p = 3 mod 4");
- if (!y || crypto_bignum_sqrtmod(v, prime, y) < 0)
- goto fail;
+ goto fail;
}
+ y = crypto_bignum_init();
+ if (!y ||
+ crypto_bignum_add(prime, one, t1) < 0 ||
+ crypto_bignum_rshift(t1, 2, t1) < 0 ||
+ crypto_bignum_exptmod(v, t1, prime, y) < 0)
+ goto fail;
debug_print_bignum("SSWU: y = sqrt(v)", y, prime_len);
/* l = CEQ(LSB(u), LSB(y)) */
diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
index e0f3599..ea9f7a2 100644
--- a/src/common/wpa_common.c
+++ b/src/common/wpa_common.c
@@ -686,7 +686,7 @@ int fils_key_auth_sk(const u8 *ick, size_t ick_len, const u8 *snonce,
len[2] = ETH_ALEN;
addr[3] = bssid;
len[3] = ETH_ALEN;
- if (g_sta && g_ap_len && g_ap && g_ap_len) {
+ if (g_sta && g_sta_len && g_ap && g_ap_len) {
addr[4] = g_sta;
len[4] = g_sta_len;
addr[5] = g_ap;
@@ -717,7 +717,7 @@ int fils_key_auth_sk(const u8 *ick, size_t ick_len, const u8 *snonce,
addr[1] = snonce;
addr[2] = bssid;
addr[3] = sta_addr;
- if (g_sta && g_ap_len && g_ap && g_ap_len) {
+ if (g_sta && g_sta_len && g_ap && g_ap_len) {
addr[4] = g_ap;
len[4] = g_ap_len;
addr[5] = g_sta;
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index 70ecf5d..5258189 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -171,6 +171,7 @@ extern "C" {
#define DPP_EVENT_CONN_STATUS_RESULT "DPP-CONN-STATUS-RESULT "
#define DPP_EVENT_CONFOBJ_AKM "DPP-CONFOBJ-AKM "
#define DPP_EVENT_CONFOBJ_SSID "DPP-CONFOBJ-SSID "
+#define DPP_EVENT_CONFOBJ_SSID_CHARSET "DPP-CONFOBJ-SSID-CHARSET "
#define DPP_EVENT_CONFOBJ_PASS "DPP-CONFOBJ-PASS "
#define DPP_EVENT_CONFOBJ_PSK "DPP-CONFOBJ-PSK "
#define DPP_EVENT_CONNECTOR "DPP-CONNECTOR "
diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h
index 68476db..440da03 100644
--- a/src/crypto/crypto.h
+++ b/src/crypto/crypto.h
@@ -657,17 +657,6 @@ int crypto_bignum_sqrmod(const struct crypto_bignum *a,
struct crypto_bignum *c);
/**
- * crypto_bignum_sqrtmod - returns sqrt(a) (mod b)
- * @a: Bignum
- * @b: Bignum
- * @c: Bignum; used to store the result
- * Returns: 0 on success, -1 on failure
- */
-int crypto_bignum_sqrtmod(const struct crypto_bignum *a,
- const struct crypto_bignum *b,
- struct crypto_bignum *c);
-
-/**
* crypto_bignum_rshift - r = a >> n
* @a: Bignum
* @n: Number of bits
diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
index ed46310..783b293 100644
--- a/src/crypto/crypto_openssl.c
+++ b/src/crypto/crypto_openssl.c
@@ -1533,27 +1533,6 @@ int crypto_bignum_sqrmod(const struct crypto_bignum *a,
}
-int crypto_bignum_sqrtmod(const struct crypto_bignum *a,
- const struct crypto_bignum *b,
- struct crypto_bignum *c)
-{
- BN_CTX *bnctx;
- BIGNUM *res;
-
- if (TEST_FAIL())
- return -1;
-
- bnctx = BN_CTX_new();
- if (!bnctx)
- return -1;
- res = BN_mod_sqrt((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b,
- bnctx);
- BN_CTX_free(bnctx);
-
- return res ? 0 : -1;
-}
-
-
int crypto_bignum_rshift(const struct crypto_bignum *a, int n,
struct crypto_bignum *r)
{
diff --git a/src/crypto/crypto_wolfssl.c b/src/crypto/crypto_wolfssl.c
index 3069b4a..85ce565 100644
--- a/src/crypto/crypto_wolfssl.c
+++ b/src/crypto/crypto_wolfssl.c
@@ -1226,15 +1226,6 @@ int crypto_bignum_sqrmod(const struct crypto_bignum *a,
}
-int crypto_bignum_sqrtmod(const struct crypto_bignum *a,
- const struct crypto_bignum *b,
- struct crypto_bignum *c)
-{
- /* TODO */
- return -1;
-}
-
-
int crypto_bignum_rshift(const struct crypto_bignum *a, int n,
struct crypto_bignum *r)
{
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 7b0522d..c6b7db8 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -517,7 +517,7 @@ struct wpa_driver_scan_params {
* mac_addr - MAC address used with randomization. The address cannot be
* a multicast one, i.e., bit 0 of byte 0 should not be set.
*/
- const u8 *mac_addr;
+ u8 *mac_addr;
/**
* mac_addr_mask - MAC address mask used with randomization.
@@ -2192,9 +2192,7 @@ struct drv_acs_params {
/* Configured ACS channel width */
u16 ch_width;
- /* ACS channel list info */
- unsigned int ch_list_len;
- const u8 *ch_list;
+ /* ACS frequency list info */
const int *freq_list;
};
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 6d88f78..02b9527 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -9558,6 +9558,40 @@ fail:
return -1;
}
+
+static int nl80211_add_sta_node(void *priv, const u8 *addr, u16 auth_alg)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg;
+ struct nlattr *params;
+
+ if (!drv->add_sta_node_vendor_cmd_avail)
+ return -EOPNOTSUPP;
+
+ wpa_printf(MSG_DEBUG, "nl80211: Add STA node");
+
+ 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_ADD_STA_NODE) ||
+ !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
+ (addr &&
+ nla_put(msg, QCA_WLAN_VENDOR_ATTR_ADD_STA_NODE_MAC_ADDR, ETH_ALEN,
+ addr)) ||
+ nla_put_u16(msg, QCA_WLAN_VENDOR_ATTR_ADD_STA_NODE_AUTH_ALGO,
+ auth_alg)) {
+ nlmsg_free(msg);
+ wpa_printf(MSG_ERROR,
+ "%s: err in adding vendor_cmd and vendor_data",
+ __func__);
+ return -1;
+ }
+ nla_nest_end(msg, params);
+
+ return send_and_recv_msgs(drv, msg, NULL, NULL);
+}
+
#endif /* CONFIG_DRIVER_NL80211_QCA */
@@ -10123,6 +10157,48 @@ static int hw_mode_to_qca_acs(enum hostapd_hw_mode hw_mode)
}
+static int add_acs_ch_list(struct nl_msg *msg, const int *freq_list)
+{
+ int num_channels = 0, num_freqs;
+ u8 *ch_list;
+ enum hostapd_hw_mode hw_mode;
+ int ret = 0;
+ int i;
+
+ if (!freq_list)
+ return 0;
+
+ num_freqs = int_array_len(freq_list);
+ ch_list = os_malloc(sizeof(u8) * num_freqs);
+ if (!ch_list)
+ return -1;
+
+ for (i = 0; i < num_freqs; i++) {
+ const int freq = freq_list[i];
+
+ if (freq == 0)
+ break;
+ /* Send 2.4 GHz and 5 GHz channels with
+ * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST to maintain backwards
+ * compatibility.
+ */
+ if (!(freq >= 2412 && freq <= 2484) &&
+ !(freq >= 5180 && freq <= 5900))
+ continue;
+ hw_mode = ieee80211_freq_to_chan(freq, &ch_list[num_channels]);
+ if (hw_mode != NUM_HOSTAPD_MODES)
+ num_channels++;
+ }
+
+ if (num_channels)
+ ret = nla_put(msg, QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST,
+ num_channels, ch_list);
+
+ os_free(ch_list);
+ return ret;
+}
+
+
static int add_acs_freq_list(struct nl_msg *msg, const int *freq_list)
{
int i, len, ret;
@@ -10170,9 +10246,7 @@ static int wpa_driver_do_acs(void *priv, struct drv_acs_params *params)
nla_put_flag(msg, QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED)) ||
nla_put_u16(msg, QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
params->ch_width) ||
- (params->ch_list_len &&
- nla_put(msg, QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST, params->ch_list_len,
- params->ch_list)) ||
+ add_acs_ch_list(msg, params->freq_list) ||
add_acs_freq_list(msg, params->freq_list)) {
nlmsg_free(msg);
return -ENOBUFS;
@@ -10180,9 +10254,9 @@ static int wpa_driver_do_acs(void *priv, struct drv_acs_params *params)
nla_nest_end(msg, data);
wpa_printf(MSG_DEBUG,
- "nl80211: ACS Params: HW_MODE: %d HT: %d HT40: %d VHT: %d BW: %d CH_LIST_LEN: %u",
+ "nl80211: ACS Params: HW_MODE: %d HT: %d HT40: %d VHT: %d BW: %d",
params->hw_mode, params->ht_enabled, params->ht40_enabled,
- params->vht_enabled, params->ch_width, params->ch_list_len);
+ params->vht_enabled, params->ch_width);
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
if (ret) {
@@ -11222,6 +11296,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.ignore_assoc_disallow = nl80211_ignore_assoc_disallow,
#endif /* CONFIG_MBO */
.set_bssid_blacklist = nl80211_set_bssid_blacklist,
+ .add_sta_node = nl80211_add_sta_node,
#endif /* CONFIG_DRIVER_NL80211_QCA */
.configure_data_frame_filters = nl80211_configure_data_frame_filters,
.get_ext_capab = nl80211_get_ext_capab,
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
index 7498269..716504c 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -172,6 +172,7 @@ struct wpa_driver_nl80211_data {
unsigned int fetch_bss_trans_status:1;
unsigned int roam_vendor_cmd_avail:1;
unsigned int get_supported_akm_suites_avail:1;
+ unsigned int add_sta_node_vendor_cmd_avail:1;
u64 vendor_scan_cookie;
u64 remain_on_chan_cookie;
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index cd9693c..d8630bb 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -787,6 +787,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
case QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_AKMS:
drv->get_supported_akm_suites_avail = 1;
break;
+ case QCA_NL80211_VENDOR_SUBCMD_ADD_STA_NODE:
+ drv->add_sta_node_vendor_cmd_avail = 1;
+ break;
#endif /* CONFIG_DRIVER_NL80211_QCA */
}
}
@@ -1202,10 +1205,13 @@ int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK |
WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B |
- WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192 |
WPA_DRIVER_CAPA_KEY_MGMT_OWE |
WPA_DRIVER_CAPA_KEY_MGMT_DPP;
+ if (drv->capa.enc & (WPA_DRIVER_CAPA_ENC_CCMP_256 |
+ WPA_DRIVER_CAPA_ENC_GCMP_256))
+ drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192;
+
if (drv->capa.flags & WPA_DRIVER_FLAGS_SME)
drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256 |
WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384 |
diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
index beee59c..341e0e8 100644
--- a/src/drivers/nl80211_copy.h
+++ b/src/drivers/nl80211_copy.h
@@ -249,6 +249,22 @@
*/
/**
+ * DOC: VLAN offload support for setting group keys and binding STAs to VLANs
+ *
+ * By setting @NL80211_EXT_FEATURE_VLAN_OFFLOAD flag drivers can indicate they
+ * support offloading VLAN functionality in a manner where the driver exposes a
+ * single netdev that uses VLAN tagged frames and separate VLAN-specific netdevs
+ * can then be added using RTM_NEWLINK/IFLA_VLAN_ID similarly to the Ethernet
+ * case. Frames received from stations that are not assigned to any VLAN are
+ * delivered on the main netdev and frames to such stations can be sent through
+ * that main netdev.
+ *
+ * %NL80211_CMD_NEW_KEY (for group keys), %NL80211_CMD_NEW_STATION, and
+ * %NL80211_CMD_SET_STATION will optionally specify vlan_id using
+ * %NL80211_ATTR_VLAN_ID.
+ */
+
+/**
* enum nl80211_commands - supported nl80211 commands
*
* @NL80211_CMD_UNSPEC: unspecified command to catch errors
@@ -571,6 +587,14 @@
* set of BSSID,frequency parameters is used (i.e., either the enforcing
* %NL80211_ATTR_MAC,%NL80211_ATTR_WIPHY_FREQ or the less strict
* %NL80211_ATTR_MAC_HINT and %NL80211_ATTR_WIPHY_FREQ_HINT).
+ * Driver shall not modify the IEs specified through %NL80211_ATTR_IE if
+ * %NL80211_ATTR_MAC is included. However, if %NL80211_ATTR_MAC_HINT is
+ * included, these IEs through %NL80211_ATTR_IE are specified by the user
+ * space based on the best possible BSS selected. Thus, if the driver ends
+ * up selecting a different BSS, it can modify these IEs accordingly (e.g.
+ * userspace asks the driver to perform PMKSA caching with BSS1 and the
+ * driver ends up selecting BSS2 with different PMKSA cache entry; RSNIE
+ * has to get updated with the apt PMKID).
* %NL80211_ATTR_PREV_BSSID can be used to request a reassociation within
* the ESS in case the device is already associated and an association with
* a different BSS is desired.
@@ -2373,6 +2397,9 @@ enum nl80211_commands {
* the allowed channel bandwidth configurations. (u8 attribute)
* Defined by IEEE P802.11ay/D4.0 section 9.4.2.251, Table 13.
*
+ * @NL80211_ATTR_VLAN_ID: VLAN ID (1..4094) for the station and VLAN group key
+ * (u16).
+ *
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2835,6 +2862,8 @@ enum nl80211_attrs {
NL80211_ATTR_WIPHY_EDMG_CHANNELS,
NL80211_ATTR_WIPHY_EDMG_BW_CONFIG,
+ NL80211_ATTR_VLAN_ID,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -5484,6 +5513,10 @@ enum nl80211_feature_flags {
* @NL80211_EXT_FEATURE_SAE_OFFLOAD: Device wants to do SAE authentication in
* station mode (SAE password is passed as part of the connect command).
*
+ * @NL80211_EXT_FEATURE_VLAN_OFFLOAD: The driver supports a single netdev
+ * with VLAN tagged frames and separate VLAN-specific netdevs added using
+ * vconfig similarly to the Ethernet case.
+ *
* @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
*/
@@ -5529,6 +5562,7 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_EXT_KEY_ID,
NL80211_EXT_FEATURE_STA_TX_PWR,
NL80211_EXT_FEATURE_SAE_OFFLOAD,
+ NL80211_EXT_FEATURE_VLAN_OFFLOAD,
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/src/eap_peer/tncc.c b/src/eap_peer/tncc.c
index a9bafe2..c460980 100644
--- a/src/eap_peer/tncc.c
+++ b/src/eap_peer/tncc.c
@@ -144,7 +144,7 @@ static TNC_Result TNC_TNCC_SendMessage(
TNC_MessageType messageType)
{
struct tnc_if_imc *imc;
- unsigned char *b64;
+ char *b64;
size_t b64len;
wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_SendMessage(imcID=%lu "
@@ -629,8 +629,7 @@ static unsigned char * tncc_get_base64(char *start, size_t *decoded_len)
return NULL;
*pos2 = '\0';
- decoded = base64_decode((unsigned char *) pos, os_strlen(pos),
- decoded_len);
+ decoded = base64_decode(pos, os_strlen(pos), decoded_len);
*pos2 = '<';
if (decoded == NULL) {
wpa_printf(MSG_DEBUG, "TNC: Failed to decode Base64 data");
diff --git a/src/eap_server/tncs.c b/src/eap_server/tncs.c
index 942a195..4a30486 100644
--- a/src/eap_server/tncs.c
+++ b/src/eap_server/tncs.c
@@ -179,7 +179,7 @@ static TNC_Result TNC_TNCS_SendMessage(
TNC_MessageType messageType)
{
struct tncs_data *tncs;
- unsigned char *b64;
+ char *b64;
size_t b64len;
wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_SendMessage(imvID=%lu "
@@ -678,8 +678,7 @@ static unsigned char * tncs_get_base64(char *start, size_t *decoded_len)
return NULL;
*pos2 = '\0';
- decoded = base64_decode((unsigned char *) pos, os_strlen(pos),
- decoded_len);
+ decoded = base64_decode(pos, os_strlen(pos), decoded_len);
*pos2 = '<';
if (decoded == NULL) {
wpa_printf(MSG_DEBUG, "TNC: Failed to decode Base64 data");
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index a08ba02..7c1a8a5 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -3451,12 +3451,18 @@ static void p2p_prov_disc_resp_cb(struct p2p_data *p2p, int success)
p2p->pending_action_state = P2P_NO_PENDING_ACTION;
- if (!success)
+ if (!success) {
+ if (p2p->state == P2P_SEARCH)
+ p2p_continue_find(p2p);
return;
+ }
if (!p2p->cfg->prov_disc_resp_cb ||
- p2p->cfg->prov_disc_resp_cb(p2p->cfg->cb_ctx) < 1)
+ p2p->cfg->prov_disc_resp_cb(p2p->cfg->cb_ctx) < 1) {
+ if (p2p->state == P2P_SEARCH)
+ p2p_continue_find(p2p);
return;
+ }
p2p_dbg(p2p,
"Post-Provision Discovery operations started - do not try to continue other P2P operations");
@@ -4915,6 +4921,7 @@ int p2p_send_action(struct p2p_data *p2p, unsigned int freq, const u8 *dst,
res = p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, dst, src, bssid,
buf, len, wait_time, &scheduled);
if (res == 0 && scheduled && p2p->in_listen && freq > 0 &&
+ p2p->drv_in_listen > 0 &&
(unsigned int) p2p->drv_in_listen != freq) {
p2p_dbg(p2p,
"Stop listen on %d MHz to allow a frame to be sent immediately on %d MHz",
diff --git a/src/rsn_supp/pmksa_cache.c b/src/rsn_supp/pmksa_cache.c
index d720f7b..cd4b050 100644
--- a/src/rsn_supp/pmksa_cache.c
+++ b/src/rsn_supp/pmksa_cache.c
@@ -277,7 +277,7 @@ pmksa_cache_add_entry(struct rsn_pmksa_cache *pmksa,
* pmksa_cache_flush - Flush PMKSA cache entries for a specific network
* @pmksa: Pointer to PMKSA cache data from pmksa_cache_init()
* @network_ctx: Network configuration context or %NULL to flush all entries
- * @pmk: PMK to match for or %NYLL to match all PMKs
+ * @pmk: PMK to match for or %NULL to match all PMKs
* @pmk_len: PMK length
*/
void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx,
diff --git a/src/tls/tlsv1_cred.c b/src/tls/tlsv1_cred.c
index 842e5dd..01b2f83 100644
--- a/src/tls/tlsv1_cred.c
+++ b/src/tls/tlsv1_cred.c
@@ -130,7 +130,7 @@ static int tlsv1_add_cert(struct x509_certificate **chain,
return -1;
}
- der = base64_decode(pos, end - pos, &der_len);
+ der = base64_decode((const char *) pos, end - pos, &der_len);
if (der == NULL) {
wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM "
"certificate");
@@ -293,7 +293,7 @@ static struct crypto_private_key * tlsv1_set_key_pem(const u8 *key, size_t len)
}
}
- der = base64_decode(pos, end - pos, &der_len);
+ der = base64_decode((const char *) pos, end - pos, &der_len);
if (!der)
return NULL;
pkey = crypto_private_key_import(der, der_len, NULL);
@@ -321,7 +321,7 @@ static struct crypto_private_key * tlsv1_set_key_enc_pem(const u8 *key,
if (!end)
return NULL;
- der = base64_decode(pos, end - pos, &der_len);
+ der = base64_decode((const char *) pos, end - pos, &der_len);
if (!der)
return NULL;
pkey = crypto_private_key_import(der, der_len, passwd);
@@ -1225,7 +1225,7 @@ static int tlsv1_set_dhparams_blob(struct tlsv1_credentials *cred,
return -1;
}
- der = base64_decode(pos, end - pos, &der_len);
+ der = base64_decode((const char *) pos, end - pos, &der_len);
if (der == NULL) {
wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM dhparams");
return -1;
diff --git a/src/utils/base64.c b/src/utils/base64.c
index 53a92f4..a17d2d3 100644
--- a/src/utils/base64.c
+++ b/src/utils/base64.c
@@ -12,18 +12,16 @@
#include "os.h"
#include "base64.h"
-static const unsigned char base64_table[65] =
+static const char base64_table[65] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-static const unsigned char base64_url_table[65] =
+static const char base64_url_table[65] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
-static unsigned char * base64_gen_encode(const unsigned char *src, size_t len,
- size_t *out_len,
- const unsigned char *table,
- int add_pad)
+static char * base64_gen_encode(const unsigned char *src, size_t len,
+ size_t *out_len, const char *table, int add_pad)
{
- unsigned char *out, *pos;
+ char *out, *pos;
const unsigned char *end, *in;
size_t olen;
int line_len;
@@ -83,9 +81,8 @@ static unsigned char * base64_gen_encode(const unsigned char *src, size_t len,
}
-static unsigned char * base64_gen_decode(const unsigned char *src, size_t len,
- size_t *out_len,
- const unsigned char *table)
+static unsigned char * base64_gen_decode(const char *src, size_t len,
+ size_t *out_len, const char *table)
{
unsigned char dtable[256], *out, *pos, block[4], tmp;
size_t i, count, olen;
@@ -94,12 +91,12 @@ static unsigned char * base64_gen_decode(const unsigned char *src, size_t len,
os_memset(dtable, 0x80, 256);
for (i = 0; i < sizeof(base64_table) - 1; i++)
- dtable[table[i]] = (unsigned char) i;
+ dtable[(unsigned char) table[i]] = (unsigned char) i;
dtable['='] = 0;
count = 0;
for (i = 0; i < len; i++) {
- if (dtable[src[i]] != 0x80)
+ if (dtable[(unsigned char) src[i]] != 0x80)
count++;
}
@@ -165,17 +162,15 @@ static unsigned char * base64_gen_decode(const unsigned char *src, size_t len,
* nul terminated to make it easier to use as a C string. The nul terminator is
* not included in out_len.
*/
-unsigned char * base64_encode(const unsigned char *src, size_t len,
- size_t *out_len)
+char * base64_encode(const void *src, size_t len, size_t *out_len)
{
return base64_gen_encode(src, len, out_len, base64_table, 1);
}
-unsigned char * base64_url_encode(const unsigned char *src, size_t len,
- size_t *out_len, int add_pad)
+char * base64_url_encode(const void *src, size_t len, size_t *out_len)
{
- return base64_gen_encode(src, len, out_len, base64_url_table, add_pad);
+ return base64_gen_encode(src, len, out_len, base64_url_table, 0);
}
@@ -189,15 +184,13 @@ unsigned char * base64_url_encode(const unsigned char *src, size_t len,
*
* Caller is responsible for freeing the returned buffer.
*/
-unsigned char * base64_decode(const unsigned char *src, size_t len,
- size_t *out_len)
+unsigned char * base64_decode(const char *src, size_t len, size_t *out_len)
{
return base64_gen_decode(src, len, out_len, base64_table);
}
-unsigned char * base64_url_decode(const unsigned char *src, size_t len,
- size_t *out_len)
+unsigned char * base64_url_decode(const char *src, size_t len, size_t *out_len)
{
return base64_gen_decode(src, len, out_len, base64_url_table);
}
diff --git a/src/utils/base64.h b/src/utils/base64.h
index 5a72c3e..6216f44 100644
--- a/src/utils/base64.h
+++ b/src/utils/base64.h
@@ -9,13 +9,9 @@
#ifndef BASE64_H
#define BASE64_H
-unsigned char * base64_encode(const unsigned char *src, size_t len,
- size_t *out_len);
-unsigned char * base64_decode(const unsigned char *src, size_t len,
- size_t *out_len);
-unsigned char * base64_url_encode(const unsigned char *src, size_t len,
- size_t *out_len, int add_pad);
-unsigned char * base64_url_decode(const unsigned char *src, size_t len,
- size_t *out_len);
+char * base64_encode(const void *src, size_t len, size_t *out_len);
+unsigned char * base64_decode(const char *src, size_t len, size_t *out_len);
+char * base64_url_encode(const void *src, size_t len, size_t *out_len);
+unsigned char * base64_url_decode(const char *src, size_t len, size_t *out_len);
#endif /* BASE64_H */
diff --git a/src/utils/json.c b/src/utils/json.c
index b644339..9ec7ac9 100644
--- a/src/utils/json.c
+++ b/src/utils/json.c
@@ -51,7 +51,7 @@ void json_escape_string(char *txt, size_t maxlen, const char *data, size_t len)
*txt++ = data[i];
} else {
txt += os_snprintf(txt, end - txt, "\\u%04x",
- data[i]);
+ (unsigned char) data[i]);
}
break;
}
@@ -514,8 +514,8 @@ struct wpabuf * json_get_member_base64url(struct json_token *json,
token = json_get_member(json, name);
if (!token || token->type != JSON_STRING)
return NULL;
- buf = base64_url_decode((const unsigned char *) token->string,
- os_strlen(token->string), &buflen);
+ buf = base64_url_decode(token->string, os_strlen(token->string),
+ &buflen);
if (!buf)
return NULL;
ret = wpabuf_alloc_ext_data(buf, buflen);
@@ -574,3 +574,79 @@ void json_print_tree(struct json_token *root, char *buf, size_t buflen)
buf[0] = '\0';
json_print_token(root, 1, buf, buflen);
}
+
+
+void json_add_int(struct wpabuf *json, const char *name, int val)
+{
+ wpabuf_printf(json, "\"%s\":%d", name, val);
+}
+
+
+void json_add_string(struct wpabuf *json, const char *name, const char *val)
+{
+ wpabuf_printf(json, "\"%s\":\"%s\"", name, val);
+}
+
+
+int json_add_string_escape(struct wpabuf *json, const char *name,
+ const void *val, size_t len)
+{
+ char *tmp;
+ size_t tmp_len = 6 * len + 1;
+
+ tmp = os_malloc(tmp_len);
+ if (!tmp)
+ return -1;
+ json_escape_string(tmp, tmp_len, val, len);
+ json_add_string(json, name, tmp);
+ bin_clear_free(tmp, tmp_len);
+ return 0;
+}
+
+
+int json_add_base64url(struct wpabuf *json, const char *name, const void *val,
+ size_t len)
+{
+ char *b64;
+
+ b64 = base64_url_encode(val, len, NULL);
+ if (!b64)
+ return -1;
+ json_add_string(json, name, b64);
+ os_free(b64);
+ return 0;
+}
+
+
+void json_start_object(struct wpabuf *json, const char *name)
+{
+ if (name)
+ wpabuf_printf(json, "\"%s\":", name);
+ wpabuf_put_u8(json, '{');
+}
+
+
+void json_end_object(struct wpabuf *json)
+{
+ wpabuf_put_u8(json, '}');
+}
+
+
+void json_start_array(struct wpabuf *json, const char *name)
+{
+ if (name)
+ wpabuf_printf(json, "\"%s\":", name);
+ wpabuf_put_u8(json, '[');
+}
+
+
+void json_end_array(struct wpabuf *json)
+{
+ wpabuf_put_u8(json, ']');
+}
+
+
+void json_value_sep(struct wpabuf *json)
+{
+ wpabuf_put_u8(json, ',');
+}
diff --git a/src/utils/json.h b/src/utils/json.h
index 8faa95d..ca4a2e4 100644
--- a/src/utils/json.h
+++ b/src/utils/json.h
@@ -38,5 +38,16 @@ struct json_token * json_get_member(struct json_token *json, const char *name);
struct wpabuf * json_get_member_base64url(struct json_token *json,
const char *name);
void json_print_tree(struct json_token *root, char *buf, size_t buflen);
+void json_add_int(struct wpabuf *json, const char *name, int val);
+void json_add_string(struct wpabuf *json, const char *name, const char *val);
+int json_add_string_escape(struct wpabuf *json, const char *name,
+ const void *val, size_t len);
+int json_add_base64url(struct wpabuf *json, const char *name, const void *val,
+ size_t len);
+void json_start_object(struct wpabuf *json, const char *name);
+void json_end_object(struct wpabuf *json);
+void json_start_array(struct wpabuf *json, const char *name);
+void json_end_array(struct wpabuf *json);
+void json_value_sep(struct wpabuf *json);
#endif /* JSON_H */
diff --git a/src/utils/utils_module_tests.c b/src/utils/utils_module_tests.c
index 3af4fcd..b09225d 100644
--- a/src/utils/utils_module_tests.c
+++ b/src/utils/utils_module_tests.c
@@ -296,52 +296,53 @@ static int base64_tests(void)
{
int errors = 0;
unsigned char *res;
+ char *res2;
size_t res_len;
wpa_printf(MSG_INFO, "base64 tests");
- res = base64_encode((const unsigned char *) "", ~0, &res_len);
- if (res) {
+ res2 = base64_encode("", ~0, &res_len);
+ if (res2) {
errors++;
- os_free(res);
+ os_free(res2);
}
- res = base64_encode((const unsigned char *) "=", 1, &res_len);
- if (!res || res_len != 5 || res[0] != 'P' || res[1] != 'Q' ||
- res[2] != '=' || res[3] != '=' || res[4] != '\n')
+ res2 = base64_encode("=", 1, &res_len);
+ if (!res2 || res_len != 5 || res2[0] != 'P' || res2[1] != 'Q' ||
+ res2[2] != '=' || res2[3] != '=' || res2[4] != '\n')
errors++;
- os_free(res);
+ os_free(res2);
- res = base64_encode((const unsigned char *) "=", 1, NULL);
- if (!res || res[0] != 'P' || res[1] != 'Q' ||
- res[2] != '=' || res[3] != '=' || res[4] != '\n')
+ res2 = base64_encode("=", 1, NULL);
+ if (!res2 || res2[0] != 'P' || res2[1] != 'Q' ||
+ res2[2] != '=' || res2[3] != '=' || res2[4] != '\n')
errors++;
- os_free(res);
+ os_free(res2);
- res = base64_decode((const unsigned char *) "", 0, &res_len);
+ res = base64_decode("", 0, &res_len);
if (res) {
errors++;
os_free(res);
}
- res = base64_decode((const unsigned char *) "a", 1, &res_len);
+ res = base64_decode("a", 1, &res_len);
if (res) {
errors++;
os_free(res);
}
- res = base64_decode((const unsigned char *) "====", 4, &res_len);
+ res = base64_decode("====", 4, &res_len);
if (res) {
errors++;
os_free(res);
}
- res = base64_decode((const unsigned char *) "PQ==", 4, &res_len);
+ res = base64_decode("PQ==", 4, &res_len);
if (!res || res_len != 1 || res[0] != '=')
errors++;
os_free(res);
- res = base64_decode((const unsigned char *) "P.Q-=!=*", 8, &res_len);
+ res = base64_decode("P.Q-=!=*", 8, &res_len);
if (!res || res_len != 1 || res[0] != '=')
errors++;
os_free(res);
diff --git a/src/utils/xml_libxml2.c b/src/utils/xml_libxml2.c
index 7b6d276..d73654e 100644
--- a/src/utils/xml_libxml2.c
+++ b/src/utils/xml_libxml2.c
@@ -409,7 +409,7 @@ char * xml_node_get_base64_text(struct xml_node_ctx *ctx, xml_node_t *node,
if (txt == NULL)
return NULL;
- ret = base64_decode((unsigned char *) txt, strlen(txt), &len);
+ ret = base64_decode(txt, strlen(txt), &len);
if (ret_len)
*ret_len = len;
xml_node_get_text_free(ctx, txt);
diff --git a/src/wps/upnp_xml.c b/src/wps/upnp_xml.c
index a9958ee..ca0925c 100644
--- a/src/wps/upnp_xml.c
+++ b/src/wps/upnp_xml.c
@@ -235,7 +235,7 @@ struct wpabuf * xml_get_base64_item(const char *data, const char *name,
return NULL;
}
- decoded = base64_decode((unsigned char *) msg, os_strlen(msg), &len);
+ decoded = base64_decode(msg, os_strlen(msg), &len);
os_free(msg);
if (decoded == NULL) {
*ret = UPNP_OUT_OF_MEMORY;
diff --git a/src/wps/wps_er.c b/src/wps/wps_er.c
index 06a8fda..6bded14 100644
--- a/src/wps/wps_er.c
+++ b/src/wps/wps_er.c
@@ -897,7 +897,7 @@ static struct wpabuf * wps_er_soap_hdr(const struct wpabuf *msg,
const struct sockaddr_in *dst,
char **len_ptr, char **body_ptr)
{
- unsigned char *encoded;
+ char *encoded;
size_t encoded_len;
struct wpabuf *buf;
@@ -939,7 +939,7 @@ static struct wpabuf * wps_er_soap_hdr(const struct wpabuf *msg,
wpabuf_put_str(buf, "\">\n");
if (encoded) {
wpabuf_printf(buf, "<%s>%s</%s>\n",
- arg_name, (char *) encoded, arg_name);
+ arg_name, encoded, arg_name);
os_free(encoded);
}
diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c
index 0ac5b28..671f5fe 100644
--- a/src/wps/wps_registrar.c
+++ b/src/wps/wps_registrar.c
@@ -1745,7 +1745,8 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
return -1;
}
os_free(wps->new_psk);
- wps->new_psk = base64_encode(r, sizeof(r), &wps->new_psk_len);
+ wps->new_psk = (u8 *) base64_encode(r, sizeof(r),
+ &wps->new_psk_len);
if (wps->new_psk == NULL)
return -1;
wps->new_psk_len--; /* remove newline */
diff --git a/src/wps/wps_upnp.c b/src/wps/wps_upnp.c
index ca893a4..61d2159 100644
--- a/src/wps/wps_upnp.c
+++ b/src/wps/wps_upnp.c
@@ -647,7 +647,7 @@ static int subscription_first_event(struct subscription *s)
"initial WLANEvent");
msg = build_fake_wsc_ack();
if (msg) {
- s->sm->wlanevent = (char *)
+ s->sm->wlanevent =
base64_encode(wpabuf_head(msg),
wpabuf_len(msg), NULL);
wpabuf_free(msg);
@@ -822,7 +822,7 @@ int upnp_wps_device_send_wlan_event(struct upnp_wps_device_sm *sm,
}
raw_len = pos;
- val = (char *) base64_encode(raw, raw_len, &val_len);
+ val = base64_encode(raw, raw_len, &val_len);
if (val == NULL)
goto fail;
diff --git a/src/wps/wps_upnp_web.c b/src/wps/wps_upnp_web.c
index 7548e84..3c5a97c 100644
--- a/src/wps/wps_upnp_web.c
+++ b/src/wps/wps_upnp_web.c
@@ -765,8 +765,8 @@ static void web_connection_send_reply(struct http_request *req,
if (reply) {
size_t len;
- replydata = (char *) base64_encode(wpabuf_head(reply),
- wpabuf_len(reply), &len);
+ replydata = base64_encode(wpabuf_head(reply), wpabuf_len(reply),
+ &len);
} else
replydata = NULL;
diff --git a/tests/hwsim/test_ap_ft.py b/tests/hwsim/test_ap_ft.py
index cc79ea3..66ca8cf 100644
--- a/tests/hwsim/test_ap_ft.py
+++ b/tests/hwsim/test_ap_ft.py
@@ -1871,7 +1871,7 @@ def test_ap_ft_ap_oom4(dev, apdev):
if dev[0].get_status_field('bssid') != bssid1:
raise Exception("Did not roam to AP1")
- with fail_test(hapd0, 1, "wpa_auth_get_seqnum;wpa_ft_gtk_subelem"):
+ with fail_test(hapd0, 1, "i802_get_seqnum;wpa_ft_gtk_subelem"):
dev[0].roam(bssid0)
if dev[0].get_status_field('bssid') != bssid0:
raise Exception("Did not roam to AP0")
diff --git a/tests/hwsim/test_ap_hs20.py b/tests/hwsim/test_ap_hs20.py
index fb12152..1c4c0fa 100644
--- a/tests/hwsim/test_ap_hs20.py
+++ b/tests/hwsim/test_ap_hs20.py
@@ -5437,7 +5437,7 @@ def test_ap_hs20_cred_and_no_roaming_consortium(dev, apdev):
'domain': "example.com",
'roaming_consortium': "112234",
'eap': 'TTLS'})
- interworking_select(dev[0], bssid, "home", freq=2412, no_match=True)
+ interworking_select(dev[0], bssid, "home", freq=2412)
def test_ap_hs20_interworking_oom(dev, apdev):
"""Hotspot 2.0 network selection and OOM"""
diff --git a/tests/hwsim/test_dbus.py b/tests/hwsim/test_dbus.py
index 33a6b76..41661b8 100644
--- a/tests/hwsim/test_dbus.py
+++ b/tests/hwsim/test_dbus.py
@@ -1153,6 +1153,85 @@ def test_dbus_scan(dev, apdev):
raise Exception("FlushBSS() did not remove scan results from BSSs property")
iface.FlushBSS(1)
+def test_dbus_scan_rand(dev, apdev):
+ """D-Bus MACAddressRandomizationMask property Get/Set"""
+ try:
+ run_dbus_scan_rand(dev, apdev)
+ finally:
+ dev[0].request("MAC_RAND_SCAN all enable=0")
+
+def run_dbus_scan_rand(dev, apdev):
+ (bus, wpas_obj, path, if_obj) = prepare_dbus(dev[0])
+ iface = dbus.Interface(if_obj, WPAS_DBUS_IFACE)
+
+ res = if_obj.Get(WPAS_DBUS_IFACE, "MACAddressRandomizationMask",
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ if len(res) != 0:
+ logger.info(str(res))
+ raise Exception("Unexpected initial MACAddressRandomizationMask value")
+
+ try:
+ if_obj.Set(WPAS_DBUS_IFACE, "MACAddressRandomizationMask", "foo",
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ raise Exception("Invalid Set accepted")
+ except dbus.exceptions.DBusException as e:
+ if "InvalidArgs: invalid message format" not in str(e):
+ raise Exception("Unexpected error message: " + str(e))
+
+ try:
+ if_obj.Set(WPAS_DBUS_IFACE, "MACAddressRandomizationMask",
+ {"foo": "bar"},
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ raise Exception("Invalid Set accepted")
+ except dbus.exceptions.DBusException as e:
+ if "wpas_dbus_setter_mac_address_randomization_mask: mask was not a byte array" not in str(e):
+ raise Exception("Unexpected error message: " + str(e))
+
+ try:
+ if_obj.Set(WPAS_DBUS_IFACE, "MACAddressRandomizationMask",
+ {"foo": dbus.ByteArray(b'123456')},
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ raise Exception("Invalid Set accepted")
+ except dbus.exceptions.DBusException as e:
+ if 'wpas_dbus_setter_mac_address_randomization_mask: bad scan type "foo"' not in str(e):
+ raise Exception("Unexpected error message: " + str(e))
+
+ try:
+ if_obj.Set(WPAS_DBUS_IFACE, "MACAddressRandomizationMask",
+ {"scan": dbus.ByteArray(b'12345')},
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ raise Exception("Invalid Set accepted")
+ except dbus.exceptions.DBusException as e:
+ if 'wpas_dbus_setter_mac_address_randomization_mask: malformed MAC mask given' not in str(e):
+ raise Exception("Unexpected error message: " + str(e))
+
+ if_obj.Set(WPAS_DBUS_IFACE, "MACAddressRandomizationMask",
+ {"scan": dbus.ByteArray(b'123456')},
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ res = if_obj.Get(WPAS_DBUS_IFACE, "MACAddressRandomizationMask",
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ if len(res) != 1:
+ logger.info(str(res))
+ raise Exception("Unexpected MACAddressRandomizationMask value")
+
+ try:
+ if_obj.Set(WPAS_DBUS_IFACE, "MACAddressRandomizationMask",
+ {"scan": dbus.ByteArray(b'123456'),
+ "sched_scan": dbus.ByteArray(b'987654')},
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ except dbus.exceptions.DBusException as e:
+ # sched_scan is unlikely to be supported
+ pass
+
+ if_obj.Set(WPAS_DBUS_IFACE, "MACAddressRandomizationMask",
+ dbus.Dictionary({}, signature='sv'),
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ res = if_obj.Get(WPAS_DBUS_IFACE, "MACAddressRandomizationMask",
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ if len(res) != 0:
+ logger.info(str(res))
+ raise Exception("Unexpected MACAddressRandomizationMask value")
+
def test_dbus_scan_busy(dev, apdev):
"""D-Bus scan trigger rejection when busy with previous scan"""
(bus, wpas_obj, path, if_obj) = prepare_dbus(dev[0])
diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py
index 123d57a..3ff9ef4 100644
--- a/tests/hwsim/test_dpp.py
+++ b/tests/hwsim/test_dpp.py
@@ -1624,6 +1624,7 @@ def update_hapd_config(hapd):
logger.info("Update AP configuration to use key_mgmt=DPP")
hapd.disable()
hapd.set("ssid", ssid)
+ hapd.set("utf8_ssid", "1")
hapd.set("wpa", "2")
hapd.set("wpa_key_mgmt", "DPP")
hapd.set("ieee80211w", "2")
@@ -1776,6 +1777,13 @@ def test_dpp_auto_connect_legacy(dev, apdev):
finally:
dev[0].set("dpp_config_processing", "0")
+def test_dpp_auto_connect_legacy_ssid_charset(dev, apdev):
+ """DPP and auto connect (legacy, ssid_charset)"""
+ try:
+ run_dpp_auto_connect_legacy(dev, apdev, ssid_charset=12345)
+ finally:
+ dev[0].set("dpp_config_processing", "0")
+
def test_dpp_auto_connect_legacy_sae_1(dev, apdev):
"""DPP and auto connect (legacy SAE)"""
try:
@@ -1814,6 +1822,7 @@ def test_dpp_auto_connect_legacy_psk_sae_3(dev, apdev):
dev[0].set("dpp_config_processing", "0")
def run_dpp_auto_connect_legacy(dev, apdev, conf='sta-psk',
+ ssid_charset=None,
psk_sae=False, sae_only=False):
check_dpp_capab(dev[0])
check_dpp_capab(dev[1])
@@ -1837,8 +1846,16 @@ def run_dpp_auto_connect_legacy(dev, apdev, conf='sta-psk',
dev[0].dpp_listen(2412)
dev[1].dpp_auth_init(uri=uri0, conf=conf, ssid="dpp-legacy",
+ ssid_charset=ssid_charset,
passphrase="secret passphrase")
wait_auth_success(dev[0], dev[1], configurator=dev[1], enrollee=dev[0])
+ if ssid_charset:
+ ev = dev[0].wait_event(["DPP-CONFOBJ-SSID-CHARSET"], timeout=1)
+ if ev is None:
+ raise Exception("ssid_charset not reported")
+ charset = ev.split(' ')[1]
+ if charset != str(ssid_charset):
+ raise Exception("Incorrect ssid_charset reported: " + ev)
ev = dev[0].wait_event(["DPP-NETWORK-ID"], timeout=1)
if ev is None:
raise Exception("DPP network profile not generated")
@@ -4799,3 +4816,58 @@ def test_dpp_mud_url_hostapd(dev, apdev):
dev[0].dpp_auth_init(uri=uri, conf="ap-dpp", configurator=conf_id)
wait_auth_success(hapd, dev[0], configurator=dev[0], enrollee=hapd)
update_hapd_config(hapd)
+
+def test_dpp_config_save(dev, apdev, params):
+ """DPP configuration saving"""
+ config = os.path.join(params['logdir'], 'dpp_config_save.conf')
+ run_dpp_config_save(dev, apdev, config, "test", '"test"')
+
+def test_dpp_config_save2(dev, apdev, params):
+ """DPP configuration saving (2)"""
+ config = os.path.join(params['logdir'], 'dpp_config_save2.conf')
+ run_dpp_config_save(dev, apdev, config, "\\u0001*", '012a')
+
+def test_dpp_config_save3(dev, apdev, params):
+ """DPP configuration saving (3)"""
+ config = os.path.join(params['logdir'], 'dpp_config_save3.conf')
+ run_dpp_config_save(dev, apdev, config, "\\u0001*\\u00c2\\u00bc\\u00c3\\u009e\\u00c3\\u00bf", '012ac2bcc39ec3bf')
+
+def run_dpp_config_save(dev, apdev, config, conf_ssid, exp_ssid):
+ with open(config, "w") as f:
+ f.write("update_config=1\n" +
+ "dpp_config_processing=1\n")
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add("wlan5", config=config)
+ check_dpp_capab(wpas)
+ conf = '{"wi-fi_tech":"infra", "discovery":{"ssid":"' + conf_ssid + '"},"cred":{"akm":"psk","pass":"secret passphrase"}}'
+ dev[1].set("dpp_config_obj_override", conf)
+ dpp_dev = [wpas, dev[1]]
+ run_dpp_qr_code_auth_unicast(dpp_dev, apdev, "prime256v1",
+ require_conf_success=True)
+ if "OK" not in wpas.request("SAVE_CONFIG"):
+ raise Exception("Failed to save configuration file")
+ with open(config, "r") as f:
+ data = f.read()
+ logger.info("Saved configuration:\n" + data)
+ if 'ssid=' + exp_ssid + '\n' not in data:
+ raise Exception("SSID not saved")
+ if 'psk="secret passphrase"' not in data:
+ raise Exception("Passphtase not saved")
+
+def test_dpp_nfc_uri(dev, apdev):
+ """DPP bootstrapping via NFC URI record"""
+ check_dpp_capab(dev[0])
+ check_dpp_capab(dev[1])
+
+ id = dev[0].dpp_bootstrap_gen(type="nfc-uri", chan="81/1", mac=True)
+ uri = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id)
+ logger.info("Generated URI: " + uri)
+ info = dev[0].request("DPP_BOOTSTRAP_INFO %d" % id)
+ logger.info("Bootstrapping info:\n" + info)
+ if "type=NFC-URI" not in info:
+ raise Exception("Unexpected bootstrapping info contents")
+
+ dev[0].dpp_listen(2412)
+ conf_id = dev[1].dpp_configurator_add()
+ dev[1].dpp_auth_init(nfc_uri=uri, configurator=conf_id, conf="sta-dpp")
+ wait_auth_success(dev[0], dev[1], configurator=dev[1], enrollee=dev[0])
diff --git a/tests/hwsim/test_hapd_ctrl.py b/tests/hwsim/test_hapd_ctrl.py
index 245aad7..5b802e4 100644
--- a/tests/hwsim/test_hapd_ctrl.py
+++ b/tests/hwsim/test_hapd_ctrl.py
@@ -79,9 +79,20 @@ def run_hapd_ctrl_sta(dev, apdev):
passphrase = "12345678"
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
hapd = hostapd.add_ap(apdev[0], params)
+ hglobal = hostapd.HostapdGlobal(apdev[0])
dev[0].request("VENDOR_ELEM_ADD 13 2102ff02")
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
addr = dev[0].own_addr()
+ ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=2)
+ if ev is None:
+ raise Exception("No hostapd per-interface event reported")
+ ev2 = hglobal.wait_event(["AP-STA-CONNECTED"], timeout=2)
+ if ev2 is None:
+ raise Exception("No hostapd global event reported")
+ if not ev2.startswith("IFNAME=" + apdev[0]['ifname'] + " <"):
+ raise Exception("Unexpected global event prefix: " + ev2)
+ if ev not in ev2:
+ raise Exception("Event mismatch (%s,%s)" % (ev, ev2))
if "FAIL" in hapd.request("STA " + addr):
raise Exception("Unexpected STA failure")
if "FAIL" not in hapd.request("STA " + addr + " eapol"):
diff --git a/tests/hwsim/test_he.py b/tests/hwsim/test_he.py
index d6087c3..f042d71 100644
--- a/tests/hwsim/test_he.py
+++ b/tests/hwsim/test_he.py
@@ -4,7 +4,18 @@
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+import logging
+logger = logging.getLogger()
+import os
+import subprocess, time
+
+import hwsim_utils
import hostapd
+from wpasupplicant import WpaSupplicant
+from utils import *
+from test_dfs import wait_dfs_event
+from test_ap_csa import csa_supported
+from test_ap_ht import clear_scan_cache
def test_he_open(dev, apdev):
"""HE AP with open mode configuration"""
@@ -65,3 +76,1000 @@ def test_he_params(dev, apdev):
if hapd.get_status_field("ieee80211ax") != "1":
raise Exception("STATUS did not indicate ieee80211ac=1")
dev[0].connect("he", key_mgmt="NONE", scan_freq="2412")
+
+def he_supported():
+ cmd = subprocess.Popen(["iw", "reg", "get"], stdout=subprocess.PIPE)
+ reg = cmd.stdout.read()
+ if "@ 80)" in reg or "@ 160)" in reg:
+ return True
+ return False
+
+def test_he80(dev, apdev):
+ """HE with 80 MHz channel width"""
+ try:
+ hapd = None
+ params = {"ssid": "he",
+ "country_code": "FI",
+ "hw_mode": "a",
+ "channel": "36",
+ "ht_capab": "[HT40+]",
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "ieee80211ax": "1",
+ "vht_oper_chwidth": "1",
+ "vht_capab": "[MAX-MPDU-11454]",
+ "vht_oper_centr_freq_seg0_idx": "42",
+ "he_oper_chwidth": "1",
+ "he_oper_centr_freq_seg0_idx": "42"}
+ hapd = hostapd.add_ap(apdev[0], params)
+ bssid = apdev[0]['bssid']
+
+ dev[0].connect("he", key_mgmt="NONE", scan_freq="5180")
+ hwsim_utils.test_connectivity(dev[0], hapd)
+ sig = dev[0].request("SIGNAL_POLL").splitlines()
+ if "FREQUENCY=5180" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(1): " + str(sig))
+ if "WIDTH=80 MHz" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig))
+ est = dev[0].get_bss(bssid)['est_throughput']
+ if est != "390001":
+ raise Exception("Unexpected BSS est_throughput: " + est)
+ status = dev[0].get_status()
+ if status["ieee80211ac"] != "1":
+ raise Exception("Unexpected STATUS ieee80211ac value (STA)")
+ status = hapd.get_status()
+ logger.info("hostapd STATUS: " + str(status))
+ if status["ieee80211n"] != "1":
+ raise Exception("Unexpected STATUS ieee80211n value")
+ if status["ieee80211ac"] != "1":
+ raise Exception("Unexpected STATUS ieee80211ac value")
+ if status["ieee80211ax"] != "1":
+ raise Exception("Unexpected STATUS ieee80211ax value")
+ if status["secondary_channel"] != "1":
+ raise Exception("Unexpected STATUS secondary_channel value")
+ if status["vht_oper_chwidth"] != "1":
+ raise Exception("Unexpected STATUS vht_oper_chwidth value")
+ if status["vht_oper_centr_freq_seg0_idx"] != "42":
+ raise Exception("Unexpected STATUS vht_oper_centr_freq_seg0_idx value")
+ if "vht_caps_info" not in status:
+ raise Exception("Missing vht_caps_info")
+ if status["he_oper_chwidth"] != "1":
+ raise Exception("Unexpected STATUS he_oper_chwidth value")
+ if status["he_oper_centr_freq_seg0_idx"] != "42":
+ raise Exception("Unexpected STATUS he_oper_centr_freq_seg0_idx value")
+
+ sta = hapd.get_sta(dev[0].own_addr())
+ logger.info("hostapd STA: " + str(sta))
+ if "[HT]" not in sta['flags']:
+ raise Exception("Missing STA flag: HT")
+ if "[VHT]" not in sta['flags']:
+ raise Exception("Missing STA flag: VHT")
+ if "[HE]" not in sta['flags']:
+ raise Exception("Missing STA flag: HE")
+
+ except Exception as e:
+ if isinstance(e, Exception) and str(e) == "AP startup failed":
+ if not he_supported():
+ raise HwsimSkip("80 MHz channel not supported in regulatory information")
+ raise
+ finally:
+ dev[0].request("DISCONNECT")
+ clear_regdom(hapd, dev)
+
+def test_he_wifi_generation(dev, apdev):
+ """HE and wifi_generation"""
+ try:
+ hapd = None
+ params = {"ssid": "he",
+ "country_code": "FI",
+ "hw_mode": "a",
+ "channel": "36",
+ "ht_capab": "[HT40+]",
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "ieee80211ax": "1",
+ "vht_oper_chwidth": "1",
+ "vht_capab": "[MAX-MPDU-11454]",
+ "vht_oper_centr_freq_seg0_idx": "42",
+ "he_oper_chwidth": "1",
+ "he_oper_centr_freq_seg0_idx": "42"}
+ hapd = hostapd.add_ap(apdev[0], params)
+ bssid = apdev[0]['bssid']
+
+ dev[0].connect("he", key_mgmt="NONE", scan_freq="5180")
+ status = dev[0].get_status()
+ if 'wifi_generation' not in status:
+ # For now, assume this is because of missing kernel support
+ raise HwsimSkip("Association Request IE reporting not supported")
+ #raise Exception("Missing wifi_generation information")
+ if status['wifi_generation'] != "6":
+ raise Exception("Unexpected wifi_generation value: " + status['wifi_generation'])
+
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
+ wpas.connect("he", key_mgmt="NONE", scan_freq="5180")
+ status = wpas.get_status()
+ if 'wifi_generation' not in status:
+ # For now, assume this is because of missing kernel support
+ raise HwsimSkip("Association Request IE reporting not supported")
+ #raise Exception("Missing wifi_generation information (connect)")
+ if status['wifi_generation'] != "6":
+ raise Exception("Unexpected wifi_generation value (connect): " + status['wifi_generation'])
+ except Exception as e:
+ if isinstance(e, Exception) and str(e) == "AP startup failed":
+ if not he_supported():
+ raise HwsimSkip("80 MHz channel not supported in regulatory information")
+ raise
+ finally:
+ dev[0].request("DISCONNECT")
+ clear_regdom(hapd, dev)
+
+def he80_test(apdev, dev, channel, ht_capab):
+ clear_scan_cache(apdev)
+ try:
+ hapd = None
+ params = {"ssid": "he",
+ "country_code": "FI",
+ "hw_mode": "a",
+ "channel": str(channel),
+ "ht_capab": ht_capab,
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "ieee80211ax": "1",
+ "vht_oper_chwidth": "1",
+ "vht_oper_centr_freq_seg0_idx": "42",
+ "he_oper_chwidth": "1",
+ "he_oper_centr_freq_seg0_idx": "42"}
+ hapd = hostapd.add_ap(apdev, params)
+ bssid = apdev['bssid']
+
+ dev[0].connect("he", key_mgmt="NONE",
+ scan_freq=str(5000 + 5 * channel))
+ hwsim_utils.test_connectivity(dev[0], hapd)
+ except Exception as e:
+ if isinstance(e, Exception) and str(e) == "AP startup failed":
+ if not he_supported():
+ raise HwsimSkip("80 MHz channel not supported in regulatory information")
+ raise
+ finally:
+ clear_regdom(hapd, dev)
+
+def test_he80b(dev, apdev):
+ """HE with 80 MHz channel width (HT40- channel 40)"""
+ he80_test(apdev[0], dev, 40, "[HT40-]")
+
+def test_he80c(dev, apdev):
+ """HE with 80 MHz channel width (HT40+ channel 44)"""
+ he80_test(apdev[0], dev, 44, "[HT40+]")
+
+def test_he80d(dev, apdev):
+ """HE with 80 MHz channel width (HT40- channel 48)"""
+ he80_test(apdev[0], dev, 48, "[HT40-]")
+
+def test_he80_params(dev, apdev):
+ """HE with 80 MHz channel width and number of optional features enabled"""
+ try:
+ hapd = None
+ params = {"ssid": "he",
+ "country_code": "FI",
+ "hw_mode": "a",
+ "channel": "36",
+ "ht_capab": "[HT40+][SHORT-GI-40][DSS_CCK-40]",
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "ieee80211ax": "1",
+ "vht_oper_chwidth": "1",
+ "vht_capab": "[MAX-MPDU-11454][RXLDPC][SHORT-GI-80][TX-STBC-2BY1][RX-STBC-1][MAX-A-MPDU-LEN-EXP0]",
+ "vht_oper_centr_freq_seg0_idx": "42",
+ "require_vht": "1",
+ "he_oper_chwidth": "1",
+ "he_oper_centr_freq_seg0_idx": "42",
+ "he_su_beamformer": "1",
+ "he_mu_beamformer": "1",
+ "he_bss_color":"1",
+ "he_default_pe_duration":"1",
+ "he_twt_required":"1",
+ "he_rts_threshold":"1"}
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[1].connect("he", key_mgmt="NONE", scan_freq="5180",
+ disable_vht="1", wait_connect=False)
+ dev[0].connect("he", key_mgmt="NONE", scan_freq="5180")
+ dev[2].connect("he", key_mgmt="NONE", scan_freq="5180",
+ disable_sgi="1")
+ ev = dev[1].wait_event(["CTRL-EVENT-ASSOC-REJECT"])
+ if ev is None:
+ raise Exception("Association rejection timed out")
+ if "status_code=104" not in ev:
+ raise Exception("Unexpected rejection status code")
+ dev[1].request("DISCONNECT")
+ hwsim_utils.test_connectivity(dev[0], hapd)
+ sta0 = hapd.get_sta(dev[0].own_addr())
+ sta2 = hapd.get_sta(dev[2].own_addr())
+ capab0 = int(sta0['vht_caps_info'], base=16)
+ capab2 = int(sta2['vht_caps_info'], base=16)
+ if capab0 & 0x60 == 0:
+ raise Exception("dev[0] did not support SGI")
+ if capab2 & 0x60 != 0:
+ raise Exception("dev[2] claimed support for SGI")
+ except Exception as e:
+ if isinstance(e, Exception) and str(e) == "AP startup failed":
+ if not he_supported():
+ raise HwsimSkip("80 MHz channel not supported in regulatory information")
+ raise
+ finally:
+ clear_regdom(hapd, dev, count=3)
+
+def test_he80_invalid(dev, apdev):
+ """HE with invalid 80 MHz channel configuration (seg1)"""
+ try:
+ hapd = None
+ params = {"ssid": "he",
+ "country_code": "US",
+ "hw_mode": "a",
+ "channel": "36",
+ "ht_capab": "[HT40+]",
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "ieee80211ax": "1",
+ "vht_oper_chwidth": "1",
+ "vht_oper_centr_freq_seg0_idx": "42",
+ "vht_oper_centr_freq_seg1_idx": "159",
+ "he_oper_chwidth": "1",
+ "he_oper_centr_freq_seg0_idx": "42",
+ "he_oper_centr_freq_seg1_idx": "155",
+ 'ieee80211d': '1',
+ 'ieee80211h': '1'}
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
+ # This fails due to unexpected seg1 configuration
+ ev = hapd.wait_event(["AP-DISABLED"], timeout=5)
+ if ev is None:
+ raise Exception("AP-DISABLED not reported")
+ except Exception as e:
+ if isinstance(e, Exception) and str(e) == "AP startup failed":
+ if not he_supported():
+ raise HwsimSkip("80/160 MHz channel not supported in regulatory information")
+ raise
+ finally:
+ clear_regdom(hapd, dev)
+
+def test_he80_invalid2(dev, apdev):
+ """HE with invalid 80 MHz channel configuration (seg0)"""
+ try:
+ hapd = None
+ params = {"ssid": "he",
+ "country_code": "US",
+ "hw_mode": "a",
+ "channel": "36",
+ "ht_capab": "[HT40+]",
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "ieee80211ax": "1",
+ "vht_oper_chwidth": "1",
+ "vht_oper_centr_freq_seg0_idx": "42",
+ "he_oper_chwidth": "1",
+ "he_oper_centr_freq_seg0_idx": "46",
+ 'ieee80211d': '1',
+ 'ieee80211h': '1'}
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
+ # This fails due to invalid seg0 configuration
+ ev = hapd.wait_event(["AP-DISABLED"], timeout=5)
+ if ev is None:
+ raise Exception("AP-DISABLED not reported")
+ except Exception as e:
+ if isinstance(e, Exception) and str(e) == "AP startup failed":
+ if not he_supported():
+ raise HwsimSkip("80/160 MHz channel not supported in regulatory information")
+ raise
+ finally:
+ clear_regdom(hapd, dev)
+
+def test_he_20(devs, apdevs):
+ """HE and 20 MHz channel"""
+ dev = devs[0]
+ ap = apdevs[0]
+ try:
+ hapd = None
+ params = {"ssid": "test-he20",
+ "country_code": "DE",
+ "hw_mode": "a",
+ "channel": "36",
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "ieee80211ax": "1",
+ "ht_capab": "",
+ "vht_capab": "",
+ "vht_oper_chwidth": "0",
+ "vht_oper_centr_freq_seg0_idx": "0",
+ "supported_rates": "60 120 240 360 480 540",
+ "require_vht": "1",
+ "he_oper_chwidth": "0",
+ "he_oper_centr_freq_seg0_idx": "0"}
+ hapd = hostapd.add_ap(ap, params)
+ dev.connect("test-he20", scan_freq="5180", key_mgmt="NONE")
+ hwsim_utils.test_connectivity(dev, hapd)
+ finally:
+ dev.request("DISCONNECT")
+ clear_regdom(hapd, devs)
+
+def test_he_40(devs, apdevs):
+ """HE and 40 MHz channel"""
+ dev = devs[0]
+ ap = apdevs[0]
+ try:
+ hapd = None
+ params = {"ssid": "test-he40",
+ "country_code": "DE",
+ "hw_mode": "a",
+ "channel": "36",
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "ieee80211ax": "1",
+ "ht_capab": "[HT40+]",
+ "vht_capab": "",
+ "vht_oper_chwidth": "0",
+ "vht_oper_centr_freq_seg0_idx": "38",
+ "he_oper_chwidth": "0",
+ "he_oper_centr_freq_seg0_idx": "38",
+ "he_su_beamformer": "1",
+ "he_mu_beamformer": "1"}
+ hapd = hostapd.add_ap(ap, params)
+ dev.connect("test-he40", scan_freq="5180", key_mgmt="NONE")
+ hwsim_utils.test_connectivity(dev, hapd)
+ finally:
+ dev.request("DISCONNECT")
+ clear_regdom(hapd, devs)
+
+def test_he160(dev, apdev, params):
+ """HE with 160 MHz channel width (1) [long]"""
+ if not params['long']:
+ raise HwsimSkip("Skip test case with long duration due to --long not specified")
+ try:
+ hapd = None
+ params = {"ssid": "he",
+ "country_code": "FI",
+ "hw_mode": "a",
+ "channel": "36",
+ "ht_capab": "[HT40+]",
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "ieee80211ax": "1",
+ "vht_oper_chwidth": "2",
+ "vht_oper_centr_freq_seg0_idx": "50",
+ "he_oper_chwidth": "2",
+ "he_oper_centr_freq_seg0_idx": "50",
+ 'ieee80211d': '1',
+ 'ieee80211h': '1'}
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
+
+ ev = wait_dfs_event(hapd, "DFS-CAC-START", 5)
+ if "DFS-CAC-START" not in ev:
+ raise Exception("Unexpected DFS event")
+
+ state = hapd.get_status_field("state")
+ if state != "DFS":
+ if state == "DISABLED" and not os.path.exists("dfs"):
+ # Not all systems have recent enough CRDA version and
+ # wireless-regdb changes to support 160 MHz and DFS. For now,
+ # do not report failures for this test case.
+ raise HwsimSkip("CRDA or wireless-regdb did not support 160 MHz")
+ raise Exception("Unexpected interface state: " + state)
+
+ logger.info("Waiting for CAC to complete")
+
+ ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70)
+ if "success=1" not in ev:
+ raise Exception("CAC failed")
+ if "freq=5180" not in ev:
+ raise Exception("Unexpected DFS freq result")
+
+ ev = hapd.wait_event(["AP-ENABLED"], timeout=5)
+ if not ev:
+ raise Exception("AP setup timed out")
+
+ state = hapd.get_status_field("state")
+ if state != "ENABLED":
+ raise Exception("Unexpected interface state")
+
+ dev[0].connect("he", key_mgmt="NONE", scan_freq="5180")
+ dev[0].wait_regdom(country_ie=True)
+ hwsim_utils.test_connectivity(dev[0], hapd)
+ sig = dev[0].request("SIGNAL_POLL").splitlines()
+ if "FREQUENCY=5180" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(1): " + str(sig))
+ if "WIDTH=160 MHz" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig))
+ except Exception as e:
+ if isinstance(e, Exception) and str(e) == "AP startup failed":
+ if not he_supported():
+ raise HwsimSkip("80/160 MHz channel not supported in regulatory information")
+ raise
+ finally:
+ if hapd:
+ hapd.request("DISABLE")
+ dev[0].disconnect_and_stop_scan()
+ subprocess.call(['iw', 'reg', 'set', '00'])
+ dev[0].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=0.5)
+ dev[0].flush_scan_cache()
+
+def test_he160b(dev, apdev, params):
+ """HE with 160 MHz channel width (2) [long]"""
+ if not params['long']:
+ raise HwsimSkip("Skip test case with long duration due to --long not specified")
+ try:
+ hapd = None
+
+ params = {"ssid": "he",
+ "country_code": "FI",
+ "hw_mode": "a",
+ "channel": "104",
+ "ht_capab": "[HT40-]",
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "ieee80211ax": "1",
+ "vht_oper_chwidth": "2",
+ "vht_oper_centr_freq_seg0_idx": "114",
+ "he_oper_chwidth": "2",
+ "he_oper_centr_freq_seg0_idx": "114",
+ 'ieee80211d': '1',
+ 'ieee80211h': '1'}
+ hapd = hostapd.add_ap(apdev[1], params, wait_enabled=False)
+
+ ev = wait_dfs_event(hapd, "DFS-CAC-START", 5)
+ if "DFS-CAC-START" not in ev:
+ raise Exception("Unexpected DFS event(2)")
+
+ state = hapd.get_status_field("state")
+ if state != "DFS":
+ if state == "DISABLED" and not os.path.exists("dfs"):
+ # Not all systems have recent enough CRDA version and
+ # wireless-regdb changes to support 160 MHz and DFS. For now,
+ # do not report failures for this test case.
+ raise HwsimSkip("CRDA or wireless-regdb did not support 160 MHz")
+ raise Exception("Unexpected interface state: " + state)
+
+ logger.info("Waiting for CAC to complete")
+
+ ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70)
+ if "success=1" not in ev:
+ raise Exception("CAC failed(2)")
+ if "freq=5520" not in ev:
+ raise Exception("Unexpected DFS freq result(2)")
+
+ ev = hapd.wait_event(["AP-ENABLED"], timeout=5)
+ if not ev:
+ raise Exception("AP setup timed out(2)")
+
+ state = hapd.get_status_field("state")
+ if state != "ENABLED":
+ raise Exception("Unexpected interface state(2)")
+
+ freq = hapd.get_status_field("freq")
+ if freq != "5520":
+ raise Exception("Unexpected frequency(2)")
+
+ dev[0].connect("he", key_mgmt="NONE", scan_freq="5520")
+ dev[0].wait_regdom(country_ie=True)
+ hwsim_utils.test_connectivity(dev[0], hapd)
+ sig = dev[0].request("SIGNAL_POLL").splitlines()
+ if "FREQUENCY=5520" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(1): " + str(sig))
+ if "WIDTH=160 MHz" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig))
+ except Exception as e:
+ if isinstance(e, Exception) and str(e) == "AP startup failed":
+ if not he_supported():
+ raise HwsimSkip("80/160 MHz channel not supported in regulatory information")
+ raise
+ finally:
+ if hapd:
+ hapd.request("DISABLE")
+ dev[0].disconnect_and_stop_scan()
+ subprocess.call(['iw', 'reg', 'set', '00'])
+ dev[0].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=0.5)
+ dev[0].flush_scan_cache()
+
+def test_he160_no_dfs_100_plus(dev, apdev):
+ """HE with 160 MHz channel width and no DFS (100 plus)"""
+ run_ap_he160_no_dfs(dev, apdev, "100", "[HT40+]")
+
+def test_he160_no_dfs(dev, apdev):
+ """HE with 160 MHz channel width and no DFS (104 minus)"""
+ run_ap_he160_no_dfs(dev, apdev, "104", "[HT40-]")
+
+def test_he160_no_dfs_108_plus(dev, apdev):
+ """HE with 160 MHz channel width and no DFS (108 plus)"""
+ run_ap_he160_no_dfs(dev, apdev, "108", "[HT40+]")
+
+def test_he160_no_dfs_112_minus(dev, apdev):
+ """HE with 160 MHz channel width and no DFS (112 minus)"""
+ run_ap_he160_no_dfs(dev, apdev, "112", "[HT40-]")
+
+def test_he160_no_dfs_116_plus(dev, apdev):
+ """HE with 160 MHz channel width and no DFS (116 plus)"""
+ run_ap_he160_no_dfs(dev, apdev, "116", "[HT40+]")
+
+def test_he160_no_dfs_120_minus(dev, apdev):
+ """HE with 160 MHz channel width and no DFS (120 minus)"""
+ run_ap_he160_no_dfs(dev, apdev, "120", "[HT40-]")
+
+def test_he160_no_dfs_124_plus(dev, apdev):
+ """HE with 160 MHz channel width and no DFS (124 plus)"""
+ run_ap_he160_no_dfs(dev, apdev, "124", "[HT40+]")
+
+def test_he160_no_dfs_128_minus(dev, apdev):
+ """HE with 160 MHz channel width and no DFS (128 minus)"""
+ run_ap_he160_no_dfs(dev, apdev, "128", "[HT40-]")
+
+def run_ap_he160_no_dfs(dev, apdev, channel, ht_capab):
+ try:
+ hapd = None
+ params = {"ssid": "he",
+ "country_code": "ZA",
+ "hw_mode": "a",
+ "channel": channel,
+ "ht_capab": ht_capab,
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "ieee80211ax": "1",
+ "vht_oper_chwidth": "2",
+ "vht_oper_centr_freq_seg0_idx": "114",
+ "he_oper_chwidth": "2",
+ "he_oper_centr_freq_seg0_idx": "114",
+ 'ieee80211d': '1',
+ 'ieee80211h': '1'}
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
+ ev = hapd.wait_event(["AP-ENABLED"], timeout=2)
+ if not ev:
+ cmd = subprocess.Popen(["iw", "reg", "get"], stdout=subprocess.PIPE)
+ reg = cmd.stdout.readlines()
+ for r in reg:
+ if "5490" in r and "DFS" in r:
+ raise HwsimSkip("ZA regulatory rule did not have DFS requirement removed")
+ raise Exception("AP setup timed out")
+
+ freq = str(int(channel) * 5 + 5000)
+ dev[0].connect("he", key_mgmt="NONE", scan_freq=freq)
+ dev[0].wait_regdom(country_ie=True)
+ hwsim_utils.test_connectivity(dev[0], hapd)
+ sig = dev[0].request("SIGNAL_POLL").splitlines()
+ if "FREQUENCY=" + freq not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(1): " + str(sig))
+ if "WIDTH=160 MHz" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig))
+ except Exception as e:
+ if isinstance(e, Exception) and str(e) == "AP startup failed":
+ if not he_supported():
+ raise HwsimSkip("80/160 MHz channel not supported in regulatory information")
+ raise
+ finally:
+ clear_regdom(hapd, dev)
+
+def test_he160_no_ht40(dev, apdev):
+ """HE with 160 MHz channel width and HT40 disabled"""
+ try:
+ hapd = None
+ params = {"ssid": "he",
+ "country_code": "ZA",
+ "hw_mode": "a",
+ "channel": "108",
+ "ht_capab": "",
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "ieee80211ax": "1",
+ "vht_oper_chwidth": "2",
+ "vht_oper_centr_freq_seg0_idx": "114",
+ "he_oper_chwidth": "2",
+ "he_oper_centr_freq_seg0_idx": "114",
+ 'ieee80211d': '1',
+ 'ieee80211h': '1'}
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
+ ev = hapd.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=2)
+ if not ev:
+ cmd = subprocess.Popen(["iw", "reg", "get"], stdout=subprocess.PIPE)
+ reg = cmd.stdout.readlines()
+ for r in reg:
+ if "5490" in r and "DFS" in r:
+ raise HwsimSkip("ZA regulatory rule did not have DFS requirement removed")
+ raise Exception("AP setup timed out")
+ if "AP-ENABLED" in ev:
+ # This was supposed to fail due to sec_channel_offset == 0
+ raise Exception("Unexpected AP-ENABLED")
+ except Exception as e:
+ if isinstance(e, Exception) and str(e) == "AP startup failed":
+ if not he_supported():
+ raise HwsimSkip("80/160 MHz channel not supported in regulatory information")
+ raise
+ finally:
+ clear_regdom(hapd, dev)
+
+def test_he80plus80(dev, apdev):
+ """HE with 80+80 MHz channel width"""
+ try:
+ hapd = None
+ hapd2 = None
+ params = {"ssid": "he",
+ "country_code": "US",
+ "hw_mode": "a",
+ "channel": "52",
+ "ht_capab": "[HT40+]",
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "ieee80211ax": "1",
+ "vht_oper_chwidth": "3",
+ "vht_oper_centr_freq_seg0_idx": "58",
+ "vht_oper_centr_freq_seg1_idx": "155",
+ "he_oper_chwidth": "3",
+ "he_oper_centr_freq_seg0_idx": "58",
+ "he_oper_centr_freq_seg1_idx": "155",
+ 'ieee80211d': '1',
+ 'ieee80211h': '1'}
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
+ # This will actually fail since DFS on 80+80 is not yet supported
+ ev = hapd.wait_event(["AP-DISABLED"], timeout=5)
+ # ignore result to avoid breaking the test once 80+80 DFS gets enabled
+
+ params = {"ssid": "he2",
+ "country_code": "US",
+ "hw_mode": "a",
+ "channel": "36",
+ "ht_capab": "[HT40+]",
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "ieee80211ax": "1",
+ "vht_oper_chwidth": "3",
+ "vht_oper_centr_freq_seg0_idx": "42",
+ "vht_oper_centr_freq_seg1_idx": "155",
+ "he_oper_chwidth": "3",
+ "he_oper_centr_freq_seg0_idx": "42",
+ "he_oper_centr_freq_seg1_idx": "155"}
+ hapd2 = hostapd.add_ap(apdev[1], params, wait_enabled=False)
+
+ ev = hapd2.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=5)
+ if not ev:
+ raise Exception("AP setup timed out(2)")
+ if "AP-DISABLED" in ev:
+ # Assume this failed due to missing regulatory update for now
+ raise HwsimSkip("80+80 MHz channel not supported in regulatory information")
+
+ state = hapd2.get_status_field("state")
+ if state != "ENABLED":
+ raise Exception("Unexpected interface state(2)")
+
+ dev[1].connect("he2", key_mgmt="NONE", scan_freq="5180")
+ hwsim_utils.test_connectivity(dev[1], hapd2)
+ sig = dev[1].request("SIGNAL_POLL").splitlines()
+ if "FREQUENCY=5180" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(1): " + str(sig))
+ if "WIDTH=80+80 MHz" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig))
+ if "CENTER_FRQ1=5210" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(3): " + str(sig))
+ if "CENTER_FRQ2=5775" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(4): " + str(sig))
+ except Exception as e:
+ if isinstance(e, Exception) and str(e) == "AP startup failed":
+ if not he_supported():
+ raise HwsimSkip("80/160 MHz channel not supported in regulatory information")
+ raise
+ finally:
+ dev[0].request("DISCONNECT")
+ dev[1].request("DISCONNECT")
+ if hapd:
+ hapd.request("DISABLE")
+ if hapd2:
+ hapd2.request("DISABLE")
+ subprocess.call(['iw', 'reg', 'set', '00'])
+ dev[0].flush_scan_cache()
+ dev[1].flush_scan_cache()
+
+def test_he80plus80_invalid(dev, apdev):
+ """HE with invalid 80+80 MHz channel"""
+ try:
+ hapd = None
+ params = {"ssid": "he",
+ "country_code": "US",
+ "hw_mode": "a",
+ "channel": "36",
+ "ht_capab": "[HT40+]",
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "ieee80211ax": "1",
+ "vht_oper_chwidth": "3",
+ "vht_oper_centr_freq_seg0_idx": "42",
+ "vht_oper_centr_freq_seg1_idx": "0",
+ "he_oper_chwidth": "3",
+ "he_oper_centr_freq_seg0_idx": "42",
+ "he_oper_centr_freq_seg1_idx": "0",
+ 'ieee80211d': '1',
+ 'ieee80211h': '1'}
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
+ # This fails due to missing(invalid) seg1 configuration
+ ev = hapd.wait_event(["AP-DISABLED"], timeout=5)
+ if ev is None:
+ raise Exception("AP-DISABLED not reported")
+ except Exception as e:
+ if isinstance(e, Exception) and str(e) == "AP startup failed":
+ if not he_supported():
+ raise HwsimSkip("80/160 MHz channel not supported in regulatory information")
+ raise
+ finally:
+ clear_regdom(hapd, dev)
+
+def test_he80_csa(dev, apdev):
+ """HE with 80 MHz channel width and CSA"""
+ csa_supported(dev[0])
+ try:
+ hapd = None
+ params = {"ssid": "he",
+ "country_code": "US",
+ "hw_mode": "a",
+ "channel": "149",
+ "ht_capab": "[HT40+]",
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "ieee80211ax": "1",
+ "vht_oper_chwidth": "1",
+ "vht_oper_centr_freq_seg0_idx": "155",
+ "he_oper_chwidth": "1",
+ "he_oper_centr_freq_seg0_idx": "155"}
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].connect("he", key_mgmt="NONE", scan_freq="5745")
+ hwsim_utils.test_connectivity(dev[0], hapd)
+
+ hapd.request("CHAN_SWITCH 5 5180 ht vht he blocktx center_freq1=5210 sec_channel_offset=1 bandwidth=80")
+ ev = hapd.wait_event(["CTRL-EVENT-STARTED-CHANNEL-SWITCH"], timeout=10)
+ if ev is None:
+ raise Exception("Channel switch start event not seen")
+ if "freq=5180" not in ev:
+ raise Exception("Unexpected channel in CS started")
+ ev = hapd.wait_event(["CTRL-EVENT-CHANNEL-SWITCH"], timeout=10)
+ if ev is None:
+ raise Exception("Channel switch completion event not seen")
+ if "freq=5180" not in ev:
+ raise Exception("Unexpected channel in CS completed")
+ ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
+ if ev is None:
+ raise Exception("CSA finished event timed out")
+ if "freq=5180" not in ev:
+ raise Exception("Unexpected channel in CSA finished event")
+ time.sleep(0.5)
+ hwsim_utils.test_connectivity(dev[0], hapd)
+
+ hapd.request("CHAN_SWITCH 5 5745")
+ ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
+ if ev is None:
+ raise Exception("CSA finished event timed out")
+ if "freq=5745" not in ev:
+ raise Exception("Unexpected channel in CSA finished event")
+ time.sleep(0.5)
+ hwsim_utils.test_connectivity(dev[0], hapd)
+
+ # This CSA to same channel will fail in kernel, so use this only for
+ # extra code coverage.
+ hapd.request("CHAN_SWITCH 5 5745")
+ hapd.wait_event(["AP-CSA-FINISHED"], timeout=1)
+ except Exception as e:
+ if isinstance(e, Exception) and str(e) == "AP startup failed":
+ if not he_supported():
+ raise HwsimSkip("80 MHz channel not supported in regulatory information")
+ raise
+ finally:
+ dev[0].request("DISCONNECT")
+ clear_regdom(hapd, dev)
+
+def test_he_on_24ghz(dev, apdev):
+ """Subset of HE features on 2.4 GHz"""
+ hapd = None
+ params = {"ssid": "test-he-2g",
+ "hw_mode": "g",
+ "channel": "1",
+ "ieee80211n": "1",
+ "ieee80211ax": "1",
+ "vht_oper_chwidth": "0",
+ "vht_oper_centr_freq_seg0_idx": "1",
+ "he_oper_chwidth": "0",
+ "he_oper_centr_freq_seg0_idx": "1"}
+ hapd = hostapd.add_ap(apdev[0], params)
+ try:
+ dev[0].connect("test-he-2g", scan_freq="2412", key_mgmt="NONE")
+ hwsim_utils.test_connectivity(dev[0], hapd)
+ sta = hapd.get_sta(dev[0].own_addr())
+
+ dev[1].connect("test-he-2g", scan_freq="2412", key_mgmt="NONE")
+ sta = hapd.get_sta(dev[1].own_addr())
+
+ finally:
+ dev[0].request("DISCONNECT")
+ dev[1].request("DISCONNECT")
+ if hapd:
+ hapd.request("DISABLE")
+ subprocess.call(['iw', 'reg', 'set', '00'])
+ dev[0].flush_scan_cache()
+ dev[1].flush_scan_cache()
+
+def test_he80_pwr_constraint(dev, apdev):
+ """HE with 80 MHz channel width and local power constraint"""
+ hapd = None
+ try:
+ params = {"ssid": "he",
+ "country_code": "FI",
+ "hw_mode": "a",
+ "channel": "36",
+ "ht_capab": "[HT40+]",
+ "ieee80211d": "1",
+ "local_pwr_constraint": "3",
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "ieee80211ax": "1",
+ "vht_oper_chwidth": "1",
+ "vht_oper_centr_freq_seg0_idx": "42",
+ "he_oper_chwidth": "1",
+ "he_oper_centr_freq_seg0_idx": "42"}
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].connect("he", key_mgmt="NONE", scan_freq="5180")
+ dev[0].wait_regdom(country_ie=True)
+ except Exception as e:
+ if isinstance(e, Exception) and str(e) == "AP startup failed":
+ if not he_supported():
+ raise HwsimSkip("80 MHz channel not supported in regulatory information")
+ raise
+ finally:
+ if hapd:
+ hapd.request("DISABLE")
+ dev[0].disconnect_and_stop_scan()
+ subprocess.call(['iw', 'reg', 'set', '00'])
+ dev[0].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=0.5)
+ dev[0].flush_scan_cache()
+
+def test_he_use_sta_nsts(dev, apdev):
+ """HE with 80 MHz channel width and use_sta_nsts=1"""
+ try:
+ hapd = None
+ params = {"ssid": "he",
+ "country_code": "FI",
+ "hw_mode": "a",
+ "channel": "36",
+ "ht_capab": "[HT40+]",
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "ieee80211ax": "1",
+ "vht_oper_chwidth": "1",
+ "vht_oper_centr_freq_seg0_idx": "42",
+ "he_oper_chwidth": "1",
+ "he_oper_centr_freq_seg0_idx": "42",
+ "use_sta_nsts": "1"}
+ hapd = hostapd.add_ap(apdev[0], params)
+ bssid = apdev[0]['bssid']
+
+ dev[0].connect("he", key_mgmt="NONE", scan_freq="5180")
+ hwsim_utils.test_connectivity(dev[0], hapd)
+ except Exception as e:
+ if isinstance(e, Exception) and str(e) == "AP startup failed":
+ if not he_supported():
+ raise HwsimSkip("80 MHz channel not supported in regulatory information")
+ raise
+ finally:
+ clear_regdom(hapd, dev)
+
+def test_he_tkip(dev, apdev):
+ """HE and TKIP"""
+ try:
+ hapd = None
+ params = {"ssid": "he",
+ "wpa": "1",
+ "wpa_key_mgmt": "WPA-PSK",
+ "wpa_pairwise": "TKIP",
+ "wpa_passphrase": "12345678",
+ "country_code": "FI",
+ "hw_mode": "a",
+ "channel": "36",
+ "ht_capab": "[HT40+]",
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "ieee80211ax": "1",
+ "vht_oper_chwidth": "1",
+ "vht_oper_centr_freq_seg0_idx": "42",
+ "he_oper_chwidth": "1",
+ "he_oper_centr_freq_seg0_idx": "42"}
+ hapd = hostapd.add_ap(apdev[0], params)
+ bssid = apdev[0]['bssid']
+
+ dev[0].connect("he", psk="12345678", scan_freq="5180")
+ hwsim_utils.test_connectivity(dev[0], hapd)
+ sig = dev[0].request("SIGNAL_POLL").splitlines()
+ if "FREQUENCY=5180" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(1): " + str(sig))
+ if "WIDTH=20 MHz (no HT)" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig))
+ status = hapd.get_status()
+ logger.info("hostapd STATUS: " + str(status))
+ if status["ieee80211n"] != "0":
+ raise Exception("Unexpected STATUS ieee80211n value")
+ if status["ieee80211ac"] != "0":
+ raise Exception("Unexpected STATUS ieee80211ac value")
+ if status["ieee80211ax"] != "1":
+ raise Exception("Unexpected STATUS ieee80211ax value")
+ if status["secondary_channel"] != "0":
+ raise Exception("Unexpected STATUS secondary_channel value")
+ except Exception as e:
+ if isinstance(e, Exception) and str(e) == "AP startup failed":
+ if not he_supported():
+ raise HwsimSkip("80 MHz channel not supported in regulatory information")
+ raise
+ finally:
+ dev[0].request("DISCONNECT")
+ clear_regdom(hapd, dev)
+
+def test_he_40_fallback_to_20(devs, apdevs):
+ """HE and 40 MHz channel configuration falling back to 20 MHz"""
+ dev = devs[0]
+ ap = apdevs[0]
+ try:
+ hapd = None
+ params = {"ssid": "test-he40",
+ "country_code": "US",
+ "hw_mode": "a",
+ "basic_rates": "60 120 240",
+ "channel": "161",
+ "ieee80211d": "1",
+ "ieee80211h": "1",
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "ieee80211ax": "1",
+ "ht_capab": "[HT40+][SHORT-GI-20][SHORT-GI-40][DSSS_CCK-40]",
+ "vht_capab": "[RXLDPC][SHORT-GI-80][TX-STBC-2BY1][RX-STBC1][MAX-MPDU-11454][MAX-A-MPDU-LEN-EXP7]",
+ "vht_oper_chwidth": "0",
+ "vht_oper_centr_freq_seg0_idx": "155",
+ "he_oper_chwidth": "0",
+ "he_oper_centr_freq_seg0_idx": "155"}
+ hapd = hostapd.add_ap(ap, params)
+ dev.connect("test-he40", scan_freq="5805", key_mgmt="NONE")
+ dev.wait_regdom(country_ie=True)
+ hwsim_utils.test_connectivity(dev, hapd)
+ finally:
+ clear_regdom(hapd, devs)
+
+def test_he80_to_24g_he(dev, apdev):
+ """HE with 80 MHz channel width reconfigured to 2.4 GHz HE"""
+ try:
+ hapd = None
+ params = {"ssid": "he",
+ "country_code": "FI",
+ "hw_mode": "a",
+ "channel": "36",
+ "ht_capab": "[HT40+]",
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "ieee80211ax": "1",
+ "vht_oper_chwidth": "1",
+ "vht_capab": "[MAX-MPDU-11454]",
+ "vht_oper_centr_freq_seg0_idx": "42",
+ "he_oper_chwidth": "1",
+ "he_oper_centr_freq_seg0_idx": "42"}
+ hapd = hostapd.add_ap(apdev[0], params)
+ bssid = apdev[0]['bssid']
+
+ hapd.disable()
+ hapd.set("ieee80211ac", "0")
+ hapd.set("hw_mode", "g")
+ hapd.set("channel", "1")
+ hapd.set("ht_capab", "")
+ hapd.set("vht_capab", "")
+ hapd.set("he_oper_chwidth", "")
+ hapd.set("he_oper_centr_freq_seg0_idx", "")
+ hapd.set("vht_oper_chwidth", "")
+ hapd.set("vht_oper_centr_freq_seg0_idx", "")
+ hapd.enable()
+
+ dev[0].connect("he", key_mgmt="NONE", scan_freq="2412")
+ except Exception as e:
+ if isinstance(e, Exception) and str(e) == "AP startup failed":
+ if not he_supported():
+ raise HwsimSkip("80 MHz channel not supported in regulatory information")
+ raise
+ finally:
+ dev[0].request("DISCONNECT")
+ clear_regdom(hapd, dev)
diff --git a/tests/hwsim/test_sae.py b/tests/hwsim/test_sae.py
index 2f612df..dbf630f 100644
--- a/tests/hwsim/test_sae.py
+++ b/tests/hwsim/test_sae.py
@@ -749,6 +749,168 @@ def test_sae_proto_ffc(dev, apdev):
hapd.set("ext_mgmt_frame_handling", "0")
hapd.dump_monitor()
+
+def test_sae_proto_commit_delayed(dev, apdev):
+ """SAE protocol testing - Commit delayed"""
+ if "SAE" not in dev[0].get_capability("auth_alg"):
+ raise HwsimSkip("SAE not supported")
+ params = hostapd.wpa2_params(ssid="test-sae",
+ passphrase="12345678")
+ params['wpa_key_mgmt'] = 'SAE'
+ hapd = hostapd.add_ap(apdev[0], params)
+ bssid = apdev[0]['bssid']
+
+ dev[0].request("SET sae_groups 19")
+
+ dev[0].scan_for_bss(bssid, freq=2412)
+ hapd.set("ext_mgmt_frame_handling", "1")
+ dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
+ scan_freq="2412", wait_connect=False)
+
+ logger.info("Commit")
+ for i in range(0, 10):
+ req = hapd.mgmt_rx()
+ if req is None:
+ raise Exception("MGMT RX wait timed out (commit)")
+ if req['subtype'] == 11:
+ break
+ req = None
+ if not req:
+ raise Exception("Authentication frame (commit) not received")
+
+ hapd.dump_monitor()
+ time.sleep(2.5)
+ hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
+
+ logger.info("Commit/Confirm")
+ for i in range(0, 10):
+ req = hapd.mgmt_rx()
+ if req is None:
+ raise Exception("MGMT RX wait timed out (confirm)")
+ if req['subtype'] == 11:
+ trans, = struct.unpack('<H', req['payload'][2:4])
+ if trans == 1:
+ logger.info("Extra Commit")
+ hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
+ continue
+ break
+ req = None
+ if not req:
+ raise Exception("Authentication frame (confirm) not received")
+
+ hapd.dump_monitor()
+ hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
+
+ logger.info("Association Request")
+ for i in range(0, 10):
+ req = hapd.mgmt_rx()
+ if req is None:
+ raise Exception("MGMT RX wait timed out (AssocReq)")
+ if req['subtype'] == 0:
+ break
+ req = None
+ if not req:
+ raise Exception("Association Request frame not received")
+
+ hapd.dump_monitor()
+ hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
+ ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5)
+ if ev is None:
+ raise Exception("Management frame TX status not reported (1)")
+ if "stype=1 ok=1" not in ev:
+ raise Exception("Unexpected management frame TX status (1): " + ev)
+ cmd = "MGMT_TX_STATUS_PROCESS %s" % (" ".join(ev.split(' ')[1:4]))
+ if "OK" not in hapd.request(cmd):
+ raise Exception("MGMT_TX_STATUS_PROCESS failed")
+
+ hapd.set("ext_mgmt_frame_handling", "0")
+
+ dev[0].wait_connected()
+
+def test_sae_proto_commit_replay(dev, apdev):
+ """SAE protocol testing - Commit replay"""
+ if "SAE" not in dev[0].get_capability("auth_alg"):
+ raise HwsimSkip("SAE not supported")
+ params = hostapd.wpa2_params(ssid="test-sae",
+ passphrase="12345678")
+ params['wpa_key_mgmt'] = 'SAE'
+ hapd = hostapd.add_ap(apdev[0], params)
+ bssid = apdev[0]['bssid']
+
+ dev[0].request("SET sae_groups 19")
+
+ dev[0].scan_for_bss(bssid, freq=2412)
+ hapd.set("ext_mgmt_frame_handling", "1")
+ dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
+ scan_freq="2412", wait_connect=False)
+
+ logger.info("Commit")
+ for i in range(0, 10):
+ req = hapd.mgmt_rx()
+ if req is None:
+ raise Exception("MGMT RX wait timed out (commit)")
+ if req['subtype'] == 11:
+ break
+ req = None
+ if not req:
+ raise Exception("Authentication frame (commit) not received")
+
+ hapd.dump_monitor()
+ hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
+ logger.info("Replay Commit")
+ hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
+
+ logger.info("Confirm")
+ for i in range(0, 10):
+ req = hapd.mgmt_rx()
+ if req is None:
+ raise Exception("MGMT RX wait timed out (confirm)")
+ if req['subtype'] == 11:
+ trans, = struct.unpack('<H', req['payload'][2:4])
+ if trans == 1:
+ logger.info("Extra Commit")
+ hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
+ continue
+ break
+ req = None
+ if not req:
+ raise Exception("Authentication frame (confirm) not received")
+
+ hapd.dump_monitor()
+ hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
+
+ logger.info("Association Request")
+ for i in range(0, 10):
+ req = hapd.mgmt_rx()
+ if req is None:
+ raise Exception("MGMT RX wait timed out (AssocReq)")
+ if req['subtype'] == 0:
+ break
+ req = None
+ if not req:
+ raise Exception("Association Request frame not received")
+
+ hapd.dump_monitor()
+ hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
+ for i in range(0, 10):
+ ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5)
+ if ev is None:
+ raise Exception("Management frame TX status not reported (1)")
+ if "stype=11 ok=1" in ev:
+ continue
+ if "stype=12 ok=1" in ev:
+ continue
+ if "stype=1 ok=1" not in ev:
+ raise Exception("Unexpected management frame TX status (1): " + ev)
+ cmd = "MGMT_TX_STATUS_PROCESS %s" % (" ".join(ev.split(' ')[1:4]))
+ if "OK" not in hapd.request(cmd):
+ raise Exception("MGMT_TX_STATUS_PROCESS failed")
+ break
+
+ hapd.set("ext_mgmt_frame_handling", "0")
+
+ dev[0].wait_connected()
+
def test_sae_proto_confirm_replay(dev, apdev):
"""SAE protocol testing - Confirm replay"""
if "SAE" not in dev[0].get_capability("auth_alg"):
@@ -777,10 +939,6 @@ def test_sae_proto_confirm_replay(dev, apdev):
if not req:
raise Exception("Authentication frame (commit) not received")
- bssid = hapd.own_addr().replace(':', '')
- addr = dev[0].own_addr().replace(':', '')
- hdr = "b0003a01" + bssid + addr + bssid + "1000"
-
hapd.dump_monitor()
hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
@@ -1723,24 +1881,20 @@ def test_sae_pwe_group_21(dev, apdev):
run_sae_pwe_group(dev, apdev, 21)
def test_sae_pwe_group_25(dev, apdev):
- """SAE PWE derivation options with group 21"""
- run_sae_pwe_group(dev, apdev, 21)
-
-def test_sae_pwe_group_26(dev, apdev):
- """SAE PWE derivation options with group 21"""
- run_sae_pwe_group(dev, apdev, 21)
+ """SAE PWE derivation options with group 25"""
+ run_sae_pwe_group(dev, apdev, 25)
def test_sae_pwe_group_28(dev, apdev):
- """SAE PWE derivation options with group 21"""
- run_sae_pwe_group(dev, apdev, 21)
+ """SAE PWE derivation options with group 28"""
+ run_sae_pwe_group(dev, apdev, 28)
def test_sae_pwe_group_29(dev, apdev):
- """SAE PWE derivation options with group 21"""
- run_sae_pwe_group(dev, apdev, 21)
+ """SAE PWE derivation options with group 29"""
+ run_sae_pwe_group(dev, apdev, 29)
def test_sae_pwe_group_30(dev, apdev):
- """SAE PWE derivation options with group 21"""
- run_sae_pwe_group(dev, apdev, 21)
+ """SAE PWE derivation options with group 30"""
+ run_sae_pwe_group(dev, apdev, 30)
def test_sae_pwe_group_1(dev, apdev):
"""SAE PWE derivation options with group 1"""
@@ -1827,6 +1981,17 @@ def test_sae_pwe_h2e_only_ap(dev, apdev):
if ev is None:
raise Exception("No indication of mismatching network seen")
+def test_sae_pwe_h2e_only_ap_sta_forcing_loop(dev, apdev):
+ """SAE PWE derivation with H2E-only AP and STA forcing loop"""
+ start_sae_pwe_ap(apdev[0], 19, 1)
+ dev[0].set("ignore_sae_h2e_only", "1")
+ dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", scan_freq="2412",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-SSID-TEMP-DISABLED"], timeout=10)
+ dev[0].request("DISCONNECT")
+ if ev is None:
+ raise Exception("No indication of temporary disabled network seen")
+
def test_sae_pwe_loop_only_ap(dev, apdev):
"""SAE PWE derivation with loop-only AP"""
start_sae_pwe_ap(apdev[0], 19, 0)
@@ -1859,6 +2024,30 @@ def test_sae_h2e_rejected_groups(dev, apdev):
dev[0].set("sae_groups", "")
dev[0].set("sae_pwe", "0")
+def test_sae_h2e_rejected_groups_unexpected(dev, apdev):
+ """SAE H2E and rejected groups indication (unexpected group)"""
+ params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678")
+ params['wpa_key_mgmt'] = 'SAE'
+ params['sae_groups'] = "19 20"
+ params['sae_pwe'] = "1"
+ hapd = hostapd.add_ap(apdev[0], params)
+ try:
+ dev[0].set("sae_groups", "21 19")
+ dev[0].set("extra_sae_rejected_groups", "19")
+ dev[0].set("sae_pwe", "1")
+ dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE",
+ scan_freq="2412", wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
+ "CTRL-EVENT-SSID-TEMP-DISABLED"], timeout=10)
+ dev[0].request("DISCONNECT")
+ if ev is None:
+ raise Exception("No indication of temporary disabled network seen")
+ if "CTRL-EVENT-CONNECTED" in ev:
+ raise Exception("Unexpected connection")
+ finally:
+ dev[0].set("sae_groups", "")
+ dev[0].set("sae_pwe", "0")
+
def test_sae_h2e_password_id(dev, apdev):
"""SAE H2E and password identifier"""
if "SAE" not in dev[0].get_capability("auth_alg"):
@@ -1878,3 +2067,131 @@ def test_sae_h2e_password_id(dev, apdev):
finally:
dev[0].set("sae_groups", "")
dev[0].set("sae_pwe", "0")
+
+def test_sae_pwe_in_psk_ap(dev, apdev):
+ """sae_pwe parameter in PSK-only-AP"""
+ params = hostapd.wpa2_params(ssid="test-psk", passphrase="12345678")
+ params['sae_pwe'] = '1'
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].connect("test-psk", psk="12345678", scan_freq="2412")
+
+def test_sae_auth_restart(dev, apdev):
+ """SAE and authentication restarts with H2E/looping"""
+ if "SAE" not in dev[0].get_capability("auth_alg"):
+ raise HwsimSkip("SAE not supported")
+ params = hostapd.wpa2_params(ssid="test-sae")
+ params['wpa_key_mgmt'] = 'SAE'
+ params['sae_pwe'] = '2'
+ params['sae_password'] = 'secret|id=pw id'
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ try:
+ dev[0].request("SET sae_groups ")
+ for pwe in [1, 0, 1]:
+ dev[0].set("sae_pwe", str(pwe))
+ dev[0].connect("test-sae", sae_password="secret",
+ sae_password_id="pw id",
+ key_mgmt="SAE", scan_freq="2412")
+ # Disconnect without hostapd removing the STA entry so that the
+ # following SAE authentication instance starts with an existing
+ # STA entry that has maintained some SAE state.
+ hapd.set("ext_mgmt_frame_handling", "1")
+ dev[0].request("REMOVE_NETWORK all")
+ req = hapd.mgmt_rx()
+ dev[0].wait_disconnected()
+ dev[0].dump_monitor()
+ hapd.set("ext_mgmt_frame_handling", "0")
+ finally:
+ dev[0].set("sae_groups", "")
+ dev[0].set("sae_pwe", "0")
+
+def test_sae_h2e_rsnxe_mismatch(dev, apdev):
+ """SAE H2E and RSNXE mismatch in EAPOL-Key msg 2/4"""
+ params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678")
+ params['wpa_key_mgmt'] = 'SAE'
+ params['sae_pwe'] = "1"
+ hapd = hostapd.add_ap(apdev[0], params)
+ try:
+ dev[0].set("sae_groups", "19")
+ dev[0].set("sae_pwe", "1")
+ for rsnxe in ["F40100", "F400", ""]:
+ dev[0].set("rsnxe_override_eapol", rsnxe)
+ dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE",
+ scan_freq="2412", wait_connect=False)
+ ev = dev[0].wait_event(["Associated with"], timeout=10)
+ if ev is None:
+ raise Exception("No indication of association seen")
+ ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
+ "CTRL-EVENT-DISCONNECTED"], timeout=5)
+ dev[0].request("REMOVE_NETWORK all")
+ if ev is None:
+ raise Exception("No disconnection seen")
+ if "CTRL-EVENT-DISCONNECTED" not in ev:
+ raise Exception("Unexpected connection")
+ dev[0].dump_monitor()
+ finally:
+ dev[0].set("sae_groups", "")
+ dev[0].set("sae_pwe", "0")
+
+def test_sae_h2e_rsnxe_mismatch_assoc(dev, apdev):
+ """SAE H2E and RSNXE mismatch in EAPOL-Key msg 2/4 (assoc)"""
+ params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678")
+ params['wpa_key_mgmt'] = 'SAE'
+ params['sae_pwe'] = "1"
+ hapd = hostapd.add_ap(apdev[0], params)
+ try:
+ dev[0].set("sae_groups", "19")
+ dev[0].set("sae_pwe", "1")
+ for rsnxe in ["F40100", "F400", ""]:
+ dev[0].set("rsnxe_override_assoc", rsnxe)
+ dev[0].set("rsnxe_override_eapol", "F40120")
+ dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE",
+ scan_freq="2412", wait_connect=False)
+ ev = dev[0].wait_event(["Associated with"], timeout=10)
+ if ev is None:
+ raise Exception("No indication of association seen")
+ ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
+ "CTRL-EVENT-DISCONNECTED"], timeout=5)
+ dev[0].request("REMOVE_NETWORK all")
+ if ev is None:
+ raise Exception("No disconnection seen")
+ if "CTRL-EVENT-DISCONNECTED" not in ev:
+ raise Exception("Unexpected connection")
+ dev[0].dump_monitor()
+ finally:
+ dev[0].set("sae_groups", "")
+ dev[0].set("sae_pwe", "0")
+
+def test_sae_h2e_rsnxe_mismatch_ap(dev, apdev):
+ """SAE H2E and RSNXE mismatch in EAPOL-Key msg 3/4"""
+ run_sae_h2e_rsnxe_mismatch_ap(dev, apdev, "F40100")
+
+def test_sae_h2e_rsnxe_mismatch_ap2(dev, apdev):
+ """SAE H2E and RSNXE mismatch in EAPOL-Key msg 3/4"""
+ run_sae_h2e_rsnxe_mismatch_ap(dev, apdev, "F400")
+
+def run_sae_h2e_rsnxe_mismatch_ap(dev, apdev, rsnxe):
+ params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678")
+ params['wpa_key_mgmt'] = 'SAE'
+ params['sae_pwe'] = "1"
+ params['rsnxe_override_eapol'] = rsnxe
+ hapd = hostapd.add_ap(apdev[0], params)
+ try:
+ dev[0].set("sae_groups", "19")
+ dev[0].set("sae_pwe", "1")
+ dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE",
+ scan_freq="2412", wait_connect=False)
+ ev = dev[0].wait_event(["Associated with"], timeout=10)
+ if ev is None:
+ raise Exception("No indication of association seen")
+ ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
+ "CTRL-EVENT-DISCONNECTED"], timeout=5)
+ dev[0].request("REMOVE_NETWORK all")
+ if ev is None:
+ raise Exception("No disconnection seen")
+ if "CTRL-EVENT-DISCONNECTED" not in ev:
+ raise Exception("Unexpected connection")
+ finally:
+ dev[0].set("sae_groups", "")
+ dev[0].set("sae_pwe", "0")
diff --git a/tests/hwsim/test_scan.py b/tests/hwsim/test_scan.py
index 0b302d5..a1e4171 100644
--- a/tests/hwsim/test_scan.py
+++ b/tests/hwsim/test_scan.py
@@ -1886,3 +1886,20 @@ def test_connect_mbssid_open_1(dev, apdev):
# able to start connection attempt.
dev[0].request("REMOVE_NETWORK all")
dev[0].dump_monitor()
+
+def test_scan_only_one(dev, apdev):
+ """Test that scanning with a single active AP only returns that one"""
+ dev[0].flush_scan_cache()
+ hostapd.add_ap(apdev[0], {"ssid": "test-scan"})
+ bssid = apdev[0]['bssid']
+
+ check_scan(dev[0], "use_id=1", test_busy=True)
+ dev[0].scan_for_bss(bssid, freq="2412")
+
+ status, stdout = hostapd.cmd_execute(dev[0], ['iw', dev[0].ifname, 'scan', 'dump'])
+ if status != 0:
+ raise Exception("iw scan dump failed with code %d" % status)
+ lines = stdout.split('\n')
+ entries = len(list(filter(lambda x: x.startswith('BSS '), lines)))
+ if entries != 1:
+ raise Exception("expected to find 1 BSS entry, got %d" % entries)
diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py
index c3ec68c..a69b872 100644
--- a/tests/hwsim/test_sigma_dut.py
+++ b/tests/hwsim/test_sigma_dut.py
@@ -73,7 +73,7 @@ def sigma_dut_cmd_check(cmd, port=9000, timeout=2):
return res
def start_sigma_dut(ifname, debug=False, hostapd_logdir=None, cert_path=None,
- bridge=None):
+ bridge=None, sae_h2e=False):
check_sigma_dut()
cmd = ['./sigma_dut',
'-M', ifname,
@@ -90,6 +90,8 @@ def start_sigma_dut(ifname, debug=False, hostapd_logdir=None, cert_path=None,
cmd += ['-C', cert_path]
if bridge:
cmd += ['-b', bridge]
+ if sae_h2e:
+ cmd += ['-2']
sigma = subprocess.Popen(cmd, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
for i in range(20):
@@ -519,6 +521,40 @@ def test_sigma_dut_ap_psk_sha256(dev, apdev, params):
finally:
stop_sigma_dut(sigma)
+def test_sigma_dut_ap_psk_deauth(dev, apdev, params):
+ """sigma_dut controlled AP and deauth commands"""
+ logdir = os.path.join(params['logdir'],
+ "sigma_dut_ap_psk_deauth.sigma-hostapd")
+ with HWSimRadio() as (radio, iface):
+ sigma = start_sigma_dut(iface, hostapd_logdir=logdir, debug=True)
+ try:
+ sigma_dut_cmd_check("ap_reset_default")
+ sigma_dut_cmd_check("ap_set_wireless,NAME,AP,CHANNEL,1,SSID,test-psk,MODE,11ng")
+ sigma_dut_cmd_check("ap_set_security,NAME,AP,KEYMGNT,WPA2-PSK,PSK,12345678,PMF,Required")
+ sigma_dut_cmd_check("ap_config_commit,NAME,AP")
+
+ dev[0].connect("test-psk", key_mgmt="WPA-PSK-SHA256",
+ psk="12345678", ieee80211w="2", scan_freq="2412")
+ addr = dev[0].own_addr()
+ dev[0].dump_monitor()
+
+ sigma_dut_cmd_check("ap_deauth_sta,NAME,AP,sta_mac_address," + addr)
+ ev = dev[0].wait_disconnected()
+ dev[0].dump_monitor()
+ if "locally_generated=1" in ev:
+ raise Exception("Unexpected disconnection reason")
+ dev[0].wait_connected()
+ dev[0].dump_monitor()
+
+ sigma_dut_cmd_check("ap_deauth_sta,NAME,AP,sta_mac_address," + addr + ",disconnect,silent")
+ ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=5)
+ if ev and "locally_generated=1" not in ev:
+ raise Exception("Unexpected disconnection")
+
+ sigma_dut_cmd_check("ap_reset_default")
+ finally:
+ stop_sigma_dut(sigma)
+
def test_sigma_dut_eap_ttls(dev, apdev, params):
"""sigma_dut controlled STA and EAP-TTLS parameters"""
logdir = params['logdir']
@@ -3239,3 +3275,324 @@ def test_sigma_dut_eap_ttls_uosc_ca_mistrust(dev, apdev, params):
dev[0].dump_monitor()
finally:
stop_sigma_dut(sigma)
+
+def start_sae_pwe_ap(apdev, sae_pwe):
+ ssid = "test-sae"
+ params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
+ params['wpa_key_mgmt'] = 'SAE'
+ params["ieee80211w"] = "2"
+ params['sae_groups'] = '19'
+ params['sae_pwe'] = str(sae_pwe)
+ return hostapd.add_ap(apdev, params)
+
+def connect_sae_pwe_sta(dev, ifname, extra=None):
+ dev.dump_monitor()
+ sigma_dut_cmd_check("sta_reset_default,interface,%s" % ifname)
+ sigma_dut_cmd_check("sta_set_ip_config,interface,%s,dhcp,0,ip,127.0.0.11,mask,255.255.255.0" % ifname)
+ cmd = "sta_set_security,interface,%s,ssid,%s,passphrase,%s,type,SAE,encpType,aes-ccmp,keymgmttype,wpa2" % (ifname, "test-sae", "12345678")
+ if extra:
+ cmd += "," + extra
+ sigma_dut_cmd_check(cmd)
+ sigma_dut_cmd_check("sta_associate,interface,%s,ssid,%s,channel,1" % (ifname, "test-sae"))
+ sigma_dut_wait_connected(ifname)
+ sigma_dut_cmd_check("sta_disconnect,interface," + ifname)
+ dev.wait_disconnected()
+ sigma_dut_cmd_check("sta_reset_default,interface," + ifname)
+ dev.dump_monitor()
+
+def no_connect_sae_pwe_sta(dev, ifname, extra=None):
+ dev.dump_monitor()
+ sigma_dut_cmd_check("sta_reset_default,interface,%s" % ifname)
+ sigma_dut_cmd_check("sta_set_ip_config,interface,%s,dhcp,0,ip,127.0.0.11,mask,255.255.255.0" % ifname)
+ cmd = "sta_set_security,interface,%s,ssid,%s,passphrase,%s,type,SAE,encpType,aes-ccmp,keymgmttype,wpa2" % (ifname, "test-sae", "12345678")
+ if extra:
+ cmd += "," + extra
+ sigma_dut_cmd_check(cmd)
+ sigma_dut_cmd_check("sta_associate,interface,%s,ssid,%s,channel,1" % (ifname, "test-sae"))
+ ev = dev.wait_event(["CTRL-EVENT-CONNECTED",
+ "CTRL-EVENT-NETWORK-NOT-FOUND"], timeout=10)
+ if ev is None or "CTRL-EVENT-CONNECTED" in ev:
+ raise Exception("Unexpected connection result")
+ sigma_dut_cmd_check("sta_reset_default,interface," + ifname)
+ dev.dump_monitor()
+
+def test_sigma_dut_sae_h2e(dev, apdev):
+ """sigma_dut controlled SAE H2E association (AP using loop+H2E)"""
+ if "SAE" not in dev[0].get_capability("auth_alg"):
+ raise HwsimSkip("SAE not supported")
+
+ start_sae_pwe_ap(apdev[0], 2)
+
+ ifname = dev[0].ifname
+ sigma = start_sigma_dut(ifname, sae_h2e=True, debug=True)
+ try:
+ connect_sae_pwe_sta(dev[0], ifname)
+ connect_sae_pwe_sta(dev[0], ifname, extra="sae_pwe,h2e")
+ connect_sae_pwe_sta(dev[0], ifname, extra="sae_pwe,loop")
+ res = sigma_dut_cmd("sta_set_security,interface,%s,ssid,%s,passphrase,%s,type,SAE,encpType,aes-ccmp,keymgmttype,wpa2,sae_pwe,unknown" % (ifname, "test-sae", "12345678"))
+ if res != "status,ERROR,errorCode,Unsupported sae_pwe value":
+ raise Exception("Unexpected error result: " + res)
+ finally:
+ stop_sigma_dut(sigma)
+ dev[0].set("sae_pwe", "0")
+
+def test_sigma_dut_sae_h2e_ap_loop(dev, apdev):
+ """sigma_dut controlled SAE H2E association (AP using loop-only)"""
+ if "SAE" not in dev[0].get_capability("auth_alg"):
+ raise HwsimSkip("SAE not supported")
+
+ start_sae_pwe_ap(apdev[0], 0)
+
+ ifname = dev[0].ifname
+ sigma = start_sigma_dut(ifname, sae_h2e=True, debug=True)
+ try:
+ connect_sae_pwe_sta(dev[0], ifname)
+ connect_sae_pwe_sta(dev[0], ifname, extra="sae_pwe,loop")
+ no_connect_sae_pwe_sta(dev[0], ifname, extra="sae_pwe,h2e")
+ finally:
+ stop_sigma_dut(sigma)
+ dev[0].set("sae_pwe", "0")
+
+def test_sigma_dut_sae_h2e_ap_h2e(dev, apdev):
+ """sigma_dut controlled SAE H2E association (AP using H2E-only)"""
+ if "SAE" not in dev[0].get_capability("auth_alg"):
+ raise HwsimSkip("SAE not supported")
+
+ start_sae_pwe_ap(apdev[0], 1)
+
+ ifname = dev[0].ifname
+ sigma = start_sigma_dut(ifname, sae_h2e=True, debug=True)
+ try:
+ connect_sae_pwe_sta(dev[0], ifname)
+ no_connect_sae_pwe_sta(dev[0], ifname, extra="sae_pwe,loop")
+ connect_sae_pwe_sta(dev[0], ifname, extra="sae_pwe,h2e")
+ finally:
+ stop_sigma_dut(sigma)
+ dev[0].set("sae_pwe", "0")
+
+def test_sigma_dut_ap_sae_h2e(dev, apdev, params):
+ """sigma_dut controlled AP with SAE H2E"""
+ logdir = os.path.join(params['logdir'],
+ "sigma_dut_ap_sae_h2e.sigma-hostapd")
+ if "SAE" not in dev[0].get_capability("auth_alg"):
+ raise HwsimSkip("SAE not supported")
+ with HWSimRadio() as (radio, iface):
+ sigma = start_sigma_dut(iface, sae_h2e=True, hostapd_logdir=logdir,
+ debug=True)
+ try:
+ sigma_dut_cmd_check("ap_reset_default")
+ sigma_dut_cmd_check("ap_set_wireless,NAME,AP,CHANNEL,1,SSID,test-sae,MODE,11ng")
+ sigma_dut_cmd_check("ap_set_security,NAME,AP,KEYMGNT,WPA2-SAE,PSK,12345678")
+ sigma_dut_cmd_check("ap_config_commit,NAME,AP")
+
+ for sae_pwe in [0, 1, 2]:
+ dev[0].request("SET sae_groups ")
+ dev[0].set("sae_pwe", str(sae_pwe))
+ dev[0].connect("test-sae", key_mgmt="SAE", psk="12345678",
+ ieee80211w="2", scan_freq="2412")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+ dev[0].dump_monitor()
+
+ sigma_dut_cmd_check("ap_reset_default")
+ finally:
+ stop_sigma_dut(sigma)
+ dev[0].set("sae_pwe", "0")
+
+def test_sigma_dut_ap_sae_h2e_only(dev, apdev, params):
+ """sigma_dut controlled AP with SAE H2E-only"""
+ logdir = os.path.join(params['logdir'],
+ "sigma_dut_ap_sae_h2e.sigma-hostapd")
+ if "SAE" not in dev[0].get_capability("auth_alg"):
+ raise HwsimSkip("SAE not supported")
+ with HWSimRadio() as (radio, iface):
+ sigma = start_sigma_dut(iface, sae_h2e=True, hostapd_logdir=logdir,
+ debug=True)
+ try:
+ sigma_dut_cmd_check("ap_reset_default")
+ sigma_dut_cmd_check("ap_set_wireless,NAME,AP,CHANNEL,1,SSID,test-sae,MODE,11ng")
+ sigma_dut_cmd_check("ap_set_security,NAME,AP,KEYMGNT,WPA2-SAE,PSK,12345678,sae_pwe,h2e")
+ sigma_dut_cmd_check("ap_config_commit,NAME,AP")
+
+ dev[0].request("SET sae_groups ")
+ dev[0].set("sae_pwe", "1")
+ dev[0].connect("test-sae", key_mgmt="SAE", psk="12345678",
+ ieee80211w="2", scan_freq="2412")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+ dev[0].dump_monitor()
+
+ dev[0].set("sae_pwe", "0")
+ dev[0].connect("test-sae", key_mgmt="SAE", psk="12345678",
+ ieee80211w="2", scan_freq="2412", wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
+ "CTRL-EVENT-NETWORK-NOT-FOUND"], timeout=10)
+ dev[0].request("DISCONNECT")
+ if ev is None or "CTRL-EVENT-CONNECTED" in ev:
+ raise Exception("Unexpected connection result")
+
+ sigma_dut_cmd_check("ap_reset_default")
+ finally:
+ stop_sigma_dut(sigma)
+ dev[0].set("sae_pwe", "0")
+
+def test_sigma_dut_ap_sae_loop_only(dev, apdev, params):
+ """sigma_dut controlled AP with SAE looping-only"""
+ logdir = os.path.join(params['logdir'],
+ "sigma_dut_ap_sae_h2e.sigma-hostapd")
+ if "SAE" not in dev[0].get_capability("auth_alg"):
+ raise HwsimSkip("SAE not supported")
+ with HWSimRadio() as (radio, iface):
+ sigma = start_sigma_dut(iface, sae_h2e=True, hostapd_logdir=logdir,
+ debug=True)
+ try:
+ sigma_dut_cmd_check("ap_reset_default")
+ sigma_dut_cmd_check("ap_set_wireless,NAME,AP,CHANNEL,1,SSID,test-sae,MODE,11ng")
+ sigma_dut_cmd_check("ap_set_security,NAME,AP,KEYMGNT,WPA2-SAE,PSK,12345678,sae_pwe,loop")
+ sigma_dut_cmd_check("ap_config_commit,NAME,AP")
+
+ dev[0].request("SET sae_groups ")
+ dev[0].set("sae_pwe", "0")
+ dev[0].connect("test-sae", key_mgmt="SAE", psk="12345678",
+ ieee80211w="2", scan_freq="2412")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+ dev[0].dump_monitor()
+
+ dev[0].set("sae_pwe", "1")
+ dev[0].connect("test-sae", key_mgmt="SAE", psk="12345678",
+ ieee80211w="2", scan_freq="2412", wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
+ "CTRL-EVENT-NETWORK-NOT-FOUND"], timeout=10)
+ dev[0].request("DISCONNECT")
+ if ev is None or "CTRL-EVENT-CONNECTED" in ev:
+ raise Exception("Unexpected connection result")
+
+ sigma_dut_cmd_check("ap_reset_default")
+ finally:
+ stop_sigma_dut(sigma)
+ dev[0].set("sae_pwe", "0")
+
+def test_sigma_dut_sae_h2e_loop_forcing(dev, apdev):
+ """sigma_dut controlled SAE H2E misbehavior with looping forced"""
+ if "SAE" not in dev[0].get_capability("auth_alg"):
+ raise HwsimSkip("SAE not supported")
+
+ ssid = "test-sae"
+ params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
+ params['wpa_key_mgmt'] = 'SAE'
+ params["ieee80211w"] = "2"
+ params['sae_pwe'] = '1'
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ ifname = dev[0].ifname
+ try:
+ sigma = start_sigma_dut(ifname)
+
+ sigma_dut_cmd_check("sta_reset_default,interface,%s" % ifname)
+ sigma_dut_cmd_check("sta_set_ip_config,interface,%s,dhcp,0,ip,127.0.0.11,mask,255.255.255.0" % ifname)
+ sigma_dut_cmd_check("sta_set_security,interface,%s,ssid,%s,passphrase,%s,type,SAE,encpType,aes-ccmp,keymgmttype,wpa2,IgnoreH2E_RSNXE_BSSMemSel,1" % (ifname, "test-sae", "12345678"))
+ sigma_dut_cmd_check("sta_associate,interface,%s,ssid,%s,channel,1" % (ifname, "test-sae"))
+ ev = dev[0].wait_event(["SME: Trying to authenticate with"], timeout=10)
+ if ev is None:
+ raise Exception("No authentication attempt reported")
+ ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=0.5)
+ if ev is not None:
+ raise Exception("Unexpected connection reported")
+ finally:
+ stop_sigma_dut(sigma)
+
+def test_sigma_dut_sae_h2e_enabled_group_rejected(dev, apdev):
+ """sigma_dut controlled SAE H2E misbehavior with rejected groups"""
+ if "SAE" not in dev[0].get_capability("auth_alg"):
+ raise HwsimSkip("SAE not supported")
+
+ ssid = "test-sae"
+ params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
+ params['wpa_key_mgmt'] = 'SAE'
+ params["ieee80211w"] = "2"
+ params['sae_groups'] = "19 20"
+ params['sae_pwe'] = '1'
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ ifname = dev[0].ifname
+ try:
+ sigma = start_sigma_dut(ifname, sae_h2e=True)
+
+ sigma_dut_cmd_check("sta_reset_default,interface,%s" % ifname)
+ sigma_dut_cmd_check("sta_set_ip_config,interface,%s,dhcp,0,ip,127.0.0.11,mask,255.255.255.0" % ifname)
+ sigma_dut_cmd_check("sta_set_security,interface,%s,ssid,%s,passphrase,%s,type,SAE,encpType,aes-ccmp,keymgmttype,wpa2,ECGroupID_RGE,19 123" % (ifname, "test-sae", "12345678"))
+ sigma_dut_cmd_check("sta_associate,interface,%s,ssid,%s,channel,1" % (ifname, "test-sae"))
+ ev = dev[0].wait_event(["SME: Trying to authenticate with"], timeout=10)
+ if ev is None:
+ raise Exception("No authentication attempt reported")
+ ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=0.5)
+ if ev is not None:
+ raise Exception("Unexpected connection reported")
+ finally:
+ stop_sigma_dut(sigma)
+
+def test_sigma_dut_sae_h2e_rsnxe_mismatch(dev, apdev):
+ """sigma_dut controlled SAE H2E misbehavior with RSNXE"""
+ if "SAE" not in dev[0].get_capability("auth_alg"):
+ raise HwsimSkip("SAE not supported")
+
+ ssid = "test-sae"
+ params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
+ params['wpa_key_mgmt'] = 'SAE'
+ params["ieee80211w"] = "2"
+ params['sae_groups'] = "19"
+ params['sae_pwe'] = '1'
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ ifname = dev[0].ifname
+ try:
+ sigma = start_sigma_dut(ifname, sae_h2e=True)
+
+ sigma_dut_cmd_check("sta_reset_default,interface,%s" % ifname)
+ sigma_dut_cmd_check("sta_set_ip_config,interface,%s,dhcp,0,ip,127.0.0.11,mask,255.255.255.0" % ifname)
+ sigma_dut_cmd_check("sta_set_security,interface,%s,ssid,%s,passphrase,%s,type,SAE,encpType,aes-ccmp,keymgmttype,wpa2,RSNXE_Content,EapolM2:F40100" % (ifname, "test-sae", "12345678"))
+ sigma_dut_cmd_check("sta_associate,interface,%s,ssid,%s,channel,1" % (ifname, "test-sae"))
+ ev = dev[0].wait_event(["SME: Trying to authenticate with"], timeout=10)
+ if ev is None:
+ raise Exception("No authentication attempt reported")
+ ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=0.5)
+ if ev is not None:
+ raise Exception("Unexpected connection reported")
+ finally:
+ stop_sigma_dut(sigma)
+
+def test_sigma_dut_ap_sae_h2e_rsnxe_mismatch(dev, apdev, params):
+ """sigma_dut controlled SAE H2E AP misbehavior with RSNXE"""
+ logdir = os.path.join(params['logdir'],
+ "sigma_dut_ap_sae_h2e_rsnxe_mismatch.sigma-hostapd")
+ if "SAE" not in dev[0].get_capability("auth_alg"):
+ raise HwsimSkip("SAE not supported")
+ with HWSimRadio() as (radio, iface):
+ sigma = start_sigma_dut(iface, sae_h2e=True, hostapd_logdir=logdir,
+ debug=True)
+ try:
+ sigma_dut_cmd_check("ap_reset_default")
+ sigma_dut_cmd_check("ap_set_wireless,NAME,AP,CHANNEL,1,SSID,test-sae,MODE,11ng")
+ sigma_dut_cmd_check("ap_set_security,NAME,AP,KEYMGNT,WPA2-SAE,PSK,12345678,sae_pwe,h2e,RSNXE_Content,EapolM3:F40100")
+ sigma_dut_cmd_check("ap_config_commit,NAME,AP")
+
+ dev[0].request("SET sae_groups ")
+ dev[0].set("sae_pwe", "1")
+ dev[0].connect("test-sae", key_mgmt="SAE", psk="12345678",
+ ieee80211w="2", scan_freq="2412", wait_connect=False)
+ ev = dev[0].wait_event(["Associated with"], timeout=10)
+ if ev is None:
+ raise Exception("No indication of association seen")
+ ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
+ "CTRL-EVENT-DISCONNECTED"], timeout=10)
+ dev[0].request("DISCONNECT")
+ if ev is None:
+ raise Exception("No disconnection seen")
+ if "CTRL-EVENT-DISCONNECTED" not in ev:
+ raise Exception("Unexpected connection")
+
+ sigma_dut_cmd_check("ap_reset_default")
+ finally:
+ stop_sigma_dut(sigma)
+ dev[0].set("sae_pwe", "0")
diff --git a/tests/hwsim/test_wmediumd.py b/tests/hwsim/test_wmediumd.py
index 0a88101..ad38f03 100644
--- a/tests/hwsim/test_wmediumd.py
+++ b/tests/hwsim/test_wmediumd.py
@@ -9,6 +9,7 @@ from utils import HwsimSkip
from wpasupplicant import WpaSupplicant
from tshark import run_tshark
from test_ap_open import _test_ap_open
+from test_scan import test_scan_only_one as _test_scan_only_one
from test_wpas_mesh import check_mesh_support, check_mesh_group_added
from test_wpas_mesh import check_mesh_peer_connected, add_open_mesh_network
from test_wpas_mesh import check_mesh_group_removed
@@ -462,3 +463,18 @@ def _test_wmediumd_path_rann(dev, apdev):
dev[i].mesh_group_remove()
check_mesh_group_removed(dev[i])
dev[i].dump_monitor()
+
+def test_wmediumd_scan_only_one(dev, apdev, params):
+ """Test that scanning with a single active AP only returns that one (wmediund)"""
+ fd, fn = tempfile.mkstemp()
+ try:
+ f = os.fdopen(fd, 'w')
+ f.write(CFG % (apdev[0]['bssid'], dev[0].own_addr()))
+ f.close()
+ p = start_wmediumd(fn, params)
+ try:
+ _test_scan_only_one(dev, apdev)
+ finally:
+ stop_wmediumd(p, params)
+ finally:
+ os.unlink(fn)
diff --git a/tests/hwsim/test_wpas_mesh.py b/tests/hwsim/test_wpas_mesh.py
index 12b00f7..5f9c83e 100644
--- a/tests/hwsim/test_wpas_mesh.py
+++ b/tests/hwsim/test_wpas_mesh.py
@@ -1668,17 +1668,21 @@ def test_wpas_mesh_pmksa_caching_ext(dev, apdev):
dev[1].mesh_group_remove()
check_mesh_group_removed(dev[1])
+ check_mesh_peer_disconnected(dev[0])
dev[0].dump_monitor()
dev[1].dump_monitor()
res = dev[1].get_pmksa(addr0)
if res is not None:
raise Exception("Unexpected PMKSA cache entry remaining")
+ time.sleep(0.1)
if "OK" not in dev[1].request("MESH_PMKSA_ADD " + res2):
raise Exception("MESH_PMKSA_ADD failed")
dev[1].mesh_group_add(id)
check_mesh_group_added(dev[1])
check_mesh_peer_connected(dev[1])
+ check_mesh_peer_connected(dev[0])
+ time.sleep(0.1)
dev[0].dump_monitor()
dev[1].dump_monitor()
pmksa1b = dev[1].get_pmksa(addr0)
diff --git a/tests/hwsim/vm/parallel-vm.py b/tests/hwsim/vm/parallel-vm.py
index 7eb44a9..521c13c 100755
--- a/tests/hwsim/vm/parallel-vm.py
+++ b/tests/hwsim/vm/parallel-vm.py
@@ -50,6 +50,8 @@ long_tests = ["ap_roam_open",
"discovery_pd_retries",
"ap_wps_setup_locked_timeout",
"ap_vht160",
+ 'he160',
+ 'he160b',
"dfs_radar",
"dfs",
"dfs_ht40_minus",
@@ -194,9 +196,14 @@ def show_progress(scr):
logger.info("VM[%d] kernel panic" % i)
updated = True
if test_queue:
- scr.addstr("unexpected exit")
- logger.info("VM[%d] unexpected exit" % i)
- updated = True
+ num_vm = 0
+ for i in range(num_servers):
+ if vm[i]['proc']:
+ num_vm += 1
+ if len(test_queue) > num_vm:
+ scr.addstr("unexpected exit")
+ logger.info("VM[%d] unexpected exit" % i)
+ updated = True
continue
running = True
diff --git a/tests/hwsim/wpasupplicant.py b/tests/hwsim/wpasupplicant.py
index 5549b7b..c9ebb25 100644
--- a/tests/hwsim/wpasupplicant.py
+++ b/tests/hwsim/wpasupplicant.py
@@ -1424,6 +1424,12 @@ class WpaSupplicant:
raise Exception("Failed to parse QR Code URI")
return int(res)
+ def dpp_nfc_uri(self, uri):
+ res = self.request("DPP_NFC_URI " + uri)
+ if "FAIL" in res:
+ raise Exception("Failed to parse NFC URI")
+ return int(res)
+
def dpp_bootstrap_gen(self, type="qrcode", chan=None, mac=None, info=None,
curve=None, key=None):
cmd = "DPP_BOOTSTRAP_GEN type=" + type
@@ -1458,10 +1464,14 @@ class WpaSupplicant:
def dpp_auth_init(self, peer=None, uri=None, conf=None, configurator=None,
extra=None, own=None, role=None, neg_freq=None,
ssid=None, passphrase=None, expect_fail=False,
- tcp_addr=None, tcp_port=None, conn_status=False):
+ tcp_addr=None, tcp_port=None, conn_status=False,
+ ssid_charset=None, nfc_uri=None):
cmd = "DPP_AUTH_INIT"
if peer is None:
- peer = self.dpp_qr_code(uri)
+ if nfc_uri:
+ peer = self.dpp_nfc_uri(nfc_uri)
+ else:
+ peer = self.dpp_qr_code(uri)
cmd += " peer=%d" % peer
if own is not None:
cmd += " own=%d" % own
@@ -1477,6 +1487,8 @@ class WpaSupplicant:
cmd += " neg_freq=%d" % neg_freq
if ssid:
cmd += " ssid=" + binascii.hexlify(ssid.encode()).decode()
+ if ssid_charset:
+ cmd += " ssid_charset=%d" % ssid_charset
if passphrase:
cmd += " pass=" + binascii.hexlify(passphrase.encode()).decode()
if tcp_addr:
diff --git a/wpa_supplicant/README-DPP b/wpa_supplicant/README-DPP
index 96b1735..457e32e 100644
--- a/wpa_supplicant/README-DPP
+++ b/wpa_supplicant/README-DPP
@@ -118,7 +118,9 @@ On successfully adding QR Code, a bootstrapping info id is returned.
Send provisioning request to enrollee. (conf is ap-dpp if enrollee is an
AP. conf is sta-dpp if enrollee is a client)
-> dpp_auth_init peer=<qr-code-id> conf=<ap-dpp|sta-dpp> configurator=<configurator-id>
+> dpp_auth_init peer=<qr-code-id> conf=<ap-dpp|sta-dpp> ssid=<SSID hexdump> configurator=<configurator-id>
+or for legacy (PSK/SAE) provisioning for a station Enrollee:
+> dpp_auth_init peer=<qr-code-id> conf=sta-psk ssid=<SSID hexdump> pass=<passphrase hexdump>
The DPP values will be printed in the console. Save this values into the
config file. If the enrollee is an AP, we need to manually write these
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index cf4b7bc..55971fc 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -296,7 +296,7 @@ static struct wpa_config_blob * wpa_config_read_blob(FILE *f, int *line,
{
struct wpa_config_blob *blob;
char buf[256], *pos;
- unsigned char *encoded = NULL, *nencoded;
+ char *encoded = NULL, *nencoded;
int end = 0;
size_t encoded_len = 0, len;
@@ -1098,7 +1098,7 @@ static void wpa_config_write_cred(FILE *f, struct wpa_cred *cred)
#ifndef CONFIG_NO_CONFIG_BLOBS
static int wpa_config_write_blob(FILE *f, struct wpa_config_blob *blob)
{
- unsigned char *encoded;
+ char *encoded;
encoded = base64_encode(blob->data, blob->len, NULL);
if (encoded == NULL)
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 7f8ec4a..f9a1fe1 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -663,6 +663,42 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
wpa_s->ignore_assoc_disallow = !!atoi(value);
wpa_drv_ignore_assoc_disallow(wpa_s,
wpa_s->ignore_assoc_disallow);
+ } else if (os_strcasecmp(cmd, "ignore_sae_h2e_only") == 0) {
+ wpa_s->ignore_sae_h2e_only = !!atoi(value);
+ } else if (os_strcasecmp(cmd, "extra_sae_rejected_groups") == 0) {
+ char *pos;
+
+ os_free(wpa_s->extra_sae_rejected_groups);
+ wpa_s->extra_sae_rejected_groups = NULL;
+ pos = value;
+ while (pos && pos[0]) {
+ int group;
+
+ group = atoi(pos);
+ wpa_printf(MSG_DEBUG,
+ "TESTING: Extra rejection of SAE group %d",
+ group);
+ if (group)
+ int_array_add_unique(
+ &wpa_s->extra_sae_rejected_groups,
+ group);
+ pos = os_strchr(pos, ' ');
+ if (!pos)
+ break;
+ pos++;
+ }
+ } else if (os_strcasecmp(cmd, "rsnxe_override_assoc") == 0) {
+ wpabuf_free(wpa_s->rsnxe_override_assoc);
+ if (os_strcmp(value, "NULL") == 0)
+ wpa_s->rsnxe_override_assoc = NULL;
+ else
+ wpa_s->rsnxe_override_assoc = wpabuf_parse_bin(value);
+ } else if (os_strcasecmp(cmd, "rsnxe_override_eapol") == 0) {
+ wpabuf_free(wpa_s->rsnxe_override_eapol);
+ if (os_strcmp(value, "NULL") == 0)
+ wpa_s->rsnxe_override_eapol = NULL;
+ else
+ wpa_s->rsnxe_override_eapol = wpabuf_parse_bin(value);
} else if (os_strcasecmp(cmd, "reject_btm_req_reason") == 0) {
wpa_s->reject_btm_req_reason = atoi(value);
} else if (os_strcasecmp(cmd, "get_pref_freq_list_override") == 0) {
@@ -8045,12 +8081,19 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
wpa_s->ignore_auth_resp = 0;
wpa_s->ignore_assoc_disallow = 0;
wpa_s->testing_resend_assoc = 0;
+ wpa_s->ignore_sae_h2e_only = 0;
wpa_s->reject_btm_req_reason = 0;
wpa_sm_set_test_assoc_ie(wpa_s->wpa, NULL);
os_free(wpa_s->get_pref_freq_list_override);
wpa_s->get_pref_freq_list_override = NULL;
wpabuf_free(wpa_s->sae_commit_override);
wpa_s->sae_commit_override = NULL;
+ os_free(wpa_s->extra_sae_rejected_groups);
+ wpa_s->extra_sae_rejected_groups = NULL;
+ wpabuf_free(wpa_s->rsnxe_override_assoc);
+ wpa_s->rsnxe_override_assoc = NULL;
+ wpabuf_free(wpa_s->rsnxe_override_eapol);
+ wpa_s->rsnxe_override_eapol = NULL;
#ifdef CONFIG_DPP
os_free(wpa_s->dpp_config_obj_override);
wpa_s->dpp_config_obj_override = NULL;
@@ -10678,6 +10721,17 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
if (os_snprintf_error(reply_size, reply_len))
reply_len = -1;
}
+ } else if (os_strncmp(buf, "DPP_NFC_URI ", 12) == 0) {
+ int res;
+
+ res = wpas_dpp_nfc_uri(wpa_s, buf + 12);
+ if (res < 0) {
+ reply_len = -1;
+ } else {
+ reply_len = os_snprintf(reply, reply_size, "%d", res);
+ if (os_snprintf_error(reply_size, reply_len))
+ reply_len = -1;
+ }
} else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) {
int res;
diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
index fc2fc2e..5e6b522 100644
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -3803,6 +3803,12 @@ static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = {
NULL,
NULL
},
+ { "MACAddressRandomizationMask", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ "a{say}",
+ wpas_dbus_getter_mac_address_randomization_mask,
+ wpas_dbus_setter_mac_address_randomization_mask,
+ NULL
+ },
{ NULL, NULL, NULL, NULL, NULL, NULL }
};
@@ -4791,8 +4797,8 @@ void wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s,
if (!wpa_s->dbus_groupobj_path) {
wpa_printf(MSG_DEBUG,
- "%s: Group object '%s' already unregistered",
- __func__, wpa_s->dbus_groupobj_path);
+ "%s: Group object has already unregistered",
+ __func__);
return;
}
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c
index d2c84e5..2582092 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -984,8 +984,7 @@ dbus_bool_t wpas_dbus_getter_global_capabilities(
const struct wpa_dbus_property_desc *property_desc,
DBusMessageIter *iter, DBusError *error, void *user_data)
{
- const char *capabilities[10] = { NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL };
+ const char *capabilities[11];
size_t num_items = 0;
#ifdef CONFIG_FILS
struct wpa_global *global = user_data;
@@ -1028,6 +1027,9 @@ dbus_bool_t wpas_dbus_getter_global_capabilities(
#ifdef CONFIG_SHA384
capabilities[num_items++] = "sha384";
#endif /* CONFIG_SHA384 */
+#ifdef CONFIG_OWE
+ capabilities[num_items++] = "owe";
+#endif /* CONFIG_OWE */
return wpas_dbus_simple_array_property_getter(iter,
DBUS_TYPE_STRING,
@@ -3984,6 +3986,173 @@ out:
/**
+ * wpas_dbus_setter_mac_address_randomization_mask - Set masks used for
+ * MAC address randomization
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Setter for "MACAddressRandomizationMask" property.
+ */
+dbus_bool_t wpas_dbus_setter_mac_address_randomization_mask(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = user_data;
+ DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter;
+ const char *key;
+ unsigned int rand_type = 0;
+ const u8 *mask;
+ int mask_len;
+ unsigned int rand_types_to_disable = MAC_ADDR_RAND_ALL;
+
+ dbus_message_iter_recurse(iter, &variant_iter);
+ if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY) {
+ dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
+ "invalid message format");
+ return FALSE;
+ }
+ dbus_message_iter_recurse(&variant_iter, &dict_iter);
+ while (dbus_message_iter_get_arg_type(&dict_iter) ==
+ DBUS_TYPE_DICT_ENTRY) {
+ dbus_message_iter_recurse(&dict_iter, &entry_iter);
+ if (dbus_message_iter_get_arg_type(&entry_iter) !=
+ DBUS_TYPE_STRING) {
+ dbus_set_error(error, DBUS_ERROR_FAILED,
+ "%s: key not a string", __func__);
+ return FALSE;
+ }
+ dbus_message_iter_get_basic(&entry_iter, &key);
+ dbus_message_iter_next(&entry_iter);
+ if (dbus_message_iter_get_arg_type(&entry_iter) !=
+ DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type(&entry_iter) !=
+ DBUS_TYPE_BYTE) {
+ dbus_set_error(error, DBUS_ERROR_FAILED,
+ "%s: mask was not a byte array",
+ __func__);
+ return FALSE;
+ }
+ dbus_message_iter_recurse(&entry_iter, &array_iter);
+ dbus_message_iter_get_fixed_array(&array_iter, &mask,
+ &mask_len);
+
+ if (os_strcmp(key, "scan") == 0) {
+ rand_type = MAC_ADDR_RAND_SCAN;
+ } else if (os_strcmp(key, "sched_scan") == 0) {
+ rand_type = MAC_ADDR_RAND_SCHED_SCAN;
+ } else if (os_strcmp(key, "pno") == 0) {
+ rand_type = MAC_ADDR_RAND_PNO;
+ } else {
+ dbus_set_error(error, DBUS_ERROR_FAILED,
+ "%s: bad scan type \"%s\"",
+ __func__, key);
+ return FALSE;
+ }
+
+ if (mask_len != ETH_ALEN) {
+ dbus_set_error(error, DBUS_ERROR_FAILED,
+ "%s: malformed MAC mask given",
+ __func__);
+ return FALSE;
+ }
+
+ if (wpas_enable_mac_addr_randomization(
+ wpa_s, rand_type, wpa_s->perm_addr, mask)) {
+ dbus_set_error(error, DBUS_ERROR_FAILED,
+ "%s: failed to set up MAC address randomization for %s",
+ __func__, key);
+ return FALSE;
+ }
+
+ wpa_printf(MSG_DEBUG,
+ "%s: Enabled MAC address randomization for %s with mask: "
+ MACSTR, wpa_s->ifname, key, MAC2STR(mask));
+ rand_types_to_disable &= ~rand_type;
+ dbus_message_iter_next(&dict_iter);
+ }
+
+ if (rand_types_to_disable &&
+ wpas_disable_mac_addr_randomization(wpa_s, rand_types_to_disable)) {
+ dbus_set_error(error, DBUS_ERROR_FAILED,
+ "%s: failed to disable MAC address randomization",
+ __func__);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+dbus_bool_t wpas_dbus_getter_mac_address_randomization_mask(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = user_data;
+ DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter;
+ unsigned int i;
+ u8 mask_buf[ETH_ALEN];
+ /* Read docs on dbus_message_iter_append_fixed_array() for why this
+ * is necessary... */
+ u8 *mask = mask_buf;
+ static const struct {
+ const char *key;
+ unsigned int type;
+ } types[] = {
+ { "scan", MAC_ADDR_RAND_SCAN },
+ { "sched_scan", MAC_ADDR_RAND_SCHED_SCAN },
+ { "pno", MAC_ADDR_RAND_PNO }
+ };
+
+ if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
+ "a{say}", &variant_iter) ||
+ !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
+ "{say}", &dict_iter)) {
+ dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
+ return FALSE;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(types); i++) {
+ if (wpas_mac_addr_rand_scan_get_mask(wpa_s, types[i].type,
+ mask))
+ continue;
+
+ if (!dbus_message_iter_open_container(&dict_iter,
+ DBUS_TYPE_DICT_ENTRY,
+ NULL, &entry_iter) ||
+ !dbus_message_iter_append_basic(&entry_iter,
+ DBUS_TYPE_STRING,
+ &types[i].key) ||
+ !dbus_message_iter_open_container(&entry_iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_TYPE_BYTE_AS_STRING,
+ &array_iter) ||
+ !dbus_message_iter_append_fixed_array(&array_iter,
+ DBUS_TYPE_BYTE,
+ &mask,
+ ETH_ALEN) ||
+ !dbus_message_iter_close_container(&entry_iter,
+ &array_iter) ||
+ !dbus_message_iter_close_container(&dict_iter,
+ &entry_iter)) {
+ dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
+ "no memory");
+ return FALSE;
+ }
+ }
+
+ if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) ||
+ !dbus_message_iter_close_container(iter, &variant_iter)) {
+ dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/**
* wpas_dbus_getter_sta_address - Return the address of a connected station
* @iter: Pointer to incoming dbus message iter
* @error: Location to store error on failure
@@ -4491,7 +4660,7 @@ static dbus_bool_t wpas_dbus_get_bss_security_prop(
DBusMessageIter iter_dict, variant_iter;
const char *group;
const char *pairwise[5]; /* max 5 pairwise ciphers is supported */
- const char *key_mgmt[15]; /* max 15 key managements may be supported */
+ const char *key_mgmt[16]; /* max 16 key managements may be supported */
int n;
if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
@@ -4544,6 +4713,10 @@ static dbus_bool_t wpas_dbus_get_bss_security_prop(
if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_SAE)
key_mgmt[n++] = "ft-sae";
#endif /* CONFIG_SAE */
+#ifdef CONFIG_OWE
+ if (ie_data->key_mgmt & WPA_KEY_MGMT_OWE)
+ key_mgmt[n++] = "owe";
+#endif /* CONFIG_OWE */
if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE)
key_mgmt[n++] = "wpa-none";
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h b/wpa_supplicant/dbus/dbus_new_handlers.h
index d922ce1..afa26ef 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.h
+++ b/wpa_supplicant/dbus/dbus_new_handlers.h
@@ -177,6 +177,8 @@ DECLARE_ACCESSOR(wpas_dbus_getter_pkcs11_engine_path);
DECLARE_ACCESSOR(wpas_dbus_getter_pkcs11_module_path);
DECLARE_ACCESSOR(wpas_dbus_getter_blobs);
DECLARE_ACCESSOR(wpas_dbus_getter_stas);
+DECLARE_ACCESSOR(wpas_dbus_getter_mac_address_randomization_mask);
+DECLARE_ACCESSOR(wpas_dbus_setter_mac_address_randomization_mask);
DECLARE_ACCESSOR(wpas_dbus_getter_sta_address);
DECLARE_ACCESSOR(wpas_dbus_getter_sta_aid);
DECLARE_ACCESSOR(wpas_dbus_getter_sta_caps);
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
index 8cdd885..19715eb 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
@@ -40,6 +40,14 @@ static int wpas_dbus_validate_dbus_ipaddr(struct wpa_dbus_dict_entry entry)
}
+static dbus_bool_t no_p2p_mgmt_interface(DBusError *error)
+{
+ dbus_set_error_const(error, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
+ "Could not find P2P mgmt interface");
+ return FALSE;
+}
+
+
/**
* Parses out the mac address from the peer object path.
* @peer_path - object path of the form
@@ -78,6 +86,22 @@ wpas_dbus_error_persistent_group_unknown(DBusMessage *message)
}
+/**
+ * wpas_dbus_error_no_p2p_mgmt_iface - Return a new InterfaceUnknown error
+ * message
+ * @message: Pointer to incoming dbus message this error refers to
+ * Returns: a dbus error message
+ *
+ * Convenience function to create and return an unknown interface error.
+ */
+static DBusMessage * wpas_dbus_error_no_p2p_mgmt_iface(DBusMessage *message)
+{
+ wpa_printf(MSG_DEBUG, "dbus: Could not find P2P mgmt interface");
+ return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
+ "Could not find P2P mgmt interface");
+}
+
+
DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message,
struct wpa_supplicant *wpa_s)
{
@@ -145,6 +169,10 @@ DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message,
}
wpa_s = wpa_s->global->p2p_init_wpa_s;
+ if (!wpa_s) {
+ reply = wpas_dbus_error_no_p2p_mgmt_iface(message);
+ goto error_nop2p;
+ }
if (wpas_p2p_find(wpa_s, timeout, type, num_req_dev_types,
req_dev_types, NULL, 0, 0, NULL, freq))
@@ -157,8 +185,9 @@ DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message,
error_clear:
wpa_dbus_dict_entry_clear(&entry);
error:
- os_free(req_dev_types);
reply = wpas_dbus_error_invalid_args(message, entry.key);
+error_nop2p:
+ os_free(req_dev_types);
return reply;
}
@@ -166,7 +195,9 @@ error:
DBusMessage * wpas_dbus_handler_p2p_stop_find(DBusMessage *message,
struct wpa_supplicant *wpa_s)
{
- wpas_p2p_stop_find(wpa_s->global->p2p_init_wpa_s);
+ wpa_s = wpa_s->global->p2p_init_wpa_s;
+ if (wpa_s)
+ wpas_p2p_stop_find(wpa_s);
return NULL;
}
@@ -185,6 +216,8 @@ DBusMessage * wpas_dbus_handler_p2p_rejectpeer(DBusMessage *message,
return wpas_dbus_error_invalid_args(message, NULL);
wpa_s = wpa_s->global->p2p_init_wpa_s;
+ if (!wpa_s)
+ return wpas_dbus_error_no_p2p_mgmt_iface(message);
if (wpas_p2p_reject(wpa_s, peer_addr) < 0)
return wpas_dbus_error_unknown_error(message,
@@ -204,6 +237,8 @@ DBusMessage * wpas_dbus_handler_p2p_listen(DBusMessage *message,
return wpas_dbus_error_no_memory(message);
wpa_s = wpa_s->global->p2p_init_wpa_s;
+ if (!wpa_s)
+ return wpas_dbus_error_no_p2p_mgmt_iface(message);
if (wpas_p2p_listen(wpa_s, (unsigned int) timeout)) {
return dbus_message_new_error(message,
@@ -245,6 +280,8 @@ DBusMessage * wpas_dbus_handler_p2p_extendedlisten(
}
wpa_s = wpa_s->global->p2p_init_wpa_s;
+ if (!wpa_s)
+ return wpas_dbus_error_no_p2p_mgmt_iface(message);
if (wpas_p2p_ext_listen(wpa_s, period, interval))
return wpas_dbus_error_unknown_error(
@@ -350,6 +387,10 @@ DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
}
wpa_s = wpa_s->global->p2p_init_wpa_s;
+ if (!wpa_s) {
+ reply = wpas_dbus_error_no_p2p_mgmt_iface(message);
+ goto out;
+ }
if (pg_object_path != NULL) {
char *net_id_str;
@@ -433,6 +474,12 @@ static dbus_bool_t wpa_dbus_p2p_check_enabled(struct wpa_supplicant *wpa_s,
"P2P is not available for this interface");
return FALSE;
}
+ if (!wpa_s->global->p2p_init_wpa_s) {
+ if (out_reply)
+ *out_reply = wpas_dbus_error_no_p2p_mgmt_iface(
+ message);
+ return no_p2p_mgmt_interface(error);
+ }
return TRUE;
}
@@ -822,6 +869,8 @@ DBusMessage * wpas_dbus_handler_p2p_prov_disc_req(DBusMessage *message,
return wpas_dbus_error_invalid_args(message, NULL);
wpa_s = wpa_s->global->p2p_init_wpa_s;
+ if (!wpa_s)
+ return wpas_dbus_error_no_p2p_mgmt_iface(message);
if (wpas_p2p_prov_disc(wpa_s, peer_addr, config_method,
WPAS_P2P_PD_FOR_GO_NEG, NULL) < 0)
@@ -1882,6 +1931,8 @@ dbus_bool_t wpas_dbus_getter_p2p_peer_groups(
wpa_s = peer_args->wpa_s;
wpa_s = wpa_s->global->p2p_init_wpa_s;
+ if (!wpa_s)
+ return no_p2p_mgmt_interface(error);
wpa_s_go = wpas_get_p2p_client_iface(wpa_s, info->p2p_device_addr);
if (wpa_s_go) {
@@ -1963,6 +2014,9 @@ dbus_bool_t wpas_dbus_getter_persistent_groups(
dbus_bool_t success = FALSE;
wpa_s = wpa_s->global->p2p_init_wpa_s;
+ if (!wpa_s)
+ return no_p2p_mgmt_interface(error);
+
if (!wpa_s->parent->dbus_new_path)
return FALSE;
@@ -2077,6 +2131,11 @@ DBusMessage * wpas_dbus_handler_add_persistent_group(
dbus_message_iter_init(message, &iter);
wpa_s = wpa_s->global->p2p_init_wpa_s;
+ if (!wpa_s) {
+ reply = wpas_dbus_error_no_p2p_mgmt_iface(message);
+ goto err;
+ }
+
if (wpa_s->parent->dbus_new_path)
ssid = wpa_config_add_network(wpa_s->conf);
if (ssid == NULL) {
@@ -2159,6 +2218,10 @@ DBusMessage * wpas_dbus_handler_remove_persistent_group(
DBUS_TYPE_INVALID);
wpa_s = wpa_s->global->p2p_init_wpa_s;
+ if (!wpa_s) {
+ reply = wpas_dbus_error_no_p2p_mgmt_iface(message);
+ goto out;
+ }
/*
* Extract the network ID and ensure the network is actually a child of
@@ -2235,6 +2298,8 @@ DBusMessage * wpas_dbus_handler_remove_all_persistent_groups(
struct wpa_config *config;
wpa_s = wpa_s->global->p2p_init_wpa_s;
+ if (!wpa_s)
+ return wpas_dbus_error_no_p2p_mgmt_iface(message);
config = wpa_s->conf;
ssid = config->ssid;
diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig
index 6ae07a4..792ab24 100644
--- a/wpa_supplicant/defconfig
+++ b/wpa_supplicant/defconfig
@@ -362,7 +362,7 @@ CONFIG_BACKEND=file
#PLATFORMSDKLIB="/opt/Program Files/Microsoft Platform SDK/Lib"
# Add support for new DBus control interface
-# (fi.w1.hostap.wpa_supplicant1)
+# (fi.w1.wpa_supplicant1)
CONFIG_CTRL_IFACE_DBUS_NEW=y
# Add introspection support for new DBus control interface
diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c
index 425eff9..80d2c9c 100644
--- a/wpa_supplicant/dpp_supplicant.c
+++ b/wpa_supplicant/dpp_supplicant.c
@@ -88,6 +88,24 @@ int wpas_dpp_qr_code(struct wpa_supplicant *wpa_s, const char *cmd)
}
+/**
+ * wpas_dpp_nfc_uri - Parse and add DPP bootstrapping info from NFC Tag (URI)
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @cmd: DPP URI read from a NFC Tag (URI NDEF message)
+ * Returns: Identifier of the stored info or -1 on failure
+ */
+int wpas_dpp_nfc_uri(struct wpa_supplicant *wpa_s, const char *cmd)
+{
+ struct dpp_bootstrap_info *bi;
+
+ bi = dpp_add_nfc_uri(wpa_s->dpp, cmd);
+ if (!bi)
+ return -1;
+
+ return bi->id;
+}
+
+
static void wpas_dpp_auth_resp_retry_timeout(void *eloop_ctx, void *timeout_ctx)
{
struct wpa_supplicant *wpa_s = eloop_ctx;
@@ -1114,6 +1132,9 @@ static int wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s,
if (conf->ssid_len)
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
wpa_ssid_txt(conf->ssid, conf->ssid_len));
+ if (conf->ssid_charset)
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID_CHARSET "%d",
+ conf->ssid_charset);
if (conf->connector) {
/* TODO: Save the Connector and consider using a command
* to fetch the value instead of sending an event with
diff --git a/wpa_supplicant/dpp_supplicant.h b/wpa_supplicant/dpp_supplicant.h
index b337982..607036a 100644
--- a/wpa_supplicant/dpp_supplicant.h
+++ b/wpa_supplicant/dpp_supplicant.h
@@ -13,6 +13,7 @@
enum dpp_status_error;
int wpas_dpp_qr_code(struct wpa_supplicant *wpa_s, const char *cmd);
+int wpas_dpp_nfc_uri(struct wpa_supplicant *wpa_s, const char *cmd);
int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd);
int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd);
void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s);
diff --git a/wpa_supplicant/eapol_test.c b/wpa_supplicant/eapol_test.c
index 524724f..53d7585 100644
--- a/wpa_supplicant/eapol_test.c
+++ b/wpa_supplicant/eapol_test.c
@@ -439,7 +439,7 @@ static void eapol_sm_cb(struct eapol_sm *eapol, enum eapol_supp_result result,
static void eapol_test_write_cert(FILE *f, const char *subject,
const struct wpabuf *cert)
{
- unsigned char *encoded;
+ char *encoded;
encoded = base64_encode(wpabuf_head(cert), wpabuf_len(cert), NULL);
if (encoded == NULL)
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index ac4274c..2316037 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -857,6 +857,13 @@ static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
if (debug_print)
wpa_dbg(wpa_s, MSG_DEBUG,
" SAE H2E disabled");
+#ifdef CONFIG_TESTING_OPTIONS
+ if (wpa_s->ignore_sae_h2e_only) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "TESTING: Ignore SAE H2E requirement mismatch");
+ continue;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
return 0;
}
continue;
@@ -3010,6 +3017,16 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_MBO
wpas_mbo_check_pmf(wpa_s, bss, wpa_s->current_ssid);
#endif /* CONFIG_MBO */
+
+#ifdef CONFIG_TESTING_OPTIONS
+ if (wpa_s->rsnxe_override_eapol) {
+ wpa_printf(MSG_DEBUG,
+ "TESTING: RSNXE EAPOL-Key msg 2/4 override");
+ wpa_sm_set_assoc_rsnxe(wpa_s->wpa,
+ wpabuf_head(wpa_s->rsnxe_override_eapol),
+ wpabuf_len(wpa_s->rsnxe_override_eapol));
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
}
@@ -3054,7 +3071,8 @@ static int could_be_psk_mismatch(struct wpa_supplicant *wpa_s, u16 reason_code,
int locally_generated)
{
if (wpa_s->wpa_state != WPA_4WAY_HANDSHAKE ||
- !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt))
+ !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
+ wpa_key_mgmt_sae(wpa_s->key_mgmt))
return 0; /* Not in 4-way handshake with PSK */
/*
diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c
index cb236df..47a1d01 100644
--- a/wpa_supplicant/hs20_supplicant.c
+++ b/wpa_supplicant/hs20_supplicant.c
@@ -340,7 +340,7 @@ int hs20_get_icon(struct wpa_supplicant *wpa_s, const u8 *bssid,
{
struct icon_entry *icon;
size_t out_size;
- unsigned char *b64;
+ char *b64;
size_t b64_size;
int reply_size;
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index 0261bb7..49b9907 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -176,7 +176,7 @@ static int cred_with_nai_realm(struct wpa_supplicant *wpa_s)
continue;
if (!cred->eap_method)
return 1;
- if (cred->realm && cred->roaming_consortium_len == 0)
+ if (cred->realm)
return 1;
}
return 0;
@@ -2262,7 +2262,7 @@ int interworking_home_sp_cred(struct wpa_supplicant *wpa_s,
realm++;
wpa_msg(wpa_s, MSG_DEBUG,
"Interworking: Search for match with SIM/USIM domain %s",
- realm);
+ realm ? realm : "[NULL]");
if (realm &&
domain_name_list_contains(domain_names, realm, 1))
return 1;
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index 7abb028..4d158a9 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -79,6 +79,33 @@ static int wpas_wps_in_use(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_WPS */
+static int wpa_setup_mac_addr_rand_params(struct wpa_driver_scan_params *params,
+ const u8 *mac_addr)
+{
+ u8 *tmp;
+
+ if (params->mac_addr) {
+ params->mac_addr_mask = NULL;
+ os_free(params->mac_addr);
+ params->mac_addr = NULL;
+ }
+
+ params->mac_addr_rand = 1;
+
+ if (!mac_addr)
+ return 0;
+
+ tmp = os_malloc(2 * ETH_ALEN);
+ if (!tmp)
+ return -1;
+
+ os_memcpy(tmp, mac_addr, 2 * ETH_ALEN);
+ params->mac_addr = tmp;
+ params->mac_addr_mask = tmp + ETH_ALEN;
+ return 0;
+}
+
+
/**
* wpa_supplicant_enabled_networks - Check whether there are enabled networks
* @wpa_s: Pointer to wpa_supplicant data
@@ -169,6 +196,10 @@ static void wpas_trigger_scan_cb(struct wpa_radio_work *work, int deinit)
return;
}
+ if ((wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_SCAN) &&
+ wpa_s->wpa_state <= WPA_SCANNING)
+ wpa_setup_mac_addr_rand_params(params, wpa_s->mac_addr_scan);
+
if (wpas_update_random_addr_disassoc(wpa_s) < 0) {
wpa_msg(wpa_s, MSG_INFO,
"Failed to assign random MAC address for a scan");
@@ -1211,13 +1242,8 @@ ssid_list_set:
#endif /* CONFIG_P2P */
if ((wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_SCAN) &&
- wpa_s->wpa_state <= WPA_SCANNING) {
- params.mac_addr_rand = 1;
- if (wpa_s->mac_addr_scan) {
- params.mac_addr = wpa_s->mac_addr_scan;
- params.mac_addr_mask = wpa_s->mac_addr_scan + ETH_ALEN;
- }
- }
+ wpa_s->wpa_state <= WPA_SCANNING)
+ wpa_setup_mac_addr_rand_params(&params, wpa_s->mac_addr_scan);
if (!is_zero_ether_addr(wpa_s->next_scan_bssid)) {
struct wpa_bss *bss;
@@ -1286,6 +1312,7 @@ scan:
wpabuf_free(extra_ie);
os_free(params.freqs);
os_free(params.filter_ssids);
+ os_free(params.mac_addr);
if (ret) {
wpa_msg(wpa_s, MSG_WARNING, "Failed to initiate AP scan");
@@ -1664,20 +1691,16 @@ scan:
wpa_setband_scan_freqs(wpa_s, scan_params);
if ((wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_SCHED_SCAN) &&
- wpa_s->wpa_state <= WPA_SCANNING) {
- params.mac_addr_rand = 1;
- if (wpa_s->mac_addr_sched_scan) {
- params.mac_addr = wpa_s->mac_addr_sched_scan;
- params.mac_addr_mask = wpa_s->mac_addr_sched_scan +
- ETH_ALEN;
- }
- }
+ wpa_s->wpa_state <= WPA_SCANNING)
+ wpa_setup_mac_addr_rand_params(&params,
+ wpa_s->mac_addr_sched_scan);
wpa_scan_set_relative_rssi_params(wpa_s, scan_params);
ret = wpa_supplicant_start_sched_scan(wpa_s, scan_params);
wpabuf_free(extra_ie);
os_free(params.filter_ssids);
+ os_free(params.mac_addr);
if (ret) {
wpa_msg(wpa_s, MSG_WARNING, "Failed to initiate sched scan");
if (prev_state != wpa_s->wpa_state)
@@ -2535,23 +2558,9 @@ wpa_scan_clone_params(const struct wpa_driver_scan_params *src)
params->sched_scan_plans_num = src->sched_scan_plans_num;
}
- if (src->mac_addr_rand) {
- params->mac_addr_rand = src->mac_addr_rand;
-
- if (src->mac_addr && src->mac_addr_mask) {
- u8 *mac_addr;
-
- mac_addr = os_malloc(2 * ETH_ALEN);
- if (!mac_addr)
- goto failed;
-
- os_memcpy(mac_addr, src->mac_addr, ETH_ALEN);
- os_memcpy(mac_addr + ETH_ALEN, src->mac_addr_mask,
- ETH_ALEN);
- params->mac_addr = mac_addr;
- params->mac_addr_mask = mac_addr + ETH_ALEN;
- }
- }
+ if (src->mac_addr_rand &&
+ wpa_setup_mac_addr_rand_params(params, src->mac_addr))
+ goto failed;
if (src->bssid) {
u8 *bssid;
@@ -2738,18 +2747,14 @@ int wpas_start_pno(struct wpa_supplicant *wpa_s)
}
if ((wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_PNO) &&
- wpa_s->wpa_state <= WPA_SCANNING) {
- params.mac_addr_rand = 1;
- if (wpa_s->mac_addr_pno) {
- params.mac_addr = wpa_s->mac_addr_pno;
- params.mac_addr_mask = wpa_s->mac_addr_pno + ETH_ALEN;
- }
- }
+ wpa_s->wpa_state <= WPA_SCANNING)
+ wpa_setup_mac_addr_rand_params(&params, wpa_s->mac_addr_pno);
wpa_scan_set_relative_rssi_params(wpa_s, &params);
ret = wpa_supplicant_start_sched_scan(wpa_s, &params);
os_free(params.filter_ssids);
+ os_free(params.mac_addr);
if (ret == 0)
wpa_s->pno = 1;
else
@@ -2843,6 +2848,32 @@ int wpas_mac_addr_rand_scan_set(struct wpa_supplicant *wpa_s,
}
+int wpas_mac_addr_rand_scan_get_mask(struct wpa_supplicant *wpa_s,
+ unsigned int type, u8 *mask)
+{
+ const u8 *to_copy;
+
+ if ((wpa_s->mac_addr_rand_enable & type) != type)
+ return -1;
+
+ if (type == MAC_ADDR_RAND_SCAN) {
+ to_copy = wpa_s->mac_addr_scan;
+ } else if (type == MAC_ADDR_RAND_SCHED_SCAN) {
+ to_copy = wpa_s->mac_addr_sched_scan;
+ } else if (type == MAC_ADDR_RAND_PNO) {
+ to_copy = wpa_s->mac_addr_pno;
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "scan: Invalid MAC randomization type=0x%x",
+ type);
+ return -1;
+ }
+
+ os_memcpy(mask, to_copy + ETH_ALEN, ETH_ALEN);
+ return 0;
+}
+
+
int wpas_abort_ongoing_scan(struct wpa_supplicant *wpa_s)
{
struct wpa_radio_work *work;
diff --git a/wpa_supplicant/scan.h b/wpa_supplicant/scan.h
index 2aa0a8b..58caa78 100644
--- a/wpa_supplicant/scan.h
+++ b/wpa_supplicant/scan.h
@@ -52,6 +52,8 @@ void wpas_mac_addr_rand_scan_clear(struct wpa_supplicant *wpa_s,
int wpas_mac_addr_rand_scan_set(struct wpa_supplicant *wpa_s,
unsigned int type, const u8 *addr,
const u8 *mask);
+int wpas_mac_addr_rand_scan_get_mask(struct wpa_supplicant *wpa_s,
+ unsigned int type, u8 *mask);
int wpas_abort_ongoing_scan(struct wpa_supplicant *wpa_s);
void filter_scan_res(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *res);
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index c8a5d4b..7498024 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -591,6 +591,18 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
os_memcpy(pos, ext_capab, ext_capab_len);
}
+#ifdef CONFIG_TESTING_OPTIONS
+ if (wpa_s->rsnxe_override_assoc &&
+ wpabuf_len(wpa_s->rsnxe_override_assoc) <=
+ sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len) {
+ wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
+ os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
+ wpabuf_head(wpa_s->rsnxe_override_assoc),
+ wpabuf_len(wpa_s->rsnxe_override_assoc));
+ wpa_s->sme.assoc_req_ie_len +=
+ wpabuf_len(wpa_s->rsnxe_override_assoc);
+ } else
+#endif /* CONFIG_TESTING_OPTIONS */
if (wpa_s->rsnxe_len > 0 &&
wpa_s->rsnxe_len <=
sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len) {
@@ -1242,8 +1254,11 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
if ((!external && wpa_s->current_bss == NULL) ||
wpa_s->current_ssid == NULL)
return -1;
- if (wpa_s->sme.sae.state != SAE_COMMITTED)
- return -1;
+ if (wpa_s->sme.sae.state != SAE_COMMITTED) {
+ wpa_printf(MSG_DEBUG,
+ "SAE: Ignore commit message while waiting for confirm");
+ return 0;
+ }
if (groups && groups[0] <= 0)
groups = NULL;
res = sae_parse_commit(&wpa_s->sme.sae, data, len, NULL, NULL,
@@ -1260,7 +1275,7 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
if (wpa_s->sme.sae.tmp &&
sme_check_sae_rejected_groups(
wpa_s,
- wpa_s->sme.sae.tmp->peer_rejected_groups) < 0)
+ wpa_s->sme.sae.tmp->peer_rejected_groups))
return -1;
if (sae_process_commit(&wpa_s->sme.sae) < 0) {
diff --git a/wpa_supplicant/wpa_priv.c b/wpa_supplicant/wpa_priv.c
index b3ad45e..f197352 100644
--- a/wpa_supplicant/wpa_priv.c
+++ b/wpa_supplicant/wpa_priv.c
@@ -598,7 +598,7 @@ static void wpa_priv_cmd_l2_send(struct wpa_priv_interface *iface,
}
dst_addr = buf;
- os_memcpy(&proto, buf + ETH_ALEN, 2);
+ os_memcpy(&proto, (char *) buf + ETH_ALEN, 2);
if (!wpa_priv_allowed_l2_proto(proto)) {
wpa_printf(MSG_DEBUG, "Refused l2_packet send for ethertype "
@@ -607,7 +607,8 @@ static void wpa_priv_cmd_l2_send(struct wpa_priv_interface *iface,
}
res = l2_packet_send(iface->l2[idx], dst_addr, proto,
- buf + ETH_ALEN + 2, len - ETH_ALEN - 2);
+ (unsigned char *) buf + ETH_ALEN + 2,
+ len - ETH_ALEN - 2);
wpa_printf(MSG_DEBUG, "L2 send[idx=%d]: res=%d", idx, res);
}
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 6688d71..0fee3c9 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -499,6 +499,12 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
wpa_s->get_pref_freq_list_override = NULL;
wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
wpa_s->last_assoc_req_wpa_ie = NULL;
+ os_free(wpa_s->extra_sae_rejected_groups);
+ wpa_s->extra_sae_rejected_groups = NULL;
+ wpabuf_free(wpa_s->rsnxe_override_assoc);
+ wpa_s->rsnxe_override_assoc = NULL;
+ wpabuf_free(wpa_s->rsnxe_override_eapol);
+ wpa_s->rsnxe_override_eapol = NULL;
#endif /* CONFIG_TESTING_OPTIONS */
if (wpa_s->conf != NULL) {
@@ -1972,6 +1978,28 @@ static void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid)
}
+static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
+{
+#if defined(CONFIG_SAE) && defined(CONFIG_SME)
+ os_free(wpa_s->sme.sae_rejected_groups);
+ wpa_s->sme.sae_rejected_groups = NULL;
+#ifdef CONFIG_TESTING_OPTIONS
+ if (wpa_s->extra_sae_rejected_groups) {
+ int i, *groups = wpa_s->extra_sae_rejected_groups;
+
+ for (i = 0; groups[i]; i++) {
+ wpa_printf(MSG_DEBUG,
+ "TESTING: Indicate rejection of an extra SAE group %d",
+ groups[i]);
+ int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
+ groups[i]);
+ }
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
+#endif /* CONFIG_SAE && CONFIG_SME */
+}
+
+
static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
/**
@@ -2020,10 +2048,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
}
} else {
#ifdef CONFIG_SAE
-#ifdef CONFIG_SME
- os_free(wpa_s->sme.sae_rejected_groups);
- wpa_s->sme.sae_rejected_groups = NULL;
-#endif /* CONFIG_SME */
+ wpa_s_clear_sae_rejected(wpa_s);
wpa_s_setup_sae_pt(wpa_s->conf, ssid);
#endif /* CONFIG_SAE */
}
@@ -3005,6 +3030,17 @@ pfs_fail:
}
#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_TESTING_OPTIONS
+ if (wpa_s->rsnxe_override_assoc &&
+ wpabuf_len(wpa_s->rsnxe_override_assoc) <=
+ max_wpa_ie_len - wpa_ie_len) {
+ wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
+ os_memcpy(wpa_ie + wpa_ie_len,
+ wpabuf_head(wpa_s->rsnxe_override_assoc),
+ wpabuf_len(wpa_s->rsnxe_override_assoc));
+ wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
+ } else
+#endif /* CONFIG_TESTING_OPTIONS */
if (wpa_s->rsnxe_len > 0 &&
wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
@@ -4039,10 +4075,7 @@ void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
wpa_s->disconnected = 0;
wpa_s->reassociate = 1;
-#if defined(CONFIG_SAE) && defined(CONFIG_SME)
- os_free(wpa_s->sme.sae_rejected_groups);
- wpa_s->sme.sae_rejected_groups = NULL;
-#endif /* CONFIG_SAE && CONFIG_SME */
+ wpa_s_clear_sae_rejected(wpa_s);
wpa_s->last_owe_group = 0;
if (ssid) {
ssid->owe_transition_bss_select_count = 0;
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 8c5defc..4a958ac 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -1117,6 +1117,7 @@ struct wpa_supplicant {
unsigned int ignore_auth_resp:1;
unsigned int ignore_assoc_disallow:1;
unsigned int testing_resend_assoc:1;
+ unsigned int ignore_sae_h2e_only:1;
struct wpabuf *sae_commit_override;
enum wpa_alg last_tk_alg;
u8 last_tk_addr[ETH_ALEN];
@@ -1124,6 +1125,9 @@ struct wpa_supplicant {
u8 last_tk[WPA_TK_MAX_LEN];
size_t last_tk_len;
struct wpabuf *last_assoc_req_wpa_ie;
+ int *extra_sae_rejected_groups;
+ struct wpabuf *rsnxe_override_assoc;
+ struct wpabuf *rsnxe_override_eapol;
#endif /* CONFIG_TESTING_OPTIONS */
struct wmm_ac_assoc_data *wmm_ac_assoc_info;